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 634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
645 this_effect = this_effects.front(); | 645 this_effect = this_effects.front(); |
646 } else { | 646 } else { |
647 this_control = | 647 this_control = |
648 graph()->NewNode(common()->Merge(this_control_count), | 648 graph()->NewNode(common()->Merge(this_control_count), |
649 this_control_count, &this_controls.front()); | 649 this_control_count, &this_controls.front()); |
650 this_effects.push_back(this_control); | 650 this_effects.push_back(this_control); |
651 this_effect = | 651 this_effect = |
652 graph()->NewNode(common()->EffectPhi(this_control_count), | 652 graph()->NewNode(common()->EffectPhi(this_control_count), |
653 this_control_count + 1, &this_effects.front()); | 653 this_control_count + 1, &this_effects.front()); |
654 } | 654 } |
| 655 |
| 656 // TODO(turbofan): The effect/control linearization will not find a |
| 657 // FrameState after the StoreField or Call that is generated for the |
| 658 // elements kind transition above. This is because those operators |
| 659 // don't have the kNoWrite flag on it, even though they are not |
| 660 // observable by JavaScript. |
| 661 this_effect = graph()->NewNode(common()->Checkpoint(), frame_state, |
| 662 this_effect, this_control); |
655 } | 663 } |
656 | 664 |
657 // Certain stores need a prototype chain check because shape changes | 665 // Certain stores need a prototype chain check because shape changes |
658 // could allow callbacks on elements in the prototype chain that are | 666 // could allow callbacks on elements in the prototype chain that are |
659 // not compatible with (monomorphic) keyed stores. | 667 // not compatible with (monomorphic) keyed stores. |
660 Handle<JSObject> holder; | 668 Handle<JSObject> holder; |
661 if (access_info.holder().ToHandle(&holder)) { | 669 if (access_info.holder().ToHandle(&holder)) { |
662 AssumePrototypesStable(receiver_type, native_context, holder); | 670 AssumePrototypesStable(receiver_type, native_context, holder); |
663 } | 671 } |
664 | 672 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
755 } | 763 } |
756 // Perform the actual backing store access. | 764 // Perform the actual backing store access. |
757 this_value = this_effect = graph()->NewNode( | 765 this_value = this_effect = graph()->NewNode( |
758 simplified()->LoadElement(element_access), this_elements, this_index, | 766 simplified()->LoadElement(element_access), this_elements, this_index, |
759 this_effect, this_control); | 767 this_effect, this_control); |
760 // Handle loading from holey backing stores correctly, by either mapping | 768 // Handle loading from holey backing stores correctly, by either mapping |
761 // the hole to undefined if possible, or deoptimizing otherwise. | 769 // the hole to undefined if possible, or deoptimizing otherwise. |
762 if (elements_kind == FAST_HOLEY_ELEMENTS || | 770 if (elements_kind == FAST_HOLEY_ELEMENTS || |
763 elements_kind == FAST_HOLEY_SMI_ELEMENTS) { | 771 elements_kind == FAST_HOLEY_SMI_ELEMENTS) { |
764 // Perform the hole check on the result. | 772 // Perform the hole check on the result. |
765 Node* check = | 773 CheckTaggedHoleMode mode = CheckTaggedHoleMode::kNeverReturnHole; |
766 graph()->NewNode(simplified()->ReferenceEqual(element_access.type), | |
767 this_value, jsgraph()->TheHoleConstant()); | |
768 // Check if we are allowed to turn the hole into undefined. | 774 // Check if we are allowed to turn the hole into undefined. |
769 Type* initial_holey_array_type = Type::Class( | 775 Type* initial_holey_array_type = Type::Class( |
770 handle(isolate()->get_initial_js_array_map(elements_kind)), | 776 handle(isolate()->get_initial_js_array_map(elements_kind)), |
771 graph()->zone()); | 777 graph()->zone()); |
772 if (receiver_type->NowIs(initial_holey_array_type) && | 778 if (receiver_type->NowIs(initial_holey_array_type) && |
773 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { | 779 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
774 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse), | |
775 check, this_control); | |
776 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | |
777 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | |
778 // Add a code dependency on the array protector cell. | 780 // Add a code dependency on the array protector cell. |
779 AssumePrototypesStable(receiver_type, native_context, | 781 AssumePrototypesStable(receiver_type, native_context, |
780 isolate()->initial_object_prototype()); | 782 isolate()->initial_object_prototype()); |
781 dependencies()->AssumePropertyCell(factory()->array_protector()); | 783 dependencies()->AssumePropertyCell(factory()->array_protector()); |
782 // Turn the hole into undefined. | 784 // Turn the hole into undefined. |
783 this_control = | 785 mode = CheckTaggedHoleMode::kConvertHoleToUndefined; |
784 graph()->NewNode(common()->Merge(2), if_true, if_false); | |
785 this_value = graph()->NewNode( | |
786 common()->Phi(MachineRepresentation::kTagged, 2), | |
787 jsgraph()->UndefinedConstant(), this_value, this_control); | |
788 element_type = | |
789 Type::Union(element_type, Type::Undefined(), graph()->zone()); | |
790 } else { | |
791 // Deoptimize in case of the hole. | |
792 this_control = this_effect = | |
793 graph()->NewNode(common()->DeoptimizeIf(), check, frame_state, | |
794 this_effect, this_control); | |
795 } | 786 } |
796 // Rename the result to represent the actual type (not polluted by the | 787 this_value = this_effect = |
797 // hole). | 788 graph()->NewNode(simplified()->CheckTaggedHole(mode), this_value, |
798 this_value = graph()->NewNode(simplified()->TypeGuard(element_type), | 789 this_effect, this_control); |
799 this_value, this_control); | |
800 } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) { | 790 } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) { |
| 791 // Perform the hole check on the result. |
| 792 CheckFloat64HoleMode mode = CheckFloat64HoleMode::kNeverReturnHole; |
801 // Check if we are allowed to return the hole directly. | 793 // Check if we are allowed to return the hole directly. |
802 Type* initial_holey_array_type = Type::Class( | 794 Type* initial_holey_array_type = Type::Class( |
803 handle(isolate()->get_initial_js_array_map(elements_kind)), | 795 handle(isolate()->get_initial_js_array_map(elements_kind)), |
804 graph()->zone()); | 796 graph()->zone()); |
805 if (receiver_type->NowIs(initial_holey_array_type) && | 797 if (receiver_type->NowIs(initial_holey_array_type) && |
806 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { | 798 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
807 // Add a code dependency on the array protector cell. | 799 // Add a code dependency on the array protector cell. |
808 AssumePrototypesStable(receiver_type, native_context, | 800 AssumePrototypesStable(receiver_type, native_context, |
809 isolate()->initial_object_prototype()); | 801 isolate()->initial_object_prototype()); |
810 dependencies()->AssumePropertyCell(factory()->array_protector()); | 802 dependencies()->AssumePropertyCell(factory()->array_protector()); |
811 // Turn the hole into undefined. | 803 // Return the signaling NaN hole directly if all uses are truncating. |
812 this_value = graph()->NewNode(simplified()->NumberConvertHoleNaN(), | 804 mode = CheckFloat64HoleMode::kAllowReturnHole; |
813 this_value); | |
814 } else { | |
815 // Perform the hole check on the result. | |
816 Node* check = | |
817 graph()->NewNode(simplified()->NumberIsHoleNaN(), this_value); | |
818 // Deoptimize in case of the hole. | |
819 this_control = this_effect = | |
820 graph()->NewNode(common()->DeoptimizeIf(), check, frame_state, | |
821 this_effect, this_control); | |
822 } | 805 } |
| 806 this_value = this_effect = |
| 807 graph()->NewNode(simplified()->CheckFloat64Hole(mode), this_value, |
| 808 this_effect, this_control); |
823 } | 809 } |
824 } else { | 810 } else { |
825 DCHECK_EQ(AccessMode::kStore, access_mode); | 811 DCHECK_EQ(AccessMode::kStore, access_mode); |
826 if (IsFastSmiElementsKind(elements_kind)) { | 812 if (IsFastSmiElementsKind(elements_kind)) { |
827 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), this_value); | 813 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), this_value); |
828 this_control = this_effect = | 814 this_control = this_effect = |
829 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state, | 815 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state, |
830 this_effect, this_control); | 816 this_effect, this_control); |
831 this_value = graph()->NewNode(simplified()->TypeGuard(type_cache_.kSmi), | 817 this_value = graph()->NewNode(simplified()->TypeGuard(type_cache_.kSmi), |
832 this_value, this_control); | 818 this_value, this_control); |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1130 } | 1116 } |
1131 | 1117 |
1132 | 1118 |
1133 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 1119 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
1134 return jsgraph()->simplified(); | 1120 return jsgraph()->simplified(); |
1135 } | 1121 } |
1136 | 1122 |
1137 } // namespace compiler | 1123 } // namespace compiler |
1138 } // namespace internal | 1124 } // namespace internal |
1139 } // namespace v8 | 1125 } // namespace v8 |
OLD | NEW |