Generate state-machine even if the object is going to be transformed

This fixes Java interop of inline functions, which use coroutines.
However, we cannot transform the state-machine. Thus, we generate
a $$forInline counterpart for suspend functions (similar to inline
suspend functions) and invokeSuspend$$forInline for lambdas if these
coroutines are going to transformed (i.e. are declared inside inline
functions).
During transformation we just skip method with state-machine and
transform the $$forInline counterpart. Of course, if inline site is
inline itself, we generate both state-machine version (which will be
dropped during the next transformation) and $$forInline version.
Consequently, the final version of the coroutines will not have
$$forInline counterpart.
Unfortunately, since CompileKotlinAgainstInlineKotlin tests do not allow
java sources, the tests for the interop are usual box tests.

 #KT-30707 Fixed
This commit is contained in:
Ilmir Usmanov
2019-04-01 19:00:46 +03:00
parent fe8bf98bce
commit 20b9d8b2f3
26 changed files with 753 additions and 157 deletions
@@ -125,7 +125,8 @@ public class FunctionCodegen {
CoroutineCodegenUtilKt.<FunctionDescriptor>unwrapInitialDescriptorForSuspendFunction(functionDescriptor),
function,
v.getThisName(),
state.getConstructorCallNormalizationMode()
state.getConstructorCallNormalizationMode(),
this
);
} else {
strategy = new SuspendInlineFunctionGenerationStrategy(
@@ -1642,4 +1643,9 @@ public class FunctionCodegen {
}
}
}
@Nullable
public Map<DeclarationDescriptor, EnclosedValueDescriptor> getCaptureVariables() {
return owner.closure == null ? null : owner.closure.getCaptureVariables();
}
}
@@ -6,11 +6,14 @@
package org.jetbrains.kotlin.codegen.coroutines
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA
import org.jetbrains.kotlin.codegen.context.ClosureContext
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor
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.config.LanguageFeature
@@ -462,10 +465,8 @@ class CoroutineCodegenForLambda private constructor(
object : FunctionGenerationStrategy.FunctionDefault(state, element as KtDeclarationWithBody) {
override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor {
val addEndLabelMethodVisitor = AddEndLabelMethodVisitor(mv, access, name, desc, endLabel)
if (forInline) return super.wrapMethodVisitor(addEndLabelMethodVisitor, access, name, desc)
return CoroutineTransformerMethodVisitor(
addEndLabelMethodVisitor, access, name, desc, null, null,
val stateMachineBuilder = CoroutineTransformerMethodVisitor(
mv, access, name, desc, null, null,
obtainClassBuilderForCoroutineState = { v },
element = element,
diagnostics = state.diagnostics,
@@ -474,6 +475,17 @@ class CoroutineCodegenForLambda private constructor(
isForNamedFunction = false,
languageVersionSettings = languageVersionSettings
)
return if (forInline) AddEndLabelMethodVisitor(
MethodNodeCopyingMethodVisitor(
SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
stateMachineBuilder, access, name, desc, v.thisName,
isCapturedSuspendLambda = { isCapturedSuspendLambda(closure.captureVariables, it.name) }
), access, name, desc,
newMethod = { origin, newAccess, newName, newDesc ->
functionCodegen.newMethod(origin, newAccess, newName, newDesc, null, null)
}
), access, name, desc, endLabel
) else AddEndLabelMethodVisitor(stateMachineBuilder, access, name, desc, endLabel)
}
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
@@ -516,13 +528,22 @@ class CoroutineCodegenForLambda private constructor(
}
}
fun isCapturedSuspendLambda(captureVariables: Map<DeclarationDescriptor, EnclosedValueDescriptor>, name: String): Boolean {
for ((param, value) in captureVariables) {
if (param !is ValueParameterDescriptor) continue
if (value.fieldName != name) continue
return param.type.isSuspendFunctionTypeOrSubtype
}
return false
}
private class AddEndLabelMethodVisitor(
delegate: MethodVisitor,
access: Int,
name: String,
desc: String,
private val endLabel: Label
): TransformationMethodVisitor(delegate, access, name, desc, null, null) {
) : TransformationMethodVisitor(delegate, access, name, desc, null, null) {
override fun performTransformations(methodNode: MethodNode) {
methodNode.instructions.add(
withInstructionAdapter {
@@ -48,6 +48,7 @@ private const val COROUTINES_METADATA_VERSION_JVM_NAME = "v"
const val SUSPEND_FUNCTION_CONTINUATION_PARAMETER = "\$completion"
const val SUSPEND_CALL_RESULT_NAME = "\$result"
const val ILLEGAL_STATE_ERROR_MESSAGE = "call to 'resume' before 'invoke' with coroutine"
class CoroutineTransformerMethodVisitor(
delegate: MethodVisitor,
@@ -176,7 +177,7 @@ class CoroutineTransformerMethodVisitor(
insert(last, defaultLabel)
insert(last, withInstructionAdapter {
AsmUtil.genThrow(this, "java/lang/IllegalStateException", "call to 'resume' before 'invoke' with coroutine")
AsmUtil.genThrow(this, "java/lang/IllegalStateException", ILLEGAL_STATE_ERROR_MESSAGE)
areturn(Type.VOID_TYPE)
})
}
@@ -5,12 +5,10 @@
package org.jetbrains.kotlin.codegen.coroutines
import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.FunctionGenerationStrategy
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.inline.addFakeContinuationConstructorCallMarker
import org.jetbrains.kotlin.codegen.inline.coroutines.SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode
import org.jetbrains.kotlin.config.LanguageVersionSettings
@@ -22,17 +20,19 @@ import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
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.Type
import org.jetbrains.org.objectweb.asm.tree.MethodNode
open class SuspendFunctionGenerationStrategy(
state: GenerationState,
protected val originalSuspendDescriptor: FunctionDescriptor,
protected val declaration: KtFunction,
private val containingClassInternalName: String,
private val constructorCallNormalizationMode: JVMConstructorCallNormalizationMode
state: GenerationState,
protected val originalSuspendDescriptor: FunctionDescriptor,
protected val declaration: KtFunction,
private val containingClassInternalName: String,
private val constructorCallNormalizationMode: JVMConstructorCallNormalizationMode,
protected val functionCodegen: FunctionCodegen
) : FunctionGenerationStrategy.CodegenBased(state) {
private lateinit var codegen: ExpressionCodegen
@@ -45,7 +45,7 @@ open class SuspendFunctionGenerationStrategy(
declaration.containingFile
).also {
val coroutineCodegen =
CoroutineCodegenForNamedFunction.create(it, codegen, originalSuspendDescriptor, declaration)
CoroutineCodegenForNamedFunction.create(it, codegen, originalSuspendDescriptor, declaration)
coroutineCodegen.generate()
}
}
@@ -53,16 +53,7 @@ open class SuspendFunctionGenerationStrategy(
override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor {
if (access and Opcodes.ACC_ABSTRACT != 0) return mv
if (state.bindingContext[CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA, originalSuspendDescriptor] == true) {
return AddConstructorCallForCoroutineRegeneration(
mv, access, name, desc, null, null, this::classBuilderForCoroutineState,
containingClassInternalName,
originalSuspendDescriptor.dispatchReceiverParameter != null,
containingClassInternalNameOrNull(),
languageVersionSettings
)
}
return CoroutineTransformerMethodVisitor(
val stateMachineBuilder = CoroutineTransformerMethodVisitor(
mv, access, name, desc, null, null, containingClassInternalName, this::classBuilderForCoroutineState,
isForNamedFunction = true,
element = declaration,
@@ -72,10 +63,37 @@ open class SuspendFunctionGenerationStrategy(
internalNameForDispatchReceiver = containingClassInternalNameOrNull(),
languageVersionSettings = languageVersionSettings
)
val forInline = state.bindingContext[CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA, originalSuspendDescriptor] == true
// Yegor Bugayenko style
return if (forInline)
AddConstructorCallForCoroutineRegeneration(
MethodNodeCopyingMethodVisitor(
SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
stateMachineBuilder,
access, name, desc, containingClassInternalName,
isCapturedSuspendLambda = {
isCapturedSuspendLambda(
functionCodegen.captureVariables.sure {
"Anonymous object should have closure"
},
it.name
)
}
), access, name, desc,
newMethod = { origin, newAccess, newName, newDesc ->
functionCodegen.newMethod(origin, newAccess, newName, newDesc, null, null)
}
), access, name, desc, null, null, this::classBuilderForCoroutineState,
containingClassInternalName,
originalSuspendDescriptor.dispatchReceiverParameter != null,
containingClassInternalNameOrNull(),
languageVersionSettings
) else stateMachineBuilder
}
private fun containingClassInternalNameOrNull() =
originalSuspendDescriptor.containingDeclaration.safeAs<ClassDescriptor>()?.let(state.typeMapper::mapClass)?.internalName
originalSuspendDescriptor.containingDeclaration.safeAs<ClassDescriptor>()?.let(state.typeMapper::mapClass)?.internalName
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
this.codegen = codegen
@@ -115,6 +133,7 @@ open class SuspendFunctionGenerationStrategy(
languageVersionSettings
)
addFakeContinuationConstructorCallMarker(this, false)
pop() // Otherwise stack-transformation breaks
})
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
@@ -9,12 +9,12 @@ import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.FunctionCodegen
import org.jetbrains.kotlin.codegen.FunctionGenerationStrategy
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
@@ -29,13 +29,14 @@ class SuspendInlineFunctionGenerationStrategy(
declaration: KtFunction,
containingClassInternalName: String,
constructorCallNormalizationMode: JVMConstructorCallNormalizationMode,
private val codegen: FunctionCodegen
codegen: FunctionCodegen
) : SuspendFunctionGenerationStrategy(
state,
originalSuspendDescriptor,
declaration,
containingClassInternalName,
constructorCallNormalizationMode
constructorCallNormalizationMode,
codegen
) {
private val defaultStrategy = FunctionGenerationStrategy.FunctionDefault(state, declaration)
@@ -43,16 +44,10 @@ class SuspendInlineFunctionGenerationStrategy(
if (access and Opcodes.ACC_ABSTRACT != 0) return mv
return MethodNodeCopyingMethodVisitor(
super.wrapMethodVisitor(mv, access, name, desc),
access,
name,
desc = desc,
signature = null,
exceptions = null,
codegen = codegen,
declaration = declaration,
originalSuspendDescriptor = originalSuspendDescriptor,
isReleaseCoroutines = state.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
super.wrapMethodVisitor(mv, access, name, desc), access, name, desc,
newMethod = { origin, newAccess, newName, newDesc ->
functionCodegen.newMethod(origin, newAccess, newName, newDesc, null, null)
}, keepAccess = false
)
}
@@ -60,46 +55,26 @@ class SuspendInlineFunctionGenerationStrategy(
super.doGenerateBody(codegen, signature)
defaultStrategy.doGenerateBody(codegen, signature)
}
}
private class MethodNodeCopyingMethodVisitor(
delegate: MethodVisitor,
private val access: Int,
private val name: String,
private val desc: String,
private val signature: String?,
private val exceptions: Array<out String>?,
private val codegen: FunctionCodegen,
private val declaration: KtFunction,
private val originalSuspendDescriptor: FunctionDescriptor,
private val isReleaseCoroutines: Boolean
) : TransformationMethodVisitor(
delegate,
calculateAccessForInline(access),
"$name\$\$forInline",
desc,
signature,
exceptions
) {
override fun performTransformations(methodNode: MethodNode) {
val newMethodNode = codegen.newMethod(
OtherOrigin(declaration, getOrCreateJvmSuspendFunctionView(originalSuspendDescriptor, isReleaseCoroutines)),
calculateAccessForInline(access), "$name\$\$forInline", desc, signature, exceptions
)
methodNode.instructions.resetLabels()
methodNode.accept(newMethodNode)
}
class MethodNodeCopyingMethodVisitor(
delegate: MethodVisitor, private val access: Int, private val name: String, private val desc: String,
private val newMethod: (JvmDeclarationOrigin, Int, String, String) -> MethodVisitor,
private val keepAccess: Boolean = true
) : TransformationMethodVisitor(
delegate, calculateAccessForInline(access, keepAccess), "$name$FOR_INLINE_SUFFIX", desc, null, null
) {
override fun performTransformations(methodNode: MethodNode) {
val newMethodNode = newMethod(
JvmDeclarationOrigin.NO_ORIGIN, calculateAccessForInline(access, keepAccess), "$name$FOR_INLINE_SUFFIX", desc
)
methodNode.instructions.resetLabels()
methodNode.accept(newMethodNode)
}
companion object {
private fun calculateAccessForInline(access: Int): Int {
var accessForInline = access
if (accessForInline and Opcodes.ACC_PUBLIC != 0) {
accessForInline = accessForInline xor Opcodes.ACC_PUBLIC
}
if (accessForInline and Opcodes.ACC_PROTECTED != 0) {
accessForInline = accessForInline xor Opcodes.ACC_PROTECTED
}
return accessForInline or Opcodes.ACC_PRIVATE
}
private fun calculateAccessForInline(access: Int, keepAccess: Boolean): Int =
if (keepAccess) access
else access or Opcodes.ACC_PRIVATE and Opcodes.ACC_PUBLIC.inv() and Opcodes.ACC_PROTECTED.inv()
}
}
}
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.codegen.inline
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.coroutines.DEBUG_METADATA_ANNOTATION_ASM_TYPE
import org.jetbrains.kotlin.codegen.coroutines.isCapturedSuspendLambda
import org.jetbrains.kotlin.codegen.coroutines.isCoroutineSuperClass
import org.jetbrains.kotlin.codegen.inline.coroutines.CoroutineTransformer
import org.jetbrains.kotlin.codegen.serialization.JvmCodegenStringTable
@@ -67,6 +69,8 @@ class AnonymousObjectTransformer(
// Empty inner class info because no inner classes are used in kotlin.Metadata and its arguments
val innerClassesInfo = FileBasedKotlinClass.InnerClassesInfo()
return FileBasedKotlinClass.convertAnnotationVisitor(metadataReader, desc, innerClassesInfo)
} else if (desc == DEBUG_METADATA_ANNOTATION_ASM_TYPE.descriptor) {
return null
}
return super.visitAnnotation(desc, visible)
}
@@ -135,12 +139,13 @@ class AnonymousObjectTransformer(
classBuilder,
methodsToTransform,
superClassName,
additionalFakeParams
allCapturedParamBuilder.listCaptured()
)
for (next in methodsToTransform) {
loop@for (next in methodsToTransform) {
val deferringVisitor =
when {
coroutineTransformer.shouldTransform(next) -> coroutineTransformer.newMethod(next)
coroutineTransformer.shouldSkip(next) -> continue@loop
coroutineTransformer.shouldGenerateStateMachine(next) -> coroutineTransformer.newMethod(next)
else -> newMethod(classBuilder, next)
}
val funResult = inlineMethodAndUpdateGlobalResult(parentRemapper, deferringVisitor, next, allCapturedParamBuilder, false)
@@ -479,6 +484,11 @@ class AnonymousObjectTransformer(
alreadyAddedParam?.newFieldName ?: getNewFieldName(desc.fieldName, false),
alreadyAddedParam != null
)
if (info is PsiExpressionLambda && info.captureVariables.any { it.value.fieldName == desc.fieldName }) {
recapturedParamInfo.functionalArgument = NonInlineableArgumentForInlineableParameterCalledInSuspend(
isCapturedSuspendLambda(info.captureVariables, desc.fieldName)
)
}
val composed = StackValue.field(
desc.type,
oldObjectType, /*TODO owner type*/
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.context.ClosureContext
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructors
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
@@ -575,7 +576,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
// 2) for inliner: with mangled name and without state machine
private fun mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor: FunctionDescriptor, asmMethod: Method): Method {
if (!functionDescriptor.isSuspend) return asmMethod
return Method("${asmMethod.name}\$\$forInline", asmMethod.descriptor)
return Method("${asmMethod.name}$FOR_INLINE_SUFFIX", asmMethod.descriptor)
}
private fun getDirectMemberAndCallableFromObject(functionDescriptor: FunctionDescriptor): CallableMemberDescriptor {
@@ -307,4 +307,6 @@ class PsiExpressionLambda(
val isPropertyReference: Boolean
get() = propertyReferenceInfo != null
val captureVariables = closure.captureVariables
}
@@ -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. 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.codegen.inline;
@@ -29,9 +18,13 @@ import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.commons.*;
import org.jetbrains.org.objectweb.asm.commons.FieldRemapper;
import java.util.HashMap;
import java.util.Map;
public class RemappingClassBuilder extends DelegatingClassBuilder {
private final ClassBuilder builder;
private final Remapper remapper;
private final Map<String, FieldVisitor> spilledCoroutineVariables = new HashMap<>();
public RemappingClassBuilder(@NotNull ClassBuilder builder, @NotNull Remapper remapper) {
this.builder = builder;
@@ -68,9 +61,39 @@ public class RemappingClassBuilder extends DelegatingClassBuilder {
@Nullable String signature,
@Nullable Object value
) {
return new FieldRemapper(
builder.newField(origin, access, name, remapper.mapDesc(desc), remapper.mapSignature(signature, true), value), remapper
if (spilledCoroutineVariables.containsKey(name)) return spilledCoroutineVariables.get(name);
FieldRemapper field = new FieldRemapper(
builder.newField(origin, access, name, this.remapper.mapDesc(desc), this.remapper.mapSignature(signature, true), value),
this.remapper
);
if (isSpilledCoroutineVariableName(name)) {
spilledCoroutineVariables.put(name, field);
}
return field;
}
private static boolean isSpilledCoroutineVariableName(String name) {
if (name.length() < 3) return false;
switch (name.charAt(0)) {
case 'L':
case 'Z':
case 'C':
case 'B':
case 'S':
case 'I':
case 'F':
case 'J':
case 'D':
break;
default:
return false;
}
if (name.charAt(1) != '$') return false;
for (int i = 2; i < name.length(); ++i) {
if (!Character.isDigit(name.charAt(i))) return false;
}
return true;
}
@Override
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.codegen.inline.coroutines
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.codegen.AsmUtil.CAPTURED_THIS_FIELD
import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
import org.jetbrains.kotlin.codegen.coroutines.*
@@ -16,7 +17,6 @@ import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.common.findPreviousOrNull
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.utils.addToStdlib.cast
@@ -29,6 +29,8 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
const val NOINLINE_CALL_MARKER = "NOINLINE_CALL_MARKER"
const val FOR_INLINE_SUFFIX = "\$\$forInline"
class CoroutineTransformer(
private val inliningContext: InliningContext,
private val classBuilder: ClassBuilder,
@@ -37,24 +39,20 @@ class CoroutineTransformer(
private val capturedParams: List<CapturedParamInfo>
) {
private val state = inliningContext.state
// If we inline into inline function, we should generate both method with state-machine for Java interop and method without
// state-machine for further transformation/inlining.
private val generateForInline = inliningContext.callSiteInfo.isInlineOrInsideInline
fun shouldTransform(node: MethodNode): Boolean {
// Never generate state-machine for objects, which are going to be retransformed
// See innerObjectRetransformation.kt
if (inliningContext.callSiteInfo.isInlineOrInsideInline) return false
fun shouldSkip(node: MethodNode): Boolean = methods.any { it.name == node.name + FOR_INLINE_SUFFIX && it.desc == node.desc }
fun shouldGenerateStateMachine(node: MethodNode): Boolean {
// Continuations are similar to lambdas from bird's view, but we should never generate state machine for them
if (isContinuationNotLambda()) return false
val crossinlineParam = crossinlineLambda()
if (inliningContext.isInliningLambda && !inliningContext.isContinuation) return false
return when {
isSuspendFunction(node) -> true
isSuspendLambda(node) -> {
if (isStateMachine(node)) return false
val functionDescriptor =
crossinlineParam?.invokeMethodDescriptor?.containingDeclaration as? FunctionDescriptor ?: return true
!functionDescriptor.isInline
}
else -> false
}
// The method does not have state-machine, but should. Generate it
if (node.name.endsWith(FOR_INLINE_SUFFIX)) return true
// there can be suspend lambdas inside inline functions, which do not
// capture crossinline lambdas, thus, there is no need to transform them
return isSuspendFunctionWithFakeConstructorCall(node) || (isSuspendLambda(node) && !isStateMachine(node))
}
private fun isContinuationNotLambda(): Boolean = inliningContext.isContinuation &&
@@ -66,7 +64,7 @@ class CoroutineTransformer(
}?.cast()
private fun isStateMachine(node: MethodNode): Boolean =
node.instructions.asSequence().any { it.opcode == Opcodes.INVOKESTATIC && (it as MethodInsnNode).name == "getCOROUTINE_SUSPENDED" }
node.instructions.asSequence().any { insn -> insn is LdcInsnNode && insn.cst == ILLEGAL_STATE_ERROR_MESSAGE }
private fun isSuspendLambda(node: MethodNode) = isResumeImpl(node)
@@ -83,28 +81,29 @@ class CoroutineTransformer(
}
newStateMachineForLambda(node, element)
}
isSuspendFunction(node) -> newStateMachineForNamedFunction(node, element)
isSuspendFunctionWithFakeConstructorCall(node) -> newStateMachineForNamedFunction(node, element)
else -> error("no need to generate state maching for ${node.name}")
}
}
private fun isResumeImpl(node: MethodNode): Boolean =
state.languageVersionSettings.isResumeImplMethodName(node.name) &&
state.languageVersionSettings.isResumeImplMethodName(node.name.removeSuffix(FOR_INLINE_SUFFIX)) &&
inliningContext.isContinuation
private fun isSuspendFunction(node: MethodNode): Boolean = findFakeContinuationConstructorClassName(node) != null
private fun isSuspendFunctionWithFakeConstructorCall(node: MethodNode): Boolean = findFakeContinuationConstructorClassName(node) != null
private fun newStateMachineForLambda(node: MethodNode, element: KtElement): DeferredMethodVisitor {
val name = node.name.removeSuffix(FOR_INLINE_SUFFIX)
return DeferredMethodVisitor(
MethodNode(
node.access, node.name, node.desc, node.signature,
node.access, name, node.desc, node.signature,
ArrayUtil.toStringArray(node.exceptions)
)
) {
surroundNoinlineCallsWithMarkersIfNeeded(
val stateMachineBuilder = surroundNoinlineCallsWithMarkersIfNeeded(
node,
CoroutineTransformerMethodVisitor(
createNewMethodFrom(node), node.access, node.name, node.desc, null, null,
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
obtainClassBuilderForCoroutineState = { classBuilder },
element = element,
diagnostics = state.diagnostics,
@@ -114,22 +113,36 @@ class CoroutineTransformer(
isForNamedFunction = false
)
)
if (generateForInline)
MethodNodeCopyingMethodVisitor(
delegate = stateMachineBuilder,
access = node.access,
name = name,
desc = node.desc,
newMethod = { origin, newAccess, newName, newDesc ->
classBuilder.newMethod(origin, newAccess, newName, newDesc, null, null)
}
)
else
stateMachineBuilder
}
}
private fun newStateMachineForNamedFunction(node: MethodNode, element: KtElement): DeferredMethodVisitor {
val name = node.name.removeSuffix(FOR_INLINE_SUFFIX)
val continuationClassName = findFakeContinuationConstructorClassName(node)
assert(inliningContext is RegeneratedClassContext)
return DeferredMethodVisitor(
MethodNode(
node.access, node.name, node.desc, node.signature,
node.access, name, node.desc, node.signature,
ArrayUtil.toStringArray(node.exceptions)
)
) {
surroundNoinlineCallsWithMarkersIfNeeded(
val stateMachineBuilder = surroundNoinlineCallsWithMarkersIfNeeded(
node,
CoroutineTransformerMethodVisitor(
createNewMethodFrom(node), node.access, node.name, node.desc, null, null,
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
obtainClassBuilderForCoroutineState = { (inliningContext as RegeneratedClassContext).continuationBuilders[continuationClassName]!! },
element = element,
diagnostics = state.diagnostics,
@@ -141,30 +154,33 @@ class CoroutineTransformer(
internalNameForDispatchReceiver = classBuilder.thisName
)
)
if (generateForInline)
MethodNodeCopyingMethodVisitor(
stateMachineBuilder, node.access, name, node.desc,
newMethod = { origin, newAccess, newName, newDesc ->
classBuilder.newMethod(origin, newAccess, newName, newDesc, null, null)
}
)
else
stateMachineBuilder
}
}
private fun surroundNoinlineCallsWithMarkersIfNeeded(node: MethodNode, delegate: MethodVisitor): MethodVisitor =
if (capturedParams.any { (it.functionalArgument as? NonInlineableArgumentForInlineableParameterCalledInSuspend)?.isSuspend == true })
if (capturedParams.any { it.functionalArgument?.isSuspendLambda() == true })
SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
delegate,
node.access,
node.name,
node.desc,
classBuilder.thisName,
capturedParams
delegate, node.access, node.name, node.desc, classBuilder.thisName, this::isCapturedSuspendLambda
)
else
delegate
private fun createNewMethodFrom(node: MethodNode): MethodVisitor {
private fun isCapturedSuspendLambda(field: FieldInsnNode): Boolean =
capturedParams.find { it.newFieldName == field.name }?.functionalArgument?.isSuspendLambda() == true
private fun createNewMethodFrom(node: MethodNode, name: String): MethodVisitor {
return classBuilder.newMethod(
JvmDeclarationOrigin.NO_ORIGIN,
node.access,
node.name,
node.desc,
node.signature,
ArrayUtil.toStringArray(node.exceptions)
JvmDeclarationOrigin.NO_ORIGIN, node.access, name, node.desc, node.signature, ArrayUtil.toStringArray(node.exceptions)
)
}
@@ -193,13 +209,10 @@ class CoroutineTransformer(
}
}
private class SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
delegate: MethodVisitor,
access: Int,
name: String,
desc: String,
val thisName: String,
val capturedParams: List<CapturedParamInfo>
class SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
delegate: MethodVisitor, access: Int, name: String, desc: String,
private val thisName: String,
private val isCapturedSuspendLambda: (FieldInsnNode) -> Boolean
) : TransformationMethodVisitor(delegate, access, name, desc, null, null) {
override fun performTransformations(methodNode: MethodNode) {
fun AbstractInsnNode.index() = methodNode.instructions.indexOf(this)
@@ -213,7 +226,7 @@ private class SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
insn as MethodInsnNode
if (!isInvokeOnLambda(insn.owner, insn.name)) continue
val frame = sourceFrames[insn.index()]
val receiver = findReceiverOfInvoke(frame, insn).takeIf { it?.isNoinlineSuspendLambda(insn) == true } as? FieldInsnNode ?: continue
val receiver = findReceiverOfInvoke(frame, insn).takeIf { it?.isSuspendLambda(insn) == true } as? FieldInsnNode ?: continue
val aload = receiver.findPreviousOrNull { it.opcode != Opcodes.GETFIELD } ?: error("GETFIELD cannot be the first instruction")
assert(aload.opcode == Opcodes.ALOAD) { "Before GETFIELD there shall be ALOAD" }
noinlineInvokes.add(insn to aload)
@@ -222,15 +235,29 @@ private class SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
surroundInvokesWithSuspendMarkers(methodNode, noinlineInvokes)
}
private fun AbstractInsnNode.isNoinlineSuspendLambda(invoke: MethodInsnNode): Boolean {
private fun AbstractInsnNode.isSuspendLambda(invoke: MethodInsnNode): Boolean {
if (opcode != Opcodes.GETFIELD) return false
this as FieldInsnNode
if (owner != thisName || desc != "L${invoke.owner};") return false
val functionalArgument = capturedParams.find { it.newFieldName == name }?.functionalArgument ?: return false
return functionalArgument is NonInlineableArgumentForInlineableParameterCalledInSuspend && functionalArgument.isSuspend
if (desc != "L${invoke.owner};") return false
var current: FieldInsnNode? = this
// Unroll the battery of
// GETFIELD <outer1>.this$0 L<outer2>;
// GETFIELD <outer2>.this$0 L<outer3>;
// ...
// GETFIELD <outerN>.$action Lkotlin/jvm/functions/FunctionM;
while (current != null) {
if (current.owner == thisName) break
if (current.previous?.opcode != Opcodes.GETFIELD || current.previous.cast<FieldInsnNode>().name != CAPTURED_THIS_FIELD) return false
current = current.previous as FieldInsnNode
}
return isCapturedSuspendLambda(this)
}
}
private fun FunctionalArgument.isSuspendLambda(): Boolean =
(this is NonInlineableArgumentForInlineableParameterCalledInSuspend && isSuspend) ||
(this is PsiExpressionLambda && invokeMethodDescriptor.isSuspend)
fun surroundInvokesWithSuspendMarkers(
methodNode: MethodNode,
noinlineInvokes: List<Pair<AbstractInsnNode, AbstractInsnNode>>
@@ -0,0 +1,103 @@
// IGNORE_BACKEND: JVM_IR
// COMMON_COROUTINES_TEST
// WITH_RUNTIME
// WITH_COROUTINES
// NO_CHECK_LAMBDA_INLINING
// CHECK_STATE_MACHINE
// FILE: inlineMe.kt
package test
inline fun inlineMe(crossinline c: suspend () -> Unit) = suspend { c(); c() }
inline fun inlineMe2(crossinline c: suspend () -> Unit) = inlineMe { c(); c() }
inline fun inlineMe3(crossinline c: suspend () -> Unit) = suspend {
var sr = inlineMe {
c()
c()
}
sr()
sr = inlineMe {
c()
c()
}
sr()
}
// FILE: A.java
import test.InlineMeKt;
import helpers.CoroutineUtilKt;
import helpers.EmptyContinuation;
import kotlin.Unit;
public class A {
public static Object call() {
return InlineMeKt.inlineMe((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
}
public static Object call2() {
return InlineMeKt.inlineMe2((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
}
public static Object call3() {
return InlineMeKt.inlineMe3((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
}
}
// FILE: box.kt
import test.*
import helpers.*
import COROUTINES_PACKAGE.*
fun builder(c: suspend () -> Unit) {
c.startCoroutine(CheckStateMachineContinuation)
}
fun box(): String {
builder {
(A.call() as (suspend () -> Unit))()
}
StateMachineChecker.check(2)
StateMachineChecker.reset()
builder {
(A.call2() as (suspend () -> Unit))()
}
StateMachineChecker.check(4)
StateMachineChecker.reset()
builder {
(A.call3() as (suspend () -> Unit))()
}
StateMachineChecker.check(8)
StateMachineChecker.reset()
builder {
inlineMe {
StateMachineChecker.suspendHere()
StateMachineChecker.suspendHere()
}()
}
StateMachineChecker.check(4)
StateMachineChecker.reset()
builder {
inlineMe2 {
StateMachineChecker.suspendHere()
StateMachineChecker.suspendHere()
}()
}
StateMachineChecker.check(8)
StateMachineChecker.reset()
builder {
inlineMe3 {
StateMachineChecker.suspendHere()
StateMachineChecker.suspendHere()
}()
}
StateMachineChecker.check(16)
return "OK"
}
@@ -0,0 +1,113 @@
// IGNORE_BACKEND: JVM_IR
// COMMON_COROUTINES_TEST
// WITH_RUNTIME
// WITH_COROUTINES
// NO_CHECK_LAMBDA_INLINING
// CHECK_STATE_MACHINE
// FILE: inlineMe.kt
package test
interface SuspendRunnable {
suspend fun run()
}
inline fun inlineMe(crossinline c: suspend () -> Unit) = object : SuspendRunnable {
override suspend fun run() {
c(); c()
}
}
inline fun inlineMe2(crossinline c: suspend () -> Unit) = inlineMe { c(); c() }
inline fun inlineMe3(crossinline c: suspend () -> Unit) = object: SuspendRunnable {
override suspend fun run() {
var sr = inlineMe {
c()
c()
}
sr.run()
sr = inlineMe {
c()
c()
}
sr.run()
}
}
// FILE: A.java
import test.InlineMeKt;
import helpers.CoroutineUtilKt;
import helpers.EmptyContinuation;
import kotlin.Unit;
public class A {
public static Object call() {
return InlineMeKt.inlineMe((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
}
public static Object call2() {
return InlineMeKt.inlineMe2((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
}
public static Object call3() {
return InlineMeKt.inlineMe3((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
}
}
// FILE: box.kt
import test.*
import helpers.*
import COROUTINES_PACKAGE.*
fun builder(c: suspend () -> Unit) {
c.startCoroutine(CheckStateMachineContinuation)
}
fun box(): String {
builder {
(A.call() as SuspendRunnable).run()
}
StateMachineChecker.check(2)
StateMachineChecker.reset()
builder {
(A.call2() as SuspendRunnable).run()
}
StateMachineChecker.check(4)
StateMachineChecker.reset()
builder {
(A.call3() as SuspendRunnable).run()
}
StateMachineChecker.check(8)
StateMachineChecker.reset()
builder {
inlineMe {
StateMachineChecker.suspendHere()
StateMachineChecker.suspendHere()
}.run()
}
StateMachineChecker.check(4)
StateMachineChecker.reset()
builder {
inlineMe2 {
StateMachineChecker.suspendHere()
StateMachineChecker.suspendHere()
}.run()
}
StateMachineChecker.check(8)
StateMachineChecker.reset()
builder {
inlineMe3 {
StateMachineChecker.suspendHere()
StateMachineChecker.suspendHere()
}.run()
}
StateMachineChecker.check(16)
return "OK"
}
@@ -1,5 +1,12 @@
@kotlin.Metadata
@kotlin.coroutines.jvm.internal.DebugMetadata
public final class CrossinlineKt$box$1$filter$$inlined$source$1$1 {
field L$0: java.lang.Object
field L$1: java.lang.Object
field L$2: java.lang.Object
field L$3: java.lang.Object
field L$4: java.lang.Object
field L$5: java.lang.Object
field label: int
synthetic field result: java.lang.Object
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1
@@ -10,7 +17,12 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1$1 {
}
@kotlin.Metadata
@kotlin.coroutines.jvm.internal.DebugMetadata
public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1 {
field L$0: java.lang.Object
field L$1: java.lang.Object
field L$2: java.lang.Object
field L$3: java.lang.Object
field label: int
synthetic field result: java.lang.Object
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1
@@ -28,6 +40,7 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1 {
inner class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1
public method <init>(p0: Sink, p1: CrossinlineKt$box$1$filter$$inlined$source$1): void
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
}
@@ -38,11 +51,18 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1 {
inner class CrossinlineKt$box$1$filter$$inlined$source$1
inner class CrossinlineKt$box$1$filter$$inlined$source$1$1
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
}
@kotlin.Metadata
@kotlin.coroutines.jvm.internal.DebugMetadata
public final class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1 {
field L$0: java.lang.Object
field L$1: java.lang.Object
field L$2: java.lang.Object
field L$3: java.lang.Object
field L$4: java.lang.Object
field label: int
synthetic field result: java.lang.Object
synthetic final field this$0: CrossinlineKt$box$1$fold$$inlined$consumeEach$1
@@ -60,6 +80,7 @@ public final class CrossinlineKt$box$1$fold$$inlined$consumeEach$1 {
inner class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function3): void
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
}
@@ -119,6 +140,11 @@ public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1 {
@kotlin.Metadata
public final class CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1$1 {
field L$0: java.lang.Object
field L$1: java.lang.Object
field L$2: java.lang.Object
field L$3: java.lang.Object
field L$4: java.lang.Object
field label: int
synthetic field result: java.lang.Object
synthetic final field this$0: CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1
@@ -173,11 +199,19 @@ public final class CrossinlineKt$consumeEach$2 {
inner class CrossinlineKt$consumeEach$2$send$1
public method <init>(p0: kotlin.jvm.functions.Function2): void
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
}
@kotlin.Metadata
@kotlin.coroutines.jvm.internal.DebugMetadata
public final class CrossinlineKt$filter$$inlined$source$1$1 {
field L$0: java.lang.Object
field L$1: java.lang.Object
field L$2: java.lang.Object
field L$3: java.lang.Object
field L$4: java.lang.Object
field L$5: java.lang.Object
field label: int
synthetic field result: java.lang.Object
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1
@@ -188,7 +222,12 @@ public final class CrossinlineKt$filter$$inlined$source$1$1 {
}
@kotlin.Metadata
@kotlin.coroutines.jvm.internal.DebugMetadata
public final class CrossinlineKt$filter$$inlined$source$1$lambda$1$1 {
field L$0: java.lang.Object
field L$1: java.lang.Object
field L$2: java.lang.Object
field L$3: java.lang.Object
field label: int
synthetic field result: java.lang.Object
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1$lambda$1
@@ -206,6 +245,7 @@ public final class CrossinlineKt$filter$$inlined$source$1$lambda$1 {
inner class CrossinlineKt$filter$$inlined$source$1$lambda$1$1
public method <init>(p0: Sink, p1: CrossinlineKt$filter$$inlined$source$1): void
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
}
@@ -216,6 +256,7 @@ public final class CrossinlineKt$filter$$inlined$source$1 {
inner class CrossinlineKt$filter$$inlined$source$1
inner class CrossinlineKt$filter$$inlined$source$1$1
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
}
@@ -238,6 +279,7 @@ public final class CrossinlineKt$fold$$inlined$consumeEach$1 {
inner class CrossinlineKt$fold$$inlined$consumeEach$1$1
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function3): void
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
}
@@ -271,7 +313,11 @@ public final class CrossinlineKt$range$$inlined$source$1 {
}
@kotlin.Metadata
@kotlin.coroutines.jvm.internal.DebugMetadata
public final class CrossinlineKt$source$1$consume$1 {
field L$0: java.lang.Object
field L$1: java.lang.Object
field L$2: java.lang.Object
field label: int
synthetic field result: java.lang.Object
synthetic final field this$0: CrossinlineKt$source$1
@@ -287,6 +333,7 @@ public final class CrossinlineKt$source$1 {
inner class CrossinlineKt$source$1
inner class CrossinlineKt$source$1$consume$1
public method <init>(p0: kotlin.jvm.functions.Function2): void
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
}
@@ -56,6 +56,11 @@ public final class CrossinlineKt$box$1$doResume$$inlined$filter$1 {
@kotlin.Metadata
public final class CrossinlineKt$box$1$doResume$$inlined$fold$1$1 {
field L$0: java.lang.Object
field L$1: java.lang.Object
field L$2: java.lang.Object
field L$3: java.lang.Object
field L$4: java.lang.Object
synthetic field data: java.lang.Object
synthetic field exception: java.lang.Throwable
synthetic final field this$0: CrossinlineKt$box$1$doResume$$inlined$fold$1
@@ -79,6 +84,12 @@ public final class CrossinlineKt$box$1$doResume$$inlined$fold$1 {
@kotlin.Metadata
public final class CrossinlineKt$box$1$filter$$inlined$source$1$1 {
field L$0: java.lang.Object
field L$1: java.lang.Object
field L$2: java.lang.Object
field L$3: java.lang.Object
field L$4: java.lang.Object
field L$5: java.lang.Object
synthetic field data: java.lang.Object
synthetic field exception: java.lang.Throwable
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1
@@ -92,6 +103,10 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1$1 {
@kotlin.Metadata
public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1 {
field L$0: java.lang.Object
field L$1: java.lang.Object
field L$2: java.lang.Object
field L$3: java.lang.Object
synthetic field data: java.lang.Object
synthetic field exception: java.lang.Throwable
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1
@@ -111,6 +126,7 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1 {
inner class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1
public method <init>(p0: Sink, p1: CrossinlineKt$box$1$filter$$inlined$source$1): void
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
}
@@ -121,11 +137,17 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1 {
inner class CrossinlineKt$box$1$filter$$inlined$source$1
inner class CrossinlineKt$box$1$filter$$inlined$source$1$1
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
}
@kotlin.Metadata
public final class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1 {
field L$0: java.lang.Object
field L$1: java.lang.Object
field L$2: java.lang.Object
field L$3: java.lang.Object
field L$4: java.lang.Object
synthetic field data: java.lang.Object
synthetic field exception: java.lang.Throwable
synthetic final field this$0: CrossinlineKt$box$1$fold$$inlined$consumeEach$1
@@ -145,6 +167,7 @@ public final class CrossinlineKt$box$1$fold$$inlined$consumeEach$1 {
inner class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function3): void
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
}
@@ -183,11 +206,18 @@ public final class CrossinlineKt$consumeEach$2 {
inner class CrossinlineKt$consumeEach$2$send$1
public method <init>(p0: kotlin.jvm.functions.Function2): void
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
}
@kotlin.Metadata
public final class CrossinlineKt$filter$$inlined$source$1$1 {
field L$0: java.lang.Object
field L$1: java.lang.Object
field L$2: java.lang.Object
field L$3: java.lang.Object
field L$4: java.lang.Object
field L$5: java.lang.Object
synthetic field data: java.lang.Object
synthetic field exception: java.lang.Throwable
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1
@@ -201,6 +231,10 @@ public final class CrossinlineKt$filter$$inlined$source$1$1 {
@kotlin.Metadata
public final class CrossinlineKt$filter$$inlined$source$1$lambda$1$1 {
field L$0: java.lang.Object
field L$1: java.lang.Object
field L$2: java.lang.Object
field L$3: java.lang.Object
synthetic field data: java.lang.Object
synthetic field exception: java.lang.Throwable
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1$lambda$1
@@ -220,6 +254,7 @@ public final class CrossinlineKt$filter$$inlined$source$1$lambda$1 {
inner class CrossinlineKt$filter$$inlined$source$1$lambda$1$1
public method <init>(p0: Sink, p1: CrossinlineKt$filter$$inlined$source$1): void
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
}
@@ -230,6 +265,7 @@ public final class CrossinlineKt$filter$$inlined$source$1 {
inner class CrossinlineKt$filter$$inlined$source$1
inner class CrossinlineKt$filter$$inlined$source$1$1
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
}
@@ -254,6 +290,7 @@ public final class CrossinlineKt$fold$$inlined$consumeEach$1 {
inner class CrossinlineKt$fold$$inlined$consumeEach$1$1
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function3): void
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
}
@@ -289,6 +326,9 @@ public final class CrossinlineKt$range$$inlined$source$1 {
@kotlin.Metadata
public final class CrossinlineKt$source$1$consume$1 {
field L$0: java.lang.Object
field L$1: java.lang.Object
field L$2: java.lang.Object
synthetic field data: java.lang.Object
synthetic field exception: java.lang.Throwable
synthetic final field this$0: CrossinlineKt$source$1
@@ -306,6 +346,7 @@ public final class CrossinlineKt$source$1 {
inner class CrossinlineKt$source$1
inner class CrossinlineKt$source$1$consume$1
public method <init>(p0: kotlin.jvm.functions.Function2): void
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
}
@@ -64,6 +64,10 @@ public final class flow/InnerObjectRetransformationKt$check$$inlined$flow$1 {
@kotlin.Metadata
public 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 L$3: java.lang.Object
field label: int
synthetic field result: java.lang.Object
synthetic final field this$0: flow.InnerObjectRetransformationKt$check$$inlined$flowWith$1
@@ -110,6 +114,7 @@ public final class flow/InnerObjectRetransformationKt$collect$2 {
inner class flow/InnerObjectRetransformationKt$collect$2
inner class flow/InnerObjectRetransformationKt$collect$2$emit$1
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
}
@@ -130,6 +135,7 @@ public final class flow/InnerObjectRetransformationKt$flow$1 {
inner class flow/InnerObjectRetransformationKt$flow$1
inner class flow/InnerObjectRetransformationKt$flow$1$collect$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
}
@@ -151,11 +157,17 @@ public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1 {
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1
public method <init>(p0: flow.Flow, p1: 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
public 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 L$3: java.lang.Object
field label: int
synthetic field result: java.lang.Object
synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$2
@@ -172,6 +184,7 @@ public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2 {
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2$1
public method <init>(p0: flow.Flow, p1: 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
}
@@ -65,6 +65,10 @@ public final class flow/InnerObjectRetransformationKt$check$$inlined$flow$1 {
@kotlin.Metadata
public 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 L$3: java.lang.Object
synthetic field data: java.lang.Object
synthetic field exception: java.lang.Throwable
synthetic final field this$0: flow.InnerObjectRetransformationKt$check$$inlined$flowWith$1
@@ -116,6 +120,7 @@ public final class flow/InnerObjectRetransformationKt$collect$2 {
inner class flow/InnerObjectRetransformationKt$collect$2
inner class flow/InnerObjectRetransformationKt$collect$2$emit$1
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.experimental.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.experimental.Continuation): java.lang.Object
}
@@ -138,6 +143,7 @@ public final class flow/InnerObjectRetransformationKt$flow$1 {
inner class flow/InnerObjectRetransformationKt$flow$1
inner class flow/InnerObjectRetransformationKt$flow$1$collect$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.experimental.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.experimental.Continuation): java.lang.Object
}
@@ -161,11 +167,16 @@ public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1 {
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1
public method <init>(p0: flow.Flow, p1: 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.experimental.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.experimental.Continuation): java.lang.Object
}
@kotlin.Metadata
public 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 L$3: java.lang.Object
synthetic field data: java.lang.Object
synthetic field exception: java.lang.Throwable
synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$2
@@ -184,6 +195,7 @@ public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2 {
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2$1
public method <init>(p0: flow.Flow, p1: 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.experimental.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.experimental.Continuation): java.lang.Object
}
@@ -41,6 +41,7 @@ final class CoroutineFieldsKt$box$1 {
field J$0: long
field L$0: java.lang.Object
field L$1: java.lang.Object
field L$2: java.lang.Object
private field p$: Controller
inner class CoroutineFieldsKt$box$1
method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: COROUTINES_PACKAGE.Continuation): void
@@ -40,6 +40,7 @@ final class CoroutineFieldsKt$box$1 {
field J$0: long
field L$0: java.lang.Object
field L$1: java.lang.Object
field L$2: java.lang.Object
field label: int
private field p$: Controller
inner class CoroutineFieldsKt$box$1
@@ -6,5 +6,8 @@ inline fun inlineMe(crossinline c: suspend () -> Int): suspend () -> Int {
return i
}
// invokeSuspend$$forInline : valueOf
// invokeSuspend : boxInt
// 1 valueOf
// 0 boxInt
// 1 boxInt
@@ -14,8 +14,8 @@ fun main(args: Array<String>) {
@BuilderInference
suspend fun SequenceScope<Int>.awaitSeq(): Int = 42
// 1 LOCALVARIABLE a I L16 L.* 3
// 1 LINENUMBER 8 L16
// 1 LOCALVARIABLE a I L17 L.* 3
// 1 LINENUMBER 8 L17
// Adding ignore flags below the test since the test relies on line numbers.
// IGNORE_BACKEND: JVM_IR
@@ -21,4 +21,6 @@ class Test {
}
}
// 4 TABLESWITCH
// suspend lambdas: 4
// suspend lambdas $$forInline: 1
// 5 TABLESWITCH
@@ -7381,6 +7381,43 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/javaInterop")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class JavaInterop extends AbstractBlackBoxCodegenTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
KotlinTestUtils.runTest(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInJavaInterop() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/javaInterop"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("returnLambda.kt")
public void testReturnLambda_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("returnLambda.kt")
public void testReturnLambda_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines");
}
@TestMetadata("returnObject.kt")
public void testReturnObject_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("returnObject.kt")
public void testReturnObject_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines");
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -7381,6 +7381,43 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/javaInterop")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class JavaInterop extends AbstractLightAnalysisModeTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
KotlinTestUtils.runTest(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInJavaInterop() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/javaInterop"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("returnLambda.kt")
public void testReturnLambda_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("returnLambda.kt")
public void testReturnLambda_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines");
}
@TestMetadata("returnObject.kt")
public void testReturnObject_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("returnObject.kt")
public void testReturnObject_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines");
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -7381,6 +7381,43 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/javaInterop")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class JavaInterop extends AbstractIrBlackBoxCodegenTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
}
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
KotlinTestUtils.runTest(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.JVM_IR, testDataFilePath);
}
public void testAllFilesPresentInJavaInterop() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/javaInterop"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
}
@TestMetadata("returnLambda.kt")
public void testReturnLambda_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("returnLambda.kt")
public void testReturnLambda_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines");
}
@TestMetadata("returnObject.kt")
public void testReturnObject_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("returnObject.kt")
public void testReturnObject_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines");
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -5701,6 +5701,33 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/javaInterop")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class JavaInterop extends AbstractIrJsCodegenBoxTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
KotlinTestUtils.runTest0(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInJavaInterop() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/javaInterop"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("returnLambda.kt")
public void testReturnLambda_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines");
}
@TestMetadata("returnObject.kt")
public void testReturnObject_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines");
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -6441,6 +6441,43 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/javaInterop")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class JavaInterop extends AbstractJsCodegenBoxTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
}
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
KotlinTestUtils.runTest0(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.JS, testDataFilePath);
}
public void testAllFilesPresentInJavaInterop() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/javaInterop"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
@TestMetadata("returnLambda.kt")
public void testReturnLambda_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("returnLambda.kt")
public void testReturnLambda_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines");
}
@TestMetadata("returnObject.kt")
public void testReturnObject_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("returnObject.kt")
public void testReturnObject_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines");
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)