| 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" |
| 11 #include "src/compiler/access-info.h" |
| 11 #include "src/compiler/js-graph.h" | 12 #include "src/compiler/js-graph.h" |
| 12 #include "src/compiler/js-operator.h" | 13 #include "src/compiler/js-operator.h" |
| 13 #include "src/compiler/linkage.h" | 14 #include "src/compiler/linkage.h" |
| 14 #include "src/compiler/node-matchers.h" | 15 #include "src/compiler/node-matchers.h" |
| 15 #include "src/field-index-inl.h" | 16 #include "src/field-index-inl.h" |
| 16 #include "src/isolate-inl.h" | 17 #include "src/isolate-inl.h" |
| 17 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! | 18 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! |
| 18 #include "src/type-cache.h" | 19 #include "src/type-cache.h" |
| 19 #include "src/type-feedback-vector.h" | 20 #include "src/type-feedback-vector.h" |
| 20 | 21 |
| 21 namespace v8 { | 22 namespace v8 { |
| 22 namespace internal { | 23 namespace internal { |
| 23 namespace compiler { | 24 namespace compiler { |
| 24 | 25 |
| 25 JSNativeContextSpecialization::JSNativeContextSpecialization( | 26 JSNativeContextSpecialization::JSNativeContextSpecialization( |
| 26 Editor* editor, JSGraph* jsgraph, Flags flags, | 27 Editor* editor, JSGraph* jsgraph, Flags flags, |
| 27 Handle<Context> native_context, CompilationDependencies* dependencies, | 28 MaybeHandle<Context> native_context, CompilationDependencies* dependencies, |
| 28 Zone* zone) | 29 Zone* zone) |
| 29 : AdvancedReducer(editor), | 30 : AdvancedReducer(editor), |
| 30 jsgraph_(jsgraph), | 31 jsgraph_(jsgraph), |
| 31 flags_(flags), | 32 flags_(flags), |
| 32 native_context_(native_context), | 33 native_context_(native_context), |
| 33 dependencies_(dependencies), | 34 dependencies_(dependencies), |
| 34 zone_(zone), | 35 zone_(zone), |
| 35 type_cache_(TypeCache::Get()), | 36 type_cache_(TypeCache::Get()) {} |
| 36 access_info_factory_(dependencies, native_context, graph()->zone()) {} | |
| 37 | 37 |
| 38 | 38 |
| 39 Reduction JSNativeContextSpecialization::Reduce(Node* node) { | 39 Reduction JSNativeContextSpecialization::Reduce(Node* node) { |
| 40 switch (node->opcode()) { | 40 switch (node->opcode()) { |
| 41 case IrOpcode::kJSLoadNamed: | 41 case IrOpcode::kJSLoadNamed: |
| 42 return ReduceJSLoadNamed(node); | 42 return ReduceJSLoadNamed(node); |
| 43 case IrOpcode::kJSStoreNamed: | 43 case IrOpcode::kJSStoreNamed: |
| 44 return ReduceJSStoreNamed(node); | 44 return ReduceJSStoreNamed(node); |
| 45 case IrOpcode::kJSLoadProperty: | 45 case IrOpcode::kJSLoadProperty: |
| 46 return ReduceJSLoadProperty(node); | 46 return ReduceJSLoadProperty(node); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 62 node->opcode() == IrOpcode::kJSLoadProperty || | 62 node->opcode() == IrOpcode::kJSLoadProperty || |
| 63 node->opcode() == IrOpcode::kJSStoreProperty); | 63 node->opcode() == IrOpcode::kJSStoreProperty); |
| 64 Node* receiver = NodeProperties::GetValueInput(node, 0); | 64 Node* receiver = NodeProperties::GetValueInput(node, 0); |
| 65 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | 65 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
| 66 Node* effect = NodeProperties::GetEffectInput(node); | 66 Node* effect = NodeProperties::GetEffectInput(node); |
| 67 Node* control = NodeProperties::GetControlInput(node); | 67 Node* control = NodeProperties::GetControlInput(node); |
| 68 | 68 |
| 69 // Not much we can do if deoptimization support is disabled. | 69 // Not much we can do if deoptimization support is disabled. |
| 70 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | 70 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); |
| 71 | 71 |
| 72 // Retrieve the native context from the given {node}. |
| 73 Handle<Context> native_context; |
| 74 if (!GetNativeContext(node).ToHandle(&native_context)) return NoChange(); |
| 75 |
| 72 // Compute property access infos for the receiver maps. | 76 // Compute property access infos for the receiver maps. |
| 77 AccessInfoFactory access_info_factory(dependencies(), native_context, |
| 78 graph()->zone()); |
| 73 ZoneVector<PropertyAccessInfo> access_infos(zone()); | 79 ZoneVector<PropertyAccessInfo> access_infos(zone()); |
| 74 if (!access_info_factory().ComputePropertyAccessInfos( | 80 if (!access_info_factory.ComputePropertyAccessInfos( |
| 75 receiver_maps, name, access_mode, &access_infos)) { | 81 receiver_maps, name, access_mode, &access_infos)) { |
| 76 return NoChange(); | 82 return NoChange(); |
| 77 } | 83 } |
| 78 | 84 |
| 79 // Nothing to do if we have no non-deprecated maps. | 85 // Nothing to do if we have no non-deprecated maps. |
| 80 if (access_infos.empty()) return NoChange(); | 86 if (access_infos.empty()) return NoChange(); |
| 81 | 87 |
| 82 // The final states for every polymorphic branch. We join them with | 88 // The final states for every polymorphic branch. We join them with |
| 83 // Merge++Phi+EffectPhi at the bottom. | 89 // Merge++Phi+EffectPhi at the bottom. |
| 84 ZoneVector<Node*> values(zone()); | 90 ZoneVector<Node*> values(zone()); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 this_effect = | 182 this_effect = |
| 177 (this_control_count == 1) | 183 (this_control_count == 1) |
| 178 ? this_effects.front() | 184 ? this_effects.front() |
| 179 : graph()->NewNode(common()->EffectPhi(this_control_count), | 185 : graph()->NewNode(common()->EffectPhi(this_control_count), |
| 180 this_effect_count, &this_effects.front()); | 186 this_effect_count, &this_effects.front()); |
| 181 } | 187 } |
| 182 | 188 |
| 183 // Determine actual holder and perform prototype chain checks. | 189 // Determine actual holder and perform prototype chain checks. |
| 184 Handle<JSObject> holder; | 190 Handle<JSObject> holder; |
| 185 if (access_info.holder().ToHandle(&holder)) { | 191 if (access_info.holder().ToHandle(&holder)) { |
| 186 AssumePrototypesStable(receiver_type, holder); | 192 AssumePrototypesStable(receiver_type, native_context, holder); |
| 187 } | 193 } |
| 188 | 194 |
| 189 // Generate the actual property access. | 195 // Generate the actual property access. |
| 190 if (access_info.IsNotFound()) { | 196 if (access_info.IsNotFound()) { |
| 191 DCHECK_EQ(AccessMode::kLoad, access_mode); | 197 DCHECK_EQ(AccessMode::kLoad, access_mode); |
| 192 if (is_strong(language_mode)) { | 198 if (is_strong(language_mode)) { |
| 193 // TODO(bmeurer/mstarzinger): Add support for lowering inside try | 199 // TODO(bmeurer/mstarzinger): Add support for lowering inside try |
| 194 // blocks rewiring the IfException edge to a runtime call/throw. | 200 // blocks rewiring the IfException edge to a runtime call/throw. |
| 195 exit_controls.push_back(this_control); | 201 exit_controls.push_back(this_control); |
| 196 continue; | 202 continue; |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | 486 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
| 481 Node* effect = NodeProperties::GetEffectInput(node); | 487 Node* effect = NodeProperties::GetEffectInput(node); |
| 482 Node* control = NodeProperties::GetControlInput(node); | 488 Node* control = NodeProperties::GetControlInput(node); |
| 483 | 489 |
| 484 // Not much we can do if deoptimization support is disabled. | 490 // Not much we can do if deoptimization support is disabled. |
| 485 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | 491 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); |
| 486 | 492 |
| 487 // TODO(bmeurer): Add support for non-standard stores. | 493 // TODO(bmeurer): Add support for non-standard stores. |
| 488 if (store_mode != STANDARD_STORE) return NoChange(); | 494 if (store_mode != STANDARD_STORE) return NoChange(); |
| 489 | 495 |
| 496 // Retrieve the native context from the given {node}. |
| 497 Handle<Context> native_context; |
| 498 if (!GetNativeContext(node).ToHandle(&native_context)) return NoChange(); |
| 499 |
| 490 // Compute element access infos for the receiver maps. | 500 // Compute element access infos for the receiver maps. |
| 501 AccessInfoFactory access_info_factory(dependencies(), native_context, |
| 502 graph()->zone()); |
| 491 ZoneVector<ElementAccessInfo> access_infos(zone()); | 503 ZoneVector<ElementAccessInfo> access_infos(zone()); |
| 492 if (!access_info_factory().ComputeElementAccessInfos( | 504 if (!access_info_factory.ComputeElementAccessInfos(receiver_maps, access_mode, |
| 493 receiver_maps, access_mode, &access_infos)) { | 505 &access_infos)) { |
| 494 return NoChange(); | 506 return NoChange(); |
| 495 } | 507 } |
| 496 | 508 |
| 497 // Nothing to do if we have no non-deprecated maps. | 509 // Nothing to do if we have no non-deprecated maps. |
| 498 if (access_infos.empty()) return NoChange(); | 510 if (access_infos.empty()) return NoChange(); |
| 499 | 511 |
| 500 // The final states for every polymorphic branch. We join them with | 512 // The final states for every polymorphic branch. We join them with |
| 501 // Merge+Phi+EffectPhi at the bottom. | 513 // Merge+Phi+EffectPhi at the bottom. |
| 502 ZoneVector<Node*> values(zone()); | 514 ZoneVector<Node*> values(zone()); |
| 503 ZoneVector<Node*> effects(zone()); | 515 ZoneVector<Node*> effects(zone()); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 graph()->NewNode(common()->EffectPhi(this_control_count), | 618 graph()->NewNode(common()->EffectPhi(this_control_count), |
| 607 this_control_count + 1, &this_effects.front()); | 619 this_control_count + 1, &this_effects.front()); |
| 608 } | 620 } |
| 609 } | 621 } |
| 610 | 622 |
| 611 // Certain stores need a prototype chain check because shape changes | 623 // Certain stores need a prototype chain check because shape changes |
| 612 // could allow callbacks on elements in the prototype chain that are | 624 // could allow callbacks on elements in the prototype chain that are |
| 613 // not compatible with (monomorphic) keyed stores. | 625 // not compatible with (monomorphic) keyed stores. |
| 614 Handle<JSObject> holder; | 626 Handle<JSObject> holder; |
| 615 if (access_info.holder().ToHandle(&holder)) { | 627 if (access_info.holder().ToHandle(&holder)) { |
| 616 AssumePrototypesStable(receiver_type, holder); | 628 AssumePrototypesStable(receiver_type, native_context, holder); |
| 617 } | 629 } |
| 618 | 630 |
| 619 // Check that the {index} is actually a Number. | 631 // Check that the {index} is actually a Number. |
| 620 if (!NumberMatcher(this_index).HasValue()) { | 632 if (!NumberMatcher(this_index).HasValue()) { |
| 621 Node* check = | 633 Node* check = |
| 622 graph()->NewNode(simplified()->ObjectIsNumber(), this_index); | 634 graph()->NewNode(simplified()->ObjectIsNumber(), this_index); |
| 623 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), | 635 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
| 624 check, this_control); | 636 check, this_control); |
| 625 exit_controls.push_back(graph()->NewNode(common()->IfFalse(), branch)); | 637 exit_controls.push_back(graph()->NewNode(common()->IfFalse(), branch)); |
| 626 this_control = graph()->NewNode(common()->IfTrue(), branch); | 638 this_control = graph()->NewNode(common()->IfTrue(), branch); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 660 check = graph()->NewNode( | 672 check = graph()->NewNode( |
| 661 simplified()->ReferenceEqual(Type::Any()), this_elements_map, | 673 simplified()->ReferenceEqual(Type::Any()), this_elements_map, |
| 662 jsgraph()->HeapConstant(factory()->fixed_array_map())); | 674 jsgraph()->HeapConstant(factory()->fixed_array_map())); |
| 663 branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), check, | 675 branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), check, |
| 664 this_control); | 676 this_control); |
| 665 exit_controls.push_back(graph()->NewNode(common()->IfFalse(), branch)); | 677 exit_controls.push_back(graph()->NewNode(common()->IfFalse(), branch)); |
| 666 this_control = graph()->NewNode(common()->IfTrue(), branch); | 678 this_control = graph()->NewNode(common()->IfTrue(), branch); |
| 667 } | 679 } |
| 668 | 680 |
| 669 // Load the length of the {receiver}. | 681 // Load the length of the {receiver}. |
| 670 Node* this_length; | 682 Node* this_length = this_effect = |
| 671 if (receiver_is_jsarray) { | 683 receiver_is_jsarray |
| 672 FieldAccess length_access = { | 684 ? graph()->NewNode( |
| 673 kTaggedBase, JSArray::kLengthOffset, factory()->name_string(), | 685 simplified()->LoadField( |
| 674 type_cache_.kJSArrayLengthType, kMachAnyTagged}; | 686 AccessBuilder::ForJSArrayLength(elements_kind)), |
| 675 if (IsFastDoubleElementsKind(elements_kind)) { | 687 this_receiver, this_effect, this_control) |
| 676 length_access.type = type_cache_.kFixedDoubleArrayLengthType; | 688 : graph()->NewNode( |
| 677 } else if (IsFastElementsKind(elements_kind)) { | 689 simplified()->LoadField(AccessBuilder::ForFixedArrayLength()), |
| 678 length_access.type = type_cache_.kFixedArrayLengthType; | 690 this_elements, this_effect, this_control); |
| 679 } | |
| 680 this_length = this_effect = | |
| 681 graph()->NewNode(simplified()->LoadField(length_access), | |
| 682 this_receiver, this_effect, this_control); | |
| 683 } else { | |
| 684 this_length = this_effect = graph()->NewNode( | |
| 685 simplified()->LoadField(AccessBuilder::ForFixedArrayLength()), | |
| 686 this_elements, this_effect, this_control); | |
| 687 } | |
| 688 | 691 |
| 689 // Check that the {index} is in the valid range for the {receiver}. | 692 // Check that the {index} is in the valid range for the {receiver}. |
| 690 Node* check = graph()->NewNode(simplified()->NumberLessThan(), this_index, | 693 Node* check = graph()->NewNode(simplified()->NumberLessThan(), this_index, |
| 691 this_length); | 694 this_length); |
| 692 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), check, | 695 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), check, |
| 693 this_control); | 696 this_control); |
| 694 exit_controls.push_back(graph()->NewNode(common()->IfFalse(), branch)); | 697 exit_controls.push_back(graph()->NewNode(common()->IfFalse(), branch)); |
| 695 this_control = graph()->NewNode(common()->IfTrue(), branch); | 698 this_control = graph()->NewNode(common()->IfTrue(), branch); |
| 696 | 699 |
| 697 // Compute the element access. | 700 // Compute the element access. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 check, this_control); | 738 check, this_control); |
| 736 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 739 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
| 737 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 740 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
| 738 // Check if we are allowed to turn the hole into undefined. | 741 // Check if we are allowed to turn the hole into undefined. |
| 739 Type* initial_holey_array_type = Type::Class( | 742 Type* initial_holey_array_type = Type::Class( |
| 740 handle(isolate()->get_initial_js_array_map(elements_kind)), | 743 handle(isolate()->get_initial_js_array_map(elements_kind)), |
| 741 graph()->zone()); | 744 graph()->zone()); |
| 742 if (receiver_type->NowIs(initial_holey_array_type) && | 745 if (receiver_type->NowIs(initial_holey_array_type) && |
| 743 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { | 746 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
| 744 // Add a code dependency on the array protector cell. | 747 // Add a code dependency on the array protector cell. |
| 745 AssumePrototypesStable(receiver_type, | 748 AssumePrototypesStable(receiver_type, native_context, |
| 746 isolate()->initial_object_prototype()); | 749 isolate()->initial_object_prototype()); |
| 747 dependencies()->AssumePropertyCell(factory()->array_protector()); | 750 dependencies()->AssumePropertyCell(factory()->array_protector()); |
| 748 // Turn the hole into undefined. | 751 // Turn the hole into undefined. |
| 749 this_control = | 752 this_control = |
| 750 graph()->NewNode(common()->Merge(2), if_true, if_false); | 753 graph()->NewNode(common()->Merge(2), if_true, if_false); |
| 751 this_value = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), | 754 this_value = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), |
| 752 jsgraph()->UndefinedConstant(), | 755 jsgraph()->UndefinedConstant(), |
| 753 this_value, this_control); | 756 this_value, this_control); |
| 754 element_type = | 757 element_type = |
| 755 Type::Union(element_type, Type::Undefined(), graph()->zone()); | 758 Type::Union(element_type, Type::Undefined(), graph()->zone()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 766 // Perform the hole check on the result. | 769 // Perform the hole check on the result. |
| 767 Node* check = | 770 Node* check = |
| 768 graph()->NewNode(simplified()->NumberIsHoleNaN(), this_value); | 771 graph()->NewNode(simplified()->NumberIsHoleNaN(), this_value); |
| 769 // Check if we are allowed to return the hole directly. | 772 // Check if we are allowed to return the hole directly. |
| 770 Type* initial_holey_array_type = Type::Class( | 773 Type* initial_holey_array_type = Type::Class( |
| 771 handle(isolate()->get_initial_js_array_map(elements_kind)), | 774 handle(isolate()->get_initial_js_array_map(elements_kind)), |
| 772 graph()->zone()); | 775 graph()->zone()); |
| 773 if (receiver_type->NowIs(initial_holey_array_type) && | 776 if (receiver_type->NowIs(initial_holey_array_type) && |
| 774 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { | 777 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
| 775 // Add a code dependency on the array protector cell. | 778 // Add a code dependency on the array protector cell. |
| 776 AssumePrototypesStable(receiver_type, | 779 AssumePrototypesStable(receiver_type, native_context, |
| 777 isolate()->initial_object_prototype()); | 780 isolate()->initial_object_prototype()); |
| 778 dependencies()->AssumePropertyCell(factory()->array_protector()); | 781 dependencies()->AssumePropertyCell(factory()->array_protector()); |
| 779 // Turn the hole into undefined. | 782 // Turn the hole into undefined. |
| 780 this_value = graph()->NewNode( | 783 this_value = graph()->NewNode( |
| 781 common()->Select(kMachAnyTagged, BranchHint::kFalse), check, | 784 common()->Select(kMachAnyTagged, BranchHint::kFalse), check, |
| 782 jsgraph()->UndefinedConstant(), this_value); | 785 jsgraph()->UndefinedConstant(), this_value); |
| 783 } else { | 786 } else { |
| 784 // Deoptimize in case of the hole. | 787 // Deoptimize in case of the hole. |
| 785 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse), | 788 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse), |
| 786 check, this_control); | 789 check, this_control); |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 938 // Extract the keyed access store mode from the KEYED_STORE_IC. | 941 // Extract the keyed access store mode from the KEYED_STORE_IC. |
| 939 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode(); | 942 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode(); |
| 940 | 943 |
| 941 // Try to lower the keyed access based on the {nexus}. | 944 // Try to lower the keyed access based on the {nexus}. |
| 942 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore, | 945 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore, |
| 943 p.language_mode(), store_mode); | 946 p.language_mode(), store_mode); |
| 944 } | 947 } |
| 945 | 948 |
| 946 | 949 |
| 947 void JSNativeContextSpecialization::AssumePrototypesStable( | 950 void JSNativeContextSpecialization::AssumePrototypesStable( |
| 948 Type* receiver_type, Handle<JSObject> holder) { | 951 Type* receiver_type, Handle<Context> native_context, |
| 952 Handle<JSObject> holder) { |
| 949 // Determine actual holder and perform prototype chain checks. | 953 // Determine actual holder and perform prototype chain checks. |
| 950 for (auto i = receiver_type->Classes(); !i.Done(); i.Advance()) { | 954 for (auto i = receiver_type->Classes(); !i.Done(); i.Advance()) { |
| 951 Handle<Map> map = i.Current(); | 955 Handle<Map> map = i.Current(); |
| 952 // Perform the implicit ToObject for primitives here. | 956 // Perform the implicit ToObject for primitives here. |
| 953 // Implemented according to ES6 section 7.3.2 GetV (V, P). | 957 // Implemented according to ES6 section 7.3.2 GetV (V, P). |
| 954 Handle<JSFunction> constructor; | 958 Handle<JSFunction> constructor; |
| 955 if (Map::GetConstructorFunction(map, native_context()) | 959 if (Map::GetConstructorFunction(map, native_context) |
| 956 .ToHandle(&constructor)) { | 960 .ToHandle(&constructor)) { |
| 957 map = handle(constructor->initial_map(), isolate()); | 961 map = handle(constructor->initial_map(), isolate()); |
| 958 } | 962 } |
| 959 for (PrototypeIterator j(map); !j.IsAtEnd(); j.Advance()) { | 963 dependencies()->AssumePrototypeMapsStable(map, holder); |
| 960 // Check that the {prototype} still has the same map. All prototype | |
| 961 // maps are guaranteed to be stable, so it's sufficient to add a | |
| 962 // stability dependency here. | |
| 963 Handle<JSReceiver> const prototype = | |
| 964 PrototypeIterator::GetCurrent<JSReceiver>(j); | |
| 965 dependencies()->AssumeMapStable(handle(prototype->map(), isolate())); | |
| 966 // Stop once we get to the holder. | |
| 967 if (prototype.is_identical_to(holder)) break; | |
| 968 } | |
| 969 } | 964 } |
| 970 } | 965 } |
| 971 | 966 |
| 972 | 967 |
| 973 void JSNativeContextSpecialization::MarkAsDeferred(Node* if_projection) { | 968 void JSNativeContextSpecialization::MarkAsDeferred(Node* if_projection) { |
| 974 Node* branch = NodeProperties::GetControlInput(if_projection); | 969 Node* branch = NodeProperties::GetControlInput(if_projection); |
| 975 DCHECK_EQ(IrOpcode::kBranch, branch->opcode()); | 970 DCHECK_EQ(IrOpcode::kBranch, branch->opcode()); |
| 976 if (if_projection->opcode() == IrOpcode::kIfTrue) { | 971 if (if_projection->opcode() == IrOpcode::kIfTrue) { |
| 977 NodeProperties::ChangeOp(branch, common()->Branch(BranchHint::kFalse)); | 972 NodeProperties::ChangeOp(branch, common()->Branch(BranchHint::kFalse)); |
| 978 } else { | 973 } else { |
| 979 DCHECK_EQ(IrOpcode::kIfFalse, if_projection->opcode()); | 974 DCHECK_EQ(IrOpcode::kIfFalse, if_projection->opcode()); |
| 980 NodeProperties::ChangeOp(branch, common()->Branch(BranchHint::kTrue)); | 975 NodeProperties::ChangeOp(branch, common()->Branch(BranchHint::kTrue)); |
| 981 } | 976 } |
| 982 } | 977 } |
| 983 | 978 |
| 984 | 979 |
| 980 MaybeHandle<Context> JSNativeContextSpecialization::GetNativeContext( |
| 981 Node* node) { |
| 982 Node* const context = NodeProperties::GetContextInput(node); |
| 983 return NodeProperties::GetSpecializationNativeContext(context, |
| 984 native_context()); |
| 985 } |
| 986 |
| 987 |
| 985 Graph* JSNativeContextSpecialization::graph() const { | 988 Graph* JSNativeContextSpecialization::graph() const { |
| 986 return jsgraph()->graph(); | 989 return jsgraph()->graph(); |
| 987 } | 990 } |
| 988 | 991 |
| 989 | 992 |
| 990 Isolate* JSNativeContextSpecialization::isolate() const { | 993 Isolate* JSNativeContextSpecialization::isolate() const { |
| 991 return jsgraph()->isolate(); | 994 return jsgraph()->isolate(); |
| 992 } | 995 } |
| 993 | 996 |
| 994 | 997 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1012 } | 1015 } |
| 1013 | 1016 |
| 1014 | 1017 |
| 1015 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 1018 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
| 1016 return jsgraph()->simplified(); | 1019 return jsgraph()->simplified(); |
| 1017 } | 1020 } |
| 1018 | 1021 |
| 1019 } // namespace compiler | 1022 } // namespace compiler |
| 1020 } // namespace internal | 1023 } // namespace internal |
| 1021 } // namespace v8 | 1024 } // namespace v8 |
| OLD | NEW |