[JS IR BE] Make coroutine compile separately from stdlib
* use accessors instead of direct field access
This commit is contained in:
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
|||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
private fun IrClassSymbol.getPropertyDeclaration(name: String) =
|
fun IrClassSymbol.getPropertyDeclaration(name: String) =
|
||||||
this.owner.declarations.filterIsInstance<IrProperty>()
|
this.owner.declarations.filterIsInstance<IrProperty>()
|
||||||
.atMostOne { it.descriptor.name == Name.identifier(name) }
|
.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.CommonBackendContext
|
||||||
import org.jetbrains.kotlin.backend.common.ReflectionTypes
|
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.descriptors.KnownPackageFragmentDescriptor
|
||||||
import org.jetbrains.kotlin.backend.common.ir.Ir
|
import org.jetbrains.kotlin.backend.common.ir.Ir
|
||||||
import org.jetbrains.kotlin.backend.common.ir.Symbols
|
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.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.inline.ModuleIndex
|
import org.jetbrains.kotlin.ir.backend.js.lower.inline.ModuleIndex
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
|
import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
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.impl.IrFileImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
@@ -86,6 +84,7 @@ class JsIrBackendContext(
|
|||||||
|
|
||||||
// TODO: what is more clear way reference this getter?
|
// TODO: what is more clear way reference this getter?
|
||||||
private val CONTINUATION_CONTEXT_GETTER_NAME = Name.special("<get-context>")
|
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 coroutinePackageName = FqName(coroutinePackageNameSrting)
|
||||||
private val coroutineIntrinsicsPackageName = coroutinePackageName.child(INTRINSICS_PACKAGE_NAME)
|
private val coroutineIntrinsicsPackageName = coroutinePackageName.child(INTRINSICS_PACKAGE_NAME)
|
||||||
@@ -103,7 +102,9 @@ class JsIrBackendContext(
|
|||||||
NoLookupLocation.FROM_BACKEND
|
NoLookupLocation.FROM_BACKEND
|
||||||
) as ClassDescriptor
|
) 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
|
return contextGetter.symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+33
-32
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.IrStatement
|
|||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
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.declarations.IrVariable
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
@@ -55,9 +56,9 @@ class StateMachineBuilder(
|
|||||||
val context: JsIrBackendContext,
|
val context: JsIrBackendContext,
|
||||||
val function: IrFunctionSymbol,
|
val function: IrFunctionSymbol,
|
||||||
private val rootLoop: IrLoop,
|
private val rootLoop: IrLoop,
|
||||||
private val exceptionSymbol: IrFieldSymbol,
|
private val exceptionSymbol: IrProperty,
|
||||||
private val exStateSymbol: IrFieldSymbol,
|
private val exStateSymbol: IrProperty,
|
||||||
private val stateSymbol: IrFieldSymbol,
|
private val stateSymbol: IrProperty,
|
||||||
thisSymbol: IrValueParameterSymbol,
|
thisSymbol: IrValueParameterSymbol,
|
||||||
private val suspendResult: IrVariableSymbol
|
private val suspendResult: IrVariableSymbol
|
||||||
) : IrElementVisitorVoid {
|
) : IrElementVisitorVoid {
|
||||||
@@ -75,7 +76,7 @@ class StateMachineBuilder(
|
|||||||
|
|
||||||
val entryState = SuspendState(unit)
|
val entryState = SuspendState(unit)
|
||||||
val rootExceptionTrap = buildExceptionTrapState()
|
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
|
lateinit var globalCatch: IrCatch
|
||||||
|
|
||||||
fun finalizeStateMachine() {
|
fun finalizeStateMachine() {
|
||||||
@@ -109,18 +110,14 @@ class StateMachineBuilder(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// TODO: exception table
|
// TODO: exception table
|
||||||
elseBlock.statements += JsIrBuilder.buildSetField(
|
elseBlock.statements += JsIrBuilder.buildCall(stateSymbol.setter!!.symbol, unit).apply {
|
||||||
stateSymbol,
|
dispatchReceiver = thisReceiver
|
||||||
thisReceiver,
|
putValueArgument(0, exceptionState())
|
||||||
exceptionState(),
|
}
|
||||||
unit
|
elseBlock.statements += JsIrBuilder.buildCall(exceptionSymbol.setter!!.symbol, unit).apply {
|
||||||
)
|
dispatchReceiver = thisReceiver
|
||||||
elseBlock.statements += JsIrBuilder.buildSetField(
|
putValueArgument(0, JsIrBuilder.buildGetValue(globalExceptionSymbol))
|
||||||
exceptionSymbol,
|
}
|
||||||
thisReceiver,
|
|
||||||
JsIrBuilder.buildGetValue(globalExceptionSymbol),
|
|
||||||
unit
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
block.statements += JsIrBuilder.buildThrow(
|
block.statements += JsIrBuilder.buildThrow(
|
||||||
nothing,
|
nothing,
|
||||||
@@ -175,7 +172,10 @@ class StateMachineBuilder(
|
|||||||
private fun doDispatchImpl(target: SuspendState, block: IrContainerExpression, andContinue: Boolean) {
|
private fun doDispatchImpl(target: SuspendState, block: IrContainerExpression, andContinue: Boolean) {
|
||||||
val irDispatch = IrDispatchPoint(target)
|
val irDispatch = IrDispatchPoint(target)
|
||||||
currentState.successors.add(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)
|
if (andContinue) doContinue(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,7 +288,12 @@ class StateMachineBuilder(
|
|||||||
|
|
||||||
currentState.successors += continueState
|
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))
|
addStatement(JsIrBuilder.buildSetVariable(suspendResult, result, unit))
|
||||||
|
|
||||||
@@ -661,14 +666,10 @@ class StateMachineBuilder(
|
|||||||
aTry.finallyExpression?.acceptVoid(this)
|
aTry.finallyExpression?.acceptVoid(this)
|
||||||
currentState.successors += listOf(throwExitState, exitState)
|
currentState.successors += listOf(throwExitState, exitState)
|
||||||
addStatement(
|
addStatement(
|
||||||
JsIrBuilder.buildSetField(
|
JsIrBuilder.buildCall(stateSymbol.setter!!.symbol, unit).also {
|
||||||
stateSymbol,
|
it.dispatchReceiver = thisReceiver
|
||||||
thisReceiver,
|
it.putValueArgument(0, JsIrBuilder.buildGetValue(finallyStateVar.symbol))
|
||||||
JsIrBuilder.buildGetValue(
|
}
|
||||||
finallyStateVar.symbol
|
|
||||||
),
|
|
||||||
unit
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
doContinue()
|
doContinue()
|
||||||
|
|
||||||
@@ -685,15 +686,15 @@ class StateMachineBuilder(
|
|||||||
|
|
||||||
private fun setupExceptionState(target: SuspendState) {
|
private fun setupExceptionState(target: SuspendState) {
|
||||||
addStatement(
|
addStatement(
|
||||||
JsIrBuilder.buildSetField(
|
JsIrBuilder.buildCall(exStateSymbol.setter!!.symbol, unit).apply {
|
||||||
exStateSymbol, thisReceiver,
|
dispatchReceiver = thisReceiver
|
||||||
IrDispatchPoint(target), unit
|
putValueArgument(0, IrDispatchPoint(target))
|
||||||
)
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun exceptionState() = JsIrBuilder.buildGetField(exStateSymbol, thisReceiver)
|
private fun exceptionState() = JsIrBuilder.buildCall(exStateSymbol.getter!!.symbol).also { it.dispatchReceiver = thisReceiver }
|
||||||
private fun pendingException() = JsIrBuilder.buildGetField(exceptionSymbol, thisReceiver)
|
private fun pendingException() = JsIrBuilder.buildCall(exceptionSymbol.getter!!.symbol).also { it.dispatchReceiver = thisReceiver }
|
||||||
|
|
||||||
private fun buildTryState(aTry: IrTry) =
|
private fun buildTryState(aTry: IrTry) =
|
||||||
TryState(
|
TryState(
|
||||||
|
|||||||
+14
-9
@@ -280,9 +280,9 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
|
|||||||
|
|
||||||
private val create1CompletionParameter = create1Function.valueParameters[0]
|
private val create1CompletionParameter = create1Function.valueParameters[0]
|
||||||
|
|
||||||
private val coroutineImplLabelFieldSymbol = coroutineImplSymbol.getPropertyField("label")!!
|
private val coroutineImplLabelProperty = coroutineImplSymbol.getPropertyDeclaration("label")!!
|
||||||
private val coroutineImplExceptionFieldSymbol = coroutineImplSymbol.getPropertyField("pendingException")!!
|
private val coroutineImplExceptionProperty = coroutineImplSymbol.getPropertyDeclaration("pendingException")!!
|
||||||
private val coroutineImplExceptionStateFieldSymbol = coroutineImplSymbol.getPropertyField("exceptionState")!!
|
private val coroutineImplExceptionStateProperty = coroutineImplSymbol.getPropertyDeclaration("exceptionState")!!
|
||||||
|
|
||||||
private val coroutineConstructors = mutableListOf<IrConstructor>()
|
private val coroutineConstructors = mutableListOf<IrConstructor>()
|
||||||
private var exceptionTrapId = -1
|
private var exceptionTrapId = -1
|
||||||
@@ -797,7 +797,7 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
|
|||||||
initializer = JsIrBuilder.buildGetValue(dataArgument.symbol)
|
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 =
|
val body =
|
||||||
(originalBody as IrBlockBody).run {
|
(originalBody as IrBlockBody).run {
|
||||||
@@ -821,7 +821,10 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
|
|||||||
(it.body as? IrBlockBody)?.run {
|
(it.body as? IrBlockBody)?.run {
|
||||||
val receiver = JsIrBuilder.buildGetValue(coroutineClassThis.symbol)
|
val receiver = JsIrBuilder.buildGetValue(coroutineClassThis.symbol)
|
||||||
val id = JsIrBuilder.buildInt(context.irBuiltIns.intType, exceptionTrapId)
|
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,
|
context,
|
||||||
function.symbol,
|
function.symbol,
|
||||||
rootLoop,
|
rootLoop,
|
||||||
coroutineImplExceptionFieldSymbol,
|
coroutineImplExceptionProperty,
|
||||||
coroutineImplExceptionStateFieldSymbol,
|
coroutineImplExceptionStateProperty,
|
||||||
coroutineImplLabelFieldSymbol,
|
coroutineImplLabelProperty,
|
||||||
thisReceiver,
|
thisReceiver,
|
||||||
suspendResult.symbol
|
suspendResult.symbol
|
||||||
)
|
)
|
||||||
@@ -877,7 +880,9 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
|
|||||||
|
|
||||||
for (state in sortedStates) {
|
for (state in sortedStates) {
|
||||||
val condition = JsIrBuilder.buildCall(eqeqeqInt).apply {
|
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))
|
putValueArgument(1, JsIrBuilder.buildInt(context.irBuiltIns.intType, state.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user