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 1060 : 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 : 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 26644 : 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 26644 : TEST(JSObjectAddingProperties) {
75 5 : CcTest::InitializeVM();
76 : Isolate* isolate = CcTest::i_isolate();
77 : Factory* factory = isolate->factory();
78 10 : 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 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
96 : .Check();
97 5 : 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 26644 : TEST(JSObjectInObjectAddingProperties) {
105 5 : CcTest::InitializeVM();
106 : Isolate* isolate = CcTest::i_isolate();
107 : Factory* factory = isolate->factory();
108 10 : 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 : // (we always reserve 8 inobject properties slack on top).
117 : function->shared()->set_expected_nof_properties(nof_inobject_properties - 8);
118 : Handle<Object> value(Smi::FromInt(42), isolate);
119 :
120 5 : Handle<JSObject> object = factory->NewJSObject(function);
121 : Handle<Map> previous_map(object->map(), isolate);
122 5 : CHECK_EQ(HOLEY_ELEMENTS, previous_map->elements_kind());
123 5 : CHECK(EQUALS(isolate, object->property_array(), empty_property_array));
124 5 : CHECK(EQUALS(isolate, object->elements(), empty_fixed_array));
125 :
126 : // we have reserved space for in-object properties, hence adding up to
127 : // |nof_inobject_properties| will not create a property store
128 105 : for (int i = 0; i < nof_inobject_properties; i++) {
129 50 : Handle<String> name = MakeName("property", i);
130 100 : JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
131 : .Check();
132 : }
133 5 : CHECK_NE(object->map(), *previous_map);
134 5 : CHECK_EQ(HOLEY_ELEMENTS, object->map()->elements_kind());
135 5 : CHECK(EQUALS(isolate, object->property_array(), empty_property_array));
136 5 : CHECK(EQUALS(isolate, object->elements(), empty_fixed_array));
137 :
138 : // adding one more property will not fit in the in-object properties, thus
139 : // creating a property store
140 : int index = nof_inobject_properties + 1;
141 5 : Handle<String> name = MakeName("property", index);
142 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
143 : .Check();
144 5 : CHECK_NE(object->map(), *previous_map);
145 5 : CHECK_EQ(HOLEY_ELEMENTS, object->map()->elements_kind());
146 : // there must be at least 1 element in the properies store
147 10 : CHECK_LE(1, object->property_array()->length());
148 5 : CHECK(EQUALS(isolate, object->elements(), empty_fixed_array));
149 5 : }
150 :
151 :
152 26644 : TEST(JSObjectAddingElements) {
153 5 : CcTest::InitializeVM();
154 : Isolate* isolate = CcTest::i_isolate();
155 : Factory* factory = isolate->factory();
156 10 : v8::HandleScope scope(CcTest::isolate());
157 :
158 : Handle<String> name;
159 5 : Handle<FixedArray> empty_fixed_array(factory->empty_fixed_array());
160 5 : Handle<PropertyArray> empty_property_array(factory->empty_property_array());
161 : Handle<JSFunction> function =
162 5 : factory->NewFunctionForTest(factory->empty_string());
163 : Handle<Object> value(Smi::FromInt(42), isolate);
164 :
165 5 : Handle<JSObject> object = factory->NewJSObject(function);
166 : Handle<Map> previous_map(object->map(), isolate);
167 5 : CHECK_EQ(HOLEY_ELEMENTS, previous_map->elements_kind());
168 5 : CHECK(EQUALS(isolate, object->property_array(), empty_property_array));
169 5 : CHECK(EQUALS(isolate, object->elements(), empty_fixed_array));
170 :
171 : // Adding an indexed element initializes the elements array
172 : name = MakeString("0");
173 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
174 : .Check();
175 : // no change in elements_kind => no map transition
176 5 : CHECK_EQ(object->map(), *previous_map);
177 5 : CHECK_EQ(HOLEY_ELEMENTS, object->map()->elements_kind());
178 5 : CHECK(EQUALS(isolate, object->property_array(), empty_property_array));
179 5 : CHECK_LE(1, object->elements()->length());
180 :
181 : // Adding more consecutive elements without a change in the backing store
182 : int non_dict_backing_store_limit = 100;
183 995 : for (int i = 1; i < non_dict_backing_store_limit; i++) {
184 495 : name = MakeName("", i);
185 990 : JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
186 : .Check();
187 : }
188 : // no change in elements_kind => no map transition
189 5 : CHECK_EQ(object->map(), *previous_map);
190 5 : CHECK_EQ(HOLEY_ELEMENTS, object->map()->elements_kind());
191 5 : CHECK(EQUALS(isolate, object->property_array(), empty_property_array));
192 5 : CHECK_LE(non_dict_backing_store_limit, object->elements()->length());
193 :
194 : // Adding an element at an very large index causes a change to
195 : // DICTIONARY_ELEMENTS
196 : name = MakeString("100000000");
197 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
198 : .Check();
199 : // change in elements_kind => map transition
200 5 : CHECK_NE(object->map(), *previous_map);
201 5 : CHECK_EQ(DICTIONARY_ELEMENTS, object->map()->elements_kind());
202 5 : CHECK(EQUALS(isolate, object->property_array(), empty_property_array));
203 5 : CHECK_LE(non_dict_backing_store_limit, object->elements()->length());
204 5 : }
205 :
206 :
207 26644 : TEST(JSArrayAddingProperties) {
208 5 : CcTest::InitializeVM();
209 : Isolate* isolate = CcTest::i_isolate();
210 : Factory* factory = isolate->factory();
211 10 : v8::HandleScope scope(CcTest::isolate());
212 :
213 5 : Handle<FixedArray> empty_fixed_array(factory->empty_fixed_array());
214 5 : Handle<PropertyArray> empty_property_array(factory->empty_property_array());
215 : Handle<Object> value(Smi::FromInt(42), isolate);
216 :
217 : Handle<JSArray> array =
218 5 : factory->NewJSArray(ElementsKind::PACKED_SMI_ELEMENTS, 0, 0);
219 : Handle<Map> previous_map(array->map(), isolate);
220 5 : CHECK_EQ(PACKED_SMI_ELEMENTS, previous_map->elements_kind());
221 5 : CHECK(EQUALS(isolate, array->property_array(), empty_property_array));
222 5 : CHECK(EQUALS(isolate, array->elements(), empty_fixed_array));
223 5 : CHECK_EQ(0, Smi::ToInt(array->length()));
224 :
225 : // for the default constructor function no in-object properties are reserved
226 : // hence adding a single property will initialize the property-array
227 5 : Handle<String> name = MakeName("property", 0);
228 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value, NONE)
229 : .Check();
230 : // No change in elements_kind but added property => new map
231 5 : CHECK_NE(array->map(), *previous_map);
232 5 : CHECK_EQ(PACKED_SMI_ELEMENTS, array->map()->elements_kind());
233 10 : CHECK_LE(1, array->property_array()->length());
234 5 : CHECK(EQUALS(isolate, array->elements(), empty_fixed_array));
235 5 : CHECK_EQ(0, Smi::ToInt(array->length()));
236 5 : }
237 :
238 :
239 26644 : TEST(JSArrayAddingElements) {
240 5 : CcTest::InitializeVM();
241 : Isolate* isolate = CcTest::i_isolate();
242 : Factory* factory = isolate->factory();
243 10 : v8::HandleScope scope(CcTest::isolate());
244 :
245 : Handle<String> name;
246 5 : Handle<FixedArray> empty_fixed_array(factory->empty_fixed_array());
247 5 : Handle<PropertyArray> empty_property_array(factory->empty_property_array());
248 : Handle<Object> value(Smi::FromInt(42), isolate);
249 :
250 : Handle<JSArray> array =
251 5 : factory->NewJSArray(ElementsKind::PACKED_SMI_ELEMENTS, 0, 0);
252 : Handle<Map> previous_map(array->map(), isolate);
253 5 : CHECK_EQ(PACKED_SMI_ELEMENTS, previous_map->elements_kind());
254 5 : CHECK(EQUALS(isolate, array->property_array(), empty_property_array));
255 5 : CHECK(EQUALS(isolate, array->elements(), empty_fixed_array));
256 5 : CHECK_EQ(0, Smi::ToInt(array->length()));
257 :
258 : // Adding an indexed element initializes the elements array
259 : name = MakeString("0");
260 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value, NONE)
261 : .Check();
262 : // no change in elements_kind => no map transition
263 5 : CHECK_EQ(array->map(), *previous_map);
264 5 : CHECK_EQ(PACKED_SMI_ELEMENTS, array->map()->elements_kind());
265 5 : CHECK(EQUALS(isolate, array->property_array(), empty_property_array));
266 5 : CHECK_LE(1, array->elements()->length());
267 5 : CHECK_EQ(1, Smi::ToInt(array->length()));
268 :
269 : // Adding more consecutive elements without a change in the backing store
270 : int non_dict_backing_store_limit = 100;
271 995 : for (int i = 1; i < non_dict_backing_store_limit; i++) {
272 495 : name = MakeName("", i);
273 990 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value, NONE)
274 : .Check();
275 : }
276 : // no change in elements_kind => no map transition
277 5 : CHECK_EQ(array->map(), *previous_map);
278 5 : CHECK_EQ(PACKED_SMI_ELEMENTS, array->map()->elements_kind());
279 5 : CHECK(EQUALS(isolate, array->property_array(), empty_property_array));
280 5 : CHECK_LE(non_dict_backing_store_limit, array->elements()->length());
281 5 : CHECK_EQ(non_dict_backing_store_limit, Smi::ToInt(array->length()));
282 :
283 : // Adding an element at an very large index causes a change to
284 : // DICTIONARY_ELEMENTS
285 : int index = 100000000;
286 5 : name = MakeName("", index);
287 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value, NONE)
288 : .Check();
289 : // change in elements_kind => map transition
290 5 : CHECK_NE(array->map(), *previous_map);
291 5 : CHECK_EQ(DICTIONARY_ELEMENTS, array->map()->elements_kind());
292 5 : CHECK(EQUALS(isolate, array->property_array(), empty_property_array));
293 5 : CHECK_LE(non_dict_backing_store_limit, array->elements()->length());
294 5 : CHECK_LE(array->elements()->length(), index);
295 5 : CHECK_EQ(index + 1, Smi::ToInt(array->length()));
296 5 : }
297 :
298 :
299 26644 : TEST(JSArrayAddingElementsGeneralizingiFastSmiElements) {
300 5 : CcTest::InitializeVM();
301 : Isolate* isolate = CcTest::i_isolate();
302 : Factory* factory = isolate->factory();
303 10 : v8::HandleScope scope(CcTest::isolate());
304 :
305 : Handle<String> name;
306 : Handle<Object> value_smi(Smi::FromInt(42), isolate);
307 : Handle<Object> value_string(MakeString("value"));
308 5 : Handle<Object> value_double = factory->NewNumber(3.1415);
309 :
310 : Handle<JSArray> array =
311 5 : factory->NewJSArray(ElementsKind::PACKED_SMI_ELEMENTS, 0, 0);
312 : Handle<Map> previous_map(array->map(), isolate);
313 5 : CHECK_EQ(PACKED_SMI_ELEMENTS, previous_map->elements_kind());
314 5 : CHECK_EQ(0, Smi::ToInt(array->length()));
315 :
316 : // `array[0] = smi_value` doesn't change the elements_kind
317 : name = MakeString("0");
318 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
319 5 : NONE)
320 : .Check();
321 : // no change in elements_kind => no map transition
322 5 : CHECK_EQ(array->map(), *previous_map);
323 5 : CHECK_EQ(PACKED_SMI_ELEMENTS, array->map()->elements_kind());
324 5 : CHECK_EQ(1, Smi::ToInt(array->length()));
325 :
326 : // `delete array[0]` does not alter length, but changes the elments_kind
327 : name = MakeString("0");
328 10 : CHECK(JSReceiver::DeletePropertyOrElement(array, name).FromMaybe(false));
329 5 : CHECK_NE(array->map(), *previous_map);
330 5 : CHECK_EQ(HOLEY_SMI_ELEMENTS, array->map()->elements_kind());
331 5 : CHECK_EQ(1, Smi::ToInt(array->length()));
332 : previous_map = handle(array->map(), isolate);
333 :
334 : // add a couple of elements again
335 : name = MakeString("0");
336 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
337 5 : NONE)
338 : .Check();
339 : name = MakeString("1");
340 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
341 5 : NONE)
342 : .Check();
343 5 : CHECK_EQ(array->map(), *previous_map);
344 5 : CHECK_EQ(HOLEY_SMI_ELEMENTS, array->map()->elements_kind());
345 5 : CHECK_EQ(2, Smi::ToInt(array->length()));
346 :
347 : // Adding a string to the array changes from FAST_HOLEY_SMI to FAST_HOLEY
348 : name = MakeString("0");
349 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_string,
350 5 : NONE)
351 : .Check();
352 5 : CHECK_NE(array->map(), *previous_map);
353 5 : CHECK_EQ(HOLEY_ELEMENTS, array->map()->elements_kind());
354 5 : CHECK_EQ(2, Smi::ToInt(array->length()));
355 : previous_map = handle(array->map(), isolate);
356 :
357 : // We don't transition back to FAST_SMI even if we remove the string
358 : name = MakeString("0");
359 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
360 5 : NONE)
361 : .Check();
362 5 : CHECK_EQ(array->map(), *previous_map);
363 :
364 : // Adding a double doesn't change the map either
365 : name = MakeString("0");
366 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_double,
367 5 : NONE)
368 : .Check();
369 5 : CHECK_EQ(array->map(), *previous_map);
370 5 : }
371 :
372 :
373 26644 : TEST(JSArrayAddingElementsGeneralizingFastElements) {
374 5 : CcTest::InitializeVM();
375 : Isolate* isolate = CcTest::i_isolate();
376 : Factory* factory = isolate->factory();
377 10 : v8::HandleScope scope(CcTest::isolate());
378 :
379 : Handle<String> name;
380 : Handle<Object> value_smi(Smi::FromInt(42), isolate);
381 : Handle<Object> value_string(MakeString("value"));
382 :
383 : Handle<JSArray> array =
384 5 : factory->NewJSArray(ElementsKind::PACKED_ELEMENTS, 0, 0);
385 : Handle<Map> previous_map(array->map(), isolate);
386 5 : CHECK_EQ(PACKED_ELEMENTS, previous_map->elements_kind());
387 5 : CHECK_EQ(0, Smi::ToInt(array->length()));
388 :
389 : // `array[0] = smi_value` doesn't change the elements_kind
390 : name = MakeString("0");
391 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
392 5 : NONE)
393 : .Check();
394 : // no change in elements_kind => no map transition
395 5 : CHECK_EQ(array->map(), *previous_map);
396 5 : CHECK_EQ(PACKED_ELEMENTS, array->map()->elements_kind());
397 5 : CHECK_EQ(1, Smi::ToInt(array->length()));
398 :
399 : // `delete array[0]` does not alter length, but changes the elments_kind
400 : name = MakeString("0");
401 10 : CHECK(JSReceiver::DeletePropertyOrElement(array, name).FromMaybe(false));
402 5 : CHECK_NE(array->map(), *previous_map);
403 5 : CHECK_EQ(HOLEY_ELEMENTS, array->map()->elements_kind());
404 5 : CHECK_EQ(1, Smi::ToInt(array->length()));
405 : previous_map = handle(array->map(), isolate);
406 :
407 : // add a couple of elements, elements_kind stays HOLEY
408 : name = MakeString("0");
409 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_string,
410 5 : NONE)
411 : .Check();
412 : name = MakeString("1");
413 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
414 5 : NONE)
415 : .Check();
416 5 : CHECK_EQ(array->map(), *previous_map);
417 5 : CHECK_EQ(HOLEY_ELEMENTS, array->map()->elements_kind());
418 5 : CHECK_EQ(2, Smi::ToInt(array->length()));
419 5 : }
420 :
421 :
422 26644 : TEST(JSArrayAddingElementsGeneralizingiFastDoubleElements) {
423 5 : CcTest::InitializeVM();
424 : Isolate* isolate = CcTest::i_isolate();
425 : Factory* factory = isolate->factory();
426 10 : v8::HandleScope scope(CcTest::isolate());
427 :
428 : Handle<String> name;
429 : Handle<Object> value_smi(Smi::FromInt(42), isolate);
430 : Handle<Object> value_string(MakeString("value"));
431 5 : Handle<Object> value_double = factory->NewNumber(3.1415);
432 :
433 : Handle<JSArray> array =
434 5 : factory->NewJSArray(ElementsKind::PACKED_SMI_ELEMENTS, 0, 0);
435 : Handle<Map> previous_map(array->map(), isolate);
436 :
437 : // `array[0] = value_double` changes |elements_kind| to PACKED_DOUBLE_ELEMENTS
438 : name = MakeString("0");
439 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_double,
440 5 : NONE)
441 : .Check();
442 5 : CHECK_NE(array->map(), *previous_map);
443 5 : CHECK_EQ(PACKED_DOUBLE_ELEMENTS, array->map()->elements_kind());
444 5 : CHECK_EQ(1, Smi::ToInt(array->length()));
445 : previous_map = handle(array->map(), isolate);
446 :
447 : // `array[1] = value_smi` doesn't alter the |elements_kind|
448 : name = MakeString("1");
449 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
450 5 : NONE)
451 : .Check();
452 5 : CHECK_EQ(array->map(), *previous_map);
453 5 : CHECK_EQ(PACKED_DOUBLE_ELEMENTS, array->map()->elements_kind());
454 5 : CHECK_EQ(2, Smi::ToInt(array->length()));
455 :
456 : // `delete array[0]` does not alter length, but changes the elments_kind
457 : name = MakeString("0");
458 10 : CHECK(JSReceiver::DeletePropertyOrElement(array, name).FromMaybe(false));
459 5 : CHECK_NE(array->map(), *previous_map);
460 5 : CHECK_EQ(HOLEY_DOUBLE_ELEMENTS, array->map()->elements_kind());
461 5 : CHECK_EQ(2, Smi::ToInt(array->length()));
462 : previous_map = handle(array->map(), isolate);
463 :
464 : // filling the hole `array[0] = value_smi` again doesn't transition back
465 : name = MakeString("0");
466 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_double,
467 5 : NONE)
468 : .Check();
469 5 : CHECK_EQ(array->map(), *previous_map);
470 5 : CHECK_EQ(HOLEY_DOUBLE_ELEMENTS, array->map()->elements_kind());
471 5 : CHECK_EQ(2, Smi::ToInt(array->length()));
472 :
473 : // Adding a string to the array changes to elements_kind PACKED_ELEMENTS
474 : name = MakeString("1");
475 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_string,
476 5 : NONE)
477 : .Check();
478 5 : CHECK_NE(array->map(), *previous_map);
479 5 : CHECK_EQ(HOLEY_ELEMENTS, array->map()->elements_kind());
480 5 : CHECK_EQ(2, Smi::ToInt(array->length()));
481 : previous_map = handle(array->map(), isolate);
482 :
483 : // Adding a double doesn't change the map
484 : name = MakeString("0");
485 10 : JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_double,
486 5 : NONE)
487 : .Check();
488 5 : CHECK_EQ(array->map(), *previous_map);
489 5 : }
490 :
491 : } // namespace test_elements_kind
492 : } // namespace internal
493 79917 : } // namespace v8
|