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