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 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: --optimize-for-in --allow-natives-syntax 29// Flags: --no-concurrent-osr 30 31// Test for-in support in Crankshaft. For simplicity this tests assumes certain 32// fixed iteration order for properties and will have to be adjusted if V8 33// stops following insertion order. 34 35 36function a(t) { 37 var result = []; 38 for (var i in t) { 39 result.push(i + t[i]); 40 } 41 return result.join(''); 42} 43 44// Check that we correctly deoptimize on map check. 45function b(t) { 46 var result = []; 47 for (var i in t) { 48 result.push(i + t[i]); 49 delete t[i]; 50 } 51 return result.join(''); 52} 53 54// Check that we correctly deoptimize during preparation step. 55function c(t) { 56 var result = []; 57 for (var i in t) { 58 result.push(i + t[i]); 59 } 60 return result.join(''); 61} 62 63// Check that we deoptimize to the place after side effect in the right state. 64function d(t) { 65 var result = []; 66 var o; 67 for (var i in (o = t())) { 68 result.push(i + o[i]); 69 } 70 return result.join(''); 71} 72 73// Check that we correctly deoptimize on map check inserted for fused load. 74function e(t) { 75 var result = []; 76 for (var i in t) { 77 delete t[i]; 78 t[i] = i; 79 result.push(i + t[i]); 80 } 81 return result.join(''); 82} 83 84// Nested for-in loops. 85function f(t) { 86 var result = []; 87 for (var i in t) { 88 for (var j in t) { 89 result.push(i + j + t[i] + t[j]); 90 } 91 } 92 return result.join(''); 93} 94 95// Deoptimization from the inner for-in loop. 96function g(t) { 97 var result = []; 98 for (var i in t) { 99 for (var j in t) { 100 result.push(i + j + t[i] + t[j]); 101 var v = t[i]; 102 delete t[i]; 103 t[i] = v; 104 } 105 } 106 return result.join(''); 107} 108 109 110// Break from the inner for-in loop. 111function h(t, deopt) { 112 var result = []; 113 for (var i in t) { 114 for (var j in t) { 115 result.push(i + j + t[i] + t[j]); 116 break; 117 } 118 } 119 deopt.deopt; 120 return result.join(''); 121} 122 123// Continue in the inner loop. 124function j(t, deopt) { 125 var result = []; 126 for (var i in t) { 127 for (var j in t) { 128 result.push(i + j + t[i] + t[j]); 129 continue; 130 } 131 } 132 deopt.deopt; 133 return result.join(''); 134} 135 136// Continue of the outer loop. 137function k(t, deopt) { 138 var result = []; 139 outer: for (var i in t) { 140 for (var j in t) { 141 result.push(i + j + t[i] + t[j]); 142 continue outer; 143 } 144 } 145 deopt.deopt; 146 return result.join(''); 147} 148 149// Break of the outer loop. 150function l(t, deopt) { 151 var result = []; 152 outer: for (var i in t) { 153 for (var j in t) { 154 result.push(i + j + t[i] + t[j]); 155 break outer; 156 } 157 } 158 deopt.deopt; 159 return result.join(''); 160} 161 162// Test deoptimization from inlined frame (currently it is not inlined). 163function m0(t, deopt) { 164 for (var i in t) { 165 for (var j in t) { 166 deopt.deopt; 167 return i + j + t[i] + t[j]; 168 } 169 } 170} 171 172function m(t, deopt) { 173 return m0(t, deopt); 174} 175 176 177function tryFunction(s, mkT, f) { 178 var d = {deopt: false}; 179 assertEquals(s, f(mkT(), d)); 180 assertEquals(s, f(mkT(), d)); 181 assertEquals(s, f(mkT(), d)); 182 %OptimizeFunctionOnNextCall(f); 183 assertEquals(s, f(mkT(), d)); 184 assertEquals(s, f(mkT(), {})); 185} 186 187var s = "a1b2c3d4"; 188function mkTable() { return { a: "1", b: "2", c: "3", d: "4" }; } 189 190 191tryFunction(s, mkTable, a); 192tryFunction(s, mkTable, b); 193tryFunction("0a1b2c3d", function () { return "abcd"; }, c); 194tryFunction("0a1b2c3d", function () { 195 var cnt = false; 196 return function () { 197 cnt = true; 198 return "abcd"; 199 } 200}, d); 201tryFunction("aabbccdd", mkTable, e); 202 203function mkSmallTable() { return { a: "1", b: "2" }; } 204 205tryFunction("aa11ab12ba21bb22", mkSmallTable, f); 206tryFunction("aa11ab12bb22ba21", mkSmallTable, g); 207tryFunction("aa11ba21", mkSmallTable, h); 208tryFunction("aa11ab12ba21bb22", mkSmallTable, j); 209tryFunction("aa11ba21", mkSmallTable, h); 210tryFunction("aa11ba21", mkSmallTable, k); 211tryFunction("aa11", mkSmallTable, l); 212tryFunction("aa11", mkSmallTable, m); 213 214// Test handling of null. 215tryFunction("", function () { 216 return function () { return null; } 217}, function (t) { 218 for (var i in t()) { return i; } 219 return ""; 220}); 221 222// Test smis. 223tryFunction("", function () { 224 return function () { return 11; } 225}, function (t) { 226 for (var i in t()) { return i; } 227 return ""; 228}); 229 230// Test LoadFieldByIndex for out of object properties. 231function O() { this.a = 1; } 232for (var i = 0; i < 10; i++) new O(); 233tryFunction("a1b2c3d4e5f6", function () { 234 var o = new O(); 235 o.b = 2; 236 o.c = 3; 237 o.d = 4; 238 o.e = 5; 239 o.f = 6; 240 return o; 241}, function (t) { 242 var r = []; 243 for (var i in t) r.push(i + t[i]); 244 return r.join(''); 245}); 246 247// Test OSR inside for-in. 248function osr_inner(t, limit) { 249 var r = 1; 250 for (var x in t) { 251 if (t.hasOwnProperty(x)) { 252 for (var i = 0; i < t[x].length; i++) { 253 r += t[x][i]; 254 if (i === limit) %OptimizeOsr(); 255 } 256 r += x; 257 } 258 } 259 return r; 260} 261 262function osr_outer(t, osr_after) { 263 var r = 1; 264 for (var x in t) { 265 for (var i = 0; i < t[x].length; i++) { 266 r += t[x][i]; 267 } 268 if (x === osr_after) %OptimizeOsr(); 269 r += x; 270 } 271 return r; 272} 273 274function osr_outer_and_deopt(t, osr_after) { 275 var r = 1; 276 for (var x in t) { 277 r += x; 278 if (x == osr_after) %OptimizeOsr(); 279 } 280 return r; 281} 282 283function test_osr() { 284 with ({}) {} // Disable optimizations of this function. 285 var arr = new Array(20); 286 for (var i = 0; i < arr.length; i++) { 287 arr[i] = i + 1; 288 } 289 arr.push(":"); // Force deopt at the end of the loop. 290 assertEquals("211:x1234567891011121314151617181920:y", osr_inner({x: arr, y: arr}, (arr.length / 2) | 0)); 291 assertEquals("7x456y", osr_outer({x: [1,2,3], y: [4,5,6]}, "x")); 292 assertEquals("101234567", osr_outer_and_deopt([1,2,3,4,5,6,7,8], "5")); 293} 294 295test_osr(); 296