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

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

Issue 2198473002: [turbofan] Add support for accessor inlining. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@TurboFan_CheckMaps
Patch Set: Fixes Created 4 years, 4 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/compiler/js-native-context-specialization.h ('k') | src/compiler/pipeline.cc » ('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 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 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 103
104 Reduction JSNativeContextSpecialization::ReduceNamedAccess( 104 Reduction JSNativeContextSpecialization::ReduceNamedAccess(
105 Node* node, Node* value, MapHandleList const& receiver_maps, 105 Node* node, Node* value, MapHandleList const& receiver_maps,
106 Handle<Name> name, AccessMode access_mode, LanguageMode language_mode, 106 Handle<Name> name, AccessMode access_mode, LanguageMode language_mode,
107 Node* index) { 107 Node* index) {
108 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || 108 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed ||
109 node->opcode() == IrOpcode::kJSStoreNamed || 109 node->opcode() == IrOpcode::kJSStoreNamed ||
110 node->opcode() == IrOpcode::kJSLoadProperty || 110 node->opcode() == IrOpcode::kJSLoadProperty ||
111 node->opcode() == IrOpcode::kJSStoreProperty); 111 node->opcode() == IrOpcode::kJSStoreProperty);
112 Node* receiver = NodeProperties::GetValueInput(node, 0); 112 Node* receiver = NodeProperties::GetValueInput(node, 0);
113 Node* context = NodeProperties::GetContextInput(node);
114 Node* frame_state_eager = NodeProperties::FindFrameStateBefore(node);
115 Node* frame_state_lazy = NodeProperties::GetFrameStateInput(node, 0);
113 Node* effect = NodeProperties::GetEffectInput(node); 116 Node* effect = NodeProperties::GetEffectInput(node);
114 Node* control = NodeProperties::GetControlInput(node); 117 Node* control = NodeProperties::GetControlInput(node);
115 118
116 // Not much we can do if deoptimization support is disabled. 119 // Not much we can do if deoptimization support is disabled.
117 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); 120 if (!(flags() & kDeoptimizationEnabled)) return NoChange();
118 121
119 // Retrieve the native context from the given {node}. 122 // Retrieve the native context from the given {node}.
120 Handle<Context> native_context; 123 Handle<Context> native_context;
121 if (!GetNativeContext(node).ToHandle(&native_context)) return NoChange(); 124 if (!GetNativeContext(node).ToHandle(&native_context)) return NoChange();
122 125
123 // Compute property access infos for the receiver maps. 126 // Compute property access infos for the receiver maps.
124 AccessInfoFactory access_info_factory(dependencies(), native_context, 127 AccessInfoFactory access_info_factory(dependencies(), native_context,
125 graph()->zone()); 128 graph()->zone());
126 ZoneVector<PropertyAccessInfo> access_infos(zone()); 129 ZoneVector<PropertyAccessInfo> access_infos(zone());
127 if (!access_info_factory.ComputePropertyAccessInfos( 130 if (!access_info_factory.ComputePropertyAccessInfos(
128 receiver_maps, name, access_mode, &access_infos)) { 131 receiver_maps, name, access_mode, &access_infos)) {
129 return NoChange(); 132 return NoChange();
130 } 133 }
131 134
135 // TODO(turbofan): Add support for inlining into try blocks.
136 if (NodeProperties::IsExceptionalCall(node) ||
137 !(flags() & kAccessorInliningEnabled)) {
138 for (auto access_info : access_infos) {
139 if (access_info.IsAccessorConstant()) return NoChange();
140 }
141 }
142
132 // Nothing to do if we have no non-deprecated maps. 143 // Nothing to do if we have no non-deprecated maps.
133 if (access_infos.empty()) { 144 if (access_infos.empty()) {
134 return ReduceSoftDeoptimize( 145 return ReduceSoftDeoptimize(
135 node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); 146 node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
136 } 147 }
137 148
138 // Ensure that {index} matches the specified {name} (if {index} is given). 149 // Ensure that {index} matches the specified {name} (if {index} is given).
139 if (index != nullptr) { 150 if (index != nullptr) {
140 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Name()), 151 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Name()),
141 index, jsgraph()->HeapConstant(name)); 152 index, jsgraph()->HeapConstant(name));
(...skipping 13 matching lines...) Expand all
155 receiver = effect = graph()->NewNode(simplified()->CheckNumber(), 166 receiver = effect = graph()->NewNode(simplified()->CheckNumber(),
156 receiver, effect, control); 167 receiver, effect, control);
157 } else { 168 } else {
158 // Monomorphic property access. 169 // Monomorphic property access.
159 effect = BuildCheckTaggedPointer(receiver, effect, control); 170 effect = BuildCheckTaggedPointer(receiver, effect, control);
160 effect = BuildCheckMaps(receiver, effect, control, 171 effect = BuildCheckMaps(receiver, effect, control,
161 access_info.receiver_maps()); 172 access_info.receiver_maps());
162 } 173 }
163 174
164 // Generate the actual property access. 175 // Generate the actual property access.
165 ValueEffectControl continuation = 176 ValueEffectControl continuation = BuildPropertyAccess(
166 BuildPropertyAccess(receiver, value, effect, control, name, 177 receiver, value, context, frame_state_lazy, effect, control, name,
167 native_context, access_info, access_mode); 178 native_context, access_info, access_mode);
168 value = continuation.value(); 179 value = continuation.value();
169 effect = continuation.effect(); 180 effect = continuation.effect();
170 control = continuation.control(); 181 control = continuation.control();
171 } else { 182 } else {
172 // The final states for every polymorphic branch. We join them with 183 // The final states for every polymorphic branch. We join them with
173 // Merge+Phi+EffectPhi at the bottom. 184 // Merge+Phi+EffectPhi at the bottom.
174 ZoneVector<Node*> values(zone()); 185 ZoneVector<Node*> values(zone());
175 ZoneVector<Node*> effects(zone()); 186 ZoneVector<Node*> effects(zone());
176 ZoneVector<Node*> controls(zone()); 187 ZoneVector<Node*> controls(zone());
177 188
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 // The Number case requires special treatment to also deal with Smis. 254 // The Number case requires special treatment to also deal with Smis.
244 if (HasNumberMaps(receiver_maps)) { 255 if (HasNumberMaps(receiver_maps)) {
245 // Join this check with the "receiver is smi" check above. 256 // Join this check with the "receiver is smi" check above.
246 DCHECK_NOT_NULL(receiverissmi_effect); 257 DCHECK_NOT_NULL(receiverissmi_effect);
247 DCHECK_NOT_NULL(receiverissmi_control); 258 DCHECK_NOT_NULL(receiverissmi_control);
248 this_effects.push_back(receiverissmi_effect); 259 this_effects.push_back(receiverissmi_effect);
249 this_controls.push_back(receiverissmi_control); 260 this_controls.push_back(receiverissmi_control);
250 receiverissmi_effect = receiverissmi_control = nullptr; 261 receiverissmi_effect = receiverissmi_control = nullptr;
251 } 262 }
252 263
253 // Create dominating Merge+EffectPhi for this {receiver} type. 264 // Create single chokepoint for the control.
254 int const this_control_count = static_cast<int>(this_controls.size()); 265 int const this_control_count = static_cast<int>(this_controls.size());
255 this_control = 266 if (this_control_count == 1) {
256 (this_control_count == 1) 267 this_control = this_controls.front();
257 ? this_controls.front() 268 this_effect = this_effects.front();
258 : graph()->NewNode(common()->Merge(this_control_count), 269 } else {
259 this_control_count, &this_controls.front()); 270 this_control =
260 this_effects.push_back(this_control); 271 graph()->NewNode(common()->Merge(this_control_count),
261 int const this_effect_count = static_cast<int>(this_effects.size()); 272 this_control_count, &this_controls.front());
262 this_effect = 273 this_effects.push_back(this_control);
263 (this_control_count == 1) 274 this_effect =
264 ? this_effects.front() 275 graph()->NewNode(common()->EffectPhi(this_control_count),
265 : graph()->NewNode(common()->EffectPhi(this_control_count), 276 this_control_count + 1, &this_effects.front());
266 this_effect_count, &this_effects.front()); 277
278 // TODO(turbofan): The effect/control linearization will not find a
279 // FrameState after the EffectPhi that is generated above.
280 this_effect =
281 graph()->NewNode(common()->Checkpoint(), frame_state_eager,
282 this_effect, this_control);
283 }
267 } 284 }
268 285
269 // Generate the actual property access. 286 // Generate the actual property access.
270 ValueEffectControl continuation = BuildPropertyAccess( 287 ValueEffectControl continuation = BuildPropertyAccess(
271 this_receiver, this_value, this_effect, this_control, name, 288 this_receiver, this_value, context, frame_state_lazy, this_effect,
272 native_context, access_info, access_mode); 289 this_control, name, native_context, access_info, access_mode);
273 values.push_back(continuation.value()); 290 values.push_back(continuation.value());
274 effects.push_back(continuation.effect()); 291 effects.push_back(continuation.effect());
275 controls.push_back(continuation.control()); 292 controls.push_back(continuation.control());
276 } 293 }
277 294
278 DCHECK_NULL(fallthrough_control); 295 DCHECK_NULL(fallthrough_control);
279 296
280 // Generate the final merge point for all (polymorphic) branches. 297 // Generate the final merge point for all (polymorphic) branches.
281 int const control_count = static_cast<int>(controls.size()); 298 int const control_count = static_cast<int>(controls.size());
282 if (control_count == 0) { 299 if (control_count == 0) {
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 } else { 565 } else {
549 this_control = 566 this_control =
550 graph()->NewNode(common()->Merge(this_control_count), 567 graph()->NewNode(common()->Merge(this_control_count),
551 this_control_count, &this_controls.front()); 568 this_control_count, &this_controls.front());
552 this_effects.push_back(this_control); 569 this_effects.push_back(this_control);
553 this_effect = 570 this_effect =
554 graph()->NewNode(common()->EffectPhi(this_control_count), 571 graph()->NewNode(common()->EffectPhi(this_control_count),
555 this_control_count + 1, &this_effects.front()); 572 this_control_count + 1, &this_effects.front());
556 573
557 // TODO(turbofan): The effect/control linearization will not find a 574 // TODO(turbofan): The effect/control linearization will not find a
558 // FrameState after the StoreField or Call that is generated for the 575 // FrameState after the EffectPhi that is generated above.
559 // elements kind transition above. This is because those operators
560 // don't have the kNoWrite flag on it, even though they are not
561 // observable by JavaScript.
562 this_effect = graph()->NewNode(common()->Checkpoint(), frame_state, 576 this_effect = graph()->NewNode(common()->Checkpoint(), frame_state,
563 this_effect, this_control); 577 this_effect, this_control);
564 } 578 }
565 } 579 }
566 580
567 // Certain stores need a prototype chain check because shape changes 581 // Certain stores need a prototype chain check because shape changes
568 // could allow callbacks on elements in the prototype chain that are 582 // could allow callbacks on elements in the prototype chain that are
569 // not compatible with (monomorphic) keyed stores. 583 // not compatible with (monomorphic) keyed stores.
570 Handle<JSObject> holder; 584 Handle<JSObject> holder;
571 if (access_info.holder().ToHandle(&holder)) { 585 if (access_info.holder().ToHandle(&holder)) {
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 // Extract the keyed access store mode from the KEYED_STORE_IC. 741 // Extract the keyed access store mode from the KEYED_STORE_IC.
728 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode(); 742 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode();
729 743
730 // Try to lower the keyed access based on the {nexus}. 744 // Try to lower the keyed access based on the {nexus}.
731 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore, 745 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore,
732 p.language_mode(), store_mode); 746 p.language_mode(), store_mode);
733 } 747 }
734 748
735 JSNativeContextSpecialization::ValueEffectControl 749 JSNativeContextSpecialization::ValueEffectControl
736 JSNativeContextSpecialization::BuildPropertyAccess( 750 JSNativeContextSpecialization::BuildPropertyAccess(
737 Node* receiver, Node* value, Node* effect, Node* control, Handle<Name> name, 751 Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect,
738 Handle<Context> native_context, PropertyAccessInfo const& access_info, 752 Node* control, Handle<Name> name, Handle<Context> native_context,
739 AccessMode access_mode) { 753 PropertyAccessInfo const& access_info, AccessMode access_mode) {
740 // Determine actual holder and perform prototype chain checks. 754 // Determine actual holder and perform prototype chain checks.
741 Handle<JSObject> holder; 755 Handle<JSObject> holder;
742 if (access_info.holder().ToHandle(&holder)) { 756 if (access_info.holder().ToHandle(&holder)) {
743 AssumePrototypesStable(access_info.receiver_maps(), native_context, holder); 757 AssumePrototypesStable(access_info.receiver_maps(), native_context, holder);
744 } 758 }
745 759
746 // Generate the actual property access. 760 // Generate the actual property access.
747 if (access_info.IsNotFound()) { 761 if (access_info.IsNotFound()) {
748 DCHECK_EQ(AccessMode::kLoad, access_mode); 762 DCHECK_EQ(AccessMode::kLoad, access_mode);
749 value = jsgraph()->UndefinedConstant(); 763 value = jsgraph()->UndefinedConstant();
750 } else if (access_info.IsDataConstant()) { 764 } else if (access_info.IsDataConstant()) {
751 value = jsgraph()->Constant(access_info.constant()); 765 value = jsgraph()->Constant(access_info.constant());
752 if (access_mode == AccessMode::kStore) { 766 if (access_mode == AccessMode::kStore) {
753 Node* check = graph()->NewNode( 767 Node* check = graph()->NewNode(
754 simplified()->ReferenceEqual(Type::Tagged()), value, value); 768 simplified()->ReferenceEqual(Type::Tagged()), value, value);
755 effect = 769 effect =
756 graph()->NewNode(simplified()->CheckIf(), check, effect, control); 770 graph()->NewNode(simplified()->CheckIf(), check, effect, control);
757 } 771 }
772 } else if (access_info.IsAccessorConstant()) {
773 // TODO(bmeurer): Properly rewire the IfException edge here if there's any.
774 Node* target = jsgraph()->Constant(access_info.constant());
775 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state);
776 Handle<SharedFunctionInfo> shared_info =
777 frame_info.shared_info().ToHandleChecked();
778 switch (access_mode) {
779 case AccessMode::kLoad: {
780 // We need a FrameState for the getter stub to restore the correct
781 // context before returning to fullcodegen.
782 FrameStateFunctionInfo const* frame_info0 =
783 common()->CreateFrameStateFunctionInfo(FrameStateType::kGetterStub,
784 1, 0, shared_info);
785 Node* frame_state0 = graph()->NewNode(
786 common()->FrameState(BailoutId::None(),
787 OutputFrameStateCombine::Ignore(),
788 frame_info0),
789 graph()->NewNode(common()->StateValues(1), receiver),
790 jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(),
791 context, target, frame_state);
792
793 // Introduce the call to the getter function.
794 value = effect = graph()->NewNode(
795 javascript()->CallFunction(
796 2, VectorSlotPair(), ConvertReceiverMode::kNotNullOrUndefined),
797 target, receiver, context, frame_state0, effect, control);
798 control = graph()->NewNode(common()->IfSuccess(), value);
799 break;
800 }
801 case AccessMode::kStore: {
802 // We need a FrameState for the setter stub to restore the correct
803 // context and return the appropriate value to fullcodegen.
804 FrameStateFunctionInfo const* frame_info0 =
805 common()->CreateFrameStateFunctionInfo(FrameStateType::kSetterStub,
806 2, 0, shared_info);
807 Node* frame_state0 = graph()->NewNode(
808 common()->FrameState(BailoutId::None(),
809 OutputFrameStateCombine::Ignore(),
810 frame_info0),
811 graph()->NewNode(common()->StateValues(2), receiver, value),
812 jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(),
813 context, target, frame_state);
814
815 // Introduce the call to the setter function.
816 effect = graph()->NewNode(
817 javascript()->CallFunction(
818 3, VectorSlotPair(), ConvertReceiverMode::kNotNullOrUndefined),
819 target, receiver, value, context, frame_state0, effect, control);
820 control = graph()->NewNode(common()->IfSuccess(), effect);
821 break;
822 }
823 }
758 } else { 824 } else {
759 DCHECK(access_info.IsDataField()); 825 DCHECK(access_info.IsDataField());
760 FieldIndex const field_index = access_info.field_index(); 826 FieldIndex const field_index = access_info.field_index();
761 Type* const field_type = access_info.field_type(); 827 Type* const field_type = access_info.field_type();
762 if (access_mode == AccessMode::kLoad && 828 if (access_mode == AccessMode::kLoad &&
763 access_info.holder().ToHandle(&holder)) { 829 access_info.holder().ToHandle(&holder)) {
764 receiver = jsgraph()->Constant(holder); 830 receiver = jsgraph()->Constant(holder);
765 } 831 }
766 Node* storage = receiver; 832 Node* storage = receiver;
767 if (!field_index.is_inobject()) { 833 if (!field_index.is_inobject()) {
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after
1193 } 1259 }
1194 1260
1195 1261
1196 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { 1262 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
1197 return jsgraph()->simplified(); 1263 return jsgraph()->simplified();
1198 } 1264 }
1199 1265
1200 } // namespace compiler 1266 } // namespace compiler
1201 } // namespace internal 1267 } // namespace internal
1202 } // namespace v8 1268 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | src/compiler/pipeline.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698