Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / v8 / test / mjsunit / allocation-site-info.js
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // 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 // Flags: --allow-natives-syntax --expose-gc
29 // Flags: --noalways-opt
30
31 var elements_kind = {
32   fast_smi_only            :  'fast smi only elements',
33   fast                     :  'fast elements',
34   fast_double              :  'fast double elements',
35   dictionary               :  'dictionary elements',
36   external_byte            :  'external byte elements',
37   external_unsigned_byte   :  'external unsigned byte elements',
38   external_short           :  'external short elements',
39   external_unsigned_short  :  'external unsigned short elements',
40   external_int             :  'external int elements',
41   external_unsigned_int    :  'external unsigned int elements',
42   external_float           :  'external float elements',
43   external_double          :  'external double elements',
44   external_pixel           :  'external pixel elements'
45 }
46
47 function getKind(obj) {
48   if (%HasFastSmiElements(obj)) return elements_kind.fast_smi_only;
49   if (%HasFastObjectElements(obj)) return elements_kind.fast;
50   if (%HasFastDoubleElements(obj)) return elements_kind.fast_double;
51   if (%HasDictionaryElements(obj)) return elements_kind.dictionary;
52 }
53
54 function isHoley(obj) {
55   if (%HasFastHoleyElements(obj)) return true;
56   return false;
57 }
58
59 function assertKind(expected, obj, name_opt) {
60   assertEquals(expected, getKind(obj), name_opt);
61 }
62
63 function assertHoley(obj, name_opt) {
64   assertEquals(true, isHoley(obj), name_opt);
65 }
66
67 function assertNotHoley(obj, name_opt) {
68   assertEquals(false, isHoley(obj), name_opt);
69 }
70
71 obj = [];
72 assertNotHoley(obj);
73 assertKind(elements_kind.fast_smi_only, obj);
74
75 obj = [1, 2, 3];
76 assertNotHoley(obj);
77 assertKind(elements_kind.fast_smi_only, obj);
78
79 obj = new Array();
80 assertNotHoley(obj);
81 assertKind(elements_kind.fast_smi_only, obj);
82
83 obj = new Array(0);
84 assertNotHoley(obj);
85 assertKind(elements_kind.fast_smi_only, obj);
86
87 obj = new Array(2);
88 assertHoley(obj);
89 assertKind(elements_kind.fast_smi_only, obj);
90
91 obj = new Array(1,2,3);
92 assertNotHoley(obj);
93 assertKind(elements_kind.fast_smi_only, obj);
94
95 obj = new Array(1, "hi", 2, undefined);
96 assertNotHoley(obj);
97 assertKind(elements_kind.fast, obj);
98
99 function fastliteralcase(literal, value) {
100   literal[0] = value;
101   return literal;
102 }
103
104 function get_standard_literal() {
105   var literal = [1, 2, 3];
106   return literal;
107 }
108
109 // Case: [1,2,3] as allocation site
110 obj = fastliteralcase(get_standard_literal(), 1);
111 assertKind(elements_kind.fast_smi_only, obj);
112 obj = fastliteralcase(get_standard_literal(), 1.5);
113 assertKind(elements_kind.fast_double, obj);
114 obj = fastliteralcase(get_standard_literal(), 2);
115 assertKind(elements_kind.fast_double, obj);
116
117 // The test below is in a loop because arrays that live
118 // at global scope without the chance of being recreated
119 // don't have allocation site information attached.
120 for (i = 0; i < 2; i++) {
121   obj = fastliteralcase([5, 3, 2], 1.5);
122   assertKind(elements_kind.fast_double, obj);
123   obj = fastliteralcase([3, 6, 2], 1.5);
124   assertKind(elements_kind.fast_double, obj);
125
126   // Note: thanks to pessimistic transition store stubs, we'll attempt
127   // to transition to the most general elements kind seen at a particular
128   // store site. So, the elements kind will be double.
129   obj = fastliteralcase([2, 6, 3], 2);
130   assertKind(elements_kind.fast_double, obj);
131 }
132
133 // Verify that we will not pretransition the double->fast path.
134 obj = fastliteralcase(get_standard_literal(), "elliot");
135 assertKind(elements_kind.fast, obj);
136 obj = fastliteralcase(get_standard_literal(), 3);
137 assertKind(elements_kind.fast, obj);
138
139 // Make sure this works in crankshafted code too.
140   %OptimizeFunctionOnNextCall(get_standard_literal);
141 get_standard_literal();
142 obj = get_standard_literal();
143 assertKind(elements_kind.fast, obj);
144
145 function fastliteralcase_smifast(value) {
146   var literal = [1, 2, 3, 4];
147   literal[0] = value;
148   return literal;
149 }
150
151 obj = fastliteralcase_smifast(1);
152 assertKind(elements_kind.fast_smi_only, obj);
153 obj = fastliteralcase_smifast("carter");
154 assertKind(elements_kind.fast, obj);
155 obj = fastliteralcase_smifast(2);
156 assertKind(elements_kind.fast, obj);
157
158 // Case: make sure transitions from packed to holey are tracked
159 function fastliteralcase_smiholey(index, value) {
160   var literal = [1, 2, 3, 4];
161   literal[index] = value;
162   return literal;
163 }
164
165 obj = fastliteralcase_smiholey(5, 1);
166 assertKind(elements_kind.fast_smi_only, obj);
167 assertHoley(obj);
168 obj = fastliteralcase_smiholey(0, 1);
169 assertKind(elements_kind.fast_smi_only, obj);
170 assertHoley(obj);
171
172 function newarraycase_smidouble(value) {
173   var a = new Array();
174   a[0] = value;
175   return a;
176 }
177
178 // Case: new Array() as allocation site, smi->double
179 obj = newarraycase_smidouble(1);
180 assertKind(elements_kind.fast_smi_only, obj);
181 obj = newarraycase_smidouble(1.5);
182 assertKind(elements_kind.fast_double, obj);
183 obj = newarraycase_smidouble(2);
184 assertKind(elements_kind.fast_double, obj);
185
186 function newarraycase_smiobj(value) {
187   var a = new Array();
188   a[0] = value;
189   return a;
190 }
191
192 // Case: new Array() as allocation site, smi->fast
193 obj = newarraycase_smiobj(1);
194 assertKind(elements_kind.fast_smi_only, obj);
195 obj = newarraycase_smiobj("gloria");
196 assertKind(elements_kind.fast, obj);
197 obj = newarraycase_smiobj(2);
198 assertKind(elements_kind.fast, obj);
199
200 function newarraycase_length_smidouble(value) {
201   var a = new Array(3);
202   a[0] = value;
203   return a;
204 }
205
206 // Case: new Array(length) as allocation site
207 obj = newarraycase_length_smidouble(1);
208 assertKind(elements_kind.fast_smi_only, obj);
209 obj = newarraycase_length_smidouble(1.5);
210 assertKind(elements_kind.fast_double, obj);
211 obj = newarraycase_length_smidouble(2);
212 assertKind(elements_kind.fast_double, obj);
213
214 // Try to continue the transition to fast object.
215 // TODO(mvstanton): re-enable commented out code when
216 // FLAG_pretenuring_call_new is turned on in the build.
217 obj = newarraycase_length_smidouble("coates");
218 assertKind(elements_kind.fast, obj);
219 obj = newarraycase_length_smidouble(2);
220 // assertKind(elements_kind.fast, obj);
221
222 function newarraycase_length_smiobj(value) {
223   var a = new Array(3);
224   a[0] = value;
225   return a;
226 }
227
228 // Case: new Array(<length>) as allocation site, smi->fast
229 obj = newarraycase_length_smiobj(1);
230 assertKind(elements_kind.fast_smi_only, obj);
231 obj = newarraycase_length_smiobj("gloria");
232 assertKind(elements_kind.fast, obj);
233 obj = newarraycase_length_smiobj(2);
234 assertKind(elements_kind.fast, obj);
235
236 function newarraycase_list_smidouble(value) {
237   var a = new Array(1, 2, 3);
238   a[0] = value;
239   return a;
240 }
241
242 obj = newarraycase_list_smidouble(1);
243 assertKind(elements_kind.fast_smi_only, obj);
244 obj = newarraycase_list_smidouble(1.5);
245 assertKind(elements_kind.fast_double, obj);
246 obj = newarraycase_list_smidouble(2);
247 assertKind(elements_kind.fast_double, obj);
248
249 function newarraycase_list_smiobj(value) {
250   var a = new Array(4, 5, 6);
251   a[0] = value;
252   return a;
253 }
254
255 obj = newarraycase_list_smiobj(1);
256 assertKind(elements_kind.fast_smi_only, obj);
257 obj = newarraycase_list_smiobj("coates");
258 assertKind(elements_kind.fast, obj);
259 obj = newarraycase_list_smiobj(2);
260 assertKind(elements_kind.fast, obj);
261
262 // Case: array constructor calls with out of date feedback.
263 // The boilerplate should incorporate all feedback, but the input array
264 // should be minimally transitioned based on immediate need.
265 (function() {
266   function foo(i) {
267     // We have two cases, one for literals one for constructed arrays.
268     var a = (i == 0)
269       ? [1, 2, 3]
270       : new Array(1, 2, 3);
271     return a;
272   }
273
274   for (i = 0; i < 2; i++) {
275     a = foo(i);
276     b = foo(i);
277     b[5] = 1;  // boilerplate goes holey
278     assertHoley(foo(i));
279     a[0] = 3.5;  // boilerplate goes holey double
280     assertKind(elements_kind.fast_double, a);
281     assertNotHoley(a);
282     c = foo(i);
283     assertKind(elements_kind.fast_double, c);
284     assertHoley(c);
285   }
286 })();
287
288 function newarraycase_onearg(len, value) {
289   var a = new Array(len);
290   a[0] = value;
291   return a;
292 }
293
294 obj = newarraycase_onearg(5, 3.5);
295 assertKind(elements_kind.fast_double, obj);
296 obj = newarraycase_onearg(10, 5);
297 assertKind(elements_kind.fast_double, obj);
298 obj = newarraycase_onearg(0, 5);
299 assertKind(elements_kind.fast_double, obj);
300
301 // Verify that cross context calls work
302 var realmA = Realm.current();
303 var realmB = Realm.create();
304 assertEquals(0, realmA);
305 assertEquals(1, realmB);
306
307 function instanceof_check(type) {
308   assertTrue(new type() instanceof type);
309   assertTrue(new type(5) instanceof type);
310   assertTrue(new type(1,2,3) instanceof type);
311 }
312
313 function instanceof_check2(type) {
314   assertTrue(new type() instanceof type);
315   assertTrue(new type(5) instanceof type);
316   assertTrue(new type(1,2,3) instanceof type);
317 }
318
319 var realmBArray = Realm.eval(realmB, "Array");
320 instanceof_check(Array);
321 instanceof_check(realmBArray);
322
323 // instanceof_check2 is here because the call site goes through a state.
324 // Since instanceof_check(Array) was first called with the current context
325 // Array function, it went from (uninit->Array) then (Array->megamorphic).
326 // We'll get a different state traversal if we start with realmBArray.
327 // It'll go (uninit->realmBArray) then (realmBArray->megamorphic). Recognize
328 // that state "Array" implies an AllocationSite is present, and code is
329 // configured to use it.
330 instanceof_check2(realmBArray);
331 instanceof_check2(Array);
332
333   %OptimizeFunctionOnNextCall(instanceof_check);
334
335 // No de-opt will occur because HCallNewArray wasn't selected, on account of
336 // the call site not being monomorphic to Array.
337 instanceof_check(Array);
338 assertOptimized(instanceof_check);
339 instanceof_check(realmBArray);
340 assertOptimized(instanceof_check);
341
342 // Try to optimize again, but first clear all type feedback, and allow it
343 // to be monomorphic on first call. Only after crankshafting do we introduce
344 // realmBArray. This should deopt the method.
345   %DeoptimizeFunction(instanceof_check);
346   %ClearFunctionTypeFeedback(instanceof_check);
347 instanceof_check(Array);
348 instanceof_check(Array);
349   %OptimizeFunctionOnNextCall(instanceof_check);
350 instanceof_check(Array);
351 assertOptimized(instanceof_check);
352
353 instanceof_check(realmBArray);
354 assertUnoptimized(instanceof_check);
355
356 // Case: make sure nested arrays benefit from allocation site feedback as
357 // well.
358 (function() {
359   // Make sure we handle nested arrays
360   function get_nested_literal() {
361     var literal = [[1,2,3,4], [2], [3]];
362     return literal;
363   }
364
365   obj = get_nested_literal();
366   assertKind(elements_kind.fast, obj);
367   obj[0][0] = 3.5;
368   obj[2][0] = "hello";
369   obj = get_nested_literal();
370   assertKind(elements_kind.fast_double, obj[0]);
371   assertKind(elements_kind.fast_smi_only, obj[1]);
372   assertKind(elements_kind.fast, obj[2]);
373
374   // A more complex nested literal case.
375   function get_deep_nested_literal() {
376     var literal = [[1], [[2], "hello"], 3, [4]];
377     return literal;
378   }
379
380   obj = get_deep_nested_literal();
381   assertKind(elements_kind.fast_smi_only, obj[1][0]);
382   obj[0][0] = 3.5;
383   obj[1][0][0] = "goodbye";
384   assertKind(elements_kind.fast_double, obj[0]);
385   assertKind(elements_kind.fast, obj[1][0]);
386
387   obj = get_deep_nested_literal();
388   assertKind(elements_kind.fast_double, obj[0]);
389   assertKind(elements_kind.fast, obj[1][0]);
390 })();
391
392 // Perform a gc because without it the test below can experience an
393 // allocation failure at an inconvenient point. Allocation mementos get
394 // cleared on gc, and they can't deliver elements kind feedback when that
395 // happens.
396 gc();
397
398 // Make sure object literals with array fields benefit from the type feedback
399 // that allocation mementos provide.
400 (function() {
401   // A literal in an object
402   function get_object_literal() {
403     var literal = {
404       array: [1,2,3],
405       data: 3.5
406     };
407     return literal;
408   }
409
410   obj = get_object_literal();
411   assertKind(elements_kind.fast_smi_only, obj.array);
412   obj.array[1] = 3.5;
413   assertKind(elements_kind.fast_double, obj.array);
414   obj = get_object_literal();
415   assertKind(elements_kind.fast_double, obj.array);
416
417   function get_nested_object_literal() {
418     var literal = {
419       array: [[1],[2],[3]],
420       data: 3.5
421     };
422     return literal;
423   }
424
425   obj = get_nested_object_literal();
426   assertKind(elements_kind.fast, obj.array);
427   assertKind(elements_kind.fast_smi_only, obj.array[1]);
428   obj.array[1][0] = 3.5;
429   assertKind(elements_kind.fast_double, obj.array[1]);
430   obj = get_nested_object_literal();
431   assertKind(elements_kind.fast_double, obj.array[1]);
432
433     %OptimizeFunctionOnNextCall(get_nested_object_literal);
434   get_nested_object_literal();
435   obj = get_nested_object_literal();
436   assertKind(elements_kind.fast_double, obj.array[1]);
437
438   // Make sure we handle nested arrays
439   function get_nested_literal() {
440     var literal = [[1,2,3,4], [2], [3]];
441     return literal;
442   }
443
444   obj = get_nested_literal();
445   assertKind(elements_kind.fast, obj);
446   obj[0][0] = 3.5;
447   obj[2][0] = "hello";
448   obj = get_nested_literal();
449   assertKind(elements_kind.fast_double, obj[0]);
450   assertKind(elements_kind.fast_smi_only, obj[1]);
451   assertKind(elements_kind.fast, obj[2]);
452
453   // A more complex nested literal case.
454   function get_deep_nested_literal() {
455     var literal = [[1], [[2], "hello"], 3, [4]];
456     return literal;
457   }
458
459   obj = get_deep_nested_literal();
460   assertKind(elements_kind.fast_smi_only, obj[1][0]);
461   obj[0][0] = 3.5;
462   obj[1][0][0] = "goodbye";
463   assertKind(elements_kind.fast_double, obj[0]);
464   assertKind(elements_kind.fast, obj[1][0]);
465
466   obj = get_deep_nested_literal();
467   assertKind(elements_kind.fast_double, obj[0]);
468   assertKind(elements_kind.fast, obj[1][0]);
469 })();