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