Introduce CoroutineImpl as a common super class for coroutines
The main benefit are class-files sizes for them (not repeating the same declaration for each coroutine) Also it helped to simplify coroutine codegen code a little Note that controller/label field become non-volatile (see KT-14636) #KT-14636 In Progress
This commit is contained in:
@@ -422,7 +422,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
|
||||
iv.load(0, superClassAsmType);
|
||||
|
||||
if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE)) {
|
||||
if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE) || superClassAsmType.equals(COROUTINE_IMPL)) {
|
||||
int arity = funDescriptor.getValueParameters().size();
|
||||
if (funDescriptor.getExtensionReceiverParameter() != null) arity++;
|
||||
if (funDescriptor.getDispatchReceiverParameter() != null) arity++;
|
||||
@@ -433,8 +433,6 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "()V", false);
|
||||
}
|
||||
|
||||
generateAdditionalCodeInConstructor(iv);
|
||||
|
||||
iv.visitInsn(RETURN);
|
||||
|
||||
FunctionCodegen.endVisit(iv, "constructor", element);
|
||||
@@ -442,10 +440,6 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
return constructor;
|
||||
}
|
||||
|
||||
protected void generateAdditionalCodeInConstructor(@NotNull InstructionAdapter iv) {
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<FieldInfo> calculateConstructorParameters(
|
||||
@NotNull KotlinTypeMapper typeMapper,
|
||||
|
||||
@@ -3045,12 +3045,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
assert classDescriptor != null : "class descriptor for coroutine " + descriptor + " should not be null";
|
||||
|
||||
StackValue coroutineReceiver = StackValue.thisOrOuter(this, classDescriptor, /* isSuper =*/ false, /* castReceiver */ false);
|
||||
return StackValue.field(
|
||||
FieldInfo.createForHiddenField(
|
||||
typeMapper.mapClass(classDescriptor),
|
||||
typeMapper.mapType(coroutineControllerType),
|
||||
CoroutineCodegenUtilKt.COROUTINE_CONTROLLER_FIELD_NAME),
|
||||
coroutineReceiver);
|
||||
return StackValue.coercion(
|
||||
StackValue.field(
|
||||
FieldInfo.createForHiddenField(
|
||||
AsmTypes.COROUTINE_IMPL,
|
||||
AsmTypes.OBJECT_TYPE,
|
||||
CoroutineCodegenUtilKt.COROUTINE_CONTROLLER_FIELD_NAME
|
||||
),
|
||||
coroutineReceiver
|
||||
),
|
||||
typeMapper.mapType(coroutineControllerType)
|
||||
);
|
||||
}
|
||||
|
||||
return context.generateReceiver(descriptor, state, false);
|
||||
|
||||
@@ -43,6 +43,7 @@ class JvmRuntimeTypes(module: ModuleDescriptor) {
|
||||
private val functionReference: ClassDescriptor by klass("FunctionReference")
|
||||
private val localVariableReference: ClassDescriptor by klass("LocalVariableReference")
|
||||
private val mutableLocalVariableReference: ClassDescriptor by klass("MutableLocalVariableReference")
|
||||
private val coroutineImplClass by klass("CoroutineImpl")
|
||||
|
||||
private val propertyReferences: List<ClassDescriptor> by lazy {
|
||||
(0..2).map { i -> createClass(kotlinJvmInternalPackage, "PropertyReference$i") }
|
||||
@@ -52,7 +53,7 @@ class JvmRuntimeTypes(module: ModuleDescriptor) {
|
||||
(0..2).map { i -> createClass(kotlinJvmInternalPackage, "MutablePropertyReference$i") }
|
||||
}
|
||||
|
||||
private val defaultContinuationSupertype: KotlinType by lazy { createNullableAnyContinuation(module) }
|
||||
val continuationOfAny: KotlinType by lazy { createNullableAnyContinuation(module) }
|
||||
|
||||
/**
|
||||
* @return `Continuation<Any?>` type
|
||||
@@ -89,7 +90,7 @@ class JvmRuntimeTypes(module: ModuleDescriptor) {
|
||||
|
||||
val coroutineControllerType = descriptor.controllerTypeIfCoroutine
|
||||
if (coroutineControllerType != null) {
|
||||
return listOf(lambda.defaultType, functionType, /*coroutineType,*/ defaultContinuationSupertype)
|
||||
return listOf(coroutineImplClass.defaultType, functionType)
|
||||
}
|
||||
|
||||
return listOf(lambda.defaultType, functionType)
|
||||
|
||||
@@ -17,25 +17,25 @@
|
||||
package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.context.ClosureContext
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.coroutines.controllerTypeIfCoroutine
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.setSingleOverridden
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
@@ -51,22 +51,11 @@ class CoroutineCodegen(
|
||||
strategy: FunctionGenerationStrategy,
|
||||
parentCodegen: MemberCodegen<*>,
|
||||
classBuilder: ClassBuilder,
|
||||
private val continuationSuperType: KotlinType,
|
||||
private val coroutineLambdaDescriptor: FunctionDescriptor
|
||||
private val coroutineLambdaDescriptor: FunctionDescriptor,
|
||||
private val controllerType: KotlinType
|
||||
) : ClosureCodegen(state, element, null, closureContext, null, strategy, parentCodegen, classBuilder) {
|
||||
private val controllerType = coroutineLambdaDescriptor.controllerTypeIfCoroutine!!
|
||||
|
||||
override fun generateClosureBody() {
|
||||
v.newField(
|
||||
JvmDeclarationOrigin.NO_ORIGIN, AsmUtil.NO_FLAG_PACKAGE_PRIVATE or Opcodes.ACC_VOLATILE,
|
||||
COROUTINE_CONTROLLER_FIELD_NAME,
|
||||
typeMapper.mapType(controllerType).descriptor, null, null)
|
||||
|
||||
v.newField(
|
||||
JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_PRIVATE or Opcodes.ACC_VOLATILE,
|
||||
COROUTINE_LABEL_FIELD_NAME,
|
||||
Type.INT_TYPE.descriptor, null, null)
|
||||
|
||||
for (parameter in funDescriptor.valueParameters) {
|
||||
v.newField(
|
||||
OtherOrigin(parameter),
|
||||
@@ -77,37 +66,37 @@ class CoroutineCodegen(
|
||||
|
||||
val classDescriptor = closureContext.contextDescriptor
|
||||
|
||||
val resumeFunctionDescriptor =
|
||||
createSynthesizedImplementationByName(
|
||||
"resume",
|
||||
interfaceSupertype = continuationSuperType,
|
||||
implementationClass = classDescriptor,
|
||||
sourceElement = funDescriptor.source)
|
||||
|
||||
val resumeWithExceptionFunctionDescriptor =
|
||||
createSynthesizedImplementationByName(
|
||||
"resumeWithException",
|
||||
interfaceSupertype = continuationSuperType,
|
||||
implementationClass = classDescriptor,
|
||||
sourceElement = funDescriptor.source)
|
||||
|
||||
// private fun doResume(result, throwable)
|
||||
// protected fun doResume(result, throwable)
|
||||
val combinedResumeFunctionDescriptor =
|
||||
resumeFunctionDescriptor.newCopyBuilder()
|
||||
.setVisibility(Visibilities.PRIVATE)
|
||||
.setName(Name.identifier("doResume"))
|
||||
.setCopyOverrides(false)
|
||||
.setPreserveSourceElement()
|
||||
.setValueParameters(
|
||||
listOf(
|
||||
resumeFunctionDescriptor.valueParameters[0].copy(
|
||||
resumeFunctionDescriptor, Name.identifier("value"), 0),
|
||||
resumeWithExceptionFunctionDescriptor.valueParameters[0].copy(
|
||||
resumeFunctionDescriptor, Name.identifier("exception"), 1))
|
||||
).build()!!
|
||||
|
||||
generatedDelegationToCombinedResume(resumeFunctionDescriptor, combinedResumeFunctionDescriptor, isSuccess = true)
|
||||
generatedDelegationToCombinedResume(resumeWithExceptionFunctionDescriptor, combinedResumeFunctionDescriptor, isSuccess = false)
|
||||
SimpleFunctionDescriptorImpl.create(
|
||||
classDescriptor, Annotations.EMPTY, Name.identifier("doResume"), 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"),
|
||||
module.builtIns.nullableAnyType,
|
||||
/* isDefault = */ false, /* isCrossinline = */ false,
|
||||
/* isNoinline = */ false, /* isCoroutine = */ false,
|
||||
/* varargElementType = */ null, SourceElement.NO_SOURCE
|
||||
),
|
||||
ValueParameterDescriptorImpl(
|
||||
this@doResume, null, 1, Annotations.EMPTY, Name.identifier("throwable"),
|
||||
module.builtIns.throwable.defaultType.makeNullable(),
|
||||
/* isDefault = */ false, /* isCrossinline = */ false,
|
||||
/* isNoinline = */ false, /* isCoroutine = */ false,
|
||||
/* varargElementType = */ null, SourceElement.NO_SOURCE
|
||||
)
|
||||
),
|
||||
module.builtIns.unitType,
|
||||
Modality.FINAL,
|
||||
Visibilities.PROTECTED
|
||||
)
|
||||
}
|
||||
|
||||
functionCodegen.generateMethod(OtherOrigin(element), combinedResumeFunctionDescriptor,
|
||||
object : FunctionGenerationStrategy.FunctionDefault(state, element as KtDeclarationWithBody) {
|
||||
@@ -130,9 +119,11 @@ class CoroutineCodegen(
|
||||
private fun generateInvokeMethod(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||
val classDescriptor = closureContext.contextDescriptor
|
||||
val owner = typeMapper.mapClass(classDescriptor)
|
||||
val controllerFieldInfo = FieldInfo.createForHiddenField(
|
||||
owner,
|
||||
typeMapper.mapType(controllerType), COROUTINE_CONTROLLER_FIELD_NAME)
|
||||
val controllerFieldInfo =
|
||||
FieldInfo.createForHiddenField(
|
||||
AsmTypes.COROUTINE_IMPL,
|
||||
AsmTypes.OBJECT_TYPE, COROUTINE_CONTROLLER_FIELD_NAME
|
||||
)
|
||||
|
||||
val thisInstance = StackValue.thisOrOuter(codegen, classDescriptor, false, false)
|
||||
|
||||
@@ -225,90 +216,43 @@ class CoroutineCodegen(
|
||||
codegen.v.areturn(Type.VOID_TYPE)
|
||||
}
|
||||
|
||||
private fun createSynthesizedImplementationByName(
|
||||
name: String,
|
||||
interfaceSupertype: KotlinType,
|
||||
implementationClass: ClassDescriptor,
|
||||
sourceElement: SourceElement
|
||||
): SimpleFunctionDescriptor {
|
||||
val inSuperType = interfaceSupertype.memberScope.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).single()
|
||||
val result = inSuperType.newCopyBuilder().setSource(sourceElement).setOwner(implementationClass).setModality(Modality.FINAL).build()!!
|
||||
result.setSingleOverridden(inSuperType)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun generatedDelegationToCombinedResume(
|
||||
from: SimpleFunctionDescriptor,
|
||||
combinedResume: SimpleFunctionDescriptor,
|
||||
isSuccess: Boolean
|
||||
) {
|
||||
functionCodegen.generateMethod(OtherOrigin(element), from,
|
||||
object : FunctionGenerationStrategy.CodegenBased(state) {
|
||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||
with(codegen.v) {
|
||||
load(0, AsmTypes.OBJECT_TYPE)
|
||||
if (isSuccess) {
|
||||
load(1, AsmTypes.OBJECT_TYPE)
|
||||
aconst(null)
|
||||
}
|
||||
else {
|
||||
aconst(null)
|
||||
load(1, AsmTypes.OBJECT_TYPE)
|
||||
}
|
||||
|
||||
val delegateTo = typeMapper.mapAsmMethod(combinedResume)
|
||||
invokevirtual(className, delegateTo.name, delegateTo.descriptor, false)
|
||||
areturn(Type.VOID_TYPE)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun InstructionAdapter.setLabelValue(value: Int) {
|
||||
load(0, AsmTypes.OBJECT_TYPE)
|
||||
iconst(value)
|
||||
putfield(v.thisName, COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor)
|
||||
}
|
||||
|
||||
override fun generateAdditionalCodeInConstructor(iv: InstructionAdapter) {
|
||||
super.generateAdditionalCodeInConstructor(iv)
|
||||
// Change label value to illegal to make sure continuation will not be used until `invoke(Controler)`
|
||||
// where correct value will be set up
|
||||
iv.setLabelValue(LABEL_VALUE_BEFORE_INVOKE)
|
||||
putfield(AsmTypes.COROUTINE_IMPL.internalName, COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val LABEL_VALUE_BEFORE_INVOKE = -2
|
||||
private const val LABEL_VALUE_BEFORE_FIRST_SUSPENSION = 0
|
||||
|
||||
@JvmStatic fun create(
|
||||
@JvmStatic
|
||||
fun create(
|
||||
expressionCodegen: ExpressionCodegen,
|
||||
originalCoroutineLambdaDescriptor: FunctionDescriptor,
|
||||
declaration: KtElement,
|
||||
classBuilder: ClassBuilder
|
||||
): ClosureCodegen? {
|
||||
val classDescriptor = expressionCodegen.bindingContext[CodegenBinding.CLASS_FOR_CALLABLE, originalCoroutineLambdaDescriptor] ?: return null
|
||||
declaration as? KtFunction ?: return null
|
||||
|
||||
val continuationSupertype =
|
||||
classDescriptor.typeConstructor.supertypes.firstOrNull {
|
||||
it.constructor.declarationDescriptor?.fqNameUnsafe ==
|
||||
DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME.toUnsafe()
|
||||
} ?: return null
|
||||
if (declaration !is KtFunction) return null
|
||||
val controllerType = originalCoroutineLambdaDescriptor.controllerTypeIfCoroutine ?: return null
|
||||
|
||||
val descriptorWithContinuationReturnType =
|
||||
originalCoroutineLambdaDescriptor.newCopyBuilder().setPreserveSourceElement().setReturnType(continuationSupertype).build()!!
|
||||
originalCoroutineLambdaDescriptor.newCopyBuilder()
|
||||
.setPreserveSourceElement()
|
||||
.setReturnType(expressionCodegen.state.jvmRuntimeTypes.continuationOfAny)
|
||||
.build()!!
|
||||
|
||||
val state = expressionCodegen.state
|
||||
return CoroutineCodegen(
|
||||
state,
|
||||
declaration,
|
||||
expressionCodegen.context.intoCoroutineClosure(
|
||||
descriptorWithContinuationReturnType, originalCoroutineLambdaDescriptor, expressionCodegen, state.typeMapper),
|
||||
FunctionGenerationStrategy.FunctionDefault(state, declaration), expressionCodegen.parentCodegen, classBuilder,
|
||||
continuationSupertype,
|
||||
originalCoroutineLambdaDescriptor)
|
||||
descriptorWithContinuationReturnType, originalCoroutineLambdaDescriptor, expressionCodegen, state.typeMapper
|
||||
),
|
||||
FunctionGenerationStrategy.FunctionDefault(state, declaration),
|
||||
expressionCodegen.parentCodegen, classBuilder,
|
||||
originalCoroutineLambdaDescriptor,
|
||||
controllerType
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-4
@@ -102,12 +102,18 @@ class CoroutineTransformerMethodVisitor(
|
||||
insnListOf(
|
||||
VarInsnNode(Opcodes.ALOAD, 0),
|
||||
FieldInsnNode(
|
||||
Opcodes.GETFIELD, classBuilder.thisName, COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor),
|
||||
Opcodes.GETFIELD,
|
||||
AsmTypes.COROUTINE_IMPL.internalName,
|
||||
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
|
||||
),
|
||||
TableSwitchInsnNode(0,
|
||||
suspensionPoints.size,
|
||||
defaultLabel,
|
||||
*(arrayOf(startLabel) + suspensionPointLabels)),
|
||||
startLabel))
|
||||
startLabel, *suspensionPointLabels.toTypedArray()
|
||||
),
|
||||
startLabel
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
insert(last, withInstructionAdapter {
|
||||
@@ -303,7 +309,11 @@ class CoroutineTransformerMethodVisitor(
|
||||
VarInsnNode(Opcodes.ALOAD, 0),
|
||||
*withInstructionAdapter { iconst(id) }.toArray(),
|
||||
FieldInsnNode(
|
||||
Opcodes.PUTFIELD, classBuilder.thisName, COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor)))
|
||||
Opcodes.PUTFIELD, AsmTypes.COROUTINE_IMPL.internalName, COROUTINE_LABEL_FIELD_NAME,
|
||||
Type.INT_TYPE.descriptor
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
// Drop default value that purpose was to simulate returned value by suspension method
|
||||
suspension.fakeReturnValueInsns.forEach { methodNode.instructions.remove(it) }
|
||||
|
||||
+3
-7
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.codegen.AsmUtil;
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder;
|
||||
import org.jetbrains.kotlin.codegen.FieldInfo;
|
||||
import org.jetbrains.kotlin.codegen.StackValue;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
@@ -67,13 +68,8 @@ public class AnonymousObjectTransformer extends ObjectTransformer<AnonymousObjec
|
||||
public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) {
|
||||
InlineCodegenUtil.assertVersionNotGreaterThanGeneratedOne(version, name, inliningContext.state);
|
||||
classBuilder.defineClass(null, version, access, name, signature, superName, interfaces);
|
||||
if (interfaces != null) {
|
||||
for (String anInterface : interfaces) {
|
||||
if("kotlin/coroutines/Continuation".equals(anInterface)) {
|
||||
inliningContext.setContinuation(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(AsmTypes.COROUTINE_IMPL.getInternalName().equals(superName)) {
|
||||
inliningContext.setContinuation(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ public class AsmTypes {
|
||||
public static final Type MUTABLE_PROPERTY_REFERENCE0 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference0");
|
||||
public static final Type MUTABLE_PROPERTY_REFERENCE1 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference1");
|
||||
public static final Type MUTABLE_PROPERTY_REFERENCE2 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference2");
|
||||
public static final Type COROUTINE_IMPL = Type.getObjectType("kotlin/jvm/internal/CoroutineImpl");
|
||||
|
||||
|
||||
public static final Type[] PROPERTY_REFERENCE_IMPL = {
|
||||
Type.getObjectType("kotlin/jvm/internal/PropertyReference0Impl"),
|
||||
|
||||
@@ -11,7 +11,7 @@ fun builder1(coroutine c: Controller.() -> Continuation<Unit>) {
|
||||
|
||||
fun builder2(coroutine c: Controller.() -> Continuation<Unit>) {
|
||||
val continuation = c(Controller())
|
||||
val declaredField = continuation!!.javaClass.getDeclaredField("label")
|
||||
val declaredField = continuation.javaClass.superclass.getDeclaredField("label")
|
||||
declaredField.setAccessible(true)
|
||||
declaredField.set(continuation, -3)
|
||||
continuation.resume(Unit)
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package kotlin.jvm.internal
|
||||
|
||||
abstract class CoroutineImpl(arity: Int) : Lambda(arity), Continuation<Any?> {
|
||||
// It's not protected because can be used from noinline lambdas inside coroutine (when calling non-suspend functions)
|
||||
// Also there might be needed a way to access a controller by Continuation instance when it's inherited from CoroutineImpl
|
||||
@JvmField
|
||||
var controller: Any? = null
|
||||
|
||||
// Any label state less then zero indicates that coroutine is not run and can't be resumed in any way.
|
||||
// Specific values do not matter by now, but currently -2 used for uninitialized coroutine (no controller is assigned),
|
||||
// and -1 will mean that coroutine execution is over (does not work yet).
|
||||
@JvmField
|
||||
protected var label: Int = -2
|
||||
|
||||
override fun resume(data: Any?) {
|
||||
doResume(data, null)
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
doResume(null, exception)
|
||||
}
|
||||
|
||||
protected abstract fun doResume(data: Any?, exception: Throwable?)
|
||||
}
|
||||
Reference in New Issue
Block a user