Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / v8 / test / mjsunit / array-constructor-feedback.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 --smi-only-arrays --expose-gc
29 // Flags: --noalways-opt
30
31 // Test element kind of objects.
32 // Since --smi-only-arrays affects builtins, its default setting at compile
33 // time sticks if built with snapshot.  If --smi-only-arrays is deactivated
34 // by default, only a no-snapshot build actually has smi-only arrays enabled
35 // in this test case.  Depending on whether smi-only arrays are actually
36 // enabled, this test takes the appropriate code path to check smi-only arrays.
37
38 // support_smi_only_arrays = %HasFastSmiElements(new Array(1,2,3,4,5,6,7,8));
39 support_smi_only_arrays = true;
40
41 if (support_smi_only_arrays) {
42   print("Tests include smi-only arrays.");
43 } else {
44   print("Tests do NOT include smi-only arrays.");
45 }
46
47 var elements_kind = {
48   fast_smi_only            :  'fast smi only elements',
49   fast                     :  'fast elements',
50   fast_double              :  'fast double elements',
51   dictionary               :  'dictionary elements',
52   external_byte            :  'external byte elements',
53   external_unsigned_byte   :  'external unsigned byte elements',
54   external_short           :  'external short elements',
55   external_unsigned_short  :  'external unsigned short elements',
56   external_int             :  'external int elements',
57   external_unsigned_int    :  'external unsigned int elements',
58   external_float           :  'external float elements',
59   external_double          :  'external double elements',
60   external_pixel           :  'external pixel elements'
61 }
62
63 function getKind(obj) {
64   if (%HasFastSmiElements(obj)) return elements_kind.fast_smi_only;
65   if (%HasFastObjectElements(obj)) return elements_kind.fast;
66   if (%HasFastDoubleElements(obj)) return elements_kind.fast_double;
67   if (%HasDictionaryElements(obj)) return elements_kind.dictionary;
68 }
69
70 function isHoley(obj) {
71   if (%HasFastHoleyElements(obj)) return true;
72   return false;
73 }
74
75 function assertKind(expected, obj, name_opt) {
76   if (!support_smi_only_arrays &&
77       expected == elements_kind.fast_smi_only) {
78     expected = elements_kind.fast;
79   }
80   assertEquals(expected, getKind(obj), name_opt);
81 }
82
83 if (support_smi_only_arrays) {
84
85   // Test: If a call site goes megamorphic, it loses the ability to
86   // use allocation site feedback.
87   (function() {
88     function bar(t, len) {
89       return new t(len);
90     }
91
92     a = bar(Array, 10);
93     a[0] = 3.5;
94     b = bar(Array, 1);
95     assertKind(elements_kind.fast_double, b);
96     c = bar(Object, 3);
97     b = bar(Array, 10);
98     assertKind(elements_kind.fast_smi_only, b);
99     b[0] = 3.5;
100     c = bar(Array, 10);
101     assertKind(elements_kind.fast_smi_only, c);
102   })();
103
104
105   // Test: ensure that crankshafted array constructor sites are deopted
106   // if another function is used.
107   (function() {
108     function bar0(t) {
109       return new t();
110     }
111     a = bar0(Array);
112     a[0] = 3.5;
113     b = bar0(Array);
114     assertKind(elements_kind.fast_double, b);
115     %OptimizeFunctionOnNextCall(bar0);
116     b = bar0(Array);
117     assertKind(elements_kind.fast_double, b);
118     assertOptimized(bar0);
119     // bar0 should deopt
120     b = bar0(Object);
121     assertUnoptimized(bar0)
122     // When it's re-optimized, we should call through the full stub
123     bar0(Array);
124     %OptimizeFunctionOnNextCall(bar0);
125     b = bar0(Array);
126     // We also lost our ability to record kind feedback, as the site
127     // is megamorphic now.
128     assertKind(elements_kind.fast_smi_only, b);
129     assertOptimized(bar0);
130     b[0] = 3.5;
131     c = bar0(Array);
132     assertKind(elements_kind.fast_smi_only, c);
133   })();
134
135
136   // Test: Ensure that inlined array calls in crankshaft learn from deopts
137   // based on the move to a dictionary for the array.
138   (function() {
139     function bar(len) {
140       return new Array(len);
141     }
142     a = bar(10);
143     a[0] = "a string";
144     a = bar(10);
145     assertKind(elements_kind.fast, a);
146     %OptimizeFunctionOnNextCall(bar);
147     a = bar(10);
148     assertKind(elements_kind.fast, a);
149     assertOptimized(bar);
150     // bar should deopt because the length is too large.
151     a = bar(100000);
152     assertUnoptimized(bar);
153     assertKind(elements_kind.dictionary, a);
154     // The allocation site now has feedback that means the array constructor
155     // will not be inlined.
156     %OptimizeFunctionOnNextCall(bar);
157     a = bar(100000);
158     assertKind(elements_kind.dictionary, a);
159     assertOptimized(bar);
160
161     // If the argument isn't a smi, it bails out as well
162     a = bar("oops");
163     assertOptimized(bar);
164     assertKind(elements_kind.fast, a);
165
166     function barn(one, two, three) {
167       return new Array(one, two, three);
168     }
169
170     barn(1, 2, 3);
171     barn(1, 2, 3);
172     %OptimizeFunctionOnNextCall(barn);
173     barn(1, 2, 3);
174     assertOptimized(barn);
175     a = barn(1, "oops", 3);
176     // The method should deopt, but learn from the failure to avoid inlining
177     // the array.
178     assertKind(elements_kind.fast, a);
179     assertUnoptimized(barn);
180     %OptimizeFunctionOnNextCall(barn);
181     a = barn(1, "oops", 3);
182     assertOptimized(barn);
183   })();
184
185
186   // Test: When a method with array constructor is crankshafted, the type
187   // feedback for elements kind is baked in. Verify that transitions don't
188   // change it anymore
189   (function() {
190     function bar() {
191       return new Array();
192     }
193     a = bar();
194     bar();
195     %OptimizeFunctionOnNextCall(bar);
196     b = bar();
197     // This only makes sense to test if we allow crankshafting
198     if (4 != %GetOptimizationStatus(bar)) {
199       assertOptimized(bar);
200       %DebugPrint(3);
201       b[0] = 3.5;
202       c = bar();
203       assertKind(elements_kind.fast_smi_only, c);
204       assertOptimized(bar);
205     }
206   })();
207
208
209   // Test: create arrays in two contexts, verifying that the correct
210   // map for Array in that context will be used.
211   (function() {
212     function bar() { return new Array(); }
213     bar();
214     bar();
215     %OptimizeFunctionOnNextCall(bar);
216     a = bar();
217     assertTrue(a instanceof Array);
218
219     var contextB = Realm.create();
220     Realm.eval(contextB, "function bar2() { return new Array(); };");
221     Realm.eval(contextB, "bar2(); bar2();");
222     Realm.eval(contextB, "%OptimizeFunctionOnNextCall(bar2);");
223     Realm.eval(contextB, "bar2();");
224     assertFalse(Realm.eval(contextB, "bar2();") instanceof Array);
225     assertTrue(Realm.eval(contextB, "bar2() instanceof Array"));
226   })();
227
228   // Test: create array with packed feedback, then optimize/inline
229   // function. Verify that if we ask for a holey array then we deopt.
230   // Reoptimization will proceed with the correct feedback and we
231   // won't deopt anymore.
232   (function() {
233     function bar(len) { return new Array(len); }
234     bar(0);
235     bar(0);
236     %OptimizeFunctionOnNextCall(bar);
237     a = bar(0);
238     assertOptimized(bar);
239     assertFalse(isHoley(a));
240     a = bar(1);  // ouch!
241     assertUnoptimized(bar);
242     assertTrue(isHoley(a));
243     // Try again
244     %OptimizeFunctionOnNextCall(bar);
245     a = bar(100);
246     assertOptimized(bar);
247     assertTrue(isHoley(a));
248     a = bar(0);
249     assertOptimized(bar);
250     assertTrue(isHoley(a));
251   })();
252 }