Regenerate anonymous object if call site of non-inlineable

functional argument is suspend
Split LambdaInfo into inlineable and non-inlineable
 #KT-26925
This commit is contained in:
Ilmir Usmanov
2019-03-14 17:50:28 +03:00
parent 1c2b8e6fad
commit 0fec3470dd
28 changed files with 633 additions and 97 deletions
@@ -18,7 +18,8 @@ enum class ValueKind {
DEFAULT_MASK, DEFAULT_MASK,
METHOD_HANDLE_IN_DEFAULT, METHOD_HANDLE_IN_DEFAULT,
CAPTURED, CAPTURED,
DEFAULT_LAMBDA_CAPTURED_PARAMETER DEFAULT_LAMBDA_CAPTURED_PARAMETER,
NON_INLINEABLE_CALLED_IN_SUSPEND
} }
interface CallGenerator { interface CallGenerator {
@@ -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.
*/ */
@@ -726,6 +726,9 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
if (variableDescriptor instanceof ValueParameterDescriptor && if (variableDescriptor instanceof ValueParameterDescriptor &&
((ValueParameterDescriptor) variableDescriptor).isCrossinline()) { ((ValueParameterDescriptor) variableDescriptor).isCrossinline()) {
DeclarationDescriptor functionWithCrossinlineParameter = variableDescriptor.getContainingDeclaration(); DeclarationDescriptor functionWithCrossinlineParameter = variableDescriptor.getContainingDeclaration();
if (functionsStack.peek().isSuspend()) {
bindingTrace.record(CALL_SITE_IS_SUSPEND_FOR_CROSSINLINE_LAMBDA, (ValueParameterDescriptor) variableDescriptor, true);
}
for (int i = functionsStack.size() - 1; i >= 0; i--) { for (int i = functionsStack.size() - 1; i >= 0; i--) {
Boolean alreadyPutValue = bindingTrace.getBindingContext() Boolean alreadyPutValue = bindingTrace.getBindingContext()
.get(CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA, functionsStack.get(i)); .get(CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA, functionsStack.get(i));
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2017 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.
*/ */
@@ -60,6 +60,9 @@ public class CodegenBinding {
public static final WritableSlice<FunctionDescriptor, Boolean> CAPTURES_CROSSINLINE_LAMBDA = public static final WritableSlice<FunctionDescriptor, Boolean> CAPTURES_CROSSINLINE_LAMBDA =
Slices.createSimpleSlice(); Slices.createSimpleSlice();
public static final WritableSlice<ValueParameterDescriptor, Boolean> CALL_SITE_IS_SUSPEND_FOR_CROSSINLINE_LAMBDA =
Slices.createSimpleSlice();
public static final WritableSlice<ClassDescriptor, Boolean> RECURSIVE_SUSPEND_CALLABLE_REFERENCE = public static final WritableSlice<ClassDescriptor, Boolean> RECURSIVE_SUSPEND_CALLABLE_REFERENCE =
Slices.createSimpleSlice(); Slices.createSimpleSlice();
@@ -343,7 +343,7 @@ class AnonymousObjectTransformer(
for (info in constructorAdditionalFakeParams) { for (info in constructorAdditionalFakeParams) {
val fake = constructorInlineBuilder.addCapturedParamCopy(info) val fake = constructorInlineBuilder.addCapturedParamCopy(info)
if (fake.lambda != null) { if (fake.functionalArgument is LambdaInfo) {
//set remap value to skip this fake (captured with lambda already skipped) //set remap value to skip this fake (captured with lambda already skipped)
val composed = StackValue.field( val composed = StackValue.field(
fake.getType(), fake.getType(),
@@ -415,7 +415,7 @@ class AnonymousObjectTransformer(
): List<CapturedParamInfo> { ): List<CapturedParamInfo> {
val capturedLambdas = LinkedHashSet<LambdaInfo>() //captured var of inlined parameter val capturedLambdas = LinkedHashSet<LambdaInfo>() //captured var of inlined parameter
val constructorAdditionalFakeParams = ArrayList<CapturedParamInfo>() val constructorAdditionalFakeParams = ArrayList<CapturedParamInfo>()
val indexToLambda = transformationInfo.lambdasToInline val indexToFunctionalArgument = transformationInfo.functionalArguments
val capturedParams = HashSet<Int>() val capturedParams = HashSet<Int>()
//load captured parameters and patch instruction list //load captured parameters and patch instruction list
@@ -425,18 +425,18 @@ class AnonymousObjectTransformer(
val fieldName = fieldNode.name val fieldName = fieldNode.name
val parameterAload = fieldNode.previous as VarInsnNode val parameterAload = fieldNode.previous as VarInsnNode
val varIndex = parameterAload.`var` val varIndex = parameterAload.`var`
val lambdaInfo = indexToLambda[varIndex] val functionalArgument = indexToFunctionalArgument[varIndex]
val newFieldName = if (isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToLambda.values)) val newFieldName = if (isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToFunctionalArgument.values))
getNewFieldName(fieldName, true) getNewFieldName(fieldName, true)
else else
fieldName fieldName
val info = capturedParamBuilder.addCapturedParam( val info = capturedParamBuilder.addCapturedParam(
Type.getObjectType(transformationInfo.oldClassName), fieldName, newFieldName, Type.getObjectType(transformationInfo.oldClassName), fieldName, newFieldName,
Type.getType(fieldNode.desc), lambdaInfo != null, null Type.getType(fieldNode.desc), functionalArgument is LambdaInfo, null
) )
if (lambdaInfo != null) { info.functionalArgument = functionalArgument
info.lambda = lambdaInfo if (functionalArgument is LambdaInfo) {
capturedLambdas.add(lambdaInfo) capturedLambdas.add(functionalArgument)
} }
constructorAdditionalFakeParams.add(info) constructorAdditionalFakeParams.add(info)
capturedParams.add(varIndex) capturedParams.add(varIndex)
@@ -451,9 +451,9 @@ class AnonymousObjectTransformer(
val paramTypes = transformationInfo.constructorDesc?.let { Type.getArgumentTypes(it) } ?: emptyArray() val paramTypes = transformationInfo.constructorDesc?.let { Type.getArgumentTypes(it) } ?: emptyArray()
for (type in paramTypes) { for (type in paramTypes) {
val info = indexToLambda[constructorParamBuilder.nextParameterOffset] val info = indexToFunctionalArgument[constructorParamBuilder.nextParameterOffset]
val parameterInfo = constructorParamBuilder.addNextParameter(type, info != null) val parameterInfo = constructorParamBuilder.addNextParameter(type, info is LambdaInfo)
parameterInfo.lambda = info parameterInfo.functionalArgument = info
if (capturedParams.contains(parameterInfo.index)) { if (capturedParams.contains(parameterInfo.index)) {
parameterInfo.isCaptured = true parameterInfo.isCaptured = true
} else { } else {
@@ -519,9 +519,9 @@ class AnonymousObjectTransformer(
return constructorAdditionalFakeParams return constructorAdditionalFakeParams
} }
private fun shouldRenameThis0(parentFieldRemapper: FieldRemapper, values: Collection<LambdaInfo>): Boolean { private fun shouldRenameThis0(parentFieldRemapper: FieldRemapper, values: Collection<FunctionalArgument>): Boolean {
return if (isFirstDeclSiteLambdaFieldRemapper(parentFieldRemapper)) { return if (isFirstDeclSiteLambdaFieldRemapper(parentFieldRemapper)) {
values.any { it.capturedVars.any { isThis0(it.fieldName) } } values.any { it is LambdaInfo && it.capturedVars.any { isThis0(it.fieldName) } }
} else false } else false
} }
@@ -65,7 +65,7 @@ public class CapturedParamInfo extends ParameterInfo {
CapturedParamInfo result = new CapturedParamInfo( CapturedParamInfo result = new CapturedParamInfo(
desc, newFieldName, isSkipped, getIndex(), getRemapValue(), skipInConstructor, newDeclarationIndex desc, newFieldName, isSkipped, getIndex(), getRemapValue(), skipInConstructor, newDeclarationIndex
); );
result.setLambda(getLambda()); result.setFunctionalArgument(getFunctionalArgument());
result.setSynthetic(synthetic); result.setSynthetic(synthetic);
return result; return result;
} }
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags 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.context.ClosureContext import org.jetbrains.kotlin.codegen.context.ClosureContext
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
@@ -83,7 +84,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
protected val invocationParamBuilder = ParametersBuilder.newBuilder() protected val invocationParamBuilder = ParametersBuilder.newBuilder()
protected val expressionMap = linkedMapOf<Int, LambdaInfo>() protected val expressionMap = linkedMapOf<Int, FunctionalArgument>()
var activeLambda: LambdaInfo? = null var activeLambda: LambdaInfo? = null
protected set protected set
@@ -234,7 +235,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
extractDefaultLambdaOffsetAndDescriptor(jvmSignature, functionDescriptor) extractDefaultLambdaOffsetAndDescriptor(jvmSignature, functionDescriptor)
) )
for (lambda in defaultLambdas) { for (lambda in defaultLambdas) {
invocationParamBuilder.buildParameters().getParameterByDeclarationSlot(lambda.offset).lambda = lambda invocationParamBuilder.buildParameters().getParameterByDeclarationSlot(lambda.offset).functionalArgument = lambda
val prev = expressionMap.put(lambda.offset, lambda) val prev = expressionMap.put(lambda.offset, lambda)
assert(prev == null) { "Lambda with offset ${lambda.offset} already exists: $prev" } assert(prev == null) { "Lambda with offset ${lambda.offset} already exists: $prev" }
} }
@@ -310,7 +311,9 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
private fun generateClosuresBodies() { private fun generateClosuresBodies() {
for (info in expressionMap.values) { for (info in expressionMap.values) {
info.generateLambdaBody(sourceCompiler, reifiedTypeInliner) if (info is LambdaInfo) {
info.generateLambdaBody(sourceCompiler, reifiedTypeInliner)
}
} }
} }
@@ -340,6 +343,9 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
info.setRemapValue(remappedValue) info.setRemapValue(remappedValue)
} else { } else {
info = invocationParamBuilder.addNextValueParameter(jvmType, false, remappedValue, parameterIndex) info = invocationParamBuilder.addNextValueParameter(jvmType, false, remappedValue, parameterIndex)
if (kind == ValueKind.NON_INLINEABLE_CALLED_IN_SUSPEND) {
info.functionalArgument = CrossinlineLambdaInSuspendContextAsNoInline
}
} }
recordParameterValueInLocalVal( recordParameterValueInLocalVal(
@@ -395,8 +401,10 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
private fun putClosureParametersOnStack() { private fun putClosureParametersOnStack() {
for (next in expressionMap.values) { for (next in expressionMap.values) {
//closure parameters for bounded callable references are generated inplace //closure parameters for bounded callable references are generated inplace
if (next is ExpressionLambda && next.isBoundCallableReference) continue if (next is LambdaInfo) {
putClosureParametersOnStack(next, null) if (next is ExpressionLambda && next.isBoundCallableReference) continue
putClosureParametersOnStack(next, null)
}
} }
} }
@@ -730,10 +738,18 @@ class PsiInlineCodegen(
} }
} else { } else {
val value = codegen.gen(argumentExpression) val value = codegen.gen(argumentExpression)
putValueIfNeeded(parameterType, value, ValueKind.GENERAL, parameterIndex) putValueIfNeeded(
parameterType,
value,
if (isCallSiteIsSuspend(valueParameterDescriptor)) ValueKind.NON_INLINEABLE_CALLED_IN_SUSPEND else ValueKind.GENERAL,
parameterIndex
)
} }
} }
private fun isCallSiteIsSuspend(descriptor: ValueParameterDescriptor): Boolean =
state.bindingContext[CodegenBinding.CALL_SITE_IS_SUSPEND_FOR_CROSSINLINE_LAMBDA, descriptor] == true
private fun rememberClosure(expression: KtExpression, type: Type, parameter: ValueParameterDescriptor): LambdaInfo { private fun rememberClosure(expression: KtExpression, type: Type, parameter: ValueParameterDescriptor): LambdaInfo {
val ktLambda = KtPsiUtil.deparenthesize(expression) val ktLambda = KtPsiUtil.deparenthesize(expression)
assert(isInlinableParameterExpression(ktLambda)) { "Couldn't find inline expression in ${expression.text}" } assert(isInlinableParameterExpression(ktLambda)) { "Couldn't find inline expression in ${expression.text}" }
@@ -743,7 +759,7 @@ class PsiInlineCodegen(
parameter.isCrossinline, getBoundCallableReferenceReceiver(expression) != null parameter.isCrossinline, getBoundCallableReferenceReceiver(expression) != null
).also { lambda -> ).also { lambda ->
val closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.index) val closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.index)
closureInfo.lambda = lambda closureInfo.functionalArgument = lambda
expressionMap.put(closureInfo.index, lambda) expressionMap.put(closureInfo.index, lambda)
} }
} }
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
class RootInliningContext( class RootInliningContext(
expressionMap: Map<Int, LambdaInfo>, expressionMap: Map<Int, FunctionalArgument>,
state: GenerationState, state: GenerationState,
nameGenerator: NameGenerator, nameGenerator: NameGenerator,
val sourceCompilerForInline: SourceCompilerForInline, val sourceCompilerForInline: SourceCompilerForInline,
@@ -22,7 +22,7 @@ class RootInliningContext(
class RegeneratedClassContext( class RegeneratedClassContext(
parent: InliningContext, parent: InliningContext,
expressionMap: Map<Int, LambdaInfo>, expressionMap: Map<Int, FunctionalArgument>,
state: GenerationState, state: GenerationState,
nameGenerator: NameGenerator, nameGenerator: NameGenerator,
typeRemapper: TypeRemapper, typeRemapper: TypeRemapper,
@@ -36,7 +36,7 @@ class RegeneratedClassContext(
open class InliningContext( open class InliningContext(
val parent: InliningContext?, val parent: InliningContext?,
val expressionMap: Map<Int, LambdaInfo>, val expressionMap: Map<Int, FunctionalArgument>,
val state: GenerationState, val state: GenerationState,
val nameGenerator: NameGenerator, val nameGenerator: NameGenerator,
val typeRemapper: TypeRemapper, val typeRemapper: TypeRemapper,
@@ -19,11 +19,11 @@ package org.jetbrains.kotlin.codegen.inline;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
class InvokeCall { class InvokeCall {
public final LambdaInfo lambdaInfo; public final FunctionalArgument functionalArgument;
public final int finallyDepthShift; public final int finallyDepthShift;
InvokeCall(@Nullable LambdaInfo lambdaInfo, int finallyDepthShift) { InvokeCall(@Nullable FunctionalArgument functionalArgument, int finallyDepthShift) {
this.lambdaInfo = lambdaInfo; this.functionalArgument = functionalArgument;
this.finallyDepthShift = finallyDepthShift; this.finallyDepthShift = finallyDepthShift;
} }
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-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.
*/ */
@@ -35,7 +35,9 @@ import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode import org.jetbrains.org.objectweb.asm.tree.MethodNode
import kotlin.properties.Delegates import kotlin.properties.Delegates
abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : LabelOwner { interface FunctionalArgument
abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgument, LabelOwner {
abstract val isBoundCallableReference: Boolean abstract val isBoundCallableReference: Boolean
@@ -77,6 +79,7 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : LabelOwner {
} }
} }
object CrossinlineLambdaInSuspendContextAsNoInline : FunctionalArgument
class DefaultLambda( class DefaultLambda(
override val lambdaClassType: Type, override val lambdaClassType: Type,
@@ -217,9 +217,9 @@ class MethodInliner(
if (/*INLINE_RUNTIME.equals(owner) &&*/ isInvokeOnLambda(owner, name)) { //TODO add method if (/*INLINE_RUNTIME.equals(owner) &&*/ isInvokeOnLambda(owner, name)) { //TODO add method
assert(!currentInvokes.isEmpty()) assert(!currentInvokes.isEmpty())
val invokeCall = currentInvokes.remove() val invokeCall = currentInvokes.remove()
val info = invokeCall.lambdaInfo val info = invokeCall.functionalArgument
if (info == null) { if (info !is LambdaInfo) {
//noninlinable lambda //noninlinable lambda
super.visitMethodInsn(opcode, owner, name, desc, itf) super.visitMethodInsn(opcode, owner, name, desc, itf)
return return
@@ -263,7 +263,7 @@ class MethodInliner(
listOf(*info.invokeMethod.argumentTypes), valueParameters, invokeParameters, valueParamShift, this, coroutineDesc listOf(*info.invokeMethod.argumentTypes), valueParameters, invokeParameters, valueParamShift, this, coroutineDesc
) )
if (invokeCall.lambdaInfo.invokeMethodDescriptor.valueParameters.isEmpty()) { if (info.invokeMethodDescriptor.valueParameters.isEmpty()) {
// There won't be no parameters processing and line call can be left without actual instructions. // There won't be no parameters processing and line call can be left without actual instructions.
// Note: if function is called on the line with other instructions like 1 + foo(), 'nop' will still be generated. // Note: if function is called on the line with other instructions like 1 + foo(), 'nop' will still be generated.
visitInsn(Opcodes.NOP) visitInsn(Opcodes.NOP)
@@ -447,7 +447,7 @@ class MethodInliner(
override fun visitMethodInsn(opcode: Int, owner: String, name: String, desc: String, itf: Boolean) { override fun visitMethodInsn(opcode: Int, owner: String, name: String, desc: String, itf: Boolean) {
if (DEFAULT_LAMBDA_FAKE_CALL == owner) { if (DEFAULT_LAMBDA_FAKE_CALL == owner) {
val index = name.substringAfter(DEFAULT_LAMBDA_FAKE_CALL).toInt() val index = name.substringAfter(DEFAULT_LAMBDA_FAKE_CALL).toInt()
val lambda = getLambdaIfExists(index) as DefaultLambda val lambda = getFunctionalArgumentIfExists(index) as DefaultLambda
lambda.parameterOffsetsInDefault.zip(lambda.capturedVars).asReversed().forEach { (_, captured) -> lambda.parameterOffsetsInDefault.zip(lambda.capturedVars).asReversed().forEach { (_, captured) ->
val originalBoundReceiverType = lambda.originalBoundReceiverType val originalBoundReceiverType = lambda.originalBoundReceiverType
if (lambda.isBoundCallableReference && AsmUtil.isPrimitive(originalBoundReceiverType)) { if (lambda.isBoundCallableReference && AsmUtil.isPrimitive(originalBoundReceiverType)) {
@@ -522,22 +522,23 @@ class MethodInliner(
val firstParameterIndex = frame.stackSize - paramCount val firstParameterIndex = frame.stackSize - paramCount
if (isInvokeOnLambda(owner, name) /*&& methodInsnNode.owner.equals(INLINE_RUNTIME)*/) { if (isInvokeOnLambda(owner, name) /*&& methodInsnNode.owner.equals(INLINE_RUNTIME)*/) {
val sourceValue = frame.getStack(firstParameterIndex) val sourceValue = frame.getStack(firstParameterIndex)
val lambdaInfo = getLambdaIfExistsAndMarkInstructions(sourceValue, true, instructions, sources, toDelete) val functionalArgument =
invokeCalls.add(InvokeCall(lambdaInfo, currentFinallyDeep)) getFunctionalArgumentIfExistsAndMarkInstructions(sourceValue, true, instructions, sources, toDelete)
invokeCalls.add(InvokeCall(functionalArgument, currentFinallyDeep))
} else if (isSamWrapperConstructorCall(owner, name)) { } else if (isSamWrapperConstructorCall(owner, name)) {
recordTransformation(SamWrapperTransformationInfo(owner, inliningContext, isAlreadyRegenerated(owner))) recordTransformation(SamWrapperTransformationInfo(owner, inliningContext, isAlreadyRegenerated(owner)))
} else if (isAnonymousConstructorCall(owner, name)) { } else if (isAnonymousConstructorCall(owner, name)) {
val lambdaMapping = HashMap<Int, LambdaInfo>() val functionalArgumentMapping = HashMap<Int, FunctionalArgument>()
var offset = 0 var offset = 0
var capturesAnonymousObjectThatMustBeRegenerated = false var capturesAnonymousObjectThatMustBeRegenerated = false
for (i in 0 until paramCount) { for (i in 0 until paramCount) {
val sourceValue = frame.getStack(firstParameterIndex + i) val sourceValue = frame.getStack(firstParameterIndex + i)
val lambdaInfo = getLambdaIfExistsAndMarkInstructions( val functionalArgument = getFunctionalArgumentIfExistsAndMarkInstructions(
sourceValue, false, instructions, sources, toDelete sourceValue, false, instructions, sources, toDelete
) )
if (lambdaInfo != null) { if (functionalArgument != null) {
lambdaMapping.put(offset, lambdaInfo) functionalArgumentMapping.put(offset, functionalArgument)
} else if (i < argTypes.size && isAnonymousClassThatMustBeRegenerated(argTypes[i])) { } else if (i < argTypes.size && isAnonymousClassThatMustBeRegenerated(argTypes[i])) {
capturesAnonymousObjectThatMustBeRegenerated = true capturesAnonymousObjectThatMustBeRegenerated = true
} }
@@ -547,7 +548,7 @@ class MethodInliner(
recordTransformation( recordTransformation(
buildConstructorInvocation( buildConstructorInvocation(
owner, cur.desc, lambdaMapping, awaitClassReification, capturesAnonymousObjectThatMustBeRegenerated owner, cur.desc, functionalArgumentMapping, awaitClassReification, capturesAnonymousObjectThatMustBeRegenerated
) )
) )
awaitClassReification = false awaitClassReification = false
@@ -595,14 +596,16 @@ class MethodInliner(
} }
} }
cur.opcode == Opcodes.POP -> getLambdaIfExistsAndMarkInstructions( cur.opcode == Opcodes.POP -> getFunctionalArgumentIfExistsAndMarkInstructions(
frame.top()!!, frame.top()!!,
true, true,
instructions, instructions,
sources, sources,
toDelete toDelete
)?.let { )?.let {
toDelete.add(cur) if (it is LambdaInfo) {
toDelete.add(cur)
}
} }
cur.opcode == Opcodes.PUTFIELD -> { cur.opcode == Opcodes.PUTFIELD -> {
@@ -620,8 +623,8 @@ class MethodInliner(
) { ) {
val stackTransformations = mutableSetOf<AbstractInsnNode>() val stackTransformations = mutableSetOf<AbstractInsnNode>()
val lambdaInfo = val lambdaInfo =
getLambdaIfExistsAndMarkInstructions(frame.peek(1)!!, false, instructions, sources, stackTransformations) getFunctionalArgumentIfExistsAndMarkInstructions(frame.peek(1)!!, false, instructions, sources, stackTransformations)
if (lambdaInfo != null && stackTransformations.all { it is VarInsnNode }) { if (lambdaInfo is LambdaInfo && stackTransformations.all { it is VarInsnNode }) {
assert(lambdaInfo.lambdaClassType.internalName == nodeRemapper.originalLambdaInternalName) { assert(lambdaInfo.lambdaClassType.internalName == nodeRemapper.originalLambdaInternalName) {
"Wrong bytecode template for contract template: ${lambdaInfo.lambdaClassType.internalName} != ${nodeRemapper.originalLambdaInternalName}" "Wrong bytecode template for contract template: ${lambdaInfo.lambdaClassType.internalName} != ${nodeRemapper.originalLambdaInternalName}"
} }
@@ -812,7 +815,7 @@ class MethodInliner(
private fun buildConstructorInvocation( private fun buildConstructorInvocation(
anonymousType: String, anonymousType: String,
desc: String, desc: String,
lambdaMapping: Map<Int, LambdaInfo>, lambdaMapping: Map<Int, FunctionalArgument>,
needReification: Boolean, needReification: Boolean,
capturesAnonymousObjectThatMustBeRegenerated: Boolean capturesAnonymousObjectThatMustBeRegenerated: Boolean
): AnonymousObjectTransformationInfo { ): AnonymousObjectTransformationInfo {
@@ -845,20 +848,20 @@ class MethodInliner(
return inliningContext.typeRemapper.hasNoAdditionalMapping(owner) return inliningContext.typeRemapper.hasNoAdditionalMapping(owner)
} }
internal fun getLambdaIfExists(insnNode: AbstractInsnNode): LambdaInfo? { internal fun getFunctionalArgumentIfExists(insnNode: AbstractInsnNode): FunctionalArgument? {
return when { return when {
insnNode.opcode == Opcodes.ALOAD -> insnNode.opcode == Opcodes.ALOAD ->
getLambdaIfExists((insnNode as VarInsnNode).`var`) getFunctionalArgumentIfExists((insnNode as VarInsnNode).`var`)
insnNode is FieldInsnNode && insnNode.name.startsWith(CAPTURED_FIELD_FOLD_PREFIX) -> insnNode is FieldInsnNode && insnNode.name.startsWith(CAPTURED_FIELD_FOLD_PREFIX) ->
findCapturedField(insnNode, nodeRemapper).lambda findCapturedField(insnNode, nodeRemapper).functionalArgument
else -> else ->
null null
} }
} }
private fun getLambdaIfExists(varIndex: Int): LambdaInfo? { private fun getFunctionalArgumentIfExists(varIndex: Int): FunctionalArgument? {
if (varIndex < parameters.argsSizeOnStack) { if (varIndex < parameters.argsSizeOnStack) {
return parameters.getParameterByDeclarationSlot(varIndex).lambda return parameters.getParameterByDeclarationSlot(varIndex).functionalArgument
} }
return null return null
} }
@@ -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
@@ -26,37 +15,39 @@ import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
fun MethodInliner.getLambdaIfExistsAndMarkInstructions( fun MethodInliner.getFunctionalArgumentIfExistsAndMarkInstructions(
sourceValue: SourceValue, sourceValue: SourceValue,
processSwap: Boolean, processSwap: Boolean,
insnList: InsnList, insnList: InsnList,
frames: Array<Frame<SourceValue>?>, frames: Array<Frame<SourceValue>?>,
toDelete: MutableSet<AbstractInsnNode> toDelete: MutableSet<AbstractInsnNode>
): LambdaInfo? { ): FunctionalArgument? {
val toDeleteInner = SmartSet.create<AbstractInsnNode>() val toDeleteInner = SmartSet.create<AbstractInsnNode>()
val lambdaSet = SmartSet.create<LambdaInfo?>() val functionalArgumentSet = SmartSet.create<FunctionalArgument?>()
sourceValue.insns.mapTo(lambdaSet) { sourceValue.insns.mapTo(functionalArgumentSet) {
getLambdaIfExistsAndMarkInstructions(it, processSwap, insnList, frames, toDeleteInner) getFunctionalArgumentIfExistsAndMarkInstructions(it, processSwap, insnList, frames, toDeleteInner)
} }
return lambdaSet.singleOrNull()?.also { return functionalArgumentSet.singleOrNull()?.also {
toDelete.addAll(toDeleteInner) if (it is LambdaInfo) {
toDelete.addAll(toDeleteInner)
}
} }
} }
private fun SourceValue.singleOrNullInsn() = insns.singleOrNull() private fun SourceValue.singleOrNullInsn() = insns.singleOrNull()
private fun MethodInliner.getLambdaIfExistsAndMarkInstructions( private fun MethodInliner.getFunctionalArgumentIfExistsAndMarkInstructions(
insnNode: AbstractInsnNode?, insnNode: AbstractInsnNode?,
processSwap: Boolean, processSwap: Boolean,
insnList: InsnList, insnList: InsnList,
frames: Array<Frame<SourceValue>?>, frames: Array<Frame<SourceValue>?>,
toDelete: MutableSet<AbstractInsnNode> toDelete: MutableSet<AbstractInsnNode>
): LambdaInfo? { ): FunctionalArgument? {
if (insnNode == null) return null if (insnNode == null) return null
getLambdaIfExists(insnNode)?.let { getFunctionalArgumentIfExists(insnNode)?.let {
//delete lambda aload instruction //delete lambda aload instruction
toDelete.add(insnNode) toDelete.add(insnNode)
return it return it
@@ -69,7 +60,7 @@ private fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
if (storeIns is VarInsnNode && storeIns.getOpcode() == Opcodes.ASTORE) { if (storeIns is VarInsnNode && storeIns.getOpcode() == Opcodes.ASTORE) {
val frame = frames[insnList.indexOf(storeIns)] ?: return null val frame = frames[insnList.indexOf(storeIns)] ?: return null
val topOfStack = frame.top()!! val topOfStack = frame.top()!!
getLambdaIfExistsAndMarkInstructions(topOfStack, processSwap, insnList, frames, toDelete)?.let { getFunctionalArgumentIfExistsAndMarkInstructions(topOfStack, processSwap, insnList, frames, toDelete)?.let {
//remove intermediate lambda astore, aload instruction: see 'complexStack/simple.1.kt' test //remove intermediate lambda astore, aload instruction: see 'complexStack/simple.1.kt' test
toDelete.add(storeIns) toDelete.add(storeIns)
toDelete.add(insnNode) toDelete.add(insnNode)
@@ -79,7 +70,7 @@ private fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
} else if (processSwap && insnNode.opcode == Opcodes.SWAP) { } else if (processSwap && insnNode.opcode == Opcodes.SWAP) {
val swapFrame = frames[insnList.indexOf(insnNode)] ?: return null val swapFrame = frames[insnList.indexOf(insnNode)] ?: return null
val dispatchReceiver = swapFrame.top()!! val dispatchReceiver = swapFrame.top()!!
getLambdaIfExistsAndMarkInstructions(dispatchReceiver, false, insnList, frames, toDelete)?.let { getFunctionalArgumentIfExistsAndMarkInstructions(dispatchReceiver, false, insnList, frames, toDelete)?.let {
//remove swap instruction (dispatch receiver would be deleted on recursion call): see 'complexStack/simpleExtension.1.kt' test //remove swap instruction (dispatch receiver would be deleted on recursion call): see 'complexStack/simpleExtension.1.kt' test
toDelete.add(insnNode) toDelete.add(insnNode)
return it return it
@@ -29,7 +29,7 @@ public class ParameterInfo {
public final boolean isSkipped; public final boolean isSkipped;
private boolean isCaptured; private boolean isCaptured;
private LambdaInfo lambda; private FunctionalArgument functionalArgument;
//in case when parameter could be extracted from outer context (e.g. from local var) //in case when parameter could be extracted from outer context (e.g. from local var)
private StackValue remapValue; private StackValue remapValue;
@@ -68,13 +68,13 @@ public class ParameterInfo {
} }
@Nullable @Nullable
public LambdaInfo getLambda() { public FunctionalArgument getFunctionalArgument() {
return lambda; return functionalArgument;
} }
@NotNull @NotNull
public ParameterInfo setLambda(@Nullable LambdaInfo lambda) { public ParameterInfo setFunctionalArgument(@Nullable FunctionalArgument functionalArgument) {
this.lambda = lambda; this.functionalArgument = functionalArgument;
return this; return this;
} }
@@ -38,7 +38,7 @@ class ParametersBuilder private constructor() {
fun addCapturedParam(original: CapturedParamInfo, newFieldName: String): CapturedParamInfo { fun addCapturedParam(original: CapturedParamInfo, newFieldName: String): CapturedParamInfo {
val info = CapturedParamInfo(original.desc, newFieldName, original.isSkipped, nextParameterOffset, original.index) val info = CapturedParamInfo(original.desc, newFieldName, original.isSkipped, nextParameterOffset, original.index)
info.lambda = original.lambda info.functionalArgument = original.functionalArgument
return addParameter(info) return addParameter(info)
} }
@@ -62,7 +62,7 @@ class ParametersBuilder private constructor() {
CapturedParamDesc(containingLambdaType, fieldName, type), newFieldName, skipped, nextParameterOffset, original?.index ?: -1 CapturedParamDesc(containingLambdaType, fieldName, type), newFieldName, skipped, nextParameterOffset, original?.index ?: -1
) )
if (original != null) { if (original != null) {
info.lambda = original.lambda info.functionalArgument = original.functionalArgument
} }
return addParameter(info) return addParameter(info)
} }
@@ -116,7 +116,7 @@ class ParametersBuilder private constructor() {
val builder = newBuilder() val builder = newBuilder()
if (inlineLambda?.hasDispatchReceiver != false && !isStatic) { if (inlineLambda?.hasDispatchReceiver != false && !isStatic) {
//skipped this for inlined lambda cause it will be removed //skipped this for inlined lambda cause it will be removed
builder.addThis(objectType, inlineLambda != null).lambda = inlineLambda builder.addThis(objectType, inlineLambda != null).functionalArgument = inlineLambda
} }
for (type in Type.getArgumentTypes(descriptor)) { for (type in Type.getArgumentTypes(descriptor)) {
@@ -75,7 +75,7 @@ class RegeneratedLambdaFieldRemapper(
val result = StackValue.field( val result = StackValue.field(
if (field.isSkipped) if (field.isSkipped && field.functionalArgument is LambdaInfo)
Type.getObjectType(parent!!.parent!!.newLambdaInternalName) Type.getObjectType(parent!!.parent!!.newLambdaInternalName)
else else
field.getType(), field.getType(),
@@ -67,7 +67,7 @@ class WhenMappingTransformationInfo(
class AnonymousObjectTransformationInfo internal constructor( class AnonymousObjectTransformationInfo internal constructor(
override val oldClassName: String, override val oldClassName: String,
private val needReification: Boolean, private val needReification: Boolean,
val lambdasToInline: Map<Int, LambdaInfo>, val functionalArguments: Map<Int, FunctionalArgument>,
private val capturedOuterRegenerated: Boolean, private val capturedOuterRegenerated: Boolean,
private val alreadyRegenerated: Boolean, private val alreadyRegenerated: Boolean,
val constructorDesc: String?, val constructorDesc: String?,
@@ -99,7 +99,7 @@ class AnonymousObjectTransformationInfo internal constructor(
override fun shouldRegenerate(sameModule: Boolean): Boolean = override fun shouldRegenerate(sameModule: Boolean): Boolean =
!alreadyRegenerated && !alreadyRegenerated &&
(!lambdasToInline.isEmpty() || !sameModule || capturedOuterRegenerated || needReification || capturesAnonymousObjectThatMustBeRegenerated) (!functionalArguments.isEmpty() || !sameModule || capturedOuterRegenerated || needReification || capturesAnonymousObjectThatMustBeRegenerated)
override fun canRemoveAfterTransformation(): Boolean { override fun canRemoveAfterTransformation(): Boolean {
// Note: It is unsafe to remove anonymous class that is referenced by GETSTATIC within lambda // Note: It is unsafe to remove anonymous class that is referenced by GETSTATIC within lambda
@@ -18,7 +18,6 @@ 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
import org.jetbrains.kotlin.utils.sure
import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode import org.jetbrains.org.objectweb.asm.tree.MethodNode
@@ -38,14 +37,14 @@ class CoroutineTransformer(
// See innerObjectRetransformation.kt // See innerObjectRetransformation.kt
if (inliningContext.callSiteInfo.isInlineOrInsideInline) return false if (inliningContext.callSiteInfo.isInlineOrInsideInline) return false
if (isContinuationNotLambda()) return false if (isContinuationNotLambda()) return false
val crossinlineParam = crossinlineLambda() ?: return false val crossinlineParam = crossinlineLambda()
if (inliningContext.isInliningLambda && !inliningContext.isContinuation) return false if (inliningContext.isInliningLambda && !inliningContext.isContinuation) return false
return when { return when {
isSuspendFunction(node) -> true isSuspendFunction(node) -> true
isSuspendLambda(node) -> { isSuspendLambda(node) -> {
if (isStateMachine(node)) return false if (isStateMachine(node)) return false
val functionDescriptor = val functionDescriptor =
crossinlineParam.invokeMethodDescriptor.containingDeclaration as? FunctionDescriptor ?: return true crossinlineParam?.invokeMethodDescriptor?.containingDeclaration as? FunctionDescriptor ?: return true
!functionDescriptor.isInline !functionDescriptor.isInline
} }
else -> false else -> false
@@ -66,9 +65,11 @@ class CoroutineTransformer(
private fun isSuspendLambda(node: MethodNode) = isResumeImpl(node) private fun isSuspendLambda(node: MethodNode) = isResumeImpl(node)
fun newMethod(node: MethodNode): DeferredMethodVisitor { fun newMethod(node: MethodNode): DeferredMethodVisitor {
val element = crossinlineLambda()?.functionWithBodyOrCallableReference.sure { // Find ANY element to report error about suspension point in monitor on.
"crossinline lambda should have element" val element = crossinlineLambda()?.functionWithBodyOrCallableReference
} ?: inliningContext.root.sourceCompilerForInline.callElement as? KtElement
?: error("crossinline lambda should have element")
return when { return when {
isResumeImpl(node) -> { isResumeImpl(node) -> {
assert(!isStateMachine(node)) { assert(!isStateMachine(node)) {
@@ -25,7 +25,7 @@ class NewJavaField(val name: String, val type: Type, val skip: Boolean)
fun getNewFieldsToGenerate(params: List<CapturedParamInfo>): List<NewJavaField> { fun getNewFieldsToGenerate(params: List<CapturedParamInfo>): List<NewJavaField> {
return params.filter { return params.filter {
//not inlined //not inlined
it.lambda == null it.functionalArgument !is LambdaInfo
}.map { }.map {
NewJavaField(it.newFieldName, it.type, it.isSkipInConstructor) NewJavaField(it.newFieldName, it.type, it.isSkipInConstructor)
} }
@@ -99,7 +99,7 @@ class IrInlineCodegen(
parameter.type.isExtensionFunctionType parameter.type.isExtensionFunctionType
).also { lambda -> ).also { lambda ->
val closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.index) val closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.index)
closureInfo.lambda = lambda closureInfo.functionalArgument = lambda
expressionMap[closureInfo.index] = lambda expressionMap[closureInfo.index] = lambda
} }
} }
@@ -0,0 +1,64 @@
// IGNORE_BACKEND: JVM_IR
// COMMON_COROUTINES_TEST
// WITH_RUNTIME
// WITH_COROUTINES
// CHECK_STATE_MACHINE
// FILE: inline.kt
class MyDeferred<T>(val t: suspend () -> T) {
suspend fun await() = t()
}
fun <T> async(block: suspend () -> T) = MyDeferred(block)
inline fun <T, R> map(source: MyDeferred<T>, crossinline mapper: (T) -> R) =
async {
mapper(source.await())
}
inline fun <T, R1, R2> map2(source: MyDeferred<T>, crossinline mapper1: (T) -> R1, crossinline mapper2: (R1) -> R2) =
async {
val c = suspend {
mapper1(source.await())
}
mapper2(c())
}
inline fun <T, R1, R2, R3> map3(source: MyDeferred<T>, crossinline mapper1: (T) -> R1, crossinline mapper2: (R1) -> R2, crossinline mapper3: (R2) -> R3) =
async {
val c = suspend {
val c = suspend {
mapper1(source.await())
}
mapper2(c())
}
mapper3(c())
}
// FILE: box.kt
import helpers.*
import COROUTINES_PACKAGE.*
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
val source = MyDeferred { 1 }
var result = -1
builder {
result = map(source) { it + 2 }.await()
}
if (result != 3) return "FAIL 1 $result"
builder {
result = map2(source, { it + 2 }, { it + 3 }).await()
}
if (result != 6) return "FAIL 2 $result"
builder {
result = map3(source, { it + 2 }, { it + 3 }, { it + 4 }).await()
}
if (result != 10) return "FAIL 3 $result"
return "OK"
}
@@ -0,0 +1,61 @@
// IGNORE_BACKEND: JVM_IR
// COMMON_COROUTINES_TEST
// WITH_RUNTIME
// WITH_COROUTINES
// CHECK_STATE_MACHINE
// FILE: inline.kt
import helpers.*
import COROUTINES_PACKAGE.*
interface SuspendRunnable {
suspend fun run()
}
fun runSuspend(c: suspend () -> Unit) {
c.startCoroutine(CheckStateMachineContinuation)
}
inline suspend fun inlineMe(crossinline c1: suspend () -> Unit) {
object : SuspendRunnable {
override suspend fun run() {
c1()
}
}.run()
StateMachineChecker.check(2)
StateMachineChecker.reset()
runSuspend {
object : SuspendRunnable {
override suspend fun run() {
StateMachineChecker.suspendHere()
StateMachineChecker.suspendHere()
}
}.run()
StateMachineChecker.check(2)
}
}
// FILE: box.kt
// COMMON_COROUTINES_TEST
import helpers.*
import COROUTINES_PACKAGE.*
fun builder(c: suspend () -> Unit) {
c.startCoroutine(CheckStateMachineContinuation)
}
fun box(): String {
builder {
inlineMe {
StateMachineChecker.suspendHere()
StateMachineChecker.suspendHere()
}
}
return "OK"
}
@@ -0,0 +1,69 @@
// IGNORE_BACKEND: JVM_IR
// COMMON_COROUTINES_TEST
// WITH_RUNTIME
// WITH_COROUTINES
// CHECK_STATE_MACHINE
// FILE: inline.kt
import helpers.*
interface SuspendRunnable {
suspend fun run()
suspend fun ownIndependentInline()
}
inline fun inlineMe(crossinline c1: suspend () -> Unit) =
object : SuspendRunnable {
override suspend fun run() {
c1()
c1()
}
override suspend fun ownIndependentInline() {
inlineMe2 {
StateMachineChecker.suspendHere()
StateMachineChecker.suspendHere()
}.ownIndependentInline()
}
}
inline fun inlineMe2(crossinline c2: suspend () -> Unit): SuspendRunnable =
object : SuspendRunnable {
override suspend fun run() {
}
override suspend fun ownIndependentInline() {
c2()
c2()
}
}
// FILE: box.kt
// COMMON_COROUTINES_TEST
import helpers.*
import COROUTINES_PACKAGE.*
fun builder(c: suspend () -> Unit) {
c.startCoroutine(CheckStateMachineContinuation)
}
fun box(): String {
val r = inlineMe {
StateMachineChecker.suspendHere()
StateMachineChecker.suspendHere()
}
builder {
r.run()
}
StateMachineChecker.check(numberOfSuspensions = 4)
StateMachineChecker.reset()
builder {
r.ownIndependentInline()
}
StateMachineChecker.check(numberOfSuspensions = 4)
return "OK"
}
@@ -0,0 +1,60 @@
// IGNORE_BACKEND: JVM_IR
// COMMON_COROUTINES_TEST
// WITH_RUNTIME
// WITH_COROUTINES
// CHECK_STATE_MACHINE
// FILE: inline.kt
import helpers.*
interface SuspendRunnable {
suspend fun run()
suspend fun run2()
}
inline fun inlineMe(crossinline c1: suspend () -> Unit, crossinline c2: suspend () -> Unit) =
object : SuspendRunnable {
override suspend fun run() {
c1() // TODO: Double this call, when suspend markers are generated for inline and crossinline lambdas
}
override suspend fun run2() {
c2()
}
}
inline fun inlineMe2(crossinline c1: suspend () -> Unit) =
inlineMe(c1) {
StateMachineChecker.suspendHere()
StateMachineChecker.suspendHere()
}
// FILE: box.kt
// COMMON_COROUTINES_TEST
import helpers.*
import COROUTINES_PACKAGE.*
fun builder(c: suspend () -> Unit) {
c.startCoroutine(CheckStateMachineContinuation)
}
fun box(): String {
val r = inlineMe2 {
StateMachineChecker.suspendHere()
StateMachineChecker.suspendHere()
}
builder {
r.run()
}
StateMachineChecker.check(numberOfSuspensions = 2)
StateMachineChecker.reset()
builder {
r.run2()
}
StateMachineChecker.check(numberOfSuspensions = 2)
return "OK"
}
@@ -0,0 +1,36 @@
// IGNORE_BACKEND: JVM_IR
// COMMON_COROUTINES_TEST
// WITH_RUNTIME
// WITH_COROUTINES
// CHECK_STATE_MACHINE
// FILE: inline.kt
import helpers.*
inline fun inlineMe(crossinline c: suspend () -> Unit) = suspend { c(); c() }
inline fun inlineMe2(crossinline c: suspend () -> Unit) = inlineMe { c(); c() }
// FILE: box.kt
// COMMON_COROUTINES_TEST
import helpers.*
import COROUTINES_PACKAGE.*
fun builder(c: suspend () -> Unit) {
c.startCoroutine(CheckStateMachineContinuation)
}
fun box(): String {
val r = inlineMe2 {
StateMachineChecker.suspendHere()
StateMachineChecker.suspendHere()
}
builder {
r()
}
StateMachineChecker.check(numberOfSuspensions = 8)
return "OK"
}
@@ -3540,6 +3540,16 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt", "kotlin.coroutines");
} }
@TestMetadata("nonSuspendCrossinline.kt")
public void testNonSuspendCrossinline_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/nonSuspendCrossinline.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("nonSuspendCrossinline.kt")
public void testNonSuspendCrossinline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/nonSuspendCrossinline.kt", "kotlin.coroutines");
}
@TestMetadata("returnValue.kt") @TestMetadata("returnValue.kt")
public void testReturnValue_1_2() throws Exception { public void testReturnValue_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/returnValue.kt", "kotlin.coroutines.experimental"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/returnValue.kt", "kotlin.coroutines.experimental");
@@ -3761,6 +3771,26 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/stateMachine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/stateMachine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
} }
@TestMetadata("crossingCoroutineBoundaries.kt")
public void testCrossingCoroutineBoundaries_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/crossingCoroutineBoundaries.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("crossingCoroutineBoundaries.kt")
public void testCrossingCoroutineBoundaries_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/crossingCoroutineBoundaries.kt", "kotlin.coroutines");
}
@TestMetadata("independentInline.kt")
public void testIndependentInline_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/independentInline.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("independentInline.kt")
public void testIndependentInline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/independentInline.kt", "kotlin.coroutines");
}
@TestMetadata("innerLambdaInsideLambda.kt") @TestMetadata("innerLambdaInsideLambda.kt")
public void testInnerLambdaInsideLambda_1_2() throws Exception { public void testInnerLambdaInsideLambda_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaInsideLambda.kt", "kotlin.coroutines.experimental"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaInsideLambda.kt", "kotlin.coroutines.experimental");
@@ -3910,6 +3940,26 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
public void testOneInlineTwoCaptures_1_3() throws Exception { public void testOneInlineTwoCaptures_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/oneInlineTwoCaptures.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/oneInlineTwoCaptures.kt", "kotlin.coroutines");
} }
@TestMetadata("passParameterLambda.kt")
public void testPassParameterLambda_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameterLambda.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("passParameterLambda.kt")
public void testPassParameterLambda_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameterLambda.kt", "kotlin.coroutines");
}
@TestMetadata("passParameter.kt")
public void testPassParameter_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameter.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("passParameter.kt")
public void testPassParameter_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameter.kt", "kotlin.coroutines");
}
} }
} }
@@ -3540,6 +3540,16 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt", "kotlin.coroutines");
} }
@TestMetadata("nonSuspendCrossinline.kt")
public void testNonSuspendCrossinline_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/nonSuspendCrossinline.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("nonSuspendCrossinline.kt")
public void testNonSuspendCrossinline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/nonSuspendCrossinline.kt", "kotlin.coroutines");
}
@TestMetadata("returnValue.kt") @TestMetadata("returnValue.kt")
public void testReturnValue_1_2() throws Exception { public void testReturnValue_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/returnValue.kt", "kotlin.coroutines.experimental"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/returnValue.kt", "kotlin.coroutines.experimental");
@@ -3761,6 +3771,26 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/stateMachine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/stateMachine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
} }
@TestMetadata("crossingCoroutineBoundaries.kt")
public void testCrossingCoroutineBoundaries_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/crossingCoroutineBoundaries.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("crossingCoroutineBoundaries.kt")
public void testCrossingCoroutineBoundaries_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/crossingCoroutineBoundaries.kt", "kotlin.coroutines");
}
@TestMetadata("independentInline.kt")
public void testIndependentInline_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/independentInline.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("independentInline.kt")
public void testIndependentInline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/independentInline.kt", "kotlin.coroutines");
}
@TestMetadata("innerLambdaInsideLambda.kt") @TestMetadata("innerLambdaInsideLambda.kt")
public void testInnerLambdaInsideLambda_1_2() throws Exception { public void testInnerLambdaInsideLambda_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaInsideLambda.kt", "kotlin.coroutines.experimental"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaInsideLambda.kt", "kotlin.coroutines.experimental");
@@ -3910,6 +3940,26 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
public void testOneInlineTwoCaptures_1_3() throws Exception { public void testOneInlineTwoCaptures_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/oneInlineTwoCaptures.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/oneInlineTwoCaptures.kt", "kotlin.coroutines");
} }
@TestMetadata("passParameterLambda.kt")
public void testPassParameterLambda_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameterLambda.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("passParameterLambda.kt")
public void testPassParameterLambda_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameterLambda.kt", "kotlin.coroutines");
}
@TestMetadata("passParameter.kt")
public void testPassParameter_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameter.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("passParameter.kt")
public void testPassParameter_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameter.kt", "kotlin.coroutines");
}
} }
} }
@@ -3540,6 +3540,16 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt", "kotlin.coroutines");
} }
@TestMetadata("nonSuspendCrossinline.kt")
public void testNonSuspendCrossinline_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/nonSuspendCrossinline.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("nonSuspendCrossinline.kt")
public void testNonSuspendCrossinline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/nonSuspendCrossinline.kt", "kotlin.coroutines");
}
@TestMetadata("returnValue.kt") @TestMetadata("returnValue.kt")
public void testReturnValue_1_2() throws Exception { public void testReturnValue_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/returnValue.kt", "kotlin.coroutines.experimental"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/returnValue.kt", "kotlin.coroutines.experimental");
@@ -3761,6 +3771,26 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/stateMachine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/stateMachine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
} }
@TestMetadata("crossingCoroutineBoundaries.kt")
public void testCrossingCoroutineBoundaries_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/crossingCoroutineBoundaries.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("crossingCoroutineBoundaries.kt")
public void testCrossingCoroutineBoundaries_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/crossingCoroutineBoundaries.kt", "kotlin.coroutines");
}
@TestMetadata("independentInline.kt")
public void testIndependentInline_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/independentInline.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("independentInline.kt")
public void testIndependentInline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/independentInline.kt", "kotlin.coroutines");
}
@TestMetadata("innerLambdaInsideLambda.kt") @TestMetadata("innerLambdaInsideLambda.kt")
public void testInnerLambdaInsideLambda_1_2() throws Exception { public void testInnerLambdaInsideLambda_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaInsideLambda.kt", "kotlin.coroutines.experimental"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaInsideLambda.kt", "kotlin.coroutines.experimental");
@@ -3910,6 +3940,26 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
public void testOneInlineTwoCaptures_1_3() throws Exception { public void testOneInlineTwoCaptures_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/oneInlineTwoCaptures.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/oneInlineTwoCaptures.kt", "kotlin.coroutines");
} }
@TestMetadata("passParameterLambda.kt")
public void testPassParameterLambda_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameterLambda.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("passParameterLambda.kt")
public void testPassParameterLambda_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameterLambda.kt", "kotlin.coroutines");
}
@TestMetadata("passParameter.kt")
public void testPassParameter_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameter.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("passParameter.kt")
public void testPassParameter_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameter.kt", "kotlin.coroutines");
}
} }
} }
@@ -98,6 +98,11 @@ public class IrInlineSuspendTestsGenerated extends AbstractIrInlineSuspendTests
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt", "kotlin.coroutines");
} }
@TestMetadata("nonSuspendCrossinline.kt")
public void testNonSuspendCrossinline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/nonSuspendCrossinline.kt", "kotlin.coroutines");
}
@TestMetadata("returnValue.kt") @TestMetadata("returnValue.kt")
public void testReturnValue_1_3() throws Exception { public void testReturnValue_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/returnValue.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/returnValue.kt", "kotlin.coroutines");
@@ -259,6 +264,16 @@ public class IrInlineSuspendTestsGenerated extends AbstractIrInlineSuspendTests
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/stateMachine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/stateMachine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
} }
@TestMetadata("crossingCoroutineBoundaries.kt")
public void testCrossingCoroutineBoundaries_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/crossingCoroutineBoundaries.kt", "kotlin.coroutines");
}
@TestMetadata("independentInline.kt")
public void testIndependentInline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/independentInline.kt", "kotlin.coroutines");
}
@TestMetadata("innerLambdaInsideLambda.kt") @TestMetadata("innerLambdaInsideLambda.kt")
public void testInnerLambdaInsideLambda_1_3() throws Exception { public void testInnerLambdaInsideLambda_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaInsideLambda.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaInsideLambda.kt", "kotlin.coroutines");
@@ -333,5 +348,15 @@ public class IrInlineSuspendTestsGenerated extends AbstractIrInlineSuspendTests
public void testOneInlineTwoCaptures_1_3() throws Exception { public void testOneInlineTwoCaptures_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/oneInlineTwoCaptures.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/oneInlineTwoCaptures.kt", "kotlin.coroutines");
} }
@TestMetadata("passParameterLambda.kt")
public void testPassParameterLambda_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameterLambda.kt", "kotlin.coroutines");
}
@TestMetadata("passParameter.kt")
public void testPassParameter_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameter.kt", "kotlin.coroutines");
}
} }
} }
@@ -158,6 +158,16 @@ public class InlineSuspendTestsGenerated extends AbstractInlineSuspendTests {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt", "kotlin.coroutines");
} }
@TestMetadata("nonSuspendCrossinline.kt")
public void testNonSuspendCrossinline_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/nonSuspendCrossinline.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("nonSuspendCrossinline.kt")
public void testNonSuspendCrossinline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/nonSuspendCrossinline.kt", "kotlin.coroutines");
}
@TestMetadata("returnValue.kt") @TestMetadata("returnValue.kt")
public void testReturnValue_1_2() throws Exception { public void testReturnValue_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/returnValue.kt", "kotlin.coroutines.experimental"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/returnValue.kt", "kotlin.coroutines.experimental");
@@ -379,6 +389,26 @@ public class InlineSuspendTestsGenerated extends AbstractInlineSuspendTests {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/stateMachine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/stateMachine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
} }
@TestMetadata("crossingCoroutineBoundaries.kt")
public void testCrossingCoroutineBoundaries_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/crossingCoroutineBoundaries.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("crossingCoroutineBoundaries.kt")
public void testCrossingCoroutineBoundaries_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/crossingCoroutineBoundaries.kt", "kotlin.coroutines");
}
@TestMetadata("independentInline.kt")
public void testIndependentInline_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/independentInline.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("independentInline.kt")
public void testIndependentInline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/independentInline.kt", "kotlin.coroutines");
}
@TestMetadata("innerLambdaInsideLambda.kt") @TestMetadata("innerLambdaInsideLambda.kt")
public void testInnerLambdaInsideLambda_1_2() throws Exception { public void testInnerLambdaInsideLambda_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaInsideLambda.kt", "kotlin.coroutines.experimental"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaInsideLambda.kt", "kotlin.coroutines.experimental");
@@ -528,5 +558,25 @@ public class InlineSuspendTestsGenerated extends AbstractInlineSuspendTests {
public void testOneInlineTwoCaptures_1_3() throws Exception { public void testOneInlineTwoCaptures_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/oneInlineTwoCaptures.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/oneInlineTwoCaptures.kt", "kotlin.coroutines");
} }
@TestMetadata("passParameterLambda.kt")
public void testPassParameterLambda_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameterLambda.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("passParameterLambda.kt")
public void testPassParameterLambda_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameterLambda.kt", "kotlin.coroutines");
}
@TestMetadata("passParameter.kt")
public void testPassParameter_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameter.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("passParameter.kt")
public void testPassParameter_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/passParameter.kt", "kotlin.coroutines");
}
} }
} }