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