From 9f736f21925535861c43316830758156cb3b9e9f Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Wed, 14 Jun 2017 14:09:50 +0200 Subject: [PATCH] Extract PsiSourceCompiler --- .../kotlin/codegen/ExpressionCodegen.java | 4 +- .../kotlin/codegen/inline/InlineCodegen.kt | 25 ++--- .../kotlin/codegen/inline/InliningContext.kt | 2 +- .../codegen/inline/ObjectTransformer.kt | 2 +- .../codegen/inline/SourceCompilerForInline.kt | 99 +++++++++++++++---- 5 files changed, 96 insertions(+), 36 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index db4db2d93ab..43736fccbd4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -2288,10 +2288,10 @@ public class ExpressionCodegen extends KtVisitor impleme FunctionDescriptor original = unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal())); if (isDefaultCompilation) { - return new InlineCodegenForDefaultBody(original, this, state, new SourceCompilerForInline(this)); + return new InlineCodegenForDefaultBody(original, this, state, new PsiSourceCompilerForInline(this, callElement)); } else { - return new PsiInlineCodegen(this, state, original, callElement, typeParameterMappings, new SourceCompilerForInline(this)); + return new PsiInlineCodegen(this, state, original, typeParameterMappings, new PsiSourceCompilerForInline(this, callElement)); } } 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 cbb6fa66a1b..bc4b3772edf 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt @@ -29,7 +29,6 @@ import org.jetbrains.kotlin.codegen.intrinsics.classId import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.isInlineOnly -import org.jetbrains.kotlin.incremental.KotlinLookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.renderer.DescriptorRenderer @@ -57,11 +56,10 @@ import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode import org.jetbrains.org.objectweb.asm.tree.MethodNode import java.util.* -abstract class InlineCodegen( - protected val codegen: BaseExpressionCodegen, +abstract class InlineCodegen( + protected val codegen: T, protected val state: GenerationState, function: FunctionDescriptor, - private val callElement: KtElement, private val typeParameterMappings: TypeParameterMappings, protected val sourceCompiler: SourceCompilerForInline ) { @@ -96,7 +94,7 @@ abstract class InlineCodegen( protected var activeLambda: LambdaInfo? = null - private val sourceMapper = sourceCompiler.lazySourceMapper + private val defaultSourceMapper = sourceCompiler.lazySourceMapper protected var delayedHiddenWriting: Function0? = null @@ -116,7 +114,7 @@ abstract class InlineCodegen( if (functionOrAccessorName != functionDescriptor.name.asString()) { val scope = getMemberScope(functionDescriptor) //Fake lookup to track track changes for property accessors and @JvmName functions/property accessors - scope?.getContributedFunctions(Name.identifier(functionOrAccessorName), KotlinLookupLocation(callElement)) + scope?.getContributedFunctions(Name.identifier(functionOrAccessorName), sourceCompiler.lookupLocation) } } } @@ -133,7 +131,7 @@ abstract class InlineCodegen( DescriptorRenderer.DEBUG_TEXT.render(contextDescriptor) + "\n" + (element?.text ?: "") + if (generateNodeText) "\nCause: " + node.nodeText else "", - e, callElement + e, sourceCompiler.callElement as? PsiElement ) } @@ -186,7 +184,6 @@ abstract class InlineCodegen( protected fun inlineCall(nodeAndSmap: SMAPAndMethodNode, callDefault: Boolean): InlineResult { assert(delayedHiddenWriting == null) { "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'" } - val defaultSourceMapper = sourceMapper defaultSourceMapper.callSiteMarker = CallSiteMarker(codegen.lastLineNumber) val node = nodeAndSmap.node if (callDefault) { @@ -212,13 +209,13 @@ abstract class InlineCodegen( val info = RootInliningContext( expressionMap, state, codegen.inlineNameGenerator.subGenerator(jvmSignature.asmMethod.name), - callElement, sourceCompiler.inlineCallSiteInfo, reifiedTypeInliner, typeParameterMappings + sourceCompiler, sourceCompiler.inlineCallSiteInfo, reifiedTypeInliner, typeParameterMappings ) val inliner = MethodInliner( node, parameters, info, FieldRemapper(null, null, parameters), isSameModule, - "Method inlining " + callElement.text, - createNestedSourceMapper(nodeAndSmap, sourceMapper), info.callSiteInfo, + "Method inlining " + sourceCompiler.callElementText, + createNestedSourceMapper(nodeAndSmap, defaultSourceMapper), info.callSiteInfo, if (functionDescriptor.isInlineOnly()) InlineOnlySmapSkipper(codegen) else null ) //with captured @@ -231,8 +228,7 @@ abstract class InlineCodegen( val result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL) result.reifiedTypeParametersUsages.mergeAll(reificationResult) - val descriptor = sourceCompiler.getLabelOwnerDescriptor() - val labels = getDeclarationLabels(DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor) + val labels = sourceCompiler.getContextLabels() val infos = MethodInliner.processReturns(adapter, LabelOwner { labels.contains(it) }, true, null) sourceCompiler.generateAndInsertFinallyBlocks( @@ -580,10 +576,9 @@ class PsiInlineCodegen( codegen: ExpressionCodegen, state: GenerationState, function: FunctionDescriptor, - callElement: KtElement, typeParameterMappings: TypeParameterMappings, sourceCompiler: SourceCompilerForInline -) : InlineCodegen(codegen, state, function, callElement, typeParameterMappings, sourceCompiler), CallGenerator { +) : InlineCodegen(codegen, state, function, typeParameterMappings, sourceCompiler), CallGenerator { override fun genCallInner( callableMethod: Callable, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.kt index 91c21fccd52..3a14f1145c5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.kt @@ -23,7 +23,7 @@ class RootInliningContext( expressionMap: Map, state: GenerationState, nameGenerator: NameGenerator, - val callElement: KtElement, + val sourceCompilerForInline: SourceCompilerForInline, override val callSiteInfo: InlineCallSiteInfo, val inlineMethodReifier: ReifiedTypeInliner, typeParameterMappings: TypeParameterMappings diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ObjectTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ObjectTransformer.kt index ad1b24585d2..04dbc390942 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ObjectTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ObjectTransformer.kt @@ -37,7 +37,7 @@ abstract class ObjectTransformer(@JvmField val trans val classBuilder = state.factory.newVisitor( JvmDeclarationOrigin.NO_ORIGIN, Type.getObjectType(transformationInfo.newClassName), - inliningContext.root.callElement.containingFile + inliningContext.root.sourceCompilerForInline.callsiteFile!! ) return RemappingClassBuilder( 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 218bc428ef8..b9fe3d0aad5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt @@ -16,11 +16,14 @@ package org.jetbrains.kotlin.codegen.inline +import com.intellij.psi.PsiFile import org.jetbrains.kotlin.backend.common.CodegenUtil import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.context.* import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.incremental.KotlinLookupLocation +import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -37,16 +40,75 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode import java.util.HashMap import kotlin.properties.Delegates -class SourceCompilerForInline(private val codegen: ExpressionCodegen) { +interface SourceCompilerForInline { + val state: GenerationState - val state = codegen.state + val callElement: Any + + val lookupLocation: LookupLocation + + val callElementText: String + + val callsiteFile: PsiFile? + + val contextKind: OwnerKind + + val inlineCallSiteInfo: InlineCallSiteInfo + + val lazySourceMapper: DefaultSourceMapper + + fun generateLambdaBody(adapter: MethodVisitor, + jvmMethodSignature: JvmMethodSignature, + lambdaInfo: ExpressionLambda): SMAP + + fun doCreateMethodNodeFromSource( + callableDescriptor: FunctionDescriptor, + jvmSignature: JvmMethodSignature, + callDefault: Boolean, + asmMethod: Method + ): SMAPAndMethodNode + + fun generateAndInsertFinallyBlocks( + intoNode: MethodNode, + insertPoints: List, + offsetForFinallyLocalVar: Int + ) + + fun isCallInsideSameModuleAsDeclared(functionDescriptor: FunctionDescriptor): Boolean + + fun isFinallyMarkerRequired(): Boolean + + val compilationContextDescriptor: DeclarationDescriptor + + val compilationContextFunctionDescriptor: FunctionDescriptor + + fun getContextLabels(): Set + + fun initializeInlineFunctionContext(functionDescriptor: FunctionDescriptor) +} + + +class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, override val callElement: KtElement): SourceCompilerForInline { + + override val state = codegen.state private var context by Delegates.notNull>() - val contextKind + override val lookupLocation = KotlinLookupLocation(callElement) + + + override val callElementText by lazy { + callElement.text + } + + override val callsiteFile by lazy { + callElement.containingFile + } + + override val contextKind get () = context.contextKind - val inlineCallSiteInfo: InlineCallSiteInfo + override val inlineCallSiteInfo: InlineCallSiteInfo get() { var context = codegen.getContext() var parentCodegen = codegen.parentCodegen @@ -65,10 +127,10 @@ class SourceCompilerForInline(private val codegen: ExpressionCodegen) { ) } - val lazySourceMapper + override val lazySourceMapper get() = codegen.parentCodegen.orCreateSourceMapper - fun generateLambdaBody(adapter: MethodVisitor, + override fun generateLambdaBody(adapter: MethodVisitor, jvmMethodSignature: JvmMethodSignature, lambdaInfo: ExpressionLambda): SMAP { val invokeMethodDescriptor = lambdaInfo.invokeMethodDescriptor @@ -179,6 +241,7 @@ class SourceCompilerForInline(private val codegen: ExpressionCodegen) { override fun getInlineNameGenerator(): NameGenerator { return delegate.inlineNameGenerator } + override //TODO: obtain name from context fun getClassName(): String { return className @@ -186,7 +249,7 @@ class SourceCompilerForInline(private val codegen: ExpressionCodegen) { } - fun doCreateMethodNodeFromSource( + override fun doCreateMethodNodeFromSource( callableDescriptor: FunctionDescriptor, jvmSignature: JvmMethodSignature, callDefault: Boolean, @@ -236,7 +299,7 @@ class SourceCompilerForInline(private val codegen: ExpressionCodegen) { return SMAPAndMethodNode(node, smap) } - fun generateAndInsertFinallyBlocks( + override fun generateAndInsertFinallyBlocks( intoNode: MethodNode, insertPoints: List, offsetForFinallyLocalVar: Int @@ -302,29 +365,31 @@ class SourceCompilerForInline(private val codegen: ExpressionCodegen) { //processor.substituteLocalVarTable(intoNode); } - fun isCallInsideSameModuleAsDeclared(functionDescriptor: FunctionDescriptor) : Boolean { + override fun isCallInsideSameModuleAsDeclared(functionDescriptor: FunctionDescriptor): Boolean { return JvmCodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext(), codegen.state.outDirectory) } - fun isFinallyMarkerRequired(): Boolean = isFinallyMarkerRequired(codegen.getContext()) + override fun isFinallyMarkerRequired(): Boolean = isFinallyMarkerRequired(codegen.getContext()) - val compilationContextDescriptor + override val compilationContextDescriptor get() = codegen.getContext().contextDescriptor - val compilationContextFunctionDescriptor + override val compilationContextFunctionDescriptor get() = codegen.getContext().functionDescriptor - fun getLabelOwnerDescriptor(): CallableMemberDescriptor { + override fun getContextLabels(): Set { val context = codegen.getContext() val parentContext = context.parentContext - if (parentContext is ClosureContext && parentContext.originalSuspendLambdaDescriptor != null) { - return parentContext.originalSuspendLambdaDescriptor!! + val descriptor = if (parentContext is ClosureContext && parentContext.originalSuspendLambdaDescriptor != null) { + parentContext.originalSuspendLambdaDescriptor!! } - return context.contextDescriptor + else context.contextDescriptor + + return InlineCodegen.getDeclarationLabels(DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor) } - fun initializeInlineFunctionContext(functionDescriptor: FunctionDescriptor) { + override fun initializeInlineFunctionContext(functionDescriptor: FunctionDescriptor) { context = getContext(functionDescriptor, state, DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile) }