LCOV - code coverage report
Current view: top level - test/cctest - test-elements-kind.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 230 231 99.6 %
Date: 2017-10-20 Functions: 15 15 100.0 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include <stdlib.h>
       6             : #include <utility>
       7             : 
       8             : #include "test/cctest/test-api.h"
       9             : 
      10             : #include "src/v8.h"
      11             : 
      12             : #include "src/compilation-cache.h"
      13             : #include "src/execution.h"
      14             : #include "src/factory.h"
      15             : #include "src/global-handles.h"
      16             : #include "src/ic/stub-cache.h"
      17             : #include "src/objects-inl.h"
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : namespace test_elements_kind {
      22             : 
      23             : //
      24             : // Helper functions.
      25             : //
      26             : 
      27             : namespace {
      28             : 
      29             : Handle<String> MakeString(const char* str) {
      30             :   Isolate* isolate = CcTest::i_isolate();
      31             :   Factory* factory = isolate->factory();
      32        1410 :   return factory->InternalizeUtf8String(str);
      33             : }
      34             : 
      35             : 
      36        1272 : Handle<String> MakeName(const char* str, int suffix) {
      37             :   EmbeddedVector<char, 128> buffer;
      38        1272 :   SNPrintF(buffer, "%s%d", str, suffix);
      39        2544 :   return MakeString(buffer.start());
      40             : }
      41             : 
      42             : 
      43             : template <typename T, typename M>
      44         126 : bool EQUALS(Handle<T> left, Handle<M> right) {
      45         126 :   if (*left == *right) return true;
      46             :   return JSObject::Equals(Handle<Object>::cast(left),
      47             :                           Handle<Object>::cast(right))
      48           0 :       .FromJust();
      49             : }
      50             : 
      51             : 
      52             : template <typename T, typename M>
      53             : bool EQUALS(Handle<T> left, M right) {
      54             :   return EQUALS(left, handle(right));
      55             : }
      56             : 
      57             : 
      58             : template <typename T, typename M>
      59         126 : bool EQUALS(T left, Handle<M> right) {
      60         126 :   return EQUALS(handle(left, right->GetIsolate()), right);
      61             : }
      62             : 
      63             : }  // namespace
      64             : 
      65             : 
      66             : //
      67             : // Tests
      68             : //
      69             : 
      70       23724 : TEST(JSObjectAddingProperties) {
      71           6 :   CcTest::InitializeVM();
      72             :   Isolate* isolate = CcTest::i_isolate();
      73             :   Factory* factory = isolate->factory();
      74           6 :   v8::HandleScope scope(CcTest::isolate());
      75             : 
      76           6 :   Handle<FixedArray> empty_fixed_array(factory->empty_fixed_array());
      77           6 :   Handle<PropertyArray> empty_property_array(factory->empty_property_array());
      78           6 :   Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
      79             :   Handle<Object> value(Smi::FromInt(42), isolate);
      80             : 
      81           6 :   Handle<JSObject> object = factory->NewJSObject(function);
      82             :   Handle<Map> previous_map(object->map());
      83           6 :   CHECK_EQ(HOLEY_ELEMENTS, previous_map->elements_kind());
      84           6 :   CHECK(EQUALS(object->property_array(), empty_property_array));
      85           6 :   CHECK(EQUALS(object->elements(), empty_fixed_array));
      86             : 
      87             :   // for the default constructor function no in-object properties are reserved
      88             :   // hence adding a single property will initialize the property-array
      89           6 :   Handle<String> name = MakeName("property", 0);
      90           6 :   JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
      91          12 :       .Check();
      92           6 :   CHECK_NE(object->map(), *previous_map);
      93           6 :   CHECK_EQ(HOLEY_ELEMENTS, object->map()->elements_kind());
      94           6 :   CHECK_LE(1, object->property_array()->length());
      95           6 :   CHECK(EQUALS(object->elements(), empty_fixed_array));
      96           6 : }
      97             : 
      98             : 
      99       23724 : TEST(JSObjectInObjectAddingProperties) {
     100           6 :   CcTest::InitializeVM();
     101             :   Isolate* isolate = CcTest::i_isolate();
     102             :   Factory* factory = isolate->factory();
     103           6 :   v8::HandleScope scope(CcTest::isolate());
     104             : 
     105           6 :   Handle<FixedArray> empty_fixed_array(factory->empty_fixed_array());
     106           6 :   Handle<PropertyArray> empty_property_array(factory->empty_property_array());
     107           6 :   Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
     108             :   int nof_inobject_properties = 10;
     109             :   // force in object properties by changing the expected_nof_properties
     110             :   function->shared()->set_expected_nof_properties(nof_inobject_properties);
     111             :   Handle<Object> value(Smi::FromInt(42), isolate);
     112             : 
     113           6 :   Handle<JSObject> object = factory->NewJSObject(function);
     114             :   Handle<Map> previous_map(object->map());
     115           6 :   CHECK_EQ(HOLEY_ELEMENTS, previous_map->elements_kind());
     116           6 :   CHECK(EQUALS(object->property_array(), empty_property_array));
     117           6 :   CHECK(EQUALS(object->elements(), empty_fixed_array));
     118             : 
     119             :   // we have reserved space for in-object properties, hence adding up to
     120             :   // |nof_inobject_properties| will not create a property store
     121          60 :   for (int i = 0; i < nof_inobject_properties; i++) {
     122          60 :     Handle<String> name = MakeName("property", i);
     123          60 :     JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
     124         120 :         .Check();
     125             :   }
     126           6 :   CHECK_NE(object->map(), *previous_map);
     127           6 :   CHECK_EQ(HOLEY_ELEMENTS, object->map()->elements_kind());
     128           6 :   CHECK(EQUALS(object->property_array(), empty_property_array));
     129           6 :   CHECK(EQUALS(object->elements(), empty_fixed_array));
     130             : 
     131             :   // adding one more property will not fit in the in-object properties, thus
     132             :   // creating a property store
     133             :   int index = nof_inobject_properties + 1;
     134           6 :   Handle<String> name = MakeName("property", index);
     135           6 :   JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
     136          12 :       .Check();
     137           6 :   CHECK_NE(object->map(), *previous_map);
     138           6 :   CHECK_EQ(HOLEY_ELEMENTS, object->map()->elements_kind());
     139             :   // there must be at least 1 element in the properies store
     140           6 :   CHECK_LE(1, object->property_array()->length());
     141           6 :   CHECK(EQUALS(object->elements(), empty_fixed_array));
     142           6 : }
     143             : 
     144             : 
     145       23724 : TEST(JSObjectAddingElements) {
     146           6 :   CcTest::InitializeVM();
     147             :   Isolate* isolate = CcTest::i_isolate();
     148             :   Factory* factory = isolate->factory();
     149           6 :   v8::HandleScope scope(CcTest::isolate());
     150             : 
     151             :   Handle<String> name;
     152           6 :   Handle<FixedArray> empty_fixed_array(factory->empty_fixed_array());
     153           6 :   Handle<PropertyArray> empty_property_array(factory->empty_property_array());
     154           6 :   Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
     155             :   Handle<Object> value(Smi::FromInt(42), isolate);
     156             : 
     157           6 :   Handle<JSObject> object = factory->NewJSObject(function);
     158             :   Handle<Map> previous_map(object->map());
     159           6 :   CHECK_EQ(HOLEY_ELEMENTS, previous_map->elements_kind());
     160           6 :   CHECK(EQUALS(object->property_array(), empty_property_array));
     161           6 :   CHECK(EQUALS(object->elements(), empty_fixed_array));
     162             : 
     163             :   // Adding an indexed element initializes the elements array
     164             :   name = MakeString("0");
     165           6 :   JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
     166          12 :       .Check();
     167             :   // no change in elements_kind => no map transition
     168           6 :   CHECK_EQ(object->map(), *previous_map);
     169           6 :   CHECK_EQ(HOLEY_ELEMENTS, object->map()->elements_kind());
     170           6 :   CHECK(EQUALS(object->property_array(), empty_property_array));
     171           6 :   CHECK_LE(1, object->elements()->length());
     172             : 
     173             :   // Adding more consecutive elements without a change in the backing store
     174             :   int non_dict_backing_store_limit = 100;
     175         594 :   for (int i = 1; i < non_dict_backing_store_limit; i++) {
     176         594 :     name = MakeName("", i);
     177         594 :     JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
     178        1188 :         .Check();
     179             :   }
     180             :   // no change in elements_kind => no map transition
     181           6 :   CHECK_EQ(object->map(), *previous_map);
     182           6 :   CHECK_EQ(HOLEY_ELEMENTS, object->map()->elements_kind());
     183           6 :   CHECK(EQUALS(object->property_array(), empty_property_array));
     184           6 :   CHECK_LE(non_dict_backing_store_limit, object->elements()->length());
     185             : 
     186             :   // Adding an element at an very large index causes a change to
     187             :   // DICTIONARY_ELEMENTS
     188             :   name = MakeString("100000000");
     189           6 :   JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
     190          12 :       .Check();
     191             :   // change in elements_kind => map transition
     192           6 :   CHECK_NE(object->map(), *previous_map);
     193           6 :   CHECK_EQ(DICTIONARY_ELEMENTS, object->map()->elements_kind());
     194           6 :   CHECK(EQUALS(object->property_array(), empty_property_array));
     195           6 :   CHECK_LE(non_dict_backing_store_limit, object->elements()->length());
     196           6 : }
     197             : 
     198             : 
     199       23724 : TEST(JSArrayAddingProperties) {
     200           6 :   CcTest::InitializeVM();
     201             :   Isolate* isolate = CcTest::i_isolate();
     202             :   Factory* factory = isolate->factory();
     203           6 :   v8::HandleScope scope(CcTest::isolate());
     204             : 
     205           6 :   Handle<FixedArray> empty_fixed_array(factory->empty_fixed_array());
     206           6 :   Handle<PropertyArray> empty_property_array(factory->empty_property_array());
     207             :   Handle<Object> value(Smi::FromInt(42), isolate);
     208             : 
     209             :   Handle<JSArray> array =
     210           6 :       factory->NewJSArray(ElementsKind::PACKED_SMI_ELEMENTS, 0, 0);
     211             :   Handle<Map> previous_map(array->map());
     212           6 :   CHECK_EQ(PACKED_SMI_ELEMENTS, previous_map->elements_kind());
     213           6 :   CHECK(EQUALS(array->property_array(), empty_property_array));
     214           6 :   CHECK(EQUALS(array->elements(), empty_fixed_array));
     215           6 :   CHECK_EQ(0, Smi::ToInt(array->length()));
     216             : 
     217             :   // for the default constructor function no in-object properties are reserved
     218             :   // hence adding a single property will initialize the property-array
     219           6 :   Handle<String> name = MakeName("property", 0);
     220           6 :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value, NONE)
     221          12 :       .Check();
     222             :   // No change in elements_kind but added property => new map
     223           6 :   CHECK_NE(array->map(), *previous_map);
     224           6 :   CHECK_EQ(PACKED_SMI_ELEMENTS, array->map()->elements_kind());
     225           6 :   CHECK_LE(1, array->property_array()->length());
     226           6 :   CHECK(EQUALS(array->elements(), empty_fixed_array));
     227           6 :   CHECK_EQ(0, Smi::ToInt(array->length()));
     228           6 : }
     229             : 
     230             : 
     231       23724 : TEST(JSArrayAddingElements) {
     232           6 :   CcTest::InitializeVM();
     233             :   Isolate* isolate = CcTest::i_isolate();
     234             :   Factory* factory = isolate->factory();
     235           6 :   v8::HandleScope scope(CcTest::isolate());
     236             : 
     237             :   Handle<String> name;
     238           6 :   Handle<FixedArray> empty_fixed_array(factory->empty_fixed_array());
     239           6 :   Handle<PropertyArray> empty_property_array(factory->empty_property_array());
     240             :   Handle<Object> value(Smi::FromInt(42), isolate);
     241             : 
     242             :   Handle<JSArray> array =
     243           6 :       factory->NewJSArray(ElementsKind::PACKED_SMI_ELEMENTS, 0, 0);
     244             :   Handle<Map> previous_map(array->map());
     245           6 :   CHECK_EQ(PACKED_SMI_ELEMENTS, previous_map->elements_kind());
     246           6 :   CHECK(EQUALS(array->property_array(), empty_property_array));
     247           6 :   CHECK(EQUALS(array->elements(), empty_fixed_array));
     248           6 :   CHECK_EQ(0, Smi::ToInt(array->length()));
     249             : 
     250             :   // Adding an indexed element initializes the elements array
     251             :   name = MakeString("0");
     252           6 :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value, NONE)
     253          12 :       .Check();
     254             :   // no change in elements_kind => no map transition
     255           6 :   CHECK_EQ(array->map(), *previous_map);
     256           6 :   CHECK_EQ(PACKED_SMI_ELEMENTS, array->map()->elements_kind());
     257           6 :   CHECK(EQUALS(array->property_array(), empty_property_array));
     258           6 :   CHECK_LE(1, array->elements()->length());
     259           6 :   CHECK_EQ(1, Smi::ToInt(array->length()));
     260             : 
     261             :   // Adding more consecutive elements without a change in the backing store
     262             :   int non_dict_backing_store_limit = 100;
     263         594 :   for (int i = 1; i < non_dict_backing_store_limit; i++) {
     264         594 :     name = MakeName("", i);
     265         594 :     JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value, NONE)
     266        1188 :         .Check();
     267             :   }
     268             :   // no change in elements_kind => no map transition
     269           6 :   CHECK_EQ(array->map(), *previous_map);
     270           6 :   CHECK_EQ(PACKED_SMI_ELEMENTS, array->map()->elements_kind());
     271           6 :   CHECK(EQUALS(array->property_array(), empty_property_array));
     272           6 :   CHECK_LE(non_dict_backing_store_limit, array->elements()->length());
     273           6 :   CHECK_EQ(non_dict_backing_store_limit, Smi::ToInt(array->length()));
     274             : 
     275             :   // Adding an element at an very large index causes a change to
     276             :   // DICTIONARY_ELEMENTS
     277             :   int index = 100000000;
     278           6 :   name = MakeName("", index);
     279           6 :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value, NONE)
     280          12 :       .Check();
     281             :   // change in elements_kind => map transition
     282           6 :   CHECK_NE(array->map(), *previous_map);
     283           6 :   CHECK_EQ(DICTIONARY_ELEMENTS, array->map()->elements_kind());
     284           6 :   CHECK(EQUALS(array->property_array(), empty_property_array));
     285           6 :   CHECK_LE(non_dict_backing_store_limit, array->elements()->length());
     286           6 :   CHECK_LE(array->elements()->length(), index);
     287           6 :   CHECK_EQ(index + 1, Smi::ToInt(array->length()));
     288           6 : }
     289             : 
     290             : 
     291       23724 : TEST(JSArrayAddingElementsGeneralizingiFastSmiElements) {
     292           6 :   CcTest::InitializeVM();
     293             :   Isolate* isolate = CcTest::i_isolate();
     294             :   Factory* factory = isolate->factory();
     295           6 :   v8::HandleScope scope(CcTest::isolate());
     296             : 
     297             :   Handle<String> name;
     298             :   Handle<Object> value_smi(Smi::FromInt(42), isolate);
     299             :   Handle<Object> value_string(MakeString("value"));
     300           6 :   Handle<Object> value_double = factory->NewNumber(3.1415);
     301             : 
     302             :   Handle<JSArray> array =
     303           6 :       factory->NewJSArray(ElementsKind::PACKED_SMI_ELEMENTS, 0, 0);
     304             :   Handle<Map> previous_map(array->map());
     305           6 :   CHECK_EQ(PACKED_SMI_ELEMENTS, previous_map->elements_kind());
     306           6 :   CHECK_EQ(0, Smi::ToInt(array->length()));
     307             : 
     308             :   // `array[0] = smi_value` doesn't change the elements_kind
     309             :   name = MakeString("0");
     310             :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
     311           6 :                                                     NONE)
     312          12 :       .Check();
     313             :   // no change in elements_kind => no map transition
     314           6 :   CHECK_EQ(array->map(), *previous_map);
     315           6 :   CHECK_EQ(PACKED_SMI_ELEMENTS, array->map()->elements_kind());
     316           6 :   CHECK_EQ(1, Smi::ToInt(array->length()));
     317             : 
     318             :   // `delete array[0]` does not alter length, but changes the elments_kind
     319             :   name = MakeString("0");
     320          12 :   CHECK(JSReceiver::DeletePropertyOrElement(array, name).FromMaybe(false));
     321           6 :   CHECK_NE(array->map(), *previous_map);
     322           6 :   CHECK_EQ(HOLEY_SMI_ELEMENTS, array->map()->elements_kind());
     323           6 :   CHECK_EQ(1, Smi::ToInt(array->length()));
     324             :   previous_map = handle(array->map());
     325             : 
     326             :   // add a couple of elements again
     327             :   name = MakeString("0");
     328             :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
     329           6 :                                                     NONE)
     330          12 :       .Check();
     331             :   name = MakeString("1");
     332             :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
     333           6 :                                                     NONE)
     334          12 :       .Check();
     335           6 :   CHECK_EQ(array->map(), *previous_map);
     336           6 :   CHECK_EQ(HOLEY_SMI_ELEMENTS, array->map()->elements_kind());
     337           6 :   CHECK_EQ(2, Smi::ToInt(array->length()));
     338             : 
     339             :   // Adding a string to the array changes from FAST_HOLEY_SMI to FAST_HOLEY
     340             :   name = MakeString("0");
     341             :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_string,
     342           6 :                                                     NONE)
     343          12 :       .Check();
     344           6 :   CHECK_NE(array->map(), *previous_map);
     345           6 :   CHECK_EQ(HOLEY_ELEMENTS, array->map()->elements_kind());
     346           6 :   CHECK_EQ(2, Smi::ToInt(array->length()));
     347             :   previous_map = handle(array->map());
     348             : 
     349             :   // We don't transition back to FAST_SMI even if we remove the string
     350             :   name = MakeString("0");
     351             :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
     352           6 :                                                     NONE)
     353          12 :       .Check();
     354           6 :   CHECK_EQ(array->map(), *previous_map);
     355             : 
     356             :   // Adding a double doesn't change the map either
     357             :   name = MakeString("0");
     358             :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_double,
     359           6 :                                                     NONE)
     360          12 :       .Check();
     361           6 :   CHECK_EQ(array->map(), *previous_map);
     362           6 : }
     363             : 
     364             : 
     365       23724 : TEST(JSArrayAddingElementsGeneralizingFastElements) {
     366           6 :   CcTest::InitializeVM();
     367             :   Isolate* isolate = CcTest::i_isolate();
     368             :   Factory* factory = isolate->factory();
     369           6 :   v8::HandleScope scope(CcTest::isolate());
     370             : 
     371             :   Handle<String> name;
     372             :   Handle<Object> value_smi(Smi::FromInt(42), isolate);
     373             :   Handle<Object> value_string(MakeString("value"));
     374             : 
     375             :   Handle<JSArray> array =
     376           6 :       factory->NewJSArray(ElementsKind::PACKED_ELEMENTS, 0, 0);
     377             :   Handle<Map> previous_map(array->map());
     378           6 :   CHECK_EQ(PACKED_ELEMENTS, previous_map->elements_kind());
     379           6 :   CHECK_EQ(0, Smi::ToInt(array->length()));
     380             : 
     381             :   // `array[0] = smi_value` doesn't change the elements_kind
     382             :   name = MakeString("0");
     383             :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
     384           6 :                                                     NONE)
     385          12 :       .Check();
     386             :   // no change in elements_kind => no map transition
     387           6 :   CHECK_EQ(array->map(), *previous_map);
     388           6 :   CHECK_EQ(PACKED_ELEMENTS, array->map()->elements_kind());
     389           6 :   CHECK_EQ(1, Smi::ToInt(array->length()));
     390             : 
     391             :   // `delete array[0]` does not alter length, but changes the elments_kind
     392             :   name = MakeString("0");
     393          12 :   CHECK(JSReceiver::DeletePropertyOrElement(array, name).FromMaybe(false));
     394           6 :   CHECK_NE(array->map(), *previous_map);
     395           6 :   CHECK_EQ(HOLEY_ELEMENTS, array->map()->elements_kind());
     396           6 :   CHECK_EQ(1, Smi::ToInt(array->length()));
     397             :   previous_map = handle(array->map());
     398             : 
     399             :   // add a couple of elements, elements_kind stays HOLEY
     400             :   name = MakeString("0");
     401             :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_string,
     402           6 :                                                     NONE)
     403          12 :       .Check();
     404             :   name = MakeString("1");
     405             :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
     406           6 :                                                     NONE)
     407          12 :       .Check();
     408           6 :   CHECK_EQ(array->map(), *previous_map);
     409           6 :   CHECK_EQ(HOLEY_ELEMENTS, array->map()->elements_kind());
     410           6 :   CHECK_EQ(2, Smi::ToInt(array->length()));
     411           6 : }
     412             : 
     413             : 
     414       23724 : TEST(JSArrayAddingElementsGeneralizingiFastDoubleElements) {
     415           6 :   CcTest::InitializeVM();
     416             :   Isolate* isolate = CcTest::i_isolate();
     417             :   Factory* factory = isolate->factory();
     418           6 :   v8::HandleScope scope(CcTest::isolate());
     419             : 
     420             :   Handle<String> name;
     421             :   Handle<Object> value_smi(Smi::FromInt(42), isolate);
     422             :   Handle<Object> value_string(MakeString("value"));
     423           6 :   Handle<Object> value_double = factory->NewNumber(3.1415);
     424             : 
     425             :   Handle<JSArray> array =
     426           6 :       factory->NewJSArray(ElementsKind::PACKED_SMI_ELEMENTS, 0, 0);
     427             :   Handle<Map> previous_map(array->map());
     428             : 
     429             :   // `array[0] = value_double` changes |elements_kind| to PACKED_DOUBLE_ELEMENTS
     430             :   name = MakeString("0");
     431             :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_double,
     432           6 :                                                     NONE)
     433          12 :       .Check();
     434           6 :   CHECK_NE(array->map(), *previous_map);
     435           6 :   CHECK_EQ(PACKED_DOUBLE_ELEMENTS, array->map()->elements_kind());
     436           6 :   CHECK_EQ(1, Smi::ToInt(array->length()));
     437             :   previous_map = handle(array->map());
     438             : 
     439             :   // `array[1] = value_smi` doesn't alter the |elements_kind|
     440             :   name = MakeString("1");
     441             :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
     442           6 :                                                     NONE)
     443          12 :       .Check();
     444           6 :   CHECK_EQ(array->map(), *previous_map);
     445           6 :   CHECK_EQ(PACKED_DOUBLE_ELEMENTS, array->map()->elements_kind());
     446           6 :   CHECK_EQ(2, Smi::ToInt(array->length()));
     447             : 
     448             :   // `delete array[0]` does not alter length, but changes the elments_kind
     449             :   name = MakeString("0");
     450          12 :   CHECK(JSReceiver::DeletePropertyOrElement(array, name).FromMaybe(false));
     451           6 :   CHECK_NE(array->map(), *previous_map);
     452           6 :   CHECK_EQ(HOLEY_DOUBLE_ELEMENTS, array->map()->elements_kind());
     453           6 :   CHECK_EQ(2, Smi::ToInt(array->length()));
     454             :   previous_map = handle(array->map());
     455             : 
     456             :   // filling the hole `array[0] = value_smi` again doesn't transition back
     457             :   name = MakeString("0");
     458             :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_double,
     459           6 :                                                     NONE)
     460          12 :       .Check();
     461           6 :   CHECK_EQ(array->map(), *previous_map);
     462           6 :   CHECK_EQ(HOLEY_DOUBLE_ELEMENTS, array->map()->elements_kind());
     463           6 :   CHECK_EQ(2, Smi::ToInt(array->length()));
     464             : 
     465             :   // Adding a string to the array changes to elements_kind PACKED_ELEMENTS
     466             :   name = MakeString("1");
     467             :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_string,
     468           6 :                                                     NONE)
     469          12 :       .Check();
     470           6 :   CHECK_NE(array->map(), *previous_map);
     471           6 :   CHECK_EQ(HOLEY_ELEMENTS, array->map()->elements_kind());
     472           6 :   CHECK_EQ(2, Smi::ToInt(array->length()));
     473             :   previous_map = handle(array->map());
     474             : 
     475             :   // Adding a double doesn't change the map
     476             :   name = MakeString("0");
     477             :   JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_double,
     478           6 :                                                     NONE)
     479          12 :       .Check();
     480           6 :   CHECK_EQ(array->map(), *previous_map);
     481           6 : }
     482             : 
     483             : }  // namespace test_elements_kind
     484             : }  // namespace internal
     485       71154 : }  // namespace v8

Generated by: LCOV version 1.10