@@ -364,9 +364,20 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
364364void IC::ConfigureVectorState (Handle<Name> name, MapHandles const & maps,
365365 MaybeObjectHandles* handlers) {
366366 DCHECK (!IsGlobalIC ());
367+ std::vector<MapAndHandler> maps_and_handlers;
368+ DCHECK_EQ (maps.size (), handlers->size ());
369+ for (size_t i = 0 ; i < maps.size (); i++) {
370+ maps_and_handlers.push_back (MapAndHandler (maps[i], handlers->at (i)));
371+ }
372+ ConfigureVectorState (name, maps_and_handlers);
373+ }
374+
375+ void IC::ConfigureVectorState (
376+ Handle<Name> name, std::vector<MapAndHandler> const & maps_and_handlers) {
377+ DCHECK (!IsGlobalIC ());
367378 // Non-keyed ICs don't track the name explicitly.
368379 if (!is_keyed ()) name = Handle<Name>::null ();
369- nexus ()->ConfigurePolymorphic (name, maps, handlers );
380+ nexus ()->ConfigurePolymorphic (name, maps_and_handlers );
370381
371382 OnFeedbackChanged (" Polymorphic" );
372383}
@@ -530,23 +541,39 @@ static bool AddOneReceiverMapIfMissing(MapHandles* receiver_maps,
530541 return true ;
531542}
532543
544+ static bool AddOneReceiverMapIfMissing (
545+ std::vector<MapAndHandler>* receiver_maps_and_handlers,
546+ Handle<Map> new_receiver_map) {
547+ DCHECK (!new_receiver_map.is_null ());
548+ if (new_receiver_map->is_deprecated ()) return false ;
549+ for (MapAndHandler map_and_handler : *receiver_maps_and_handlers) {
550+ Handle<Map> map = map_and_handler.first ;
551+ if (!map.is_null () && map.is_identical_to (new_receiver_map)) {
552+ return false ;
553+ }
554+ }
555+ receiver_maps_and_handlers->push_back (
556+ MapAndHandler (new_receiver_map, MaybeObjectHandle ()));
557+ return true ;
558+ }
559+
533560bool IC::UpdatePolymorphicIC (Handle<Name> name,
534561 const MaybeObjectHandle& handler) {
535562 DCHECK (IsHandler (*handler));
536563 if (is_keyed () && state () != RECOMPUTE_HANDLER) {
537564 if (nexus ()->GetName () != *name) return false ;
538565 }
539566 Handle<Map> map = receiver_map ();
540- MapHandles maps;
541- MaybeObjectHandles handlers;
542567
543- nexus ()->ExtractMapsAndHandlers (&maps, &handlers);
544- int number_of_maps = static_cast <int >(maps.size ());
568+ std::vector<MapAndHandler> maps_and_handlers;
569+ nexus ()->ExtractMapsAndHandlers (&maps_and_handlers);
570+ int number_of_maps = static_cast <int >(maps_and_handlers.size ());
545571 int deprecated_maps = 0 ;
546572 int handler_to_overwrite = -1 ;
547573
548574 for (int i = 0 ; i < number_of_maps; i++) {
549- Handle<Map> current_map = maps.at (i);
575+ Handle<Map> current_map = maps_and_handlers.at (i).first ;
576+ MaybeObjectHandle current_handler = maps_and_handlers.at (i).second ;
550577 if (current_map->is_deprecated ()) {
551578 // Filter out deprecated maps to ensure their instances get migrated.
552579 ++deprecated_maps;
@@ -556,7 +583,7 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name,
556583 // in the lattice and need to go MEGAMORPHIC instead. There's one
557584 // exception to this rule, which is when we're in RECOMPUTE_HANDLER
558585 // state, there we allow to migrate to a new handler.
559- if (handler.is_identical_to (handlers[i] ) &&
586+ if (handler.is_identical_to (current_handler ) &&
560587 state () != RECOMPUTE_HANDLER) {
561588 return false ;
562589 }
@@ -584,16 +611,16 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name,
584611 } else {
585612 if (is_keyed () && nexus ()->GetName () != *name) return false ;
586613 if (handler_to_overwrite >= 0 ) {
587- handlers[handler_to_overwrite] = handler;
588- if (!map.is_identical_to (maps.at (handler_to_overwrite))) {
589- maps[handler_to_overwrite] = map;
614+ maps_and_handlers[handler_to_overwrite].second = handler;
615+ if (!map.is_identical_to (
616+ maps_and_handlers.at (handler_to_overwrite).first )) {
617+ maps_and_handlers[handler_to_overwrite].first = map;
590618 }
591619 } else {
592- maps.push_back (map);
593- handlers.push_back (handler);
620+ maps_and_handlers.push_back (MapAndHandler (map, handler));
594621 }
595622
596- ConfigureVectorState (name, maps, &handlers );
623+ ConfigureVectorState (name, maps_and_handlers );
597624 }
598625
599626 return true ;
@@ -606,11 +633,10 @@ void IC::UpdateMonomorphicIC(const MaybeObjectHandle& handler,
606633}
607634
608635void IC::CopyICToMegamorphicCache (Handle<Name> name) {
609- MapHandles maps;
610- MaybeObjectHandles handlers;
611- nexus ()->ExtractMapsAndHandlers (&maps, &handlers);
612- for (size_t i = 0 ; i < maps.size (); ++i) {
613- UpdateMegamorphicCache (maps.at (i), name, handlers.at (i));
636+ std::vector<MapAndHandler> maps_and_handlers;
637+ nexus ()->ExtractMapsAndHandlers (&maps_and_handlers);
638+ for (const MapAndHandler& map_and_handler : maps_and_handlers) {
639+ UpdateMegamorphicCache (map_and_handler.first , name, map_and_handler.second );
614640 }
615641}
616642
@@ -1768,9 +1794,9 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
17681794void KeyedStoreIC::UpdateStoreElement (Handle<Map> receiver_map,
17691795 KeyedAccessStoreMode store_mode,
17701796 Handle<Map> new_receiver_map) {
1771- MapHandles target_receiver_maps ;
1772- TargetMaps (&target_receiver_maps );
1773- if (target_receiver_maps .empty ()) {
1797+ std::vector<MapAndHandler> target_maps_and_handlers ;
1798+ nexus ()-> ExtractMapsAndHandlers (&target_maps_and_handlers, true );
1799+ if (target_maps_and_handlers .empty ()) {
17741800 Handle<Map> monomorphic_map = receiver_map;
17751801 // If we transitioned to a map that is a more general map than incoming
17761802 // then use the new map.
@@ -1781,7 +1807,8 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
17811807 return ConfigureVectorState (Handle<Name>(), monomorphic_map, handler);
17821808 }
17831809
1784- for (Handle<Map> map : target_receiver_maps) {
1810+ for (const MapAndHandler& map_and_handler : target_maps_and_handlers) {
1811+ Handle<Map> map = map_and_handler.first ;
17851812 if (!map.is_null () && map->instance_type () == JS_PRIMITIVE_WRAPPER_TYPE) {
17861813 DCHECK (!IsStoreInArrayLiteralICKind (kind ()));
17871814 set_slow_stub_reason (" JSPrimitiveWrapper" );
@@ -1794,7 +1821,7 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
17941821 // Handle those here if the receiver map hasn't changed or it has transitioned
17951822 // to a more general kind.
17961823 KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode ();
1797- Handle<Map> previous_receiver_map = target_receiver_maps .at (0 );
1824+ Handle<Map> previous_receiver_map = target_maps_and_handlers .at (0 ). first ;
17981825 if (state () == MONOMORPHIC) {
17991826 Handle<Map> transitioned_receiver_map = new_receiver_map;
18001827 if (IsTransitionOfMonomorphicTarget (*previous_receiver_map,
@@ -1823,11 +1850,11 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
18231850 DCHECK (state () != GENERIC);
18241851
18251852 bool map_added =
1826- AddOneReceiverMapIfMissing (&target_receiver_maps , receiver_map);
1853+ AddOneReceiverMapIfMissing (&target_maps_and_handlers , receiver_map);
18271854
18281855 if (IsTransitionOfMonomorphicTarget (*receiver_map, *new_receiver_map)) {
18291856 map_added |=
1830- AddOneReceiverMapIfMissing (&target_receiver_maps , new_receiver_map);
1857+ AddOneReceiverMapIfMissing (&target_maps_and_handlers , new_receiver_map);
18311858 }
18321859
18331860 if (!map_added) {
@@ -1839,7 +1866,7 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
18391866
18401867 // If the maximum number of receiver maps has been exceeded, use the
18411868 // megamorphic version of the IC.
1842- if (static_cast <int >(target_receiver_maps .size ()) >
1869+ if (static_cast <int >(target_maps_and_handlers .size ()) >
18431870 FLAG_max_polymorphic_map_count) {
18441871 return ;
18451872 }
@@ -1860,36 +1887,37 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
18601887 // use the megamorphic stub.
18611888 if (store_mode != STANDARD_STORE) {
18621889 size_t external_arrays = 0 ;
1863- for (Handle<Map> map : target_receiver_maps) {
1890+ for (MapAndHandler map_and_handler : target_maps_and_handlers) {
1891+ Handle<Map> map = map_and_handler.first ;
18641892 if (map->has_typed_array_elements ()) {
18651893 DCHECK (!IsStoreInArrayLiteralICKind (kind ()));
18661894 external_arrays++;
18671895 }
18681896 }
18691897 if (external_arrays != 0 &&
1870- external_arrays != target_receiver_maps .size ()) {
1898+ external_arrays != target_maps_and_handlers .size ()) {
18711899 DCHECK (!IsStoreInArrayLiteralICKind (kind ()));
18721900 set_slow_stub_reason (
18731901 " unsupported combination of external and normal arrays" );
18741902 return ;
18751903 }
18761904 }
18771905
1878- MaybeObjectHandles handlers;
1879- handlers.reserve (target_receiver_maps.size ());
1880- StoreElementPolymorphicHandlers (&target_receiver_maps, &handlers, store_mode);
1881- if (target_receiver_maps.size () == 0 ) {
1906+ StoreElementPolymorphicHandlers (&target_maps_and_handlers, store_mode);
1907+ if (target_maps_and_handlers.size () == 0 ) {
18821908 Handle<Object> handler = StoreElementHandler (receiver_map, store_mode);
18831909 ConfigureVectorState (Handle<Name>(), receiver_map, handler);
1884- } else if (target_receiver_maps.size () == 1 ) {
1885- ConfigureVectorState (Handle<Name>(), target_receiver_maps[0 ], handlers[0 ]);
1910+ } else if (target_maps_and_handlers.size () == 1 ) {
1911+ ConfigureVectorState (Handle<Name>(), target_maps_and_handlers[0 ].first ,
1912+ target_maps_and_handlers[0 ].second );
18861913 } else {
1887- ConfigureVectorState (Handle<Name>(), target_receiver_maps, &handlers );
1914+ ConfigureVectorState (Handle<Name>(), target_maps_and_handlers );
18881915 }
18891916}
18901917
18911918Handle<Object> KeyedStoreIC::StoreElementHandler (
1892- Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
1919+ Handle<Map> receiver_map, KeyedAccessStoreMode store_mode,
1920+ MaybeHandle<Object> prev_validity_cell) {
18931921 DCHECK_IMPLIES (
18941922 receiver_map->DictionaryElementsInPrototypeChainOnly (isolate ()),
18951923 IsStoreInArrayLiteralICKind (kind ()));
@@ -1925,8 +1953,11 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
19251953 }
19261954
19271955 if (IsStoreInArrayLiteralICKind (kind ())) return code;
1928- Handle<Object> validity_cell =
1929- Map::GetOrCreatePrototypeChainValidityCell (receiver_map, isolate ());
1956+ Handle<Object> validity_cell;
1957+ if (!prev_validity_cell.ToHandle (&validity_cell)) {
1958+ validity_cell =
1959+ Map::GetOrCreatePrototypeChainValidityCell (receiver_map, isolate ());
1960+ }
19301961 if (validity_cell->IsSmi ()) {
19311962 // There's no prototype validity cell to check, so we can just use the stub.
19321963 return code;
@@ -1938,16 +1969,17 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
19381969}
19391970
19401971void KeyedStoreIC::StoreElementPolymorphicHandlers (
1941- MapHandles* receiver_maps, MaybeObjectHandles* handlers ,
1972+ std::vector<MapAndHandler>* receiver_maps_and_handlers ,
19421973 KeyedAccessStoreMode store_mode) {
1943- // Filter out deprecated maps to ensure their instances get migrated.
1944- receiver_maps->erase (
1945- std::remove_if (
1946- receiver_maps->begin (), receiver_maps->end (),
1947- [](const Handle<Map>& map) { return map->is_deprecated (); }),
1948- receiver_maps->end ());
1974+ std::vector<Handle<Map>> receiver_maps;
1975+ for (size_t i = 0 ; i < receiver_maps_and_handlers->size (); i++) {
1976+ receiver_maps.push_back (receiver_maps_and_handlers->at (i).first );
1977+ }
19491978
1950- for (Handle<Map> receiver_map : *receiver_maps) {
1979+ for (size_t i = 0 ; i < receiver_maps_and_handlers->size (); i++) {
1980+ Handle<Map> receiver_map = receiver_maps_and_handlers->at (i).first ;
1981+ DCHECK (!receiver_map->is_deprecated ());
1982+ MaybeObjectHandle old_handler = receiver_maps_and_handlers->at (i).second ;
19511983 Handle<Object> handler;
19521984 Handle<Map> transition;
19531985
@@ -1960,8 +1992,8 @@ void KeyedStoreIC::StoreElementPolymorphicHandlers(
19601992
19611993 } else {
19621994 {
1963- Map tmap = receiver_map->FindElementsKindTransitionedMap (
1964- isolate (), * receiver_maps);
1995+ Map tmap = receiver_map->FindElementsKindTransitionedMap (isolate (),
1996+ receiver_maps);
19651997 if (!tmap.is_null ()) {
19661998 if (receiver_map->is_stable ()) {
19671999 receiver_map->NotifyLeafMapLayoutChange (isolate ());
@@ -1970,6 +2002,16 @@ void KeyedStoreIC::StoreElementPolymorphicHandlers(
19702002 }
19712003 }
19722004
2005+ MaybeHandle<Object> validity_cell;
2006+ HeapObject old_handler_obj;
2007+ if (!old_handler.is_null () &&
2008+ old_handler->GetHeapObject (&old_handler_obj) &&
2009+ old_handler_obj.IsDataHandler ()) {
2010+ validity_cell = MaybeHandle<Object>(
2011+ DataHandler::cast (old_handler_obj).validity_cell (), isolate ());
2012+ }
2013+ // TODO(mythria): Do not recompute the handler if we know there is no
2014+ // change in the handler.
19732015 // TODO(mvstanton): The code below is doing pessimistic elements
19742016 // transitions. I would like to stop doing that and rely on Allocation
19752017 // Site Tracking to do a better job of ensuring the data types are what
@@ -1978,14 +2020,15 @@ void KeyedStoreIC::StoreElementPolymorphicHandlers(
19782020 if (!transition.is_null ()) {
19792021 TRACE_HANDLER_STATS (isolate (),
19802022 KeyedStoreIC_ElementsTransitionAndStoreStub);
1981- handler = StoreHandler::StoreElementTransition (isolate (), receiver_map,
1982- transition, store_mode);
2023+ handler = StoreHandler::StoreElementTransition (
2024+ isolate (), receiver_map, transition, store_mode, validity_cell );
19832025 } else {
1984- handler = StoreElementHandler (receiver_map, store_mode);
2026+ handler = StoreElementHandler (receiver_map, store_mode, validity_cell );
19852027 }
19862028 }
19872029 DCHECK (!handler.is_null ());
1988- handlers->push_back (MaybeObjectHandle (handler));
2030+ receiver_maps_and_handlers->at (i) =
2031+ MapAndHandler (receiver_map, MaybeObjectHandle (handler));
19892032 }
19902033}
19912034
0 commit comments