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

Side by Side Diff: src/ic/ic.cc

Issue 2809923002: Unify implementations of Map handles vectors and lists (Closed)
Patch Set: Review feedback Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/ic/ic.h ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 (Handle<Map> 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
689 number_of_valid_maps++; 690 number_of_valid_maps++;
690 if (number_of_valid_maps > 1 && is_keyed()) return false; 691 if (number_of_valid_maps > 1 && is_keyed()) return false;
691 if (number_of_valid_maps == 1) { 692 if (number_of_valid_maps == 1) {
692 ConfigureVectorState(name, receiver_map(), handler); 693 ConfigureVectorState(name, receiver_map(), handler);
693 } else { 694 } else {
694 if (handler_to_overwrite >= 0) { 695 if (handler_to_overwrite >= 0) {
695 handlers.Set(handler_to_overwrite, handler); 696 handlers.Set(handler_to_overwrite, handler);
696 if (!map.is_identical_to(maps.at(handler_to_overwrite))) { 697 if (!map.is_identical_to(maps.at(handler_to_overwrite))) {
697 maps.Set(handler_to_overwrite, map); 698 maps[handler_to_overwrite] = map;
698 } 699 }
699 } else { 700 } else {
700 maps.Add(map); 701 maps.push_back(map);
701 handlers.Add(handler); 702 handlers.Add(handler);
702 } 703 }
703 704
704 ConfigureVectorState(name, &maps, &handlers); 705 ConfigureVectorState(name, maps, &handlers);
705 } 706 }
706 707
707 return true; 708 return true;
708 } 709 }
709 710
710 void IC::UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name) { 711 void IC::UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name) {
711 DCHECK(IsHandler(*handler)); 712 DCHECK(IsHandler(*handler));
712 ConfigureVectorState(name, receiver_map(), handler); 713 ConfigureVectorState(name, receiver_map(), handler);
713 } 714 }
714 715
715 716
716 void IC::CopyICToMegamorphicCache(Handle<Name> name) { 717 void IC::CopyICToMegamorphicCache(Handle<Name> name) {
717 MapHandleList maps; 718 MapHandles maps;
718 List<Handle<Object>> handlers; 719 List<Handle<Object>> handlers;
719 TargetMaps(&maps); 720 TargetMaps(&maps);
720 if (!nexus()->FindHandlers(&handlers, maps.length())) return; 721 if (!nexus()->FindHandlers(&handlers, static_cast<int>(maps.size()))) return;
721 for (int i = 0; i < maps.length(); i++) { 722 for (int i = 0; i < static_cast<int>(maps.size()); i++) {
722 UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i)); 723 UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i));
723 } 724 }
724 } 725 }
725 726
726 727
727 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) { 728 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
728 if (source_map == NULL) return true; 729 if (source_map == NULL) return true;
729 if (target_map == NULL) return false; 730 if (target_map == NULL) return false;
730 ElementsKind target_elements_kind = target_map->elements_kind(); 731 ElementsKind target_elements_kind = target_map->elements_kind();
731 bool more_general_transition = IsMoreGeneralElementsKindTransition( 732 bool more_general_transition = IsMoreGeneralElementsKindTransition(
732 source_map->elements_kind(), target_elements_kind); 733 source_map->elements_kind(), target_elements_kind);
733 Map* transitioned_map = nullptr; 734 Map* transitioned_map = nullptr;
734 if (more_general_transition) { 735 if (more_general_transition) {
735 MapHandleList map_list; 736 MapHandles map_list;
736 map_list.Add(handle(target_map)); 737 map_list.push_back(handle(target_map));
737 transitioned_map = source_map->FindElementsKindTransitionedMap(&map_list); 738 transitioned_map = source_map->FindElementsKindTransitionedMap(map_list);
738 } 739 }
739 return transitioned_map == target_map; 740 return transitioned_map == target_map;
740 } 741 }
741 742
742 void IC::PatchCache(Handle<Name> name, Handle<Object> handler) { 743 void IC::PatchCache(Handle<Name> name, Handle<Object> handler) {
743 DCHECK(IsHandler(*handler)); 744 DCHECK(IsHandler(*handler));
744 // Currently only load and store ICs support non-code handlers. 745 // Currently only load and store ICs support non-code handlers.
745 DCHECK(IsAnyLoad() || IsAnyStore()); 746 DCHECK(IsAnyLoad() || IsAnyStore());
746 switch (state()) { 747 switch (state()) {
747 case UNINITIALIZED: 748 case UNINITIALIZED:
(...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after
1316 } else if (key->IsString()) { 1317 } else if (key->IsString()) {
1317 key = isolate->factory()->InternalizeString(Handle<String>::cast(key)); 1318 key = isolate->factory()->InternalizeString(Handle<String>::cast(key));
1318 } 1319 }
1319 return key; 1320 return key;
1320 } 1321 }
1321 1322
1322 void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) { 1323 void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) {
1323 Handle<Map> receiver_map(receiver->map(), isolate()); 1324 Handle<Map> receiver_map(receiver->map(), isolate());
1324 DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE && 1325 DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE &&
1325 receiver_map->instance_type() != JS_PROXY_TYPE); // Checked by caller. 1326 receiver_map->instance_type() != JS_PROXY_TYPE); // Checked by caller.
1326 MapHandleList target_receiver_maps; 1327 MapHandles target_receiver_maps;
1327 TargetMaps(&target_receiver_maps); 1328 TargetMaps(&target_receiver_maps);
1328 1329
1329 if (target_receiver_maps.length() == 0) { 1330 if (target_receiver_maps.empty()) {
1330 Handle<Object> handler = LoadElementHandler(receiver_map); 1331 Handle<Object> handler = LoadElementHandler(receiver_map);
1331 return ConfigureVectorState(Handle<Name>(), receiver_map, handler); 1332 return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
1332 } 1333 }
1333 1334
1334 for (int i = 0; i < target_receiver_maps.length(); i++) { 1335 for (Handle<Map> map : target_receiver_maps) {
1335 Handle<Map> map = target_receiver_maps.at(i);
1336 if (map.is_null()) continue; 1336 if (map.is_null()) continue;
1337 if (map->instance_type() == JS_VALUE_TYPE) { 1337 if (map->instance_type() == JS_VALUE_TYPE) {
1338 TRACE_GENERIC_IC("JSValue"); 1338 TRACE_GENERIC_IC("JSValue");
1339 return; 1339 return;
1340 } 1340 }
1341 if (map->instance_type() == JS_PROXY_TYPE) { 1341 if (map->instance_type() == JS_PROXY_TYPE) {
1342 TRACE_GENERIC_IC("JSProxy"); 1342 TRACE_GENERIC_IC("JSProxy");
1343 return; 1343 return;
1344 } 1344 }
1345 } 1345 }
(...skipping 19 matching lines...) Expand all
1365 // adding the map that was just encountered. 1365 // adding the map that was just encountered.
1366 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { 1366 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
1367 // If the miss wasn't due to an unseen map, a polymorphic stub 1367 // If the miss wasn't due to an unseen map, a polymorphic stub
1368 // won't help, use the generic stub. 1368 // won't help, use the generic stub.
1369 TRACE_GENERIC_IC("same map added twice"); 1369 TRACE_GENERIC_IC("same map added twice");
1370 return; 1370 return;
1371 } 1371 }
1372 1372
1373 // If the maximum number of receiver maps has been exceeded, use the generic 1373 // If the maximum number of receiver maps has been exceeded, use the generic
1374 // version of the IC. 1374 // version of the IC.
1375 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { 1375 if (target_receiver_maps.size() > kMaxKeyedPolymorphism) {
1376 TRACE_GENERIC_IC("max polymorph exceeded"); 1376 TRACE_GENERIC_IC("max polymorph exceeded");
1377 return; 1377 return;
1378 } 1378 }
1379 1379
1380 List<Handle<Object>> handlers(target_receiver_maps.length()); 1380 List<Handle<Object>> handlers(static_cast<int>(target_receiver_maps.size()));
1381 LoadElementPolymorphicHandlers(&target_receiver_maps, &handlers); 1381 LoadElementPolymorphicHandlers(&target_receiver_maps, &handlers);
1382 DCHECK_LE(1, target_receiver_maps.length()); 1382 DCHECK_LE(1, target_receiver_maps.size());
1383 if (target_receiver_maps.length() == 1) { 1383 if (target_receiver_maps.size() == 1) {
1384 ConfigureVectorState(Handle<Name>(), target_receiver_maps.at(0), 1384 ConfigureVectorState(Handle<Name>(), target_receiver_maps[0],
1385 handlers.at(0)); 1385 handlers.at(0));
1386 } else { 1386 } else {
1387 ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers); 1387 ConfigureVectorState(Handle<Name>(), target_receiver_maps, &handlers);
1388 } 1388 }
1389 } 1389 }
1390 1390
1391 Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map) { 1391 Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map) {
1392 if (receiver_map->has_indexed_interceptor() && 1392 if (receiver_map->has_indexed_interceptor() &&
1393 !receiver_map->GetIndexedInterceptor()->getter()->IsUndefined( 1393 !receiver_map->GetIndexedInterceptor()->getter()->IsUndefined(
1394 isolate()) && 1394 isolate()) &&
1395 !receiver_map->GetIndexedInterceptor()->non_masking()) { 1395 !receiver_map->GetIndexedInterceptor()->non_masking()) {
1396 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedInterceptorStub); 1396 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedInterceptorStub);
1397 return LoadIndexedInterceptorStub(isolate()).GetCode(); 1397 return LoadIndexedInterceptorStub(isolate()).GetCode();
(...skipping 24 matching lines...) Expand all
1422 // TODO(jkummerow): Use IsHoleyElementsKind(elements_kind). 1422 // TODO(jkummerow): Use IsHoleyElementsKind(elements_kind).
1423 bool convert_hole_to_undefined = 1423 bool convert_hole_to_undefined =
1424 is_js_array && elements_kind == FAST_HOLEY_ELEMENTS && 1424 is_js_array && elements_kind == FAST_HOLEY_ELEMENTS &&
1425 *receiver_map == isolate()->get_initial_js_array_map(elements_kind); 1425 *receiver_map == isolate()->get_initial_js_array_map(elements_kind);
1426 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadElementDH); 1426 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadElementDH);
1427 return LoadHandler::LoadElement(isolate(), elements_kind, 1427 return LoadHandler::LoadElement(isolate(), elements_kind,
1428 convert_hole_to_undefined, is_js_array); 1428 convert_hole_to_undefined, is_js_array);
1429 } 1429 }
1430 1430
1431 void KeyedLoadIC::LoadElementPolymorphicHandlers( 1431 void KeyedLoadIC::LoadElementPolymorphicHandlers(
1432 MapHandleList* receiver_maps, List<Handle<Object>>* handlers) { 1432 MapHandles* receiver_maps, List<Handle<Object>>* handlers) {
1433 for (int i = 0; i < receiver_maps->length(); ++i) { 1433 // Filter out deprecated maps to ensure their instances get migrated.
1434 Handle<Map> receiver_map(receiver_maps->at(i)); 1434 receiver_maps->erase(
1435 if (receiver_map->is_deprecated()) { 1435 std::remove_if(
1436 // Filter out deprecated maps to ensure their instances get migrated. 1436 receiver_maps->begin(), receiver_maps->end(),
1437 receiver_maps->Remove(i--); 1437 [](const Handle<Map>& map) { return map->is_deprecated(); }),
1438 continue; 1438 receiver_maps->end());
1439 }
1440 1439
1440 for (Handle<Map> receiver_map : *receiver_maps) {
1441 // Mark all stable receiver maps that have elements kind transition map 1441 // Mark all stable receiver maps that have elements kind transition map
1442 // among receiver_maps as unstable because the optimizing compilers may 1442 // among receiver_maps as unstable because the optimizing compilers may
1443 // generate an elements kind transition for this kind of receivers. 1443 // generate an elements kind transition for this kind of receivers.
1444 if (receiver_map->is_stable()) { 1444 if (receiver_map->is_stable()) {
1445 Map* tmap = receiver_map->FindElementsKindTransitionedMap(receiver_maps); 1445 Map* tmap = receiver_map->FindElementsKindTransitionedMap(*receiver_maps);
1446 if (tmap != nullptr) { 1446 if (tmap != nullptr) {
1447 receiver_map->NotifyLeafMapLayoutChange(); 1447 receiver_map->NotifyLeafMapLayoutChange();
1448 } 1448 }
1449 } 1449 }
1450 handlers->Add(LoadElementHandler(receiver_map)); 1450 handlers->Add(LoadElementHandler(receiver_map));
1451 } 1451 }
1452 } 1452 }
1453 1453
1454 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, 1454 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
1455 Handle<Object> key) { 1455 Handle<Object> key) {
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after
1918 } 1918 }
1919 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter); 1919 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter);
1920 int expected_arguments = 1920 int expected_arguments =
1921 JSFunction::cast(*setter)->shared()->internal_formal_parameter_count(); 1921 JSFunction::cast(*setter)->shared()->internal_formal_parameter_count();
1922 return compiler.CompileStoreViaSetter( 1922 return compiler.CompileStoreViaSetter(
1923 receiver, lookup->name(), lookup->GetAccessorIndex(), expected_arguments); 1923 receiver, lookup->name(), lookup->GetAccessorIndex(), expected_arguments);
1924 } 1924 }
1925 1925
1926 void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map, 1926 void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
1927 KeyedAccessStoreMode store_mode) { 1927 KeyedAccessStoreMode store_mode) {
1928 MapHandleList target_receiver_maps; 1928 MapHandles target_receiver_maps;
1929 TargetMaps(&target_receiver_maps); 1929 TargetMaps(&target_receiver_maps);
1930 if (target_receiver_maps.length() == 0) { 1930 if (target_receiver_maps.empty()) {
1931 Handle<Map> monomorphic_map = 1931 Handle<Map> monomorphic_map =
1932 ComputeTransitionedMap(receiver_map, store_mode); 1932 ComputeTransitionedMap(receiver_map, store_mode);
1933 store_mode = GetNonTransitioningStoreMode(store_mode); 1933 store_mode = GetNonTransitioningStoreMode(store_mode);
1934 Handle<Object> handler = StoreElementHandler(monomorphic_map, store_mode); 1934 Handle<Object> handler = StoreElementHandler(monomorphic_map, store_mode);
1935 return ConfigureVectorState(Handle<Name>(), monomorphic_map, handler); 1935 return ConfigureVectorState(Handle<Name>(), monomorphic_map, handler);
1936 } 1936 }
1937 1937
1938 for (int i = 0; i < target_receiver_maps.length(); i++) { 1938 for (Handle<Map> map : target_receiver_maps) {
1939 if (!target_receiver_maps.at(i).is_null() && 1939 if (!map.is_null() && map->instance_type() == JS_VALUE_TYPE) {
1940 target_receiver_maps.at(i)->instance_type() == JS_VALUE_TYPE) {
1941 TRACE_GENERIC_IC("JSValue"); 1940 TRACE_GENERIC_IC("JSValue");
1942 return; 1941 return;
1943 } 1942 }
1944 } 1943 }
1945 1944
1946 // There are several special cases where an IC that is MONOMORPHIC can still 1945 // There are several special cases where an IC that is MONOMORPHIC can still
1947 // transition to a different GetNonTransitioningStoreMode IC that handles a 1946 // transition to a different GetNonTransitioningStoreMode IC that handles a
1948 // superset of the original IC. Handle those here if the receiver map hasn't 1947 // superset of the original IC. Handle those here if the receiver map hasn't
1949 // changed or it has transitioned to a more general kind. 1948 // changed or it has transitioned to a more general kind.
1950 KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode(); 1949 KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1995 1994
1996 if (!map_added) { 1995 if (!map_added) {
1997 // If the miss wasn't due to an unseen map, a polymorphic stub 1996 // If the miss wasn't due to an unseen map, a polymorphic stub
1998 // won't help, use the megamorphic stub which can handle everything. 1997 // won't help, use the megamorphic stub which can handle everything.
1999 TRACE_GENERIC_IC("same map added twice"); 1998 TRACE_GENERIC_IC("same map added twice");
2000 return; 1999 return;
2001 } 2000 }
2002 2001
2003 // If the maximum number of receiver maps has been exceeded, use the 2002 // If the maximum number of receiver maps has been exceeded, use the
2004 // megamorphic version of the IC. 2003 // megamorphic version of the IC.
2005 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) return; 2004 if (target_receiver_maps.size() > kMaxKeyedPolymorphism) return;
2006 2005
2007 // Make sure all polymorphic handlers have the same store mode, otherwise the 2006 // Make sure all polymorphic handlers have the same store mode, otherwise the
2008 // megamorphic stub must be used. 2007 // megamorphic stub must be used.
2009 store_mode = GetNonTransitioningStoreMode(store_mode); 2008 store_mode = GetNonTransitioningStoreMode(store_mode);
2010 if (old_store_mode != STANDARD_STORE) { 2009 if (old_store_mode != STANDARD_STORE) {
2011 if (store_mode == STANDARD_STORE) { 2010 if (store_mode == STANDARD_STORE) {
2012 store_mode = old_store_mode; 2011 store_mode = old_store_mode;
2013 } else if (store_mode != old_store_mode) { 2012 } else if (store_mode != old_store_mode) {
2014 TRACE_GENERIC_IC("store mode mismatch"); 2013 TRACE_GENERIC_IC("store mode mismatch");
2015 return; 2014 return;
2016 } 2015 }
2017 } 2016 }
2018 2017
2019 // If the store mode isn't the standard mode, make sure that all polymorphic 2018 // If the store mode isn't the standard mode, make sure that all polymorphic
2020 // receivers are either external arrays, or all "normal" arrays. Otherwise, 2019 // receivers are either external arrays, or all "normal" arrays. Otherwise,
2021 // use the megamorphic stub. 2020 // use the megamorphic stub.
2022 if (store_mode != STANDARD_STORE) { 2021 if (store_mode != STANDARD_STORE) {
2023 int external_arrays = 0; 2022 size_t external_arrays = 0;
2024 for (int i = 0; i < target_receiver_maps.length(); ++i) { 2023 for (Handle<Map> map : target_receiver_maps) {
2025 if (target_receiver_maps[i]->has_fixed_typed_array_elements()) { 2024 if (map->has_fixed_typed_array_elements()) {
2026 external_arrays++; 2025 external_arrays++;
2027 } 2026 }
2028 } 2027 }
2029 if (external_arrays != 0 && 2028 if (external_arrays != 0 &&
2030 external_arrays != target_receiver_maps.length()) { 2029 external_arrays != target_receiver_maps.size()) {
2031 TRACE_GENERIC_IC("unsupported combination of external and normal arrays"); 2030 TRACE_GENERIC_IC("unsupported combination of external and normal arrays");
2032 return; 2031 return;
2033 } 2032 }
2034 } 2033 }
2035 2034
2036 List<Handle<Object>> handlers(target_receiver_maps.length()); 2035 List<Handle<Object>> handlers(static_cast<int>(target_receiver_maps.size()));
2037 StoreElementPolymorphicHandlers(&target_receiver_maps, &handlers, store_mode); 2036 StoreElementPolymorphicHandlers(&target_receiver_maps, &handlers, store_mode);
2038 DCHECK_LE(1, target_receiver_maps.length()); 2037 DCHECK_LE(1, target_receiver_maps.size());
2039 if (target_receiver_maps.length() == 1) { 2038 if (target_receiver_maps.size() == 1) {
2040 ConfigureVectorState(Handle<Name>(), target_receiver_maps.at(0), 2039 ConfigureVectorState(Handle<Name>(), target_receiver_maps[0],
2041 handlers.at(0)); 2040 handlers.at(0));
2042 } else { 2041 } else {
2043 ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers); 2042 ConfigureVectorState(Handle<Name>(), target_receiver_maps, &handlers);
2044 } 2043 }
2045 } 2044 }
2046 2045
2047 2046
2048 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( 2047 Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
2049 Handle<Map> map, KeyedAccessStoreMode store_mode) { 2048 Handle<Map> map, KeyedAccessStoreMode store_mode) {
2050 switch (store_mode) { 2049 switch (store_mode) {
2051 case STORE_TRANSITION_TO_OBJECT: 2050 case STORE_TRANSITION_TO_OBJECT:
2052 case STORE_AND_GROW_TRANSITION_TO_OBJECT: { 2051 case STORE_AND_GROW_TRANSITION_TO_OBJECT: {
2053 ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind()) 2052 ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind())
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
2099 DCHECK_EQ(DICTIONARY_ELEMENTS, elements_kind); 2098 DCHECK_EQ(DICTIONARY_ELEMENTS, elements_kind);
2100 stub = StoreSlowElementStub(isolate(), store_mode).GetCode(); 2099 stub = StoreSlowElementStub(isolate(), store_mode).GetCode();
2101 } 2100 }
2102 Handle<Object> validity_cell = 2101 Handle<Object> validity_cell =
2103 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); 2102 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
2104 if (validity_cell.is_null()) return stub; 2103 if (validity_cell.is_null()) return stub;
2105 return isolate()->factory()->NewTuple2(validity_cell, stub); 2104 return isolate()->factory()->NewTuple2(validity_cell, stub);
2106 } 2105 }
2107 2106
2108 void KeyedStoreIC::StoreElementPolymorphicHandlers( 2107 void KeyedStoreIC::StoreElementPolymorphicHandlers(
2109 MapHandleList* receiver_maps, List<Handle<Object>>* handlers, 2108 MapHandles* receiver_maps, List<Handle<Object>>* handlers,
2110 KeyedAccessStoreMode store_mode) { 2109 KeyedAccessStoreMode store_mode) {
2111 DCHECK(store_mode == STANDARD_STORE || 2110 DCHECK(store_mode == STANDARD_STORE ||
2112 store_mode == STORE_AND_GROW_NO_TRANSITION || 2111 store_mode == STORE_AND_GROW_NO_TRANSITION ||
2113 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || 2112 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
2114 store_mode == STORE_NO_TRANSITION_HANDLE_COW); 2113 store_mode == STORE_NO_TRANSITION_HANDLE_COW);
2115 2114
2116 for (int i = 0; i < receiver_maps->length(); ++i) { 2115 // Filter out deprecated maps to ensure their instances get migrated.
2117 Handle<Map> receiver_map(receiver_maps->at(i)); 2116 receiver_maps->erase(
2118 if (receiver_map->is_deprecated()) { 2117 std::remove_if(
2119 // Filter out deprecated maps to ensure their instances get migrated. 2118 receiver_maps->begin(), receiver_maps->end(),
2120 receiver_maps->Remove(i--); 2119 [](const Handle<Map>& map) { return map->is_deprecated(); }),
2121 continue; 2120 receiver_maps->end());
2122 }
2123 2121
2122 for (Handle<Map> receiver_map : *receiver_maps) {
2124 Handle<Object> handler; 2123 Handle<Object> handler;
2125 Handle<Map> transitioned_map; 2124 Handle<Map> transitioned_map;
2126 2125
2127 if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE || 2126 if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE ||
2128 receiver_map->DictionaryElementsInPrototypeChainOnly()) { 2127 receiver_map->DictionaryElementsInPrototypeChainOnly()) {
2129 // TODO(mvstanton): Consider embedding store_mode in the state of the slow 2128 // TODO(mvstanton): Consider embedding store_mode in the state of the slow
2130 // keyed store ic for uniformity. 2129 // keyed store ic for uniformity.
2131 TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_SlowStub); 2130 TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_SlowStub);
2132 handler = isolate()->builtins()->KeyedStoreIC_Slow(); 2131 handler = isolate()->builtins()->KeyedStoreIC_Slow();
2133 2132
2134 } else { 2133 } else {
2135 { 2134 {
2136 Map* tmap = 2135 Map* tmap =
2137 receiver_map->FindElementsKindTransitionedMap(receiver_maps); 2136 receiver_map->FindElementsKindTransitionedMap(*receiver_maps);
2138 if (tmap != nullptr) { 2137 if (tmap != nullptr) {
2139 if (receiver_map->is_stable()) { 2138 if (receiver_map->is_stable()) {
2140 receiver_map->NotifyLeafMapLayoutChange(); 2139 receiver_map->NotifyLeafMapLayoutChange();
2141 } 2140 }
2142 transitioned_map = handle(tmap); 2141 transitioned_map = handle(tmap);
2143 } 2142 }
2144 } 2143 }
2145 2144
2146 // TODO(mvstanton): The code below is doing pessimistic elements 2145 // TODO(mvstanton): The code below is doing pessimistic elements
2147 // transitions. I would like to stop doing that and rely on Allocation 2146 // transitions. I would like to stop doing that and rely on Allocation
(...skipping 846 matching lines...) Expand 10 before | Expand all | Expand 10 after
2994 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); 2993 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
2995 it.Next(); 2994 it.Next();
2996 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, 2995 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2997 Object::GetProperty(&it)); 2996 Object::GetProperty(&it));
2998 } 2997 }
2999 2998
3000 return *result; 2999 return *result;
3001 } 3000 }
3002 } // namespace internal 3001 } // namespace internal
3003 } // namespace v8 3002 } // namespace v8
OLDNEW
« no previous file with comments | « src/ic/ic.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698