JVM_IR: Support crossinline suspend lambdas
The main idea is the following: since we need to generate (fake)continuations before inlining, we move IrClasses of suspend lambdas and continuation classes of named functions into the functions. Thus, it allows the codegen to generate them prior to inlining and the inliner will happily transform them for us. Because of that, lowerings which transform call-site function are likely to change reference to lowered suspend lambdas or functions. Hence, do not rely on references to lowered suspend lambdas or functions, instead, rely on attributes. Do not generate continuation for inline suspend lambdas. Previously, inline suspend lambdas were treated like suspend functions, thus we generated continuations for them. Now we just do not treat them as suspend functions or lambdas during AddContinuationLowering. We should add continuation parameter to them, however. Do not generate secondary constructor for suspend lambdas, otherwise, the inliner is unable to transform them (it requires only one constructor to be present). Generate continuation classes for suspend functions as first statement inside the function. This enables suspend functions in local object inside inline functions. Since we already have attributes inside suspend named functions, we just reuse them to generate continuation class names. This allows us to close the gap between code generated by old back-end and the new one. If a suspend named function captures crossinline lambda, we should generate a template for inliner: a copy of the function without state-machine and a continuation constructor call. The call is needed so the inliner transforms the continuation as well. Refactor CoroutineTransformerMethodVisitor, so it no longer depends on PSI.
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure
|
||||
@@ -17,6 +18,7 @@ import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -32,6 +34,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
@@ -470,8 +473,9 @@ class CoroutineCodegenForLambda private constructor(
|
||||
val stateMachineBuilder = CoroutineTransformerMethodVisitor(
|
||||
mv, access, name, desc, null, null,
|
||||
obtainClassBuilderForCoroutineState = { v },
|
||||
element = element,
|
||||
diagnostics = state.diagnostics,
|
||||
reportSuspensionPointInsideMonitor = { reportSuspensionPointInsideMonitor(element, state, it) },
|
||||
lineNumber = CodegenUtil.getLineNumberForElement(element, false) ?: 0,
|
||||
sourceFile = element.containingKtFile.name,
|
||||
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
|
||||
containingClassInternalName = v.thisName,
|
||||
isForNamedFunction = false,
|
||||
@@ -768,3 +772,7 @@ private object FailingFunctionGenerationStrategy : FunctionGenerationStrategy()
|
||||
error("This functions must not be called")
|
||||
}
|
||||
}
|
||||
|
||||
fun reportSuspensionPointInsideMonitor(element: KtElement, state: GenerationState, stackTraceElement: String) {
|
||||
state.diagnostics.report(ErrorsJvm.SUSPENSION_POINT_INSIDE_MONITOR.on(element, stackTraceElement))
|
||||
}
|
||||
+4
-6
@@ -60,13 +60,13 @@ class CoroutineTransformerMethodVisitor(
|
||||
private val isForNamedFunction: Boolean,
|
||||
private val shouldPreserveClassInitialization: Boolean,
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
// These two are needed to report diagnostics about suspension points inside critical section
|
||||
private val element: KtElement,
|
||||
private val diagnostics: DiagnosticSink,
|
||||
// Since tail-call optimization of functions with Unit return type relies on ability of call-site to recognize them,
|
||||
// in order to ignore return value and push Unit, when we cannot ensure this ability, for example, when the function overrides function,
|
||||
// returning Any, we need to disable tail-call optimization for these functions.
|
||||
private val disableTailCallOptimizationForFunctionReturningUnit: Boolean,
|
||||
private val reportSuspensionPointInsideMonitor: (String) -> Unit,
|
||||
private val lineNumber: Int,
|
||||
private val sourceFile: String,
|
||||
// It's only matters for named functions, may differ from '!isStatic(access)' in case of DefaultImpls
|
||||
private val needDispatchReceiver: Boolean = false,
|
||||
// May differ from containingClassInternalName in case of DefaultImpls
|
||||
@@ -76,8 +76,6 @@ class CoroutineTransformerMethodVisitor(
|
||||
) : TransformationMethodVisitor(delegate, access, name, desc, signature, exceptions) {
|
||||
|
||||
private val classBuilderForCoroutineState: ClassBuilder by lazy(obtainClassBuilderForCoroutineState)
|
||||
private val lineNumber = CodegenUtil.getLineNumberForElement(element, false) ?: 0
|
||||
private val sourceFile = element.containingKtFile.name
|
||||
|
||||
private var continuationIndex = if (isForNamedFunction) -1 else 0
|
||||
private var dataIndex = if (isForNamedFunction) -1 else 1
|
||||
@@ -315,7 +313,7 @@ class CoroutineTransformerMethodVisitor(
|
||||
sourceFile,
|
||||
findSuspensionPointLineNumber(suspensionPoint)?.line ?: -1
|
||||
)
|
||||
diagnostics.report(ErrorsJvm.SUSPENSION_POINT_INSIDE_MONITOR.on(element, "$stackTraceElement"))
|
||||
reportSuspensionPointInsideMonitor("$stackTraceElement")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.inline.addFakeContinuationConstructorCallMarker
|
||||
@@ -96,8 +97,9 @@ open class SuspendFunctionGenerationStrategy(
|
||||
return CoroutineTransformerMethodVisitor(
|
||||
mv, access, name, desc, null, null, containingClassInternalName, this::classBuilderForCoroutineState,
|
||||
isForNamedFunction = true,
|
||||
element = declaration,
|
||||
diagnostics = state.diagnostics,
|
||||
reportSuspensionPointInsideMonitor = { reportSuspensionPointInsideMonitor(declaration, state, it) },
|
||||
lineNumber = CodegenUtil.getLineNumberForElement(declaration, false) ?: 0,
|
||||
sourceFile = declaration.containingKtFile.name,
|
||||
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
|
||||
needDispatchReceiver = originalSuspendDescriptor.dispatchReceiverParameter != null,
|
||||
internalNameForDispatchReceiver = containingClassInternalNameOrNull(),
|
||||
|
||||
+2
-1
@@ -302,7 +302,8 @@ class AnonymousObjectTransformer(
|
||||
sourceNode.name,
|
||||
if (isConstructor) transformationInfo.newConstructorDescriptor else sourceNode.desc,
|
||||
inliningContext.callSiteInfo.isInlineOrInsideInline,
|
||||
isSuspendFunctionOrLambda(sourceNode)
|
||||
isSuspendFunctionOrLambda(sourceNode),
|
||||
inliningContext.root.sourceCompilerForInline.inlineCallSiteInfo.lineNumber
|
||||
), null
|
||||
)
|
||||
|
||||
|
||||
@@ -10,5 +10,6 @@ class InlineCallSiteInfo(
|
||||
val functionName: String?,
|
||||
val functionDesc: String?,
|
||||
val isInlineOrInsideInline: Boolean,
|
||||
val isSuspend: Boolean
|
||||
val isSuspend: Boolean,
|
||||
val lineNumber: Int
|
||||
)
|
||||
@@ -157,6 +157,7 @@ class MethodInliner(
|
||||
), AsmTypeRemapper(remapper, result)
|
||||
)
|
||||
|
||||
val fakeContinuationName = CoroutineTransformer.findFakeContinuationConstructorClassName(node)
|
||||
val markerShift = calcMarkerShift(parameters, node)
|
||||
val lambdaInliner = object : InlineAdapter(remappingMethodAdapter, parameters.argsSizeOnStack, sourceMapper) {
|
||||
private var transformationInfo: TransformationInfo? = null
|
||||
@@ -176,9 +177,7 @@ class MethodInliner(
|
||||
inlineCallSiteInfo
|
||||
)
|
||||
val transformer = transformationInfo!!.createTransformer(
|
||||
childInliningContext,
|
||||
isSameModule,
|
||||
CoroutineTransformer.findFakeContinuationConstructorClassName(node)
|
||||
childInliningContext, isSameModule, fakeContinuationName
|
||||
)
|
||||
|
||||
val transformResult = transformer.doTransform(nodeRemapper)
|
||||
|
||||
@@ -75,6 +75,8 @@ interface SourceCompilerForInline {
|
||||
val compilationContextFunctionDescriptor: FunctionDescriptor
|
||||
|
||||
fun getContextLabels(): Set<String>
|
||||
|
||||
fun reportSuspensionPointInsideMonitor(stackTraceElement: String)
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +122,8 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
signature.asmMethod.name,
|
||||
signature.asmMethod.descriptor,
|
||||
compilationContextFunctionDescriptor.isInlineOrInsideInline(),
|
||||
compilationContextFunctionDescriptor.isSuspend
|
||||
compilationContextFunctionDescriptor.isSuspend,
|
||||
CodegenUtil.getLineNumberForElement(callElement, false) ?: 0
|
||||
)
|
||||
}
|
||||
|
||||
@@ -365,6 +368,10 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
)
|
||||
}
|
||||
|
||||
override fun reportSuspensionPointInsideMonitor(stackTraceElement: String) {
|
||||
org.jetbrains.kotlin.codegen.coroutines.reportSuspensionPointInsideMonitor(callElement, state, stackTraceElement)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getContext(
|
||||
descriptor: DeclarationDescriptor,
|
||||
|
||||
+17
-19
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.codegen.inline.coroutines
|
||||
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.CAPTURED_THIS_FIELD
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
|
||||
@@ -66,29 +67,20 @@ class CoroutineTransformer(
|
||||
if (state.languageVersionSettings.isReleaseCoroutines()) superClassName.endsWith("ContinuationImpl")
|
||||
else methods.any { it.name == "getLabel" }
|
||||
|
||||
private fun crossinlineLambda(): PsiExpressionLambda? = inliningContext.expressionMap.values.find {
|
||||
it is PsiExpressionLambda && it.isCrossInline
|
||||
}?.cast()
|
||||
|
||||
private fun isStateMachine(node: MethodNode): Boolean =
|
||||
node.instructions.asSequence().any { insn -> insn is LdcInsnNode && insn.cst == ILLEGAL_STATE_ERROR_MESSAGE }
|
||||
|
||||
private fun isSuspendLambda(node: MethodNode) = isResumeImpl(node)
|
||||
|
||||
fun newMethod(node: MethodNode): DeferredMethodVisitor {
|
||||
// Find ANY element to report error about suspension point in monitor on.
|
||||
val element = crossinlineLambda()?.functionWithBodyOrCallableReference
|
||||
?: inliningContext.root.sourceCompilerForInline.callElement as? KtElement
|
||||
?: error("crossinline lambda should have element")
|
||||
|
||||
return when {
|
||||
isResumeImpl(node) -> {
|
||||
assert(!isStateMachine(node)) {
|
||||
"Inlining/transforming state-machine"
|
||||
}
|
||||
newStateMachineForLambda(node, element)
|
||||
newStateMachineForLambda(node)
|
||||
}
|
||||
isSuspendFunctionWithFakeConstructorCall(node) -> newStateMachineForNamedFunction(node, element)
|
||||
isSuspendFunctionWithFakeConstructorCall(node) -> newStateMachineForNamedFunction(node)
|
||||
else -> error("no need to generate state maching for ${node.name}")
|
||||
}
|
||||
}
|
||||
@@ -99,7 +91,7 @@ class CoroutineTransformer(
|
||||
|
||||
private fun isSuspendFunctionWithFakeConstructorCall(node: MethodNode): Boolean = findFakeContinuationConstructorClassName(node) != null
|
||||
|
||||
private fun newStateMachineForLambda(node: MethodNode, element: KtElement): DeferredMethodVisitor {
|
||||
private fun newStateMachineForLambda(node: MethodNode): DeferredMethodVisitor {
|
||||
val name = node.name.removeSuffix(FOR_INLINE_SUFFIX)
|
||||
return DeferredMethodVisitor(
|
||||
MethodNode(
|
||||
@@ -107,13 +99,16 @@ class CoroutineTransformer(
|
||||
ArrayUtil.toStringArray(node.exceptions)
|
||||
)
|
||||
) {
|
||||
val sourceCompilerForInline = inliningContext.root.sourceCompilerForInline
|
||||
val stateMachineBuilder = surroundNoinlineCallsWithMarkers(
|
||||
node,
|
||||
CoroutineTransformerMethodVisitor(
|
||||
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
|
||||
obtainClassBuilderForCoroutineState = { classBuilder },
|
||||
element = element,
|
||||
diagnostics = state.diagnostics,
|
||||
reportSuspensionPointInsideMonitor = { sourceCompilerForInline.reportSuspensionPointInsideMonitor(it) },
|
||||
// TODO: this linenumbers might not be correct and since they are used only for step-over, check them.
|
||||
lineNumber = sourceCompilerForInline.inlineCallSiteInfo.lineNumber,
|
||||
sourceFile = sourceCompilerForInline.callsiteFile?.name ?: "",
|
||||
languageVersionSettings = state.languageVersionSettings,
|
||||
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
|
||||
containingClassInternalName = classBuilder.thisName,
|
||||
@@ -137,7 +132,7 @@ class CoroutineTransformer(
|
||||
}
|
||||
}
|
||||
|
||||
private fun newStateMachineForNamedFunction(node: MethodNode, element: KtElement): DeferredMethodVisitor {
|
||||
private fun newStateMachineForNamedFunction(node: MethodNode): DeferredMethodVisitor {
|
||||
val name = node.name.removeSuffix(FOR_INLINE_SUFFIX)
|
||||
val continuationClassName = findFakeContinuationConstructorClassName(node)
|
||||
assert(inliningContext is RegeneratedClassContext)
|
||||
@@ -149,20 +144,23 @@ class CoroutineTransformer(
|
||||
) {
|
||||
// If the node already has state-machine, it is safer to generate state-machine.
|
||||
val disableTailCallOptimization = methods.find { it.name == name && it.desc == node.desc }?.let { isStateMachine(it) } ?: false
|
||||
val sourceCompilerForInline = inliningContext.root.sourceCompilerForInline
|
||||
val stateMachineBuilder = surroundNoinlineCallsWithMarkers(
|
||||
node,
|
||||
CoroutineTransformerMethodVisitor(
|
||||
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
|
||||
obtainClassBuilderForCoroutineState = { (inliningContext as RegeneratedClassContext).continuationBuilders[continuationClassName]!! },
|
||||
element = element,
|
||||
diagnostics = state.diagnostics,
|
||||
reportSuspensionPointInsideMonitor = { sourceCompilerForInline.reportSuspensionPointInsideMonitor(it) },
|
||||
lineNumber = sourceCompilerForInline.inlineCallSiteInfo.lineNumber,
|
||||
sourceFile = sourceCompilerForInline.callsiteFile?.name ?: "",
|
||||
languageVersionSettings = state.languageVersionSettings,
|
||||
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
|
||||
containingClassInternalName = classBuilder.thisName,
|
||||
isForNamedFunction = true,
|
||||
needDispatchReceiver = true,
|
||||
internalNameForDispatchReceiver = classBuilder.thisName,
|
||||
disableTailCallOptimizationForFunctionReturningUnit = disableTailCallOptimization
|
||||
disableTailCallOptimizationForFunctionReturningUnit = disableTailCallOptimization,
|
||||
putContinuationParameterToLvt = !state.isIrBackend
|
||||
)
|
||||
)
|
||||
|
||||
@@ -233,7 +231,7 @@ class CoroutineTransformer(
|
||||
|
||||
fun oldContinuationFrom(method: MethodNode): String? =
|
||||
methods.find { it.name == method.name + FOR_INLINE_SUFFIX && it.desc == method.desc }
|
||||
?.let { findFakeContinuationConstructorClassName(it) }
|
||||
?.let { findFakeContinuationConstructorClassName(it) }
|
||||
|
||||
companion object {
|
||||
fun findFakeContinuationConstructorClassName(node: MethodNode): String? {
|
||||
|
||||
@@ -431,7 +431,7 @@ fun addSuspendMarker(v: InstructionAdapter, isStartNotEnd: Boolean) {
|
||||
v.emitInlineMarker(if (isStartNotEnd) INLINE_MARKER_BEFORE_SUSPEND_ID else INLINE_MARKER_AFTER_SUSPEND_ID)
|
||||
}
|
||||
|
||||
internal fun addFakeContinuationConstructorCallMarker(v: InstructionAdapter, isStartNotEnd: Boolean) {
|
||||
fun addFakeContinuationConstructorCallMarker(v: InstructionAdapter, isStartNotEnd: Boolean) {
|
||||
v.emitInlineMarker(if (isStartNotEnd) INLINE_MARKER_BEFORE_FAKE_CONTINUATION_CONSTRUCTOR_CALL else INLINE_MARKER_AFTER_FAKE_CONTINUATION_CONSTRUCTOR_CALL)
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -83,6 +83,7 @@ abstract class IrElementTransformerVoidWithContext : IrElementTransformerVoid()
|
||||
protected val currentScope get() = scopeStack.peek()
|
||||
protected val parentScope get() = if (scopeStack.size < 2) null else scopeStack[scopeStack.size - 2]
|
||||
protected val allScopes get() = scopeStack
|
||||
protected val currentDeclarationParent get() = allScopes.last { it.irElement is IrDeclarationParent }.irElement as IrDeclarationParent
|
||||
|
||||
fun printScopeStack() {
|
||||
scopeStack.forEach { println(it.scope.scopeOwner) }
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.common.ir
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor
|
||||
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
@@ -566,9 +567,17 @@ fun copyBodyToStatic(oldFunction: IrFunction, staticFunction: IrFunction) {
|
||||
val mapping: Map<IrValueParameter, IrValueParameter> =
|
||||
(listOfNotNull(oldFunction.dispatchReceiverParameter, oldFunction.extensionReceiverParameter) + oldFunction.valueParameters)
|
||||
.zip(staticFunction.valueParameters).toMap()
|
||||
staticFunction.body = oldFunction.body
|
||||
copyBodyWithParametersMapping(staticFunction, oldFunction, mapping)
|
||||
}
|
||||
|
||||
fun copyBodyWithParametersMapping(
|
||||
newFunction: IrFunction,
|
||||
oldFunction: IrFunction,
|
||||
mapping: Map<IrValueParameter, IrValueParameter>
|
||||
) {
|
||||
newFunction.body = oldFunction.body?.deepCopyWithSymbols(oldFunction)
|
||||
?.transform(
|
||||
object: IrElementTransformerVoid() {
|
||||
object : IrElementTransformerVoid() {
|
||||
// Remap return targets to the static method so they do not appear to be
|
||||
// non-local returns.
|
||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||
@@ -578,8 +587,9 @@ fun copyBodyToStatic(oldFunction: IrFunction, staticFunction: IrFunction) {
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
expression.type,
|
||||
staticFunction.symbol,
|
||||
expression.value)
|
||||
newFunction.symbol,
|
||||
expression.value
|
||||
)
|
||||
} else expression
|
||||
}
|
||||
|
||||
@@ -589,8 +599,9 @@ fun copyBodyToStatic(oldFunction: IrFunction, staticFunction: IrFunction) {
|
||||
IrGetValueImpl(expression.startOffset, expression.endOffset, it.type, it.symbol, expression.origin)
|
||||
} ?: expression
|
||||
|
||||
}, null)
|
||||
?.patchDeclarationParents(staticFunction)
|
||||
}, null
|
||||
)
|
||||
?.patchDeclarationParents(newFunction)
|
||||
}
|
||||
|
||||
val IrSymbol.isSuspend: Boolean
|
||||
|
||||
+11
-5
@@ -87,6 +87,9 @@ class LocalDeclarationsLowering(
|
||||
object DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE :
|
||||
IrDeclarationOriginImpl("FIELD_FOR_CAPTURED_VALUE", isSynthetic = true)
|
||||
|
||||
object DECLARATION_ORIGIN_FIELD_FOR_CROSSINLINE_CAPTURED_VALUE :
|
||||
IrDeclarationOriginImpl("FIELD_FOR_CROSSINLINE_CAPTURED_VALUE", isSynthetic = true)
|
||||
|
||||
private object STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE :
|
||||
IrStatementOriginImpl("INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE")
|
||||
|
||||
@@ -655,14 +658,15 @@ class LocalDeclarationsLowering(
|
||||
name: Name,
|
||||
visibility: Visibility,
|
||||
parent: IrClass,
|
||||
fieldType: IrType
|
||||
fieldType: IrType,
|
||||
isCrossinline: Boolean
|
||||
): IrField {
|
||||
val descriptor = WrappedFieldDescriptor()
|
||||
val symbol = IrFieldSymbolImpl(descriptor)
|
||||
return IrFieldImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE,
|
||||
if (isCrossinline) DECLARATION_ORIGIN_FIELD_FOR_CROSSINLINE_CAPTURED_VALUE else DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE,
|
||||
symbol,
|
||||
name,
|
||||
fieldType,
|
||||
@@ -682,16 +686,18 @@ class LocalDeclarationsLowering(
|
||||
val generatedNames = mutableSetOf<Name>()
|
||||
localClassContext.closure.capturedValues.forEach { capturedValue ->
|
||||
|
||||
val owner = capturedValue.owner
|
||||
val irField = createFieldForCapturedValue(
|
||||
classDeclaration.startOffset,
|
||||
classDeclaration.endOffset,
|
||||
suggestNameForCapturedValue(capturedValue.owner, generatedNames),
|
||||
suggestNameForCapturedValue(owner, generatedNames),
|
||||
Visibilities.PRIVATE,
|
||||
classDeclaration,
|
||||
capturedValue.owner.type
|
||||
owner.type,
|
||||
owner is IrValueParameter && owner.isCrossinline
|
||||
)
|
||||
|
||||
localClassContext.capturedValueToField[capturedValue.owner] = irField
|
||||
localClassContext.capturedValueToField[owner] = irField
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -176,13 +176,15 @@ fun IrDeclarationContainer.addFunction(
|
||||
returnType: IrType,
|
||||
modality: Modality = Modality.FINAL,
|
||||
isStatic: Boolean = false,
|
||||
isSuspend: Boolean = false
|
||||
isSuspend: Boolean = false,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||
): IrSimpleFunction =
|
||||
addFunction {
|
||||
this.name = Name.identifier(name)
|
||||
this.returnType = returnType
|
||||
this.modality = modality
|
||||
this.isSuspend = isSuspend
|
||||
this.origin = origin
|
||||
}.apply {
|
||||
if (!isStatic) {
|
||||
dispatchReceiverParameter = parentAsClass.thisReceiver!!.copyTo(this)
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm
|
||||
@@ -51,4 +40,9 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
||||
object POLYMORPHIC_SIGNATURE_INSTANTIATION : IrDeclarationOriginImpl("POLYMORPHIC_SIGNATURE_INSTANTIATION", isSynthetic = true)
|
||||
object ENUM_CONSTRUCTOR_SYNTHETIC_PARAMETER : IrDeclarationOriginImpl("ENUM_CONSTRUCTOR_SYNTHETIC_PARAMETER", isSynthetic = true)
|
||||
object OBJECT_SUPER_CONSTRUCTOR_PARAMETER : IrDeclarationOriginImpl("OBJECT_SUPER_CONSTURCTOR_PARAMETER", isSynthetic = true)
|
||||
object CONTINUATION_CLASS : IrDeclarationOriginImpl("CONTINUATION_CLASS")
|
||||
object SUSPEND_LAMBDA : IrDeclarationOriginImpl("SUSPEND_LAMBDA")
|
||||
object FOR_INLINE_STATE_MACHINE_TEMPLATE : IrDeclarationOriginImpl("FOR_INLINE_TEMPLATE")
|
||||
object FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE : IrDeclarationOriginImpl("FOR_INLINE_TEMPLATE_CROSSINLINE")
|
||||
object FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE_VIEW : IrDeclarationOriginImpl("FOR_INLINE_TEMPLATE_CROSSINLINE_VIEW")
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.ir.builders.irNull
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
@@ -97,9 +98,8 @@ class JvmBackendContext(
|
||||
|
||||
override val internalPackageFqn = FqName("kotlin.jvm")
|
||||
|
||||
val suspendFunctionContinuations = mutableMapOf<IrFunction, IrClass>()
|
||||
val suspendLambdaToOriginalFunctionMap = mutableMapOf<IrClass, IrFunction>()
|
||||
val continuationClassBuilders = mutableMapOf<IrClass, ClassBuilder>()
|
||||
val suspendLambdaToOriginalFunctionMap = mutableMapOf<IrFunctionReference, IrFunction>()
|
||||
val continuationClassBuilders = mutableMapOf<IrSimpleFunction, ClassBuilder>()
|
||||
val suspendFunctionOriginalToView = mutableMapOf<IrFunction, IrFunction>()
|
||||
val suspendFunctionViewToOriginal = mutableMapOf<IrFunction, IrFunction>()
|
||||
val fakeContinuation: IrExpression = createFakeContinuation(this)
|
||||
|
||||
+4
-9
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.buildAssertionsDisabledField
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.hasAssertionsDisabledField
|
||||
@@ -126,12 +127,6 @@ open class ClassCodegen protected constructor(
|
||||
} else null
|
||||
}
|
||||
|
||||
// Suspend function state-machine builder requires half-built continuation class
|
||||
val continuationCodegens = nestedClasses.filter { it.irClass in context.suspendFunctionContinuations.values }
|
||||
for (continuationCodegen in continuationCodegens) {
|
||||
continuationCodegen.generate()
|
||||
}
|
||||
|
||||
val fileEntry = context.psiSourceManager.getFileEntry(irClass.fileParent)
|
||||
if (fileEntry != null) {
|
||||
/* TODO: Temporary workaround: ClassBuilder needs a pathless name. */
|
||||
@@ -153,14 +148,14 @@ open class ClassCodegen protected constructor(
|
||||
|
||||
// Generate nested classes at the end, to ensure that codegen for companion object will have the necessary JVM signatures in its
|
||||
// trace for properties moved to the outer class
|
||||
for (codegen in (nestedClasses - continuationCodegens)) {
|
||||
for (codegen in nestedClasses) {
|
||||
codegen.generate()
|
||||
}
|
||||
|
||||
generateKotlinMetadataAnnotation()
|
||||
|
||||
if (irClass in context.suspendFunctionContinuations.values) {
|
||||
context.continuationClassBuilders[irClass] = visitor
|
||||
if (irClass.origin == JvmLoweredDeclarationOrigin.CONTINUATION_CLASS) {
|
||||
context.continuationClassBuilders[irClass.attributeOwnerId as IrSimpleFunction] = visitor
|
||||
} else {
|
||||
done()
|
||||
}
|
||||
|
||||
+65
-22
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
|
||||
import org.jetbrains.kotlin.backend.common.ir.isSuspend
|
||||
@@ -14,6 +15,8 @@ import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
|
||||
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME
|
||||
import org.jetbrains.kotlin.codegen.coroutines.reportSuspensionPointInsideMonitor
|
||||
import org.jetbrains.kotlin.codegen.inline.addFakeContinuationConstructorCallMarker
|
||||
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
@@ -37,11 +40,14 @@ import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
internal fun generateStateMachineForNamedFunction(
|
||||
irFunction: IrFunction,
|
||||
@@ -49,21 +55,19 @@ internal fun generateStateMachineForNamedFunction(
|
||||
methodVisitor: MethodVisitor,
|
||||
access: Int,
|
||||
signature: JvmMethodGenericSignature,
|
||||
continuationClassBuilder: ClassBuilder?,
|
||||
obtainContinuationClassBuilder: () -> ClassBuilder,
|
||||
element: KtElement
|
||||
): MethodVisitor {
|
||||
assert(irFunction.isSuspend)
|
||||
assert(continuationClassBuilder != null) {
|
||||
"Class builder for continuation is null"
|
||||
}
|
||||
val state = classCodegen.state
|
||||
val languageVersionSettings = state.languageVersionSettings
|
||||
assert(languageVersionSettings.isReleaseCoroutines()) { "Experimental coroutines are unsupported in JVM_IR backend" }
|
||||
return CoroutineTransformerMethodVisitor(
|
||||
methodVisitor, access, signature.asmMethod.name, signature.asmMethod.descriptor, signature.genericsSignature, null,
|
||||
obtainClassBuilderForCoroutineState = { continuationClassBuilder!! },
|
||||
element = element,
|
||||
diagnostics = state.diagnostics,
|
||||
methodVisitor, access, signature.asmMethod.name, signature.asmMethod.descriptor, null, null,
|
||||
obtainClassBuilderForCoroutineState = obtainContinuationClassBuilder,
|
||||
reportSuspensionPointInsideMonitor = { reportSuspensionPointInsideMonitor(element, state, it) },
|
||||
lineNumber = CodegenUtil.getLineNumberForElement(element, false) ?: 0,
|
||||
sourceFile = classCodegen.irClass.file.name,
|
||||
languageVersionSettings = languageVersionSettings,
|
||||
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
|
||||
containingClassInternalName = classCodegen.visitor.thisName,
|
||||
@@ -92,8 +96,9 @@ internal fun generateStateMachineForLambda(
|
||||
return CoroutineTransformerMethodVisitor(
|
||||
methodVisitor, access, signature.asmMethod.name, signature.asmMethod.descriptor, signature.genericsSignature, null,
|
||||
obtainClassBuilderForCoroutineState = { classCodegen.visitor },
|
||||
element = element,
|
||||
diagnostics = state.diagnostics,
|
||||
reportSuspensionPointInsideMonitor = { reportSuspensionPointInsideMonitor(element, state, it) },
|
||||
lineNumber = CodegenUtil.getLineNumberForElement(element, false) ?: 0,
|
||||
sourceFile = classCodegen.irClass.file.name,
|
||||
languageVersionSettings = languageVersionSettings,
|
||||
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
|
||||
containingClassInternalName = classCodegen.visitor.thisName,
|
||||
@@ -102,17 +107,18 @@ internal fun generateStateMachineForLambda(
|
||||
)
|
||||
}
|
||||
|
||||
internal fun IrFunction.isInvokeSuspendOfLambda(context: JvmBackendContext): Boolean =
|
||||
name.asString() == INVOKE_SUSPEND_METHOD_NAME && parent in context.suspendLambdaToOriginalFunctionMap
|
||||
internal fun IrFunction.isInvokeSuspendOfLambda(): Boolean =
|
||||
name.asString() == INVOKE_SUSPEND_METHOD_NAME && parentAsClass.origin == JvmLoweredDeclarationOrigin.SUSPEND_LAMBDA
|
||||
|
||||
internal fun IrFunction.isInvokeOfSuspendLambda(context: JvmBackendContext): Boolean =
|
||||
name.asString() == "invoke" && parent in context.suspendLambdaToOriginalFunctionMap
|
||||
internal fun IrFunction.isInvokeSuspendForInlineOfLambda(): Boolean =
|
||||
origin == JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE
|
||||
&& parentAsClass.origin == JvmLoweredDeclarationOrigin.SUSPEND_LAMBDA
|
||||
|
||||
internal fun IrFunction.isInvokeSuspendOfContinuation(context: JvmBackendContext): Boolean =
|
||||
name.asString() == INVOKE_SUSPEND_METHOD_NAME && parentAsClass in context.suspendFunctionContinuations.values
|
||||
internal fun IrFunction.isInvokeSuspendOfContinuation(): Boolean =
|
||||
name.asString() == INVOKE_SUSPEND_METHOD_NAME && parentAsClass.origin == JvmLoweredDeclarationOrigin.CONTINUATION_CLASS
|
||||
|
||||
internal fun IrFunction.isInvokeOfSuspendCallableReference(): Boolean = isSuspend && name.asString() == "invoke" &&
|
||||
(parent as? IrClass)?.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL
|
||||
parentAsClass.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL
|
||||
|
||||
internal fun IrFunction.isKnownToBeTailCall(): Boolean =
|
||||
when (origin) {
|
||||
@@ -126,13 +132,15 @@ internal fun IrFunction.isKnownToBeTailCall(): Boolean =
|
||||
else -> isInvokeOfSuspendCallableReference()
|
||||
}
|
||||
|
||||
internal fun IrFunction.shouldNotContainSuspendMarkers(context: JvmBackendContext): Boolean =
|
||||
isInvokeSuspendOfContinuation(context) || isKnownToBeTailCall()
|
||||
internal fun IrFunction.shouldNotContainSuspendMarkers(): Boolean =
|
||||
isInvokeSuspendOfContinuation() || isKnownToBeTailCall()
|
||||
|
||||
// Transform `suspend fun foo(params): RetType` into `fun foo(params, $completion: Continuation<RetType>): Any?`
|
||||
// the result is called 'view', just to be consistent with old backend.
|
||||
internal fun IrFunction.getOrCreateSuspendFunctionViewIfNeeded(context: JvmBackendContext): IrFunction {
|
||||
if (!isSuspend || origin == JvmLoweredDeclarationOrigin.SUSPEND_FUNCTION_VIEW) return this
|
||||
if (!isSuspend || origin == JvmLoweredDeclarationOrigin.SUSPEND_FUNCTION_VIEW ||
|
||||
origin == JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE_VIEW
|
||||
) return this
|
||||
context.suspendFunctionOriginalToView[this]?.let { return it }
|
||||
return suspendFunctionView(context)
|
||||
}
|
||||
@@ -152,7 +160,12 @@ private fun IrFunction.suspendFunctionView(context: JvmBackendContext): IrFuncti
|
||||
else
|
||||
WrappedSimpleFunctionDescriptor(sourceElement = originalDescriptor.source)
|
||||
return IrFunctionImpl(
|
||||
startOffset, endOffset, JvmLoweredDeclarationOrigin.SUSPEND_FUNCTION_VIEW, IrSimpleFunctionSymbolImpl(descriptor),
|
||||
startOffset, endOffset,
|
||||
if (origin == JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE)
|
||||
JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE_VIEW
|
||||
else
|
||||
JvmLoweredDeclarationOrigin.SUSPEND_FUNCTION_VIEW,
|
||||
IrSimpleFunctionSymbolImpl(descriptor),
|
||||
name, visibility, modality, context.irBuiltIns.anyNType,
|
||||
isInline = isInline, isExternal = isExternal, isTailrec = isTailrec, isSuspend = isSuspend, isExpect = isExpect,
|
||||
isFakeOverride = false, isOperator = false
|
||||
@@ -196,6 +209,7 @@ private fun IrFunction.suspendFunctionView(context: JvmBackendContext): IrFuncti
|
||||
return super.visitCall(expression.createSuspendFunctionCallViewIfNeeded(context, it, callerIsInlineLambda = false))
|
||||
}
|
||||
})
|
||||
it.copyAttributes(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +230,8 @@ internal fun IrCall.createSuspendFunctionCallViewIfNeeded(
|
||||
}
|
||||
val continuationParameter =
|
||||
when {
|
||||
caller.isInvokeSuspendOfLambda(context) || caller.isInvokeSuspendOfContinuation(context) ->
|
||||
caller.isInvokeSuspendOfLambda() || caller.isInvokeSuspendOfContinuation() ||
|
||||
caller.isInvokeSuspendForInlineOfLambda() ->
|
||||
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, caller.dispatchReceiverParameter!!.symbol)
|
||||
callerIsInlineLambda -> context.fakeContinuation
|
||||
else -> IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, caller.valueParameters.last().symbol)
|
||||
@@ -231,3 +246,31 @@ internal fun createFakeContinuation(context: JvmBackendContext): IrExpression =
|
||||
context.ir.symbols.continuationClass.createType(true, listOf(makeTypeProjection(context.irBuiltIns.anyNType, Variance.INVARIANT))),
|
||||
"FAKE_CONTINUATION"
|
||||
)
|
||||
|
||||
internal fun generateFakeContinuationConstructorCall(
|
||||
v: InstructionAdapter,
|
||||
containingClassBuilder: ClassBuilder,
|
||||
classBuilder: ClassBuilder,
|
||||
irFunction: IrFunction
|
||||
) {
|
||||
val continuationType = Type.getObjectType(classBuilder.thisName)
|
||||
// TODO: This is different in case of DefaultImpls
|
||||
val thisNameType = Type.getObjectType(containingClassBuilder.thisName.replace(".", "/"))
|
||||
val continuationIndex = listOfNotNull(irFunction.dispatchReceiverParameter, irFunction.extensionReceiverParameter).size +
|
||||
irFunction.valueParameters.size - 1
|
||||
with(v) {
|
||||
addFakeContinuationConstructorCallMarker(this, true)
|
||||
anew(continuationType)
|
||||
dup()
|
||||
if (irFunction.dispatchReceiverParameter != null) {
|
||||
load(0, AsmTypes.OBJECT_TYPE)
|
||||
load(continuationIndex, Type.getObjectType("kotlin/coroutines/Continuation"))
|
||||
invokespecial(continuationType.internalName, "<init>", "(${thisNameType}Lkotlin/coroutines/Continuation;)V", false)
|
||||
} else {
|
||||
load(continuationIndex, Type.getObjectType("kotlin/coroutines/Continuation"))
|
||||
invokespecial(continuationType.internalName, "<init>", "(Lkotlin/coroutines/Continuation;)V", false)
|
||||
}
|
||||
pop()
|
||||
addFakeContinuationConstructorCallMarker(this, false)
|
||||
}
|
||||
}
|
||||
+25
-5
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.codegen.inline.*
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.putNeedClassReificationMarker
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.OperationKind.AS
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.OperationKind.SAFE_AS
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
|
||||
import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysFalseIfeq
|
||||
import org.jetbrains.kotlin.codegen.pseudoInsns.fixStackAndJump
|
||||
@@ -48,9 +49,11 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||
import org.jetbrains.kotlin.types.model.TypeParameterMarker
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
@@ -193,6 +196,7 @@ class ExpressionCodegen(
|
||||
val info = BlockInfo()
|
||||
val body = irFunction.body!!
|
||||
generateNonNullAssertions()
|
||||
generateFakeContinuationConstructorIfNeeded()
|
||||
val result = body.accept(this, info)
|
||||
// If this function has an expression body, return the result of that expression.
|
||||
// Otherwise, if it does not end in a return statement, it must be void-returning,
|
||||
@@ -213,6 +217,19 @@ class ExpressionCodegen(
|
||||
writeParameterInLocalVariableTable(startLabel, endLabel)
|
||||
}
|
||||
|
||||
private fun generateFakeContinuationConstructorIfNeeded() {
|
||||
if (irFunction.origin != JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE_VIEW) return
|
||||
val continuationClass = classCodegen.irClass.functions.find {
|
||||
it.name.asString() == irFunction.name.asString().removeSuffix(FOR_INLINE_SUFFIX)
|
||||
}?.body?.statements?.get(0) ?: error("could not find continuation for ${irFunction.render()}")
|
||||
generateFakeContinuationConstructorCall(
|
||||
mv,
|
||||
classCodegen.visitor,
|
||||
context.continuationClassBuilders[(continuationClass as IrClass).attributeOwnerId]!!,
|
||||
irFunction
|
||||
)
|
||||
}
|
||||
|
||||
private fun generateNonNullAssertions() {
|
||||
if (state.isParamAssertionsDisabled)
|
||||
return
|
||||
@@ -229,14 +246,17 @@ class ExpressionCodegen(
|
||||
irFunction.origin == IrDeclarationOrigin.BRIDGE_SPECIAL ||
|
||||
irFunction.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE ||
|
||||
irFunction.origin == JvmLoweredDeclarationOrigin.JVM_STATIC_WRAPPER ||
|
||||
irFunction.origin == JvmLoweredDeclarationOrigin.MULTIFILE_BRIDGE
|
||||
irFunction.origin == JvmLoweredDeclarationOrigin.MULTIFILE_BRIDGE ||
|
||||
irFunction.parentAsClass.origin == JvmLoweredDeclarationOrigin.CONTINUATION_CLASS ||
|
||||
irFunction.parentAsClass.origin == JvmLoweredDeclarationOrigin.SUSPEND_LAMBDA
|
||||
|
||||
if (notCallableFromJava)
|
||||
return
|
||||
|
||||
// Do not generate non-null checks for suspend function views. When resumed the arguments
|
||||
// will be null and the actual values are taken from the continuation.
|
||||
val isSuspendFunctionView = irFunction.origin == JvmLoweredDeclarationOrigin.SUSPEND_FUNCTION_VIEW
|
||||
val isSuspendFunctionView = irFunction.origin == JvmLoweredDeclarationOrigin.SUSPEND_FUNCTION_VIEW ||
|
||||
irFunction.origin == JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE_VIEW
|
||||
|
||||
if (isSuspendFunctionView)
|
||||
return
|
||||
@@ -381,7 +401,7 @@ class ExpressionCodegen(
|
||||
}
|
||||
expression.symbol.descriptor is ConstructorDescriptor ->
|
||||
throw AssertionError("IrCall with ConstructorDescriptor: ${expression.javaClass.simpleName}")
|
||||
callee.isSuspend && !irFunction.shouldNotContainSuspendMarkers(classCodegen.context) ->
|
||||
callee.isSuspend && !irFunction.shouldNotContainSuspendMarkers() ->
|
||||
addInlineMarker(mv, isStartNotEnd = true)
|
||||
}
|
||||
|
||||
@@ -407,13 +427,13 @@ class ExpressionCodegen(
|
||||
expression.markLineNumber(true)
|
||||
|
||||
// Do not generate redundant markers in continuation class.
|
||||
if (callee.isSuspend && !irFunction.shouldNotContainSuspendMarkers(classCodegen.context)) {
|
||||
if (callee.isSuspend && !irFunction.shouldNotContainSuspendMarkers()) {
|
||||
addSuspendMarker(mv, isStartNotEnd = true)
|
||||
}
|
||||
|
||||
callGenerator.genCall(callable, this, expression)
|
||||
|
||||
if (callee.isSuspend && !irFunction.shouldNotContainSuspendMarkers(classCodegen.context)) {
|
||||
if (callee.isSuspend && !irFunction.shouldNotContainSuspendMarkers()) {
|
||||
addSuspendMarker(mv, isStartNotEnd = false)
|
||||
addInlineMarker(mv, isStartNotEnd = false)
|
||||
}
|
||||
|
||||
+39
-14
@@ -12,6 +12,8 @@ import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.mangleNameIfNeeded
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilderMode
|
||||
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_IMPL_NAME_SUFFIX
|
||||
import org.jetbrains.kotlin.codegen.visitAnnotableParameterCount
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
@@ -28,6 +30,7 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
@@ -77,34 +80,56 @@ open class FunctionCodegen(
|
||||
generateAnnotationDefaultValueIfNeeded(methodVisitor)
|
||||
} else {
|
||||
val frameMap = createFrameMapWithReceivers()
|
||||
val irClass = context.suspendFunctionContinuations[irFunction]
|
||||
val element = (irFunction.symbol.descriptor.psiElement
|
||||
?: context.suspendLambdaToOriginalFunctionMap[irFunction.parent]?.symbol?.descriptor?.psiElement) as? KtElement
|
||||
val continuationClassBuilder = context.continuationClassBuilders[irClass]
|
||||
methodVisitor = when {
|
||||
irFunction.isSuspend &&
|
||||
// We do not generate continuation and state-machine for synthetic accessors, bridges, and delegated members,
|
||||
// in a sense, they are tail-call
|
||||
!irFunction.isKnownToBeTailCall() &&
|
||||
// TODO: We should generate two versions of inline suspend function: one with state-machine and one without
|
||||
!irFunction.isInline ->
|
||||
irFunction.hasContinuation() -> {
|
||||
generateStateMachineForNamedFunction(
|
||||
irFunction, classCodegen, methodVisitor, flags, signature, continuationClassBuilder, element!!
|
||||
irFunction, classCodegen, methodVisitor,
|
||||
access = flags,
|
||||
signature = signature,
|
||||
obtainContinuationClassBuilder = {
|
||||
context.continuationClassBuilders[continuationClass().attributeOwnerId]!!
|
||||
},
|
||||
element = psiElement()
|
||||
)
|
||||
irFunction.isInvokeSuspendOfLambda(context) -> generateStateMachineForLambda(
|
||||
classCodegen, methodVisitor, flags, signature, element!!
|
||||
}
|
||||
irFunction.isInvokeSuspendOfLambda() -> generateStateMachineForLambda(
|
||||
classCodegen, methodVisitor, flags, signature, psiElement()
|
||||
)
|
||||
else -> methodVisitor
|
||||
}
|
||||
ExpressionCodegen(functionView, signature, frameMap, InstructionAdapter(methodVisitor), classCodegen, inlinedInto).generate()
|
||||
methodVisitor.visitMaxs(-1, -1)
|
||||
continuationClassBuilder?.done()
|
||||
if (irFunction.hasContinuation()) {
|
||||
context.continuationClassBuilders[continuationClass().attributeOwnerId].sure {
|
||||
"Could not find continuation class builder for ${continuationClass().render()}"
|
||||
}.done()
|
||||
}
|
||||
}
|
||||
methodVisitor.visitEnd()
|
||||
|
||||
return signature
|
||||
}
|
||||
|
||||
private fun psiElement(): KtElement =
|
||||
if (irFunction.isSuspend) irFunction.symbol.descriptor.psiElement as KtElement
|
||||
else context.suspendLambdaToOriginalFunctionMap[irFunction.parentAsClass.attributeOwnerId]!!.symbol.descriptor.psiElement as KtElement
|
||||
|
||||
private fun IrFunction.hasContinuation(): Boolean = isSuspend &&
|
||||
// We do not generate continuation and state-machine for synthetic accessors, bridges, and delegated members,
|
||||
// in a sense, they are tail-call
|
||||
!isKnownToBeTailCall() &&
|
||||
// TODO: We should generate two versions of inline suspend function: one with state-machine and one without
|
||||
!isInline &&
|
||||
// This is suspend lambda parameter of inline function
|
||||
origin != IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA &&
|
||||
// This is just a template for inliner
|
||||
origin != JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE &&
|
||||
// Continuations are generated for suspendImpls
|
||||
parentAsClass.functions.none { it.name.asString() == name.asString() + SUSPEND_IMPL_NAME_SUFFIX }
|
||||
|
||||
private fun continuationClass(): IrClass =
|
||||
irFunction.body!!.statements[0] as IrClass
|
||||
|
||||
private fun calculateMethodFlags(isStatic: Boolean): Int {
|
||||
if (irFunction.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER) {
|
||||
return Opcodes.ACC_PUBLIC or Opcodes.ACC_SYNTHETIC.let {
|
||||
|
||||
+19
-2
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.backend.common.ir.ir2string
|
||||
import org.jetbrains.kotlin.codegen.BaseExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
@@ -16,16 +17,24 @@ import org.jetbrains.kotlin.codegen.inline.*
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
||||
import org.jetbrains.kotlin.ir.util.isSuspend
|
||||
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
@@ -61,7 +70,8 @@ class IrSourceCompilerForInline(
|
||||
root.signature.asmMethod.descriptor,
|
||||
//compilationContextFunctionDescriptor.isInlineOrInsideInline()
|
||||
false,
|
||||
compilationContextFunctionDescriptor.isSuspend
|
||||
compilationContextFunctionDescriptor.isSuspend,
|
||||
findElement()?.let { CodegenUtil.getLineNumberForElement(it, false) } ?: 0
|
||||
)
|
||||
}
|
||||
|
||||
@@ -127,13 +137,20 @@ class IrSourceCompilerForInline(
|
||||
override fun getContextLabels(): Set<String> {
|
||||
val name = codegen.irFunction.name.asString()
|
||||
if (name == INVOKE_SUSPEND_METHOD_NAME) {
|
||||
codegen.context.suspendLambdaToOriginalFunctionMap[codegen.irFunction.parent]?.let {
|
||||
codegen.context.suspendLambdaToOriginalFunctionMap[codegen.irFunction.parentAsClass.attributeOwnerId]?.let {
|
||||
return setOf(it.name.asString())
|
||||
}
|
||||
}
|
||||
return setOf(name)
|
||||
}
|
||||
|
||||
// TODO: Find a way to avoid using PSI here
|
||||
override fun reportSuspensionPointInsideMonitor(stackTraceElement: String) {
|
||||
org.jetbrains.kotlin.codegen.coroutines.reportSuspensionPointInsideMonitor(findElement()!!, state, stackTraceElement)
|
||||
}
|
||||
|
||||
private fun findElement() = (callElement.symbol.descriptor.original as? DeclarationDescriptorWithSource)?.source?.getPsi() as? KtElement
|
||||
|
||||
internal val isPrimaryCopy: Boolean
|
||||
get() = codegen.classCodegen !is FakeClassCodegen
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
@@ -25,6 +26,7 @@ import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||
import org.jetbrains.kotlin.ir.util.isSuspendFunction
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.load.kotlin.computeExpandedTypeForInlineClass
|
||||
import org.jetbrains.kotlin.load.kotlin.mapBuiltInType
|
||||
|
||||
+4
-1
@@ -5,12 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.eraseTypeParameters
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
@@ -90,7 +92,8 @@ fun PromisedValue.coerce(target: Type, irTarget: IrType): PromisedValue {
|
||||
|
||||
// Boxing and unboxing kotlin.Result leads to CCE in generated code
|
||||
val doNotCoerceKotlinResultInContinuation =
|
||||
(codegen.irFunction.isInvokeSuspendOfContinuation(codegen.context) || codegen.irFunction.isInvokeOfSuspendLambda(codegen.context))
|
||||
(codegen.irFunction.parentAsClass.origin == JvmLoweredDeclarationOrigin.CONTINUATION_CLASS ||
|
||||
codegen.irFunction.parentAsClass.origin == JvmLoweredDeclarationOrigin.SUSPEND_LAMBDA)
|
||||
&& (irType.isKotlinResult() || irTarget.isKotlinResult())
|
||||
|
||||
// Coerce inline classes
|
||||
|
||||
+216
-151
@@ -5,19 +5,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.backend.common.ir.*
|
||||
import org.jetbrains.kotlin.backend.common.lower.LocalDeclarationsLowering
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.parents
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.common.pop
|
||||
import org.jetbrains.kotlin.backend.common.push
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrBlock
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.isInvokeOfSuspendCallableReference
|
||||
import org.jetbrains.kotlin.codegen.coroutines.*
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
@@ -43,7 +40,6 @@ import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||
|
||||
internal val addContinuationPhase = makeIrFilePhase(
|
||||
::AddContinuationLowering,
|
||||
@@ -51,50 +47,53 @@ internal val addContinuationPhase = makeIrFilePhase(
|
||||
"Add continuation classes to suspend functions and transform suspend lambdas into continuations"
|
||||
)
|
||||
|
||||
private object CONTINUATION_CLASS : IrDeclarationOriginImpl("CONTINUATION_CLASS")
|
||||
|
||||
private class AddContinuationLowering(private val context: JvmBackendContext) : FileLoweringPass {
|
||||
private val functionsToAdd = mutableMapOf<IrClass, MutableSet<IrFunction>>()
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
val suspendLambdas = markSuspendLambdas(irFile)
|
||||
val suspendFunctions = markSuspendFunctions(irFile, suspendLambdas.map { it.function }.toSet())
|
||||
for (lambda in suspendLambdas) {
|
||||
generateContinuationClassForLambda(lambda)
|
||||
val (suspendLambdas, inlineLambdas) = markSuspendLambdas(irFile)
|
||||
transformSuspendFunctions(irFile, (suspendLambdas.map { it.function } + inlineLambdas).toSet())
|
||||
for ((clazz, functions) in functionsToAdd) {
|
||||
for (function in functions) {
|
||||
clazz.declarations.add(function)
|
||||
}
|
||||
}
|
||||
transformReferencesToSuspendLambdas(irFile, suspendLambdas)
|
||||
transformSuspendCalls(irFile)
|
||||
for (suspendFunction in suspendFunctions) {
|
||||
generateContinuationClassForNamedFunction(suspendFunction)
|
||||
}
|
||||
}
|
||||
|
||||
private fun transformReferencesToSuspendLambdas(irFile: IrFile, suspendLambdas: List<SuspendLambdaInfo>) {
|
||||
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
for (lambda in suspendLambdas) {
|
||||
(lambda.function.parent as IrDeclarationContainer).declarations.remove(lambda.function)
|
||||
}
|
||||
irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
||||
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
if (!expression.isSuspend)
|
||||
return expression
|
||||
val constructor = suspendLambdas.singleOrNull { it.function == expression.symbol.owner }?.constructor
|
||||
?: return expression
|
||||
val expressionArguments = expression.getArguments().map { it.second }
|
||||
assert(constructor.valueParameters.size == expressionArguments.size) {
|
||||
"Inconsistency between callable reference to suspend lambda and the corresponding continuation"
|
||||
}
|
||||
val irBuilder = context.createIrBuilder(expression.symbol, expression.startOffset, expression.endOffset)
|
||||
irBuilder.run {
|
||||
return irCall(constructor.symbol).apply {
|
||||
expressionArguments.forEachIndexed { index, argument ->
|
||||
putValueArgument(index, argument)
|
||||
val info = suspendLambdas.singleOrNull { it.function == expression.symbol.owner } ?: return expression
|
||||
return context.createIrBuilder(expression.symbol, expression.startOffset, expression.endOffset).run {
|
||||
val expressionArguments = expression.getArguments().map { it.second }
|
||||
irBlock {
|
||||
+generateContinuationClassForLambda(info, currentDeclarationParent)
|
||||
val constructor = info.constructor
|
||||
assert(constructor.valueParameters.size == expressionArguments.size + 1) {
|
||||
"Inconsistency between callable reference to suspend lambda and the corresponding continuation"
|
||||
}
|
||||
+irCall(constructor.symbol).apply {
|
||||
expressionArguments.forEachIndexed { index, argument ->
|
||||
putValueArgument(index, argument)
|
||||
}
|
||||
// Pass null as completion parameter
|
||||
putValueArgument(expressionArguments.size, irNull())
|
||||
}
|
||||
}
|
||||
}
|
||||
}.also { it.transformChildrenVoid(this) }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun generateContinuationClassForLambda(info: SuspendLambdaInfo) {
|
||||
private fun generateContinuationClassForLambda(info: SuspendLambdaInfo, parent: IrDeclarationParent): IrClass {
|
||||
val suspendLambda = context.ir.symbols.suspendLambdaClass.owner
|
||||
suspendLambda.createContinuationClassFor(info.function).apply {
|
||||
return suspendLambda.createContinuationClassFor(parent, JvmLoweredDeclarationOrigin.SUSPEND_LAMBDA).apply {
|
||||
copyAttributes(info.reference)
|
||||
val functionNClass = context.ir.symbols.getJvmFunctionClass(info.arity + 1)
|
||||
superTypes.add(
|
||||
@@ -120,11 +119,14 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
.mapNotNull { (i, field) -> if (info.reference.getValueArgument(i) == null) field else null }
|
||||
val parametersWithArguments = parametersFields - parametersWithoutArguments
|
||||
val constructor = addPrimaryConstructorForLambda(info.arity, info.reference, parametersFields)
|
||||
val secondaryConstructor = addSecondaryConstructorForLambda(constructor)
|
||||
val invokeToOverride = functionNClass.functions.single {
|
||||
it.owner.valueParameters.size == info.arity + 1 && it.owner.name.asString() == "invoke"
|
||||
}
|
||||
val invokeSuspend = addInvokeSuspendForLambda(info.function, parametersFields, receiverField)
|
||||
if (info.capturesCrossinline) {
|
||||
addInvokeSuspendForInlineForLambda(invokeSuspend, info.function, parametersFields, receiverField)
|
||||
}
|
||||
info.function.parentAsClass.declarations.remove(info.function)
|
||||
if (info.arity <= 1) {
|
||||
val singleParameterField = receiverField ?: parametersWithoutArguments.singleOrNull()
|
||||
val create = addCreate(constructor, suspendLambda, info, parametersWithArguments, singleParameterField)
|
||||
@@ -139,9 +141,9 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
)
|
||||
}
|
||||
|
||||
context.suspendLambdaToOriginalFunctionMap[this] = info.function
|
||||
context.suspendLambdaToOriginalFunctionMap[attributeOwnerId as IrFunctionReference] = info.function
|
||||
|
||||
info.constructor = secondaryConstructor
|
||||
info.constructor = constructor
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,46 +156,73 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
it.owner.name.asString() == INVOKE_SUSPEND_METHOD_NAME && it.owner.valueParameters.size == 1 &&
|
||||
it.owner.valueParameters[0].type.isKotlinResult()
|
||||
}.owner
|
||||
return addFunctionOverride(superMethod)
|
||||
.also { function ->
|
||||
function.copyTypeParametersFrom(irFunction)
|
||||
function.body = irFunction.body?.deepCopyWithSymbols(function)
|
||||
function.body?.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
if (expression.symbol.owner == irFunction.extensionReceiverParameter) {
|
||||
assert(receiverField != null)
|
||||
return IrGetFieldImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
receiverField!!.symbol,
|
||||
receiverField.type
|
||||
).also {
|
||||
it.receiver =
|
||||
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, function.dispatchReceiverParameter!!.symbol)
|
||||
}
|
||||
} else if (expression.symbol.owner == irFunction.dispatchReceiverParameter) {
|
||||
return IrGetValueImpl(expression.startOffset, expression.endOffset, function.dispatchReceiverParameter!!.symbol)
|
||||
}
|
||||
val field = fields.find { it.name == expression.symbol.owner.name } ?: return expression
|
||||
return IrGetFieldImpl(expression.startOffset, expression.endOffset, field.symbol, field.type).also {
|
||||
it.receiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, function.dispatchReceiverParameter!!.symbol)
|
||||
}
|
||||
}
|
||||
return addFunctionOverride(superMethod).also { it.copySuspendLambdaBodyFrom(irFunction, receiverField, fields) }
|
||||
}
|
||||
|
||||
// If the suspend lambda body contains declarations of other classes (for other lambdas),
|
||||
// do not rewrite those. In particular, that could lead to rewriting of returns in nested
|
||||
// lambdas to unintended non-local returns.
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
return declaration
|
||||
}
|
||||
private fun IrClass.addInvokeSuspendForInlineForLambda(
|
||||
invokeSuspend: IrFunction,
|
||||
irFunction: IrFunction,
|
||||
fields: List<IrField>,
|
||||
receiverField: IrField?
|
||||
): IrFunction {
|
||||
return addFunction(
|
||||
INVOKE_SUSPEND_METHOD_NAME + FOR_INLINE_SUFFIX,
|
||||
context.irBuiltIns.anyNType,
|
||||
Modality.FINAL,
|
||||
origin = JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE
|
||||
).apply {
|
||||
invokeSuspend.valueParameters.mapTo(valueParameters) { it.copyTo(this) }
|
||||
}.also { it.copySuspendLambdaBodyFrom(irFunction, receiverField, fields) }
|
||||
}
|
||||
|
||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||
val ret = super.visitReturn(expression) as IrReturn
|
||||
return IrReturnImpl(ret.startOffset, ret.endOffset, ret.type, function.symbol, ret.value)
|
||||
private fun IrSimpleFunction.copySuspendLambdaBodyFrom(
|
||||
irFunction: IrFunction,
|
||||
receiverField: IrField?,
|
||||
fields: List<IrField>
|
||||
) {
|
||||
copyTypeParametersFrom(irFunction)
|
||||
body = irFunction.body?.deepCopyWithSymbols(this)
|
||||
body?.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
if (expression.symbol.owner == irFunction.extensionReceiverParameter) {
|
||||
assert(receiverField != null)
|
||||
return IrGetFieldImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
receiverField!!.symbol,
|
||||
receiverField.type
|
||||
).also {
|
||||
it.receiver =
|
||||
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchReceiverParameter!!.symbol)
|
||||
}
|
||||
})
|
||||
(irFunction.parent as IrDeclarationContainer).declarations.remove(irFunction)
|
||||
} else if (expression.symbol.owner == irFunction.dispatchReceiverParameter) {
|
||||
return IrGetValueImpl(expression.startOffset, expression.endOffset, dispatchReceiverParameter!!.symbol)
|
||||
}
|
||||
val field = fields.find { it.name == expression.symbol.owner.name } ?: return expression
|
||||
return IrGetFieldImpl(expression.startOffset, expression.endOffset, field.symbol, field.type).also {
|
||||
it.receiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchReceiverParameter!!.symbol)
|
||||
}
|
||||
}
|
||||
|
||||
// If the suspend lambda body contains declarations of other classes (for other lambdas),
|
||||
// do not rewrite those. In particular, that could lead to rewriting of returns in nested
|
||||
// lambdas to unintended non-local returns.
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
return declaration
|
||||
}
|
||||
|
||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||
val ret = super.visitReturn(expression) as IrReturn
|
||||
return IrReturnImpl(ret.startOffset, ret.endOffset, ret.type, symbol, ret.value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun IrFunction.copyBodyFrom(oldFunction: IrFunction) {
|
||||
val mapping: Map<IrValueParameter, IrValueParameter> =
|
||||
(listOfNotNull(oldFunction.dispatchReceiverParameter, oldFunction.extensionReceiverParameter) + oldFunction.valueParameters)
|
||||
.zip(listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).toMap()
|
||||
copyBodyWithParametersMapping(this, oldFunction, mapping)
|
||||
}
|
||||
|
||||
private fun IrDeclarationContainer.addFunctionOverride(
|
||||
@@ -311,17 +340,15 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrClass.createContinuationClassFor(irFunction: IrFunction): IrClass = buildClass {
|
||||
name = "${irFunction.name}\$Continuation".synthesizedName
|
||||
origin = CONTINUATION_CLASS
|
||||
private fun IrClass.createContinuationClassFor(parent: IrDeclarationParent, newOrigin: IrDeclarationOrigin): IrClass = buildClass {
|
||||
name = Name.special("<Continuation>")
|
||||
origin = newOrigin
|
||||
visibility = JavaVisibilities.PACKAGE_VISIBILITY
|
||||
}.also { irClass ->
|
||||
irClass.createImplicitParameterDeclarationWithWrappedDescriptor()
|
||||
irClass.superTypes.add(defaultType)
|
||||
|
||||
val parent = irFunction.parents.firstIsInstance<IrDeclarationContainer>()
|
||||
irClass.parent = parent
|
||||
parent.declarations.add(irClass)
|
||||
}
|
||||
|
||||
// Primary constructor accepts parameters equal to function reference arguments + continuation and sets the fields.
|
||||
@@ -354,51 +381,37 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
}
|
||||
}
|
||||
|
||||
// Secondary constructor accepts parameters equals to arguments of function reference and is used for callable references
|
||||
// TODO: get rid of it and use primary constructor only
|
||||
private fun IrClass.addSecondaryConstructorForLambda(primary: IrConstructor): IrConstructor =
|
||||
addConstructor {
|
||||
isPrimary = false
|
||||
returnType = defaultType
|
||||
}.also { constructor ->
|
||||
constructor.valueParameters.addAll(primary.valueParameters.dropLast(1).map { it.copyTo(constructor) })
|
||||
|
||||
constructor.body = context.createIrBuilder(constructor.symbol).irBlockBody {
|
||||
+irDelegatingConstructorCall(primary).also {
|
||||
for ((index, param) in constructor.valueParameters.withIndex()) {
|
||||
it.putValueArgument(index, irGet(param))
|
||||
}
|
||||
it.putValueArgument(constructor.valueParameters.size, irNull())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrFunction.addCompletionValueParameter(): IrValueParameter =
|
||||
addValueParameter(SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME, continuationType())
|
||||
|
||||
private fun IrFunction.continuationType(): IrType =
|
||||
context.ir.symbols.continuationClass.typeWith(returnType).makeNullable()
|
||||
|
||||
private fun generateContinuationClassForNamedFunction(irFunction: IrFunction) {
|
||||
context.ir.symbols.continuationImplClass.owner.createContinuationClassFor(irFunction).apply {
|
||||
val resultField = addField(
|
||||
context.state.languageVersionSettings.dataFieldName(),
|
||||
context.irBuiltIns.anyType,
|
||||
JavaVisibilities.PACKAGE_VISIBILITY
|
||||
)
|
||||
val capturedThisField = irFunction.dispatchReceiverParameter?.let { addField("this\$0", it.type) }
|
||||
val labelField = addField(COROUTINE_LABEL_FIELD_NAME, context.irBuiltIns.intType, JavaVisibilities.PACKAGE_VISIBILITY)
|
||||
addConstructorForNamedFunction(capturedThisField)
|
||||
var function = irFunction
|
||||
if (function is IrSimpleFunction && function.isOverridable && function.body != null) {
|
||||
// Create static method for the suspend state machine method so that reentering the method
|
||||
// does not lead to virtual dispatch to the wrong method.
|
||||
context.suspendFunctionContinuations[function] = this
|
||||
function = createStaticSuspendImpl(function)
|
||||
private fun generateContinuationClassForNamedFunction(
|
||||
irFunction: IrFunction,
|
||||
dispatchReceiverParameter: IrValueParameter?,
|
||||
attributeContainer: IrAttributeContainer
|
||||
): IrClass {
|
||||
return context.ir.symbols.continuationImplClass.owner
|
||||
.createContinuationClassFor(irFunction, JvmLoweredDeclarationOrigin.CONTINUATION_CLASS)
|
||||
.apply {
|
||||
val resultField = addField(
|
||||
context.state.languageVersionSettings.dataFieldName(),
|
||||
context.irBuiltIns.anyType,
|
||||
JavaVisibilities.PACKAGE_VISIBILITY
|
||||
)
|
||||
val capturedThisField = dispatchReceiverParameter?.let { addField("this\$0", it.type) }
|
||||
val labelField = addField(COROUTINE_LABEL_FIELD_NAME, context.irBuiltIns.intType, JavaVisibilities.PACKAGE_VISIBILITY)
|
||||
addConstructorForNamedFunction(capturedThisField)
|
||||
addInvokeSuspendForNamedFunction(
|
||||
irFunction,
|
||||
resultField,
|
||||
labelField,
|
||||
capturedThisField,
|
||||
irFunction.origin == JvmLoweredDeclarationOrigin.SUSPEND_IMPL_STATIC_FUNCTION
|
||||
)
|
||||
copyAttributes(attributeContainer)
|
||||
}
|
||||
addInvokeSuspendForNamedFunction(function, resultField, labelField, capturedThisField, function != irFunction)
|
||||
context.suspendFunctionContinuations[function] = this
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrClass.addConstructorForNamedFunction(capturedThisField: IrField?): IrConstructor = addConstructor {
|
||||
@@ -433,7 +446,8 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
capturedThisField: IrField?,
|
||||
isStaticSuspendImpl: Boolean
|
||||
) {
|
||||
val invokeSuspend = context.ir.symbols.continuationImplClass.owner.functions.single { it.name == Name.identifier(INVOKE_SUSPEND_METHOD_NAME) }
|
||||
val invokeSuspend = context.ir.symbols.continuationImplClass.owner.functions
|
||||
.single { it.name == Name.identifier(INVOKE_SUSPEND_METHOD_NAME) }
|
||||
addFunctionOverride(invokeSuspend).also { function ->
|
||||
function.body = context.createIrBuilder(function.symbol).irBlockBody {
|
||||
+irSetField(irGet(function.dispatchReceiverParameter!!), resultField, irGet(function.valueParameters[0]))
|
||||
@@ -495,7 +509,6 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
copyMetadata = false
|
||||
)
|
||||
copyBodyToStatic(irFunction, static)
|
||||
(irFunction.parent as IrClass).declarations.add(static)
|
||||
// Rewrite the body of the original suspend method to forward to the new static method.
|
||||
irFunction.body = context.createIrBuilder(irFunction.symbol).irBlockBody {
|
||||
+irReturn(irCall(static).also {
|
||||
@@ -521,30 +534,78 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
}
|
||||
|
||||
// TODO: Generate two copies of inline suspend functions
|
||||
private fun markSuspendFunctions(irFile: IrFile, suspendLambdas: Set<IrFunction>): Set<IrFunction> {
|
||||
val result = hashSetOf<IrFunction>()
|
||||
private fun transformSuspendFunctions(irFile: IrFile, suspendAndInlineLambdas: Set<IrFunction>) {
|
||||
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
private val functionsStack = arrayListOf<IrFunction>()
|
||||
private val suspendFunctionsCapturingCrossinline = mutableSetOf<IrFunction>()
|
||||
|
||||
irFile.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||
functionsStack.push(declaration)
|
||||
val function = super.visitFunction(declaration) as IrFunction
|
||||
functionsStack.pop()
|
||||
if (skip(function)) return function
|
||||
|
||||
function as IrSimpleFunction
|
||||
if (function in suspendFunctionsCapturingCrossinline) {
|
||||
val newFunction = buildFun {
|
||||
name = Name.identifier(function.name.asString() + FOR_INLINE_SUFFIX)
|
||||
returnType = function.returnType
|
||||
modality = function.modality
|
||||
isSuspend = function.isSuspend
|
||||
origin = JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE
|
||||
}.apply {
|
||||
dispatchReceiverParameter = function.dispatchReceiverParameter?.copyTo(this)
|
||||
extensionReceiverParameter = function.extensionReceiverParameter?.copyTo(this)
|
||||
function.valueParameters.mapTo(valueParameters) { it.copyTo(this) }
|
||||
copyBodyFrom(function)
|
||||
copyAttributes(function)
|
||||
}
|
||||
functionsToAdd[function.parentAsClass] = mutableSetOf(newFunction)
|
||||
}
|
||||
|
||||
val newFunction = if (function.isOverridable) {
|
||||
// Create static method for the suspend state machine method so that reentering the method
|
||||
// does not lead to virtual dispatch to the wrong method.
|
||||
functionsToAdd.getOrPut(function.parentAsClass) { mutableSetOf() }.add(function)
|
||||
createStaticSuspendImpl(function)
|
||||
} else function
|
||||
|
||||
newFunction.body = context.createIrBuilder(newFunction.symbol).irBlockBody {
|
||||
+generateContinuationClassForNamedFunction(
|
||||
newFunction,
|
||||
function.dispatchReceiverParameter,
|
||||
declaration as IrAttributeContainer
|
||||
)
|
||||
for (statement in newFunction.body!!.statements) {
|
||||
+statement
|
||||
}
|
||||
}
|
||||
return newFunction
|
||||
}
|
||||
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
super.visitFunction(declaration)
|
||||
if (declaration.isSuspend && declaration !in suspendLambdas && !declaration.isInline &&
|
||||
!declaration.isInvokeOfSuspendCallableReference()
|
||||
private fun skip(function: IrFunction) =
|
||||
!function.isSuspend || function in suspendAndInlineLambdas || function.isInline || function.body == null ||
|
||||
function.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE ||
|
||||
function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
||||
function.parentAsClass.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL
|
||||
|
||||
override fun visitFieldAccess(expression: IrFieldAccessExpression): IrExpression {
|
||||
val result = super.visitFieldAccess(expression)
|
||||
val function = functionsStack.peek() ?: return result
|
||||
if (function.isSuspend &&
|
||||
expression.symbol.owner.origin == LocalDeclarationsLowering.DECLARATION_ORIGIN_FIELD_FOR_CROSSINLINE_CAPTURED_VALUE
|
||||
) {
|
||||
result.add(declaration)
|
||||
suspendFunctionsCapturingCrossinline += function
|
||||
}
|
||||
return result
|
||||
}
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun markSuspendLambdas(irElement: IrElement): List<SuspendLambdaInfo> {
|
||||
private fun markSuspendLambdas(irElement: IrElement): Pair<List<SuspendLambdaInfo>, List<IrFunction>> {
|
||||
val suspendLambdas = arrayListOf<SuspendLambdaInfo>()
|
||||
val inlineLambdas = mutableSetOf<IrFunctionReference>()
|
||||
val capturesCrossinline = mutableSetOf<IrFunctionReference>()
|
||||
irElement.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
@@ -552,6 +613,7 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
|
||||
override fun visitCall(expression: IrCall) {
|
||||
val owner = expression.symbol.owner
|
||||
// Collect inline lambdas
|
||||
if (owner.isInline) {
|
||||
for (i in 0 until expression.valueArgumentsCount) {
|
||||
if (owner.valueParameters[i].isNoinline) continue
|
||||
@@ -565,6 +627,20 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
}
|
||||
}
|
||||
}
|
||||
// collect lambdas, which capture crossinline
|
||||
for (i in 0 until expression.valueArgumentsCount) {
|
||||
val valueArgument = expression.getValueArgument(i) as? IrBlock ?: continue
|
||||
if (valueArgument.origin != IrStatementOrigin.LAMBDA) continue
|
||||
val reference = valueArgument.statements.last() as? IrFunctionReference ?: continue
|
||||
for (j in 0 until reference.valueArgumentsCount) {
|
||||
val getValue = (reference.getValueArgument(j) as? IrGetValue) ?: continue
|
||||
val parameter = getValue.symbol.owner as? IrValueParameter ?: continue
|
||||
if (parameter.isCrossinline) {
|
||||
capturesCrossinline += reference
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
expression.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
@@ -575,32 +651,21 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
suspendLambdas += SuspendLambdaInfo(
|
||||
expression.symbol.owner,
|
||||
(expression.type as IrSimpleType).arguments.size - 1,
|
||||
expression
|
||||
expression,
|
||||
expression in capturesCrossinline
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
return suspendLambdas
|
||||
return suspendLambdas to inlineLambdas.map { it.symbol.owner }
|
||||
}
|
||||
|
||||
private fun transformSuspendCalls(irFile: IrFile) {
|
||||
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
private val functionStack = mutableListOf<IrFunction>()
|
||||
override fun visitElement(element: IrElement): IrElement {
|
||||
element.transformChildrenVoid(this)
|
||||
return element
|
||||
}
|
||||
|
||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||
functionStack.push(declaration)
|
||||
val res = super.visitFunction(declaration)
|
||||
functionStack.pop()
|
||||
return res
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private class SuspendLambdaInfo(val function: IrFunction, val arity: Int, val reference: IrFunctionReference) {
|
||||
private class SuspendLambdaInfo(
|
||||
val function: IrFunction,
|
||||
val arity: Int,
|
||||
val reference: IrFunctionReference,
|
||||
val capturesCrossinline: Boolean
|
||||
) {
|
||||
lateinit var constructor: IrConstructor
|
||||
}
|
||||
}
|
||||
-3
@@ -414,7 +414,4 @@ internal class CallableReferenceLowering(private val context: JvmBackendContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val currentDeclarationParent
|
||||
get() = allScopes.last { it.irElement is IrDeclarationParent }.irElement as IrDeclarationParent
|
||||
}
|
||||
|
||||
@@ -56,10 +56,6 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
||||
?.let {
|
||||
declareSimpleFunctionInner(it, ktElement, IrDeclarationOrigin.FAKE_OVERRIDE).buildWithScope { irFunction ->
|
||||
generateFunctionParameterDeclarationsAndReturnType(irFunction, ktElement, null)
|
||||
val overridenSymbol = irFunction.overriddenSymbols.first()
|
||||
if (overridenSymbol.isBound) {
|
||||
irFunction.copyAttributes(overridenSymbol.owner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,7 @@ package org.jetbrains.kotlin.ir.declarations.lazy
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.ir.declarations.IrAttributeContainer
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
|
||||
|
||||
+10
-11
@@ -1,18 +1,10 @@
|
||||
@kotlin.Metadata
|
||||
final class LambdaWithLongReceiverKt$$call$Continuation {
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
public method <init>(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaWithLongReceiverKt$box$1$1 {
|
||||
private field $p: long
|
||||
private field label: int
|
||||
inner class LambdaWithLongReceiverKt$box$1
|
||||
inner class LambdaWithLongReceiverKt$box$1$1
|
||||
public method <init>(): void
|
||||
public method <init>(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
|
||||
@@ -26,17 +18,24 @@ final class LambdaWithLongReceiverKt$box$1 {
|
||||
field L$0: java.lang.Object
|
||||
private field label: int
|
||||
inner class LambdaWithLongReceiverKt$box$1
|
||||
public method <init>(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.internal.Ref$ObjectRef): void
|
||||
inner class LambdaWithLongReceiverKt$box$1$1
|
||||
public method <init>(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.internal.Ref$ObjectRef, @org.jetbrains.annotations.Nullable p1: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class LambdaWithLongReceiverKt$call$1 {
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
public method <init>(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class LambdaWithLongReceiverKt {
|
||||
inner class LambdaWithLongReceiverKt$box$1
|
||||
inner class LambdaWithLongReceiverKt$box$1$1
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.Nullable method call(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
|
||||
+10
-11
@@ -1,11 +1,3 @@
|
||||
@kotlin.Metadata
|
||||
final class LambdaWithMultipleParametersKt$$call$Continuation {
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
public method <init>(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaWithMultipleParametersKt$box$1$1 {
|
||||
@@ -16,8 +8,8 @@ final class LambdaWithMultipleParametersKt$box$1$1 {
|
||||
private field e: long
|
||||
private field f: long
|
||||
private field label: int
|
||||
inner class LambdaWithMultipleParametersKt$box$1
|
||||
inner class LambdaWithMultipleParametersKt$box$1$1
|
||||
public method <init>(): void
|
||||
public method <init>(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object, p4: java.lang.Object, p5: java.lang.Object, p6: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
@@ -30,17 +22,24 @@ final class LambdaWithMultipleParametersKt$box$1 {
|
||||
field L$0: java.lang.Object
|
||||
private field label: int
|
||||
inner class LambdaWithMultipleParametersKt$box$1
|
||||
public method <init>(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.internal.Ref$ObjectRef): void
|
||||
inner class LambdaWithMultipleParametersKt$box$1$1
|
||||
public method <init>(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.internal.Ref$ObjectRef, @org.jetbrains.annotations.Nullable p1: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class LambdaWithMultipleParametersKt$call$1 {
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
public method <init>(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class LambdaWithMultipleParametersKt {
|
||||
inner class LambdaWithMultipleParametersKt$box$1
|
||||
inner class LambdaWithMultipleParametersKt$box$1$1
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.Nullable method call(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function7, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// WITH_REFLECT
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_COROUTINES
|
||||
// WITH_RUNTIME
|
||||
|
||||
Vendored
+21
-22
@@ -1,24 +1,3 @@
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
final class InlineWithoutStateMachineKt$$complexSuspend$Continuation {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
public method <init>(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
final class InlineWithoutStateMachineKt$$suspendHere$Continuation {
|
||||
field L$0: java.lang.Object
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
public method <init>(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class InlineWithoutStateMachineKt$box$1 {
|
||||
@@ -27,13 +6,33 @@ final class InlineWithoutStateMachineKt$box$1 {
|
||||
field L$1: java.lang.Object
|
||||
private field label: int
|
||||
inner class InlineWithoutStateMachineKt$box$1
|
||||
public method <init>(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.internal.Ref$ObjectRef): void
|
||||
public method <init>(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.internal.Ref$ObjectRef, @org.jetbrains.annotations.Nullable p1: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
final class InlineWithoutStateMachineKt$complexSuspend$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
public method <init>(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
final class InlineWithoutStateMachineKt$suspendHere$1 {
|
||||
field L$0: java.lang.Object
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
public method <init>(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class InlineWithoutStateMachineKt {
|
||||
inner class InlineWithoutStateMachineKt$box$1
|
||||
|
||||
Vendored
-1
@@ -1,5 +1,4 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
Vendored
+170
@@ -0,0 +1,170 @@
|
||||
@kotlin.Metadata
|
||||
public interface flow/Flow {
|
||||
public abstract @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public interface flow/FlowCollector {
|
||||
public abstract @org.jetbrains.annotations.Nullable method emit(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class flow/InnerObjectRetransformationKt$box$1 {
|
||||
private field label: int
|
||||
inner class flow/InnerObjectRetransformationKt$box$1
|
||||
public method <init>(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class flow/InnerObjectRetransformationKt$check$$inlined$collect$1 {
|
||||
inner class flow/InnerObjectRetransformationKt$check$$inlined$collect$1
|
||||
public method <init>(): void
|
||||
public @org.jetbrains.annotations.Nullable method emit(@org.jetbrains.annotations.NotNull p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
final class flow/InnerObjectRetransformationKt$check$$inlined$flow$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
synthetic final field this$0: flow.InnerObjectRetransformationKt$check$$inlined$flow$1
|
||||
public method <init>(p0: flow.InnerObjectRetransformationKt$check$$inlined$flow$1, p1: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class flow/InnerObjectRetransformationKt$check$$inlined$flow$1 {
|
||||
inner class flow/InnerObjectRetransformationKt$check$$inlined$flow$1
|
||||
public method <init>(): void
|
||||
public @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class flow/InnerObjectRetransformationKt$check$$inlined$flowWith$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
synthetic final field this$0: flow.InnerObjectRetransformationKt$check$$inlined$flowWith$1
|
||||
public method <init>(p0: flow.InnerObjectRetransformationKt$check$$inlined$flowWith$1, p1: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class flow/InnerObjectRetransformationKt$check$$inlined$flowWith$1 {
|
||||
synthetic final field $this$flowWith$inlined: flow.Flow
|
||||
inner class flow/InnerObjectRetransformationKt$check$$inlined$flowWith$1
|
||||
public method <init>(p0: flow.Flow): void
|
||||
public @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
final class flow/InnerObjectRetransformationKt$check$1 {
|
||||
field L$0: java.lang.Object
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
public method <init>(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class flow/InnerObjectRetransformationKt$collect$2$emit$1 {
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
private field this$0: flow.InnerObjectRetransformationKt$collect$2
|
||||
public method <init>(@org.jetbrains.annotations.NotNull p0: flow.InnerObjectRetransformationKt$collect$2, @org.jetbrains.annotations.Nullable p1: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class flow/InnerObjectRetransformationKt$collect$2 {
|
||||
private synthetic final field $action: kotlin.jvm.functions.Function2
|
||||
inner class flow/InnerObjectRetransformationKt$collect$2
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2): void
|
||||
public @org.jetbrains.annotations.Nullable method emit$$forInline(@org.jetbrains.annotations.NotNull p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method emit(@org.jetbrains.annotations.NotNull p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class flow/InnerObjectRetransformationKt$flow$1$collect$1 {
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
private field this$0: flow.InnerObjectRetransformationKt$flow$1
|
||||
public method <init>(@org.jetbrains.annotations.NotNull p0: flow.InnerObjectRetransformationKt$flow$1, @org.jetbrains.annotations.Nullable p1: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class flow/InnerObjectRetransformationKt$flow$1 {
|
||||
private synthetic final field $block: kotlin.jvm.functions.Function2
|
||||
inner class flow/InnerObjectRetransformationKt$flow$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2): void
|
||||
public @org.jetbrains.annotations.Nullable method collect$$forInline(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$1
|
||||
public method <init>(p0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$1, p1: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1 {
|
||||
synthetic final field $builderBlock$inlined: kotlin.jvm.functions.Function2
|
||||
synthetic final field $this$flowWith$inlined: flow.Flow
|
||||
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2, p1: flow.Flow): void
|
||||
public @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$2
|
||||
public method <init>(p0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$2, p1: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2 {
|
||||
synthetic final field $builderBlock$inlined: kotlin.jvm.functions.Function2
|
||||
synthetic final field $this$flowWith$inlined: flow.Flow
|
||||
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2, p1: flow.Flow): void
|
||||
public @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class flow/InnerObjectRetransformationKt {
|
||||
inner class flow/InnerObjectRetransformationKt$box$1
|
||||
inner class flow/InnerObjectRetransformationKt$collect$2
|
||||
inner class flow/InnerObjectRetransformationKt$flow$1
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.Nullable method check(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
private final static @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.NotNull method flow(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): flow.Flow
|
||||
public final static @org.jetbrains.annotations.NotNull method flowWith(@org.jetbrains.annotations.NotNull p0: flow.Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2): flow.Flow
|
||||
}
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// FILE: test.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: flow.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// FILE: test.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// FILE: test.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// FILE: test.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// FILE: test.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// FILE: test.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// FILE: test.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// FILE: test.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// FILE: test.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// FILE: inlined.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// FILE: inlined.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// FILE: inlined.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
|
||||
Vendored
-2
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// FILE: inlined.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// FILE: inlined.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
||||
// FILE: inlined.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
|
||||
+2
-2
@@ -4,9 +4,9 @@ compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/so
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:14:13: error: a suspension point at SourceKt$test$2.invokeSuspend(source.kt:17) is inside a critical section
|
||||
builder {
|
||||
^
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:24:25: error: a suspension point at SourceKt$test$3$invokeSuspend$$inlined$withCrossinline$2.invokeSuspend(source.kt:62) is inside a critical section
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:24:9: error: a suspension point at SourceKt$test$3$invokeSuspend$$inlined$withCrossinline$2.invokeSuspend(source.kt:62) is inside a critical section
|
||||
withCrossinline {
|
||||
^
|
||||
^
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:50:34: error: a suspension point at SourceKt$withCrossinline$c$1.invokeSuspend(source.kt:52) is inside a critical section
|
||||
val c : suspend () -> Unit = {
|
||||
^
|
||||
|
||||
Reference in New Issue
Block a user