JVM: do not use crossinline flag when inlining assertions

Crossinline lambdas *can* be inlined into objects, but don't *have* to;
the correct place should be determined from the context, not from the
parameter.
This commit is contained in:
pyos
2021-07-06 10:57:48 +02:00
committed by max-kammerer
parent e64cda61d5
commit 50797dba8d
13 changed files with 191 additions and 27 deletions
@@ -1264,7 +1264,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
// Thus, do not generate it. Otherwise, it leads to VerifyError on run-time.
boolean isCrossinlineLambda = (callGenerator instanceof PsiInlineCodegen) &&
Objects.requireNonNull(((PsiInlineCodegen) callGenerator).getActiveLambda(),
"no active lambda found").isCrossInline;
"no active lambda found").isCrossInline();
if (!isCrossinlineLambda) {
v.aconst(null);
}
@@ -16,8 +16,7 @@ import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
interface FunctionalArgument
abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgument {
abstract class LambdaInfo : FunctionalArgument {
abstract val isBoundCallableReference: Boolean
abstract val isSuspend: Boolean
@@ -66,7 +65,7 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgu
object NonInlineableArgumentForInlineableParameterCalledInSuspend : FunctionalArgument
object NonInlineableArgumentForInlineableSuspendParameter : FunctionalArgument
abstract class ExpressionLambda(isCrossInline: Boolean) : LambdaInfo(isCrossInline) {
abstract class ExpressionLambda : LambdaInfo() {
fun generateLambdaBody(sourceCompiler: SourceCompilerForInline) {
node = sourceCompiler.generateLambdaBody(this, reifiedTypeParametersUsages)
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
@@ -76,11 +75,10 @@ abstract class ExpressionLambda(isCrossInline: Boolean) : LambdaInfo(isCrossInli
abstract class DefaultLambda(
final override val lambdaClassType: Type,
capturedArgs: Array<Type>,
isCrossinline: Boolean,
val offset: Int,
val needReification: Boolean,
sourceCompiler: SourceCompilerForInline
) : LambdaInfo(isCrossinline) {
) : LambdaInfo() {
final override val isSuspend
get() = false // TODO: it should probably be true sometimes, but it never was
final override val isBoundCallableReference: Boolean
@@ -558,21 +558,17 @@ class MethodInliner(
)
} else if (fieldInsnNode.isCheckAssertionsStatus()) {
fieldInsnNode.owner = inlineCallSiteInfo.ownerClassName
if (inliningContext.isInliningLambda) {
if (inliningContext.lambdaInfo!!.isCrossInline) {
assert(inliningContext.parent?.parent is RegeneratedClassContext) {
"$inliningContext grandparent shall be RegeneratedClassContext but got ${inliningContext.parent?.parent}"
}
inliningContext.parent!!.parent!!.generateAssertField = true
} else {
assert(inliningContext.parent != null) {
"$inliningContext parent shall not be null"
}
inliningContext.parent!!.generateAssertField = true
}
} else {
inliningContext.generateAssertField = true
}
when {
// In inline function itself:
inliningContext.parent == null -> inliningContext
// In method of regenerated object - field should already exist:
inliningContext.parent is RegeneratedClassContext -> inliningContext.parent
// In lambda inlined into the root function:
inliningContext.parent.parent == null -> inliningContext.parent
// In lambda inlined into a method of a regenerated object:
else -> inliningContext.parent.parent as? RegeneratedClassContext
?: throw AssertionError("couldn't find class for \$assertionsDisabled (context = $inliningContext)")
}.generateAssertField = true
}
}
@@ -181,7 +181,7 @@ class PsiInlineCodegen(
}
}
var activeLambda: LambdaInfo? = null
var activeLambda: PsiExpressionLambda? = null
private set
private fun putClosureParametersOnStack(next: PsiExpressionLambda, receiverValue: StackValue?) {
@@ -210,9 +210,9 @@ private val FunctionDescriptor.explicitParameters
class PsiExpressionLambda(
expression: KtExpression,
private val state: GenerationState,
isCrossInline: Boolean,
val isCrossInline: Boolean,
override val isBoundCallableReference: Boolean
) : ExpressionLambda(isCrossInline) {
) : ExpressionLambda() {
override val lambdaClassType: Type
override val invokeMethod: Method
@@ -308,7 +308,7 @@ class PsiDefaultLambda(
offset: Int,
needReification: Boolean,
sourceCompiler: SourceCompilerForInline
) : DefaultLambda(lambdaClassType, capturedArgs, parameterDescriptor.isCrossinline, offset, needReification, sourceCompiler) {
) : DefaultLambda(lambdaClassType, capturedArgs, offset, needReification, sourceCompiler) {
private val invokeMethodDescriptor: FunctionDescriptor
override val invokeMethodParameters: List<KotlinType?>