JVM: remove functionDescriptor from InlineCodegen
This commit is contained in:
@@ -10,15 +10,11 @@ import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
|
||||
import org.jetbrains.kotlin.codegen.context.ClosureContext
|
||||
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.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
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.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
@@ -29,18 +25,11 @@ import kotlin.math.max
|
||||
abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
protected val codegen: T,
|
||||
protected val state: GenerationState,
|
||||
protected val functionDescriptor: FunctionDescriptor,
|
||||
protected val jvmSignature: JvmMethodSignature,
|
||||
private val typeParameterMappings: TypeParameterMappings<*>,
|
||||
protected val sourceCompiler: SourceCompilerForInline,
|
||||
protected val reifiedTypeInliner: ReifiedTypeInliner<*>
|
||||
) {
|
||||
init {
|
||||
assert(InlineUtil.isInline(functionDescriptor)) {
|
||||
"InlineCodegen can inline only inline functions: $functionDescriptor"
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: implement AS_FUNCTION inline strategy
|
||||
private val asFunctionInline = false
|
||||
|
||||
@@ -52,15 +41,6 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
protected var maskStartIndex = -1
|
||||
protected var methodHandleInDefaultMethodIndex = -1
|
||||
|
||||
init {
|
||||
if (functionDescriptor !is FictitiousArrayConstructor) {
|
||||
//track changes for property accessor and @JvmName inline functions/property accessors
|
||||
if (jvmSignature.asmMethod.name != functionDescriptor.name.asString()) {
|
||||
trackLookup(functionDescriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun throwCompilationException(
|
||||
nodeAndSmap: SMAPAndMethodNode?, e: Exception, generateNodeText: Boolean
|
||||
): CompilationException {
|
||||
@@ -68,7 +48,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
val element = DescriptorToSourceUtils.descriptorToDeclaration(contextDescriptor)
|
||||
val node = nodeAndSmap?.node
|
||||
throw CompilationException(
|
||||
"Couldn't inline method call '" + functionDescriptor.name + "' into\n" +
|
||||
"Couldn't inline method call '${jvmSignature.asmMethod}' into\n" +
|
||||
DescriptorRenderer.DEBUG_TEXT.render(contextDescriptor) + "\n" +
|
||||
(element?.text ?: "<no source>") +
|
||||
if (generateNodeText) "\nCause: " + node.nodeText else "",
|
||||
@@ -81,13 +61,13 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
AsmUtil.genThrow(codegen.visitor, "java/lang/UnsupportedOperationException", "Call is part of inline cycle: $text")
|
||||
}
|
||||
|
||||
fun performInline(inlineDefaultLambdas: Boolean, registerLineNumberAfterwards: Boolean) {
|
||||
fun performInline(registerLineNumberAfterwards: Boolean, isInlineOnly: Boolean, isSuspend: Boolean) {
|
||||
var nodeAndSmap: SMAPAndMethodNode? = null
|
||||
try {
|
||||
nodeAndSmap = sourceCompiler.compileInlineFunction(jvmSignature).apply {
|
||||
node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
|
||||
}
|
||||
val result = inlineCall(nodeAndSmap, inlineDefaultLambdas)
|
||||
val result = inlineCall(nodeAndSmap, isInlineOnly, isSuspend)
|
||||
leaveTemps()
|
||||
codegen.propagateChildReifiedTypeParametersUsages(result.reifiedTypeParametersUsages)
|
||||
codegen.markLineNumberAfterInlineIfNeeded(registerLineNumberAfterwards)
|
||||
@@ -109,8 +89,6 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
//
|
||||
// Instead of checking for loops precisely, we just check if there are any backward jumps -
|
||||
// that is, a jump from instruction #i to instruction #j where j < i
|
||||
|
||||
if (functionDescriptor.isSuspend) return false
|
||||
if (methodNode.tryCatchBlocks.isNotEmpty()) return false
|
||||
|
||||
fun isBackwardJump(fromIndex: Int, toLabel: LabelNode) =
|
||||
@@ -162,9 +140,9 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
expressionMap[closureInfo.index] = lambdaInfo
|
||||
}
|
||||
|
||||
private fun inlineCall(nodeAndSmap: SMAPAndMethodNode, inlineDefaultLambda: Boolean): InlineResult {
|
||||
private fun inlineCall(nodeAndSmap: SMAPAndMethodNode, isInlineOnly: Boolean, isSuspend: Boolean): InlineResult {
|
||||
val node = nodeAndSmap.node
|
||||
if (inlineDefaultLambda) {
|
||||
if (maskStartIndex != -1) {
|
||||
for (lambda in extractDefaultLambdas(node)) {
|
||||
invocationParamBuilder.buildParameters().getParameterByDeclarationSlot(lambda.offset).functionalArgument = lambda
|
||||
val prev = expressionMap.put(lambda.offset, lambda)
|
||||
@@ -190,7 +168,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
node, parameters, info, FieldRemapper(null, null, parameters), sourceCompiler.isCallInsideSameModuleAsCallee,
|
||||
"Method inlining " + sourceCompiler.callElementText,
|
||||
SourceMapCopier(sourceMapper, nodeAndSmap.classSMAP, callSite),
|
||||
info.callSiteInfo, if (functionDescriptor.isInlineOnly()) InlineOnlySmapSkipper(codegen) else null,
|
||||
info.callSiteInfo, if (isInlineOnly) InlineOnlySmapSkipper(codegen) else null,
|
||||
!isInlinedToInlineFunInKotlinRuntime()
|
||||
) //with captured
|
||||
|
||||
@@ -215,7 +193,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
// needs to be inserted before the code that actually uses it.
|
||||
generateAssertFieldIfNeeded(info)
|
||||
|
||||
val shouldSpillStack = !canSkipStackSpillingOnInline(node)
|
||||
val shouldSpillStack = isSuspend || !canSkipStackSpillingOnInline(node)
|
||||
if (shouldSpillStack) {
|
||||
addInlineMarker(codegen.visitor, true)
|
||||
}
|
||||
@@ -389,21 +367,6 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
return true
|
||||
}
|
||||
|
||||
private fun trackLookup(functionOrAccessor: FunctionDescriptor) {
|
||||
val functionOrAccessorName = jvmSignature.asmMethod.name
|
||||
val lookupTracker = state.configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER) ?: return
|
||||
val location = sourceCompiler.lookupLocation.location ?: return
|
||||
val position = if (lookupTracker.requiresPosition) location.position else Position.NO_POSITION
|
||||
val classOrPackageFragment = functionOrAccessor.containingDeclaration
|
||||
lookupTracker.record(
|
||||
location.filePath,
|
||||
position,
|
||||
DescriptorUtils.getFqName(classOrPackageFragment).asString(),
|
||||
ScopeKind.CLASSIFIER,
|
||||
functionOrAccessorName
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun StackValue.isCapturedInlineParameter(): Boolean {
|
||||
val field = if (this is StackValue.FieldForSharedVar) receiver else this
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil.isInlinableParameterExpression
|
||||
import org.jetbrains.kotlin.resolve.inline.isInlineOnly
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -39,14 +40,14 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
class PsiInlineCodegen(
|
||||
codegen: ExpressionCodegen,
|
||||
state: GenerationState,
|
||||
function: FunctionDescriptor,
|
||||
private val functionDescriptor: FunctionDescriptor,
|
||||
signature: JvmMethodSignature,
|
||||
typeParameterMappings: TypeParameterMappings<KotlinType>,
|
||||
sourceCompiler: SourceCompilerForInline,
|
||||
private val methodOwner: Type,
|
||||
private val actualDispatchReceiver: Type
|
||||
) : InlineCodegen<ExpressionCodegen>(
|
||||
codegen, state, function, signature, typeParameterMappings, sourceCompiler,
|
||||
codegen, state, signature, typeParameterMappings, sourceCompiler,
|
||||
ReifiedTypeInliner(
|
||||
typeParameterMappings, PsiInlineIntrinsicsSupport(state), codegen.typeSystem,
|
||||
state.languageVersionSettings, state.unifiedNullChecks
|
||||
@@ -83,7 +84,7 @@ class PsiInlineCodegen(
|
||||
}
|
||||
}
|
||||
}
|
||||
performInline(callDefault, registerLineNumber)
|
||||
performInline(registerLineNumber, functionDescriptor.isInlineOnly(), functionDescriptor.isSuspend)
|
||||
} finally {
|
||||
state.globalInlineContext.exitFromInlining()
|
||||
}
|
||||
|
||||
+10
-14
@@ -52,7 +52,7 @@ class PsiSourceCompilerForInline(
|
||||
codegen.state,
|
||||
DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile,
|
||||
additionalInnerClasses
|
||||
)
|
||||
) as MethodContext
|
||||
|
||||
override val lookupLocation = KotlinLookupLocation(callElement)
|
||||
|
||||
@@ -246,6 +246,9 @@ class PsiSourceCompilerForInline(
|
||||
}
|
||||
|
||||
val asmMethod = if (callDefault) mapDefault() else jvmSignature.asmMethod
|
||||
if (asmMethod.name != functionDescriptor.name.asString()) {
|
||||
trackLookup(DescriptorUtils.getFqNameSafe(functionDescriptor.containingDeclaration), asmMethod.name) // ?
|
||||
}
|
||||
|
||||
val directMember = getDirectMemberAndCallableFromObject()
|
||||
if (directMember is DescriptorWithContainerSource) {
|
||||
@@ -254,12 +257,8 @@ class PsiSourceCompilerForInline(
|
||||
return loadCompiledInlineFunction(containerId, asmMethod, functionDescriptor.isSuspend, isMangled, state)
|
||||
}
|
||||
|
||||
val element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)
|
||||
|
||||
if (!(element is KtNamedFunction || element is KtPropertyAccessor)) {
|
||||
throw IllegalStateException("Couldn't find declaration for function $functionDescriptor")
|
||||
}
|
||||
val inliningFunction = element as KtDeclarationWithBody?
|
||||
val element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor) as? KtDeclarationWithBody
|
||||
?: throw IllegalStateException("Couldn't find declaration for function $functionDescriptor")
|
||||
|
||||
val node = MethodNode(
|
||||
Opcodes.API_VERSION,
|
||||
@@ -271,13 +270,10 @@ class PsiSourceCompilerForInline(
|
||||
|
||||
//for maxLocals calculation
|
||||
val maxCalcAdapter = wrapWithMaxLocalCalc(node)
|
||||
val parentContext = context.parentContext ?: error("Context has no parent: $context")
|
||||
val methodContext = parentContext.intoFunction(functionDescriptor)
|
||||
|
||||
val smap = if (callDefault) {
|
||||
val implementationOwner = state.typeMapper.mapImplementationOwner(functionDescriptor)
|
||||
val parentCodegen = FakeMemberCodegen(
|
||||
codegen.parentCodegen, inliningFunction!!, methodContext.parentContext as FieldOwnerContext<*>,
|
||||
codegen.parentCodegen, element, context.parentContext as FieldOwnerContext<*>,
|
||||
implementationOwner.internalName,
|
||||
additionalInnerClasses,
|
||||
false
|
||||
@@ -286,12 +282,12 @@ class PsiSourceCompilerForInline(
|
||||
throw IllegalStateException("Property accessors with default parameters not supported $functionDescriptor")
|
||||
}
|
||||
FunctionCodegen.generateDefaultImplBody(
|
||||
methodContext, functionDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
|
||||
inliningFunction as KtNamedFunction?, parentCodegen, asmMethod
|
||||
context, functionDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
|
||||
element as KtNamedFunction?, parentCodegen, asmMethod
|
||||
)
|
||||
SMAP(parentCodegen.orCreateSourceMapper.resultMappings)
|
||||
} else {
|
||||
generateMethodBody(maxCalcAdapter, functionDescriptor, methodContext, inliningFunction!!, jvmSignature, null)
|
||||
generateMethodBody(maxCalcAdapter, functionDescriptor, context, element, jvmSignature, null)
|
||||
}
|
||||
maxCalcAdapter.visitMaxs(-1, -1)
|
||||
maxCalcAdapter.visitEnd()
|
||||
|
||||
@@ -11,10 +11,14 @@ 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.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.incremental.components.Position
|
||||
import org.jetbrains.kotlin.incremental.components.ScopeKind
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
@@ -64,6 +68,19 @@ interface SourceCompilerForInline {
|
||||
fun reportSuspensionPointInsideMonitor(stackTraceElement: String)
|
||||
}
|
||||
|
||||
fun SourceCompilerForInline.trackLookup(container: FqName, functionName: String) {
|
||||
val lookupTracker = state.configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER) ?: return
|
||||
val location = lookupLocation.location ?: return
|
||||
val position = if (lookupTracker.requiresPosition) location.position else Position.NO_POSITION
|
||||
lookupTracker.record(
|
||||
location.filePath,
|
||||
position,
|
||||
container.asString(),
|
||||
ScopeKind.CLASSIFIER,
|
||||
functionName
|
||||
)
|
||||
}
|
||||
|
||||
fun loadCompiledInlineFunction(
|
||||
containerId: ClassId,
|
||||
asmMethod: Method,
|
||||
|
||||
+2
-6
@@ -41,9 +41,7 @@ class IrInlineCodegen(
|
||||
sourceCompiler: SourceCompilerForInline,
|
||||
reifiedTypeInliner: ReifiedTypeInliner<IrType>
|
||||
) :
|
||||
InlineCodegen<ExpressionCodegen>(
|
||||
codegen, state, function.toIrBasedDescriptor(), signature, typeParameterMappings, sourceCompiler, reifiedTypeInliner
|
||||
),
|
||||
InlineCodegen<ExpressionCodegen>(codegen, state, signature, typeParameterMappings, sourceCompiler, reifiedTypeInliner),
|
||||
IrInlineCallGenerator {
|
||||
|
||||
override fun generateAssertFieldIfNeeded(info: RootInliningContext) {
|
||||
@@ -126,8 +124,7 @@ class IrInlineCodegen(
|
||||
expression: IrFunctionAccessExpression,
|
||||
isInsideIfCondition: Boolean,
|
||||
) {
|
||||
// Always look for default lambdas to allow custom default argument handling in compiler plugins.
|
||||
performInline(inlineDefaultLambdas = true, registerLineNumberAfterwards = isInsideIfCondition)
|
||||
performInline(isInsideIfCondition, function.isInlineOnly(), function.isSuspend)
|
||||
}
|
||||
|
||||
override fun genCycleStub(text: String, codegen: ExpressionCodegen) {
|
||||
@@ -135,7 +132,6 @@ class IrInlineCodegen(
|
||||
}
|
||||
|
||||
override fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda> {
|
||||
if (maskStartIndex == -1) return listOf()
|
||||
return expandMaskConditionsAndUpdateVariableNodes(
|
||||
node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex,
|
||||
extractDefaultLambdaOffsetAndDescriptor(jvmSignature, function),
|
||||
|
||||
+4
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||
import org.jetbrains.kotlin.ir.util.isSuspend
|
||||
import org.jetbrains.kotlin.ir.util.kotlinFqName
|
||||
import org.jetbrains.kotlin.ir.util.module
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
@@ -108,6 +109,9 @@ class IrSourceCompilerForInline(
|
||||
generateInlineIntrinsicForIr(state.languageVersionSettings, callee.toIrBasedDescriptor())?.let {
|
||||
return it
|
||||
}
|
||||
if (jvmSignature.asmMethod.name != callee.name.asString()) {
|
||||
trackLookup(callee.parentAsClass.kotlinFqName, jvmSignature.asmMethod.name) // ?
|
||||
}
|
||||
callee.parentClassId?.let {
|
||||
return loadCompiledInlineFunction(it, jvmSignature.asmMethod, callee.isSuspend, callee.hasMangledReturnType, state)
|
||||
}
|
||||
|
||||
+8
-16
@@ -179,7 +179,7 @@ private fun IrDeclarationWithVisibility.specialCaseVisibility(kind: OwnerKind?):
|
||||
return Opcodes.ACC_PRIVATE
|
||||
}
|
||||
|
||||
if (isInlineOnlyPrivateInBytecode() || isInlineOnlyPropertyAccessor()) {
|
||||
if (isInlineOnlyPrivateInBytecode()) {
|
||||
return Opcodes.ACC_PRIVATE
|
||||
}
|
||||
|
||||
@@ -223,26 +223,18 @@ private tailrec fun isInlineOrContainedInInline(declaration: IrDeclaration?): Bo
|
||||
|
||||
/* Borrowed from inlineOnly.kt */
|
||||
|
||||
fun IrDeclarationWithVisibility.isInlineOnlyOrReifiable(): Boolean =
|
||||
this is IrFunction && (isReifiable() || isInlineOnly())
|
||||
|
||||
fun IrDeclarationWithVisibility.isEffectivelyInlineOnly(): Boolean =
|
||||
isInlineOnlyOrReifiable() || isInlineOnlyPrivateInBytecode() || isInlineOnlyPropertyAccessor()
|
||||
this is IrFunction && (isReifiable() || isInlineOnly() || isPrivateInlineSuspend())
|
||||
|
||||
fun IrDeclarationWithVisibility.isInlineOnlyPrivateInBytecode(): Boolean =
|
||||
(this is IrFunction && isInlineOnly()) || isPrivateInlineSuspend()
|
||||
private fun IrDeclarationWithVisibility.isInlineOnlyPrivateInBytecode(): Boolean =
|
||||
this is IrFunction && (isInlineOnly() || isPrivateInlineSuspend())
|
||||
|
||||
private fun IrDeclarationWithVisibility.isPrivateInlineSuspend(): Boolean =
|
||||
this is IrFunction && isSuspend && isInline && visibility == DescriptorVisibilities.PRIVATE
|
||||
|
||||
private fun IrDeclarationWithVisibility.isInlineOnlyPropertyAccessor(): Boolean {
|
||||
if (this !is IrSimpleFunction) return false
|
||||
val propertySymbol = correspondingPropertySymbol ?: return false
|
||||
return propertySymbol.owner.hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME)
|
||||
}
|
||||
private fun IrFunction.isPrivateInlineSuspend(): Boolean =
|
||||
isSuspend && isInline && visibility == DescriptorVisibilities.PRIVATE
|
||||
|
||||
fun IrFunction.isInlineOnly() =
|
||||
isInline && hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME)
|
||||
(isInline && hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME)) ||
|
||||
(this is IrSimpleFunction && correspondingPropertySymbol?.owner?.hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME) == true)
|
||||
|
||||
fun IrFunction.isReifiable() = typeParameters.any { it.isReified }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user