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
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.
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.
28 // Flags: --allow-natives-syntax --smi-only-arrays --expose-gc
29 // Flags: --noalways-opt
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.
38 // support_smi_only_arrays = %HasFastSmiElements(new Array(1,2,3,4,5,6,7,8));
39 support_smi_only_arrays = true;
41 if (support_smi_only_arrays) {
42 print("Tests include smi-only arrays.");
44 print("Tests do NOT include smi-only arrays.");
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'
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;
70 function isHoley(obj) {
71 if (%HasFastHoleyElements(obj)) return true;
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;
80 assertEquals(expected, getKind(obj), name_opt);
83 if (support_smi_only_arrays) {
85 // Test: If a call site goes megamorphic, it loses the ability to
86 // use allocation site feedback.
88 function bar(t, len) {
95 assertKind(elements_kind.fast_double, b);
98 assertKind(elements_kind.fast_smi_only, b);
101 assertKind(elements_kind.fast_smi_only, c);
105 // Test: ensure that crankshafted array constructor sites are deopted
106 // if another function is used.
114 assertKind(elements_kind.fast_double, b);
115 %OptimizeFunctionOnNextCall(bar0);
117 assertKind(elements_kind.fast_double, b);
118 assertOptimized(bar0);
121 assertUnoptimized(bar0)
122 // When it's re-optimized, we should call through the full stub
124 %OptimizeFunctionOnNextCall(bar0);
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);
132 assertKind(elements_kind.fast_smi_only, c);
136 // Test: Ensure that inlined array calls in crankshaft learn from deopts
137 // based on the move to a dictionary for the array.
140 return new Array(len);
145 assertKind(elements_kind.fast, a);
146 %OptimizeFunctionOnNextCall(bar);
148 assertKind(elements_kind.fast, a);
149 assertOptimized(bar);
150 // bar should deopt because the length is too large.
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);
158 assertKind(elements_kind.dictionary, a);
159 assertOptimized(bar);
161 // If the argument isn't a smi, it bails out as well
163 assertOptimized(bar);
164 assertKind(elements_kind.fast, a);
166 function barn(one, two, three) {
167 return new Array(one, two, three);
172 %OptimizeFunctionOnNextCall(barn);
174 assertOptimized(barn);
175 a = barn(1, "oops", 3);
176 // The method should deopt, but learn from the failure to avoid inlining
178 assertKind(elements_kind.fast, a);
179 assertUnoptimized(barn);
180 %OptimizeFunctionOnNextCall(barn);
181 a = barn(1, "oops", 3);
182 assertOptimized(barn);
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
195 %OptimizeFunctionOnNextCall(bar);
197 // This only makes sense to test if we allow crankshafting
198 if (4 != %GetOptimizationStatus(bar)) {
199 assertOptimized(bar);
203 assertKind(elements_kind.fast_smi_only, c);
204 assertOptimized(bar);
209 // Test: create arrays in two contexts, verifying that the correct
210 // map for Array in that context will be used.
212 function bar() { return new Array(); }
215 %OptimizeFunctionOnNextCall(bar);
217 assertTrue(a instanceof Array);
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"));
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.
233 function bar(len) { return new Array(len); }
236 %OptimizeFunctionOnNextCall(bar);
238 assertOptimized(bar);
239 assertFalse(isHoley(a));
241 assertUnoptimized(bar);
242 assertTrue(isHoley(a));
244 %OptimizeFunctionOnNextCall(bar);
246 assertOptimized(bar);
247 assertTrue(isHoley(a));
249 assertOptimized(bar);
250 assertTrue(isHoley(a));