From 49453ca705499b3441e935f24a336803781ea2c8 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Thu, 18 May 2017 08:48:16 +0300 Subject: [PATCH] Avoid dependency on coroutine-related public API changes These changes has been introduced in c3a032ea0b6c5c48da63e275fe784bffe14e0446 to support new scheme for named functions At the same time they can be avoided by generating some additional code/accessors in the anonymous classes for coroutine state Now we cannot simply remove introduced API because of bootstrap problems #KT-17898 Fixed --- .../kotlin/codegen/ExpressionCodegen.java | 4 +- .../kotlin/codegen/JvmRuntimeTypes.kt | 6 +- .../codegen/coroutines/CoroutineCodegen.kt | 167 +++++++++++------- .../CoroutineTransformerMethodVisitor.kt | 59 +++++-- .../coroutines/coroutineCodegenUtil.kt | 6 +- .../inlineWithStateMachine.txt | 6 +- .../inlineWithoutStateMachine.txt | 6 +- .../bytecodeListing/coroutineFields.txt | 12 +- 8 files changed, 178 insertions(+), 88 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 5ccec818a9b..8a883d334d2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -1037,7 +1037,7 @@ public class ExpressionCodegen extends KtVisitor impleme if (captureReceiver != null) { StackValue capturedReceiver = functionReferenceReceiver != null ? functionReferenceReceiver : - generateExtensionReceiver(unwrapOriginalReceiverOwnerForSuspendFunction(context)); + generateExtensionReceiver(unwrapOriginalReceiverOwnerForSuspendLambda(context)); callGenerator.putCapturedValueOnStack(capturedReceiver, capturedReceiver.type, paramIndex++); } @@ -1076,7 +1076,7 @@ public class ExpressionCodegen extends KtVisitor impleme } @NotNull - private static CallableDescriptor unwrapOriginalReceiverOwnerForSuspendFunction(@NotNull MethodContext context) { + private static CallableDescriptor unwrapOriginalReceiverOwnerForSuspendLambda(@NotNull MethodContext context) { FunctionDescriptor originalForDoResume = context.getFunctionDescriptor().getUserData(CoroutineCodegenUtilKt.INITIAL_SUSPEND_DESCRIPTOR_FOR_DO_RESUME); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.kt index 90ef9009920..f6490482dc7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.kt @@ -43,7 +43,6 @@ class JvmRuntimeTypes(module: ModuleDescriptor) { private val localVariableReference: ClassDescriptor by klass("LocalVariableReference") private val mutableLocalVariableReference: ClassDescriptor by klass("MutableLocalVariableReference") private val coroutineImplClass by lazy { createClass(kotlinCoroutinesJvmInternalPackage, "CoroutineImpl") } - private val coroutineImplForNamedFunctionClass by lazy { createClass(kotlinCoroutinesJvmInternalPackage, "CoroutineImplForNamedFunction") } private val propertyReferences: List by lazy { (0..2).map { i -> createClass(kotlinJvmInternalPackage, "PropertyReference$i") } @@ -85,13 +84,10 @@ class JvmRuntimeTypes(module: ModuleDescriptor) { if (descriptor.isSuspend) { return mutableListOf().apply { + add(coroutineImplClass.defaultType) if (descriptor.isSuspendLambda) { - add(coroutineImplClass.defaultType) add(functionType) } - else { - add(coroutineImplForNamedFunctionClass.defaultType) - } } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt index 094e03f46ba..491714e4542 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt @@ -54,13 +54,45 @@ abstract class AbstractCoroutineCodegen( outerExpressionCodegen: ExpressionCodegen, element: KtElement, closureContext: ClosureContext, - classBuilder: ClassBuilder + classBuilder: ClassBuilder, + userDataForDoResume: Map, *>? = null ) : ClosureCodegen( outerExpressionCodegen.state, element, null, closureContext, null, FailingFunctionGenerationStrategy, outerExpressionCodegen.parentCodegen, classBuilder ) { + protected val classDescriptor = closureContext.contextDescriptor + + protected val doResumeDescriptor = + SimpleFunctionDescriptorImpl.create( + classDescriptor, Annotations.EMPTY, Name.identifier(DO_RESUME_METHOD_NAME), CallableMemberDescriptor.Kind.DECLARATION, + funDescriptor.source + ).apply doResume@{ + initialize( + null, + classDescriptor.thisAsReceiverParameter, + emptyList(), + listOf( + createValueParameterForDoResume(Name.identifier("data"), builtIns.nullableAnyType, 0), + createValueParameterForDoResume(Name.identifier("throwable"), builtIns.throwable.defaultType.makeNullable(), 1) + ), + builtIns.nullableAnyType, + Modality.FINAL, + Visibilities.PUBLIC, + userDataForDoResume + ) + } + + private fun FunctionDescriptor.createValueParameterForDoResume(name: Name, type: KotlinType, index: Int) = + ValueParameterDescriptorImpl( + this, null, index, Annotations.EMPTY, name, + type, + false, false, + false, + null, SourceElement.NO_SOURCE + ) + override fun generateConstructor(): Method { val args = calculateConstructorParameters(typeMapper, closure, asmType) val argTypes = args.map { it.fieldType }.plus(CONTINUATION_ASM_TYPE).toTypedArray() @@ -78,14 +110,12 @@ abstract class AbstractCoroutineCodegen( iv.generateClosureFieldsInitializationFromParameters(closure, args) iv.load(0, AsmTypes.OBJECT_TYPE) - if (passArityToSuperClass) { - iv.iconst(calculateArity()) - } + iv.iconst(if (passArityToSuperClass) calculateArity() else 0) iv.load(argTypes.map { it.size }.sum(), AsmTypes.OBJECT_TYPE) val superClassConstructorDescriptor = Type.getMethodDescriptor( Type.VOID_TYPE, - *(if (passArityToSuperClass) arrayOf(Type.INT_TYPE) else emptyArray()), + Type.INT_TYPE, CONTINUATION_ASM_TYPE ) iv.invokespecial(superClassAsmType.internalName, "", superClassConstructorDescriptor, false) @@ -107,45 +137,14 @@ class CoroutineCodegenForLambda private constructor( private val closureContext: ClosureContext, classBuilder: ClassBuilder, private val originalSuspendFunctionDescriptor: FunctionDescriptor -) : AbstractCoroutineCodegen(outerExpressionCodegen, element, closureContext, classBuilder) { - private val classDescriptor = closureContext.contextDescriptor +) : AbstractCoroutineCodegen( + outerExpressionCodegen, element, closureContext, classBuilder, + userDataForDoResume = mapOf(INITIAL_SUSPEND_DESCRIPTOR_FOR_DO_RESUME to originalSuspendFunctionDescriptor) +) { private val builtIns = funDescriptor.builtIns private lateinit var constructorToUseFromInvoke: Method - // protected fun doResume(result, throwable) - private val doResumeDescriptor = - SimpleFunctionDescriptorImpl.create( - classDescriptor, Annotations.EMPTY, Name.identifier(DO_RESUME_METHOD_NAME), CallableMemberDescriptor.Kind.DECLARATION, - funDescriptor.source - ).apply doResume@{ - initialize( - /* receiverParameterType = */ null, - classDescriptor.thisAsReceiverParameter, - /* typeParameters = */ emptyList(), - listOf( - ValueParameterDescriptorImpl( - this@doResume, null, 0, Annotations.EMPTY, Name.identifier("data"), - builtIns.nullableAnyType, - /* isDefault = */ false, /* isCrossinline = */ false, - /* isNoinline = */ false, - /* varargElementType = */ null, SourceElement.NO_SOURCE - ), - ValueParameterDescriptorImpl( - this@doResume, null, 1, Annotations.EMPTY, Name.identifier("throwable"), - builtIns.throwable.defaultType.makeNullable(), - /* isDefault = */ false, /* isCrossinline = */ false, - /* isNoinline = */ false, - /* varargElementType = */ null, SourceElement.NO_SOURCE - ) - ), - builtIns.nullableAnyType, - Modality.FINAL, - Visibilities.PUBLIC, - mapOf(INITIAL_SUSPEND_DESCRIPTOR_FOR_DO_RESUME to originalSuspendFunctionDescriptor) - ) - } - private val createCoroutineDescriptor = funDescriptor.createCustomCopy { setName(Name.identifier(SUSPEND_FUNCTION_CREATE_METHOD_NAME)) @@ -355,28 +354,9 @@ class CoroutineCodegenForNamedFunction private constructor( classBuilder: ClassBuilder, originalSuspendFunctionDescriptor: FunctionDescriptor ) : AbstractCoroutineCodegen(outerExpressionCodegen, element, closureContext, classBuilder) { - private val classDescriptor = closureContext.contextDescriptor - private val suspendFunctionJvmView = bindingContext[CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, originalSuspendFunctionDescriptor]!! - // protected fun doResume(): Any? - private val doResumeDescriptor = - SimpleFunctionDescriptorImpl.create( - classDescriptor, Annotations.EMPTY, Name.identifier(DO_RESUME_METHOD_NAME), CallableMemberDescriptor.Kind.DECLARATION, - funDescriptor.source - ).apply doResume@{ - initialize( - /* receiverParameterType = */ null, - classDescriptor.thisAsReceiverParameter, - /* typeParameters = */ emptyList(), - listOf(), - builtIns.nullableAnyType, - Modality.FINAL, - Visibilities.PUBLIC - ) - } - override val passArityToSuperClass get() = false override fun generateBridges() { @@ -385,6 +365,18 @@ class CoroutineCodegenForNamedFunction private constructor( override fun generateClosureBody() { generateDoResume() + + generateGetLabelMethod() + generateSetLabelMethod() + + v.newField( + JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_SYNTHETIC or AsmUtil.NO_FLAG_PACKAGE_PRIVATE, + DATA_FIELD_NAME, AsmTypes.OBJECT_TYPE.descriptor, null, null + ) + v.newField( + JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_SYNTHETIC or AsmUtil.NO_FLAG_PACKAGE_PRIVATE, + EXCEPTION_FIELD_NAME, AsmTypes.JAVA_THROWABLE_TYPE.descriptor, null, null + ) } private fun generateDoResume() { @@ -393,6 +385,25 @@ class CoroutineCodegenForNamedFunction private constructor( doResumeDescriptor, object : FunctionGenerationStrategy.CodegenBased(state) { override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) { + StackValue.field( + AsmTypes.OBJECT_TYPE, Type.getObjectType(v.thisName), DATA_FIELD_NAME, false, + StackValue.LOCAL_0 + ).store(StackValue.local(1, AsmTypes.OBJECT_TYPE), codegen.v) + + StackValue.field( + AsmTypes.JAVA_THROWABLE_TYPE, Type.getObjectType(v.thisName), EXCEPTION_FIELD_NAME, false, + StackValue.LOCAL_0 + ).store(StackValue.local(2, AsmTypes.JAVA_THROWABLE_TYPE), codegen.v) + + LABEL_FIELD_STACK_VALUE.store( + StackValue.operation(Type.INT_TYPE) { + LABEL_FIELD_STACK_VALUE.put(Type.INT_TYPE, it) + it.iconst(1 shl 31) + it.or(Type.INT_TYPE) + }, + codegen.v + ) + val captureThisType = closure.captureThis?.let(typeMapper::mapType) if (captureThisType != null) { StackValue.field( @@ -430,6 +441,38 @@ class CoroutineCodegenForNamedFunction private constructor( ) } + private fun generateGetLabelMethod() { + val mv = v.newMethod( + JvmDeclarationOrigin.NO_ORIGIN, + Opcodes.ACC_SYNTHETIC or Opcodes.ACC_FINAL or AsmUtil.NO_FLAG_PACKAGE_PRIVATE, + "getLabel", + Type.getMethodDescriptor(Type.INT_TYPE), + null, + null + ) + + mv.visitCode() + LABEL_FIELD_STACK_VALUE.put(Type.INT_TYPE, InstructionAdapter(mv)) + mv.visitInsn(Opcodes.IRETURN) + mv.visitEnd() + } + + private fun generateSetLabelMethod() { + val mv = v.newMethod( + JvmDeclarationOrigin.NO_ORIGIN, + Opcodes.ACC_SYNTHETIC or Opcodes.ACC_FINAL or AsmUtil.NO_FLAG_PACKAGE_PRIVATE, + "setLabel", + Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE), + null, + null + ) + + mv.visitCode() + LABEL_FIELD_STACK_VALUE.store(StackValue.local(1, Type.INT_TYPE), InstructionAdapter(mv)) + mv.visitInsn(Opcodes.RETURN) + mv.visitEnd() + } + override fun generateKotlinMetadataAnnotation() { writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0) { // Do not write method metadata for raw coroutine state machines @@ -437,6 +480,12 @@ class CoroutineCodegenForNamedFunction private constructor( } companion object { + private val LABEL_FIELD_STACK_VALUE = + StackValue.field( + FieldInfo.createForHiddenField(COROUTINE_IMPL_ASM_TYPE, Type.INT_TYPE, COROUTINE_LABEL_FIELD_NAME), + StackValue.LOCAL_0 + ) + fun create( cv: ClassBuilder, expressionCodegen: ExpressionCodegen, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt index 86f89424d83..de477ee52c5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt @@ -158,7 +158,7 @@ class CoroutineTransformerMethodVisitor( val objectTypeForState = Type.getObjectType(classBuilderForCoroutineState.thisName) methodNode.instructions.insert(withInstructionAdapter { val createStateInstance = Label() - val storeStateObject = Label() + val afterCoroutineStateCreated = Label() // We have to distinguish the following situations: // - Our function got called in a common way (e.g. from another function or via recursive call) and we should execute our @@ -180,15 +180,39 @@ class CoroutineTransformerMethodVisitor( visitVarInsn(Opcodes.ALOAD, continuationIndex) checkcast(objectTypeForState) + visitVarInsn(Opcodes.ASTORE, continuationIndex) + + visitVarInsn(Opcodes.ALOAD, continuationIndex) invokevirtual( - COROUTINE_IMPL_FOR_NAMED_ASM_TYPE.internalName, - "checkAndFlushLastBit", Type.getMethodDescriptor(Type.BOOLEAN_TYPE), false + classBuilderForCoroutineState.thisName, + "getLabel", + Type.getMethodDescriptor(Type.INT_TYPE), + false ) + + iconst(1 shl 31) + and(Type.INT_TYPE) ifeq(createStateInstance) visitVarInsn(Opcodes.ALOAD, continuationIndex) - checkcast(objectTypeForState) - goTo(storeStateObject) + dup() + invokevirtual( + classBuilderForCoroutineState.thisName, + "getLabel", + Type.getMethodDescriptor(Type.INT_TYPE), + false + ) + + iconst(1 shl 31) + sub(Type.INT_TYPE) + invokevirtual( + classBuilderForCoroutineState.thisName, + "setLabel", + Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE), + false + ) + + goTo(afterCoroutineStateCreated) visitLabel(createStateInstance) @@ -218,17 +242,16 @@ class CoroutineTransformerMethodVisitor( false ) - visitLabel(storeStateObject) visitVarInsn(Opcodes.ASTORE, continuationIndex) + visitLabel(afterCoroutineStateCreated) + visitVarInsn(Opcodes.ALOAD, continuationIndex) - checkcast(objectTypeForState) - getfield(COROUTINE_IMPL_FOR_NAMED_ASM_TYPE.internalName, "data", AsmTypes.OBJECT_TYPE.descriptor) + getfield(classBuilderForCoroutineState.thisName, DATA_FIELD_NAME, AsmTypes.OBJECT_TYPE.descriptor) visitVarInsn(Opcodes.ASTORE, dataIndex) visitVarInsn(Opcodes.ALOAD, continuationIndex) - checkcast(objectTypeForState) - getfield(COROUTINE_IMPL_FOR_NAMED_ASM_TYPE.internalName, "exception", AsmTypes.JAVA_THROWABLE_TYPE.descriptor) + getfield(classBuilderForCoroutineState.thisName, EXCEPTION_FIELD_NAME, AsmTypes.JAVA_THROWABLE_TYPE.descriptor) visitVarInsn(Opcodes.ASTORE, exceptionIndex) }) } @@ -418,10 +441,18 @@ class CoroutineTransformerMethodVisitor( insnListOf( VarInsnNode(Opcodes.ALOAD, continuationIndex), *withInstructionAdapter { iconst(id) }.toArray(), - FieldInsnNode( - Opcodes.PUTFIELD, COROUTINE_IMPL_ASM_TYPE.internalName, COROUTINE_LABEL_FIELD_NAME, - Type.INT_TYPE.descriptor - ) + if (isForNamedFunction) + MethodInsnNode( + Opcodes.INVOKEVIRTUAL, classBuilderForCoroutineState.thisName, + "setLabel", + Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE), + false + ) + else + FieldInsnNode( + Opcodes.PUTFIELD, COROUTINE_IMPL_ASM_TYPE.internalName, COROUTINE_LABEL_FIELD_NAME, + Type.INT_TYPE.descriptor + ) ) ) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt index 8dd27e7ec71..07d64165d5e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt @@ -60,6 +60,8 @@ const val AFTER_SUSPENSION_POINT_MARKER_NAME = "afterSuspensionPoint" const val COROUTINE_LABEL_FIELD_NAME = "label" const val SUSPEND_FUNCTION_CREATE_METHOD_NAME = "create" const val DO_RESUME_METHOD_NAME = "doResume" +const val DATA_FIELD_NAME = "data" +const val EXCEPTION_FIELD_NAME = "exception" @JvmField val COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME = @@ -71,10 +73,6 @@ val CONTINUATION_ASM_TYPE = DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME.topLe @JvmField val COROUTINE_IMPL_ASM_TYPE = COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineImpl")).topLevelClassAsmType() -@JvmField -val COROUTINE_IMPL_FOR_NAMED_ASM_TYPE = - COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineImplForNamedFunction")).topLevelClassAsmType() - private val COROUTINES_INTRINSICS_FILE_FACADE_INTERNAL_NAME = COROUTINES_INTRINSICS_PACKAGE_FQ_NAME.child(Name.identifier("IntrinsicsKt")).topLevelClassAsmType() diff --git a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithStateMachine.txt b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithStateMachine.txt index 86c091fb732..957dbe4f089 100644 --- a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithStateMachine.txt +++ b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithStateMachine.txt @@ -14,9 +14,13 @@ final class InlineWithStateMachineKt$box$1 { final class InlineWithStateMachineKt$mainSuspend$1 { field L$0: java.lang.Object field L$1: java.lang.Object + synthetic field data: java.lang.Object + synthetic field exception: java.lang.Throwable inner class InlineWithStateMachineKt$mainSuspend$1 method (p0: kotlin.coroutines.experimental.Continuation): void - public final @org.jetbrains.annotations.Nullable method doResume(): java.lang.Object + public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object + synthetic final method getLabel(): int + synthetic final method setLabel(p0: int): void } @kotlin.Metadata diff --git a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithoutStateMachine.txt b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithoutStateMachine.txt index c042efb10c9..6c2735eec89 100644 --- a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithoutStateMachine.txt +++ b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithoutStateMachine.txt @@ -15,9 +15,13 @@ final class InlineWithoutStateMachineKt$box$1 { final class InlineWithoutStateMachineKt$complexSuspend$1 { field L$0: java.lang.Object field L$1: java.lang.Object + synthetic field data: java.lang.Object + synthetic field exception: java.lang.Throwable inner class InlineWithoutStateMachineKt$complexSuspend$1 method (p0: kotlin.coroutines.experimental.Continuation): void - public final @org.jetbrains.annotations.Nullable method doResume(): java.lang.Object + public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object + synthetic final method getLabel(): int + synthetic final method setLabel(p0: int): void } @kotlin.Metadata diff --git a/compiler/testData/codegen/bytecodeListing/coroutineFields.txt b/compiler/testData/codegen/bytecodeListing/coroutineFields.txt index 00a6576f8d9..a92a8b481f8 100644 --- a/compiler/testData/codegen/bytecodeListing/coroutineFields.txt +++ b/compiler/testData/codegen/bytecodeListing/coroutineFields.txt @@ -1,19 +1,27 @@ @kotlin.Metadata final class Controller$multipleSuspensions$1 { field L$0: java.lang.Object + synthetic field data: java.lang.Object + synthetic field exception: java.lang.Throwable synthetic final field this$0: Controller inner class Controller$multipleSuspensions$1 method (p0: Controller, p1: kotlin.coroutines.experimental.Continuation): void - public final @org.jetbrains.annotations.Nullable method doResume(): java.lang.Object + public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object + synthetic final method getLabel(): int + synthetic final method setLabel(p0: int): void } @kotlin.Metadata final class Controller$nonTailCall$1 { field L$0: java.lang.Object + synthetic field data: java.lang.Object + synthetic field exception: java.lang.Throwable synthetic final field this$0: Controller inner class Controller$nonTailCall$1 method (p0: Controller, p1: kotlin.coroutines.experimental.Continuation): void - public final @org.jetbrains.annotations.Nullable method doResume(): java.lang.Object + public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object + synthetic final method getLabel(): int + synthetic final method setLabel(p0: int): void } @kotlin.Metadata