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

Jesper Steen Møller jesper at selskabet.org
Thu Apr 23 14:58:55 UTC 2020


I love puzzlers, but I can't solve this one.

I know instanceof Point p will bind p, and perhaps ECJ may perform certain optimizations, but you can't use instanceof on an int...

super(Math.sqrt(circle.center instanceof Point p ? p.x * p.x + p.y * p.y : 0));


-Jesper


> On 23 Apr 2020, at 16.53, Tagir Valeev <amaembo at gmail.com> wrote:
> 
> Wow, Java puzzlers!
> 
> I bet it's
> 
> super(switch(0) {default->{
> ... the rest is simple...}})
> 
> чт, 23 апр. 2020 г., 19:39 Remi Forax <forax at univ-mlv.fr>:
> 
>> 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