mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 22:07:34 +00:00
LibJS: Call builtins directly in the bytecode interpreter
Allows the bytecode interpreter to call the builtins c++ implementation directly without making a javascript call just as the JIT. Kraken test speedups: imaging-gaussian-blur.js (1.5x) and audio-oscillator.js (1.2x)
This commit is contained in:
parent
ce6cd4f45f
commit
e335354b30
4 changed files with 46 additions and 3 deletions
|
@ -27,6 +27,7 @@
|
||||||
#include <LibJS/Runtime/GlobalEnvironment.h>
|
#include <LibJS/Runtime/GlobalEnvironment.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
#include <LibJS/Runtime/Iterator.h>
|
#include <LibJS/Runtime/Iterator.h>
|
||||||
|
#include <LibJS/Runtime/MathObject.h>
|
||||||
#include <LibJS/Runtime/NativeFunction.h>
|
#include <LibJS/Runtime/NativeFunction.h>
|
||||||
#include <LibJS/Runtime/ObjectEnvironment.h>
|
#include <LibJS/Runtime/ObjectEnvironment.h>
|
||||||
#include <LibJS/Runtime/Realm.h>
|
#include <LibJS/Runtime/Realm.h>
|
||||||
|
@ -970,6 +971,33 @@ ThrowCompletionOr<void> JumpUndefined::execute_impl(Bytecode::Interpreter&) cons
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ThrowCompletionOr<Value> dispatch_builtin_call(Bytecode::Interpreter& interpreter, Bytecode::Builtin builtin, Register first_argument)
|
||||||
|
{
|
||||||
|
switch (builtin) {
|
||||||
|
case Builtin::MathAbs:
|
||||||
|
return TRY(MathObject::abs_impl(interpreter.vm(), interpreter.reg(first_argument)));
|
||||||
|
case Builtin::MathLog:
|
||||||
|
return TRY(MathObject::log_impl(interpreter.vm(), interpreter.reg(first_argument)));
|
||||||
|
case Builtin::MathPow: {
|
||||||
|
auto exponent = interpreter.reg(Register { first_argument.index() + 1 });
|
||||||
|
return TRY(MathObject::pow_impl(interpreter.vm(), interpreter.reg(first_argument), exponent));
|
||||||
|
}
|
||||||
|
case Builtin::MathExp:
|
||||||
|
return TRY(MathObject::exp_impl(interpreter.vm(), interpreter.reg(first_argument)));
|
||||||
|
case Builtin::MathCeil:
|
||||||
|
return TRY(MathObject::ceil_impl(interpreter.vm(), interpreter.reg(first_argument)));
|
||||||
|
case Builtin::MathFloor:
|
||||||
|
return TRY(MathObject::floor_impl(interpreter.vm(), interpreter.reg(first_argument)));
|
||||||
|
case Builtin::MathRound:
|
||||||
|
return TRY(MathObject::round_impl(interpreter.vm(), interpreter.reg(first_argument)));
|
||||||
|
case Builtin::MathSqrt:
|
||||||
|
return TRY(MathObject::sqrt_impl(interpreter.vm(), interpreter.reg(first_argument)));
|
||||||
|
case Bytecode::Builtin::__Count:
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
ThrowCompletionOr<void> Call::execute_impl(Bytecode::Interpreter& interpreter) const
|
ThrowCompletionOr<void> Call::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||||
{
|
{
|
||||||
auto& vm = interpreter.vm();
|
auto& vm = interpreter.vm();
|
||||||
|
@ -977,6 +1005,11 @@ ThrowCompletionOr<void> Call::execute_impl(Bytecode::Interpreter& interpreter) c
|
||||||
|
|
||||||
TRY(throw_if_needed_for_call(interpreter, callee, call_type(), expression_string()));
|
TRY(throw_if_needed_for_call(interpreter, callee, call_type(), expression_string()));
|
||||||
|
|
||||||
|
if (m_builtin.has_value() && m_argument_count == Bytecode::builtin_argument_count(m_builtin.value()) && interpreter.realm().get_builtin_value(m_builtin.value()) == callee) {
|
||||||
|
interpreter.accumulator() = TRY(dispatch_builtin_call(interpreter, m_builtin.value(), m_first_argument));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
MarkedVector<Value> argument_values(vm.heap());
|
MarkedVector<Value> argument_values(vm.heap());
|
||||||
argument_values.ensure_capacity(m_argument_count);
|
argument_values.ensure_capacity(m_argument_count);
|
||||||
for (u32 i = 0; i < m_argument_count; ++i) {
|
for (u32 i = 0; i < m_argument_count; ++i) {
|
||||||
|
|
|
@ -80,10 +80,8 @@ void MathObject::initialize(Realm& realm)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 21.3.2.1 Math.abs ( x ), https://tc39.es/ecma262/#sec-math.abs
|
// 21.3.2.1 Math.abs ( x ), https://tc39.es/ecma262/#sec-math.abs
|
||||||
JS_DEFINE_NATIVE_FUNCTION(MathObject::abs)
|
ThrowCompletionOr<Value> MathObject::abs_impl(VM& vm, Value x)
|
||||||
{
|
{
|
||||||
auto x = vm.argument(0);
|
|
||||||
|
|
||||||
// OPTIMIZATION: Fast path for Int32 values.
|
// OPTIMIZATION: Fast path for Int32 values.
|
||||||
if (x.is_int32())
|
if (x.is_int32())
|
||||||
return Value(AK::abs(x.as_i32()));
|
return Value(AK::abs(x.as_i32()));
|
||||||
|
@ -108,6 +106,12 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::abs)
|
||||||
return Value(number.as_double() < 0 ? -number.as_double() : number.as_double());
|
return Value(number.as_double() < 0 ? -number.as_double() : number.as_double());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 21.3.2.1 Math.abs ( x ), https://tc39.es/ecma262/#sec-math.abs
|
||||||
|
JS_DEFINE_NATIVE_FUNCTION(MathObject::abs)
|
||||||
|
{
|
||||||
|
return abs_impl(vm, vm.argument(0));
|
||||||
|
}
|
||||||
|
|
||||||
// 21.3.2.2 Math.acos ( x ), https://tc39.es/ecma262/#sec-math.acos
|
// 21.3.2.2 Math.acos ( x ), https://tc39.es/ecma262/#sec-math.acos
|
||||||
JS_DEFINE_NATIVE_FUNCTION(MathObject::acos)
|
JS_DEFINE_NATIVE_FUNCTION(MathObject::acos)
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,6 +25,7 @@ public:
|
||||||
static ThrowCompletionOr<Value> ceil_impl(VM&, Value);
|
static ThrowCompletionOr<Value> ceil_impl(VM&, Value);
|
||||||
static ThrowCompletionOr<Value> round_impl(VM&, Value);
|
static ThrowCompletionOr<Value> round_impl(VM&, Value);
|
||||||
static ThrowCompletionOr<Value> exp_impl(VM&, Value);
|
static ThrowCompletionOr<Value> exp_impl(VM&, Value);
|
||||||
|
static ThrowCompletionOr<Value> abs_impl(VM&, Value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit MathObject(Realm&);
|
explicit MathObject(Realm&);
|
||||||
|
|
|
@ -57,6 +57,11 @@ public:
|
||||||
m_builtins[to_underlying(builtin)] = value;
|
m_builtins[to_underlying(builtin)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value get_builtin_value(Bytecode::Builtin builtin)
|
||||||
|
{
|
||||||
|
return m_builtins[to_underlying(builtin)];
|
||||||
|
}
|
||||||
|
|
||||||
static FlatPtr global_environment_offset() { return OFFSET_OF(Realm, m_global_environment); }
|
static FlatPtr global_environment_offset() { return OFFSET_OF(Realm, m_global_environment); }
|
||||||
static FlatPtr builtins_offset() { return OFFSET_OF(Realm, m_builtins); }
|
static FlatPtr builtins_offset() { return OFFSET_OF(Realm, m_builtins); }
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue