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: --track-allocation-sites --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 // Reset the GC stress mode to be off. Needed because AllocationMementos only
39 // live for one gc, so a gc that happens in certain fragile areas of the test
40 // can break assumptions.
41 %SetFlags("--gc-interval=-1")
43 // support_smi_only_arrays = %HasFastSmiElements(new Array(1,2,3,4,5,6,7,8));
44 support_smi_only_arrays = true;
46 if (support_smi_only_arrays) {
47 print("Tests include smi-only arrays.");
49 print("Tests do NOT include smi-only arrays.");
53 fast_smi_only : 'fast smi only elements',
54 fast : 'fast elements',
55 fast_double : 'fast double elements',
56 dictionary : 'dictionary elements',
57 external_byte : 'external byte elements',
58 external_unsigned_byte : 'external unsigned byte elements',
59 external_short : 'external short elements',
60 external_unsigned_short : 'external unsigned short elements',
61 external_int : 'external int elements',
62 external_unsigned_int : 'external unsigned int elements',
63 external_float : 'external float elements',
64 external_double : 'external double elements',
65 external_pixel : 'external pixel elements'
68 function getKind(obj) {
69 if (%HasFastSmiElements(obj)) return elements_kind.fast_smi_only;
70 if (%HasFastObjectElements(obj)) return elements_kind.fast;
71 if (%HasFastDoubleElements(obj)) return elements_kind.fast_double;
72 if (%HasDictionaryElements(obj)) return elements_kind.dictionary;
75 function isHoley(obj) {
76 if (%HasFastHoleyElements(obj)) return true;
80 function assertKind(expected, obj, name_opt) {
81 if (!support_smi_only_arrays &&
82 expected == elements_kind.fast_smi_only) {
83 expected = elements_kind.fast;
85 assertEquals(expected, getKind(obj), name_opt);
88 if (support_smi_only_arrays) {
90 // Test: If a call site goes megamorphic, it loses the ability to
91 // use allocation site feedback.
93 function bar(t, len) {
100 assertKind(elements_kind.fast_double, b);
103 assertKind(elements_kind.fast_smi_only, b);
106 assertKind(elements_kind.fast_smi_only, c);
110 // Test: ensure that crankshafted array constructor sites are deopted
111 // if another function is used.
119 assertKind(elements_kind.fast_double, b);
120 %OptimizeFunctionOnNextCall(bar0);
122 assertKind(elements_kind.fast_double, b);
123 assertOptimized(bar0);
126 assertUnoptimized(bar0)
127 // When it's re-optimized, we should call through the full stub
129 %OptimizeFunctionOnNextCall(bar0);
131 // We also lost our ability to record kind feedback, as the site
132 // is megamorphic now.
133 assertKind(elements_kind.fast_smi_only, b);
134 assertOptimized(bar0);
137 assertKind(elements_kind.fast_smi_only, c);
141 // Test: Ensure that bailouts from the stub don't deopt a crankshafted
142 // method with a call to that stub.
145 return new Array(len);
150 assertKind(elements_kind.fast, a);
151 %OptimizeFunctionOnNextCall(bar);
153 assertKind(elements_kind.fast, a);
154 assertOptimized(bar);
155 // The stub bails out, but the method call should be fine.
157 assertOptimized(bar);
158 assertKind(elements_kind.dictionary, a);
160 // If the argument isn't a smi, it bails out as well
162 assertOptimized(bar);
163 assertKind(elements_kind.fast, a);
165 function barn(one, two, three) {
166 return new Array(one, two, three);
171 %OptimizeFunctionOnNextCall(barn);
173 assertOptimized(barn);
174 a = barn(1, "oops", 3);
175 // The stub should bail out but the method should remain optimized.
176 assertKind(elements_kind.fast, a);
177 assertOptimized(barn);
181 // Test: When a method with array constructor is crankshafted, the type
182 // feedback for elements kind is baked in. Verify that transitions don't
190 %OptimizeFunctionOnNextCall(bar);
192 // This only makes sense to test if we allow crankshafting
193 if (4 != %GetOptimizationStatus(bar)) {
194 assertOptimized(bar);
198 assertKind(elements_kind.fast_smi_only, c);
199 assertOptimized(bar);
204 // Test: create arrays in two contexts, verifying that the correct
205 // map for Array in that context will be used.
207 function bar() { return new Array(); }
210 %OptimizeFunctionOnNextCall(bar);
212 assertTrue(a instanceof Array);
214 var contextB = Realm.create();
215 Realm.eval(contextB, "function bar2() { return new Array(); };");
216 Realm.eval(contextB, "bar2(); bar2();");
217 Realm.eval(contextB, "%OptimizeFunctionOnNextCall(bar2);");
218 Realm.eval(contextB, "bar2();");
219 assertFalse(Realm.eval(contextB, "bar2();") instanceof Array);
220 assertTrue(Realm.eval(contextB, "bar2() instanceof Array"));