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" |
11 #include "src/compiler/access-info.h" | 11 #include "src/compiler/access-info.h" |
12 #include "src/compiler/js-graph.h" | 12 #include "src/compiler/js-graph.h" |
13 #include "src/compiler/js-operator.h" | 13 #include "src/compiler/js-operator.h" |
14 #include "src/compiler/linkage.h" | 14 #include "src/compiler/linkage.h" |
15 #include "src/compiler/node-matchers.h" | 15 #include "src/compiler/node-matchers.h" |
16 #include "src/compiler/type-cache.h" | 16 #include "src/compiler/type-cache.h" |
17 #include "src/feedback-vector.h" | 17 #include "src/feedback-vector.h" |
18 #include "src/field-index-inl.h" | 18 #include "src/field-index-inl.h" |
19 #include "src/isolate-inl.h" | 19 #include "src/isolate-inl.h" |
20 | 20 |
21 namespace v8 { | 21 namespace v8 { |
22 namespace internal { | 22 namespace internal { |
23 namespace compiler { | 23 namespace compiler { |
24 | 24 |
25 namespace { | 25 namespace { |
26 | 26 |
27 bool HasNumberMaps(MapList const& maps) { | 27 bool HasNumberMaps(MapHandles const& maps) { |
28 for (auto map : maps) { | 28 for (auto map : maps) { |
29 if (map->instance_type() == HEAP_NUMBER_TYPE) return true; | 29 if (map->instance_type() == HEAP_NUMBER_TYPE) return true; |
30 } | 30 } |
31 return false; | 31 return false; |
32 } | 32 } |
33 | 33 |
34 bool HasOnlyJSArrayMaps(MapList const& maps) { | 34 bool HasOnlyJSArrayMaps(MapHandles const& maps) { |
35 for (auto map : maps) { | 35 for (auto map : maps) { |
36 if (!map->IsJSArrayMap()) return false; | 36 if (!map->IsJSArrayMap()) return false; |
37 } | 37 } |
38 return true; | 38 return true; |
39 } | 39 } |
40 | 40 |
41 bool HasOnlyNumberMaps(MapList const& maps) { | 41 bool HasOnlyNumberMaps(MapHandles const& maps) { |
42 for (auto map : maps) { | 42 for (auto map : maps) { |
43 if (map->instance_type() != HEAP_NUMBER_TYPE) return false; | 43 if (map->instance_type() != HEAP_NUMBER_TYPE) return false; |
44 } | 44 } |
45 return true; | 45 return true; |
46 } | 46 } |
47 | 47 |
48 template <typename T> | 48 template <typename T> |
49 bool HasOnlyStringMaps(T const& maps) { | 49 bool HasOnlyStringMaps(T const& maps) { |
50 for (auto map : maps) { | 50 for (auto map : maps) { |
51 if (!map->IsStringMap()) return false; | 51 if (!map->IsStringMap()) return false; |
(...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
699 value, context, effect, control); | 699 value, context, effect, control); |
700 ReplaceWithValue(node, value, effect, control); | 700 ReplaceWithValue(node, value, effect, control); |
701 return Replace(value); | 701 return Replace(value); |
702 } | 702 } |
703 | 703 |
704 // Lookup the {name} on the global object instead. | 704 // Lookup the {name} on the global object instead. |
705 return ReduceGlobalAccess(node, nullptr, value, name, AccessMode::kStore); | 705 return ReduceGlobalAccess(node, nullptr, value, name, AccessMode::kStore); |
706 } | 706 } |
707 | 707 |
708 Reduction JSNativeContextSpecialization::ReduceNamedAccess( | 708 Reduction JSNativeContextSpecialization::ReduceNamedAccess( |
709 Node* node, Node* value, MapHandleList const& receiver_maps, | 709 Node* node, Node* value, MapHandles const& receiver_maps, Handle<Name> name, |
710 Handle<Name> name, AccessMode access_mode, LanguageMode language_mode, | 710 AccessMode access_mode, LanguageMode language_mode, Node* index) { |
711 Node* index) { | |
712 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || | 711 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || |
713 node->opcode() == IrOpcode::kJSStoreNamed || | 712 node->opcode() == IrOpcode::kJSStoreNamed || |
714 node->opcode() == IrOpcode::kJSLoadProperty || | 713 node->opcode() == IrOpcode::kJSLoadProperty || |
715 node->opcode() == IrOpcode::kJSStoreProperty || | 714 node->opcode() == IrOpcode::kJSStoreProperty || |
716 node->opcode() == IrOpcode::kJSStoreNamedOwn); | 715 node->opcode() == IrOpcode::kJSStoreNamedOwn); |
717 Node* receiver = NodeProperties::GetValueInput(node, 0); | 716 Node* receiver = NodeProperties::GetValueInput(node, 0); |
718 Node* context = NodeProperties::GetContextInput(node); | 717 Node* context = NodeProperties::GetContextInput(node); |
719 Node* frame_state = NodeProperties::GetFrameStateInput(node); | 718 Node* frame_state = NodeProperties::GetFrameStateInput(node); |
720 Node* effect = NodeProperties::GetEffectInput(node); | 719 Node* effect = NodeProperties::GetEffectInput(node); |
721 Node* control = NodeProperties::GetControlInput(node); | 720 Node* control = NodeProperties::GetControlInput(node); |
722 | 721 |
723 // Check if we have an access o.x or o.x=v where o is the current | 722 // Check if we have an access o.x or o.x=v where o is the current |
724 // native contexts' global proxy, and turn that into a direct access | 723 // native contexts' global proxy, and turn that into a direct access |
725 // to the current native contexts' global object instead. | 724 // to the current native contexts' global object instead. |
726 if (receiver_maps.length() == 1) { | 725 if (receiver_maps.size() == 1) { |
727 Handle<Map> receiver_map = receiver_maps.first(); | 726 Handle<Map> receiver_map = receiver_maps.front(); |
728 if (receiver_map->IsJSGlobalProxyMap()) { | 727 if (receiver_map->IsJSGlobalProxyMap()) { |
729 Object* maybe_constructor = receiver_map->GetConstructor(); | 728 Object* maybe_constructor = receiver_map->GetConstructor(); |
730 // Detached global proxies have |null| as their constructor. | 729 // Detached global proxies have |null| as their constructor. |
731 if (maybe_constructor->IsJSFunction() && | 730 if (maybe_constructor->IsJSFunction() && |
732 JSFunction::cast(maybe_constructor)->native_context() == | 731 JSFunction::cast(maybe_constructor)->native_context() == |
733 *native_context()) { | 732 *native_context()) { |
734 return ReduceGlobalAccess(node, receiver, value, name, access_mode, | 733 return ReduceGlobalAccess(node, receiver, value, name, access_mode, |
735 index); | 734 index); |
736 } | 735 } |
737 } | 736 } |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
834 // Generate code for the various different property access patterns. | 833 // Generate code for the various different property access patterns. |
835 Node* fallthrough_control = control; | 834 Node* fallthrough_control = control; |
836 for (size_t j = 0; j < access_infos.size(); ++j) { | 835 for (size_t j = 0; j < access_infos.size(); ++j) { |
837 PropertyAccessInfo const& access_info = access_infos[j]; | 836 PropertyAccessInfo const& access_info = access_infos[j]; |
838 Node* this_value = value; | 837 Node* this_value = value; |
839 Node* this_receiver = receiver; | 838 Node* this_receiver = receiver; |
840 Node* this_effect = effect; | 839 Node* this_effect = effect; |
841 Node* this_control = fallthrough_control; | 840 Node* this_control = fallthrough_control; |
842 | 841 |
843 // Perform map check on {receiver}. | 842 // Perform map check on {receiver}. |
844 MapList const& receiver_maps = access_info.receiver_maps(); | 843 MapHandles const& receiver_maps = access_info.receiver_maps(); |
845 { | 844 { |
846 // Emit a (sequence of) map checks for other {receiver}s. | 845 // Emit a (sequence of) map checks for other {receiver}s. |
847 ZoneVector<Node*> this_controls(zone()); | 846 ZoneVector<Node*> this_controls(zone()); |
848 ZoneVector<Node*> this_effects(zone()); | 847 ZoneVector<Node*> this_effects(zone()); |
849 if (j == access_infos.size() - 1) { | 848 if (j == access_infos.size() - 1) { |
850 // Last map check on the fallthrough control path, do a | 849 // Last map check on the fallthrough control path, do a |
851 // conditional eager deoptimization exit here. | 850 // conditional eager deoptimization exit here. |
852 this_effect = BuildCheckMaps(receiver, this_effect, this_control, | 851 this_effect = BuildCheckMaps(receiver, this_effect, this_control, |
853 receiver_maps); | 852 receiver_maps); |
854 this_effects.push_back(this_effect); | 853 this_effects.push_back(this_effect); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
949 if (nexus.IsUninitialized()) { | 948 if (nexus.IsUninitialized()) { |
950 if (flags() & kBailoutOnUninitialized) { | 949 if (flags() & kBailoutOnUninitialized) { |
951 return ReduceSoftDeoptimize( | 950 return ReduceSoftDeoptimize( |
952 node, | 951 node, |
953 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); | 952 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); |
954 } | 953 } |
955 return NoChange(); | 954 return NoChange(); |
956 } | 955 } |
957 | 956 |
958 // Extract receiver maps from the IC using the {nexus}. | 957 // Extract receiver maps from the IC using the {nexus}. |
959 MapHandleList receiver_maps; | 958 MapHandles receiver_maps; |
960 if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) { | 959 if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) { |
961 return NoChange(); | 960 return NoChange(); |
962 } else if (receiver_maps.length() == 0) { | 961 } else if (receiver_maps.empty()) { |
963 if (flags() & kBailoutOnUninitialized) { | 962 if (flags() & kBailoutOnUninitialized) { |
964 return ReduceSoftDeoptimize( | 963 return ReduceSoftDeoptimize( |
965 node, | 964 node, |
966 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); | 965 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); |
967 } | 966 } |
968 return NoChange(); | 967 return NoChange(); |
969 } | 968 } |
970 | 969 |
971 // Try to lower the named access based on the {receiver_maps}. | 970 // Try to lower the named access based on the {receiver_maps}. |
972 return ReduceNamedAccess(node, value, receiver_maps, name, access_mode, | 971 return ReduceNamedAccess(node, value, receiver_maps, name, access_mode, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1040 // Extract receiver maps from the IC using the StoreOwnICNexus. | 1039 // Extract receiver maps from the IC using the StoreOwnICNexus. |
1041 if (!p.feedback().IsValid()) return NoChange(); | 1040 if (!p.feedback().IsValid()) return NoChange(); |
1042 StoreOwnICNexus nexus(p.feedback().vector(), p.feedback().slot()); | 1041 StoreOwnICNexus nexus(p.feedback().vector(), p.feedback().slot()); |
1043 | 1042 |
1044 // Try to lower the creation of a named property based on the {receiver_maps}. | 1043 // Try to lower the creation of a named property based on the {receiver_maps}. |
1045 return ReduceNamedAccessFromNexus(node, value, nexus, p.name(), | 1044 return ReduceNamedAccessFromNexus(node, value, nexus, p.name(), |
1046 AccessMode::kStoreInLiteral, STRICT); | 1045 AccessMode::kStoreInLiteral, STRICT); |
1047 } | 1046 } |
1048 | 1047 |
1049 Reduction JSNativeContextSpecialization::ReduceElementAccess( | 1048 Reduction JSNativeContextSpecialization::ReduceElementAccess( |
1050 Node* node, Node* index, Node* value, MapHandleList const& receiver_maps, | 1049 Node* node, Node* index, Node* value, MapHandles const& receiver_maps, |
1051 AccessMode access_mode, LanguageMode language_mode, | 1050 AccessMode access_mode, LanguageMode language_mode, |
1052 KeyedAccessStoreMode store_mode) { | 1051 KeyedAccessStoreMode store_mode) { |
1053 DCHECK(node->opcode() == IrOpcode::kJSLoadProperty || | 1052 DCHECK(node->opcode() == IrOpcode::kJSLoadProperty || |
1054 node->opcode() == IrOpcode::kJSStoreProperty); | 1053 node->opcode() == IrOpcode::kJSStoreProperty); |
1055 Node* receiver = NodeProperties::GetValueInput(node, 0); | 1054 Node* receiver = NodeProperties::GetValueInput(node, 0); |
1056 Node* effect = NodeProperties::GetEffectInput(node); | 1055 Node* effect = NodeProperties::GetEffectInput(node); |
1057 Node* control = NodeProperties::GetControlInput(node); | 1056 Node* control = NodeProperties::GetControlInput(node); |
1058 Node* frame_state = NodeProperties::FindFrameStateBefore(node); | 1057 Node* frame_state = NodeProperties::FindFrameStateBefore(node); |
1059 | 1058 |
1060 // Check for keyed access to strings. | 1059 // Check for keyed access to strings. |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1204 transition_source, transition_target)), | 1203 transition_source, transition_target)), |
1205 receiver, this_effect, this_control); | 1204 receiver, this_effect, this_control); |
1206 } | 1205 } |
1207 | 1206 |
1208 // Load the {receiver} map. | 1207 // Load the {receiver} map. |
1209 Node* receiver_map = this_effect = | 1208 Node* receiver_map = this_effect = |
1210 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | 1209 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), |
1211 receiver, this_effect, this_control); | 1210 receiver, this_effect, this_control); |
1212 | 1211 |
1213 // Perform map check(s) on {receiver}. | 1212 // Perform map check(s) on {receiver}. |
1214 MapList const& receiver_maps = access_info.receiver_maps(); | 1213 MapHandles const& receiver_maps = access_info.receiver_maps(); |
1215 if (j == access_infos.size() - 1) { | 1214 if (j == access_infos.size() - 1) { |
1216 // Last map check on the fallthrough control path, do a | 1215 // Last map check on the fallthrough control path, do a |
1217 // conditional eager deoptimization exit here. | 1216 // conditional eager deoptimization exit here. |
1218 this_effect = BuildCheckMaps(receiver, this_effect, this_control, | 1217 this_effect = BuildCheckMaps(receiver, this_effect, this_control, |
1219 receiver_maps); | 1218 receiver_maps); |
1220 fallthrough_control = nullptr; | 1219 fallthrough_control = nullptr; |
1221 } else { | 1220 } else { |
1222 ZoneVector<Node*> this_controls(zone()); | 1221 ZoneVector<Node*> this_controls(zone()); |
1223 ZoneVector<Node*> this_effects(zone()); | 1222 ZoneVector<Node*> this_effects(zone()); |
1224 for (Handle<Map> map : receiver_maps) { | 1223 for (Handle<Map> map : receiver_maps) { |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1337 if (nexus.IsUninitialized()) { | 1336 if (nexus.IsUninitialized()) { |
1338 if (flags() & kBailoutOnUninitialized) { | 1337 if (flags() & kBailoutOnUninitialized) { |
1339 return ReduceSoftDeoptimize( | 1338 return ReduceSoftDeoptimize( |
1340 node, | 1339 node, |
1341 DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess); | 1340 DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess); |
1342 } | 1341 } |
1343 return NoChange(); | 1342 return NoChange(); |
1344 } | 1343 } |
1345 | 1344 |
1346 // Extract receiver maps from the {nexus}. | 1345 // Extract receiver maps from the {nexus}. |
1347 MapHandleList receiver_maps; | 1346 MapHandles receiver_maps; |
1348 if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) { | 1347 if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) { |
1349 return NoChange(); | 1348 return NoChange(); |
1350 } else if (receiver_maps.length() == 0) { | 1349 } else if (receiver_maps.empty()) { |
1351 if (flags() & kBailoutOnUninitialized) { | 1350 if (flags() & kBailoutOnUninitialized) { |
1352 return ReduceSoftDeoptimize( | 1351 return ReduceSoftDeoptimize( |
1353 node, | 1352 node, |
1354 DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess); | 1353 DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess); |
1355 } | 1354 } |
1356 return NoChange(); | 1355 return NoChange(); |
1357 } | 1356 } |
1358 | 1357 |
1359 // Optimize access for constant {index}. | 1358 // Optimize access for constant {index}. |
1360 HeapObjectMatcher mindex(index); | 1359 HeapObjectMatcher mindex(index); |
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1904 JSNativeContextSpecialization::ValueEffectControl | 1903 JSNativeContextSpecialization::ValueEffectControl |
1905 JSNativeContextSpecialization::BuildElementAccess( | 1904 JSNativeContextSpecialization::BuildElementAccess( |
1906 Node* receiver, Node* index, Node* value, Node* effect, Node* control, | 1905 Node* receiver, Node* index, Node* value, Node* effect, Node* control, |
1907 ElementAccessInfo const& access_info, AccessMode access_mode, | 1906 ElementAccessInfo const& access_info, AccessMode access_mode, |
1908 KeyedAccessStoreMode store_mode) { | 1907 KeyedAccessStoreMode store_mode) { |
1909 DCHECK_NE(AccessMode::kStoreInLiteral, access_mode); | 1908 DCHECK_NE(AccessMode::kStoreInLiteral, access_mode); |
1910 | 1909 |
1911 // TODO(bmeurer): We currently specialize based on elements kind. We should | 1910 // TODO(bmeurer): We currently specialize based on elements kind. We should |
1912 // also be able to properly support strings and other JSObjects here. | 1911 // also be able to properly support strings and other JSObjects here. |
1913 ElementsKind elements_kind = access_info.elements_kind(); | 1912 ElementsKind elements_kind = access_info.elements_kind(); |
1914 MapList const& receiver_maps = access_info.receiver_maps(); | 1913 MapHandles const& receiver_maps = access_info.receiver_maps(); |
1915 | 1914 |
1916 if (IsFixedTypedArrayElementsKind(elements_kind)) { | 1915 if (IsFixedTypedArrayElementsKind(elements_kind)) { |
1917 Node* buffer; | 1916 Node* buffer; |
1918 Node* length; | 1917 Node* length; |
1919 Node* base_pointer; | 1918 Node* base_pointer; |
1920 Node* external_pointer; | 1919 Node* external_pointer; |
1921 | 1920 |
1922 // Check if we can constant-fold information about the {receiver} (i.e. | 1921 // Check if we can constant-fold information about the {receiver} (i.e. |
1923 // for asm.js-like code patterns). | 1922 // for asm.js-like code patterns). |
1924 HeapObjectMatcher m(receiver); | 1923 HeapObjectMatcher m(receiver); |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2275 } | 2274 } |
2276 default: { | 2275 default: { |
2277 return *effect = graph()->NewNode(simplified()->CheckHeapObject(), | 2276 return *effect = graph()->NewNode(simplified()->CheckHeapObject(), |
2278 receiver, *effect, control); | 2277 receiver, *effect, control); |
2279 } | 2278 } |
2280 } | 2279 } |
2281 } | 2280 } |
2282 | 2281 |
2283 Node* JSNativeContextSpecialization::BuildCheckMaps( | 2282 Node* JSNativeContextSpecialization::BuildCheckMaps( |
2284 Node* receiver, Node* effect, Node* control, | 2283 Node* receiver, Node* effect, Node* control, |
2285 std::vector<Handle<Map>> const& receiver_maps) { | 2284 MapHandles const& receiver_maps) { |
2286 HeapObjectMatcher m(receiver); | 2285 HeapObjectMatcher m(receiver); |
2287 if (m.HasValue()) { | 2286 if (m.HasValue()) { |
2288 Handle<Map> receiver_map(m.Value()->map(), isolate()); | 2287 Handle<Map> receiver_map(m.Value()->map(), isolate()); |
2289 if (receiver_map->is_stable()) { | 2288 if (receiver_map->is_stable()) { |
2290 for (Handle<Map> map : receiver_maps) { | 2289 for (Handle<Map> map : receiver_maps) { |
2291 if (map.is_identical_to(receiver_map)) { | 2290 if (map.is_identical_to(receiver_map)) { |
2292 dependencies()->AssumeMapStable(receiver_map); | 2291 dependencies()->AssumeMapStable(receiver_map); |
2293 return effect; | 2292 return effect; |
2294 } | 2293 } |
2295 } | 2294 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2349 new_properties, jsgraph()->Constant(new_length), effect, control); | 2348 new_properties, jsgraph()->Constant(new_length), effect, control); |
2350 for (int i = 0; i < new_length; ++i) { | 2349 for (int i = 0; i < new_length; ++i) { |
2351 effect = graph()->NewNode( | 2350 effect = graph()->NewNode( |
2352 simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)), | 2351 simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)), |
2353 new_properties, values[i], effect, control); | 2352 new_properties, values[i], effect, control); |
2354 } | 2353 } |
2355 return graph()->NewNode(common()->FinishRegion(), new_properties, effect); | 2354 return graph()->NewNode(common()->FinishRegion(), new_properties, effect); |
2356 } | 2355 } |
2357 | 2356 |
2358 void JSNativeContextSpecialization::AssumePrototypesStable( | 2357 void JSNativeContextSpecialization::AssumePrototypesStable( |
2359 std::vector<Handle<Map>> const& receiver_maps, Handle<JSObject> holder) { | 2358 MapHandles const& receiver_maps, Handle<JSObject> holder) { |
2360 // Determine actual holder and perform prototype chain checks. | 2359 // Determine actual holder and perform prototype chain checks. |
2361 for (auto map : receiver_maps) { | 2360 for (auto map : receiver_maps) { |
2362 // Perform the implicit ToObject for primitives here. | 2361 // Perform the implicit ToObject for primitives here. |
2363 // Implemented according to ES6 section 7.3.2 GetV (V, P). | 2362 // Implemented according to ES6 section 7.3.2 GetV (V, P). |
2364 Handle<JSFunction> constructor; | 2363 Handle<JSFunction> constructor; |
2365 if (Map::GetConstructorFunction(map, native_context()) | 2364 if (Map::GetConstructorFunction(map, native_context()) |
2366 .ToHandle(&constructor)) { | 2365 .ToHandle(&constructor)) { |
2367 map = handle(constructor->initial_map(), isolate()); | 2366 map = handle(constructor->initial_map(), isolate()); |
2368 } | 2367 } |
2369 dependencies()->AssumePrototypeMapsStable(map, holder); | 2368 dependencies()->AssumePrototypeMapsStable(map, holder); |
2370 } | 2369 } |
2371 } | 2370 } |
2372 | 2371 |
2373 bool JSNativeContextSpecialization::CanTreatHoleAsUndefined( | 2372 bool JSNativeContextSpecialization::CanTreatHoleAsUndefined( |
2374 std::vector<Handle<Map>> const& receiver_maps) { | 2373 MapHandles const& receiver_maps) { |
2375 // Check if the array prototype chain is intact. | 2374 // Check if the array prototype chain is intact. |
2376 if (!isolate()->IsFastArrayConstructorPrototypeChainIntact()) return false; | 2375 if (!isolate()->IsFastArrayConstructorPrototypeChainIntact()) return false; |
2377 | 2376 |
2378 // Make sure both the initial Array and Object prototypes are stable. | 2377 // Make sure both the initial Array and Object prototypes are stable. |
2379 Handle<JSObject> initial_array_prototype( | 2378 Handle<JSObject> initial_array_prototype( |
2380 native_context()->initial_array_prototype(), isolate()); | 2379 native_context()->initial_array_prototype(), isolate()); |
2381 Handle<JSObject> initial_object_prototype( | 2380 Handle<JSObject> initial_object_prototype( |
2382 native_context()->initial_object_prototype(), isolate()); | 2381 native_context()->initial_object_prototype(), isolate()); |
2383 if (!initial_array_prototype->map()->is_stable() || | 2382 if (!initial_array_prototype->map()->is_stable() || |
2384 !initial_object_prototype->map()->is_stable()) { | 2383 !initial_object_prototype->map()->is_stable()) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2451 DCHECK_IMPLIES(all, !none); | 2450 DCHECK_IMPLIES(all, !none); |
2452 DCHECK_IMPLIES(none, !all); | 2451 DCHECK_IMPLIES(none, !all); |
2453 | 2452 |
2454 if (all) return kIsInPrototypeChain; | 2453 if (all) return kIsInPrototypeChain; |
2455 if (none) return kIsNotInPrototypeChain; | 2454 if (none) return kIsNotInPrototypeChain; |
2456 return kMayBeInPrototypeChain; | 2455 return kMayBeInPrototypeChain; |
2457 } | 2456 } |
2458 | 2457 |
2459 bool JSNativeContextSpecialization::ExtractReceiverMaps( | 2458 bool JSNativeContextSpecialization::ExtractReceiverMaps( |
2460 Node* receiver, Node* effect, FeedbackNexus const& nexus, | 2459 Node* receiver, Node* effect, FeedbackNexus const& nexus, |
2461 MapHandleList* receiver_maps) { | 2460 MapHandles* receiver_maps) { |
2462 DCHECK_EQ(0, receiver_maps->length()); | 2461 DCHECK_EQ(0, receiver_maps->size()); |
2463 // See if we can infer a concrete type for the {receiver}. | 2462 // See if we can infer a concrete type for the {receiver}. |
2464 if (InferReceiverMaps(receiver, effect, receiver_maps)) { | 2463 if (InferReceiverMaps(receiver, effect, receiver_maps)) { |
2465 // We can assume that the {receiver} still has the infered {receiver_maps}. | 2464 // We can assume that the {receiver} still has the infered {receiver_maps}. |
2466 return true; | 2465 return true; |
2467 } | 2466 } |
2468 // Try to extract some maps from the {nexus}. | 2467 // Try to extract some maps from the {nexus}. |
2469 if (nexus.ExtractMaps(receiver_maps) != 0) { | 2468 if (nexus.ExtractMaps(receiver_maps) != 0) { |
2470 // Try to filter impossible candidates based on infered root map. | 2469 // Try to filter impossible candidates based on infered root map. |
2471 Handle<Map> receiver_map; | 2470 Handle<Map> receiver_map; |
2472 if (InferReceiverRootMap(receiver).ToHandle(&receiver_map)) { | 2471 if (InferReceiverRootMap(receiver).ToHandle(&receiver_map)) { |
2473 for (int i = receiver_maps->length(); --i >= 0;) { | 2472 receiver_maps->erase( |
2474 if (receiver_maps->at(i)->FindRootMap() != *receiver_map) { | 2473 std::remove_if(receiver_maps->begin(), receiver_maps->end(), |
2475 receiver_maps->Remove(i); | 2474 [receiver_map](const Handle<Map>& map) { |
2476 } | 2475 return map->FindRootMap() != *receiver_map; |
2477 } | 2476 }), |
| 2477 receiver_maps->end()); |
2478 } | 2478 } |
2479 return true; | 2479 return true; |
2480 } | 2480 } |
2481 return false; | 2481 return false; |
2482 } | 2482 } |
2483 | 2483 |
2484 bool JSNativeContextSpecialization::InferReceiverMaps( | 2484 bool JSNativeContextSpecialization::InferReceiverMaps( |
2485 Node* receiver, Node* effect, MapHandleList* receiver_maps) { | 2485 Node* receiver, Node* effect, MapHandles* receiver_maps) { |
2486 ZoneHandleSet<Map> maps; | 2486 ZoneHandleSet<Map> maps; |
2487 NodeProperties::InferReceiverMapsResult result = | 2487 NodeProperties::InferReceiverMapsResult result = |
2488 NodeProperties::InferReceiverMaps(receiver, effect, &maps); | 2488 NodeProperties::InferReceiverMaps(receiver, effect, &maps); |
2489 if (result == NodeProperties::kReliableReceiverMaps) { | 2489 if (result == NodeProperties::kReliableReceiverMaps) { |
2490 for (size_t i = 0; i < maps.size(); ++i) { | 2490 for (size_t i = 0; i < maps.size(); ++i) { |
2491 receiver_maps->Add(maps[i]); | 2491 receiver_maps->push_back(maps[i]); |
2492 } | 2492 } |
2493 return true; | 2493 return true; |
2494 } else if (result == NodeProperties::kUnreliableReceiverMaps) { | 2494 } else if (result == NodeProperties::kUnreliableReceiverMaps) { |
2495 // For untrusted receiver maps, we can still use the information | 2495 // For untrusted receiver maps, we can still use the information |
2496 // if the maps are stable. | 2496 // if the maps are stable. |
2497 for (size_t i = 0; i < maps.size(); ++i) { | 2497 for (size_t i = 0; i < maps.size(); ++i) { |
2498 if (!maps[i]->is_stable()) return false; | 2498 if (!maps[i]->is_stable()) return false; |
2499 } | 2499 } |
2500 for (size_t i = 0; i < maps.size(); ++i) { | 2500 for (size_t i = 0; i < maps.size(); ++i) { |
2501 receiver_maps->Add(maps[i]); | 2501 receiver_maps->push_back(maps[i]); |
2502 } | 2502 } |
2503 return true; | 2503 return true; |
2504 } | 2504 } |
2505 return false; | 2505 return false; |
2506 } | 2506 } |
2507 | 2507 |
2508 MaybeHandle<Map> JSNativeContextSpecialization::InferReceiverRootMap( | 2508 MaybeHandle<Map> JSNativeContextSpecialization::InferReceiverRootMap( |
2509 Node* receiver) { | 2509 Node* receiver) { |
2510 HeapObjectMatcher m(receiver); | 2510 HeapObjectMatcher m(receiver); |
2511 if (m.HasValue()) { | 2511 if (m.HasValue()) { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2570 return jsgraph()->javascript(); | 2570 return jsgraph()->javascript(); |
2571 } | 2571 } |
2572 | 2572 |
2573 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 2573 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
2574 return jsgraph()->simplified(); | 2574 return jsgraph()->simplified(); |
2575 } | 2575 } |
2576 | 2576 |
2577 } // namespace compiler | 2577 } // namespace compiler |
2578 } // namespace internal | 2578 } // namespace internal |
2579 } // namespace v8 | 2579 } // namespace v8 |
OLD | NEW |