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

Generated by: LCOV version 1.10