From b317187f20ddcada16a9b10b5b2f627a4ec33a57 Mon Sep 17 00:00:00 2001 From: pyos Date: Fri, 20 Mar 2020 16:19:36 +0100 Subject: [PATCH] JVM_IR: buffer method bytecode in FunctionCodegen --- .../backend/jvm/codegen/ClassCodegen.kt | 8 +++-- .../backend/jvm/codegen/FunctionCodegen.kt | 31 +++++++++-------- .../jvm/codegen/IrSourceCompilerForInline.kt | 33 ++++--------------- 3 files changed, 27 insertions(+), 45 deletions(-) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index 732168b919b..c37c233aa44 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -45,6 +45,7 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature import org.jetbrains.kotlin.serialization.DescriptorSerializer import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.org.objectweb.asm.* +import org.jetbrains.org.objectweb.asm.commons.Method import java.io.File open class ClassCodegen protected constructor( @@ -352,8 +353,11 @@ open class ClassCodegen protected constructor( return } - val signature = FunctionCodegen(method, this).generate().asmMethod - jvmSignatureClashDetector.trackMethod(method, RawSignature(signature.name, signature.descriptor, MemberKind.METHOD)) + val node = FunctionCodegen(method, this).generate() + node.accept(with(node) { visitor.newMethod(method.OtherOrigin, access, name, desc, signature, exceptions.toTypedArray()) }) + jvmSignatureClashDetector.trackMethod(method, RawSignature(node.name, node.desc, MemberKind.METHOD)) + + val signature = Method(node.name, node.desc) when (val metadata = method.metadata) { is MetadataSource.Property -> { // We can't check for JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS because for interface methods diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt index c3668f36bb7..d49cf1b2879 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt @@ -13,6 +13,7 @@ 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.inline.wrapWithMaxLocalCalc import org.jetbrains.kotlin.codegen.mangleNameIfNeeded import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.visitAnnotableParameterCount @@ -28,31 +29,39 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_SYNTHETIC_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.jvm.annotations.STRICTFP_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.jvm.annotations.SYNCHRONIZED_ANNOTATION_FQ_NAME -import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.org.objectweb.asm.* import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter +import org.jetbrains.org.objectweb.asm.tree.MethodNode -open class FunctionCodegen( +class FunctionCodegen( private val irFunction: IrFunction, private val classCodegen: ClassCodegen, private val inlinedInto: ExpressionCodegen? = null ) { private val context = classCodegen.context - fun generate(smapOverride: DefaultSourceMapper? = null): JvmMethodGenericSignature = + fun generate(smapOverride: DefaultSourceMapper? = null): MethodNode = try { doGenerate(smapOverride) } catch (e: Throwable) { throw RuntimeException("Exception while generating code for:\n${irFunction.dump()}", e) } - private fun doGenerate(smapOverride: DefaultSourceMapper?): JvmMethodGenericSignature { + private fun doGenerate(smapOverride: DefaultSourceMapper?): MethodNode { val signature = context.methodSignatureMapper.mapSignatureWithGeneric(irFunction) val flags = irFunction.calculateMethodFlags() - var methodVisitor = createMethod(flags, signature) + val methodNode = MethodNode( + Opcodes.API_VERSION, + flags, + signature.asmMethod.name, + signature.asmMethod.descriptor, + signature.genericsSignature.takeIf { flags.and(Opcodes.ACC_SYNTHETIC) == 0 }, + getThrownExceptions(irFunction)?.toTypedArray() + ) + var methodVisitor: MethodVisitor = wrapWithMaxLocalCalc(methodNode) if (context.state.generateParametersMetadata && flags.and(Opcodes.ACC_SYNTHETIC) == 0) { generateParameterNames(irFunction, methodVisitor, signature, context.state) @@ -103,7 +112,7 @@ open class FunctionCodegen( if (continuationClassCodegen.isInitialized() || irFunction.alwaysNeedsContinuation()) { continuationClassCodegen.value.done() } - return signature + return methodNode } // Since the only arguments to anonymous object constructors are captured variables and complex @@ -156,16 +165,6 @@ open class FunctionCodegen( (if (isSynchronized) Opcodes.ACC_SYNCHRONIZED else 0) } - protected open fun createMethod(flags: Int, signature: JvmMethodGenericSignature): MethodVisitor = - classCodegen.visitor.newMethod( - irFunction.OtherOrigin, - flags, - signature.asmMethod.name, - signature.asmMethod.descriptor, - signature.genericsSignature.takeIf { flags.and(Opcodes.ACC_SYNTHETIC) == 0 }, - getThrownExceptions(irFunction)?.toTypedArray() - ) - private fun getThrownExceptions(function: IrFunction): List? { if (context.state.languageVersionSettings.supportsFeature(LanguageFeature.DoNotGenerateThrowsForDelegatedKotlinMembers) && function.origin == IrDeclarationOrigin.DELEGATED_MEMBER diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt index dca62282a45..ba33ac2a2a1 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt @@ -37,7 +37,6 @@ import org.jetbrains.kotlin.psi.doNotAnalyze import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.SUSPENSION_POINT_INSIDE_MONITOR 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.kotlin.resolve.source.getPsi import org.jetbrains.org.objectweb.asm.* @@ -97,32 +96,10 @@ class IrSourceCompilerForInline( override val lazySourceMapper: DefaultSourceMapper 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 - node = MethodNode( - Opcodes.API_VERSION, - flags, - asmMethod.name.removeSuffix(FOR_INLINE_SUFFIX), - asmMethod.descriptor, - signature.genericsSignature, - null - ) - return wrapWithMaxLocalCalc(node!!) - } - } - functionCodegen.generate(smap) - return SMAPAndMethodNode(node!!, SMAP(smap.resultMappings)) - } - override fun generateLambdaBody(lambdaInfo: ExpressionLambda): SMAPAndMethodNode { - return makeInlineNode((lambdaInfo as IrExpressionLambdaImpl).function, codegen.classCodegen, true) + val smap = codegen.context.getSourceMapper(codegen.classCodegen.irClass) + val node = FunctionCodegen((lambdaInfo as IrExpressionLambdaImpl).function, codegen.classCodegen, codegen).generate(smap) + return SMAPAndMethodNode(node, SMAP(smap.resultMappings)) } override fun doCreateMethodNodeFromSource( @@ -141,7 +118,9 @@ class IrSourceCompilerForInline( } ?: callee else callee - return makeInlineNode(forInlineFunction, FakeClassCodegen(forInlineFunction, codegen.classCodegen), false) + val fakeCodegen = FakeClassCodegen(forInlineFunction, codegen.classCodegen) + val node = FunctionCodegen(forInlineFunction, fakeCodegen).generate() + return SMAPAndMethodNode(node, SMAP(fakeCodegen.getOrCreateSourceMapper().resultMappings)) } override fun hasFinallyBlocks() = data.hasFinallyBlocks()