blob: 8711ffdf3d954f98b98ae1f720e004e6647c2db6 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28// Test dictionary -> double elements -> dictionary elements round trip
29
30// Flags: --allow-natives-syntax --unbox-double-arrays --expose-gc
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000032var large_array_size = 100000;
Ben Murdoch69a99ed2011-11-30 16:03:39 +000033var approx_dict_to_elements_threshold = 70000;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000034
35var name = 0;
36
37function expected_array_value(i) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +000038 if ((i % 50) != 0) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000039 return i;
40 } else {
41 return i + 0.5;
42 }
43}
44
45function force_to_fast_double_array(a) {
46 a[large_array_size - 2] = 1;
47 for (var i= 0; i < approx_dict_to_elements_threshold; ++i ) {
48 a[i] = expected_array_value(i);
49 }
50 assertTrue(%HasFastDoubleElements(a));
51}
52
53function make_object_like_array(size) {
54 obj = new Object();
55 obj.length = size;
56 return obj;
57}
58
59function testOneArrayType(allocator) {
60 var large_array = new allocator(large_array_size);
61 force_to_fast_double_array(large_array);
62 var six = 6;
63
64 for (var i= 0; i < approx_dict_to_elements_threshold; i += 501 ) {
65 assertEquals(expected_array_value(i), large_array[i]);
66 }
67
68 // This function has a constant and won't get inlined.
69 function computed_6() {
70 return six;
71 }
72
73 // Multiple versions of the test function makes sure that IC/Crankshaft state
74 // doesn't get reused.
75 function test_various_loads(a, value_5, value_6, value_7) {
76 assertTrue(%HasFastDoubleElements(a));
77 assertEquals(value_5, a[5]);
78 assertEquals(value_6, a[6]);
79 assertEquals(value_6, a[computed_6()]); // Test non-constant key
80 assertEquals(value_7, a[7]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000081 assertEquals(large_array_size, a.length);
82 assertTrue(%HasFastDoubleElements(a));
83 }
84
85 function test_various_loads2(a, value_5, value_6, value_7) {
86 assertTrue(%HasFastDoubleElements(a));
87 assertEquals(value_5, a[5]);
88 assertEquals(value_6, a[6]);
89 assertEquals(value_6, a[computed_6()]); // Test non-constant key
90 assertEquals(value_7, a[7]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000091 assertEquals(large_array_size, a.length);
92 assertTrue(%HasFastDoubleElements(a));
93 }
94
95 function test_various_loads3(a, value_5, value_6, value_7) {
96 assertTrue(%HasFastDoubleElements(a));
97 assertEquals(value_5, a[5]);
98 assertEquals(value_6, a[6]);
99 assertEquals(value_6, a[computed_6()]); // Test non-constant key
100 assertEquals(value_7, a[7]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000101 assertEquals(large_array_size, a.length);
102 assertTrue(%HasFastDoubleElements(a));
103 }
104
105 function test_various_loads4(a, value_5, value_6, value_7) {
106 assertTrue(%HasFastDoubleElements(a));
107 assertEquals(value_5, a[5]);
108 assertEquals(value_6, a[6]);
109 assertEquals(value_6, a[computed_6()]); // Test non-constant key
110 assertEquals(value_7, a[7]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000111 assertEquals(large_array_size, a.length);
112 assertTrue(%HasFastDoubleElements(a));
113 }
114
115 function test_various_loads5(a, value_5, value_6, value_7) {
116 assertTrue(%HasFastDoubleElements(a));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100117 if (value_5 != undefined) {
118 assertEquals(value_5, a[5]);
119 };
120 if (value_6 != undefined) {
121 assertEquals(value_6, a[6]);
122 assertEquals(value_6, a[computed_6()]); // Test non-constant key
123 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000124 assertEquals(value_7, a[7]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000125 assertEquals(large_array_size, a.length);
126 assertTrue(%HasFastDoubleElements(a));
127 }
128
129 function test_various_loads6(a, value_5, value_6, value_7) {
130 assertTrue(%HasFastDoubleElements(a));
131 assertEquals(value_5, a[5]);
132 assertEquals(value_6, a[6]);
133 assertEquals(value_6, a[computed_6()]); // Test non-constant key
134 assertEquals(value_7, a[7]);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100135 assertEquals(large_array_size, a.length);
136 assertTrue(%HasFastDoubleElements(a));
137 }
138
139 function test_various_loads7(a, value_5, value_6, value_7) {
140 assertTrue(%HasFastDoubleElements(a));
141 assertEquals(value_5, a[5]);
142 assertEquals(value_6, a[6]);
143 assertEquals(value_6, a[computed_6()]); // Test non-constant key
144 assertEquals(value_7, a[7]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000145 assertEquals(large_array_size, a.length);
146 assertTrue(%HasFastDoubleElements(a));
147 }
148
149 function test_various_stores(a, value_5, value_6, value_7) {
150 assertTrue(%HasFastDoubleElements(a));
151 a[5] = value_5;
152 a[computed_6()] = value_6;
153 a[7] = value_7;
154 assertTrue(%HasFastDoubleElements(a));
155 }
156
157 // Test double and integer values
158 test_various_loads(large_array,
159 expected_array_value(5),
160 expected_array_value(6),
161 expected_array_value(7));
162 test_various_loads(large_array,
163 expected_array_value(5),
164 expected_array_value(6),
165 expected_array_value(7));
166 test_various_loads(large_array,
167 expected_array_value(5),
168 expected_array_value(6),
169 expected_array_value(7));
170 %OptimizeFunctionOnNextCall(test_various_loads);
171 test_various_loads(large_array,
172 expected_array_value(5),
173 expected_array_value(6),
174 expected_array_value(7));
175
176 // Test NaN values
177 test_various_stores(large_array, NaN, -NaN, expected_array_value(7));
178
179 test_various_loads2(large_array,
180 NaN,
181 -NaN,
182 expected_array_value(7));
183 test_various_loads2(large_array,
184 NaN,
185 -NaN,
186 expected_array_value(7));
187 test_various_loads2(large_array,
188 NaN,
189 -NaN,
190 expected_array_value(7));
191 %OptimizeFunctionOnNextCall(test_various_loads2);
192 test_various_loads2(large_array,
193 NaN,
194 -NaN,
195 expected_array_value(7));
196
197 // Test Infinity values
198 test_various_stores(large_array,
199 Infinity,
200 -Infinity,
201 expected_array_value(7));
202
203 test_various_loads3(large_array,
204 Infinity,
205 -Infinity,
206 expected_array_value(7));
207 test_various_loads3(large_array,
208 Infinity,
209 -Infinity,
210 expected_array_value(7));
211 test_various_loads3(large_array,
212 Infinity,
213 -Infinity,
214 expected_array_value(7));
215 %OptimizeFunctionOnNextCall(test_various_loads3);
216 test_various_loads3(large_array,
217 Infinity,
218 -Infinity,
219 expected_array_value(7));
220
221 // Test the hole for the default runtime implementation.
222 delete large_array[5];
223 delete large_array[6];
224 test_various_loads4(large_array,
225 undefined,
226 undefined,
227 expected_array_value(7));
228
229 // Test the keyed load IC implementation when the value is the hole.
230 test_various_stores(large_array,
231 expected_array_value(5),
232 expected_array_value(6),
233 expected_array_value(7));
234 test_various_loads5(large_array,
235 expected_array_value(5),
236 expected_array_value(6),
237 expected_array_value(7));
238 test_various_loads5(large_array,
239 expected_array_value(5),
240 expected_array_value(6),
241 expected_array_value(7));
242 delete large_array[5];
243 delete large_array[6];
244 test_various_loads5(large_array,
245 undefined,
246 undefined,
247 expected_array_value(7));
248 test_various_loads5(large_array,
249 undefined,
250 undefined,
251 expected_array_value(7));
252
253 // Make sure Crankshaft code handles the hole correctly (bailout)
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100254 var large_array = new allocator(large_array_size);
255 force_to_fast_double_array(large_array);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000256 test_various_stores(large_array,
257 expected_array_value(5),
258 expected_array_value(6),
259 expected_array_value(7));
260 test_various_loads6(large_array,
261 expected_array_value(5),
262 expected_array_value(6),
263 expected_array_value(7));
264 test_various_loads6(large_array,
265 expected_array_value(5),
266 expected_array_value(6),
267 expected_array_value(7));
268 %OptimizeFunctionOnNextCall(test_various_loads6);
269 test_various_loads6(large_array,
270 expected_array_value(5),
271 expected_array_value(6),
272 expected_array_value(7));
273
274 delete large_array[5];
275 delete large_array[6];
276 test_various_loads6(large_array,
277 undefined,
278 undefined,
279 expected_array_value(7));
280
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100281 %DeoptimizeFunction(test_various_loads6);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000282 %ClearFunctionTypeFeedback(test_various_stores);
283 %ClearFunctionTypeFeedback(test_various_loads7);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100284
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000285 // Test stores for non-NaN.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100286 var large_array = new allocator(large_array_size);
287 force_to_fast_double_array(large_array);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000288 %OptimizeFunctionOnNextCall(test_various_stores);
289 test_various_stores(large_array,
290 expected_array_value(5),
291 expected_array_value(6),
292 expected_array_value(7));
293
294 test_various_stores(large_array,
295 expected_array_value(5),
296 expected_array_value(6),
297 expected_array_value(7));
298
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100299 test_various_loads7(large_array,
300 expected_array_value(5),
301 expected_array_value(6),
302 expected_array_value(7));
303
304 test_various_loads7(large_array,
305 expected_array_value(5),
306 expected_array_value(6),
307 expected_array_value(7));
308
309 %OptimizeFunctionOnNextCall(test_various_loads7);
310
311 test_various_loads7(large_array,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000312 expected_array_value(5),
313 expected_array_value(6),
314 expected_array_value(7));
315
316 // Test NaN behavior for stores.
317 test_various_stores(large_array,
318 NaN,
319 -NaN,
320 expected_array_value(7));
321
322 test_various_stores(large_array,
323 NaN,
324 -NaN,
325 expected_array_value(7));
326
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100327 test_various_loads7(large_array,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000328 NaN,
329 -NaN,
330 expected_array_value(7));
331
332 // Test Infinity behavior for stores.
333 test_various_stores(large_array,
334 Infinity,
335 -Infinity,
336 expected_array_value(7));
337
338 test_various_stores(large_array,
339 Infinity,
340 -Infinity,
341 expected_array_value(7));
342
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100343 test_various_loads7(large_array,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000344 Infinity,
345 -Infinity,
346 expected_array_value(7));
347
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000348 // Make sure that we haven't converted from fast double.
349 assertTrue(%HasFastDoubleElements(large_array));
350}
351
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000352// Force gc here to start with a clean heap if we repeat this test multiple
353// times.
354gc();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000355testOneArrayType(make_object_like_array);
356testOneArrayType(Array);
357
358var large_array = new Array(large_array_size);
359force_to_fast_double_array(large_array);
360assertTrue(%HasFastDoubleElements(large_array));
361
362// Cause the array to grow beyond it's JSArray length. This will double the
363// size of the capacity and force the array into "slow" dictionary case.
364large_array[5] = Infinity;
365large_array[large_array_size+10001] = 50;
366assertTrue(%HasDictionaryElements(large_array));
367assertEquals(50, large_array[large_array_size+10001]);
368assertEquals(large_array_size+10002, large_array.length);
369assertEquals(Infinity, large_array[5]);
370assertEquals(undefined, large_array[large_array_size-1]);
371assertEquals(undefined, large_array[-1]);
372assertEquals(large_array_size+10002, large_array.length);
373
374// Test dictionary -> double elements -> fast elements.
375var large_array2 = new Array(large_array_size);
376force_to_fast_double_array(large_array2);
377delete large_array2[5];
378
379// Convert back to fast elements and make sure the contents of the array are
380// unchanged.
381large_array2[25] = new Object();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000382assertTrue(%HasFastObjectElements(large_array2));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000383for (var i= 0; i < approx_dict_to_elements_threshold; i += 500 ) {
384 if (i != 25 && i != 5) {
385 assertEquals(expected_array_value(i), large_array2[i]);
386 }
387}
388assertEquals(undefined, large_array2[5]);
389assertEquals(undefined, large_array2[large_array_size-1]);
390assertEquals(undefined, large_array2[-1]);
391assertEquals(large_array_size, large_array2.length);
392
393// Make sure it's possible to change the array's length and that array is still
394// intact after the resize.
395var large_array3 = new Array(large_array_size);
396force_to_fast_double_array(large_array3);
397large_array3.length = 60000;
398assertEquals(60000, large_array3.length);
399assertEquals(undefined, large_array3[60000]);
400assertTrue(%HasFastDoubleElements(large_array3));
401assertEquals(expected_array_value(5), large_array3[5]);
402assertEquals(expected_array_value(6), large_array3[6]);
403assertEquals(expected_array_value(7), large_array3[7]);
404assertEquals(expected_array_value(large_array3.length-1),
405 large_array3[large_array3.length-1]);
406assertEquals(undefined, large_array3[large_array_size-1]);
407assertEquals(undefined, large_array3[-1]);
408gc();
409
410for (var i= 0; i < large_array3.length; i += 501 ) {
411 assertEquals(expected_array_value(i), large_array3[i]);
412}
413
414large_array3.length = 25;
415assertEquals(25, large_array3.length);
416assertTrue(%HasFastDoubleElements(large_array3));
417assertEquals(undefined, large_array3[25]);
418assertEquals(expected_array_value(5), large_array3[5]);
419assertEquals(expected_array_value(6), large_array3[6]);
420assertEquals(expected_array_value(7), large_array3[7]);
421assertEquals(expected_array_value(large_array3.length-1),
422 large_array3[large_array3.length-1]);
423assertEquals(undefined, large_array3[large_array_size-1]);
424assertEquals(undefined, large_array3[-1]);
425gc();
426
427for (var i= 0; i < large_array3.length; ++i) {
428 assertEquals(expected_array_value(i), large_array3[i]);
429}
430
431large_array3.length = 100;
432assertEquals(100, large_array3.length);
433large_array3[95] = 95;
434assertTrue(%HasFastDoubleElements(large_array3));
435assertEquals(undefined, large_array3[100]);
436assertEquals(95, large_array3[95]);
437assertEquals(expected_array_value(5), large_array3[5]);
438assertEquals(expected_array_value(6), large_array3[6]);
439assertEquals(expected_array_value(7), large_array3[7]);
440assertEquals(undefined, large_array3[large_array3.length-1]);
441assertEquals(undefined, large_array3[large_array_size-1]);
442assertEquals(undefined, large_array3[-1]);
443gc();
444
445// Test apply on arrays backed by double elements.
446function called_by_apply(arg0, arg1, arg2, arg3, arg4, arg5, arg6) {
447 assertEquals(expected_array_value(0), arg0);
448 assertEquals(NaN, arg1);
449 assertEquals(-NaN, arg2);
450 assertEquals(Infinity, arg3);
451 assertEquals(-Infinity, arg4);
452 assertEquals(expected_array_value(5), arg5);
453}
454
455large_array3[1] = NaN;
456large_array3[2] = -NaN;
457large_array3[3] = Infinity;
458large_array3[4] = -Infinity;
459
460function call_apply() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000461 called_by_apply.apply({}, large_array3);
462}
463
464call_apply();
465call_apply();
466call_apply();
467%OptimizeFunctionOnNextCall(call_apply);
468call_apply();
469call_apply();
470call_apply();
471
472function test_for_in() {
473 // Due to previous tests, keys 0..25 and 95 should be present.
474 next_expected = 0;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000475 for (x in large_array3) {
476 assertTrue(next_expected++ == x);
477 if (next_expected == 25) {
478 next_expected = 95;
479 }
480 }
481 assertTrue(next_expected == 96);
482}
483
484test_for_in();
485test_for_in();
486test_for_in();
487%OptimizeFunctionOnNextCall(test_for_in);
488test_for_in();
489test_for_in();
490test_for_in();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000491
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000492// Test elements getters.
493assertEquals(expected_array_value(10), large_array3[10]);
494assertEquals(expected_array_value(-NaN), large_array3[2]);
495large_array3.__defineGetter__("2", function(){
496 return expected_array_value(10);
497});
498
499function test_getter() {
500 assertEquals(expected_array_value(10), large_array3[10]);
501 assertEquals(expected_array_value(10), large_array3[2]);
502}
503
504test_getter();
505test_getter();
506test_getter();
507%OptimizeFunctionOnNextCall(test_getter);
508test_getter();
509test_getter();
510test_getter();
511
512// Test element setters.
513large_array4 = new Array(large_array_size);
514force_to_fast_double_array(large_array4);
515
516var setter_called = false;
517
518assertEquals(expected_array_value(10), large_array4[10]);
519assertEquals(expected_array_value(2), large_array4[2]);
520large_array4.__defineSetter__("10", function(value){
521 setter_called = true;
522 });
523
524function test_setter() {
525 setter_called = false;
526 large_array4[10] = 119;
527 assertTrue(setter_called);
528 assertEquals(undefined, large_array4[10]);
529 assertEquals(expected_array_value(2), large_array4[2]);
530}
531
532test_setter();
533test_setter();
534test_setter();
535%OptimizeFunctionOnNextCall(test_setter);
536test_setter();
537test_setter();
538test_setter();