Support release coroutines (#1909)
This commit is contained in:
committed by
GitHub
parent
d52a3f0c3d
commit
29cddb46bf
@@ -198,7 +198,7 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
||||
}
|
||||
|
||||
override fun createArguments(): K2NativeCompilerArguments {
|
||||
return K2NativeCompilerArguments().apply { coroutinesState = "enable" }
|
||||
return K2NativeCompilerArguments()
|
||||
}
|
||||
|
||||
override fun executableScriptFileName() = "kotlinc-native"
|
||||
|
||||
@@ -18,8 +18,6 @@ package org.jetbrains.kotlin.cli.bc
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.Argument
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
|
||||
class K2NativeCompilerArguments : CommonCompilerArguments() {
|
||||
// First go the options interesting to the general public.
|
||||
@@ -149,10 +147,5 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
|
||||
description = "Paths to friend modules"
|
||||
)
|
||||
var friendModules: String? = null
|
||||
|
||||
override fun configureLanguageFeatures(collector: MessageCollector) = super.configureLanguageFeatures(collector).also {
|
||||
it[LanguageFeature.InlineClasses] = LanguageFeature.State.ENABLED // TODO: remove after updating to 1.3.
|
||||
it[LanguageFeature.ReleaseCoroutines] = LanguageFeature.State.DISABLED
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+21
-4
@@ -327,9 +327,6 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
|
||||
val getContinuation = symbolTable.referenceSimpleFunction(
|
||||
context.getInternalFunctions("getContinuation").single())
|
||||
|
||||
val konanIntercepted = symbolTable.referenceSimpleFunction(
|
||||
context.getInternalFunctions("intercepted").single())
|
||||
|
||||
val konanSuspendCoroutineUninterceptedOrReturn = symbolTable.referenceSimpleFunction(
|
||||
context.getInternalFunctions("suspendCoroutineUninterceptedOrReturn").single())
|
||||
|
||||
@@ -347,7 +344,22 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
|
||||
.single()
|
||||
.getter!!
|
||||
|
||||
override val coroutineImpl = symbolTable.referenceClass(context.getInternalClass("CoroutineImpl"))
|
||||
override val coroutineImpl get() = TODO()
|
||||
|
||||
val baseContinuationImpl = symbolTable.referenceClass(
|
||||
builtIns.builtInsModule.findClassAcrossModuleDependencies(
|
||||
ClassId.topLevel(FqName("kotlin.coroutines.native.internal.BaseContinuationImpl")))!!
|
||||
)
|
||||
|
||||
val restrictedContinuationImpl = symbolTable.referenceClass(
|
||||
builtIns.builtInsModule.findClassAcrossModuleDependencies(
|
||||
ClassId.topLevel(FqName("kotlin.coroutines.native.internal.RestrictedContinuationImpl")))!!
|
||||
)
|
||||
|
||||
val continuationImpl = symbolTable.referenceClass(
|
||||
builtIns.builtInsModule.findClassAcrossModuleDependencies(
|
||||
ClassId.topLevel(FqName("kotlin.coroutines.native.internal.ContinuationImpl")))!!
|
||||
)
|
||||
|
||||
override val coroutineSuspendedGetter = symbolTable.referenceSimpleFunction(
|
||||
coroutinesIntrinsicsPackage
|
||||
@@ -355,6 +367,11 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
|
||||
.filterNot { it.isExpect }.single().getter!!
|
||||
)
|
||||
|
||||
val successOrFailure = symbolTable.referenceClass(
|
||||
builtIns.builtInsModule.findClassAcrossModuleDependencies(
|
||||
ClassId.topLevel(FqName("kotlin.SuccessOrFailure")))!!
|
||||
)
|
||||
|
||||
val refClass = symbolTable.referenceClass(context.getInternalClass("Ref"))
|
||||
|
||||
val kLocalDelegatedPropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedPropertyImpl)
|
||||
|
||||
+6
-7
@@ -1920,19 +1920,18 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private val coroutineImplDescriptor = context.ir.symbols.coroutineImpl.owner
|
||||
private val doResumeFunctionDescriptor = coroutineImplDescriptor.declarations
|
||||
.filterIsInstance<IrSimpleFunction>().single { it.name.asString() == "doResume" }
|
||||
private val invokeSuspendFunction = context.ir.symbols.baseContinuationImpl.owner.declarations
|
||||
.filterIsInstance<IrSimpleFunction>().single { it.name.asString() == "invokeSuspend" }
|
||||
|
||||
private fun getContinuation(): LLVMValueRef {
|
||||
val caller = functionGenerationContext.functionDescriptor!!
|
||||
return if (caller.isSuspend)
|
||||
codegen.param(caller, caller.allParameters.size) // The last argument.
|
||||
else {
|
||||
// Suspend call from non-suspend function - must be [CoroutineImpl].
|
||||
assert (doResumeFunctionDescriptor.symbol in (caller as IrSimpleFunction).overriddenSymbols,
|
||||
{ "Expected 'CoroutineImpl.doResume' but was '$caller'" })
|
||||
currentCodeContext.genGetValue(caller.dispatchReceiverParameter!!) // Coroutine itself is a continuation.
|
||||
// Suspend call from non-suspend function - must be [BaseContinuationImpl].
|
||||
assert ((caller as IrSimpleFunction).overrides(invokeSuspendFunction),
|
||||
{ "Expected 'BaseContinuationImpl.invokeSuspend' but was '$caller'" })
|
||||
currentCodeContext.genGetValue(caller.dispatchReceiverParameter!!)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -99,7 +99,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
||||
descriptor.resolveFakeOverride().original.let {
|
||||
when {
|
||||
it.isBuiltInIntercepted(context.config.configuration.languageVersionSettings) ->
|
||||
getFunctionDeclaration(context.ir.symbols.konanIntercepted.descriptor)
|
||||
error("Continuation.intercepted is not available with release coroutines")
|
||||
|
||||
it.isBuiltInSuspendCoroutineUninterceptedOrReturn(context.config.configuration.languageVersionSettings) ->
|
||||
getFunctionDeclaration(context.ir.symbols.konanSuspendCoroutineUninterceptedOrReturn.descriptor)
|
||||
|
||||
+88
-53
@@ -18,11 +18,11 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.getFunction
|
||||
import org.jetbrains.kotlin.backend.common.ir.createOverriddenDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||
@@ -242,7 +242,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
val irBuilder = context.createIrBuilder(irFunction.symbol, irFunction.startOffset, irFunction.endOffset)
|
||||
irFunction.body = irBuilder.irBlockBody(irFunction) {
|
||||
+irReturn(
|
||||
irCall(coroutine.doResumeFunction.symbol).apply {
|
||||
irCall(coroutine.invokeSuspendFunction.symbol).apply {
|
||||
dispatchReceiver = irCall(coroutine.coroutineConstructor.symbol).apply {
|
||||
val functionParameters = irFunction.explicitParameters
|
||||
functionParameters.forEachIndexed { index, argument ->
|
||||
@@ -251,8 +251,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
putValueArgument(functionParameters.size,
|
||||
irCall(getContinuation, listOf(irFunction.returnType)))
|
||||
}
|
||||
putValueArgument(0, irGetObject(symbols.unit)) // value
|
||||
putValueArgument(1, irNull()) // exception
|
||||
putValueArgument(0, irSuccess(irGetObject(symbols.unit)))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -262,7 +261,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
|
||||
private class BuiltCoroutine(val coroutineClass: IrClass,
|
||||
val coroutineConstructor: IrConstructor,
|
||||
val doResumeFunction: IrFunction)
|
||||
val invokeSuspendFunction: IrFunction)
|
||||
|
||||
private var coroutineId = 0
|
||||
|
||||
@@ -280,26 +279,28 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
|
||||
private var tempIndex = 0
|
||||
private var suspensionPointIdIndex = 0
|
||||
private lateinit var labelField: IrField
|
||||
private lateinit var suspendResult: IrVariable
|
||||
private lateinit var dataArgument: IrValueParameter
|
||||
private lateinit var exceptionArgument: IrValueParameter
|
||||
private lateinit var resultArgument: IrValueParameter
|
||||
private lateinit var coroutineClassDescriptor: ClassDescriptorImpl
|
||||
private lateinit var coroutineClass: IrClassImpl
|
||||
private lateinit var coroutineClassThis: IrValueParameter
|
||||
private lateinit var argumentToPropertiesMap: Map<ParameterDescriptor, IrField>
|
||||
|
||||
private val coroutineImplSymbol = symbols.coroutineImpl
|
||||
private val coroutineImplConstructorSymbol = coroutineImplSymbol.constructors.single()
|
||||
private val coroutineImplClassDescriptor = coroutineImplSymbol.descriptor
|
||||
private val create1Function = coroutineImplSymbol.owner.simpleFunctions()
|
||||
private val baseClass =
|
||||
(if (irFunction.isRestrictedSuspendFunction(context.config.configuration.languageVersionSettings)) {
|
||||
symbols.restrictedContinuationImpl
|
||||
} else {
|
||||
symbols.continuationImpl
|
||||
}).owner
|
||||
|
||||
private val baseClassConstructor = baseClass.constructors.single { it.valueParameters.size == 1 }
|
||||
private val create1Function = baseClass.simpleFunctions()
|
||||
.single { it.name.asString() == "create" && it.valueParameters.size == 1 }
|
||||
private val create1CompletionParameter = create1Function.valueParameters[0]
|
||||
|
||||
private val coroutineImplLabelGetterSymbol = coroutineImplSymbol.getPropertyGetter("label")!!
|
||||
private val coroutineImplLabelSetterSymbol = coroutineImplSymbol.getPropertySetter("label")!!
|
||||
|
||||
fun build(): BuiltCoroutine {
|
||||
val superTypes = mutableListOf<IrType>(coroutineImplSymbol.owner.defaultType)
|
||||
val superTypes = mutableListOf<IrType>(baseClass.defaultType)
|
||||
var suspendFunctionClass: IrClass? = null
|
||||
var functionClass: IrClass? = null
|
||||
var suspendFunctionClassTypeArguments: List<IrType>? = null
|
||||
@@ -340,16 +341,27 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
coroutineClass.createParameterDeclarations()
|
||||
coroutineClassThis = coroutineClass.thisReceiver!!
|
||||
|
||||
labelField = createField(
|
||||
irFunction.startOffset,
|
||||
irFunction.endOffset,
|
||||
symbols.nativePtrType,
|
||||
Name.identifier("label"),
|
||||
true,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
coroutineClass.descriptor
|
||||
)
|
||||
coroutineClass.addChild(labelField)
|
||||
|
||||
|
||||
val overriddenMap = mutableMapOf<CallableMemberDescriptor, CallableMemberDescriptor>()
|
||||
val coroutineConstructorBuilder = createConstructorBuilder()
|
||||
coroutineConstructorBuilder.initialize()
|
||||
|
||||
val doResumeFunction = coroutineImplSymbol.owner.simpleFunctions()
|
||||
.single { it.name.asString() == "doResume" }
|
||||
val doResumeMethodBuilder = createDoResumeMethodBuilder(doResumeFunction, coroutineClass)
|
||||
doResumeMethodBuilder.initialize()
|
||||
overriddenMap += doResumeFunction.descriptor to doResumeMethodBuilder.symbol.descriptor
|
||||
val invokeSuspendFunction = baseClass.simpleFunctions()
|
||||
.single { it.name.asString() == "invokeSuspend" }
|
||||
val invokeSuspendMethodBuilder = createInvokeSuspendMethodBuilder(invokeSuspendFunction, coroutineClass)
|
||||
invokeSuspendMethodBuilder.initialize()
|
||||
overriddenMap += invokeSuspendFunction.descriptor to invokeSuspendMethodBuilder.symbol.descriptor
|
||||
|
||||
var coroutineFactoryConstructorBuilder: SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>? = null
|
||||
var createMethodBuilder: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>? = null
|
||||
@@ -358,7 +370,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
// Suspend lambda - create factory methods.
|
||||
coroutineFactoryConstructorBuilder = createFactoryConstructorBuilder(boundFunctionParameters!!)
|
||||
|
||||
val createFunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope
|
||||
val createFunctionDescriptor = baseClass.descriptor.unsubstitutedMemberScope
|
||||
.getContributedFunctions(Name.identifier("create"), NoLookupLocation.FROM_BACKEND)
|
||||
.atMostOne { it.valueParameters.size == unboundFunctionParameters!!.size + 1 }
|
||||
createMethodBuilder = createCreateMethodBuilder(
|
||||
@@ -378,7 +390,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
suspendFunctionInvokeFunctionDescriptor = suspendInvokeFunctionDescriptor,
|
||||
functionInvokeFunctionDescriptor = invokeFunctionDescriptor,
|
||||
createFunction = createMethodBuilder.ir,
|
||||
doResumeFunction = doResumeMethodBuilder.ir,
|
||||
invokeSuspendFunction = invokeSuspendMethodBuilder.ir,
|
||||
coroutineClass = coroutineClass)
|
||||
}
|
||||
|
||||
@@ -398,7 +410,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
coroutineClass.addChild(it.ir)
|
||||
}
|
||||
|
||||
coroutineClass.addChild(doResumeMethodBuilder.ir)
|
||||
coroutineClass.addChild(invokeSuspendMethodBuilder.ir)
|
||||
|
||||
coroutineClass.setSuperSymbolsAndAddFakeOverrides(superTypes)
|
||||
|
||||
@@ -406,7 +418,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
coroutineClass = coroutineClass,
|
||||
coroutineConstructor = coroutineFactoryConstructorBuilder?.ir
|
||||
?: coroutineConstructorBuilder.ir,
|
||||
doResumeFunction = doResumeMethodBuilder.ir)
|
||||
invokeSuspendFunction = invokeSuspendMethodBuilder.ir)
|
||||
}
|
||||
|
||||
private fun createConstructorBuilder()
|
||||
@@ -427,7 +439,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl
|
||||
constructorParameters = (
|
||||
functionParameters
|
||||
+ coroutineImplConstructorSymbol.owner.valueParameters[0] // completion.
|
||||
+ baseClassConstructor.valueParameters[0] // completion.
|
||||
).mapIndexed { index, parameter ->
|
||||
|
||||
val parameterDescriptor = parameter.descriptor.copyAsValueParameter(descriptor, index)
|
||||
@@ -464,10 +476,13 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
val completionParameter = valueParameters.last()
|
||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply {
|
||||
baseClassConstructor.symbol, baseClassConstructor.descriptor).apply {
|
||||
putValueArgument(0, irGet(completionParameter))
|
||||
}
|
||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol, context.irBuiltIns.unitType)
|
||||
|
||||
+irSetField(irGet(coroutineClassThis), labelField, irCall(symbols.getNativeNullPtr.owner))
|
||||
|
||||
functionParameters.forEachIndexed { index, parameter ->
|
||||
+irSetField(
|
||||
irGet(coroutineClassThis),
|
||||
@@ -523,7 +538,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||
body = irBuilder.irBlockBody {
|
||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset, context.irBuiltIns.unitType,
|
||||
coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply {
|
||||
baseClassConstructor.symbol, baseClassConstructor.descriptor).apply {
|
||||
putValueArgument(0, irNull()) // Completion.
|
||||
}
|
||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol,
|
||||
@@ -573,8 +588,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* visibility = */ Visibilities.PRIVATE).apply {
|
||||
if (superFunctionDescriptor != null) {
|
||||
overriddenDescriptors += superFunctionDescriptor.overriddenDescriptors
|
||||
overriddenDescriptors += superFunctionDescriptor
|
||||
overriddenDescriptors = listOf(superFunctionDescriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -622,7 +636,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
private fun createInvokeMethodBuilder(suspendFunctionInvokeFunctionDescriptor: FunctionDescriptor,
|
||||
functionInvokeFunctionDescriptor: FunctionDescriptor,
|
||||
createFunction: IrFunction,
|
||||
doResumeFunction: IrFunction,
|
||||
invokeSuspendFunction: IrFunction,
|
||||
coroutineClass: IrClass)
|
||||
= object: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||
|
||||
@@ -679,7 +693,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||
+irReturn(
|
||||
irCall(doResumeFunction).apply {
|
||||
irCall(invokeSuspendFunction).apply {
|
||||
dispatchReceiver = irCall(createFunction).apply {
|
||||
dispatchReceiver = irGet(thisReceiver)
|
||||
valueParameters.forEachIndexed { index, parameter ->
|
||||
@@ -688,8 +702,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
putValueArgument(valueParameters.size,
|
||||
irCall(getContinuation, listOf(returnType)))
|
||||
}
|
||||
putValueArgument(0, irGetObject(symbols.unit)) // value
|
||||
putValueArgument(1, irNull()) // exception
|
||||
putValueArgument(0, irSuccess(irGetObject(symbols.unit)))
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -709,11 +722,11 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
coroutineClass.addChild(it)
|
||||
}
|
||||
|
||||
private fun createDoResumeMethodBuilder(doResumeFunction: IrFunction, coroutineClass: IrClass)
|
||||
private fun createInvokeSuspendMethodBuilder(invokeSuspendFunction: IrFunction, coroutineClass: IrClass)
|
||||
= object: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||
|
||||
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
||||
doResumeFunction.descriptor.createOverriddenDescriptor(coroutineClassDescriptor)
|
||||
invokeSuspendFunction.descriptor.createOverriddenDescriptor(coroutineClassDescriptor)
|
||||
)
|
||||
|
||||
override fun doInitialize() { }
|
||||
@@ -733,17 +746,13 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
|
||||
this.createDispatchReceiverParameter()
|
||||
|
||||
doResumeFunction.valueParameters.mapIndexedTo(this.valueParameters) { index, it ->
|
||||
invokeSuspendFunction.valueParameters.mapIndexedTo(this.valueParameters) { index, it ->
|
||||
it.copy(descriptor.valueParameters[index])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dataArgument = function.valueParameters[0]
|
||||
exceptionArgument = function.valueParameters[1]
|
||||
|
||||
val label = coroutineImplSymbol.owner.declarations.filterIsInstance<IrProperty>()
|
||||
.single { it.name.asString() == "label" }
|
||||
resultArgument = function.valueParameters.single()
|
||||
|
||||
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
|
||||
function.body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||
@@ -756,7 +765,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
, context.irBuiltIns.anyNType)
|
||||
|
||||
// Extract all suspend calls to temporaries in order to make correct jumps to them.
|
||||
originalBody.transformChildrenVoid(ExpressionSlicer(label.getter!!.returnType))
|
||||
originalBody.transformChildrenVoid(ExpressionSlicer(labelField.type))
|
||||
|
||||
val liveLocals = computeLivenessAtSuspensionPoints(originalBody)
|
||||
|
||||
@@ -837,10 +846,11 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
val variable = localsMap[it.descriptor] ?: it
|
||||
+irSetField(irGet(thisReceiver), localToPropertyMap[it.symbol]!!, irGet(variable))
|
||||
}
|
||||
+irCall(coroutineImplLabelSetterSymbol).apply {
|
||||
dispatchReceiver = irGet(thisReceiver)
|
||||
putValueArgument(0, irGet(suspensionPoint.suspensionPointIdParameter))
|
||||
}
|
||||
+irSetField(
|
||||
irGet(thisReceiver),
|
||||
labelField,
|
||||
irGet(suspensionPoint.suspensionPointIdParameter)
|
||||
)
|
||||
}
|
||||
}
|
||||
restoreState.symbol -> {
|
||||
@@ -865,11 +875,9 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
type = context.irBuiltIns.unitType,
|
||||
suspensionPointId = irCall(coroutineImplLabelGetterSymbol).apply {
|
||||
dispatchReceiver = irGet(function.dispatchReceiverParameter!!)
|
||||
},
|
||||
suspensionPointId = irGetField(irGet(function.dispatchReceiverParameter!!), labelField),
|
||||
result = irBlock(startOffset, endOffset) {
|
||||
+irThrowIfNotNull(exceptionArgument) // Coroutine might start with an exception.
|
||||
+irThrowIfNotNull(irExceptionOrNull(irGet(resultArgument))) // Coroutine might start with an exception.
|
||||
statements.forEach { +it }
|
||||
})
|
||||
if (irFunction.returnType.isUnit())
|
||||
@@ -1107,8 +1115,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
},
|
||||
resumeResult = irBlock(startOffset, endOffset) {
|
||||
+irCall(restoreState)
|
||||
+irThrowIfNotNull(exceptionArgument)
|
||||
+irGet(dataArgument)
|
||||
+irGetOrThrow(irGet(resultArgument))
|
||||
})
|
||||
val expressionResult = when {
|
||||
suspendCall.type.isUnit() -> irImplicitCoercionToUnit(suspensionPoint)
|
||||
@@ -1188,7 +1195,11 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
irIfThen(irEqeqeq(irGet(value), irCall(symbols.coroutineSuspendedGetter)),
|
||||
irReturn(irGet(value)))
|
||||
|
||||
private fun IrBuilderWithScope.irThrowIfNotNull(exception: IrValueDeclaration) =
|
||||
private fun IrBuilderWithScope.irThrowIfNotNull(exception: IrExpression) = irLetS(exception) {
|
||||
irThrowIfNotNull(it.owner)
|
||||
}
|
||||
|
||||
fun IrBuilderWithScope.irThrowIfNotNull(exception: IrValueDeclaration) =
|
||||
irIfThen(irNot(irEqeqeq(irGet(exception), irNull())),
|
||||
irThrow(irImplicitCast(irGet(exception), exception.type.makeNotNull())))
|
||||
|
||||
@@ -1200,6 +1211,30 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.irGetOrThrow(successOrFailure: IrExpression): IrExpression {
|
||||
// TODO: consider inlining getOrThrow function body here.
|
||||
val successOrFailureClass = symbols.successOrFailure.owner
|
||||
val getOrThrow = successOrFailureClass.simpleFunctions().single { it.name.asString() == "getOrThrow" }
|
||||
return irCall(getOrThrow).apply {
|
||||
dispatchReceiver = successOrFailure
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.irExceptionOrNull(successOrFailure: IrExpression): IrExpression {
|
||||
val successOrFailureClass = symbols.successOrFailure.owner
|
||||
val exceptionOrNull = successOrFailureClass.simpleFunctions().single { it.name.asString() == "exceptionOrNull" }
|
||||
return irCall(exceptionOrNull).apply {
|
||||
dispatchReceiver = successOrFailure
|
||||
}
|
||||
}
|
||||
|
||||
fun IrBlockBodyBuilder.irSuccess(value: IrExpression): IrCall {
|
||||
val createSuccessOrFailure = symbols.successOrFailure.owner.constructors.single { it.isPrimary }
|
||||
return irCall(createSuccessOrFailure).apply {
|
||||
putValueArgument(0, value)
|
||||
}
|
||||
}
|
||||
|
||||
private open class VariablesScopeTracker: IrElementVisitorVoid {
|
||||
|
||||
protected val scopeStack = mutableListOf<MutableSet<IrVariable>>(mutableSetOf())
|
||||
|
||||
+4
-4
@@ -403,9 +403,9 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
}
|
||||
}
|
||||
|
||||
private val doResumeFunctionSymbol =
|
||||
context.ir.symbols.coroutineImpl.owner.declarations
|
||||
.filterIsInstance<IrSimpleFunction>().single { it.name.asString() == "doResume" }.symbol
|
||||
private val invokeSuspendFunctionSymbol =
|
||||
context.ir.symbols.baseContinuationImpl.owner.declarations
|
||||
.filterIsInstance<IrSimpleFunction>().single { it.name.asString() == "invokeSuspend" }.symbol
|
||||
|
||||
private val getContinuationSymbol = context.ir.symbols.getContinuation
|
||||
private val continuationType = getContinuationSymbol.owner.returnType
|
||||
@@ -439,7 +439,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
|
||||
descriptor.isSuspend -> DataFlowIR.Node.Parameter(allParameters.size)
|
||||
|
||||
doResumeFunctionSymbol in descriptor.overriddenSymbols -> // <this> is a CoroutineImpl inheritor.
|
||||
descriptor.overrides(invokeSuspendFunctionSymbol.owner) -> // <this> is a ContinuationImpl inheritor.
|
||||
templateParameters[descriptor.dispatchReceiverParameter!!] // It is its own continuation.
|
||||
|
||||
else -> null
|
||||
|
||||
+3
-3
@@ -259,7 +259,7 @@ class KonanDescriptorSerializer private constructor(
|
||||
if (requirement != null) {
|
||||
builder.addAllVersionRequirement(requirement)
|
||||
}
|
||||
else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
|
||||
if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
|
||||
builder.addVersionRequirement(writeVersionRequirementDependingOnCoroutinesVersion())
|
||||
}
|
||||
|
||||
@@ -342,7 +342,7 @@ class KonanDescriptorSerializer private constructor(
|
||||
if (requirement != null) {
|
||||
builder.addAllVersionRequirement(requirement)
|
||||
}
|
||||
else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
|
||||
if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
|
||||
builder.addVersionRequirement(writeVersionRequirementDependingOnCoroutinesVersion())
|
||||
}
|
||||
|
||||
@@ -380,7 +380,7 @@ class KonanDescriptorSerializer private constructor(
|
||||
if (requirement != null) {
|
||||
builder.addAllVersionRequirement(requirement)
|
||||
}
|
||||
else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
|
||||
if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
|
||||
builder.addVersionRequirement(writeVersionRequirementDependingOnCoroutinesVersion())
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -17,6 +17,8 @@
|
||||
package org.jetbrains.kotlin.backend.konan.serialization
|
||||
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
@@ -102,6 +104,9 @@ internal class KonanSerializerExtension(val context: Context, override val metad
|
||||
return IrSerializer(
|
||||
context, inlineDescriptorTable, stringTable, serializer, descriptor).serializeInlineBody()
|
||||
}
|
||||
|
||||
override fun releaseCoroutines(): Boolean =
|
||||
context.config.configuration.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
|
||||
}
|
||||
|
||||
internal interface IrAwareExtension {
|
||||
|
||||
+17
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
||||
import org.jetbrains.kotlin.backend.konan.KonanCompilationException
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
@@ -50,6 +51,8 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.OverridingStrategy
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.isRestrictsSuspensionReceiver
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
||||
@@ -721,3 +724,17 @@ val IrType.isSimpleTypeWithQuestionMark: Boolean
|
||||
|
||||
fun IrClass.defaultOrNullableType(hasQuestionMark: Boolean) =
|
||||
if (hasQuestionMark) this.defaultType.makeNullable() else this.defaultType
|
||||
|
||||
fun FunctionDescriptor.createOverriddenDescriptor(owner: ClassDescriptor, final: Boolean = true): FunctionDescriptor {
|
||||
return this.newCopyBuilder()
|
||||
.setOwner(owner)
|
||||
.setCopyOverrides(true)
|
||||
.setModality(if (final) Modality.FINAL else Modality.OPEN)
|
||||
.setDispatchReceiverParameter(owner.thisAsReceiverParameter)
|
||||
.build()!!.apply {
|
||||
overriddenDescriptors = listOf(this@createOverriddenDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
fun IrFunction.isRestrictedSuspendFunction(languageVersionSettings: LanguageVersionSettings): Boolean =
|
||||
this.descriptor.extensionReceiverParameter?.type?.isRestrictsSuspensionReceiver(languageVersionSettings) == true
|
||||
|
||||
@@ -1329,16 +1329,19 @@ task coroutines_controlFlow_finally4(type: RunKonanTest) {
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_finally5(type: RunKonanTest) {
|
||||
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
|
||||
goldValue = "s1\nf2\nfinally\n1\n"
|
||||
source = "codegen/coroutines/controlFlow_finally5.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_finally6(type: RunKonanTest) {
|
||||
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
|
||||
goldValue = "s1\nfinally\nerror\n0\n"
|
||||
source = "codegen/coroutines/controlFlow_finally6.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_finally7(type: RunKonanTest) {
|
||||
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
|
||||
goldValue = "s1\nf2\nfinally1\ns2\nfinally2\n42\n"
|
||||
source = "codegen/coroutines/controlFlow_finally7.kt"
|
||||
}
|
||||
@@ -1364,21 +1367,25 @@ task coroutines_controlFlow_tryCatch1(type: RunKonanTest) {
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_tryCatch2(type: RunKonanTest) {
|
||||
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
|
||||
goldValue = "s1\n42\n"
|
||||
source = "codegen/coroutines/controlFlow_tryCatch2.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_tryCatch3(type: RunKonanTest) {
|
||||
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
|
||||
goldValue = "s2\nf2\n1\n"
|
||||
source = "codegen/coroutines/controlFlow_tryCatch3.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_tryCatch4(type: RunKonanTest) {
|
||||
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
|
||||
goldValue = "s2\nf2\n1\n"
|
||||
source = "codegen/coroutines/controlFlow_tryCatch4.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_tryCatch5(type: RunKonanTest) {
|
||||
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
|
||||
goldValue = "s2\ns1\nError\n42\n"
|
||||
source = "codegen/coroutines/controlFlow_tryCatch5.kt"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package codegen.controlflow.for_loops_coroutines
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.*
|
||||
|
||||
@Test fun runTest() {
|
||||
val sq = buildSequence {
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.anonymousObject
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun suspendHere(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun suspendHere(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.controlFlow_finally1
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.controlFlow_finally2
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.controlFlow_finally3
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.controlFlow_finally4
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.controlFlow_finally5
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resumeWithException(Error())
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.controlFlow_finally6
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resumeWithException(Error("error"))
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,22 +2,21 @@ package codegen.coroutines.controlFlow_finally7
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resumeWithException(Error())
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
suspend fun s2(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s2(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s2")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.controlFlow_if1
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.controlFlow_if2
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.controlFlow_inline1
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.controlFlow_inline2
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.controlFlow_inline3
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.controlFlow_tryCatch1
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.controlFlow_tryCatch2
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,22 +2,21 @@ package codegen.coroutines.controlFlow_tryCatch3
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
suspend fun s2(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s2(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s2")
|
||||
x.resumeWithException(Error())
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,22 +2,21 @@ package codegen.coroutines.controlFlow_tryCatch4
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
suspend fun s2(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s2(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s2")
|
||||
x.resumeWithException(Error())
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,22 +2,21 @@ package codegen.coroutines.controlFlow_tryCatch5
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
suspend fun s2(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s2(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s2")
|
||||
x.resumeWithException(Error("Error"))
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,28 +2,27 @@ package codegen.coroutines.controlFlow_while1
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
suspend fun s2(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s2(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s2")
|
||||
x.resumeWithException(Error("Error"))
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
suspend fun s3(value: Int): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s3(value: Int): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s3")
|
||||
x.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,28 +2,27 @@ package codegen.coroutines.controlFlow_while2
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
suspend fun s2(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s2(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s2")
|
||||
x.resumeWithException(Error("Error"))
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
suspend fun s3(value: Int): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s3(value: Int): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s3")
|
||||
x.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,13 +2,12 @@ package codegen.coroutines.coroutineContext1
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
|
||||
@@ -2,13 +2,12 @@ package codegen.coroutines.coroutineContext2
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.correctOrder1
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,13 +2,12 @@ package codegen.coroutines.degenerate1
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1() {
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.degenerate2
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Unit = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Unit = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(Unit)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.returnsUnit1
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun s1(): Unit = suspendCoroutineOrReturn { x ->
|
||||
suspend fun s1(): Unit = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
println("s1")
|
||||
x.resume(Unit)
|
||||
COROUTINE_SUSPENDED
|
||||
|
||||
@@ -2,16 +2,15 @@ package codegen.coroutines.simple
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
suspend fun suspendHere(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun suspendHere(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
@@ -2,17 +2,16 @@ package codegen.coroutines.withReceiver
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
class Controller {
|
||||
suspend fun suspendHere(): Int = suspendCoroutineOrReturn { x ->
|
||||
suspend fun suspendHere(): Int = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
x.resume(42)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
@@ -151,59 +151,47 @@ abstract class KonanTest extends JavaExec {
|
||||
}
|
||||
|
||||
void createCoroutineUtil(String file) {
|
||||
StringBuilder text = new StringBuilder("import kotlin.coroutines.experimental.*\n")
|
||||
StringBuilder text = new StringBuilder("import kotlin.coroutines.*\n")
|
||||
text.append(
|
||||
"""
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
fun <T> handleResultContinuation(x: (T) -> Unit): Continuation<T> = object: Continuation<T> {
|
||||
override val context = EmptyCoroutineContext
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
|
||||
override fun resume(data: T) = x(data)
|
||||
override fun resumeWith(result: SuccessOrFailure<T>) { x(result.getOrThrow()) }
|
||||
}
|
||||
|
||||
fun handleExceptionContinuation(x: (Throwable) -> Unit): Continuation<Any?> = object: Continuation<Any?> {
|
||||
override val context = EmptyCoroutineContext
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) {
|
||||
val exception = result.exceptionOrNull() ?: return
|
||||
x(exception)
|
||||
}
|
||||
|
||||
override fun resume(data: Any?) { }
|
||||
}
|
||||
""" )
|
||||
createFile(file, text.toString())
|
||||
}
|
||||
|
||||
String createTextForHelpers() {
|
||||
def coroutinesPackage = "kotlin.coroutines.experimental"
|
||||
def coroutinesPackage = "kotlin.coroutines"
|
||||
|
||||
def emptyContinuationBody =
|
||||
"""
|
||||
|override fun resume(data: Any?) {}
|
||||
|override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
|override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
""".stripMargin()
|
||||
|
||||
def handleResultContinuationBody = """
|
||||
|override fun resumeWithException(exception: Throwable) {
|
||||
| throw exception
|
||||
|}
|
||||
|
|
||||
|override fun resume(data: T) = x(data)
|
||||
|override fun resumeWith(result: SuccessOrFailure<T>) { x(result.getOrThrow()) }
|
||||
""".stripMargin()
|
||||
|
||||
def handleExceptionContinuationBody = """
|
||||
|override fun resumeWithException(exception: Throwable) {
|
||||
| x(exception)
|
||||
|override fun resumeWith(result: SuccessOrFailure<Any?>) {
|
||||
| val exception = result.exceptionOrNull() ?: return
|
||||
| x(exception)
|
||||
|}
|
||||
|
|
||||
|override fun resume(data: Any?) {}
|
||||
""".stripMargin()
|
||||
|
||||
return """
|
||||
@@ -228,6 +216,16 @@ fun handleExceptionContinuation(x: (Throwable) -> Unit): Continuation<Any?> = ob
|
||||
|
|
||||
|abstract class ContinuationAdapter<in T> : Continuation<T> {
|
||||
| override val context: CoroutineContext = EmptyCoroutineContext
|
||||
| override fun resumeWith(result: SuccessOrFailure<T>) {
|
||||
| if (result.isSuccess) {
|
||||
| resume(result.getOrThrow())
|
||||
| } else {
|
||||
| resumeWithException(result.exceptionOrNull()!!)
|
||||
| }
|
||||
| }
|
||||
|
|
||||
| abstract fun resumeWithException(exception: Throwable)
|
||||
| abstract fun resume(value: T)
|
||||
|}
|
||||
""".stripMargin()
|
||||
}
|
||||
@@ -741,7 +739,7 @@ class RunExternalTestGroup extends RunStandaloneKonanTest {
|
||||
for (String filePath : result) {
|
||||
def text = project.file(filePath).text
|
||||
if (text.contains('COROUTINES_PACKAGE')) {
|
||||
text = text.replace('COROUTINES_PACKAGE', 'kotlin.coroutines.experimental')
|
||||
text = text.replace('COROUTINES_PACKAGE', 'kotlin.coroutines')
|
||||
}
|
||||
def pkg = null
|
||||
if (text =~ packagePattern) {
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2010-2018 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.coroutines.native.internal
|
||||
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.CoroutineSingletons
|
||||
|
||||
@SinceKotlin("1.3")
|
||||
internal abstract class BaseContinuationImpl(
|
||||
// This is `public val` so that it is private on JVM and cannot be modified by untrusted code, yet
|
||||
// it has a public getter (since even untrusted code is allowed to inspect its call stack).
|
||||
public val completion: Continuation<Any?>?
|
||||
) : Continuation<Any?>, Serializable {
|
||||
// This implementation is final. This fact is used to unroll resumeWith recursion.
|
||||
public final override fun resumeWith(result: SuccessOrFailure<Any?>) {
|
||||
// Invoke "resume" debug probe only once, even if previous frames are "resumed" in the loop below, too
|
||||
probeCoroutineResumed(this)
|
||||
// This loop unrolls recursion in current.resumeWith(param) to make saner and shorter stack traces on resume
|
||||
var current = this
|
||||
var param = result
|
||||
while (true) {
|
||||
with(current) {
|
||||
val completion = completion!! // fail fast when trying to resume continuation without completion
|
||||
val outcome: SuccessOrFailure<Any?> =
|
||||
try {
|
||||
val outcome = invokeSuspend(param)
|
||||
if (outcome === CoroutineSingletons.COROUTINE_SUSPENDED) return
|
||||
SuccessOrFailure.success(outcome)
|
||||
} catch (exception: Throwable) {
|
||||
SuccessOrFailure.failure(exception)
|
||||
}
|
||||
releaseIntercepted() // this state machine instance is terminating
|
||||
if (completion is BaseContinuationImpl) {
|
||||
// unrolling recursion via loop
|
||||
current = completion
|
||||
param = outcome
|
||||
} else {
|
||||
// top-level completion reached -- invoke and return
|
||||
completion.resumeWith(outcome)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun invokeSuspend(result: SuccessOrFailure<Any?>): Any?
|
||||
|
||||
protected open fun releaseIntercepted() {
|
||||
// does nothing here, overridden in ContinuationImpl
|
||||
}
|
||||
|
||||
public open fun create(completion: Continuation<*>): Continuation<Unit> {
|
||||
throw UnsupportedOperationException("create(Continuation) has not been overridden")
|
||||
}
|
||||
|
||||
public open fun create(value: Any?, completion: Continuation<*>): Continuation<Unit> {
|
||||
throw UnsupportedOperationException("create(Any?;Continuation) has not been overridden")
|
||||
}
|
||||
|
||||
public override fun toString(): String {
|
||||
// todo: how continuation shall be rendered?
|
||||
return "Continuation @ ${this::class.simpleName}"
|
||||
}
|
||||
}
|
||||
|
||||
@SinceKotlin("1.3")
|
||||
// State machines for named restricted suspend functions extend from this class
|
||||
internal abstract class RestrictedContinuationImpl(
|
||||
completion: Continuation<Any?>?
|
||||
) : BaseContinuationImpl(completion) {
|
||||
init {
|
||||
completion?.let {
|
||||
require(it.context === EmptyCoroutineContext) {
|
||||
"Coroutines with restricted suspension must have EmptyCoroutineContext"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
}
|
||||
|
||||
@SinceKotlin("1.3")
|
||||
// State machines for named suspend functions extend from this class
|
||||
internal abstract class ContinuationImpl(
|
||||
completion: Continuation<Any?>?,
|
||||
private val _context: CoroutineContext?
|
||||
) : BaseContinuationImpl(completion) {
|
||||
constructor(completion: Continuation<Any?>?) : this(completion, completion?.context)
|
||||
|
||||
public override val context: CoroutineContext
|
||||
get() = _context!!
|
||||
|
||||
private var intercepted: Continuation<Any?>? = null
|
||||
|
||||
public fun intercepted(): Continuation<Any?> =
|
||||
intercepted
|
||||
?: (context[ContinuationInterceptor]?.interceptContinuation(this) ?: this)
|
||||
.also { intercepted = it }
|
||||
|
||||
protected override fun releaseIntercepted() {
|
||||
val intercepted = intercepted
|
||||
if (intercepted != null && intercepted !== this) {
|
||||
context[ContinuationInterceptor]!!.releaseInterceptedContinuation(intercepted)
|
||||
}
|
||||
this.intercepted = CompletedContinuation // just in case
|
||||
}
|
||||
}
|
||||
|
||||
internal object CompletedContinuation : Continuation<Any?> {
|
||||
override val context: CoroutineContext
|
||||
get() = error("This continuation is already complete")
|
||||
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) {
|
||||
error("This continuation is already complete")
|
||||
}
|
||||
|
||||
override fun toString(): String = "This continuation is already complete"
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2010-2018 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.coroutines.native.internal
|
||||
|
||||
// TODO: support coroutines debugging in Kotlin/Native.
|
||||
|
||||
import kotlin.coroutines.Continuation
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
/**
|
||||
* This probe is invoked when coroutine is being created and it can replace completion
|
||||
* with its own wrapped object to intercept completion of this coroutine.
|
||||
*
|
||||
* This probe is invoked from stdlib implementation of [createCoroutineUnintercepted] function.
|
||||
*
|
||||
* Once created, coroutine is repeatedly [resumed][probeCoroutineResumed] and [suspended][probeCoroutineSuspended],
|
||||
* until it is complete. On completion, the object that was returned by this probe is invoked.
|
||||
*
|
||||
* ```
|
||||
* +-------+ probeCoroutineCreated +-----------+
|
||||
* | START | ---------------------->| SUSPENDED |
|
||||
* +-------+ +-----------+
|
||||
* probeCoroutineResumed | ^ probeCoroutineSuspended
|
||||
* V |
|
||||
* +------------+ completion invoked +-----------+
|
||||
* | RUNNING | ------------------->| COMPLETED |
|
||||
* +------------+ +-----------+
|
||||
* ```
|
||||
*
|
||||
* While the coroutine is resumed and suspended, it is represented by the pointer to its `frame`
|
||||
* which always extends [BaseContinuationImpl] and represents a pointer to the topmost frame of the
|
||||
* coroutine. Each [BaseContinuationImpl] object has [completion][BaseContinuationImpl.completion] reference
|
||||
* that points either to another frame (extending [BaseContinuationImpl]) or to the completion object
|
||||
* that was returned by this `probeCoroutineCreated` function.
|
||||
*
|
||||
* When coroutine is [suspended][probeCoroutineSuspended], then it is later [resumed][probeCoroutineResumed]
|
||||
* with a reference to the same frame. However, while coroutine is running it can unwind its frames and
|
||||
* invoke other suspending functions, so its next suspension can happen with a different frame pointer.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
internal fun <T> probeCoroutineCreated(completion: Continuation<T>): Continuation<T> {
|
||||
return completion
|
||||
}
|
||||
|
||||
/**
|
||||
* This probe is invoked when coroutine is resumed using [Continuation.resumeWith].
|
||||
*
|
||||
* This probe is invoked from stdlib implementation of [BaseContinuationImpl.resumeWith] function.
|
||||
*
|
||||
* Coroutines machinery implementation guarantees that the actual [frame] instance extends
|
||||
* [BaseContinuationImpl] class, despite the fact that the declared type of [frame]
|
||||
* parameter in this function is `Continuation<*>`. See [probeCoroutineCreated] for details.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
internal fun probeCoroutineResumed(frame: Continuation<*>) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This probe is invoked when coroutine is suspended using [suspendCoroutineUninterceptedOrReturn], that is
|
||||
* when the corresponding `block` returns [COROUTINE_SUSPENDED].
|
||||
*
|
||||
* This probe is invoked from compiler-generated intrinsic for [suspendCoroutineUninterceptedOrReturn] function.
|
||||
*
|
||||
* Coroutines machinery implementation guarantees that the actual [frame] instance extends
|
||||
* [BaseContinuationImpl] class, despite the fact that the declared type of [frame]
|
||||
* parameter in this function is `Continuation<*>`. See [probeCoroutineCreated] for details.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
internal fun probeCoroutineSuspended(frame: Continuation<*>) {
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package kotlin.coroutines
|
||||
|
||||
// TODO: implement them right.
|
||||
import kotlin.*
|
||||
import kotlin.coroutines.intrinsics.CoroutineSingletons.*
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
internal actual class SafeContinuation<in T>
|
||||
@@ -24,14 +26,37 @@ internal actual constructor(
|
||||
private val delegate: Continuation<T>,
|
||||
initialResult: Any?
|
||||
) : Continuation<T> {
|
||||
|
||||
actual override val context: CoroutineContext
|
||||
get() = TODO("unimplemented")
|
||||
@PublishedApi
|
||||
internal actual constructor(delegate: Continuation<T>) : this(delegate, /*UNDECIDED*/ null)
|
||||
internal actual constructor(delegate: Continuation<T>) : this(delegate, UNDECIDED)
|
||||
|
||||
public actual override val context: CoroutineContext
|
||||
get() = delegate.context
|
||||
|
||||
private var result: Any? = initialResult
|
||||
|
||||
public actual override fun resumeWith(result: SuccessOrFailure<T>) {
|
||||
val cur = this.result
|
||||
when {
|
||||
cur === UNDECIDED -> this.result = result.value
|
||||
cur === COROUTINE_SUSPENDED -> {
|
||||
this.result = RESUMED
|
||||
delegate.resumeWith(result)
|
||||
}
|
||||
else -> throw IllegalStateException("Already resumed")
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal actual fun getOrThrow(): Any? = TODO("unimplemented")
|
||||
|
||||
actual override fun resumeWith(result: SuccessOrFailure<T>):Unit = TODO("unimplemented")
|
||||
internal actual fun getOrThrow(): Any? {
|
||||
val result = this.result
|
||||
if (result === UNDECIDED) {
|
||||
this.result = COROUTINE_SUSPENDED
|
||||
return COROUTINE_SUSPENDED
|
||||
}
|
||||
return when {
|
||||
result === RESUMED -> COROUTINE_SUSPENDED // already called continuation, indicate COROUTINE_SUSPENDED upstream
|
||||
result is SuccessOrFailure.Failure -> throw result.exception
|
||||
else -> result // either COROUTINE_SUSPENDED or data
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,9 +17,6 @@
|
||||
package kotlin.coroutines.experimental.intrinsics
|
||||
|
||||
import kotlin.coroutines.experimental.Continuation
|
||||
import kotlin.coroutines.experimental.CoroutineContext
|
||||
import kotlin.coroutines.experimental.processBareContinuationResume
|
||||
import kotlin.native.internal.*
|
||||
|
||||
|
||||
/**
|
||||
@@ -34,13 +31,7 @@ import kotlin.native.internal.*
|
||||
*/
|
||||
public actual fun <T> (suspend () -> T).createCoroutineUnchecked(
|
||||
completion: Continuation<T>
|
||||
): Continuation<Unit> =
|
||||
if (this !is CoroutineImpl)
|
||||
buildContinuationByInvokeCall(completion) {
|
||||
@Suppress("UNCHECKED_CAST") (this as Function1<Continuation<T>, Any?>).invoke(completion)
|
||||
}
|
||||
else
|
||||
(this.create(completion) as CoroutineImpl).facade
|
||||
): Continuation<Unit> = errorExperimentalCoroutinesAreNoLongerSupported()
|
||||
|
||||
/**
|
||||
* Creates a coroutine with receiver type [R] and result type [T].
|
||||
@@ -55,35 +46,7 @@ public actual fun <T> (suspend () -> T).createCoroutineUnchecked(
|
||||
public actual fun <R, T> (suspend R.() -> T).createCoroutineUnchecked(
|
||||
receiver: R,
|
||||
completion: Continuation<T>
|
||||
): Continuation<Unit> =
|
||||
if (this !is CoroutineImpl)
|
||||
buildContinuationByInvokeCall(completion) {
|
||||
@Suppress("UNCHECKED_CAST") (this as Function2<R, Continuation<T>, Any?>).invoke(receiver, completion)
|
||||
}
|
||||
else
|
||||
(this.create(receiver, completion) as CoroutineImpl).facade
|
||||
|
||||
// INTERNAL DEFINITIONS
|
||||
private inline fun <T> buildContinuationByInvokeCall(
|
||||
completion: Continuation<T>,
|
||||
crossinline block: () -> Any?
|
||||
): Continuation<Unit> {
|
||||
val continuation =
|
||||
object : Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = completion.context
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
processBareContinuationResume(completion, block)
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
completion.resumeWithException(exception)
|
||||
}
|
||||
}
|
||||
|
||||
return interceptContinuationIfNeeded(completion.context, continuation)
|
||||
}
|
||||
): Continuation<Unit> = errorExperimentalCoroutinesAreNoLongerSupported()
|
||||
|
||||
/**
|
||||
* Starts unintercepted coroutine without receiver and with result type [T] and executes it until its first suspension.
|
||||
@@ -96,7 +59,7 @@ private inline fun <T> buildContinuationByInvokeCall(
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrReturn(
|
||||
completion: Continuation<T>
|
||||
): Any? = (this as Function1<Continuation<T>, Any?>).invoke(completion)
|
||||
): Any? = errorExperimentalCoroutinesAreNoLongerSupported()
|
||||
|
||||
/**
|
||||
* Starts unintercepted coroutine with receiver type [R] and result type [T] and executes it until its first suspension.
|
||||
@@ -110,7 +73,7 @@ public actual inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrRetu
|
||||
public actual inline fun <R, T> (suspend R.() -> T).startCoroutineUninterceptedOrReturn(
|
||||
receiver: R,
|
||||
completion: Continuation<T>
|
||||
): Any? = (this as Function2<R, Continuation<T>, Any?>).invoke(receiver, completion)
|
||||
): Any? = errorExperimentalCoroutinesAreNoLongerSupported()
|
||||
|
||||
|
||||
|
||||
@@ -119,6 +82,8 @@ public actual inline fun <R, T> (suspend R.() -> T).startCoroutineUninterceptedO
|
||||
* the execution was suspended and will not return any result immediately.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
public actual val COROUTINE_SUSPENDED: Any = CoroutineSuspendedMarker
|
||||
public actual val COROUTINE_SUSPENDED: Any get() = errorExperimentalCoroutinesAreNoLongerSupported()
|
||||
|
||||
private object CoroutineSuspendedMarker
|
||||
@PublishedApi
|
||||
internal fun errorExperimentalCoroutinesAreNoLongerSupported(): Nothing =
|
||||
error("kotlin.coroutines.experimental is no longer supported, please migrate to kotlin.coroutines")
|
||||
|
||||
@@ -17,35 +17,178 @@
|
||||
package kotlin.coroutines.intrinsics
|
||||
|
||||
import kotlin.coroutines.*
|
||||
// TODO: implement them right.
|
||||
import kotlin.coroutines.native.internal.*
|
||||
import kotlin.native.internal.*
|
||||
|
||||
/**
|
||||
* Starts unintercepted coroutine without receiver and with result type [T] and executes it until its first suspension.
|
||||
* Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends.
|
||||
* In the later case, the [completion] continuation is invoked when coroutine completes with result or exception.
|
||||
* This function is designed to be used from inside of [suspendCoroutineOrReturn] to resume the execution of suspended
|
||||
* coroutine using a reference to the suspending function.
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrReturn(
|
||||
completion: Continuation<T>
|
||||
): Any? {
|
||||
TODO("Unimplemented")
|
||||
}
|
||||
): Any? = (this as Function1<Continuation<T>, Any?>).invoke(completion)
|
||||
|
||||
/**
|
||||
* Starts unintercepted coroutine with receiver type [R] and result type [T] and executes it until its first suspension.
|
||||
* Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends.
|
||||
* In the later case, the [completion] continuation is invoked when coroutine completes with result or exception.
|
||||
* This function is designed to be used from inside of [suspendCoroutineOrReturn] to resume the execution of suspended
|
||||
* coroutine using a reference to the suspending function.
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun <R, T> (suspend R.() -> T).startCoroutineUninterceptedOrReturn(
|
||||
receiver: R,
|
||||
completion: Continuation<T>
|
||||
): Any? {
|
||||
TODO("Unimplemented")
|
||||
}
|
||||
): Any? = (this as Function2<R, Continuation<T>, Any?>).invoke(receiver, completion)
|
||||
|
||||
private object CoroutineSuspendedMarker
|
||||
|
||||
|
||||
/**
|
||||
* Creates unintercepted coroutine without receiver and with result type [T].
|
||||
* This function creates a new, fresh instance of suspendable computation every time it is invoked.
|
||||
*
|
||||
* To start executing the created coroutine, invoke `resume(Unit)` on the returned [Continuation] instance.
|
||||
* The [completion] continuation is invoked when coroutine completes with result or exception.
|
||||
*
|
||||
* This function returns unintercepted continuation.
|
||||
* Invocation of `resume(Unit)` starts coroutine immediately in the invoker's call stack without going through the
|
||||
* [ContinuationInterceptor] that might be present in the completion's [CoroutineContext].
|
||||
* It is invoker's responsibility to ensure that the proper invocation context is established.
|
||||
* Note that [completion] of this function may get invoked in an arbitrary context.
|
||||
*
|
||||
* [Continuation.intercepted] can be used to acquire the intercepted continuation.
|
||||
* Invocation of `resume(Unit)` on intercepted continuation guarantees that execution of
|
||||
* both the coroutine and [completion] happens in the invocation context established by
|
||||
* [ContinuationInterceptor].
|
||||
*
|
||||
* Repeated invocation of any resume function on the resulting continuation corrupts the
|
||||
* state machine of the coroutine and may result in arbitrary behaviour or exception.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public actual fun <T> (suspend () -> T).createCoroutineUnintercepted(
|
||||
completion: Continuation<T>
|
||||
): Continuation<Unit> {
|
||||
TODO("Unimplemented")
|
||||
val probeCompletion = probeCoroutineCreated(completion)
|
||||
return if (this is BaseContinuationImpl)
|
||||
create(probeCompletion)
|
||||
else
|
||||
createCoroutineFromSuspendFunction(probeCompletion) {
|
||||
(this as Function1<Continuation<T>, Any?>).invoke(it)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates unintercepted coroutine with receiver type [R] and result type [T].
|
||||
* This function creates a new, fresh instance of suspendable computation every time it is invoked.
|
||||
*
|
||||
* To start executing the created coroutine, invoke `resume(Unit)` on the returned [Continuation] instance.
|
||||
* The [completion] continuation is invoked when coroutine completes with result or exception.
|
||||
*
|
||||
* This function returns unintercepted continuation.
|
||||
* Invocation of `resume(Unit)` starts coroutine immediately in the invoker's call stack without going through the
|
||||
* [ContinuationInterceptor] that might be present in the completion's [CoroutineContext].
|
||||
* It is invoker's responsibility to ensure that the proper invocation context is established.
|
||||
* Note that [completion] of this function may get invoked in an arbitrary context.
|
||||
*
|
||||
* [Continuation.intercepted] can be used to acquire the intercepted continuation.
|
||||
* Invocation of `resume(Unit)` on intercepted continuation guarantees that execution of
|
||||
* both the coroutine and [completion] happens in the invocation context established by
|
||||
* [ContinuationInterceptor].
|
||||
*
|
||||
* Repeated invocation of any resume function on the resulting continuation corrupts the
|
||||
* state machine of the coroutine and may result in arbitrary behaviour or exception.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public actual fun <R, T> (suspend R.() -> T).createCoroutineUnintercepted(
|
||||
receiver: R,
|
||||
completion: Continuation<T>
|
||||
): Continuation<Unit> {
|
||||
TODO("Unimplemented")
|
||||
val probeCompletion = probeCoroutineCreated(completion)
|
||||
return if (this is BaseContinuationImpl)
|
||||
create(receiver, probeCompletion)
|
||||
else {
|
||||
createCoroutineFromSuspendFunction(probeCompletion) {
|
||||
(this as Function2<R, Continuation<T>, Any?>).invoke(receiver, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercepts this continuation with [ContinuationInterceptor].
|
||||
*
|
||||
* This function shall be used on the immediate result of [createCoroutineUnintercepted] or [suspendCoroutineUninterceptedOrReturn],
|
||||
* in which case it checks for [ContinuationInterceptor] in the continuation's [context][Continuation.context],
|
||||
* invokes [ContinuationInterceptor.interceptContinuation], caches and returns result.
|
||||
*
|
||||
* If this function is invoked on other [Continuation] instances it returns `this` continuation unchanged.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public actual fun <T> Continuation<T>.intercepted(): Continuation<T> = TODO("unimplemented")
|
||||
public actual fun <T> Continuation<T>.intercepted(): Continuation<T> =
|
||||
(this as? ContinuationImpl)?.intercepted() ?: this
|
||||
|
||||
// INTERNAL DEFINITIONS
|
||||
|
||||
/**
|
||||
* This function is used when [createCoroutineUnintercepted] encounters suspending lambda that does not extend BaseContinuationImpl.
|
||||
*
|
||||
* It happens in two cases:
|
||||
* 1. Callable reference to suspending function,
|
||||
* 2. Suspending function reference implemented by Java code.
|
||||
*
|
||||
* We must wrap it into an instance that extends [BaseContinuationImpl], because that is an expectation of all coroutines machinery.
|
||||
* As an optimization we use lighter-weight [RestrictedContinuationImpl] base class (it has less fields) if the context is
|
||||
* [EmptyCoroutineContext], and a full-blown [ContinuationImpl] class otherwise.
|
||||
*
|
||||
* The instance of [BaseContinuationImpl] is passed to the [block] so that it can be passed to the corresponding invocation.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
private inline fun <T> createCoroutineFromSuspendFunction(
|
||||
completion: Continuation<T>,
|
||||
crossinline block: (Continuation<T>) -> Any?
|
||||
): Continuation<Unit> {
|
||||
val context = completion.context
|
||||
// label == 0 when coroutine is not started yet (initially) or label == 1 when it was
|
||||
return if (context === EmptyCoroutineContext)
|
||||
object : RestrictedContinuationImpl(completion as Continuation<Any?>) {
|
||||
private var label = 0
|
||||
|
||||
override fun invokeSuspend(result: SuccessOrFailure<Any?>): Any? =
|
||||
when (label) {
|
||||
0 -> {
|
||||
label = 1
|
||||
result.getOrThrow() // Rethrow exception if trying to start with exception (will be caught by BaseContinuationImpl.resumeWith
|
||||
block(this) // run the block, may return or suspend
|
||||
}
|
||||
1 -> {
|
||||
label = 2
|
||||
result.getOrThrow() // this is the result if the block had suspended
|
||||
}
|
||||
else -> error("This coroutine had already completed")
|
||||
}
|
||||
}
|
||||
else
|
||||
object : ContinuationImpl(completion as Continuation<Any?>, context) {
|
||||
private var label = 0
|
||||
|
||||
override fun invokeSuspend(result: SuccessOrFailure<Any?>): Any? =
|
||||
when (label) {
|
||||
0 -> {
|
||||
label = 1
|
||||
result.getOrThrow() // Rethrow exception if trying to start with exception (will be caught by BaseContinuationImpl.resumeWith
|
||||
block(this) // run the block, may return or suspend
|
||||
}
|
||||
1 -> {
|
||||
label = 2
|
||||
result.getOrThrow() // this is the result if the block had suspended
|
||||
}
|
||||
else -> error("This coroutine had already completed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,19 +16,14 @@
|
||||
|
||||
package kotlin.native.internal
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
@kotlin.internal.InlineOnly
|
||||
@PublishedApi
|
||||
internal inline suspend fun <T> suspendCoroutineUninterceptedOrReturn(crossinline block: (Continuation<T>) -> Any?): T =
|
||||
returnIfSuspended<T>(block(getContinuation<T>()))
|
||||
|
||||
@kotlin.internal.InlineOnly
|
||||
@PublishedApi
|
||||
internal inline fun <T> Continuation<T>.intercepted(): Continuation<T> =
|
||||
normalizeContinuation<T>(this)
|
||||
|
||||
@Intrinsic
|
||||
@PublishedApi
|
||||
internal external fun <T> getContinuation(): Continuation<T>
|
||||
@@ -41,65 +36,3 @@ internal inline suspend fun getCoroutineContext(): CoroutineContext =
|
||||
@Intrinsic
|
||||
@PublishedApi
|
||||
internal external suspend fun <T> returnIfSuspended(@Suppress("UNUSED_PARAMETER") argument: Any?): T
|
||||
|
||||
|
||||
@ExportForCompiler
|
||||
internal fun <T> interceptContinuationIfNeeded(
|
||||
context: CoroutineContext,
|
||||
continuation: Continuation<T>
|
||||
) = context[ContinuationInterceptor]?.interceptContinuation(continuation) ?: continuation
|
||||
|
||||
/**
|
||||
* @suppress
|
||||
*/
|
||||
@ExportForCompiler
|
||||
@PublishedApi
|
||||
internal fun <T> normalizeContinuation(continuation: Continuation<T>): Continuation<T> =
|
||||
(continuation as? CoroutineImpl)?.facade ?: continuation
|
||||
|
||||
/**
|
||||
* @suppress
|
||||
*/
|
||||
@ExportForCompiler
|
||||
abstract internal class CoroutineImpl(
|
||||
protected var completion: Continuation<Any?>?
|
||||
) : Continuation<Any?> {
|
||||
|
||||
// label == -1 when coroutine cannot be started (it is just a factory object) or has already finished execution
|
||||
// label == 0 in initial part of the coroutine
|
||||
protected var label: NativePtr = if (completion != null) NativePtr.NULL else NativePtr.NULL + (-1L)
|
||||
|
||||
private val _context: CoroutineContext? = completion?.context
|
||||
|
||||
override val context: CoroutineContext
|
||||
get() = _context!!
|
||||
|
||||
private var _facade: Continuation<Any?>? = null
|
||||
|
||||
val facade: Continuation<Any?> get() {
|
||||
if (_facade == null) _facade = interceptContinuationIfNeeded(_context!!, this)
|
||||
return _facade!!
|
||||
}
|
||||
|
||||
override fun resume(value: Any?) {
|
||||
processBareContinuationResume(completion!!) {
|
||||
doResume(value, null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
processBareContinuationResume(completion!!) {
|
||||
doResume(null, exception)
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun doResume(data: Any?, exception: Throwable?): Any?
|
||||
|
||||
open fun create(completion: Continuation<*>): Continuation<Unit> {
|
||||
throw IllegalStateException("create(Continuation) has not been overridden")
|
||||
}
|
||||
|
||||
open fun create(value: Any?, completion: Continuation<*>): Continuation<Unit> {
|
||||
throw IllegalStateException("create(Any?;Continuation) has not been overridden")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
import kotlinx.cinterop.*
|
||||
import platform.posix.*
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
if (args.size < 1) {
|
||||
@@ -96,9 +96,8 @@ class Client(val clientFd: Int, val waitingList: MutableMap<Int, WaitingFor>) {
|
||||
if (posix_errno() != EWOULDBLOCK)
|
||||
throw IOException(getUnixError())
|
||||
// Save continuation and suspend.
|
||||
return suspendCoroutineOrReturn { continuation ->
|
||||
return suspendCoroutine { continuation ->
|
||||
waitingList.put(clientFd, WaitingFor.Read(data, dataLength, continuation))
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,17 +108,15 @@ class Client(val clientFd: Int, val waitingList: MutableMap<Int, WaitingFor>) {
|
||||
if (posix_errno() != EWOULDBLOCK)
|
||||
throw IOException(getUnixError())
|
||||
// Save continuation and suspend.
|
||||
return suspendCoroutineOrReturn { continuation ->
|
||||
return suspendCoroutine { continuation ->
|
||||
waitingList.put(clientFd, WaitingFor.Write(data, length, continuation))
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(value: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
override fun resumeWith(result: SuccessOrFailure<Any?>) { result.getOrThrow() }
|
||||
}
|
||||
|
||||
fun acceptClientsAndRun(serverFd: Int, block: suspend Client.() -> Unit) {
|
||||
|
||||
Reference in New Issue
Block a user