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

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

Issue 2494673002: [turbofan] Introduce map-guarded generic handler for named store. (Closed)
Patch Set: Rebase Created 4 years, 1 month 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/compiler/js-native-context-specialization.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 Node* value = jsgraph()->HeapConstant(native_context()); 95 Node* value = jsgraph()->HeapConstant(native_context());
96 ReplaceWithValue(node, value); 96 ReplaceWithValue(node, value);
97 return Replace(value); 97 return Replace(value);
98 } 98 }
99 return NoChange(); 99 return NoChange();
100 } 100 }
101 101
102 Reduction JSNativeContextSpecialization::ReduceNamedAccess( 102 Reduction JSNativeContextSpecialization::ReduceNamedAccess(
103 Node* node, Node* value, MapHandleList const& receiver_maps, 103 Node* node, Node* value, MapHandleList const& receiver_maps,
104 Handle<Name> name, AccessMode access_mode, LanguageMode language_mode, 104 Handle<Name> name, AccessMode access_mode, LanguageMode language_mode,
105 Node* index) { 105 Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot, Node* index) {
106 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || 106 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed ||
107 node->opcode() == IrOpcode::kJSStoreNamed || 107 node->opcode() == IrOpcode::kJSStoreNamed ||
108 node->opcode() == IrOpcode::kJSLoadProperty || 108 node->opcode() == IrOpcode::kJSLoadProperty ||
109 node->opcode() == IrOpcode::kJSStoreProperty); 109 node->opcode() == IrOpcode::kJSStoreProperty);
110 Node* receiver = NodeProperties::GetValueInput(node, 0); 110 Node* receiver = NodeProperties::GetValueInput(node, 0);
111 Node* context = NodeProperties::GetContextInput(node); 111 Node* context = NodeProperties::GetContextInput(node);
112 Node* frame_state_eager = NodeProperties::FindFrameStateBefore(node); 112 Node* frame_state_eager = NodeProperties::FindFrameStateBefore(node);
113 Node* frame_state_lazy = NodeProperties::GetFrameStateInput(node); 113 Node* frame_state_lazy = NodeProperties::GetFrameStateInput(node);
114 Node* effect = NodeProperties::GetEffectInput(node); 114 Node* effect = NodeProperties::GetEffectInput(node);
115 Node* control = NodeProperties::GetControlInput(node); 115 Node* control = NodeProperties::GetControlInput(node);
116 116
117 // Not much we can do if deoptimization support is disabled. 117 // Not much we can do if deoptimization support is disabled.
118 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); 118 if (!(flags() & kDeoptimizationEnabled)) return NoChange();
119 119
120 // Compute property access infos for the receiver maps. 120 // Compute property access infos for the receiver maps.
121 AccessInfoFactory access_info_factory(dependencies(), native_context(), 121 AccessInfoFactory access_info_factory(dependencies(), native_context(),
122 graph()->zone()); 122 graph()->zone());
123 ZoneVector<PropertyAccessInfo> access_infos(zone()); 123 ZoneVector<PropertyAccessInfo> access_infos(zone());
124 if (!access_info_factory.ComputePropertyAccessInfos( 124 if (!access_info_factory.ComputePropertyAccessInfos(
125 receiver_maps, name, access_mode, &access_infos)) { 125 receiver_maps, name, access_mode, &access_infos)) {
126 return NoChange(); 126 return NoChange();
127 } 127 }
128 128
129 // TODO(turbofan): Add support for inlining into try blocks. 129 // TODO(turbofan): Add support for inlining into try blocks.
130 if (NodeProperties::IsExceptionalCall(node) || 130 bool is_exceptional = NodeProperties::IsExceptionalCall(node);
131 !(flags() & kAccessorInliningEnabled)) { 131 for (auto access_info : access_infos) {
132 for (auto access_info : access_infos) { 132 if (access_info.IsAccessorConstant()) {
133 if (access_info.IsAccessorConstant()) return NoChange(); 133 // Accessor in try-blocks are not supported yet.
134 if (is_exceptional || !(flags() & kAccessorInliningEnabled)) {
135 return NoChange();
136 }
137 } else if (access_info.IsGeneric()) {
138 // We do not handle generic calls in try blocks.
139 if (is_exceptional) return NoChange();
140 // We only handle the generic store IC case.
141 if (vector->GetKind(slot) != FeedbackVectorSlotKind::STORE_IC) {
142 return NoChange();
143 }
134 } 144 }
135 } 145 }
136 146
137 // Nothing to do if we have no non-deprecated maps. 147 // Nothing to do if we have no non-deprecated maps.
138 if (access_infos.empty()) { 148 if (access_infos.empty()) {
139 return ReduceSoftDeoptimize( 149 return ReduceSoftDeoptimize(
140 node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); 150 node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
141 } 151 }
142 152
143 // Ensure that {index} matches the specified {name} (if {index} is given). 153 // Ensure that {index} matches the specified {name} (if {index} is given).
(...skipping 17 matching lines...) Expand all
161 receiver, effect, control); 171 receiver, effect, control);
162 } else { 172 } else {
163 // Monomorphic property access. 173 // Monomorphic property access.
164 receiver = effect = graph()->NewNode(simplified()->CheckHeapObject(), 174 receiver = effect = graph()->NewNode(simplified()->CheckHeapObject(),
165 receiver, effect, control); 175 receiver, effect, control);
166 effect = BuildCheckMaps(receiver, effect, control, 176 effect = BuildCheckMaps(receiver, effect, control,
167 access_info.receiver_maps()); 177 access_info.receiver_maps());
168 } 178 }
169 179
170 // Generate the actual property access. 180 // Generate the actual property access.
171 ValueEffectControl continuation = 181 ValueEffectControl continuation = BuildPropertyAccess(
172 BuildPropertyAccess(receiver, value, context, frame_state_lazy, effect, 182 receiver, value, context, frame_state_lazy, effect, control, name,
173 control, name, access_info, access_mode); 183 access_info, access_mode, language_mode, vector, slot);
174 value = continuation.value(); 184 value = continuation.value();
175 effect = continuation.effect(); 185 effect = continuation.effect();
176 control = continuation.control(); 186 control = continuation.control();
177 } else { 187 } else {
178 // The final states for every polymorphic branch. We join them with 188 // The final states for every polymorphic branch. We join them with
179 // Merge+Phi+EffectPhi at the bottom. 189 // Merge+Phi+EffectPhi at the bottom.
180 ZoneVector<Node*> values(zone()); 190 ZoneVector<Node*> values(zone());
181 ZoneVector<Node*> effects(zone()); 191 ZoneVector<Node*> effects(zone());
182 ZoneVector<Node*> controls(zone()); 192 ZoneVector<Node*> controls(zone());
183 193
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 // FrameState after the EffectPhi that is generated above. 285 // FrameState after the EffectPhi that is generated above.
276 this_effect = 286 this_effect =
277 graph()->NewNode(common()->Checkpoint(), frame_state_eager, 287 graph()->NewNode(common()->Checkpoint(), frame_state_eager,
278 this_effect, this_control); 288 this_effect, this_control);
279 } 289 }
280 } 290 }
281 291
282 // Generate the actual property access. 292 // Generate the actual property access.
283 ValueEffectControl continuation = BuildPropertyAccess( 293 ValueEffectControl continuation = BuildPropertyAccess(
284 this_receiver, this_value, context, frame_state_lazy, this_effect, 294 this_receiver, this_value, context, frame_state_lazy, this_effect,
285 this_control, name, access_info, access_mode); 295 this_control, name, access_info, access_mode, language_mode, vector,
296 slot);
286 values.push_back(continuation.value()); 297 values.push_back(continuation.value());
287 effects.push_back(continuation.effect()); 298 effects.push_back(continuation.effect());
288 controls.push_back(continuation.control()); 299 controls.push_back(continuation.control());
289 } 300 }
290 301
291 DCHECK_NULL(fallthrough_control); 302 DCHECK_NULL(fallthrough_control);
292 303
293 // Generate the final merge point for all (polymorphic) branches. 304 // Generate the final merge point for all (polymorphic) branches.
294 int const control_count = static_cast<int>(controls.size()); 305 int const control_count = static_cast<int>(controls.size());
295 if (control_count == 0) { 306 if (control_count == 0) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 (flags() & kBailoutOnUninitialized)) { 353 (flags() & kBailoutOnUninitialized)) {
343 return ReduceSoftDeoptimize( 354 return ReduceSoftDeoptimize(
344 node, 355 node,
345 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); 356 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
346 } 357 }
347 return NoChange(); 358 return NoChange();
348 } 359 }
349 360
350 // Try to lower the named access based on the {receiver_maps}. 361 // Try to lower the named access based on the {receiver_maps}.
351 return ReduceNamedAccess(node, value, receiver_maps, name, access_mode, 362 return ReduceNamedAccess(node, value, receiver_maps, name, access_mode,
352 language_mode); 363 language_mode, nexus.vector_handle(), nexus.slot());
353 } 364 }
354 365
355 366
356 Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) { 367 Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
357 DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode()); 368 DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
358 NamedAccess const& p = NamedAccessOf(node->op()); 369 NamedAccess const& p = NamedAccessOf(node->op());
359 Node* const receiver = NodeProperties::GetValueInput(node, 0); 370 Node* const receiver = NodeProperties::GetValueInput(node, 0);
360 Node* const value = jsgraph()->Dead(); 371 Node* const value = jsgraph()->Dead();
361 372
362 // Check if we have a constant receiver. 373 // Check if we have a constant receiver.
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
751 // so we limit the constant indices to primitives at this point. 762 // so we limit the constant indices to primitives at this point.
752 Handle<Name> name; 763 Handle<Name> name;
753 if (Object::ToName(isolate(), mindex.Value()).ToHandle(&name)) { 764 if (Object::ToName(isolate(), mindex.Value()).ToHandle(&name)) {
754 uint32_t array_index; 765 uint32_t array_index;
755 if (name->AsArrayIndex(&array_index)) { 766 if (name->AsArrayIndex(&array_index)) {
756 // Use the constant array index. 767 // Use the constant array index.
757 index = jsgraph()->Constant(static_cast<double>(array_index)); 768 index = jsgraph()->Constant(static_cast<double>(array_index));
758 } else { 769 } else {
759 name = factory()->InternalizeName(name); 770 name = factory()->InternalizeName(name);
760 return ReduceNamedAccess(node, value, receiver_maps, name, access_mode, 771 return ReduceNamedAccess(node, value, receiver_maps, name, access_mode,
761 language_mode); 772 language_mode, nexus.vector_handle(),
773 nexus.slot());
762 } 774 }
763 } 775 }
764 } 776 }
765 777
766 // Check if we have feedback for a named access. 778 // Check if we have feedback for a named access.
767 if (Name* name = nexus.FindFirstName()) { 779 if (Name* name = nexus.FindFirstName()) {
768 return ReduceNamedAccess(node, value, receiver_maps, 780 return ReduceNamedAccess(
769 handle(name, isolate()), access_mode, 781 node, value, receiver_maps, handle(name, isolate()), access_mode,
770 language_mode, index); 782 language_mode, nexus.vector_handle(), nexus.slot(), index);
771 } else if (nexus.GetKeyType() != ELEMENT) { 783 } else if (nexus.GetKeyType() != ELEMENT) {
772 // The KeyedLoad/StoreIC has seen non-element accesses, so we cannot assume 784 // The KeyedLoad/StoreIC has seen non-element accesses, so we cannot assume
773 // that the {index} is a valid array index, thus we just let the IC continue 785 // that the {index} is a valid array index, thus we just let the IC continue
774 // to deal with this load/store. 786 // to deal with this load/store.
775 return NoChange(); 787 return NoChange();
776 } else if (nexus.ic_state() == MEGAMORPHIC) { 788 } else if (nexus.ic_state() == MEGAMORPHIC) {
777 // The KeyedLoad/StoreIC uses the MEGAMORPHIC state to guard the assumption 789 // The KeyedLoad/StoreIC uses the MEGAMORPHIC state to guard the assumption
778 // that a numeric {index} is within the valid bounds for {receiver}, i.e. 790 // that a numeric {index} is within the valid bounds for {receiver}, i.e.
779 // it transitions to MEGAMORPHIC once it sees an out-of-bounds access. Thus 791 // it transitions to MEGAMORPHIC once it sees an out-of-bounds access. Thus
780 // we cannot continue here if the IC state is MEGAMORPHIC. 792 // we cannot continue here if the IC state is MEGAMORPHIC.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
834 846
835 // Try to lower the keyed access based on the {nexus}. 847 // Try to lower the keyed access based on the {nexus}.
836 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore, 848 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore,
837 p.language_mode(), store_mode); 849 p.language_mode(), store_mode);
838 } 850 }
839 851
840 JSNativeContextSpecialization::ValueEffectControl 852 JSNativeContextSpecialization::ValueEffectControl
841 JSNativeContextSpecialization::BuildPropertyAccess( 853 JSNativeContextSpecialization::BuildPropertyAccess(
842 Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect, 854 Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect,
843 Node* control, Handle<Name> name, PropertyAccessInfo const& access_info, 855 Node* control, Handle<Name> name, PropertyAccessInfo const& access_info,
844 AccessMode access_mode) { 856 AccessMode access_mode, LanguageMode language_mode,
857 Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot) {
845 // Determine actual holder and perform prototype chain checks. 858 // Determine actual holder and perform prototype chain checks.
846 Handle<JSObject> holder; 859 Handle<JSObject> holder;
847 if (access_info.holder().ToHandle(&holder)) { 860 if (access_info.holder().ToHandle(&holder)) {
848 AssumePrototypesStable(access_info.receiver_maps(), holder); 861 AssumePrototypesStable(access_info.receiver_maps(), holder);
849 } 862 }
850 863
851 // Generate the actual property access. 864 // Generate the actual property access.
852 if (access_info.IsNotFound()) { 865 if (access_info.IsNotFound()) {
853 DCHECK_EQ(AccessMode::kLoad, access_mode); 866 DCHECK_EQ(AccessMode::kLoad, access_mode);
854 value = jsgraph()->UndefinedConstant(); 867 value = jsgraph()->UndefinedConstant();
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
936 ValueEffectControl value_effect_control = InlineApiCall( 949 ValueEffectControl value_effect_control = InlineApiCall(
937 receiver, context, target, frame_state0, &stack_parameters, 950 receiver, context, target, frame_state0, &stack_parameters,
938 effect, control, shared_info, function_template_info); 951 effect, control, shared_info, function_template_info);
939 value = value_effect_control.value(); 952 value = value_effect_control.value();
940 effect = value_effect_control.effect(); 953 effect = value_effect_control.effect();
941 control = value_effect_control.control(); 954 control = value_effect_control.control();
942 } 955 }
943 break; 956 break;
944 } 957 }
945 } 958 }
946 } else { 959 } else if (access_info.IsDataField()) {
947 DCHECK(access_info.IsDataField());
948 FieldIndex const field_index = access_info.field_index(); 960 FieldIndex const field_index = access_info.field_index();
949 Type* const field_type = access_info.field_type(); 961 Type* const field_type = access_info.field_type();
950 MachineRepresentation const field_representation = 962 MachineRepresentation const field_representation =
951 access_info.field_representation(); 963 access_info.field_representation();
952 if (access_mode == AccessMode::kLoad) { 964 if (access_mode == AccessMode::kLoad) {
953 if (access_info.holder().ToHandle(&holder)) { 965 if (access_info.holder().ToHandle(&holder)) {
954 receiver = jsgraph()->Constant(holder); 966 receiver = jsgraph()->Constant(holder);
955 } 967 }
956 // Optimize immutable property loads. 968 // Optimize immutable property loads.
957 HeapObjectMatcher m(receiver); 969 HeapObjectMatcher m(receiver);
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
1089 simplified()->StoreField(AccessBuilder::ForMap()), receiver, 1101 simplified()->StoreField(AccessBuilder::ForMap()), receiver,
1090 jsgraph()->Constant(transition_map), effect, control); 1102 jsgraph()->Constant(transition_map), effect, control);
1091 } 1103 }
1092 effect = graph()->NewNode(simplified()->StoreField(field_access), storage, 1104 effect = graph()->NewNode(simplified()->StoreField(field_access), storage,
1093 value, effect, control); 1105 value, effect, control);
1094 if (access_info.HasTransitionMap()) { 1106 if (access_info.HasTransitionMap()) {
1095 effect = graph()->NewNode(common()->FinishRegion(), 1107 effect = graph()->NewNode(common()->FinishRegion(),
1096 jsgraph()->UndefinedConstant(), effect); 1108 jsgraph()->UndefinedConstant(), effect);
1097 } 1109 }
1098 } 1110 }
1111 } else {
1112 DCHECK(access_info.IsGeneric());
1113 DCHECK_EQ(AccessMode::kStore, access_mode);
1114 DCHECK_EQ(FeedbackVectorSlotKind::STORE_IC, vector->GetKind(slot));
1115 Callable callable =
1116 CodeFactory::StoreICInOptimizedCode(isolate(), language_mode);
1117 const CallInterfaceDescriptor& descriptor = callable.descriptor();
1118 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1119 isolate(), graph()->zone(), descriptor,
1120 descriptor.GetStackParameterCount(), CallDescriptor::kNeedsFrameState,
1121 Operator::kNoProperties);
1122 Node* stub_code = jsgraph()->HeapConstant(callable.code());
1123 Node* name_node = jsgraph()->HeapConstant(name);
1124 Node* slot_node = jsgraph()->Constant(vector->GetIndex(slot));
1125 Node* vector_node = jsgraph()->HeapConstant(vector);
1126
1127 Node* inputs[] = {stub_code, receiver, name_node, value, slot_node,
1128 vector_node, context, frame_state, effect, control};
1129
1130 value = effect = control =
1131 graph()->NewNode(common()->Call(desc), arraysize(inputs), inputs);
1132 control = graph()->NewNode(common()->IfSuccess(), control);
1099 } 1133 }
1100 1134
1101 return ValueEffectControl(value, effect, control); 1135 return ValueEffectControl(value, effect, control);
1102 } 1136 }
1103 1137
1104 namespace { 1138 namespace {
1105 1139
1106 ExternalArrayType GetArrayTypeFromElementsKind(ElementsKind kind) { 1140 ExternalArrayType GetArrayTypeFromElementsKind(ElementsKind kind) {
1107 switch (kind) { 1141 switch (kind) {
1108 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ 1142 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after
1617 return jsgraph()->javascript(); 1651 return jsgraph()->javascript();
1618 } 1652 }
1619 1653
1620 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { 1654 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
1621 return jsgraph()->simplified(); 1655 return jsgraph()->simplified();
1622 } 1656 }
1623 1657
1624 } // namespace compiler 1658 } // namespace compiler
1625 } // namespace internal 1659 } // namespace internal
1626 } // namespace v8 1660 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698