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 import java.util.Arrays; 18 19 public class Main { 20 21 /// CHECK-START: int Main.sieve(int) BCE (before) 22 /// CHECK: BoundsCheck 23 /// CHECK: ArraySet 24 /// CHECK: BoundsCheck 25 /// CHECK: ArrayGet 26 /// CHECK: BoundsCheck 27 /// CHECK: ArraySet 28 29 /// CHECK-START: int Main.sieve(int) BCE (after) 30 /// CHECK-NOT: BoundsCheck 31 /// CHECK: ArraySet 32 /// CHECK-NOT: BoundsCheck 33 /// CHECK: ArrayGet 34 /// CHECK: BoundsCheck 35 /// CHECK: ArraySet 36 sieve(int size)37 static int sieve(int size) { 38 int primeCount = 0; 39 boolean[] flags = new boolean[size + 1]; 40 for (int i = 1; i < size; i++) flags[i] = true; // Can eliminate. 41 for (int i = 2; i < size; i++) { 42 if (flags[i]) { // Can eliminate. 43 primeCount++; 44 for (int k = i + 1; k <= size; k += i) 45 flags[k - 1] = false; // Can't eliminate yet due to (k+i) may overflow. 46 } 47 } 48 return primeCount; 49 } 50 51 52 /// CHECK-START: void Main.narrow(int[], int) BCE (before) 53 /// CHECK: BoundsCheck 54 /// CHECK: ArraySet 55 /// CHECK: BoundsCheck 56 /// CHECK: ArraySet 57 /// CHECK: BoundsCheck 58 /// CHECK: ArraySet 59 60 /// CHECK-START: void Main.narrow(int[], int) BCE (after) 61 /// CHECK-NOT: BoundsCheck 62 /// CHECK: ArraySet 63 /// CHECK-NOT: BoundsCheck 64 /// CHECK: ArraySet 65 /// CHECK: BoundsCheck 66 /// CHECK: ArraySet 67 /// CHECK-NOT: BoundsCheck 68 /// CHECK: ArraySet 69 /// CHECK: BoundsCheck 70 /// CHECK: ArraySet 71 narrow(int[] array, int offset)72 static void narrow(int[] array, int offset) { 73 if (offset < 0) { 74 return; 75 } 76 if (offset < array.length) { 77 // offset is in range [0, array.length-1]. 78 // Bounds check can be eliminated. 79 array[offset] = 1; 80 81 int biased_offset1 = offset + 1; 82 // biased_offset1 is in range [1, array.length]. 83 if (biased_offset1 < array.length) { 84 // biased_offset1 is in range [1, array.length-1]. 85 // Bounds check can be eliminated. 86 array[biased_offset1] = 1; 87 } 88 89 int biased_offset2 = offset + 0x70000000; 90 // biased_offset2 is in range [0x70000000, array.length-1+0x70000000]. 91 // It may overflow and be negative. 92 if (biased_offset2 < array.length) { 93 // Even with this test, biased_offset2 can be negative so we can't 94 // eliminate this bounds check. 95 array[biased_offset2] = 1; 96 } 97 98 // offset_sub1 won't underflow since offset is no less than 0. 99 int offset_sub1 = offset - Integer.MAX_VALUE; 100 if (offset_sub1 >= 0) { 101 array[offset_sub1] = 1; // Bounds check can be eliminated. 102 } 103 104 // offset_sub2 can underflow. 105 int offset_sub2 = offset_sub1 - Integer.MAX_VALUE; 106 if (offset_sub2 >= 0) { 107 array[offset_sub2] = 1; // Bounds check can't be eliminated. 108 } 109 } 110 } 111 112 113 /// CHECK-START: void Main.constantIndexing1(int[]) BCE (before) 114 /// CHECK: BoundsCheck 115 /// CHECK: ArraySet 116 /// CHECK: BoundsCheck 117 /// CHECK: ArraySet 118 119 /// CHECK-START: void Main.constantIndexing1(int[]) BCE (after) 120 /// CHECK-NOT: Deoptimize 121 /// CHECK: BoundsCheck 122 /// CHECK: ArraySet 123 /// CHECK-NOT: BoundsCheck 124 /// CHECK: ArraySet 125 constantIndexing1(int[] array)126 static void constantIndexing1(int[] array) { 127 // Decreasing order: bc for 5 but not for 4. 128 array[5] = 11; 129 array[4] = 11; 130 } 131 132 133 /// CHECK-START: void Main.$opt$noinline$constantIndexing2(int[]) BCE (before) 134 /// CHECK: BoundsCheck 135 /// CHECK: ArraySet 136 /// CHECK: BoundsCheck 137 /// CHECK: ArraySet 138 /// CHECK: BoundsCheck 139 /// CHECK: ArraySet 140 /// CHECK: BoundsCheck 141 /// CHECK: ArraySet 142 143 /// CHECK-START: void Main.$opt$noinline$constantIndexing2(int[]) BCE (after) 144 /// CHECK: Deoptimize 145 /// CHECK-NOT: BoundsCheck 146 /// CHECK: ArraySet 147 /// CHECK-NOT: BoundsCheck 148 /// CHECK: ArraySet 149 /// CHECK-NOT: BoundsCheck 150 /// CHECK: ArraySet 151 /// CHECK-NOT: BoundsCheck 152 /// CHECK: ArraySet 153 $opt$noinline$constantIndexing2(int[] array)154 static void $opt$noinline$constantIndexing2(int[] array) { 155 array[1] = 1; 156 array[2] = 1; 157 array[3] = 1; 158 array[4] = 1; 159 if (array[1] != 1) { 160 throw new Error(""); 161 } 162 } 163 164 /// CHECK-START: void Main.constantIndexing2b(int[]) BCE (before) 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 /// CHECK: BoundsCheck 174 /// CHECK: ArraySet 175 176 /// CHECK-START: void Main.constantIndexing2b(int[]) BCE (after) 177 /// CHECK-NOT: Deoptimize 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 /// CHECK: BoundsCheck 187 /// CHECK: ArraySet 188 constantIndexing2b(int[] array)189 static void constantIndexing2b(int[] array) { 190 array[0] = 6; 191 array[1] = 6; 192 array[2] = 6; 193 array[3] = 6; 194 array[-1] = 1; // prevents the whole opt on [-1:4] 195 } 196 197 /// CHECK-START: void Main.constantIndexing2c(int[]) BCE (before) 198 /// CHECK: BoundsCheck 199 /// CHECK: ArraySet 200 /// CHECK: BoundsCheck 201 /// CHECK: ArraySet 202 /// CHECK: BoundsCheck 203 /// CHECK: ArraySet 204 /// CHECK: BoundsCheck 205 /// CHECK: ArraySet 206 207 /// CHECK-START: void Main.constantIndexing2c(int[]) BCE (after) 208 /// CHECK: Deoptimize 209 /// CHECK-NOT: BoundsCheck 210 /// CHECK: ArraySet 211 /// CHECK-NOT: BoundsCheck 212 /// CHECK: ArraySet 213 /// CHECK-NOT: BoundsCheck 214 /// CHECK: ArraySet 215 /// CHECK-NOT: BoundsCheck 216 /// CHECK: ArraySet 217 constantIndexing2c(int[] array)218 static void constantIndexing2c(int[] array) { 219 array[0] = 7; 220 array[1] = 7; 221 array[2] = 7; 222 array[3] = 7; 223 } 224 225 /// CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (before) 226 /// CHECK: BoundsCheck 227 /// CHECK: ArrayGet 228 /// CHECK: BoundsCheck 229 /// CHECK: ArraySet 230 /// CHECK: BoundsCheck 231 /// CHECK: ArrayGet 232 /// CHECK: BoundsCheck 233 /// CHECK: ArraySet 234 /// CHECK: BoundsCheck 235 /// CHECK: ArrayGet 236 /// CHECK: BoundsCheck 237 /// CHECK: ArraySet 238 /// CHECK: BoundsCheck 239 /// CHECK: ArrayGet 240 /// CHECK: BoundsCheck 241 /// CHECK: ArraySet 242 243 /// CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (after) 244 /// CHECK: Deoptimize 245 /// CHECK-NOT: BoundsCheck 246 /// CHECK: ArrayGet 247 /// CHECK: Deoptimize 248 /// CHECK-NOT: BoundsCheck 249 /// CHECK: ArraySet 250 /// CHECK-NOT: BoundsCheck 251 /// CHECK: ArrayGet 252 /// CHECK-NOT: BoundsCheck 253 /// CHECK: ArraySet 254 /// CHECK-NOT: BoundsCheck 255 /// CHECK: ArrayGet 256 /// CHECK-NOT: BoundsCheck 257 /// CHECK: ArraySet 258 /// CHECK-NOT: BoundsCheck 259 /// CHECK: ArrayGet 260 /// CHECK-NOT: BoundsCheck 261 /// CHECK: ArraySet 262 constantIndexing3(int[] array1, int[] array2, boolean copy)263 static int[] constantIndexing3(int[] array1, int[] array2, boolean copy) { 264 if (!copy) { 265 return array1; 266 } 267 array2[0] = array1[0]; 268 array2[1] = array1[1]; 269 array2[2] = array1[2]; 270 array2[3] = array1[3]; 271 return array2; 272 } 273 274 275 /// CHECK-START: void Main.constantIndexing4(int[]) BCE (before) 276 /// CHECK: BoundsCheck 277 /// CHECK: ArraySet 278 279 /// CHECK-START: void Main.constantIndexing4(int[]) BCE (after) 280 /// CHECK-NOT: Deoptimize 281 /// CHECK: BoundsCheck 282 /// CHECK: ArraySet 283 284 // There is only one array access. It's not beneficial 285 // to create a compare with deoptimization instruction. constantIndexing4(int[] array)286 static void constantIndexing4(int[] array) { 287 array[0] = -1; 288 } 289 290 291 /// CHECK-START: void Main.constantIndexing5(int[]) BCE (before) 292 /// CHECK: BoundsCheck 293 /// CHECK: ArraySet 294 /// CHECK: BoundsCheck 295 /// CHECK: ArraySet 296 297 /// CHECK-START: void Main.constantIndexing5(int[]) BCE (after) 298 /// CHECK-NOT: Deoptimize 299 /// CHECK: BoundsCheck 300 /// CHECK: ArraySet 301 /// CHECK: BoundsCheck 302 /// CHECK: ArraySet 303 constantIndexing5(int[] array)304 static void constantIndexing5(int[] array) { 305 // We don't apply the deoptimization for very large constant index 306 // since it's likely to be an anomaly and will throw AIOOBE. 307 array[Integer.MAX_VALUE - 1000] = 1; 308 array[Integer.MAX_VALUE - 999] = 1; 309 array[Integer.MAX_VALUE - 998] = 1; 310 } 311 312 /// CHECK-START: void Main.constantIndexing6(int[]) BCE (before) 313 /// CHECK: BoundsCheck 314 /// CHECK: ArraySet 315 /// CHECK: BoundsCheck 316 /// CHECK: ArraySet 317 318 /// CHECK-START: void Main.constantIndexing6(int[]) BCE (after) 319 /// CHECK: Deoptimize 320 /// CHECK-NOT: BoundsCheck 321 /// CHECK: ArraySet 322 /// CHECK-NOT: BoundsCheck 323 /// CHECK: ArraySet 324 constantIndexing6(int[] array)325 static void constantIndexing6(int[] array) { 326 array[3] = 111; 327 array[4] = 111; 328 } 329 330 /// CHECK-START: void Main.constantIndexing7(int[], int) BCE (before) 331 /// CHECK: BoundsCheck 332 /// CHECK: ArraySet 333 /// CHECK: BoundsCheck 334 /// CHECK: ArraySet 335 /// CHECK: BoundsCheck 336 /// CHECK: ArraySet 337 /// CHECK: BoundsCheck 338 /// CHECK: ArraySet 339 340 /// CHECK-START: void Main.constantIndexing7(int[], int) BCE (after) 341 /// CHECK: Deoptimize 342 /// CHECK: Deoptimize 343 /// CHECK-NOT: BoundsCheck 344 /// CHECK: ArraySet 345 /// CHECK-NOT: BoundsCheck 346 /// CHECK: ArraySet 347 /// CHECK-NOT: BoundsCheck 348 /// CHECK: ArraySet 349 /// CHECK-NOT: BoundsCheck 350 /// CHECK: ArraySet 351 constantIndexing7(int[] array, int base)352 static void constantIndexing7(int[] array, int base) { 353 // With constant offsets to symbolic base. 354 array[base] = 10; 355 array[base + 1] = 20; 356 array[base + 2] = 30; 357 array[base + 3] = 40; 358 } 359 360 /// CHECK-START: void Main.constantIndexing8(int[], int) BCE (before) 361 /// CHECK: BoundsCheck 362 /// CHECK: ArraySet 363 /// CHECK: BoundsCheck 364 /// CHECK: ArraySet 365 /// CHECK: BoundsCheck 366 /// CHECK: ArraySet 367 /// CHECK: BoundsCheck 368 /// CHECK: ArraySet 369 370 /// CHECK-START: void Main.constantIndexing8(int[], int) BCE (after) 371 /// CHECK: Deoptimize 372 /// CHECK: Deoptimize 373 /// CHECK-NOT: BoundsCheck 374 /// CHECK: ArraySet 375 /// CHECK-NOT: BoundsCheck 376 /// CHECK: ArraySet 377 /// CHECK-NOT: BoundsCheck 378 /// CHECK: ArraySet 379 /// CHECK-NOT: BoundsCheck 380 /// CHECK: ArraySet 381 constantIndexing8(int[] array, int base)382 static void constantIndexing8(int[] array, int base) { 383 // With constant offsets "both ways" to symbolic base. 384 array[base - 1] = 100; 385 array[base] = 200; 386 array[base + 1] = 300; 387 array[base + 2] = 400; 388 } 389 390 /// CHECK-START: void Main.constantIndexing9(int[], int) BCE (before) 391 /// CHECK: BoundsCheck 392 /// CHECK: ArraySet 393 /// CHECK: BoundsCheck 394 /// CHECK: ArraySet 395 /// CHECK: BoundsCheck 396 /// CHECK: ArraySet 397 /// CHECK: BoundsCheck 398 /// CHECK: ArraySet 399 400 /// CHECK-START: void Main.constantIndexing9(int[], int) BCE (after) 401 /// CHECK: Deoptimize 402 /// CHECK: Deoptimize 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 /// CHECK: ArraySet 411 /// CHECK-NOT: BoundsCheck 412 constantIndexing9(int[] array, int base)413 static void constantIndexing9(int[] array, int base) { 414 // Final range is base..base+3 so conditional 415 // references may be included in the end. 416 array[base] = 0; 417 if (base != 12345) 418 array[base + 2] = 2; 419 array[base + 3] = 3; 420 if (base != 67890) 421 array[base + 1] = 1; 422 } 423 424 /// CHECK-START: void Main.constantIndexing10(int[], int) BCE (before) 425 /// CHECK: BoundsCheck 426 /// CHECK: ArraySet 427 /// CHECK: BoundsCheck 428 /// CHECK: ArraySet 429 /// CHECK: BoundsCheck 430 /// CHECK: ArraySet 431 /// CHECK: BoundsCheck 432 /// CHECK: ArraySet 433 434 /// CHECK-START: void Main.constantIndexing10(int[], int) BCE (after) 435 /// CHECK: Deoptimize 436 /// CHECK: Deoptimize 437 /// CHECK-NOT: BoundsCheck 438 /// CHECK: ArraySet 439 /// CHECK-NOT: BoundsCheck 440 /// CHECK: ArraySet 441 /// CHECK-NOT: BoundsCheck 442 /// CHECK: ArraySet 443 /// CHECK-NOT: BoundsCheck 444 /// CHECK: ArraySet 445 constantIndexing10(int[] array, int base)446 static void constantIndexing10(int[] array, int base) { 447 // Offset hidden in incremented base. 448 array[base] = 1; 449 array[++base] = 2; 450 array[++base] = 3; 451 array[++base] = 4; 452 } 453 runAllConstantIndices()454 static void runAllConstantIndices() { 455 int[] a1 = { 0 }; 456 int[] a6 = { 0, 0, 0, 0, 0, 0 }; 457 458 boolean caught = false; 459 try { 460 constantIndexing1(a1); 461 } catch (ArrayIndexOutOfBoundsException e) { 462 caught = true; 463 } 464 if (!caught) { 465 System.out.println("constant indices 1 failed!"); 466 } 467 468 constantIndexing1(a6); 469 if (a6[4] != 11 || a6[5] != 11) { 470 System.out.println("constant indices 1 failed!"); 471 } 472 473 $opt$noinline$constantIndexing2(a6); 474 if (a6[0] != 0 || a6[1] != 1 || a6[2] != 1 || 475 a6[3] != 1 || a6[4] != 1 || a6[5] != 11) { 476 System.out.println("constant indices 2 failed!"); 477 } 478 479 caught = false; 480 try { 481 constantIndexing2b(a6); 482 } catch (ArrayIndexOutOfBoundsException e) { 483 caught = true; 484 } 485 if (!caught || a6[0] != 6 || a6[1] != 6 || a6[2] != 6 || 486 a6[3] != 6 || a6[4] != 1 || a6[5] != 11) { 487 System.out.println("constant indices 2b failed!"); 488 } 489 490 caught = false; 491 try { 492 constantIndexing2c(a1); 493 } catch (ArrayIndexOutOfBoundsException e) { 494 caught = true; 495 } 496 if (!caught || a1[0] != 7) { 497 System.out.println("constant indices 2c failed!"); 498 } 499 500 constantIndexing2c(a6); 501 if (a6[0] != 7 || a6[1] != 7 || a6[2] != 7 || 502 a6[3] != 7 || a6[4] != 1 || a6[5] != 11) { 503 System.out.println("constant indices 2c failed!"); 504 } 505 506 int[] b4 = new int[4]; 507 constantIndexing3(a6, b4, true); 508 if (b4[0] != 7 || b4[1] != 7 || b4[2] != 7 || b4[3] != 7) { 509 System.out.println("constant indices 3 failed!"); 510 } 511 512 constantIndexing4(a1); 513 if (a1[0] != -1) { 514 System.out.println("constant indices 4 failed!"); 515 } 516 517 caught = false; 518 try { 519 constantIndexing5(a6); 520 } catch (ArrayIndexOutOfBoundsException e) { 521 caught = true; 522 } 523 if (!caught) { 524 System.out.println("constant indices 5 failed!"); 525 } 526 527 constantIndexing6(a6); 528 if (a6[0] != 7 || a6[1] != 7 || a6[2] != 7 || 529 a6[3] != 111 || a6[4] != 111 || a6[5] != 11) { 530 System.out.println("constant indices 6 failed!"); 531 } 532 533 constantIndexing7(a6, 1); 534 if (a6[0] != 7 || a6[1] != 10 || a6[2] != 20 || 535 a6[3] != 30 || a6[4] != 40 || a6[5] != 11) { 536 System.out.println("constant indices 7 failed!"); 537 } 538 539 caught = false; 540 try { 541 constantIndexing7(a6, 5); 542 } catch (ArrayIndexOutOfBoundsException e) { 543 caught = true; 544 } 545 if (!caught || a6[0] != 7 || a6[1] != 10 || a6[2] != 20 || 546 a6[3] != 30 || a6[4] != 40 || a6[5] != 10) { 547 System.out.println("constant indices 7 failed!"); 548 } 549 550 constantIndexing8(a6, 1); 551 if (a6[0] != 100 || a6[1] != 200 || a6[2] != 300 || 552 a6[3] != 400 || a6[4] != 40 || a6[5] != 10) { 553 System.out.println("constant indices 8 failed!"); 554 } 555 556 caught = false; 557 try { 558 constantIndexing8(a6, 0); 559 } catch (ArrayIndexOutOfBoundsException e) { 560 caught = true; 561 } 562 if (!caught || a6[0] != 100) { 563 System.out.println("constant indices 8 failed!"); 564 } 565 566 constantIndexing9(a6, 0); 567 if (a6[0] != 0 || a6[1] != 1 || a6[2] != 2 || 568 a6[3] != 3 || a6[4] != 40 || a6[5] != 10) { 569 System.out.println("constant indices 9 failed!"); 570 } 571 572 constantIndexing10(a6, 0); 573 if (a6[0] != 1 || a6[1] != 2 || a6[2] != 3 || 574 a6[3] != 4 || a6[4] != 40 || a6[5] != 10) { 575 System.out.println("constant indices 10 failed!"); 576 } 577 } 578 579 // A helper into which the actual throwing function should be inlined. constantIndexingForward6(int[] array)580 static void constantIndexingForward6(int[] array) { 581 assertIsManaged(); 582 constantIndexing6(array); 583 } 584 585 /// CHECK-START: void Main.loopPattern1(int[]) BCE (before) 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 /// CHECK: BoundsCheck 599 /// CHECK: ArraySet 600 601 /// CHECK-START: void Main.loopPattern1(int[]) BCE (after) 602 /// CHECK-NOT: BoundsCheck 603 /// CHECK: ArraySet 604 /// CHECK-NOT: BoundsCheck 605 /// CHECK: ArraySet 606 /// CHECK-NOT: BoundsCheck 607 /// CHECK: ArraySet 608 /// CHECK: BoundsCheck 609 /// CHECK: ArraySet 610 /// CHECK: BoundsCheck 611 /// CHECK: ArraySet 612 /// CHECK: BoundsCheck 613 /// CHECK: ArraySet 614 /// CHECK-NOT: BoundsCheck 615 /// CHECK: ArraySet 616 loopPattern1(int[] array)617 static void loopPattern1(int[] array) { 618 for (int i = 0; i < array.length; i++) { 619 array[i] = 1; // Bounds check can be eliminated. 620 } 621 622 for (int i = 1; i < array.length; i++) { 623 array[i] = 1; // Bounds check can be eliminated. 624 } 625 626 for (int i = 1; i < array.length - 1; i++) { 627 array[i] = 1; // Bounds check can be eliminated. 628 } 629 630 for (int i = -1; i < array.length; i++) { 631 array[i] = 1; // Bounds check can't be eliminated. 632 } 633 634 for (int i = 0; i <= array.length; i++) { 635 array[i] = 1; // Bounds check can't be eliminated. 636 } 637 638 for (int i = 0; i < array.length; i += 2) { 639 // We don't have any assumption on max array length yet. 640 // Bounds check can't be eliminated due to overflow concern. 641 array[i] = 1; 642 } 643 644 for (int i = 1; i < array.length; i += 2) { 645 // Bounds check can be eliminated since i is odd so the last 646 // i that's less than array.length is at most (Integer.MAX_VALUE - 2). 647 array[i] = 1; 648 } 649 } 650 651 652 /// CHECK-START: void Main.loopPattern2(int[]) BCE (before) 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 /// CHECK: BoundsCheck 664 /// CHECK: ArraySet 665 666 /// CHECK-START: void Main.loopPattern2(int[]) BCE (after) 667 /// CHECK-NOT: BoundsCheck 668 /// CHECK: ArraySet 669 /// CHECK-NOT: BoundsCheck 670 /// CHECK: ArraySet 671 /// CHECK-NOT: BoundsCheck 672 /// CHECK: ArraySet 673 /// CHECK: BoundsCheck 674 /// CHECK: ArraySet 675 /// CHECK: BoundsCheck 676 /// CHECK: ArraySet 677 /// CHECK-NOT: BoundsCheck 678 /// CHECK: ArraySet 679 loopPattern2(int[] array)680 static void loopPattern2(int[] array) { 681 for (int i = array.length - 1; i >= 0; i--) { 682 array[i] = 1; // Bounds check can be eliminated. 683 } 684 685 for (int i = array.length; i > 0; i--) { 686 array[i - 1] = 1; // Bounds check can be eliminated. 687 } 688 689 for (int i = array.length - 1; i > 0; i--) { 690 array[i] = 1; // Bounds check can be eliminated. 691 } 692 693 for (int i = array.length; i >= 0; i--) { 694 array[i] = 1; // Bounds check can't be eliminated. 695 } 696 697 for (int i = array.length; i >= 0; i--) { 698 array[i - 1] = 1; // Bounds check can't be eliminated. 699 } 700 701 for (int i = array.length; i > 0; i -= 20) { 702 // For i >= 0, (i - 20 - 1) is guaranteed not to underflow. 703 array[i - 1] = 1; // Bounds check can be eliminated. 704 } 705 } 706 707 708 /// CHECK-START: void Main.loopPattern3(int[]) BCE (before) 709 /// CHECK: BoundsCheck 710 /// CHECK: ArraySet 711 712 /// CHECK-START: void Main.loopPattern3(int[]) BCE (after) 713 /// CHECK: BoundsCheck 714 /// CHECK: ArraySet 715 loopPattern3(int[] array)716 static void loopPattern3(int[] array) { 717 java.util.Random random = new java.util.Random(); 718 for (int i = 0; ; i++) { 719 if (random.nextInt() % 1000 == 0 && i < array.length) { 720 // Can't eliminate the bound check since not every i++ is 721 // matched with a array length check, so there is some chance that i 722 // overflows and is negative. 723 array[i] = 1; 724 } 725 } 726 } 727 728 729 /// CHECK-START: void Main.constantNewArray() BCE (before) 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 /// CHECK: BoundsCheck 739 /// CHECK: ArraySet 740 741 /// CHECK-START: void Main.constantNewArray() BCE (after) 742 /// CHECK-NOT: BoundsCheck 743 /// CHECK: ArraySet 744 /// CHECK: BoundsCheck 745 /// CHECK: ArraySet 746 /// CHECK-NOT: BoundsCheck 747 /// CHECK: ArraySet 748 /// CHECK-NOT: BoundsCheck 749 /// CHECK: ArraySet 750 /// CHECK: BoundsCheck 751 /// CHECK: ArraySet 752 constantNewArray()753 static void constantNewArray() { 754 int[] array = new int[10]; 755 for (int i = 0; i < 10; i++) { 756 array[i] = 1; // Bounds check can be eliminated. 757 } 758 759 for (int i = 0; i <= 10; i++) { 760 array[i] = 1; // Bounds check can't be eliminated. 761 } 762 763 array[0] = 1; // Bounds check can be eliminated. 764 array[9] = 1; // Bounds check can be eliminated. 765 array[10] = 1; // Bounds check can't be eliminated. 766 } 767 768 readData()769 static byte readData() { 770 return 1; 771 } 772 773 /// CHECK-START: void Main.circularBufferProducer() BCE (before) 774 /// CHECK: BoundsCheck 775 /// CHECK: ArraySet 776 777 /// CHECK-START: void Main.circularBufferProducer() BCE (after) 778 /// CHECK-NOT: BoundsCheck 779 /// CHECK: ArraySet 780 circularBufferProducer()781 static void circularBufferProducer() { 782 byte[] array = new byte[4096]; 783 int i = 0; 784 while (true) { 785 array[i & (array.length - 1)] = readData(); 786 i++; 787 } 788 } 789 790 791 /// CHECK-START: void Main.pyramid1(int[]) BCE (before) 792 /// CHECK: BoundsCheck 793 /// CHECK: ArraySet 794 /// CHECK: BoundsCheck 795 /// CHECK: ArraySet 796 797 /// CHECK-START: void Main.pyramid1(int[]) BCE (after) 798 /// CHECK-NOT: BoundsCheck 799 /// CHECK: ArraySet 800 /// CHECK-NOT: BoundsCheck 801 /// CHECK: ArraySet 802 803 // Set array to something like {0, 1, 2, 3, 2, 1, 0}. pyramid1(int[] array)804 static void pyramid1(int[] array) { 805 for (int i = 0; i < (array.length + 1) / 2; i++) { 806 array[i] = i; 807 array[array.length - 1 - i] = i; 808 } 809 } 810 811 812 /// CHECK-START: void Main.pyramid2(int[]) BCE (before) 813 /// CHECK: BoundsCheck 814 /// CHECK: ArraySet 815 /// CHECK: BoundsCheck 816 /// CHECK: ArraySet 817 818 /// CHECK-START: void Main.pyramid2(int[]) BCE (after) 819 /// CHECK-NOT: BoundsCheck 820 /// CHECK: ArraySet 821 /// CHECK-NOT: BoundsCheck 822 /// CHECK: ArraySet 823 824 // Set array to something like {0, 1, 2, 3, 2, 1, 0}. pyramid2(int[] array)825 static void pyramid2(int[] array) { 826 for (int i = 0; i < (array.length + 1) >> 1; i++) { 827 array[i] = i; 828 array[array.length - 1 - i] = i; 829 } 830 } 831 832 833 /// CHECK-START: void Main.pyramid3(int[]) BCE (before) 834 /// CHECK: BoundsCheck 835 /// CHECK: ArraySet 836 /// CHECK: BoundsCheck 837 /// CHECK: ArraySet 838 839 /// CHECK-START: void Main.pyramid3(int[]) BCE (after) 840 /// CHECK-NOT: BoundsCheck 841 /// CHECK: ArraySet 842 /// CHECK-NOT: BoundsCheck 843 /// CHECK: ArraySet 844 845 // Set array to something like {0, 1, 2, 3, 2, 1, 0}. pyramid3(int[] array)846 static void pyramid3(int[] array) { 847 for (int i = 0; i < (array.length + 1) >>> 1; i++) { 848 array[i] = i; 849 array[array.length - 1 - i] = i; 850 } 851 } 852 853 854 /// CHECK-START: boolean Main.isPyramid(int[]) BCE (before) 855 /// CHECK: BoundsCheck 856 /// CHECK: ArrayGet 857 /// CHECK: BoundsCheck 858 /// CHECK: ArrayGet 859 860 /// CHECK-START: boolean Main.isPyramid(int[]) BCE (after) 861 /// CHECK-NOT: BoundsCheck 862 /// CHECK: ArrayGet 863 /// CHECK-NOT: BoundsCheck 864 /// CHECK: ArrayGet 865 isPyramid(int[] array)866 static boolean isPyramid(int[] array) { 867 int i = 0; 868 int j = array.length - 1; 869 while (i <= j) { 870 if (array[i] != i) { 871 return false; 872 } 873 if (array[j] != i) { 874 return false; 875 } 876 i++; j--; 877 } 878 return true; 879 } 880 881 /// CHECK-START: void Main.modArrayIndex1(int[]) BCE (before) 882 /// CHECK-DAG: BoundsCheck 883 /// CHECK-DAG: ArraySet 884 /// CHECK-DAG: BoundsCheck 885 /// CHECK-DAG: ArraySet 886 887 /// CHECK-START: void Main.modArrayIndex1(int[]) BCE (after) 888 /// CHECK-NOT: Deoptimize 889 /// CHECK-DAG: BoundsCheck 890 /// CHECK-DAG: ArraySet 891 /// CHECK-NOT: BoundsCheck 892 /// CHECK-DAG: ArraySet modArrayIndex1(int[] array)893 public static void modArrayIndex1(int[] array) { 894 for(int i = 0; i < 100; i++) { 895 // Cannot statically eliminate, for example, when array.length == 5. 896 // Currently dynamic BCE isn't applied for this case. 897 array[i % 10] = i; 898 // Can be eliminated by BCE. 899 array[i % array.length] = i; 900 } 901 } 902 903 /// CHECK-START: void Main.modArrayIndex2(int[], int) BCE (before) 904 /// CHECK-DAG: BoundsCheck 905 /// CHECK-DAG: ArraySet 906 /// CHECK-DAG: BoundsCheck 907 /// CHECK-DAG: ArraySet 908 909 /// CHECK-START: void Main.modArrayIndex2(int[], int) BCE (after) 910 /// CHECK-NOT: Deoptimize 911 /// CHECK-DAG: BoundsCheck 912 /// CHECK-DAG: ArraySet 913 /// CHECK-DAG: BoundsCheck 914 /// CHECK-DAG: ArraySet modArrayIndex2(int array[], int index)915 public static void modArrayIndex2(int array[], int index) { 916 for(int i = 0; i < 100; i++) { 917 // Both bounds checks cannot be statically eliminated, because index can be < 0. 918 // Currently dynamic BCE isn't applied for this case. 919 array[(index+i) % 10] = i; 920 array[(index+i) % array.length] = i; 921 } 922 } 923 924 static final int[] staticArray = new int[10]; 925 926 /// CHECK-START: void Main.modArrayIndex3() BCE (before) 927 /// CHECK-DAG: BoundsCheck 928 /// CHECK-DAG: ArraySet 929 /// CHECK-DAG: BoundsCheck 930 /// CHECK-DAG: ArraySet 931 932 /// CHECK-START: void Main.modArrayIndex3() BCE (after) 933 /// CHECK-NOT: Deoptimize 934 /// CHECK-DAG: BoundsCheck 935 /// CHECK-DAG: ArraySet 936 /// CHECK-NOT: BoundsCheck 937 /// CHECK-DAG: ArraySet modArrayIndex3()938 public static void modArrayIndex3() { 939 for(int i = 0; i < 100; i++) { 940 // Currently dynamic BCE isn't applied for this case. 941 staticArray[i % 10] = i; 942 // Can be eliminated by BCE. 943 staticArray[i % staticArray.length] = i; 944 } 945 } 946 947 /// CHECK-START: void Main.modArrayIndex4() BCE (before) 948 /// CHECK-DAG: BoundsCheck 949 /// CHECK-DAG: ArraySet 950 /// CHECK-DAG: BoundsCheck 951 /// CHECK-DAG: ArraySet 952 953 /// CHECK-START: void Main.modArrayIndex4() BCE (after) 954 /// CHECK-NOT: BoundsCheck 955 /// CHECK-DAG: ArraySet 956 /// CHECK-NOT: BoundsCheck 957 /// CHECK-DAG: ArraySet modArrayIndex4()958 public static void modArrayIndex4() { 959 int[] array = new int[20]; 960 for(int i = 0; i < 100; i++) { 961 // The local array length is statically know. Both can be eliminated by BCE. 962 array[i % 10] = i; 963 array[i % array.length] = i; 964 } 965 } 966 967 /// CHECK-START: void Main.modArrayIndex5(int[], int) BCE (before) 968 /// CHECK-DAG: BoundsCheck 969 /// CHECK-DAG: ArraySet 970 // 971 /// CHECK-START: void Main.modArrayIndex5(int[], int) BCE (after) 972 /// CHECK-NOT: BoundsCheck 973 /// CHECK-DAG: ArraySet modArrayIndex5(int[] x, int i)974 public static void modArrayIndex5(int[] x, int i) { 975 while (true) { 976 int xi = i % x.length; 977 if (xi < 0) 978 break; 979 if (i >= x.length) 980 break; 981 x[xi] = i; 982 i++; 983 } 984 } 985 986 /// CHECK-START: void Main.bubbleSort(int[]) GVN (before) 987 /// CHECK: BoundsCheck 988 /// CHECK: ArrayGet 989 /// CHECK: BoundsCheck 990 /// CHECK: ArrayGet 991 /// CHECK: BoundsCheck 992 /// CHECK: ArrayGet 993 /// CHECK: BoundsCheck 994 /// CHECK: ArrayGet 995 /// CHECK: BoundsCheck 996 /// CHECK: ArraySet 997 /// CHECK: BoundsCheck 998 /// CHECK: ArraySet 999 1000 /// CHECK-START: void Main.bubbleSort(int[]) GVN (after) 1001 /// CHECK: BoundsCheck 1002 /// CHECK: ArrayGet 1003 /// CHECK: BoundsCheck 1004 /// CHECK: ArrayGet 1005 /// CHECK-NOT: ArrayGet 1006 /// CHECK-NOT: ArrayGet 1007 /// CHECK-NOT: BoundsCheck 1008 /// CHECK: ArraySet 1009 /// CHECK-NOT: BoundsCheck 1010 /// CHECK: ArraySet 1011 1012 /// CHECK-START: void Main.bubbleSort(int[]) BCE (after) 1013 /// CHECK-NOT: BoundsCheck 1014 /// CHECK: ArrayGet 1015 /// CHECK-NOT: BoundsCheck 1016 /// CHECK: ArrayGet 1017 /// CHECK-NOT: ArrayGet 1018 /// CHECK-NOT: ArrayGet 1019 /// CHECK-NOT: BoundsCheck 1020 /// CHECK: ArraySet 1021 /// CHECK-NOT: BoundsCheck 1022 /// CHECK: ArraySet 1023 bubbleSort(int[] array)1024 static void bubbleSort(int[] array) { 1025 for (int i = 0; i < array.length - 1; i++) { 1026 for (int j = 0; j < array.length - i - 1; j++) { 1027 if (array[j] > array[j + 1]) { 1028 int temp = array[j + 1]; 1029 array[j + 1] = array[j]; 1030 array[j] = temp; 1031 } 1032 } 1033 } 1034 } 1035 1036 /// CHECK-START: void Main.nonzeroLength(int[]) BCE (before) 1037 /// CHECK-DAG: BoundsCheck 1038 // 1039 /// CHECK-START: void Main.nonzeroLength(int[]) BCE (after) 1040 /// CHECK-NOT: BoundsCheck 1041 /// CHECK-NOT: Deoptimize nonzeroLength(int[] a)1042 public static void nonzeroLength(int[] a) { 1043 if (a.length != 0) { 1044 a[0] = 112; 1045 } 1046 } 1047 1048 /// CHECK-START: void Main.knownLength(int[]) BCE (before) 1049 /// CHECK-DAG: BoundsCheck 1050 /// CHECK-DAG: BoundsCheck 1051 // 1052 /// CHECK-START: void Main.knownLength(int[]) BCE (after) 1053 /// CHECK-NOT: BoundsCheck 1054 /// CHECK-NOT: Deoptimize knownLength(int[] a)1055 public static void knownLength(int[] a) { 1056 if (a.length == 2) { 1057 a[0] = -1; 1058 a[1] = -2; 1059 } 1060 } 1061 1062 /// CHECK-START: void Main.lengthAlias1(int[], int) BCE (before) 1063 /// CHECK-DAG: <<Arr:l\d+>> ParameterValue loop:none 1064 /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none 1065 /// CHECK-DAG: <<Nul:l\d+>> NullCheck [<<Arr>>] loop:none 1066 /// CHECK-DAG: <<Len:i\d+>> ArrayLength [<<Nul>>] loop:none 1067 /// CHECK-DAG: NotEqual [<<Par>>,<<Len>>] loop:none 1068 /// CHECK-DAG: <<Idx:i\d+>> Phi loop:<<Loop:B\d+>> 1069 /// CHECK-DAG: BoundsCheck [<<Idx>>,<<Len>>] loop:<<Loop>> 1070 // 1071 /// CHECK-START: void Main.lengthAlias1(int[], int) BCE (after) 1072 /// CHECK-NOT: BoundsCheck 1073 /// CHECK-NOT: Deoptimize lengthAlias1(int[] a, int len)1074 public static void lengthAlias1(int[] a, int len) { 1075 if (len == a.length) { 1076 for (int i = 0; i < len; i++) { 1077 a[i] = 1; 1078 } 1079 } 1080 } 1081 1082 /// CHECK-START: void Main.lengthAlias2(int[], int) BCE (before) 1083 /// CHECK-DAG: <<Arr:l\d+>> ParameterValue loop:none 1084 /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none 1085 /// CHECK-DAG: <<Nul:l\d+>> NullCheck [<<Arr>>] loop:none 1086 /// CHECK-DAG: <<Len:i\d+>> ArrayLength [<<Nul>>] loop:none 1087 /// CHECK-DAG: Equal [<<Par>>,<<Len>>] loop:none 1088 /// CHECK-DAG: <<Idx:i\d+>> Phi loop:<<Loop:B\d+>> 1089 /// CHECK-DAG: BoundsCheck [<<Idx>>,<<Len>>] loop:<<Loop>> 1090 // 1091 /// CHECK-START: void Main.lengthAlias2(int[], int) BCE (after) 1092 /// CHECK-NOT: BoundsCheck 1093 /// CHECK-NOT: Deoptimize lengthAlias2(int[] a, int len)1094 public static void lengthAlias2(int[] a, int len) { 1095 if (len != a.length) { 1096 return; 1097 } 1098 for (int i = 0; i < len; i++) { 1099 a[i] = 2; 1100 } 1101 } 1102 1103 /// CHECK-START: void Main.lengthAlias3(int[], int) BCE (before) 1104 /// CHECK-DAG: <<Arr:l\d+>> ParameterValue loop:none 1105 /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none 1106 /// CHECK-DAG: <<Nul:l\d+>> NullCheck [<<Arr>>] loop:none 1107 /// CHECK-DAG: <<Len:i\d+>> ArrayLength [<<Nul>>] loop:none 1108 /// CHECK-DAG: NotEqual [<<Par>>,<<Len>>] loop:none 1109 /// CHECK-DAG: <<Idx:i\d+>> Phi loop:<<Loop:B\d+>> 1110 /// CHECK-DAG: BoundsCheck [<<Idx>>,<<Len>>] loop:<<Loop>> 1111 // 1112 /// CHECK-START: void Main.lengthAlias3(int[], int) BCE (after) 1113 /// CHECK-NOT: BoundsCheck 1114 /// CHECK-NOT: Deoptimize lengthAlias3(int[] a, int len)1115 public static void lengthAlias3(int[] a, int len) { 1116 if (a.length == len) { 1117 for (int i = 0; i < len; i++) { 1118 a[i] = 3; 1119 } 1120 } 1121 } 1122 1123 /// CHECK-START: void Main.lengthAlias4(int[]) BCE (before) 1124 /// CHECK-DAG: <<Arr:l\d+>> ParameterValue loop:none 1125 /// CHECK-DAG: <<Val:i\d+>> IntConstant 8 loop:none 1126 /// CHECK-DAG: <<Nul:l\d+>> NullCheck [<<Arr>>] loop:none 1127 /// CHECK-DAG: <<Len:i\d+>> ArrayLength [<<Nul>>] loop:none 1128 /// CHECK-DAG: Equal [<<Len>>,<<Val>>] loop:none 1129 /// CHECK-DAG: <<Idx:i\d+>> Phi loop:<<Loop:B\d+>> 1130 /// CHECK-DAG: BoundsCheck [<<Idx>>,<<Val>>] loop:<<Loop>> 1131 // 1132 /// CHECK-START: void Main.lengthAlias4(int[]) BCE (after) 1133 /// CHECK-NOT: BoundsCheck 1134 /// CHECK-NOT: Deoptimize lengthAlias4(int[] a)1135 public static void lengthAlias4(int[] a) { 1136 if (8 != a.length) { 1137 return; 1138 } 1139 for (int i = 0; i < 8; i++) { 1140 a[i] = 4; 1141 } 1142 } 1143 1144 static int[][] mA; 1145 1146 /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (before) 1147 // Array references mA[i] and ..[j] both in inner loop. 1148 /// CHECK-DAG: <<Get1:l\d+>> ArrayGet [<<Array1:l\d+>>,<<Bounds1:i\d+>>] loop:<<InnerLoop:B\d+>> 1149 /// CHECK-DAG: <<Array1>> NullCheck [<<Field1:l\d+>>] loop:<<InnerLoop>> 1150 /// CHECK-DAG: <<Len1:i\d+>> ArrayLength [<<Array1>>] loop:<<InnerLoop>> 1151 /// CHECK-DAG: <<Bounds1>> BoundsCheck [<<Index1:i\d+>>,<<Len1>>] loop:<<InnerLoop>> 1152 /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [<<Array2:l\d+>>,<<Bounds2:i\d+>>] loop:<<InnerLoop>> 1153 /// CHECK-DAG: <<Array2>> NullCheck [<<Get1>>] loop:<<InnerLoop>> 1154 /// CHECK-DAG: <<Len2:i\d+>> ArrayLength [<<Array2>>] loop:<<InnerLoop>> 1155 /// CHECK-DAG: <<Bounds2>> BoundsCheck [<<Index2:i\d+>>,<<Len2>>] loop:<<InnerLoop>> 1156 /// CHECK-DAG: Abs [<<Get2>>] loop:<<InnerLoop>> 1157 /// CHECK-DAG: <<Index2>> Phi loop:<<InnerLoop>> 1158 /// CHECK-DAG: <<Index1>> Phi loop:<<OuterLoop:B\d+>> 1159 /// CHECK-DAG: <<Field1>> StaticFieldGet loop:none 1160 /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>" 1161 // 1162 /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (after) 1163 // Array reference mA[i] hoisted to same level as deopt. 1164 /// CHECK-DAG: Deoptimize loop:<<OuterLoop:B\d+>> 1165 /// CHECK-DAG: ArrayLength loop:<<OuterLoop>> 1166 /// CHECK-DAG: <<Get1:l\d+>> ArrayGet [<<Array1:l\d+>>,<<Index1:i\d+>>] loop:<<OuterLoop>> 1167 // Array reference ..[j] still in inner loop, with a direct index. 1168 /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [<<Array2:l\d+>>,<<Index2:i\d+>>] loop:<<InnerLoop:B\d+>> 1169 /// CHECK-DAG: Abs [<<Get2>>] loop:<<InnerLoop>> 1170 /// CHECK-DAG: <<Index2>> Phi loop:<<InnerLoop>> 1171 /// CHECK-DAG: <<Index1>> Phi loop:<<OuterLoop>> 1172 // Synthetic phi. 1173 /// CHECK-DAG: <<Array2>> Phi loop:<<OuterLoop>> 1174 /// CHECK-DAG: <<Array1>> StaticFieldGet loop:none 1175 /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>" 1176 // 1177 /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (after) 1178 /// CHECK-NOT: NullCheck 1179 /// CHECK-NOT: BoundsCheck dynamicBCEAndIntrinsic(int n)1180 static void dynamicBCEAndIntrinsic(int n) { 1181 for (int i = 0; i < n; i++) { 1182 for (int j = 0; j < n; j++) { 1183 // Since intrinsic call cannot modify fields or arrays, 1184 // dynamic BCE and hoisting can be applied to the inner loop. 1185 mA[i][j] = Math.abs(mA[i][j]); 1186 } 1187 } 1188 } 1189 foo()1190 static int foo() { 1191 try { 1192 assertIsManaged(); 1193 // This will cause AIOOBE. 1194 $opt$noinline$constantIndexing2(new int[3]); 1195 } catch (ArrayIndexOutOfBoundsException e) { 1196 assertIsManaged(); // This is to ensure that single-frame deoptimization works. 1197 // Will need to be updated if $opt$noinline$constantIndexing2 is inlined. 1198 try { 1199 // This will cause AIOOBE. 1200 constantIndexingForward6(new int[3]); 1201 } catch (ArrayIndexOutOfBoundsException e2) { 1202 // Having deopted, we expect to be running interpreted at this point. 1203 // Does not apply to debuggable, however, since we do not inline. 1204 return 99; 1205 } 1206 } 1207 return 0; 1208 } 1209 1210 1211 int sum; 1212 1213 /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (before) 1214 /// CHECK: BoundsCheck 1215 /// CHECK: ArraySet 1216 /// CHECK-NOT: BoundsCheck 1217 /// CHECK: ArrayGet 1218 1219 /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (after) 1220 /// CHECK: Phi 1221 /// CHECK-NOT: BoundsCheck 1222 /// CHECK: ArraySet 1223 /// CHECK-NOT: BoundsCheck 1224 /// CHECK: ArrayGet 1225 // Added blocks at end for deoptimization. 1226 /// CHECK: Exit 1227 /// CHECK: If 1228 /// CHECK: Deoptimize 1229 /// CHECK: Deoptimize 1230 /// CHECK: Deoptimize 1231 /// CHECK-NOT: Deoptimize 1232 /// CHECK: Goto 1233 /// CHECK: Goto 1234 /// CHECK: Goto 1235 foo1(int[] array, int start, int end, boolean expectInterpreter)1236 void foo1(int[] array, int start, int end, boolean expectInterpreter) { 1237 if (end < 0) 1238 throw new Error(""); 1239 // Three HDeoptimize will be added. Two for the index 1240 // and one for null check on array (to hoist null 1241 // check and array.length out of loop). 1242 for (int i = start ; i < end; i++) { 1243 if (expectInterpreter) { 1244 assertIsInterpreted(); 1245 } else { 1246 assertIsManaged(); 1247 } 1248 array[i] = 1; 1249 sum += array[i]; 1250 } 1251 } 1252 1253 1254 /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (before) 1255 /// CHECK: BoundsCheck 1256 /// CHECK: ArraySet 1257 /// CHECK-NOT: BoundsCheck 1258 /// CHECK: ArrayGet 1259 /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (after) 1260 /// CHECK: Phi 1261 /// CHECK-NOT: BoundsCheck 1262 /// CHECK: ArraySet 1263 /// CHECK-NOT: BoundsCheck 1264 /// CHECK: ArrayGet 1265 // Added blocks at end for deoptimization. 1266 /// CHECK: Exit 1267 /// CHECK: If 1268 /// CHECK: Deoptimize 1269 /// CHECK: Deoptimize 1270 /// CHECK: Deoptimize 1271 /// CHECK-NOT: Deoptimize 1272 /// CHECK: Goto 1273 /// CHECK: Goto 1274 /// CHECK: Goto 1275 foo2(int[] array, int start, int end, boolean expectInterpreter)1276 void foo2(int[] array, int start, int end, boolean expectInterpreter) { 1277 if (end < 0) 1278 throw new Error(""); 1279 // Three HDeoptimize will be added. Two for the index 1280 // and one for null check on array (to hoist null 1281 // check and array.length out of loop). 1282 for (int i = start ; i <= end; i++) { 1283 if (expectInterpreter) { 1284 assertIsInterpreted(); 1285 } else { 1286 assertIsManaged(); 1287 } 1288 array[i] = 1; 1289 sum += array[i]; 1290 } 1291 } 1292 1293 1294 /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (before) 1295 /// CHECK: BoundsCheck 1296 /// CHECK: ArraySet 1297 /// CHECK-NOT: BoundsCheck 1298 /// CHECK: ArrayGet 1299 /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (after) 1300 /// CHECK: Phi 1301 /// CHECK-NOT: BoundsCheck 1302 /// CHECK: ArraySet 1303 /// CHECK-NOT: BoundsCheck 1304 /// CHECK: ArrayGet 1305 // Added blocks at end for deoptimization. 1306 /// CHECK: Exit 1307 /// CHECK: If 1308 /// CHECK: Deoptimize 1309 /// CHECK: Deoptimize 1310 /// CHECK: Deoptimize 1311 /// CHECK-NOT: Deoptimize 1312 /// CHECK: Goto 1313 /// CHECK: Goto 1314 /// CHECK: Goto 1315 foo3(int[] array, int end, boolean expectInterpreter)1316 void foo3(int[] array, int end, boolean expectInterpreter) { 1317 if (end < 0) 1318 throw new Error(""); 1319 // Three HDeoptimize will be added. Two for the index 1320 // and one for null check on array (to hoist null check 1321 // and array.length out of loop). 1322 for (int i = 3 ; i <= end; i++) { 1323 if (expectInterpreter) { 1324 assertIsInterpreted(); 1325 } else { 1326 assertIsManaged(); 1327 } 1328 array[i] = 1; 1329 sum += array[i]; 1330 } 1331 } 1332 1333 1334 /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (before) 1335 /// CHECK: BoundsCheck 1336 /// CHECK: ArraySet 1337 /// CHECK-NOT: BoundsCheck 1338 /// CHECK: ArrayGet 1339 1340 /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (after) 1341 /// CHECK: Phi 1342 /// CHECK-NOT: BoundsCheck 1343 /// CHECK: ArraySet 1344 /// CHECK-NOT: BoundsCheck 1345 /// CHECK: ArrayGet 1346 // Added blocks at end for deoptimization. 1347 /// CHECK: Exit 1348 /// CHECK: If 1349 /// CHECK: Deoptimize 1350 /// CHECK: Deoptimize 1351 /// CHECK: Deoptimize 1352 /// CHECK-NOT: Deoptimize 1353 /// CHECK: Goto 1354 /// CHECK: Goto 1355 /// CHECK: Goto 1356 foo4(int[] array, int end, boolean expectInterpreter)1357 void foo4(int[] array, int end, boolean expectInterpreter) { 1358 if (end < 0) 1359 throw new Error(""); 1360 // Three HDeoptimize will be added. Two for the index 1361 // and one for null check on array (to hoist null check 1362 // and array.length out of loop). 1363 for (int i = end ; i > 0; i--) { 1364 if (expectInterpreter) { 1365 assertIsInterpreted(); 1366 } else { 1367 assertIsManaged(); 1368 } 1369 array[i - 1] = 1; 1370 sum += array[i - 1]; 1371 } 1372 } 1373 1374 1375 /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (before) 1376 /// CHECK: BoundsCheck 1377 /// CHECK: ArraySet 1378 /// CHECK: BoundsCheck 1379 /// CHECK: ArrayGet 1380 /// CHECK: BoundsCheck 1381 /// CHECK: ArrayGet 1382 /// CHECK: BoundsCheck 1383 /// CHECK: ArrayGet 1384 1385 /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (after) 1386 /// CHECK-NOT: BoundsCheck 1387 /// CHECK: ArraySet 1388 /// CHECK: Phi 1389 /// CHECK-NOT: BoundsCheck 1390 /// CHECK: ArrayGet 1391 /// CHECK-NOT: BoundsCheck 1392 /// CHECK: ArrayGet 1393 /// CHECK-NOT: BoundsCheck 1394 /// CHECK: ArrayGet 1395 // Added blocks at end for deoptimization. 1396 /// CHECK: Exit 1397 /// CHECK: If 1398 /// CHECK: Deoptimize 1399 /// CHECK: Deoptimize 1400 /// CHECK: Deoptimize 1401 /// CHECK-NOT: Deoptimize 1402 /// CHECK: Goto 1403 /// CHECK: Goto 1404 /// CHECK: Goto 1405 foo5(int[] array, int end, boolean expectInterpreter)1406 void foo5(int[] array, int end, boolean expectInterpreter) { 1407 if (end < 0) 1408 throw new Error(""); 1409 // Bounds check in this loop can be eliminated without deoptimization. 1410 for (int i = array.length - 1 ; i >= 0; i--) { 1411 array[i] = 1; 1412 } 1413 // Three HDeoptimize will be added for the bounds. 1414 // The null check is not necessary. 1415 for (int i = end - 2 ; i > 0; i--) { 1416 if (expectInterpreter) { 1417 assertIsInterpreted(); 1418 } else { 1419 assertIsManaged(); 1420 } 1421 sum += array[i - 1]; 1422 sum += array[i]; 1423 sum += array[i + 1]; 1424 } 1425 } 1426 1427 1428 /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (before) 1429 /// CHECK: BoundsCheck 1430 /// CHECK: ArrayGet 1431 /// CHECK: BoundsCheck 1432 /// CHECK: ArrayGet 1433 /// CHECK: BoundsCheck 1434 /// CHECK: ArrayGet 1435 /// CHECK: BoundsCheck 1436 /// CHECK: ArrayGet 1437 /// CHECK: BoundsCheck 1438 /// CHECK: ArrayGet 1439 /// CHECK-NOT: BoundsCheck 1440 /// CHECK: ArraySet 1441 /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (after) 1442 /// CHECK: Phi 1443 /// CHECK-NOT: BoundsCheck 1444 /// CHECK: ArrayGet 1445 /// CHECK-NOT: BoundsCheck 1446 /// CHECK: ArrayGet 1447 /// CHECK-NOT: BoundsCheck 1448 /// CHECK: ArrayGet 1449 /// CHECK-NOT: BoundsCheck 1450 /// CHECK: ArrayGet 1451 /// CHECK-NOT: BoundsCheck 1452 /// CHECK: ArrayGet 1453 /// CHECK-NOT: BoundsCheck 1454 /// CHECK: ArraySet 1455 // Added blocks at end for deoptimization. 1456 /// CHECK: Exit 1457 /// CHECK: If 1458 /// CHECK: Deoptimize 1459 /// CHECK: Deoptimize 1460 /// CHECK: Deoptimize 1461 /// CHECK: Deoptimize 1462 /// CHECK-NOT: Deoptimize 1463 /// CHECK: Goto 1464 /// CHECK: Goto 1465 /// CHECK: Goto 1466 foo6(int[] array, int start, int end, boolean expectInterpreter)1467 void foo6(int[] array, int start, int end, boolean expectInterpreter) { 1468 if (end < 0) 1469 throw new Error(""); 1470 for (int i = end; i >= start; i--) { 1471 if (expectInterpreter) { 1472 assertIsInterpreted(); 1473 } else { 1474 assertIsManaged(); 1475 } 1476 array[i] = (array[i-2] + array[i-1] + array[i] + array[i+1] + array[i+2]) / 5; 1477 } 1478 } 1479 1480 1481 /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (before) 1482 /// CHECK: BoundsCheck 1483 /// CHECK: ArrayGet 1484 /// CHECK: BoundsCheck 1485 /// CHECK: ArrayGet 1486 1487 /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (after) 1488 /// CHECK: Phi 1489 /// CHECK: BoundsCheck 1490 /// CHECK: ArrayGet 1491 /// CHECK-NOT: BoundsCheck 1492 /// CHECK: ArrayGet 1493 // Added blocks at end for deoptimization. 1494 /// CHECK: Exit 1495 /// CHECK: If 1496 /// CHECK: Deoptimize 1497 /// CHECK: Deoptimize 1498 /// CHECK: Deoptimize 1499 /// CHECK-NOT: Deoptimize 1500 /// CHECK: Goto 1501 /// CHECK: Goto 1502 /// CHECK: Goto 1503 foo7(int[] array, int start, int end, boolean lowEnd)1504 void foo7(int[] array, int start, int end, boolean lowEnd) { 1505 // Three HDeoptimize will be added. One for the index 1506 // and one for null check on array (to hoist null 1507 // check and array.length out of loop). 1508 for (int i = start ; i < end; i++) { 1509 if (lowEnd) { 1510 // This array access isn't certain. So we don't 1511 // use +1000 offset in decision making for deoptimization 1512 // conditions. 1513 sum += array[i + 1000]; 1514 } 1515 sum += array[i]; 1516 } 1517 } 1518 1519 1520 /// CHECK-START: void Main.foo8(int[][], int, int) BCE (before) 1521 /// CHECK: BoundsCheck 1522 /// CHECK: ArrayGet 1523 /// CHECK: BoundsCheck 1524 /// CHECK: ArraySet 1525 1526 /// CHECK-START: void Main.foo8(int[][], int, int) BCE (after) 1527 /// CHECK: Phi 1528 /// CHECK-NOT: BoundsCheck 1529 /// CHECK: ArrayGet 1530 /// CHECK: Phi 1531 /// CHECK-NOT: BoundsCheck 1532 /// CHECK: ArraySet 1533 // Added blocks at end for deoptimization. 1534 /// CHECK: Exit 1535 /// CHECK: If 1536 /// CHECK: Deoptimize 1537 /// CHECK: Deoptimize 1538 /// CHECK: Deoptimize 1539 /// CHECK: Goto 1540 /// CHECK: Goto 1541 /// CHECK: Goto 1542 /// CHECK: If 1543 /// CHECK: Deoptimize 1544 /// CHECK: Deoptimize 1545 /// CHECK: Deoptimize 1546 /// CHECK-NOT: Deoptimize 1547 /// CHECK: Goto 1548 /// CHECK: Goto 1549 /// CHECK: Goto 1550 foo8(int[][] matrix, int start, int end)1551 void foo8(int[][] matrix, int start, int end) { 1552 // Three HDeoptimize will be added for the outer loop, 1553 // two for the index, and null check on matrix. Same 1554 // for the inner loop. 1555 for (int i = start; i < end; i++) { 1556 int[] row = matrix[i]; 1557 for (int j = start; j < end; j++) { 1558 row[j] = 1; 1559 } 1560 } 1561 } 1562 1563 1564 /// CHECK-START: void Main.foo9(int[], boolean) BCE (before) 1565 /// CHECK: NullCheck 1566 /// CHECK: BoundsCheck 1567 /// CHECK: ArrayGet 1568 1569 /// CHECK-START: void Main.foo9(int[], boolean) BCE (after) 1570 // The loop is guaranteed to be entered. No need to transform the 1571 // loop for loop body entry test. 1572 /// CHECK: Deoptimize 1573 /// CHECK: Deoptimize 1574 /// CHECK: Deoptimize 1575 /// CHECK-NOT: Deoptimize 1576 /// CHECK: Phi 1577 /// CHECK-NOT: NullCheck 1578 /// CHECK-NOT: BoundsCheck 1579 /// CHECK: ArrayGet 1580 1581 /// CHECK-START: void Main.foo9(int[], boolean) instruction_simplifier$before_codegen (after) 1582 // Simplification removes the redundant check 1583 /// CHECK: Deoptimize 1584 /// CHECK: Deoptimize 1585 /// CHECK-NOT: Deoptimize 1586 foo9(int[] array, boolean expectInterpreter)1587 void foo9(int[] array, boolean expectInterpreter) { 1588 // Three HDeoptimize will be added. Two for the index and one for null check on array. Then 1589 // simplification removes one redundant HDeoptimize. 1590 for (int i = 0 ; i < 10; i++) { 1591 if (expectInterpreter) { 1592 assertIsInterpreted(); 1593 } else { 1594 assertIsManaged(); 1595 } 1596 sum += array[i]; 1597 } 1598 } 1599 1600 1601 /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (before) 1602 /// CHECK: BoundsCheck 1603 /// CHECK: ArraySet 1604 1605 /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (after) 1606 /// CHECK-NOT: Deoptimize 1607 /// CHECK: BoundsCheck 1608 /// CHECK: ArraySet 1609 partialLooping(int[] array, int start, int end)1610 void partialLooping(int[] array, int start, int end) { 1611 // This loop doesn't cover the full range of [start, end) so 1612 // adding deoptimization is too aggressive, since end can be 1613 // greater than array.length but the loop is never going to work on 1614 // more than 2 elements. 1615 for (int i = start; i < end; i++) { 1616 if (i == 2) { 1617 return; 1618 } 1619 array[i] = 1; 1620 } 1621 } 1622 1623 testUnknownBounds()1624 static void testUnknownBounds() { 1625 boolean caught = false; 1626 1627 runAllConstantIndices(); 1628 1629 Main main = new Main(); 1630 main.foo1(new int[10], 0, 10, false); 1631 if (main.sum != 10) { 1632 System.out.println("foo1 failed!"); 1633 } 1634 1635 caught = false; 1636 main = new Main(); 1637 try { 1638 main.foo1(new int[10], 0, 11, true); 1639 } catch (ArrayIndexOutOfBoundsException e) { 1640 caught = true; 1641 } 1642 if (!caught || main.sum != 10) { 1643 System.out.println("foo1 exception failed!"); 1644 } 1645 1646 main = new Main(); 1647 main.foo2(new int[10], 0, 9, false); 1648 if (main.sum != 10) { 1649 System.out.println("foo2 failed!"); 1650 } 1651 1652 caught = false; 1653 main = new Main(); 1654 try { 1655 main.foo2(new int[10], 0, 10, true); 1656 } catch (ArrayIndexOutOfBoundsException e) { 1657 caught = true; 1658 } 1659 if (!caught || main.sum != 10) { 1660 System.out.println("foo2 exception failed!"); 1661 } 1662 1663 main = new Main(); 1664 main.foo3(new int[10], 9, false); 1665 if (main.sum != 7) { 1666 System.out.println("foo3 failed!"); 1667 } 1668 1669 caught = false; 1670 main = new Main(); 1671 try { 1672 main.foo3(new int[10], 10, true); 1673 } catch (ArrayIndexOutOfBoundsException e) { 1674 caught = true; 1675 } 1676 if (!caught || main.sum != 7) { 1677 System.out.println("foo3 exception failed!"); 1678 } 1679 1680 main = new Main(); 1681 main.foo4(new int[10], 10, false); 1682 if (main.sum != 10) { 1683 System.out.println("foo4 failed!"); 1684 } 1685 1686 caught = false; 1687 main = new Main(); 1688 try { 1689 main.foo4(new int[10], 11, true); 1690 } catch (ArrayIndexOutOfBoundsException e) { 1691 caught = true; 1692 } 1693 if (!caught || main.sum != 0) { 1694 System.out.println("foo4 exception failed!"); 1695 } 1696 1697 main = new Main(); 1698 main.foo5(new int[10], 10, false); 1699 if (main.sum != 24) { 1700 System.out.println("foo5 failed!"); 1701 } 1702 1703 caught = false; 1704 main = new Main(); 1705 try { 1706 main.foo5(new int[10], 11, true); 1707 } catch (ArrayIndexOutOfBoundsException e) { 1708 caught = true; 1709 } 1710 if (!caught || main.sum != 2) { 1711 System.out.println("foo5 exception failed!"); 1712 } 1713 1714 main = new Main(); 1715 main.foo6(new int[10], 2, 7, false); 1716 1717 main = new Main(); 1718 int[] array9 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 1719 main.foo9(array9, false); 1720 if (main.sum != 45) { 1721 System.out.println("foo9 failed!"); 1722 } 1723 1724 main = new Main(); 1725 int[] array = new int[4]; 1726 main.partialLooping(new int[3], 0, 4); 1727 if ((array[0] != 1) && (array[1] != 1) && 1728 (array[2] != 0) && (array[3] != 0)) { 1729 System.out.println("partialLooping failed!"); 1730 } 1731 1732 caught = false; 1733 main = new Main(); 1734 try { 1735 main.foo6(new int[10], 2, 8, true); 1736 } catch (ArrayIndexOutOfBoundsException e) { 1737 caught = true; 1738 } 1739 if (!caught) { 1740 System.out.println("foo6 exception failed!"); 1741 } 1742 1743 caught = false; 1744 main = new Main(); 1745 try { 1746 main.foo6(new int[10], 1, 7, true); 1747 } catch (ArrayIndexOutOfBoundsException e) { 1748 caught = true; 1749 } 1750 if (!caught) { 1751 System.out.println("foo6 exception failed!"); 1752 } 1753 1754 } 1755 testExceptionMessage()1756 public void testExceptionMessage() { 1757 short[] B1 = new short[5]; 1758 int[] B2 = new int[5]; 1759 Exception err = null; 1760 try { 1761 testExceptionMessage1(B1, B2, null, -1, 6); 1762 } catch (Exception e) { 1763 err = e; 1764 } 1765 System.out.println(err); 1766 } 1767 testExceptionMessage1(short[] a1, int[] a2, long a3[], int start, int finish)1768 void testExceptionMessage1(short[] a1, int[] a2, long a3[], int start, int finish) { 1769 int j = finish + 77; 1770 // Bug: 22665511 1771 // A deoptimization will be triggered here right before the loop. Need to make 1772 // sure the value of j is preserved for the interpreter. 1773 for (int i = start; i <= finish; i++) { 1774 a2[j - 1] = a1[i + 1]; 1775 } 1776 } 1777 1778 // Tests `setZeroToRange` with a range of values. Checks for exceptions as well as the correctness 1779 // of setting the right values to zero. $noinline$testSetZeroToRange()1780 static void $noinline$testSetZeroToRange() { 1781 for (int start = -2; start < 7; ++start) { 1782 for (int len = -2; len < 7; ++len) { 1783 int[] array = {1, 2, 3, 4, 5}; 1784 final int lower = start; 1785 final int upper = start + len - 1; 1786 // We expect an exception if: 1787 // * The first value is out of range, or 1788 // * The last value is more than the length of the array. 1789 // Note that if `upper < 0` it means that we will only do one iteration of the do while in 1790 // `setZeroToRange` so we have the exception covered with the `lower` checks. 1791 final boolean expected_exception = 1792 (lower < 0) || (lower >= array.length) || (upper >= array.length); 1793 try { 1794 $noinline$setZeroToRange(array, start, len); 1795 if (expected_exception) { 1796 System.out.println("Missing ArrayIndexOutOfBoundsException for start " + start 1797 + " and len " + len); 1798 } 1799 $noinline$checkZerosForSetZeroToRange(array, start, len); 1800 } catch (ArrayIndexOutOfBoundsException e) { 1801 if (!expected_exception) { 1802 System.out.println("Unexpected ArrayIndexOutOfBoundsException for start " + start 1803 + " and len " + len); 1804 } 1805 } 1806 } 1807 } 1808 } 1809 1810 // TODO(solanes): Improve the code to replace the following BoundsCheck with HDeoptimize 1811 // instructions. See b/304967775 and aosp/2804075. 1812 1813 /// CHECK-START: void Main.$noinline$setZeroToRange(int[], int, int) BCE (before) 1814 /// CHECK: BoundsCheck 1815 1816 /// CHECK-START: void Main.$noinline$setZeroToRange(int[], int, int) BCE (after) 1817 /// CHECK: BoundsCheck 1818 1819 // Sets to `0` the values of `arr` in the range `[start, len)`. $noinline$setZeroToRange(int[] arr, int start, int len)1820 static void $noinline$setZeroToRange(int[] arr, int start, int len) { 1821 int charPos = start; 1822 do { 1823 arr[charPos++] = 0; 1824 } while (charPos < start + len); 1825 } 1826 $noinline$checkZerosForSetZeroToRange(int[] arr, int start, int len)1827 static void $noinline$checkZerosForSetZeroToRange(int[] arr, int start, int len) { 1828 // Non-zeroes before zeroes. 1829 int i = 0; 1830 for (; i < Math.min(start, arr.length); ++i) { 1831 if (arr[i] == 0) { 1832 System.out.println("Expected non-zero for arr " + Arrays.toString(arr) + " before zeroes i " 1833 + i + " start " + start + " and len " + len); 1834 } 1835 } 1836 1837 int bound = start + len; 1838 if (bound < 1 || len < 1) { 1839 // We always set one zero since it is a do-while. 1840 bound = i + 1; 1841 } 1842 1843 for (; i < Math.min(bound, arr.length); ++i) { 1844 if (arr[i] != 0) { 1845 System.out.println("Expected zero for arr " + Arrays.toString(arr) + " i " + i + " start " 1846 + start + " and len " + len); 1847 } 1848 } 1849 1850 // Then zeroes until the end. 1851 for (; i < arr.length; ++i) { 1852 if (arr[i] == 0) { 1853 System.out.println("Expected non-zero after zeroes for arr " + Arrays.toString(arr) + " i " 1854 + i + " start " + start + " and len " + len); 1855 } 1856 } 1857 } 1858 1859 // Make sure this method is compiled with optimizing. 1860 /// CHECK-START: void Main.main(java.lang.String[]) register (after) 1861 /// CHECK: ParallelMove 1862 main(String[] args)1863 public static void main(String[] args) { 1864 System.loadLibrary(args[0]); 1865 1866 if (!compiledWithOptimizing() || 1867 !hasOatFile() || 1868 runtimeIsSoftFail() || 1869 isInterpreted()) { 1870 disableStackFrameAsserts(); 1871 } 1872 1873 sieve(20); 1874 1875 int[] x1 = new int[10]; 1876 int[] x2 = new int[10]; 1877 int[] x3 = new int[10]; 1878 modArrayIndex5(x1, -1); 1879 modArrayIndex5(x2, 0); 1880 modArrayIndex5(x3, 5); 1881 for (int i = 0; i < 10; i++) { 1882 int e1 = 0; 1883 int e2 = i; 1884 int e3 = i < 5 ? 0 : i; 1885 if (x1[i] != e1 || x2[i] != e2 || x3[i] != e3) { 1886 System.out.println("modarray failed!"); 1887 } 1888 } 1889 1890 int[] array = {5, 2, 3, 7, 0, 1, 6, 4}; 1891 bubbleSort(array); 1892 for (int i = 0; i < 8; i++) { 1893 if (array[i] != i) { 1894 System.out.println("bubble sort failed!"); 1895 } 1896 } 1897 1898 nonzeroLength(array); 1899 if (array[0] != 112) { 1900 System.out.println("nonzero length failed!"); 1901 } 1902 1903 knownLength(array); 1904 if (array[0] != 112 || array[1] != 1) { 1905 System.out.println("nonzero length failed!"); 1906 } 1907 array = new int[2]; 1908 knownLength(array); 1909 if (array[0] != -1 || array[1] != -2) { 1910 System.out.println("nonzero length failed!"); 1911 } 1912 1913 array = new int[8]; 1914 lengthAlias1(array, 8); 1915 for (int i = 0; i < 8; i++) { 1916 if (array[i] != 1) { 1917 System.out.println("alias1 failed!"); 1918 } 1919 } 1920 lengthAlias2(array, 8); 1921 for (int i = 0; i < 8; i++) { 1922 if (array[i] != 2) { 1923 System.out.println("alias2 failed!"); 1924 } 1925 } 1926 lengthAlias3(array, 8); 1927 for (int i = 0; i < 8; i++) { 1928 if (array[i] != 3) { 1929 System.out.println("alias3 failed!"); 1930 } 1931 } 1932 lengthAlias4(array); 1933 for (int i = 0; i < 8; i++) { 1934 if (array[i] != 4) { 1935 System.out.println("alias4 failed!"); 1936 } 1937 } 1938 1939 array = new int[10]; 1940 lengthAlias1(array, /*mismatched value*/ 8); 1941 lengthAlias2(array, /*mismatched value*/ 8); 1942 lengthAlias3(array, /*mismatched value*/ 8); 1943 lengthAlias4(array); // implicit mismatch 1944 for (int i = 0; i < 10; i++) { 1945 if (array[i] != 0) { 1946 System.out.println("mismatch failed!"); 1947 } 1948 } 1949 1950 // Zero length array does not break. 1951 array = new int[0]; 1952 nonzeroLength(array); 1953 knownLength(array); 1954 lengthAlias1(array, 0); 1955 lengthAlias2(array, 0); 1956 lengthAlias3(array, 0); 1957 1958 mA = new int[4][4]; 1959 for (int i = 0; i < 4; i++) { 1960 for (int j = 0; j < 4; j++) { 1961 mA[i][j] = -1; 1962 } 1963 } 1964 dynamicBCEAndIntrinsic(4); 1965 for (int i = 0; i < 4; i++) { 1966 for (int j = 0; j < 4; j++) { 1967 if (mA[i][i] != 1) { 1968 System.out.println("dynamic bce failed!"); 1969 } 1970 } 1971 } 1972 1973 array = new int[7]; 1974 pyramid1(array); 1975 if (!isPyramid(array)) { 1976 System.out.println("pyramid1 failed!"); 1977 } 1978 1979 array = new int[8]; 1980 pyramid2(array); 1981 if (!isPyramid(array)) { 1982 System.out.println("pyramid2 failed!"); 1983 } 1984 1985 java.util.Arrays.fill(array, -1); 1986 pyramid3(array); 1987 if (!isPyramid(array)) { 1988 System.out.println("pyramid3 failed!"); 1989 } 1990 1991 // Make sure this value is kept after deoptimization. 1992 int i = 1; 1993 if (foo() + i != 100) { 1994 System.out.println("foo failed!"); 1995 } 1996 1997 testUnknownBounds(); 1998 new Main().testExceptionMessage(); 1999 2000 $noinline$testSetZeroToRange(); 2001 } 2002 2003 public static native boolean compiledWithOptimizing(); 2004 public static native void disableStackFrameAsserts(); 2005 public static native void assertIsManaged(); 2006 public static native void assertIsInterpreted(); 2007 public static native boolean hasOatFile(); 2008 public static native boolean runtimeIsSoftFail(); 2009 public static native boolean isInterpreted(); 2010 } 2011