JVM_IR: buffer method bytecode in FunctionCodegen
This commit is contained in:
+6
-2
@@ -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
|
||||
|
||||
+15
-16
@@ -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<String>? {
|
||||
if (context.state.languageVersionSettings.supportsFeature(LanguageFeature.DoNotGenerateThrowsForDelegatedKotlinMembers) &&
|
||||
function.origin == IrDeclarationOrigin.DELEGATED_MEMBER
|
||||
|
||||
+6
-27
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user