mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 07:47:35 +00:00
LibJS: Introduce Builtins
Builtins are functions that can be detected during bytecode generation and enable fast-paths in the JIT.
This commit is contained in:
parent
b9141d85d8
commit
86b85aa68b
13 changed files with 191 additions and 4 deletions
|
@ -2518,9 +2518,56 @@ static Value cxx_call(VM& vm, Value callee, u32 first_argument_index, u32 argume
|
|||
return TRY_OR_SET_EXCEPTION(perform_call(vm.bytecode_interpreter(), this_value, call_type, callee, move(argument_values)));
|
||||
}
|
||||
|
||||
Assembler::Reg Compiler::argument_register(u32 index)
|
||||
{
|
||||
switch (index) {
|
||||
case 0:
|
||||
return ARG0;
|
||||
case 1:
|
||||
return ARG1;
|
||||
case 2:
|
||||
return ARG2;
|
||||
case 3:
|
||||
return ARG3;
|
||||
case 4:
|
||||
return ARG4;
|
||||
case 5:
|
||||
return ARG5;
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
void Compiler::compile_call(Bytecode::Op::Call const& op)
|
||||
{
|
||||
Assembler::Label slow_case {};
|
||||
Assembler::Label end {};
|
||||
load_vm_register(ARG1, op.callee());
|
||||
if (op.call_type() == Bytecode::Op::CallType::Call && op.builtin().has_value() && op.argument_count() == Bytecode::builtin_argument_count(op.builtin().value())) {
|
||||
auto builtin = op.builtin().value();
|
||||
|
||||
// GPR0 = vm.running_execution_context().realm;
|
||||
m_assembler.mov(
|
||||
Assembler::Operand::Register(GPR0),
|
||||
Assembler::Operand::Mem64BaseAndOffset(RUNNING_EXECUTION_CONTEXT_BASE, ExecutionContext::realm_offset()));
|
||||
|
||||
// GPR0 = GPR0->m_builtins[to_underlying(builtin)]
|
||||
m_assembler.mov(
|
||||
Assembler::Operand::Register(GPR0),
|
||||
Assembler::Operand::Mem64BaseAndOffset(GPR0, Realm::builtins_offset() + sizeof(Value) * to_underlying(builtin)));
|
||||
|
||||
// if (callee != GPR0) goto slow_case;
|
||||
m_assembler.jump_if(
|
||||
Assembler::Operand::Register(ARG1),
|
||||
Assembler::Condition::NotEqualTo,
|
||||
Assembler::Operand::Register(GPR0),
|
||||
slow_case);
|
||||
|
||||
// Load arguments into ARG2, ARG3, ...
|
||||
for (u32 arg = 0; arg < op.argument_count(); arg++)
|
||||
load_vm_register(argument_register(arg + 2), Bytecode::Register { op.first_argument().index() + arg });
|
||||
compile_builtin(builtin, slow_case, end);
|
||||
}
|
||||
slow_case.link(m_assembler);
|
||||
m_assembler.mov(
|
||||
Assembler::Operand::Register(ARG2),
|
||||
Assembler::Operand::Imm(op.first_argument().index()));
|
||||
|
@ -2537,6 +2584,21 @@ void Compiler::compile_call(Bytecode::Op::Call const& op)
|
|||
native_call((void*)cxx_call, { Assembler::Operand::Register(GPR0) });
|
||||
store_accumulator(RET);
|
||||
check_exception();
|
||||
end.link(m_assembler);
|
||||
}
|
||||
|
||||
void Compiler::compile_builtin(Bytecode::Builtin builtin, [[maybe_unused]] Assembler::Label& slow_case, [[maybe_unused]] Assembler::Label& end)
|
||||
{
|
||||
switch (builtin) {
|
||||
# define DEFINE_BUILTIN_CASE(name, snake_case_name, ...) \
|
||||
case Bytecode::Builtin::name: \
|
||||
compile_builtin_##snake_case_name(slow_case, end); \
|
||||
break;
|
||||
JS_ENUMERATE_BUILTINS(DEFINE_BUILTIN_CASE)
|
||||
# undef DEFINE_BUILTIN_CASE
|
||||
case Bytecode::Builtin::__Count:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <AK/Platform.h>
|
||||
#include <LibJIT/Assembler.h>
|
||||
#include <LibJS/Bytecode/Builtins.h>
|
||||
#include <LibJS/Bytecode/Executable.h>
|
||||
#include <LibJS/Bytecode/Op.h>
|
||||
#include <LibJS/JIT/NativeExecutable.h>
|
||||
|
@ -44,6 +45,8 @@ private:
|
|||
static constexpr auto RUNNING_EXECUTION_CONTEXT_BASE = Assembler::Reg::R15;
|
||||
# endif
|
||||
|
||||
static Assembler::Reg argument_register(u32);
|
||||
|
||||
# define JS_ENUMERATE_COMMON_BINARY_OPS_WITHOUT_FAST_PATH(O) \
|
||||
O(Div, div) \
|
||||
O(Exp, exp) \
|
||||
|
@ -147,6 +150,12 @@ private:
|
|||
JS_ENUMERATE_IMPLEMENTED_JIT_OPS(DECLARE_COMPILE_OP)
|
||||
# undef DECLARE_COMPILE_OP
|
||||
|
||||
void compile_builtin(Bytecode::Builtin, Assembler::Label& slow_case, Assembler::Label& end);
|
||||
# define DECLARE_COMPILE_BUILTIN(name, snake_case_name, ...) \
|
||||
void compile_builtin_##snake_case_name(Assembler::Label& slow_case, Assembler::Label& end);
|
||||
JS_ENUMERATE_BUILTINS(DECLARE_COMPILE_BUILTIN)
|
||||
# undef DECLARE_COMPILE_BUILTIN
|
||||
|
||||
void store_vm_register(Bytecode::Register, Assembler::Reg);
|
||||
void load_vm_register(Assembler::Reg, Bytecode::Register);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue