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