Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Unified Diff: src/code-stub-assembler.cc

Issue 2930243002: [WIP] Refactor OrdinaryHasInstance to be self-contained.
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/external-reference-table.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/code-stub-assembler.cc
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
index 000c064a7057d072cca4c9c14fb0b2223f1cdc17..50fcfa19bdd12373b984b31841a36642b8cba7c0 100644
--- a/src/code-stub-assembler.cc
+++ b/src/code-stub-assembler.cc
@@ -1,7 +1,10 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+
#include "src/code-stub-assembler.h"
+
+#include "src/builtins/builtins-descriptors.h"
#include "src/code-factory.h"
#include "src/frames-inl.h"
#include "src/frames.h"
@@ -5997,60 +6000,78 @@ void CodeStubAssembler::TryPrototypeChainLookup(
Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
Node* object) {
VARIABLE(var_result, MachineRepresentation::kTagged);
- Label return_false(this), return_true(this),
+ Label return_false(this, Label::kDeferred), return_true(this),
+ return_instanceof(this, Label::kDeferred),
return_runtime(this, Label::kDeferred), return_result(this);
- // Goto runtime if {object} is a Smi.
- GotoIf(TaggedIsSmi(object), &return_runtime);
-
- // Load map of {object}.
- Node* object_map = LoadMap(object);
-
- // Goto runtime if {callable} is a Smi.
- GotoIf(TaggedIsSmi(callable), &return_runtime);
-
- // Load map of {callable}.
+ // Return false if {callable} is not Callable.
+ GotoIf(TaggedIsSmi(callable), &return_false);
Node* callable_map = LoadMap(callable);
+ GotoIfNot(IsCallableMap(callable_map), &return_false);
- // Goto runtime if {callable} is not a JSFunction.
+ // If {callable} is a JSBoundFunction, call the instanceof operator
+ // recursively with the bound target function.
Node* callable_instance_type = LoadMapInstanceType(callable_map);
- GotoIfNot(
- Word32Equal(callable_instance_type, Int32Constant(JS_FUNCTION_TYPE)),
- &return_runtime);
+ GotoIf(InstanceTypeEqual(callable_instance_type, JS_BOUND_FUNCTION_TYPE),
+ &return_instanceof);
- // Goto runtime if {callable} is not a constructor or has
- // a non-instance "prototype".
+ // Return false if {object} is not a JSReceiver.
+ GotoIf(TaggedIsSmi(object), &return_false);
+ Node* object_map = LoadMap(object);
+ GotoIfNot(IsJSReceiverMap(object_map), &return_false);
+
+ // Load the "prototype" from the {callable}. We have a fast-path here for
+ // JSFunction objects that are marked as constructors and have an instance
+ // "prototype".
+ VARIABLE(var_callable_prototype, MachineRepresentation::kTagged);
+ Label fast_callable_prototype(this),
+ slow_callable_prototype(this, Label::kDeferred),
+ done_callable_prototype(this);
+ GotoIfNot(IsJSFunctionInstanceType(callable_instance_type),
+ &slow_callable_prototype);
Node* callable_bitfield = LoadMapBitField(callable_map);
- GotoIfNot(
+ Branch(
Word32Equal(Word32And(callable_bitfield,
Int32Constant((1 << Map::kHasNonInstancePrototype) |
(1 << Map::kIsConstructor))),
Int32Constant(1 << Map::kIsConstructor)),
- &return_runtime);
-
- // Get the "prototype" (or initial map) of the {callable}.
- Node* callable_prototype =
- LoadObjectField(callable, JSFunction::kPrototypeOrInitialMapOffset);
- {
- Label callable_prototype_valid(this);
- VARIABLE(var_callable_prototype, MachineRepresentation::kTagged,
- callable_prototype);
-
- // Resolve the "prototype" if the {callable} has an initial map. Afterwards
- // the {callable_prototype} will be either the JSReceiver prototype object
- // or the hole value, which means that no instances of the {callable} were
- // created so far and hence we should return false.
- Node* callable_prototype_instance_type =
- LoadInstanceType(callable_prototype);
- GotoIfNot(
- Word32Equal(callable_prototype_instance_type, Int32Constant(MAP_TYPE)),
- &callable_prototype_valid);
+ &fast_callable_prototype, &slow_callable_prototype);
+ BIND(&fast_callable_prototype);
+ {
+ // Get the "prototype" (or initial map) of the {callable}.
+ Node* callable_prototype =
+ LoadObjectField(callable, JSFunction::kPrototypeOrInitialMapOffset);
+ var_callable_prototype.Bind(callable_prototype);
+
+ // Resolve the "prototype" if the {callable} has an initial map.
+ // Afterwards the {callable_prototype} will be either the JSReceiver
+ // prototype object or the hole value, which means that no instances of
+ // the {callable} were created so far and hence we should return false.
+ GotoIfNot(IsMap(callable_prototype), &done_callable_prototype);
var_callable_prototype.Bind(
LoadObjectField(callable_prototype, Map::kPrototypeOffset));
- Goto(&callable_prototype_valid);
- BIND(&callable_prototype_valid);
- callable_prototype = var_callable_prototype.value();
+ Goto(&done_callable_prototype);
+ }
+ BIND(&slow_callable_prototype);
+ {
+ // Generic "prototype" lookup on the {callable}, including check
+ // that the resulting prototype is a proper JSReceiver.
+ Label callable_prototype_not_receiver(this, Label::kDeferred);
+ Node* callable_prototype =
+ GetProperty(context, callable, PrototypeStringConstant());
+ GotoIf(TaggedIsSmi(callable_prototype), &callable_prototype_not_receiver);
+ var_callable_prototype.Bind(callable_prototype);
+ Branch(IsJSReceiver(callable_prototype), &done_callable_prototype,
+ &callable_prototype_not_receiver);
+ BIND(&callable_prototype_not_receiver);
+ {
+ CallRuntime(Runtime::kThrowInstanceofNonobjectProto, context,
+ callable_prototype);
+ Unreachable();
+ }
}
+ BIND(&done_callable_prototype);
+ Node* callable_prototype = var_callable_prototype.value();
// Loop through the prototype chain looking for the {callable} prototype.
VARIABLE(var_object_map, MachineRepresentation::kTagged, object_map);
@@ -6058,9 +6079,8 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
Goto(&loop);
BIND(&loop);
{
- Node* object_map = var_object_map.value();
-
// Check if the current {object} needs to be access checked.
+ Node* object_map = var_object_map.value();
Node* object_bitfield = LoadMapBitField(object_map);
GotoIfNot(
Word32Equal(Word32And(object_bitfield,
@@ -6070,7 +6090,7 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
// Check if the current {object} is a proxy.
Node* object_instance_type = LoadMapInstanceType(object_map);
- GotoIf(Word32Equal(object_instance_type, Int32Constant(JS_PROXY_TYPE)),
+ GotoIf(InstanceTypeEqual(object_instance_type, JS_PROXY_TYPE),
&return_runtime);
// Check the current {object} prototype.
@@ -6094,8 +6114,21 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
BIND(&return_runtime);
{
// Fallback to the runtime implementation.
- var_result.Bind(
- CallRuntime(Runtime::kOrdinaryHasInstance, context, callable, object));
+ var_result.Bind(CallRuntime(Runtime::kHasInPrototypeChain, context, object,
+ callable_prototype));
+ }
+ Goto(&return_result);
+
+ BIND(&return_instanceof);
+ {
+ // Use the InstanceOf algorithm on the [[BoundTargetFunction]].
+ ExternalReference ref(Builtins::kInstanceOf, isolate());
+ Node* code = Load(MachineType::AnyTagged(), ExternalConstant(ref));
+ Node* bound_target_function =
+ LoadObjectField(callable, JSBoundFunction::kBoundTargetFunctionOffset);
+ Node* result = CallStub(Builtin_InstanceOf_InterfaceDescriptor(isolate()),
+ code, context, object, bound_target_function);
+ var_result.Bind(result);
}
Goto(&return_result);
@@ -8758,8 +8791,8 @@ Node* CodeStubAssembler::InstanceOf(Node* object, Node* callable,
GotoIfNot(IsCallable(callable), &if_notcallable);
// Use the OrdinaryHasInstance algorithm.
- Node* result = CallStub(CodeFactory::OrdinaryHasInstance(isolate()),
- context, callable, object);
+ Node* result =
+ CallBuiltin(Builtins::kOrdinaryHasInstance, context, callable, object);
var_result.Bind(result);
Goto(&return_result);
}
« no previous file with comments | « no previous file | src/external-reference-table.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698