Kotlin编译器:`nop`s字节码

时间:2020-01-08 17:24:27

标签: kotlin jvm bytecode kotlinc

我正在检查kotlinc个捕获lambda的字节码。并试图了解生成的字节码具有nop指令的原因。

kotlinc -jvm-target 1.6 .

private inline fun lambdaCapturing(f: () -> Int): Int = f()

fun main(args: Array<String>) {
    lambdaCapturing { 42 }
}

结果我得到

public final class x.y.z.LambdaCaptKt {
  private static final int lambdaCapturing(kotlin.jvm.functions.Function0<java.lang.Integer>);
    Code:
       0: ldc           #8                  // int 0
       2: istore_1
       3: aload_0
       4: invokeinterface #14,  1           // InterfaceMethod kotlin/jvm/functions/Function0.invoke:()Ljava/lang/Object;
       9: checkcast     #16                 // class java/lang/Number
      12: invokevirtual #20                 // Method java/lang/Number.intValue:()I
      15: ireturn

  public static final void main(java.lang.String[]);
    Code:
       0: aload_0
       1: ldc           #29                 // String args
       3: invokestatic  #35                 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
       6: iconst_0
       7: istore_1
       8: iconst_0
       9: istore_2
      10: nop
      11: nop
      12: nop
      13: return
}

在主要功能中带有多条nop指令。

如果我将使用-Xno-optimize编译相同的代码段,则main函数将类似于

public static final void main(java.lang.String[]);
    Code:
       0: aload_0
       1: ldc           #29                 // String args
       3: invokestatic  #35                 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
       6: nop
       7: iconst_0
       8: istore_1
       9: nop
      10: iconst_0
      11: istore_2
      12: bipush        10
      14: nop
      15: goto          18
      18: invokestatic  #41                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      21: checkcast     #16                 // class java/lang/Number
      24: invokevirtual #20                 // Method java/lang/Number.intValue:()I
      27: nop
      28: goto          31
      31: pop
      32: return

也有nop个。

  1. 在未经优化的代码中包含nop的原因是什么? (调试信息/...)
  2. 是否有理由在优化的代码中包含nop

1 个答案:

答案 0 :(得分:4)

Kotlin编译器发出的字节码中有nop s的原因是,调试器可能在函数或{{1}的最后一个括号(即最后一条语句之后)处放置一个断点。 }-条款和其他子句,并使其能够移至那些位置。为此,需要在字节码中显示一条指令,该指令中还标有行号。

如果某些if多余,例如在最后一条语句指令之后已经有一条有效指令时,则会对其进行优化。