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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 } | 131 } |
132 } | 132 } |
133 return NoChange(); | 133 return NoChange(); |
134 } | 134 } |
135 | 135 |
136 Reduction JSNativeContextSpecialization::ReduceJSGetSuperConstructor( | 136 Reduction JSNativeContextSpecialization::ReduceJSGetSuperConstructor( |
137 Node* node) { | 137 Node* node) { |
138 DCHECK_EQ(IrOpcode::kJSGetSuperConstructor, node->opcode()); | 138 DCHECK_EQ(IrOpcode::kJSGetSuperConstructor, node->opcode()); |
139 Node* constructor = NodeProperties::GetValueInput(node, 0); | 139 Node* constructor = NodeProperties::GetValueInput(node, 0); |
140 | 140 |
141 // If deoptimization is disabled, we cannot optimize. | |
142 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | |
143 | |
144 // Check if the input is a known JSFunction. | 141 // Check if the input is a known JSFunction. |
145 HeapObjectMatcher m(constructor); | 142 HeapObjectMatcher m(constructor); |
146 if (!m.HasValue()) return NoChange(); | 143 if (!m.HasValue()) return NoChange(); |
147 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); | 144 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); |
148 Handle<Map> function_map(function->map(), isolate()); | 145 Handle<Map> function_map(function->map(), isolate()); |
149 Handle<Object> function_prototype(function_map->prototype(), isolate()); | 146 Handle<Object> function_prototype(function_map->prototype(), isolate()); |
150 | 147 |
151 // We can constant-fold the super constructor access if the | 148 // We can constant-fold the super constructor access if the |
152 // {function}s map is stable, i.e. we can use a code dependency | 149 // {function}s map is stable, i.e. we can use a code dependency |
153 // to guard against [[Prototype]] changes of {function}. | 150 // to guard against [[Prototype]] changes of {function}. |
(...skipping 15 matching lines...) Expand all Loading... |
169 } | 166 } |
170 | 167 |
171 Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) { | 168 Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) { |
172 DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode()); | 169 DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode()); |
173 Node* object = NodeProperties::GetValueInput(node, 0); | 170 Node* object = NodeProperties::GetValueInput(node, 0); |
174 Node* constructor = NodeProperties::GetValueInput(node, 1); | 171 Node* constructor = NodeProperties::GetValueInput(node, 1); |
175 Node* context = NodeProperties::GetContextInput(node); | 172 Node* context = NodeProperties::GetContextInput(node); |
176 Node* effect = NodeProperties::GetEffectInput(node); | 173 Node* effect = NodeProperties::GetEffectInput(node); |
177 Node* control = NodeProperties::GetControlInput(node); | 174 Node* control = NodeProperties::GetControlInput(node); |
178 | 175 |
179 // If deoptimization is disabled, we cannot optimize. | |
180 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | |
181 | |
182 // Check if the right hand side is a known {receiver}. | 176 // Check if the right hand side is a known {receiver}. |
183 HeapObjectMatcher m(constructor); | 177 HeapObjectMatcher m(constructor); |
184 if (!m.HasValue() || !m.Value()->IsJSObject()) return NoChange(); | 178 if (!m.HasValue() || !m.Value()->IsJSObject()) return NoChange(); |
185 Handle<JSObject> receiver = Handle<JSObject>::cast(m.Value()); | 179 Handle<JSObject> receiver = Handle<JSObject>::cast(m.Value()); |
186 Handle<Map> receiver_map(receiver->map(), isolate()); | 180 Handle<Map> receiver_map(receiver->map(), isolate()); |
187 | 181 |
188 // Compute property access info for @@hasInstance on {receiver}. | 182 // Compute property access info for @@hasInstance on {receiver}. |
189 PropertyAccessInfo access_info; | 183 PropertyAccessInfo access_info; |
190 AccessInfoFactory access_info_factory(dependencies(), native_context(), | 184 AccessInfoFactory access_info_factory(dependencies(), native_context(), |
191 graph()->zone()); | 185 graph()->zone()); |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 if (LookupInScriptContextTable(name, &result)) { | 500 if (LookupInScriptContextTable(name, &result)) { |
507 if (result.context->is_the_hole(isolate(), result.index)) return NoChange(); | 501 if (result.context->is_the_hole(isolate(), result.index)) return NoChange(); |
508 Node* context = jsgraph()->HeapConstant(result.context); | 502 Node* context = jsgraph()->HeapConstant(result.context); |
509 Node* value = effect = graph()->NewNode( | 503 Node* value = effect = graph()->NewNode( |
510 javascript()->LoadContext(0, result.index, result.immutable), context, | 504 javascript()->LoadContext(0, result.index, result.immutable), context, |
511 effect); | 505 effect); |
512 ReplaceWithValue(node, value, effect); | 506 ReplaceWithValue(node, value, effect); |
513 return Replace(value); | 507 return Replace(value); |
514 } | 508 } |
515 | 509 |
516 // Not much we can do if deoptimization support is disabled. | |
517 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | |
518 | |
519 // Lookup the {name} on the global object instead. | 510 // Lookup the {name} on the global object instead. |
520 return ReduceGlobalAccess(node, nullptr, nullptr, name, AccessMode::kLoad); | 511 return ReduceGlobalAccess(node, nullptr, nullptr, name, AccessMode::kLoad); |
521 } | 512 } |
522 | 513 |
523 Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) { | 514 Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) { |
524 DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode()); | 515 DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode()); |
525 Handle<Name> name = StoreGlobalParametersOf(node->op()).name(); | 516 Handle<Name> name = StoreGlobalParametersOf(node->op()).name(); |
526 Node* value = NodeProperties::GetValueInput(node, 0); | 517 Node* value = NodeProperties::GetValueInput(node, 0); |
527 Node* effect = NodeProperties::GetEffectInput(node); | 518 Node* effect = NodeProperties::GetEffectInput(node); |
528 Node* control = NodeProperties::GetControlInput(node); | 519 Node* control = NodeProperties::GetControlInput(node); |
529 | 520 |
530 // Try to lookup the name on the script context table first (lexical scoping). | 521 // Try to lookup the name on the script context table first (lexical scoping). |
531 ScriptContextTableLookupResult result; | 522 ScriptContextTableLookupResult result; |
532 if (LookupInScriptContextTable(name, &result)) { | 523 if (LookupInScriptContextTable(name, &result)) { |
533 if (result.context->is_the_hole(isolate(), result.index)) return NoChange(); | 524 if (result.context->is_the_hole(isolate(), result.index)) return NoChange(); |
534 if (result.immutable) return NoChange(); | 525 if (result.immutable) return NoChange(); |
535 Node* context = jsgraph()->HeapConstant(result.context); | 526 Node* context = jsgraph()->HeapConstant(result.context); |
536 effect = graph()->NewNode(javascript()->StoreContext(0, result.index), | 527 effect = graph()->NewNode(javascript()->StoreContext(0, result.index), |
537 value, context, effect, control); | 528 value, context, effect, control); |
538 ReplaceWithValue(node, value, effect, control); | 529 ReplaceWithValue(node, value, effect, control); |
539 return Replace(value); | 530 return Replace(value); |
540 } | 531 } |
541 | 532 |
542 // Not much we can do if deoptimization support is disabled. | |
543 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | |
544 | |
545 // Lookup the {name} on the global object instead. | 533 // Lookup the {name} on the global object instead. |
546 return ReduceGlobalAccess(node, nullptr, value, name, AccessMode::kStore); | 534 return ReduceGlobalAccess(node, nullptr, value, name, AccessMode::kStore); |
547 } | 535 } |
548 | 536 |
549 Reduction JSNativeContextSpecialization::ReduceNamedAccess( | 537 Reduction JSNativeContextSpecialization::ReduceNamedAccess( |
550 Node* node, Node* value, MapHandleList const& receiver_maps, | 538 Node* node, Node* value, MapHandleList const& receiver_maps, |
551 Handle<Name> name, AccessMode access_mode, LanguageMode language_mode, | 539 Handle<Name> name, AccessMode access_mode, LanguageMode language_mode, |
552 Handle<FeedbackVector> vector, FeedbackSlot slot, Node* index) { | 540 Handle<FeedbackVector> vector, FeedbackSlot slot, Node* index) { |
553 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || | 541 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || |
554 node->opcode() == IrOpcode::kJSStoreNamed || | 542 node->opcode() == IrOpcode::kJSStoreNamed || |
555 node->opcode() == IrOpcode::kJSLoadProperty || | 543 node->opcode() == IrOpcode::kJSLoadProperty || |
556 node->opcode() == IrOpcode::kJSStoreProperty || | 544 node->opcode() == IrOpcode::kJSStoreProperty || |
557 node->opcode() == IrOpcode::kJSStoreNamedOwn); | 545 node->opcode() == IrOpcode::kJSStoreNamedOwn); |
558 Node* receiver = NodeProperties::GetValueInput(node, 0); | 546 Node* receiver = NodeProperties::GetValueInput(node, 0); |
559 Node* context = NodeProperties::GetContextInput(node); | 547 Node* context = NodeProperties::GetContextInput(node); |
560 Node* frame_state = NodeProperties::GetFrameStateInput(node); | 548 Node* frame_state = NodeProperties::GetFrameStateInput(node); |
561 Node* effect = NodeProperties::GetEffectInput(node); | 549 Node* effect = NodeProperties::GetEffectInput(node); |
562 Node* control = NodeProperties::GetControlInput(node); | 550 Node* control = NodeProperties::GetControlInput(node); |
563 | 551 |
564 // Not much we can do if deoptimization support is disabled. | |
565 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | |
566 | |
567 // Check if we have an access o.x or o.x=v where o is the current | 552 // Check if we have an access o.x or o.x=v where o is the current |
568 // native contexts' global proxy, and turn that into a direct access | 553 // native contexts' global proxy, and turn that into a direct access |
569 // to the current native contexts' global object instead. | 554 // to the current native contexts' global object instead. |
570 if (receiver_maps.length() == 1) { | 555 if (receiver_maps.length() == 1) { |
571 Handle<Map> receiver_map = receiver_maps.first(); | 556 Handle<Map> receiver_map = receiver_maps.first(); |
572 if (receiver_map->IsJSGlobalProxyMap()) { | 557 if (receiver_map->IsJSGlobalProxyMap()) { |
573 Object* maybe_constructor = receiver_map->GetConstructor(); | 558 Object* maybe_constructor = receiver_map->GetConstructor(); |
574 // Detached global proxies have |null| as their constructor. | 559 // Detached global proxies have |null| as their constructor. |
575 if (maybe_constructor->IsJSFunction() && | 560 if (maybe_constructor->IsJSFunction() && |
576 JSFunction::cast(maybe_constructor)->native_context() == | 561 JSFunction::cast(maybe_constructor)->native_context() == |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 | 768 |
784 Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus( | 769 Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus( |
785 Node* node, Node* value, FeedbackNexus const& nexus, Handle<Name> name, | 770 Node* node, Node* value, FeedbackNexus const& nexus, Handle<Name> name, |
786 AccessMode access_mode, LanguageMode language_mode) { | 771 AccessMode access_mode, LanguageMode language_mode) { |
787 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || | 772 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || |
788 node->opcode() == IrOpcode::kJSStoreNamed || | 773 node->opcode() == IrOpcode::kJSStoreNamed || |
789 node->opcode() == IrOpcode::kJSStoreNamedOwn); | 774 node->opcode() == IrOpcode::kJSStoreNamedOwn); |
790 Node* const receiver = NodeProperties::GetValueInput(node, 0); | 775 Node* const receiver = NodeProperties::GetValueInput(node, 0); |
791 Node* const effect = NodeProperties::GetEffectInput(node); | 776 Node* const effect = NodeProperties::GetEffectInput(node); |
792 | 777 |
793 if (flags() & kDeoptimizationEnabled) { | 778 // Check if we are accessing the current native contexts' global proxy. |
794 // Check if we are accessing the current native contexts' global proxy. | 779 HeapObjectMatcher m(receiver); |
795 HeapObjectMatcher m(receiver); | 780 if (m.HasValue() && m.Value().is_identical_to(global_proxy())) { |
796 if (m.HasValue() && m.Value().is_identical_to(global_proxy())) { | 781 // Optimize accesses to the current native contexts' global proxy. |
797 // Optimize accesses to the current native contexts' global proxy. | 782 return ReduceGlobalAccess(node, nullptr, value, name, access_mode); |
798 return ReduceGlobalAccess(node, nullptr, value, name, access_mode); | |
799 } | |
800 } | 783 } |
801 | 784 |
802 // Check if the {nexus} reports type feedback for the IC. | 785 // Check if the {nexus} reports type feedback for the IC. |
803 if (nexus.IsUninitialized()) { | 786 if (nexus.IsUninitialized()) { |
804 if ((flags() & kDeoptimizationEnabled) && | 787 if (flags() & kBailoutOnUninitialized) { |
805 (flags() & kBailoutOnUninitialized)) { | |
806 return ReduceSoftDeoptimize( | 788 return ReduceSoftDeoptimize( |
807 node, | 789 node, |
808 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); | 790 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); |
809 } | 791 } |
810 return NoChange(); | 792 return NoChange(); |
811 } | 793 } |
812 | 794 |
813 // Extract receiver maps from the IC using the {nexus}. | 795 // Extract receiver maps from the IC using the {nexus}. |
814 MapHandleList receiver_maps; | 796 MapHandleList receiver_maps; |
815 if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) { | 797 if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) { |
816 return NoChange(); | 798 return NoChange(); |
817 } else if (receiver_maps.length() == 0) { | 799 } else if (receiver_maps.length() == 0) { |
818 if ((flags() & kDeoptimizationEnabled) && | 800 if (flags() & kBailoutOnUninitialized) { |
819 (flags() & kBailoutOnUninitialized)) { | |
820 return ReduceSoftDeoptimize( | 801 return ReduceSoftDeoptimize( |
821 node, | 802 node, |
822 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); | 803 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); |
823 } | 804 } |
824 return NoChange(); | 805 return NoChange(); |
825 } | 806 } |
826 | 807 |
827 // Try to lower the named access based on the {receiver_maps}. | 808 // Try to lower the named access based on the {receiver_maps}. |
828 return ReduceNamedAccess(node, value, receiver_maps, name, access_mode, | 809 return ReduceNamedAccess(node, value, receiver_maps, name, access_mode, |
829 language_mode, nexus.vector_handle(), nexus.slot()); | 810 language_mode, nexus.vector_handle(), nexus.slot()); |
(...skipping 10 matching lines...) Expand all Loading... |
840 if (m.HasValue()) { | 821 if (m.HasValue()) { |
841 if (m.Value()->IsJSFunction() && | 822 if (m.Value()->IsJSFunction() && |
842 p.name().is_identical_to(factory()->prototype_string())) { | 823 p.name().is_identical_to(factory()->prototype_string())) { |
843 // Optimize "prototype" property of functions. | 824 // Optimize "prototype" property of functions. |
844 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); | 825 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); |
845 if (function->has_initial_map()) { | 826 if (function->has_initial_map()) { |
846 // We need to add a code dependency on the initial map of the | 827 // We need to add a code dependency on the initial map of the |
847 // {function} in order to be notified about changes to the | 828 // {function} in order to be notified about changes to the |
848 // "prototype" of {function}, so it doesn't make sense to | 829 // "prototype" of {function}, so it doesn't make sense to |
849 // continue unless deoptimization is enabled. | 830 // continue unless deoptimization is enabled. |
850 if (flags() & kDeoptimizationEnabled) { | 831 Handle<Map> initial_map(function->initial_map(), isolate()); |
851 Handle<Map> initial_map(function->initial_map(), isolate()); | 832 dependencies()->AssumeInitialMapCantChange(initial_map); |
852 dependencies()->AssumeInitialMapCantChange(initial_map); | 833 Handle<Object> prototype(initial_map->prototype(), isolate()); |
853 Handle<Object> prototype(initial_map->prototype(), isolate()); | 834 Node* value = jsgraph()->Constant(prototype); |
854 Node* value = jsgraph()->Constant(prototype); | 835 ReplaceWithValue(node, value); |
855 ReplaceWithValue(node, value); | 836 return Replace(value); |
856 return Replace(value); | |
857 } | |
858 } | 837 } |
859 } else if (m.Value()->IsString() && | 838 } else if (m.Value()->IsString() && |
860 p.name().is_identical_to(factory()->length_string())) { | 839 p.name().is_identical_to(factory()->length_string())) { |
861 // Constant-fold "length" property on constant strings. | 840 // Constant-fold "length" property on constant strings. |
862 Handle<String> string = Handle<String>::cast(m.Value()); | 841 Handle<String> string = Handle<String>::cast(m.Value()); |
863 Node* value = jsgraph()->Constant(string->length()); | 842 Node* value = jsgraph()->Constant(string->length()); |
864 ReplaceWithValue(node, value); | 843 ReplaceWithValue(node, value); |
865 return Replace(value); | 844 return Replace(value); |
866 } | 845 } |
867 } | 846 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
908 Node* node, Node* index, Node* value, MapHandleList const& receiver_maps, | 887 Node* node, Node* index, Node* value, MapHandleList const& receiver_maps, |
909 AccessMode access_mode, LanguageMode language_mode, | 888 AccessMode access_mode, LanguageMode language_mode, |
910 KeyedAccessStoreMode store_mode) { | 889 KeyedAccessStoreMode store_mode) { |
911 DCHECK(node->opcode() == IrOpcode::kJSLoadProperty || | 890 DCHECK(node->opcode() == IrOpcode::kJSLoadProperty || |
912 node->opcode() == IrOpcode::kJSStoreProperty); | 891 node->opcode() == IrOpcode::kJSStoreProperty); |
913 Node* receiver = NodeProperties::GetValueInput(node, 0); | 892 Node* receiver = NodeProperties::GetValueInput(node, 0); |
914 Node* effect = NodeProperties::GetEffectInput(node); | 893 Node* effect = NodeProperties::GetEffectInput(node); |
915 Node* control = NodeProperties::GetControlInput(node); | 894 Node* control = NodeProperties::GetControlInput(node); |
916 Node* frame_state = NodeProperties::FindFrameStateBefore(node); | 895 Node* frame_state = NodeProperties::FindFrameStateBefore(node); |
917 | 896 |
918 // Not much we can do if deoptimization support is disabled. | |
919 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | |
920 | |
921 // Check for keyed access to strings. | 897 // Check for keyed access to strings. |
922 if (HasOnlyStringMaps(receiver_maps)) { | 898 if (HasOnlyStringMaps(receiver_maps)) { |
923 // Strings are immutable in JavaScript. | 899 // Strings are immutable in JavaScript. |
924 if (access_mode == AccessMode::kStore) return NoChange(); | 900 if (access_mode == AccessMode::kStore) return NoChange(); |
925 | 901 |
926 // Ensure that the {receiver} is actually a String. | 902 // Ensure that the {receiver} is actually a String. |
927 receiver = effect = graph()->NewNode(simplified()->CheckString(), receiver, | 903 receiver = effect = graph()->NewNode(simplified()->CheckString(), receiver, |
928 effect, control); | 904 effect, control); |
929 | 905 |
930 // Determine the {receiver} length. | 906 // Determine the {receiver} length. |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1156 node->opcode() == IrOpcode::kJSStoreProperty); | 1132 node->opcode() == IrOpcode::kJSStoreProperty); |
1157 Node* receiver = NodeProperties::GetValueInput(node, 0); | 1133 Node* receiver = NodeProperties::GetValueInput(node, 0); |
1158 Node* effect = NodeProperties::GetEffectInput(node); | 1134 Node* effect = NodeProperties::GetEffectInput(node); |
1159 Node* control = NodeProperties::GetControlInput(node); | 1135 Node* control = NodeProperties::GetControlInput(node); |
1160 | 1136 |
1161 // Optimize access for constant {receiver}. | 1137 // Optimize access for constant {receiver}. |
1162 HeapObjectMatcher mreceiver(receiver); | 1138 HeapObjectMatcher mreceiver(receiver); |
1163 if (mreceiver.HasValue() && mreceiver.Value()->IsString()) { | 1139 if (mreceiver.HasValue() && mreceiver.Value()->IsString()) { |
1164 Handle<String> string = Handle<String>::cast(mreceiver.Value()); | 1140 Handle<String> string = Handle<String>::cast(mreceiver.Value()); |
1165 | 1141 |
| 1142 // Strings are immutable in JavaScript. |
| 1143 if (access_mode == AccessMode::kStore) return NoChange(); |
| 1144 |
| 1145 // Properly deal with constant {index}. |
| 1146 NumberMatcher mindex(index); |
| 1147 if (mindex.IsInteger() && mindex.IsInRange(0.0, string->length() - 1)) { |
| 1148 // Constant-fold the {index} access to {string}. |
| 1149 Node* value = jsgraph()->HeapConstant( |
| 1150 factory()->LookupSingleCharacterStringFromCode( |
| 1151 string->Get(static_cast<int>(mindex.Value())))); |
| 1152 ReplaceWithValue(node, value, effect, control); |
| 1153 return Replace(value); |
| 1154 } |
| 1155 |
1166 // We can only assume that the {index} is a valid array index if the IC | 1156 // We can only assume that the {index} is a valid array index if the IC |
1167 // is in element access mode and not MEGAMORPHIC, otherwise there's no | 1157 // is in element access mode and not MEGAMORPHIC, otherwise there's no |
1168 // guard for the bounds check below. | 1158 // guard for the bounds check below. |
1169 if (nexus.ic_state() != MEGAMORPHIC && nexus.GetKeyType() == ELEMENT) { | 1159 if (nexus.ic_state() != MEGAMORPHIC && nexus.GetKeyType() == ELEMENT) { |
1170 // Strings are immutable in JavaScript. | 1160 // Ensure that {index} is less than {receiver} length. |
1171 if (access_mode == AccessMode::kStore) return NoChange(); | 1161 Node* length = jsgraph()->Constant(string->length()); |
| 1162 index = effect = graph()->NewNode(simplified()->CheckBounds(), index, |
| 1163 length, effect, control); |
1172 | 1164 |
1173 // Properly deal with constant {index}. | 1165 // Return the character from the {receiver} as single character string. |
1174 NumberMatcher mindex(index); | 1166 value = graph()->NewNode(simplified()->StringCharAt(), receiver, index, |
1175 if (mindex.IsInteger() && mindex.IsInRange(0.0, string->length() - 1)) { | 1167 control); |
1176 // Constant-fold the {index} access to {string}. | 1168 ReplaceWithValue(node, value, effect, control); |
1177 Node* value = jsgraph()->HeapConstant( | 1169 return Replace(value); |
1178 factory()->LookupSingleCharacterStringFromCode( | |
1179 string->Get(static_cast<int>(mindex.Value())))); | |
1180 ReplaceWithValue(node, value, effect, control); | |
1181 return Replace(value); | |
1182 } else if (flags() & kDeoptimizationEnabled) { | |
1183 // Ensure that {index} is less than {receiver} length. | |
1184 Node* length = jsgraph()->Constant(string->length()); | |
1185 index = effect = graph()->NewNode(simplified()->CheckBounds(), index, | |
1186 length, effect, control); | |
1187 | |
1188 // Return the character from the {receiver} as single character string. | |
1189 value = graph()->NewNode(simplified()->StringCharAt(), receiver, index, | |
1190 control); | |
1191 ReplaceWithValue(node, value, effect, control); | |
1192 return Replace(value); | |
1193 } | |
1194 } | 1170 } |
1195 } | 1171 } |
1196 | 1172 |
1197 // Check if the {nexus} reports type feedback for the IC. | 1173 // Check if the {nexus} reports type feedback for the IC. |
1198 if (nexus.IsUninitialized()) { | 1174 if (nexus.IsUninitialized()) { |
1199 if ((flags() & kDeoptimizationEnabled) && | 1175 if (flags() & kBailoutOnUninitialized) { |
1200 (flags() & kBailoutOnUninitialized)) { | |
1201 return ReduceSoftDeoptimize( | 1176 return ReduceSoftDeoptimize( |
1202 node, | 1177 node, |
1203 DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess); | 1178 DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess); |
1204 } | 1179 } |
1205 return NoChange(); | 1180 return NoChange(); |
1206 } | 1181 } |
1207 | 1182 |
1208 // Extract receiver maps from the {nexus}. | 1183 // Extract receiver maps from the {nexus}. |
1209 MapHandleList receiver_maps; | 1184 MapHandleList receiver_maps; |
1210 if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) { | 1185 if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) { |
1211 return NoChange(); | 1186 return NoChange(); |
1212 } else if (receiver_maps.length() == 0) { | 1187 } else if (receiver_maps.length() == 0) { |
1213 if ((flags() & kDeoptimizationEnabled) && | 1188 if (flags() & kBailoutOnUninitialized) { |
1214 (flags() & kBailoutOnUninitialized)) { | |
1215 return ReduceSoftDeoptimize( | 1189 return ReduceSoftDeoptimize( |
1216 node, | 1190 node, |
1217 DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess); | 1191 DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess); |
1218 } | 1192 } |
1219 return NoChange(); | 1193 return NoChange(); |
1220 } | 1194 } |
1221 | 1195 |
1222 // Optimize access for constant {index}. | 1196 // Optimize access for constant {index}. |
1223 HeapObjectMatcher mindex(index); | 1197 HeapObjectMatcher mindex(index); |
1224 if (mindex.HasValue() && mindex.Value()->IsPrimitive()) { | 1198 if (mindex.HasValue() && mindex.Value()->IsPrimitive()) { |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1674 control = graph()->NewNode(common()->IfSuccess(), control); | 1648 control = graph()->NewNode(common()->IfSuccess(), control); |
1675 } | 1649 } |
1676 | 1650 |
1677 return ValueEffectControl(value, effect, control); | 1651 return ValueEffectControl(value, effect, control); |
1678 } | 1652 } |
1679 | 1653 |
1680 Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral( | 1654 Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral( |
1681 Node* node) { | 1655 Node* node) { |
1682 DCHECK_EQ(IrOpcode::kJSStoreDataPropertyInLiteral, node->opcode()); | 1656 DCHECK_EQ(IrOpcode::kJSStoreDataPropertyInLiteral, node->opcode()); |
1683 | 1657 |
1684 // If deoptimization is disabled, we cannot optimize. | |
1685 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | |
1686 | |
1687 FeedbackParameter const& p = FeedbackParameterOf(node->op()); | 1658 FeedbackParameter const& p = FeedbackParameterOf(node->op()); |
1688 | 1659 |
1689 if (!p.feedback().IsValid()) return NoChange(); | 1660 if (!p.feedback().IsValid()) return NoChange(); |
1690 | 1661 |
1691 StoreDataPropertyInLiteralICNexus nexus(p.feedback().vector(), | 1662 StoreDataPropertyInLiteralICNexus nexus(p.feedback().vector(), |
1692 p.feedback().slot()); | 1663 p.feedback().slot()); |
1693 if (nexus.IsUninitialized()) { | 1664 if (nexus.IsUninitialized()) { |
1694 return NoChange(); | 1665 return NoChange(); |
1695 } | 1666 } |
1696 | 1667 |
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2330 return jsgraph()->javascript(); | 2301 return jsgraph()->javascript(); |
2331 } | 2302 } |
2332 | 2303 |
2333 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 2304 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
2334 return jsgraph()->simplified(); | 2305 return jsgraph()->simplified(); |
2335 } | 2306 } |
2336 | 2307 |
2337 } // namespace compiler | 2308 } // namespace compiler |
2338 } // namespace internal | 2309 } // namespace internal |
2339 } // namespace v8 | 2310 } // namespace v8 |
OLD | NEW |