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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « no previous file | src/external-reference-table.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4
4 #include "src/code-stub-assembler.h" 5 #include "src/code-stub-assembler.h"
6
7 #include "src/builtins/builtins-descriptors.h"
5 #include "src/code-factory.h" 8 #include "src/code-factory.h"
6 #include "src/frames-inl.h" 9 #include "src/frames-inl.h"
7 #include "src/frames.h" 10 #include "src/frames.h"
8 11
9 namespace v8 { 12 namespace v8 {
10 namespace internal { 13 namespace internal {
11 14
12 using compiler::Node; 15 using compiler::Node;
13 16
14 CodeStubAssembler::CodeStubAssembler(compiler::CodeAssemblerState* state) 17 CodeStubAssembler::CodeStubAssembler(compiler::CodeAssemblerState* state)
(...skipping 5975 matching lines...) Expand 10 before | Expand all | Expand 10 after
5990 var_holder_map.Bind(map); 5993 var_holder_map.Bind(map);
5991 var_holder_instance_type.Bind(instance_type); 5994 var_holder_instance_type.Bind(instance_type);
5992 Goto(&loop); 5995 Goto(&loop);
5993 } 5996 }
5994 } 5997 }
5995 } 5998 }
5996 5999
5997 Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable, 6000 Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
5998 Node* object) { 6001 Node* object) {
5999 VARIABLE(var_result, MachineRepresentation::kTagged); 6002 VARIABLE(var_result, MachineRepresentation::kTagged);
6000 Label return_false(this), return_true(this), 6003 Label return_false(this, Label::kDeferred), return_true(this),
6004 return_instanceof(this, Label::kDeferred),
6001 return_runtime(this, Label::kDeferred), return_result(this); 6005 return_runtime(this, Label::kDeferred), return_result(this);
6002 6006
6003 // Goto runtime if {object} is a Smi. 6007 // Return false if {callable} is not Callable.
6004 GotoIf(TaggedIsSmi(object), &return_runtime); 6008 GotoIf(TaggedIsSmi(callable), &return_false);
6009 Node* callable_map = LoadMap(callable);
6010 GotoIfNot(IsCallableMap(callable_map), &return_false);
6005 6011
6006 // Load map of {object}. 6012 // If {callable} is a JSBoundFunction, call the instanceof operator
6013 // recursively with the bound target function.
6014 Node* callable_instance_type = LoadMapInstanceType(callable_map);
6015 GotoIf(InstanceTypeEqual(callable_instance_type, JS_BOUND_FUNCTION_TYPE),
6016 &return_instanceof);
6017
6018 // Return false if {object} is not a JSReceiver.
6019 GotoIf(TaggedIsSmi(object), &return_false);
6007 Node* object_map = LoadMap(object); 6020 Node* object_map = LoadMap(object);
6021 GotoIfNot(IsJSReceiverMap(object_map), &return_false);
6008 6022
6009 // Goto runtime if {callable} is a Smi. 6023 // Load the "prototype" from the {callable}. We have a fast-path here for
6010 GotoIf(TaggedIsSmi(callable), &return_runtime); 6024 // JSFunction objects that are marked as constructors and have an instance
6011 6025 // "prototype".
6012 // Load map of {callable}. 6026 VARIABLE(var_callable_prototype, MachineRepresentation::kTagged);
6013 Node* callable_map = LoadMap(callable); 6027 Label fast_callable_prototype(this),
6014 6028 slow_callable_prototype(this, Label::kDeferred),
6015 // Goto runtime if {callable} is not a JSFunction. 6029 done_callable_prototype(this);
6016 Node* callable_instance_type = LoadMapInstanceType(callable_map); 6030 GotoIfNot(IsJSFunctionInstanceType(callable_instance_type),
6017 GotoIfNot( 6031 &slow_callable_prototype);
6018 Word32Equal(callable_instance_type, Int32Constant(JS_FUNCTION_TYPE)),
6019 &return_runtime);
6020
6021 // Goto runtime if {callable} is not a constructor or has
6022 // a non-instance "prototype".
6023 Node* callable_bitfield = LoadMapBitField(callable_map); 6032 Node* callable_bitfield = LoadMapBitField(callable_map);
6024 GotoIfNot( 6033 Branch(
6025 Word32Equal(Word32And(callable_bitfield, 6034 Word32Equal(Word32And(callable_bitfield,
6026 Int32Constant((1 << Map::kHasNonInstancePrototype) | 6035 Int32Constant((1 << Map::kHasNonInstancePrototype) |
6027 (1 << Map::kIsConstructor))), 6036 (1 << Map::kIsConstructor))),
6028 Int32Constant(1 << Map::kIsConstructor)), 6037 Int32Constant(1 << Map::kIsConstructor)),
6029 &return_runtime); 6038 &fast_callable_prototype, &slow_callable_prototype);
6039 BIND(&fast_callable_prototype);
6040 {
6041 // Get the "prototype" (or initial map) of the {callable}.
6042 Node* callable_prototype =
6043 LoadObjectField(callable, JSFunction::kPrototypeOrInitialMapOffset);
6044 var_callable_prototype.Bind(callable_prototype);
6030 6045
6031 // Get the "prototype" (or initial map) of the {callable}. 6046 // Resolve the "prototype" if the {callable} has an initial map.
6032 Node* callable_prototype = 6047 // Afterwards the {callable_prototype} will be either the JSReceiver
6033 LoadObjectField(callable, JSFunction::kPrototypeOrInitialMapOffset); 6048 // prototype object or the hole value, which means that no instances of
6034 { 6049 // the {callable} were created so far and hence we should return false.
6035 Label callable_prototype_valid(this); 6050 GotoIfNot(IsMap(callable_prototype), &done_callable_prototype);
6036 VARIABLE(var_callable_prototype, MachineRepresentation::kTagged,
6037 callable_prototype);
6038
6039 // Resolve the "prototype" if the {callable} has an initial map. Afterwards
6040 // the {callable_prototype} will be either the JSReceiver prototype object
6041 // or the hole value, which means that no instances of the {callable} were
6042 // created so far and hence we should return false.
6043 Node* callable_prototype_instance_type =
6044 LoadInstanceType(callable_prototype);
6045 GotoIfNot(
6046 Word32Equal(callable_prototype_instance_type, Int32Constant(MAP_TYPE)),
6047 &callable_prototype_valid);
6048 var_callable_prototype.Bind( 6051 var_callable_prototype.Bind(
6049 LoadObjectField(callable_prototype, Map::kPrototypeOffset)); 6052 LoadObjectField(callable_prototype, Map::kPrototypeOffset));
6050 Goto(&callable_prototype_valid); 6053 Goto(&done_callable_prototype);
6051 BIND(&callable_prototype_valid);
6052 callable_prototype = var_callable_prototype.value();
6053 } 6054 }
6055 BIND(&slow_callable_prototype);
6056 {
6057 // Generic "prototype" lookup on the {callable}, including check
6058 // that the resulting prototype is a proper JSReceiver.
6059 Label callable_prototype_not_receiver(this, Label::kDeferred);
6060 Node* callable_prototype =
6061 GetProperty(context, callable, PrototypeStringConstant());
6062 GotoIf(TaggedIsSmi(callable_prototype), &callable_prototype_not_receiver);
6063 var_callable_prototype.Bind(callable_prototype);
6064 Branch(IsJSReceiver(callable_prototype), &done_callable_prototype,
6065 &callable_prototype_not_receiver);
6066 BIND(&callable_prototype_not_receiver);
6067 {
6068 CallRuntime(Runtime::kThrowInstanceofNonobjectProto, context,
6069 callable_prototype);
6070 Unreachable();
6071 }
6072 }
6073 BIND(&done_callable_prototype);
6074 Node* callable_prototype = var_callable_prototype.value();
6054 6075
6055 // Loop through the prototype chain looking for the {callable} prototype. 6076 // Loop through the prototype chain looking for the {callable} prototype.
6056 VARIABLE(var_object_map, MachineRepresentation::kTagged, object_map); 6077 VARIABLE(var_object_map, MachineRepresentation::kTagged, object_map);
6057 Label loop(this, &var_object_map); 6078 Label loop(this, &var_object_map);
6058 Goto(&loop); 6079 Goto(&loop);
6059 BIND(&loop); 6080 BIND(&loop);
6060 { 6081 {
6082 // Check if the current {object} needs to be access checked.
6061 Node* object_map = var_object_map.value(); 6083 Node* object_map = var_object_map.value();
6062
6063 // Check if the current {object} needs to be access checked.
6064 Node* object_bitfield = LoadMapBitField(object_map); 6084 Node* object_bitfield = LoadMapBitField(object_map);
6065 GotoIfNot( 6085 GotoIfNot(
6066 Word32Equal(Word32And(object_bitfield, 6086 Word32Equal(Word32And(object_bitfield,
6067 Int32Constant(1 << Map::kIsAccessCheckNeeded)), 6087 Int32Constant(1 << Map::kIsAccessCheckNeeded)),
6068 Int32Constant(0)), 6088 Int32Constant(0)),
6069 &return_runtime); 6089 &return_runtime);
6070 6090
6071 // Check if the current {object} is a proxy. 6091 // Check if the current {object} is a proxy.
6072 Node* object_instance_type = LoadMapInstanceType(object_map); 6092 Node* object_instance_type = LoadMapInstanceType(object_map);
6073 GotoIf(Word32Equal(object_instance_type, Int32Constant(JS_PROXY_TYPE)), 6093 GotoIf(InstanceTypeEqual(object_instance_type, JS_PROXY_TYPE),
6074 &return_runtime); 6094 &return_runtime);
6075 6095
6076 // Check the current {object} prototype. 6096 // Check the current {object} prototype.
6077 Node* object_prototype = LoadMapPrototype(object_map); 6097 Node* object_prototype = LoadMapPrototype(object_map);
6078 GotoIf(WordEqual(object_prototype, NullConstant()), &return_false); 6098 GotoIf(WordEqual(object_prototype, NullConstant()), &return_false);
6079 GotoIf(WordEqual(object_prototype, callable_prototype), &return_true); 6099 GotoIf(WordEqual(object_prototype, callable_prototype), &return_true);
6080 6100
6081 // Continue with the prototype. 6101 // Continue with the prototype.
6082 var_object_map.Bind(LoadMap(object_prototype)); 6102 var_object_map.Bind(LoadMap(object_prototype));
6083 Goto(&loop); 6103 Goto(&loop);
6084 } 6104 }
6085 6105
6086 BIND(&return_true); 6106 BIND(&return_true);
6087 var_result.Bind(BooleanConstant(true)); 6107 var_result.Bind(BooleanConstant(true));
6088 Goto(&return_result); 6108 Goto(&return_result);
6089 6109
6090 BIND(&return_false); 6110 BIND(&return_false);
6091 var_result.Bind(BooleanConstant(false)); 6111 var_result.Bind(BooleanConstant(false));
6092 Goto(&return_result); 6112 Goto(&return_result);
6093 6113
6094 BIND(&return_runtime); 6114 BIND(&return_runtime);
6095 { 6115 {
6096 // Fallback to the runtime implementation. 6116 // Fallback to the runtime implementation.
6097 var_result.Bind( 6117 var_result.Bind(CallRuntime(Runtime::kHasInPrototypeChain, context, object,
6098 CallRuntime(Runtime::kOrdinaryHasInstance, context, callable, object)); 6118 callable_prototype));
6099 } 6119 }
6100 Goto(&return_result); 6120 Goto(&return_result);
6101 6121
6122 BIND(&return_instanceof);
6123 {
6124 // Use the InstanceOf algorithm on the [[BoundTargetFunction]].
6125 ExternalReference ref(Builtins::kInstanceOf, isolate());
6126 Node* code = Load(MachineType::AnyTagged(), ExternalConstant(ref));
6127 Node* bound_target_function =
6128 LoadObjectField(callable, JSBoundFunction::kBoundTargetFunctionOffset);
6129 Node* result = CallStub(Builtin_InstanceOf_InterfaceDescriptor(isolate()),
6130 code, context, object, bound_target_function);
6131 var_result.Bind(result);
6132 }
6133 Goto(&return_result);
6134
6102 BIND(&return_result); 6135 BIND(&return_result);
6103 return var_result.value(); 6136 return var_result.value();
6104 } 6137 }
6105 6138
6106 Node* CodeStubAssembler::ElementOffsetFromIndex(Node* index_node, 6139 Node* CodeStubAssembler::ElementOffsetFromIndex(Node* index_node,
6107 ElementsKind kind, 6140 ElementsKind kind,
6108 ParameterMode mode, 6141 ParameterMode mode,
6109 int base_size) { 6142 int base_size) {
6110 int element_size_shift = ElementsKindToShiftSize(kind); 6143 int element_size_shift = ElementsKindToShiftSize(kind);
6111 int element_size = 1 << element_size_shift; 6144 int element_size = 1 << element_size_shift;
(...skipping 2639 matching lines...) Expand 10 before | Expand all | Expand 10 after
8751 // Convert the {result} to a Boolean. 8784 // Convert the {result} to a Boolean.
8752 BranchIfToBooleanIsTrue(result, &return_true, &return_false); 8785 BranchIfToBooleanIsTrue(result, &return_true, &return_false);
8753 } 8786 }
8754 8787
8755 BIND(&if_nohandler); 8788 BIND(&if_nohandler);
8756 { 8789 {
8757 // Ensure that the {callable} is actually Callable. 8790 // Ensure that the {callable} is actually Callable.
8758 GotoIfNot(IsCallable(callable), &if_notcallable); 8791 GotoIfNot(IsCallable(callable), &if_notcallable);
8759 8792
8760 // Use the OrdinaryHasInstance algorithm. 8793 // Use the OrdinaryHasInstance algorithm.
8761 Node* result = CallStub(CodeFactory::OrdinaryHasInstance(isolate()), 8794 Node* result =
8762 context, callable, object); 8795 CallBuiltin(Builtins::kOrdinaryHasInstance, context, callable, object);
8763 var_result.Bind(result); 8796 var_result.Bind(result);
8764 Goto(&return_result); 8797 Goto(&return_result);
8765 } 8798 }
8766 8799
8767 BIND(&if_notcallable); 8800 BIND(&if_notcallable);
8768 { 8801 {
8769 CallRuntime(Runtime::kThrowNonCallableInInstanceOfCheck, context); 8802 CallRuntime(Runtime::kThrowNonCallableInInstanceOfCheck, context);
8770 Unreachable(); 8803 Unreachable();
8771 } 8804 }
8772 8805
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after
9355 formatted.c_str(), TENURED); 9388 formatted.c_str(), TENURED);
9356 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), 9389 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(),
9357 HeapConstant(string)); 9390 HeapConstant(string));
9358 } 9391 }
9359 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); 9392 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value);
9360 #endif 9393 #endif
9361 } 9394 }
9362 9395
9363 } // namespace internal 9396 } // namespace internal
9364 } // namespace v8 9397 } // namespace v8
OLDNEW
« 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