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

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

Issue 2809923002: Unify implementations of Map handles vectors and lists (Closed)
Patch Set: Style nit 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 561 matching lines...) Expand 10 before | Expand all | Expand 10 after
1309 } else if (key->IsString()) { 1310 } else if (key->IsString()) {
1310 key = isolate->factory()->InternalizeString(Handle<String>::cast(key)); 1311 key = isolate->factory()->InternalizeString(Handle<String>::cast(key));
1311 } 1312 }
1312 return key; 1313 return key;
1313 } 1314 }
1314 1315
1315 void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) { 1316 void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) {
1316 Handle<Map> receiver_map(receiver->map(), isolate()); 1317 Handle<Map> receiver_map(receiver->map(), isolate());
1317 DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE && 1318 DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE &&
1318 receiver_map->instance_type() != JS_PROXY_TYPE); // Checked by caller. 1319 receiver_map->instance_type() != JS_PROXY_TYPE); // Checked by caller.
1319 MapHandleList target_receiver_maps; 1320 MapHandles target_receiver_maps;
1320 TargetMaps(&target_receiver_maps); 1321 TargetMaps(&target_receiver_maps);
1321 1322
1322 if (target_receiver_maps.length() == 0) { 1323 if (target_receiver_maps.empty()) {
1323 Handle<Object> handler = LoadElementHandler(receiver_map); 1324 Handle<Object> handler = LoadElementHandler(receiver_map);
1324 return ConfigureVectorState(Handle<Name>(), receiver_map, handler); 1325 return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
1325 } 1326 }
1326 1327
1327 for (int i = 0; i < target_receiver_maps.length(); i++) { 1328 for (Handle<Map> map : target_receiver_maps) {
1328 Handle<Map> map = target_receiver_maps.at(i);
1329 if (map.is_null()) continue; 1329 if (map.is_null()) continue;
1330 if (map->instance_type() == JS_VALUE_TYPE) { 1330 if (map->instance_type() == JS_VALUE_TYPE) {
1331 TRACE_GENERIC_IC("JSValue"); 1331 TRACE_GENERIC_IC("JSValue");
1332 return; 1332 return;
1333 } 1333 }
1334 if (map->instance_type() == JS_PROXY_TYPE) { 1334 if (map->instance_type() == JS_PROXY_TYPE) {
1335 TRACE_GENERIC_IC("JSProxy"); 1335 TRACE_GENERIC_IC("JSProxy");
1336 return; 1336 return;
1337 } 1337 }
1338 } 1338 }
(...skipping 19 matching lines...) Expand all
1358 // adding the map that was just encountered. 1358 // adding the map that was just encountered.
1359 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { 1359 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
1360 // If the miss wasn't due to an unseen map, a polymorphic stub 1360 // If the miss wasn't due to an unseen map, a polymorphic stub
1361 // won't help, use the generic stub. 1361 // won't help, use the generic stub.
1362 TRACE_GENERIC_IC("same map added twice"); 1362 TRACE_GENERIC_IC("same map added twice");
1363 return; 1363 return;
1364 } 1364 }
1365 1365
1366 // If the maximum number of receiver maps has been exceeded, use the generic 1366 // If the maximum number of receiver maps has been exceeded, use the generic
1367 // version of the IC. 1367 // version of the IC.
1368 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { 1368 if (target_receiver_maps.size() > kMaxKeyedPolymorphism) {
1369 TRACE_GENERIC_IC("max polymorph exceeded"); 1369 TRACE_GENERIC_IC("max polymorph exceeded");
1370 return; 1370 return;
1371 } 1371 }
1372 1372
1373 List<Handle<Object>> handlers(target_receiver_maps.length()); 1373 List<Handle<Object>> handlers(static_cast<int>(target_receiver_maps.size()));
1374 LoadElementPolymorphicHandlers(&target_receiver_maps, &handlers); 1374 LoadElementPolymorphicHandlers(&target_receiver_maps, &handlers);
1375 DCHECK_LE(1, target_receiver_maps.length()); 1375 DCHECK_LE(1, target_receiver_maps.size());
1376 if (target_receiver_maps.length() == 1) { 1376 if (target_receiver_maps.size() == 1) {
1377 ConfigureVectorState(Handle<Name>(), target_receiver_maps.at(0), 1377 ConfigureVectorState(Handle<Name>(), target_receiver_maps[0],
1378 handlers.at(0)); 1378 handlers.at(0));
1379 } else { 1379 } else {
1380 ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers); 1380 ConfigureVectorState(Handle<Name>(), target_receiver_maps, &handlers);
1381 } 1381 }
1382 } 1382 }
1383 1383
1384 Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map) { 1384 Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map) {
1385 if (receiver_map->has_indexed_interceptor() && 1385 if (receiver_map->has_indexed_interceptor() &&
1386 !receiver_map->GetIndexedInterceptor()->getter()->IsUndefined( 1386 !receiver_map->GetIndexedInterceptor()->getter()->IsUndefined(
1387 isolate()) && 1387 isolate()) &&
1388 !receiver_map->GetIndexedInterceptor()->non_masking()) { 1388 !receiver_map->GetIndexedInterceptor()->non_masking()) {
1389 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedInterceptorStub); 1389 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedInterceptorStub);
1390 return LoadIndexedInterceptorStub(isolate()).GetCode(); 1390 return LoadIndexedInterceptorStub(isolate()).GetCode();
(...skipping 24 matching lines...) Expand all
1415 // TODO(jkummerow): Use IsHoleyElementsKind(elements_kind). 1415 // TODO(jkummerow): Use IsHoleyElementsKind(elements_kind).
1416 bool convert_hole_to_undefined = 1416 bool convert_hole_to_undefined =
1417 is_js_array && elements_kind == FAST_HOLEY_ELEMENTS && 1417 is_js_array && elements_kind == FAST_HOLEY_ELEMENTS &&
1418 *receiver_map == isolate()->get_initial_js_array_map(elements_kind); 1418 *receiver_map == isolate()->get_initial_js_array_map(elements_kind);
1419 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadElementDH); 1419 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadElementDH);
1420 return LoadHandler::LoadElement(isolate(), elements_kind, 1420 return LoadHandler::LoadElement(isolate(), elements_kind,
1421 convert_hole_to_undefined, is_js_array); 1421 convert_hole_to_undefined, is_js_array);
1422 } 1422 }
1423 1423
1424 void KeyedLoadIC::LoadElementPolymorphicHandlers( 1424 void KeyedLoadIC::LoadElementPolymorphicHandlers(
1425 MapHandleList* receiver_maps, List<Handle<Object>>* handlers) { 1425 MapHandles* receiver_maps, List<Handle<Object>>* handlers) {
1426 for (int i = 0; i < receiver_maps->length(); ++i) { 1426 receiver_maps->erase(
1427 Handle<Map> receiver_map(receiver_maps->at(i)); 1427 std::remove_if(
1428 if (receiver_map->is_deprecated()) { 1428 receiver_maps->begin(), receiver_maps->end(),
1429 // Filter out deprecated maps to ensure their instances get migrated. 1429 [](const Handle<Map>& map) { return map->is_deprecated(); }),
Jakob Kummerow 2017/05/05 15:28:39 nit: this comment got lost
danno 2017/05/09 21:29:03 Done.
1430 receiver_maps->Remove(i--); 1430 receiver_maps->end());
1431 continue;
1432 }
1433 1431
1432 for (Handle<Map> receiver_map : *receiver_maps) {
1434 // Mark all stable receiver maps that have elements kind transition map 1433 // Mark all stable receiver maps that have elements kind transition map
1435 // among receiver_maps as unstable because the optimizing compilers may 1434 // among receiver_maps as unstable because the optimizing compilers may
1436 // generate an elements kind transition for this kind of receivers. 1435 // generate an elements kind transition for this kind of receivers.
1437 if (receiver_map->is_stable()) { 1436 if (receiver_map->is_stable()) {
1438 Map* tmap = receiver_map->FindElementsKindTransitionedMap(receiver_maps); 1437 Map* tmap = receiver_map->FindElementsKindTransitionedMap(*receiver_maps);
1439 if (tmap != nullptr) { 1438 if (tmap != nullptr) {
1440 receiver_map->NotifyLeafMapLayoutChange(); 1439 receiver_map->NotifyLeafMapLayoutChange();
1441 } 1440 }
1442 } 1441 }
1443 handlers->Add(LoadElementHandler(receiver_map)); 1442 handlers->Add(LoadElementHandler(receiver_map));
1444 } 1443 }
1445 } 1444 }
1446 1445
1447 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, 1446 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
1448 Handle<Object> key) { 1447 Handle<Object> key) {
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after
1911 } 1910 }
1912 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter); 1911 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter);
1913 int expected_arguments = 1912 int expected_arguments =
1914 JSFunction::cast(*setter)->shared()->internal_formal_parameter_count(); 1913 JSFunction::cast(*setter)->shared()->internal_formal_parameter_count();
1915 return compiler.CompileStoreViaSetter( 1914 return compiler.CompileStoreViaSetter(
1916 receiver, lookup->name(), lookup->GetAccessorIndex(), expected_arguments); 1915 receiver, lookup->name(), lookup->GetAccessorIndex(), expected_arguments);
1917 } 1916 }
1918 1917
1919 void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map, 1918 void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
1920 KeyedAccessStoreMode store_mode) { 1919 KeyedAccessStoreMode store_mode) {
1921 MapHandleList target_receiver_maps; 1920 MapHandles target_receiver_maps;
1922 TargetMaps(&target_receiver_maps); 1921 TargetMaps(&target_receiver_maps);
1923 if (target_receiver_maps.length() == 0) { 1922 if (target_receiver_maps.empty()) {
1924 Handle<Map> monomorphic_map = 1923 Handle<Map> monomorphic_map =
1925 ComputeTransitionedMap(receiver_map, store_mode); 1924 ComputeTransitionedMap(receiver_map, store_mode);
1926 store_mode = GetNonTransitioningStoreMode(store_mode); 1925 store_mode = GetNonTransitioningStoreMode(store_mode);
1927 Handle<Object> handler = StoreElementHandler(monomorphic_map, store_mode); 1926 Handle<Object> handler = StoreElementHandler(monomorphic_map, store_mode);
1928 return ConfigureVectorState(Handle<Name>(), monomorphic_map, handler); 1927 return ConfigureVectorState(Handle<Name>(), monomorphic_map, handler);
1929 } 1928 }
1930 1929
1931 for (int i = 0; i < target_receiver_maps.length(); i++) { 1930 for (Handle<Map> map : target_receiver_maps) {
1932 if (!target_receiver_maps.at(i).is_null() && 1931 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"); 1932 TRACE_GENERIC_IC("JSValue");
1935 return; 1933 return;
1936 } 1934 }
1937 } 1935 }
1938 1936
1939 // There are several special cases where an IC that is MONOMORPHIC can still 1937 // There are several special cases where an IC that is MONOMORPHIC can still
1940 // transition to a different GetNonTransitioningStoreMode IC that handles a 1938 // transition to a different GetNonTransitioningStoreMode IC that handles a
1941 // superset of the original IC. Handle those here if the receiver map hasn't 1939 // 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. 1940 // changed or it has transitioned to a more general kind.
1943 KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode(); 1941 KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1988 1986
1989 if (!map_added) { 1987 if (!map_added) {
1990 // If the miss wasn't due to an unseen map, a polymorphic stub 1988 // 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. 1989 // won't help, use the megamorphic stub which can handle everything.
1992 TRACE_GENERIC_IC("same map added twice"); 1990 TRACE_GENERIC_IC("same map added twice");
1993 return; 1991 return;
1994 } 1992 }
1995 1993
1996 // If the maximum number of receiver maps has been exceeded, use the 1994 // If the maximum number of receiver maps has been exceeded, use the
1997 // megamorphic version of the IC. 1995 // megamorphic version of the IC.
1998 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) return; 1996 if (target_receiver_maps.size() > kMaxKeyedPolymorphism) return;
1999 1997
2000 // Make sure all polymorphic handlers have the same store mode, otherwise the 1998 // Make sure all polymorphic handlers have the same store mode, otherwise the
2001 // megamorphic stub must be used. 1999 // megamorphic stub must be used.
2002 store_mode = GetNonTransitioningStoreMode(store_mode); 2000 store_mode = GetNonTransitioningStoreMode(store_mode);
2003 if (old_store_mode != STANDARD_STORE) { 2001 if (old_store_mode != STANDARD_STORE) {
2004 if (store_mode == STANDARD_STORE) { 2002 if (store_mode == STANDARD_STORE) {
2005 store_mode = old_store_mode; 2003 store_mode = old_store_mode;
2006 } else if (store_mode != old_store_mode) { 2004 } else if (store_mode != old_store_mode) {
2007 TRACE_GENERIC_IC("store mode mismatch"); 2005 TRACE_GENERIC_IC("store mode mismatch");
2008 return; 2006 return;
2009 } 2007 }
2010 } 2008 }
2011 2009
2012 // If the store mode isn't the standard mode, make sure that all polymorphic 2010 // 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, 2011 // receivers are either external arrays, or all "normal" arrays. Otherwise,
2014 // use the megamorphic stub. 2012 // use the megamorphic stub.
2015 if (store_mode != STANDARD_STORE) { 2013 if (store_mode != STANDARD_STORE) {
2016 int external_arrays = 0; 2014 size_t external_arrays = 0;
2017 for (int i = 0; i < target_receiver_maps.length(); ++i) { 2015 for (Handle<Map> map : target_receiver_maps) {
2018 if (target_receiver_maps[i]->has_fixed_typed_array_elements()) { 2016 if (map->has_fixed_typed_array_elements()) {
2019 external_arrays++; 2017 external_arrays++;
2020 } 2018 }
2021 } 2019 }
2022 if (external_arrays != 0 && 2020 if (external_arrays != 0 &&
2023 external_arrays != target_receiver_maps.length()) { 2021 external_arrays != target_receiver_maps.size()) {
2024 TRACE_GENERIC_IC("unsupported combination of external and normal arrays"); 2022 TRACE_GENERIC_IC("unsupported combination of external and normal arrays");
2025 return; 2023 return;
2026 } 2024 }
2027 } 2025 }
2028 2026
2029 List<Handle<Object>> handlers(target_receiver_maps.length()); 2027 List<Handle<Object>> handlers(static_cast<int>(target_receiver_maps.size()));
2030 StoreElementPolymorphicHandlers(&target_receiver_maps, &handlers, store_mode); 2028 StoreElementPolymorphicHandlers(&target_receiver_maps, &handlers, store_mode);
2031 DCHECK_LE(1, target_receiver_maps.length()); 2029 DCHECK_LE(1, target_receiver_maps.size());
2032 if (target_receiver_maps.length() == 1) { 2030 if (target_receiver_maps.size() == 1) {
2033 ConfigureVectorState(Handle<Name>(), target_receiver_maps.at(0), 2031 ConfigureVectorState(Handle<Name>(), target_receiver_maps[0],
2034 handlers.at(0)); 2032 handlers.at(0));
2035 } else { 2033 } else {
2036 ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers); 2034 ConfigureVectorState(Handle<Name>(), target_receiver_maps, &handlers);
2037 } 2035 }
2038 } 2036 }
2039 2037
2040 2038
2041 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( 2039 Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
2042 Handle<Map> map, KeyedAccessStoreMode store_mode) { 2040 Handle<Map> map, KeyedAccessStoreMode store_mode) {
2043 switch (store_mode) { 2041 switch (store_mode) {
2044 case STORE_TRANSITION_TO_OBJECT: 2042 case STORE_TRANSITION_TO_OBJECT:
2045 case STORE_AND_GROW_TRANSITION_TO_OBJECT: { 2043 case STORE_AND_GROW_TRANSITION_TO_OBJECT: {
2046 ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind()) 2044 ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind())
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
2092 DCHECK_EQ(DICTIONARY_ELEMENTS, elements_kind); 2090 DCHECK_EQ(DICTIONARY_ELEMENTS, elements_kind);
2093 stub = StoreSlowElementStub(isolate(), store_mode).GetCode(); 2091 stub = StoreSlowElementStub(isolate(), store_mode).GetCode();
2094 } 2092 }
2095 Handle<Object> validity_cell = 2093 Handle<Object> validity_cell =
2096 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); 2094 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
2097 if (validity_cell.is_null()) return stub; 2095 if (validity_cell.is_null()) return stub;
2098 return isolate()->factory()->NewTuple2(validity_cell, stub); 2096 return isolate()->factory()->NewTuple2(validity_cell, stub);
2099 } 2097 }
2100 2098
2101 void KeyedStoreIC::StoreElementPolymorphicHandlers( 2099 void KeyedStoreIC::StoreElementPolymorphicHandlers(
2102 MapHandleList* receiver_maps, List<Handle<Object>>* handlers, 2100 MapHandles* receiver_maps, List<Handle<Object>>* handlers,
2103 KeyedAccessStoreMode store_mode) { 2101 KeyedAccessStoreMode store_mode) {
2104 DCHECK(store_mode == STANDARD_STORE || 2102 DCHECK(store_mode == STANDARD_STORE ||
2105 store_mode == STORE_AND_GROW_NO_TRANSITION || 2103 store_mode == STORE_AND_GROW_NO_TRANSITION ||
2106 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || 2104 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
2107 store_mode == STORE_NO_TRANSITION_HANDLE_COW); 2105 store_mode == STORE_NO_TRANSITION_HANDLE_COW);
2108 2106
2109 for (int i = 0; i < receiver_maps->length(); ++i) { 2107 receiver_maps->erase(
2110 Handle<Map> receiver_map(receiver_maps->at(i)); 2108 std::remove_if(
2111 if (receiver_map->is_deprecated()) { 2109 receiver_maps->begin(), receiver_maps->end(),
2112 // Filter out deprecated maps to ensure their instances get migrated. 2110 [](const Handle<Map>& map) { return map->is_deprecated(); }),
Jakob Kummerow 2017/05/05 15:28:39 nit: this comment got lost
danno 2017/05/09 21:29:03 Done.
2113 receiver_maps->Remove(i--); 2111 receiver_maps->end());
2114 continue;
2115 }
2116 2112
2113 for (Handle<Map> receiver_map : *receiver_maps) {
2117 Handle<Object> handler; 2114 Handle<Object> handler;
2118 Handle<Map> transitioned_map; 2115 Handle<Map> transitioned_map;
2119 2116
2120 if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE || 2117 if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE ||
2121 receiver_map->DictionaryElementsInPrototypeChainOnly()) { 2118 receiver_map->DictionaryElementsInPrototypeChainOnly()) {
2122 // TODO(mvstanton): Consider embedding store_mode in the state of the slow 2119 // TODO(mvstanton): Consider embedding store_mode in the state of the slow
2123 // keyed store ic for uniformity. 2120 // keyed store ic for uniformity.
2124 TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_SlowStub); 2121 TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_SlowStub);
2125 handler = isolate()->builtins()->KeyedStoreIC_Slow(); 2122 handler = isolate()->builtins()->KeyedStoreIC_Slow();
2126 2123
2127 } else { 2124 } else {
2128 { 2125 {
2129 Map* tmap = 2126 Map* tmap =
2130 receiver_map->FindElementsKindTransitionedMap(receiver_maps); 2127 receiver_map->FindElementsKindTransitionedMap(*receiver_maps);
2131 if (tmap != nullptr) { 2128 if (tmap != nullptr) {
2132 if (receiver_map->is_stable()) { 2129 if (receiver_map->is_stable()) {
2133 receiver_map->NotifyLeafMapLayoutChange(); 2130 receiver_map->NotifyLeafMapLayoutChange();
2134 } 2131 }
2135 transitioned_map = handle(tmap); 2132 transitioned_map = handle(tmap);
2136 } 2133 }
2137 } 2134 }
2138 2135
2139 // TODO(mvstanton): The code below is doing pessimistic elements 2136 // TODO(mvstanton): The code below is doing pessimistic elements
2140 // transitions. I would like to stop doing that and rely on Allocation 2137 // transitions. I would like to stop doing that and rely on Allocation
(...skipping 846 matching lines...) Expand 10 before | Expand all | Expand 10 after
2987 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); 2984 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
2988 it.Next(); 2985 it.Next();
2989 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, 2986 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2990 Object::GetProperty(&it)); 2987 Object::GetProperty(&it));
2991 } 2988 }
2992 2989
2993 return *result; 2990 return *result;
2994 } 2991 }
2995 } // namespace internal 2992 } // namespace internal
2996 } // namespace v8 2993 } // 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