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:
@@ -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 {
|
||||||
|
|||||||
+4
-1
@@ -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();
|
||||||
|
|
||||||
|
|||||||
+13
-13
@@ -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)) {
|
||||||
|
|||||||
+1
-1
@@ -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
|
||||||
|
|||||||
+7
-6
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -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"
|
||||||
|
}
|
||||||
+61
@@ -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"
|
||||||
|
}
|
||||||
+69
@@ -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"
|
||||||
|
}
|
||||||
+36
@@ -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"
|
||||||
|
}
|
||||||
+50
@@ -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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Generated
+50
@@ -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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+50
@@ -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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Generated
+25
@@ -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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+50
@@ -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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user