| 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 |