[JS IR BE] Make coroutine compile separately from stdlib

* use accessors instead of direct field access
This commit is contained in:
Roman Artemev
2018-08-31 18:53:54 +03:00
committed by romanart
parent 4f803d03cf
commit 54e98fc014
4 changed files with 54 additions and 47 deletions
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.name.Name
private fun IrClassSymbol.getPropertyDeclaration(name: String) =
fun IrClassSymbol.getPropertyDeclaration(name: String) =
this.owner.declarations.filterIsInstance<IrProperty>()
.atMostOne { it.descriptor.name == Name.identifier(name) }
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.ReflectionTypes
import org.jetbrains.kotlin.backend.common.atMostOne
import org.jetbrains.kotlin.backend.common.descriptors.KnownPackageFragmentDescriptor
import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.backend.common.ir.Symbols
@@ -22,10 +23,7 @@ import org.jetbrains.kotlin.ir.SourceRangeInfo
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.lower.inline.ModuleIndex
import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
@@ -86,6 +84,7 @@ class JsIrBackendContext(
// TODO: what is more clear way reference this getter?
private val CONTINUATION_CONTEXT_GETTER_NAME = Name.special("<get-context>")
private val CONTINUATION_CONTEXT_PROPERTY_NAME = Name.identifier("context")
private val coroutinePackageName = FqName(coroutinePackageNameSrting)
private val coroutineIntrinsicsPackageName = coroutinePackageName.child(INTRINSICS_PACKAGE_NAME)
@@ -103,7 +102,9 @@ class JsIrBackendContext(
NoLookupLocation.FROM_BACKEND
) as ClassDescriptor
)
val contextGetter = continuation.owner.declarations.single { it.descriptor.name == CONTINUATION_CONTEXT_GETTER_NAME } as IrFunction
val contextGetter =
continuation.owner.declarations.filterIsInstance<IrFunction>().atMostOne { it.descriptor.name == CONTINUATION_CONTEXT_GETTER_NAME }
?: continuation.owner.declarations.filterIsInstance<IrProperty>().atMostOne { it.descriptor.name == CONTINUATION_CONTEXT_PROPERTY_NAME }?.getter!!
return contextGetter.symbol
}
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
@@ -55,9 +56,9 @@ class StateMachineBuilder(
val context: JsIrBackendContext,
val function: IrFunctionSymbol,
private val rootLoop: IrLoop,
private val exceptionSymbol: IrFieldSymbol,
private val exStateSymbol: IrFieldSymbol,
private val stateSymbol: IrFieldSymbol,
private val exceptionSymbol: IrProperty,
private val exStateSymbol: IrProperty,
private val stateSymbol: IrProperty,
thisSymbol: IrValueParameterSymbol,
private val suspendResult: IrVariableSymbol
) : IrElementVisitorVoid {
@@ -75,7 +76,7 @@ class StateMachineBuilder(
val entryState = SuspendState(unit)
val rootExceptionTrap = buildExceptionTrapState()
private val globalExceptionVar = JsIrBuilder.buildVar(exceptionSymbol.owner.type, function.owner, "e")
private val globalExceptionVar = JsIrBuilder.buildVar(exceptionSymbol.getter!!.returnType, function.owner, "e")
lateinit var globalCatch: IrCatch
fun finalizeStateMachine() {
@@ -109,18 +110,14 @@ class StateMachineBuilder(
)
// TODO: exception table
elseBlock.statements += JsIrBuilder.buildSetField(
stateSymbol,
thisReceiver,
exceptionState(),
unit
)
elseBlock.statements += JsIrBuilder.buildSetField(
exceptionSymbol,
thisReceiver,
JsIrBuilder.buildGetValue(globalExceptionSymbol),
unit
)
elseBlock.statements += JsIrBuilder.buildCall(stateSymbol.setter!!.symbol, unit).apply {
dispatchReceiver = thisReceiver
putValueArgument(0, exceptionState())
}
elseBlock.statements += JsIrBuilder.buildCall(exceptionSymbol.setter!!.symbol, unit).apply {
dispatchReceiver = thisReceiver
putValueArgument(0, JsIrBuilder.buildGetValue(globalExceptionSymbol))
}
} else {
block.statements += JsIrBuilder.buildThrow(
nothing,
@@ -175,7 +172,10 @@ class StateMachineBuilder(
private fun doDispatchImpl(target: SuspendState, block: IrContainerExpression, andContinue: Boolean) {
val irDispatch = IrDispatchPoint(target)
currentState.successors.add(target)
block.addStatement(JsIrBuilder.buildSetField(stateSymbol, thisReceiver, irDispatch, unit))
block.addStatement(JsIrBuilder.buildCall(stateSymbol.setter!!.symbol, unit).apply {
dispatchReceiver = thisReceiver
putValueArgument(0, irDispatch)
})
if (andContinue) doContinue(block)
}
@@ -288,7 +288,12 @@ class StateMachineBuilder(
currentState.successors += continueState
transformLastExpression { JsIrBuilder.buildSetField(stateSymbol, thisReceiver, dispatch, unit) }
transformLastExpression {
JsIrBuilder.buildCall(stateSymbol.setter!!.symbol, unit).apply {
dispatchReceiver = thisReceiver
putValueArgument(0, dispatch)
}
}
addStatement(JsIrBuilder.buildSetVariable(suspendResult, result, unit))
@@ -661,14 +666,10 @@ class StateMachineBuilder(
aTry.finallyExpression?.acceptVoid(this)
currentState.successors += listOf(throwExitState, exitState)
addStatement(
JsIrBuilder.buildSetField(
stateSymbol,
thisReceiver,
JsIrBuilder.buildGetValue(
finallyStateVar.symbol
),
unit
)
JsIrBuilder.buildCall(stateSymbol.setter!!.symbol, unit).also {
it.dispatchReceiver = thisReceiver
it.putValueArgument(0, JsIrBuilder.buildGetValue(finallyStateVar.symbol))
}
)
doContinue()
@@ -685,15 +686,15 @@ class StateMachineBuilder(
private fun setupExceptionState(target: SuspendState) {
addStatement(
JsIrBuilder.buildSetField(
exStateSymbol, thisReceiver,
IrDispatchPoint(target), unit
)
JsIrBuilder.buildCall(exStateSymbol.setter!!.symbol, unit).apply {
dispatchReceiver = thisReceiver
putValueArgument(0, IrDispatchPoint(target))
}
)
}
private fun exceptionState() = JsIrBuilder.buildGetField(exStateSymbol, thisReceiver)
private fun pendingException() = JsIrBuilder.buildGetField(exceptionSymbol, thisReceiver)
private fun exceptionState() = JsIrBuilder.buildCall(exStateSymbol.getter!!.symbol).also { it.dispatchReceiver = thisReceiver }
private fun pendingException() = JsIrBuilder.buildCall(exceptionSymbol.getter!!.symbol).also { it.dispatchReceiver = thisReceiver }
private fun buildTryState(aTry: IrTry) =
TryState(
@@ -280,9 +280,9 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
private val create1CompletionParameter = create1Function.valueParameters[0]
private val coroutineImplLabelFieldSymbol = coroutineImplSymbol.getPropertyField("label")!!
private val coroutineImplExceptionFieldSymbol = coroutineImplSymbol.getPropertyField("pendingException")!!
private val coroutineImplExceptionStateFieldSymbol = coroutineImplSymbol.getPropertyField("exceptionState")!!
private val coroutineImplLabelProperty = coroutineImplSymbol.getPropertyDeclaration("label")!!
private val coroutineImplExceptionProperty = coroutineImplSymbol.getPropertyDeclaration("pendingException")!!
private val coroutineImplExceptionStateProperty = coroutineImplSymbol.getPropertyDeclaration("exceptionState")!!
private val coroutineConstructors = mutableListOf<IrConstructor>()
private var exceptionTrapId = -1
@@ -797,7 +797,7 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
initializer = JsIrBuilder.buildGetValue(dataArgument.symbol)
)
suspendState = JsIrBuilder.buildVar(coroutineImplLabelFieldSymbol.owner.type, function, "suspendState", true)
suspendState = JsIrBuilder.buildVar(coroutineImplLabelProperty.getter!!.returnType, function, "suspendState", true)
val body =
(originalBody as IrBlockBody).run {
@@ -821,7 +821,10 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
(it.body as? IrBlockBody)?.run {
val receiver = JsIrBuilder.buildGetValue(coroutineClassThis.symbol)
val id = JsIrBuilder.buildInt(context.irBuiltIns.intType, exceptionTrapId)
statements += JsIrBuilder.buildSetField(coroutineImplExceptionStateFieldSymbol, receiver, id, context.irBuiltIns.unitType)
statements += JsIrBuilder.buildCall(coroutineImplExceptionStateProperty.setter!!.symbol).also { call ->
call.dispatchReceiver = receiver
call.putValueArgument(0, id)
}
}
}
}
@@ -850,9 +853,9 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
context,
function.symbol,
rootLoop,
coroutineImplExceptionFieldSymbol,
coroutineImplExceptionStateFieldSymbol,
coroutineImplLabelFieldSymbol,
coroutineImplExceptionProperty,
coroutineImplExceptionStateProperty,
coroutineImplLabelProperty,
thisReceiver,
suspendResult.symbol
)
@@ -877,7 +880,9 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
for (state in sortedStates) {
val condition = JsIrBuilder.buildCall(eqeqeqInt).apply {
putValueArgument(0, JsIrBuilder.buildGetField(coroutineImplLabelFieldSymbol, JsIrBuilder.buildGetValue(thisReceiver)))
putValueArgument(0, JsIrBuilder.buildCall(coroutineImplLabelProperty.getter!!.symbol).also {
it.dispatchReceiver = JsIrBuilder.buildGetValue(thisReceiver)
})
putValueArgument(1, JsIrBuilder.buildInt(context.irBuiltIns.intType, state.id))
}