OLD | NEW |
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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 for (auto map : maps) { | 50 for (auto map : maps) { |
51 if (!map->IsStringMap()) return false; | 51 if (!map->IsStringMap()) return false; |
52 } | 52 } |
53 return true; | 53 return true; |
54 } | 54 } |
55 | 55 |
56 } // namespace | 56 } // namespace |
57 | 57 |
58 JSNativeContextSpecialization::JSNativeContextSpecialization( | 58 JSNativeContextSpecialization::JSNativeContextSpecialization( |
59 Editor* editor, JSGraph* jsgraph, Flags flags, | 59 Editor* editor, JSGraph* jsgraph, Flags flags, |
60 MaybeHandle<Context> native_context, CompilationDependencies* dependencies, | 60 Handle<Context> native_context, CompilationDependencies* dependencies, |
61 Zone* zone) | 61 Zone* zone) |
62 : AdvancedReducer(editor), | 62 : AdvancedReducer(editor), |
63 jsgraph_(jsgraph), | 63 jsgraph_(jsgraph), |
64 flags_(flags), | 64 flags_(flags), |
65 native_context_(native_context), | 65 native_context_(native_context), |
66 dependencies_(dependencies), | 66 dependencies_(dependencies), |
67 zone_(zone), | 67 zone_(zone), |
68 type_cache_(TypeCache::Get()) {} | 68 type_cache_(TypeCache::Get()) {} |
69 | 69 |
70 | |
71 Reduction JSNativeContextSpecialization::Reduce(Node* node) { | 70 Reduction JSNativeContextSpecialization::Reduce(Node* node) { |
72 switch (node->opcode()) { | 71 switch (node->opcode()) { |
73 case IrOpcode::kJSLoadContext: | 72 case IrOpcode::kJSLoadContext: |
74 return ReduceJSLoadContext(node); | 73 return ReduceJSLoadContext(node); |
75 case IrOpcode::kJSLoadNamed: | 74 case IrOpcode::kJSLoadNamed: |
76 return ReduceJSLoadNamed(node); | 75 return ReduceJSLoadNamed(node); |
77 case IrOpcode::kJSStoreNamed: | 76 case IrOpcode::kJSStoreNamed: |
78 return ReduceJSStoreNamed(node); | 77 return ReduceJSStoreNamed(node); |
79 case IrOpcode::kJSLoadProperty: | 78 case IrOpcode::kJSLoadProperty: |
80 return ReduceJSLoadProperty(node); | 79 return ReduceJSLoadProperty(node); |
81 case IrOpcode::kJSStoreProperty: | 80 case IrOpcode::kJSStoreProperty: |
82 return ReduceJSStoreProperty(node); | 81 return ReduceJSStoreProperty(node); |
83 default: | 82 default: |
84 break; | 83 break; |
85 } | 84 } |
86 return NoChange(); | 85 return NoChange(); |
87 } | 86 } |
88 | 87 |
89 Reduction JSNativeContextSpecialization::ReduceJSLoadContext(Node* node) { | 88 Reduction JSNativeContextSpecialization::ReduceJSLoadContext(Node* node) { |
90 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); | 89 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); |
91 ContextAccess const& access = ContextAccessOf(node->op()); | 90 ContextAccess const& access = ContextAccessOf(node->op()); |
92 Handle<Context> native_context; | |
93 // Specialize JSLoadContext(NATIVE_CONTEXT_INDEX) to the known native | 91 // Specialize JSLoadContext(NATIVE_CONTEXT_INDEX) to the known native |
94 // context (if any), so we can constant-fold those fields, which is | 92 // context (if any), so we can constant-fold those fields, which is |
95 // safe, since the NATIVE_CONTEXT_INDEX slot is always immutable. | 93 // safe, since the NATIVE_CONTEXT_INDEX slot is always immutable. |
96 if (access.index() == Context::NATIVE_CONTEXT_INDEX && | 94 if (access.index() == Context::NATIVE_CONTEXT_INDEX) { |
97 GetNativeContext(node).ToHandle(&native_context)) { | 95 Node* value = jsgraph()->HeapConstant(native_context()); |
98 Node* value = jsgraph()->HeapConstant(native_context); | |
99 ReplaceWithValue(node, value); | 96 ReplaceWithValue(node, value); |
100 return Replace(value); | 97 return Replace(value); |
101 } | 98 } |
102 return NoChange(); | 99 return NoChange(); |
103 } | 100 } |
104 | 101 |
105 Reduction JSNativeContextSpecialization::ReduceNamedAccess( | 102 Reduction JSNativeContextSpecialization::ReduceNamedAccess( |
106 Node* node, Node* value, MapHandleList const& receiver_maps, | 103 Node* node, Node* value, MapHandleList const& receiver_maps, |
107 Handle<Name> name, AccessMode access_mode, LanguageMode language_mode, | 104 Handle<Name> name, AccessMode access_mode, LanguageMode language_mode, |
108 Node* index) { | 105 Node* index) { |
109 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || | 106 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || |
110 node->opcode() == IrOpcode::kJSStoreNamed || | 107 node->opcode() == IrOpcode::kJSStoreNamed || |
111 node->opcode() == IrOpcode::kJSLoadProperty || | 108 node->opcode() == IrOpcode::kJSLoadProperty || |
112 node->opcode() == IrOpcode::kJSStoreProperty); | 109 node->opcode() == IrOpcode::kJSStoreProperty); |
113 Node* receiver = NodeProperties::GetValueInput(node, 0); | 110 Node* receiver = NodeProperties::GetValueInput(node, 0); |
114 Node* context = NodeProperties::GetContextInput(node); | 111 Node* context = NodeProperties::GetContextInput(node); |
115 Node* frame_state_eager = NodeProperties::FindFrameStateBefore(node); | 112 Node* frame_state_eager = NodeProperties::FindFrameStateBefore(node); |
116 Node* frame_state_lazy = NodeProperties::GetFrameStateInput(node); | 113 Node* frame_state_lazy = NodeProperties::GetFrameStateInput(node); |
117 Node* effect = NodeProperties::GetEffectInput(node); | 114 Node* effect = NodeProperties::GetEffectInput(node); |
118 Node* control = NodeProperties::GetControlInput(node); | 115 Node* control = NodeProperties::GetControlInput(node); |
119 | 116 |
120 // Not much we can do if deoptimization support is disabled. | 117 // Not much we can do if deoptimization support is disabled. |
121 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | 118 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); |
122 | 119 |
123 // Retrieve the native context from the given {node}. | |
124 Handle<Context> native_context; | |
125 if (!GetNativeContext(node).ToHandle(&native_context)) return NoChange(); | |
126 | |
127 // Compute property access infos for the receiver maps. | 120 // Compute property access infos for the receiver maps. |
128 AccessInfoFactory access_info_factory(dependencies(), native_context, | 121 AccessInfoFactory access_info_factory(dependencies(), native_context(), |
129 graph()->zone()); | 122 graph()->zone()); |
130 ZoneVector<PropertyAccessInfo> access_infos(zone()); | 123 ZoneVector<PropertyAccessInfo> access_infos(zone()); |
131 if (!access_info_factory.ComputePropertyAccessInfos( | 124 if (!access_info_factory.ComputePropertyAccessInfos( |
132 receiver_maps, name, access_mode, &access_infos)) { | 125 receiver_maps, name, access_mode, &access_infos)) { |
133 return NoChange(); | 126 return NoChange(); |
134 } | 127 } |
135 | 128 |
136 // TODO(turbofan): Add support for inlining into try blocks. | 129 // TODO(turbofan): Add support for inlining into try blocks. |
137 if (NodeProperties::IsExceptionalCall(node) || | 130 if (NodeProperties::IsExceptionalCall(node) || |
138 !(flags() & kAccessorInliningEnabled)) { | 131 !(flags() & kAccessorInliningEnabled)) { |
(...skipping 28 matching lines...) Expand all Loading... |
167 receiver = effect = graph()->NewNode(simplified()->CheckNumber(), | 160 receiver = effect = graph()->NewNode(simplified()->CheckNumber(), |
168 receiver, effect, control); | 161 receiver, effect, control); |
169 } else { | 162 } else { |
170 // Monomorphic property access. | 163 // Monomorphic property access. |
171 effect = BuildCheckHeapObject(receiver, effect, control); | 164 effect = BuildCheckHeapObject(receiver, effect, control); |
172 effect = BuildCheckMaps(receiver, effect, control, | 165 effect = BuildCheckMaps(receiver, effect, control, |
173 access_info.receiver_maps()); | 166 access_info.receiver_maps()); |
174 } | 167 } |
175 | 168 |
176 // Generate the actual property access. | 169 // Generate the actual property access. |
177 ValueEffectControl continuation = BuildPropertyAccess( | 170 ValueEffectControl continuation = |
178 receiver, value, context, frame_state_lazy, effect, control, name, | 171 BuildPropertyAccess(receiver, value, context, frame_state_lazy, effect, |
179 native_context, access_info, access_mode); | 172 control, name, access_info, access_mode); |
180 value = continuation.value(); | 173 value = continuation.value(); |
181 effect = continuation.effect(); | 174 effect = continuation.effect(); |
182 control = continuation.control(); | 175 control = continuation.control(); |
183 } else { | 176 } else { |
184 // The final states for every polymorphic branch. We join them with | 177 // The final states for every polymorphic branch. We join them with |
185 // Merge+Phi+EffectPhi at the bottom. | 178 // Merge+Phi+EffectPhi at the bottom. |
186 ZoneVector<Node*> values(zone()); | 179 ZoneVector<Node*> values(zone()); |
187 ZoneVector<Node*> effects(zone()); | 180 ZoneVector<Node*> effects(zone()); |
188 ZoneVector<Node*> controls(zone()); | 181 ZoneVector<Node*> controls(zone()); |
189 | 182 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 // FrameState after the EffectPhi that is generated above. | 273 // FrameState after the EffectPhi that is generated above. |
281 this_effect = | 274 this_effect = |
282 graph()->NewNode(common()->Checkpoint(), frame_state_eager, | 275 graph()->NewNode(common()->Checkpoint(), frame_state_eager, |
283 this_effect, this_control); | 276 this_effect, this_control); |
284 } | 277 } |
285 } | 278 } |
286 | 279 |
287 // Generate the actual property access. | 280 // Generate the actual property access. |
288 ValueEffectControl continuation = BuildPropertyAccess( | 281 ValueEffectControl continuation = BuildPropertyAccess( |
289 this_receiver, this_value, context, frame_state_lazy, this_effect, | 282 this_receiver, this_value, context, frame_state_lazy, this_effect, |
290 this_control, name, native_context, access_info, access_mode); | 283 this_control, name, access_info, access_mode); |
291 values.push_back(continuation.value()); | 284 values.push_back(continuation.value()); |
292 effects.push_back(continuation.effect()); | 285 effects.push_back(continuation.effect()); |
293 controls.push_back(continuation.control()); | 286 controls.push_back(continuation.control()); |
294 } | 287 } |
295 | 288 |
296 DCHECK_NULL(fallthrough_control); | 289 DCHECK_NULL(fallthrough_control); |
297 | 290 |
298 // Generate the final merge point for all (polymorphic) branches. | 291 // Generate the final merge point for all (polymorphic) branches. |
299 int const control_count = static_cast<int>(controls.size()); | 292 int const control_count = static_cast<int>(controls.size()); |
300 if (control_count == 0) { | 293 if (control_count == 0) { |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
446 length, effect, control); | 439 length, effect, control); |
447 | 440 |
448 // Load the character from the {receiver}. | 441 // Load the character from the {receiver}. |
449 value = graph()->NewNode(simplified()->StringCharCodeAt(), receiver, index, | 442 value = graph()->NewNode(simplified()->StringCharCodeAt(), receiver, index, |
450 control); | 443 control); |
451 | 444 |
452 // Return it as a single character string. | 445 // Return it as a single character string. |
453 value = graph()->NewNode(simplified()->StringFromCharCode(), value); | 446 value = graph()->NewNode(simplified()->StringFromCharCode(), value); |
454 } else { | 447 } else { |
455 // Retrieve the native context from the given {node}. | 448 // Retrieve the native context from the given {node}. |
456 Handle<Context> native_context; | |
457 if (!GetNativeContext(node).ToHandle(&native_context)) return NoChange(); | |
458 | |
459 // Compute element access infos for the receiver maps. | 449 // Compute element access infos for the receiver maps. |
460 AccessInfoFactory access_info_factory(dependencies(), native_context, | 450 AccessInfoFactory access_info_factory(dependencies(), native_context(), |
461 graph()->zone()); | 451 graph()->zone()); |
462 ZoneVector<ElementAccessInfo> access_infos(zone()); | 452 ZoneVector<ElementAccessInfo> access_infos(zone()); |
463 if (!access_info_factory.ComputeElementAccessInfos( | 453 if (!access_info_factory.ComputeElementAccessInfos( |
464 receiver_maps, access_mode, &access_infos)) { | 454 receiver_maps, access_mode, &access_infos)) { |
465 return NoChange(); | 455 return NoChange(); |
466 } | 456 } |
467 | 457 |
468 // Nothing to do if we have no non-deprecated maps. | 458 // Nothing to do if we have no non-deprecated maps. |
469 if (access_infos.empty()) { | 459 if (access_infos.empty()) { |
470 return ReduceSoftDeoptimize( | 460 return ReduceSoftDeoptimize( |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 // don't have the kNoWrite flag on it, even though they are not | 526 // don't have the kNoWrite flag on it, even though they are not |
537 // observable by JavaScript. | 527 // observable by JavaScript. |
538 effect = graph()->NewNode(common()->Checkpoint(), frame_state, effect, | 528 effect = graph()->NewNode(common()->Checkpoint(), frame_state, effect, |
539 control); | 529 control); |
540 | 530 |
541 // Perform map check on the {receiver}. | 531 // Perform map check on the {receiver}. |
542 effect = BuildCheckMaps(receiver, effect, control, | 532 effect = BuildCheckMaps(receiver, effect, control, |
543 access_info.receiver_maps()); | 533 access_info.receiver_maps()); |
544 | 534 |
545 // Access the actual element. | 535 // Access the actual element. |
546 ValueEffectControl continuation = BuildElementAccess( | 536 ValueEffectControl continuation = |
547 receiver, index, value, effect, control, native_context, access_info, | 537 BuildElementAccess(receiver, index, value, effect, control, |
548 access_mode, store_mode); | 538 access_info, access_mode, store_mode); |
549 value = continuation.value(); | 539 value = continuation.value(); |
550 effect = continuation.effect(); | 540 effect = continuation.effect(); |
551 control = continuation.control(); | 541 control = continuation.control(); |
552 } else { | 542 } else { |
553 // The final states for every polymorphic branch. We join them with | 543 // The final states for every polymorphic branch. We join them with |
554 // Merge+Phi+EffectPhi at the bottom. | 544 // Merge+Phi+EffectPhi at the bottom. |
555 ZoneVector<Node*> values(zone()); | 545 ZoneVector<Node*> values(zone()); |
556 ZoneVector<Node*> effects(zone()); | 546 ZoneVector<Node*> effects(zone()); |
557 ZoneVector<Node*> controls(zone()); | 547 ZoneVector<Node*> controls(zone()); |
558 | 548 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 // TODO(turbofan): The effect/control linearization will not find a | 627 // TODO(turbofan): The effect/control linearization will not find a |
638 // FrameState after the EffectPhi that is generated above. | 628 // FrameState after the EffectPhi that is generated above. |
639 this_effect = graph()->NewNode(common()->Checkpoint(), frame_state, | 629 this_effect = graph()->NewNode(common()->Checkpoint(), frame_state, |
640 this_effect, this_control); | 630 this_effect, this_control); |
641 } | 631 } |
642 } | 632 } |
643 | 633 |
644 // Access the actual element. | 634 // Access the actual element. |
645 ValueEffectControl continuation = BuildElementAccess( | 635 ValueEffectControl continuation = BuildElementAccess( |
646 this_receiver, this_index, this_value, this_effect, this_control, | 636 this_receiver, this_index, this_value, this_effect, this_control, |
647 native_context, access_info, access_mode, store_mode); | 637 access_info, access_mode, store_mode); |
648 values.push_back(continuation.value()); | 638 values.push_back(continuation.value()); |
649 effects.push_back(continuation.effect()); | 639 effects.push_back(continuation.effect()); |
650 controls.push_back(continuation.control()); | 640 controls.push_back(continuation.control()); |
651 } | 641 } |
652 | 642 |
653 DCHECK_NULL(fallthrough_control); | 643 DCHECK_NULL(fallthrough_control); |
654 | 644 |
655 // Generate the final merge point for all (polymorphic) branches. | 645 // Generate the final merge point for all (polymorphic) branches. |
656 int const control_count = static_cast<int>(controls.size()); | 646 int const control_count = static_cast<int>(controls.size()); |
657 if (control_count == 0) { | 647 if (control_count == 0) { |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
798 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode(); | 788 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode(); |
799 | 789 |
800 // Try to lower the keyed access based on the {nexus}. | 790 // Try to lower the keyed access based on the {nexus}. |
801 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore, | 791 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore, |
802 p.language_mode(), store_mode); | 792 p.language_mode(), store_mode); |
803 } | 793 } |
804 | 794 |
805 JSNativeContextSpecialization::ValueEffectControl | 795 JSNativeContextSpecialization::ValueEffectControl |
806 JSNativeContextSpecialization::BuildPropertyAccess( | 796 JSNativeContextSpecialization::BuildPropertyAccess( |
807 Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect, | 797 Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect, |
808 Node* control, Handle<Name> name, Handle<Context> native_context, | 798 Node* control, Handle<Name> name, PropertyAccessInfo const& access_info, |
809 PropertyAccessInfo const& access_info, AccessMode access_mode) { | 799 AccessMode access_mode) { |
810 // Determine actual holder and perform prototype chain checks. | 800 // Determine actual holder and perform prototype chain checks. |
811 Handle<JSObject> holder; | 801 Handle<JSObject> holder; |
812 if (access_info.holder().ToHandle(&holder)) { | 802 if (access_info.holder().ToHandle(&holder)) { |
813 AssumePrototypesStable(access_info.receiver_maps(), native_context, holder); | 803 AssumePrototypesStable(access_info.receiver_maps(), holder); |
814 } | 804 } |
815 | 805 |
816 // Generate the actual property access. | 806 // Generate the actual property access. |
817 if (access_info.IsNotFound()) { | 807 if (access_info.IsNotFound()) { |
818 DCHECK_EQ(AccessMode::kLoad, access_mode); | 808 DCHECK_EQ(AccessMode::kLoad, access_mode); |
819 value = jsgraph()->UndefinedConstant(); | 809 value = jsgraph()->UndefinedConstant(); |
820 } else if (access_info.IsDataConstant()) { | 810 } else if (access_info.IsDataConstant()) { |
821 value = jsgraph()->Constant(access_info.constant()); | 811 value = jsgraph()->Constant(access_info.constant()); |
822 if (access_mode == AccessMode::kStore) { | 812 if (access_mode == AccessMode::kStore) { |
823 Node* check = | 813 Node* check = |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1051 } | 1041 } |
1052 UNREACHABLE(); | 1042 UNREACHABLE(); |
1053 return kExternalInt8Array; | 1043 return kExternalInt8Array; |
1054 } | 1044 } |
1055 | 1045 |
1056 } // namespace | 1046 } // namespace |
1057 | 1047 |
1058 JSNativeContextSpecialization::ValueEffectControl | 1048 JSNativeContextSpecialization::ValueEffectControl |
1059 JSNativeContextSpecialization::BuildElementAccess( | 1049 JSNativeContextSpecialization::BuildElementAccess( |
1060 Node* receiver, Node* index, Node* value, Node* effect, Node* control, | 1050 Node* receiver, Node* index, Node* value, Node* effect, Node* control, |
1061 Handle<Context> native_context, ElementAccessInfo const& access_info, | 1051 ElementAccessInfo const& access_info, AccessMode access_mode, |
1062 AccessMode access_mode, KeyedAccessStoreMode store_mode) { | 1052 KeyedAccessStoreMode store_mode) { |
1063 // TODO(bmeurer): We currently specialize based on elements kind. We should | 1053 // TODO(bmeurer): We currently specialize based on elements kind. We should |
1064 // also be able to properly support strings and other JSObjects here. | 1054 // also be able to properly support strings and other JSObjects here. |
1065 ElementsKind elements_kind = access_info.elements_kind(); | 1055 ElementsKind elements_kind = access_info.elements_kind(); |
1066 MapList const& receiver_maps = access_info.receiver_maps(); | 1056 MapList const& receiver_maps = access_info.receiver_maps(); |
1067 | 1057 |
1068 // Load the elements for the {receiver}. | 1058 // Load the elements for the {receiver}. |
1069 Node* elements = effect = graph()->NewNode( | 1059 Node* elements = effect = graph()->NewNode( |
1070 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver, | 1060 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver, |
1071 effect, control); | 1061 effect, control); |
1072 | 1062 |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1227 } | 1217 } |
1228 // Perform the actual backing store access. | 1218 // Perform the actual backing store access. |
1229 value = effect = | 1219 value = effect = |
1230 graph()->NewNode(simplified()->LoadElement(element_access), elements, | 1220 graph()->NewNode(simplified()->LoadElement(element_access), elements, |
1231 index, effect, control); | 1221 index, effect, control); |
1232 // Handle loading from holey backing stores correctly, by either mapping | 1222 // Handle loading from holey backing stores correctly, by either mapping |
1233 // the hole to undefined if possible, or deoptimizing otherwise. | 1223 // the hole to undefined if possible, or deoptimizing otherwise. |
1234 if (elements_kind == FAST_HOLEY_ELEMENTS || | 1224 if (elements_kind == FAST_HOLEY_ELEMENTS || |
1235 elements_kind == FAST_HOLEY_SMI_ELEMENTS) { | 1225 elements_kind == FAST_HOLEY_SMI_ELEMENTS) { |
1236 // Check if we are allowed to turn the hole into undefined. | 1226 // Check if we are allowed to turn the hole into undefined. |
1237 if (CanTreatHoleAsUndefined(receiver_maps, native_context)) { | 1227 if (CanTreatHoleAsUndefined(receiver_maps)) { |
1238 // Turn the hole into undefined. | 1228 // Turn the hole into undefined. |
1239 value = graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), | 1229 value = graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), |
1240 value); | 1230 value); |
1241 } else { | 1231 } else { |
1242 // Bailout if we see the hole. | 1232 // Bailout if we see the hole. |
1243 value = effect = graph()->NewNode(simplified()->CheckTaggedHole(), | 1233 value = effect = graph()->NewNode(simplified()->CheckTaggedHole(), |
1244 value, effect, control); | 1234 value, effect, control); |
1245 } | 1235 } |
1246 } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) { | 1236 } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) { |
1247 // Perform the hole check on the result. | 1237 // Perform the hole check on the result. |
1248 CheckFloat64HoleMode mode = CheckFloat64HoleMode::kNeverReturnHole; | 1238 CheckFloat64HoleMode mode = CheckFloat64HoleMode::kNeverReturnHole; |
1249 // Check if we are allowed to return the hole directly. | 1239 // Check if we are allowed to return the hole directly. |
1250 if (CanTreatHoleAsUndefined(receiver_maps, native_context)) { | 1240 if (CanTreatHoleAsUndefined(receiver_maps)) { |
1251 // Return the signaling NaN hole directly if all uses are truncating. | 1241 // Return the signaling NaN hole directly if all uses are truncating. |
1252 mode = CheckFloat64HoleMode::kAllowReturnHole; | 1242 mode = CheckFloat64HoleMode::kAllowReturnHole; |
1253 } | 1243 } |
1254 value = effect = graph()->NewNode(simplified()->CheckFloat64Hole(mode), | 1244 value = effect = graph()->NewNode(simplified()->CheckFloat64Hole(mode), |
1255 value, effect, control); | 1245 value, effect, control); |
1256 } | 1246 } |
1257 } else { | 1247 } else { |
1258 DCHECK_EQ(AccessMode::kStore, access_mode); | 1248 DCHECK_EQ(AccessMode::kStore, access_mode); |
1259 if (IsFastSmiElementsKind(elements_kind)) { | 1249 if (IsFastSmiElementsKind(elements_kind)) { |
1260 value = effect = | 1250 value = effect = |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1350 return effect; | 1340 return effect; |
1351 } | 1341 } |
1352 default: { | 1342 default: { |
1353 return graph()->NewNode(simplified()->CheckHeapObject(), receiver, effect, | 1343 return graph()->NewNode(simplified()->CheckHeapObject(), receiver, effect, |
1354 control); | 1344 control); |
1355 } | 1345 } |
1356 } | 1346 } |
1357 } | 1347 } |
1358 | 1348 |
1359 void JSNativeContextSpecialization::AssumePrototypesStable( | 1349 void JSNativeContextSpecialization::AssumePrototypesStable( |
1360 std::vector<Handle<Map>> const& receiver_maps, | 1350 std::vector<Handle<Map>> const& receiver_maps, Handle<JSObject> holder) { |
1361 Handle<Context> native_context, Handle<JSObject> holder) { | |
1362 // Determine actual holder and perform prototype chain checks. | 1351 // Determine actual holder and perform prototype chain checks. |
1363 for (auto map : receiver_maps) { | 1352 for (auto map : receiver_maps) { |
1364 // Perform the implicit ToObject for primitives here. | 1353 // Perform the implicit ToObject for primitives here. |
1365 // Implemented according to ES6 section 7.3.2 GetV (V, P). | 1354 // Implemented according to ES6 section 7.3.2 GetV (V, P). |
1366 Handle<JSFunction> constructor; | 1355 Handle<JSFunction> constructor; |
1367 if (Map::GetConstructorFunction(map, native_context) | 1356 if (Map::GetConstructorFunction(map, native_context()) |
1368 .ToHandle(&constructor)) { | 1357 .ToHandle(&constructor)) { |
1369 map = handle(constructor->initial_map(), isolate()); | 1358 map = handle(constructor->initial_map(), isolate()); |
1370 } | 1359 } |
1371 dependencies()->AssumePrototypeMapsStable(map, holder); | 1360 dependencies()->AssumePrototypeMapsStable(map, holder); |
1372 } | 1361 } |
1373 } | 1362 } |
1374 | 1363 |
1375 bool JSNativeContextSpecialization::CanTreatHoleAsUndefined( | 1364 bool JSNativeContextSpecialization::CanTreatHoleAsUndefined( |
1376 std::vector<Handle<Map>> const& receiver_maps, | 1365 std::vector<Handle<Map>> const& receiver_maps) { |
1377 Handle<Context> native_context) { | |
1378 // Check if the array prototype chain is intact. | 1366 // Check if the array prototype chain is intact. |
1379 if (!isolate()->IsFastArrayConstructorPrototypeChainIntact()) return false; | 1367 if (!isolate()->IsFastArrayConstructorPrototypeChainIntact()) return false; |
1380 | 1368 |
1381 // Make sure both the initial Array and Object prototypes are stable. | 1369 // Make sure both the initial Array and Object prototypes are stable. |
1382 Handle<JSObject> initial_array_prototype( | 1370 Handle<JSObject> initial_array_prototype( |
1383 native_context->initial_array_prototype(), isolate()); | 1371 native_context()->initial_array_prototype(), isolate()); |
1384 Handle<JSObject> initial_object_prototype( | 1372 Handle<JSObject> initial_object_prototype( |
1385 native_context->initial_object_prototype(), isolate()); | 1373 native_context()->initial_object_prototype(), isolate()); |
1386 if (!initial_array_prototype->map()->is_stable() || | 1374 if (!initial_array_prototype->map()->is_stable() || |
1387 !initial_object_prototype->map()->is_stable()) { | 1375 !initial_object_prototype->map()->is_stable()) { |
1388 return false; | 1376 return false; |
1389 } | 1377 } |
1390 | 1378 |
1391 // Check if all {receiver_maps} either have the initial Array.prototype | 1379 // Check if all {receiver_maps} either have the initial Array.prototype |
1392 // or the initial Object.prototype as their prototype, as those are | 1380 // or the initial Object.prototype as their prototype, as those are |
1393 // guarded by the array protector cell. | 1381 // guarded by the array protector cell. |
1394 for (Handle<Map> map : receiver_maps) { | 1382 for (Handle<Map> map : receiver_maps) { |
1395 if (map->prototype() != *initial_array_prototype && | 1383 if (map->prototype() != *initial_array_prototype && |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1484 if (initial_map->constructor_or_backpointer() == *mnewtarget.Value()) { | 1472 if (initial_map->constructor_or_backpointer() == *mnewtarget.Value()) { |
1485 DCHECK_EQ(*initial_map, initial_map->FindRootMap()); | 1473 DCHECK_EQ(*initial_map, initial_map->FindRootMap()); |
1486 return initial_map; | 1474 return initial_map; |
1487 } | 1475 } |
1488 } | 1476 } |
1489 } | 1477 } |
1490 } | 1478 } |
1491 return MaybeHandle<Map>(); | 1479 return MaybeHandle<Map>(); |
1492 } | 1480 } |
1493 | 1481 |
1494 MaybeHandle<Context> JSNativeContextSpecialization::GetNativeContext( | |
1495 Node* node) { | |
1496 Node* const context = NodeProperties::GetContextInput(node); | |
1497 return NodeProperties::GetSpecializationNativeContext(context, | |
1498 native_context()); | |
1499 } | |
1500 | |
1501 | |
1502 Graph* JSNativeContextSpecialization::graph() const { | 1482 Graph* JSNativeContextSpecialization::graph() const { |
1503 return jsgraph()->graph(); | 1483 return jsgraph()->graph(); |
1504 } | 1484 } |
1505 | 1485 |
1506 | |
1507 Isolate* JSNativeContextSpecialization::isolate() const { | 1486 Isolate* JSNativeContextSpecialization::isolate() const { |
1508 return jsgraph()->isolate(); | 1487 return jsgraph()->isolate(); |
1509 } | 1488 } |
1510 | 1489 |
1511 | |
1512 Factory* JSNativeContextSpecialization::factory() const { | 1490 Factory* JSNativeContextSpecialization::factory() const { |
1513 return isolate()->factory(); | 1491 return isolate()->factory(); |
1514 } | 1492 } |
1515 | 1493 |
1516 | |
1517 MachineOperatorBuilder* JSNativeContextSpecialization::machine() const { | 1494 MachineOperatorBuilder* JSNativeContextSpecialization::machine() const { |
1518 return jsgraph()->machine(); | 1495 return jsgraph()->machine(); |
1519 } | 1496 } |
1520 | 1497 |
1521 | |
1522 CommonOperatorBuilder* JSNativeContextSpecialization::common() const { | 1498 CommonOperatorBuilder* JSNativeContextSpecialization::common() const { |
1523 return jsgraph()->common(); | 1499 return jsgraph()->common(); |
1524 } | 1500 } |
1525 | 1501 |
1526 | |
1527 JSOperatorBuilder* JSNativeContextSpecialization::javascript() const { | 1502 JSOperatorBuilder* JSNativeContextSpecialization::javascript() const { |
1528 return jsgraph()->javascript(); | 1503 return jsgraph()->javascript(); |
1529 } | 1504 } |
1530 | 1505 |
1531 | |
1532 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 1506 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
1533 return jsgraph()->simplified(); | 1507 return jsgraph()->simplified(); |
1534 } | 1508 } |
1535 | 1509 |
1536 } // namespace compiler | 1510 } // namespace compiler |
1537 } // namespace internal | 1511 } // namespace internal |
1538 } // namespace v8 | 1512 } // namespace v8 |
OLD | NEW |