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 17public 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 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 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 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 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 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 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 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. 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 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 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 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 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 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 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 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. 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 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 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 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 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 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 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}. 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}. 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}. 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 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 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 static int[][] mA; 931 932 /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (before) 933 // Array references mA[i] and ..[j] both in inner loop. 934 /// CHECK-DAG: <<Get1:l\d+>> ArrayGet [<<Array1:l\d+>>,<<Bounds1:i\d+>>] loop:<<InnerLoop:B\d+>> 935 /// CHECK-DAG: <<Array1>> NullCheck [<<Field1:l\d+>>] loop:<<InnerLoop>> 936 /// CHECK-DAG: <<Len1:i\d+>> ArrayLength [<<Array1>>] loop:<<InnerLoop>> 937 /// CHECK-DAG: <<Bounds1>> BoundsCheck [<<Index1:i\d+>>,<<Len1>>] loop:<<InnerLoop>> 938 /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [<<Array2:l\d+>>,<<Bounds2:i\d+>>] loop:<<InnerLoop>> 939 /// CHECK-DAG: <<Array2>> NullCheck [<<Get1>>] loop:<<InnerLoop>> 940 /// CHECK-DAG: <<Len2:i\d+>> ArrayLength [<<Array2>>] loop:<<InnerLoop>> 941 /// CHECK-DAG: <<Bounds2>> BoundsCheck [<<Index2:i\d+>>,<<Len2>>] loop:<<InnerLoop>> 942 // Note: The ArtMethod* (typed as int or long) is optional after sharpening. 943 /// CHECK-DAG: InvokeStaticOrDirect [<<Get2>>{{(,[ij]\d+)?}}] loop:<<InnerLoop>> 944 /// CHECK-DAG: <<Index2>> Phi loop:<<InnerLoop>> 945 /// CHECK-DAG: <<Index1>> Phi loop:<<OuterLoop:B\d+>> 946 /// CHECK-DAG: <<Field1>> StaticFieldGet loop:none 947 /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>" 948 // 949 /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (after) 950 // Array reference mA[i] hoisted to same level as deopt. 951 /// CHECK-DAG: Deoptimize loop:<<OuterLoop:B\d+>> 952 /// CHECK-DAG: ArrayLength loop:<<OuterLoop>> 953 /// CHECK-DAG: <<Get1:l\d+>> ArrayGet [<<Array1:l\d+>>,<<Index1:i\d+>>] loop:<<OuterLoop>> 954 // Array reference ..[j] still in inner loop, with a direct index. 955 /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [<<Array2:l\d+>>,<<Index2:i\d+>>] loop:<<InnerLoop:B\d+>> 956 // Note: The ArtMethod* (typed as int or long) is optional after sharpening. 957 /// CHECK-DAG: InvokeStaticOrDirect [<<Get2>>{{(,[ij]\d+)?}}] loop:<<InnerLoop>> 958 /// CHECK-DAG: <<Index2>> Phi loop:<<InnerLoop>> 959 /// CHECK-DAG: <<Index1>> Phi loop:<<OuterLoop>> 960 // Synthetic phi. 961 /// CHECK-DAG: <<Array2>> Phi loop:<<OuterLoop>> 962 /// CHECK-DAG: <<Array1>> StaticFieldGet loop:none 963 /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>" 964 // 965 /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (after) 966 /// CHECK-NOT: NullCheck 967 /// CHECK-NOT: BoundsCheck 968 static void dynamicBCEAndIntrinsic(int n) { 969 for (int i = 0; i < n; i++) { 970 for (int j = 0; j < n; j++) { 971 // Since intrinsic call cannot modify fields or arrays, 972 // dynamic BCE and hoisting can be applied to the inner loop. 973 mA[i][j] = Math.abs(mA[i][j]); 974 } 975 } 976 } 977 978 static int foo() { 979 try { 980 assertIsManaged(); 981 // This will cause AIOOBE. 982 $opt$noinline$constantIndexing2(new int[3]); 983 } catch (ArrayIndexOutOfBoundsException e) { 984 assertIsManaged(); // This is to ensure that single-frame deoptimization works. 985 // Will need to be updated if $opt$noinline$constantIndexing2 is inlined. 986 try { 987 // This will cause AIOOBE. 988 constantIndexingForward6(new int[3]); 989 } catch (ArrayIndexOutOfBoundsException e2) { 990 // Having deopted, we expect to be running interpreted at this point. 991 // Does not apply to debuggable, however, since we do not inline. 992 return 99; 993 } 994 } 995 return 0; 996 } 997 998 999 int sum; 1000 1001 /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (before) 1002 /// CHECK: BoundsCheck 1003 /// CHECK: ArraySet 1004 /// CHECK-NOT: BoundsCheck 1005 /// CHECK: ArrayGet 1006 1007 /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (after) 1008 /// CHECK: Phi 1009 /// CHECK-NOT: BoundsCheck 1010 /// CHECK: ArraySet 1011 /// CHECK-NOT: BoundsCheck 1012 /// CHECK: ArrayGet 1013 // Added blocks at end for deoptimization. 1014 /// CHECK: Exit 1015 /// CHECK: If 1016 /// CHECK: Deoptimize 1017 /// CHECK: Deoptimize 1018 /// CHECK: Deoptimize 1019 /// CHECK-NOT: Deoptimize 1020 /// CHECK: Goto 1021 /// CHECK: Goto 1022 /// CHECK: Goto 1023 1024 void foo1(int[] array, int start, int end, boolean expectInterpreter) { 1025 // Three HDeoptimize will be added. Two for the index 1026 // and one for null check on array (to hoist null 1027 // check and array.length out of loop). 1028 for (int i = start ; i < end; i++) { 1029 if (expectInterpreter) { 1030 assertIsInterpreted(); 1031 } else { 1032 assertIsManaged(); 1033 } 1034 array[i] = 1; 1035 sum += array[i]; 1036 } 1037 } 1038 1039 1040 /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (before) 1041 /// CHECK: BoundsCheck 1042 /// CHECK: ArraySet 1043 /// CHECK-NOT: BoundsCheck 1044 /// CHECK: ArrayGet 1045 /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (after) 1046 /// CHECK: Phi 1047 /// CHECK-NOT: BoundsCheck 1048 /// CHECK: ArraySet 1049 /// CHECK-NOT: BoundsCheck 1050 /// CHECK: ArrayGet 1051 // Added blocks at end for deoptimization. 1052 /// CHECK: Exit 1053 /// CHECK: If 1054 /// CHECK: Deoptimize 1055 /// CHECK: Deoptimize 1056 /// CHECK: Deoptimize 1057 /// CHECK-NOT: Deoptimize 1058 /// CHECK: Goto 1059 /// CHECK: Goto 1060 /// CHECK: Goto 1061 1062 void foo2(int[] array, int start, int end, boolean expectInterpreter) { 1063 // Three HDeoptimize will be added. Two for the index 1064 // and one for null check on array (to hoist null 1065 // check and array.length out of loop). 1066 for (int i = start ; i <= end; i++) { 1067 if (expectInterpreter) { 1068 assertIsInterpreted(); 1069 } else { 1070 assertIsManaged(); 1071 } 1072 array[i] = 1; 1073 sum += array[i]; 1074 } 1075 } 1076 1077 1078 /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (before) 1079 /// CHECK: BoundsCheck 1080 /// CHECK: ArraySet 1081 /// CHECK-NOT: BoundsCheck 1082 /// CHECK: ArrayGet 1083 /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (after) 1084 /// CHECK: Phi 1085 /// CHECK-NOT: BoundsCheck 1086 /// CHECK: ArraySet 1087 /// CHECK-NOT: BoundsCheck 1088 /// CHECK: ArrayGet 1089 // Added blocks at end for deoptimization. 1090 /// CHECK: Exit 1091 /// CHECK: If 1092 /// CHECK: Deoptimize 1093 /// CHECK: Deoptimize 1094 /// CHECK: Deoptimize 1095 /// CHECK-NOT: Deoptimize 1096 /// CHECK: Goto 1097 /// CHECK: Goto 1098 /// CHECK: Goto 1099 1100 void foo3(int[] array, int end, boolean expectInterpreter) { 1101 // Three HDeoptimize will be added. Two for the index 1102 // and one for null check on array (to hoist null check 1103 // and array.length out of loop). 1104 for (int i = 3 ; i <= end; i++) { 1105 if (expectInterpreter) { 1106 assertIsInterpreted(); 1107 } else { 1108 assertIsManaged(); 1109 } 1110 array[i] = 1; 1111 sum += array[i]; 1112 } 1113 } 1114 1115 1116 /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (before) 1117 /// CHECK: BoundsCheck 1118 /// CHECK: ArraySet 1119 /// CHECK-NOT: BoundsCheck 1120 /// CHECK: ArrayGet 1121 1122 /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (after) 1123 /// CHECK: Phi 1124 /// CHECK-NOT: BoundsCheck 1125 /// CHECK: ArraySet 1126 /// CHECK-NOT: BoundsCheck 1127 /// CHECK: ArrayGet 1128 // Added blocks at end for deoptimization. 1129 /// CHECK: Exit 1130 /// CHECK: If 1131 /// CHECK: Deoptimize 1132 /// CHECK: Deoptimize 1133 /// CHECK: Deoptimize 1134 /// CHECK-NOT: Deoptimize 1135 /// CHECK: Goto 1136 /// CHECK: Goto 1137 /// CHECK: Goto 1138 1139 void foo4(int[] array, int end, boolean expectInterpreter) { 1140 // Three HDeoptimize will be added. Two for the index 1141 // and one for null check on array (to hoist null check 1142 // and array.length out of loop). 1143 for (int i = end ; i > 0; i--) { 1144 if (expectInterpreter) { 1145 assertIsInterpreted(); 1146 } else { 1147 assertIsManaged(); 1148 } 1149 array[i - 1] = 1; 1150 sum += array[i - 1]; 1151 } 1152 } 1153 1154 1155 /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (before) 1156 /// CHECK: BoundsCheck 1157 /// CHECK: ArraySet 1158 /// CHECK: BoundsCheck 1159 /// CHECK: ArrayGet 1160 /// CHECK: BoundsCheck 1161 /// CHECK: ArrayGet 1162 /// CHECK: BoundsCheck 1163 /// CHECK: ArrayGet 1164 1165 /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (after) 1166 /// CHECK-NOT: BoundsCheck 1167 /// CHECK: ArraySet 1168 /// CHECK: Phi 1169 /// CHECK-NOT: BoundsCheck 1170 /// CHECK: ArrayGet 1171 /// CHECK-NOT: BoundsCheck 1172 /// CHECK: ArrayGet 1173 /// CHECK-NOT: BoundsCheck 1174 /// CHECK: ArrayGet 1175 // Added blocks at end for deoptimization. 1176 /// CHECK: Exit 1177 /// CHECK: If 1178 /// CHECK: Deoptimize 1179 /// CHECK: Deoptimize 1180 /// CHECK: Deoptimize 1181 /// CHECK: Deoptimize 1182 /// CHECK: Deoptimize 1183 /// CHECK: Deoptimize 1184 /// CHECK-NOT: Deoptimize 1185 /// CHECK: Goto 1186 /// CHECK: Goto 1187 /// CHECK: Goto 1188 1189 void foo5(int[] array, int end, boolean expectInterpreter) { 1190 // Bounds check in this loop can be eliminated without deoptimization. 1191 for (int i = array.length - 1 ; i >= 0; i--) { 1192 array[i] = 1; 1193 } 1194 // Several HDeoptimize will be added. Two for each index. 1195 // The null check is not necessary. 1196 for (int i = end - 2 ; i > 0; i--) { 1197 if (expectInterpreter) { 1198 assertIsInterpreted(); 1199 } else { 1200 assertIsManaged(); 1201 } 1202 sum += array[i - 1]; 1203 sum += array[i]; 1204 sum += array[i + 1]; 1205 } 1206 } 1207 1208 1209 /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (before) 1210 /// CHECK: BoundsCheck 1211 /// CHECK: ArrayGet 1212 /// CHECK: BoundsCheck 1213 /// CHECK: ArrayGet 1214 /// CHECK: BoundsCheck 1215 /// CHECK: ArrayGet 1216 /// CHECK: BoundsCheck 1217 /// CHECK: ArrayGet 1218 /// CHECK: BoundsCheck 1219 /// CHECK: ArrayGet 1220 /// CHECK-NOT: BoundsCheck 1221 /// CHECK: ArraySet 1222 /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (after) 1223 /// CHECK: Phi 1224 /// CHECK-NOT: BoundsCheck 1225 /// CHECK: ArrayGet 1226 /// CHECK-NOT: BoundsCheck 1227 /// CHECK: ArrayGet 1228 /// CHECK-NOT: BoundsCheck 1229 /// CHECK: ArrayGet 1230 /// CHECK-NOT: BoundsCheck 1231 /// CHECK: ArrayGet 1232 /// CHECK-NOT: BoundsCheck 1233 /// CHECK: ArrayGet 1234 /// CHECK-NOT: BoundsCheck 1235 /// CHECK: ArraySet 1236 // Added blocks at end for deoptimization. 1237 /// CHECK: Exit 1238 /// CHECK: If 1239 /// CHECK: Deoptimize 1240 /// CHECK: Deoptimize 1241 /// CHECK: Deoptimize 1242 /// CHECK: Deoptimize 1243 /// CHECK: Deoptimize 1244 /// CHECK: Deoptimize 1245 /// CHECK: Deoptimize 1246 /// CHECK: Deoptimize 1247 /// CHECK: Deoptimize 1248 /// CHECK: Deoptimize 1249 /// CHECK: Deoptimize 1250 /// CHECK-NOT: Deoptimize 1251 /// CHECK: Goto 1252 /// CHECK: Goto 1253 /// CHECK: Goto 1254 1255 void foo6(int[] array, int start, int end, boolean expectInterpreter) { 1256 // Several HDeoptimize will be added. 1257 for (int i = end; i >= start; i--) { 1258 if (expectInterpreter) { 1259 assertIsInterpreted(); 1260 } else { 1261 assertIsManaged(); 1262 } 1263 array[i] = (array[i-2] + array[i-1] + array[i] + array[i+1] + array[i+2]) / 5; 1264 } 1265 } 1266 1267 1268 /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (before) 1269 /// CHECK: BoundsCheck 1270 /// CHECK: ArrayGet 1271 /// CHECK: BoundsCheck 1272 /// CHECK: ArrayGet 1273 1274 /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (after) 1275 /// CHECK: Phi 1276 /// CHECK: BoundsCheck 1277 /// CHECK: ArrayGet 1278 /// CHECK-NOT: BoundsCheck 1279 /// CHECK: ArrayGet 1280 // Added blocks at end for deoptimization. 1281 /// CHECK: Exit 1282 /// CHECK: If 1283 /// CHECK: Deoptimize 1284 /// CHECK: Deoptimize 1285 /// CHECK: Deoptimize 1286 /// CHECK-NOT: Deoptimize 1287 /// CHECK: Goto 1288 /// CHECK: Goto 1289 /// CHECK: Goto 1290 1291 void foo7(int[] array, int start, int end, boolean lowEnd) { 1292 // Three HDeoptimize will be added. One for the index 1293 // and one for null check on array (to hoist null 1294 // check and array.length out of loop). 1295 for (int i = start ; i < end; i++) { 1296 if (lowEnd) { 1297 // This array access isn't certain. So we don't 1298 // use +1000 offset in decision making for deoptimization 1299 // conditions. 1300 sum += array[i + 1000]; 1301 } 1302 sum += array[i]; 1303 } 1304 } 1305 1306 1307 /// CHECK-START: void Main.foo8(int[][], int, int) BCE (before) 1308 /// CHECK: BoundsCheck 1309 /// CHECK: ArrayGet 1310 /// CHECK: BoundsCheck 1311 /// CHECK: ArraySet 1312 1313 /// CHECK-START: void Main.foo8(int[][], int, int) BCE (after) 1314 /// CHECK: Phi 1315 /// CHECK-NOT: BoundsCheck 1316 /// CHECK: ArrayGet 1317 /// CHECK: Phi 1318 /// CHECK-NOT: BoundsCheck 1319 /// CHECK: ArraySet 1320 // Added blocks at end for deoptimization. 1321 /// CHECK: Exit 1322 /// CHECK: If 1323 /// CHECK: Deoptimize 1324 /// CHECK: Deoptimize 1325 /// CHECK: Deoptimize 1326 /// CHECK: Goto 1327 /// CHECK: Goto 1328 /// CHECK: Goto 1329 /// CHECK: If 1330 /// CHECK: Deoptimize 1331 /// CHECK: Deoptimize 1332 /// CHECK: Deoptimize 1333 /// CHECK-NOT: Deoptimize 1334 /// CHECK: Goto 1335 /// CHECK: Goto 1336 /// CHECK: Goto 1337 1338 void foo8(int[][] matrix, int start, int end) { 1339 // Three HDeoptimize will be added for the outer loop, 1340 // two for the index, and null check on matrix. Same 1341 // for the inner loop. 1342 for (int i = start; i < end; i++) { 1343 int[] row = matrix[i]; 1344 for (int j = start; j < end; j++) { 1345 row[j] = 1; 1346 } 1347 } 1348 } 1349 1350 1351 /// CHECK-START: void Main.foo9(int[], boolean) BCE (before) 1352 /// CHECK: NullCheck 1353 /// CHECK: BoundsCheck 1354 /// CHECK: ArrayGet 1355 1356 /// CHECK-START: void Main.foo9(int[], boolean) BCE (after) 1357 // The loop is guaranteed to be entered. No need to transform the 1358 // loop for loop body entry test. 1359 /// CHECK: Deoptimize 1360 /// CHECK: Deoptimize 1361 /// CHECK: Deoptimize 1362 /// CHECK-NOT: Deoptimize 1363 /// CHECK: Phi 1364 /// CHECK-NOT: NullCheck 1365 /// CHECK-NOT: BoundsCheck 1366 /// CHECK: ArrayGet 1367 1368 /// CHECK-START: void Main.foo9(int[], boolean) instruction_simplifier_after_bce (after) 1369 // Simplification removes the redundant check 1370 /// CHECK: Deoptimize 1371 /// CHECK: Deoptimize 1372 /// CHECK-NOT: Deoptimize 1373 1374 void foo9(int[] array, boolean expectInterpreter) { 1375 // Two HDeoptimize will be added. Two for the index 1376 // and one for null check on array. 1377 for (int i = 0 ; i < 10; i++) { 1378 if (expectInterpreter) { 1379 assertIsInterpreted(); 1380 } else { 1381 assertIsManaged(); 1382 } 1383 sum += array[i]; 1384 } 1385 } 1386 1387 1388 /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (before) 1389 /// CHECK: BoundsCheck 1390 /// CHECK: ArraySet 1391 1392 /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (after) 1393 /// CHECK-NOT: Deoptimize 1394 /// CHECK: BoundsCheck 1395 /// CHECK: ArraySet 1396 1397 void partialLooping(int[] array, int start, int end) { 1398 // This loop doesn't cover the full range of [start, end) so 1399 // adding deoptimization is too aggressive, since end can be 1400 // greater than array.length but the loop is never going to work on 1401 // more than 2 elements. 1402 for (int i = start; i < end; i++) { 1403 if (i == 2) { 1404 return; 1405 } 1406 array[i] = 1; 1407 } 1408 } 1409 1410 1411 static void testUnknownBounds() { 1412 boolean caught = false; 1413 1414 runAllConstantIndices(); 1415 1416 Main main = new Main(); 1417 main.foo1(new int[10], 0, 10, false); 1418 if (main.sum != 10) { 1419 System.out.println("foo1 failed!"); 1420 } 1421 1422 caught = false; 1423 main = new Main(); 1424 try { 1425 main.foo1(new int[10], 0, 11, true); 1426 } catch (ArrayIndexOutOfBoundsException e) { 1427 caught = true; 1428 } 1429 if (!caught || main.sum != 10) { 1430 System.out.println("foo1 exception failed!"); 1431 } 1432 1433 main = new Main(); 1434 main.foo2(new int[10], 0, 9, false); 1435 if (main.sum != 10) { 1436 System.out.println("foo2 failed!"); 1437 } 1438 1439 caught = false; 1440 main = new Main(); 1441 try { 1442 main.foo2(new int[10], 0, 10, true); 1443 } catch (ArrayIndexOutOfBoundsException e) { 1444 caught = true; 1445 } 1446 if (!caught || main.sum != 10) { 1447 System.out.println("foo2 exception failed!"); 1448 } 1449 1450 main = new Main(); 1451 main.foo3(new int[10], 9, false); 1452 if (main.sum != 7) { 1453 System.out.println("foo3 failed!"); 1454 } 1455 1456 caught = false; 1457 main = new Main(); 1458 try { 1459 main.foo3(new int[10], 10, true); 1460 } catch (ArrayIndexOutOfBoundsException e) { 1461 caught = true; 1462 } 1463 if (!caught || main.sum != 7) { 1464 System.out.println("foo3 exception failed!"); 1465 } 1466 1467 main = new Main(); 1468 main.foo4(new int[10], 10, false); 1469 if (main.sum != 10) { 1470 System.out.println("foo4 failed!"); 1471 } 1472 1473 caught = false; 1474 main = new Main(); 1475 try { 1476 main.foo4(new int[10], 11, true); 1477 } catch (ArrayIndexOutOfBoundsException e) { 1478 caught = true; 1479 } 1480 if (!caught || main.sum != 0) { 1481 System.out.println("foo4 exception failed!"); 1482 } 1483 1484 main = new Main(); 1485 main.foo5(new int[10], 10, false); 1486 if (main.sum != 24) { 1487 System.out.println("foo5 failed!"); 1488 } 1489 1490 caught = false; 1491 main = new Main(); 1492 try { 1493 main.foo5(new int[10], 11, true); 1494 } catch (ArrayIndexOutOfBoundsException e) { 1495 caught = true; 1496 } 1497 if (!caught || main.sum != 2) { 1498 System.out.println("foo5 exception failed!"); 1499 } 1500 1501 main = new Main(); 1502 main.foo6(new int[10], 2, 7, false); 1503 1504 main = new Main(); 1505 int[] array9 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 1506 main.foo9(array9, false); 1507 if (main.sum != 45) { 1508 System.out.println("foo9 failed!"); 1509 } 1510 1511 main = new Main(); 1512 int[] array = new int[4]; 1513 main.partialLooping(new int[3], 0, 4); 1514 if ((array[0] != 1) && (array[1] != 1) && 1515 (array[2] != 0) && (array[3] != 0)) { 1516 System.out.println("partialLooping failed!"); 1517 } 1518 1519 caught = false; 1520 main = new Main(); 1521 try { 1522 main.foo6(new int[10], 2, 8, true); 1523 } catch (ArrayIndexOutOfBoundsException e) { 1524 caught = true; 1525 } 1526 if (!caught) { 1527 System.out.println("foo6 exception failed!"); 1528 } 1529 1530 caught = false; 1531 main = new Main(); 1532 try { 1533 main.foo6(new int[10], 1, 7, true); 1534 } catch (ArrayIndexOutOfBoundsException e) { 1535 caught = true; 1536 } 1537 if (!caught) { 1538 System.out.println("foo6 exception failed!"); 1539 } 1540 1541 } 1542 1543 public void testExceptionMessage() { 1544 short[] B1 = new short[5]; 1545 int[] B2 = new int[5]; 1546 Exception err = null; 1547 try { 1548 testExceptionMessage1(B1, B2, null, -1, 6); 1549 } catch (Exception e) { 1550 err = e; 1551 } 1552 System.out.println(err); 1553 } 1554 1555 void testExceptionMessage1(short[] a1, int[] a2, long a3[], int start, int finish) { 1556 int j = finish + 77; 1557 // Bug: 22665511 1558 // A deoptimization will be triggered here right before the loop. Need to make 1559 // sure the value of j is preserved for the interpreter. 1560 for (int i = start; i <= finish; i++) { 1561 a2[j - 1] = a1[i + 1]; 1562 } 1563 } 1564 1565 // Make sure this method is compiled with optimizing. 1566 /// CHECK-START: void Main.main(java.lang.String[]) register (after) 1567 /// CHECK: ParallelMove 1568 1569 public static void main(String[] args) { 1570 System.loadLibrary(args[0]); 1571 1572 if (!compiledWithOptimizing() || 1573 !hasOatFile() || 1574 runtimeIsSoftFail() || 1575 isInterpreted()) { 1576 disableStackFrameAsserts(); 1577 } 1578 1579 sieve(20); 1580 1581 int[] array = {5, 2, 3, 7, 0, 1, 6, 4}; 1582 bubbleSort(array); 1583 for (int i = 0; i < 8; i++) { 1584 if (array[i] != i) { 1585 System.out.println("bubble sort failed!"); 1586 } 1587 } 1588 1589 mA = new int[4][4]; 1590 for (int i = 0; i < 4; i++) { 1591 for (int j = 0; j < 4; j++) { 1592 mA[i][j] = -1; 1593 } 1594 } 1595 dynamicBCEAndIntrinsic(4); 1596 for (int i = 0; i < 4; i++) { 1597 for (int j = 0; j < 4; j++) { 1598 if (mA[i][i] != 1) { 1599 System.out.println("dynamic bce failed!"); 1600 } 1601 } 1602 } 1603 1604 array = new int[7]; 1605 pyramid1(array); 1606 if (!isPyramid(array)) { 1607 System.out.println("pyramid1 failed!"); 1608 } 1609 1610 array = new int[8]; 1611 pyramid2(array); 1612 if (!isPyramid(array)) { 1613 System.out.println("pyramid2 failed!"); 1614 } 1615 1616 java.util.Arrays.fill(array, -1); 1617 pyramid3(array); 1618 if (!isPyramid(array)) { 1619 System.out.println("pyramid3 failed!"); 1620 } 1621 1622 // Make sure this value is kept after deoptimization. 1623 int i = 1; 1624 if (foo() + i != 100) { 1625 System.out.println("foo failed!"); 1626 }; 1627 1628 testUnknownBounds(); 1629 new Main().testExceptionMessage(); 1630 } 1631 1632 public static native boolean compiledWithOptimizing(); 1633 public static native void disableStackFrameAsserts(); 1634 public static native void assertIsManaged(); 1635 public static native void assertIsInterpreted(); 1636 public static native boolean hasOatFile(); 1637 public static native boolean runtimeIsSoftFail(); 1638 public static native boolean isInterpreted(); 1639} 1640