JVM: move loadCompiledInlineFunction out of InlineCodegen

This commit is contained in:
pyos
2021-05-27 16:03:18 +02:00
committed by max-kammerer
parent 8307367f90
commit 7dbf08ae1c
5 changed files with 50 additions and 51 deletions
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.inline.InlineCodegen
import org.jetbrains.kotlin.codegen.inline.loadCompiledInlineFunction
import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
@@ -74,7 +74,7 @@ class DelegatedPropertiesCodegenHelper(private val state: GenerationState) {
val containerId = KotlinTypeMapper.getContainingClassesForDeserializedCallable(calleeDescriptor).implClassId
val asmMethod = state.typeMapper.mapAsmMethod(calleeDescriptor)
val isMangled = requiresFunctionNameManglingForReturnType(calleeDescriptor)
val methodNode = InlineCodegen.loadCompiledInlineFunction(containerId, asmMethod, calleeDescriptor.isSuspend, isMangled, state).node
val methodNode = loadCompiledInlineFunction(containerId, asmMethod, calleeDescriptor.isSuspend, isMangled, state).node
return isMetadataParameterUsedInCompiledMethodBody(metadataParameterIndex, methodNode)
}
@@ -9,13 +9,11 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
import org.jetbrains.kotlin.codegen.context.ClosureContext
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.Position
import org.jetbrains.kotlin.incremental.components.ScopeKind
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -27,7 +25,6 @@ import org.jetbrains.kotlin.types.model.TypeParameterMarker
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.Method
import org.jetbrains.org.objectweb.asm.tree.*
import kotlin.math.max
@@ -424,50 +421,6 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
}
companion object {
fun loadCompiledInlineFunction(
containerId: ClassId,
asmMethod: Method,
isSuspend: Boolean,
isMangled: Boolean,
state: GenerationState
): SMAPAndMethodNode {
val containerType = AsmUtil.asmTypeByClassId(containerId)
val bytes = state.inlineCache.classBytes.getOrPut(containerId) {
findVirtualFile(state, containerId)?.contentsToByteArray()
?: throw IllegalStateException("Couldn't find declaration file for $containerId")
}
val resultInCache = state.inlineCache.methodNodeById.getOrPut(MethodId(containerType.descriptor, asmMethod)) {
getMethodNode(containerType, bytes, asmMethod.name, asmMethod.descriptor, isSuspend, isMangled)
}
return SMAPAndMethodNode(cloneMethodNode(resultInCache.node), resultInCache.classSMAP)
}
private fun getMethodNode(
owner: Type,
bytes: ByteArray,
name: String,
descriptor: String,
isSuspend: Boolean,
isMangled: Boolean
): SMAPAndMethodNode {
getMethodNode(owner, bytes, name, descriptor, isSuspend)?.let { return it }
if (isMangled) {
// Compatibility with old inline class ABI versions.
val dashIndex = name.indexOf('-')
val nameWithoutManglingSuffix = if (dashIndex > 0) name.substring(0, dashIndex) else name
if (nameWithoutManglingSuffix != name) {
getMethodNode(owner, bytes, nameWithoutManglingSuffix, descriptor, isSuspend)?.let { return it }
}
getMethodNode(owner, bytes, "$nameWithoutManglingSuffix-impl", descriptor, isSuspend)?.let { return it }
}
throw IllegalStateException("couldn't find inline method $owner.$name$descriptor")
}
// If an `inline suspend fun` has a state machine, it should have a `$$forInline` version without one.
private fun getMethodNode(owner: Type, bytes: ByteArray, name: String, descriptor: String, isSuspend: Boolean) =
(if (isSuspend) getMethodNode(bytes, name + FOR_INLINE_SUFFIX, descriptor, owner) else null)
?: getMethodNode(bytes, name, descriptor, owner)
private fun StackValue.isCapturedInlineParameter(): Boolean {
val field = if (this is StackValue.FieldForSharedVar) receiver else this
return field is StackValue.Field && field.descriptor is ParameterDescriptor &&
@@ -247,7 +247,7 @@ class PsiSourceCompilerForInline(
if (directMember is DescriptorWithContainerSource) {
val containerId = KotlinTypeMapper.getContainingClassesForDeserializedCallable(directMember).implClassId
val isMangled = requiresFunctionNameManglingForReturnType(functionDescriptor)
return InlineCodegen.loadCompiledInlineFunction(containerId, asmMethod, functionDescriptor.isSuspend, isMangled, state)
return loadCompiledInlineFunction(containerId, asmMethod, functionDescriptor.isSuspend, isMangled, state)
}
val element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)
@@ -6,8 +6,10 @@
package org.jetbrains.kotlin.codegen.inline
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.BaseExpressionCodegen
import org.jetbrains.kotlin.codegen.OwnerKind
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -61,3 +63,47 @@ interface SourceCompilerForInline {
fun reportSuspensionPointInsideMonitor(stackTraceElement: String)
}
fun loadCompiledInlineFunction(
containerId: ClassId,
asmMethod: Method,
isSuspend: Boolean,
isMangled: Boolean,
state: GenerationState
): SMAPAndMethodNode {
val containerType = AsmUtil.asmTypeByClassId(containerId)
val bytes = state.inlineCache.classBytes.getOrPut(containerId) {
findVirtualFile(state, containerId)?.contentsToByteArray()
?: throw IllegalStateException("Couldn't find declaration file for $containerId")
}
val resultInCache = state.inlineCache.methodNodeById.getOrPut(MethodId(containerType.descriptor, asmMethod)) {
getMethodNode(containerType, bytes, asmMethod.name, asmMethod.descriptor, isSuspend, isMangled)
}
return SMAPAndMethodNode(cloneMethodNode(resultInCache.node), resultInCache.classSMAP)
}
private fun getMethodNode(
owner: Type,
bytes: ByteArray,
name: String,
descriptor: String,
isSuspend: Boolean,
isMangled: Boolean
): SMAPAndMethodNode {
getMethodNode(owner, bytes, name, descriptor, isSuspend)?.let { return it }
if (isMangled) {
// Compatibility with old inline class ABI versions.
val dashIndex = name.indexOf('-')
val nameWithoutManglingSuffix = if (dashIndex > 0) name.substring(0, dashIndex) else name
if (nameWithoutManglingSuffix != name) {
getMethodNode(owner, bytes, nameWithoutManglingSuffix, descriptor, isSuspend)?.let { return it }
}
getMethodNode(owner, bytes, "$nameWithoutManglingSuffix-impl", descriptor, isSuspend)?.let { return it }
}
throw IllegalStateException("couldn't find inline method $owner.$name$descriptor")
}
// If an `inline suspend fun` has a state machine, it should have a `$$forInline` version without one.
private fun getMethodNode(owner: Type, bytes: ByteArray, name: String, descriptor: String, isSuspend: Boolean) =
(if (isSuspend) getMethodNode(bytes, name + FOR_INLINE_SUFFIX, descriptor, owner) else null)
?: getMethodNode(bytes, name, descriptor, owner)
@@ -106,7 +106,7 @@ class IrSourceCompilerForInline(
override fun compileInlineFunction(jvmSignature: JvmMethodSignature): SMAPAndMethodNode =
callee.parentClassId?.let { containerId ->
InlineCodegen.loadCompiledInlineFunction(containerId, jvmSignature.asmMethod, callee.isSuspend, callee.hasMangledReturnType, state)
loadCompiledInlineFunction(containerId, jvmSignature.asmMethod, callee.isSuspend, callee.hasMangledReturnType, state)
} ?: ClassCodegen.getOrCreate(callee.parentAsClass, codegen.context).generateMethodNode(callee)
override fun hasFinallyBlocks() = data.hasFinallyBlocks()