Main.java revision 0b5849be045c5683d4a6b6b6c306abadba5f0fcc
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 array[5] = 1; 126 array[4] = 1; 127 } 128 129 130 /// CHECK-START: void Main.constantIndexing2(int[]) BCE (before) 131 /// CHECK: BoundsCheck 132 /// CHECK: ArraySet 133 /// CHECK: BoundsCheck 134 /// CHECK: ArraySet 135 /// CHECK: BoundsCheck 136 /// CHECK: ArraySet 137 /// CHECK: BoundsCheck 138 /// CHECK: ArraySet 139 140 /// CHECK-START: void Main.constantIndexing2(int[]) BCE (after) 141 /// CHECK: LessThanOrEqual 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 /// CHECK: BoundsCheck 152 /// CHECK: ArraySet 153 154 static void constantIndexing2(int[] array) { 155 array[1] = 1; 156 array[2] = 1; 157 array[3] = 1; 158 array[4] = 1; 159 array[-1] = 1; 160 } 161 162 163 /// CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (before) 164 /// CHECK: BoundsCheck 165 /// CHECK: ArrayGet 166 /// CHECK: BoundsCheck 167 /// CHECK: ArraySet 168 /// CHECK: BoundsCheck 169 /// CHECK: ArrayGet 170 /// CHECK: BoundsCheck 171 /// CHECK: ArraySet 172 /// CHECK: BoundsCheck 173 /// CHECK: ArrayGet 174 /// CHECK: BoundsCheck 175 /// CHECK: ArraySet 176 /// CHECK: BoundsCheck 177 /// CHECK: ArrayGet 178 /// CHECK: BoundsCheck 179 /// CHECK: ArraySet 180 181 /// CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (after) 182 /// CHECK: LessThanOrEqual 183 /// CHECK: Deoptimize 184 /// CHECK-NOT: BoundsCheck 185 /// CHECK: ArrayGet 186 /// CHECK: LessThanOrEqual 187 /// CHECK: Deoptimize 188 /// CHECK-NOT: BoundsCheck 189 /// CHECK: ArraySet 190 /// CHECK-NOT: BoundsCheck 191 /// CHECK: ArrayGet 192 /// CHECK-NOT: BoundsCheck 193 /// CHECK: ArraySet 194 /// CHECK-NOT: BoundsCheck 195 /// CHECK: ArrayGet 196 /// CHECK-NOT: BoundsCheck 197 /// CHECK: ArraySet 198 /// CHECK-NOT: BoundsCheck 199 /// CHECK: ArrayGet 200 /// CHECK-NOT: BoundsCheck 201 /// CHECK: ArraySet 202 203 static int[] constantIndexing3(int[] array1, int[] array2, boolean copy) { 204 if (!copy) { 205 return array1; 206 } 207 array2[0] = array1[0]; 208 array2[1] = array1[1]; 209 array2[2] = array1[2]; 210 array2[3] = array1[3]; 211 return array2; 212 } 213 214 215 /// CHECK-START: void Main.constantIndexing4(int[]) BCE (before) 216 /// CHECK: BoundsCheck 217 /// CHECK: ArraySet 218 219 /// CHECK-START: void Main.constantIndexing4(int[]) BCE (after) 220 /// CHECK-NOT: LessThanOrEqual 221 /// CHECK: BoundsCheck 222 /// CHECK: ArraySet 223 224 // There is only one array access. It's not beneficial 225 // to create a compare with deoptimization instruction. 226 static void constantIndexing4(int[] array) { 227 array[0] = 1; 228 } 229 230 231 /// CHECK-START: void Main.constantIndexing5(int[]) BCE (before) 232 /// CHECK: BoundsCheck 233 /// CHECK: ArraySet 234 /// CHECK: BoundsCheck 235 /// CHECK: ArraySet 236 237 /// CHECK-START: void Main.constantIndexing5(int[]) BCE (after) 238 /// CHECK-NOT: Deoptimize 239 /// CHECK: BoundsCheck 240 /// CHECK: ArraySet 241 /// CHECK: BoundsCheck 242 /// CHECK: ArraySet 243 244 static void constantIndexing5(int[] array) { 245 // We don't apply the deoptimization for very large constant index 246 // since it's likely to be an anomaly and will throw AIOOBE. 247 array[Integer.MAX_VALUE - 1000] = 1; 248 array[Integer.MAX_VALUE - 999] = 1; 249 array[Integer.MAX_VALUE - 998] = 1; 250 } 251 252 /// CHECK-START: void Main.constantIndexing6(int[]) BCE (before) 253 /// CHECK: BoundsCheck 254 /// CHECK: ArraySet 255 /// CHECK: BoundsCheck 256 /// CHECK: ArraySet 257 258 /// CHECK-START: void Main.constantIndexing6(int[]) BCE (after) 259 /// CHECK: Deoptimize 260 261 static void constantIndexing6(int[] array) { 262 array[3] = 1; 263 array[4] = 1; 264 } 265 266 // A helper into which the actual throwing function should be inlined. 267 static void constantIndexingForward6(int[] array) { 268 assertIsManaged(); 269 constantIndexing6(array); 270 } 271 272 /// CHECK-START: void Main.loopPattern1(int[]) BCE (before) 273 /// CHECK: BoundsCheck 274 /// CHECK: ArraySet 275 /// CHECK: BoundsCheck 276 /// CHECK: ArraySet 277 /// CHECK: BoundsCheck 278 /// CHECK: ArraySet 279 /// CHECK: BoundsCheck 280 /// CHECK: ArraySet 281 /// CHECK: BoundsCheck 282 /// CHECK: ArraySet 283 /// CHECK: BoundsCheck 284 /// CHECK: ArraySet 285 /// CHECK: BoundsCheck 286 /// CHECK: ArraySet 287 288 /// CHECK-START: void Main.loopPattern1(int[]) BCE (after) 289 /// CHECK-NOT: BoundsCheck 290 /// CHECK: ArraySet 291 /// CHECK-NOT: BoundsCheck 292 /// CHECK: ArraySet 293 /// CHECK-NOT: BoundsCheck 294 /// CHECK: ArraySet 295 /// CHECK: BoundsCheck 296 /// CHECK: ArraySet 297 /// CHECK: BoundsCheck 298 /// CHECK: ArraySet 299 /// CHECK: BoundsCheck 300 /// CHECK: ArraySet 301 /// CHECK-NOT: BoundsCheck 302 /// CHECK: ArraySet 303 304 static void loopPattern1(int[] array) { 305 for (int i = 0; i < array.length; i++) { 306 array[i] = 1; // Bounds check can be eliminated. 307 } 308 309 for (int i = 1; i < array.length; i++) { 310 array[i] = 1; // Bounds check can be eliminated. 311 } 312 313 for (int i = 1; i < array.length - 1; i++) { 314 array[i] = 1; // Bounds check can be eliminated. 315 } 316 317 for (int i = -1; i < array.length; i++) { 318 array[i] = 1; // Bounds check can't be eliminated. 319 } 320 321 for (int i = 0; i <= array.length; i++) { 322 array[i] = 1; // Bounds check can't be eliminated. 323 } 324 325 for (int i = 0; i < array.length; i += 2) { 326 // We don't have any assumption on max array length yet. 327 // Bounds check can't be eliminated due to overflow concern. 328 array[i] = 1; 329 } 330 331 for (int i = 1; i < array.length; i += 2) { 332 // Bounds check can be eliminated since i is odd so the last 333 // i that's less than array.length is at most (Integer.MAX_VALUE - 2). 334 array[i] = 1; 335 } 336 } 337 338 339 /// CHECK-START: void Main.loopPattern2(int[]) BCE (before) 340 /// CHECK: BoundsCheck 341 /// CHECK: ArraySet 342 /// CHECK: BoundsCheck 343 /// CHECK: ArraySet 344 /// CHECK: BoundsCheck 345 /// CHECK: ArraySet 346 /// CHECK: BoundsCheck 347 /// CHECK: ArraySet 348 /// CHECK: BoundsCheck 349 /// CHECK: ArraySet 350 /// CHECK: BoundsCheck 351 /// CHECK: ArraySet 352 353 /// CHECK-START: void Main.loopPattern2(int[]) BCE (after) 354 /// CHECK-NOT: BoundsCheck 355 /// CHECK: ArraySet 356 /// CHECK-NOT: BoundsCheck 357 /// CHECK: ArraySet 358 /// CHECK-NOT: BoundsCheck 359 /// CHECK: ArraySet 360 /// CHECK: BoundsCheck 361 /// CHECK: ArraySet 362 /// CHECK: BoundsCheck 363 /// CHECK: ArraySet 364 /// CHECK-NOT: BoundsCheck 365 /// CHECK: ArraySet 366 367 static void loopPattern2(int[] array) { 368 for (int i = array.length - 1; i >= 0; i--) { 369 array[i] = 1; // Bounds check can be eliminated. 370 } 371 372 for (int i = array.length; i > 0; i--) { 373 array[i - 1] = 1; // Bounds check can be eliminated. 374 } 375 376 for (int i = array.length - 1; i > 0; i--) { 377 array[i] = 1; // Bounds check can be eliminated. 378 } 379 380 for (int i = array.length; i >= 0; i--) { 381 array[i] = 1; // Bounds check can't be eliminated. 382 } 383 384 for (int i = array.length; i >= 0; i--) { 385 array[i - 1] = 1; // Bounds check can't be eliminated. 386 } 387 388 for (int i = array.length; i > 0; i -= 20) { 389 // For i >= 0, (i - 20 - 1) is guaranteed not to underflow. 390 array[i - 1] = 1; // Bounds check can be eliminated. 391 } 392 } 393 394 395 /// CHECK-START: void Main.loopPattern3(int[]) BCE (before) 396 /// CHECK: BoundsCheck 397 /// CHECK: ArraySet 398 399 /// CHECK-START: void Main.loopPattern3(int[]) BCE (after) 400 /// CHECK: BoundsCheck 401 /// CHECK: ArraySet 402 403 static void loopPattern3(int[] array) { 404 java.util.Random random = new java.util.Random(); 405 for (int i = 0; ; i++) { 406 if (random.nextInt() % 1000 == 0 && i < array.length) { 407 // Can't eliminate the bound check since not every i++ is 408 // matched with a array length check, so there is some chance that i 409 // overflows and is negative. 410 array[i] = 1; 411 } 412 } 413 } 414 415 416 /// CHECK-START: void Main.constantNewArray() BCE (before) 417 /// CHECK: BoundsCheck 418 /// CHECK: ArraySet 419 /// CHECK: BoundsCheck 420 /// CHECK: ArraySet 421 /// CHECK: BoundsCheck 422 /// CHECK: ArraySet 423 /// CHECK: BoundsCheck 424 /// CHECK: ArraySet 425 /// CHECK: BoundsCheck 426 /// CHECK: ArraySet 427 428 /// CHECK-START: void Main.constantNewArray() BCE (after) 429 /// CHECK-NOT: BoundsCheck 430 /// CHECK: ArraySet 431 /// CHECK: BoundsCheck 432 /// CHECK: ArraySet 433 /// CHECK-NOT: BoundsCheck 434 /// CHECK: ArraySet 435 /// CHECK-NOT: BoundsCheck 436 /// CHECK: ArraySet 437 /// CHECK: BoundsCheck 438 /// CHECK: ArraySet 439 440 static void constantNewArray() { 441 int[] array = new int[10]; 442 for (int i = 0; i < 10; i++) { 443 array[i] = 1; // Bounds check can be eliminated. 444 } 445 446 for (int i = 0; i <= 10; i++) { 447 array[i] = 1; // Bounds check can't be eliminated. 448 } 449 450 array[0] = 1; // Bounds check can be eliminated. 451 array[9] = 1; // Bounds check can be eliminated. 452 array[10] = 1; // Bounds check can't be eliminated. 453 } 454 455 456 static byte readData() { 457 return 1; 458 } 459 460 /// CHECK-START: void Main.circularBufferProducer() BCE (before) 461 /// CHECK: BoundsCheck 462 /// CHECK: ArraySet 463 464 /// CHECK-START: void Main.circularBufferProducer() BCE (after) 465 /// CHECK-NOT: BoundsCheck 466 /// CHECK: ArraySet 467 468 static void circularBufferProducer() { 469 byte[] array = new byte[4096]; 470 int i = 0; 471 while (true) { 472 array[i & (array.length - 1)] = readData(); 473 i++; 474 } 475 } 476 477 478 /// CHECK-START: void Main.pyramid1(int[]) BCE (before) 479 /// CHECK: BoundsCheck 480 /// CHECK: ArraySet 481 /// CHECK: BoundsCheck 482 /// CHECK: ArraySet 483 484 /// CHECK-START: void Main.pyramid1(int[]) BCE (after) 485 /// CHECK-NOT: BoundsCheck 486 /// CHECK: ArraySet 487 /// CHECK-NOT: BoundsCheck 488 /// CHECK: ArraySet 489 490 // Set array to something like {0, 1, 2, 3, 2, 1, 0}. 491 static void pyramid1(int[] array) { 492 for (int i = 0; i < (array.length + 1) / 2; i++) { 493 array[i] = i; 494 array[array.length - 1 - i] = i; 495 } 496 } 497 498 499 /// CHECK-START: void Main.pyramid2(int[]) BCE (before) 500 /// CHECK: BoundsCheck 501 /// CHECK: ArraySet 502 /// CHECK: BoundsCheck 503 /// CHECK: ArraySet 504 505 /// CHECK-START: void Main.pyramid2(int[]) BCE (after) 506 /// CHECK-NOT: BoundsCheck 507 /// CHECK: ArraySet 508 /// CHECK-NOT: BoundsCheck 509 /// CHECK: ArraySet 510 511 // Set array to something like {0, 1, 2, 3, 2, 1, 0}. 512 static void pyramid2(int[] array) { 513 for (int i = 0; i < (array.length + 1) >> 1; i++) { 514 array[i] = i; 515 array[array.length - 1 - i] = i; 516 } 517 } 518 519 520 /// CHECK-START: void Main.pyramid3(int[]) BCE (before) 521 /// CHECK: BoundsCheck 522 /// CHECK: ArraySet 523 /// CHECK: BoundsCheck 524 /// CHECK: ArraySet 525 526 /// CHECK-START: void Main.pyramid3(int[]) BCE (after) 527 /// CHECK-NOT: BoundsCheck 528 /// CHECK: ArraySet 529 /// CHECK-NOT: BoundsCheck 530 /// CHECK: ArraySet 531 532 // Set array to something like {0, 1, 2, 3, 2, 1, 0}. 533 static void pyramid3(int[] array) { 534 for (int i = 0; i < (array.length + 1) >>> 1; i++) { 535 array[i] = i; 536 array[array.length - 1 - i] = i; 537 } 538 } 539 540 541 /// CHECK-START: boolean Main.isPyramid(int[]) BCE (before) 542 /// CHECK: BoundsCheck 543 /// CHECK: ArrayGet 544 /// CHECK: BoundsCheck 545 /// CHECK: ArrayGet 546 547 /// CHECK-START: boolean Main.isPyramid(int[]) BCE (after) 548 /// CHECK-NOT: BoundsCheck 549 /// CHECK: ArrayGet 550 /// CHECK-NOT: BoundsCheck 551 /// CHECK: ArrayGet 552 553 static boolean isPyramid(int[] array) { 554 int i = 0; 555 int j = array.length - 1; 556 while (i <= j) { 557 if (array[i] != i) { 558 return false; 559 } 560 if (array[j] != i) { 561 return false; 562 } 563 i++; j--; 564 } 565 return true; 566 } 567 568 569 /// CHECK-START: void Main.bubbleSort(int[]) GVN (before) 570 /// CHECK: BoundsCheck 571 /// CHECK: ArrayGet 572 /// CHECK: BoundsCheck 573 /// CHECK: ArrayGet 574 /// CHECK: BoundsCheck 575 /// CHECK: ArrayGet 576 /// CHECK: BoundsCheck 577 /// CHECK: ArrayGet 578 /// CHECK: BoundsCheck 579 /// CHECK: ArraySet 580 /// CHECK: BoundsCheck 581 /// CHECK: ArraySet 582 583 /// CHECK-START: void Main.bubbleSort(int[]) GVN (after) 584 /// CHECK: BoundsCheck 585 /// CHECK: ArrayGet 586 /// CHECK: BoundsCheck 587 /// CHECK: ArrayGet 588 /// CHECK-NOT: ArrayGet 589 /// CHECK-NOT: ArrayGet 590 /// CHECK-NOT: BoundsCheck 591 /// CHECK: ArraySet 592 /// CHECK-NOT: BoundsCheck 593 /// CHECK: ArraySet 594 595 /// CHECK-START: void Main.bubbleSort(int[]) BCE (after) 596 /// CHECK-NOT: BoundsCheck 597 /// CHECK: ArrayGet 598 /// CHECK-NOT: BoundsCheck 599 /// CHECK: ArrayGet 600 /// CHECK-NOT: ArrayGet 601 /// CHECK-NOT: ArrayGet 602 /// CHECK-NOT: BoundsCheck 603 /// CHECK: ArraySet 604 /// CHECK-NOT: BoundsCheck 605 /// CHECK: ArraySet 606 607 static void bubbleSort(int[] array) { 608 for (int i = 0; i < array.length - 1; i++) { 609 for (int j = 0; j < array.length - i - 1; j++) { 610 if (array[j] > array[j + 1]) { 611 int temp = array[j + 1]; 612 array[j + 1] = array[j]; 613 array[j] = temp; 614 } 615 } 616 } 617 } 618 619 620 static int foo() { 621 try { 622 assertIsManaged(); 623 // This will cause AIOOBE. 624 constantIndexing2(new int[3]); 625 } catch (ArrayIndexOutOfBoundsException e) { 626 assertIsManaged(); // This is to ensure that single-frame deoptimization works. 627 // Will need to be updated if constantIndexing2 is inlined. 628 try { 629 // This will cause AIOOBE. 630 constantIndexingForward6(new int[3]); 631 } catch (ArrayIndexOutOfBoundsException e2) { 632 // Having deopted, we expect to be running interpreted at this point. 633 // Does not apply to debuggable, however, since we do not inline. 634 return 99; 635 } 636 } 637 return 0; 638 } 639 640 641 int sum; 642 643 /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (before) 644 /// CHECK: BoundsCheck 645 /// CHECK: ArraySet 646 /// CHECK-NOT: BoundsCheck 647 /// CHECK: ArrayGet 648 649 /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (after) 650 /// CHECK: Phi 651 /// CHECK-NOT: BoundsCheck 652 /// CHECK: ArraySet 653 /// CHECK-NOT: BoundsCheck 654 /// CHECK: ArrayGet 655 // Added blocks at end for deoptimization. 656 /// CHECK: Exit 657 /// CHECK: If 658 /// CHECK: Deoptimize 659 /// CHECK: Deoptimize 660 /// CHECK: Deoptimize 661 /// CHECK-NOT: Deoptimize 662 /// CHECK: Goto 663 /// CHECK: Goto 664 /// CHECK: Goto 665 666 void foo1(int[] array, int start, int end, boolean expectInterpreter) { 667 // Three HDeoptimize will be added. Two for the index 668 // and one for null check on array (to hoist null 669 // check and array.length out of loop). 670 for (int i = start ; i < end; i++) { 671 if (expectInterpreter) { 672 assertIsInterpreted(); 673 } else { 674 assertIsManaged(); 675 } 676 array[i] = 1; 677 sum += array[i]; 678 } 679 } 680 681 682 /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (before) 683 /// CHECK: BoundsCheck 684 /// CHECK: ArraySet 685 /// CHECK-NOT: BoundsCheck 686 /// CHECK: ArrayGet 687 /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (after) 688 /// CHECK: Phi 689 /// CHECK-NOT: BoundsCheck 690 /// CHECK: ArraySet 691 /// CHECK-NOT: BoundsCheck 692 /// CHECK: ArrayGet 693 // Added blocks at end for deoptimization. 694 /// CHECK: Exit 695 /// CHECK: If 696 /// CHECK: Deoptimize 697 /// CHECK: Deoptimize 698 /// CHECK: Deoptimize 699 /// CHECK-NOT: Deoptimize 700 /// CHECK: Goto 701 /// CHECK: Goto 702 /// CHECK: Goto 703 704 void foo2(int[] array, int start, int end, boolean expectInterpreter) { 705 // Three HDeoptimize will be added. Two for the index 706 // and one for null check on array (to hoist null 707 // check and array.length out of loop). 708 for (int i = start ; i <= end; i++) { 709 if (expectInterpreter) { 710 assertIsInterpreted(); 711 } else { 712 assertIsManaged(); 713 } 714 array[i] = 1; 715 sum += array[i]; 716 } 717 } 718 719 720 /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (before) 721 /// CHECK: BoundsCheck 722 /// CHECK: ArraySet 723 /// CHECK-NOT: BoundsCheck 724 /// CHECK: ArrayGet 725 /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (after) 726 /// CHECK: Phi 727 /// CHECK-NOT: BoundsCheck 728 /// CHECK: ArraySet 729 /// CHECK-NOT: BoundsCheck 730 /// CHECK: ArrayGet 731 // Added blocks at end for deoptimization. 732 /// CHECK: Exit 733 /// CHECK: If 734 /// CHECK: Deoptimize 735 /// CHECK: Deoptimize 736 /// CHECK: Deoptimize 737 /// CHECK-NOT: Deoptimize 738 /// CHECK: Goto 739 /// CHECK: Goto 740 /// CHECK: Goto 741 742 void foo3(int[] array, int end, boolean expectInterpreter) { 743 // Three HDeoptimize will be added. Two for the index 744 // and one for null check on array (to hoist null check 745 // and array.length out of loop). 746 for (int i = 3 ; i <= end; i++) { 747 if (expectInterpreter) { 748 assertIsInterpreted(); 749 } else { 750 assertIsManaged(); 751 } 752 array[i] = 1; 753 sum += array[i]; 754 } 755 } 756 757 758 /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (before) 759 /// CHECK: BoundsCheck 760 /// CHECK: ArraySet 761 /// CHECK-NOT: BoundsCheck 762 /// CHECK: ArrayGet 763 764 /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (after) 765 /// CHECK: Phi 766 /// CHECK-NOT: BoundsCheck 767 /// CHECK: ArraySet 768 /// CHECK-NOT: BoundsCheck 769 /// CHECK: ArrayGet 770 // Added blocks at end for deoptimization. 771 /// CHECK: Exit 772 /// CHECK: If 773 /// CHECK: Deoptimize 774 /// CHECK: Deoptimize 775 /// CHECK: Deoptimize 776 /// CHECK-NOT: Deoptimize 777 /// CHECK: Goto 778 /// CHECK: Goto 779 /// CHECK: Goto 780 781 void foo4(int[] array, int end, boolean expectInterpreter) { 782 // Three HDeoptimize will be added. Two for the index 783 // and one for null check on array (to hoist null check 784 // and array.length out of loop). 785 for (int i = end ; i > 0; i--) { 786 if (expectInterpreter) { 787 assertIsInterpreted(); 788 } else { 789 assertIsManaged(); 790 } 791 array[i - 1] = 1; 792 sum += array[i - 1]; 793 } 794 } 795 796 797 /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (before) 798 /// CHECK: BoundsCheck 799 /// CHECK: ArraySet 800 /// CHECK: BoundsCheck 801 /// CHECK: ArrayGet 802 /// CHECK: BoundsCheck 803 /// CHECK: ArrayGet 804 /// CHECK: BoundsCheck 805 /// CHECK: ArrayGet 806 807 /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (after) 808 /// CHECK-NOT: BoundsCheck 809 /// CHECK: ArraySet 810 /// CHECK: Phi 811 /// CHECK-NOT: BoundsCheck 812 /// CHECK: ArrayGet 813 /// CHECK-NOT: BoundsCheck 814 /// CHECK: ArrayGet 815 /// CHECK-NOT: BoundsCheck 816 /// CHECK: ArrayGet 817 // Added blocks at end for deoptimization. 818 /// CHECK: Exit 819 /// CHECK: If 820 /// CHECK: Deoptimize 821 /// CHECK: Deoptimize 822 /// CHECK: Deoptimize 823 /// CHECK: Deoptimize 824 /// CHECK: Deoptimize 825 /// CHECK: Deoptimize 826 /// CHECK-NOT: Deoptimize 827 /// CHECK: Goto 828 /// CHECK: Goto 829 /// CHECK: Goto 830 831 void foo5(int[] array, int end, boolean expectInterpreter) { 832 // Bounds check in this loop can be eliminated without deoptimization. 833 for (int i = array.length - 1 ; i >= 0; i--) { 834 array[i] = 1; 835 } 836 // Several HDeoptimize will be added. Two for each index. 837 // The null check is not necessary. 838 for (int i = end - 2 ; i > 0; i--) { 839 if (expectInterpreter) { 840 assertIsInterpreted(); 841 } else { 842 assertIsManaged(); 843 } 844 sum += array[i - 1]; 845 sum += array[i]; 846 sum += array[i + 1]; 847 } 848 } 849 850 851 /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (before) 852 /// CHECK: BoundsCheck 853 /// CHECK: ArrayGet 854 /// CHECK: BoundsCheck 855 /// CHECK: ArrayGet 856 /// CHECK: BoundsCheck 857 /// CHECK: ArrayGet 858 /// CHECK: BoundsCheck 859 /// CHECK: ArrayGet 860 /// CHECK: BoundsCheck 861 /// CHECK: ArrayGet 862 /// CHECK-NOT: BoundsCheck 863 /// CHECK: ArraySet 864 /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (after) 865 /// CHECK: Phi 866 /// CHECK-NOT: BoundsCheck 867 /// CHECK: ArrayGet 868 /// CHECK-NOT: BoundsCheck 869 /// CHECK: ArrayGet 870 /// CHECK-NOT: BoundsCheck 871 /// CHECK: ArrayGet 872 /// CHECK-NOT: BoundsCheck 873 /// CHECK: ArrayGet 874 /// CHECK-NOT: BoundsCheck 875 /// CHECK: ArrayGet 876 /// CHECK-NOT: BoundsCheck 877 /// CHECK: ArraySet 878 // Added blocks at end for deoptimization. 879 /// CHECK: Exit 880 /// CHECK: If 881 /// CHECK: Deoptimize 882 /// CHECK: Deoptimize 883 /// CHECK: Deoptimize 884 /// CHECK: Deoptimize 885 /// CHECK: Deoptimize 886 /// CHECK: Deoptimize 887 /// CHECK: Deoptimize 888 /// CHECK: Deoptimize 889 /// CHECK: Deoptimize 890 /// CHECK: Deoptimize 891 /// CHECK: Deoptimize 892 /// CHECK-NOT: Deoptimize 893 /// CHECK: Goto 894 /// CHECK: Goto 895 /// CHECK: Goto 896 897 void foo6(int[] array, int start, int end, boolean expectInterpreter) { 898 // Several HDeoptimize will be added. 899 for (int i = end; i >= start; i--) { 900 if (expectInterpreter) { 901 assertIsInterpreted(); 902 } else { 903 assertIsManaged(); 904 } 905 array[i] = (array[i-2] + array[i-1] + array[i] + array[i+1] + array[i+2]) / 5; 906 } 907 } 908 909 910 /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (before) 911 /// CHECK: BoundsCheck 912 /// CHECK: ArrayGet 913 /// CHECK: BoundsCheck 914 /// CHECK: ArrayGet 915 916 /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (after) 917 /// CHECK: Phi 918 /// CHECK: BoundsCheck 919 /// CHECK: ArrayGet 920 /// CHECK-NOT: BoundsCheck 921 /// CHECK: ArrayGet 922 // Added blocks at end for deoptimization. 923 /// CHECK: Exit 924 /// CHECK: If 925 /// CHECK: Deoptimize 926 /// CHECK: Deoptimize 927 /// CHECK: Deoptimize 928 /// CHECK-NOT: Deoptimize 929 /// CHECK: Goto 930 /// CHECK: Goto 931 /// CHECK: Goto 932 933 void foo7(int[] array, int start, int end, boolean lowEnd) { 934 // Three HDeoptimize will be added. One for the index 935 // and one for null check on array (to hoist null 936 // check and array.length out of loop). 937 for (int i = start ; i < end; i++) { 938 if (lowEnd) { 939 // This array access isn't certain. So we don't 940 // use +1000 offset in decision making for deoptimization 941 // conditions. 942 sum += array[i + 1000]; 943 } 944 sum += array[i]; 945 } 946 } 947 948 949 /// CHECK-START: void Main.foo8(int[][], int, int) BCE (before) 950 /// CHECK: BoundsCheck 951 /// CHECK: ArrayGet 952 /// CHECK: BoundsCheck 953 /// CHECK: ArraySet 954 955 /// CHECK-START: void Main.foo8(int[][], int, int) BCE (after) 956 /// CHECK: Phi 957 /// CHECK-NOT: BoundsCheck 958 /// CHECK: ArrayGet 959 /// CHECK: Phi 960 /// CHECK-NOT: BoundsCheck 961 /// CHECK: ArraySet 962 // Added blocks at end for deoptimization. 963 /// CHECK: Exit 964 /// CHECK: If 965 /// CHECK: Deoptimize 966 /// CHECK: Deoptimize 967 /// CHECK: Deoptimize 968 /// CHECK: Goto 969 /// CHECK: Goto 970 /// CHECK: Goto 971 /// CHECK: If 972 /// CHECK: Deoptimize 973 /// CHECK: Deoptimize 974 /// CHECK: Deoptimize 975 /// CHECK-NOT: Deoptimize 976 /// CHECK: Goto 977 /// CHECK: Goto 978 /// CHECK: Goto 979 980 void foo8(int[][] matrix, int start, int end) { 981 // Three HDeoptimize will be added for the outer loop, 982 // two for the index, and null check on matrix. Same 983 // for the inner loop. 984 for (int i = start; i < end; i++) { 985 int[] row = matrix[i]; 986 for (int j = start; j < end; j++) { 987 row[j] = 1; 988 } 989 } 990 } 991 992 993 /// CHECK-START: void Main.foo9(int[], boolean) BCE (before) 994 /// CHECK: NullCheck 995 /// CHECK: BoundsCheck 996 /// CHECK: ArrayGet 997 998 /// CHECK-START: void Main.foo9(int[], boolean) BCE (after) 999 // The loop is guaranteed to be entered. No need to transform the 1000 // loop for loop body entry test. 1001 /// CHECK: Deoptimize 1002 /// CHECK: Deoptimize 1003 /// CHECK: Deoptimize 1004 /// CHECK-NOT: Deoptimize 1005 /// CHECK: Phi 1006 /// CHECK-NOT: NullCheck 1007 /// CHECK-NOT: BoundsCheck 1008 /// CHECK: ArrayGet 1009 1010 /// CHECK-START: void Main.foo9(int[], boolean) instruction_simplifier_after_bce (after) 1011 // Simplification removes the redundant check 1012 /// CHECK: Deoptimize 1013 /// CHECK: Deoptimize 1014 /// CHECK-NOT: Deoptimize 1015 1016 void foo9(int[] array, boolean expectInterpreter) { 1017 // Two HDeoptimize will be added. Two for the index 1018 // and one for null check on array. 1019 for (int i = 0 ; i < 10; i++) { 1020 if (expectInterpreter) { 1021 assertIsInterpreted(); 1022 } else { 1023 assertIsManaged(); 1024 } 1025 sum += array[i]; 1026 } 1027 } 1028 1029 1030 /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (before) 1031 /// CHECK: BoundsCheck 1032 /// CHECK: ArraySet 1033 1034 /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (after) 1035 /// CHECK-NOT: Deoptimize 1036 /// CHECK: BoundsCheck 1037 /// CHECK: ArraySet 1038 1039 void partialLooping(int[] array, int start, int end) { 1040 // This loop doesn't cover the full range of [start, end) so 1041 // adding deoptimization is too aggressive, since end can be 1042 // greater than array.length but the loop is never going to work on 1043 // more than 2 elements. 1044 for (int i = start; i < end; i++) { 1045 if (i == 2) { 1046 return; 1047 } 1048 array[i] = 1; 1049 } 1050 } 1051 1052 1053 static void testUnknownBounds() { 1054 boolean caught = false; 1055 Main main = new Main(); 1056 main.foo1(new int[10], 0, 10, false); 1057 if (main.sum != 10) { 1058 System.out.println("foo1 failed!"); 1059 } 1060 1061 caught = false; 1062 main = new Main(); 1063 try { 1064 main.foo1(new int[10], 0, 11, true); 1065 } catch (ArrayIndexOutOfBoundsException e) { 1066 caught = true; 1067 } 1068 if (!caught || main.sum != 10) { 1069 System.out.println("foo1 exception failed!"); 1070 } 1071 1072 main = new Main(); 1073 main.foo2(new int[10], 0, 9, false); 1074 if (main.sum != 10) { 1075 System.out.println("foo2 failed!"); 1076 } 1077 1078 caught = false; 1079 main = new Main(); 1080 try { 1081 main.foo2(new int[10], 0, 10, true); 1082 } catch (ArrayIndexOutOfBoundsException e) { 1083 caught = true; 1084 } 1085 if (!caught || main.sum != 10) { 1086 System.out.println("foo2 exception failed!"); 1087 } 1088 1089 main = new Main(); 1090 main.foo3(new int[10], 9, false); 1091 if (main.sum != 7) { 1092 System.out.println("foo3 failed!"); 1093 } 1094 1095 caught = false; 1096 main = new Main(); 1097 try { 1098 main.foo3(new int[10], 10, true); 1099 } catch (ArrayIndexOutOfBoundsException e) { 1100 caught = true; 1101 } 1102 if (!caught || main.sum != 7) { 1103 System.out.println("foo3 exception failed!"); 1104 } 1105 1106 main = new Main(); 1107 main.foo4(new int[10], 10, false); 1108 if (main.sum != 10) { 1109 System.out.println("foo4 failed!"); 1110 } 1111 1112 caught = false; 1113 main = new Main(); 1114 try { 1115 main.foo4(new int[10], 11, true); 1116 } catch (ArrayIndexOutOfBoundsException e) { 1117 caught = true; 1118 } 1119 if (!caught || main.sum != 0) { 1120 System.out.println("foo4 exception failed!"); 1121 } 1122 1123 main = new Main(); 1124 main.foo5(new int[10], 10, false); 1125 if (main.sum != 24) { 1126 System.out.println("foo5 failed!"); 1127 } 1128 1129 caught = false; 1130 main = new Main(); 1131 try { 1132 main.foo5(new int[10], 11, true); 1133 } catch (ArrayIndexOutOfBoundsException e) { 1134 caught = true; 1135 } 1136 if (!caught || main.sum != 2) { 1137 System.out.println("foo5 exception failed!"); 1138 } 1139 1140 main = new Main(); 1141 main.foo6(new int[10], 2, 7, false); 1142 1143 main = new Main(); 1144 int[] array9 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 1145 main.foo9(array9, false); 1146 if (main.sum != 45) { 1147 System.out.println("foo9 failed!"); 1148 } 1149 1150 main = new Main(); 1151 int[] array = new int[4]; 1152 main.partialLooping(new int[3], 0, 4); 1153 if ((array[0] != 1) && (array[1] != 1) && 1154 (array[2] != 0) && (array[3] != 0)) { 1155 System.out.println("partialLooping failed!"); 1156 } 1157 1158 caught = false; 1159 main = new Main(); 1160 try { 1161 main.foo6(new int[10], 2, 8, true); 1162 } catch (ArrayIndexOutOfBoundsException e) { 1163 caught = true; 1164 } 1165 if (!caught) { 1166 System.out.println("foo6 exception failed!"); 1167 } 1168 1169 caught = false; 1170 main = new Main(); 1171 try { 1172 main.foo6(new int[10], 1, 7, true); 1173 } catch (ArrayIndexOutOfBoundsException e) { 1174 caught = true; 1175 } 1176 if (!caught) { 1177 System.out.println("foo6 exception failed!"); 1178 } 1179 1180 } 1181 1182 public void testExceptionMessage() { 1183 short[] B1 = new short[5]; 1184 int[] B2 = new int[5]; 1185 Exception err = null; 1186 try { 1187 testExceptionMessage1(B1, B2, null, -1, 6); 1188 } catch (Exception e) { 1189 err = e; 1190 } 1191 System.out.println(err); 1192 } 1193 1194 void testExceptionMessage1(short[] a1, int[] a2, long a3[], int start, int finish) { 1195 int j = finish + 77; 1196 // Bug: 22665511 1197 // A deoptimization will be triggered here right before the loop. Need to make 1198 // sure the value of j is preserved for the interpreter. 1199 for (int i = start; i <= finish; i++) { 1200 a2[j - 1] = a1[i + 1]; 1201 } 1202 } 1203 1204 // Make sure this method is compiled with optimizing. 1205 /// CHECK-START: void Main.main(java.lang.String[]) register (after) 1206 /// CHECK: ParallelMove 1207 1208 public static void main(String[] args) { 1209 System.loadLibrary(args[0]); 1210 1211 if (!compiledWithOptimizing() || 1212 !hasOatFile() || 1213 runtimeIsSoftFail() || 1214 isInterpreted()) { 1215 disableStackFrameAsserts(); 1216 } 1217 1218 sieve(20); 1219 1220 int[] array = {5, 2, 3, 7, 0, 1, 6, 4}; 1221 bubbleSort(array); 1222 for (int i = 0; i < 8; i++) { 1223 if (array[i] != i) { 1224 System.out.println("bubble sort failed!"); 1225 } 1226 } 1227 1228 array = new int[7]; 1229 pyramid1(array); 1230 if (!isPyramid(array)) { 1231 System.out.println("pyramid1 failed!"); 1232 } 1233 1234 array = new int[8]; 1235 pyramid2(array); 1236 if (!isPyramid(array)) { 1237 System.out.println("pyramid2 failed!"); 1238 } 1239 1240 java.util.Arrays.fill(array, -1); 1241 pyramid3(array); 1242 if (!isPyramid(array)) { 1243 System.out.println("pyramid3 failed!"); 1244 } 1245 1246 // Make sure this value is kept after deoptimization. 1247 int i = 1; 1248 if (foo() + i != 100) { 1249 System.out.println("foo failed!"); 1250 }; 1251 1252 testUnknownBounds(); 1253 new Main().testExceptionMessage(); 1254 } 1255 1256 public static native boolean compiledWithOptimizing(); 1257 public static native void disableStackFrameAsserts(); 1258 public static native void assertIsManaged(); 1259 public static native void assertIsInterpreted(); 1260 public static native boolean hasOatFile(); 1261 public static native boolean runtimeIsSoftFail(); 1262 public static native boolean isInterpreted(); 1263} 1264