From 38f3b78a1d8815fe4f79837f0cf070af49fa10bd Mon Sep 17 00:00:00 2001 From: Idan Horowitz Date: Sun, 29 Oct 2023 15:29:42 +0200 Subject: [PATCH] LibJS: Store the bytecode accumulator in a dedicated physical register We now use a dedicated physical register to store the bytecode accumulator, instead of loading and storing it to the memory everytime. --- .../LibJS/Bytecode/CommonImplementations.cpp | 11 +- .../LibJS/Bytecode/CommonImplementations.h | 4 +- .../Libraries/LibJS/Bytecode/Interpreter.cpp | 4 +- Userland/Libraries/LibJS/JIT/Compiler.cpp | 267 ++++++++++-------- Userland/Libraries/LibJS/JIT/Compiler.h | 6 + 5 files changed, 163 insertions(+), 129 deletions(-) diff --git a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp index feaf8c7607..b435a1419d 100644 --- a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp +++ b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp @@ -399,16 +399,13 @@ Value new_regexp(VM& vm, ParsedRegex const& parsed_regex, DeprecatedString const } // 13.3.8.1 https://tc39.es/ecma262/#sec-runtime-semantics-argumentlistevaluation -MarkedVector argument_list_evaluation(Bytecode::Interpreter& interpreter) +MarkedVector argument_list_evaluation(VM& vm, Value arguments) { // Note: Any spreading and actual evaluation is handled in preceding opcodes // Note: The spec uses the concept of a list, while we create a temporary array // in the preceding opcodes, so we have to convert in a manner that is not // visible to the user - auto& vm = interpreter.vm(); - MarkedVector argument_values { vm.heap() }; - auto arguments = interpreter.accumulator(); auto& argument_array = arguments.as_array(); auto array_length = argument_array.indexed_properties().array_like_size(); @@ -451,11 +448,10 @@ ThrowCompletionOr create_variable(VM& vm, DeprecatedFlyString const& name, return verify_cast(vm.variable_environment())->create_global_var_binding(name, false); } -ThrowCompletionOr new_class(VM& vm, ClassExpression const& class_expression, Optional const& lhs_name) +ThrowCompletionOr new_class(VM& vm, Value super_class, ClassExpression const& class_expression, Optional const& lhs_name) { auto& interpreter = vm.bytecode_interpreter(); auto name = class_expression.name(); - auto super_class = interpreter.accumulator(); // NOTE: NewClass expects classEnv to be active lexical environment auto* class_environment = vm.lexical_environment(); @@ -476,7 +472,6 @@ ThrowCompletionOr new_class(VM& vm, ClassExpression c // 13.3.7.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation ThrowCompletionOr> super_call_with_argument_array(VM& vm, Value argument_array, bool is_synthetic) { - auto& interpreter = vm.bytecode_interpreter(); // 1. Let newTarget be GetNewTarget(). auto new_target = vm.get_new_target(); @@ -495,7 +490,7 @@ ThrowCompletionOr> super_call_with_argument_array(VM& vm, V for (size_t i = 0; i < length; ++i) arg_list.append(array_value.get_without_side_effects(PropertyKey { i })); } else { - arg_list = argument_list_evaluation(interpreter); + arg_list = argument_list_evaluation(vm, argument_array); } // 5. If IsConstructor(func) is false, throw a TypeError exception. diff --git a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h index 1bf37c0642..d271fc1263 100644 --- a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h +++ b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h @@ -31,9 +31,9 @@ struct CalleeAndThis { }; ThrowCompletionOr get_callee_and_this_from_environment(Bytecode::Interpreter&, DeprecatedFlyString const& name, u32 cache_index); Value new_regexp(VM&, ParsedRegex const&, DeprecatedString const& pattern, DeprecatedString const& flags); -MarkedVector argument_list_evaluation(Bytecode::Interpreter&); +MarkedVector argument_list_evaluation(VM&, Value arguments); ThrowCompletionOr create_variable(VM&, DeprecatedFlyString const& name, Op::EnvironmentMode, bool is_global, bool is_immutable, bool is_strict); -ThrowCompletionOr new_class(VM&, ClassExpression const&, Optional const& lhs_name); +ThrowCompletionOr new_class(VM&, Value super_class, ClassExpression const&, Optional const& lhs_name); ThrowCompletionOr> super_call_with_argument_array(VM&, Value argument_array, bool is_synthetic); Object* iterator_to_object(VM&, IteratorRecord); IteratorRecord object_to_iterator(VM&, Object&); diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index a1bb4227d0..e93422496b 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -934,7 +934,7 @@ ThrowCompletionOr CallWithArgumentArray::execute_impl(Bytecode::Interprete { auto callee = interpreter.reg(m_callee); TRY(throw_if_needed_for_call(interpreter, callee, call_type(), expression_string())); - auto argument_values = argument_list_evaluation(interpreter); + auto argument_values = argument_list_evaluation(interpreter.vm(), interpreter.accumulator()); interpreter.accumulator() = TRY(perform_call(interpreter, interpreter.reg(m_this_value), call_type(), callee, move(argument_values))); return {}; } @@ -1217,7 +1217,7 @@ ThrowCompletionOr IteratorResultValue::execute_impl(Bytecode::Interpreter& ThrowCompletionOr NewClass::execute_impl(Bytecode::Interpreter& interpreter) const { - interpreter.accumulator() = TRY(new_class(interpreter.vm(), m_class_expression, m_lhs_name)); + interpreter.accumulator() = TRY(new_class(interpreter.vm(), interpreter.accumulator(), m_class_expression, m_lhs_name)); return {}; } diff --git a/Userland/Libraries/LibJS/JIT/Compiler.cpp b/Userland/Libraries/LibJS/JIT/Compiler.cpp index f8909021dc..9bdf46f5ff 100644 --- a/Userland/Libraries/LibJS/JIT/Compiler.cpp +++ b/Userland/Libraries/LibJS/JIT/Compiler.cpp @@ -59,6 +59,34 @@ void Compiler::load_vm_register(Assembler::Reg dst, Bytecode::Register src) Assembler::Operand::Mem64BaseAndOffset(REGISTER_ARRAY_BASE, src.index() * sizeof(Value))); } +void Compiler::load_accumulator(Assembler::Reg dst) +{ + m_assembler.mov( + Assembler::Operand::Register(dst), + Assembler::Operand::Register(CACHED_ACCUMULATOR)); +} + +void Compiler::store_accumulator(Assembler::Reg src) +{ + m_assembler.mov( + Assembler::Operand::Register(CACHED_ACCUMULATOR), + Assembler::Operand::Register(src)); +} + +void Compiler::reload_cached_accumulator() +{ + m_assembler.mov( + Assembler::Operand::Register(CACHED_ACCUMULATOR), + Assembler::Operand::Mem64BaseAndOffset(REGISTER_ARRAY_BASE, Bytecode::Register::accumulator_index * sizeof(Value))); +} + +void Compiler::flush_cached_accumulator() +{ + m_assembler.mov( + Assembler::Operand::Mem64BaseAndOffset(REGISTER_ARRAY_BASE, Bytecode::Register::accumulator_index * sizeof(Value)), + Assembler::Operand::Register(CACHED_ACCUMULATOR)); +} + void Compiler::store_vm_local(size_t dst, Assembler::Reg src) { m_assembler.mov( @@ -78,18 +106,18 @@ void Compiler::compile_load_immediate(Bytecode::Op::LoadImmediate const& op) m_assembler.mov( Assembler::Operand::Register(GPR0), Assembler::Operand::Imm(op.value().encoded())); - store_vm_register(Bytecode::Register::accumulator(), GPR0); + store_accumulator(GPR0); } void Compiler::compile_load(Bytecode::Op::Load const& op) { load_vm_register(GPR0, op.src()); - store_vm_register(Bytecode::Register::accumulator(), GPR0); + store_accumulator(GPR0); } void Compiler::compile_store(Bytecode::Op::Store const& op) { - load_vm_register(GPR0, Bytecode::Register::accumulator()); + load_accumulator(GPR0); store_vm_register(op.dst(), GPR0); } @@ -119,12 +147,12 @@ void Compiler::compile_get_local(Bytecode::Op::GetLocal const& op) check_exception(); not_empty.link(m_assembler); - store_vm_register(Bytecode::Register::accumulator(), GPR0); + store_accumulator(GPR0); } void Compiler::compile_set_local(Bytecode::Op::SetLocal const& op) { - load_vm_register(GPR0, Bytecode::Register::accumulator()); + load_accumulator(GPR0); store_vm_local(op.index(), GPR0); } @@ -137,7 +165,7 @@ void Compiler::compile_typeof_local(Bytecode::Op::TypeofLocal const& op) { load_vm_local(ARG1, op.index()); native_call((void*)cxx_typeof_local); - store_vm_register(Bytecode::Register::accumulator(), GPR0); + store_accumulator(GPR0); } void Compiler::compile_jump(Bytecode::Op::Jump const& op) @@ -201,7 +229,7 @@ void Compiler::compile_to_boolean(Assembler::Reg dst, Assembler::Reg src) void Compiler::compile_jump_conditional(Bytecode::Op::JumpConditional const& op) { - load_vm_register(GPR1, Bytecode::Register::accumulator()); + load_accumulator(GPR1); compile_to_boolean(GPR0, GPR1); @@ -216,7 +244,7 @@ void Compiler::compile_jump_conditional(Bytecode::Op::JumpConditional const& op) void Compiler::compile_jump_nullish(Bytecode::Op::JumpNullish const& op) { - load_vm_register(GPR0, Bytecode::Register::accumulator()); + load_accumulator(GPR0); m_assembler.shift_right( Assembler::Operand::Register(GPR0), @@ -237,7 +265,7 @@ void Compiler::compile_jump_nullish(Bytecode::Op::JumpNullish const& op) void Compiler::compile_jump_undefined(Bytecode::Op::JumpUndefined const& op) { - load_vm_register(GPR0, Bytecode::Register::accumulator()); + load_accumulator(GPR0); m_assembler.shift_right( Assembler::Operand::Register(GPR0), @@ -322,7 +350,7 @@ void Compiler::branch_if_both_int32(Assembler::Reg lhs, Assembler::Reg rhs, Code void Compiler::compile_increment(Bytecode::Op::Increment const&) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); Assembler::Label end {}; Assembler::Label slow_case {}; @@ -352,14 +380,14 @@ void Compiler::compile_increment(Bytecode::Op::Increment const&) Assembler::Operand::Imm(1)); // accumulator = ARG1; - store_vm_register(Bytecode::Register::accumulator(), ARG1); + store_accumulator(ARG1); m_assembler.jump(end); }); slow_case.link(m_assembler); native_call((void*)cxx_increment); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); end.link(m_assembler); @@ -375,9 +403,9 @@ static Value cxx_decrement(VM& vm, Value value) void Compiler::compile_decrement(Bytecode::Op::Decrement const&) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); native_call((void*)cxx_decrement); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -393,7 +421,7 @@ void Compiler::check_exception() Assembler::Condition::EqualTo, Assembler::Operand::Register(GPR1), no_exception); - store_vm_register(Bytecode::Register::accumulator(), GPR0); + store_accumulator(GPR0); store_vm_register(Bytecode::Register::exception(), GPR1); m_assembler.jump(label_for(*handler)); no_exception.link(m_assembler); @@ -423,7 +451,7 @@ void Compiler::compile_leave_unwind_context(Bytecode::Op::LeaveUnwindContext con void Compiler::compile_throw(Bytecode::Op::Throw const&) { - load_vm_register(GPR0, Bytecode::Register::accumulator()); + load_accumulator(GPR0); store_vm_register(Bytecode::Register::exception(), GPR0); check_exception(); } @@ -457,9 +485,9 @@ static ThrowCompletionOr typed_equals(VM&, Value src1, Value src2) void Compiler::compile_##snake_case_name(Bytecode::Op::TitleCaseName const& op) \ { \ load_vm_register(ARG1, op.lhs()); \ - load_vm_register(ARG2, Bytecode::Register::accumulator()); \ + load_accumulator(ARG2); \ native_call((void*)cxx_##snake_case_name); \ - store_vm_register(Bytecode::Register::accumulator(), RET); \ + store_accumulator(RET); \ check_exception(); \ } @@ -474,7 +502,7 @@ static Value cxx_add(VM& vm, Value lhs, Value rhs) void Compiler::compile_add(Bytecode::Op::Add const& op) { load_vm_register(ARG1, op.lhs()); - load_vm_register(ARG2, Bytecode::Register::accumulator()); + load_accumulator(ARG2); Assembler::Label end {}; Assembler::Label slow_case {}; @@ -497,13 +525,13 @@ void Compiler::compile_add(Bytecode::Op::Add const& op) m_assembler.bitwise_or( Assembler::Operand::Register(GPR0), Assembler::Operand::Register(GPR1)); - store_vm_register(Bytecode::Register::accumulator(), GPR0); + store_accumulator(GPR0); m_assembler.jump(end); }); slow_case.link(m_assembler); native_call((void*)cxx_add); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); end.link(m_assembler); } @@ -516,7 +544,7 @@ static Value cxx_less_than(VM& vm, Value lhs, Value rhs) void Compiler::compile_less_than(Bytecode::Op::LessThan const& op) { load_vm_register(ARG1, op.lhs()); - load_vm_register(ARG2, Bytecode::Register::accumulator()); + load_accumulator(ARG2); Assembler::Label end {}; @@ -538,20 +566,20 @@ void Compiler::compile_less_than(Bytecode::Op::LessThan const& op) m_assembler.mov( Assembler::Operand::Register(GPR0), Assembler::Operand::Imm(Value(false).encoded())); - store_vm_register(Bytecode::Register::accumulator(), GPR0); + store_accumulator(GPR0); m_assembler.jump(end); true_case.link(m_assembler); m_assembler.mov( Assembler::Operand::Register(GPR0), Assembler::Operand::Imm(Value(true).encoded())); - store_vm_register(Bytecode::Register::accumulator(), GPR0); + store_accumulator(GPR0); m_assembler.jump(end); }); native_call((void*)cxx_less_than); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); end.link(m_assembler); } @@ -574,9 +602,9 @@ static ThrowCompletionOr typeof_(VM& vm, Value value) \ void Compiler::compile_##snake_case_name(Bytecode::Op::TitleCaseName const&) \ { \ - load_vm_register(ARG1, Bytecode::Register::accumulator()); \ + load_accumulator(ARG1); \ native_call((void*)cxx_##snake_case_name); \ - store_vm_register(Bytecode::Register::accumulator(), RET); \ + store_accumulator(RET); \ check_exception(); \ } @@ -585,7 +613,7 @@ JS_ENUMERATE_COMMON_UNARY_OPS(DO_COMPILE_COMMON_UNARY_OP) void Compiler::compile_return(Bytecode::Op::Return const&) { - load_vm_register(GPR0, Bytecode::Register::accumulator()); + load_accumulator(GPR0); if (auto const* finalizer = current_block().finalizer(); finalizer) { store_vm_register(Bytecode::Register::saved_return_value(), GPR0); @@ -608,7 +636,7 @@ void Compiler::compile_new_string(Bytecode::Op::NewString const& op) Assembler::Operand::Register(ARG1), Assembler::Operand::Imm(bit_cast(&string))); native_call((void*)cxx_new_string); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); } void Compiler::compile_new_regexp(Bytecode::Op::NewRegExp const& op) @@ -628,7 +656,7 @@ void Compiler::compile_new_regexp(Bytecode::Op::NewRegExp const& op) Assembler::Operand::Imm(bit_cast(&flags))); native_call((void*)Bytecode::new_regexp); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); } static Value cxx_new_bigint(VM& vm, Crypto::SignedBigInteger const& bigint) @@ -642,7 +670,7 @@ void Compiler::compile_new_bigint(Bytecode::Op::NewBigInt const& op) Assembler::Operand::Register(ARG1), Assembler::Operand::Imm(bit_cast(&op.bigint()))); native_call((void*)cxx_new_bigint); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); } static Value cxx_new_object(VM& vm) @@ -654,7 +682,7 @@ static Value cxx_new_object(VM& vm) void Compiler::compile_new_object(Bytecode::Op::NewObject const&) { native_call((void*)cxx_new_object); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); } static Value cxx_new_array(VM& vm, size_t element_count, u32 first_register_index) @@ -677,7 +705,7 @@ void Compiler::compile_new_array(Bytecode::Op::NewArray const& op) Assembler::Operand::Register(ARG2), Assembler::Operand::Imm(op.element_count() ? op.start().index() : 0)); native_call((void*)cxx_new_array); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); } void Compiler::compile_new_function(Bytecode::Op::NewFunction const& op) @@ -692,24 +720,25 @@ void Compiler::compile_new_function(Bytecode::Op::NewFunction const& op) Assembler::Operand::Register(ARG3), Assembler::Operand::Imm(bit_cast(&op.home_object()))); native_call((void*)Bytecode::new_function); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); } -static Value cxx_new_class(VM& vm, ClassExpression const& class_expression, Optional const& lhs_name) +static Value cxx_new_class(VM& vm, Value super_class, ClassExpression const& class_expression, Optional const& lhs_name) { - return TRY_OR_SET_EXCEPTION(Bytecode::new_class(vm, class_expression, lhs_name)); + return TRY_OR_SET_EXCEPTION(Bytecode::new_class(vm, super_class, class_expression, lhs_name)); } void Compiler::compile_new_class(Bytecode::Op::NewClass const& op) { - m_assembler.mov( - Assembler::Operand::Register(ARG1), - Assembler::Operand::Imm(bit_cast(&op.class_expression()))); + load_accumulator(ARG1); m_assembler.mov( Assembler::Operand::Register(ARG2), + Assembler::Operand::Imm(bit_cast(&op.class_expression()))); + m_assembler.mov( + Assembler::Operand::Register(ARG3), Assembler::Operand::Imm(bit_cast(&op.lhs_name()))); native_call((void*)cxx_new_class); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); } static Value cxx_get_by_id(VM& vm, Value base, Bytecode::IdentifierTableIndex property, u32 cache_index) @@ -719,7 +748,7 @@ static Value cxx_get_by_id(VM& vm, Value base, Bytecode::IdentifierTableIndex pr void Compiler::compile_get_by_id(Bytecode::Op::GetById const& op) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); m_assembler.mov( Assembler::Operand::Register(ARG2), Assembler::Operand::Imm(op.property().value())); @@ -727,7 +756,7 @@ void Compiler::compile_get_by_id(Bytecode::Op::GetById const& op) Assembler::Operand::Register(ARG3), Assembler::Operand::Imm(op.cache_index())); native_call((void*)cxx_get_by_id); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -739,9 +768,9 @@ static Value cxx_get_by_value(VM& vm, Value base, Value property) void Compiler::compile_get_by_value(Bytecode::Op::GetByValue const& op) { load_vm_register(ARG1, op.base()); - load_vm_register(ARG2, Bytecode::Register::accumulator()); + load_accumulator(ARG2); native_call((void*)cxx_get_by_value); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -759,7 +788,7 @@ void Compiler::compile_get_global(Bytecode::Op::GetGlobal const& op) Assembler::Operand::Register(ARG2), Assembler::Operand::Imm(op.cache_index())); native_call((void*)cxx_get_global); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -777,7 +806,7 @@ void Compiler::compile_get_variable(Bytecode::Op::GetVariable const& op) Assembler::Operand::Register(ARG2), Assembler::Operand::Imm(op.cache_index())); native_call((void*)cxx_get_variable); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -821,11 +850,11 @@ void Compiler::compile_to_numeric(Bytecode::Op::ToNumeric const&) { Assembler::Label fast_case {}; - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); jump_if_int32(ARG1, fast_case); native_call((void*)cxx_to_numeric); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); fast_case.link(m_assembler); @@ -856,12 +885,12 @@ void Compiler::compile_resolve_this_binding(Bytecode::Op::ResolveThisBinding con slow_case); // Fast case: We have a cached `this` value! - store_vm_register(Bytecode::Register::accumulator(), GPR0); + store_accumulator(GPR0); auto end = m_assembler.jump(); slow_case.link(m_assembler); native_call((void*)cxx_resolve_this_binding); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); end.link(m_assembler); @@ -871,8 +900,7 @@ static Value cxx_put_by_id(VM& vm, Value base, Bytecode::IdentifierTableIndex pr { PropertyKey name = vm.bytecode_interpreter().current_executable().get_identifier(property); TRY_OR_SET_EXCEPTION(Bytecode::put_by_property_key(vm, base, base, value, name, kind)); - vm.bytecode_interpreter().accumulator() = value; - return {}; + return value; } void Compiler::compile_put_by_id(Bytecode::Op::PutById const& op) @@ -881,30 +909,31 @@ void Compiler::compile_put_by_id(Bytecode::Op::PutById const& op) m_assembler.mov( Assembler::Operand::Register(ARG2), Assembler::Operand::Imm(op.property().value())); - load_vm_register(ARG3, Bytecode::Register::accumulator()); + load_accumulator(ARG3); m_assembler.mov( Assembler::Operand::Register(ARG4), Assembler::Operand::Imm(to_underlying(op.kind()))); native_call((void*)cxx_put_by_id); + store_accumulator(RET); check_exception(); } static Value cxx_put_by_value(VM& vm, Value base, Value property, Value value, Bytecode::Op::PropertyKind kind) { TRY_OR_SET_EXCEPTION(Bytecode::put_by_value(vm, base, property, value, kind)); - vm.bytecode_interpreter().accumulator() = value; - return {}; + return value; } void Compiler::compile_put_by_value(Bytecode::Op::PutByValue const& op) { load_vm_register(ARG1, op.base()); load_vm_register(ARG2, op.property()); - load_vm_register(ARG3, Bytecode::Register::accumulator()); + load_accumulator(ARG3); m_assembler.mov( Assembler::Operand::Register(ARG4), Assembler::Operand::Imm(to_underlying(op.kind()))); native_call((void*)cxx_put_by_value); + store_accumulator(RET); check_exception(); } @@ -937,29 +966,30 @@ void Compiler::compile_call(Bytecode::Op::Call const& op) Assembler::Operand::Register(GPR0), Assembler::Operand::Imm(bit_cast(&op.expression_string()))); native_call((void*)cxx_call, { Assembler::Operand::Register(GPR0) }); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } -static Value cxx_call_with_argument_array(VM& vm, Value callee, Value this_value, Bytecode::Op::CallType call_type, Optional const& expression_string) +static Value cxx_call_with_argument_array(VM& vm, Value arguments, Value callee, Value this_value, Bytecode::Op::CallType call_type, Optional const& expression_string) { TRY_OR_SET_EXCEPTION(throw_if_needed_for_call(vm.bytecode_interpreter(), callee, call_type, expression_string)); - auto argument_values = argument_list_evaluation(vm.bytecode_interpreter()); + auto argument_values = Bytecode::argument_list_evaluation(vm, arguments); return TRY_OR_SET_EXCEPTION(perform_call(vm.bytecode_interpreter(), this_value, call_type, callee, move(argument_values))); } void Compiler::compile_call_with_argument_array(Bytecode::Op::CallWithArgumentArray const& op) { - load_vm_register(ARG1, op.callee()); - load_vm_register(ARG2, op.this_value()); - m_assembler.mov( - Assembler::Operand::Register(ARG3), - Assembler::Operand::Imm(to_underlying(op.call_type()))); + load_accumulator(ARG1); + load_vm_register(ARG2, op.callee()); + load_vm_register(ARG3, op.this_value()); m_assembler.mov( Assembler::Operand::Register(ARG4), + Assembler::Operand::Imm(to_underlying(op.call_type()))); + m_assembler.mov( + Assembler::Operand::Register(ARG5), Assembler::Operand::Imm(bit_cast(&op.expression_string()))); native_call((void*)cxx_call_with_argument_array); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -974,7 +1004,7 @@ void Compiler::compile_typeof_variable(Bytecode::Op::TypeofVariable const& op) Assembler::Operand::Register(ARG1), Assembler::Operand::Imm(bit_cast(&m_bytecode_executable.get_identifier(op.identifier().value())))); native_call((void*)cxx_typeof_variable); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1027,7 +1057,7 @@ void Compiler::compile_set_variable(Bytecode::Op::SetVariable const& op) m_assembler.mov( Assembler::Operand::Register(ARG1), Assembler::Operand::Imm(bit_cast(&m_bytecode_executable.get_identifier(op.identifier().value())))); - load_vm_register(ARG2, Bytecode::Register::accumulator()); + load_accumulator(ARG2); m_assembler.mov( Assembler::Operand::Register(ARG3), Assembler::Operand::Imm(to_underlying(op.mode()))); @@ -1091,7 +1121,7 @@ static Value cxx_concat_string(VM& vm, Value lhs, Value rhs) void Compiler::compile_concat_string(Bytecode::Op::ConcatString const& op) { load_vm_register(ARG1, op.lhs()); - load_vm_register(ARG2, Bytecode::Register::accumulator()); + load_accumulator(ARG2); native_call((void*)cxx_concat_string); store_vm_register(op.lhs(), RET); check_exception(); @@ -1120,12 +1150,12 @@ static Value cxx_super_call_with_argument_array(VM& vm, Value argument_array, bo void Compiler::compile_super_call_with_argument_array(Bytecode::Op::SuperCallWithArgumentArray const& op) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); m_assembler.mov( Assembler::Operand::Register(ARG2), Assembler::Operand::Imm(static_cast(op.is_synthetic()))); native_call((void*)cxx_super_call_with_argument_array); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1137,12 +1167,12 @@ static Value cxx_get_iterator(VM& vm, Value value, IteratorHint hint) void Compiler::compile_get_iterator(Bytecode::Op::GetIterator const& op) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); m_assembler.mov( Assembler::Operand::Register(ARG2), Assembler::Operand::Imm(to_underlying(op.hint()))); native_call((void*)cxx_get_iterator); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1155,9 +1185,9 @@ static Value cxx_iterator_next(VM& vm, Value iterator) void Compiler::compile_iterator_next(Bytecode::Op::IteratorNext const&) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); native_call((void*)cxx_iterator_next); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1169,9 +1199,9 @@ static Value cxx_iterator_result_done(VM& vm, Value iterator) void Compiler::compile_iterator_result_done(Bytecode::Op::IteratorResultDone const&) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); native_call((void*)cxx_iterator_result_done); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1184,7 +1214,7 @@ static Value cxx_throw_if_not_object(VM& vm, Value value) void Compiler::compile_throw_if_not_object(Bytecode::Op::ThrowIfNotObject const&) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); native_call((void*)cxx_throw_if_not_object); check_exception(); } @@ -1198,7 +1228,7 @@ static Value cxx_throw_if_nullish(VM& vm, Value value) void Compiler::compile_throw_if_nullish(Bytecode::Op::ThrowIfNullish const&) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); native_call((void*)cxx_throw_if_nullish); check_exception(); } @@ -1211,9 +1241,9 @@ static Value cxx_iterator_result_value(VM& vm, Value iterator) void Compiler::compile_iterator_result_value(Bytecode::Op::IteratorResultValue const&) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); native_call((void*)cxx_iterator_result_value); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1229,7 +1259,7 @@ static Value cxx_iterator_close(VM& vm, Value iterator, Completion::Type complet void Compiler::compile_iterator_close(Bytecode::Op::IteratorClose const& op) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); m_assembler.mov( Assembler::Operand::Register(ARG2), Assembler::Operand::Imm(to_underlying(op.completion_type()))); @@ -1247,9 +1277,9 @@ static Value iterator_to_array(VM& vm, Value iterator) void Compiler::compile_iterator_to_array(Bytecode::Op::IteratorToArray const&) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); native_call((void*)iterator_to_array); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1262,7 +1292,7 @@ static Value cxx_append(VM& vm, Value lhs, Value rhs, bool is_spread) void Compiler::compile_append(Bytecode::Op::Append const& op) { load_vm_register(ARG1, op.lhs()); - load_vm_register(ARG2, Bytecode::Register::accumulator()); + load_accumulator(ARG2); m_assembler.mov( Assembler::Operand::Register(ARG3), Assembler::Operand::Imm(static_cast(op.is_spread()))); @@ -1277,12 +1307,12 @@ static Value cxx_delete_by_id(VM& vm, Value base, Bytecode::IdentifierTableIndex void Compiler::compile_delete_by_id(Bytecode::Op::DeleteById const& op) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); m_assembler.mov( Assembler::Operand::Register(ARG2), Assembler::Operand::Imm(op.property().value())); native_call((void*)cxx_delete_by_id); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1294,9 +1324,9 @@ static Value cxx_delete_by_value(VM& vm, Value base_value, Value property_key_va void Compiler::compile_delete_by_value(Bytecode::Op::DeleteByValue const& op) { load_vm_register(ARG1, op.base()); - load_vm_register(ARG2, Bytecode::Register::accumulator()); + load_accumulator(ARG2); native_call((void*)cxx_delete_by_value); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1308,10 +1338,10 @@ static Value cxx_delete_by_value_with_this(VM& vm, Value base_value, Value prope void Compiler::compile_delete_by_value_with_this(Bytecode::Op::DeleteByValueWithThis const& op) { load_vm_register(ARG1, op.base()); - load_vm_register(ARG2, Bytecode::Register::accumulator()); + load_accumulator(ARG2); load_vm_register(ARG3, op.this_value()); native_call((void*)cxx_delete_by_value_with_this); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1322,9 +1352,9 @@ static Value cxx_get_object_property_iterator(VM& vm, Value object) void Compiler::compile_get_object_property_iterator(Bytecode::Op::GetObjectPropertyIterator const&) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); native_call((void*)cxx_get_object_property_iterator); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1336,12 +1366,12 @@ static Value cxx_get_private_by_id(VM& vm, Value base_value, DeprecatedFlyString void Compiler::compile_get_private_by_id(Bytecode::Op::GetPrivateById const& op) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); m_assembler.mov( Assembler::Operand::Register(ARG2), Assembler::Operand::Imm(bit_cast(&m_bytecode_executable.get_identifier(op.property())))); native_call((void*)cxx_get_private_by_id); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1360,7 +1390,7 @@ static Value cxx_resolve_super_base(VM& vm) void Compiler::compile_resolve_super_base(Bytecode::Op::ResolveSuperBase const&) { native_call((void*)cxx_resolve_super_base); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1374,13 +1404,13 @@ void Compiler::compile_get_by_id_with_this(Bytecode::Op::GetByIdWithThis const& m_assembler.mov( Assembler::Operand::Register(ARG1), Assembler::Operand::Imm(op.property().value())); - load_vm_register(ARG2, Bytecode::Register::accumulator()); + load_accumulator(ARG2); load_vm_register(ARG3, op.this_value()); m_assembler.mov( Assembler::Operand::Register(ARG4), Assembler::Operand::Imm(op.cache_index())); native_call((void*)cxx_get_by_id_with_this); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1393,11 +1423,11 @@ static Value cxx_get_by_value_with_this(VM& vm, Value property_key_value, Value void Compiler::compile_get_by_value_with_this(Bytecode::Op::GetByValueWithThis const& op) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); load_vm_register(ARG2, op.base()); load_vm_register(ARG3, op.this_value()); native_call((void*)cxx_get_by_value_with_this); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1409,13 +1439,13 @@ static Value cxx_delete_by_id_with_this(VM& vm, Value base_value, DeprecatedFlyS void Compiler::compile_delete_by_id_with_this(Bytecode::Op::DeleteByIdWithThis const& op) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); m_assembler.mov( Assembler::Operand::Register(ARG2), Assembler::Operand::Imm(bit_cast(&m_bytecode_executable.get_identifier(op.property())))); load_vm_register(ARG3, op.this_value()); native_call((void*)cxx_delete_by_id_with_this); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); } static Value cxx_put_by_id_with_this(VM& vm, Value base, Value value, DeprecatedFlyString const& name, Value this_value, Bytecode::Op::PropertyKind kind) @@ -1427,7 +1457,7 @@ static Value cxx_put_by_id_with_this(VM& vm, Value base, Value value, Deprecated void Compiler::compile_put_by_id_with_this(Bytecode::Op::PutByIdWithThis const& op) { load_vm_register(ARG1, op.base()); - load_vm_register(ARG2, Bytecode::Register::accumulator()); + load_accumulator(ARG2); m_assembler.mov( Assembler::Operand::Register(ARG3), Assembler::Operand::Imm(bit_cast(&m_bytecode_executable.get_identifier(op.property())))); @@ -1450,12 +1480,12 @@ static Value cxx_put_private_by_id(VM& vm, Value base, Value value, DeprecatedFl void Compiler::compile_put_private_by_id(Bytecode::Op::PutPrivateById const& op) { load_vm_register(ARG1, op.base()); - load_vm_register(ARG2, Bytecode::Register::accumulator()); + load_accumulator(ARG2); m_assembler.mov( Assembler::Operand::Register(ARG3), Assembler::Operand::Imm(bit_cast(&m_bytecode_executable.get_identifier(op.property())))); native_call((void*)cxx_put_private_by_id); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1469,7 +1499,7 @@ void Compiler::compile_import_call(Bytecode::Op::ImportCall const& op) load_vm_register(ARG1, op.specifier()); load_vm_register(ARG2, op.options()); native_call((void*)cxx_import_call); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1481,7 +1511,7 @@ static Value cxx_get_import_meta(VM& vm) void Compiler::compile_get_import_meta(Bytecode::Op::GetImportMeta const&) { native_call((void*)cxx_get_import_meta); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); } static Value cxx_delete_variable(VM& vm, DeprecatedFlyString const& identifier) @@ -1496,7 +1526,7 @@ void Compiler::compile_delete_variable(Bytecode::Op::DeleteVariable const& op) Assembler::Operand::Register(ARG1), Assembler::Operand::Imm(bit_cast(&m_bytecode_executable.get_identifier(op.identifier().value())))); native_call((void*)cxx_delete_variable); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1508,12 +1538,12 @@ static Value cxx_get_method(VM& vm, Value value, DeprecatedFlyString const& iden void Compiler::compile_get_method(Bytecode::Op::GetMethod const& op) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); m_assembler.mov( Assembler::Operand::Register(ARG2), Assembler::Operand::Imm(bit_cast(&m_bytecode_executable.get_identifier(op.property())))); native_call((void*)cxx_get_method); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1525,7 +1555,7 @@ static Value cxx_get_new_target(VM& vm) void Compiler::compile_get_new_target(Bytecode::Op::GetNewTarget const&) { native_call((void*)cxx_get_new_target); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); } static Value cxx_has_private_id(VM& vm, Value object, DeprecatedFlyString const& identifier) @@ -1541,12 +1571,12 @@ static Value cxx_has_private_id(VM& vm, Value object, DeprecatedFlyString const& void Compiler::compile_has_private_id(Bytecode::Op::HasPrivateId const& op) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); m_assembler.mov( Assembler::Operand::Register(ARG2), Assembler::Operand::Imm(bit_cast(&m_bytecode_executable.get_identifier(op.property())))); native_call((void*)cxx_has_private_id); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1562,7 +1592,7 @@ void Compiler::compile_has_private_id(Bytecode::Op::HasPrivateId const& op) Assembler::Operand::Register(ARG1), \ Assembler::Operand::Imm(bit_cast(&m_bytecode_executable.get_string(op.error_string())))); \ native_call((void*)cxx_##new_error_name); \ - store_vm_register(Bytecode::Register::accumulator(), RET); \ + store_accumulator(RET); \ } JS_ENUMERATE_NEW_BUILTIN_ERROR_BYTECODE_OPS(COMPILE_NEW_BUILTIN_ERROR_OP) # undef COMPILE_NEW_BUILTIN_ERROR_OP @@ -1577,7 +1607,7 @@ static Value cxx_put_by_value_with_this(VM& vm, Value base, Value value, Value n void Compiler::compile_put_by_value_with_this(Bytecode::Op::PutByValueWithThis const& op) { load_vm_register(ARG1, op.base()); - load_vm_register(ARG2, Bytecode::Register::accumulator()); + load_accumulator(ARG2); if (op.kind() != Bytecode::Op::PropertyKind::Spread) { load_vm_register(ARG3, op.property()); } else { @@ -1590,7 +1620,7 @@ void Compiler::compile_put_by_value_with_this(Bytecode::Op::PutByValueWithThis c Assembler::Operand::Register(ARG5), Assembler::Operand::Imm(to_underlying(op.kind()))); native_call((void*)cxx_put_by_value_with_this); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1628,7 +1658,7 @@ void Compiler::compile_copy_object_excluding_properties(Bytecode::Op::CopyObject // Restore the stack pointer / discard array. m_assembler.add(Assembler::Operand::Register(STACK_POINTER), Assembler::Operand::Imm(stack_space)); - store_vm_register(Bytecode::Register::accumulator(), RET); + store_accumulator(RET); check_exception(); } @@ -1644,7 +1674,7 @@ static Value cxx_async_iterator_close(VM& vm, Value iterator, Completion::Type c void Compiler::compile_async_iterator_close(Bytecode::Op::AsyncIteratorClose const& op) { - load_vm_register(ARG1, Bytecode::Register::accumulator()); + load_accumulator(ARG1); m_assembler.mov( Assembler::Operand::Register(ARG2), Assembler::Operand::Imm(to_underlying(op.completion_type()))); @@ -1704,6 +1734,8 @@ OwnPtr Compiler::compile(Bytecode::Executable& bytecode_execut Assembler::Operand::Register(LOCALS_ARRAY_BASE), Assembler::Operand::Register(ARG2)); + compiler.reload_cached_accumulator(); + for (size_t block_index = 0; block_index < bytecode_executable.basic_blocks.size(); block_index++) { auto& block = bytecode_executable.basic_blocks[block_index]; compiler.block_data_for(*block).start_offset = compiler.m_output.size(); @@ -1746,6 +1778,7 @@ OwnPtr Compiler::compile(Bytecode::Executable& bytecode_execut }); compiler.m_exit_label.link(compiler.m_assembler); + compiler.flush_cached_accumulator(); compiler.m_assembler.exit(); auto* executable_memory = mmap(nullptr, compiler.m_output.size(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); diff --git a/Userland/Libraries/LibJS/JIT/Compiler.h b/Userland/Libraries/LibJS/JIT/Compiler.h index 2f8f1fd8fc..121fb4aa26 100644 --- a/Userland/Libraries/LibJS/JIT/Compiler.h +++ b/Userland/Libraries/LibJS/JIT/Compiler.h @@ -37,6 +37,7 @@ private: static constexpr auto STACK_POINTER = Assembler::Reg::RSP; static constexpr auto REGISTER_ARRAY_BASE = Assembler::Reg::RBX; static constexpr auto LOCALS_ARRAY_BASE = Assembler::Reg::R14; + static constexpr auto CACHED_ACCUMULATOR = Assembler::Reg::R13; # endif # define JS_ENUMERATE_COMMON_BINARY_OPS_WITHOUT_FAST_PATH(O) \ @@ -153,6 +154,11 @@ private: void store_vm_local(size_t, Assembler::Reg); void load_vm_local(Assembler::Reg, size_t); + void reload_cached_accumulator(); + void flush_cached_accumulator(); + void load_accumulator(Assembler::Reg); + void store_accumulator(Assembler::Reg); + void compile_to_boolean(Assembler::Reg dst, Assembler::Reg src); void check_exception();