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), CoroutineCodegenUtilKt.<FunctionDescriptor>unwrapInitialDescriptorForSuspendFunction(functionDescriptor),
function, function,
v.getThisName(), v.getThisName(),
state.getConstructorCallNormalizationMode() state.getConstructorCallNormalizationMode(),
this
); );
} else { } else {
strategy = new SuspendInlineFunctionGenerationStrategy( 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 package org.jetbrains.kotlin.codegen.coroutines
import com.intellij.util.ArrayUtil import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.binding.CodegenBinding import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA
import org.jetbrains.kotlin.codegen.context.ClosureContext 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.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.JvmSerializationBindings.METHOD_FOR_FUNCTION
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
@@ -462,10 +465,8 @@ class CoroutineCodegenForLambda private constructor(
object : FunctionGenerationStrategy.FunctionDefault(state, element as KtDeclarationWithBody) { object : FunctionGenerationStrategy.FunctionDefault(state, element as KtDeclarationWithBody) {
override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor { override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor {
val addEndLabelMethodVisitor = AddEndLabelMethodVisitor(mv, access, name, desc, endLabel) val stateMachineBuilder = CoroutineTransformerMethodVisitor(
if (forInline) return super.wrapMethodVisitor(addEndLabelMethodVisitor, access, name, desc) mv, access, name, desc, null, null,
return CoroutineTransformerMethodVisitor(
addEndLabelMethodVisitor, access, name, desc, null, null,
obtainClassBuilderForCoroutineState = { v }, obtainClassBuilderForCoroutineState = { v },
element = element, element = element,
diagnostics = state.diagnostics, diagnostics = state.diagnostics,
@@ -474,6 +475,17 @@ class CoroutineCodegenForLambda private constructor(
isForNamedFunction = false, isForNamedFunction = false,
languageVersionSettings = languageVersionSettings 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) { 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( private class AddEndLabelMethodVisitor(
delegate: MethodVisitor, delegate: MethodVisitor,
access: Int, access: Int,
name: String, name: String,
desc: String, desc: String,
private val endLabel: Label private val endLabel: Label
): TransformationMethodVisitor(delegate, access, name, desc, null, null) { ) : TransformationMethodVisitor(delegate, access, name, desc, null, null) {
override fun performTransformations(methodNode: MethodNode) { override fun performTransformations(methodNode: MethodNode) {
methodNode.instructions.add( methodNode.instructions.add(
withInstructionAdapter { withInstructionAdapter {
@@ -48,6 +48,7 @@ private const val COROUTINES_METADATA_VERSION_JVM_NAME = "v"
const val SUSPEND_FUNCTION_CONTINUATION_PARAMETER = "\$completion" const val SUSPEND_FUNCTION_CONTINUATION_PARAMETER = "\$completion"
const val SUSPEND_CALL_RESULT_NAME = "\$result" const val SUSPEND_CALL_RESULT_NAME = "\$result"
const val ILLEGAL_STATE_ERROR_MESSAGE = "call to 'resume' before 'invoke' with coroutine"
class CoroutineTransformerMethodVisitor( class CoroutineTransformerMethodVisitor(
delegate: MethodVisitor, delegate: MethodVisitor,
@@ -176,7 +177,7 @@ class CoroutineTransformerMethodVisitor(
insert(last, defaultLabel) insert(last, defaultLabel)
insert(last, withInstructionAdapter { 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) areturn(Type.VOID_TYPE)
}) })
} }
@@ -5,12 +5,10 @@
package org.jetbrains.kotlin.codegen.coroutines package org.jetbrains.kotlin.codegen.coroutines
import org.jetbrains.kotlin.codegen.ClassBuilder import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.FunctionGenerationStrategy
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
import org.jetbrains.kotlin.codegen.binding.CodegenBinding import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.inline.addFakeContinuationConstructorCallMarker 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.codegen.state.GenerationState
import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode
import org.jetbrains.kotlin.config.LanguageVersionSettings 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.diagnostics.OtherOrigin
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.utils.addToStdlib.safeAs 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.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.MethodNode import org.jetbrains.org.objectweb.asm.tree.MethodNode
open class SuspendFunctionGenerationStrategy( open class SuspendFunctionGenerationStrategy(
state: GenerationState, state: GenerationState,
protected val originalSuspendDescriptor: FunctionDescriptor, protected val originalSuspendDescriptor: FunctionDescriptor,
protected val declaration: KtFunction, protected val declaration: KtFunction,
private val containingClassInternalName: String, private val containingClassInternalName: String,
private val constructorCallNormalizationMode: JVMConstructorCallNormalizationMode private val constructorCallNormalizationMode: JVMConstructorCallNormalizationMode,
protected val functionCodegen: FunctionCodegen
) : FunctionGenerationStrategy.CodegenBased(state) { ) : FunctionGenerationStrategy.CodegenBased(state) {
private lateinit var codegen: ExpressionCodegen private lateinit var codegen: ExpressionCodegen
@@ -45,7 +45,7 @@ open class SuspendFunctionGenerationStrategy(
declaration.containingFile declaration.containingFile
).also { ).also {
val coroutineCodegen = val coroutineCodegen =
CoroutineCodegenForNamedFunction.create(it, codegen, originalSuspendDescriptor, declaration) CoroutineCodegenForNamedFunction.create(it, codegen, originalSuspendDescriptor, declaration)
coroutineCodegen.generate() coroutineCodegen.generate()
} }
} }
@@ -53,16 +53,7 @@ open class SuspendFunctionGenerationStrategy(
override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor { override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor {
if (access and Opcodes.ACC_ABSTRACT != 0) return mv if (access and Opcodes.ACC_ABSTRACT != 0) return mv
if (state.bindingContext[CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA, originalSuspendDescriptor] == true) { val stateMachineBuilder = CoroutineTransformerMethodVisitor(
return AddConstructorCallForCoroutineRegeneration(
mv, access, name, desc, null, null, this::classBuilderForCoroutineState,
containingClassInternalName,
originalSuspendDescriptor.dispatchReceiverParameter != null,
containingClassInternalNameOrNull(),
languageVersionSettings
)
}
return CoroutineTransformerMethodVisitor(
mv, access, name, desc, null, null, containingClassInternalName, this::classBuilderForCoroutineState, mv, access, name, desc, null, null, containingClassInternalName, this::classBuilderForCoroutineState,
isForNamedFunction = true, isForNamedFunction = true,
element = declaration, element = declaration,
@@ -72,10 +63,37 @@ open class SuspendFunctionGenerationStrategy(
internalNameForDispatchReceiver = containingClassInternalNameOrNull(), internalNameForDispatchReceiver = containingClassInternalNameOrNull(),
languageVersionSettings = languageVersionSettings 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() = 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) { override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
this.codegen = codegen this.codegen = codegen
@@ -115,6 +133,7 @@ open class SuspendFunctionGenerationStrategy(
languageVersionSettings languageVersionSettings
) )
addFakeContinuationConstructorCallMarker(this, false) 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. * 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.FunctionCodegen
import org.jetbrains.kotlin.codegen.FunctionGenerationStrategy import org.jetbrains.kotlin.codegen.FunctionGenerationStrategy
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor 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.codegen.state.GenerationState
import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.psi.KtFunction 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.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.MethodVisitor import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Opcodes
@@ -29,13 +29,14 @@ class SuspendInlineFunctionGenerationStrategy(
declaration: KtFunction, declaration: KtFunction,
containingClassInternalName: String, containingClassInternalName: String,
constructorCallNormalizationMode: JVMConstructorCallNormalizationMode, constructorCallNormalizationMode: JVMConstructorCallNormalizationMode,
private val codegen: FunctionCodegen codegen: FunctionCodegen
) : SuspendFunctionGenerationStrategy( ) : SuspendFunctionGenerationStrategy(
state, state,
originalSuspendDescriptor, originalSuspendDescriptor,
declaration, declaration,
containingClassInternalName, containingClassInternalName,
constructorCallNormalizationMode constructorCallNormalizationMode,
codegen
) { ) {
private val defaultStrategy = FunctionGenerationStrategy.FunctionDefault(state, declaration) private val defaultStrategy = FunctionGenerationStrategy.FunctionDefault(state, declaration)
@@ -43,16 +44,10 @@ class SuspendInlineFunctionGenerationStrategy(
if (access and Opcodes.ACC_ABSTRACT != 0) return mv if (access and Opcodes.ACC_ABSTRACT != 0) return mv
return MethodNodeCopyingMethodVisitor( return MethodNodeCopyingMethodVisitor(
super.wrapMethodVisitor(mv, access, name, desc), super.wrapMethodVisitor(mv, access, name, desc), access, name, desc,
access, newMethod = { origin, newAccess, newName, newDesc ->
name, functionCodegen.newMethod(origin, newAccess, newName, newDesc, null, null)
desc = desc, }, keepAccess = false
signature = null,
exceptions = null,
codegen = codegen,
declaration = declaration,
originalSuspendDescriptor = originalSuspendDescriptor,
isReleaseCoroutines = state.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
) )
} }
@@ -60,46 +55,26 @@ class SuspendInlineFunctionGenerationStrategy(
super.doGenerateBody(codegen, signature) super.doGenerateBody(codegen, signature)
defaultStrategy.doGenerateBody(codegen, signature) defaultStrategy.doGenerateBody(codegen, signature)
} }
}
private class MethodNodeCopyingMethodVisitor( class MethodNodeCopyingMethodVisitor(
delegate: MethodVisitor, delegate: MethodVisitor, private val access: Int, private val name: String, private val desc: String,
private val access: Int, private val newMethod: (JvmDeclarationOrigin, Int, String, String) -> MethodVisitor,
private val name: String, private val keepAccess: Boolean = true
private val desc: String, ) : TransformationMethodVisitor(
private val signature: String?, delegate, calculateAccessForInline(access, keepAccess), "$name$FOR_INLINE_SUFFIX", desc, null, null
private val exceptions: Array<out String>?, ) {
private val codegen: FunctionCodegen, override fun performTransformations(methodNode: MethodNode) {
private val declaration: KtFunction, val newMethodNode = newMethod(
private val originalSuspendDescriptor: FunctionDescriptor, JvmDeclarationOrigin.NO_ORIGIN, calculateAccessForInline(access, keepAccess), "$name$FOR_INLINE_SUFFIX", desc
private val isReleaseCoroutines: Boolean )
) : TransformationMethodVisitor( methodNode.instructions.resetLabels()
delegate, methodNode.accept(newMethodNode)
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)
}
} }
companion object { companion object {
private fun calculateAccessForInline(access: Int): Int { private fun calculateAccessForInline(access: Int, keepAccess: Boolean): Int =
var accessForInline = access if (keepAccess) access
if (accessForInline and Opcodes.ACC_PUBLIC != 0) { else access or Opcodes.ACC_PRIVATE and Opcodes.ACC_PUBLIC.inv() and Opcodes.ACC_PROTECTED.inv()
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
}
} }
} }
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.codegen.inline
import com.intellij.util.ArrayUtil import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.codegen.* 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.coroutines.isCoroutineSuperClass
import org.jetbrains.kotlin.codegen.inline.coroutines.CoroutineTransformer import org.jetbrains.kotlin.codegen.inline.coroutines.CoroutineTransformer
import org.jetbrains.kotlin.codegen.serialization.JvmCodegenStringTable 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 // Empty inner class info because no inner classes are used in kotlin.Metadata and its arguments
val innerClassesInfo = FileBasedKotlinClass.InnerClassesInfo() val innerClassesInfo = FileBasedKotlinClass.InnerClassesInfo()
return FileBasedKotlinClass.convertAnnotationVisitor(metadataReader, desc, innerClassesInfo) return FileBasedKotlinClass.convertAnnotationVisitor(metadataReader, desc, innerClassesInfo)
} else if (desc == DEBUG_METADATA_ANNOTATION_ASM_TYPE.descriptor) {
return null
} }
return super.visitAnnotation(desc, visible) return super.visitAnnotation(desc, visible)
} }
@@ -135,12 +139,13 @@ class AnonymousObjectTransformer(
classBuilder, classBuilder,
methodsToTransform, methodsToTransform,
superClassName, superClassName,
additionalFakeParams allCapturedParamBuilder.listCaptured()
) )
for (next in methodsToTransform) { loop@for (next in methodsToTransform) {
val deferringVisitor = val deferringVisitor =
when { when {
coroutineTransformer.shouldTransform(next) -> coroutineTransformer.newMethod(next) coroutineTransformer.shouldSkip(next) -> continue@loop
coroutineTransformer.shouldGenerateStateMachine(next) -> coroutineTransformer.newMethod(next)
else -> newMethod(classBuilder, next) else -> newMethod(classBuilder, next)
} }
val funResult = inlineMethodAndUpdateGlobalResult(parentRemapper, deferringVisitor, next, allCapturedParamBuilder, false) val funResult = inlineMethodAndUpdateGlobalResult(parentRemapper, deferringVisitor, next, allCapturedParamBuilder, false)
@@ -479,6 +484,11 @@ class AnonymousObjectTransformer(
alreadyAddedParam?.newFieldName ?: getNewFieldName(desc.fieldName, false), alreadyAddedParam?.newFieldName ?: getNewFieldName(desc.fieldName, false),
alreadyAddedParam != null 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( val composed = StackValue.field(
desc.type, desc.type,
oldObjectType, /*TODO owner 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.AsmUtil.isPrimitive
import org.jetbrains.kotlin.codegen.binding.CodegenBinding import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.context.ClosureContext 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.intrinsics.IntrinsicArrayConstructors
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper 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 // 2) for inliner: with mangled name and without state machine
private fun mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor: FunctionDescriptor, asmMethod: Method): Method { private fun mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor: FunctionDescriptor, asmMethod: Method): Method {
if (!functionDescriptor.isSuspend) return asmMethod 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 { private fun getDirectMemberAndCallableFromObject(functionDescriptor: FunctionDescriptor): CallableMemberDescriptor {
@@ -307,4 +307,6 @@ class PsiExpressionLambda(
val isPropertyReference: Boolean val isPropertyReference: Boolean
get() = propertyReferenceInfo != null get() = propertyReferenceInfo != null
val captureVariables = closure.captureVariables
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.codegen.inline; 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.*;
import org.jetbrains.org.objectweb.asm.commons.FieldRemapper; import org.jetbrains.org.objectweb.asm.commons.FieldRemapper;
import java.util.HashMap;
import java.util.Map;
public class RemappingClassBuilder extends DelegatingClassBuilder { public class RemappingClassBuilder extends DelegatingClassBuilder {
private final ClassBuilder builder; private final ClassBuilder builder;
private final Remapper remapper; private final Remapper remapper;
private final Map<String, FieldVisitor> spilledCoroutineVariables = new HashMap<>();
public RemappingClassBuilder(@NotNull ClassBuilder builder, @NotNull Remapper remapper) { public RemappingClassBuilder(@NotNull ClassBuilder builder, @NotNull Remapper remapper) {
this.builder = builder; this.builder = builder;
@@ -68,9 +61,39 @@ public class RemappingClassBuilder extends DelegatingClassBuilder {
@Nullable String signature, @Nullable String signature,
@Nullable Object value @Nullable Object value
) { ) {
return new FieldRemapper( if (spilledCoroutineVariables.containsKey(name)) return spilledCoroutineVariables.get(name);
builder.newField(origin, access, name, remapper.mapDesc(desc), remapper.mapSignature(signature, true), value), remapper
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 @Override
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.codegen.inline.coroutines package org.jetbrains.kotlin.codegen.inline.coroutines
import com.intellij.util.ArrayUtil 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.ClassBuilder
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
import org.jetbrains.kotlin.codegen.coroutines.* 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.common.findPreviousOrNull
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.config.isReleaseCoroutines import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.utils.addToStdlib.cast 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 NOINLINE_CALL_MARKER = "NOINLINE_CALL_MARKER"
const val FOR_INLINE_SUFFIX = "\$\$forInline"
class CoroutineTransformer( class CoroutineTransformer(
private val inliningContext: InliningContext, private val inliningContext: InliningContext,
private val classBuilder: ClassBuilder, private val classBuilder: ClassBuilder,
@@ -37,24 +39,20 @@ class CoroutineTransformer(
private val capturedParams: List<CapturedParamInfo> private val capturedParams: List<CapturedParamInfo>
) { ) {
private val state = inliningContext.state 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 { fun shouldSkip(node: MethodNode): Boolean = methods.any { it.name == node.name + FOR_INLINE_SUFFIX && it.desc == node.desc }
// Never generate state-machine for objects, which are going to be retransformed
// See innerObjectRetransformation.kt fun shouldGenerateStateMachine(node: MethodNode): Boolean {
if (inliningContext.callSiteInfo.isInlineOrInsideInline) return false // Continuations are similar to lambdas from bird's view, but we should never generate state machine for them
if (isContinuationNotLambda()) return false if (isContinuationNotLambda()) return false
val crossinlineParam = crossinlineLambda() // The method does not have state-machine, but should. Generate it
if (inliningContext.isInliningLambda && !inliningContext.isContinuation) return false if (node.name.endsWith(FOR_INLINE_SUFFIX)) return true
return when { // there can be suspend lambdas inside inline functions, which do not
isSuspendFunction(node) -> true // capture crossinline lambdas, thus, there is no need to transform them
isSuspendLambda(node) -> { return isSuspendFunctionWithFakeConstructorCall(node) || (isSuspendLambda(node) && !isStateMachine(node))
if (isStateMachine(node)) return false
val functionDescriptor =
crossinlineParam?.invokeMethodDescriptor?.containingDeclaration as? FunctionDescriptor ?: return true
!functionDescriptor.isInline
}
else -> false
}
} }
private fun isContinuationNotLambda(): Boolean = inliningContext.isContinuation && private fun isContinuationNotLambda(): Boolean = inliningContext.isContinuation &&
@@ -66,7 +64,7 @@ class CoroutineTransformer(
}?.cast() }?.cast()
private fun isStateMachine(node: MethodNode): Boolean = 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) private fun isSuspendLambda(node: MethodNode) = isResumeImpl(node)
@@ -83,28 +81,29 @@ class CoroutineTransformer(
} }
newStateMachineForLambda(node, element) newStateMachineForLambda(node, element)
} }
isSuspendFunction(node) -> newStateMachineForNamedFunction(node, element) isSuspendFunctionWithFakeConstructorCall(node) -> newStateMachineForNamedFunction(node, element)
else -> error("no need to generate state maching for ${node.name}") else -> error("no need to generate state maching for ${node.name}")
} }
} }
private fun isResumeImpl(node: MethodNode): Boolean = private fun isResumeImpl(node: MethodNode): Boolean =
state.languageVersionSettings.isResumeImplMethodName(node.name) && state.languageVersionSettings.isResumeImplMethodName(node.name.removeSuffix(FOR_INLINE_SUFFIX)) &&
inliningContext.isContinuation 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 { private fun newStateMachineForLambda(node: MethodNode, element: KtElement): DeferredMethodVisitor {
val name = node.name.removeSuffix(FOR_INLINE_SUFFIX)
return DeferredMethodVisitor( return DeferredMethodVisitor(
MethodNode( MethodNode(
node.access, node.name, node.desc, node.signature, node.access, name, node.desc, node.signature,
ArrayUtil.toStringArray(node.exceptions) ArrayUtil.toStringArray(node.exceptions)
) )
) { ) {
surroundNoinlineCallsWithMarkersIfNeeded( val stateMachineBuilder = surroundNoinlineCallsWithMarkersIfNeeded(
node, node,
CoroutineTransformerMethodVisitor( CoroutineTransformerMethodVisitor(
createNewMethodFrom(node), node.access, node.name, node.desc, null, null, createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
obtainClassBuilderForCoroutineState = { classBuilder }, obtainClassBuilderForCoroutineState = { classBuilder },
element = element, element = element,
diagnostics = state.diagnostics, diagnostics = state.diagnostics,
@@ -114,22 +113,36 @@ class CoroutineTransformer(
isForNamedFunction = false 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 { private fun newStateMachineForNamedFunction(node: MethodNode, element: KtElement): DeferredMethodVisitor {
val name = node.name.removeSuffix(FOR_INLINE_SUFFIX)
val continuationClassName = findFakeContinuationConstructorClassName(node) val continuationClassName = findFakeContinuationConstructorClassName(node)
assert(inliningContext is RegeneratedClassContext) assert(inliningContext is RegeneratedClassContext)
return DeferredMethodVisitor( return DeferredMethodVisitor(
MethodNode( MethodNode(
node.access, node.name, node.desc, node.signature, node.access, name, node.desc, node.signature,
ArrayUtil.toStringArray(node.exceptions) ArrayUtil.toStringArray(node.exceptions)
) )
) { ) {
surroundNoinlineCallsWithMarkersIfNeeded( val stateMachineBuilder = surroundNoinlineCallsWithMarkersIfNeeded(
node, node,
CoroutineTransformerMethodVisitor( 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]!! }, obtainClassBuilderForCoroutineState = { (inliningContext as RegeneratedClassContext).continuationBuilders[continuationClassName]!! },
element = element, element = element,
diagnostics = state.diagnostics, diagnostics = state.diagnostics,
@@ -141,30 +154,33 @@ class CoroutineTransformer(
internalNameForDispatchReceiver = classBuilder.thisName 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 = 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( SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
delegate, delegate, node.access, node.name, node.desc, classBuilder.thisName, this::isCapturedSuspendLambda
node.access,
node.name,
node.desc,
classBuilder.thisName,
capturedParams
) )
else else
delegate 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( return classBuilder.newMethod(
JvmDeclarationOrigin.NO_ORIGIN, JvmDeclarationOrigin.NO_ORIGIN, node.access, name, node.desc, node.signature, ArrayUtil.toStringArray(node.exceptions)
node.access,
node.name,
node.desc,
node.signature,
ArrayUtil.toStringArray(node.exceptions)
) )
} }
@@ -193,13 +209,10 @@ class CoroutineTransformer(
} }
} }
private class SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor( class SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
delegate: MethodVisitor, delegate: MethodVisitor, access: Int, name: String, desc: String,
access: Int, private val thisName: String,
name: String, private val isCapturedSuspendLambda: (FieldInsnNode) -> Boolean
desc: String,
val thisName: String,
val capturedParams: List<CapturedParamInfo>
) : TransformationMethodVisitor(delegate, access, name, desc, null, null) { ) : TransformationMethodVisitor(delegate, access, name, desc, null, null) {
override fun performTransformations(methodNode: MethodNode) { override fun performTransformations(methodNode: MethodNode) {
fun AbstractInsnNode.index() = methodNode.instructions.indexOf(this) fun AbstractInsnNode.index() = methodNode.instructions.indexOf(this)
@@ -213,7 +226,7 @@ private class SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
insn as MethodInsnNode insn as MethodInsnNode
if (!isInvokeOnLambda(insn.owner, insn.name)) continue if (!isInvokeOnLambda(insn.owner, insn.name)) continue
val frame = sourceFrames[insn.index()] 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") 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" } assert(aload.opcode == Opcodes.ALOAD) { "Before GETFIELD there shall be ALOAD" }
noinlineInvokes.add(insn to aload) noinlineInvokes.add(insn to aload)
@@ -222,15 +235,29 @@ private class SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
surroundInvokesWithSuspendMarkers(methodNode, noinlineInvokes) surroundInvokesWithSuspendMarkers(methodNode, noinlineInvokes)
} }
private fun AbstractInsnNode.isNoinlineSuspendLambda(invoke: MethodInsnNode): Boolean { private fun AbstractInsnNode.isSuspendLambda(invoke: MethodInsnNode): Boolean {
if (opcode != Opcodes.GETFIELD) return false if (opcode != Opcodes.GETFIELD) return false
this as FieldInsnNode this as FieldInsnNode
if (owner != thisName || desc != "L${invoke.owner};") return false if (desc != "L${invoke.owner};") return false
val functionalArgument = capturedParams.find { it.newFieldName == name }?.functionalArgument ?: return false var current: FieldInsnNode? = this
return functionalArgument is NonInlineableArgumentForInlineableParameterCalledInSuspend && functionalArgument.isSuspend // 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( fun surroundInvokesWithSuspendMarkers(
methodNode: MethodNode, methodNode: MethodNode,
noinlineInvokes: List<Pair<AbstractInsnNode, AbstractInsnNode>> 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.Metadata
@kotlin.coroutines.jvm.internal.DebugMetadata
public final class CrossinlineKt$box$1$filter$$inlined$source$1$1 { 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 field label: int
synthetic field result: java.lang.Object synthetic field result: java.lang.Object
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1 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.Metadata
@kotlin.coroutines.jvm.internal.DebugMetadata
public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1 { 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 field label: int
synthetic field result: java.lang.Object synthetic field result: java.lang.Object
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1 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 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 <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 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 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
inner class CrossinlineKt$box$1$filter$$inlined$source$1$1 inner class CrossinlineKt$box$1$filter$$inlined$source$1$1
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void 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 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.Metadata
@kotlin.coroutines.jvm.internal.DebugMetadata
public final class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1 { 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 field label: int
synthetic field result: java.lang.Object synthetic field result: java.lang.Object
synthetic final field this$0: CrossinlineKt$box$1$fold$$inlined$consumeEach$1 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 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 <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 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 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 @kotlin.Metadata
public final class CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1$1 { 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 field label: int
synthetic field result: java.lang.Object synthetic field result: java.lang.Object
synthetic final field this$0: CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1 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 inner class CrossinlineKt$consumeEach$2$send$1
public method <init>(p0: kotlin.jvm.functions.Function2): void public method <init>(p0: kotlin.jvm.functions.Function2): void
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): 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 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.Metadata
@kotlin.coroutines.jvm.internal.DebugMetadata
public final class CrossinlineKt$filter$$inlined$source$1$1 { 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 field label: int
synthetic field result: java.lang.Object synthetic field result: java.lang.Object
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1 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.Metadata
@kotlin.coroutines.jvm.internal.DebugMetadata
public final class CrossinlineKt$filter$$inlined$source$1$lambda$1$1 { 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 field label: int
synthetic field result: java.lang.Object synthetic field result: java.lang.Object
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1$lambda$1 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 inner class CrossinlineKt$filter$$inlined$source$1$lambda$1$1
public method <init>(p0: Sink, p1: CrossinlineKt$filter$$inlined$source$1): void 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 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 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
inner class CrossinlineKt$filter$$inlined$source$1$1 inner class CrossinlineKt$filter$$inlined$source$1$1
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void 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 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 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 <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 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 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.Metadata
@kotlin.coroutines.jvm.internal.DebugMetadata
public final class CrossinlineKt$source$1$consume$1 { 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 field label: int
synthetic field result: java.lang.Object synthetic field result: java.lang.Object
synthetic final field this$0: CrossinlineKt$source$1 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
inner class CrossinlineKt$source$1$consume$1 inner class CrossinlineKt$source$1$consume$1
public method <init>(p0: kotlin.jvm.functions.Function2): void 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 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 @kotlin.Metadata
public final class CrossinlineKt$box$1$doResume$$inlined$fold$1$1 { 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 data: java.lang.Object
synthetic field exception: java.lang.Throwable synthetic field exception: java.lang.Throwable
synthetic final field this$0: CrossinlineKt$box$1$doResume$$inlined$fold$1 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 @kotlin.Metadata
public final class CrossinlineKt$box$1$filter$$inlined$source$1$1 { 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 data: java.lang.Object
synthetic field exception: java.lang.Throwable synthetic field exception: java.lang.Throwable
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1 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 @kotlin.Metadata
public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1 { 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 data: java.lang.Object
synthetic field exception: java.lang.Throwable synthetic field exception: java.lang.Throwable
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1 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 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 <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 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 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
inner class CrossinlineKt$box$1$filter$$inlined$source$1$1 inner class CrossinlineKt$box$1$filter$$inlined$source$1$1
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void 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 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 @kotlin.Metadata
public final class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1 { 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 data: java.lang.Object
synthetic field exception: java.lang.Throwable synthetic field exception: java.lang.Throwable
synthetic final field this$0: CrossinlineKt$box$1$fold$$inlined$consumeEach$1 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 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 <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 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 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 inner class CrossinlineKt$consumeEach$2$send$1
public method <init>(p0: kotlin.jvm.functions.Function2): void public method <init>(p0: kotlin.jvm.functions.Function2): void
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): 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 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 @kotlin.Metadata
public final class CrossinlineKt$filter$$inlined$source$1$1 { 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 data: java.lang.Object
synthetic field exception: java.lang.Throwable synthetic field exception: java.lang.Throwable
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1 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 @kotlin.Metadata
public final class CrossinlineKt$filter$$inlined$source$1$lambda$1$1 { 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 data: java.lang.Object
synthetic field exception: java.lang.Throwable synthetic field exception: java.lang.Throwable
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1$lambda$1 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 inner class CrossinlineKt$filter$$inlined$source$1$lambda$1$1
public method <init>(p0: Sink, p1: CrossinlineKt$filter$$inlined$source$1): void 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 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 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
inner class CrossinlineKt$filter$$inlined$source$1$1 inner class CrossinlineKt$filter$$inlined$source$1$1
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void 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 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 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 <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 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 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 @kotlin.Metadata
public final class CrossinlineKt$source$1$consume$1 { 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 data: java.lang.Object
synthetic field exception: java.lang.Throwable synthetic field exception: java.lang.Throwable
synthetic final field this$0: CrossinlineKt$source$1 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
inner class CrossinlineKt$source$1$consume$1 inner class CrossinlineKt$source$1$consume$1
public method <init>(p0: kotlin.jvm.functions.Function2): void 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 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 @kotlin.Metadata
public final class flow/InnerObjectRetransformationKt$check$$inlined$flowWith$1$1 { 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 field label: int
synthetic field result: java.lang.Object synthetic field result: java.lang.Object
synthetic final field this$0: flow.InnerObjectRetransformationKt$check$$inlined$flowWith$1 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
inner class flow/InnerObjectRetransformationKt$collect$2$emit$1 inner class flow/InnerObjectRetransformationKt$collect$2$emit$1
public method <init>(p0: kotlin.jvm.functions.Function2): void 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 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
inner class flow/InnerObjectRetransformationKt$flow$1$collect$1 inner class flow/InnerObjectRetransformationKt$flow$1$collect$1
public method <init>(p0: kotlin.jvm.functions.Function2): void 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 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
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1 inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1
public method <init>(p0: flow.Flow, p1: kotlin.jvm.functions.Function2): void 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 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.Metadata
@kotlin.coroutines.jvm.internal.DebugMetadata
public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2$1 { 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 field label: int
synthetic field result: java.lang.Object synthetic field result: java.lang.Object
synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$2 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
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2$1 inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2$1
public method <init>(p0: flow.Flow, p1: kotlin.jvm.functions.Function2): void 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 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 @kotlin.Metadata
public final class flow/InnerObjectRetransformationKt$check$$inlined$flowWith$1$1 { 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 data: java.lang.Object
synthetic field exception: java.lang.Throwable synthetic field exception: java.lang.Throwable
synthetic final field this$0: flow.InnerObjectRetransformationKt$check$$inlined$flowWith$1 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
inner class flow/InnerObjectRetransformationKt$collect$2$emit$1 inner class flow/InnerObjectRetransformationKt$collect$2$emit$1
public method <init>(p0: kotlin.jvm.functions.Function2): void 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 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
inner class flow/InnerObjectRetransformationKt$flow$1$collect$1 inner class flow/InnerObjectRetransformationKt$flow$1$collect$1
public method <init>(p0: kotlin.jvm.functions.Function2): void 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 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
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1 inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1
public method <init>(p0: flow.Flow, p1: kotlin.jvm.functions.Function2): void 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 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 @kotlin.Metadata
public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2$1 { 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 data: java.lang.Object
synthetic field exception: java.lang.Throwable synthetic field exception: java.lang.Throwable
synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$2 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
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2$1 inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2$1
public method <init>(p0: flow.Flow, p1: kotlin.jvm.functions.Function2): void 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 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 J$0: long
field L$0: java.lang.Object field L$0: java.lang.Object
field L$1: java.lang.Object field L$1: java.lang.Object
field L$2: java.lang.Object
private field p$: Controller private field p$: Controller
inner class CoroutineFieldsKt$box$1 inner class CoroutineFieldsKt$box$1
method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: COROUTINES_PACKAGE.Continuation): void 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 J$0: long
field L$0: java.lang.Object field L$0: java.lang.Object
field L$1: java.lang.Object field L$1: java.lang.Object
field L$2: java.lang.Object
field label: int field label: int
private field p$: Controller private field p$: Controller
inner class CoroutineFieldsKt$box$1 inner class CoroutineFieldsKt$box$1
@@ -6,5 +6,8 @@ inline fun inlineMe(crossinline c: suspend () -> Int): suspend () -> Int {
return i return i
} }
// invokeSuspend$$forInline : valueOf
// invokeSuspend : boxInt
// 1 valueOf // 1 valueOf
// 0 boxInt // 1 boxInt
@@ -14,8 +14,8 @@ fun main(args: Array<String>) {
@BuilderInference @BuilderInference
suspend fun SequenceScope<Int>.awaitSeq(): Int = 42 suspend fun SequenceScope<Int>.awaitSeq(): Int = 42
// 1 LOCALVARIABLE a I L16 L.* 3 // 1 LOCALVARIABLE a I L17 L.* 3
// 1 LINENUMBER 8 L16 // 1 LINENUMBER 8 L17
// Adding ignore flags below the test since the test relies on line numbers. // Adding ignore flags below the test since the test relies on line numbers.
// IGNORE_BACKEND: JVM_IR // 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") @TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @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") @TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @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") @TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @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") @TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @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") @TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)