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
|