diff --git a/deps/v8/src/bootstrapper.cc b/deps/v8/src/bootstrapper.cc index 5142817986cc56..cfea3208c9d7f1 100644 --- a/deps/v8/src/bootstrapper.cc +++ b/deps/v8/src/bootstrapper.cc @@ -1206,6 +1206,7 @@ void Genesis::InitializeGlobal(Handle global_object, JSObject::kHeaderSize, MaybeHandle(), Builtins::kFunctionPrototypeHasInstance, static_cast(DONT_ENUM | DONT_DELETE | READ_ONLY)); + native_context()->set_function_has_instance(*has_instance); // Set the expected parameters for @@hasInstance to 1; required by builtin. has_instance->shared()->set_internal_formal_parameter_count(1); diff --git a/deps/v8/src/contexts.h b/deps/v8/src/contexts.h index d73135f7a44047..fd5b006192b4ad 100644 --- a/deps/v8/src/contexts.h +++ b/deps/v8/src/contexts.h @@ -78,6 +78,7 @@ enum ContextLookupFlags { V(MAP_GET_METHOD_INDEX, JSFunction, map_get) \ V(MAP_HAS_METHOD_INDEX, JSFunction, map_has) \ V(MAP_SET_METHOD_INDEX, JSFunction, map_set) \ + V(FUNCTION_HAS_INSTANCE_INDEX, JSFunction, function_has_instance) \ V(OBJECT_VALUE_OF, JSFunction, object_value_of) \ V(OBJECT_TO_STRING, JSFunction, object_to_string) \ V(PROMISE_CATCH_INDEX, JSFunction, promise_catch) \ diff --git a/deps/v8/src/crankshaft/hydrogen.cc b/deps/v8/src/crankshaft/hydrogen.cc index a33d2a61200753..f40337e645f96b 100644 --- a/deps/v8/src/crankshaft/hydrogen.cc +++ b/deps/v8/src/crankshaft/hydrogen.cc @@ -11563,24 +11563,37 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { HConstant::cast(right)->handle(isolate())->IsJSFunction()) { Handle function = Handle::cast(HConstant::cast(right)->handle(isolate())); - // Make sure the prototype of {function} is the %FunctionPrototype%, and - // it already has a meaningful initial map (i.e. we constructed at least - // one instance using the constructor {function}). - // We can only use the fast case if @@hasInstance was not used so far. - if (function->has_initial_map() && - function->map()->prototype() == - function->native_context()->closure() && - !function->map()->has_non_instance_prototype() && - isolate()->IsHasInstanceLookupChainIntact()) { - Handle initial_map(function->initial_map(), isolate()); - top_info()->dependencies()->AssumeInitialMapCantChange(initial_map); - top_info()->dependencies()->AssumePropertyCell( - isolate()->factory()->has_instance_protector()); - HInstruction* prototype = - Add(handle(initial_map->prototype(), isolate())); - HHasInPrototypeChainAndBranch* result = - New(left, prototype); - return ast_context()->ReturnControl(result, expr->id()); + // Make sure that the {function} already has a meaningful initial map + // (i.e. we constructed at least one instance using the constructor + // {function}). + if (function->has_initial_map()) { + // Lookup @@hasInstance on the {function}. + Handle function_map(function->map(), isolate()); + PropertyAccessInfo has_instance( + this, LOAD, function_map, + isolate()->factory()->has_instance_symbol()); + // Check if we are using the Function.prototype[@@hasInstance]. + if (has_instance.CanAccessMonomorphic() && + has_instance.IsDataConstant() && + has_instance.constant().is_identical_to( + isolate()->function_has_instance())) { + // Add appropriate receiver map check and prototype chain + // checks to guard the @@hasInstance lookup chain. + AddCheckMap(right, function_map); + if (has_instance.has_holder()) { + Handle prototype( + JSObject::cast(has_instance.map()->prototype()), isolate()); + BuildCheckPrototypeMaps(prototype, has_instance.holder()); + } + // Perform the prototype chain walk. + Handle initial_map(function->initial_map(), isolate()); + top_info()->dependencies()->AssumeInitialMapCantChange(initial_map); + HInstruction* prototype = + Add(handle(initial_map->prototype(), isolate())); + HHasInPrototypeChainAndBranch* result = + New(left, prototype); + return ast_context()->ReturnControl(result, expr->id()); + } } }