xref: /aosp_15_r20/art/test/476-checker-ctor-fence-redun-elim/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Array;
18*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Field;
19*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method;
20*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Modifier;
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker // Baseline class. This has no final fields, so there are no additional freezes
23*795d594fSAndroid Build Coastguard Worker // in its constructor.
24*795d594fSAndroid Build Coastguard Worker //
25*795d594fSAndroid Build Coastguard Worker // The new-instance itself always has 1 freeze for the happens-before on the object header
26*795d594fSAndroid Build Coastguard Worker // write (i.e. [obj.class = X] happens-before any access to obj).
27*795d594fSAndroid Build Coastguard Worker //
28*795d594fSAndroid Build Coastguard Worker // Total freezes for "new Base()": 1.
29*795d594fSAndroid Build Coastguard Worker class Base {
30*795d594fSAndroid Build Coastguard Worker   int w0;
31*795d594fSAndroid Build Coastguard Worker   int w1;
32*795d594fSAndroid Build Coastguard Worker   int w2;
33*795d594fSAndroid Build Coastguard Worker   int w3;
34*795d594fSAndroid Build Coastguard Worker 
Base()35*795d594fSAndroid Build Coastguard Worker   Base() {
36*795d594fSAndroid Build Coastguard Worker     // Prevent inliner from matching the code pattern when calling this constructor
37*795d594fSAndroid Build Coastguard Worker     // to test the normal inlining that builds and inserts the callee graph.
38*795d594fSAndroid Build Coastguard Worker     // (Pattern matching can merge or eliminate constructor barriers.)
39*795d594fSAndroid Build Coastguard Worker     $inline$nop();
40*795d594fSAndroid Build Coastguard Worker   }
41*795d594fSAndroid Build Coastguard Worker 
42*795d594fSAndroid Build Coastguard Worker   @Override
toString()43*795d594fSAndroid Build Coastguard Worker   public String toString() {
44*795d594fSAndroid Build Coastguard Worker     return getClass().getName() + "(" + baseString() + ")";
45*795d594fSAndroid Build Coastguard Worker   }
46*795d594fSAndroid Build Coastguard Worker 
baseString()47*795d594fSAndroid Build Coastguard Worker   protected String baseString() {
48*795d594fSAndroid Build Coastguard Worker     return String.format("w0: %d, w1: %d, w2: %d, w3: %d", w0, w1, w2, w3);
49*795d594fSAndroid Build Coastguard Worker   }
50*795d594fSAndroid Build Coastguard Worker 
$inline$nop()51*795d594fSAndroid Build Coastguard Worker   private void $inline$nop() {}
52*795d594fSAndroid Build Coastguard Worker }
53*795d594fSAndroid Build Coastguard Worker 
54*795d594fSAndroid Build Coastguard Worker // This has a final field in its constructor, so there must be a field freeze
55*795d594fSAndroid Build Coastguard Worker // at the end of <init>.
56*795d594fSAndroid Build Coastguard Worker //
57*795d594fSAndroid Build Coastguard Worker // Total freezes for "new OneFinal()": 2.
58*795d594fSAndroid Build Coastguard Worker class OneFinal extends Base {
59*795d594fSAndroid Build Coastguard Worker   final int x;
OneFinal(int x)60*795d594fSAndroid Build Coastguard Worker   OneFinal(int x) {
61*795d594fSAndroid Build Coastguard Worker     this.x = x;
62*795d594fSAndroid Build Coastguard Worker   }
63*795d594fSAndroid Build Coastguard Worker 
64*795d594fSAndroid Build Coastguard Worker   @Override
baseString()65*795d594fSAndroid Build Coastguard Worker   protected String baseString() {
66*795d594fSAndroid Build Coastguard Worker     return String.format("%s, x: %d", super.baseString(), x);
67*795d594fSAndroid Build Coastguard Worker   }
68*795d594fSAndroid Build Coastguard Worker }
69*795d594fSAndroid Build Coastguard Worker 
70*795d594fSAndroid Build Coastguard Worker class Assert {
stringEquals(String expected, Object actual)71*795d594fSAndroid Build Coastguard Worker   public static void stringEquals(String expected, Object actual) {
72*795d594fSAndroid Build Coastguard Worker     stringEquals$noinline$(expected, actual);
73*795d594fSAndroid Build Coastguard Worker   }
74*795d594fSAndroid Build Coastguard Worker 
75*795d594fSAndroid Build Coastguard Worker   // Forbid compiler from inlining this to avoid overly clever optimizations.
stringEquals$noinline$(String expected, Object actual)76*795d594fSAndroid Build Coastguard Worker   private static void stringEquals$noinline$(String expected, Object actual) {
77*795d594fSAndroid Build Coastguard Worker     String actualStr = Main.valueToString(actual);
78*795d594fSAndroid Build Coastguard Worker     if (!expected.equals(actualStr)) {
79*795d594fSAndroid Build Coastguard Worker       throw new AssertionError("Expected: " + expected + ", actual: " + actualStr);
80*795d594fSAndroid Build Coastguard Worker     }
81*795d594fSAndroid Build Coastguard Worker   }
82*795d594fSAndroid Build Coastguard Worker }
83*795d594fSAndroid Build Coastguard Worker 
84*795d594fSAndroid Build Coastguard Worker interface Test {
exercise()85*795d594fSAndroid Build Coastguard Worker   public void exercise();
check()86*795d594fSAndroid Build Coastguard Worker   public void check();
87*795d594fSAndroid Build Coastguard Worker }
88*795d594fSAndroid Build Coastguard Worker 
89*795d594fSAndroid Build Coastguard Worker class TestOneFinal implements Test {
90*795d594fSAndroid Build Coastguard Worker   // Initialize at least once before actual test.
91*795d594fSAndroid Build Coastguard Worker   public static Object external;
92*795d594fSAndroid Build Coastguard Worker 
93*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void TestOneFinal.exercise() constructor_fence_redundancy_elimination (before)
94*795d594fSAndroid Build Coastguard Worker   /// CHECK: <<NewInstance:l\d+>>     NewInstance
95*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
96*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
97*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                      ConstructorFence
98*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
99*795d594fSAndroid Build Coastguard Worker 
100*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void TestOneFinal.exercise() constructor_fence_redundancy_elimination (after)
101*795d594fSAndroid Build Coastguard Worker   /// CHECK: <<NewInstance:l\d+>>     NewInstance
102*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
103*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                      ConstructorFence
104*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
105*795d594fSAndroid Build Coastguard Worker   @Override
exercise()106*795d594fSAndroid Build Coastguard Worker   public void exercise() {
107*795d594fSAndroid Build Coastguard Worker       Base b = new OneFinal(1);
108*795d594fSAndroid Build Coastguard Worker       // 1 store, 2 freezes.
109*795d594fSAndroid Build Coastguard Worker 
110*795d594fSAndroid Build Coastguard Worker       // Stores to 'b' do not escape b.
111*795d594fSAndroid Build Coastguard Worker       b.w0 = 1;
112*795d594fSAndroid Build Coastguard Worker       b.w1 = 2;
113*795d594fSAndroid Build Coastguard Worker       b.w2 = 3;
114*795d594fSAndroid Build Coastguard Worker 
115*795d594fSAndroid Build Coastguard Worker       // Publish the result to a global so that it is not LSE-eliminated.
116*795d594fSAndroid Build Coastguard Worker       external = b;
117*795d594fSAndroid Build Coastguard Worker   }
118*795d594fSAndroid Build Coastguard Worker 
119*795d594fSAndroid Build Coastguard Worker   @Override
check()120*795d594fSAndroid Build Coastguard Worker   public void check() {
121*795d594fSAndroid Build Coastguard Worker     Assert.stringEquals("OneFinal(w0: 1, w1: 2, w2: 3, w3: 0, x: 1)", external);
122*795d594fSAndroid Build Coastguard Worker   }
123*795d594fSAndroid Build Coastguard Worker }
124*795d594fSAndroid Build Coastguard Worker 
125*795d594fSAndroid Build Coastguard Worker // This has a final field in its constructor, so there must be a field freeze
126*795d594fSAndroid Build Coastguard Worker // at the end of <init>. The previous base class's freezes accumulate on top
127*795d594fSAndroid Build Coastguard Worker // of this one.
128*795d594fSAndroid Build Coastguard Worker //
129*795d594fSAndroid Build Coastguard Worker // Total freezes for "new TwoFinal()": 3.
130*795d594fSAndroid Build Coastguard Worker class TwoFinal extends OneFinal {
131*795d594fSAndroid Build Coastguard Worker   final int y;
TwoFinal(int x, int y)132*795d594fSAndroid Build Coastguard Worker   TwoFinal(int x, int y) {
133*795d594fSAndroid Build Coastguard Worker     super(x);
134*795d594fSAndroid Build Coastguard Worker     this.y = y;
135*795d594fSAndroid Build Coastguard Worker   }
136*795d594fSAndroid Build Coastguard Worker 
137*795d594fSAndroid Build Coastguard Worker   @Override
baseString()138*795d594fSAndroid Build Coastguard Worker   protected String baseString() {
139*795d594fSAndroid Build Coastguard Worker     return String.format("%s, y: %d", super.baseString(), y);
140*795d594fSAndroid Build Coastguard Worker   }
141*795d594fSAndroid Build Coastguard Worker }
142*795d594fSAndroid Build Coastguard Worker 
143*795d594fSAndroid Build Coastguard Worker // This has a final field in its constructor, so there must be a field freeze
144*795d594fSAndroid Build Coastguard Worker // at the end of <init>. The previous base class's freezes accumulate on top
145*795d594fSAndroid Build Coastguard Worker // of this one.
146*795d594fSAndroid Build Coastguard Worker //
147*795d594fSAndroid Build Coastguard Worker // Total freezes for "new ThreeFinal()": 4.
148*795d594fSAndroid Build Coastguard Worker class ThreeFinal extends TwoFinal {
149*795d594fSAndroid Build Coastguard Worker   final int z;
ThreeFinal(int x, int y, int z)150*795d594fSAndroid Build Coastguard Worker   ThreeFinal(int x, int y, int z) {
151*795d594fSAndroid Build Coastguard Worker     super(x, y);
152*795d594fSAndroid Build Coastguard Worker     this.z = z;
153*795d594fSAndroid Build Coastguard Worker   }
154*795d594fSAndroid Build Coastguard Worker 
155*795d594fSAndroid Build Coastguard Worker   @Override
baseString()156*795d594fSAndroid Build Coastguard Worker   protected String baseString() {
157*795d594fSAndroid Build Coastguard Worker     return String.format("%s, z: %d", super.baseString(), z);
158*795d594fSAndroid Build Coastguard Worker   }
159*795d594fSAndroid Build Coastguard Worker }
160*795d594fSAndroid Build Coastguard Worker 
161*795d594fSAndroid Build Coastguard Worker class TestThreeFinal implements Test {
162*795d594fSAndroid Build Coastguard Worker   // Initialize at least once before actual test.
163*795d594fSAndroid Build Coastguard Worker   public static Object external;
164*795d594fSAndroid Build Coastguard Worker 
165*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void TestThreeFinal.exercise() constructor_fence_redundancy_elimination (before)
166*795d594fSAndroid Build Coastguard Worker   /// CHECK: <<NewInstance:l\d+>>     NewInstance
167*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
168*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
169*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
170*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
171*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                      ConstructorFence
172*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
173*795d594fSAndroid Build Coastguard Worker 
174*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void TestThreeFinal.exercise() constructor_fence_redundancy_elimination (after)
175*795d594fSAndroid Build Coastguard Worker   /// CHECK: <<NewInstance:l\d+>>     NewInstance
176*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
177*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                      ConstructorFence
178*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
179*795d594fSAndroid Build Coastguard Worker   @Override
exercise()180*795d594fSAndroid Build Coastguard Worker   public void exercise() {
181*795d594fSAndroid Build Coastguard Worker     Base b = new ThreeFinal(1, 1, 2);
182*795d594fSAndroid Build Coastguard Worker     // 3 store, 4 freezes.
183*795d594fSAndroid Build Coastguard Worker 
184*795d594fSAndroid Build Coastguard Worker     // Stores to 'b' do not escape b.
185*795d594fSAndroid Build Coastguard Worker     b.w0 = 3;
186*795d594fSAndroid Build Coastguard Worker 
187*795d594fSAndroid Build Coastguard Worker     // Publish the result to a global so that it is not LSE-eliminated.
188*795d594fSAndroid Build Coastguard Worker     external = b;
189*795d594fSAndroid Build Coastguard Worker   }
190*795d594fSAndroid Build Coastguard Worker 
191*795d594fSAndroid Build Coastguard Worker   @Override
check()192*795d594fSAndroid Build Coastguard Worker   public void check() {
193*795d594fSAndroid Build Coastguard Worker     Assert.stringEquals("ThreeFinal(w0: 3, w1: 0, w2: 0, w3: 0, x: 1, y: 1, z: 2)", external);
194*795d594fSAndroid Build Coastguard Worker   }
195*795d594fSAndroid Build Coastguard Worker }
196*795d594fSAndroid Build Coastguard Worker 
197*795d594fSAndroid Build Coastguard Worker // Ensure "freezes" between multiple new-instances are optimized out.
198*795d594fSAndroid Build Coastguard Worker class TestMultiAlloc implements Test {
199*795d594fSAndroid Build Coastguard Worker   public static Object external;
200*795d594fSAndroid Build Coastguard Worker   public static Object external2;
201*795d594fSAndroid Build Coastguard Worker 
202*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void TestMultiAlloc.exercise() constructor_fence_redundancy_elimination (before)
203*795d594fSAndroid Build Coastguard Worker   /// CHECK: <<NewInstance:l\d+>>     NewInstance
204*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
205*795d594fSAndroid Build Coastguard Worker   /// CHECK: <<NewInstance2:l\d+>>    NewInstance
206*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
207*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                      ConstructorFence
208*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
209*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      StaticFieldSet [<<External2:l\d+>>,<<NewInstance2>>]
210*795d594fSAndroid Build Coastguard Worker 
211*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void TestMultiAlloc.exercise() constructor_fence_redundancy_elimination (after)
212*795d594fSAndroid Build Coastguard Worker   /// CHECK: <<NewInstance:l\d+>>     NewInstance
213*795d594fSAndroid Build Coastguard Worker   /// CHECK: <<NewInstance2:l\d+>>    NewInstance
214*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>,<<NewInstance>>]
215*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                      ConstructorFence
216*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
217*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      StaticFieldSet [<<External2:l\d+>>,<<NewInstance2>>]
218*795d594fSAndroid Build Coastguard Worker   @Override
exercise()219*795d594fSAndroid Build Coastguard Worker   public void exercise() {
220*795d594fSAndroid Build Coastguard Worker     // 1 freeze
221*795d594fSAndroid Build Coastguard Worker     Base b = new Base();
222*795d594fSAndroid Build Coastguard Worker     // 1 freeze
223*795d594fSAndroid Build Coastguard Worker     Base b2 = new Base();
224*795d594fSAndroid Build Coastguard Worker 
225*795d594fSAndroid Build Coastguard Worker     // Merge 2 freezes above into 1 constructor fence.
226*795d594fSAndroid Build Coastguard Worker     external = b;
227*795d594fSAndroid Build Coastguard Worker     external2 = b2;
228*795d594fSAndroid Build Coastguard Worker   }
229*795d594fSAndroid Build Coastguard Worker 
230*795d594fSAndroid Build Coastguard Worker   @Override
check()231*795d594fSAndroid Build Coastguard Worker   public void check() {
232*795d594fSAndroid Build Coastguard Worker     Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external);
233*795d594fSAndroid Build Coastguard Worker     Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external2);
234*795d594fSAndroid Build Coastguard Worker   }
235*795d594fSAndroid Build Coastguard Worker }
236*795d594fSAndroid Build Coastguard Worker 
237*795d594fSAndroid Build Coastguard Worker // Ensure "freezes" between multiple new-instances are optimized out.
238*795d594fSAndroid Build Coastguard Worker class TestThreeFinalTwice implements Test {
239*795d594fSAndroid Build Coastguard Worker   // Initialize at least once before actual test.
240*795d594fSAndroid Build Coastguard Worker   public static Object external;
241*795d594fSAndroid Build Coastguard Worker   public static Object external2;
242*795d594fSAndroid Build Coastguard Worker 
243*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void TestThreeFinalTwice.exercise() constructor_fence_redundancy_elimination (before)
244*795d594fSAndroid Build Coastguard Worker   /// CHECK: <<NewInstance:l\d+>>     NewInstance
245*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
246*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
247*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
248*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
249*795d594fSAndroid Build Coastguard Worker   /// CHECK: <<NewInstance2:l\d+>>    NewInstance
250*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
251*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
252*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
253*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
254*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                      ConstructorFence
255*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
256*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      StaticFieldSet [<<External2:l\d+>>,<<NewInstance2>>]
257*795d594fSAndroid Build Coastguard Worker 
258*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void TestThreeFinalTwice.exercise() constructor_fence_redundancy_elimination (after)
259*795d594fSAndroid Build Coastguard Worker   /// CHECK: <<NewInstance:l\d+>>     NewInstance
260*795d594fSAndroid Build Coastguard Worker   /// CHECK: <<NewInstance2:l\d+>>    NewInstance
261*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>,<<NewInstance>>]
262*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                      ConstructorFence
263*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
264*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      StaticFieldSet [<<External2:l\d+>>,<<NewInstance2>>]
265*795d594fSAndroid Build Coastguard Worker   @Override
exercise()266*795d594fSAndroid Build Coastguard Worker   public void exercise() {
267*795d594fSAndroid Build Coastguard Worker     Base b = new ThreeFinal(1, 1, 2);
268*795d594fSAndroid Build Coastguard Worker     // 3 store, 4 freezes.
269*795d594fSAndroid Build Coastguard Worker 
270*795d594fSAndroid Build Coastguard Worker     // Stores to 'b' do not escape b.
271*795d594fSAndroid Build Coastguard Worker     b.w0 = 3;
272*795d594fSAndroid Build Coastguard Worker 
273*795d594fSAndroid Build Coastguard Worker     Base b2 = new ThreeFinal(4, 5, 6);
274*795d594fSAndroid Build Coastguard Worker     // 3 store, 4 freezes.
275*795d594fSAndroid Build Coastguard Worker 
276*795d594fSAndroid Build Coastguard Worker     // Stores to 'b2' do not escape b2.
277*795d594fSAndroid Build Coastguard Worker     b2.w0 = 7;
278*795d594fSAndroid Build Coastguard Worker 
279*795d594fSAndroid Build Coastguard Worker     // Publish the result to a global so that it is not LSE-eliminated.
280*795d594fSAndroid Build Coastguard Worker     // Publishing is done at the end to give freezes above a chance to merge.
281*795d594fSAndroid Build Coastguard Worker     external = b;
282*795d594fSAndroid Build Coastguard Worker     external2 = b2;
283*795d594fSAndroid Build Coastguard Worker   }
284*795d594fSAndroid Build Coastguard Worker 
285*795d594fSAndroid Build Coastguard Worker   @Override
check()286*795d594fSAndroid Build Coastguard Worker   public void check() {
287*795d594fSAndroid Build Coastguard Worker     Assert.stringEquals("ThreeFinal(w0: 3, w1: 0, w2: 0, w3: 0, x: 1, y: 1, z: 2)", external);
288*795d594fSAndroid Build Coastguard Worker     Assert.stringEquals("ThreeFinal(w0: 7, w1: 0, w2: 0, w3: 0, x: 4, y: 5, z: 6)", external2);
289*795d594fSAndroid Build Coastguard Worker   }
290*795d594fSAndroid Build Coastguard Worker }
291*795d594fSAndroid Build Coastguard Worker 
292*795d594fSAndroid Build Coastguard Worker class TestNonEscaping {
293*795d594fSAndroid Build Coastguard Worker   // Prevent constant folding.
294*795d594fSAndroid Build Coastguard Worker   static boolean test;
295*795d594fSAndroid Build Coastguard Worker 
296*795d594fSAndroid Build Coastguard Worker   static Object external;
297*795d594fSAndroid Build Coastguard Worker   static Object external2;
298*795d594fSAndroid Build Coastguard Worker   static Object external3;
299*795d594fSAndroid Build Coastguard Worker   static Object external4;
300*795d594fSAndroid Build Coastguard Worker 
301*795d594fSAndroid Build Coastguard Worker   static class Invoke implements Test {
302*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestNonEscaping$Invoke.exercise() constructor_fence_redundancy_elimination (before)
303*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance:l\d+>>     NewInstance
304*795d594fSAndroid Build Coastguard Worker     /// CHECK:                          ConstructorFence [<<NewInstance>>]
305*795d594fSAndroid Build Coastguard Worker     /// CHECK:                          InvokeStaticOrDirect
306*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance2:l\d+>>    NewInstance
307*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
308*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                      ConstructorFence
309*795d594fSAndroid Build Coastguard Worker 
310*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestNonEscaping$Invoke.exercise() constructor_fence_redundancy_elimination (after)
311*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance:l\d+>>     NewInstance
312*795d594fSAndroid Build Coastguard Worker     /// CHECK:                          InvokeStaticOrDirect
313*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance2:l\d+>>    NewInstance
314*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>,<<NewInstance>>]
315*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                      ConstructorFence
316*795d594fSAndroid Build Coastguard Worker     @Override
exercise()317*795d594fSAndroid Build Coastguard Worker     public void exercise() {
318*795d594fSAndroid Build Coastguard Worker       Base b = new Base();
319*795d594fSAndroid Build Coastguard Worker 
320*795d594fSAndroid Build Coastguard Worker       // b cannot possibly escape into this invoke because it hasn't escaped onto the heap earlier,
321*795d594fSAndroid Build Coastguard Worker       // and the invoke doesn't take it as a parameter.
322*795d594fSAndroid Build Coastguard Worker       noEscape$noinline$();
323*795d594fSAndroid Build Coastguard Worker 
324*795d594fSAndroid Build Coastguard Worker       // Remove the Constructor Fence for b, merging into the fence for b2.
325*795d594fSAndroid Build Coastguard Worker       Base b2 = new Base();
326*795d594fSAndroid Build Coastguard Worker 
327*795d594fSAndroid Build Coastguard Worker       // Do not LSE-eliminate b,b2
328*795d594fSAndroid Build Coastguard Worker       external = b;
329*795d594fSAndroid Build Coastguard Worker       external2 = b2;
330*795d594fSAndroid Build Coastguard Worker     }
331*795d594fSAndroid Build Coastguard Worker 
332*795d594fSAndroid Build Coastguard Worker     @Override
check()333*795d594fSAndroid Build Coastguard Worker     public void check() {
334*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external);
335*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external2);
336*795d594fSAndroid Build Coastguard Worker     }
337*795d594fSAndroid Build Coastguard Worker   }
338*795d594fSAndroid Build Coastguard Worker 
339*795d594fSAndroid Build Coastguard Worker   public static int[] array = new int[1];
340*795d594fSAndroid Build Coastguard Worker   static Base base = new Base();
341*795d594fSAndroid Build Coastguard Worker 
342*795d594fSAndroid Build Coastguard Worker   static class Store implements Test {
343*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestNonEscaping$Store.exercise() constructor_fence_redundancy_elimination (before)
344*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance:l\d+>>     NewInstance
345*795d594fSAndroid Build Coastguard Worker     /// CHECK:                          ConstructorFence [<<NewInstance>>]
346*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      ArraySet
347*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      StaticFieldSet
348*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      InstanceFieldSet
349*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance2:l\d+>>    NewInstance
350*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
351*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                      ConstructorFence
352*795d594fSAndroid Build Coastguard Worker 
353*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestNonEscaping$Store.exercise() constructor_fence_redundancy_elimination (after)
354*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG: <<NewInstance:l\d+>>   NewInstance
355*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG: <<NewInstance2:l\d+>>  NewInstance
356*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                        ConstructorFence [<<NewInstance2>>,<<NewInstance>>]
357*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                        ConstructorFence
358*795d594fSAndroid Build Coastguard Worker     @Override
exercise()359*795d594fSAndroid Build Coastguard Worker     public void exercise() {
360*795d594fSAndroid Build Coastguard Worker       Base b = new Base();
361*795d594fSAndroid Build Coastguard Worker 
362*795d594fSAndroid Build Coastguard Worker       // Stores of inputs other than the fence target do not publish 'b'.
363*795d594fSAndroid Build Coastguard Worker       array[0] = b.w0;  // aput
364*795d594fSAndroid Build Coastguard Worker       external = array; // sput
365*795d594fSAndroid Build Coastguard Worker       base.w0 = b.w0;   // iput
366*795d594fSAndroid Build Coastguard Worker 
367*795d594fSAndroid Build Coastguard Worker       // Remove the Constructor Fence for b, merging into the fence for b2.
368*795d594fSAndroid Build Coastguard Worker       Base b2 = new Base();
369*795d594fSAndroid Build Coastguard Worker 
370*795d594fSAndroid Build Coastguard Worker       // Do not LSE-eliminate b,b2
371*795d594fSAndroid Build Coastguard Worker       external3 = b;
372*795d594fSAndroid Build Coastguard Worker       external4 = b2;
373*795d594fSAndroid Build Coastguard Worker     }
374*795d594fSAndroid Build Coastguard Worker 
375*795d594fSAndroid Build Coastguard Worker     @Override
check()376*795d594fSAndroid Build Coastguard Worker     public void check() {
377*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("[0]", array);
378*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("[0]", external);
379*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", base);
380*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external3);
381*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external4);
382*795d594fSAndroid Build Coastguard Worker     }
383*795d594fSAndroid Build Coastguard Worker   }
384*795d594fSAndroid Build Coastguard Worker 
noEscape$noinline$()385*795d594fSAndroid Build Coastguard Worker   private static void noEscape$noinline$() {
386*795d594fSAndroid Build Coastguard Worker   }
387*795d594fSAndroid Build Coastguard Worker }
388*795d594fSAndroid Build Coastguard Worker 
389*795d594fSAndroid Build Coastguard Worker class TestDontOptimizeAcrossBlocks implements Test {
390*795d594fSAndroid Build Coastguard Worker   // Prevent constant folding.
391*795d594fSAndroid Build Coastguard Worker   static boolean test;
392*795d594fSAndroid Build Coastguard Worker 
393*795d594fSAndroid Build Coastguard Worker   static Object external;
394*795d594fSAndroid Build Coastguard Worker   static Object external3;
395*795d594fSAndroid Build Coastguard Worker 
396*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void TestDontOptimizeAcrossBlocks.exercise() constructor_fence_redundancy_elimination (before)
397*795d594fSAndroid Build Coastguard Worker   /// CHECK: <<NewInstance:l\d+>>     NewInstance
398*795d594fSAndroid Build Coastguard Worker   /// CHECK:                          ConstructorFence [<<NewInstance>>]
399*795d594fSAndroid Build Coastguard Worker   /// CHECK: <<NewInstance2:l\d+>>    NewInstance
400*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
401*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                      ConstructorFence
402*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
403*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      StaticFieldSet [<<External2:l\d+>>,<<NewInstance2>>]
404*795d594fSAndroid Build Coastguard Worker 
405*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void TestDontOptimizeAcrossBlocks.exercise() constructor_fence_redundancy_elimination (after)
406*795d594fSAndroid Build Coastguard Worker   /// CHECK: <<NewInstance:l\d+>>     NewInstance
407*795d594fSAndroid Build Coastguard Worker   /// CHECK:                          ConstructorFence [<<NewInstance>>]
408*795d594fSAndroid Build Coastguard Worker   /// CHECK: <<NewInstance2:l\d+>>    NewInstance
409*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
410*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                      ConstructorFence
411*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
412*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                      StaticFieldSet [<<External2:l\d+>>,<<NewInstance2>>]
413*795d594fSAndroid Build Coastguard Worker   @Override
exercise()414*795d594fSAndroid Build Coastguard Worker   public void exercise() {
415*795d594fSAndroid Build Coastguard Worker     Base b = new Base();
416*795d594fSAndroid Build Coastguard Worker 
417*795d594fSAndroid Build Coastguard Worker     // Do not move constructor fence across this block, even though 'b' is not published yet.
418*795d594fSAndroid Build Coastguard Worker     if (test) {
419*795d594fSAndroid Build Coastguard Worker       external = null;
420*795d594fSAndroid Build Coastguard Worker     }
421*795d594fSAndroid Build Coastguard Worker 
422*795d594fSAndroid Build Coastguard Worker     Base b2 = new Base();
423*795d594fSAndroid Build Coastguard Worker     external = b2;
424*795d594fSAndroid Build Coastguard Worker     external3 = b;
425*795d594fSAndroid Build Coastguard Worker   }
426*795d594fSAndroid Build Coastguard Worker 
427*795d594fSAndroid Build Coastguard Worker   @Override
check()428*795d594fSAndroid Build Coastguard Worker   public void check() {
429*795d594fSAndroid Build Coastguard Worker     Assert.stringEquals("false", test);
430*795d594fSAndroid Build Coastguard Worker     Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external);
431*795d594fSAndroid Build Coastguard Worker     Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external3);
432*795d594fSAndroid Build Coastguard Worker   }
433*795d594fSAndroid Build Coastguard Worker }
434*795d594fSAndroid Build Coastguard Worker 
435*795d594fSAndroid Build Coastguard Worker class TestDontOptimizeAcrossEscape {
436*795d594fSAndroid Build Coastguard Worker   // Prevent constant folding.
437*795d594fSAndroid Build Coastguard Worker   static boolean test;
438*795d594fSAndroid Build Coastguard Worker 
439*795d594fSAndroid Build Coastguard Worker   static Object external;
440*795d594fSAndroid Build Coastguard Worker   static Object external2;
441*795d594fSAndroid Build Coastguard Worker   static Object external3;
442*795d594fSAndroid Build Coastguard Worker   static Object external4;
443*795d594fSAndroid Build Coastguard Worker 
444*795d594fSAndroid Build Coastguard Worker   static class Invoke implements Test {
445*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestDontOptimizeAcrossEscape$Invoke.exercise() constructor_fence_redundancy_elimination (before)
446*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance:l\d+>>     NewInstance
447*795d594fSAndroid Build Coastguard Worker     /// CHECK:                          ConstructorFence [<<NewInstance>>]
448*795d594fSAndroid Build Coastguard Worker     /// CHECK:                          InvokeStaticOrDirect
449*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance2:l\d+>>    NewInstance
450*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
451*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                      ConstructorFence
452*795d594fSAndroid Build Coastguard Worker 
453*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestDontOptimizeAcrossEscape$Invoke.exercise() constructor_fence_redundancy_elimination (after)
454*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance:l\d+>>     NewInstance
455*795d594fSAndroid Build Coastguard Worker     /// CHECK:                          ConstructorFence [<<NewInstance>>]
456*795d594fSAndroid Build Coastguard Worker     /// CHECK:                          InvokeStaticOrDirect
457*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance2:l\d+>>    NewInstance
458*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
459*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                      ConstructorFence
460*795d594fSAndroid Build Coastguard Worker     @Override
exercise()461*795d594fSAndroid Build Coastguard Worker     public void exercise() {
462*795d594fSAndroid Build Coastguard Worker       Base b = new Base();
463*795d594fSAndroid Build Coastguard Worker       // Do not optimize across invokes into which the fence target escapes.
464*795d594fSAndroid Build Coastguard Worker       invoke$noinline$(b);
465*795d594fSAndroid Build Coastguard Worker 
466*795d594fSAndroid Build Coastguard Worker       Base b2 = new Base();
467*795d594fSAndroid Build Coastguard Worker 
468*795d594fSAndroid Build Coastguard Worker       // Do not LSE-eliminate b,b2
469*795d594fSAndroid Build Coastguard Worker       external = b;
470*795d594fSAndroid Build Coastguard Worker       external2 = b2;
471*795d594fSAndroid Build Coastguard Worker     }
472*795d594fSAndroid Build Coastguard Worker 
invoke$noinline$(Object b)473*795d594fSAndroid Build Coastguard Worker     private static void invoke$noinline$(Object b) {
474*795d594fSAndroid Build Coastguard Worker       // Even though 'b' does not escape this method, we conservatively assume all parameters
475*795d594fSAndroid Build Coastguard Worker       // of an invoke escape.
476*795d594fSAndroid Build Coastguard Worker     }
477*795d594fSAndroid Build Coastguard Worker 
478*795d594fSAndroid Build Coastguard Worker     @Override
check()479*795d594fSAndroid Build Coastguard Worker     public void check() {
480*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external);
481*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external2);
482*795d594fSAndroid Build Coastguard Worker     }
483*795d594fSAndroid Build Coastguard Worker   }
484*795d594fSAndroid Build Coastguard Worker 
485*795d594fSAndroid Build Coastguard Worker   public static Object[] array = new Object[3];
486*795d594fSAndroid Build Coastguard Worker   static Base base = new Base();
487*795d594fSAndroid Build Coastguard Worker 
488*795d594fSAndroid Build Coastguard Worker   static class InstanceEscaper {
489*795d594fSAndroid Build Coastguard Worker     public Object holder;
490*795d594fSAndroid Build Coastguard Worker 
491*795d594fSAndroid Build Coastguard Worker     @Override
toString()492*795d594fSAndroid Build Coastguard Worker     public String toString() {
493*795d594fSAndroid Build Coastguard Worker       return getClass().getName() + "(" + baseString() + ")";
494*795d594fSAndroid Build Coastguard Worker     }
495*795d594fSAndroid Build Coastguard Worker 
baseString()496*795d594fSAndroid Build Coastguard Worker     protected String baseString() {
497*795d594fSAndroid Build Coastguard Worker       return String.format("holder: %s", Main.valueToString(holder));
498*795d594fSAndroid Build Coastguard Worker     }
499*795d594fSAndroid Build Coastguard Worker   }
500*795d594fSAndroid Build Coastguard Worker 
501*795d594fSAndroid Build Coastguard Worker   static InstanceEscaper instanceEscaper = new InstanceEscaper();
502*795d594fSAndroid Build Coastguard Worker 
503*795d594fSAndroid Build Coastguard Worker   static class StoreIput implements Test {
504*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestDontOptimizeAcrossEscape$StoreIput.exercise() constructor_fence_redundancy_elimination (before)
505*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance:l\d+>>     NewInstance
506*795d594fSAndroid Build Coastguard Worker     /// CHECK:                          ConstructorFence [<<NewInstance>>]
507*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      InstanceFieldSet
508*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance2:l\d+>>    NewInstance
509*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
510*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                      ConstructorFence
511*795d594fSAndroid Build Coastguard Worker 
512*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestDontOptimizeAcrossEscape$StoreIput.exercise() constructor_fence_redundancy_elimination (after)
513*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG: <<NewInstance:l\d+>>   NewInstance
514*795d594fSAndroid Build Coastguard Worker     /// CHECK:                            ConstructorFence [<<NewInstance>>]
515*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG: <<NewInstance2:l\d+>>  NewInstance
516*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                        ConstructorFence [<<NewInstance2>>]
517*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                        ConstructorFence
518*795d594fSAndroid Build Coastguard Worker     @Override
exercise()519*795d594fSAndroid Build Coastguard Worker     public void exercise() {
520*795d594fSAndroid Build Coastguard Worker       Base b = new Base();
521*795d594fSAndroid Build Coastguard Worker 
522*795d594fSAndroid Build Coastguard Worker       // A store of 'b' into another instance will publish 'b'.
523*795d594fSAndroid Build Coastguard Worker       instanceEscaper.holder = b;
524*795d594fSAndroid Build Coastguard Worker 
525*795d594fSAndroid Build Coastguard Worker       // Do not remove any constructor fences above.
526*795d594fSAndroid Build Coastguard Worker       Base b2 = new Base();
527*795d594fSAndroid Build Coastguard Worker 
528*795d594fSAndroid Build Coastguard Worker       // Do not LSE-eliminate b,b2
529*795d594fSAndroid Build Coastguard Worker       external3 = b;
530*795d594fSAndroid Build Coastguard Worker       external4 = b2;
531*795d594fSAndroid Build Coastguard Worker     }
532*795d594fSAndroid Build Coastguard Worker 
533*795d594fSAndroid Build Coastguard Worker     @Override
check()534*795d594fSAndroid Build Coastguard Worker     public void check() {
535*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals(
536*795d594fSAndroid Build Coastguard Worker           "TestDontOptimizeAcrossEscape$InstanceEscaper(holder: Base(w0: 0, w1: 0, w2: 0, w3: 0))",
537*795d594fSAndroid Build Coastguard Worker           instanceEscaper);
538*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external3);
539*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external4);
540*795d594fSAndroid Build Coastguard Worker     }
541*795d594fSAndroid Build Coastguard Worker   }
542*795d594fSAndroid Build Coastguard Worker 
543*795d594fSAndroid Build Coastguard Worker   static class StoreAput implements Test {
544*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestDontOptimizeAcrossEscape$StoreAput.exercise() constructor_fence_redundancy_elimination (before)
545*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance:l\d+>>     NewInstance
546*795d594fSAndroid Build Coastguard Worker     /// CHECK:                          ConstructorFence [<<NewInstance>>]
547*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      ArraySet
548*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance2:l\d+>>    NewInstance
549*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
550*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                      ConstructorFence
551*795d594fSAndroid Build Coastguard Worker 
552*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestDontOptimizeAcrossEscape$StoreAput.exercise() constructor_fence_redundancy_elimination (after)
553*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG: <<NewInstance:l\d+>>   NewInstance
554*795d594fSAndroid Build Coastguard Worker     /// CHECK:                            ConstructorFence [<<NewInstance>>]
555*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG: <<NewInstance2:l\d+>>  NewInstance
556*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                        ConstructorFence [<<NewInstance2>>]
557*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                        ConstructorFence
558*795d594fSAndroid Build Coastguard Worker     @Override
exercise()559*795d594fSAndroid Build Coastguard Worker     public void exercise() {
560*795d594fSAndroid Build Coastguard Worker       Base b = new Base();
561*795d594fSAndroid Build Coastguard Worker 
562*795d594fSAndroid Build Coastguard Worker       // A store of 'b' into another array will publish 'b'.
563*795d594fSAndroid Build Coastguard Worker       array[0] = b;  // aput
564*795d594fSAndroid Build Coastguard Worker 
565*795d594fSAndroid Build Coastguard Worker       // Do not remove any constructor fences above.
566*795d594fSAndroid Build Coastguard Worker       Base b2 = new Base();
567*795d594fSAndroid Build Coastguard Worker 
568*795d594fSAndroid Build Coastguard Worker       // Do not LSE-eliminate b,b2
569*795d594fSAndroid Build Coastguard Worker       external3 = b;
570*795d594fSAndroid Build Coastguard Worker       external4 = b2;
571*795d594fSAndroid Build Coastguard Worker     }
572*795d594fSAndroid Build Coastguard Worker 
573*795d594fSAndroid Build Coastguard Worker     @Override
check()574*795d594fSAndroid Build Coastguard Worker     public void check() {
575*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("[Base(w0: 0, w1: 0, w2: 0, w3: 0),<null>,<null>]", array);
576*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external3);
577*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external4);
578*795d594fSAndroid Build Coastguard Worker     }
579*795d594fSAndroid Build Coastguard Worker   }
580*795d594fSAndroid Build Coastguard Worker 
581*795d594fSAndroid Build Coastguard Worker   static class StoreSput implements Test {
582*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestDontOptimizeAcrossEscape$StoreSput.exercise() constructor_fence_redundancy_elimination (before)
583*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance:l\d+>>     NewInstance
584*795d594fSAndroid Build Coastguard Worker     /// CHECK:                          ConstructorFence [<<NewInstance>>]
585*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      StaticFieldSet
586*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance2:l\d+>>    NewInstance
587*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
588*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                      ConstructorFence
589*795d594fSAndroid Build Coastguard Worker 
590*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestDontOptimizeAcrossEscape$StoreSput.exercise() constructor_fence_redundancy_elimination (after)
591*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG: <<NewInstance:l\d+>>   NewInstance
592*795d594fSAndroid Build Coastguard Worker     /// CHECK:                            ConstructorFence [<<NewInstance>>]
593*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG: <<NewInstance2:l\d+>>  NewInstance
594*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                        ConstructorFence [<<NewInstance2>>]
595*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                        ConstructorFence
596*795d594fSAndroid Build Coastguard Worker     @Override
exercise()597*795d594fSAndroid Build Coastguard Worker     public void exercise() {
598*795d594fSAndroid Build Coastguard Worker       Base b = new Base();
599*795d594fSAndroid Build Coastguard Worker 
600*795d594fSAndroid Build Coastguard Worker       // A store of 'b' into a static will publish 'b'.
601*795d594fSAndroid Build Coastguard Worker       external = b;
602*795d594fSAndroid Build Coastguard Worker 
603*795d594fSAndroid Build Coastguard Worker       // Do not remove any constructor fences above.
604*795d594fSAndroid Build Coastguard Worker       Base b2 = new Base();
605*795d594fSAndroid Build Coastguard Worker 
606*795d594fSAndroid Build Coastguard Worker       // Do not LSE-eliminate b,b2
607*795d594fSAndroid Build Coastguard Worker       external3 = b;
608*795d594fSAndroid Build Coastguard Worker       external4 = b2;
609*795d594fSAndroid Build Coastguard Worker     }
610*795d594fSAndroid Build Coastguard Worker 
611*795d594fSAndroid Build Coastguard Worker     @Override
check()612*795d594fSAndroid Build Coastguard Worker     public void check() {
613*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external);
614*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external3);
615*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external4);
616*795d594fSAndroid Build Coastguard Worker     }
617*795d594fSAndroid Build Coastguard Worker   }
618*795d594fSAndroid Build Coastguard Worker 
619*795d594fSAndroid Build Coastguard Worker   static class Deopt implements Test {
620*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestDontOptimizeAcrossEscape$Deopt.exercise() constructor_fence_redundancy_elimination (before)
621*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance:l\d+>>     NewInstance
622*795d594fSAndroid Build Coastguard Worker     /// CHECK:                          ConstructorFence [<<NewInstance>>]
623*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      Deoptimize
624*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance2:l\d+>>    NewInstance
625*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
626*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                      ConstructorFence
627*795d594fSAndroid Build Coastguard Worker 
628*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestDontOptimizeAcrossEscape$Deopt.exercise() constructor_fence_redundancy_elimination (after)
629*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG: <<NewInstance:l\d+>>   NewInstance
630*795d594fSAndroid Build Coastguard Worker     /// CHECK:                            ConstructorFence [<<NewInstance>>]
631*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG: <<NewInstance2:l\d+>>  NewInstance
632*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                        ConstructorFence [<<NewInstance2>>]
633*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                        ConstructorFence
634*795d594fSAndroid Build Coastguard Worker     @Override
exercise()635*795d594fSAndroid Build Coastguard Worker     public void exercise() {
636*795d594fSAndroid Build Coastguard Worker       Base b = new Base();
637*795d594fSAndroid Build Coastguard Worker 
638*795d594fSAndroid Build Coastguard Worker       // An array access generates a Deopt to avoid doing bounds check.
639*795d594fSAndroid Build Coastguard Worker       array[0] = external;  // aput
640*795d594fSAndroid Build Coastguard Worker       array[1] = external;  // aput
641*795d594fSAndroid Build Coastguard Worker       array[2] = external;  // aput
642*795d594fSAndroid Build Coastguard Worker 
643*795d594fSAndroid Build Coastguard Worker       // Do not remove any constructor fences above.
644*795d594fSAndroid Build Coastguard Worker       Base b2 = new Base();
645*795d594fSAndroid Build Coastguard Worker 
646*795d594fSAndroid Build Coastguard Worker       // Do not LSE-eliminate b,b2
647*795d594fSAndroid Build Coastguard Worker       external3 = b;
648*795d594fSAndroid Build Coastguard Worker       external4 = b2;
649*795d594fSAndroid Build Coastguard Worker     }
650*795d594fSAndroid Build Coastguard Worker 
651*795d594fSAndroid Build Coastguard Worker     @Override
check()652*795d594fSAndroid Build Coastguard Worker     public void check() {
653*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("[Base(w0: 0, w1: 0, w2: 0, w3: 0),"
654*795d594fSAndroid Build Coastguard Worker               + "Base(w0: 0, w1: 0, w2: 0, w3: 0),"
655*795d594fSAndroid Build Coastguard Worker               + "Base(w0: 0, w1: 0, w2: 0, w3: 0)]",
656*795d594fSAndroid Build Coastguard Worker           array);
657*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external3);
658*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external4);
659*795d594fSAndroid Build Coastguard Worker     }
660*795d594fSAndroid Build Coastguard Worker   }
661*795d594fSAndroid Build Coastguard Worker 
662*795d594fSAndroid Build Coastguard Worker   static class Select implements Test {
663*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestDontOptimizeAcrossEscape$Select.exercise() constructor_fence_redundancy_elimination (before)
664*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance:l\d+>>     NewInstance
665*795d594fSAndroid Build Coastguard Worker     /// CHECK:                          ConstructorFence [<<NewInstance>>]
666*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      Select
667*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<NewInstance2:l\d+>>    NewInstance
668*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
669*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                      ConstructorFence
670*795d594fSAndroid Build Coastguard Worker 
671*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestDontOptimizeAcrossEscape$Select.exercise() constructor_fence_redundancy_elimination (after)
672*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG: <<NewInstance:l\d+>>   NewInstance
673*795d594fSAndroid Build Coastguard Worker     /// CHECK:                            ConstructorFence [<<NewInstance>>]
674*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG: <<NewInstance2:l\d+>>  NewInstance
675*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                        ConstructorFence [<<NewInstance2>>]
676*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                        ConstructorFence
677*795d594fSAndroid Build Coastguard Worker     @Override
exercise()678*795d594fSAndroid Build Coastguard Worker     public void exercise() {
679*795d594fSAndroid Build Coastguard Worker       Base b = new Base();
680*795d594fSAndroid Build Coastguard Worker 
681*795d594fSAndroid Build Coastguard Worker       boolean localTest = test;
682*795d594fSAndroid Build Coastguard Worker       Object localExternal = external3;
683*795d594fSAndroid Build Coastguard Worker 
684*795d594fSAndroid Build Coastguard Worker       // Selecting 'b' creates an alias, which we conservatively assume escapes immediately.
685*795d594fSAndroid Build Coastguard Worker       external = localTest ? b : localExternal;
686*795d594fSAndroid Build Coastguard Worker 
687*795d594fSAndroid Build Coastguard Worker       // Do not remove any constructor fences above.
688*795d594fSAndroid Build Coastguard Worker       Base b2 = new Base();
689*795d594fSAndroid Build Coastguard Worker 
690*795d594fSAndroid Build Coastguard Worker       // Do not LSE-eliminate b,b2
691*795d594fSAndroid Build Coastguard Worker       external3 = b;
692*795d594fSAndroid Build Coastguard Worker       external4 = b2;
693*795d594fSAndroid Build Coastguard Worker     }
694*795d594fSAndroid Build Coastguard Worker 
695*795d594fSAndroid Build Coastguard Worker     @Override
check()696*795d594fSAndroid Build Coastguard Worker     public void check() {
697*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external);
698*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external3);
699*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external4);
700*795d594fSAndroid Build Coastguard Worker     }
701*795d594fSAndroid Build Coastguard Worker   }
702*795d594fSAndroid Build Coastguard Worker 
703*795d594fSAndroid Build Coastguard Worker   static class MakeBoundTypeTest implements Test {
704*795d594fSAndroid Build Coastguard Worker     public static Object makeBoundType;
705*795d594fSAndroid Build Coastguard Worker     public static Object makeBoundTypeSub;
706*795d594fSAndroid Build Coastguard Worker 
707*795d594fSAndroid Build Coastguard Worker     @Override
exercise()708*795d594fSAndroid Build Coastguard Worker     public void exercise() {
709*795d594fSAndroid Build Coastguard Worker       // Note: MakeBoundType is special and we have to call the constructor directly
710*795d594fSAndroid Build Coastguard Worker       // to prevent inlining it.
711*795d594fSAndroid Build Coastguard Worker       try {
712*795d594fSAndroid Build Coastguard Worker         makeBoundType = exerciseNewInstance(MakeBoundType.class, 123);
713*795d594fSAndroid Build Coastguard Worker         makeBoundTypeSub = exerciseNewInstance(MakeBoundTypeSub.class, 123);
714*795d594fSAndroid Build Coastguard Worker       } catch (Exception e) {
715*795d594fSAndroid Build Coastguard Worker         throw new RuntimeException(e);
716*795d594fSAndroid Build Coastguard Worker       }
717*795d594fSAndroid Build Coastguard Worker     }
718*795d594fSAndroid Build Coastguard Worker 
719*795d594fSAndroid Build Coastguard Worker     @Override
check()720*795d594fSAndroid Build Coastguard Worker     public void check() {
721*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals(
722*795d594fSAndroid Build Coastguard Worker           "TestDontOptimizeAcrossEscape$MakeBoundTypeTest$MakeBoundType(abcdefgh: 123, x: 2)",
723*795d594fSAndroid Build Coastguard Worker           makeBoundType);
724*795d594fSAndroid Build Coastguard Worker       Assert.stringEquals(
725*795d594fSAndroid Build Coastguard Worker           "TestDontOptimizeAcrossEscape$MakeBoundTypeTest$MakeBoundTypeSub(abcdefgh: 123, x: 1)",
726*795d594fSAndroid Build Coastguard Worker           makeBoundTypeSub);
727*795d594fSAndroid Build Coastguard Worker     }
728*795d594fSAndroid Build Coastguard Worker 
729*795d594fSAndroid Build Coastguard Worker     // Make a new instance of 'klass'.
exerciseNewInstance(Class<T> klass, int params)730*795d594fSAndroid Build Coastguard Worker     private static <T> T exerciseNewInstance(Class<T> klass, int params) throws Exception {
731*795d594fSAndroid Build Coastguard Worker       return klass.cast(klass.getDeclaredConstructor(int.class).newInstance(params));
732*795d594fSAndroid Build Coastguard Worker     }
733*795d594fSAndroid Build Coastguard Worker 
734*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestDontOptimizeAcrossEscape$MakeBoundTypeTest$MakeBoundType.<init>(int) constructor_fence_redundancy_elimination (before)
735*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG: <<This:l\d+>>         ParameterValue
736*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG: <<NewInstance:l\d+>>  NewInstance
737*795d594fSAndroid Build Coastguard Worker     /// CHECK:                           ConstructorFence [<<NewInstance>>]
738*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                       BoundType
739*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                       ConstructorFence [<<This>>]
740*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                       ConstructorFence
741*795d594fSAndroid Build Coastguard Worker 
742*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: void TestDontOptimizeAcrossEscape$MakeBoundTypeTest$MakeBoundType.<init>(int) constructor_fence_redundancy_elimination (after)
743*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG: <<This:l\d+>>         ParameterValue
744*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG: <<NewInstance:l\d+>>  NewInstance
745*795d594fSAndroid Build Coastguard Worker     /// CHECK:                           ConstructorFence [<<NewInstance>>]
746*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                       BoundType
747*795d594fSAndroid Build Coastguard Worker     /// CHECK-DAG:                       ConstructorFence [<<This>>]
748*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT:                       ConstructorFence
749*795d594fSAndroid Build Coastguard Worker     static class MakeBoundType {
750*795d594fSAndroid Build Coastguard Worker       final int abcdefgh;
751*795d594fSAndroid Build Coastguard Worker       int x;
752*795d594fSAndroid Build Coastguard Worker 
MakeBoundType(int param)753*795d594fSAndroid Build Coastguard Worker       MakeBoundType(int param) {
754*795d594fSAndroid Build Coastguard Worker         abcdefgh = param;
755*795d594fSAndroid Build Coastguard Worker 
756*795d594fSAndroid Build Coastguard Worker         Base b = new Base();
757*795d594fSAndroid Build Coastguard Worker         // constructor-fence(b)
758*795d594fSAndroid Build Coastguard Worker 
759*795d594fSAndroid Build Coastguard Worker         if (this instanceof MakeBoundTypeSub) {
760*795d594fSAndroid Build Coastguard Worker           // Create a "BoundType(this)" which prevents
761*795d594fSAndroid Build Coastguard Worker           // a merged constructor-fence(this, b)
762*795d594fSAndroid Build Coastguard Worker           x = 1;
763*795d594fSAndroid Build Coastguard Worker         } else {
764*795d594fSAndroid Build Coastguard Worker           x = 2;
765*795d594fSAndroid Build Coastguard Worker         }
766*795d594fSAndroid Build Coastguard Worker 
767*795d594fSAndroid Build Coastguard Worker         // publish(b).
768*795d594fSAndroid Build Coastguard Worker         external = b;
769*795d594fSAndroid Build Coastguard Worker 
770*795d594fSAndroid Build Coastguard Worker         // constructor-fence(this)
771*795d594fSAndroid Build Coastguard Worker       }
772*795d594fSAndroid Build Coastguard Worker 
773*795d594fSAndroid Build Coastguard Worker       @Override
toString()774*795d594fSAndroid Build Coastguard Worker       public String toString() {
775*795d594fSAndroid Build Coastguard Worker         return getClass().getName() + "(" + baseString() + ")";
776*795d594fSAndroid Build Coastguard Worker       }
777*795d594fSAndroid Build Coastguard Worker 
baseString()778*795d594fSAndroid Build Coastguard Worker       protected String baseString() {
779*795d594fSAndroid Build Coastguard Worker         return String.format("abcdefgh: %d, x: %d", abcdefgh, x);
780*795d594fSAndroid Build Coastguard Worker       }
781*795d594fSAndroid Build Coastguard Worker     }
782*795d594fSAndroid Build Coastguard Worker 
783*795d594fSAndroid Build Coastguard Worker     static class MakeBoundTypeSub extends MakeBoundType {
MakeBoundTypeSub(int xyz)784*795d594fSAndroid Build Coastguard Worker       MakeBoundTypeSub(int xyz) {
785*795d594fSAndroid Build Coastguard Worker         super(xyz);
786*795d594fSAndroid Build Coastguard Worker       }
787*795d594fSAndroid Build Coastguard Worker     }
788*795d594fSAndroid Build Coastguard Worker   }
789*795d594fSAndroid Build Coastguard Worker }
790*795d594fSAndroid Build Coastguard Worker 
791*795d594fSAndroid Build Coastguard Worker public class Main {
main(String[] args)792*795d594fSAndroid Build Coastguard Worker   public static void main(String[] args) throws Exception {
793*795d594fSAndroid Build Coastguard Worker     // Ensure that all of this code does not get optimized out into a no-op
794*795d594fSAndroid Build Coastguard Worker     // by actually running the code with reflection, then validating
795*795d594fSAndroid Build Coastguard Worker     // the result by asserting it against a string.
796*795d594fSAndroid Build Coastguard Worker     Class<? extends Test>[] testClasses = new Class[] {
797*795d594fSAndroid Build Coastguard Worker       TestOneFinal.class,
798*795d594fSAndroid Build Coastguard Worker       TestThreeFinal.class,
799*795d594fSAndroid Build Coastguard Worker       TestMultiAlloc.class,
800*795d594fSAndroid Build Coastguard Worker       TestThreeFinalTwice.class,
801*795d594fSAndroid Build Coastguard Worker       TestNonEscaping.Invoke.class,
802*795d594fSAndroid Build Coastguard Worker       TestNonEscaping.Store.class,
803*795d594fSAndroid Build Coastguard Worker       TestDontOptimizeAcrossBlocks.class,
804*795d594fSAndroid Build Coastguard Worker       TestDontOptimizeAcrossEscape.Invoke.class,
805*795d594fSAndroid Build Coastguard Worker       TestDontOptimizeAcrossEscape.StoreIput.class,
806*795d594fSAndroid Build Coastguard Worker       TestDontOptimizeAcrossEscape.StoreAput.class,
807*795d594fSAndroid Build Coastguard Worker       TestDontOptimizeAcrossEscape.StoreSput.class,
808*795d594fSAndroid Build Coastguard Worker       TestDontOptimizeAcrossEscape.Deopt.class,
809*795d594fSAndroid Build Coastguard Worker       TestDontOptimizeAcrossEscape.Select.class,
810*795d594fSAndroid Build Coastguard Worker       TestDontOptimizeAcrossEscape.MakeBoundTypeTest.class,
811*795d594fSAndroid Build Coastguard Worker     };
812*795d594fSAndroid Build Coastguard Worker 
813*795d594fSAndroid Build Coastguard Worker     for (Class<? extends Test> klass : testClasses) {
814*795d594fSAndroid Build Coastguard Worker       exerciseTestClass(klass);
815*795d594fSAndroid Build Coastguard Worker     }
816*795d594fSAndroid Build Coastguard Worker   }
817*795d594fSAndroid Build Coastguard Worker 
818*795d594fSAndroid Build Coastguard Worker   /**
819*795d594fSAndroid Build Coastguard Worker    * Invoke Test#exercise(), then Test#check().
820*795d594fSAndroid Build Coastguard Worker    * @throws AssertionError if test fails.
821*795d594fSAndroid Build Coastguard Worker    */
exerciseTestClass(Class<? extends Test> klass)822*795d594fSAndroid Build Coastguard Worker   private static void exerciseTestClass(Class<? extends Test> klass) throws Exception {
823*795d594fSAndroid Build Coastguard Worker     Test instance = klass.cast(klass.getDeclaredConstructor().newInstance());
824*795d594fSAndroid Build Coastguard Worker 
825*795d594fSAndroid Build Coastguard Worker     // Use reflection as a best-effort to avoid compiler optimizations (e.g. inlining).
826*795d594fSAndroid Build Coastguard Worker     instance.getClass().getDeclaredMethod("exercise").invoke(instance);
827*795d594fSAndroid Build Coastguard Worker     instance.getClass().getDeclaredMethod("check").invoke(instance);
828*795d594fSAndroid Build Coastguard Worker   }
829*795d594fSAndroid Build Coastguard Worker 
830*795d594fSAndroid Build Coastguard Worker   // Print an object, with special handling for array and null.
valueToString(Object val)831*795d594fSAndroid Build Coastguard Worker   public static String valueToString(Object val) {
832*795d594fSAndroid Build Coastguard Worker     if (val == null) {
833*795d594fSAndroid Build Coastguard Worker       return "<null>";
834*795d594fSAndroid Build Coastguard Worker     }
835*795d594fSAndroid Build Coastguard Worker     if (val.getClass().isArray()) {
836*795d594fSAndroid Build Coastguard Worker       String fmt = "[";
837*795d594fSAndroid Build Coastguard Worker       int length = Array.getLength(val);
838*795d594fSAndroid Build Coastguard Worker       for (int i = 0; i < length; ++i) {
839*795d594fSAndroid Build Coastguard Worker         Object arrayElement = Array.get(val, i);
840*795d594fSAndroid Build Coastguard Worker         fmt += valueToString(arrayElement);
841*795d594fSAndroid Build Coastguard Worker 
842*795d594fSAndroid Build Coastguard Worker         if (i != length - 1) {
843*795d594fSAndroid Build Coastguard Worker           fmt += ",";
844*795d594fSAndroid Build Coastguard Worker         }
845*795d594fSAndroid Build Coastguard Worker       }
846*795d594fSAndroid Build Coastguard Worker       fmt += "]";
847*795d594fSAndroid Build Coastguard Worker 
848*795d594fSAndroid Build Coastguard Worker       return fmt;
849*795d594fSAndroid Build Coastguard Worker     }
850*795d594fSAndroid Build Coastguard Worker 
851*795d594fSAndroid Build Coastguard Worker     return val.toString();
852*795d594fSAndroid Build Coastguard Worker   }
853*795d594fSAndroid Build Coastguard Worker }
854