From b6e9f64e184171139b5e1f9650c462c1ecc995d7 Mon Sep 17 00:00:00 2001 From: pyos Date: Thu, 27 May 2021 17:34:41 +0200 Subject: [PATCH] JVM: remove functionDescriptor from InlineCodegen --- .../kotlin/codegen/inline/InlineCodegen.kt | 51 +++---------------- .../kotlin/codegen/inline/PsiInlineCodegen.kt | 7 +-- .../inline/PsiSourceCompilerForInline.kt | 24 ++++----- .../codegen/inline/SourceCompilerForInline.kt | 17 +++++++ .../backend/jvm/codegen/IrInlineCodegen.kt | 8 +-- .../jvm/codegen/IrSourceCompilerForInline.kt | 4 ++ .../backend/jvm/codegen/irCodegenUtils.kt | 24 +++------ 7 files changed, 52 insertions(+), 83 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt index b81adf8b1d1..c51098d36ee 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt @@ -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( 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( 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( 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 ?: "") + if (generateNodeText) "\nCause: " + node.nodeText else "", @@ -81,13 +61,13 @@ abstract class InlineCodegen( 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( // // 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( 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( 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( // 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( 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 diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt index 9befc9b13cd..e05df6b253c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt @@ -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, sourceCompiler: SourceCompilerForInline, private val methodOwner: Type, private val actualDispatchReceiver: Type ) : InlineCodegen( - 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() } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiSourceCompilerForInline.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiSourceCompilerForInline.kt index 3fd74e47a9b..fbf1cc89c07 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiSourceCompilerForInline.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiSourceCompilerForInline.kt @@ -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() diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt index 96947988555..04ca767f055 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt @@ -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, diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt index caad268137f..f491d8adbf2 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt @@ -41,9 +41,7 @@ class IrInlineCodegen( sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner ) : - InlineCodegen( - codegen, state, function.toIrBasedDescriptor(), signature, typeParameterMappings, sourceCompiler, reifiedTypeInliner - ), + InlineCodegen(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 { - if (maskStartIndex == -1) return listOf() return expandMaskConditionsAndUpdateVariableNodes( node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex, extractDefaultLambdaOffsetAndDescriptor(jvmSignature, function), 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 331c1e935aa..6c9e4115bfd 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 @@ -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) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt index af6e074061c..e57b1c0d5da 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt @@ -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 }