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 // Add a class that will be the first entry in the dex cache, to
18 // avoid having the OtherDex and Main classes share the same cache index.
19 class AAA {
20 }
21 
22 public class Main {
23 
24   /// CHECK-START: void Main.inlineEmptyMethod() inliner (before)
25   /// CHECK-DAG:     <<Invoke:v\d+>>  InvokeStaticOrDirect
26   /// CHECK-DAG:                      ReturnVoid
27 
28   /// CHECK-START: void Main.inlineEmptyMethod() inliner (after)
29   /// CHECK-NOT:                      InvokeStaticOrDirect
30 
inlineEmptyMethod()31   public static void inlineEmptyMethod() {
32     OtherDex.emptyMethod();
33   }
34 
35   /// CHECK-START: int Main.inlineReturnIntMethod() inliner (before)
36   /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
37   /// CHECK-DAG:                      Return [<<Invoke>>]
38 
39   /// CHECK-START: int Main.inlineReturnIntMethod() inliner (after)
40   /// CHECK-NOT:                      InvokeStaticOrDirect
41 
42   /// CHECK-START: int Main.inlineReturnIntMethod() inliner (after)
43   /// CHECK-DAG:     <<Const38:i\d+>> IntConstant 38
44   /// CHECK-DAG:                      Return [<<Const38>>]
45 
inlineReturnIntMethod()46   public static int inlineReturnIntMethod() {
47     return OtherDex.returnIntMethod();
48   }
49 
50   /// CHECK-START: int Main.inlineOtherDexStatic() inliner (before)
51   /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect method_name:OtherDex.returnOtherDexStatic
52   /// CHECK-DAG:                      Return [<<Invoke>>]
53 
54   /// CHECK-START: int Main.inlineOtherDexStatic() inliner (after)
55   /// CHECK-NOT:                      InvokeStaticOrDirect method_name:OtherDex.returnOtherDexStatic
56 
inlineOtherDexStatic()57   public static int inlineOtherDexStatic() {
58     return OtherDex.returnOtherDexStatic();
59   }
60 
61   /// CHECK-START: int Main.inlineMainStatic() inliner (before)
62   /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
63   /// CHECK-DAG:                      Return [<<Invoke>>]
64 
65   /// CHECK-START: int Main.inlineMainStatic() inliner (after)
66   /// CHECK-NOT:                      InvokeStaticOrDirect
67 
68   /// CHECK-START: int Main.inlineMainStatic() inliner (after)
69   /// CHECK-DAG:     <<Static:i\d+>>  StaticFieldGet
70   /// CHECK-DAG:                      Return [<<Static>>]
71 
inlineMainStatic()72   public static int inlineMainStatic() {
73     return OtherDex.returnMainStatic();
74   }
75 
76   /// CHECK-START: int Main.dontInlineRecursiveCall() inliner (before)
77   /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect method_name:OtherDex.recursiveCall
78   /// CHECK-DAG:                      Return [<<Invoke>>]
79 
80   /// CHECK-START: int Main.dontInlineRecursiveCall() inliner (after)
81   /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect method_name:OtherDex.recursiveCall
82   /// CHECK-DAG:                      Return [<<Invoke>>]
83 
dontInlineRecursiveCall()84   public static int dontInlineRecursiveCall() {
85     return OtherDex.recursiveCall();
86   }
87 
88   /// CHECK-START: java.lang.String Main.inlineReturnString() inliner (before)
89   /// CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect method_name:OtherDex.returnString
90   /// CHECK-DAG:                      Return [<<Invoke>>]
91 
92   /// CHECK-START: java.lang.String Main.inlineReturnString() inliner (after)
93   /// CHECK-NOT:                      InvokeStaticOrDirect method_name:OtherDex.returnString
94 
inlineReturnString()95   public static String inlineReturnString() {
96     return OtherDex.returnString();
97   }
98 
99   /// CHECK-START: java.lang.Class Main.inlineOtherDexClass() inliner (before)
100   /// CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect method_name:OtherDex.returnOtherDexClass
101   /// CHECK-DAG:                      Return [<<Invoke>>]
102 
103   /// CHECK-START: java.lang.Class Main.inlineOtherDexClass() inliner (after)
104   /// CHECK-NOT:                      InvokeStaticOrDirect method_name:OtherDex.returnOtherDexClass
105 
inlineOtherDexClass()106   public static Class<?> inlineOtherDexClass() {
107     return OtherDex.returnOtherDexClass();
108   }
109 
110   /// CHECK-START: java.lang.Class Main.inlineMainClass() inliner (before)
111   /// CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
112   /// CHECK-DAG:                      Return [<<Invoke>>]
113 
114   /// CHECK-START: java.lang.Class Main.inlineMainClass() inliner (after)
115   /// CHECK-NOT:                      InvokeStaticOrDirect
116 
117   /// CHECK-START: java.lang.Class Main.inlineMainClass() inliner (after)
118   /// CHECK-DAG:                     Return [<<Class:l\d+>>]
119   /// CHECK-DAG:     <<Class>>       LoadClass
120   // Note: There are two LoadClass instructions. We obtain the correct
121   //       instruction id by matching the Return's input list first.
122 
inlineMainClass()123   public static Class<?> inlineMainClass() {
124     return OtherDex.returnMainClass();
125   }
126 
127   /// CHECK-START: java.lang.Class Main.inlineOtherDexClassStaticCall() inliner (before)
128   /// CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect method_name:OtherDex.returnOtherDexClassStaticCall
129   /// CHECK-DAG:                      Return [<<Invoke>>]
130 
131   /// CHECK-START: java.lang.Class Main.inlineOtherDexClassStaticCall() inliner (after)
132   /// CHECK-NOT:                      InvokeStaticOrDirect method_name:OtherDex.returnOtherDexClassStaticCall
133 
inlineOtherDexClassStaticCall()134   public static Class<?> inlineOtherDexClassStaticCall() {
135     return OtherDex.returnOtherDexClassStaticCall();
136   }
137 
138   /// CHECK-START: java.lang.Class Main.inlineOtherDexCallingMain() inliner (before)
139   /// CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
140   /// CHECK-DAG:                      Return [<<Invoke>>]
141 
142   /// CHECK-START: java.lang.Class Main.inlineOtherDexCallingMain() inliner (after)
143   /// CHECK-NOT:                      InvokeStaticOrDirect
144 
145   /// CHECK-START: java.lang.Class Main.inlineOtherDexCallingMain() inliner (after)
146   /// CHECK-DAG:                     Return [<<Class:l\d+>>]
147   /// CHECK-DAG:     <<Class>>       LoadClass
148   // Note: There are two LoadClass instructions. We obtain the correct
149   //       instruction id by matching the Return's input list first.
150 
inlineOtherDexCallingMain()151   public static Class<?> inlineOtherDexCallingMain() {
152     return OtherDex.returnOtherDexCallingMain();
153   }
154 
getOtherClass()155   public static Class<?> getOtherClass() {
156     return Main.class;
157   }
158 
main(String[] args)159   public static void main(String[] args) {
160     inlineEmptyMethod();
161     if (inlineReturnIntMethod() != 38) {
162       throw new Error("Expected 38");
163     }
164 
165     if (inlineOtherDexStatic() != 1) {
166       throw new Error("Expected 1");
167     }
168 
169     if (inlineMainStatic() != 42) {
170       throw new Error("Expected 42");
171     }
172 
173     if (inlineReturnString() != "OtherDex") {
174       throw new Error("Expected OtherDex");
175     }
176 
177     if (inlineOtherDexClass() != OtherDex.class) {
178       throw new Error("Expected " + OtherDex.class);
179     }
180 
181     if (inlineOtherDexClassStaticCall() != OtherDex.class) {
182       throw new Error("Expected " + OtherDex.class);
183     }
184 
185     if (inlineMainClass() != Main.class) {
186       throw new Error("Expected " + Main.class);
187     }
188 
189     if (inlineOtherDexCallingMain() != Main.class) {
190       throw new Error("Expected " + Main.class);
191     }
192   }
193 
194   // Reference the AAA class to ensure it is in the dex cache.
195   public static Class<?> cls = AAA.class;
196 
197   // Add a field that will be the first entry in the dex cache, to
198   // avoid having the OtherDex.myStatic and Main.myStatic fields
199   // share the same cache index.
200   public static int aaa = 32;
201   public static int myStatic = 42;
202 }
203