• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 {
main(String[] args)18   public static void main(String[] args) throws Exception {
19     System.loadLibrary(args[0]);
20 
21     $noinline$intUpdate(new Main());
22     ensureJitCompiled(Main.class, "$noinline$intUpdate");
23     $noinline$intUpdate(new SubMain());
24     if (myIntStatic != 5000) {
25       throw new Error("Expected 5000, got " + myIntStatic);
26     }
27 
28     $noinline$objectUpdate(new Main());
29     ensureJitCompiled(Main.class, "$noinline$objectUpdate");
30     $noinline$objectUpdate(new SubMain());
31 
32     $noinline$loopIncrement(new Main());
33     ensureJitCompiled(Main.class, "$noinline$loopIncrement");
34     $noinline$loopIncrement(new SubMain());
35   }
36 
doCheck()37   public boolean doCheck() {
38     return false;
39   }
40 
$noinline$intUpdate(Main m)41   public static void $noinline$intUpdate(Main m) {
42     int a = 0;
43     // We used to kill 'a' when the inline cache of 'doCheck' only
44     // contains 'Main' (which makes the only branch using 'a' dead).
45     // So the deoptimization at the inline cache was incorrectly assuming
46     // 'a' was dead.
47     for (int i = 0; i < 5000; i++) {
48       if (m.doCheck()) {
49         a++;
50         // We make this branch the only true user of the 'a' phi. All other uses
51         // of 'a' are phi updates.
52         myIntStatic = a;
53       } else if (myIntStatic == 42) {
54         a = 1;
55       }
56     }
57   }
58 
$noinline$objectUpdate(Main m)59   public static void $noinline$objectUpdate(Main m) {
60     Object o = new Object();
61     // We used to kill 'o' when the inline cache of 'doCheck' only
62     // contains 'Main' (which makes the only branch using 'a' dead).
63     // So the deoptimization at the inline cache was incorrectly assuming
64     // 'o' was dead.
65     // This lead to a NPE on the 'toString' call just after deoptimizing.
66     for (int i = 0; i < 5000; i++) {
67       if (m.doCheck()) {
68         // We make this branch the only true user of the 'o' phi. All other uses
69         // of 'o' are phi updates.
70         o.toString();
71       } else if (myIntStatic == 42) {
72         o = m;
73       }
74     }
75   }
76 
$noinline$loopIncrement(Main m)77   public static void $noinline$loopIncrement(Main m) {
78     int k = 0;
79     // We used to kill 'k' and replace it with 5000 when the inline cache
80     // of 'doCheck' only contains 'Main'.
81     // So the deoptimization at the inline cache was incorrectly assuming
82     // 'k' was 5000.
83     for (int i = 0; i < 5000; i++, k++) {
84       if (m.doCheck()) {
85         // We make this branch the only true user of the 'a' phi. All other uses
86         // of 'a' are phi updates.
87         myIntStatic = k;
88       }
89     }
90     if (k != 5000) {
91       throw new Error("Expected 5000, got " + k);
92     }
93   }
94 
95   public static int myIntStatic = 0;
96 
ensureJitCompiled(Class<?> itf, String name)97   public static native void ensureJitCompiled(Class<?> itf, String name);
98 }
99 
100 class SubMain extends Main {
doCheck()101   public boolean doCheck() {
102     return true;
103   }
104 }
105