3

我正在检查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-optimizemain函数将如下所示

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

还有nops。

  1. nop在非优化代码中有 s 的原因是什么?(调试信息/...)
  2. 有什么理由nop在优化代码中有 s 吗?
4

1 回答 1

4

Kotlin 编译器发出的字节码中 s的原因nop是调试器有可能在函数或 - 子句和其他子句的最后一条语句之后放置一个断点if,并使其成为可能走到那些地方。这样做需要字节码中存在一条指令,该指令也标有行号。

如果某些nops 是冗余的,则它们会被优化掉,例如当最后一条语句指令之后已经有一条有效指令时。

于 2020-01-08T23:15:16.983 回答