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:
Idan Horowitz 2023-10-29 15:29:42 +02:00 committed by Andreas Kling
parent f9cab320e6
commit 38f3b78a1d
Notes: sideshowbarker 2024-07-17 18:23:22 +09:00
5 changed files with 163 additions and 129 deletions

View file

@ -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.

View file

@ -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&);

View file

@ -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 {};
}

View file

@ -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);

View file

@ -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();