diff --git a/erts/emulator/beam/jit/arm/beam_asm_global.hpp.pl b/erts/emulator/beam/jit/arm/beam_asm_global.hpp.pl index 59524b32c73b..3f4403279e58 100644 --- a/erts/emulator/beam/jit/arm/beam_asm_global.hpp.pl +++ b/erts/emulator/beam/jit/arm/beam_asm_global.hpp.pl @@ -40,6 +40,7 @@ bs_add_body_shared bs_bit_size_shared bs_create_bin_error_shared + bs_get_bin_and_tail_shared bs_get_tail_shared bs_get_utf8_shared bs_get_utf8_short_shared diff --git a/erts/emulator/beam/jit/arm/instr_bs.cpp b/erts/emulator/beam/jit/arm/instr_bs.cpp index 45090f24990a..5c6c9f73c1a7 100644 --- a/erts/emulator/beam/jit/arm/instr_bs.cpp +++ b/erts/emulator/beam/jit/arm/instr_bs.cpp @@ -954,6 +954,85 @@ void BeamModuleAssembler::emit_i_bs_get_binary2(const ArgRegister &Ctx, } } +void BeamGlobalAssembler::emit_bs_get_bin_and_tail_shared() { + Label fail = a.newLabel(); + + a.ldr(ARG5, TMP_MEM1q); + + lea(ARG6, emit_boxed_val(ARG6, offsetof(ErlBinMatchState, mb))); + + ERTS_CT_ASSERT_FIELD_PAIR(ErlBinMatchBuffer, orig, base); + a.ldp(ARG2, ARG3, arm::Mem(ARG6, offsetof(ErlBinMatchBuffer, orig))); + + ERTS_CT_ASSERT_FIELD_PAIR(ErlBinMatchBuffer, offset, size); + a.ldp(ARG4, TMP1, arm::Mem(ARG6, offsetof(ErlBinMatchBuffer, offset))); + + lea(ARG1, arm::Mem(c_p, offsetof(Process, htop))); + + a.add(TMP2, ARG4, ARG5); + a.cmp(TMP2, TMP1); + a.b_hi(fail); + + a.str(TMP2, arm::Mem(ARG6, offsetof(ErlBinMatchBuffer, offset))); + a.str(ARG6, TMP_MEM1q); + + emit_enter_runtime_frame(); + emit_enter_runtime(); + + runtime_call<5>(erts_extract_sub_binary); + + a.ldr(ARG6, TMP_MEM1q); + a.str(ARG1, TMP_MEM2q); + lea(ARG1, arm::Mem(c_p, offsetof(Process, htop))); + + ERTS_CT_ASSERT_FIELD_PAIR(ErlBinMatchBuffer, offset, size); + a.ldp(ARG4, TMP1, arm::Mem(ARG6, offsetof(ErlBinMatchBuffer, offset))); + + ERTS_CT_ASSERT_FIELD_PAIR(ErlBinMatchBuffer, orig, base); + a.ldp(ARG2, ARG3, arm::Mem(ARG6, offsetof(ErlBinMatchBuffer, orig))); + + a.sub(ARG5, TMP1, ARG4); + + runtime_call<5>(erts_extract_sub_binary); + + emit_leave_runtime(); + emit_leave_runtime_frame(); + + a.ldr(ARG2, TMP_MEM2q); + a.ret(a64::x30); + + a.bind(fail); + mov_imm(ARG1, THE_NON_VALUE); + a.ret(a64::x30); +} + +void BeamModuleAssembler::emit_i_bs_get_bin_and_tail(const ArgRegister &Ctx, + const ArgLabel &Fail, + const ArgWord &Live, + const ArgRegister &Size, + const ArgWord &Unit, + const ArgRegister &Dst1, + const ArgRegister &Dst2) { + Label fail; + int unit; + + fail = resolve_beam_label(Fail, dispUnknown); + unit = Unit.get(); + + if (emit_bs_get_field_size(Size, unit, fail, ARG5) >= 0) { + mov_arg(ARG6, Ctx); + a.str(ARG5, TMP_MEM1q); + emit_gc_test_preserve(ArgWord(2*EXTRACT_SUB_BIN_HEAP_NEED), + Live, + Ctx, + ARG6); + fragment_call(ga->get_bs_get_bin_and_tail_shared()); + emit_branch_if_not_value(ARG1, fail); + mov_arg(Dst1, ARG2); + mov_arg(Dst2, ARG1); + } +} + void BeamModuleAssembler::emit_i_bs_get_float2(const ArgRegister &Ctx, const ArgLabel &Fail, const ArgWord &Live, diff --git a/erts/emulator/beam/jit/arm/ops.tab b/erts/emulator/beam/jit/arm/ops.tab index b657f7c420d0..cd23ba001841 100644 --- a/erts/emulator/beam/jit/arm/ops.tab +++ b/erts/emulator/beam/jit/arm/ops.tab @@ -920,6 +920,14 @@ i_bs_match_string S f W M # Fetching integers from binaries. bs_get_integer2 f S t s t t d +bs_get_binary2 Fail=f Ms1=xy Live1=u Sz=xy Unit=u Flags=u Dst1=d | + bs_get_tail Ms2=xy Dst2 Live2 | + equal(Ms1, Ms2) | + equal(Live1, Live2) => + i_bs_get_bin_and_tail Ms1 Fail Live1 Sz Unit Dst1 Dst2 + +i_bs_get_bin_and_tail S f t S t d d + # Fetching binaries from binaries. bs_get_binary2 Fail=f Ms=xy Live=u Sz=a==am_all Unit=u Flags=u Dst=d => i_bs_get_binary_all2 Ms Fail Live Unit Dst