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

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: Fix bailouts 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
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
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 receiver = effect = graph()->NewNode(simplified()->CheckNumber(), 158 receiver = effect = graph()->NewNode(simplified()->CheckNumber(),
156 receiver, effect, control); 159 receiver, effect, control);
157 } else { 160 } else {
158 // Monomorphic property access. 161 // Monomorphic property access.
159 effect = BuildCheckTaggedPointer(receiver, effect, control); 162 effect = BuildCheckTaggedPointer(receiver, effect, control);
160 effect = BuildCheckMaps(receiver, effect, control, 163 effect = BuildCheckMaps(receiver, effect, control,
161 access_info.receiver_maps()); 164 access_info.receiver_maps());
162 } 165 }
163 166
164 // Generate the actual property access. 167 // Generate the actual property access.
165 ValueEffectControl continuation = 168 ValueEffectControl continuation = BuildPropertyAccess(
166 BuildPropertyAccess(receiver, value, effect, control, name, 169 receiver, value, context, frame_state_lazy, effect, control, name,
167 native_context, access_info, access_mode); 170 native_context, access_info, access_mode);
168 value = continuation.value(); 171 value = continuation.value();
169 effect = continuation.effect(); 172 effect = continuation.effect();
170 control = continuation.control(); 173 control = continuation.control();
171 } else { 174 } else {
172 // The final states for every polymorphic branch. We join them with 175 // The final states for every polymorphic branch. We join them with
173 // Merge+Phi+EffectPhi at the bottom. 176 // Merge+Phi+EffectPhi at the bottom.
174 ZoneVector<Node*> values(zone()); 177 ZoneVector<Node*> values(zone());
175 ZoneVector<Node*> effects(zone()); 178 ZoneVector<Node*> effects(zone());
176 ZoneVector<Node*> controls(zone()); 179 ZoneVector<Node*> controls(zone());
177 180
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 // The Number case requires special treatment to also deal with Smis. 246 // The Number case requires special treatment to also deal with Smis.
244 if (HasNumberMaps(receiver_maps)) { 247 if (HasNumberMaps(receiver_maps)) {
245 // Join this check with the "receiver is smi" check above. 248 // Join this check with the "receiver is smi" check above.
246 DCHECK_NOT_NULL(receiverissmi_effect); 249 DCHECK_NOT_NULL(receiverissmi_effect);
247 DCHECK_NOT_NULL(receiverissmi_control); 250 DCHECK_NOT_NULL(receiverissmi_control);
248 this_effects.push_back(receiverissmi_effect); 251 this_effects.push_back(receiverissmi_effect);
249 this_controls.push_back(receiverissmi_control); 252 this_controls.push_back(receiverissmi_control);
250 receiverissmi_effect = receiverissmi_control = nullptr; 253 receiverissmi_effect = receiverissmi_control = nullptr;
251 } 254 }
252 255
253 // Create dominating Merge+EffectPhi for this {receiver} type. 256 // Create single chokepoint for the control.
254 int const this_control_count = static_cast<int>(this_controls.size()); 257 int const this_control_count = static_cast<int>(this_controls.size());
255 this_control = 258 if (this_control_count == 1) {
256 (this_control_count == 1) 259 this_control = this_controls.front();
257 ? this_controls.front() 260 this_effect = this_effects.front();
258 : graph()->NewNode(common()->Merge(this_control_count), 261 } else {
259 this_control_count, &this_controls.front()); 262 this_control =
260 this_effects.push_back(this_control); 263 graph()->NewNode(common()->Merge(this_control_count),
261 int const this_effect_count = static_cast<int>(this_effects.size()); 264 this_control_count, &this_controls.front());
262 this_effect = 265 this_effects.push_back(this_control);
263 (this_control_count == 1) 266 this_effect =
264 ? this_effects.front() 267 graph()->NewNode(common()->EffectPhi(this_control_count),
265 : graph()->NewNode(common()->EffectPhi(this_control_count), 268 this_control_count + 1, &this_effects.front());
266 this_effect_count, &this_effects.front()); 269
270 // TODO(turbofan): The effect/control linearization will not find a
271 // FrameState after the EffectPhi that is generated above.
272 this_effect =
273 graph()->NewNode(common()->Checkpoint(), frame_state_eager,
274 this_effect, this_control);
275 }
267 } 276 }
268 277
269 // Generate the actual property access. 278 // Generate the actual property access.
270 ValueEffectControl continuation = BuildPropertyAccess( 279 ValueEffectControl continuation = BuildPropertyAccess(
271 this_receiver, this_value, this_effect, this_control, name, 280 this_receiver, this_value, context, frame_state_lazy, this_effect,
272 native_context, access_info, access_mode); 281 this_control, name, native_context, access_info, access_mode);
273 values.push_back(continuation.value()); 282 values.push_back(continuation.value());
274 effects.push_back(continuation.effect()); 283 effects.push_back(continuation.effect());
275 controls.push_back(continuation.control()); 284 controls.push_back(continuation.control());
276 } 285 }
277 286
278 DCHECK_NULL(fallthrough_control); 287 DCHECK_NULL(fallthrough_control);
279 288
280 // Generate the final merge point for all (polymorphic) branches. 289 // Generate the final merge point for all (polymorphic) branches.
281 int const control_count = static_cast<int>(controls.size()); 290 int const control_count = static_cast<int>(controls.size());
282 if (control_count == 0) { 291 if (control_count == 0) {
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 } else { 557 } else {
549 this_control = 558 this_control =
550 graph()->NewNode(common()->Merge(this_control_count), 559 graph()->NewNode(common()->Merge(this_control_count),
551 this_control_count, &this_controls.front()); 560 this_control_count, &this_controls.front());
552 this_effects.push_back(this_control); 561 this_effects.push_back(this_control);
553 this_effect = 562 this_effect =
554 graph()->NewNode(common()->EffectPhi(this_control_count), 563 graph()->NewNode(common()->EffectPhi(this_control_count),
555 this_control_count + 1, &this_effects.front()); 564 this_control_count + 1, &this_effects.front());
556 565
557 // TODO(turbofan): The effect/control linearization will not find a 566 // TODO(turbofan): The effect/control linearization will not find a
558 // FrameState after the StoreField or Call that is generated for the 567 // 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, 568 this_effect = graph()->NewNode(common()->Checkpoint(), frame_state,
563 this_effect, this_control); 569 this_effect, this_control);
564 } 570 }
565 } 571 }
566 572
567 // Certain stores need a prototype chain check because shape changes 573 // Certain stores need a prototype chain check because shape changes
568 // could allow callbacks on elements in the prototype chain that are 574 // could allow callbacks on elements in the prototype chain that are
569 // not compatible with (monomorphic) keyed stores. 575 // not compatible with (monomorphic) keyed stores.
570 Handle<JSObject> holder; 576 Handle<JSObject> holder;
571 if (access_info.holder().ToHandle(&holder)) { 577 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. 733 // Extract the keyed access store mode from the KEYED_STORE_IC.
728 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode(); 734 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode();
729 735
730 // Try to lower the keyed access based on the {nexus}. 736 // Try to lower the keyed access based on the {nexus}.
731 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore, 737 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore,
732 p.language_mode(), store_mode); 738 p.language_mode(), store_mode);
733 } 739 }
734 740
735 JSNativeContextSpecialization::ValueEffectControl 741 JSNativeContextSpecialization::ValueEffectControl
736 JSNativeContextSpecialization::BuildPropertyAccess( 742 JSNativeContextSpecialization::BuildPropertyAccess(
737 Node* receiver, Node* value, Node* effect, Node* control, Handle<Name> name, 743 Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect,
738 Handle<Context> native_context, PropertyAccessInfo const& access_info, 744 Node* control, Handle<Name> name, Handle<Context> native_context,
739 AccessMode access_mode) { 745 PropertyAccessInfo const& access_info, AccessMode access_mode) {
740 // Determine actual holder and perform prototype chain checks. 746 // Determine actual holder and perform prototype chain checks.
741 Handle<JSObject> holder; 747 Handle<JSObject> holder;
742 if (access_info.holder().ToHandle(&holder)) { 748 if (access_info.holder().ToHandle(&holder)) {
743 AssumePrototypesStable(access_info.receiver_maps(), native_context, holder); 749 AssumePrototypesStable(access_info.receiver_maps(), native_context, holder);
744 } 750 }
745 751
746 // Generate the actual property access. 752 // Generate the actual property access.
747 if (access_info.IsNotFound()) { 753 if (access_info.IsNotFound()) {
748 DCHECK_EQ(AccessMode::kLoad, access_mode); 754 DCHECK_EQ(AccessMode::kLoad, access_mode);
749 value = jsgraph()->UndefinedConstant(); 755 value = jsgraph()->UndefinedConstant();
750 } else if (access_info.IsDataConstant()) { 756 } else if (access_info.IsDataConstant()) {
751 value = jsgraph()->Constant(access_info.constant()); 757 value = jsgraph()->Constant(access_info.constant());
752 if (access_mode == AccessMode::kStore) { 758 if (access_mode == AccessMode::kStore) {
753 Node* check = graph()->NewNode( 759 Node* check = graph()->NewNode(
754 simplified()->ReferenceEqual(Type::Tagged()), value, value); 760 simplified()->ReferenceEqual(Type::Tagged()), value, value);
755 effect = 761 effect =
756 graph()->NewNode(simplified()->CheckIf(), check, effect, control); 762 graph()->NewNode(simplified()->CheckIf(), check, effect, control);
757 } 763 }
764 } else if (access_info.IsAccessorConstant()) {
765 // TODO(bmeurer): Properly rewire the IfException edge here if there's any.
766 Node* target = jsgraph()->Constant(access_info.constant());
767 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state);
768 Handle<SharedFunctionInfo> shared_info =
769 frame_info.shared_info().ToHandleChecked();
770 switch (access_mode) {
771 case AccessMode::kLoad: {
772 // We need a FrameState for the getter stub to restore the correct
773 // context before returning to fullcodegen.
774 FrameStateFunctionInfo const* frame_info0 =
775 common()->CreateFrameStateFunctionInfo(FrameStateType::kGetterStub,
776 1, 0, shared_info);
777 Node* frame_state0 = graph()->NewNode(
778 common()->FrameState(BailoutId::None(),
779 OutputFrameStateCombine::Ignore(),
780 frame_info0),
781 graph()->NewNode(common()->StateValues(1), receiver),
782 jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(),
783 context, target, frame_state);
784
785 // Introduce the call to the getter function.
786 value = effect = graph()->NewNode(
787 javascript()->CallFunction(
788 2, VectorSlotPair(), ConvertReceiverMode::kNotNullOrUndefined),
789 target, receiver, context, frame_state0, effect, control);
790 control = graph()->NewNode(common()->IfSuccess(), value);
791 break;
792 }
793 case AccessMode::kStore: {
794 // We need a FrameState for the setter stub to restore the correct
795 // context and return the appropriate value to fullcodegen.
796 FrameStateFunctionInfo const* frame_info0 =
797 common()->CreateFrameStateFunctionInfo(FrameStateType::kSetterStub,
798 2, 0, shared_info);
799 Node* frame_state0 = graph()->NewNode(
800 common()->FrameState(BailoutId::None(),
801 OutputFrameStateCombine::Ignore(),
802 frame_info0),
803 graph()->NewNode(common()->StateValues(2), receiver, value),
804 jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(),
805 context, target, frame_state);
806
807 // Introduce the call to the setter function.
808 effect = graph()->NewNode(
809 javascript()->CallFunction(
810 3, VectorSlotPair(), ConvertReceiverMode::kNotNullOrUndefined),
811 target, receiver, value, context, frame_state0, effect, control);
812 control = graph()->NewNode(common()->IfSuccess(), effect);
813 break;
814 }
815 }
758 } else { 816 } else {
759 DCHECK(access_info.IsDataField()); 817 DCHECK(access_info.IsDataField());
760 FieldIndex const field_index = access_info.field_index(); 818 FieldIndex const field_index = access_info.field_index();
761 Type* const field_type = access_info.field_type(); 819 Type* const field_type = access_info.field_type();
762 if (access_mode == AccessMode::kLoad && 820 if (access_mode == AccessMode::kLoad &&
763 access_info.holder().ToHandle(&holder)) { 821 access_info.holder().ToHandle(&holder)) {
764 receiver = jsgraph()->Constant(holder); 822 receiver = jsgraph()->Constant(holder);
765 } 823 }
766 Node* storage = receiver; 824 Node* storage = receiver;
767 if (!field_index.is_inobject()) { 825 if (!field_index.is_inobject()) {
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after
1193 } 1251 }
1194 1252
1195 1253
1196 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { 1254 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
1197 return jsgraph()->simplified(); 1255 return jsgraph()->simplified();
1198 } 1256 }
1199 1257
1200 } // namespace compiler 1258 } // namespace compiler
1201 } // namespace internal 1259 } // namespace internal
1202 } // namespace v8 1260 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698