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