recover-arrays.js (8519B)
1 // Ion eager fails the test below because we have not yet created any 2 // template object in baseline before running the content of the top-level 3 // function. 4 if (getJitCompilerOptions()["ion.warmup.trigger"] <= 100) 5 setJitCompilerOption("ion.warmup.trigger", 100); 6 7 // This test checks that we are able to remove the getelem & setelem with scalar 8 // replacement, so we should not force inline caches, as this would skip the 9 // generation of getelem & setelem instructions. 10 if (getJitCompilerOptions()["ion.forceinlineCaches"]) 11 setJitCompilerOption("ion.forceinlineCaches", 0); 12 13 // Prevent the GC from cancelling Ion compilations, when we expect them to succeed 14 gczeal(0); 15 16 // This function is used to force a bailout when it is inlined, and to recover 17 // the frame which is inlining this function. 18 var resumeHere = function (i) { if (i >= 99) bailout(); }; 19 20 // This function is used to cause an invalidation after having removed a branch 21 // after DCE. This is made to check if we correctly recover an array 22 // allocation. 23 var uceFault = function (i) { 24 if (i > 98) 25 uceFault = function (i) { return true; }; 26 return false; 27 }; 28 29 // This function is used to ensure that we do escape the array, and thus prevent 30 // any escape analysis. 31 var global_arr; 32 function escape(arr) { global_arr = arr; } 33 34 // Check Array length defined by the literal. 35 function array0Length(i) { 36 var a = []; 37 assertRecoveredOnBailout(a, true); 38 return a.length; 39 } 40 41 function array0LengthBail(i) { 42 var a = []; 43 resumeHere(i); 44 assertRecoveredOnBailout(a, true); 45 return a.length; 46 } 47 48 function array1Length(i) { 49 var a = [ i ]; 50 assertRecoveredOnBailout(a, true); 51 return a.length; 52 } 53 54 function array1LengthBail(i) { 55 var a = [ i ]; 56 resumeHere(i); 57 assertRecoveredOnBailout(a, true); 58 return a.length; 59 } 60 61 function array2Length(i) { 62 var a = [ i, i ]; 63 assertRecoveredOnBailout(a, true); 64 return a.length; 65 } 66 67 function array2LengthBail(i) { 68 var a = [ i, i ]; 69 resumeHere(i); 70 assertRecoveredOnBailout(a, true); 71 return a.length; 72 } 73 74 // Check that we can correctly gc in the middle of an incomplete object 75 // intialization. 76 function arrayWithGCInit0(i) { 77 var a = [ (i == 99 ? (gc(), i) : i), i ]; 78 assertRecoveredOnBailout(a, true); 79 return a.length; 80 } 81 82 function arrayWithGCInit1(i) { 83 var a = [ i, (i == 99 ? (gc(), i) : i) ]; 84 assertRecoveredOnBailout(a, true); 85 return a.length; 86 } 87 88 function arrayWithGCInit2(i) { 89 var a = [ i, i ]; 90 if (i == 99) gc(); 91 assertRecoveredOnBailout(a, true); 92 return a.length; 93 } 94 95 // Check Array content 96 function array1Content(i) { 97 var a = [ i ]; 98 assertEq(a[0], i); 99 assertRecoveredOnBailout(a, true); 100 return a.length; 101 } 102 function array1ContentBail0(i) { 103 var a = [ i ]; 104 resumeHere(i); 105 assertEq(a[0], i); 106 assertRecoveredOnBailout(a, true); 107 return a.length; 108 } 109 function array1ContentBail1(i) { 110 var a = [ i ]; 111 assertEq(a[0], i); 112 resumeHere(i); 113 assertRecoveredOnBailout(a, true); 114 return a.length; 115 } 116 117 function array2Content(i) { 118 var a = [ i, i ]; 119 assertEq(a[0], i); 120 assertEq(a[1], i); 121 assertRecoveredOnBailout(a, true); 122 return a.length; 123 } 124 125 function array2ContentBail0(i) { 126 var a = [ i, i ]; 127 resumeHere(i); 128 assertEq(a[0], i); 129 assertEq(a[1], i); 130 assertRecoveredOnBailout(a, true); 131 return a.length; 132 } 133 134 function array2ContentBail1(i) { 135 var a = [ i, i ]; 136 assertEq(a[0], i); 137 resumeHere(i); 138 assertEq(a[1], i); 139 assertRecoveredOnBailout(a, true); 140 return a.length; 141 } 142 143 function array2ContentBail2(i) { 144 var a = [ i, i ]; 145 assertEq(a[0], i); 146 assertEq(a[1], i); 147 resumeHere(i); 148 assertRecoveredOnBailout(a, true); 149 return a.length; 150 } 151 152 // Check bailouts during the initialization. 153 function arrayInitBail0(i) { 154 var a = [ resumeHere(i), i ]; 155 assertRecoveredOnBailout(a, true); 156 return a.length; 157 } 158 159 function arrayInitBail1(i) { 160 var a = [ i, resumeHere(i) ]; 161 assertRecoveredOnBailout(a, true); 162 return a.length; 163 } 164 165 // Check recovery of large arrays. 166 function arrayLarge0(i) { 167 var a = new Array(10000000); 168 resumeHere(); bailout(); // always resume here. 169 // IsArrayEscaped prevent us from escaping Arrays with too many elements. 170 assertRecoveredOnBailout(a, false); 171 return a.length; 172 } 173 174 function arrayLarge1(i) { 175 var a = new Array(10000000); 176 a[0] = i; 177 assertEq(a[0], i); 178 // IsArrayEscaped prevent us from escaping Arrays with too many elements. 179 assertRecoveredOnBailout(a, false); 180 return a.length; 181 } 182 183 function arrayLarge2(i) { 184 var a = new Array(10000000); 185 a[0] = i; 186 a[100] = i; 187 assertEq(a[0], i); 188 assertEq(a[100], i); 189 // IsArrayEscaped prevent us from escaping Arrays with too many elements. 190 assertRecoveredOnBailout(a, false); 191 return a.length; 192 } 193 194 // Check escape analysis in case of branches. 195 function arrayCond(i) { 196 var a = [i,0,i]; 197 if (i % 2 == 1) 198 a[1] = i; 199 assertEq(a[0], i); 200 assertEq(a[1], (i % 2) * i); 201 assertEq(a[2], i); 202 assertRecoveredOnBailout(a, true); 203 return a.length; 204 } 205 206 // Check escape analysis in case of holes. 207 function arrayHole0(i) { 208 var a = [i,,i]; 209 if (i != 99) 210 a[1] = i; 211 assertEq(a[0], i); 212 assertEq(a[1], i != 99 ? i : undefined); 213 assertEq(a[2], i); 214 // need to check for holes. 215 assertRecoveredOnBailout(a, false); 216 return a.length; 217 } 218 219 // Same test as the previous one, but the Array.prototype is changed to reutn 220 // "100" when we request for the element "1". 221 function arrayHole1(i) { 222 var a = [i,,i]; 223 if (i != 99) 224 a[1] = i; 225 assertEq(a[0], i); 226 assertEq(a[1], i != 99 ? i : 100); 227 assertEq(a[2], i); 228 // need to check for holes. 229 assertRecoveredOnBailout(a, false); 230 return a.length; 231 } 232 233 // Check that we correctly allocate the array after taking the recover path. 234 var uceFault_arrayAlloc0 = eval(`(${uceFault})`.replace('uceFault', 'uceFault_arrayAlloc0')); 235 function arrayAlloc0(i) { 236 var a = new Array(10); 237 if (uceFault_arrayAlloc0(i) || uceFault_arrayAlloc0(i)) { 238 return a.length; 239 } 240 assertRecoveredOnBailout(a, true); 241 return 0; 242 } 243 244 var uceFault_arrayAlloc1 = eval(`(${uceFault})`.replace('uceFault', 'uceFault_arrayAlloc1')); 245 function arrayAlloc1(i) { 246 var a = new Array(10); 247 if (uceFault_arrayAlloc1(i) || uceFault_arrayAlloc1(i)) { 248 a[0] = i; 249 a[1] = i; 250 assertEq(a[0], i); 251 assertEq(a[1], i); 252 assertEq(a[2], undefined); 253 return a.length; 254 } 255 assertRecoveredOnBailout(a, true); 256 return 0; 257 } 258 259 var uceFault_arrayAlloc2 = eval(`(${uceFault})`.replace('uceFault', 'uceFault_arrayAlloc2')); 260 function arrayAlloc2(i) { 261 var a = new Array(10); 262 if (uceFault_arrayAlloc2(i) || uceFault_arrayAlloc2(i)) { 263 a[4096] = i; 264 assertEq(a[0], undefined); 265 assertEq(a[4096], i); 266 return a.length; 267 } 268 assertRecoveredOnBailout(a, true); 269 return 0; 270 } 271 272 function build(l) { var arr = []; for (var i = 0; i < l; i++) arr.push(i); return arr } 273 var uceFault_arrayAlloc3 = eval(`(${uceFault})`.replace('uceFault', 'uceFault_arrayAlloc3')); 274 function arrayAlloc3(i) { 275 var a = [0,1,2,3,4,5,6,7,8]; 276 if (uceFault_arrayAlloc3(i) || uceFault_arrayAlloc3(i)) { 277 assertEq(a[0], 0); 278 assertEq(a[3], 3); 279 return a.length; 280 } 281 assertRecoveredOnBailout(a, true); 282 return 0; 283 }; 284 285 // Prevent compilation of the top-level 286 eval(`(${resumeHere})`); 287 288 for (var i = 0; i < 100; i++) { 289 array0Length(i); 290 array0LengthBail(i); 291 array1Length(i); 292 array1LengthBail(i); 293 array2Length(i); 294 array2LengthBail(i); 295 array1Content(i); 296 array1ContentBail0(i); 297 array1ContentBail1(i); 298 array2Content(i); 299 array2ContentBail0(i); 300 array2ContentBail1(i); 301 array2ContentBail2(i); 302 arrayInitBail0(i); 303 arrayInitBail1(i); 304 arrayLarge0(i); 305 arrayLarge1(i); 306 arrayLarge2(i); 307 //arrayCond(i); See bug 1697691. 308 arrayHole0(i); 309 arrayAlloc0(i); 310 arrayAlloc1(i); 311 arrayAlloc2(i); 312 arrayAlloc3(i); 313 } 314 315 for (var i = 0; i < 100; i++) { 316 arrayWithGCInit0(i); 317 arrayWithGCInit1(i); 318 arrayWithGCInit2(i); 319 } 320 321 // If arr[1] is not defined, then we fallback on the prototype which instead of 322 // returning undefined, returns "0". 323 Object.defineProperty(Array.prototype, 1, { 324 value: 100, 325 configurable: true, 326 enumerable: true, 327 writable: true 328 }); 329 330 for (var i = 0; i < 100; i++) { 331 arrayHole1(i); 332 }