Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:26
erlang
1135-Simplify-updating-a-single-element-of-a-ma...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 1135-Simplify-updating-a-single-element-of-a-map.patch of Package erlang
From 2b227d7149ab81f90a482853a7842ae8f1cde7ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org> Date: Mon, 4 Sep 2023 06:14:03 +0200 Subject: [PATCH 05/25] Simplify updating a single element of a map --- erts/emulator/beam/jit/arm/beam_asm.hpp | 30 +++++ .../beam/jit/arm/beam_asm_global.hpp.pl | 6 +- erts/emulator/beam/jit/arm/instr_map.cpp | 101 +++++++++++++---- .../beam/jit/x86/beam_asm_global.hpp.pl | 2 + erts/emulator/beam/jit/x86/instr_map.cpp | 104 ++++++++++++++---- 5 files changed, 201 insertions(+), 42 deletions(-) diff --git a/erts/emulator/beam/jit/arm/beam_asm.hpp b/erts/emulator/beam/jit/arm/beam_asm.hpp index 38f1c6875f..c51edb512f 100644 --- a/erts/emulator/beam/jit/arm/beam_asm.hpp +++ b/erts/emulator/beam/jit/arm/beam_asm.hpp @@ -1440,6 +1440,36 @@ protected: return Variable<arm::VecD>(tmp); } + void emit_load_args(const ArgSource &Src1, + arm::Gp src1_default, + const ArgSource &Src2, + arm::Gp src2_default, + const ArgSource &Src3, + arm::Gp src3_default) { + if (isRegisterBacked(Src1) || !Src1.isRegister()) { + auto src1 = load_source(Src1, src1_default); + auto [src2, src3] = + load_sources(Src2, src2_default, Src3, src3_default); + mov_var(src1_default, src1); + mov_var(src2_default, src2); + mov_var(src3_default, src3); + } else if (isRegisterBacked(Src2) || !Src2.isRegister()) { + auto [src1, src3] = + load_sources(Src1, src1_default, Src3, src3_default); + auto src2 = load_source(Src2, src2_default); + mov_var(src1_default, src1); + mov_var(src2_default, src2); + mov_var(src3_default, src3); + } else { + auto [src1, src2] = + load_sources(Src1, src1_default, Src2, src2_default); + auto src3 = load_source(Src3, src3_default); + mov_var(src1_default, src1); + mov_var(src2_default, src2); + mov_var(src3_default, src3); + } + } + template<typename Reg> void mov_var(const Variable<Reg> &to, const Variable<Reg> &from) { mov_var(to.reg, from); 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 93b239ddbd..0cb95c5ce3 100644 --- a/erts/emulator/beam/jit/arm/beam_asm_global.hpp.pl +++ b/erts/emulator/beam/jit/arm/beam_asm_global.hpp.pl @@ -103,17 +103,19 @@ my @beam_global_funcs = qw( mul_body_shared mul_guard_shared new_map_shared - update_map_assoc_shared - unloaded_fun plus_body_shared process_exit process_main raise_exception raise_exception_shared store_unaligned + unloaded_fun unary_minus_body_shared + update_map_assoc_shared + update_map_single_assoc_shared update_map_exact_guard_shared update_map_exact_body_shared + update_map_single_exact_body_shared ); diff --git a/erts/emulator/beam/jit/arm/instr_map.cpp b/erts/emulator/beam/jit/arm/instr_map.cpp index daecdb80ef..129c29d5b2 100644 --- a/erts/emulator/beam/jit/arm/instr_map.cpp +++ b/erts/emulator/beam/jit/arm/instr_map.cpp @@ -545,23 +545,44 @@ void BeamGlobalAssembler::emit_update_map_assoc_shared() { a.ret(a64::x30); } +/* ARG2 = key + * ARG3 = value + * ARG4 = map + */ +void BeamGlobalAssembler::emit_update_map_single_assoc_shared() { + emit_enter_runtime_frame(); + emit_enter_runtime<Update::eHeapAlloc>(); + + a.mov(ARG1, c_p); + runtime_call<4>(erts_maps_put); + + emit_leave_runtime<Update::eHeapAlloc>(); + emit_leave_runtime_frame(); + + a.ret(a64::x30); +} + void BeamModuleAssembler::emit_update_map_assoc(const ArgSource &Src, const ArgRegister &Dst, const ArgWord &Live, const ArgWord &Size, const Span<ArgVal> &args) { - auto src_reg = load_source(Src, TMP1); - ASSERT(Size.get() == args.size()); - embed_vararg_rodata(args, ARG5); + if (args.size() == 2) { + emit_load_args(args[0], ARG2, args[1], ARG3, Src, ARG4); + fragment_call(ga->get_update_map_single_assoc_shared()); + } else { + auto src = load_source(Src, TMP1); - mov_arg(ArgXRegister(Live.get()), src_reg.reg); - mov_arg(ARG3, Live); - mov_imm(ARG4, args.size()); + embed_vararg_rodata(args, ARG5); - fragment_call(ga->get_update_map_assoc_shared()); + mov_arg(ArgXRegister(Live.get()), src.reg); + mov_arg(ARG3, Live); + mov_imm(ARG4, args.size()); + fragment_call(ga->get_update_map_assoc_shared()); + } mov_arg(Dst, ARG1); } @@ -612,29 +633,67 @@ void BeamGlobalAssembler::emit_update_map_exact_body_shared() { } } +/* ARG2 = key + * ARG3 = value + * ARG4 = map + * + * Does not return on error. */ +void BeamGlobalAssembler::emit_update_map_single_exact_body_shared() { + Label error = a.newLabel(); + + a.str(ARG2, TMP_MEM2q); + + emit_enter_runtime_frame(); + emit_enter_runtime<Update::eHeapAlloc>(); + + a.mov(ARG1, c_p); + lea(ARG5, TMP_MEM1q); + runtime_call<5>(erts_maps_update); + + emit_leave_runtime<Update::eHeapAlloc>(); + emit_leave_runtime_frame(); + + a.cbz(ARG1.w(), error); + + a.ldr(ARG1, TMP_MEM1q); + a.ret(a64::x30); + + a.bind(error); + { + a.ldr(TMP2, TMP_MEM2q); + mov_imm(TMP1, BADKEY); + ERTS_CT_ASSERT_FIELD_PAIR(Process, freason, fvalue); + a.stp(TMP1, TMP2, arm::Mem(c_p, offsetof(Process, freason))); + mov_imm(ARG4, 0); + a.b(labels[raise_exception]); + } +} + void BeamModuleAssembler::emit_update_map_exact(const ArgSource &Src, const ArgLabel &Fail, const ArgRegister &Dst, const ArgWord &Live, const ArgWord &Size, const Span<ArgVal> &args) { - auto src_reg = load_source(Src, TMP1); - ASSERT(Size.get() == args.size()); - embed_vararg_rodata(args, ARG5); - - /* We _KNOW_ Src is a map */ - - mov_arg(ArgXRegister(Live.get()), src_reg.reg); - mov_arg(ARG3, Live); - mov_imm(ARG4, args.size()); - - if (Fail.get() != 0) { - fragment_call(ga->get_update_map_exact_guard_shared()); - emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown)); + if (args.size() == 2 && Fail.get() == 0) { + emit_load_args(args[0], ARG2, args[1], ARG3, Src, ARG4); + fragment_call(ga->get_update_map_single_exact_body_shared()); } else { - fragment_call(ga->get_update_map_exact_body_shared()); + auto src = load_source(Src, ARG4); + embed_vararg_rodata(args, ARG5); + mov_arg(ArgXRegister(Live.get()), src.reg); + mov_arg(ARG3, Live); + mov_imm(ARG4, args.size()); + + if (Fail.get() != 0) { + fragment_call(ga->get_update_map_exact_guard_shared()); + emit_branch_if_not_value(ARG1, + resolve_beam_label(Fail, dispUnknown)); + } else { + fragment_call(ga->get_update_map_exact_body_shared()); + } } mov_arg(Dst, ARG1); diff --git a/erts/emulator/beam/jit/x86/beam_asm_global.hpp.pl b/erts/emulator/beam/jit/x86/beam_asm_global.hpp.pl index 9782bbb226..e6f8a53219 100755 --- a/erts/emulator/beam/jit/x86/beam_asm_global.hpp.pl +++ b/erts/emulator/beam/jit/x86/beam_asm_global.hpp.pl @@ -108,6 +108,8 @@ my @beam_global_funcs = qw( update_map_assoc_shared update_map_exact_guard_shared update_map_exact_body_shared + update_map_single_assoc_shared + update_map_single_exact_body_shared ); # Labels exported from within process_main diff --git a/erts/emulator/beam/jit/x86/instr_map.cpp b/erts/emulator/beam/jit/x86/instr_map.cpp index 18eb9eb50a..c386208b63 100644 --- a/erts/emulator/beam/jit/x86/instr_map.cpp +++ b/erts/emulator/beam/jit/x86/instr_map.cpp @@ -574,21 +574,45 @@ void BeamGlobalAssembler::emit_update_map_assoc_shared() { a.ret(); } +/* ARG2 = key + * ARG3 = value + * ARG4 = map + */ +void BeamGlobalAssembler::emit_update_map_single_assoc_shared() { + emit_enter_frame(); + emit_enter_runtime<Update::eHeapAlloc>(); + + a.mov(ARG1, c_p); + runtime_call<4>(erts_maps_put); + + emit_leave_runtime<Update::eHeapAlloc>(); + emit_leave_frame(); + + a.ret(); +} + void BeamModuleAssembler::emit_update_map_assoc(const ArgSource &Src, const ArgRegister &Dst, const ArgWord &Live, const ArgWord &Size, const Span<ArgVal> &args) { - Label data = embed_vararg_rodata(args, CP_SIZE); - ASSERT(Size.get() == args.size()); - mov_arg(getXRef(Live.get()), Src); + if (args.size() == 2) { + mov_arg(ARG2, args[0]); + mov_arg(ARG3, args[1]); + mov_arg(ARG4, Src); + safe_fragment_call(ga->get_update_map_single_assoc_shared()); + } else { + Label data = embed_vararg_rodata(args, CP_SIZE); - mov_imm(ARG3, Live.get()); - mov_imm(ARG4, args.size()); - a.lea(ARG5, x86::qword_ptr(data)); - fragment_call(ga->get_update_map_assoc_shared()); + mov_arg(getXRef(Live.get()), Src); + + mov_imm(ARG3, Live.get()); + mov_imm(ARG4, args.size()); + a.lea(ARG5, x86::qword_ptr(data)); + fragment_call(ga->get_update_map_assoc_shared()); + } mov_arg(Dst, RET); } @@ -639,28 +663,70 @@ void BeamGlobalAssembler::emit_update_map_exact_body_shared() { } } +/* ARG2 = key + * ARG3 = value + * ARG4 = map + * + * Does not return on error. */ +void BeamGlobalAssembler::emit_update_map_single_exact_body_shared() { + Label error = a.newLabel(); + + a.mov(TMP_MEM2q, ARG2); + + emit_enter_frame(); + emit_enter_runtime<Update::eHeapAlloc>(); + + a.mov(ARG1, c_p); + a.lea(ARG5, TMP_MEM1q); + runtime_call<5>(erts_maps_update); + + emit_leave_runtime<Update::eHeapAlloc>(); + emit_leave_frame(); + + a.test(RETd, RETd); + a.short_().je(error); + + a.mov(RET, TMP_MEM1q); + a.ret(); + + a.bind(error); + { + a.mov(RET, TMP_MEM2q); + a.mov(x86::qword_ptr(c_p, offsetof(Process, freason)), imm(BADKEY)); + a.mov(x86::qword_ptr(c_p, offsetof(Process, fvalue)), RET); + mov_imm(ARG4, 0); + a.jmp(labels[raise_exception]); + } +} + void BeamModuleAssembler::emit_update_map_exact(const ArgSource &Src, const ArgLabel &Fail, const ArgRegister &Dst, const ArgWord &Live, const ArgWord &Size, const Span<ArgVal> &args) { - Label data = embed_vararg_rodata(args, CP_SIZE); - ASSERT(Size.get() == args.size()); - /* We _KNOW_ Src is a map */ - mov_arg(getXRef(Live.get()), Src); + if (args.size() == 2 && Fail.get() == 0) { + mov_arg(ARG2, args[0]); + mov_arg(ARG3, args[1]); + mov_arg(ARG4, Src); + fragment_call(ga->get_update_map_single_exact_body_shared()); + } else { + Label data = embed_vararg_rodata(args, CP_SIZE); - mov_imm(ARG3, Live.get()); - mov_imm(ARG4, args.size()); - a.lea(ARG5, x86::qword_ptr(data)); + mov_arg(getXRef(Live.get()), Src); - if (Fail.get() != 0) { - fragment_call(ga->get_update_map_exact_guard_shared()); - a.je(resolve_beam_label(Fail)); - } else { - fragment_call(ga->get_update_map_exact_body_shared()); + mov_imm(ARG3, Live.get()); + mov_imm(ARG4, args.size()); + a.lea(ARG5, x86::qword_ptr(data)); + + if (Fail.get() != 0) { + fragment_call(ga->get_update_map_exact_guard_shared()); + a.je(resolve_beam_label(Fail)); + } else { + fragment_call(ga->get_update_map_exact_body_shared()); + } } mov_arg(Dst, RET); -- 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