Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:25
erlang
1114-jit-Optimize-emit_gc_test_preserve.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 1114-jit-Optimize-emit_gc_test_preserve.patch of Package erlang
From cc62a444411dc92b66a944db0dba9af16ef014de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org> Date: Fri, 6 May 2022 23:21:54 +0200 Subject: [PATCH 4/7] jit: Optimize `emit_gc_test_preserve` We don't need to stash the preserved term if it's currently live, making the code slightly shorter. --- erts/emulator/beam/jit/arm/beam_asm.hpp | 3 ++- erts/emulator/beam/jit/arm/instr_bs.cpp | 29 +++++++------------- erts/emulator/beam/jit/arm/instr_common.cpp | 21 +++++++++++---- erts/emulator/beam/jit/x86/beam_asm.hpp | 3 ++- erts/emulator/beam/jit/x86/instr_bs.cpp | 30 +++++++++------------ erts/emulator/beam/jit/x86/instr_common.cpp | 22 ++++++++++----- 6 files changed, 57 insertions(+), 51 deletions(-) diff --git a/erts/emulator/beam/jit/arm/beam_asm.hpp b/erts/emulator/beam/jit/arm/beam_asm.hpp index 518abf4896..74d1e85559 100644 --- a/erts/emulator/beam/jit/arm/beam_asm.hpp +++ b/erts/emulator/beam/jit/arm/beam_asm.hpp @@ -1212,7 +1212,8 @@ protected: const ArgWord &Live); void emit_gc_test_preserve(const ArgWord &Need, const ArgWord &Live, - arm::Gp term); + const ArgSource &Preserve, + arm::Gp preserve_reg); arm::Mem emit_variable_apply(bool includeI); arm::Mem emit_fixed_apply(const ArgWord &arity, bool includeI); diff --git a/erts/emulator/beam/jit/arm/instr_bs.cpp b/erts/emulator/beam/jit/arm/instr_bs.cpp index d18585121d..7c953e105f 100644 --- a/erts/emulator/beam/jit/arm/instr_bs.cpp +++ b/erts/emulator/beam/jit/arm/instr_bs.cpp @@ -541,10 +541,9 @@ void BeamModuleAssembler::emit_i_bs_start_match3(const ArgRegister &Src, a.bind(is_binary); { - /* Src is not guaranteed to be inside the live range, so we need to - * stash it during GC. */ - emit_gc_test_preserve(ArgVal(ArgVal::Word, ERL_BIN_MATCHSTATE_SIZE(0)), + emit_gc_test_preserve(ArgWord(ERL_BIN_MATCHSTATE_SIZE(0)), Live, + Src, ARG2); emit_enter_runtime<Update::eStack | Update::eHeap>(Live.get()); @@ -637,8 +636,9 @@ void BeamModuleAssembler::emit_i_bs_get_fixed_integer(const ArgRegister &Ctx, bits = Bits.get(); if (bits >= SMALL_BITS) { - emit_gc_test_preserve(ArgVal(ArgVal::Word, BIG_NEED_FOR_BITS(bits)), + emit_gc_test_preserve(ArgWord(BIG_NEED_FOR_BITS(bits)), Live, + Ctx, ctx.reg); } @@ -738,11 +738,7 @@ void BeamModuleAssembler::emit_i_bs_get_binary_all2(const ArgRegister &Ctx, mov_arg(ARG1, Ctx); - /* Ctx is not guaranteed to be inside the live range, so we need to stash - * it during GC. */ - emit_gc_test_preserve(ArgVal(ArgVal::Word, EXTRACT_SUB_BIN_HEAP_NEED), - Live, - ARG1); + emit_gc_test_preserve(ArgWord(EXTRACT_SUB_BIN_HEAP_NEED), Live, Ctx, ARG1); /* Make field fetching slightly more compact by pre-loading the match * buffer into the right argument slot for `erts_bs_get_binary_all_2`. */ @@ -811,11 +807,7 @@ void BeamModuleAssembler::emit_bs_get_tail(const ArgRegister &Ctx, const ArgWord &Live) { mov_arg(ARG1, Ctx); - /* Ctx is not guaranteed to be inside the live range, so we need to stash - * it during GC. */ - emit_gc_test_preserve(ArgVal(ArgVal::Word, EXTRACT_SUB_BIN_HEAP_NEED), - Live, - ARG1); + emit_gc_test_preserve(ArgWord(EXTRACT_SUB_BIN_HEAP_NEED), Live, Ctx, ARG1); fragment_call(ga->get_bs_get_tail_shared()); @@ -875,10 +867,9 @@ void BeamModuleAssembler::emit_i_bs_get_binary2(const ArgRegister &Ctx, mov_arg(ARG4, Ctx); - /* Ctx is not guaranteed to be inside the live range, so we need to - * stash it during GC. */ - emit_gc_test_preserve(ArgVal(ArgVal::Word, EXTRACT_SUB_BIN_HEAP_NEED), + emit_gc_test_preserve(ArgWord(EXTRACT_SUB_BIN_HEAP_NEED), Live, + Ctx, ARG4); lea(ARG4, emit_boxed_val(ARG4, offsetof(ErlBinMatchState, mb))); @@ -912,9 +903,7 @@ void BeamModuleAssembler::emit_i_bs_get_float2(const ArgRegister &Ctx, mov_arg(ARG4, Ctx); - /* Ctx is not guaranteed to be inside the live range, so we need to stash - * it during GC. */ - emit_gc_test_preserve(ArgWord(FLOAT_SIZE_OBJECT), Live, ARG4); + emit_gc_test_preserve(ArgWord(FLOAT_SIZE_OBJECT), Live, Ctx, ARG4); if (emit_bs_get_field_size(Sz, unit, fail, ARG2) >= 0) { lea(ARG4, emit_boxed_val(ARG4, offsetof(ErlBinMatchState, mb))); diff --git a/erts/emulator/beam/jit/arm/instr_common.cpp b/erts/emulator/beam/jit/arm/instr_common.cpp index 70097efdc4..ec97941614 100644 --- a/erts/emulator/beam/jit/arm/instr_common.cpp +++ b/erts/emulator/beam/jit/arm/instr_common.cpp @@ -75,7 +75,8 @@ void BeamModuleAssembler::emit_error(int reason) { void BeamModuleAssembler::emit_gc_test_preserve(const ArgWord &Need, const ArgWord &Live, - arm::Gp term) { + const ArgSource &Preserve, + arm::Gp preserve_reg) { const int32_t bytes_needed = (Need.get() + S_RESERVED) * sizeof(Eterm); Label after_gc_check = a.newLabel(); @@ -84,12 +85,22 @@ void BeamModuleAssembler::emit_gc_test_preserve(const ArgWord &Need, a.b_ls(after_gc_check); ASSERT(Live.get() < ERTS_X_REGS_ALLOCATED); - mov_arg(ArgVal(ArgVal::XReg, Live.get()), term); - mov_imm(ARG4, Live.get() + 1); - fragment_call(ga->get_garbage_collect()); + /* We don't need to stash the preserved term if it's currently live, making + * the code slightly shorter. */ + if (!(Preserve.isXRegister() && + Preserve.as<ArgXRegister>().get() >= Live.get())) { + mov_imm(ARG4, Live.get()); + fragment_call(ga->get_garbage_collect()); + mov_arg(preserve_reg, Preserve); + } else { + mov_arg(ArgXRegister(Live.get()), preserve_reg); - mov_arg(term, ArgVal(ArgVal::XReg, Live.get())); + mov_imm(ARG4, Live.get() + 1); + fragment_call(ga->get_garbage_collect()); + + mov_arg(preserve_reg, ArgXRegister(Live.get())); + } a.bind(after_gc_check); } diff --git a/erts/emulator/beam/jit/x86/beam_asm.hpp b/erts/emulator/beam/jit/x86/beam_asm.hpp index da037aa235..f7b824619d 100644 --- a/erts/emulator/beam/jit/x86/beam_asm.hpp +++ b/erts/emulator/beam/jit/x86/beam_asm.hpp @@ -1202,7 +1202,8 @@ protected: const ArgWord &Live); void emit_gc_test_preserve(const ArgWord &Need, const ArgWord &Live, - x86::Gp term); + const ArgSource &Preserve, + x86::Gp preserve_reg); x86::Mem emit_variable_apply(bool includeI); x86::Mem emit_fixed_apply(const ArgWord &arity, bool includeI); diff --git a/erts/emulator/beam/jit/x86/instr_bs.cpp b/erts/emulator/beam/jit/x86/instr_bs.cpp index 91438fbdc2..a29c3d831d 100644 --- a/erts/emulator/beam/jit/x86/instr_bs.cpp +++ b/erts/emulator/beam/jit/x86/instr_bs.cpp @@ -576,9 +576,10 @@ void BeamModuleAssembler::emit_i_bs_start_match3(const ArgRegister &Src, a.bind(is_binary); { - /* Src is not guaranteed to be inside the live range, so we need to - * stash it during GC. */ - emit_gc_test_preserve(ArgWord(ERL_BIN_MATCHSTATE_SIZE(0)), Live, ARG2); + emit_gc_test_preserve(ArgWord(ERL_BIN_MATCHSTATE_SIZE(0)), + Live, + Src, + ARG2); emit_enter_runtime<Update::eStack | Update::eHeap>(); @@ -834,9 +835,7 @@ void BeamModuleAssembler::emit_i_bs_get_integer_64(const ArgRegister &Ctx, mov_arg(ARG4, Ctx); - /* Ctx is not guaranteed to be inside the live range, so we need to stash - * it during GC. */ - emit_gc_test_preserve(ArgWord(BIG_UINT_HEAP_SIZE), Live, ARG4); + emit_gc_test_preserve(ArgWord(BIG_UINT_HEAP_SIZE), Live, Ctx, ARG4); address = emit_bs_get_integer_prologue(next, resolve_beam_label(Fail), @@ -957,9 +956,7 @@ void BeamModuleAssembler::emit_i_bs_get_binary_all2(const ArgRegister &Ctx, mov_arg(ARG1, Ctx); - /* Ctx is not guaranteed to be inside the live range, so we need to stash - * it during GC. */ - emit_gc_test_preserve(ArgWord(EXTRACT_SUB_BIN_HEAP_NEED), Live, ARG1); + emit_gc_test_preserve(ArgWord(EXTRACT_SUB_BIN_HEAP_NEED), Live, Ctx, ARG1); a.mov(RET, emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb.size))); a.sub(RET, emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb.offset))); @@ -1011,9 +1008,7 @@ void BeamModuleAssembler::emit_bs_get_tail(const ArgRegister &Ctx, const ArgWord &Live) { mov_arg(ARG1, Ctx); - /* Ctx is not guaranteed to be inside the live range, so we need to stash - * it during GC. */ - emit_gc_test_preserve(ArgWord(EXTRACT_SUB_BIN_HEAP_NEED), Live, ARG1); + emit_gc_test_preserve(ArgWord(EXTRACT_SUB_BIN_HEAP_NEED), Live, Ctx, ARG1); safe_fragment_call(ga->get_bs_get_tail_shared()); @@ -1071,9 +1066,10 @@ void BeamModuleAssembler::emit_i_bs_get_binary2(const ArgRegister &Ctx, mov_arg(ARG4, Ctx); - /* Ctx is not guaranteed to be inside the live range, so we need to - * stash it during GC. */ - emit_gc_test_preserve(ArgWord(EXTRACT_SUB_BIN_HEAP_NEED), Live, ARG4); + emit_gc_test_preserve(ArgWord(EXTRACT_SUB_BIN_HEAP_NEED), + Live, + Ctx, + ARG4); emit_enter_runtime<Update::eHeap>(); @@ -1106,9 +1102,7 @@ void BeamModuleAssembler::emit_i_bs_get_float2(const ArgRegister &Ctx, mov_arg(ARG4, Ctx); - /* Ctx is not guaranteed to be inside the live range, so we need to stash - * it during GC. */ - emit_gc_test_preserve(ArgWord(FLOAT_SIZE_OBJECT), Live, ARG4); + emit_gc_test_preserve(ArgWord(FLOAT_SIZE_OBJECT), Live, Ctx, ARG4); if (emit_bs_get_field_size(Sz, unit, fail, ARG2, 64) >= 0) { /* erts_bs_get_float_2 uses HeapOnlyAlloc which usually requires just diff --git a/erts/emulator/beam/jit/x86/instr_common.cpp b/erts/emulator/beam/jit/x86/instr_common.cpp index bf26f5284f..58552d8a67 100644 --- a/erts/emulator/beam/jit/x86/instr_common.cpp +++ b/erts/emulator/beam/jit/x86/instr_common.cpp @@ -103,20 +103,30 @@ void BeamModuleAssembler::emit_error(int reason) { void BeamModuleAssembler::emit_gc_test_preserve(const ArgWord &Need, const ArgWord &Live, - x86::Gp term) { + const ArgSource &Preserve, + x86::Gp preserve_reg) { const int32_t bytes_needed = (Need.get() + S_RESERVED) * sizeof(Eterm); Label after_gc_check = a.newLabel(); - ASSERT(term != ARG3); + ASSERT(preserve_reg != ARG3); a.lea(ARG3, x86::qword_ptr(HTOP, bytes_needed)); a.cmp(ARG3, E); a.short_().jbe(after_gc_check); - a.mov(getXRef(Live.get()), term); - mov_imm(ARG4, Live.get() + 1); - fragment_call(ga->get_garbage_collect()); - a.mov(term, getXRef(Live.get())); + /* We don't need to stash the preserved term if it's currently live, making + * the code slightly shorter. */ + if (!(Preserve.isXRegister() && + Preserve.as<ArgXRegister>().get() >= Live.get())) { + mov_imm(ARG4, Live.get()); + fragment_call(ga->get_garbage_collect()); + mov_arg(preserve_reg, Preserve); + } else { + a.mov(getXRef(Live.get()), preserve_reg); + mov_imm(ARG4, Live.get() + 1); + fragment_call(ga->get_garbage_collect()); + a.mov(preserve_reg, getXRef(Live.get())); + } a.bind(after_gc_check); } -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor