1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 public class Main { 18 19 /// CHECK-START: int Main.sieve(int) BCE (before) 20 /// CHECK: BoundsCheck 21 /// CHECK: ArraySet 22 /// CHECK: BoundsCheck 23 /// CHECK: ArrayGet 24 /// CHECK: BoundsCheck 25 /// CHECK: ArraySet 26 27 /// CHECK-START: int Main.sieve(int) BCE (after) 28 /// CHECK-NOT: BoundsCheck 29 /// CHECK: ArraySet 30 /// CHECK-NOT: BoundsCheck 31 /// CHECK: ArrayGet 32 /// CHECK: BoundsCheck 33 /// CHECK: ArraySet 34 sieve(int size)35 static int sieve(int size) { 36 int primeCount = 0; 37 boolean[] flags = new boolean[size + 1]; 38 for (int i = 1; i < size; i++) flags[i] = true; // Can eliminate. 39 for (int i = 2; i < size; i++) { 40 if (flags[i]) { // Can eliminate. 41 primeCount++; 42 for (int k = i + 1; k <= size; k += i) 43 flags[k - 1] = false; // Can't eliminate yet due to (k+i) may overflow. 44 } 45 } 46 return primeCount; 47 } 48 49 50 /// CHECK-START: void Main.narrow(int[], int) BCE (before) 51 /// CHECK: BoundsCheck 52 /// CHECK: ArraySet 53 /// CHECK: BoundsCheck 54 /// CHECK: ArraySet 55 /// CHECK: BoundsCheck 56 /// CHECK: ArraySet 57 58 /// CHECK-START: void Main.narrow(int[], int) BCE (after) 59 /// CHECK-NOT: BoundsCheck 60 /// CHECK: ArraySet 61 /// CHECK-NOT: BoundsCheck 62 /// CHECK: ArraySet 63 /// CHECK: BoundsCheck 64 /// CHECK: ArraySet 65 /// CHECK-NOT: BoundsCheck 66 /// CHECK: ArraySet 67 /// CHECK: BoundsCheck 68 /// CHECK: ArraySet 69 narrow(int[] array, int offset)70 static void narrow(int[] array, int offset) { 71 if (offset < 0) { 72 return; 73 } 74 if (offset < array.length) { 75 // offset is in range [0, array.length-1]. 76 // Bounds check can be eliminated. 77 array[offset] = 1; 78 79 int biased_offset1 = offset + 1; 80 // biased_offset1 is in range [1, array.length]. 81 if (biased_offset1 < array.length) { 82 // biased_offset1 is in range [1, array.length-1]. 83 // Bounds check can be eliminated. 84 array[biased_offset1] = 1; 85 } 86 87 int biased_offset2 = offset + 0x70000000; 88 // biased_offset2 is in range [0x70000000, array.length-1+0x70000000]. 89 // It may overflow and be negative. 90 if (biased_offset2 < array.length) { 91 // Even with this test, biased_offset2 can be negative so we can't 92 // eliminate this bounds check. 93 array[biased_offset2] = 1; 94 } 95 96 // offset_sub1 won't underflow since offset is no less than 0. 97 int offset_sub1 = offset - Integer.MAX_VALUE; 98 if (offset_sub1 >= 0) { 99 array[offset_sub1] = 1; // Bounds check can be eliminated. 100 } 101 102 // offset_sub2 can underflow. 103 int offset_sub2 = offset_sub1 - Integer.MAX_VALUE; 104 if (offset_sub2 >= 0) { 105 array[offset_sub2] = 1; // Bounds check can't be eliminated. 106 } 107 } 108 } 109 110 111 /// CHECK-START: void Main.constantIndexing1(int[]) BCE (before) 112 /// CHECK: BoundsCheck 113 /// CHECK: ArraySet 114 /// CHECK: BoundsCheck 115 /// CHECK: ArraySet 116 117 /// CHECK-START: void Main.constantIndexing1(int[]) BCE (after) 118 /// CHECK-NOT: Deoptimize 119 /// CHECK: BoundsCheck 120 /// CHECK: ArraySet 121 /// CHECK-NOT: BoundsCheck 122 /// CHECK: ArraySet 123 constantIndexing1(int[] array)124 static void constantIndexing1(int[] array) { 125 // Decreasing order: bc for 5 but not for 4. 126 array[5] = 11; 127 array[4] = 11; 128 } 129 130 131 /// CHECK-START: void Main.$opt$noinline$constantIndexing2(int[]) BCE (before) 132 /// CHECK: BoundsCheck 133 /// CHECK: ArraySet 134 /// CHECK: BoundsCheck 135 /// CHECK: ArraySet 136 /// CHECK: BoundsCheck 137 /// CHECK: ArraySet 138 /// CHECK: BoundsCheck 139 /// CHECK: ArraySet 140 141 /// CHECK-START: void Main.$opt$noinline$constantIndexing2(int[]) BCE (after) 142 /// CHECK: Deoptimize 143 /// CHECK-NOT: BoundsCheck 144 /// CHECK: ArraySet 145 /// CHECK-NOT: BoundsCheck 146 /// CHECK: ArraySet 147 /// CHECK-NOT: BoundsCheck 148 /// CHECK: ArraySet 149 /// CHECK-NOT: BoundsCheck 150 /// CHECK: ArraySet 151 $opt$noinline$constantIndexing2(int[] array)152 static void $opt$noinline$constantIndexing2(int[] array) { 153 array[1] = 1; 154 array[2] = 1; 155 array[3] = 1; 156 array[4] = 1; 157 if (array[1] != 1) { 158 throw new Error(""); 159 } 160 } 161 162 /// CHECK-START: void Main.constantIndexing2b(int[]) BCE (before) 163 /// CHECK: BoundsCheck 164 /// CHECK: ArraySet 165 /// CHECK: BoundsCheck 166 /// CHECK: ArraySet 167 /// CHECK: BoundsCheck 168 /// CHECK: ArraySet 169 /// CHECK: BoundsCheck 170 /// CHECK: ArraySet 171 /// CHECK: BoundsCheck 172 /// CHECK: ArraySet 173 174 /// CHECK-START: void Main.constantIndexing2b(int[]) BCE (after) 175 /// CHECK-NOT: Deoptimize 176 /// CHECK: BoundsCheck 177 /// CHECK: ArraySet 178 /// CHECK: BoundsCheck 179 /// CHECK: ArraySet 180 /// CHECK: BoundsCheck 181 /// CHECK: ArraySet 182 /// CHECK: BoundsCheck 183 /// CHECK: ArraySet 184 /// CHECK: BoundsCheck 185 /// CHECK: ArraySet 186 constantIndexing2b(int[] array)187 static void constantIndexing2b(int[] array) { 188 array[0] = 6; 189 array[1] = 6; 190 array[2] = 6; 191 array[3] = 6; 192 array[-1] = 1; // prevents the whole opt on [-1:4] 193 } 194 195 /// CHECK-START: void Main.constantIndexing2c(int[]) BCE (before) 196 /// CHECK: BoundsCheck 197 /// CHECK: ArraySet 198 /// CHECK: BoundsCheck 199 /// CHECK: ArraySet 200 /// CHECK: BoundsCheck 201 /// CHECK: ArraySet 202 /// CHECK: BoundsCheck 203 /// CHECK: ArraySet 204 205 /// CHECK-START: void Main.constantIndexing2c(int[]) BCE (after) 206 /// CHECK: Deoptimize 207 /// CHECK-NOT: BoundsCheck 208 /// CHECK: ArraySet 209 /// CHECK-NOT: BoundsCheck 210 /// CHECK: ArraySet 211 /// CHECK-NOT: BoundsCheck 212 /// CHECK: ArraySet 213 /// CHECK-NOT: BoundsCheck 214 /// CHECK: ArraySet 215 constantIndexing2c(int[] array)216 static void constantIndexing2c(int[] array) { 217 array[0] = 7; 218 array[1] = 7; 219 array[2] = 7; 220 array[3] = 7; 221 } 222 223 /// CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (before) 224 /// CHECK: BoundsCheck 225 /// CHECK: ArrayGet 226 /// CHECK: BoundsCheck 227 /// CHECK: ArraySet 228 /// CHECK: BoundsCheck 229 /// CHECK: ArrayGet 230 /// CHECK: BoundsCheck 231 /// CHECK: ArraySet 232 /// CHECK: BoundsCheck 233 /// CHECK: ArrayGet 234 /// CHECK: BoundsCheck 235 /// CHECK: ArraySet 236 /// CHECK: BoundsCheck 237 /// CHECK: ArrayGet 238 /// CHECK: BoundsCheck 239 /// CHECK: ArraySet 240 241 /// CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (after) 242 /// CHECK: Deoptimize 243 /// CHECK-NOT: BoundsCheck 244 /// CHECK: ArrayGet 245 /// CHECK: Deoptimize 246 /// CHECK-NOT: BoundsCheck 247 /// CHECK: ArraySet 248 /// CHECK-NOT: BoundsCheck 249 /// CHECK: ArrayGet 250 /// CHECK-NOT: BoundsCheck 251 /// CHECK: ArraySet 252 /// CHECK-NOT: BoundsCheck 253 /// CHECK: ArrayGet 254 /// CHECK-NOT: BoundsCheck 255 /// CHECK: ArraySet 256 /// CHECK-NOT: BoundsCheck 257 /// CHECK: ArrayGet 258 /// CHECK-NOT: BoundsCheck 259 /// CHECK: ArraySet 260 constantIndexing3(int[] array1, int[] array2, boolean copy)261 static int[] constantIndexing3(int[] array1, int[] array2, boolean copy) { 262 if (!copy) { 263 return array1; 264 } 265 array2[0] = array1[0]; 266 array2[1] = array1[1]; 267 array2[2] = array1[2]; 268 array2[3] = array1[3]; 269 return array2; 270 } 271 272 273 /// CHECK-START: void Main.constantIndexing4(int[]) BCE (before) 274 /// CHECK: BoundsCheck 275 /// CHECK: ArraySet 276 277 /// CHECK-START: void Main.constantIndexing4(int[]) BCE (after) 278 /// CHECK-NOT: Deoptimize 279 /// CHECK: BoundsCheck 280 /// CHECK: ArraySet 281 282 // There is only one array access. It's not beneficial 283 // to create a compare with deoptimization instruction. constantIndexing4(int[] array)284 static void constantIndexing4(int[] array) { 285 array[0] = -1; 286 } 287 288 289 /// CHECK-START: void Main.constantIndexing5(int[]) BCE (before) 290 /// CHECK: BoundsCheck 291 /// CHECK: ArraySet 292 /// CHECK: BoundsCheck 293 /// CHECK: ArraySet 294 295 /// CHECK-START: void Main.constantIndexing5(int[]) BCE (after) 296 /// CHECK-NOT: Deoptimize 297 /// CHECK: BoundsCheck 298 /// CHECK: ArraySet 299 /// CHECK: BoundsCheck 300 /// CHECK: ArraySet 301 constantIndexing5(int[] array)302 static void constantIndexing5(int[] array) { 303 // We don't apply the deoptimization for very large constant index 304 // since it's likely to be an anomaly and will throw AIOOBE. 305 array[Integer.MAX_VALUE - 1000] = 1; 306 array[Integer.MAX_VALUE - 999] = 1; 307 array[Integer.MAX_VALUE - 998] = 1; 308 } 309 310 /// CHECK-START: void Main.constantIndexing6(int[]) BCE (before) 311 /// CHECK: BoundsCheck 312 /// CHECK: ArraySet 313 /// CHECK: BoundsCheck 314 /// CHECK: ArraySet 315 316 /// CHECK-START: void Main.constantIndexing6(int[]) BCE (after) 317 /// CHECK: Deoptimize 318 /// CHECK-NOT: BoundsCheck 319 /// CHECK: ArraySet 320 /// CHECK-NOT: BoundsCheck 321 /// CHECK: ArraySet 322 constantIndexing6(int[] array)323 static void constantIndexing6(int[] array) { 324 array[3] = 111; 325 array[4] = 111; 326 } 327 328 /// CHECK-START: void Main.constantIndexing7(int[], int) BCE (before) 329 /// CHECK: BoundsCheck 330 /// CHECK: ArraySet 331 /// CHECK: BoundsCheck 332 /// CHECK: ArraySet 333 /// CHECK: BoundsCheck 334 /// CHECK: ArraySet 335 /// CHECK: BoundsCheck 336 /// CHECK: ArraySet 337 338 /// CHECK-START: void Main.constantIndexing7(int[], int) BCE (after) 339 /// CHECK: Deoptimize 340 /// CHECK: Deoptimize 341 /// CHECK-NOT: BoundsCheck 342 /// CHECK: ArraySet 343 /// CHECK-NOT: BoundsCheck 344 /// CHECK: ArraySet 345 /// CHECK-NOT: BoundsCheck 346 /// CHECK: ArraySet 347 /// CHECK-NOT: BoundsCheck 348 /// CHECK: ArraySet 349 constantIndexing7(int[] array, int base)350 static void constantIndexing7(int[] array, int base) { 351 // With constant offsets to symbolic base. 352 array[base] = 10; 353 array[base + 1] = 20; 354 array[base + 2] = 30; 355 array[base + 3] = 40; 356 } 357 358 /// CHECK-START: void Main.constantIndexing8(int[], int) BCE (before) 359 /// CHECK: BoundsCheck 360 /// CHECK: ArraySet 361 /// CHECK: BoundsCheck 362 /// CHECK: ArraySet 363 /// CHECK: BoundsCheck 364 /// CHECK: ArraySet 365 /// CHECK: BoundsCheck 366 /// CHECK: ArraySet 367 368 /// CHECK-START: void Main.constantIndexing8(int[], int) BCE (after) 369 /// CHECK: Deoptimize 370 /// CHECK: Deoptimize 371 /// CHECK-NOT: BoundsCheck 372 /// CHECK: ArraySet 373 /// CHECK-NOT: BoundsCheck 374 /// CHECK: ArraySet 375 /// CHECK-NOT: BoundsCheck 376 /// CHECK: ArraySet 377 /// CHECK-NOT: BoundsCheck 378 /// CHECK: ArraySet 379 constantIndexing8(int[] array, int base)380 static void constantIndexing8(int[] array, int base) { 381 // With constant offsets "both ways" to symbolic base. 382 array[base - 1] = 100; 383 array[base] = 200; 384 array[base + 1] = 300; 385 array[base + 2] = 400; 386 } 387 388 /// CHECK-START: void Main.constantIndexing9(int[], int) BCE (before) 389 /// CHECK: BoundsCheck 390 /// CHECK: ArraySet 391 /// CHECK: BoundsCheck 392 /// CHECK: ArraySet 393 /// CHECK: BoundsCheck 394 /// CHECK: ArraySet 395 /// CHECK: BoundsCheck 396 /// CHECK: ArraySet 397 398 /// CHECK-START: void Main.constantIndexing9(int[], int) BCE (after) 399 /// CHECK: Deoptimize 400 /// CHECK: Deoptimize 401 /// CHECK-NOT: BoundsCheck 402 /// CHECK: ArraySet 403 /// CHECK-NOT: BoundsCheck 404 /// CHECK: ArraySet 405 /// CHECK-NOT: BoundsCheck 406 /// CHECK: ArraySet 407 /// CHECK-NOT: BoundsCheck 408 /// CHECK: ArraySet 409 /// CHECK-NOT: BoundsCheck 410 constantIndexing9(int[] array, int base)411 static void constantIndexing9(int[] array, int base) { 412 // Final range is base..base+3 so conditional 413 // references may be included in the end. 414 array[base] = 0; 415 if (base != 12345) 416 array[base + 2] = 2; 417 array[base + 3] = 3; 418 if (base != 67890) 419 array[base + 1] = 1; 420 } 421 422 /// CHECK-START: void Main.constantIndexing10(int[], int) BCE (before) 423 /// CHECK: BoundsCheck 424 /// CHECK: ArraySet 425 /// CHECK: BoundsCheck 426 /// CHECK: ArraySet 427 /// CHECK: BoundsCheck 428 /// CHECK: ArraySet 429 /// CHECK: BoundsCheck 430 /// CHECK: ArraySet 431 432 /// CHECK-START: void Main.constantIndexing10(int[], int) BCE (after) 433 /// CHECK: Deoptimize 434 /// CHECK: Deoptimize 435 /// CHECK-NOT: BoundsCheck 436 /// CHECK: ArraySet 437 /// CHECK-NOT: BoundsCheck 438 /// CHECK: ArraySet 439 /// CHECK-NOT: BoundsCheck 440 /// CHECK: ArraySet 441 /// CHECK-NOT: BoundsCheck 442 /// CHECK: ArraySet 443 constantIndexing10(int[] array, int base)444 static void constantIndexing10(int[] array, int base) { 445 // Offset hidden in incremented base. 446 array[base] = 1; 447 array[++base] = 2; 448 array[++base] = 3; 449 array[++base] = 4; 450 } 451 runAllConstantIndices()452 static void runAllConstantIndices() { 453 int[] a1 = { 0 }; 454 int[] a6 = { 0, 0, 0, 0, 0, 0 }; 455 456 boolean caught = false; 457 try { 458 constantIndexing1(a1); 459 } catch (ArrayIndexOutOfBoundsException e) { 460 caught = true; 461 } 462 if (!caught) { 463 System.out.println("constant indices 1 failed!"); 464 } 465 466 constantIndexing1(a6); 467 if (a6[4] != 11 || a6[5] != 11) { 468 System.out.println("constant indices 1 failed!"); 469 } 470 471 $opt$noinline$constantIndexing2(a6); 472 if (a6[0] != 0 || a6[1] != 1 || a6[2] != 1 || 473 a6[3] != 1 || a6[4] != 1 || a6[5] != 11) { 474 System.out.println("constant indices 2 failed!"); 475 } 476 477 caught = false; 478 try { 479 constantIndexing2b(a6); 480 } catch (ArrayIndexOutOfBoundsException e) { 481 caught = true; 482 } 483 if (!caught || a6[0] != 6 || a6[1] != 6 || a6[2] != 6 || 484 a6[3] != 6 || a6[4] != 1 || a6[5] != 11) { 485 System.out.println("constant indices 2b failed!"); 486 } 487 488 caught = false; 489 try { 490 constantIndexing2c(a1); 491 } catch (ArrayIndexOutOfBoundsException e) { 492 caught = true; 493 } 494 if (!caught || a1[0] != 7) { 495 System.out.println("constant indices 2c failed!"); 496 } 497 498 constantIndexing2c(a6); 499 if (a6[0] != 7 || a6[1] != 7 || a6[2] != 7 || 500 a6[3] != 7 || a6[4] != 1 || a6[5] != 11) { 501 System.out.println("constant indices 2c failed!"); 502 } 503 504 int[] b4 = new int[4]; 505 constantIndexing3(a6, b4, true); 506 if (b4[0] != 7 || b4[1] != 7 || b4[2] != 7 || b4[3] != 7) { 507 System.out.println("constant indices 3 failed!"); 508 } 509 510 constantIndexing4(a1); 511 if (a1[0] != -1) { 512 System.out.println("constant indices 4 failed!"); 513 } 514 515 caught = false; 516 try { 517 constantIndexing5(a6); 518 } catch (ArrayIndexOutOfBoundsException e) { 519 caught = true; 520 } 521 if (!caught) { 522 System.out.println("constant indices 5 failed!"); 523 } 524 525 constantIndexing6(a6); 526 if (a6[0] != 7 || a6[1] != 7 || a6[2] != 7 || 527 a6[3] != 111 || a6[4] != 111 || a6[5] != 11) { 528 System.out.println("constant indices 6 failed!"); 529 } 530 531 constantIndexing7(a6, 1); 532 if (a6[0] != 7 || a6[1] != 10 || a6[2] != 20 || 533 a6[3] != 30 || a6[4] != 40 || a6[5] != 11) { 534 System.out.println("constant indices 7 failed!"); 535 } 536 537 caught = false; 538 try { 539 constantIndexing7(a6, 5); 540 } catch (ArrayIndexOutOfBoundsException e) { 541 caught = true; 542 } 543 if (!caught || a6[0] != 7 || a6[1] != 10 || a6[2] != 20 || 544 a6[3] != 30 || a6[4] != 40 || a6[5] != 10) { 545 System.out.println("constant indices 7 failed!"); 546 } 547 548 constantIndexing8(a6, 1); 549 if (a6[0] != 100 || a6[1] != 200 || a6[2] != 300 || 550 a6[3] != 400 || a6[4] != 40 || a6[5] != 10) { 551 System.out.println("constant indices 8 failed!"); 552 } 553 554 caught = false; 555 try { 556 constantIndexing8(a6, 0); 557 } catch (ArrayIndexOutOfBoundsException e) { 558 caught = true; 559 } 560 if (!caught || a6[0] != 100) { 561 System.out.println("constant indices 8 failed!"); 562 } 563 564 constantIndexing9(a6, 0); 565 if (a6[0] != 0 || a6[1] != 1 || a6[2] != 2 || 566 a6[3] != 3 || a6[4] != 40 || a6[5] != 10) { 567 System.out.println("constant indices 9 failed!"); 568 } 569 570 constantIndexing10(a6, 0); 571 if (a6[0] != 1 || a6[1] != 2 || a6[2] != 3 || 572 a6[3] != 4 || a6[4] != 40 || a6[5] != 10) { 573 System.out.println("constant indices 10 failed!"); 574 } 575 } 576 577 // A helper into which the actual throwing function should be inlined. constantIndexingForward6(int[] array)578 static void constantIndexingForward6(int[] array) { 579 assertIsManaged(); 580 constantIndexing6(array); 581 } 582 583 /// CHECK-START: void Main.loopPattern1(int[]) BCE (before) 584 /// CHECK: BoundsCheck 585 /// CHECK: ArraySet 586 /// CHECK: BoundsCheck 587 /// CHECK: ArraySet 588 /// CHECK: BoundsCheck 589 /// CHECK: ArraySet 590 /// CHECK: BoundsCheck 591 /// CHECK: ArraySet 592 /// CHECK: BoundsCheck 593 /// CHECK: ArraySet 594 /// CHECK: BoundsCheck 595 /// CHECK: ArraySet 596 /// CHECK: BoundsCheck 597 /// CHECK: ArraySet 598 599 /// CHECK-START: void Main.loopPattern1(int[]) BCE (after) 600 /// CHECK-NOT: BoundsCheck 601 /// CHECK: ArraySet 602 /// CHECK-NOT: BoundsCheck 603 /// CHECK: ArraySet 604 /// CHECK-NOT: BoundsCheck 605 /// CHECK: ArraySet 606 /// CHECK: BoundsCheck 607 /// CHECK: ArraySet 608 /// CHECK: BoundsCheck 609 /// CHECK: ArraySet 610 /// CHECK: BoundsCheck 611 /// CHECK: ArraySet 612 /// CHECK-NOT: BoundsCheck 613 /// CHECK: ArraySet 614 loopPattern1(int[] array)615 static void loopPattern1(int[] array) { 616 for (int i = 0; i < array.length; i++) { 617 array[i] = 1; // Bounds check can be eliminated. 618 } 619 620 for (int i = 1; i < array.length; i++) { 621 array[i] = 1; // Bounds check can be eliminated. 622 } 623 624 for (int i = 1; i < array.length - 1; i++) { 625 array[i] = 1; // Bounds check can be eliminated. 626 } 627 628 for (int i = -1; i < array.length; i++) { 629 array[i] = 1; // Bounds check can't be eliminated. 630 } 631 632 for (int i = 0; i <= array.length; i++) { 633 array[i] = 1; // Bounds check can't be eliminated. 634 } 635 636 for (int i = 0; i < array.length; i += 2) { 637 // We don't have any assumption on max array length yet. 638 // Bounds check can't be eliminated due to overflow concern. 639 array[i] = 1; 640 } 641 642 for (int i = 1; i < array.length; i += 2) { 643 // Bounds check can be eliminated since i is odd so the last 644 // i that's less than array.length is at most (Integer.MAX_VALUE - 2). 645 array[i] = 1; 646 } 647 } 648 649 650 /// CHECK-START: void Main.loopPattern2(int[]) BCE (before) 651 /// CHECK: BoundsCheck 652 /// CHECK: ArraySet 653 /// CHECK: BoundsCheck 654 /// CHECK: ArraySet 655 /// CHECK: BoundsCheck 656 /// CHECK: ArraySet 657 /// CHECK: BoundsCheck 658 /// CHECK: ArraySet 659 /// CHECK: BoundsCheck 660 /// CHECK: ArraySet 661 /// CHECK: BoundsCheck 662 /// CHECK: ArraySet 663 664 /// CHECK-START: void Main.loopPattern2(int[]) BCE (after) 665 /// CHECK-NOT: BoundsCheck 666 /// CHECK: ArraySet 667 /// CHECK-NOT: BoundsCheck 668 /// CHECK: ArraySet 669 /// CHECK-NOT: BoundsCheck 670 /// CHECK: ArraySet 671 /// CHECK: BoundsCheck 672 /// CHECK: ArraySet 673 /// CHECK: BoundsCheck 674 /// CHECK: ArraySet 675 /// CHECK-NOT: BoundsCheck 676 /// CHECK: ArraySet 677 loopPattern2(int[] array)678 static void loopPattern2(int[] array) { 679 for (int i = array.length - 1; i >= 0; i--) { 680 array[i] = 1; // Bounds check can be eliminated. 681 } 682 683 for (int i = array.length; i > 0; i--) { 684 array[i - 1] = 1; // Bounds check can be eliminated. 685 } 686 687 for (int i = array.length - 1; i > 0; i--) { 688 array[i] = 1; // Bounds check can be eliminated. 689 } 690 691 for (int i = array.length; i >= 0; i--) { 692 array[i] = 1; // Bounds check can't be eliminated. 693 } 694 695 for (int i = array.length; i >= 0; i--) { 696 array[i - 1] = 1; // Bounds check can't be eliminated. 697 } 698 699 for (int i = array.length; i > 0; i -= 20) { 700 // For i >= 0, (i - 20 - 1) is guaranteed not to underflow. 701 array[i - 1] = 1; // Bounds check can be eliminated. 702 } 703 } 704 705 706 /// CHECK-START: void Main.loopPattern3(int[]) BCE (before) 707 /// CHECK: BoundsCheck 708 /// CHECK: ArraySet 709 710 /// CHECK-START: void Main.loopPattern3(int[]) BCE (after) 711 /// CHECK: BoundsCheck 712 /// CHECK: ArraySet 713 loopPattern3(int[] array)714 static void loopPattern3(int[] array) { 715 java.util.Random random = new java.util.Random(); 716 for (int i = 0; ; i++) { 717 if (random.nextInt() % 1000 == 0 && i < array.length) { 718 // Can't eliminate the bound check since not every i++ is 719 // matched with a array length check, so there is some chance that i 720 // overflows and is negative. 721 array[i] = 1; 722 } 723 } 724 } 725 726 727 /// CHECK-START: void Main.constantNewArray() BCE (before) 728 /// CHECK: BoundsCheck 729 /// CHECK: ArraySet 730 /// CHECK: BoundsCheck 731 /// CHECK: ArraySet 732 /// CHECK: BoundsCheck 733 /// CHECK: ArraySet 734 /// CHECK: BoundsCheck 735 /// CHECK: ArraySet 736 /// CHECK: BoundsCheck 737 /// CHECK: ArraySet 738 739 /// CHECK-START: void Main.constantNewArray() BCE (after) 740 /// CHECK-NOT: BoundsCheck 741 /// CHECK: ArraySet 742 /// CHECK: BoundsCheck 743 /// CHECK: ArraySet 744 /// CHECK-NOT: BoundsCheck 745 /// CHECK: ArraySet 746 /// CHECK-NOT: BoundsCheck 747 /// CHECK: ArraySet 748 /// CHECK: BoundsCheck 749 /// CHECK: ArraySet 750 constantNewArray()751 static void constantNewArray() { 752 int[] array = new int[10]; 753 for (int i = 0; i < 10; i++) { 754 array[i] = 1; // Bounds check can be eliminated. 755 } 756 757 for (int i = 0; i <= 10; i++) { 758 array[i] = 1; // Bounds check can't be eliminated. 759 } 760 761 array[0] = 1; // Bounds check can be eliminated. 762 array[9] = 1; // Bounds check can be eliminated. 763 array[10] = 1; // Bounds check can't be eliminated. 764 } 765 766 readData()767 static byte readData() { 768 return 1; 769 } 770 771 /// CHECK-START: void Main.circularBufferProducer() BCE (before) 772 /// CHECK: BoundsCheck 773 /// CHECK: ArraySet 774 775 /// CHECK-START: void Main.circularBufferProducer() BCE (after) 776 /// CHECK-NOT: BoundsCheck 777 /// CHECK: ArraySet 778 circularBufferProducer()779 static void circularBufferProducer() { 780 byte[] array = new byte[4096]; 781 int i = 0; 782 while (true) { 783 array[i & (array.length - 1)] = readData(); 784 i++; 785 } 786 } 787 788 789 /// CHECK-START: void Main.pyramid1(int[]) BCE (before) 790 /// CHECK: BoundsCheck 791 /// CHECK: ArraySet 792 /// CHECK: BoundsCheck 793 /// CHECK: ArraySet 794 795 /// CHECK-START: void Main.pyramid1(int[]) BCE (after) 796 /// CHECK-NOT: BoundsCheck 797 /// CHECK: ArraySet 798 /// CHECK-NOT: BoundsCheck 799 /// CHECK: ArraySet 800 801 // Set array to something like {0, 1, 2, 3, 2, 1, 0}. pyramid1(int[] array)802 static void pyramid1(int[] array) { 803 for (int i = 0; i < (array.length + 1) / 2; i++) { 804 array[i] = i; 805 array[array.length - 1 - i] = i; 806 } 807 } 808 809 810 /// CHECK-START: void Main.pyramid2(int[]) BCE (before) 811 /// CHECK: BoundsCheck 812 /// CHECK: ArraySet 813 /// CHECK: BoundsCheck 814 /// CHECK: ArraySet 815 816 /// CHECK-START: void Main.pyramid2(int[]) BCE (after) 817 /// CHECK-NOT: BoundsCheck 818 /// CHECK: ArraySet 819 /// CHECK-NOT: BoundsCheck 820 /// CHECK: ArraySet 821 822 // Set array to something like {0, 1, 2, 3, 2, 1, 0}. pyramid2(int[] array)823 static void pyramid2(int[] array) { 824 for (int i = 0; i < (array.length + 1) >> 1; i++) { 825 array[i] = i; 826 array[array.length - 1 - i] = i; 827 } 828 } 829 830 831 /// CHECK-START: void Main.pyramid3(int[]) BCE (before) 832 /// CHECK: BoundsCheck 833 /// CHECK: ArraySet 834 /// CHECK: BoundsCheck 835 /// CHECK: ArraySet 836 837 /// CHECK-START: void Main.pyramid3(int[]) BCE (after) 838 /// CHECK-NOT: BoundsCheck 839 /// CHECK: ArraySet 840 /// CHECK-NOT: BoundsCheck 841 /// CHECK: ArraySet 842 843 // Set array to something like {0, 1, 2, 3, 2, 1, 0}. pyramid3(int[] array)844 static void pyramid3(int[] array) { 845 for (int i = 0; i < (array.length + 1) >>> 1; i++) { 846 array[i] = i; 847 array[array.length - 1 - i] = i; 848 } 849 } 850 851 852 /// CHECK-START: boolean Main.isPyramid(int[]) BCE (before) 853 /// CHECK: BoundsCheck 854 /// CHECK: ArrayGet 855 /// CHECK: BoundsCheck 856 /// CHECK: ArrayGet 857 858 /// CHECK-START: boolean Main.isPyramid(int[]) BCE (after) 859 /// CHECK-NOT: BoundsCheck 860 /// CHECK: ArrayGet 861 /// CHECK-NOT: BoundsCheck 862 /// CHECK: ArrayGet 863 isPyramid(int[] array)864 static boolean isPyramid(int[] array) { 865 int i = 0; 866 int j = array.length - 1; 867 while (i <= j) { 868 if (array[i] != i) { 869 return false; 870 } 871 if (array[j] != i) { 872 return false; 873 } 874 i++; j--; 875 } 876 return true; 877 } 878 879 880 /// CHECK-START: void Main.bubbleSort(int[]) GVN (before) 881 /// CHECK: BoundsCheck 882 /// CHECK: ArrayGet 883 /// CHECK: BoundsCheck 884 /// CHECK: ArrayGet 885 /// CHECK: BoundsCheck 886 /// CHECK: ArrayGet 887 /// CHECK: BoundsCheck 888 /// CHECK: ArrayGet 889 /// CHECK: BoundsCheck 890 /// CHECK: ArraySet 891 /// CHECK: BoundsCheck 892 /// CHECK: ArraySet 893 894 /// CHECK-START: void Main.bubbleSort(int[]) GVN (after) 895 /// CHECK: BoundsCheck 896 /// CHECK: ArrayGet 897 /// CHECK: BoundsCheck 898 /// CHECK: ArrayGet 899 /// CHECK-NOT: ArrayGet 900 /// CHECK-NOT: ArrayGet 901 /// CHECK-NOT: BoundsCheck 902 /// CHECK: ArraySet 903 /// CHECK-NOT: BoundsCheck 904 /// CHECK: ArraySet 905 906 /// CHECK-START: void Main.bubbleSort(int[]) BCE (after) 907 /// CHECK-NOT: BoundsCheck 908 /// CHECK: ArrayGet 909 /// CHECK-NOT: BoundsCheck 910 /// CHECK: ArrayGet 911 /// CHECK-NOT: ArrayGet 912 /// CHECK-NOT: ArrayGet 913 /// CHECK-NOT: BoundsCheck 914 /// CHECK: ArraySet 915 /// CHECK-NOT: BoundsCheck 916 /// CHECK: ArraySet 917 bubbleSort(int[] array)918 static void bubbleSort(int[] array) { 919 for (int i = 0; i < array.length - 1; i++) { 920 for (int j = 0; j < array.length - i - 1; j++) { 921 if (array[j] > array[j + 1]) { 922 int temp = array[j + 1]; 923 array[j + 1] = array[j]; 924 array[j] = temp; 925 } 926 } 927 } 928 } 929 930 /// CHECK-START: void Main.nonzeroLength(int[]) BCE (before) 931 /// CHECK-DAG: BoundsCheck 932 // 933 /// CHECK-START: void Main.nonzeroLength(int[]) BCE (after) 934 /// CHECK-NOT: BoundsCheck 935 /// CHECK-NOT: Deoptimize nonzeroLength(int[] a)936 public static void nonzeroLength(int[] a) { 937 if (a.length != 0) { 938 a[0] = 112; 939 } 940 } 941 942 /// CHECK-START: void Main.knownLength(int[]) BCE (before) 943 /// CHECK-DAG: BoundsCheck 944 /// CHECK-DAG: BoundsCheck 945 // 946 /// CHECK-START: void Main.knownLength(int[]) BCE (after) 947 /// CHECK-NOT: BoundsCheck 948 /// CHECK-NOT: Deoptimize knownLength(int[] a)949 public static void knownLength(int[] a) { 950 if (a.length == 2) { 951 a[0] = -1; 952 a[1] = -2; 953 } 954 } 955 956 static int[][] mA; 957 958 /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (before) 959 // Array references mA[i] and ..[j] both in inner loop. 960 /// CHECK-DAG: <<Get1:l\d+>> ArrayGet [<<Array1:l\d+>>,<<Bounds1:i\d+>>] loop:<<InnerLoop:B\d+>> 961 /// CHECK-DAG: <<Array1>> NullCheck [<<Field1:l\d+>>] loop:<<InnerLoop>> 962 /// CHECK-DAG: <<Len1:i\d+>> ArrayLength [<<Array1>>] loop:<<InnerLoop>> 963 /// CHECK-DAG: <<Bounds1>> BoundsCheck [<<Index1:i\d+>>,<<Len1>>] loop:<<InnerLoop>> 964 /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [<<Array2:l\d+>>,<<Bounds2:i\d+>>] loop:<<InnerLoop>> 965 /// CHECK-DAG: <<Array2>> NullCheck [<<Get1>>] loop:<<InnerLoop>> 966 /// CHECK-DAG: <<Len2:i\d+>> ArrayLength [<<Array2>>] loop:<<InnerLoop>> 967 /// CHECK-DAG: <<Bounds2>> BoundsCheck [<<Index2:i\d+>>,<<Len2>>] loop:<<InnerLoop>> 968 // Note: The ArtMethod* (typed as int or long) is optional after sharpening. 969 /// CHECK-DAG: InvokeStaticOrDirect [<<Get2>>{{(,[ij]\d+)?}}] loop:<<InnerLoop>> 970 /// CHECK-DAG: <<Index2>> Phi loop:<<InnerLoop>> 971 /// CHECK-DAG: <<Index1>> Phi loop:<<OuterLoop:B\d+>> 972 /// CHECK-DAG: <<Field1>> StaticFieldGet loop:none 973 /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>" 974 // 975 /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (after) 976 // Array reference mA[i] hoisted to same level as deopt. 977 /// CHECK-DAG: Deoptimize loop:<<OuterLoop:B\d+>> 978 /// CHECK-DAG: ArrayLength loop:<<OuterLoop>> 979 /// CHECK-DAG: <<Get1:l\d+>> ArrayGet [<<Array1:l\d+>>,<<Index1:i\d+>>] loop:<<OuterLoop>> 980 // Array reference ..[j] still in inner loop, with a direct index. 981 /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [<<Array2:l\d+>>,<<Index2:i\d+>>] loop:<<InnerLoop:B\d+>> 982 // Note: The ArtMethod* (typed as int or long) is optional after sharpening. 983 /// CHECK-DAG: InvokeStaticOrDirect [<<Get2>>{{(,[ij]\d+)?}}] loop:<<InnerLoop>> 984 /// CHECK-DAG: <<Index2>> Phi loop:<<InnerLoop>> 985 /// CHECK-DAG: <<Index1>> Phi loop:<<OuterLoop>> 986 // Synthetic phi. 987 /// CHECK-DAG: <<Array2>> Phi loop:<<OuterLoop>> 988 /// CHECK-DAG: <<Array1>> StaticFieldGet loop:none 989 /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>" 990 // 991 /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (after) 992 /// CHECK-NOT: NullCheck 993 /// CHECK-NOT: BoundsCheck dynamicBCEAndIntrinsic(int n)994 static void dynamicBCEAndIntrinsic(int n) { 995 for (int i = 0; i < n; i++) { 996 for (int j = 0; j < n; j++) { 997 // Since intrinsic call cannot modify fields or arrays, 998 // dynamic BCE and hoisting can be applied to the inner loop. 999 mA[i][j] = Math.abs(mA[i][j]); 1000 } 1001 } 1002 } 1003 foo()1004 static int foo() { 1005 try { 1006 assertIsManaged(); 1007 // This will cause AIOOBE. 1008 $opt$noinline$constantIndexing2(new int[3]); 1009 } catch (ArrayIndexOutOfBoundsException e) { 1010 assertIsManaged(); // This is to ensure that single-frame deoptimization works. 1011 // Will need to be updated if $opt$noinline$constantIndexing2 is inlined. 1012 try { 1013 // This will cause AIOOBE. 1014 constantIndexingForward6(new int[3]); 1015 } catch (ArrayIndexOutOfBoundsException e2) { 1016 // Having deopted, we expect to be running interpreted at this point. 1017 // Does not apply to debuggable, however, since we do not inline. 1018 return 99; 1019 } 1020 } 1021 return 0; 1022 } 1023 1024 1025 int sum; 1026 1027 /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (before) 1028 /// CHECK: BoundsCheck 1029 /// CHECK: ArraySet 1030 /// CHECK-NOT: BoundsCheck 1031 /// CHECK: ArrayGet 1032 1033 /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (after) 1034 /// CHECK: Phi 1035 /// CHECK-NOT: BoundsCheck 1036 /// CHECK: ArraySet 1037 /// CHECK-NOT: BoundsCheck 1038 /// CHECK: ArrayGet 1039 // Added blocks at end for deoptimization. 1040 /// CHECK: Exit 1041 /// CHECK: If 1042 /// CHECK: Deoptimize 1043 /// CHECK: Deoptimize 1044 /// CHECK: Deoptimize 1045 /// CHECK-NOT: Deoptimize 1046 /// CHECK: Goto 1047 /// CHECK: Goto 1048 /// CHECK: Goto 1049 foo1(int[] array, int start, int end, boolean expectInterpreter)1050 void foo1(int[] array, int start, int end, boolean expectInterpreter) { 1051 if (end < 0) 1052 throw new Error(""); 1053 // Three HDeoptimize will be added. Two for the index 1054 // and one for null check on array (to hoist null 1055 // check and array.length out of loop). 1056 for (int i = start ; i < end; i++) { 1057 if (expectInterpreter) { 1058 assertIsInterpreted(); 1059 } else { 1060 assertIsManaged(); 1061 } 1062 array[i] = 1; 1063 sum += array[i]; 1064 } 1065 } 1066 1067 1068 /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (before) 1069 /// CHECK: BoundsCheck 1070 /// CHECK: ArraySet 1071 /// CHECK-NOT: BoundsCheck 1072 /// CHECK: ArrayGet 1073 /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (after) 1074 /// CHECK: Phi 1075 /// CHECK-NOT: BoundsCheck 1076 /// CHECK: ArraySet 1077 /// CHECK-NOT: BoundsCheck 1078 /// CHECK: ArrayGet 1079 // Added blocks at end for deoptimization. 1080 /// CHECK: Exit 1081 /// CHECK: If 1082 /// CHECK: Deoptimize 1083 /// CHECK: Deoptimize 1084 /// CHECK: Deoptimize 1085 /// CHECK-NOT: Deoptimize 1086 /// CHECK: Goto 1087 /// CHECK: Goto 1088 /// CHECK: Goto 1089 foo2(int[] array, int start, int end, boolean expectInterpreter)1090 void foo2(int[] array, int start, int end, boolean expectInterpreter) { 1091 if (end < 0) 1092 throw new Error(""); 1093 // Three HDeoptimize will be added. Two for the index 1094 // and one for null check on array (to hoist null 1095 // check and array.length out of loop). 1096 for (int i = start ; i <= end; i++) { 1097 if (expectInterpreter) { 1098 assertIsInterpreted(); 1099 } else { 1100 assertIsManaged(); 1101 } 1102 array[i] = 1; 1103 sum += array[i]; 1104 } 1105 } 1106 1107 1108 /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (before) 1109 /// CHECK: BoundsCheck 1110 /// CHECK: ArraySet 1111 /// CHECK-NOT: BoundsCheck 1112 /// CHECK: ArrayGet 1113 /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (after) 1114 /// CHECK: Phi 1115 /// CHECK-NOT: BoundsCheck 1116 /// CHECK: ArraySet 1117 /// CHECK-NOT: BoundsCheck 1118 /// CHECK: ArrayGet 1119 // Added blocks at end for deoptimization. 1120 /// CHECK: Exit 1121 /// CHECK: If 1122 /// CHECK: Deoptimize 1123 /// CHECK: Deoptimize 1124 /// CHECK: Deoptimize 1125 /// CHECK-NOT: Deoptimize 1126 /// CHECK: Goto 1127 /// CHECK: Goto 1128 /// CHECK: Goto 1129 foo3(int[] array, int end, boolean expectInterpreter)1130 void foo3(int[] array, int end, boolean expectInterpreter) { 1131 if (end < 0) 1132 throw new Error(""); 1133 // Three HDeoptimize will be added. Two for the index 1134 // and one for null check on array (to hoist null check 1135 // and array.length out of loop). 1136 for (int i = 3 ; i <= end; i++) { 1137 if (expectInterpreter) { 1138 assertIsInterpreted(); 1139 } else { 1140 assertIsManaged(); 1141 } 1142 array[i] = 1; 1143 sum += array[i]; 1144 } 1145 } 1146 1147 1148 /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (before) 1149 /// CHECK: BoundsCheck 1150 /// CHECK: ArraySet 1151 /// CHECK-NOT: BoundsCheck 1152 /// CHECK: ArrayGet 1153 1154 /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (after) 1155 /// CHECK: Phi 1156 /// CHECK-NOT: BoundsCheck 1157 /// CHECK: ArraySet 1158 /// CHECK-NOT: BoundsCheck 1159 /// CHECK: ArrayGet 1160 // Added blocks at end for deoptimization. 1161 /// CHECK: Exit 1162 /// CHECK: If 1163 /// CHECK: Deoptimize 1164 /// CHECK: Deoptimize 1165 /// CHECK: Deoptimize 1166 /// CHECK-NOT: Deoptimize 1167 /// CHECK: Goto 1168 /// CHECK: Goto 1169 /// CHECK: Goto 1170 foo4(int[] array, int end, boolean expectInterpreter)1171 void foo4(int[] array, int end, boolean expectInterpreter) { 1172 if (end < 0) 1173 throw new Error(""); 1174 // Three HDeoptimize will be added. Two for the index 1175 // and one for null check on array (to hoist null check 1176 // and array.length out of loop). 1177 for (int i = end ; i > 0; i--) { 1178 if (expectInterpreter) { 1179 assertIsInterpreted(); 1180 } else { 1181 assertIsManaged(); 1182 } 1183 array[i - 1] = 1; 1184 sum += array[i - 1]; 1185 } 1186 } 1187 1188 1189 /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (before) 1190 /// CHECK: BoundsCheck 1191 /// CHECK: ArraySet 1192 /// CHECK: BoundsCheck 1193 /// CHECK: ArrayGet 1194 /// CHECK: BoundsCheck 1195 /// CHECK: ArrayGet 1196 /// CHECK: BoundsCheck 1197 /// CHECK: ArrayGet 1198 1199 /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (after) 1200 /// CHECK-NOT: BoundsCheck 1201 /// CHECK: ArraySet 1202 /// CHECK: Phi 1203 /// CHECK-NOT: BoundsCheck 1204 /// CHECK: ArrayGet 1205 /// CHECK-NOT: BoundsCheck 1206 /// CHECK: ArrayGet 1207 /// CHECK-NOT: BoundsCheck 1208 /// CHECK: ArrayGet 1209 // Added blocks at end for deoptimization. 1210 /// CHECK: Exit 1211 /// CHECK: If 1212 /// CHECK: Deoptimize 1213 /// CHECK: Deoptimize 1214 /// CHECK: Deoptimize 1215 /// CHECK-NOT: Deoptimize 1216 /// CHECK: Goto 1217 /// CHECK: Goto 1218 /// CHECK: Goto 1219 foo5(int[] array, int end, boolean expectInterpreter)1220 void foo5(int[] array, int end, boolean expectInterpreter) { 1221 if (end < 0) 1222 throw new Error(""); 1223 // Bounds check in this loop can be eliminated without deoptimization. 1224 for (int i = array.length - 1 ; i >= 0; i--) { 1225 array[i] = 1; 1226 } 1227 // Three HDeoptimize will be added for the bounds. 1228 // The null check is not necessary. 1229 for (int i = end - 2 ; i > 0; i--) { 1230 if (expectInterpreter) { 1231 assertIsInterpreted(); 1232 } else { 1233 assertIsManaged(); 1234 } 1235 sum += array[i - 1]; 1236 sum += array[i]; 1237 sum += array[i + 1]; 1238 } 1239 } 1240 1241 1242 /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (before) 1243 /// CHECK: BoundsCheck 1244 /// CHECK: ArrayGet 1245 /// CHECK: BoundsCheck 1246 /// CHECK: ArrayGet 1247 /// CHECK: BoundsCheck 1248 /// CHECK: ArrayGet 1249 /// CHECK: BoundsCheck 1250 /// CHECK: ArrayGet 1251 /// CHECK: BoundsCheck 1252 /// CHECK: ArrayGet 1253 /// CHECK-NOT: BoundsCheck 1254 /// CHECK: ArraySet 1255 /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (after) 1256 /// CHECK: Phi 1257 /// CHECK-NOT: BoundsCheck 1258 /// CHECK: ArrayGet 1259 /// CHECK-NOT: BoundsCheck 1260 /// CHECK: ArrayGet 1261 /// CHECK-NOT: BoundsCheck 1262 /// CHECK: ArrayGet 1263 /// CHECK-NOT: BoundsCheck 1264 /// CHECK: ArrayGet 1265 /// CHECK-NOT: BoundsCheck 1266 /// CHECK: ArrayGet 1267 /// CHECK-NOT: BoundsCheck 1268 /// CHECK: ArraySet 1269 // Added blocks at end for deoptimization. 1270 /// CHECK: Exit 1271 /// CHECK: If 1272 /// CHECK: Deoptimize 1273 /// CHECK: Deoptimize 1274 /// CHECK: Deoptimize 1275 /// CHECK: Deoptimize 1276 /// CHECK-NOT: Deoptimize 1277 /// CHECK: Goto 1278 /// CHECK: Goto 1279 /// CHECK: Goto 1280 foo6(int[] array, int start, int end, boolean expectInterpreter)1281 void foo6(int[] array, int start, int end, boolean expectInterpreter) { 1282 if (end < 0) 1283 throw new Error(""); 1284 for (int i = end; i >= start; i--) { 1285 if (expectInterpreter) { 1286 assertIsInterpreted(); 1287 } else { 1288 assertIsManaged(); 1289 } 1290 array[i] = (array[i-2] + array[i-1] + array[i] + array[i+1] + array[i+2]) / 5; 1291 } 1292 } 1293 1294 1295 /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (before) 1296 /// CHECK: BoundsCheck 1297 /// CHECK: ArrayGet 1298 /// CHECK: BoundsCheck 1299 /// CHECK: ArrayGet 1300 1301 /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (after) 1302 /// CHECK: Phi 1303 /// CHECK: BoundsCheck 1304 /// CHECK: ArrayGet 1305 /// CHECK-NOT: BoundsCheck 1306 /// CHECK: ArrayGet 1307 // Added blocks at end for deoptimization. 1308 /// CHECK: Exit 1309 /// CHECK: If 1310 /// CHECK: Deoptimize 1311 /// CHECK: Deoptimize 1312 /// CHECK: Deoptimize 1313 /// CHECK-NOT: Deoptimize 1314 /// CHECK: Goto 1315 /// CHECK: Goto 1316 /// CHECK: Goto 1317 foo7(int[] array, int start, int end, boolean lowEnd)1318 void foo7(int[] array, int start, int end, boolean lowEnd) { 1319 // Three HDeoptimize will be added. One for the index 1320 // and one for null check on array (to hoist null 1321 // check and array.length out of loop). 1322 for (int i = start ; i < end; i++) { 1323 if (lowEnd) { 1324 // This array access isn't certain. So we don't 1325 // use +1000 offset in decision making for deoptimization 1326 // conditions. 1327 sum += array[i + 1000]; 1328 } 1329 sum += array[i]; 1330 } 1331 } 1332 1333 1334 /// CHECK-START: void Main.foo8(int[][], int, int) BCE (before) 1335 /// CHECK: BoundsCheck 1336 /// CHECK: ArrayGet 1337 /// CHECK: BoundsCheck 1338 /// CHECK: ArraySet 1339 1340 /// CHECK-START: void Main.foo8(int[][], int, int) BCE (after) 1341 /// CHECK: Phi 1342 /// CHECK-NOT: BoundsCheck 1343 /// CHECK: ArrayGet 1344 /// CHECK: Phi 1345 /// CHECK-NOT: BoundsCheck 1346 /// CHECK: ArraySet 1347 // Added blocks at end for deoptimization. 1348 /// CHECK: Exit 1349 /// CHECK: If 1350 /// CHECK: Deoptimize 1351 /// CHECK: Deoptimize 1352 /// CHECK: Deoptimize 1353 /// CHECK: Goto 1354 /// CHECK: Goto 1355 /// CHECK: Goto 1356 /// CHECK: If 1357 /// CHECK: Deoptimize 1358 /// CHECK: Deoptimize 1359 /// CHECK: Deoptimize 1360 /// CHECK-NOT: Deoptimize 1361 /// CHECK: Goto 1362 /// CHECK: Goto 1363 /// CHECK: Goto 1364 foo8(int[][] matrix, int start, int end)1365 void foo8(int[][] matrix, int start, int end) { 1366 // Three HDeoptimize will be added for the outer loop, 1367 // two for the index, and null check on matrix. Same 1368 // for the inner loop. 1369 for (int i = start; i < end; i++) { 1370 int[] row = matrix[i]; 1371 for (int j = start; j < end; j++) { 1372 row[j] = 1; 1373 } 1374 } 1375 } 1376 1377 1378 /// CHECK-START: void Main.foo9(int[], boolean) BCE (before) 1379 /// CHECK: NullCheck 1380 /// CHECK: BoundsCheck 1381 /// CHECK: ArrayGet 1382 1383 /// CHECK-START: void Main.foo9(int[], boolean) BCE (after) 1384 // The loop is guaranteed to be entered. No need to transform the 1385 // loop for loop body entry test. 1386 /// CHECK: Deoptimize 1387 /// CHECK: Deoptimize 1388 /// CHECK: Deoptimize 1389 /// CHECK-NOT: Deoptimize 1390 /// CHECK: Phi 1391 /// CHECK-NOT: NullCheck 1392 /// CHECK-NOT: BoundsCheck 1393 /// CHECK: ArrayGet 1394 1395 /// CHECK-START: void Main.foo9(int[], boolean) instruction_simplifier$after_bce (after) 1396 // Simplification removes the redundant check 1397 /// CHECK: Deoptimize 1398 /// CHECK: Deoptimize 1399 /// CHECK-NOT: Deoptimize 1400 foo9(int[] array, boolean expectInterpreter)1401 void foo9(int[] array, boolean expectInterpreter) { 1402 // Three HDeoptimize will be added. Two for the index and one for null check on array. Then 1403 // simplification removes one redundant HDeoptimize. 1404 for (int i = 0 ; i < 10; i++) { 1405 if (expectInterpreter) { 1406 assertIsInterpreted(); 1407 } else { 1408 assertIsManaged(); 1409 } 1410 sum += array[i]; 1411 } 1412 } 1413 1414 1415 /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (before) 1416 /// CHECK: BoundsCheck 1417 /// CHECK: ArraySet 1418 1419 /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (after) 1420 /// CHECK-NOT: Deoptimize 1421 /// CHECK: BoundsCheck 1422 /// CHECK: ArraySet 1423 partialLooping(int[] array, int start, int end)1424 void partialLooping(int[] array, int start, int end) { 1425 // This loop doesn't cover the full range of [start, end) so 1426 // adding deoptimization is too aggressive, since end can be 1427 // greater than array.length but the loop is never going to work on 1428 // more than 2 elements. 1429 for (int i = start; i < end; i++) { 1430 if (i == 2) { 1431 return; 1432 } 1433 array[i] = 1; 1434 } 1435 } 1436 1437 testUnknownBounds()1438 static void testUnknownBounds() { 1439 boolean caught = false; 1440 1441 runAllConstantIndices(); 1442 1443 Main main = new Main(); 1444 main.foo1(new int[10], 0, 10, false); 1445 if (main.sum != 10) { 1446 System.out.println("foo1 failed!"); 1447 } 1448 1449 caught = false; 1450 main = new Main(); 1451 try { 1452 main.foo1(new int[10], 0, 11, true); 1453 } catch (ArrayIndexOutOfBoundsException e) { 1454 caught = true; 1455 } 1456 if (!caught || main.sum != 10) { 1457 System.out.println("foo1 exception failed!"); 1458 } 1459 1460 main = new Main(); 1461 main.foo2(new int[10], 0, 9, false); 1462 if (main.sum != 10) { 1463 System.out.println("foo2 failed!"); 1464 } 1465 1466 caught = false; 1467 main = new Main(); 1468 try { 1469 main.foo2(new int[10], 0, 10, true); 1470 } catch (ArrayIndexOutOfBoundsException e) { 1471 caught = true; 1472 } 1473 if (!caught || main.sum != 10) { 1474 System.out.println("foo2 exception failed!"); 1475 } 1476 1477 main = new Main(); 1478 main.foo3(new int[10], 9, false); 1479 if (main.sum != 7) { 1480 System.out.println("foo3 failed!"); 1481 } 1482 1483 caught = false; 1484 main = new Main(); 1485 try { 1486 main.foo3(new int[10], 10, true); 1487 } catch (ArrayIndexOutOfBoundsException e) { 1488 caught = true; 1489 } 1490 if (!caught || main.sum != 7) { 1491 System.out.println("foo3 exception failed!"); 1492 } 1493 1494 main = new Main(); 1495 main.foo4(new int[10], 10, false); 1496 if (main.sum != 10) { 1497 System.out.println("foo4 failed!"); 1498 } 1499 1500 caught = false; 1501 main = new Main(); 1502 try { 1503 main.foo4(new int[10], 11, true); 1504 } catch (ArrayIndexOutOfBoundsException e) { 1505 caught = true; 1506 } 1507 if (!caught || main.sum != 0) { 1508 System.out.println("foo4 exception failed!"); 1509 } 1510 1511 main = new Main(); 1512 main.foo5(new int[10], 10, false); 1513 if (main.sum != 24) { 1514 System.out.println("foo5 failed!"); 1515 } 1516 1517 caught = false; 1518 main = new Main(); 1519 try { 1520 main.foo5(new int[10], 11, true); 1521 } catch (ArrayIndexOutOfBoundsException e) { 1522 caught = true; 1523 } 1524 if (!caught || main.sum != 2) { 1525 System.out.println("foo5 exception failed!"); 1526 } 1527 1528 main = new Main(); 1529 main.foo6(new int[10], 2, 7, false); 1530 1531 main = new Main(); 1532 int[] array9 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 1533 main.foo9(array9, false); 1534 if (main.sum != 45) { 1535 System.out.println("foo9 failed!"); 1536 } 1537 1538 main = new Main(); 1539 int[] array = new int[4]; 1540 main.partialLooping(new int[3], 0, 4); 1541 if ((array[0] != 1) && (array[1] != 1) && 1542 (array[2] != 0) && (array[3] != 0)) { 1543 System.out.println("partialLooping failed!"); 1544 } 1545 1546 caught = false; 1547 main = new Main(); 1548 try { 1549 main.foo6(new int[10], 2, 8, true); 1550 } catch (ArrayIndexOutOfBoundsException e) { 1551 caught = true; 1552 } 1553 if (!caught) { 1554 System.out.println("foo6 exception failed!"); 1555 } 1556 1557 caught = false; 1558 main = new Main(); 1559 try { 1560 main.foo6(new int[10], 1, 7, true); 1561 } catch (ArrayIndexOutOfBoundsException e) { 1562 caught = true; 1563 } 1564 if (!caught) { 1565 System.out.println("foo6 exception failed!"); 1566 } 1567 1568 } 1569 testExceptionMessage()1570 public void testExceptionMessage() { 1571 short[] B1 = new short[5]; 1572 int[] B2 = new int[5]; 1573 Exception err = null; 1574 try { 1575 testExceptionMessage1(B1, B2, null, -1, 6); 1576 } catch (Exception e) { 1577 err = e; 1578 } 1579 System.out.println(err); 1580 } 1581 testExceptionMessage1(short[] a1, int[] a2, long a3[], int start, int finish)1582 void testExceptionMessage1(short[] a1, int[] a2, long a3[], int start, int finish) { 1583 int j = finish + 77; 1584 // Bug: 22665511 1585 // A deoptimization will be triggered here right before the loop. Need to make 1586 // sure the value of j is preserved for the interpreter. 1587 for (int i = start; i <= finish; i++) { 1588 a2[j - 1] = a1[i + 1]; 1589 } 1590 } 1591 1592 // Make sure this method is compiled with optimizing. 1593 /// CHECK-START: void Main.main(java.lang.String[]) register (after) 1594 /// CHECK: ParallelMove 1595 main(String[] args)1596 public static void main(String[] args) { 1597 System.loadLibrary(args[0]); 1598 1599 if (!compiledWithOptimizing() || 1600 !hasOatFile() || 1601 runtimeIsSoftFail() || 1602 isInterpreted()) { 1603 disableStackFrameAsserts(); 1604 } 1605 1606 sieve(20); 1607 1608 int[] array = {5, 2, 3, 7, 0, 1, 6, 4}; 1609 bubbleSort(array); 1610 for (int i = 0; i < 8; i++) { 1611 if (array[i] != i) { 1612 System.out.println("bubble sort failed!"); 1613 } 1614 } 1615 1616 nonzeroLength(array); 1617 if (array[0] != 112) { 1618 System.out.println("nonzero length failed!"); 1619 } 1620 1621 knownLength(array); 1622 if (array[0] != 112 || array[1] != 1) { 1623 System.out.println("nonzero length failed!"); 1624 } 1625 array = new int[2]; 1626 knownLength(array); 1627 if (array[0] != -1 || array[1] != -2) { 1628 System.out.println("nonzero length failed!"); 1629 } 1630 1631 // Zero length array does not break. 1632 array = new int[0]; 1633 nonzeroLength(array); 1634 knownLength(array); 1635 1636 mA = new int[4][4]; 1637 for (int i = 0; i < 4; i++) { 1638 for (int j = 0; j < 4; j++) { 1639 mA[i][j] = -1; 1640 } 1641 } 1642 dynamicBCEAndIntrinsic(4); 1643 for (int i = 0; i < 4; i++) { 1644 for (int j = 0; j < 4; j++) { 1645 if (mA[i][i] != 1) { 1646 System.out.println("dynamic bce failed!"); 1647 } 1648 } 1649 } 1650 1651 array = new int[7]; 1652 pyramid1(array); 1653 if (!isPyramid(array)) { 1654 System.out.println("pyramid1 failed!"); 1655 } 1656 1657 array = new int[8]; 1658 pyramid2(array); 1659 if (!isPyramid(array)) { 1660 System.out.println("pyramid2 failed!"); 1661 } 1662 1663 java.util.Arrays.fill(array, -1); 1664 pyramid3(array); 1665 if (!isPyramid(array)) { 1666 System.out.println("pyramid3 failed!"); 1667 } 1668 1669 // Make sure this value is kept after deoptimization. 1670 int i = 1; 1671 if (foo() + i != 100) { 1672 System.out.println("foo failed!"); 1673 }; 1674 1675 testUnknownBounds(); 1676 new Main().testExceptionMessage(); 1677 } 1678 compiledWithOptimizing()1679 public static native boolean compiledWithOptimizing(); disableStackFrameAsserts()1680 public static native void disableStackFrameAsserts(); assertIsManaged()1681 public static native void assertIsManaged(); assertIsInterpreted()1682 public static native void assertIsInterpreted(); hasOatFile()1683 public static native boolean hasOatFile(); runtimeIsSoftFail()1684 public static native boolean runtimeIsSoftFail(); isInterpreted()1685 public static native boolean isInterpreted(); 1686 } 1687