@@ -363,9 +363,20 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
363363void IC::ConfigureVectorState (Handle<Name> name, MapHandles const & maps,
364364 MaybeObjectHandles* handlers) {
365365 DCHECK (!IsGlobalIC ());
366+ std::vector<MapAndHandler> maps_and_handlers;
367+ DCHECK_EQ (maps.size (), handlers->size ());
368+ for (size_t i = 0 ; i < maps.size (); i++) {
369+ maps_and_handlers.push_back (MapAndHandler (maps[i], handlers->at (i)));
370+ }
371+ ConfigureVectorState (name, maps_and_handlers);
372+ }
373+
374+ void IC::ConfigureVectorState (
375+ Handle<Name> name, std::vector<MapAndHandler> const & maps_and_handlers) {
376+ DCHECK (!IsGlobalIC ());
366377 // Non-keyed ICs don't track the name explicitly.
367378 if (!is_keyed ()) name = Handle<Name>::null ();
368- nexus ()->ConfigurePolymorphic (name, maps, handlers );
379+ nexus ()->ConfigurePolymorphic (name, maps_and_handlers );
369380
370381 OnFeedbackChanged (" Polymorphic" );
371382}
@@ -521,23 +532,39 @@ static bool AddOneReceiverMapIfMissing(MapHandles* receiver_maps,
521532 return true ;
522533}
523534
535+ static bool AddOneReceiverMapIfMissing (
536+ std::vector<MapAndHandler>* receiver_maps_and_handlers,
537+ Handle<Map> new_receiver_map) {
538+ DCHECK (!new_receiver_map.is_null ());
539+ if (new_receiver_map->is_deprecated ()) return false ;
540+ for (MapAndHandler map_and_handler : *receiver_maps_and_handlers) {
541+ Handle<Map> map = map_and_handler.first ;
542+ if (!map.is_null () && map.is_identical_to (new_receiver_map)) {
543+ return false ;
544+ }
545+ }
546+ receiver_maps_and_handlers->push_back (
547+ MapAndHandler (new_receiver_map, MaybeObjectHandle ()));
548+ return true ;
549+ }
550+
524551bool IC::UpdatePolymorphicIC (Handle<Name> name,
525552 const MaybeObjectHandle& handler) {
526553 DCHECK (IsHandler (*handler));
527554 if (is_keyed () && state () != RECOMPUTE_HANDLER) {
528555 if (nexus ()->GetName () != *name) return false ;
529556 }
530557 Handle<Map> map = receiver_map ();
531- MapHandles maps;
532- MaybeObjectHandles handlers;
533558
534- nexus ()->ExtractMapsAndHandlers (&maps, &handlers);
535- int number_of_maps = static_cast <int >(maps.size ());
559+ std::vector<MapAndHandler> maps_and_handlers;
560+ nexus ()->ExtractMapsAndHandlers (&maps_and_handlers);
561+ int number_of_maps = static_cast <int >(maps_and_handlers.size ());
536562 int deprecated_maps = 0 ;
537563 int handler_to_overwrite = -1 ;
538564
539565 for (int i = 0 ; i < number_of_maps; i++) {
540- Handle<Map> current_map = maps.at (i);
566+ Handle<Map> current_map = maps_and_handlers.at (i).first ;
567+ MaybeObjectHandle current_handler = maps_and_handlers.at (i).second ;
541568 if (current_map->is_deprecated ()) {
542569 // Filter out deprecated maps to ensure their instances get migrated.
543570 ++deprecated_maps;
@@ -547,7 +574,7 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name,
547574 // in the lattice and need to go MEGAMORPHIC instead. There's one
548575 // exception to this rule, which is when we're in RECOMPUTE_HANDLER
549576 // state, there we allow to migrate to a new handler.
550- if (handler.is_identical_to (handlers[i] ) &&
577+ if (handler.is_identical_to (current_handler ) &&
551578 state () != RECOMPUTE_HANDLER) {
552579 return false ;
553580 }
@@ -575,16 +602,16 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name,
575602 } else {
576603 if (is_keyed () && nexus ()->GetName () != *name) return false ;
577604 if (handler_to_overwrite >= 0 ) {
578- handlers[handler_to_overwrite] = handler;
579- if (!map.is_identical_to (maps.at (handler_to_overwrite))) {
580- maps[handler_to_overwrite] = map;
605+ maps_and_handlers[handler_to_overwrite].second = handler;
606+ if (!map.is_identical_to (
607+ maps_and_handlers.at (handler_to_overwrite).first )) {
608+ maps_and_handlers[handler_to_overwrite].first = map;
581609 }
582610 } else {
583- maps.push_back (map);
584- handlers.push_back (handler);
611+ maps_and_handlers.push_back (MapAndHandler (map, handler));
585612 }
586613
587- ConfigureVectorState (name, maps, &handlers );
614+ ConfigureVectorState (name, maps_and_handlers );
588615 }
589616
590617 return true ;
@@ -597,11 +624,10 @@ void IC::UpdateMonomorphicIC(const MaybeObjectHandle& handler,
597624}
598625
599626void IC::CopyICToMegamorphicCache (Handle<Name> name) {
600- MapHandles maps;
601- MaybeObjectHandles handlers;
602- nexus ()->ExtractMapsAndHandlers (&maps, &handlers);
603- for (size_t i = 0 ; i < maps.size (); ++i) {
604- UpdateMegamorphicCache (maps.at (i), name, handlers.at (i));
627+ std::vector<MapAndHandler> maps_and_handlers;
628+ nexus ()->ExtractMapsAndHandlers (&maps_and_handlers);
629+ for (const MapAndHandler& map_and_handler : maps_and_handlers) {
630+ UpdateMegamorphicCache (map_and_handler.first , name, map_and_handler.second );
605631 }
606632}
607633
@@ -1760,9 +1786,9 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
17601786void KeyedStoreIC::UpdateStoreElement (Handle<Map> receiver_map,
17611787 KeyedAccessStoreMode store_mode,
17621788 Handle<Map> new_receiver_map) {
1763- MapHandles target_receiver_maps ;
1764- TargetMaps (&target_receiver_maps );
1765- if (target_receiver_maps .empty ()) {
1789+ std::vector<MapAndHandler> target_maps_and_handlers ;
1790+ nexus ()-> ExtractMapsAndHandlers (&target_maps_and_handlers, true );
1791+ if (target_maps_and_handlers .empty ()) {
17661792 Handle<Map> monomorphic_map = receiver_map;
17671793 // If we transitioned to a map that is a more general map than incoming
17681794 // then use the new map.
@@ -1773,7 +1799,8 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
17731799 return ConfigureVectorState (Handle<Name>(), monomorphic_map, handler);
17741800 }
17751801
1776- for (Handle<Map> map : target_receiver_maps) {
1802+ for (const MapAndHandler& map_and_handler : target_maps_and_handlers) {
1803+ Handle<Map> map = map_and_handler.first ;
17771804 if (!map.is_null () && map->instance_type () == JS_PRIMITIVE_WRAPPER_TYPE) {
17781805 DCHECK (!IsStoreInArrayLiteralICKind (kind ()));
17791806 set_slow_stub_reason (" JSPrimitiveWrapper" );
@@ -1786,7 +1813,7 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
17861813 // Handle those here if the receiver map hasn't changed or it has transitioned
17871814 // to a more general kind.
17881815 KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode ();
1789- Handle<Map> previous_receiver_map = target_receiver_maps .at (0 );
1816+ Handle<Map> previous_receiver_map = target_maps_and_handlers .at (0 ). first ;
17901817 if (state () == MONOMORPHIC) {
17911818 Handle<Map> transitioned_receiver_map = new_receiver_map;
17921819 if (IsTransitionOfMonomorphicTarget (*previous_receiver_map,
@@ -1815,11 +1842,11 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
18151842 DCHECK (state () != GENERIC);
18161843
18171844 bool map_added =
1818- AddOneReceiverMapIfMissing (&target_receiver_maps , receiver_map);
1845+ AddOneReceiverMapIfMissing (&target_maps_and_handlers , receiver_map);
18191846
18201847 if (IsTransitionOfMonomorphicTarget (*receiver_map, *new_receiver_map)) {
18211848 map_added |=
1822- AddOneReceiverMapIfMissing (&target_receiver_maps , new_receiver_map);
1849+ AddOneReceiverMapIfMissing (&target_maps_and_handlers , new_receiver_map);
18231850 }
18241851
18251852 if (!map_added) {
@@ -1831,7 +1858,7 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
18311858
18321859 // If the maximum number of receiver maps has been exceeded, use the
18331860 // megamorphic version of the IC.
1834- if (static_cast <int >(target_receiver_maps .size ()) >
1861+ if (static_cast <int >(target_maps_and_handlers .size ()) >
18351862 FLAG_max_polymorphic_map_count) {
18361863 return ;
18371864 }
@@ -1852,36 +1879,37 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
18521879 // use the megamorphic stub.
18531880 if (store_mode != STANDARD_STORE) {
18541881 size_t external_arrays = 0 ;
1855- for (Handle<Map> map : target_receiver_maps) {
1882+ for (MapAndHandler map_and_handler : target_maps_and_handlers) {
1883+ Handle<Map> map = map_and_handler.first ;
18561884 if (map->has_typed_array_elements ()) {
18571885 DCHECK (!IsStoreInArrayLiteralICKind (kind ()));
18581886 external_arrays++;
18591887 }
18601888 }
18611889 if (external_arrays != 0 &&
1862- external_arrays != target_receiver_maps .size ()) {
1890+ external_arrays != target_maps_and_handlers .size ()) {
18631891 DCHECK (!IsStoreInArrayLiteralICKind (kind ()));
18641892 set_slow_stub_reason (
18651893 " unsupported combination of external and normal arrays" );
18661894 return ;
18671895 }
18681896 }
18691897
1870- MaybeObjectHandles handlers;
1871- handlers.reserve (target_receiver_maps.size ());
1872- StoreElementPolymorphicHandlers (&target_receiver_maps, &handlers, store_mode);
1873- if (target_receiver_maps.size () == 0 ) {
1898+ StoreElementPolymorphicHandlers (&target_maps_and_handlers, store_mode);
1899+ if (target_maps_and_handlers.size () == 0 ) {
18741900 Handle<Object> handler = StoreElementHandler (receiver_map, store_mode);
18751901 ConfigureVectorState (Handle<Name>(), receiver_map, handler);
1876- } else if (target_receiver_maps.size () == 1 ) {
1877- ConfigureVectorState (Handle<Name>(), target_receiver_maps[0 ], handlers[0 ]);
1902+ } else if (target_maps_and_handlers.size () == 1 ) {
1903+ ConfigureVectorState (Handle<Name>(), target_maps_and_handlers[0 ].first ,
1904+ target_maps_and_handlers[0 ].second );
18781905 } else {
1879- ConfigureVectorState (Handle<Name>(), target_receiver_maps, &handlers );
1906+ ConfigureVectorState (Handle<Name>(), target_maps_and_handlers );
18801907 }
18811908}
18821909
18831910Handle<Object> KeyedStoreIC::StoreElementHandler (
1884- Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
1911+ Handle<Map> receiver_map, KeyedAccessStoreMode store_mode,
1912+ MaybeHandle<Object> prev_validity_cell) {
18851913 DCHECK_IMPLIES (
18861914 receiver_map->DictionaryElementsInPrototypeChainOnly (isolate ()),
18871915 IsStoreInArrayLiteralICKind (kind ()));
@@ -1917,8 +1945,11 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
19171945 }
19181946
19191947 if (IsStoreInArrayLiteralICKind (kind ())) return code;
1920- Handle<Object> validity_cell =
1921- Map::GetOrCreatePrototypeChainValidityCell (receiver_map, isolate ());
1948+ Handle<Object> validity_cell;
1949+ if (!prev_validity_cell.ToHandle (&validity_cell)) {
1950+ validity_cell =
1951+ Map::GetOrCreatePrototypeChainValidityCell (receiver_map, isolate ());
1952+ }
19221953 if (validity_cell->IsSmi ()) {
19231954 // There's no prototype validity cell to check, so we can just use the stub.
19241955 return code;
@@ -1930,16 +1961,17 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
19301961}
19311962
19321963void KeyedStoreIC::StoreElementPolymorphicHandlers (
1933- MapHandles* receiver_maps, MaybeObjectHandles* handlers ,
1964+ std::vector<MapAndHandler>* receiver_maps_and_handlers ,
19341965 KeyedAccessStoreMode store_mode) {
1935- // Filter out deprecated maps to ensure their instances get migrated.
1936- receiver_maps->erase (
1937- std::remove_if (
1938- receiver_maps->begin (), receiver_maps->end (),
1939- [](const Handle<Map>& map) { return map->is_deprecated (); }),
1940- receiver_maps->end ());
1966+ std::vector<Handle<Map>> receiver_maps;
1967+ for (size_t i = 0 ; i < receiver_maps_and_handlers->size (); i++) {
1968+ receiver_maps.push_back (receiver_maps_and_handlers->at (i).first );
1969+ }
19411970
1942- for (Handle<Map> receiver_map : *receiver_maps) {
1971+ for (size_t i = 0 ; i < receiver_maps_and_handlers->size (); i++) {
1972+ Handle<Map> receiver_map = receiver_maps_and_handlers->at (i).first ;
1973+ DCHECK (!receiver_map->is_deprecated ());
1974+ MaybeObjectHandle old_handler = receiver_maps_and_handlers->at (i).second ;
19431975 Handle<Object> handler;
19441976 Handle<Map> transition;
19451977
@@ -1952,8 +1984,8 @@ void KeyedStoreIC::StoreElementPolymorphicHandlers(
19521984
19531985 } else {
19541986 {
1955- Map tmap = receiver_map->FindElementsKindTransitionedMap (
1956- isolate (), * receiver_maps);
1987+ Map tmap = receiver_map->FindElementsKindTransitionedMap (isolate (),
1988+ receiver_maps);
19571989 if (!tmap.is_null ()) {
19581990 if (receiver_map->is_stable ()) {
19591991 receiver_map->NotifyLeafMapLayoutChange (isolate ());
@@ -1962,6 +1994,16 @@ void KeyedStoreIC::StoreElementPolymorphicHandlers(
19621994 }
19631995 }
19641996
1997+ MaybeHandle<Object> validity_cell;
1998+ HeapObject old_handler_obj;
1999+ if (!old_handler.is_null () &&
2000+ old_handler->GetHeapObject (&old_handler_obj) &&
2001+ old_handler_obj.IsDataHandler ()) {
2002+ validity_cell = MaybeHandle<Object>(
2003+ DataHandler::cast (old_handler_obj).validity_cell (), isolate ());
2004+ }
2005+ // TODO(mythria): Do not recompute the handler if we know there is no
2006+ // change in the handler.
19652007 // TODO(mvstanton): The code below is doing pessimistic elements
19662008 // transitions. I would like to stop doing that and rely on Allocation
19672009 // Site Tracking to do a better job of ensuring the data types are what
@@ -1970,14 +2012,15 @@ void KeyedStoreIC::StoreElementPolymorphicHandlers(
19702012 if (!transition.is_null ()) {
19712013 TRACE_HANDLER_STATS (isolate (),
19722014 KeyedStoreIC_ElementsTransitionAndStoreStub);
1973- handler = StoreHandler::StoreElementTransition (isolate (), receiver_map,
1974- transition, store_mode);
2015+ handler = StoreHandler::StoreElementTransition (
2016+ isolate (), receiver_map, transition, store_mode, validity_cell );
19752017 } else {
1976- handler = StoreElementHandler (receiver_map, store_mode);
2018+ handler = StoreElementHandler (receiver_map, store_mode, validity_cell );
19772019 }
19782020 }
19792021 DCHECK (!handler.is_null ());
1980- handlers->push_back (MaybeObjectHandle (handler));
2022+ receiver_maps_and_handlers->at (i) =
2023+ MapAndHandler (receiver_map, MaybeObjectHandle (handler));
19812024 }
19822025}
19832026
0 commit comments