| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/ic/ic.h" | 5 #include "src/ic/ic.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/api-arguments-inl.h" | 8 #include "src/api-arguments-inl.h" |
| 9 #include "src/api.h" | 9 #include "src/api.h" |
| 10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
| (...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 } else { | 542 } else { |
| 543 // Non-keyed ICs don't track the name explicitly. | 543 // Non-keyed ICs don't track the name explicitly. |
| 544 if (!is_keyed()) name = Handle<Name>::null(); | 544 if (!is_keyed()) name = Handle<Name>::null(); |
| 545 nexus()->ConfigureMonomorphic(name, map, handler); | 545 nexus()->ConfigureMonomorphic(name, map, handler); |
| 546 } | 546 } |
| 547 | 547 |
| 548 vector_set_ = true; | 548 vector_set_ = true; |
| 549 OnFeedbackChanged(isolate(), GetHostFunction()); | 549 OnFeedbackChanged(isolate(), GetHostFunction()); |
| 550 } | 550 } |
| 551 | 551 |
| 552 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, | 552 void IC::ConfigureVectorState(Handle<Name> name, MapHandles const& maps, |
| 553 List<Handle<Object>>* handlers) { | 553 List<Handle<Object>>* handlers) { |
| 554 DCHECK(!IsLoadGlobalIC()); | 554 DCHECK(!IsLoadGlobalIC()); |
| 555 // Non-keyed ICs don't track the name explicitly. | 555 // Non-keyed ICs don't track the name explicitly. |
| 556 if (!is_keyed()) name = Handle<Name>::null(); | 556 if (!is_keyed()) name = Handle<Name>::null(); |
| 557 nexus()->ConfigurePolymorphic(name, maps, handlers); | 557 nexus()->ConfigurePolymorphic(name, maps, handlers); |
| 558 | 558 |
| 559 vector_set_ = true; | 559 vector_set_ = true; |
| 560 OnFeedbackChanged(isolate(), GetHostFunction()); | 560 OnFeedbackChanged(isolate(), GetHostFunction()); |
| 561 } | 561 } |
| 562 | 562 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 LoadScriptContextFieldStub stub(isolate(), &lookup_result); | 629 LoadScriptContextFieldStub stub(isolate(), &lookup_result); |
| 630 PatchCache(name, stub.GetCode()); | 630 PatchCache(name, stub.GetCode()); |
| 631 TRACE_IC("LoadGlobalIC", name); | 631 TRACE_IC("LoadGlobalIC", name); |
| 632 } | 632 } |
| 633 return result; | 633 return result; |
| 634 } | 634 } |
| 635 } | 635 } |
| 636 return LoadIC::Load(global, name); | 636 return LoadIC::Load(global, name); |
| 637 } | 637 } |
| 638 | 638 |
| 639 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, | 639 static bool AddOneReceiverMapIfMissing(MapHandles* receiver_maps, |
| 640 Handle<Map> new_receiver_map) { | 640 Handle<Map> new_receiver_map) { |
| 641 DCHECK(!new_receiver_map.is_null()); | 641 DCHECK(!new_receiver_map.is_null()); |
| 642 for (int current = 0; current < receiver_maps->length(); ++current) { | 642 for (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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |