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

Side by Side Diff: src/compiler/js-native-context-specialization.cc

Issue 2076493002: Revert of [turbofan] Properly handle dictionary maps in the prototype chain. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@TurboFan_CheckedOperators
Patch Set: Created 4 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
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 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
5 #include "src/compiler/js-native-context-specialization.h" 5 #include "src/compiler/js-native-context-specialization.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 #include "src/compilation-dependencies.h" 9 #include "src/compilation-dependencies.h"
10 #include "src/compiler/access-builder.h" 10 #include "src/compiler/access-builder.h"
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 this_effect = 218 this_effect =
219 (this_control_count == 1) 219 (this_control_count == 1)
220 ? this_effects.front() 220 ? this_effects.front()
221 : graph()->NewNode(common()->EffectPhi(this_control_count), 221 : graph()->NewNode(common()->EffectPhi(this_control_count),
222 this_effect_count, &this_effects.front()); 222 this_effect_count, &this_effects.front());
223 } 223 }
224 224
225 // Determine actual holder and perform prototype chain checks. 225 // Determine actual holder and perform prototype chain checks.
226 Handle<JSObject> holder; 226 Handle<JSObject> holder;
227 if (access_info.holder().ToHandle(&holder)) { 227 if (access_info.holder().ToHandle(&holder)) {
228 this_effect = CheckPrototypeMaps(receiver_type, native_context, holder, 228 AssumePrototypesStable(receiver_type, native_context, holder);
229 this_effect, this_control);
230 } 229 }
231 230
232 // Generate the actual property access. 231 // Generate the actual property access.
233 if (access_info.IsNotFound()) { 232 if (access_info.IsNotFound()) {
234 DCHECK_EQ(AccessMode::kLoad, access_mode); 233 DCHECK_EQ(AccessMode::kLoad, access_mode);
235 this_value = jsgraph()->UndefinedConstant(); 234 this_value = jsgraph()->UndefinedConstant();
236 } else if (access_info.IsDataConstant()) { 235 } else if (access_info.IsDataConstant()) {
237 this_value = jsgraph()->Constant(access_info.constant()); 236 this_value = jsgraph()->Constant(access_info.constant());
238 if (access_mode == AccessMode::kStore) { 237 if (access_mode == AccessMode::kStore) {
239 Node* check = graph()->NewNode( 238 Node* check = graph()->NewNode(
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 // observable by JavaScript. 661 // observable by JavaScript.
663 this_effect = graph()->NewNode(common()->Checkpoint(), frame_state, 662 this_effect = graph()->NewNode(common()->Checkpoint(), frame_state,
664 this_effect, this_control); 663 this_effect, this_control);
665 } 664 }
666 665
667 // Certain stores need a prototype chain check because shape changes 666 // Certain stores need a prototype chain check because shape changes
668 // could allow callbacks on elements in the prototype chain that are 667 // could allow callbacks on elements in the prototype chain that are
669 // not compatible with (monomorphic) keyed stores. 668 // not compatible with (monomorphic) keyed stores.
670 Handle<JSObject> holder; 669 Handle<JSObject> holder;
671 if (access_info.holder().ToHandle(&holder)) { 670 if (access_info.holder().ToHandle(&holder)) {
672 this_effect = CheckPrototypeMaps(receiver_type, native_context, holder, 671 AssumePrototypesStable(receiver_type, native_context, holder);
673 this_effect, this_control);
674 } 672 }
675 673
676 // TODO(bmeurer): We currently specialize based on elements kind. We should 674 // TODO(bmeurer): We currently specialize based on elements kind. We should
677 // also be able to properly support strings and other JSObjects here. 675 // also be able to properly support strings and other JSObjects here.
678 ElementsKind elements_kind = access_info.elements_kind(); 676 ElementsKind elements_kind = access_info.elements_kind();
679 677
680 // Load the elements for the {receiver}. 678 // Load the elements for the {receiver}.
681 Node* this_elements = this_effect = graph()->NewNode( 679 Node* this_elements = this_effect = graph()->NewNode(
682 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), 680 simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
683 this_receiver, this_effect, this_control); 681 this_receiver, this_effect, this_control);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
748 elements_kind == FAST_HOLEY_SMI_ELEMENTS) { 746 elements_kind == FAST_HOLEY_SMI_ELEMENTS) {
749 // Perform the hole check on the result. 747 // Perform the hole check on the result.
750 CheckTaggedHoleMode mode = CheckTaggedHoleMode::kNeverReturnHole; 748 CheckTaggedHoleMode mode = CheckTaggedHoleMode::kNeverReturnHole;
751 // Check if we are allowed to turn the hole into undefined. 749 // Check if we are allowed to turn the hole into undefined.
752 Type* initial_holey_array_type = Type::Class( 750 Type* initial_holey_array_type = Type::Class(
753 handle(isolate()->get_initial_js_array_map(elements_kind)), 751 handle(isolate()->get_initial_js_array_map(elements_kind)),
754 graph()->zone()); 752 graph()->zone());
755 if (receiver_type->NowIs(initial_holey_array_type) && 753 if (receiver_type->NowIs(initial_holey_array_type) &&
756 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { 754 isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
757 // Add a code dependency on the array protector cell. 755 // Add a code dependency on the array protector cell.
758 this_effect = CheckPrototypeMaps( 756 AssumePrototypesStable(receiver_type, native_context,
759 receiver_type, native_context, 757 isolate()->initial_object_prototype());
760 isolate()->initial_object_prototype(), this_effect, this_control);
761 dependencies()->AssumePropertyCell(factory()->array_protector()); 758 dependencies()->AssumePropertyCell(factory()->array_protector());
762 // Turn the hole into undefined. 759 // Turn the hole into undefined.
763 mode = CheckTaggedHoleMode::kConvertHoleToUndefined; 760 mode = CheckTaggedHoleMode::kConvertHoleToUndefined;
764 } 761 }
765 this_value = this_effect = 762 this_value = this_effect =
766 graph()->NewNode(simplified()->CheckTaggedHole(mode), this_value, 763 graph()->NewNode(simplified()->CheckTaggedHole(mode), this_value,
767 this_effect, this_control); 764 this_effect, this_control);
768 } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) { 765 } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) {
769 // Perform the hole check on the result. 766 // Perform the hole check on the result.
770 CheckFloat64HoleMode mode = CheckFloat64HoleMode::kNeverReturnHole; 767 CheckFloat64HoleMode mode = CheckFloat64HoleMode::kNeverReturnHole;
771 // Check if we are allowed to return the hole directly. 768 // Check if we are allowed to return the hole directly.
772 Type* initial_holey_array_type = Type::Class( 769 Type* initial_holey_array_type = Type::Class(
773 handle(isolate()->get_initial_js_array_map(elements_kind)), 770 handle(isolate()->get_initial_js_array_map(elements_kind)),
774 graph()->zone()); 771 graph()->zone());
775 if (receiver_type->NowIs(initial_holey_array_type) && 772 if (receiver_type->NowIs(initial_holey_array_type) &&
776 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { 773 isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
777 // Add a code dependency on the array protector cell. 774 // Add a code dependency on the array protector cell.
778 this_effect = CheckPrototypeMaps( 775 AssumePrototypesStable(receiver_type, native_context,
779 receiver_type, native_context, 776 isolate()->initial_object_prototype());
780 isolate()->initial_object_prototype(), this_effect, this_control);
781 dependencies()->AssumePropertyCell(factory()->array_protector()); 777 dependencies()->AssumePropertyCell(factory()->array_protector());
782 // Return the signaling NaN hole directly if all uses are truncating. 778 // Return the signaling NaN hole directly if all uses are truncating.
783 mode = CheckFloat64HoleMode::kAllowReturnHole; 779 mode = CheckFloat64HoleMode::kAllowReturnHole;
784 } 780 }
785 this_value = this_effect = 781 this_value = this_effect =
786 graph()->NewNode(simplified()->CheckFloat64Hole(mode), this_value, 782 graph()->NewNode(simplified()->CheckFloat64Hole(mode), this_value,
787 this_effect, this_control); 783 this_effect, this_control);
788 } 784 }
789 } else { 785 } else {
790 DCHECK_EQ(AccessMode::kStore, access_mode); 786 DCHECK_EQ(AccessMode::kStore, access_mode);
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
953 KeyedStoreICNexus nexus(p.feedback().vector(), p.feedback().slot()); 949 KeyedStoreICNexus nexus(p.feedback().vector(), p.feedback().slot());
954 950
955 // Extract the keyed access store mode from the KEYED_STORE_IC. 951 // Extract the keyed access store mode from the KEYED_STORE_IC.
956 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode(); 952 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode();
957 953
958 // Try to lower the keyed access based on the {nexus}. 954 // Try to lower the keyed access based on the {nexus}.
959 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore, 955 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore,
960 p.language_mode(), store_mode); 956 p.language_mode(), store_mode);
961 } 957 }
962 958
963 Node* JSNativeContextSpecialization::CheckPrototypeMaps( 959
960 void JSNativeContextSpecialization::AssumePrototypesStable(
964 Type* receiver_type, Handle<Context> native_context, 961 Type* receiver_type, Handle<Context> native_context,
965 Handle<JSObject> holder, Node* effect, Node* control) { 962 Handle<JSObject> holder) {
966 // Determine actual holder and perform prototype chain checks. 963 // Determine actual holder and perform prototype chain checks.
967 for (auto i = receiver_type->Classes(); !i.Done(); i.Advance()) { 964 for (auto i = receiver_type->Classes(); !i.Done(); i.Advance()) {
968 Handle<Map> map = i.Current(); 965 Handle<Map> map = i.Current();
969 // Perform the implicit ToObject for primitives here. 966 // Perform the implicit ToObject for primitives here.
970 // Implemented according to ES6 section 7.3.2 GetV (V, P). 967 // Implemented according to ES6 section 7.3.2 GetV (V, P).
971 Handle<JSFunction> constructor; 968 Handle<JSFunction> constructor;
972 if (Map::GetConstructorFunction(map, native_context) 969 if (Map::GetConstructorFunction(map, native_context)
973 .ToHandle(&constructor)) { 970 .ToHandle(&constructor)) {
974 map = handle(constructor->initial_map(), isolate()); 971 map = handle(constructor->initial_map(), isolate());
975 } 972 }
976 for (PrototypeIterator j(map); !j.IsAtEnd(); j.Advance()) { 973 dependencies()->AssumePrototypeMapsStable(map, holder);
977 Handle<JSReceiver> const current =
978 PrototypeIterator::GetCurrent<JSReceiver>(j);
979 Handle<Map> current_map(current->map(), isolate());
980 if (current_map->is_stable()) {
981 dependencies()->AssumeMapStable(current_map);
982 } else {
983 // TODO(bmeurer): Introduce a dedicated CheckMaps operator.
984 Node* prototype = jsgraph()->HeapConstant(current);
985 Node* prototype_map = effect =
986 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
987 prototype, effect, control);
988 Node* check = graph()->NewNode(
989 simplified()->ReferenceEqual(Type::Internal()), prototype_map,
990 jsgraph()->HeapConstant(current_map));
991 effect =
992 graph()->NewNode(simplified()->CheckIf(), check, effect, control);
993 }
994 if (holder.is_identical_to(current)) break;
995 }
996 } 974 }
997 return effect;
998 } 975 }
999 976
1000 bool JSNativeContextSpecialization::ExtractReceiverMaps( 977 bool JSNativeContextSpecialization::ExtractReceiverMaps(
1001 Node* receiver, Node* effect, FeedbackNexus const& nexus, 978 Node* receiver, Node* effect, FeedbackNexus const& nexus,
1002 MapHandleList* receiver_maps) { 979 MapHandleList* receiver_maps) {
1003 DCHECK_EQ(0, receiver_maps->length()); 980 DCHECK_EQ(0, receiver_maps->length());
1004 // See if we can infer a concrete type for the {receiver}. 981 // See if we can infer a concrete type for the {receiver}.
1005 Handle<Map> receiver_map; 982 Handle<Map> receiver_map;
1006 if (InferReceiverMap(receiver, effect).ToHandle(&receiver_map)) { 983 if (InferReceiverMap(receiver, effect).ToHandle(&receiver_map)) {
1007 // We can assume that the {receiver} still has the infered {receiver_map}. 984 // We can assume that the {receiver} still has the infered {receiver_map}.
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1114 } 1091 }
1115 1092
1116 1093
1117 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { 1094 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
1118 return jsgraph()->simplified(); 1095 return jsgraph()->simplified();
1119 } 1096 }
1120 1097
1121 } // namespace compiler 1098 } // namespace compiler
1122 } // namespace internal 1099 } // namespace internal
1123 } // namespace v8 1100 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | test/mjsunit/regress/regress-crbug-616709.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698