Created
March 27, 2017 19:09
-
-
Save Deamon5550/18e2f1a88e89f89e75a19157d9777707 to your computer and use it in GitHub Desktop.
Kotlin Bytecode Issues
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fun main(args: Array<String>) { | |
val x = 10 | |
val y = 9 | |
if(x == 6) { | |
if(y == 6) { | |
println("a") | |
} else { | |
println("b") | |
} | |
} else { | |
println("c") | |
} | |
} | |
/* | |
The goto at the end of the inner if block (instruction 34 in hello.kt.javap) | |
points directly at another goto (insn 47) which is the end of the outer if block. | |
In the equivalent compiled java you can see that the goto at the | |
end of the inner if (insn 26) targets directly the end of the outer else (insn 48). | |
Kotlin: | |
Code: | |
0: aload_0 | |
1: ldc #50 // String args | |
3: invokestatic #29 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V | |
6: bipush 10 | |
8: istore_1 | |
9: bipush 9 | |
11: istore_2 | |
12: iload_1 | |
13: bipush 6 | |
15: if_icmpne 50 | |
18: iload_2 | |
19: bipush 6 | |
21: if_icmpne 37 | |
24: ldc #51 // String a | |
26: astore_3 | |
27: getstatic #57 // Field java/lang/System.out:Ljava/io/PrintStream; | |
30: aload_3 | |
31: invokevirtual #63 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V | |
34: goto 47 | |
37: ldc #64 // String b | |
39: astore_3 | |
40: getstatic #57 // Field java/lang/System.out:Ljava/io/PrintStream; | |
43: aload_3 | |
44: invokevirtual #63 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V | |
47: goto 60 | |
50: ldc #66 // String c | |
52: astore_3 | |
53: getstatic #57 // Field java/lang/System.out:Ljava/io/PrintStream; | |
56: aload_3 | |
57: invokevirtual #63 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V | |
60: return | |
Java: | |
Code: | |
0: bipush 9 | |
2: istore_1 | |
3: bipush 10 | |
5: istore_2 | |
6: iload_1 | |
7: bipush 6 | |
9: if_icmpne 40 | |
12: iload_2 | |
13: bipush 6 | |
15: if_icmpne 29 | |
18: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; | |
21: ldc #3 // String a | |
23: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V | |
26: goto 48 | |
29: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; | |
32: ldc #5 // String b | |
34: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V | |
37: goto 48 | |
40: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; | |
43: ldc #6 // String c | |
45: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V | |
48: return | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fun main(args: Array<String>) { | |
println("Hello World") | |
} | |
/* | |
As you can see in the bytecode below even in this most simple of cases the constant value | |
"Hello World" is assigned first to local 1 (which isn't actually defined in the lvt) and | |
then loaded again to be passed to the method. | |
I'm really not sure what this extra reassignment is, I suspect its an artifact of some other | |
part of their byte code generation that has to do some validate or something before its | |
passed, but I have yet to see any code that actually does anything with the value. | |
Code: | |
0: aload_0 | |
1: ldc #9 // String args | |
3: invokestatic #15 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V | |
6: ldc #17 // String Hello World | |
8: astore_1 | |
9: getstatic #23 // Field java/lang/System.out:Ljava/io/PrintStream; | |
12: aload_1 | |
13: invokevirtual #29 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V | |
16: return | |
LineNumberTable: | |
line 4: 6 | |
line 5: 16 | |
LocalVariableTable: | |
Start Length Slot Name Signature | |
0 17 0 args [Ljava/lang/String; | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fun main(args: Array<String>) { | |
for (x in 1..5) { | |
print(x) | |
} | |
} | |
/* | |
Two issues here first of all theres a redundant condition. The generated code | |
is essentially a do-while in an if when it could just be a standard while loop. | |
The other issue is they're using the local slot 1 (which is the value within | |
the loop) before the lvt actually defines it. It is used in insn 10 below but not | |
defined until insn 15. | |
Code: | |
0: aload_0 | |
1: ldc #9 // String args | |
3: invokestatic #15 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V | |
6: iconst_1 | |
7: istore_1 | |
8: iconst_5 | |
9: istore_2 | |
10: iload_1 | |
11: iload_2 | |
12: if_icmpgt 33 | |
15: getstatic #21 // Field java/lang/System.out:Ljava/io/PrintStream; | |
18: iload_1 | |
19: invokevirtual #27 // Method java/io/PrintStream.print:(I)V | |
22: iload_1 | |
23: iload_2 | |
24: if_icmpeq 33 | |
27: iinc 1, 1 | |
30: goto 15 | |
33: return | |
LineNumberTable: | |
line 4: 6 | |
line 5: 15 | |
line 4: 22 | |
line 7: 33 | |
LocalVariableTable: | |
Start Length Slot Name Signature | |
15 15 1 x I | |
0 34 0 args [Ljava/lang/String; | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment