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

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

Issue 2809923002: Unify implementations of Map handles vectors and lists (Closed)
Patch Set: Format 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
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 (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
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
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
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
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
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
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
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
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
OLDNEW
« src/compiler/access-info.cc ('K') | « src/ic/ic.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698