Bytecode carving game - how to declare local variables inside a call to super() ?

Remi Forax forax at univ-mlv.fr
Thu Apr 23 12:34:18 UTC 2020


I'm sure you want to play a game,
what about i give you the bytecode, show me the corresponding Java code :)

Let say i have this code:
public interface Fun {
  record Point(int x, int y) { }
  record Circle(Point center, int radius) { }

  class Shape {
    private final double distanceToOrigin;
    
    public Shape(double distanceToOrigin) {
      this.distanceToOrigin = distanceToOrigin;
    }
  }

  class Disc extends Shape {
    public Disc(Circle circle) {
      super(Math.sqrt(circle.center.x * circle.center.x + circle.center.y * circle.center.y));
    }
  }
}

The code in super() has a lot of repetition, circle.center is used 4 times !

The generated bytecode for this example (it is the same using javac or ecj, the eclipse compiler),
shows 4 calls to getfield Fun$Circle.center:LFun$Point;

$ javap -c Fun\$Disc.class 
Compiled from "Fun.java"
public class Fun$Disc extends Fun$Shape {
  public Fun$Disc(Fun$Circle);
    Code:
       0: aload_0
       1: aload_1
       2: getfield      #8                  // Field Fun$Circle.center:LFun$Point;
       5: getfield      #14                 // Field Fun$Point.x:I
       8: aload_1
       9: getfield      #8                  // Field Fun$Circle.center:LFun$Point;
      12: getfield      #14                 // Field Fun$Point.x:I
      15: imul
      16: aload_1
      17: getfield      #8                  // Field Fun$Circle.center:LFun$Point;
      20: getfield      #20                 // Field Fun$Point.y:I
      23: aload_1
      24: getfield      #8                  // Field Fun$Circle.center:LFun$Point;
      27: getfield      #20                 // Field Fun$Point.y:I
      30: imul
      31: iadd
      32: i2d
      33: invokestatic  #23                 // Method java/lang/Math.sqrt:(D)D
      36: invokespecial #29                 // Method Fun$Shape."<init>":(D)V
      39: return
}


Now, refactoring the java source code using the jdk 14, I was able to get ecj to generate this bytecode:

$ javap -c Fun\$Disc.class 
Compiled from "Fun.java"
public class Fun$Disc extends Fun$Shape {
  public Fun$Disc(Fun$Circle);
    Code:
       0: aload_0
       1: aload_1
       2: getfield      #8                  // Field Fun$Circle.center:LFun$Point;
       5: astore_2
       6: aload_2
       7: getfield      #14                 // Field Fun$Point.x:I
      10: istore_3
      11: aload_2
      12: getfield      #20                 // Field Fun$Point.y:I
      15: istore        4
      17: iload_3
      18: iload_3
      19: imul
      20: iload         4
      22: iload         4
      24: imul
      25: iadd
      26: i2d
      27: invokestatic  #23                 // Method java/lang/Math.sqrt:(D)D
      30: invokespecial #29                 // Method Fun$Shape."<init>":(D)V
      33: return
}

as you can see i'm able to declare local variables, the slot 2, 3 and 4, to store center, center.x and center.y, inside the call to super !

How to do declare a local variable inside a call to super (several solutions) ?
What is the Java code corresponding to the bytecode above ?

regards,
Rémi


More information about the amber-dev mailing list