JVM IR: Check for cycles when inlining into default stubs

This commit is contained in:
Steven Schäfer
2020-09-15 16:59:03 +02:00
committed by max-kammerer
parent 111c550f3c
commit 648bc9b1c4
3 changed files with 64 additions and 27 deletions
@@ -0,0 +1,43 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.backend.jvm.codegen
import org.jetbrains.kotlin.backend.jvm.lower.suspendFunctionOriginal
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.util.render
interface IrInlineCallGenerator : IrCallGenerator {
override fun genCall(
callableMethod: IrCallableMethod,
codegen: ExpressionCodegen,
expression: IrFunctionAccessExpression,
isInsideIfCondition: Boolean,
) {
val element = codegen.context.psiSourceManager.findPsiElement(expression, codegen.irFunction)
?: codegen.context.psiSourceManager.findPsiElement(codegen.irFunction)
if (!codegen.state.globalInlineContext.enterIntoInlining(
expression.symbol.owner.suspendFunctionOriginal().toIrBasedDescriptor(), element)
) {
val message = "Call is a part of inline call cycle: ${expression.render()}"
AsmUtil.genThrow(codegen.visitor, "java/lang/UnsupportedOperationException", message)
return
}
try {
genInlineCall(callableMethod, codegen, expression, isInsideIfCondition)
} finally {
codegen.state.globalInlineContext.exitFromInlining()
}
}
fun genInlineCall(
callableMethod: IrCallableMethod,
codegen: ExpressionCodegen,
expression: IrFunctionAccessExpression,
isInsideIfCondition: Boolean,
)
}
@@ -7,8 +7,10 @@ package org.jetbrains.kotlin.backend.jvm.codegen
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.ir.isInlineParameter import org.jetbrains.kotlin.backend.jvm.ir.isInlineParameter
import org.jetbrains.kotlin.backend.jvm.lower.suspendFunctionOriginal import org.jetbrains.kotlin.codegen.IrExpressionLambda
import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.JvmKotlinType
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.ValueKind
import org.jetbrains.kotlin.codegen.inline.* import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -41,7 +43,7 @@ class IrInlineCodegen(
InlineCodegen<ExpressionCodegen>( InlineCodegen<ExpressionCodegen>(
codegen, state, function.toIrBasedDescriptor(), methodOwner, signature, typeParameterMappings, sourceCompiler, reifiedTypeInliner codegen, state, function.toIrBasedDescriptor(), methodOwner, signature, typeParameterMappings, sourceCompiler, reifiedTypeInliner
), ),
IrCallGenerator { IrInlineCallGenerator {
override fun generateAssertFieldIfNeeded(info: RootInliningContext) { override fun generateAssertFieldIfNeeded(info: RootInliningContext) {
if (info.generateAssertField) { if (info.generateAssertField) {
@@ -134,33 +136,20 @@ class IrInlineCodegen(
invocationParamBuilder.markValueParametersStart() invocationParamBuilder.markValueParametersStart()
} }
override fun genCall( override fun genInlineCall(
callableMethod: IrCallableMethod, callableMethod: IrCallableMethod,
codegen: ExpressionCodegen, codegen: ExpressionCodegen,
expression: IrFunctionAccessExpression, expression: IrFunctionAccessExpression,
isInsideIfCondition: Boolean, isInsideIfCondition: Boolean,
) { ) {
val element = codegen.context.psiSourceManager.findPsiElement(expression, codegen.irFunction) performInline(
?: codegen.context.psiSourceManager.findPsiElement(codegen.irFunction) expression.symbol.owner.typeParameters.map { it.symbol },
if (!state.globalInlineContext.enterIntoInlining( // Always look for default lambdas to allow custom default argument handling in compiler plugins.
expression.symbol.owner.suspendFunctionOriginal().toIrBasedDescriptor(), element) true,
) { false,
val message = "Call is a part of inline call cycle: ${expression.render()}" codegen.typeMapper.typeSystem,
AsmUtil.genThrow(codegen.v, "java/lang/UnsupportedOperationException", message) registerLineNumberAfterwards = isInsideIfCondition,
return )
}
try {
performInline(
expression.symbol.owner.typeParameters.map { it.symbol },
// Always look for default lambdas to allow custom default argument handling in compiler plugins.
true,
false,
codegen.typeMapper.typeSystem,
registerLineNumberAfterwards = isInsideIfCondition,
)
} finally {
state.globalInlineContext.exitFromInlining()
}
} }
private fun rememberClosure( private fun rememberClosure(
@@ -20,7 +20,7 @@ import org.jetbrains.org.objectweb.asm.Type
* Such calls are inlined verbatim in the JVM backend (see InlineCodegenForDefaultBody.kt). * Such calls are inlined verbatim in the JVM backend (see InlineCodegenForDefaultBody.kt).
* For compatibility we have to do the same thing in the JVM IR backend. * For compatibility we have to do the same thing in the JVM IR backend.
*/ */
object IrInlineDefaultCodegen : IrCallGenerator { object IrInlineDefaultCodegen : IrInlineCallGenerator {
override fun genValueAndPut( override fun genValueAndPut(
irValueParameter: IrValueParameter, irValueParameter: IrValueParameter,
argumentExpression: IrExpression, argumentExpression: IrExpression,
@@ -34,7 +34,12 @@ object IrInlineDefaultCodegen : IrCallGenerator {
assert(argumentExpression is IrGetValue || argumentExpression is IrTypeOperatorCall && argumentExpression.argument is IrGetValue) assert(argumentExpression is IrGetValue || argumentExpression is IrTypeOperatorCall && argumentExpression.argument is IrGetValue)
} }
override fun genCall(callableMethod: IrCallableMethod, codegen: ExpressionCodegen, expression: IrFunctionAccessExpression) { override fun genInlineCall(
callableMethod: IrCallableMethod,
codegen: ExpressionCodegen,
expression: IrFunctionAccessExpression,
isInsideIfCondition: Boolean
) {
val function = expression.symbol.owner val function = expression.symbol.owner
val nodeAndSmap = codegen.classCodegen.generateMethodNode(function, codegen.delegatedPropertyOptimizer) val nodeAndSmap = codegen.classCodegen.generateMethodNode(function, codegen.delegatedPropertyOptimizer)
val childSourceMapper = SourceMapCopier(codegen.smap, nodeAndSmap.classSMAP) val childSourceMapper = SourceMapCopier(codegen.smap, nodeAndSmap.classSMAP)