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,
METHOD_HANDLE_IN_DEFAULT,
CAPTURED,
DEFAULT_LAMBDA_CAPTURED_PARAMETER
DEFAULT_LAMBDA_CAPTURED_PARAMETER,
NON_INLINEABLE_CALLED_IN_SUSPEND
}
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.
*/
@@ -726,6 +726,9 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
if (variableDescriptor instanceof ValueParameterDescriptor &&
((ValueParameterDescriptor) variableDescriptor).isCrossinline()) {
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--) {
Boolean alreadyPutValue = bindingTrace.getBindingContext()
.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.
*/
@@ -60,6 +60,9 @@ public class CodegenBinding {
public static final WritableSlice<FunctionDescriptor, Boolean> CAPTURES_CROSSINLINE_LAMBDA =
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 =
Slices.createSimpleSlice();
@@ -343,7 +343,7 @@ class AnonymousObjectTransformer(
for (info in constructorAdditionalFakeParams) {
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)
val composed = StackValue.field(
fake.getType(),
@@ -415,7 +415,7 @@ class AnonymousObjectTransformer(
): List<CapturedParamInfo> {
val capturedLambdas = LinkedHashSet<LambdaInfo>() //captured var of inlined parameter
val constructorAdditionalFakeParams = ArrayList<CapturedParamInfo>()
val indexToLambda = transformationInfo.lambdasToInline
val indexToFunctionalArgument = transformationInfo.functionalArguments
val capturedParams = HashSet<Int>()
//load captured parameters and patch instruction list
@@ -425,18 +425,18 @@ class AnonymousObjectTransformer(
val fieldName = fieldNode.name
val parameterAload = fieldNode.previous as VarInsnNode
val varIndex = parameterAload.`var`
val lambdaInfo = indexToLambda[varIndex]
val newFieldName = if (isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToLambda.values))
val functionalArgument = indexToFunctionalArgument[varIndex]
val newFieldName = if (isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToFunctionalArgument.values))
getNewFieldName(fieldName, true)
else
fieldName
val info = capturedParamBuilder.addCapturedParam(
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.lambda = lambdaInfo
capturedLambdas.add(lambdaInfo)
info.functionalArgument = functionalArgument
if (functionalArgument is LambdaInfo) {
capturedLambdas.add(functionalArgument)
}
constructorAdditionalFakeParams.add(info)
capturedParams.add(varIndex)
@@ -451,9 +451,9 @@ class AnonymousObjectTransformer(
val paramTypes = transformationInfo.constructorDesc?.let { Type.getArgumentTypes(it) } ?: emptyArray()
for (type in paramTypes) {
val info = indexToLambda[constructorParamBuilder.nextParameterOffset]
val parameterInfo = constructorParamBuilder.addNextParameter(type, info != null)
parameterInfo.lambda = info
val info = indexToFunctionalArgument[constructorParamBuilder.nextParameterOffset]
val parameterInfo = constructorParamBuilder.addNextParameter(type, info is LambdaInfo)
parameterInfo.functionalArgument = info
if (capturedParams.contains(parameterInfo.index)) {
parameterInfo.isCaptured = true
} else {
@@ -519,9 +519,9 @@ class AnonymousObjectTransformer(
return constructorAdditionalFakeParams
}
private fun shouldRenameThis0(parentFieldRemapper: FieldRemapper, values: Collection<LambdaInfo>): Boolean {
private fun shouldRenameThis0(parentFieldRemapper: FieldRemapper, values: Collection<FunctionalArgument>): Boolean {
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
}
@@ -65,7 +65,7 @@ public class CapturedParamInfo extends ParameterInfo {
CapturedParamInfo result = new CapturedParamInfo(
desc, newFieldName, isSkipped, getIndex(), getRemapValue(), skipInConstructor, newDeclarationIndex
);
result.setLambda(getLambda());
result.setFunctionalArgument(getFunctionalArgument());
result.setSynthetic(synthetic);
return result;
}
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.context.ClosureContext
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructors
import org.jetbrains.kotlin.codegen.state.GenerationState
@@ -83,7 +84,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
protected val invocationParamBuilder = ParametersBuilder.newBuilder()
protected val expressionMap = linkedMapOf<Int, LambdaInfo>()
protected val expressionMap = linkedMapOf<Int, FunctionalArgument>()
var activeLambda: LambdaInfo? = null
protected set
@@ -234,7 +235,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
extractDefaultLambdaOffsetAndDescriptor(jvmSignature, functionDescriptor)
)
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)
assert(prev == null) { "Lambda with offset ${lambda.offset} already exists: $prev" }
}
@@ -310,7 +311,9 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
private fun generateClosuresBodies() {
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)
} else {
info = invocationParamBuilder.addNextValueParameter(jvmType, false, remappedValue, parameterIndex)
if (kind == ValueKind.NON_INLINEABLE_CALLED_IN_SUSPEND) {
info.functionalArgument = CrossinlineLambdaInSuspendContextAsNoInline
}
}
recordParameterValueInLocalVal(
@@ -395,8 +401,10 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
private fun putClosureParametersOnStack() {
for (next in expressionMap.values) {
//closure parameters for bounded callable references are generated inplace
if (next is ExpressionLambda && next.isBoundCallableReference) continue
putClosureParametersOnStack(next, null)
if (next is LambdaInfo) {
if (next is ExpressionLambda && next.isBoundCallableReference) continue
putClosureParametersOnStack(next, null)
}
}
}
@@ -730,10 +738,18 @@ class PsiInlineCodegen(
}
} else {
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 {
val ktLambda = KtPsiUtil.deparenthesize(expression)
assert(isInlinableParameterExpression(ktLambda)) { "Couldn't find inline expression in ${expression.text}" }
@@ -743,7 +759,7 @@ class PsiInlineCodegen(
parameter.isCrossinline, getBoundCallableReferenceReceiver(expression) != null
).also { lambda ->
val closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.index)
closureInfo.lambda = lambda
closureInfo.functionalArgument = lambda
expressionMap.put(closureInfo.index, lambda)
}
}
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.state.GenerationState
class RootInliningContext(
expressionMap: Map<Int, LambdaInfo>,
expressionMap: Map<Int, FunctionalArgument>,
state: GenerationState,
nameGenerator: NameGenerator,
val sourceCompilerForInline: SourceCompilerForInline,
@@ -22,7 +22,7 @@ class RootInliningContext(
class RegeneratedClassContext(
parent: InliningContext,
expressionMap: Map<Int, LambdaInfo>,
expressionMap: Map<Int, FunctionalArgument>,
state: GenerationState,
nameGenerator: NameGenerator,
typeRemapper: TypeRemapper,
@@ -36,7 +36,7 @@ class RegeneratedClassContext(
open class InliningContext(
val parent: InliningContext?,
val expressionMap: Map<Int, LambdaInfo>,
val expressionMap: Map<Int, FunctionalArgument>,
val state: GenerationState,
val nameGenerator: NameGenerator,
val typeRemapper: TypeRemapper,
@@ -19,11 +19,11 @@ package org.jetbrains.kotlin.codegen.inline;
import org.jetbrains.annotations.Nullable;
class InvokeCall {
public final LambdaInfo lambdaInfo;
public final FunctionalArgument functionalArgument;
public final int finallyDepthShift;
InvokeCall(@Nullable LambdaInfo lambdaInfo, int finallyDepthShift) {
this.lambdaInfo = lambdaInfo;
InvokeCall(@Nullable FunctionalArgument functionalArgument, int finallyDepthShift) {
this.functionalArgument = functionalArgument;
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.
*/
@@ -35,7 +35,9 @@ import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
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
@@ -77,6 +79,7 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : LabelOwner {
}
}
object CrossinlineLambdaInSuspendContextAsNoInline : FunctionalArgument
class DefaultLambda(
override val lambdaClassType: Type,
@@ -217,9 +217,9 @@ class MethodInliner(
if (/*INLINE_RUNTIME.equals(owner) &&*/ isInvokeOnLambda(owner, name)) { //TODO add method
assert(!currentInvokes.isEmpty())
val invokeCall = currentInvokes.remove()
val info = invokeCall.lambdaInfo
val info = invokeCall.functionalArgument
if (info == null) {
if (info !is LambdaInfo) {
//noninlinable lambda
super.visitMethodInsn(opcode, owner, name, desc, itf)
return
@@ -263,7 +263,7 @@ class MethodInliner(
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.
// Note: if function is called on the line with other instructions like 1 + foo(), 'nop' will still be generated.
visitInsn(Opcodes.NOP)
@@ -447,7 +447,7 @@ class MethodInliner(
override fun visitMethodInsn(opcode: Int, owner: String, name: String, desc: String, itf: Boolean) {
if (DEFAULT_LAMBDA_FAKE_CALL == owner) {
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) ->
val originalBoundReceiverType = lambda.originalBoundReceiverType
if (lambda.isBoundCallableReference && AsmUtil.isPrimitive(originalBoundReceiverType)) {
@@ -522,22 +522,23 @@ class MethodInliner(
val firstParameterIndex = frame.stackSize - paramCount
if (isInvokeOnLambda(owner, name) /*&& methodInsnNode.owner.equals(INLINE_RUNTIME)*/) {
val sourceValue = frame.getStack(firstParameterIndex)
val lambdaInfo = getLambdaIfExistsAndMarkInstructions(sourceValue, true, instructions, sources, toDelete)
invokeCalls.add(InvokeCall(lambdaInfo, currentFinallyDeep))
val functionalArgument =
getFunctionalArgumentIfExistsAndMarkInstructions(sourceValue, true, instructions, sources, toDelete)
invokeCalls.add(InvokeCall(functionalArgument, currentFinallyDeep))
} else if (isSamWrapperConstructorCall(owner, name)) {
recordTransformation(SamWrapperTransformationInfo(owner, inliningContext, isAlreadyRegenerated(owner)))
} else if (isAnonymousConstructorCall(owner, name)) {
val lambdaMapping = HashMap<Int, LambdaInfo>()
val functionalArgumentMapping = HashMap<Int, FunctionalArgument>()
var offset = 0
var capturesAnonymousObjectThatMustBeRegenerated = false
for (i in 0 until paramCount) {
val sourceValue = frame.getStack(firstParameterIndex + i)
val lambdaInfo = getLambdaIfExistsAndMarkInstructions(
val functionalArgument = getFunctionalArgumentIfExistsAndMarkInstructions(
sourceValue, false, instructions, sources, toDelete
)
if (lambdaInfo != null) {
lambdaMapping.put(offset, lambdaInfo)
if (functionalArgument != null) {
functionalArgumentMapping.put(offset, functionalArgument)
} else if (i < argTypes.size && isAnonymousClassThatMustBeRegenerated(argTypes[i])) {
capturesAnonymousObjectThatMustBeRegenerated = true
}
@@ -547,7 +548,7 @@ class MethodInliner(
recordTransformation(
buildConstructorInvocation(
owner, cur.desc, lambdaMapping, awaitClassReification, capturesAnonymousObjectThatMustBeRegenerated
owner, cur.desc, functionalArgumentMapping, awaitClassReification, capturesAnonymousObjectThatMustBeRegenerated
)
)
awaitClassReification = false
@@ -595,14 +596,16 @@ class MethodInliner(
}
}
cur.opcode == Opcodes.POP -> getLambdaIfExistsAndMarkInstructions(
cur.opcode == Opcodes.POP -> getFunctionalArgumentIfExistsAndMarkInstructions(
frame.top()!!,
true,
instructions,
sources,
toDelete
)?.let {
toDelete.add(cur)
if (it is LambdaInfo) {
toDelete.add(cur)
}
}
cur.opcode == Opcodes.PUTFIELD -> {
@@ -620,8 +623,8 @@ class MethodInliner(
) {
val stackTransformations = mutableSetOf<AbstractInsnNode>()
val lambdaInfo =
getLambdaIfExistsAndMarkInstructions(frame.peek(1)!!, false, instructions, sources, stackTransformations)
if (lambdaInfo != null && stackTransformations.all { it is VarInsnNode }) {
getFunctionalArgumentIfExistsAndMarkInstructions(frame.peek(1)!!, false, instructions, sources, stackTransformations)
if (lambdaInfo is LambdaInfo && stackTransformations.all { it is VarInsnNode }) {
assert(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(
anonymousType: String,
desc: String,
lambdaMapping: Map<Int, LambdaInfo>,
lambdaMapping: Map<Int, FunctionalArgument>,
needReification: Boolean,
capturesAnonymousObjectThatMustBeRegenerated: Boolean
): AnonymousObjectTransformationInfo {
@@ -845,20 +848,20 @@ class MethodInliner(
return inliningContext.typeRemapper.hasNoAdditionalMapping(owner)
}
internal fun getLambdaIfExists(insnNode: AbstractInsnNode): LambdaInfo? {
internal fun getFunctionalArgumentIfExists(insnNode: AbstractInsnNode): FunctionalArgument? {
return when {
insnNode.opcode == Opcodes.ALOAD ->
getLambdaIfExists((insnNode as VarInsnNode).`var`)
getFunctionalArgumentIfExists((insnNode as VarInsnNode).`var`)
insnNode is FieldInsnNode && insnNode.name.startsWith(CAPTURED_FIELD_FOLD_PREFIX) ->
findCapturedField(insnNode, nodeRemapper).lambda
findCapturedField(insnNode, nodeRemapper).functionalArgument
else ->
null
}
}
private fun getLambdaIfExists(varIndex: Int): LambdaInfo? {
private fun getFunctionalArgumentIfExists(varIndex: Int): FunctionalArgument? {
if (varIndex < parameters.argsSizeOnStack) {
return parameters.getParameterByDeclarationSlot(varIndex).lambda
return parameters.getParameterByDeclarationSlot(varIndex).functionalArgument
}
return null
}
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.inline
@@ -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.SourceValue
fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
fun MethodInliner.getFunctionalArgumentIfExistsAndMarkInstructions(
sourceValue: SourceValue,
processSwap: Boolean,
insnList: InsnList,
frames: Array<Frame<SourceValue>?>,
toDelete: MutableSet<AbstractInsnNode>
): LambdaInfo? {
): FunctionalArgument? {
val toDeleteInner = SmartSet.create<AbstractInsnNode>()
val lambdaSet = SmartSet.create<LambdaInfo?>()
sourceValue.insns.mapTo(lambdaSet) {
getLambdaIfExistsAndMarkInstructions(it, processSwap, insnList, frames, toDeleteInner)
val functionalArgumentSet = SmartSet.create<FunctionalArgument?>()
sourceValue.insns.mapTo(functionalArgumentSet) {
getFunctionalArgumentIfExistsAndMarkInstructions(it, processSwap, insnList, frames, toDeleteInner)
}
return lambdaSet.singleOrNull()?.also {
toDelete.addAll(toDeleteInner)
return functionalArgumentSet.singleOrNull()?.also {
if (it is LambdaInfo) {
toDelete.addAll(toDeleteInner)
}
}
}
private fun SourceValue.singleOrNullInsn() = insns.singleOrNull()
private fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
private fun MethodInliner.getFunctionalArgumentIfExistsAndMarkInstructions(
insnNode: AbstractInsnNode?,
processSwap: Boolean,
insnList: InsnList,
frames: Array<Frame<SourceValue>?>,
toDelete: MutableSet<AbstractInsnNode>
): LambdaInfo? {
): FunctionalArgument? {
if (insnNode == null) return null
getLambdaIfExists(insnNode)?.let {
getFunctionalArgumentIfExists(insnNode)?.let {
//delete lambda aload instruction
toDelete.add(insnNode)
return it
@@ -69,7 +60,7 @@ private fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
if (storeIns is VarInsnNode && storeIns.getOpcode() == Opcodes.ASTORE) {
val frame = frames[insnList.indexOf(storeIns)] ?: return null
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
toDelete.add(storeIns)
toDelete.add(insnNode)
@@ -79,7 +70,7 @@ private fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
} else if (processSwap && insnNode.opcode == Opcodes.SWAP) {
val swapFrame = frames[insnList.indexOf(insnNode)] ?: return null
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
toDelete.add(insnNode)
return it
@@ -29,7 +29,7 @@ public class ParameterInfo {
public final boolean isSkipped;
private boolean isCaptured;
private LambdaInfo lambda;
private FunctionalArgument functionalArgument;
//in case when parameter could be extracted from outer context (e.g. from local var)
private StackValue remapValue;
@@ -68,13 +68,13 @@ public class ParameterInfo {
}
@Nullable
public LambdaInfo getLambda() {
return lambda;
public FunctionalArgument getFunctionalArgument() {
return functionalArgument;
}
@NotNull
public ParameterInfo setLambda(@Nullable LambdaInfo lambda) {
this.lambda = lambda;
public ParameterInfo setFunctionalArgument(@Nullable FunctionalArgument functionalArgument) {
this.functionalArgument = functionalArgument;
return this;
}
@@ -38,7 +38,7 @@ class ParametersBuilder private constructor() {
fun addCapturedParam(original: CapturedParamInfo, newFieldName: String): CapturedParamInfo {
val info = CapturedParamInfo(original.desc, newFieldName, original.isSkipped, nextParameterOffset, original.index)
info.lambda = original.lambda
info.functionalArgument = original.functionalArgument
return addParameter(info)
}
@@ -62,7 +62,7 @@ class ParametersBuilder private constructor() {
CapturedParamDesc(containingLambdaType, fieldName, type), newFieldName, skipped, nextParameterOffset, original?.index ?: -1
)
if (original != null) {
info.lambda = original.lambda
info.functionalArgument = original.functionalArgument
}
return addParameter(info)
}
@@ -116,7 +116,7 @@ class ParametersBuilder private constructor() {
val builder = newBuilder()
if (inlineLambda?.hasDispatchReceiver != false && !isStatic) {
//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)) {
@@ -75,7 +75,7 @@ class RegeneratedLambdaFieldRemapper(
val result = StackValue.field(
if (field.isSkipped)
if (field.isSkipped && field.functionalArgument is LambdaInfo)
Type.getObjectType(parent!!.parent!!.newLambdaInternalName)
else
field.getType(),
@@ -67,7 +67,7 @@ class WhenMappingTransformationInfo(
class AnonymousObjectTransformationInfo internal constructor(
override val oldClassName: String,
private val needReification: Boolean,
val lambdasToInline: Map<Int, LambdaInfo>,
val functionalArguments: Map<Int, FunctionalArgument>,
private val capturedOuterRegenerated: Boolean,
private val alreadyRegenerated: Boolean,
val constructorDesc: String?,
@@ -99,7 +99,7 @@ class AnonymousObjectTransformationInfo internal constructor(
override fun shouldRegenerate(sameModule: Boolean): Boolean =
!alreadyRegenerated &&
(!lambdasToInline.isEmpty() || !sameModule || capturedOuterRegenerated || needReification || capturesAnonymousObjectThatMustBeRegenerated)
(!functionalArguments.isEmpty() || !sameModule || capturedOuterRegenerated || needReification || capturesAnonymousObjectThatMustBeRegenerated)
override fun canRemoveAfterTransformation(): Boolean {
// 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.resolve.jvm.diagnostics.JvmDeclarationOrigin
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.tree.MethodInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
@@ -38,14 +37,14 @@ class CoroutineTransformer(
// See innerObjectRetransformation.kt
if (inliningContext.callSiteInfo.isInlineOrInsideInline) return false
if (isContinuationNotLambda()) return false
val crossinlineParam = crossinlineLambda() ?: return false
val crossinlineParam = crossinlineLambda()
if (inliningContext.isInliningLambda && !inliningContext.isContinuation) return false
return when {
isSuspendFunction(node) -> true
isSuspendLambda(node) -> {
if (isStateMachine(node)) return false
val functionDescriptor =
crossinlineParam.invokeMethodDescriptor.containingDeclaration as? FunctionDescriptor ?: return true
crossinlineParam?.invokeMethodDescriptor?.containingDeclaration as? FunctionDescriptor ?: return true
!functionDescriptor.isInline
}
else -> false
@@ -66,9 +65,11 @@ class CoroutineTransformer(
private fun isSuspendLambda(node: MethodNode) = isResumeImpl(node)
fun newMethod(node: MethodNode): DeferredMethodVisitor {
val element = crossinlineLambda()?.functionWithBodyOrCallableReference.sure {
"crossinline lambda should have element"
}
// Find ANY element to report error about suspension point in monitor on.
val element = crossinlineLambda()?.functionWithBodyOrCallableReference
?: inliningContext.root.sourceCompilerForInline.callElement as? KtElement
?: error("crossinline lambda should have element")
return when {
isResumeImpl(node) -> {
assert(!isStateMachine(node)) {
@@ -25,7 +25,7 @@ class NewJavaField(val name: String, val type: Type, val skip: Boolean)
fun getNewFieldsToGenerate(params: List<CapturedParamInfo>): List<NewJavaField> {
return params.filter {
//not inlined
it.lambda == null
it.functionalArgument !is LambdaInfo
}.map {
NewJavaField(it.newFieldName, it.type, it.isSkipInConstructor)
}
@@ -99,7 +99,7 @@ class IrInlineCodegen(
parameter.type.isExtensionFunctionType
).also { lambda ->
val closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.index)
closureInfo.lambda = lambda
closureInfo.functionalArgument = 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");
}
@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")
public void testReturnValue_1_2() throws Exception {
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);
}
@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")
public void testInnerLambdaInsideLambda_1_2() throws Exception {
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 {
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");
}
@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")
public void testReturnValue_1_2() throws Exception {
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);
}
@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")
public void testInnerLambdaInsideLambda_1_2() throws Exception {
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 {
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");
}
@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")
public void testReturnValue_1_2() throws Exception {
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);
}
@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")
public void testInnerLambdaInsideLambda_1_2() throws Exception {
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 {
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");
}
@TestMetadata("nonSuspendCrossinline.kt")
public void testNonSuspendCrossinline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/nonSuspendCrossinline.kt", "kotlin.coroutines");
}
@TestMetadata("returnValue.kt")
public void testReturnValue_1_3() throws Exception {
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);
}
@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")
public void testInnerLambdaInsideLambda_1_3() throws Exception {
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 {
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");
}
@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")
public void testReturnValue_1_2() throws Exception {
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);
}
@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")
public void testInnerLambdaInsideLambda_1_2() throws Exception {
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 {
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");
}
}
}