@@ -363,9 +363,20 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
363
363
void IC::ConfigureVectorState (Handle <Name> name, MapHandles const & maps,
364
364
MaybeObjectHandles* handlers) {
365
365
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 ());
366
377
// Non-keyed ICs don't track the name explicitly.
367
378
if (!is_keyed ()) name = Handle <Name>::null ();
368
- nexus ()->ConfigurePolymorphic (name, maps, handlers );
379
+ nexus ()->ConfigurePolymorphic (name, maps_and_handlers );
369
380
370
381
OnFeedbackChanged (" Polymorphic" );
371
382
}
@@ -521,23 +532,39 @@ static bool AddOneReceiverMapIfMissing(MapHandles* receiver_maps,
521
532
return true ;
522
533
}
523
534
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
+
524
551
bool IC::UpdatePolymorphicIC (Handle <Name> name,
525
552
const MaybeObjectHandle& handler) {
526
553
DCHECK (IsHandler (*handler));
527
554
if (is_keyed () && state () != RECOMPUTE_HANDLER) {
528
555
if (nexus ()->GetName () != *name) return false ;
529
556
}
530
557
Handle <Map> map = receiver_map ();
531
- MapHandles maps;
532
- MaybeObjectHandles handlers;
533
558
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 ());
536
562
int deprecated_maps = 0 ;
537
563
int handler_to_overwrite = -1 ;
538
564
539
565
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 ;
541
568
if (current_map->is_deprecated ()) {
542
569
// Filter out deprecated maps to ensure their instances get migrated.
543
570
++deprecated_maps;
@@ -547,7 +574,7 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name,
547
574
// in the lattice and need to go MEGAMORPHIC instead. There's one
548
575
// exception to this rule, which is when we're in RECOMPUTE_HANDLER
549
576
// 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 ) &&
551
578
state () != RECOMPUTE_HANDLER) {
552
579
return false ;
553
580
}
@@ -575,16 +602,16 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name,
575
602
} else {
576
603
if (is_keyed () && nexus ()->GetName () != *name) return false ;
577
604
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;
581
609
}
582
610
} else {
583
- maps.push_back (map);
584
- handlers.push_back (handler);
611
+ maps_and_handlers.push_back (MapAndHandler (map, handler));
585
612
}
586
613
587
- ConfigureVectorState (name, maps, &handlers );
614
+ ConfigureVectorState (name, maps_and_handlers );
588
615
}
589
616
590
617
return true ;
@@ -597,11 +624,10 @@ void IC::UpdateMonomorphicIC(const MaybeObjectHandle& handler,
597
624
}
598
625
599
626
void 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 );
605
631
}
606
632
}
607
633
@@ -1760,9 +1786,9 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
1760
1786
void KeyedStoreIC::UpdateStoreElement (Handle <Map> receiver_map,
1761
1787
KeyedAccessStoreMode store_mode,
1762
1788
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 ()) {
1766
1792
Handle <Map> monomorphic_map = receiver_map;
1767
1793
// If we transitioned to a map that is a more general map than incoming
1768
1794
// then use the new map.
@@ -1773,7 +1799,8 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
1773
1799
return ConfigureVectorState (Handle <Name>(), monomorphic_map, handler);
1774
1800
}
1775
1801
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 ;
1777
1804
if (!map.is_null () && map->instance_type () == JS_PRIMITIVE_WRAPPER_TYPE) {
1778
1805
DCHECK (!IsStoreInArrayLiteralICKind (kind ()));
1779
1806
set_slow_stub_reason (" JSPrimitiveWrapper" );
@@ -1786,7 +1813,7 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
1786
1813
// Handle those here if the receiver map hasn't changed or it has transitioned
1787
1814
// to a more general kind.
1788
1815
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 ;
1790
1817
if (state () == MONOMORPHIC) {
1791
1818
Handle <Map> transitioned_receiver_map = new_receiver_map;
1792
1819
if (IsTransitionOfMonomorphicTarget (*previous_receiver_map,
@@ -1815,11 +1842,11 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
1815
1842
DCHECK (state () != GENERIC);
1816
1843
1817
1844
bool map_added =
1818
- AddOneReceiverMapIfMissing (&target_receiver_maps , receiver_map);
1845
+ AddOneReceiverMapIfMissing (&target_maps_and_handlers , receiver_map);
1819
1846
1820
1847
if (IsTransitionOfMonomorphicTarget (*receiver_map, *new_receiver_map)) {
1821
1848
map_added |=
1822
- AddOneReceiverMapIfMissing (&target_receiver_maps , new_receiver_map);
1849
+ AddOneReceiverMapIfMissing (&target_maps_and_handlers , new_receiver_map);
1823
1850
}
1824
1851
1825
1852
if (!map_added) {
@@ -1831,7 +1858,7 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
1831
1858
1832
1859
// If the maximum number of receiver maps has been exceeded, use the
1833
1860
// megamorphic version of the IC.
1834
- if (static_cast <int >(target_receiver_maps .size ()) >
1861
+ if (static_cast <int >(target_maps_and_handlers .size ()) >
1835
1862
FLAG_max_polymorphic_map_count) {
1836
1863
return ;
1837
1864
}
@@ -1852,36 +1879,37 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
1852
1879
// use the megamorphic stub.
1853
1880
if (store_mode != STANDARD_STORE) {
1854
1881
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 ;
1856
1884
if (map->has_typed_array_elements ()) {
1857
1885
DCHECK (!IsStoreInArrayLiteralICKind (kind ()));
1858
1886
external_arrays++;
1859
1887
}
1860
1888
}
1861
1889
if (external_arrays != 0 &&
1862
- external_arrays != target_receiver_maps .size ()) {
1890
+ external_arrays != target_maps_and_handlers .size ()) {
1863
1891
DCHECK (!IsStoreInArrayLiteralICKind (kind ()));
1864
1892
set_slow_stub_reason (
1865
1893
" unsupported combination of external and normal arrays" );
1866
1894
return ;
1867
1895
}
1868
1896
}
1869
1897
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 ) {
1874
1900
Handle <Object> handler = StoreElementHandler (receiver_map, store_mode);
1875
1901
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 );
1878
1905
} else {
1879
- ConfigureVectorState (Handle <Name>(), target_receiver_maps, &handlers );
1906
+ ConfigureVectorState (Handle <Name>(), target_maps_and_handlers );
1880
1907
}
1881
1908
}
1882
1909
1883
1910
Handle <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) {
1885
1913
DCHECK_IMPLIES (
1886
1914
receiver_map->DictionaryElementsInPrototypeChainOnly (isolate ()),
1887
1915
IsStoreInArrayLiteralICKind (kind ()));
@@ -1917,8 +1945,11 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
1917
1945
}
1918
1946
1919
1947
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
+ }
1922
1953
if (validity_cell->IsSmi ()) {
1923
1954
// There's no prototype validity cell to check, so we can just use the stub.
1924
1955
return code;
@@ -1930,16 +1961,17 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
1930
1961
}
1931
1962
1932
1963
void KeyedStoreIC::StoreElementPolymorphicHandlers (
1933
- MapHandles* receiver_maps, MaybeObjectHandles* handlers ,
1964
+ std::vector<MapAndHandler>* receiver_maps_and_handlers ,
1934
1965
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
+ }
1941
1970
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 ;
1943
1975
Handle <Object> handler;
1944
1976
Handle <Map> transition;
1945
1977
@@ -1952,8 +1984,8 @@ void KeyedStoreIC::StoreElementPolymorphicHandlers(
1952
1984
1953
1985
} else {
1954
1986
{
1955
- Map tmap = receiver_map->FindElementsKindTransitionedMap (
1956
- isolate (), * receiver_maps);
1987
+ Map tmap = receiver_map->FindElementsKindTransitionedMap (isolate (),
1988
+ receiver_maps);
1957
1989
if (!tmap.is_null ()) {
1958
1990
if (receiver_map->is_stable ()) {
1959
1991
receiver_map->NotifyLeafMapLayoutChange (isolate ());
@@ -1962,6 +1994,16 @@ void KeyedStoreIC::StoreElementPolymorphicHandlers(
1962
1994
}
1963
1995
}
1964
1996
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.
1965
2007
// TODO(mvstanton): The code below is doing pessimistic elements
1966
2008
// transitions. I would like to stop doing that and rely on Allocation
1967
2009
// Site Tracking to do a better job of ensuring the data types are what
@@ -1970,14 +2012,15 @@ void KeyedStoreIC::StoreElementPolymorphicHandlers(
1970
2012
if (!transition.is_null ()) {
1971
2013
TRACE_HANDLER_STATS (isolate (),
1972
2014
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 );
1975
2017
} else {
1976
- handler = StoreElementHandler (receiver_map, store_mode);
2018
+ handler = StoreElementHandler (receiver_map, store_mode, validity_cell );
1977
2019
}
1978
2020
}
1979
2021
DCHECK (!handler.is_null ());
1980
- handlers->push_back (MaybeObjectHandle (handler));
2022
+ receiver_maps_and_handlers->at (i) =
2023
+ MapAndHandler (receiver_map, MaybeObjectHandle (handler));
1981
2024
}
1982
2025
}
1983
2026
0 commit comments