JVM: refactor loading of inline functions from binaries
The IR path no longer does any descriptor unwrapping or old-style type mapping.
This commit is contained in:
+7
-4
@@ -9,11 +9,13 @@ import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.inline.InlineCodegen
|
||||
import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.FunctionImportedFromObject
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||
@@ -65,13 +67,14 @@ class DelegatedPropertiesCodegenHelper(private val state: GenerationState) {
|
||||
this
|
||||
|
||||
private fun isDelegatedPropertyMetadataRequiredForFunctionFromBinaries(calleeDescriptor: FunctionDescriptor): Boolean {
|
||||
assert(calleeDescriptor is DescriptorWithContainerSource) {
|
||||
require(calleeDescriptor is DescriptorWithContainerSource) {
|
||||
"Function descriptor from binaries expected: $calleeDescriptor"
|
||||
}
|
||||
|
||||
val metadataParameterIndex = getMetadataParameterIndex(calleeDescriptor)
|
||||
val methodNode = InlineCodegen.createSpecialInlineMethodNodeFromBinaries(calleeDescriptor, state)
|
||||
|
||||
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
|
||||
return isMetadataParameterUsedInCompiledMethodBody(metadataParameterIndex, methodNode)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,28 +6,23 @@
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
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.intrinsics.IntrinsicArrayConstructors
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
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
|
||||
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.inline.isInlineOnly
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
|
||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||
import org.jetbrains.kotlin.types.model.TypeParameterMarker
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
@@ -250,8 +245,6 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
|
||||
abstract fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda>
|
||||
|
||||
abstract fun descriptorIsDeserialized(memberDescriptor: CallableMemberDescriptor): Boolean
|
||||
|
||||
private fun generateAndInsertFinallyBlocks(
|
||||
intoNode: MethodNode,
|
||||
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
|
||||
@@ -433,144 +426,63 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
typeArguments: List<TypeParameterMarker>?,
|
||||
typeSystem: TypeSystemCommonBackendContext
|
||||
): SMAPAndMethodNode {
|
||||
val intrinsic = generateInlineIntrinsic(state, functionDescriptor, typeArguments, typeSystem)
|
||||
val intrinsic = generateInlineIntrinsic(state, functionDescriptor, jvmSignature.asmMethod, typeArguments, typeSystem)
|
||||
if (intrinsic != null) {
|
||||
return SMAPAndMethodNode(intrinsic, createDefaultFakeSMAP())
|
||||
return SMAPAndMethodNode(intrinsic, SMAP(listOf()))
|
||||
}
|
||||
|
||||
var asmMethod = mapMethod(callDefault)
|
||||
if (asmMethod.name.contains("-") &&
|
||||
!state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME) &&
|
||||
classFileContainsMethod(functionDescriptor, state, asmMethod) == false
|
||||
) {
|
||||
state.typeMapper.useOldManglingRulesForFunctionAcceptingInlineClass = true
|
||||
asmMethod = mapMethod(callDefault)
|
||||
state.typeMapper.useOldManglingRulesForFunctionAcceptingInlineClass = false
|
||||
sourceCompiler.inlineFunctionSignature(jvmSignature, callDefault)?.let { (containerId, asmMethod) ->
|
||||
val isMangled = requiresFunctionNameManglingForReturnType(functionDescriptor)
|
||||
return loadCompiledInlineFunction(containerId, asmMethod, functionDescriptor.isSuspend, isMangled, state)
|
||||
}
|
||||
|
||||
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
|
||||
if (!isBuiltInArrayIntrinsic(functionDescriptor) && !descriptorIsDeserialized(directMember)) {
|
||||
val node = sourceCompiler.compileInlineFunction(jvmSignature, callDefault, asmMethod)
|
||||
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
|
||||
return node
|
||||
return sourceCompiler.compileInlineFunction(jvmSignature, callDefault).apply {
|
||||
node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
|
||||
}
|
||||
|
||||
return getCompiledMethodNodeInner(functionDescriptor, directMember, asmMethod, methodOwner, state, jvmSignature)
|
||||
}
|
||||
|
||||
private fun mapMethod(callDefault: Boolean): Method =
|
||||
if (callDefault) state.typeMapper.mapDefaultMethod(functionDescriptor, sourceCompiler.contextKind)
|
||||
else mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor, jvmSignature.asmMethod)
|
||||
|
||||
companion object {
|
||||
|
||||
internal fun createSpecialInlineMethodNodeFromBinaries(functionDescriptor: FunctionDescriptor, state: GenerationState): MethodNode {
|
||||
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
|
||||
assert(directMember is DescriptorWithContainerSource) {
|
||||
"Function is not in binaries: $functionDescriptor"
|
||||
}
|
||||
assert(directMember is FunctionDescriptor && directMember.isOperator) {
|
||||
"Operator function expected: $directMember"
|
||||
}
|
||||
|
||||
val methodOwner = state.typeMapper.mapImplementationOwner(functionDescriptor)
|
||||
val jvmSignature = state.typeMapper.mapSignatureWithGeneric(functionDescriptor, OwnerKind.IMPLEMENTATION)
|
||||
|
||||
val asmMethod = mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor, jvmSignature.asmMethod)
|
||||
|
||||
return getCompiledMethodNodeInner(functionDescriptor, directMember, asmMethod, methodOwner, state, jvmSignature).node
|
||||
}
|
||||
|
||||
private fun getCompiledMethodNodeInner(
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
directMember: CallableMemberDescriptor,
|
||||
internal fun loadCompiledInlineFunction(
|
||||
containerId: ClassId,
|
||||
asmMethod: Method,
|
||||
methodOwner: Type,
|
||||
state: GenerationState,
|
||||
jvmSignature: JvmMethodSignature
|
||||
isSuspend: Boolean,
|
||||
isMangled: Boolean,
|
||||
state: GenerationState
|
||||
): SMAPAndMethodNode {
|
||||
val methodId = MethodId(methodOwner.internalName, asmMethod)
|
||||
|
||||
val resultInCache = state.inlineCache.methodNodeById.getOrPut(methodId) {
|
||||
val result = doCreateMethodNodeFromCompiled(directMember, state, asmMethod)
|
||||
?: if (functionDescriptor.isSuspend)
|
||||
doCreateMethodNodeFromCompiled(directMember, state, jvmSignature.asmMethod)
|
||||
else
|
||||
null
|
||||
result ?: throw IllegalStateException("Couldn't obtain compiled function body for $functionDescriptor")
|
||||
}
|
||||
|
||||
return SMAPAndMethodNode(cloneMethodNode(resultInCache.node), resultInCache.classSMAP)
|
||||
}
|
||||
|
||||
private fun createDefaultFakeSMAP() = SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
|
||||
|
||||
// For suspend inline functions we generate two methods:
|
||||
// 1) normal one: with state machine to call directly
|
||||
// 2) for inliner: with mangled name and without state machine
|
||||
private fun mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor: FunctionDescriptor, asmMethod: Method): Method {
|
||||
if (!functionDescriptor.isSuspend) return asmMethod
|
||||
return Method("${asmMethod.name}$FOR_INLINE_SUFFIX", asmMethod.descriptor)
|
||||
}
|
||||
|
||||
private fun getDirectMemberAndCallableFromObject(functionDescriptor: FunctionDescriptor): CallableMemberDescriptor {
|
||||
val directMember = JvmCodegenUtil.getDirectMember(functionDescriptor)
|
||||
return (directMember as? ImportedFromObjectCallableDescriptor<*>)?.callableFromObject ?: directMember
|
||||
}
|
||||
|
||||
private fun doCreateMethodNodeFromCompiled(
|
||||
callableDescriptor: CallableMemberDescriptor,
|
||||
state: GenerationState,
|
||||
asmMethod: Method
|
||||
): SMAPAndMethodNode? {
|
||||
if (isBuiltInArrayIntrinsic(callableDescriptor)) {
|
||||
val body = when {
|
||||
callableDescriptor is FictitiousArrayConstructor -> IntrinsicArrayConstructors.generateArrayConstructorBody(asmMethod)
|
||||
callableDescriptor.name.asString() == "emptyArray" -> IntrinsicArrayConstructors.generateEmptyArrayBody(asmMethod)
|
||||
callableDescriptor.name.asString() == "arrayOf" -> IntrinsicArrayConstructors.generateArrayOfBody(asmMethod)
|
||||
else -> throw UnsupportedOperationException("Not an array intrinsic: $callableDescriptor")
|
||||
}
|
||||
return SMAPAndMethodNode(body, SMAP(listOf()))
|
||||
}
|
||||
|
||||
assert(callableDescriptor is DescriptorWithContainerSource) { "Not a deserialized function or proper: $callableDescriptor" }
|
||||
|
||||
val containingClasses =
|
||||
KotlinTypeMapper.getContainingClassesForDeserializedCallable(callableDescriptor as DescriptorWithContainerSource)
|
||||
|
||||
val containerId = containingClasses.implClassId
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
val classType = AsmUtil.asmTypeByClassId(containerId)
|
||||
val methodNode = getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, classType)
|
||||
if (methodNode == null && requiresFunctionNameManglingForReturnType(callableDescriptor)) {
|
||||
val nameWithoutManglingSuffix = asmMethod.name.stripManglingSuffixOrNull()
|
||||
if (nameWithoutManglingSuffix != null) {
|
||||
val methodWithoutMangling = getMethodNode(bytes, nameWithoutManglingSuffix, asmMethod.descriptor, classType)
|
||||
if (methodWithoutMangling != null) return methodWithoutMangling
|
||||
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 }
|
||||
}
|
||||
return getMethodNode(bytes, "$nameWithoutManglingSuffix-impl", asmMethod.descriptor, classType)
|
||||
getMethodNode(owner, bytes, "$nameWithoutManglingSuffix-impl", descriptor, isSuspend)?.let { return it }
|
||||
}
|
||||
|
||||
return methodNode
|
||||
throw IllegalStateException("couldn't find inline method $owner.$name$descriptor")
|
||||
}
|
||||
|
||||
private fun String.stripManglingSuffixOrNull(): String? {
|
||||
val dashIndex = indexOf('-')
|
||||
return if (dashIndex < 0) null else substring(0, dashIndex)
|
||||
}
|
||||
|
||||
private fun isBuiltInArrayIntrinsic(callableDescriptor: CallableMemberDescriptor): Boolean {
|
||||
if (callableDescriptor is FictitiousArrayConstructor) return true
|
||||
val name = callableDescriptor.name.asString()
|
||||
return (name == "arrayOf" || name == "emptyArray") && callableDescriptor.containingDeclaration.let { container ->
|
||||
container is PackageFragmentDescriptor && container.fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME
|
||||
}
|
||||
}
|
||||
// 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
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ class InlineCodegenForDefaultBody(
|
||||
|
||||
override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) {
|
||||
assert(!callDefault) { "inlining default stub into another default stub" }
|
||||
val (node, smap) = sourceCompilerForInline.compileInlineFunction(jvmSignature, callDefault, jvmSignature.asmMethod)
|
||||
val (node, smap) = sourceCompilerForInline.compileInlineFunction(jvmSignature, callDefault)
|
||||
val childSourceMapper = SourceMapCopier(sourceMapper, smap)
|
||||
|
||||
val argsSize =
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil.isInlinableParameterExpression
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
@@ -219,9 +218,6 @@ class PsiInlineCodegen(
|
||||
::PsiDefaultLambda
|
||||
)
|
||||
}
|
||||
|
||||
override fun descriptorIsDeserialized(memberDescriptor: CallableMemberDescriptor): Boolean =
|
||||
memberDescriptor is DescriptorWithContainerSource
|
||||
}
|
||||
|
||||
private val FunctionDescriptor.explicitParameters
|
||||
|
||||
+35
-1
@@ -11,16 +11,21 @@ import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.context.*
|
||||
import org.jetbrains.kotlin.codegen.coroutines.getOrCreateJvmSuspendFunctionView
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.isCallableMemberCompiledToJvmDefault
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||
import org.jetbrains.kotlin.types.expressions.LabelResolver
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
@@ -214,7 +219,32 @@ class PsiSourceCompilerForInline(
|
||||
}
|
||||
}
|
||||
|
||||
override fun compileInlineFunction(jvmSignature: JvmMethodSignature, callDefault: Boolean, asmMethod: Method): SMAPAndMethodNode {
|
||||
private fun getDirectMemberAndCallableFromObject(): CallableMemberDescriptor {
|
||||
val directMember = JvmCodegenUtil.getDirectMember(functionDescriptor)
|
||||
return (directMember as? ImportedFromObjectCallableDescriptor<*>)?.callableFromObject ?: directMember
|
||||
}
|
||||
|
||||
override fun inlineFunctionSignature(jvmSignature: JvmMethodSignature, callDefault: Boolean): Pair<ClassId, Method>? {
|
||||
val directMember = getDirectMemberAndCallableFromObject() as? DescriptorWithContainerSource
|
||||
?: return null
|
||||
val containerId = KotlinTypeMapper.getContainingClassesForDeserializedCallable(directMember).implClassId
|
||||
if (!callDefault) {
|
||||
return containerId to jvmSignature.asmMethod
|
||||
}
|
||||
// This is all available in the `Callable` passed to `PsiInlineCodegen.genCallInner`, but it's not forwarded through the inliner...
|
||||
var result = state.typeMapper.mapDefaultMethod(functionDescriptor, contextKind)
|
||||
if (result.name.contains("-") &&
|
||||
!state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME) &&
|
||||
classFileContainsMethod(functionDescriptor, state, result) == false
|
||||
) {
|
||||
state.typeMapper.useOldManglingRulesForFunctionAcceptingInlineClass = true
|
||||
result = state.typeMapper.mapDefaultMethod(functionDescriptor, contextKind)
|
||||
state.typeMapper.useOldManglingRulesForFunctionAcceptingInlineClass = false
|
||||
}
|
||||
return containerId to result
|
||||
}
|
||||
|
||||
override fun compileInlineFunction(jvmSignature: JvmMethodSignature, callDefault: Boolean): SMAPAndMethodNode {
|
||||
val element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)
|
||||
|
||||
if (!(element is KtNamedFunction || element is KtPropertyAccessor)) {
|
||||
@@ -222,6 +252,10 @@ class PsiSourceCompilerForInline(
|
||||
}
|
||||
val inliningFunction = element as KtDeclarationWithBody?
|
||||
|
||||
val asmMethod = if (callDefault)
|
||||
state.typeMapper.mapDefaultMethod(functionDescriptor, contextKind)
|
||||
else
|
||||
jvmSignature.asmMethod
|
||||
val node = MethodNode(
|
||||
Opcodes.API_VERSION,
|
||||
DescriptorAsmUtil.getMethodAsmFlags(functionDescriptor, context.contextKind, state) or
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
@@ -37,7 +38,9 @@ interface SourceCompilerForInline {
|
||||
|
||||
fun generateLambdaBody(lambdaInfo: ExpressionLambda, reifiedTypeParameters: ReifiedTypeParametersUsages): SMAPAndMethodNode
|
||||
|
||||
fun compileInlineFunction(jvmSignature: JvmMethodSignature, callDefault: Boolean, asmMethod: Method): SMAPAndMethodNode
|
||||
fun inlineFunctionSignature(jvmSignature: JvmMethodSignature, callDefault: Boolean): Pair<ClassId, Method>?
|
||||
|
||||
fun compileInlineFunction(jvmSignature: JvmMethodSignature, callDefault: Boolean): SMAPAndMethodNode
|
||||
|
||||
fun hasFinallyBlocks(): Boolean
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForCoroutineConte
|
||||
import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForIntercepted
|
||||
import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForSuspendCoroutineUninterceptedOrReturn
|
||||
import org.jetbrains.kotlin.codegen.createMethodNodeForAlwaysEnabledAssert
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructors
|
||||
import org.jetbrains.kotlin.codegen.isBuiltinAlwaysEnabledAssert
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
@@ -26,11 +27,13 @@ import org.jetbrains.kotlin.types.model.TypeParameterMarker
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
internal fun generateInlineIntrinsic(
|
||||
state: GenerationState,
|
||||
descriptor: FunctionDescriptor,
|
||||
asmMethod: Method,
|
||||
typeParameters: List<TypeParameterMarker>?,
|
||||
typeSystem: TypeSystemCommonBackendContext
|
||||
): MethodNode? {
|
||||
@@ -49,6 +52,12 @@ internal fun generateInlineIntrinsic(
|
||||
createMethodNodeForSuspendCoroutineUninterceptedOrReturn(languageVersionSettings)
|
||||
descriptor.isBuiltinAlwaysEnabledAssert() ->
|
||||
createMethodNodeForAlwaysEnabledAssert(descriptor)
|
||||
descriptor is FictitiousArrayConstructor ->
|
||||
IntrinsicArrayConstructors.generateArrayConstructorBody(asmMethod)
|
||||
IntrinsicArrayConstructors.isArrayOf(descriptor) ->
|
||||
IntrinsicArrayConstructors.generateArrayOfBody(asmMethod)
|
||||
IntrinsicArrayConstructors.isEmptyArray(descriptor) ->
|
||||
IntrinsicArrayConstructors.generateEmptyArrayBody(asmMethod)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
+13
@@ -16,10 +16,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.intrinsics
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.inline.ReificationArgument
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
@@ -30,6 +34,15 @@ import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
internal object IntrinsicArrayConstructors {
|
||||
fun isArrayOf(descriptor: FunctionDescriptor): Boolean =
|
||||
descriptor.name.asString() == "arrayOf" && descriptor.containingDeclaration.isBuiltInsPackage
|
||||
|
||||
fun isEmptyArray(descriptor: FunctionDescriptor): Boolean =
|
||||
descriptor.name.asString() == "emptyArray" && descriptor.containingDeclaration.isBuiltInsPackage
|
||||
|
||||
private val DeclarationDescriptor.isBuiltInsPackage: Boolean
|
||||
get() = this is PackageFragmentDescriptor && fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME
|
||||
|
||||
fun generateArrayConstructorBody(method: Method): MethodNode {
|
||||
val node = MethodNode(
|
||||
Opcodes.ASM6, Opcodes.ACC_PUBLIC or Opcodes.ACC_STATIC or Opcodes.ACC_FINAL, method.name, method.descriptor, null, null
|
||||
|
||||
-4
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.ValueKind
|
||||
import org.jetbrains.kotlin.codegen.inline.*
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
@@ -150,9 +149,6 @@ class IrInlineCodegen(
|
||||
::IrDefaultLambda
|
||||
)
|
||||
}
|
||||
|
||||
override fun descriptorIsDeserialized(memberDescriptor: CallableMemberDescriptor): Boolean =
|
||||
((memberDescriptor as IrBasedDeclarationDescriptor<*>).owner as IrMemberWithContainerSource).parentClassId != null
|
||||
}
|
||||
|
||||
class IrExpressionLambdaImpl(
|
||||
|
||||
+5
-1
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||
import org.jetbrains.kotlin.ir.util.isSuspend
|
||||
import org.jetbrains.kotlin.ir.util.module
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.doNotAnalyze
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.SUSPENSION_POINT_INSIDE_MONITOR
|
||||
@@ -104,7 +105,10 @@ class IrSourceCompilerForInline(
|
||||
return FunctionCodegen(lambdaInfo.function, codegen.classCodegen).generate(codegen, reifiedTypeParameters)
|
||||
}
|
||||
|
||||
override fun compileInlineFunction(jvmSignature: JvmMethodSignature, callDefault: Boolean, asmMethod: Method): SMAPAndMethodNode =
|
||||
override fun inlineFunctionSignature(jvmSignature: JvmMethodSignature, callDefault: Boolean): Pair<ClassId, Method>? =
|
||||
callee.parentClassId?.let { it to jvmSignature.asmMethod }
|
||||
|
||||
override fun compileInlineFunction(jvmSignature: JvmMethodSignature, callDefault: Boolean): SMAPAndMethodNode =
|
||||
ClassCodegen.getOrCreate(callee.parentAsClass, codegen.context).generateMethodNode(callee)
|
||||
|
||||
override fun hasFinallyBlocks() = data.hasFinallyBlocks()
|
||||
|
||||
Reference in New Issue
Block a user