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