mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:12:45 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									f9cab320e6
								
							
						
					
					
						commit
						38f3b78a1d
					
				
					 5 changed files with 163 additions and 129 deletions
				
			
		|  | @ -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<Value> argument_list_evaluation(Bytecode::Interpreter& interpreter) | ||||
| MarkedVector<Value> 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<Value> 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<void> create_variable(VM& vm, DeprecatedFlyString const& name, | |||
|     return verify_cast<GlobalEnvironment>(vm.variable_environment())->create_global_var_binding(name, false); | ||||
| } | ||||
| 
 | ||||
| ThrowCompletionOr<ECMAScriptFunctionObject*> new_class(VM& vm, ClassExpression const& class_expression, Optional<IdentifierTableIndex> const& lhs_name) | ||||
| ThrowCompletionOr<ECMAScriptFunctionObject*> new_class(VM& vm, Value super_class, ClassExpression const& class_expression, Optional<IdentifierTableIndex> 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<ECMAScriptFunctionObject*> new_class(VM& vm, ClassExpression c | |||
| // 13.3.7.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation
 | ||||
| ThrowCompletionOr<NonnullGCPtr<Object>> 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<NonnullGCPtr<Object>> 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.
 | ||||
|  |  | |||
|  | @ -31,9 +31,9 @@ struct CalleeAndThis { | |||
| }; | ||||
| ThrowCompletionOr<CalleeAndThis> 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<Value> argument_list_evaluation(Bytecode::Interpreter&); | ||||
| MarkedVector<Value> argument_list_evaluation(VM&, Value arguments); | ||||
| ThrowCompletionOr<void> create_variable(VM&, DeprecatedFlyString const& name, Op::EnvironmentMode, bool is_global, bool is_immutable, bool is_strict); | ||||
| ThrowCompletionOr<ECMAScriptFunctionObject*> new_class(VM&, ClassExpression const&, Optional<IdentifierTableIndex> const& lhs_name); | ||||
| ThrowCompletionOr<ECMAScriptFunctionObject*> new_class(VM&, Value super_class, ClassExpression const&, Optional<IdentifierTableIndex> const& lhs_name); | ||||
| ThrowCompletionOr<NonnullGCPtr<Object>> super_call_with_argument_array(VM&, Value argument_array, bool is_synthetic); | ||||
| Object* iterator_to_object(VM&, IteratorRecord); | ||||
| IteratorRecord object_to_iterator(VM&, Object&); | ||||
|  |  | |||
|  | @ -934,7 +934,7 @@ ThrowCompletionOr<void> 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<void> IteratorResultValue::execute_impl(Bytecode::Interpreter& | |||
| 
 | ||||
| ThrowCompletionOr<void> 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 {}; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<Value> 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<Value> 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<u64>(&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<u64>(&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<u64>(&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<u64>(&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<Bytecode::IdentifierTableIndex> const& lhs_name) | ||||
| static Value cxx_new_class(VM& vm, Value super_class, ClassExpression const& class_expression, Optional<Bytecode::IdentifierTableIndex> 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<u64>(&op.class_expression()))); | ||||
|     load_accumulator(ARG1); | ||||
|     m_assembler.mov( | ||||
|         Assembler::Operand::Register(ARG2), | ||||
|         Assembler::Operand::Imm(bit_cast<u64>(&op.class_expression()))); | ||||
|     m_assembler.mov( | ||||
|         Assembler::Operand::Register(ARG3), | ||||
|         Assembler::Operand::Imm(bit_cast<u64>(&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<u64>(&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<Bytecode::StringTableIndex> 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<Bytecode::StringTableIndex> 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<u64>(&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<u64>(&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<u64>(&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<u64>(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<u64>(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<u64>(&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<u64>(&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<u64>(&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<u64>(&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<u64>(&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<u64>(&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<u64>(&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<u64>(&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<NativeExecutable> 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<NativeExecutable> 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); | ||||
|  |  | |||
|  | @ -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(); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Idan Horowitz
						Idan Horowitz