1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // This base class has a single final field; 18 // the constructor should have one fence. 19 class Circle { Circle(double radius)20 Circle(double radius) { 21 this.radius = radius; 22 } getRadius()23 public double getRadius() { 24 return radius; 25 } getArea()26 public double getArea() { 27 return radius * radius * Math.PI; 28 } 29 getCircumference()30 public double getCircumference() { 31 return 2 * Math.PI * radius; 32 } 33 34 private final double radius; 35 } 36 37 // This subclass adds an extra final field; 38 // there should be an extra constructor fence added 39 // (for a total of 2 after inlining). 40 class Ellipse extends Circle { Ellipse(double vertex, double covertex)41 Ellipse(double vertex, double covertex) { 42 super(vertex); 43 44 this.covertex = covertex; 45 } 46 getVertex()47 public double getVertex() { 48 return getRadius(); 49 } 50 getCovertex()51 public double getCovertex() { 52 return covertex; 53 } 54 55 @Override getArea()56 public double getArea() { 57 return getRadius() * covertex * Math.PI; 58 } 59 60 private final double covertex; 61 } 62 63 class CalcCircleAreaOrCircumference { 64 public static final int TYPE_AREA = 0; 65 public static final int TYPE_CIRCUMFERENCE = 1; 66 67 double value; 68 CalcCircleAreaOrCircumference(int type)69 public CalcCircleAreaOrCircumference(int type) { 70 this.type = type; 71 } 72 73 final int type; 74 } 75 76 public class Main { 77 78 /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (before) 79 /// CHECK: NewInstance 80 /// CHECK: InstanceFieldSet 81 /// CHECK: ConstructorFence 82 /// CHECK: InstanceFieldGet 83 84 /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (after) 85 /// CHECK-NOT: NewInstance 86 /// CHECK-NOT: InstanceFieldSet 87 /// CHECK-NOT: ConstructorFence 88 /// CHECK-NOT: InstanceFieldGet 89 90 // Make sure the constructor fence gets eliminated when the allocation is eliminated. calcCircleArea(double radius)91 static double calcCircleArea(double radius) { 92 return new Circle(radius).getArea(); 93 } 94 95 /// CHECK-START: double Main.calcEllipseArea(double, double) load_store_elimination (before) 96 /// CHECK: NewInstance 97 /// CHECK: InstanceFieldSet 98 /// CHECK: InstanceFieldSet 99 /// CHECK: ConstructorFence 100 /// CHECK: InstanceFieldGet 101 /// CHECK: InstanceFieldGet 102 103 /// CHECK-START: double Main.calcEllipseArea(double, double) load_store_elimination (after) 104 /// CHECK-NOT: NewInstance 105 /// CHECK-NOT: InstanceFieldSet 106 /// CHECK-NOT: ConstructorFence 107 /// CHECK-NOT: InstanceFieldGet 108 109 // Multiple constructor fences can accumulate through inheritance, make sure 110 // they are all eliminated when the allocation is eliminated. calcEllipseArea(double vertex, double covertex)111 static double calcEllipseArea(double vertex, double covertex) { 112 return new Ellipse(vertex, covertex).getArea(); 113 } 114 115 /// CHECK-START: double Main.calcCircleAreaOrCircumference(double, boolean) load_store_elimination (before) 116 /// CHECK: NewInstance 117 /// CHECK: InstanceFieldSet 118 /// CHECK: ConstructorFence 119 /// CHECK: InstanceFieldGet 120 121 /// CHECK-START: double Main.calcCircleAreaOrCircumference(double, boolean) load_store_elimination (after) 122 /// CHECK: NewInstance 123 /// CHECK-NOT: ConstructorFence 124 125 // 126 // The object allocation will not be eliminated by LSE because of aliased stores. 127 // However the object is still a singleton, so it never escapes the current thread. 128 // There should not be a constructor fence here after LSE. calcCircleAreaOrCircumference(double radius, boolean area_or_circumference)129 static double calcCircleAreaOrCircumference(double radius, boolean area_or_circumference) { 130 CalcCircleAreaOrCircumference calc = 131 new CalcCircleAreaOrCircumference( 132 area_or_circumference ? CalcCircleAreaOrCircumference.TYPE_AREA : 133 CalcCircleAreaOrCircumference.TYPE_CIRCUMFERENCE); 134 135 if (area_or_circumference) { 136 // Area 137 calc.value = Math.PI * Math.PI * radius; 138 } else { 139 // Circumference 140 calc.value = 2 * Math.PI * radius; 141 } 142 143 return calc.value; 144 } 145 146 /// CHECK-START: Circle Main.makeCircle(double) load_store_elimination (after) 147 /// CHECK: NewInstance 148 /// CHECK: ConstructorFence 149 150 // The object allocation is considered a singleton by LSE, 151 // but we cannot eliminate the new because it is returned. 152 // 153 // The constructor fence must also not be removed because the object could escape the 154 // current thread (in the caller). makeCircle(double radius)155 static Circle makeCircle(double radius) { 156 return new Circle(radius); 157 } 158 assertIntEquals(int result, int expected)159 static void assertIntEquals(int result, int expected) { 160 if (expected != result) { 161 throw new Error("Expected: " + expected + ", found: " + result); 162 } 163 } 164 assertFloatEquals(float result, float expected)165 static void assertFloatEquals(float result, float expected) { 166 if (expected != result) { 167 throw new Error("Expected: " + expected + ", found: " + result); 168 } 169 } 170 assertDoubleEquals(double result, double expected)171 static void assertDoubleEquals(double result, double expected) { 172 if (expected != result) { 173 throw new Error("Expected: " + expected + ", found: " + result); 174 } 175 } 176 assertInstanceOf(Object result, Class<?> expected)177 static void assertInstanceOf(Object result, Class<?> expected) { 178 if (result.getClass() != expected) { 179 throw new Error("Expected type: " + expected + ", found : " + result.getClass()); 180 } 181 } 182 main(String[] args)183 public static void main(String[] args) { 184 assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcCircleArea(Math.PI)); 185 assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcEllipseArea(Math.PI, Math.PI)); 186 assertDoubleEquals(2 * Math.PI * Math.PI, calcCircleAreaOrCircumference(Math.PI, false)); 187 assertInstanceOf(makeCircle(Math.PI), Circle.class); 188 } 189 190 static boolean sFlag; 191 } 192