| Index: src/code-stub-assembler.cc
|
| diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
|
| index 56778b500277c5f880f7f5548a70b1d72d3b6147..ce7e4137ad0ed01f0b84c2ab49bcb6bfbe12bb3a 100644
|
| --- a/src/code-stub-assembler.cc
|
| +++ b/src/code-stub-assembler.cc
|
| @@ -5997,18 +5997,78 @@ void CodeStubAssembler::TryPrototypeChainLookup(
|
| }
|
| }
|
|
|
| -Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
|
| - Node* object) {
|
| +Node* CodeStubAssembler::HasInPrototypeChain(Node* context, Node* object,
|
| + Node* prototype) {
|
| + CSA_ASSERT(this, TaggedIsNotSmi(object));
|
| VARIABLE(var_result, MachineRepresentation::kTagged);
|
| Label return_false(this), return_true(this),
|
| return_runtime(this, Label::kDeferred), return_result(this);
|
|
|
| + // Loop through the prototype chain looking for the {prototype}.
|
| + VARIABLE(var_object_map, MachineRepresentation::kTagged, LoadMap(object));
|
| + Label loop(this, &var_object_map);
|
| + Goto(&loop);
|
| + BIND(&loop);
|
| + {
|
| + // Check if we can determine the prototype directly from the {object_map}.
|
| + Label if_objectisdirect(this), if_objectisspecial(this, Label::kDeferred);
|
| + Node* object_map = var_object_map.value();
|
| + Node* object_instance_type = LoadMapInstanceType(object_map);
|
| + Branch(IsSpecialReceiverInstanceType(object_instance_type),
|
| + &if_objectisspecial, &if_objectisdirect);
|
| + BIND(&if_objectisspecial);
|
| + {
|
| + // The {object_map} is a special receiver map or a primitive map, check
|
| + // if we need to use the if_objectisspecial path in the runtime.
|
| + GotoIf(InstanceTypeEqual(object_instance_type, JS_PROXY_TYPE),
|
| + &return_runtime);
|
| + Node* object_bitfield = LoadMapBitField(object_map);
|
| + Node* mask = Int32Constant(1 << Map::kHasNamedInterceptor |
|
| + 1 << Map::kIsAccessCheckNeeded);
|
| + Branch(Word32NotEqual(Word32And(object_bitfield, mask), Int32Constant(0)),
|
| + &return_runtime, &if_objectisdirect);
|
| + }
|
| + BIND(&if_objectisdirect);
|
| +
|
| + // Check the current {object} prototype.
|
| + Node* object_prototype = LoadMapPrototype(object_map);
|
| + GotoIf(IsNull(object_prototype), &return_false);
|
| + GotoIf(WordEqual(object_prototype, prototype), &return_true);
|
| +
|
| + // Continue with the prototype.
|
| + CSA_ASSERT(this, TaggedIsNotSmi(object_prototype));
|
| + var_object_map.Bind(LoadMap(object_prototype));
|
| + Goto(&loop);
|
| + }
|
| +
|
| + BIND(&return_true);
|
| + var_result.Bind(TrueConstant());
|
| + Goto(&return_result);
|
| +
|
| + BIND(&return_false);
|
| + var_result.Bind(FalseConstant());
|
| + Goto(&return_result);
|
| +
|
| + BIND(&return_runtime);
|
| + {
|
| + // Fallback to the runtime implementation.
|
| + var_result.Bind(
|
| + CallRuntime(Runtime::kHasInPrototypeChain, context, object, prototype));
|
| + }
|
| + Goto(&return_result);
|
| +
|
| + BIND(&return_result);
|
| + return var_result.value();
|
| +}
|
| +
|
| +Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
|
| + Node* object) {
|
| + VARIABLE(var_result, MachineRepresentation::kTagged);
|
| + Label 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);
|
|
|
| @@ -6056,42 +6116,7 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
|
| }
|
|
|
| // Loop through the prototype chain looking for the {callable} prototype.
|
| - VARIABLE(var_object_map, MachineRepresentation::kTagged, object_map);
|
| - Label loop(this, &var_object_map);
|
| - Goto(&loop);
|
| - BIND(&loop);
|
| - {
|
| - Node* object_map = var_object_map.value();
|
| -
|
| - // Check if the current {object} needs to be access checked.
|
| - Node* object_bitfield = LoadMapBitField(object_map);
|
| - GotoIfNot(
|
| - Word32Equal(Word32And(object_bitfield,
|
| - Int32Constant(1 << Map::kIsAccessCheckNeeded)),
|
| - Int32Constant(0)),
|
| - &return_runtime);
|
| -
|
| - // Check if the current {object} is a proxy.
|
| - Node* object_instance_type = LoadMapInstanceType(object_map);
|
| - GotoIf(Word32Equal(object_instance_type, Int32Constant(JS_PROXY_TYPE)),
|
| - &return_runtime);
|
| -
|
| - // Check the current {object} prototype.
|
| - Node* object_prototype = LoadMapPrototype(object_map);
|
| - GotoIf(WordEqual(object_prototype, NullConstant()), &return_false);
|
| - GotoIf(WordEqual(object_prototype, callable_prototype), &return_true);
|
| -
|
| - // Continue with the prototype.
|
| - var_object_map.Bind(LoadMap(object_prototype));
|
| - Goto(&loop);
|
| - }
|
| -
|
| - BIND(&return_true);
|
| - var_result.Bind(BooleanConstant(true));
|
| - Goto(&return_result);
|
| -
|
| - BIND(&return_false);
|
| - var_result.Bind(BooleanConstant(false));
|
| + var_result.Bind(HasInPrototypeChain(context, object, callable_prototype));
|
| Goto(&return_result);
|
|
|
| BIND(&return_runtime);
|
|
|