diff --git a/erts/emulator/beam/jit/arm/instr_bs.cpp b/erts/emulator/beam/jit/arm/instr_bs.cpp index d28c40321cce..05a400341097 100644 --- a/erts/emulator/beam/jit/arm/instr_bs.cpp +++ b/erts/emulator/beam/jit/arm/instr_bs.cpp @@ -2173,24 +2173,34 @@ void BeamModuleAssembler::emit_i_bs_create_bin(const ArgLabel &Fail, seg.size.as().get() == am_all) { /* Include the entire binary/bitstring in the * resulting binary. */ + + can_fail = + !(exact_type(seg.src) && + std::gcd(seg.unit, getSizeUnit(seg.src)) == seg.unit); + load_erl_bits_state(ARG1); a.mov(ARG2, c_p); mov_arg(ARG3, seg.src); - mov_imm(ARG4, seg.unit); + + if (can_fail) { + mov_imm(ARG4, seg.unit); + } emit_enter_runtime(Live.get()); - runtime_call<4>(erts_bs_put_binary_all); + if (can_fail) { + runtime_call<4>(erts_bs_put_binary_all); + } else { + runtime_call<3>(beam_jit_bs_put_binary_all); + } emit_leave_runtime(Live.get()); error_info = beam_jit_update_bsc_reason_info(seg.error_info, BSC_REASON_BADARG, BSC_INFO_UNIT, BSC_VALUE_FVALUE); - if (exact_type(seg.src) && - std::gcd(seg.unit, getSizeUnit(seg.src)) == seg.unit) { + if (!can_fail) { comment("skipped test for success because units are " "compatible"); - can_fail = false; } } else { /* The size is a variable. We have verified that diff --git a/erts/emulator/beam/jit/beam_jit_common.cpp b/erts/emulator/beam/jit/beam_jit_common.cpp index b4386fdb9b39..655c4d01ab10 100644 --- a/erts/emulator/beam/jit/beam_jit_common.cpp +++ b/erts/emulator/beam/jit/beam_jit_common.cpp @@ -1033,6 +1033,23 @@ Eterm beam_jit_int128_to_big(Process *p, Uint sign, Uint low, Uint high) { return make_big(hp); } +void beam_jit_bs_put_binary_all(ErlBitsState *EBS, Process *c_p, Eterm arg) { + Uint offset, size; + byte *base; + + /* This instruction is always preceded by a size calculation that + * guarantees that 'arg' is a bitstring. */ + ASSERT(is_bitstring(arg)); + + ERTS_GET_BITSTRING(arg, base, offset, size); + + copy_binary_to_buffer(EBS->erts_current_bin, EBS->erts_bin_offset, + base, offset, size); + EBS->erts_bin_offset += size; + + BUMP_REDS(c_p, size / ERL_BITS_PER_REDUCTION); +} + ErtsMessage *beam_jit_decode_dist(Process *c_p, ErtsMessage *msgp) { if (!erts_proc_sig_decode_dist(c_p, ERTS_PROC_LOCK_MAIN, msgp, 0)) { /* diff --git a/erts/emulator/beam/jit/beam_jit_common.hpp b/erts/emulator/beam/jit/beam_jit_common.hpp index 7c659d94c3b5..2141abba6d33 100644 --- a/erts/emulator/beam/jit/beam_jit_common.hpp +++ b/erts/emulator/beam/jit/beam_jit_common.hpp @@ -623,6 +623,7 @@ void beam_jit_bs_construct_fail_info(Process *c_p, Eterm arg3, Eterm arg1); Sint beam_jit_bs_bit_size(Eterm term); +void beam_jit_bs_put_binary_all(ErlBitsState *EBS, Process *c_p, Eterm arg); Eterm beam_jit_int128_to_big(Process *p, Uint sign, Uint low, Uint high);