OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/ic/ic.h" | 5 #include "src/ic/ic.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api-arguments-inl.h" | 8 #include "src/api-arguments-inl.h" |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
542 } else { | 542 } else { |
543 // Non-keyed ICs don't track the name explicitly. | 543 // Non-keyed ICs don't track the name explicitly. |
544 if (!is_keyed()) name = Handle<Name>::null(); | 544 if (!is_keyed()) name = Handle<Name>::null(); |
545 nexus()->ConfigureMonomorphic(name, map, handler); | 545 nexus()->ConfigureMonomorphic(name, map, handler); |
546 } | 546 } |
547 | 547 |
548 vector_set_ = true; | 548 vector_set_ = true; |
549 OnFeedbackChanged(isolate(), GetHostFunction()); | 549 OnFeedbackChanged(isolate(), GetHostFunction()); |
550 } | 550 } |
551 | 551 |
552 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, | 552 void IC::ConfigureVectorState(Handle<Name> name, MapHandles const& maps, |
553 List<Handle<Object>>* handlers) { | 553 List<Handle<Object>>* handlers) { |
554 DCHECK(!IsLoadGlobalIC()); | 554 DCHECK(!IsLoadGlobalIC()); |
555 // Non-keyed ICs don't track the name explicitly. | 555 // Non-keyed ICs don't track the name explicitly. |
556 if (!is_keyed()) name = Handle<Name>::null(); | 556 if (!is_keyed()) name = Handle<Name>::null(); |
557 nexus()->ConfigurePolymorphic(name, maps, handlers); | 557 nexus()->ConfigurePolymorphic(name, maps, handlers); |
558 | 558 |
559 vector_set_ = true; | 559 vector_set_ = true; |
560 OnFeedbackChanged(isolate(), GetHostFunction()); | 560 OnFeedbackChanged(isolate(), GetHostFunction()); |
561 } | 561 } |
562 | 562 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
629 LoadScriptContextFieldStub stub(isolate(), &lookup_result); | 629 LoadScriptContextFieldStub stub(isolate(), &lookup_result); |
630 PatchCache(name, stub.GetCode()); | 630 PatchCache(name, stub.GetCode()); |
631 TRACE_IC("LoadGlobalIC", name); | 631 TRACE_IC("LoadGlobalIC", name); |
632 } | 632 } |
633 return result; | 633 return result; |
634 } | 634 } |
635 } | 635 } |
636 return LoadIC::Load(global, name); | 636 return LoadIC::Load(global, name); |
637 } | 637 } |
638 | 638 |
639 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, | 639 static bool AddOneReceiverMapIfMissing(MapHandles* receiver_maps, |
640 Handle<Map> new_receiver_map) { | 640 Handle<Map> new_receiver_map) { |
641 DCHECK(!new_receiver_map.is_null()); | 641 DCHECK(!new_receiver_map.is_null()); |
642 for (int current = 0; current < receiver_maps->length(); ++current) { | 642 for (auto map : *receiver_maps) { |
643 if (!receiver_maps->at(current).is_null() && | 643 if (!map.is_null() && map.is_identical_to(new_receiver_map)) { |
644 receiver_maps->at(current).is_identical_to(new_receiver_map)) { | |
645 return false; | 644 return false; |
646 } | 645 } |
647 } | 646 } |
648 receiver_maps->Add(new_receiver_map); | 647 receiver_maps->push_back(new_receiver_map); |
649 return true; | 648 return true; |
650 } | 649 } |
651 | 650 |
652 bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> handler) { | 651 bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> handler) { |
653 DCHECK(IsHandler(*handler)); | 652 DCHECK(IsHandler(*handler)); |
654 if (is_keyed() && state() != RECOMPUTE_HANDLER) return false; | 653 if (is_keyed() && state() != RECOMPUTE_HANDLER) return false; |
655 Handle<Map> map = receiver_map(); | 654 Handle<Map> map = receiver_map(); |
656 MapHandleList maps; | 655 MapHandles maps; |
657 List<Handle<Object>> handlers; | 656 List<Handle<Object>> handlers; |
658 | 657 |
659 TargetMaps(&maps); | 658 TargetMaps(&maps); |
660 int number_of_maps = maps.length(); | 659 int number_of_maps = static_cast<int>(maps.size()); |
661 int deprecated_maps = 0; | 660 int deprecated_maps = 0; |
662 int handler_to_overwrite = -1; | 661 int handler_to_overwrite = -1; |
663 | 662 |
664 for (int i = 0; i < number_of_maps; i++) { | 663 for (int i = 0; i < number_of_maps; i++) { |
665 Handle<Map> current_map = maps.at(i); | 664 Handle<Map> current_map = maps.at(i); |
666 if (current_map->is_deprecated()) { | 665 if (current_map->is_deprecated()) { |
667 // Filter out deprecated maps to ensure their instances get migrated. | 666 // Filter out deprecated maps to ensure their instances get migrated. |
668 ++deprecated_maps; | 667 ++deprecated_maps; |
669 } else if (map.is_identical_to(current_map)) { | 668 } else if (map.is_identical_to(current_map)) { |
670 // If the receiver type is already in the polymorphic IC, this indicates | 669 // If the receiver type is already in the polymorphic IC, this indicates |
671 // there was a prototoype chain failure. In that case, just overwrite the | 670 // there was a prototoype chain failure. In that case, just overwrite the |
672 // handler. | 671 // handler. |
673 handler_to_overwrite = i; | 672 handler_to_overwrite = i; |
674 } else if (handler_to_overwrite == -1 && | 673 } else if (handler_to_overwrite == -1 && |
675 IsTransitionOfMonomorphicTarget(*current_map, *map)) { | 674 IsTransitionOfMonomorphicTarget(*current_map, *map)) { |
676 handler_to_overwrite = i; | 675 handler_to_overwrite = i; |
677 } | 676 } |
678 } | 677 } |
679 | 678 |
680 int number_of_valid_maps = | 679 int number_of_valid_maps = |
681 number_of_maps - deprecated_maps - (handler_to_overwrite != -1); | 680 number_of_maps - deprecated_maps - (handler_to_overwrite != -1); |
682 | 681 |
683 if (number_of_valid_maps >= kMaxPolymorphicMapCount) return false; | 682 if (number_of_valid_maps >= kMaxPolymorphicMapCount) return false; |
684 if (number_of_maps == 0 && state() != MONOMORPHIC && state() != POLYMORPHIC) { | 683 if (number_of_maps == 0 && state() != MONOMORPHIC && state() != POLYMORPHIC) { |
685 return false; | 684 return false; |
686 } | 685 } |
687 if (!nexus()->FindHandlers(&handlers, maps.length())) return false; | 686 if (!nexus()->FindHandlers(&handlers, static_cast<int>(maps.size()))) |
687 return false; | |
688 | 688 |
689 number_of_valid_maps++; | 689 number_of_valid_maps++; |
690 if (number_of_valid_maps > 1 && is_keyed()) return false; | 690 if (number_of_valid_maps > 1 && is_keyed()) return false; |
691 if (number_of_valid_maps == 1) { | 691 if (number_of_valid_maps == 1) { |
692 ConfigureVectorState(name, receiver_map(), handler); | 692 ConfigureVectorState(name, receiver_map(), handler); |
693 } else { | 693 } else { |
694 if (handler_to_overwrite >= 0) { | 694 if (handler_to_overwrite >= 0) { |
695 handlers.Set(handler_to_overwrite, handler); | 695 handlers.Set(handler_to_overwrite, handler); |
696 if (!map.is_identical_to(maps.at(handler_to_overwrite))) { | 696 if (!map.is_identical_to(maps.at(handler_to_overwrite))) { |
697 maps.Set(handler_to_overwrite, map); | 697 maps[handler_to_overwrite] = map; |
698 } | 698 } |
699 } else { | 699 } else { |
700 maps.Add(map); | 700 maps.push_back(map); |
701 handlers.Add(handler); | 701 handlers.Add(handler); |
702 } | 702 } |
703 | 703 |
704 ConfigureVectorState(name, &maps, &handlers); | 704 ConfigureVectorState(name, maps, &handlers); |
705 } | 705 } |
706 | 706 |
707 return true; | 707 return true; |
708 } | 708 } |
709 | 709 |
710 void IC::UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name) { | 710 void IC::UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name) { |
711 DCHECK(IsHandler(*handler)); | 711 DCHECK(IsHandler(*handler)); |
712 ConfigureVectorState(name, receiver_map(), handler); | 712 ConfigureVectorState(name, receiver_map(), handler); |
713 } | 713 } |
714 | 714 |
715 | 715 |
716 void IC::CopyICToMegamorphicCache(Handle<Name> name) { | 716 void IC::CopyICToMegamorphicCache(Handle<Name> name) { |
717 MapHandleList maps; | 717 MapHandles maps; |
718 List<Handle<Object>> handlers; | 718 List<Handle<Object>> handlers; |
719 TargetMaps(&maps); | 719 TargetMaps(&maps); |
720 if (!nexus()->FindHandlers(&handlers, maps.length())) return; | 720 if (!nexus()->FindHandlers(&handlers, static_cast<int>(maps.size()))) return; |
721 for (int i = 0; i < maps.length(); i++) { | 721 for (int i = 0; i < static_cast<int>(maps.size()); i++) { |
722 UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i)); | 722 UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i)); |
723 } | 723 } |
724 } | 724 } |
725 | 725 |
726 | 726 |
727 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) { | 727 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) { |
728 if (source_map == NULL) return true; | 728 if (source_map == NULL) return true; |
729 if (target_map == NULL) return false; | 729 if (target_map == NULL) return false; |
730 ElementsKind target_elements_kind = target_map->elements_kind(); | 730 ElementsKind target_elements_kind = target_map->elements_kind(); |
731 bool more_general_transition = IsMoreGeneralElementsKindTransition( | 731 bool more_general_transition = IsMoreGeneralElementsKindTransition( |
732 source_map->elements_kind(), target_elements_kind); | 732 source_map->elements_kind(), target_elements_kind); |
733 Map* transitioned_map = nullptr; | 733 Map* transitioned_map = nullptr; |
734 if (more_general_transition) { | 734 if (more_general_transition) { |
735 MapHandleList map_list; | 735 MapHandles map_list; |
736 map_list.Add(handle(target_map)); | 736 map_list.push_back(handle(target_map)); |
737 transitioned_map = source_map->FindElementsKindTransitionedMap(&map_list); | 737 transitioned_map = source_map->FindElementsKindTransitionedMap(map_list); |
738 } | 738 } |
739 return transitioned_map == target_map; | 739 return transitioned_map == target_map; |
740 } | 740 } |
741 | 741 |
742 void IC::PatchCache(Handle<Name> name, Handle<Object> handler) { | 742 void IC::PatchCache(Handle<Name> name, Handle<Object> handler) { |
743 DCHECK(IsHandler(*handler)); | 743 DCHECK(IsHandler(*handler)); |
744 // Currently only load and store ICs support non-code handlers. | 744 // Currently only load and store ICs support non-code handlers. |
745 DCHECK(IsAnyLoad() || IsAnyStore()); | 745 DCHECK(IsAnyLoad() || IsAnyStore()); |
746 switch (state()) { | 746 switch (state()) { |
747 case UNINITIALIZED: | 747 case UNINITIALIZED: |
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1309 } else if (key->IsString()) { | 1309 } else if (key->IsString()) { |
1310 key = isolate->factory()->InternalizeString(Handle<String>::cast(key)); | 1310 key = isolate->factory()->InternalizeString(Handle<String>::cast(key)); |
1311 } | 1311 } |
1312 return key; | 1312 return key; |
1313 } | 1313 } |
1314 | 1314 |
1315 void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) { | 1315 void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) { |
1316 Handle<Map> receiver_map(receiver->map(), isolate()); | 1316 Handle<Map> receiver_map(receiver->map(), isolate()); |
1317 DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE && | 1317 DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE && |
1318 receiver_map->instance_type() != JS_PROXY_TYPE); // Checked by caller. | 1318 receiver_map->instance_type() != JS_PROXY_TYPE); // Checked by caller. |
1319 MapHandleList target_receiver_maps; | 1319 MapHandles target_receiver_maps; |
1320 TargetMaps(&target_receiver_maps); | 1320 TargetMaps(&target_receiver_maps); |
1321 | 1321 |
1322 if (target_receiver_maps.length() == 0) { | 1322 if (target_receiver_maps.empty()) { |
1323 Handle<Object> handler = LoadElementHandler(receiver_map); | 1323 Handle<Object> handler = LoadElementHandler(receiver_map); |
1324 return ConfigureVectorState(Handle<Name>(), receiver_map, handler); | 1324 return ConfigureVectorState(Handle<Name>(), receiver_map, handler); |
1325 } | 1325 } |
1326 | 1326 |
1327 for (int i = 0; i < target_receiver_maps.length(); i++) { | 1327 for (auto map : target_receiver_maps) { |
1328 Handle<Map> map = target_receiver_maps.at(i); | |
1329 if (map.is_null()) continue; | 1328 if (map.is_null()) continue; |
1330 if (map->instance_type() == JS_VALUE_TYPE) { | 1329 if (map->instance_type() == JS_VALUE_TYPE) { |
1331 TRACE_GENERIC_IC("JSValue"); | 1330 TRACE_GENERIC_IC("JSValue"); |
1332 return; | 1331 return; |
1333 } | 1332 } |
1334 if (map->instance_type() == JS_PROXY_TYPE) { | 1333 if (map->instance_type() == JS_PROXY_TYPE) { |
1335 TRACE_GENERIC_IC("JSProxy"); | 1334 TRACE_GENERIC_IC("JSProxy"); |
1336 return; | 1335 return; |
1337 } | 1336 } |
1338 } | 1337 } |
(...skipping 19 matching lines...) Expand all Loading... | |
1358 // adding the map that was just encountered. | 1357 // adding the map that was just encountered. |
1359 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { | 1358 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { |
1360 // If the miss wasn't due to an unseen map, a polymorphic stub | 1359 // If the miss wasn't due to an unseen map, a polymorphic stub |
1361 // won't help, use the generic stub. | 1360 // won't help, use the generic stub. |
1362 TRACE_GENERIC_IC("same map added twice"); | 1361 TRACE_GENERIC_IC("same map added twice"); |
1363 return; | 1362 return; |
1364 } | 1363 } |
1365 | 1364 |
1366 // If the maximum number of receiver maps has been exceeded, use the generic | 1365 // If the maximum number of receiver maps has been exceeded, use the generic |
1367 // version of the IC. | 1366 // version of the IC. |
1368 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1367 if (target_receiver_maps.size() > kMaxKeyedPolymorphism) { |
1369 TRACE_GENERIC_IC("max polymorph exceeded"); | 1368 TRACE_GENERIC_IC("max polymorph exceeded"); |
1370 return; | 1369 return; |
1371 } | 1370 } |
1372 | 1371 |
1373 List<Handle<Object>> handlers(target_receiver_maps.length()); | 1372 List<Handle<Object>> handlers(static_cast<int>(target_receiver_maps.size())); |
1374 LoadElementPolymorphicHandlers(&target_receiver_maps, &handlers); | 1373 LoadElementPolymorphicHandlers(&target_receiver_maps, &handlers); |
1375 DCHECK_LE(1, target_receiver_maps.length()); | 1374 DCHECK_LE(1, target_receiver_maps.size()); |
1376 if (target_receiver_maps.length() == 1) { | 1375 if (target_receiver_maps.size() == 1) { |
1377 ConfigureVectorState(Handle<Name>(), target_receiver_maps.at(0), | 1376 ConfigureVectorState(Handle<Name>(), target_receiver_maps[0], |
1378 handlers.at(0)); | 1377 handlers.at(0)); |
1379 } else { | 1378 } else { |
1380 ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers); | 1379 ConfigureVectorState(Handle<Name>(), target_receiver_maps, &handlers); |
1381 } | 1380 } |
1382 } | 1381 } |
1383 | 1382 |
1384 Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map) { | 1383 Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map) { |
1385 if (receiver_map->has_indexed_interceptor() && | 1384 if (receiver_map->has_indexed_interceptor() && |
1386 !receiver_map->GetIndexedInterceptor()->getter()->IsUndefined( | 1385 !receiver_map->GetIndexedInterceptor()->getter()->IsUndefined( |
1387 isolate()) && | 1386 isolate()) && |
1388 !receiver_map->GetIndexedInterceptor()->non_masking()) { | 1387 !receiver_map->GetIndexedInterceptor()->non_masking()) { |
1389 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedInterceptorStub); | 1388 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedInterceptorStub); |
1390 return LoadIndexedInterceptorStub(isolate()).GetCode(); | 1389 return LoadIndexedInterceptorStub(isolate()).GetCode(); |
(...skipping 24 matching lines...) Expand all Loading... | |
1415 // TODO(jkummerow): Use IsHoleyElementsKind(elements_kind). | 1414 // TODO(jkummerow): Use IsHoleyElementsKind(elements_kind). |
1416 bool convert_hole_to_undefined = | 1415 bool convert_hole_to_undefined = |
1417 is_js_array && elements_kind == FAST_HOLEY_ELEMENTS && | 1416 is_js_array && elements_kind == FAST_HOLEY_ELEMENTS && |
1418 *receiver_map == isolate()->get_initial_js_array_map(elements_kind); | 1417 *receiver_map == isolate()->get_initial_js_array_map(elements_kind); |
1419 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadElementDH); | 1418 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadElementDH); |
1420 return LoadHandler::LoadElement(isolate(), elements_kind, | 1419 return LoadHandler::LoadElement(isolate(), elements_kind, |
1421 convert_hole_to_undefined, is_js_array); | 1420 convert_hole_to_undefined, is_js_array); |
1422 } | 1421 } |
1423 | 1422 |
1424 void KeyedLoadIC::LoadElementPolymorphicHandlers( | 1423 void KeyedLoadIC::LoadElementPolymorphicHandlers( |
1425 MapHandleList* receiver_maps, List<Handle<Object>>* handlers) { | 1424 MapHandles* receiver_maps, List<Handle<Object>>* handlers) { |
1426 for (int i = 0; i < receiver_maps->length(); ++i) { | 1425 MapHandles::iterator current_map = receiver_maps->begin(); |
1427 Handle<Map> receiver_map(receiver_maps->at(i)); | 1426 MapHandles::iterator last_valid_map = receiver_maps->end(); |
1427 while (current_map < last_valid_map) { | |
1428 Handle<Map> receiver_map = *current_map; | |
1428 if (receiver_map->is_deprecated()) { | 1429 if (receiver_map->is_deprecated()) { |
1429 // Filter out deprecated maps to ensure their instances get migrated. | 1430 // Filter out deprecated maps to ensure their instances get migrated. |
1430 receiver_maps->Remove(i--); | 1431 --last_valid_map; |
1432 std::swap(*current_map, *last_valid_map); | |
1433 receiver_maps->erase(last_valid_map, receiver_maps->end()); | |
1431 continue; | 1434 continue; |
1432 } | 1435 } |
1433 | 1436 |
1434 // Mark all stable receiver maps that have elements kind transition map | 1437 // Mark all stable receiver maps that have elements kind transition map |
1435 // among receiver_maps as unstable because the optimizing compilers may | 1438 // among receiver_maps as unstable because the optimizing compilers may |
1436 // generate an elements kind transition for this kind of receivers. | 1439 // generate an elements kind transition for this kind of receivers. |
1437 if (receiver_map->is_stable()) { | 1440 if (receiver_map->is_stable()) { |
1438 Map* tmap = receiver_map->FindElementsKindTransitionedMap(receiver_maps); | 1441 Map* tmap = receiver_map->FindElementsKindTransitionedMap(*receiver_maps); |
1439 if (tmap != nullptr) { | 1442 if (tmap != nullptr) { |
1440 receiver_map->NotifyLeafMapLayoutChange(); | 1443 receiver_map->NotifyLeafMapLayoutChange(); |
1441 } | 1444 } |
1442 } | 1445 } |
1443 handlers->Add(LoadElementHandler(receiver_map)); | 1446 handlers->Add(LoadElementHandler(receiver_map)); |
1447 ++current_map; | |
1444 } | 1448 } |
1445 } | 1449 } |
1446 | 1450 |
1447 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, | 1451 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, |
1448 Handle<Object> key) { | 1452 Handle<Object> key) { |
1449 if (MigrateDeprecated(object)) { | 1453 if (MigrateDeprecated(object)) { |
1450 Handle<Object> result; | 1454 Handle<Object> result; |
1451 ASSIGN_RETURN_ON_EXCEPTION( | 1455 ASSIGN_RETURN_ON_EXCEPTION( |
1452 isolate(), result, Runtime::GetObjectProperty(isolate(), object, key), | 1456 isolate(), result, Runtime::GetObjectProperty(isolate(), object, key), |
1453 Object); | 1457 Object); |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1911 } | 1915 } |
1912 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter); | 1916 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter); |
1913 int expected_arguments = | 1917 int expected_arguments = |
1914 JSFunction::cast(*setter)->shared()->internal_formal_parameter_count(); | 1918 JSFunction::cast(*setter)->shared()->internal_formal_parameter_count(); |
1915 return compiler.CompileStoreViaSetter( | 1919 return compiler.CompileStoreViaSetter( |
1916 receiver, lookup->name(), lookup->GetAccessorIndex(), expected_arguments); | 1920 receiver, lookup->name(), lookup->GetAccessorIndex(), expected_arguments); |
1917 } | 1921 } |
1918 | 1922 |
1919 void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map, | 1923 void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map, |
1920 KeyedAccessStoreMode store_mode) { | 1924 KeyedAccessStoreMode store_mode) { |
1921 MapHandleList target_receiver_maps; | 1925 MapHandles target_receiver_maps; |
1922 TargetMaps(&target_receiver_maps); | 1926 TargetMaps(&target_receiver_maps); |
1923 if (target_receiver_maps.length() == 0) { | 1927 if (target_receiver_maps.empty()) { |
1924 Handle<Map> monomorphic_map = | 1928 Handle<Map> monomorphic_map = |
1925 ComputeTransitionedMap(receiver_map, store_mode); | 1929 ComputeTransitionedMap(receiver_map, store_mode); |
1926 store_mode = GetNonTransitioningStoreMode(store_mode); | 1930 store_mode = GetNonTransitioningStoreMode(store_mode); |
1927 Handle<Object> handler = StoreElementHandler(monomorphic_map, store_mode); | 1931 Handle<Object> handler = StoreElementHandler(monomorphic_map, store_mode); |
1928 return ConfigureVectorState(Handle<Name>(), monomorphic_map, handler); | 1932 return ConfigureVectorState(Handle<Name>(), monomorphic_map, handler); |
1929 } | 1933 } |
1930 | 1934 |
1931 for (int i = 0; i < target_receiver_maps.length(); i++) { | 1935 for (auto map : target_receiver_maps) { |
1932 if (!target_receiver_maps.at(i).is_null() && | 1936 if (!map.is_null() && map->instance_type() == JS_VALUE_TYPE) { |
1933 target_receiver_maps.at(i)->instance_type() == JS_VALUE_TYPE) { | |
1934 TRACE_GENERIC_IC("JSValue"); | 1937 TRACE_GENERIC_IC("JSValue"); |
1935 return; | 1938 return; |
1936 } | 1939 } |
1937 } | 1940 } |
1938 | 1941 |
1939 // There are several special cases where an IC that is MONOMORPHIC can still | 1942 // There are several special cases where an IC that is MONOMORPHIC can still |
1940 // transition to a different GetNonTransitioningStoreMode IC that handles a | 1943 // transition to a different GetNonTransitioningStoreMode IC that handles a |
1941 // superset of the original IC. Handle those here if the receiver map hasn't | 1944 // superset of the original IC. Handle those here if the receiver map hasn't |
1942 // changed or it has transitioned to a more general kind. | 1945 // changed or it has transitioned to a more general kind. |
1943 KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode(); | 1946 KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode(); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1988 | 1991 |
1989 if (!map_added) { | 1992 if (!map_added) { |
1990 // If the miss wasn't due to an unseen map, a polymorphic stub | 1993 // If the miss wasn't due to an unseen map, a polymorphic stub |
1991 // won't help, use the megamorphic stub which can handle everything. | 1994 // won't help, use the megamorphic stub which can handle everything. |
1992 TRACE_GENERIC_IC("same map added twice"); | 1995 TRACE_GENERIC_IC("same map added twice"); |
1993 return; | 1996 return; |
1994 } | 1997 } |
1995 | 1998 |
1996 // If the maximum number of receiver maps has been exceeded, use the | 1999 // If the maximum number of receiver maps has been exceeded, use the |
1997 // megamorphic version of the IC. | 2000 // megamorphic version of the IC. |
1998 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) return; | 2001 if (target_receiver_maps.size() > kMaxKeyedPolymorphism) return; |
1999 | 2002 |
2000 // Make sure all polymorphic handlers have the same store mode, otherwise the | 2003 // Make sure all polymorphic handlers have the same store mode, otherwise the |
2001 // megamorphic stub must be used. | 2004 // megamorphic stub must be used. |
2002 store_mode = GetNonTransitioningStoreMode(store_mode); | 2005 store_mode = GetNonTransitioningStoreMode(store_mode); |
2003 if (old_store_mode != STANDARD_STORE) { | 2006 if (old_store_mode != STANDARD_STORE) { |
2004 if (store_mode == STANDARD_STORE) { | 2007 if (store_mode == STANDARD_STORE) { |
2005 store_mode = old_store_mode; | 2008 store_mode = old_store_mode; |
2006 } else if (store_mode != old_store_mode) { | 2009 } else if (store_mode != old_store_mode) { |
2007 TRACE_GENERIC_IC("store mode mismatch"); | 2010 TRACE_GENERIC_IC("store mode mismatch"); |
2008 return; | 2011 return; |
2009 } | 2012 } |
2010 } | 2013 } |
2011 | 2014 |
2012 // If the store mode isn't the standard mode, make sure that all polymorphic | 2015 // If the store mode isn't the standard mode, make sure that all polymorphic |
2013 // receivers are either external arrays, or all "normal" arrays. Otherwise, | 2016 // receivers are either external arrays, or all "normal" arrays. Otherwise, |
2014 // use the megamorphic stub. | 2017 // use the megamorphic stub. |
2015 if (store_mode != STANDARD_STORE) { | 2018 if (store_mode != STANDARD_STORE) { |
2016 int external_arrays = 0; | 2019 size_t external_arrays = 0; |
2017 for (int i = 0; i < target_receiver_maps.length(); ++i) { | 2020 for (auto map : target_receiver_maps) { |
2018 if (target_receiver_maps[i]->has_fixed_typed_array_elements()) { | 2021 if (map->has_fixed_typed_array_elements()) { |
2019 external_arrays++; | 2022 external_arrays++; |
2020 } | 2023 } |
2021 } | 2024 } |
2022 if (external_arrays != 0 && | 2025 if (external_arrays != 0 && |
2023 external_arrays != target_receiver_maps.length()) { | 2026 external_arrays != target_receiver_maps.size()) { |
2024 TRACE_GENERIC_IC("unsupported combination of external and normal arrays"); | 2027 TRACE_GENERIC_IC("unsupported combination of external and normal arrays"); |
2025 return; | 2028 return; |
2026 } | 2029 } |
2027 } | 2030 } |
2028 | 2031 |
2029 List<Handle<Object>> handlers(target_receiver_maps.length()); | 2032 List<Handle<Object>> handlers(static_cast<int>(target_receiver_maps.size())); |
2030 StoreElementPolymorphicHandlers(&target_receiver_maps, &handlers, store_mode); | 2033 StoreElementPolymorphicHandlers(&target_receiver_maps, &handlers, store_mode); |
2031 DCHECK_LE(1, target_receiver_maps.length()); | 2034 DCHECK_LE(1, target_receiver_maps.size()); |
2032 if (target_receiver_maps.length() == 1) { | 2035 if (target_receiver_maps.size() == 1) { |
2033 ConfigureVectorState(Handle<Name>(), target_receiver_maps.at(0), | 2036 ConfigureVectorState(Handle<Name>(), target_receiver_maps[0], |
2034 handlers.at(0)); | 2037 handlers.at(0)); |
2035 } else { | 2038 } else { |
2036 ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers); | 2039 ConfigureVectorState(Handle<Name>(), target_receiver_maps, &handlers); |
2037 } | 2040 } |
2038 } | 2041 } |
2039 | 2042 |
2040 | 2043 |
2041 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( | 2044 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( |
2042 Handle<Map> map, KeyedAccessStoreMode store_mode) { | 2045 Handle<Map> map, KeyedAccessStoreMode store_mode) { |
2043 switch (store_mode) { | 2046 switch (store_mode) { |
2044 case STORE_TRANSITION_TO_OBJECT: | 2047 case STORE_TRANSITION_TO_OBJECT: |
2045 case STORE_AND_GROW_TRANSITION_TO_OBJECT: { | 2048 case STORE_AND_GROW_TRANSITION_TO_OBJECT: { |
2046 ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind()) | 2049 ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind()) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2092 DCHECK_EQ(DICTIONARY_ELEMENTS, elements_kind); | 2095 DCHECK_EQ(DICTIONARY_ELEMENTS, elements_kind); |
2093 stub = StoreSlowElementStub(isolate(), store_mode).GetCode(); | 2096 stub = StoreSlowElementStub(isolate(), store_mode).GetCode(); |
2094 } | 2097 } |
2095 Handle<Object> validity_cell = | 2098 Handle<Object> validity_cell = |
2096 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); | 2099 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); |
2097 if (validity_cell.is_null()) return stub; | 2100 if (validity_cell.is_null()) return stub; |
2098 return isolate()->factory()->NewTuple2(validity_cell, stub); | 2101 return isolate()->factory()->NewTuple2(validity_cell, stub); |
2099 } | 2102 } |
2100 | 2103 |
2101 void KeyedStoreIC::StoreElementPolymorphicHandlers( | 2104 void KeyedStoreIC::StoreElementPolymorphicHandlers( |
2102 MapHandleList* receiver_maps, List<Handle<Object>>* handlers, | 2105 MapHandles* receiver_maps, List<Handle<Object>>* handlers, |
2103 KeyedAccessStoreMode store_mode) { | 2106 KeyedAccessStoreMode store_mode) { |
2104 DCHECK(store_mode == STANDARD_STORE || | 2107 DCHECK(store_mode == STANDARD_STORE || |
2105 store_mode == STORE_AND_GROW_NO_TRANSITION || | 2108 store_mode == STORE_AND_GROW_NO_TRANSITION || |
2106 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 2109 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
2107 store_mode == STORE_NO_TRANSITION_HANDLE_COW); | 2110 store_mode == STORE_NO_TRANSITION_HANDLE_COW); |
2108 | 2111 |
2109 for (int i = 0; i < receiver_maps->length(); ++i) { | 2112 MapHandles::iterator current_map = receiver_maps->begin(); |
2110 Handle<Map> receiver_map(receiver_maps->at(i)); | 2113 MapHandles::iterator last_valid_map = receiver_maps->end(); |
2114 while (current_map < last_valid_map) { | |
Franzi
2017/05/02 16:29:32
Are there strong performance reasons for this patt
danno
2017/05/03 15:10:30
Done.
| |
2115 Handle<Map> receiver_map = *current_map; | |
2111 if (receiver_map->is_deprecated()) { | 2116 if (receiver_map->is_deprecated()) { |
2112 // Filter out deprecated maps to ensure their instances get migrated. | 2117 // Filter out deprecated maps to ensure their instances get migrated. |
2113 receiver_maps->Remove(i--); | 2118 --last_valid_map; |
2119 std::swap(*current_map, *last_valid_map); | |
2120 receiver_maps->erase(last_valid_map, receiver_maps->end()); | |
2114 continue; | 2121 continue; |
2115 } | 2122 } |
2116 | 2123 |
2117 Handle<Object> handler; | 2124 Handle<Object> handler; |
2118 Handle<Map> transitioned_map; | 2125 Handle<Map> transitioned_map; |
2119 | 2126 |
2120 if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE || | 2127 if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE || |
2121 receiver_map->DictionaryElementsInPrototypeChainOnly()) { | 2128 receiver_map->DictionaryElementsInPrototypeChainOnly()) { |
2122 // TODO(mvstanton): Consider embedding store_mode in the state of the slow | 2129 // TODO(mvstanton): Consider embedding store_mode in the state of the slow |
2123 // keyed store ic for uniformity. | 2130 // keyed store ic for uniformity. |
2124 TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_SlowStub); | 2131 TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_SlowStub); |
2125 handler = isolate()->builtins()->KeyedStoreIC_Slow(); | 2132 handler = isolate()->builtins()->KeyedStoreIC_Slow(); |
2126 | 2133 |
2127 } else { | 2134 } else { |
2128 { | 2135 { |
2129 Map* tmap = | 2136 Map* tmap = |
2130 receiver_map->FindElementsKindTransitionedMap(receiver_maps); | 2137 receiver_map->FindElementsKindTransitionedMap(*receiver_maps); |
2131 if (tmap != nullptr) { | 2138 if (tmap != nullptr) { |
2132 if (receiver_map->is_stable()) { | 2139 if (receiver_map->is_stable()) { |
2133 receiver_map->NotifyLeafMapLayoutChange(); | 2140 receiver_map->NotifyLeafMapLayoutChange(); |
2134 } | 2141 } |
2135 transitioned_map = handle(tmap); | 2142 transitioned_map = handle(tmap); |
2136 } | 2143 } |
2137 } | 2144 } |
2138 | 2145 |
2139 // TODO(mvstanton): The code below is doing pessimistic elements | 2146 // TODO(mvstanton): The code below is doing pessimistic elements |
2140 // transitions. I would like to stop doing that and rely on Allocation | 2147 // transitions. I would like to stop doing that and rely on Allocation |
(...skipping 17 matching lines...) Expand all Loading... | |
2158 } | 2165 } |
2159 Handle<WeakCell> transition = Map::WeakCellForMap(transitioned_map); | 2166 Handle<WeakCell> transition = Map::WeakCellForMap(transitioned_map); |
2160 handler = | 2167 handler = |
2161 isolate()->factory()->NewTuple3(transition, stub, validity_cell); | 2168 isolate()->factory()->NewTuple3(transition, stub, validity_cell); |
2162 } else { | 2169 } else { |
2163 handler = StoreElementHandler(receiver_map, store_mode); | 2170 handler = StoreElementHandler(receiver_map, store_mode); |
2164 } | 2171 } |
2165 } | 2172 } |
2166 DCHECK(!handler.is_null()); | 2173 DCHECK(!handler.is_null()); |
2167 handlers->Add(handler); | 2174 handlers->Add(handler); |
2175 ++current_map; | |
2168 } | 2176 } |
2169 } | 2177 } |
2170 | 2178 |
2171 bool IsOutOfBoundsAccess(Handle<JSObject> receiver, uint32_t index) { | 2179 bool IsOutOfBoundsAccess(Handle<JSObject> receiver, uint32_t index) { |
2172 uint32_t length = 0; | 2180 uint32_t length = 0; |
2173 if (receiver->IsJSArray()) { | 2181 if (receiver->IsJSArray()) { |
2174 JSArray::cast(*receiver)->length()->ToArrayLength(&length); | 2182 JSArray::cast(*receiver)->length()->ToArrayLength(&length); |
2175 } else { | 2183 } else { |
2176 length = static_cast<uint32_t>(receiver->elements()->length()); | 2184 length = static_cast<uint32_t>(receiver->elements()->length()); |
2177 } | 2185 } |
(...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2987 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); | 2995 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); |
2988 it.Next(); | 2996 it.Next(); |
2989 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | 2997 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
2990 Object::GetProperty(&it)); | 2998 Object::GetProperty(&it)); |
2991 } | 2999 } |
2992 | 3000 |
2993 return *result; | 3001 return *result; |
2994 } | 3002 } |
2995 } // namespace internal | 3003 } // namespace internal |
2996 } // namespace v8 | 3004 } // namespace v8 |
OLD | NEW |