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/compilation-dependencies.h" | 8 #include "src/compilation-dependencies.h" |
9 #include "src/compiler/access-builder.h" | 9 #include "src/compiler/access-builder.h" |
10 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/js-graph.h" |
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
562 (this_control_count == 1) | 562 (this_control_count == 1) |
563 ? this_controls.front() | 563 ? this_controls.front() |
564 : graph()->NewNode(common()->Merge(this_control_count), | 564 : graph()->NewNode(common()->Merge(this_control_count), |
565 this_control_count, &this_controls.front()); | 565 this_control_count, &this_controls.front()); |
566 } | 566 } |
567 | 567 |
568 // Determine actual holder and perform prototype chain checks. | 568 // Determine actual holder and perform prototype chain checks. |
569 Handle<JSObject> holder; | 569 Handle<JSObject> holder; |
570 if (access_info.holder().ToHandle(&holder)) { | 570 if (access_info.holder().ToHandle(&holder)) { |
571 this_value = jsgraph()->Constant(holder); | 571 this_value = jsgraph()->Constant(holder); |
572 for (auto i = access_info.receiver_type()->Classes(); !i.Done(); | 572 AssumePrototypesStable(receiver_type, holder); |
573 i.Advance()) { | |
574 Handle<Map> map = i.Current(); | |
575 PrototypeIterator j(map); | |
576 while (true) { | |
577 // Check that the {prototype} still has the same map. For stable | |
578 // maps, we can add a stability dependency on the prototype map; | |
579 // for everything else we need to perform a map check at runtime. | |
580 Handle<JSReceiver> prototype = | |
581 PrototypeIterator::GetCurrent<JSReceiver>(j); | |
582 if (prototype->map()->is_stable()) { | |
583 dependencies()->AssumeMapStable( | |
584 handle(prototype->map(), isolate())); | |
585 } else { | |
586 Node* prototype_map = this_effect = graph()->NewNode( | |
587 simplified()->LoadField(AccessBuilder::ForMap()), | |
588 jsgraph()->Constant(prototype), this_effect, this_control); | |
589 Node* check = graph()->NewNode( | |
590 simplified()->ReferenceEqual(Type::Internal()), prototype_map, | |
591 jsgraph()->Constant(handle(prototype->map(), isolate()))); | |
592 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), | |
593 check, this_control); | |
594 exit_controls.push_back( | |
595 graph()->NewNode(common()->IfFalse(), branch)); | |
596 this_control = graph()->NewNode(common()->IfTrue(), branch); | |
597 } | |
598 // Stop once we get to the holder. | |
599 if (prototype.is_identical_to(holder)) break; | |
600 j.Advance(); | |
601 } | |
602 } | |
603 } | 573 } |
604 | 574 |
605 // Generate the actual property access. | 575 // Generate the actual property access. |
606 if (access_info.IsDataConstant()) { | 576 if (access_info.IsDataConstant()) { |
607 this_value = jsgraph()->Constant(access_info.constant()); | 577 this_value = jsgraph()->Constant(access_info.constant()); |
608 } else { | 578 } else { |
609 // TODO(bmeurer): This is sort of adhoc, and must be refactored into some | 579 // TODO(bmeurer): This is sort of adhoc, and must be refactored into some |
610 // common code once we also have support for stores. | 580 // common code once we also have support for stores. |
611 DCHECK(access_info.IsDataField()); | 581 DCHECK(access_info.IsDataField()); |
612 FieldIndex const field_index = access_info.field_index(); | 582 FieldIndex const field_index = access_info.field_index(); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
775 this_control = | 745 this_control = |
776 (this_control_count == 1) | 746 (this_control_count == 1) |
777 ? this_controls.front() | 747 ? this_controls.front() |
778 : graph()->NewNode(common()->Merge(this_control_count), | 748 : graph()->NewNode(common()->Merge(this_control_count), |
779 this_control_count, &this_controls.front()); | 749 this_control_count, &this_controls.front()); |
780 } | 750 } |
781 | 751 |
782 // Determine actual holder and perform prototype chain checks. | 752 // Determine actual holder and perform prototype chain checks. |
783 Handle<JSObject> holder; | 753 Handle<JSObject> holder; |
784 if (access_info.holder().ToHandle(&holder)) { | 754 if (access_info.holder().ToHandle(&holder)) { |
785 for (auto i = access_info.receiver_type()->Classes(); !i.Done(); | 755 AssumePrototypesStable(receiver_type, holder); |
786 i.Advance()) { | |
787 Handle<Map> map = i.Current(); | |
788 PrototypeIterator j(map); | |
789 while (true) { | |
790 // Check that the {prototype} still has the same map. For stable | |
791 // maps, we can add a stability dependency on the prototype map; | |
792 // for everything else we need to perform a map check at runtime. | |
793 Handle<JSReceiver> prototype = | |
794 PrototypeIterator::GetCurrent<JSReceiver>(j); | |
795 if (prototype->map()->is_stable()) { | |
796 dependencies()->AssumeMapStable( | |
797 handle(prototype->map(), isolate())); | |
798 } else { | |
799 Node* prototype_map = this_effect = graph()->NewNode( | |
800 simplified()->LoadField(AccessBuilder::ForMap()), | |
801 jsgraph()->Constant(prototype), this_effect, this_control); | |
802 Node* check = graph()->NewNode( | |
803 simplified()->ReferenceEqual(Type::Internal()), prototype_map, | |
804 jsgraph()->Constant(handle(prototype->map(), isolate()))); | |
805 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), | |
806 check, this_control); | |
807 exit_controls.push_back( | |
808 graph()->NewNode(common()->IfFalse(), branch)); | |
809 this_control = graph()->NewNode(common()->IfTrue(), branch); | |
810 } | |
811 // Stop once we get to the holder. | |
812 if (prototype.is_identical_to(holder)) break; | |
813 j.Advance(); | |
814 } | |
815 } | |
816 } | 756 } |
817 | 757 |
Toon Verwaest
2015/10/23 13:45:40
What Object.prototype.x? Object.prototype has a nu
Benedikt Meurer
2015/10/23 13:56:26
NotFound case is not implemented.
| |
818 // Generate the actual property access. | 758 // Generate the actual property access. |
819 if (access_info.IsDataConstant()) { | 759 if (access_info.IsDataConstant()) { |
820 Node* check = | 760 Node* check = |
821 graph()->NewNode(simplified()->ReferenceEqual(Type::Tagged()), value, | 761 graph()->NewNode(simplified()->ReferenceEqual(Type::Tagged()), value, |
822 jsgraph()->Constant(access_info.constant())); | 762 jsgraph()->Constant(access_info.constant())); |
823 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), | 763 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
824 check, this_control); | 764 check, this_control); |
825 exit_controls.push_back(graph()->NewNode(common()->IfFalse(), branch)); | 765 exit_controls.push_back(graph()->NewNode(common()->IfFalse(), branch)); |
826 this_control = graph()->NewNode(common()->IfTrue(), branch); | 766 this_control = graph()->NewNode(common()->IfTrue(), branch); |
827 } else { | 767 } else { |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
944 } | 884 } |
945 Handle<Context> script_context = ScriptContextTable::GetContext( | 885 Handle<Context> script_context = ScriptContextTable::GetContext( |
946 script_context_table, lookup_result.context_index); | 886 script_context_table, lookup_result.context_index); |
947 result->context = script_context; | 887 result->context = script_context; |
948 result->immutable = IsImmutableVariableMode(lookup_result.mode); | 888 result->immutable = IsImmutableVariableMode(lookup_result.mode); |
949 result->index = lookup_result.slot_index; | 889 result->index = lookup_result.slot_index; |
950 return true; | 890 return true; |
951 } | 891 } |
952 | 892 |
953 | 893 |
894 void JSNativeContextSpecialization::AssumePrototypesStable( | |
895 Type* receiver_type, Handle<JSObject> holder) { | |
896 // Determine actual holder and perform prototype chain checks. | |
897 for (auto i = receiver_type->Classes(); !i.Done(); i.Advance()) { | |
898 Handle<Map> const map = i.Current(); | |
899 for (PrototypeIterator j(map);; j.Advance()) { | |
Jarin
2015/10/23 13:09:34
Does not it make sense to dcheck that we are not a
| |
900 // Check that the {prototype} still has the same map. All prototype | |
901 // maps are guaranteed to be stable, so it's sufficient to add a | |
902 // stability dependency here. | |
903 Handle<JSReceiver> const prototype = | |
904 PrototypeIterator::GetCurrent<JSReceiver>(j); | |
905 dependencies()->AssumeMapStable(handle(prototype->map(), isolate())); | |
906 // Stop once we get to the holder. | |
907 if (prototype.is_identical_to(holder)) break; | |
908 } | |
909 } | |
910 } | |
911 | |
912 | |
954 Graph* JSNativeContextSpecialization::graph() const { | 913 Graph* JSNativeContextSpecialization::graph() const { |
955 return jsgraph()->graph(); | 914 return jsgraph()->graph(); |
956 } | 915 } |
957 | 916 |
958 | 917 |
959 Isolate* JSNativeContextSpecialization::isolate() const { | 918 Isolate* JSNativeContextSpecialization::isolate() const { |
960 return jsgraph()->isolate(); | 919 return jsgraph()->isolate(); |
961 } | 920 } |
962 | 921 |
963 | 922 |
(...skipping 17 matching lines...) Expand all Loading... | |
981 } | 940 } |
982 | 941 |
983 | 942 |
984 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 943 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
985 return jsgraph()->simplified(); | 944 return jsgraph()->simplified(); |
986 } | 945 } |
987 | 946 |
988 } // namespace compiler | 947 } // namespace compiler |
989 } // namespace internal | 948 } // namespace internal |
990 } // namespace v8 | 949 } // namespace v8 |
OLD | NEW |