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

Side by Side Diff: src/code-stub-assembler.cc

Issue 2934893002: [builtins] Properly optimize Object.prototype.isPrototypeOf. (Closed)
Patch Set: Address feedback. 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 | « src/code-stub-assembler.h ('k') | src/compiler/js-call-reducer.h » ('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 #include "src/code-stub-assembler.h" 4 #include "src/code-stub-assembler.h"
5 #include "src/code-factory.h" 5 #include "src/code-factory.h"
6 #include "src/frames-inl.h" 6 #include "src/frames-inl.h"
7 #include "src/frames.h" 7 #include "src/frames.h"
8 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
(...skipping 5979 matching lines...) Expand 10 before | Expand all | Expand 10 after
5990 Node* instance_type = LoadMapInstanceType(map); 5990 Node* instance_type = LoadMapInstanceType(map);
5991 5991
5992 var_holder.Bind(proto); 5992 var_holder.Bind(proto);
5993 var_holder_map.Bind(map); 5993 var_holder_map.Bind(map);
5994 var_holder_instance_type.Bind(instance_type); 5994 var_holder_instance_type.Bind(instance_type);
5995 Goto(&loop); 5995 Goto(&loop);
5996 } 5996 }
5997 } 5997 }
5998 } 5998 }
5999 5999
6000 Node* CodeStubAssembler::HasInPrototypeChain(Node* context, Node* object,
6001 Node* prototype) {
6002 CSA_ASSERT(this, TaggedIsNotSmi(object));
6003 VARIABLE(var_result, MachineRepresentation::kTagged);
6004 Label return_false(this), return_true(this),
6005 return_runtime(this, Label::kDeferred), return_result(this);
6006
6007 // Loop through the prototype chain looking for the {prototype}.
6008 VARIABLE(var_object_map, MachineRepresentation::kTagged, LoadMap(object));
6009 Label loop(this, &var_object_map);
6010 Goto(&loop);
6011 BIND(&loop);
6012 {
6013 // Check if we can determine the prototype directly from the {object_map}.
6014 Label if_objectisdirect(this), if_objectisspecial(this, Label::kDeferred);
6015 Node* object_map = var_object_map.value();
6016 Node* object_instance_type = LoadMapInstanceType(object_map);
6017 Branch(IsSpecialReceiverInstanceType(object_instance_type),
6018 &if_objectisspecial, &if_objectisdirect);
6019 BIND(&if_objectisspecial);
6020 {
6021 // The {object_map} is a special receiver map or a primitive map, check
6022 // if we need to use the if_objectisspecial path in the runtime.
6023 GotoIf(InstanceTypeEqual(object_instance_type, JS_PROXY_TYPE),
6024 &return_runtime);
6025 Node* object_bitfield = LoadMapBitField(object_map);
6026 Node* mask = Int32Constant(1 << Map::kHasNamedInterceptor |
6027 1 << Map::kIsAccessCheckNeeded);
6028 Branch(Word32NotEqual(Word32And(object_bitfield, mask), Int32Constant(0)),
6029 &return_runtime, &if_objectisdirect);
6030 }
6031 BIND(&if_objectisdirect);
6032
6033 // Check the current {object} prototype.
6034 Node* object_prototype = LoadMapPrototype(object_map);
6035 GotoIf(IsNull(object_prototype), &return_false);
6036 GotoIf(WordEqual(object_prototype, prototype), &return_true);
6037
6038 // Continue with the prototype.
6039 CSA_ASSERT(this, TaggedIsNotSmi(object_prototype));
6040 var_object_map.Bind(LoadMap(object_prototype));
6041 Goto(&loop);
6042 }
6043
6044 BIND(&return_true);
6045 var_result.Bind(TrueConstant());
6046 Goto(&return_result);
6047
6048 BIND(&return_false);
6049 var_result.Bind(FalseConstant());
6050 Goto(&return_result);
6051
6052 BIND(&return_runtime);
6053 {
6054 // Fallback to the runtime implementation.
6055 var_result.Bind(
6056 CallRuntime(Runtime::kHasInPrototypeChain, context, object, prototype));
6057 }
6058 Goto(&return_result);
6059
6060 BIND(&return_result);
6061 return var_result.value();
6062 }
6063
6000 Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable, 6064 Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
6001 Node* object) { 6065 Node* object) {
6002 VARIABLE(var_result, MachineRepresentation::kTagged); 6066 VARIABLE(var_result, MachineRepresentation::kTagged);
6003 Label return_false(this), return_true(this), 6067 Label return_runtime(this, Label::kDeferred), return_result(this);
6004 return_runtime(this, Label::kDeferred), return_result(this);
6005 6068
6006 // Goto runtime if {object} is a Smi. 6069 // Goto runtime if {object} is a Smi.
6007 GotoIf(TaggedIsSmi(object), &return_runtime); 6070 GotoIf(TaggedIsSmi(object), &return_runtime);
6008 6071
6009 // Load map of {object}.
6010 Node* object_map = LoadMap(object);
6011
6012 // Goto runtime if {callable} is a Smi. 6072 // Goto runtime if {callable} is a Smi.
6013 GotoIf(TaggedIsSmi(callable), &return_runtime); 6073 GotoIf(TaggedIsSmi(callable), &return_runtime);
6014 6074
6015 // Load map of {callable}. 6075 // Load map of {callable}.
6016 Node* callable_map = LoadMap(callable); 6076 Node* callable_map = LoadMap(callable);
6017 6077
6018 // Goto runtime if {callable} is not a JSFunction. 6078 // Goto runtime if {callable} is not a JSFunction.
6019 Node* callable_instance_type = LoadMapInstanceType(callable_map); 6079 Node* callable_instance_type = LoadMapInstanceType(callable_map);
6020 GotoIfNot( 6080 GotoIfNot(
6021 Word32Equal(callable_instance_type, Int32Constant(JS_FUNCTION_TYPE)), 6081 Word32Equal(callable_instance_type, Int32Constant(JS_FUNCTION_TYPE)),
(...skipping 27 matching lines...) Expand all
6049 Word32Equal(callable_prototype_instance_type, Int32Constant(MAP_TYPE)), 6109 Word32Equal(callable_prototype_instance_type, Int32Constant(MAP_TYPE)),
6050 &callable_prototype_valid); 6110 &callable_prototype_valid);
6051 var_callable_prototype.Bind( 6111 var_callable_prototype.Bind(
6052 LoadObjectField(callable_prototype, Map::kPrototypeOffset)); 6112 LoadObjectField(callable_prototype, Map::kPrototypeOffset));
6053 Goto(&callable_prototype_valid); 6113 Goto(&callable_prototype_valid);
6054 BIND(&callable_prototype_valid); 6114 BIND(&callable_prototype_valid);
6055 callable_prototype = var_callable_prototype.value(); 6115 callable_prototype = var_callable_prototype.value();
6056 } 6116 }
6057 6117
6058 // Loop through the prototype chain looking for the {callable} prototype. 6118 // Loop through the prototype chain looking for the {callable} prototype.
6059 VARIABLE(var_object_map, MachineRepresentation::kTagged, object_map); 6119 var_result.Bind(HasInPrototypeChain(context, object, callable_prototype));
6060 Label loop(this, &var_object_map);
6061 Goto(&loop);
6062 BIND(&loop);
6063 {
6064 Node* object_map = var_object_map.value();
6065
6066 // Check if the current {object} needs to be access checked.
6067 Node* object_bitfield = LoadMapBitField(object_map);
6068 GotoIfNot(
6069 Word32Equal(Word32And(object_bitfield,
6070 Int32Constant(1 << Map::kIsAccessCheckNeeded)),
6071 Int32Constant(0)),
6072 &return_runtime);
6073
6074 // Check if the current {object} is a proxy.
6075 Node* object_instance_type = LoadMapInstanceType(object_map);
6076 GotoIf(Word32Equal(object_instance_type, Int32Constant(JS_PROXY_TYPE)),
6077 &return_runtime);
6078
6079 // Check the current {object} prototype.
6080 Node* object_prototype = LoadMapPrototype(object_map);
6081 GotoIf(WordEqual(object_prototype, NullConstant()), &return_false);
6082 GotoIf(WordEqual(object_prototype, callable_prototype), &return_true);
6083
6084 // Continue with the prototype.
6085 var_object_map.Bind(LoadMap(object_prototype));
6086 Goto(&loop);
6087 }
6088
6089 BIND(&return_true);
6090 var_result.Bind(BooleanConstant(true));
6091 Goto(&return_result);
6092
6093 BIND(&return_false);
6094 var_result.Bind(BooleanConstant(false));
6095 Goto(&return_result); 6120 Goto(&return_result);
6096 6121
6097 BIND(&return_runtime); 6122 BIND(&return_runtime);
6098 { 6123 {
6099 // Fallback to the runtime implementation. 6124 // Fallback to the runtime implementation.
6100 var_result.Bind( 6125 var_result.Bind(
6101 CallRuntime(Runtime::kOrdinaryHasInstance, context, callable, object)); 6126 CallRuntime(Runtime::kOrdinaryHasInstance, context, callable, object));
6102 } 6127 }
6103 Goto(&return_result); 6128 Goto(&return_result);
6104 6129
(...skipping 3260 matching lines...) Expand 10 before | Expand all | Expand 10 after
9365 formatted.c_str(), TENURED); 9390 formatted.c_str(), TENURED);
9366 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), 9391 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(),
9367 HeapConstant(string)); 9392 HeapConstant(string));
9368 } 9393 }
9369 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); 9394 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value);
9370 #endif 9395 #endif
9371 } 9396 }
9372 9397
9373 } // namespace internal 9398 } // namespace internal
9374 } // namespace v8 9399 } // namespace v8
OLDNEW
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/compiler/js-call-reducer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698