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