| 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 |