package basic

import kotlin.concurrent.thread
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

internal suspend fun bar() {
    suspendCoroutine {
        thread {
            Thread.sleep(1000)
            it.resume(Unit)
        }
    }
}



package basic

class SimpleCoroutine {
    private suspend fun foo() {
        bar()
    }
}

Bytecode for above

// ================basic/SimpleCoroutine.class =================
// class version 52.0 (52)
// access flags 0x31
public final class basic/SimpleCoroutine {


  // access flags 0x12
  // signature (Lkotlin/coroutines/Continuation<-Lkotlin/Unit;>;)Ljava/lang/Object;
  // declaration:  foo(kotlin.coroutines.Continuation<? super kotlin.Unit>)
  private final foo(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
    // annotable parameter count: 1 (visible)
    // annotable parameter count: 1 (invisible)
   L0
    LINENUMBER 5 L0
    ALOAD 1
    INVOKESTATIC basic/BarKt.bar (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
    DUP
    INVOKESTATIC kotlin/coroutines/intrinsics/IntrinsicsKt.getCOROUTINE_SUSPENDED ()Ljava/lang/Object;
    IF_ACMPNE L1
    ARETURN
   L1
    POP
   L2
    LINENUMBER 6 L2
    GETSTATIC kotlin/Unit.INSTANCE : Lkotlin/Unit;
    ARETURN
   L3
    LOCALVARIABLE this Lbasic/SimpleCoroutine; L0 L3 0
    LOCALVARIABLE $completion Lkotlin/coroutines/Continuation; L0 L3 1
    MAXSTACK = 3
    MAXLOCALS = 2

  // access flags 0x1
  public <init>()V
   L0
    LINENUMBER 3 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
   L1
    LOCALVARIABLE this Lbasic/SimpleCoroutine; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  @Lkotlin/Metadata;(mv={1, 7, 0}, k=1, d1={"\u0000\u0014\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\u0008\u0002\n\u0002\u0010\u0002\n\u0002\u0008\u0002\u0018\u00002\u00020\u0001B\u0005\u00a2\u0006\u0002\u0010\u0002J\u0011\u0010\u0003\u001a\u00020\u0004H\u0082@\u00f8\u0001\u0000\u00a2\u0006\u0002\u0010\u0005\u0082\u0002\u0004\n\u0002\u0008\u0019\u00a8\u0006\u0006"}, d2={"Lbasic/SimpleCoroutine;", "", "()V", "foo", "", "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", "KotlinSuspendingFunctions"})
  // compiled from: SimpleCoroutine.kt
}


// ================META-INF/KotlinSuspendingFunctions.kotlin_module =================
"*

Decompiled Java code

package basic;

import kotlin.Metadata;
import kotlin.Unit;
import kotlin.coroutines.Continuation;
import kotlin.coroutines.intrinsics.IntrinsicsKt;

public final class SimpleCoroutine {
   private final Object foo(Continuation $completion) {
      Object var10000 = BarKt.bar($completion);
      return var10000 == IntrinsicsKt.getCOROUTINE_SUSPENDED() ? var10000 : Unit.INSTANCE;
   }
}

我不确定是否应该说这是不必要的,因为我不确定这样做背后是否有正当的理由

Label 1

Object var10000 = BarKt.bar($completion);
return var10000 == IntrinsicsKt.getCOROUTINE_SUSPENDED() ? var10000 : Unit.INSTANCE;

原来的方法是调用一个暂停方法/函数,对应的字节代码应该如下所示

BarKt.bar($completion);

WHY?

if you see Label 1个, it is doing a check and returning value, but that check seems to be meaning less, since it returns the same value that it received from the call, If no manipulation or conditional return is required then why to have this overhead?

102

推荐答案

它是多余的,我刚刚用一些代码片段确认了这一点,

100

我用下面的示例片段对其进行了一些深入的研究,

package basic

class SimpleCoroutine {
    private suspend fun foo(): String {
        return bar()
    }

    private suspend fun foo1(): Any {
        return bar1()
    }

    private suspend fun foo2(): RandomSingleton {
        return bar2()
    }

    private suspend fun foo3() {
        return bar3()
    }
}

The generated code is as follows

public final class SimpleCoroutine {
   private final Object foo(Continuation $completion) {
      return BarKt.bar($completion);
   }

   private final Object foo1(Continuation $completion) {
      return BarKt.bar1($completion);
   }

   private final Object foo2(Continuation $completion) {
      return BarKt.bar2($completion);
   }

   private final Object foo3(Continuation $completion) {
      Object var10000 = BarKt.bar3($completion);
      return var10000 == IntrinsicsKt.getCOROUTINE_SUSPENDED() ? var10000 : Unit.INSTANCE;
   }
}

在所有函数中,生成的代码与源代码几乎相同,除了foo3,其中返回类型是kotlin.Unit,这是来自Kotlin标准库的单例.现在我们都知道Kotlin中的默认返回类型是Unit.

因此,为了澄清错误,我还制作了一个我自己的单例对象,我用它来判断foo2(),但是没有应用多余的判断.

我能得出的唯一结论是,编译器正在进行猜测工作;

Object var10000 = BarKt.bar($completion);
return var10000 == IntrinsicsKt.getCOROUTINE_SUSPENDED() ? var10000 : Unit.INSTANCE;

从你问题的上述片段来看,

var10000 == IntrinsicsKt.getCOROUTINE_SUSPENDED() ? var10000 : Unit.INSTANCE;

棘手的部分是它不确定BarKt.bar($completion);返回的值是否会是COROUTINE_SUSPENDED | kotlin.Unit,似乎编译器对正确的部分有一些不确定的地方总是kotlin.Unit,这就是为什么它显式返回Unit.INSTANCE.

Kotlin相关问答推荐

如果一项工作失败,请继续在Kotlin 等待其他工作/子元素完成

如何在Kotlin中反射多个对象以查找特定类型的属性

Scala与Kotlin中的迭代

数据源配置

在 Kotlin 中将 Array 转换为 IntArray 时丢失值

如何将消费者放入 Kotlin 的 map 中?

Rabin-Karp字符串匹配的实现(Rolling hash)

ActivityResultContracts TakePicture 结果总是返回 false

Kotlin中用于调用常量名称的枚举类方法之间的区别

如何使用子变量在 Kotlin 中初始化父级

Moshi:解析单个对象或对象列表(kotlin)

使用 Hilt 注入 CoroutineWorker

在 Scaffold Jetpack Compose 内的特定屏幕上隐藏顶部和底部导航器

Kotlin:找不到符号类片段或其他 android 类

什么是开放式property?为什么我不能将其设置器设为private私有?

如何暂停kotlin coroutine直到收到通知

TypeConverter()在Android的TypeConverter错误中具有私有访问权限

Kotlin扩展函数与成员函数?

WebFlux 功能:如何检测空 Flux 并返回 404?

函数引用和lambdas