From 6bb77ba51db62513c141340289da30092102230a Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Tue, 4 Sep 2018 14:08:05 +0300 Subject: [PATCH] [JS IR BE] Get rid of parameters in `doResume` method. Make its signature similar for both 1.2 and 1.3 coroutines --- .../ir/backend/js/JsIrBackendContext.kt | 11 ++- .../coroutines/SuspendFunctionsLowering.kt | 94 +++++++++++-------- .../stdlib/js/irRuntime/coroutinesInternal.kt | 18 ++-- 3 files changed, 75 insertions(+), 48 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt index 0cc1d4c11b9..1d31f5a38a2 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.types.impl.IrDynamicTypeImpl import org.jetbrains.kotlin.ir.util.SymbolTable +import org.jetbrains.kotlin.ir.util.getPropertyDeclaration import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.scopes.MemberScope @@ -74,7 +75,8 @@ class JsIrBackendContext( private val internalPackage = module.getPackage(internalPackageName) // TODO: replace it with appropriate package name once we migrate to 1.3 coroutines - private val coroutinePackageNameSrting = "kotlin.coroutines.experimental" + private val coroutinePackageNameSrting_12 = "kotlin.coroutines.experimental" + private val coroutinePackageNameSrting_13 = "kotlin.coroutines" private val INTRINSICS_PACKAGE_NAME = Name.identifier("intrinsics") private val COROUTINE_SUSPENDED_NAME = Name.identifier("COROUTINE_SUSPENDED") @@ -86,7 +88,7 @@ class JsIrBackendContext( private val CONTINUATION_CONTEXT_GETTER_NAME = Name.special("") private val CONTINUATION_CONTEXT_PROPERTY_NAME = Name.identifier("context") - private val coroutinePackageName = FqName(coroutinePackageNameSrting) + private val coroutinePackageName = FqName(coroutinePackageNameSrting_12) private val coroutineIntrinsicsPackageName = coroutinePackageName.child(INTRINSICS_PACKAGE_NAME) private val coroutinePackage = module.getPackage(coroutinePackageName) @@ -193,6 +195,11 @@ class JsIrBackendContext( override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true } + val coroutineImplLabelProperty by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("label")!! } + val coroutineImplResultSymbol by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("result")!! } + val coroutineImplExceptionProperty by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("exception")!! } + val coroutineImplExceptionStateProperty by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("exceptionState")!! } + private fun referenceOperators() = OperatorNames.ALL.map { name -> // TODO to replace KotlinType with IrType we need right equals on IrType name to irBuiltIns.primitiveTypes.fold(mutableMapOf()) { m, t -> diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendFunctionsLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendFunctionsLowering.kt index ea9d4baa814..8df27b67517 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendFunctionsLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendFunctionsLowering.kt @@ -227,24 +227,34 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo builtCoroutines[irFunction] = coroutine if (functionReference == null) { + val resultSetter = context.coroutineImplResultSymbol.setter!! + val exceptionSetter = context.coroutineImplExceptionProperty.setter!! // It is not a lambda - replace original function with a call to constructor of the built coroutine. val irBuilder = context.createIrBuilder(irFunction.symbol, irFunction.startOffset, irFunction.endOffset) irFunction.body = irBuilder.irBlockBody(irFunction) { - +irReturn( - irCall(coroutine.doResumeFunction.symbol).apply { - dispatchReceiver = irCall(coroutine.coroutineConstructor.symbol).apply { - val functionParameters = irFunction.explicitParameters - functionParameters.forEachIndexed { index, argument -> - putValueArgument(index, irGet(argument)) - } - putValueArgument( - functionParameters.size, - irCall(getContinuationSymbol, getContinuationSymbol.owner.returnType, listOf(irFunction.returnType)) - ) - } - putValueArgument(0, irGetObject(unit)) // value - putValueArgument(1, irNull()) // exception - }) + val dispatchReceiverCall = irCall(coroutine.coroutineConstructor.symbol).apply { + val functionParameters = irFunction.explicitParameters + functionParameters.forEachIndexed { index, argument -> + putValueArgument(index, irGet(argument)) + } + putValueArgument( + functionParameters.size, + irCall(getContinuationSymbol, getContinuationSymbol.owner.returnType, listOf(irFunction.returnType)) + ) + } + val dispatchReceiverVar = JsIrBuilder.buildVar(dispatchReceiverCall.type, irFunction, initializer = dispatchReceiverCall) + +dispatchReceiverVar + +irCall(resultSetter).apply { + dispatchReceiver = irGet(dispatchReceiverVar) + putValueArgument(0, irGetObject(unit)) + } + +irCall(exceptionSetter).apply { + dispatchReceiver = irGet(dispatchReceiverVar) + putValueArgument(0, irNull()) + } + +irReturn(irCall(coroutine.doResumeFunction.symbol).apply { + dispatchReceiver = irGet(dispatchReceiverVar) + }) } } @@ -267,8 +277,6 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo private lateinit var suspendResult: IrVariable private lateinit var suspendState: IrVariable - private lateinit var dataArgument: IrValueParameter - private lateinit var exceptionArgument: IrValueParameter private lateinit var coroutineClass: IrClassImpl private lateinit var coroutineClassThis: IrValueParameter private lateinit var argumentToPropertiesMap: Map @@ -280,9 +288,10 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo private val create1CompletionParameter = create1Function.valueParameters[0] - private val coroutineImplLabelProperty = coroutineImplSymbol.getPropertyDeclaration("label")!! - private val coroutineImplExceptionProperty = coroutineImplSymbol.getPropertyDeclaration("pendingException")!! - private val coroutineImplExceptionStateProperty = coroutineImplSymbol.getPropertyDeclaration("exceptionState")!! + private val coroutineImplLabelProperty = context.coroutineImplLabelProperty + private val coroutineImplResultSymbol = context.coroutineImplResultSymbol + private val coroutineImplExceptionProperty = context.coroutineImplExceptionProperty + private val coroutineImplExceptionStateProperty = context.coroutineImplExceptionStateProperty private val coroutineConstructors = mutableListOf() private var exceptionTrapId = -1 @@ -710,25 +719,35 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo JsIrBuilder.buildValueParameter(p.name, p.index, p.type, p.origin).also { it.parent = declaration } } + val resultSetter = context.coroutineImplResultSymbol.setter!! + val exceptionSetter = context.coroutineImplExceptionProperty.setter!! + val thisReceiver = coroutineClassThis val irBuilder = context.createIrBuilder(symbol, irFunction.startOffset, irFunction.endOffset) declaration.body = irBuilder.irBlockBody(irFunction.startOffset, irFunction.endOffset) { - +irReturn( - irCall(doResumeFunction).apply { - dispatchReceiver = irCall(createFunction).apply { - dispatchReceiver = irGet(thisReceiver) - declaration.valueParameters.forEachIndexed { index, parameter -> - putValueArgument(index, irGet(parameter)) - } - putValueArgument( - declaration.valueParameters.size, - irCall(getContinuationSymbol, getContinuationSymbol.owner.returnType, listOf(declaration.returnType)) - ) - } - putValueArgument(0, irGetObject(symbols.unit)) // value - putValueArgument(1, irNull()) // exception + val dispatchReceiverCall = irCall(createFunction).apply { + dispatchReceiver = irGet(thisReceiver) + declaration.valueParameters.forEachIndexed { index, parameter -> + putValueArgument(index, irGet(parameter)) } - ) + putValueArgument( + declaration.valueParameters.size, + irCall(getContinuationSymbol, getContinuationSymbol.owner.returnType, listOf(declaration.returnType)) + ) + } + val dispatchReceiverVar = JsIrBuilder.buildVar(dispatchReceiverCall.type, irFunction, initializer = dispatchReceiverCall) + +dispatchReceiverVar + +irCall(resultSetter).apply { + dispatchReceiver = irGet(dispatchReceiverVar) + putValueArgument(0, irGetObject(unit)) + } + +irCall(exceptionSetter).apply { + dispatchReceiver = irGet(dispatchReceiverVar) + putValueArgument(0, irNull()) + } + +irReturn(irCall(doResumeFunction).apply { + dispatchReceiver = irGet(dispatchReceiverVar) + }) } return declaration @@ -787,14 +806,13 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo JsIrBuilder.buildValueParameter(it.name, it.index, it.type, it.origin).also { p -> p.parent = function } } - dataArgument = function.valueParameters[0] - exceptionArgument = function.valueParameters[1] + val thisReceiver = JsIrBuilder.buildGetValue(coroutineClassThis.symbol) suspendResult = JsIrBuilder.buildVar( context.irBuiltIns.anyNType, function, "suspendResult", true, - initializer = JsIrBuilder.buildGetValue(dataArgument.symbol) + initializer = JsIrBuilder.buildCall(coroutineImplResultSymbol.getter!!.symbol).apply { dispatchReceiver = thisReceiver } ) suspendState = JsIrBuilder.buildVar(coroutineImplLabelProperty.getter!!.returnType, function, "suspendState", true) diff --git a/libraries/stdlib/js/irRuntime/coroutinesInternal.kt b/libraries/stdlib/js/irRuntime/coroutinesInternal.kt index 238d8d8f74a..58744328f74 100644 --- a/libraries/stdlib/js/irRuntime/coroutinesInternal.kt +++ b/libraries/stdlib/js/irRuntime/coroutinesInternal.kt @@ -34,7 +34,8 @@ internal abstract class CoroutineImpl(private val completion: Continuation protected var exceptionState = 0 protected var label: Int = 0 - protected var pendingException: dynamic = null + protected var exception: dynamic = null + protected var result: dynamic = null public override val context: CoroutineContext get() = completion?.context @@ -44,21 +45,22 @@ internal abstract class CoroutineImpl(private val completion: Continuation } override fun resume(value: Any?) { - doResumeWrapper(value, null) + this.result = value + doResumeWrapper() } override fun resumeWithException(exception: Throwable) { // TODO: once we have arrays working refact it with exception table - label = exceptionState - pendingException = exception - doResumeWrapper(null, exception) + this.label = exceptionState + this.exception = exception + doResumeWrapper() } - protected fun doResumeWrapper(data: Any?, exception: Throwable?) { - processBareContinuationResume(completion) { doResume(data, exception) } + protected fun doResumeWrapper() { + processBareContinuationResume(completion) { doResume() } } - protected abstract fun doResume(data: Any?, exception: Throwable?): Any? + protected abstract fun doResume(): Any? open fun create(completion: Continuation<*>): Continuation { throw IllegalStateException("create(Continuation) has not been overridden")