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

Brian Goetz brian.goetz at oracle.com
Thu Apr 23 15:24:38 UTC 2020


I don't even have to look at the code.  I know Remi's been itching for a 
puzzler that uses switch expressions as fake block expressions.

Do I win?

On 4/23/2020 8:34 AM, Remi Forax wrote:
> 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