Support finally blocks in non-local returns
This commit is contained in:
+26
-7
@@ -109,9 +109,12 @@ class ExpressionCodegen(
|
||||
val irFunction: IrFunction,
|
||||
val frame: IrFrameMap,
|
||||
val mv: InstructionAdapter,
|
||||
val classCodegen: ClassCodegen
|
||||
val classCodegen: ClassCodegen,
|
||||
val isInlineLambda: Boolean = false
|
||||
) : IrElementVisitor<StackValue, BlockInfo>, BaseExpressionCodegen {
|
||||
|
||||
var finallyDepth = 0
|
||||
|
||||
/*TODO*/
|
||||
val intrinsics = IrIntrinsicMethods(classCodegen.context.irBuiltIns)
|
||||
|
||||
@@ -331,7 +334,7 @@ class ExpressionCodegen(
|
||||
}
|
||||
|
||||
fun generateCall(expression: IrMemberAccessExpression, callable: Callable, data: BlockInfo, isSuperCall: Boolean = false): StackValue {
|
||||
val callGenerator = getOrCreateCallGenerator(expression, expression.descriptor)
|
||||
val callGenerator = getOrCreateCallGenerator(expression, expression.descriptor, data)
|
||||
|
||||
val receiver = expression.dispatchReceiver
|
||||
receiver?.apply {
|
||||
@@ -1123,7 +1126,17 @@ class ExpressionCodegen(
|
||||
private fun genFinallyBlock(tryInfo: TryInfo, tryCatchBlockEnd: Label?, afterJumpLabel: Label?, data: BlockInfo) {
|
||||
assert(tryInfo.gaps.size % 2 == 0) { "Finally block gaps are inconsistent" }
|
||||
tryInfo.gaps.add(markNewLabel())
|
||||
finallyDepth++
|
||||
if (isFinallyMarkerRequired()) {
|
||||
generateFinallyMarker(mv, finallyDepth, true)
|
||||
}
|
||||
gen(tryInfo.tryBlock.finallyExpression!!, data).discard()
|
||||
|
||||
if (isFinallyMarkerRequired()) {
|
||||
generateFinallyMarker(mv, finallyDepth, false)
|
||||
}
|
||||
finallyDepth--
|
||||
|
||||
if (tryCatchBlockEnd != null) {
|
||||
tryInfo.tryBlock.finallyExpression!!.markLineNumber(startOffset = false)
|
||||
mv.goTo(tryCatchBlockEnd)
|
||||
@@ -1131,7 +1144,7 @@ class ExpressionCodegen(
|
||||
tryInfo.gaps.add(afterJumpLabel ?: markNewLabel())
|
||||
}
|
||||
|
||||
private fun generateFinallyBlocksIfNeeded(returnType: Type, afterReturnLabel: Label, data: BlockInfo) {
|
||||
fun generateFinallyBlocksIfNeeded(returnType: Type, afterReturnLabel: Label, data: BlockInfo) {
|
||||
if (data.hasFinallyBlocks()) {
|
||||
if (Type.VOID_TYPE != returnType) {
|
||||
val returnValIndex = frame.enterTemp(returnType)
|
||||
@@ -1226,7 +1239,8 @@ class ExpressionCodegen(
|
||||
descriptor: CallableDescriptor,
|
||||
element: IrMemberAccessExpression?,
|
||||
typeParameterMappings: TypeParameterMappings?,
|
||||
isDefaultCompilation: Boolean
|
||||
isDefaultCompilation: Boolean,
|
||||
data: BlockInfo
|
||||
): IrCallGenerator {
|
||||
if (element == null) return IrCallGenerator.DefaultCallGenerator
|
||||
|
||||
@@ -1240,13 +1254,14 @@ class ExpressionCodegen(
|
||||
return if (isDefaultCompilation) {
|
||||
TODO()
|
||||
} else {
|
||||
IrInlineCodegen(this, state, original, typeParameterMappings!!, IrSourceCompilerForInline(state, element, this))
|
||||
IrInlineCodegen(this, state, original, typeParameterMappings!!, IrSourceCompilerForInline(state, element, this, data))
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getOrCreateCallGenerator(
|
||||
memberAccessExpression: IrMemberAccessExpression,
|
||||
descriptor: CallableDescriptor
|
||||
descriptor: CallableDescriptor,
|
||||
data: BlockInfo
|
||||
): IrCallGenerator {
|
||||
val typeArguments =
|
||||
if (memberAccessExpression.typeArgumentsCount == 0) {
|
||||
@@ -1280,7 +1295,7 @@ class ExpressionCodegen(
|
||||
}
|
||||
}
|
||||
|
||||
return getOrCreateCallGenerator(descriptor, memberAccessExpression, mappings, false)
|
||||
return getOrCreateCallGenerator(descriptor, memberAccessExpression, mappings, false, data)
|
||||
}
|
||||
|
||||
override val frameMap: IrFrameMap
|
||||
@@ -1311,6 +1326,10 @@ class ExpressionCodegen(
|
||||
override fun markLineNumberAfterInlineIfNeeded() {
|
||||
//TODO
|
||||
}
|
||||
|
||||
fun isFinallyMarkerRequired(): Boolean {
|
||||
return irFunction.isInline || isInlineLambda
|
||||
}
|
||||
}
|
||||
|
||||
fun DefaultCallArgs.generateOnStackIfNeeded(callGenerator: IrCallGenerator, isConstructor: Boolean, codegen: ExpressionCodegen): Boolean {
|
||||
|
||||
+6
-2
@@ -27,7 +27,11 @@ import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
open class FunctionCodegen(private val irFunction: IrFunction, private val classCodegen: ClassCodegen) {
|
||||
open class FunctionCodegen(
|
||||
private val irFunction: IrFunction,
|
||||
private val classCodegen: ClassCodegen,
|
||||
private val isInlineLambda: Boolean = false
|
||||
) {
|
||||
|
||||
val state = classCodegen.state
|
||||
|
||||
@@ -56,7 +60,7 @@ open class FunctionCodegen(private val irFunction: IrFunction, private val class
|
||||
methodVisitor.visitEnd()
|
||||
} else {
|
||||
val frameMap = createFrameMapWithReceivers(classCodegen.state, irFunction, signature)
|
||||
ExpressionCodegen(irFunction, frameMap, InstructionAdapter(methodVisitor), classCodegen).generate()
|
||||
ExpressionCodegen(irFunction, frameMap, InstructionAdapter(methodVisitor), classCodegen, isInlineLambda).generate()
|
||||
}
|
||||
|
||||
return signature
|
||||
|
||||
+18
-10
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.codegen.BaseExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.inline.*
|
||||
@@ -37,13 +38,15 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
class IrSourceCompilerForInline(
|
||||
override val state: GenerationState,
|
||||
override val callElement: IrMemberAccessExpression,
|
||||
private val codegen: ExpressionCodegen
|
||||
private val codegen: ExpressionCodegen,
|
||||
private val data: BlockInfo
|
||||
) : SourceCompilerForInline {
|
||||
|
||||
|
||||
@@ -71,7 +74,7 @@ class IrSourceCompilerForInline(
|
||||
override fun generateLambdaBody(adapter: MethodVisitor, jvmMethodSignature: JvmMethodSignature, lambdaInfo: ExpressionLambda): SMAP {
|
||||
lambdaInfo as? IrExpressionLambdaImpl ?: error("Expecting ir lambda, but $lambdaInfo")
|
||||
|
||||
val functionCodegen = object : FunctionCodegen(lambdaInfo.function, codegen.classCodegen) {
|
||||
val functionCodegen = object : FunctionCodegen(lambdaInfo.function, codegen.classCodegen, true) {
|
||||
override fun createMethod(flags: Int, signature: JvmMethodGenericSignature): MethodVisitor {
|
||||
return adapter
|
||||
}
|
||||
@@ -135,22 +138,27 @@ class IrSourceCompilerForInline(
|
||||
return SMAPAndMethodNode(node!!, SMAP(fakeClassCodegen.getOrCreateSourceMapper().resultMappings))
|
||||
}
|
||||
|
||||
override fun generateAndInsertFinallyBlocks(
|
||||
intoNode: MethodNode,
|
||||
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
|
||||
offsetForFinallyLocalVar: Int
|
||||
) {
|
||||
//TODO("not implemented")
|
||||
override fun hasFinallyBlocks() = data.hasFinallyBlocks()
|
||||
|
||||
override fun generateFinallyBlocksIfNeeded(finallyCodegen: BaseExpressionCodegen, returnType: Type, afterReturnLabel: Label) {
|
||||
require(finallyCodegen is ExpressionCodegen)
|
||||
finallyCodegen.generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data)
|
||||
}
|
||||
|
||||
override fun createCodegenForExternalFinallyBlockGenerationOnNonLocalReturn(finallyNode: MethodNode, curFinallyDepth: Int) =
|
||||
ExpressionCodegen(
|
||||
codegen.irFunction, codegen.frame, InstructionAdapter(finallyNode), codegen.classCodegen, codegen.isInlineLambda
|
||||
).also {
|
||||
it.finallyDepth = curFinallyDepth
|
||||
}
|
||||
|
||||
override fun isCallInsideSameModuleAsDeclared(functionDescriptor: FunctionDescriptor): Boolean {
|
||||
//TODO("not implemented")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun isFinallyMarkerRequired(): Boolean {
|
||||
//TODO("not implemented")
|
||||
return false
|
||||
return codegen.isFinallyMarkerRequired()
|
||||
}
|
||||
|
||||
override val compilationContextDescriptor: DeclarationDescriptor
|
||||
|
||||
Reference in New Issue
Block a user