OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |