blob: c2c1a1842f7d580800bbed37b62527f45f1454b1 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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// Test element kind of objects.
32
33var elements_kind = {
34 fast_smi_only : 'fast smi only elements',
35 fast : 'fast elements',
36 fast_double : 'fast double elements',
37 dictionary : 'dictionary elements',
38 external_byte : 'external byte elements',
39 external_unsigned_byte : 'external unsigned byte elements',
40 external_short : 'external short elements',
41 external_unsigned_short : 'external unsigned short elements',
42 external_int : 'external int elements',
43 external_unsigned_int : 'external unsigned int elements',
44 external_float : 'external float elements',
45 external_double : 'external double elements',
46 external_pixel : 'external pixel elements'
47}
48
49function getKind(obj) {
50 if (%HasFastSmiElements(obj)) return elements_kind.fast_smi_only;
51 if (%HasFastObjectElements(obj)) return elements_kind.fast;
52 if (%HasFastDoubleElements(obj)) return elements_kind.fast_double;
53 if (%HasDictionaryElements(obj)) return elements_kind.dictionary;
54}
55
56function isHoley(obj) {
57 if (%HasFastHoleyElements(obj)) return true;
58 return false;
59}
60
61function assertKind(expected, obj, name_opt) {
62 assertEquals(expected, getKind(obj), name_opt);
63}
64
65// Test: If a call site goes megamorphic, it retains the ability to
66// use allocation site feedback (if FLAG_allocation_site_pretenuring
67// is on).
68(function() {
69 function bar(t, len) {
70 return new t(len);
71 }
72
73 a = bar(Array, 10);
74 a[0] = 3.5;
75 b = bar(Array, 1);
76 assertKind(elements_kind.fast_double, b);
77 c = bar(Object, 3);
78 b = bar(Array, 10);
79 // TODO(mvstanton): re-enable when FLAG_allocation_site_pretenuring
80 // is on in the build.
81 // assertKind(elements_kind.fast_double, b);
82})();
83
84
85// Test: ensure that crankshafted array constructor sites are deopted
86// if another function is used.
87(function() {
88 function bar0(t) {
89 return new t();
90 }
91 a = bar0(Array);
92 a[0] = 3.5;
93 b = bar0(Array);
94 assertKind(elements_kind.fast_double, b);
95 %OptimizeFunctionOnNextCall(bar0);
96 b = bar0(Array);
97 assertKind(elements_kind.fast_double, b);
98 assertOptimized(bar0);
99 // bar0 should deopt
100 b = bar0(Object);
101 assertUnoptimized(bar0)
102 // When it's re-optimized, we should call through the full stub
103 bar0(Array);
104 %OptimizeFunctionOnNextCall(bar0);
105 b = bar0(Array);
106 // This only makes sense to test if we allow crankshafting
107 if (4 != %GetOptimizationStatus(bar0)) {
108 // We also lost our ability to record kind feedback, as the site
109 // is megamorphic now.
110 assertKind(elements_kind.fast_smi_only, b);
111 assertOptimized(bar0);
112 b[0] = 3.5;
113 c = bar0(Array);
114 assertKind(elements_kind.fast_smi_only, c);
115 }
116})();
117
118
119// Test: Ensure that inlined array calls in crankshaft learn from deopts
120// based on the move to a dictionary for the array.
121(function() {
122 function bar(len) {
123 return new Array(len);
124 }
125 a = bar(10);
126 a[0] = "a string";
127 a = bar(10);
128 assertKind(elements_kind.fast, a);
129 %OptimizeFunctionOnNextCall(bar);
130 a = bar(10);
131 assertKind(elements_kind.fast, a);
132 assertOptimized(bar);
133 bar(100000);
134 assertOptimized(bar);
135
136 // If the argument isn't a smi, things should still work.
137 a = bar("oops");
138 assertOptimized(bar);
139 assertKind(elements_kind.fast, a);
140
141 function barn(one, two, three) {
142 return new Array(one, two, three);
143 }
144
145 barn(1, 2, 3);
146 barn(1, 2, 3);
147 %OptimizeFunctionOnNextCall(barn);
148 barn(1, 2, 3);
149 assertOptimized(barn);
150 a = barn(1, "oops", 3);
151 assertOptimized(barn);
152})();
153
154
155// Test: When a method with array constructor is crankshafted, the type
156// feedback for elements kind is baked in. Verify that transitions don't
157// change it anymore
158(function() {
159 function bar() {
160 return new Array();
161 }
162 a = bar();
163 bar();
164 %OptimizeFunctionOnNextCall(bar);
165 b = bar();
166 // This only makes sense to test if we allow crankshafting
167 if (4 != %GetOptimizationStatus(bar)) {
168 assertOptimized(bar);
169 %DebugPrint(3);
170 b[0] = 3.5;
171 c = bar();
172 assertKind(elements_kind.fast_smi_only, c);
173 assertOptimized(bar);
174 }
175})();
176
177
178// Test: create arrays in two contexts, verifying that the correct
179// map for Array in that context will be used.
180(function() {
181 function bar() { return new Array(); }
182 bar();
183 bar();
184 %OptimizeFunctionOnNextCall(bar);
185 a = bar();
186 assertTrue(a instanceof Array);
187
188 var contextB = Realm.create();
189 Realm.eval(contextB, "function bar2() { return new Array(); };");
190 Realm.eval(contextB, "bar2(); bar2();");
191 Realm.eval(contextB, "%OptimizeFunctionOnNextCall(bar2);");
192 Realm.eval(contextB, "bar2();");
193 assertFalse(Realm.eval(contextB, "bar2();") instanceof Array);
194 assertTrue(Realm.eval(contextB, "bar2() instanceof Array"));
195})();
196
197// Test: create array with packed feedback, then optimize function, which
198// should deal with arguments that create holey arrays.
199(function() {
200 function bar(len) { return new Array(len); }
201 bar(0);
202 bar(0);
203 %OptimizeFunctionOnNextCall(bar);
204 a = bar(0);
205 assertOptimized(bar);
206 assertFalse(isHoley(a));
207 a = bar(1); // ouch!
208 assertOptimized(bar);
209 assertTrue(isHoley(a));
210 a = bar(100);
211 assertTrue(isHoley(a));
212 a = bar(0);
213 assertOptimized(bar);
214 // Crankshafted functions don't use mementos, so feedback still
215 // indicates a packed array is desired. (unless --nocrankshaft is in use).
216 if (4 != %GetOptimizationStatus(bar)) {
217 assertFalse(isHoley(a));
218 }
219})();