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     x = 0;
65   }
66 
67   /// CHECK-START: void ClassWithFinals.<init>(int) inliner (after)
68   /// CHECK: <<This:l\d+>>            ParameterValue
69   /// CHECK: <<NewInstance:l\d+>>     NewInstance
70   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
71   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
72   /// CHECK-DAG:                      ConstructorFence [<<This>>]
73   /// CHECK-NOT:                      ConstructorFence
ClassWithFinals(int x)74   public ClassWithFinals(int x) {
75     // This should have exactly three barriers:
76     //   - one for the new-instance
77     //   - one for the constructor
78     //   - one for the `new` which should be inlined.
79     obj = new ClassWithFinals();
80     this.x = x;
81   }
82 }
83 
84 class InheritFromClassWithFinals extends ClassWithFinals {
85   /// CHECK-START: void InheritFromClassWithFinals.<init>() inliner (after)
86   /// CHECK: <<This:l\d+>>            ParameterValue
87   /// CHECK:                          ConstructorFence [<<This>>]
88   /// CHECK-NOT:                      ConstructorFence
89 
90   /// CHECK-START: void InheritFromClassWithFinals.<init>() inliner (after)
91   /// CHECK-NOT:  InvokeStaticOrDirect
InheritFromClassWithFinals()92   public InheritFromClassWithFinals() {
93     // Should inline the super constructor.
94     //
95     // Exactly one constructor barrier here.
96   }
97 
98   /// CHECK-START: void InheritFromClassWithFinals.<init>(boolean) inliner (after)
99   /// CHECK:      InvokeStaticOrDirect
100 
101   /// CHECK-START: void InheritFromClassWithFinals.<init>(boolean) inliner (after)
102   /// CHECK-NOT:  ConstructorFence
InheritFromClassWithFinals(boolean cond)103   public InheritFromClassWithFinals(boolean cond) {
104     super(cond);
105     // should not inline the super constructor
106   }
107 
108   /// CHECK-START: void InheritFromClassWithFinals.<init>(int) inliner (after)
109   /// CHECK: <<This:l\d+>>            ParameterValue
110   /// CHECK-DAG: <<NewHere:l\d+>>     NewInstance klass:InheritFromClassWithFinals
111   /// CHECK-DAG:                      ConstructorFence [<<This>>]
112   /// CHECK-DAG:                      ConstructorFence [<<NewHere>>]
113   /// CHECK-DAG:                      ConstructorFence [<<NewHere>>]
114   /// CHECK-NOT:                      ConstructorFence
115 
116   /// CHECK-START: void InheritFromClassWithFinals.<init>(int) inliner (after)
117   /// CHECK-NOT:  InvokeStaticOrDirect
InheritFromClassWithFinals(int unused)118   public InheritFromClassWithFinals(int unused) {
119     // super();  // implicitly the first invoke in this constructor.
120     //   Should inline the super constructor and insert a constructor fence there.
121 
122     // Should inline the new instance call (barrier); and add another one
123     // because the superclass has finals.
124     new InheritFromClassWithFinals();
125   }
126 }
127 
128 class HaveFinalsAndInheritFromClassWithFinals extends ClassWithFinals {
129   final int y;
130 
131   /// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>() inliner (after)
132   /// CHECK: <<This:l\d+>>            ParameterValue
133   /// CHECK:                          ConstructorFence [<<This>>]
134   /// CHECK:                          ConstructorFence [<<This>>]
135   /// CHECK-NOT:                      ConstructorFence
136 
137   /// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>() inliner (after)
138   /// CHECK-NOT: InvokeStaticOrDirect
HaveFinalsAndInheritFromClassWithFinals()139   public HaveFinalsAndInheritFromClassWithFinals() {
140     // Should inline the super constructor and keep the memory barrier.
141     y = 0;
142   }
143 
144   /// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(boolean) inliner (after)
145   /// CHECK: <<This:l\d+>>            ParameterValue
146   /// CHECK:                          InvokeStaticOrDirect
147   /// CHECK:                          ConstructorFence [<<This>>]
148   /// CHECK-NOT:                      ConstructorFence
HaveFinalsAndInheritFromClassWithFinals(boolean cond)149   public HaveFinalsAndInheritFromClassWithFinals(boolean cond) {
150     super(cond);
151     // should not inline the super constructor
152     y = 0;
153   }
154 
155   /// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(int) inliner (after)
156   /// CHECK: <<This:l\d+>>            ParameterValue
157   /// CHECK-DAG: <<NewHF:l\d+>>       NewInstance klass:HaveFinalsAndInheritFromClassWithFinals
158   /// CHECK-DAG: <<NewIF:l\d+>>       NewInstance klass:InheritFromClassWithFinals
159   /// CHECK-DAG:                      ConstructorFence [<<This>>]
160   /// CHECK-DAG:                      ConstructorFence [<<NewHF>>]
161   /// CHECK-DAG:                      ConstructorFence [<<NewHF>>]
162   /// CHECK-DAG:                      ConstructorFence [<<NewHF>>]
163   /// CHECK-DAG:                      ConstructorFence [<<NewIF>>]
164   /// CHECK-DAG:                      ConstructorFence [<<NewIF>>]
165   /// CHECK-DAG:                      ConstructorFence [<<This>>]
166   /// CHECK-NOT:                      ConstructorFence
167 
168   /// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(int) inliner (after)
169   /// CHECK-NOT:  InvokeStaticOrDirect
HaveFinalsAndInheritFromClassWithFinals(int unused)170   public HaveFinalsAndInheritFromClassWithFinals(int unused) {
171     // super()
172     // -- Inlined super constructor, insert memory barrier here.
173     y = 0;
174 
175     // Should inline new instance and keep both memory barriers.
176     // One more memory barrier for new-instance.
177     // (3 total for this new-instance #1)
178     new HaveFinalsAndInheritFromClassWithFinals();
179     // Should inline new instance and have exactly one barrier.
180     // One more barrier for new-instance.
181     // (2 total for this new-instance #2)
182     new InheritFromClassWithFinals();
183 
184     // -- End of constructor, insert memory barrier here to freeze 'y'.
185   }
186 }
187 
188 public class Main {
189 
190   /// CHECK-START: ClassWithFinals Main.noInlineNoConstructorBarrier() inliner (after)
191   /// CHECK:      InvokeStaticOrDirect
192 
193   /// CHECK-START: ClassWithFinals Main.noInlineNoConstructorBarrier() inliner (after)
194   /// CHECK: <<NewInstance:l\d+>>     NewInstance
195   /// CHECK:                          ConstructorFence [<<NewInstance>>]
196   /// CHECK-NOT:                      ConstructorFence
noInlineNoConstructorBarrier()197   public static ClassWithFinals noInlineNoConstructorBarrier() {
198     // Exactly one barrier for the new-instance.
199     return new ClassWithFinals(false);
200     // should not inline the constructor
201   }
202 
203   /// CHECK-START: void Main.inlineNew() inliner (after)
204   /// CHECK: <<NewInstance:l\d+>>     NewInstance
205   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
206   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
207   /// CHECK-NOT:                      ConstructorFence
208 
209   /// CHECK-START: void Main.inlineNew() inliner (after)
210   /// CHECK-NOT:  InvokeStaticOrDirect
inlineNew()211   public static void inlineNew() {
212     // Exactly 2 barriers. One for new-instance, one for constructor with finals.
213     new ClassWithFinals();
214   }
215 
216   /// CHECK-START: void Main.inlineNew1() inliner (after)
217   /// CHECK: <<NewInstance:l\d+>>     NewInstance
218   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
219   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
220   /// CHECK-NOT:                      ConstructorFence
221 
222   /// CHECK-START: void Main.inlineNew1() inliner (after)
223   /// CHECK-NOT:  InvokeStaticOrDirect
inlineNew1()224   public static void inlineNew1() {
225     new InheritFromClassWithFinals();
226   }
227 
228   /// CHECK-START: void Main.inlineNew2() inliner (after)
229   /// CHECK: <<NewInstance:l\d+>>     NewInstance
230   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
231   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
232   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
233   /// CHECK-NOT:                      ConstructorFence
234 
235   /// CHECK-START: void Main.inlineNew2() inliner (after)
236   /// CHECK-NOT:  InvokeStaticOrDirect
inlineNew2()237   public static void inlineNew2() {
238     new HaveFinalsAndInheritFromClassWithFinals();
239   }
240 
241   /// CHECK-START: void Main.inlineNew3() inliner (after)
242   /// CHECK: <<NewInstance:l\d+>>     NewInstance
243   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
244   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
245   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
246   /// CHECK-NOT:                      ConstructorFence
247   /// CHECK: <<NewInstance2:l\d+>>    NewInstance
248   /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
249   /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
250   /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
251   /// CHECK-NOT:                      ConstructorFence
252 
253   /// CHECK-START: void Main.inlineNew3() inliner (after)
254   /// CHECK-NOT:  InvokeStaticOrDirect
inlineNew3()255   public static void inlineNew3() {
256     new HaveFinalsAndInheritFromClassWithFinals();
257     new HaveFinalsAndInheritFromClassWithFinals();
258   }
259 
260   static int[] mCodePointsEmpty = new int[0];
261 
262   /// CHECK-START: void Main.testNewString() inliner (after)
263   /// CHECK-NOT:  ConstructorFence
264   /// CHECK:      InvokeStaticOrDirect method_load_kind:StringInit
265   /// CHECK-NOT:  ConstructorFence
266   /// CHECK-NOT:  InvokeStaticOrDirect
testNewString()267   public static void testNewString() {
268     // Strings are special because of StringFactory hackeries.
269     //
270     // Assume they handle their own fencing internally in the StringFactory.
271     int[] codePoints = null;
272     String some_new_string = new String(mCodePointsEmpty, 0, 0);
273   }
274 
main(String[] args)275   public static void main(String[] args) {}
276 }
277