Chromium Code Reviews| 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 |