Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/compiler/js-native-context-specialization.cc

Issue 1448903002: [turbofan] Initial support for keyed access to holey elements. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/js-graph.h" 11 #include "src/compiler/js-graph.h"
12 #include "src/compiler/js-operator.h" 12 #include "src/compiler/js-operator.h"
13 #include "src/compiler/linkage.h" 13 #include "src/compiler/linkage.h"
14 #include "src/compiler/node-matchers.h" 14 #include "src/compiler/node-matchers.h"
15 #include "src/field-index-inl.h" 15 #include "src/field-index-inl.h"
16 #include "src/isolate-inl.h"
16 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! 17 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker!
17 #include "src/type-cache.h" 18 #include "src/type-cache.h"
18 #include "src/type-feedback-vector.h" 19 #include "src/type-feedback-vector.h"
19 20
20 namespace v8 { 21 namespace v8 {
21 namespace internal { 22 namespace internal {
22 namespace compiler { 23 namespace compiler {
23 24
24 JSNativeContextSpecialization::JSNativeContextSpecialization( 25 JSNativeContextSpecialization::JSNativeContextSpecialization(
25 Editor* editor, JSGraph* jsgraph, Flags flags, 26 Editor* editor, JSGraph* jsgraph, Flags flags,
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 DCHECK_LT(0, receiver_maps.length()); 490 DCHECK_LT(0, receiver_maps.length());
490 491
491 // Try to lower the named access based on the {receiver_maps}. 492 // Try to lower the named access based on the {receiver_maps}.
492 return ReduceNamedAccess(node, value, receiver_maps, p.name(), 493 return ReduceNamedAccess(node, value, receiver_maps, p.name(),
493 AccessMode::kStore, p.language_mode()); 494 AccessMode::kStore, p.language_mode());
494 } 495 }
495 496
496 497
497 Reduction JSNativeContextSpecialization::ReduceElementAccess( 498 Reduction JSNativeContextSpecialization::ReduceElementAccess(
498 Node* node, Node* index, Node* value, MapHandleList const& receiver_maps, 499 Node* node, Node* index, Node* value, MapHandleList const& receiver_maps,
499 AccessMode access_mode, LanguageMode language_mode) { 500 AccessMode access_mode, LanguageMode language_mode,
501 KeyedAccessStoreMode store_mode) {
500 DCHECK(node->opcode() == IrOpcode::kJSLoadProperty || 502 DCHECK(node->opcode() == IrOpcode::kJSLoadProperty ||
501 node->opcode() == IrOpcode::kJSStoreProperty); 503 node->opcode() == IrOpcode::kJSStoreProperty);
502 Node* receiver = NodeProperties::GetValueInput(node, 0); 504 Node* receiver = NodeProperties::GetValueInput(node, 0);
503 Node* context = NodeProperties::GetContextInput(node); 505 Node* context = NodeProperties::GetContextInput(node);
504 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); 506 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
505 Node* effect = NodeProperties::GetEffectInput(node); 507 Node* effect = NodeProperties::GetEffectInput(node);
506 Node* control = NodeProperties::GetControlInput(node); 508 Node* control = NodeProperties::GetControlInput(node);
507 509
508 // Not much we can do if deoptimization support is disabled. 510 // Not much we can do if deoptimization support is disabled.
509 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); 511 if (!(flags() & kDeoptimizationEnabled)) return NoChange();
510 512
513 // TODO(bmeurer): Add support for non-standard stores.
514 if (store_mode != STANDARD_STORE) return NoChange();
515
511 // Compute element access infos for the receiver maps. 516 // Compute element access infos for the receiver maps.
512 ZoneVector<ElementAccessInfo> access_infos(zone()); 517 ZoneVector<ElementAccessInfo> access_infos(zone());
513 if (!access_info_factory().ComputeElementAccessInfos( 518 if (!access_info_factory().ComputeElementAccessInfos(
514 receiver_maps, access_mode, &access_infos)) { 519 receiver_maps, access_mode, &access_infos)) {
515 return NoChange(); 520 return NoChange();
516 } 521 }
517 522
518 // Nothing to do if we have no non-deprecated maps. 523 // Nothing to do if we have no non-deprecated maps.
519 if (access_infos.empty()) return NoChange(); 524 if (access_infos.empty()) return NoChange();
520 525
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 if (IsFastDoubleElementsKind(elements_kind)) { 726 if (IsFastDoubleElementsKind(elements_kind)) {
722 element_type = type_cache_.kFloat64; 727 element_type = type_cache_.kFloat64;
723 element_machine_type = kMachFloat64; 728 element_machine_type = kMachFloat64;
724 } else if (IsFastSmiElementsKind(elements_kind)) { 729 } else if (IsFastSmiElementsKind(elements_kind)) {
725 element_type = type_cache_.kSmi; 730 element_type = type_cache_.kSmi;
726 } 731 }
727 ElementAccess element_access = {kTaggedBase, FixedArray::kHeaderSize, 732 ElementAccess element_access = {kTaggedBase, FixedArray::kHeaderSize,
728 element_type, element_machine_type}; 733 element_type, element_machine_type};
729 734
730 // Access the actual element. 735 // Access the actual element.
736 // TODO(bmeurer): Refactor this into separate methods or even a separate
737 // class that deals with the elements access.
731 if (access_mode == AccessMode::kLoad) { 738 if (access_mode == AccessMode::kLoad) {
739 // Compute the real element access type, which includes the hole in case
740 // of holey backing stores.
741 if (elements_kind == FAST_HOLEY_ELEMENTS ||
742 elements_kind == FAST_HOLEY_SMI_ELEMENTS) {
743 element_access.type = Type::Union(
744 element_type,
745 Type::Constant(factory()->the_hole_value(), graph()->zone()),
746 graph()->zone());
747 }
748 // Perform the actual backing store access.
732 this_value = this_effect = graph()->NewNode( 749 this_value = this_effect = graph()->NewNode(
733 simplified()->LoadElement(element_access), this_elements, this_index, 750 simplified()->LoadElement(element_access), this_elements, this_index,
734 this_effect, this_control); 751 this_effect, this_control);
752 // Handle loading from holey backing stores correctly, by either mapping
753 // the hole to undefined if possible, or deoptimizing otherwise.
754 if (elements_kind == FAST_HOLEY_ELEMENTS ||
755 elements_kind == FAST_HOLEY_SMI_ELEMENTS) {
756 // Perform the hole check on the result.
757 Node* check =
758 graph()->NewNode(simplified()->ReferenceEqual(element_access.type),
759 this_value, jsgraph()->TheHoleConstant());
760 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse),
761 check, this_control);
762 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
763 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
764 // Check if we are allowed to turn the hole into undefined.
765 Type* initial_holey_array_type = Type::Class(
766 handle(isolate()->get_initial_js_array_map(FAST_HOLEY_ELEMENTS)),
767 graph()->zone());
768 if (receiver_type->NowIs(initial_holey_array_type) &&
769 isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
770 // Add a code dependency on the array protector cell.
771 AssumePrototypesStable(receiver_type,
772 isolate()->initial_object_prototype());
773 dependencies()->AssumePropertyCell(factory()->array_protector());
774 // Turn the hole into undefined.
775 this_control =
776 graph()->NewNode(common()->Merge(2), if_true, if_false);
777 this_value = graph()->NewNode(common()->Phi(kMachAnyTagged, 2),
778 jsgraph()->UndefinedConstant(),
779 this_value, this_control);
780 element_type =
781 Type::Union(element_type, Type::Undefined(), graph()->zone());
782 } else {
783 // Deoptimize in case of the hole.
784 exit_controls.push_back(if_true);
785 this_control = if_false;
786 }
787 // Rename the result to represent the actual type (not polluted by the
788 // hole).
789 this_value = graph()->NewNode(common()->Guard(element_type), this_value,
790 this_control);
791 }
735 } else { 792 } else {
736 DCHECK_EQ(AccessMode::kStore, access_mode); 793 DCHECK_EQ(AccessMode::kStore, access_mode);
737 if (IsFastSmiElementsKind(elements_kind)) { 794 if (IsFastSmiElementsKind(elements_kind)) {
738 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), this_value); 795 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), this_value);
739 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), 796 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
740 check, this_control); 797 check, this_control);
741 exit_controls.push_back(graph()->NewNode(common()->IfFalse(), branch)); 798 exit_controls.push_back(graph()->NewNode(common()->IfFalse(), branch));
742 this_control = graph()->NewNode(common()->IfTrue(), branch); 799 this_control = graph()->NewNode(common()->IfTrue(), branch);
743 } else if (IsFastDoubleElementsKind(elements_kind)) { 800 } else if (IsFastDoubleElementsKind(elements_kind)) {
744 Node* check = 801 Node* check =
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 effect = graph()->NewNode(common()->EffectPhi(control_count), 859 effect = graph()->NewNode(common()->EffectPhi(control_count),
803 control_count + 1, &effects.front()); 860 control_count + 1, &effects.front());
804 } 861 }
805 ReplaceWithValue(node, value, effect, control); 862 ReplaceWithValue(node, value, effect, control);
806 return Replace(value); 863 return Replace(value);
807 } 864 }
808 865
809 866
810 Reduction JSNativeContextSpecialization::ReduceKeyedAccess( 867 Reduction JSNativeContextSpecialization::ReduceKeyedAccess(
811 Node* node, Node* index, Node* value, FeedbackNexus const& nexus, 868 Node* node, Node* index, Node* value, FeedbackNexus const& nexus,
812 AccessMode access_mode, LanguageMode language_mode) { 869 AccessMode access_mode, LanguageMode language_mode,
870 KeyedAccessStoreMode store_mode) {
813 DCHECK(node->opcode() == IrOpcode::kJSLoadProperty || 871 DCHECK(node->opcode() == IrOpcode::kJSLoadProperty ||
814 node->opcode() == IrOpcode::kJSStoreProperty); 872 node->opcode() == IrOpcode::kJSStoreProperty);
815 873
816 // Extract receiver maps from the {nexus}. 874 // Extract receiver maps from the {nexus}.
817 MapHandleList receiver_maps; 875 MapHandleList receiver_maps;
818 if (nexus.ExtractMaps(&receiver_maps) == 0) return NoChange(); 876 if (nexus.ExtractMaps(&receiver_maps) == 0) return NoChange();
819 DCHECK_LT(0, receiver_maps.length()); 877 DCHECK_LT(0, receiver_maps.length());
820 878
821 // Optimize access for constant {index}. 879 // Optimize access for constant {index}.
822 HeapObjectMatcher mindex(index); 880 HeapObjectMatcher mindex(index);
(...skipping 18 matching lines...) Expand all
841 899
842 // Check if we have feedback for a named access. 900 // Check if we have feedback for a named access.
843 if (Name* name = nexus.FindFirstName()) { 901 if (Name* name = nexus.FindFirstName()) {
844 return ReduceNamedAccess(node, value, receiver_maps, 902 return ReduceNamedAccess(node, value, receiver_maps,
845 handle(name, isolate()), access_mode, 903 handle(name, isolate()), access_mode,
846 language_mode, index); 904 language_mode, index);
847 } 905 }
848 906
849 // Try to lower the element access based on the {receiver_maps}. 907 // Try to lower the element access based on the {receiver_maps}.
850 return ReduceElementAccess(node, index, value, receiver_maps, access_mode, 908 return ReduceElementAccess(node, index, value, receiver_maps, access_mode,
851 language_mode); 909 language_mode, store_mode);
852 } 910 }
853 911
854 912
855 Reduction JSNativeContextSpecialization::ReduceJSLoadProperty(Node* node) { 913 Reduction JSNativeContextSpecialization::ReduceJSLoadProperty(Node* node) {
856 DCHECK_EQ(IrOpcode::kJSLoadProperty, node->opcode()); 914 DCHECK_EQ(IrOpcode::kJSLoadProperty, node->opcode());
857 PropertyAccess const& p = PropertyAccessOf(node->op()); 915 PropertyAccess const& p = PropertyAccessOf(node->op());
858 Node* const index = NodeProperties::GetValueInput(node, 1); 916 Node* const index = NodeProperties::GetValueInput(node, 1);
859 Node* const value = jsgraph()->Dead(); 917 Node* const value = jsgraph()->Dead();
860 918
861 // Extract receiver maps from the KEYED_LOAD_IC using the KeyedLoadICNexus. 919 // Extract receiver maps from the KEYED_LOAD_IC using the KeyedLoadICNexus.
862 if (!p.feedback().IsValid()) return NoChange(); 920 if (!p.feedback().IsValid()) return NoChange();
863 KeyedLoadICNexus nexus(p.feedback().vector(), p.feedback().slot()); 921 KeyedLoadICNexus nexus(p.feedback().vector(), p.feedback().slot());
864 922
865 // Try to lower the keyed access based on the {nexus}. 923 // Try to lower the keyed access based on the {nexus}.
866 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kLoad, 924 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kLoad,
867 p.language_mode()); 925 p.language_mode(), STANDARD_STORE);
868 } 926 }
869 927
870 928
871 Reduction JSNativeContextSpecialization::ReduceJSStoreProperty(Node* node) { 929 Reduction JSNativeContextSpecialization::ReduceJSStoreProperty(Node* node) {
872 DCHECK_EQ(IrOpcode::kJSStoreProperty, node->opcode()); 930 DCHECK_EQ(IrOpcode::kJSStoreProperty, node->opcode());
873 PropertyAccess const& p = PropertyAccessOf(node->op()); 931 PropertyAccess const& p = PropertyAccessOf(node->op());
874 Node* const index = NodeProperties::GetValueInput(node, 1); 932 Node* const index = NodeProperties::GetValueInput(node, 1);
875 Node* const value = NodeProperties::GetValueInput(node, 2); 933 Node* const value = NodeProperties::GetValueInput(node, 2);
876 934
877 // Extract receiver maps from the KEYED_STORE_IC using the KeyedStoreICNexus. 935 // Extract receiver maps from the KEYED_STORE_IC using the KeyedStoreICNexus.
878 if (!p.feedback().IsValid()) return NoChange(); 936 if (!p.feedback().IsValid()) return NoChange();
879 KeyedStoreICNexus nexus(p.feedback().vector(), p.feedback().slot()); 937 KeyedStoreICNexus nexus(p.feedback().vector(), p.feedback().slot());
880 938
939 // Extract the keyed access store mode from the KEYED_STORE_IC.
940 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode();
941
881 // Try to lower the keyed access based on the {nexus}. 942 // Try to lower the keyed access based on the {nexus}.
882 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore, 943 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore,
883 p.language_mode()); 944 p.language_mode(), store_mode);
884 } 945 }
885 946
886 947
887 void JSNativeContextSpecialization::AssumePrototypesStable( 948 void JSNativeContextSpecialization::AssumePrototypesStable(
888 Type* receiver_type, Handle<JSObject> holder) { 949 Type* receiver_type, Handle<JSObject> holder) {
889 // Determine actual holder and perform prototype chain checks. 950 // Determine actual holder and perform prototype chain checks.
890 for (auto i = receiver_type->Classes(); !i.Done(); i.Advance()) { 951 for (auto i = receiver_type->Classes(); !i.Done(); i.Advance()) {
891 Handle<Map> map = i.Current(); 952 Handle<Map> map = i.Current();
892 // Perform the implicit ToObject for primitives here. 953 // Perform the implicit ToObject for primitives here.
893 // Implemented according to ES6 section 7.3.2 GetV (V, P). 954 // Implemented according to ES6 section 7.3.2 GetV (V, P).
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
952 } 1013 }
953 1014
954 1015
955 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { 1016 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
956 return jsgraph()->simplified(); 1017 return jsgraph()->simplified();
957 } 1018 }
958 1019
959 } // namespace compiler 1020 } // namespace compiler
960 } // namespace internal 1021 } // namespace internal
961 } // namespace v8 1022 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698