Home | History | Annotate | Download | only in src
      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 {
     20   Circle(double radius) {
     21     this.radius = radius;
     22   }
     23   public double getRadius() {
     24     return radius;
     25   }
     26   public double getArea() {
     27     return radius * radius * Math.PI;
     28   }
     29 
     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 {
     41   Ellipse(double vertex, double covertex) {
     42     super(vertex);
     43 
     44     this.covertex = covertex;
     45   }
     46 
     47   public double getVertex() {
     48     return getRadius();
     49   }
     50 
     51   public double getCovertex() {
     52     return covertex;
     53   }
     54 
     55   @Override
     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 
     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.
     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.
    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.
    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).
    155   static Circle makeCircle(double radius) {
    156     return new Circle(radius);
    157   }
    158 
    159   static void assertIntEquals(int result, int expected) {
    160     if (expected != result) {
    161       throw new Error("Expected: " + expected + ", found: " + result);
    162     }
    163   }
    164 
    165   static void assertFloatEquals(float result, float expected) {
    166     if (expected != result) {
    167       throw new Error("Expected: " + expected + ", found: " + result);
    168     }
    169   }
    170 
    171   static void assertDoubleEquals(double result, double expected) {
    172     if (expected != result) {
    173       throw new Error("Expected: " + expected + ", found: " + result);
    174     }
    175   }
    176 
    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 
    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