mirror of
https://github.com/zebrajr/ladybird.git
synced 2025-12-06 00:19:53 +01:00
LibJS: Avoid function call if @@hasInstance is default implementation
This makes the instanceof operator signficantly faster by avoiding a generic function call to @@hasInstance unless it has been overridden. 1.15x speed-up on Octane/earley-boyer.js
This commit is contained in:
parent
5a7b0a07cb
commit
0e4450f4b3
|
|
@ -26,6 +26,7 @@ namespace JS::Bytecode {
|
|||
O(MathSin, math_sin, Math, sin, 1) \
|
||||
O(MathCos, math_cos, Math, cos, 1) \
|
||||
O(MathTan, math_tan, Math, tan, 1) \
|
||||
O(OrdinaryHasInstance, ordinary_has_instance, InternalBuiltin, ordinary_has_instance, 1) \
|
||||
O(ArrayIteratorPrototypeNext, array_iterator_prototype_next, ArrayIteratorPrototype, next, 0) \
|
||||
O(MapIteratorPrototypeNext, map_iterator_prototype_next, MapIteratorPrototype, next, 0) \
|
||||
O(SetIteratorPrototypeNext, set_iterator_prototype_next, SetIteratorPrototype, next, 0) \
|
||||
|
|
|
|||
|
|
@ -2904,6 +2904,8 @@ static ThrowCompletionOr<Value> dispatch_builtin_call(Bytecode::Interpreter& int
|
|||
case Builtin::SetIteratorPrototypeNext:
|
||||
case Builtin::StringIteratorPrototypeNext:
|
||||
VERIFY_NOT_REACHED();
|
||||
case Builtin::OrdinaryHasInstance:
|
||||
VERIFY_NOT_REACHED();
|
||||
case Bytecode::Builtin::__Count:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ void FunctionPrototype::initialize(Realm& realm)
|
|||
define_native_function(realm, vm.names.bind, bind, 1, attr);
|
||||
define_native_function(realm, vm.names.call, call, 1, attr);
|
||||
define_native_function(realm, vm.names.toString, to_string, 0, attr);
|
||||
define_native_function(realm, vm.well_known_symbol_has_instance(), symbol_has_instance, 1, 0);
|
||||
define_native_function(realm, vm.well_known_symbol_has_instance(), symbol_has_instance, 1, 0, Bytecode::Builtin::OrdinaryHasInstance);
|
||||
define_direct_property(vm.names.length, Value(0), Attribute::Configurable);
|
||||
define_direct_property(vm.names.name, PrimitiveString::create(vm, String {}), Attribute::Configurable);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ public:
|
|||
bool is_set_prototype_next_builtin() const { return m_builtin.has_value() && *m_builtin == Bytecode::Builtin::SetIteratorPrototypeNext; }
|
||||
bool is_string_prototype_next_builtin() const { return m_builtin.has_value() && *m_builtin == Bytecode::Builtin::StringIteratorPrototypeNext; }
|
||||
|
||||
Optional<Bytecode::Builtin> builtin() const { return m_builtin; }
|
||||
|
||||
protected:
|
||||
NativeFunction(Utf16FlyString name, Object& prototype);
|
||||
NativeFunction(AK::Function<ThrowCompletionOr<Value>(VM&)>, Object* prototype, Realm& realm, Optional<Bytecode::Builtin> builtin);
|
||||
|
|
|
|||
|
|
@ -2172,6 +2172,12 @@ ThrowCompletionOr<Value> instance_of(VM& vm, Value value, Value target)
|
|||
|
||||
// 3. If instOfHandler is not undefined, then
|
||||
if (instance_of_handler) {
|
||||
// OPTIMIZATION: If the handler is the default OrdinaryHasInstance, we can skip doing a generic call.
|
||||
if (auto* native_function = as_if<NativeFunction>(*instance_of_handler)) {
|
||||
if (native_function->builtin() == Bytecode::Builtin::OrdinaryHasInstance) {
|
||||
return ordinary_has_instance(vm, value, target);
|
||||
}
|
||||
}
|
||||
// a. Return ToBoolean(? Call(instOfHandler, target, « V »)).
|
||||
return Value(TRY(call(vm, *instance_of_handler, target, value)).to_boolean());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user