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 // TODO: Add more tests after we can inline functions with calls.
18 
19 class ClassWithoutFinals {
20   /// CHECK-START: void ClassWithoutFinals.<init>() inliner (after)
21   /// CHECK-NOT: ConstructorFence
ClassWithoutFinals()22   public ClassWithoutFinals() {}
23 }
24 
25 class ClassWithFinals {
26   public final int x;
27   public ClassWithFinals obj;
28   public static boolean doThrow = false;
29 
ClassWithFinals(boolean cond)30   public ClassWithFinals(boolean cond) {
31     x = 1;
32     throw new RuntimeException();
33     // should not inline this constructor
34   }
35 
36   /// CHECK-START: void ClassWithFinals.<init>() inliner (after)
37   /// CHECK:      ConstructorFence
38   /// CHECK-NOT:  ConstructorFence
39 
40   /*
41    * Check that the correct assembly instructions are selected for a Store/Store fence.
42    *
43    * - ARM variants:   DMB ISHST (store-store fence for inner shareable domain)
44    * - Intel variants: no-op (store-store does not need a fence).
45    */
46 
47   /// CHECK-START-ARM64: void ClassWithFinals.<init>() disassembly (after)
48   /// CHECK:      ConstructorFence
49   /// CHECK-NEXT: dmb ishst
50 
51   /// CHECK-START-ARM: void ClassWithFinals.<init>() disassembly (after)
52   /// CHECK:      ConstructorFence
53   /// CHECK-NEXT: dmb ishst
54 
55   /// CHECK-START-X86_64: void ClassWithFinals.<init>() disassembly (after)
56   /// CHECK:      ConstructorFence
57   /// CHECK-NOT:  {{[slm]}}fence
58 
59   /// CHECK-START-X86: void ClassWithFinals.<init>() disassembly (after)
60   /// CHECK:      ConstructorFence
61   /// CHECK-NOT:  {{[slm]}}fence
ClassWithFinals()62   public ClassWithFinals() {
63     // Exactly one constructor barrier.
64     // Note: Do not store 0 as that can be eliminated together with the constructor
65     // barrier by the code pattern substitution in the inliner.
66     x = 1;
67   }
68 
69   /// CHECK-START: void ClassWithFinals.<init>(int) inliner (after)
70   /// CHECK: <<This:l\d+>>            ParameterValue
71   /// CHECK: <<NewInstance:l\d+>>     NewInstance
72   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
73   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
74   /// CHECK-DAG:                      ConstructorFence [<<This>>]
75   /// CHECK-NOT:                      ConstructorFence
ClassWithFinals(int x)76   public ClassWithFinals(int x) {
77     // This should have exactly three barriers:
78     //   - one for the new-instance
79     //   - one for the constructor
80     //   - one for the `new` which should be inlined.
81     obj = new ClassWithFinals();
82     this.x = x;
83   }
84 }
85 
86 class InheritFromClassWithFinals extends ClassWithFinals {
87   /// CHECK-START: void InheritFromClassWithFinals.<init>() inliner (after)
88   /// CHECK: <<This:l\d+>>            ParameterValue
89   /// CHECK:                          ConstructorFence [<<This>>]
90   /// CHECK-NOT:                      ConstructorFence
91 
92   /// CHECK-START: void InheritFromClassWithFinals.<init>() inliner (after)
93   /// CHECK-NOT:  InvokeStaticOrDirect
InheritFromClassWithFinals()94   public InheritFromClassWithFinals() {
95     // Should inline the super constructor.
96     //
97     // Exactly one constructor barrier here.
98   }
99 
100   /// CHECK-START: void InheritFromClassWithFinals.<init>(boolean) inliner (after)
101   /// CHECK:      InvokeStaticOrDirect
102 
103   /// CHECK-START: void InheritFromClassWithFinals.<init>(boolean) inliner (after)
104   /// CHECK-NOT:  ConstructorFence
InheritFromClassWithFinals(boolean cond)105   public InheritFromClassWithFinals(boolean cond) {
106     super(cond);
107     // should not inline the super constructor
108   }
109 
110   /// CHECK-START: void InheritFromClassWithFinals.<init>(int) inliner (after)
111   /// CHECK: <<This:l\d+>>            ParameterValue
112   /// CHECK-DAG: <<NewHere:l\d+>>     NewInstance klass:InheritFromClassWithFinals
113   /// CHECK-DAG:                      ConstructorFence [<<This>>]
114   /// CHECK-DAG:                      ConstructorFence [<<NewHere>>]
115   /// CHECK-DAG:                      ConstructorFence [<<NewHere>>]
116   /// CHECK-NOT:                      ConstructorFence
117 
118   /// CHECK-START: void InheritFromClassWithFinals.<init>(int) inliner (after)
119   /// CHECK-NOT:  InvokeStaticOrDirect
InheritFromClassWithFinals(int unused)120   public InheritFromClassWithFinals(int unused) {
121     // super();  // implicitly the first invoke in this constructor.
122     //   Should inline the super constructor and insert a constructor fence there.
123 
124     // Should inline the new instance call (barrier); and add another one
125     // because the superclass has finals.
126     new InheritFromClassWithFinals();
127   }
128 }
129 
130 class HaveFinalsAndInheritFromClassWithFinals extends ClassWithFinals {
131   final int y;
132 
133   /// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>() inliner (after)
134   /// CHECK: <<This:l\d+>>            ParameterValue
135   /// CHECK:                          ConstructorFence [<<This>>]
136   /// CHECK:                          ConstructorFence [<<This>>]
137   /// CHECK-NOT:                      ConstructorFence
138 
139   /// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>() inliner (after)
140   /// CHECK-NOT: InvokeStaticOrDirect
HaveFinalsAndInheritFromClassWithFinals()141   public HaveFinalsAndInheritFromClassWithFinals() {
142     // Should inline the super constructor and keep the memory barrier.
143     y = 0;
144   }
145 
146   /// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(boolean) inliner (after)
147   /// CHECK: <<This:l\d+>>            ParameterValue
148   /// CHECK:                          InvokeStaticOrDirect
149   /// CHECK:                          ConstructorFence [<<This>>]
150   /// CHECK-NOT:                      ConstructorFence
HaveFinalsAndInheritFromClassWithFinals(boolean cond)151   public HaveFinalsAndInheritFromClassWithFinals(boolean cond) {
152     super(cond);
153     // should not inline the super constructor
154     y = 0;
155   }
156 
157   /// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(int) inliner (after)
158   /// CHECK: <<This:l\d+>>            ParameterValue
159   /// CHECK-DAG: <<NewHF:l\d+>>       NewInstance klass:HaveFinalsAndInheritFromClassWithFinals
160   /// CHECK-DAG: <<NewIF:l\d+>>       NewInstance klass:InheritFromClassWithFinals
161   /// CHECK-DAG:                      ConstructorFence [<<This>>]
162   /// CHECK-DAG:                      ConstructorFence [<<NewHF>>]
163   /// CHECK-DAG:                      ConstructorFence [<<NewHF>>]
164   /// CHECK-DAG:                      ConstructorFence [<<NewHF>>]
165   /// CHECK-DAG:                      ConstructorFence [<<NewIF>>]
166   /// CHECK-DAG:                      ConstructorFence [<<NewIF>>]
167   /// CHECK-DAG:                      ConstructorFence [<<This>>]
168   /// CHECK-NOT:                      ConstructorFence
169 
170   /// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(int) inliner (after)
171   /// CHECK-NOT:  InvokeStaticOrDirect
HaveFinalsAndInheritFromClassWithFinals(int unused)172   public HaveFinalsAndInheritFromClassWithFinals(int unused) {
173     // super()
174     // -- Inlined super constructor, insert memory barrier here.
175     y = 0;
176 
177     // Should inline new instance and keep both memory barriers.
178     // One more memory barrier for new-instance.
179     // (3 total for this new-instance #1)
180     new HaveFinalsAndInheritFromClassWithFinals();
181     // Should inline new instance and have exactly one barrier.
182     // One more barrier for new-instance.
183     // (2 total for this new-instance #2)
184     new InheritFromClassWithFinals();
185 
186     // -- End of constructor, insert memory barrier here to freeze 'y'.
187   }
188 }
189 
190 public class Main {
191 
192   /// CHECK-START: ClassWithFinals Main.noInlineNoConstructorBarrier() inliner (after)
193   /// CHECK:      InvokeStaticOrDirect
194 
195   /// CHECK-START: ClassWithFinals Main.noInlineNoConstructorBarrier() inliner (after)
196   /// CHECK: <<NewInstance:l\d+>>     NewInstance
197   /// CHECK:                          ConstructorFence [<<NewInstance>>]
198   /// CHECK-NOT:                      ConstructorFence
noInlineNoConstructorBarrier()199   public static ClassWithFinals noInlineNoConstructorBarrier() {
200     // Exactly one barrier for the new-instance.
201     return new ClassWithFinals(false);
202     // should not inline the constructor
203   }
204 
205   /// CHECK-START: void Main.inlineNew() inliner (after)
206   /// CHECK: <<NewInstance:l\d+>>     NewInstance
207   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
208   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
209   /// CHECK-NOT:                      ConstructorFence
210 
211   /// CHECK-START: void Main.inlineNew() inliner (after)
212   /// CHECK-NOT:  InvokeStaticOrDirect
inlineNew()213   public static void inlineNew() {
214     // Exactly 2 barriers. One for new-instance, one for constructor with finals.
215     new ClassWithFinals();
216   }
217 
218   /// CHECK-START: void Main.inlineNew1() inliner (after)
219   /// CHECK: <<NewInstance:l\d+>>     NewInstance
220   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
221   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
222   /// CHECK-NOT:                      ConstructorFence
223 
224   /// CHECK-START: void Main.inlineNew1() inliner (after)
225   /// CHECK-NOT:  InvokeStaticOrDirect
inlineNew1()226   public static void inlineNew1() {
227     new InheritFromClassWithFinals();
228   }
229 
230   /// CHECK-START: void Main.inlineNew2() inliner (after)
231   /// CHECK: <<NewInstance:l\d+>>     NewInstance
232   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
233   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
234   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
235   /// CHECK-NOT:                      ConstructorFence
236 
237   /// CHECK-START: void Main.inlineNew2() inliner (after)
238   /// CHECK-NOT:  InvokeStaticOrDirect
inlineNew2()239   public static void inlineNew2() {
240     new HaveFinalsAndInheritFromClassWithFinals();
241   }
242 
243   /// CHECK-START: void Main.inlineNew3() inliner (after)
244   /// CHECK: <<NewInstance:l\d+>>     NewInstance
245   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
246   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
247   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
248   /// CHECK-NOT:                      ConstructorFence
249   /// CHECK: <<NewInstance2:l\d+>>    NewInstance
250   /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
251   /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
252   /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
253   /// CHECK-NOT:                      ConstructorFence
254 
255   /// CHECK-START: void Main.inlineNew3() inliner (after)
256   /// CHECK-NOT:  InvokeStaticOrDirect
inlineNew3()257   public static void inlineNew3() {
258     new HaveFinalsAndInheritFromClassWithFinals();
259     new HaveFinalsAndInheritFromClassWithFinals();
260   }
261 
262   static int[] mCodePointsEmpty = new int[0];
263 
264   /// CHECK-START: void Main.testNewString() inliner (after)
265   /// CHECK-NOT:  ConstructorFence
266   /// CHECK:      InvokeStaticOrDirect method_load_kind:StringInit
267   /// CHECK-NOT:  ConstructorFence
268   /// CHECK-NOT:  InvokeStaticOrDirect
testNewString()269   public static void testNewString() {
270     // Strings are special because of StringFactory hackeries.
271     //
272     // Assume they handle their own fencing internally in the StringFactory.
273     int[] codePoints = null;
274     String some_new_string = new String(mCodePointsEmpty, 0, 0);
275   }
276 
main(String[] args)277   public static void main(String[] args) {}
278 }
279