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