JVM_IR: restore InnerClasses for objects in lambdas

This commit is contained in:
pyos
2020-03-19 11:13:20 +01:00
parent be87d5fab5
commit 186302d84e
7 changed files with 25 additions and 28 deletions
@@ -345,17 +345,6 @@ open class ClassCodegen protected constructor(
fun createLocalClassCodegen(klass: IrClass, parentFunction: IrFunction): ClassCodegen =
ClassCodegen(klass, context, this, parentFunction, withinInline = withinInline || parentFunction.isInline)
fun createClassCodegenForLambdaBody(parentClass: IrClass, lambda: IrFunction): ClassCodegen =
object : ClassCodegen(parentClass, context, parentFunction = parentFunction, withinInline = withinInline) {
override fun createClassBuilder(): ClassBuilder {
return object : AbstractClassBuilder() {
override fun getVisitor(): ClassVisitor {
TODO("Expect to be _not_ reached")
}
}
}
}
private fun generateField(field: IrField) {
if (field.origin == IrDeclarationOrigin.FAKE_OVERRIDE) return
@@ -109,7 +109,8 @@ class ExpressionCodegen(
override val frameMap: IrFrameMap,
val mv: InstructionAdapter,
val classCodegen: ClassCodegen,
val inlinedInto: ExpressionCodegen?
val inlinedInto: ExpressionCodegen?,
val smapOverride: DefaultSourceMapper?
) : IrElementVisitor<PromisedValue, BlockInfo>, BaseExpressionCodegen {
var finallyDepth = 0
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.lower.suspendFunctionOriginal
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.inline.DefaultSourceMapper
import org.jetbrains.kotlin.codegen.mangleNameIfNeeded
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.visitAnnotableParameterCount
@@ -38,7 +39,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
open class FunctionCodegen(
private val irFunction: IrFunction,
private val classCodegen: ClassCodegen,
private val inlinedInto: ExpressionCodegen? = null,
private val inlinedInto: ExpressionCodegen? = null
) {
val context = classCodegen.context
val state = classCodegen.state
@@ -47,14 +48,14 @@ open class FunctionCodegen(
classCodegen.createLocalClassCodegen(irFunction.continuationClass(), irFunction).also { it.generate() }
}
fun generate(): JvmMethodGenericSignature =
fun generate(smapOverride: DefaultSourceMapper? = null): JvmMethodGenericSignature =
try {
doGenerate()
doGenerate(smapOverride)
} catch (e: Throwable) {
throw RuntimeException("Exception while generating code for:\n${irFunction.dump()}", e)
}
private fun doGenerate(): JvmMethodGenericSignature {
private fun doGenerate(smapOverride: DefaultSourceMapper?): JvmMethodGenericSignature {
val signature = classCodegen.methodSignatureMapper.mapSignatureWithGeneric(irFunction)
val flags = calculateMethodFlags(irFunction.isStatic)
@@ -113,7 +114,8 @@ open class FunctionCodegen(
}
context.state.globalInlineContext.enterDeclaration(irFunction.suspendFunctionOriginal().descriptor)
try {
ExpressionCodegen(irFunction, signature, frameMap, InstructionAdapter(methodVisitor), classCodegen, inlinedInto).generate()
val adapter = InstructionAdapter(methodVisitor)
ExpressionCodegen(irFunction, signature, frameMap, adapter, classCodegen, inlinedInto, smapOverride).generate()
} finally {
context.state.globalInlineContext.exitDeclaration()
}
@@ -95,10 +95,14 @@ class IrSourceCompilerForInline(
}
override val lazySourceMapper: DefaultSourceMapper
get() = codegen.classCodegen.getOrCreateSourceMapper()
get() = codegen.smapOverride ?: codegen.classCodegen.getOrCreateSourceMapper()
private fun makeInlineNode(function: IrFunction, classCodegen: ClassCodegen, isLambda: Boolean): SMAPAndMethodNode {
var node: MethodNode? = null
val smap = if (isLambda)
codegen.context.getSourceMapper(codegen.classCodegen.irClass)
else
classCodegen.getOrCreateSourceMapper()
val functionCodegen = object : FunctionCodegen(function, classCodegen, codegen.takeIf { isLambda }) {
override fun createMethod(flags: Int, signature: JvmMethodGenericSignature): MethodVisitor {
val asmMethod = signature.asmMethod
@@ -113,13 +117,12 @@ class IrSourceCompilerForInline(
return wrapWithMaxLocalCalc(node!!)
}
}
functionCodegen.generate()
return SMAPAndMethodNode(node!!, SMAP(classCodegen.getOrCreateSourceMapper().resultMappings))
functionCodegen.generate(smap)
return SMAPAndMethodNode(node!!, SMAP(smap.resultMappings))
}
override fun generateLambdaBody(lambdaInfo: ExpressionLambda): SMAPAndMethodNode {
val function = (lambdaInfo as IrExpressionLambdaImpl).function
return makeInlineNode(function, codegen.classCodegen.createClassCodegenForLambdaBody(codegen.classCodegen.irClass, function), true)
return makeInlineNode((lambdaInfo as IrExpressionLambdaImpl).function, codegen.classCodegen, true)
}
override fun doCreateMethodNodeFromSource(
@@ -151,7 +154,7 @@ class IrSourceCompilerForInline(
override fun createCodegenForExternalFinallyBlockGenerationOnNonLocalReturn(finallyNode: MethodNode, curFinallyDepth: Int) =
ExpressionCodegen(
codegen.irFunction, codegen.signature, codegen.frameMap, InstructionAdapter(finallyNode), codegen.classCodegen,
codegen.inlinedInto
codegen.inlinedInto, codegen.smapOverride
).also {
it.finallyDepth = curFinallyDepth
}
@@ -14,6 +14,7 @@ public final class _2Kt$complicatedCast$1$1 {
@kotlin.Metadata
public final class _2Kt {
inner class _2Kt$complicatedCast$1$1
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
public synthetic final static method complicatedCast(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
}
+3 -3
View File
@@ -17,9 +17,8 @@ inline fun test(s: () -> Unit) {
s()
}
// 4 INNERCLASS
// JVM_TEMPLATES
// 4 INNERCLASS
// 2 INNERCLASS Kt10259Kt\$box\$\$inlined\$test\$lambda\$1\s
// 2 INNERCLASS Kt10259Kt\$box\$\$inlined\$test\$lambda\$1\$1
@@ -28,7 +27,8 @@ inline fun test(s: () -> Unit) {
// this behavior is equivalent to javac and seems to be correct.
// JVM_IR_TEMPLATES
// 2 INNERCLASS Kt10259Kt\$box\$1\$1\s
// 5 INNERCLASS
// 3 INNERCLASS Kt10259Kt\$box\$1\$1\s
// 2 INNERCLASS Kt10259Kt\$box\$1\$1\$1
// 1 class Kt10259Kt\$box\$1\$1\ extends
// 1 class Kt10259Kt\$box\$1\$1\$1 extends
+3 -2
View File
@@ -21,9 +21,9 @@ inline fun test(crossinline s: () -> Unit) {
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$1\s
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$1\$1\s
// 13 INNERCLASS
// JVM_TEMPLATES
// 13 INNERCLASS
// 3 INNERCLASS Kt10259_3Kt\$test\$1 null
// 2 INNERCLASS Kt10259_3Kt\$test\$1\$1
// inlined:
@@ -38,7 +38,8 @@ inline fun test(crossinline s: () -> Unit) {
// this behavior is equivalent to javac and seems to be correct.
// JVM_IR_TEMPLATES
// 2 INNERCLASS Kt10259_3Kt\$box\$1\$1\s
// 14 INNERCLASS
// 3 INNERCLASS Kt10259_3Kt\$box\$1\$1\s
// 2 INNERCLASS Kt10259_3Kt\$box\$1\$1\$1\s
// 3 INNERCLASS Kt10259_3Kt\$test\$1\s
// 2 INNERCLASS Kt10259_3Kt\$test\$1\$1\s