| 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 |