OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
11 // with the distribution. | 11 // with the distribution. |
12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
15 // | 15 // |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 // Flags: --allow-natives-syntax --smi-only-arrays --expose-gc | 28 // Flags: --allow-natives-syntax --expose-gc |
29 // Flags: --noalways-opt | 29 // Flags: --noalways-opt |
30 | 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 = { | 31 var elements_kind = { |
48 fast_smi_only : 'fast smi only elements', | 32 fast_smi_only : 'fast smi only elements', |
49 fast : 'fast elements', | 33 fast : 'fast elements', |
50 fast_double : 'fast double elements', | 34 fast_double : 'fast double elements', |
51 dictionary : 'dictionary elements', | 35 dictionary : 'dictionary elements', |
52 external_byte : 'external byte elements', | 36 external_byte : 'external byte elements', |
53 external_unsigned_byte : 'external unsigned byte elements', | 37 external_unsigned_byte : 'external unsigned byte elements', |
54 external_short : 'external short elements', | 38 external_short : 'external short elements', |
55 external_unsigned_short : 'external unsigned short elements', | 39 external_unsigned_short : 'external unsigned short elements', |
56 external_int : 'external int elements', | 40 external_int : 'external int elements', |
57 external_unsigned_int : 'external unsigned int elements', | 41 external_unsigned_int : 'external unsigned int elements', |
58 external_float : 'external float elements', | 42 external_float : 'external float elements', |
59 external_double : 'external double elements', | 43 external_double : 'external double elements', |
60 external_pixel : 'external pixel elements' | 44 external_pixel : 'external pixel elements' |
61 } | 45 } |
62 | 46 |
63 function getKind(obj) { | 47 function getKind(obj) { |
64 if (%HasFastSmiElements(obj)) return elements_kind.fast_smi_only; | 48 if (%HasFastSmiElements(obj)) return elements_kind.fast_smi_only; |
65 if (%HasFastObjectElements(obj)) return elements_kind.fast; | 49 if (%HasFastObjectElements(obj)) return elements_kind.fast; |
66 if (%HasFastDoubleElements(obj)) return elements_kind.fast_double; | 50 if (%HasFastDoubleElements(obj)) return elements_kind.fast_double; |
67 if (%HasDictionaryElements(obj)) return elements_kind.dictionary; | 51 if (%HasDictionaryElements(obj)) return elements_kind.dictionary; |
68 } | 52 } |
69 | 53 |
70 function isHoley(obj) { | 54 function isHoley(obj) { |
71 if (%HasFastHoleyElements(obj)) return true; | 55 if (%HasFastHoleyElements(obj)) return true; |
72 return false; | 56 return false; |
73 } | 57 } |
74 | 58 |
75 function assertKind(expected, obj, name_opt) { | 59 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); | 60 assertEquals(expected, getKind(obj), name_opt); |
81 } | 61 } |
82 | 62 |
83 function assertHoley(obj, name_opt) { | 63 function assertHoley(obj, name_opt) { |
84 assertEquals(true, isHoley(obj), name_opt); | 64 assertEquals(true, isHoley(obj), name_opt); |
85 } | 65 } |
86 | 66 |
87 function assertNotHoley(obj, name_opt) { | 67 function assertNotHoley(obj, name_opt) { |
88 assertEquals(false, isHoley(obj), name_opt); | 68 assertEquals(false, isHoley(obj), name_opt); |
89 } | 69 } |
90 | 70 |
91 if (support_smi_only_arrays) { | 71 obj = []; |
92 obj = []; | 72 assertNotHoley(obj); |
93 assertNotHoley(obj); | 73 assertKind(elements_kind.fast_smi_only, obj); |
94 assertKind(elements_kind.fast_smi_only, obj); | 74 |
95 | 75 obj = [1, 2, 3]; |
96 obj = [1, 2, 3]; | 76 assertNotHoley(obj); |
97 assertNotHoley(obj); | 77 assertKind(elements_kind.fast_smi_only, obj); |
98 assertKind(elements_kind.fast_smi_only, obj); | 78 |
99 | 79 obj = new Array(); |
100 obj = new Array(); | 80 assertNotHoley(obj); |
101 assertNotHoley(obj); | 81 assertKind(elements_kind.fast_smi_only, obj); |
102 assertKind(elements_kind.fast_smi_only, obj); | 82 |
103 | 83 obj = new Array(0); |
104 obj = new Array(0); | 84 assertNotHoley(obj); |
105 assertNotHoley(obj); | 85 assertKind(elements_kind.fast_smi_only, obj); |
106 assertKind(elements_kind.fast_smi_only, obj); | 86 |
107 | 87 obj = new Array(2); |
108 obj = new Array(2); | 88 assertHoley(obj); |
109 assertHoley(obj); | 89 assertKind(elements_kind.fast_smi_only, obj); |
110 assertKind(elements_kind.fast_smi_only, obj); | 90 |
111 | 91 obj = new Array(1,2,3); |
112 obj = new Array(1,2,3); | 92 assertNotHoley(obj); |
113 assertNotHoley(obj); | 93 assertKind(elements_kind.fast_smi_only, obj); |
114 assertKind(elements_kind.fast_smi_only, obj); | 94 |
115 | 95 obj = new Array(1, "hi", 2, undefined); |
116 obj = new Array(1, "hi", 2, undefined); | 96 assertNotHoley(obj); |
117 assertNotHoley(obj); | 97 assertKind(elements_kind.fast, obj); |
118 assertKind(elements_kind.fast, obj); | 98 |
119 | 99 function fastliteralcase(literal, value) { |
120 function fastliteralcase(literal, value) { | 100 literal[0] = value; |
121 literal[0] = value; | 101 return literal; |
122 return literal; | 102 } |
123 } | 103 |
124 | 104 function get_standard_literal() { |
125 function get_standard_literal() { | 105 var literal = [1, 2, 3]; |
126 var literal = [1, 2, 3]; | 106 return literal; |
127 return literal; | 107 } |
128 } | 108 |
129 | 109 // Case: [1,2,3] as allocation site |
130 // Case: [1,2,3] as allocation site | 110 obj = fastliteralcase(get_standard_literal(), 1); |
131 obj = fastliteralcase(get_standard_literal(), 1); | 111 assertKind(elements_kind.fast_smi_only, obj); |
132 assertKind(elements_kind.fast_smi_only, obj); | 112 obj = fastliteralcase(get_standard_literal(), 1.5); |
133 obj = fastliteralcase(get_standard_literal(), 1.5); | 113 assertKind(elements_kind.fast_double, obj); |
| 114 obj = fastliteralcase(get_standard_literal(), 2); |
| 115 assertKind(elements_kind.fast_double, obj); |
| 116 |
| 117 // The test below is in a loop because arrays that live |
| 118 // at global scope without the chance of being recreated |
| 119 // don't have allocation site information attached. |
| 120 for (i = 0; i < 2; i++) { |
| 121 obj = fastliteralcase([5, 3, 2], 1.5); |
134 assertKind(elements_kind.fast_double, obj); | 122 assertKind(elements_kind.fast_double, obj); |
135 obj = fastliteralcase(get_standard_literal(), 2); | 123 obj = fastliteralcase([3, 6, 2], 1.5); |
136 assertKind(elements_kind.fast_double, obj); | 124 assertKind(elements_kind.fast_double, obj); |
137 | 125 |
138 // The test below is in a loop because arrays that live | 126 // Note: thanks to pessimistic transition store stubs, we'll attempt |
139 // at global scope without the chance of being recreated | 127 // to transition to the most general elements kind seen at a particular |
140 // don't have allocation site information attached. | 128 // store site. So, the elements kind will be double. |
| 129 obj = fastliteralcase([2, 6, 3], 2); |
| 130 assertKind(elements_kind.fast_double, obj); |
| 131 } |
| 132 |
| 133 // Verify that we will not pretransition the double->fast path. |
| 134 obj = fastliteralcase(get_standard_literal(), "elliot"); |
| 135 assertKind(elements_kind.fast, obj); |
| 136 obj = fastliteralcase(get_standard_literal(), 3); |
| 137 assertKind(elements_kind.fast, obj); |
| 138 |
| 139 // Make sure this works in crankshafted code too. |
| 140 %OptimizeFunctionOnNextCall(get_standard_literal); |
| 141 get_standard_literal(); |
| 142 obj = get_standard_literal(); |
| 143 assertKind(elements_kind.fast, obj); |
| 144 |
| 145 function fastliteralcase_smifast(value) { |
| 146 var literal = [1, 2, 3, 4]; |
| 147 literal[0] = value; |
| 148 return literal; |
| 149 } |
| 150 |
| 151 obj = fastliteralcase_smifast(1); |
| 152 assertKind(elements_kind.fast_smi_only, obj); |
| 153 obj = fastliteralcase_smifast("carter"); |
| 154 assertKind(elements_kind.fast, obj); |
| 155 obj = fastliteralcase_smifast(2); |
| 156 assertKind(elements_kind.fast, obj); |
| 157 |
| 158 // Case: make sure transitions from packed to holey are tracked |
| 159 function fastliteralcase_smiholey(index, value) { |
| 160 var literal = [1, 2, 3, 4]; |
| 161 literal[index] = value; |
| 162 return literal; |
| 163 } |
| 164 |
| 165 obj = fastliteralcase_smiholey(5, 1); |
| 166 assertKind(elements_kind.fast_smi_only, obj); |
| 167 assertHoley(obj); |
| 168 obj = fastliteralcase_smiholey(0, 1); |
| 169 assertKind(elements_kind.fast_smi_only, obj); |
| 170 assertHoley(obj); |
| 171 |
| 172 function newarraycase_smidouble(value) { |
| 173 var a = new Array(); |
| 174 a[0] = value; |
| 175 return a; |
| 176 } |
| 177 |
| 178 // Case: new Array() as allocation site, smi->double |
| 179 obj = newarraycase_smidouble(1); |
| 180 assertKind(elements_kind.fast_smi_only, obj); |
| 181 obj = newarraycase_smidouble(1.5); |
| 182 assertKind(elements_kind.fast_double, obj); |
| 183 obj = newarraycase_smidouble(2); |
| 184 assertKind(elements_kind.fast_double, obj); |
| 185 |
| 186 function newarraycase_smiobj(value) { |
| 187 var a = new Array(); |
| 188 a[0] = value; |
| 189 return a; |
| 190 } |
| 191 |
| 192 // Case: new Array() as allocation site, smi->fast |
| 193 obj = newarraycase_smiobj(1); |
| 194 assertKind(elements_kind.fast_smi_only, obj); |
| 195 obj = newarraycase_smiobj("gloria"); |
| 196 assertKind(elements_kind.fast, obj); |
| 197 obj = newarraycase_smiobj(2); |
| 198 assertKind(elements_kind.fast, obj); |
| 199 |
| 200 function newarraycase_length_smidouble(value) { |
| 201 var a = new Array(3); |
| 202 a[0] = value; |
| 203 return a; |
| 204 } |
| 205 |
| 206 // Case: new Array(length) as allocation site |
| 207 obj = newarraycase_length_smidouble(1); |
| 208 assertKind(elements_kind.fast_smi_only, obj); |
| 209 obj = newarraycase_length_smidouble(1.5); |
| 210 assertKind(elements_kind.fast_double, obj); |
| 211 obj = newarraycase_length_smidouble(2); |
| 212 assertKind(elements_kind.fast_double, obj); |
| 213 |
| 214 // Try to continue the transition to fast object. |
| 215 // TODO(mvstanton): re-enable commented out code when |
| 216 // FLAG_pretenuring_call_new is turned on in the build. |
| 217 obj = newarraycase_length_smidouble("coates"); |
| 218 assertKind(elements_kind.fast, obj); |
| 219 obj = newarraycase_length_smidouble(2); |
| 220 // assertKind(elements_kind.fast, obj); |
| 221 |
| 222 function newarraycase_length_smiobj(value) { |
| 223 var a = new Array(3); |
| 224 a[0] = value; |
| 225 return a; |
| 226 } |
| 227 |
| 228 // Case: new Array(<length>) as allocation site, smi->fast |
| 229 obj = newarraycase_length_smiobj(1); |
| 230 assertKind(elements_kind.fast_smi_only, obj); |
| 231 obj = newarraycase_length_smiobj("gloria"); |
| 232 assertKind(elements_kind.fast, obj); |
| 233 obj = newarraycase_length_smiobj(2); |
| 234 assertKind(elements_kind.fast, obj); |
| 235 |
| 236 function newarraycase_list_smidouble(value) { |
| 237 var a = new Array(1, 2, 3); |
| 238 a[0] = value; |
| 239 return a; |
| 240 } |
| 241 |
| 242 obj = newarraycase_list_smidouble(1); |
| 243 assertKind(elements_kind.fast_smi_only, obj); |
| 244 obj = newarraycase_list_smidouble(1.5); |
| 245 assertKind(elements_kind.fast_double, obj); |
| 246 obj = newarraycase_list_smidouble(2); |
| 247 assertKind(elements_kind.fast_double, obj); |
| 248 |
| 249 function newarraycase_list_smiobj(value) { |
| 250 var a = new Array(4, 5, 6); |
| 251 a[0] = value; |
| 252 return a; |
| 253 } |
| 254 |
| 255 obj = newarraycase_list_smiobj(1); |
| 256 assertKind(elements_kind.fast_smi_only, obj); |
| 257 obj = newarraycase_list_smiobj("coates"); |
| 258 assertKind(elements_kind.fast, obj); |
| 259 obj = newarraycase_list_smiobj(2); |
| 260 assertKind(elements_kind.fast, obj); |
| 261 |
| 262 // Case: array constructor calls with out of date feedback. |
| 263 // The boilerplate should incorporate all feedback, but the input array |
| 264 // should be minimally transitioned based on immediate need. |
| 265 (function() { |
| 266 function foo(i) { |
| 267 // We have two cases, one for literals one for constructed arrays. |
| 268 var a = (i == 0) |
| 269 ? [1, 2, 3] |
| 270 : new Array(1, 2, 3); |
| 271 return a; |
| 272 } |
| 273 |
141 for (i = 0; i < 2; i++) { | 274 for (i = 0; i < 2; i++) { |
142 obj = fastliteralcase([5, 3, 2], 1.5); | 275 a = foo(i); |
143 assertKind(elements_kind.fast_double, obj); | 276 b = foo(i); |
144 obj = fastliteralcase([3, 6, 2], 1.5); | 277 b[5] = 1; // boilerplate goes holey |
145 assertKind(elements_kind.fast_double, obj); | 278 assertHoley(foo(i)); |
146 | 279 a[0] = 3.5; // boilerplate goes holey double |
147 // Note: thanks to pessimistic transition store stubs, we'll attempt | 280 assertKind(elements_kind.fast_double, a); |
148 // to transition to the most general elements kind seen at a particular | 281 assertNotHoley(a); |
149 // store site. So, the elements kind will be double. | 282 c = foo(i); |
150 obj = fastliteralcase([2, 6, 3], 2); | 283 assertKind(elements_kind.fast_double, c); |
151 assertKind(elements_kind.fast_double, obj); | 284 assertHoley(c); |
152 } | 285 } |
153 | 286 })(); |
154 // Verify that we will not pretransition the double->fast path. | 287 |
155 obj = fastliteralcase(get_standard_literal(), "elliot"); | 288 function newarraycase_onearg(len, value) { |
156 assertKind(elements_kind.fast, obj); | 289 var a = new Array(len); |
157 obj = fastliteralcase(get_standard_literal(), 3); | 290 a[0] = value; |
158 assertKind(elements_kind.fast, obj); | 291 return a; |
159 | 292 } |
160 // Make sure this works in crankshafted code too. | 293 |
161 %OptimizeFunctionOnNextCall(get_standard_literal); | 294 obj = newarraycase_onearg(5, 3.5); |
162 get_standard_literal(); | 295 assertKind(elements_kind.fast_double, obj); |
163 obj = get_standard_literal(); | 296 obj = newarraycase_onearg(10, 5); |
164 assertKind(elements_kind.fast, obj); | 297 assertKind(elements_kind.fast_double, obj); |
165 | 298 obj = newarraycase_onearg(0, 5); |
166 function fastliteralcase_smifast(value) { | 299 assertKind(elements_kind.fast_double, obj); |
167 var literal = [1, 2, 3, 4]; | 300 // Now pass a length that forces the dictionary path. |
168 literal[0] = value; | 301 obj = newarraycase_onearg(100000, 5); |
169 return literal; | 302 assertKind(elements_kind.dictionary, obj); |
170 } | 303 assertTrue(obj.length == 100000); |
171 | 304 |
172 obj = fastliteralcase_smifast(1); | 305 // Verify that cross context calls work |
173 assertKind(elements_kind.fast_smi_only, obj); | 306 var realmA = Realm.current(); |
174 obj = fastliteralcase_smifast("carter"); | 307 var realmB = Realm.create(); |
175 assertKind(elements_kind.fast, obj); | 308 assertEquals(0, realmA); |
176 obj = fastliteralcase_smifast(2); | 309 assertEquals(1, realmB); |
177 assertKind(elements_kind.fast, obj); | 310 |
178 | 311 function instanceof_check(type) { |
179 // Case: make sure transitions from packed to holey are tracked | 312 assertTrue(new type() instanceof type); |
180 function fastliteralcase_smiholey(index, value) { | 313 assertTrue(new type(5) instanceof type); |
181 var literal = [1, 2, 3, 4]; | 314 assertTrue(new type(1,2,3) instanceof type); |
182 literal[index] = value; | 315 } |
183 return literal; | 316 |
184 } | 317 function instanceof_check2(type) { |
185 | 318 assertTrue(new type() instanceof type); |
186 obj = fastliteralcase_smiholey(5, 1); | 319 assertTrue(new type(5) instanceof type); |
187 assertKind(elements_kind.fast_smi_only, obj); | 320 assertTrue(new type(1,2,3) instanceof type); |
188 assertHoley(obj); | 321 } |
189 obj = fastliteralcase_smiholey(0, 1); | 322 |
190 assertKind(elements_kind.fast_smi_only, obj); | 323 var realmBArray = Realm.eval(realmB, "Array"); |
191 assertHoley(obj); | 324 instanceof_check(Array); |
192 | 325 instanceof_check(realmBArray); |
193 function newarraycase_smidouble(value) { | 326 |
194 var a = new Array(); | 327 // instanceof_check2 is here because the call site goes through a state. |
195 a[0] = value; | 328 // Since instanceof_check(Array) was first called with the current context |
196 return a; | 329 // Array function, it went from (uninit->Array) then (Array->megamorphic). |
197 } | 330 // We'll get a different state traversal if we start with realmBArray. |
198 | 331 // It'll go (uninit->realmBArray) then (realmBArray->megamorphic). Recognize |
199 // Case: new Array() as allocation site, smi->double | 332 // that state "Array" implies an AllocationSite is present, and code is |
200 obj = newarraycase_smidouble(1); | 333 // configured to use it. |
201 assertKind(elements_kind.fast_smi_only, obj); | 334 instanceof_check2(realmBArray); |
202 obj = newarraycase_smidouble(1.5); | 335 instanceof_check2(Array); |
203 assertKind(elements_kind.fast_double, obj); | |
204 obj = newarraycase_smidouble(2); | |
205 assertKind(elements_kind.fast_double, obj); | |
206 | |
207 function newarraycase_smiobj(value) { | |
208 var a = new Array(); | |
209 a[0] = value; | |
210 return a; | |
211 } | |
212 | |
213 // Case: new Array() as allocation site, smi->fast | |
214 obj = newarraycase_smiobj(1); | |
215 assertKind(elements_kind.fast_smi_only, obj); | |
216 obj = newarraycase_smiobj("gloria"); | |
217 assertKind(elements_kind.fast, obj); | |
218 obj = newarraycase_smiobj(2); | |
219 assertKind(elements_kind.fast, obj); | |
220 | |
221 function newarraycase_length_smidouble(value) { | |
222 var a = new Array(3); | |
223 a[0] = value; | |
224 return a; | |
225 } | |
226 | |
227 // Case: new Array(length) as allocation site | |
228 obj = newarraycase_length_smidouble(1); | |
229 assertKind(elements_kind.fast_smi_only, obj); | |
230 obj = newarraycase_length_smidouble(1.5); | |
231 assertKind(elements_kind.fast_double, obj); | |
232 obj = newarraycase_length_smidouble(2); | |
233 assertKind(elements_kind.fast_double, obj); | |
234 | |
235 // Try to continue the transition to fast object. | |
236 // TODO(mvstanton): re-enable commented out code when | |
237 // FLAG_pretenuring_call_new is turned on in the build. | |
238 obj = newarraycase_length_smidouble("coates"); | |
239 assertKind(elements_kind.fast, obj); | |
240 obj = newarraycase_length_smidouble(2); | |
241 // assertKind(elements_kind.fast, obj); | |
242 | |
243 function newarraycase_length_smiobj(value) { | |
244 var a = new Array(3); | |
245 a[0] = value; | |
246 return a; | |
247 } | |
248 | |
249 // Case: new Array(<length>) as allocation site, smi->fast | |
250 obj = newarraycase_length_smiobj(1); | |
251 assertKind(elements_kind.fast_smi_only, obj); | |
252 obj = newarraycase_length_smiobj("gloria"); | |
253 assertKind(elements_kind.fast, obj); | |
254 obj = newarraycase_length_smiobj(2); | |
255 assertKind(elements_kind.fast, obj); | |
256 | |
257 function newarraycase_list_smidouble(value) { | |
258 var a = new Array(1, 2, 3); | |
259 a[0] = value; | |
260 return a; | |
261 } | |
262 | |
263 obj = newarraycase_list_smidouble(1); | |
264 assertKind(elements_kind.fast_smi_only, obj); | |
265 obj = newarraycase_list_smidouble(1.5); | |
266 assertKind(elements_kind.fast_double, obj); | |
267 obj = newarraycase_list_smidouble(2); | |
268 assertKind(elements_kind.fast_double, obj); | |
269 | |
270 function newarraycase_list_smiobj(value) { | |
271 var a = new Array(4, 5, 6); | |
272 a[0] = value; | |
273 return a; | |
274 } | |
275 | |
276 obj = newarraycase_list_smiobj(1); | |
277 assertKind(elements_kind.fast_smi_only, obj); | |
278 obj = newarraycase_list_smiobj("coates"); | |
279 assertKind(elements_kind.fast, obj); | |
280 obj = newarraycase_list_smiobj(2); | |
281 assertKind(elements_kind.fast, obj); | |
282 | |
283 // Case: array constructor calls with out of date feedback. | |
284 // The boilerplate should incorporate all feedback, but the input array | |
285 // should be minimally transitioned based on immediate need. | |
286 (function() { | |
287 function foo(i) { | |
288 // We have two cases, one for literals one for constructed arrays. | |
289 var a = (i == 0) | |
290 ? [1, 2, 3] | |
291 : new Array(1, 2, 3); | |
292 return a; | |
293 } | |
294 | |
295 for (i = 0; i < 2; i++) { | |
296 a = foo(i); | |
297 b = foo(i); | |
298 b[5] = 1; // boilerplate goes holey | |
299 assertHoley(foo(i)); | |
300 a[0] = 3.5; // boilerplate goes holey double | |
301 assertKind(elements_kind.fast_double, a); | |
302 assertNotHoley(a); | |
303 c = foo(i); | |
304 assertKind(elements_kind.fast_double, c); | |
305 assertHoley(c); | |
306 } | |
307 })(); | |
308 | |
309 function newarraycase_onearg(len, value) { | |
310 var a = new Array(len); | |
311 a[0] = value; | |
312 return a; | |
313 } | |
314 | |
315 obj = newarraycase_onearg(5, 3.5); | |
316 assertKind(elements_kind.fast_double, obj); | |
317 obj = newarraycase_onearg(10, 5); | |
318 assertKind(elements_kind.fast_double, obj); | |
319 obj = newarraycase_onearg(0, 5); | |
320 assertKind(elements_kind.fast_double, obj); | |
321 // Now pass a length that forces the dictionary path. | |
322 obj = newarraycase_onearg(100000, 5); | |
323 assertKind(elements_kind.dictionary, obj); | |
324 assertTrue(obj.length == 100000); | |
325 | |
326 // Verify that cross context calls work | |
327 var realmA = Realm.current(); | |
328 var realmB = Realm.create(); | |
329 assertEquals(0, realmA); | |
330 assertEquals(1, realmB); | |
331 | |
332 function instanceof_check(type) { | |
333 assertTrue(new type() instanceof type); | |
334 assertTrue(new type(5) instanceof type); | |
335 assertTrue(new type(1,2,3) instanceof type); | |
336 } | |
337 | |
338 function instanceof_check2(type) { | |
339 assertTrue(new type() instanceof type); | |
340 assertTrue(new type(5) instanceof type); | |
341 assertTrue(new type(1,2,3) instanceof type); | |
342 } | |
343 | |
344 var realmBArray = Realm.eval(realmB, "Array"); | |
345 instanceof_check(Array); | |
346 instanceof_check(realmBArray); | |
347 | |
348 // instanceof_check2 is here because the call site goes through a state. | |
349 // Since instanceof_check(Array) was first called with the current context | |
350 // Array function, it went from (uninit->Array) then (Array->megamorphic). | |
351 // We'll get a different state traversal if we start with realmBArray. | |
352 // It'll go (uninit->realmBArray) then (realmBArray->megamorphic). Recognize | |
353 // that state "Array" implies an AllocationSite is present, and code is | |
354 // configured to use it. | |
355 instanceof_check2(realmBArray); | |
356 instanceof_check2(Array); | |
357 | 336 |
358 %OptimizeFunctionOnNextCall(instanceof_check); | 337 %OptimizeFunctionOnNextCall(instanceof_check); |
359 | 338 |
360 // No de-opt will occur because HCallNewArray wasn't selected, on account of | 339 // No de-opt will occur because HCallNewArray wasn't selected, on account of |
361 // the call site not being monomorphic to Array. | 340 // the call site not being monomorphic to Array. |
362 instanceof_check(Array); | 341 instanceof_check(Array); |
363 assertOptimized(instanceof_check); | 342 assertOptimized(instanceof_check); |
364 instanceof_check(realmBArray); | 343 instanceof_check(realmBArray); |
365 assertOptimized(instanceof_check); | 344 assertOptimized(instanceof_check); |
366 | 345 |
367 // Try to optimize again, but first clear all type feedback, and allow it | 346 // Try to optimize again, but first clear all type feedback, and allow it |
368 // to be monomorphic on first call. Only after crankshafting do we introduce | 347 // to be monomorphic on first call. Only after crankshafting do we introduce |
369 // realmBArray. This should deopt the method. | 348 // realmBArray. This should deopt the method. |
370 %DeoptimizeFunction(instanceof_check); | 349 %DeoptimizeFunction(instanceof_check); |
371 %ClearFunctionTypeFeedback(instanceof_check); | 350 %ClearFunctionTypeFeedback(instanceof_check); |
372 instanceof_check(Array); | 351 instanceof_check(Array); |
373 instanceof_check(Array); | 352 instanceof_check(Array); |
374 %OptimizeFunctionOnNextCall(instanceof_check); | 353 %OptimizeFunctionOnNextCall(instanceof_check); |
375 instanceof_check(Array); | 354 instanceof_check(Array); |
376 assertOptimized(instanceof_check); | 355 assertOptimized(instanceof_check); |
377 | 356 |
378 instanceof_check(realmBArray); | 357 instanceof_check(realmBArray); |
379 assertUnoptimized(instanceof_check); | 358 assertUnoptimized(instanceof_check); |
380 | 359 |
381 // Case: make sure nested arrays benefit from allocation site feedback as | 360 // Case: make sure nested arrays benefit from allocation site feedback as |
382 // well. | 361 // well. |
383 (function() { | 362 (function() { |
384 // Make sure we handle nested arrays | 363 // Make sure we handle nested arrays |
385 function get_nested_literal() { | 364 function get_nested_literal() { |
386 var literal = [[1,2,3,4], [2], [3]]; | 365 var literal = [[1,2,3,4], [2], [3]]; |
387 return literal; | 366 return literal; |
388 } | 367 } |
389 | 368 |
390 obj = get_nested_literal(); | 369 obj = get_nested_literal(); |
391 assertKind(elements_kind.fast, obj); | 370 assertKind(elements_kind.fast, obj); |
392 obj[0][0] = 3.5; | 371 obj[0][0] = 3.5; |
393 obj[2][0] = "hello"; | 372 obj[2][0] = "hello"; |
394 obj = get_nested_literal(); | 373 obj = get_nested_literal(); |
395 assertKind(elements_kind.fast_double, obj[0]); | 374 assertKind(elements_kind.fast_double, obj[0]); |
396 assertKind(elements_kind.fast_smi_only, obj[1]); | 375 assertKind(elements_kind.fast_smi_only, obj[1]); |
397 assertKind(elements_kind.fast, obj[2]); | 376 assertKind(elements_kind.fast, obj[2]); |
398 | 377 |
399 // A more complex nested literal case. | 378 // A more complex nested literal case. |
400 function get_deep_nested_literal() { | 379 function get_deep_nested_literal() { |
401 var literal = [[1], [[2], "hello"], 3, [4]]; | 380 var literal = [[1], [[2], "hello"], 3, [4]]; |
402 return literal; | 381 return literal; |
403 } | 382 } |
404 | 383 |
405 obj = get_deep_nested_literal(); | 384 obj = get_deep_nested_literal(); |
406 assertKind(elements_kind.fast_smi_only, obj[1][0]); | 385 assertKind(elements_kind.fast_smi_only, obj[1][0]); |
407 obj[0][0] = 3.5; | 386 obj[0][0] = 3.5; |
408 obj[1][0][0] = "goodbye"; | 387 obj[1][0][0] = "goodbye"; |
409 assertKind(elements_kind.fast_double, obj[0]); | 388 assertKind(elements_kind.fast_double, obj[0]); |
410 assertKind(elements_kind.fast, obj[1][0]); | 389 assertKind(elements_kind.fast, obj[1][0]); |
411 | 390 |
412 obj = get_deep_nested_literal(); | 391 obj = get_deep_nested_literal(); |
413 assertKind(elements_kind.fast_double, obj[0]); | 392 assertKind(elements_kind.fast_double, obj[0]); |
414 assertKind(elements_kind.fast, obj[1][0]); | 393 assertKind(elements_kind.fast, obj[1][0]); |
415 })(); | 394 })(); |
416 | 395 |
417 // Perform a gc because without it the test below can experience an | 396 // Perform a gc because without it the test below can experience an |
418 // allocation failure at an inconvenient point. Allocation mementos get | 397 // allocation failure at an inconvenient point. Allocation mementos get |
419 // cleared on gc, and they can't deliver elements kind feedback when that | 398 // cleared on gc, and they can't deliver elements kind feedback when that |
420 // happens. | 399 // happens. |
421 gc(); | 400 gc(); |
422 | 401 |
423 // Make sure object literals with array fields benefit from the type feedback | 402 // Make sure object literals with array fields benefit from the type feedback |
424 // that allocation mementos provide. | 403 // that allocation mementos provide. |
425 (function() { | 404 (function() { |
426 // A literal in an object | 405 // A literal in an object |
427 function get_object_literal() { | 406 function get_object_literal() { |
428 var literal = { | 407 var literal = { |
429 array: [1,2,3], | 408 array: [1,2,3], |
430 data: 3.5 | 409 data: 3.5 |
431 }; | 410 }; |
432 return literal; | 411 return literal; |
433 } | 412 } |
434 | 413 |
435 obj = get_object_literal(); | 414 obj = get_object_literal(); |
436 assertKind(elements_kind.fast_smi_only, obj.array); | 415 assertKind(elements_kind.fast_smi_only, obj.array); |
437 obj.array[1] = 3.5; | 416 obj.array[1] = 3.5; |
438 assertKind(elements_kind.fast_double, obj.array); | 417 assertKind(elements_kind.fast_double, obj.array); |
439 obj = get_object_literal(); | 418 obj = get_object_literal(); |
440 assertKind(elements_kind.fast_double, obj.array); | 419 assertKind(elements_kind.fast_double, obj.array); |
441 | 420 |
442 function get_nested_object_literal() { | 421 function get_nested_object_literal() { |
443 var literal = { | 422 var literal = { |
444 array: [[1],[2],[3]], | 423 array: [[1],[2],[3]], |
445 data: 3.5 | 424 data: 3.5 |
446 }; | 425 }; |
447 return literal; | 426 return literal; |
448 } | 427 } |
449 | 428 |
450 obj = get_nested_object_literal(); | 429 obj = get_nested_object_literal(); |
451 assertKind(elements_kind.fast, obj.array); | 430 assertKind(elements_kind.fast, obj.array); |
452 assertKind(elements_kind.fast_smi_only, obj.array[1]); | 431 assertKind(elements_kind.fast_smi_only, obj.array[1]); |
453 obj.array[1][0] = 3.5; | 432 obj.array[1][0] = 3.5; |
454 assertKind(elements_kind.fast_double, obj.array[1]); | 433 assertKind(elements_kind.fast_double, obj.array[1]); |
455 obj = get_nested_object_literal(); | 434 obj = get_nested_object_literal(); |
456 assertKind(elements_kind.fast_double, obj.array[1]); | 435 assertKind(elements_kind.fast_double, obj.array[1]); |
457 | 436 |
458 %OptimizeFunctionOnNextCall(get_nested_object_literal); | 437 %OptimizeFunctionOnNextCall(get_nested_object_literal); |
459 get_nested_object_literal(); | 438 get_nested_object_literal(); |
460 obj = get_nested_object_literal(); | 439 obj = get_nested_object_literal(); |
461 assertKind(elements_kind.fast_double, obj.array[1]); | 440 assertKind(elements_kind.fast_double, obj.array[1]); |
462 | 441 |
463 // Make sure we handle nested arrays | 442 // Make sure we handle nested arrays |
464 function get_nested_literal() { | 443 function get_nested_literal() { |
465 var literal = [[1,2,3,4], [2], [3]]; | 444 var literal = [[1,2,3,4], [2], [3]]; |
466 return literal; | 445 return literal; |
467 } | 446 } |
468 | 447 |
469 obj = get_nested_literal(); | 448 obj = get_nested_literal(); |
470 assertKind(elements_kind.fast, obj); | 449 assertKind(elements_kind.fast, obj); |
471 obj[0][0] = 3.5; | 450 obj[0][0] = 3.5; |
472 obj[2][0] = "hello"; | 451 obj[2][0] = "hello"; |
473 obj = get_nested_literal(); | 452 obj = get_nested_literal(); |
474 assertKind(elements_kind.fast_double, obj[0]); | 453 assertKind(elements_kind.fast_double, obj[0]); |
475 assertKind(elements_kind.fast_smi_only, obj[1]); | 454 assertKind(elements_kind.fast_smi_only, obj[1]); |
476 assertKind(elements_kind.fast, obj[2]); | 455 assertKind(elements_kind.fast, obj[2]); |
477 | 456 |
478 // A more complex nested literal case. | 457 // A more complex nested literal case. |
479 function get_deep_nested_literal() { | 458 function get_deep_nested_literal() { |
480 var literal = [[1], [[2], "hello"], 3, [4]]; | 459 var literal = [[1], [[2], "hello"], 3, [4]]; |
481 return literal; | 460 return literal; |
482 } | 461 } |
483 | 462 |
484 obj = get_deep_nested_literal(); | 463 obj = get_deep_nested_literal(); |
485 assertKind(elements_kind.fast_smi_only, obj[1][0]); | 464 assertKind(elements_kind.fast_smi_only, obj[1][0]); |
486 obj[0][0] = 3.5; | 465 obj[0][0] = 3.5; |
487 obj[1][0][0] = "goodbye"; | 466 obj[1][0][0] = "goodbye"; |
488 assertKind(elements_kind.fast_double, obj[0]); | 467 assertKind(elements_kind.fast_double, obj[0]); |
489 assertKind(elements_kind.fast, obj[1][0]); | 468 assertKind(elements_kind.fast, obj[1][0]); |
490 | 469 |
491 obj = get_deep_nested_literal(); | 470 obj = get_deep_nested_literal(); |
492 assertKind(elements_kind.fast_double, obj[0]); | 471 assertKind(elements_kind.fast_double, obj[0]); |
493 assertKind(elements_kind.fast, obj[1][0]); | 472 assertKind(elements_kind.fast, obj[1][0]); |
494 })(); | 473 })(); |
495 } | |
OLD | NEW |