Extract PsiSourceCompiler

This commit is contained in:
Mikhael Bogdanov
2017-06-14 14:09:50 +02:00
parent 2507780e19
commit 9f736f2192
5 changed files with 96 additions and 36 deletions
@@ -2288,10 +2288,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
FunctionDescriptor original = FunctionDescriptor original =
unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal())); unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal()));
if (isDefaultCompilation) { if (isDefaultCompilation) {
return new InlineCodegenForDefaultBody(original, this, state, new SourceCompilerForInline(this)); return new InlineCodegenForDefaultBody(original, this, state, new PsiSourceCompilerForInline(this, callElement));
} }
else { else {
return new PsiInlineCodegen(this, state, original, callElement, typeParameterMappings, new SourceCompilerForInline(this)); return new PsiInlineCodegen(this, state, original, typeParameterMappings, new PsiSourceCompilerForInline(this, callElement));
} }
} }
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.codegen.intrinsics.classId
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.isInlineOnly import org.jetbrains.kotlin.descriptors.annotations.isInlineOnly
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.renderer.DescriptorRenderer 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 org.jetbrains.org.objectweb.asm.tree.MethodNode
import java.util.* import java.util.*
abstract class InlineCodegen( abstract class InlineCodegen<out T: BaseExpressionCodegen>(
protected val codegen: BaseExpressionCodegen, protected val codegen: T,
protected val state: GenerationState, protected val state: GenerationState,
function: FunctionDescriptor, function: FunctionDescriptor,
private val callElement: KtElement,
private val typeParameterMappings: TypeParameterMappings, private val typeParameterMappings: TypeParameterMappings,
protected val sourceCompiler: SourceCompilerForInline protected val sourceCompiler: SourceCompilerForInline
) { ) {
@@ -96,7 +94,7 @@ abstract class InlineCodegen(
protected var activeLambda: LambdaInfo? = null protected var activeLambda: LambdaInfo? = null
private val sourceMapper = sourceCompiler.lazySourceMapper private val defaultSourceMapper = sourceCompiler.lazySourceMapper
protected var delayedHiddenWriting: Function0<Unit>? = null protected var delayedHiddenWriting: Function0<Unit>? = null
@@ -116,7 +114,7 @@ abstract class InlineCodegen(
if (functionOrAccessorName != functionDescriptor.name.asString()) { if (functionOrAccessorName != functionDescriptor.name.asString()) {
val scope = getMemberScope(functionDescriptor) val scope = getMemberScope(functionDescriptor)
//Fake lookup to track track changes for property accessors and @JvmName functions/property accessors //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" + DescriptorRenderer.DEBUG_TEXT.render(contextDescriptor) + "\n" +
(element?.text ?: "<no source>") + (element?.text ?: "<no source>") +
if (generateNodeText) "\nCause: " + node.nodeText else "", 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 { protected fun inlineCall(nodeAndSmap: SMAPAndMethodNode, callDefault: Boolean): InlineResult {
assert(delayedHiddenWriting == null) { "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'" } assert(delayedHiddenWriting == null) { "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'" }
val defaultSourceMapper = sourceMapper
defaultSourceMapper.callSiteMarker = CallSiteMarker(codegen.lastLineNumber) defaultSourceMapper.callSiteMarker = CallSiteMarker(codegen.lastLineNumber)
val node = nodeAndSmap.node val node = nodeAndSmap.node
if (callDefault) { if (callDefault) {
@@ -212,13 +209,13 @@ abstract class InlineCodegen(
val info = RootInliningContext( val info = RootInliningContext(
expressionMap, state, codegen.inlineNameGenerator.subGenerator(jvmSignature.asmMethod.name), expressionMap, state, codegen.inlineNameGenerator.subGenerator(jvmSignature.asmMethod.name),
callElement, sourceCompiler.inlineCallSiteInfo, reifiedTypeInliner, typeParameterMappings sourceCompiler, sourceCompiler.inlineCallSiteInfo, reifiedTypeInliner, typeParameterMappings
) )
val inliner = MethodInliner( val inliner = MethodInliner(
node, parameters, info, FieldRemapper(null, null, parameters), isSameModule, node, parameters, info, FieldRemapper(null, null, parameters), isSameModule,
"Method inlining " + callElement.text, "Method inlining " + sourceCompiler.callElementText,
createNestedSourceMapper(nodeAndSmap, sourceMapper), info.callSiteInfo, createNestedSourceMapper(nodeAndSmap, defaultSourceMapper), info.callSiteInfo,
if (functionDescriptor.isInlineOnly()) InlineOnlySmapSkipper(codegen) else null if (functionDescriptor.isInlineOnly()) InlineOnlySmapSkipper(codegen) else null
) //with captured ) //with captured
@@ -231,8 +228,7 @@ abstract class InlineCodegen(
val result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL) val result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL)
result.reifiedTypeParametersUsages.mergeAll(reificationResult) result.reifiedTypeParametersUsages.mergeAll(reificationResult)
val descriptor = sourceCompiler.getLabelOwnerDescriptor() val labels = sourceCompiler.getContextLabels()
val labels = getDeclarationLabels(DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor)
val infos = MethodInliner.processReturns(adapter, LabelOwner { labels.contains(it) }, true, null) val infos = MethodInliner.processReturns(adapter, LabelOwner { labels.contains(it) }, true, null)
sourceCompiler.generateAndInsertFinallyBlocks( sourceCompiler.generateAndInsertFinallyBlocks(
@@ -580,10 +576,9 @@ class PsiInlineCodegen(
codegen: ExpressionCodegen, codegen: ExpressionCodegen,
state: GenerationState, state: GenerationState,
function: FunctionDescriptor, function: FunctionDescriptor,
callElement: KtElement,
typeParameterMappings: TypeParameterMappings, typeParameterMappings: TypeParameterMappings,
sourceCompiler: SourceCompilerForInline sourceCompiler: SourceCompilerForInline
) : InlineCodegen(codegen, state, function, callElement, typeParameterMappings, sourceCompiler), CallGenerator { ) : InlineCodegen<ExpressionCodegen>(codegen, state, function, typeParameterMappings, sourceCompiler), CallGenerator {
override fun genCallInner( override fun genCallInner(
callableMethod: Callable, callableMethod: Callable,
@@ -23,7 +23,7 @@ class RootInliningContext(
expressionMap: Map<Int, LambdaInfo>, expressionMap: Map<Int, LambdaInfo>,
state: GenerationState, state: GenerationState,
nameGenerator: NameGenerator, nameGenerator: NameGenerator,
val callElement: KtElement, val sourceCompilerForInline: SourceCompilerForInline,
override val callSiteInfo: InlineCallSiteInfo, override val callSiteInfo: InlineCallSiteInfo,
val inlineMethodReifier: ReifiedTypeInliner, val inlineMethodReifier: ReifiedTypeInliner,
typeParameterMappings: TypeParameterMappings typeParameterMappings: TypeParameterMappings
@@ -37,7 +37,7 @@ abstract class ObjectTransformer<out T : TransformationInfo>(@JvmField val trans
val classBuilder = state.factory.newVisitor( val classBuilder = state.factory.newVisitor(
JvmDeclarationOrigin.NO_ORIGIN, JvmDeclarationOrigin.NO_ORIGIN,
Type.getObjectType(transformationInfo.newClassName), Type.getObjectType(transformationInfo.newClassName),
inliningContext.root.callElement.containingFile inliningContext.root.sourceCompilerForInline.callsiteFile!!
) )
return RemappingClassBuilder( return RemappingClassBuilder(
@@ -16,11 +16,14 @@
package org.jetbrains.kotlin.codegen.inline package org.jetbrains.kotlin.codegen.inline
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.backend.common.CodegenUtil import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.context.* import org.jetbrains.kotlin.codegen.context.*
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.* 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.psi.*
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -37,16 +40,75 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode
import java.util.HashMap import java.util.HashMap
import kotlin.properties.Delegates 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<MethodInliner.PointForExternalFinallyBlocks>,
offsetForFinallyLocalVar: Int
)
fun isCallInsideSameModuleAsDeclared(functionDescriptor: FunctionDescriptor): Boolean
fun isFinallyMarkerRequired(): Boolean
val compilationContextDescriptor: DeclarationDescriptor
val compilationContextFunctionDescriptor: FunctionDescriptor
fun getContextLabels(): Set<String>
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<CodegenContext<*>>() private var context by Delegates.notNull<CodegenContext<*>>()
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 get () = context.contextKind
val inlineCallSiteInfo: InlineCallSiteInfo override val inlineCallSiteInfo: InlineCallSiteInfo
get() { get() {
var context = codegen.getContext() var context = codegen.getContext()
var parentCodegen = codegen.parentCodegen var parentCodegen = codegen.parentCodegen
@@ -65,10 +127,10 @@ class SourceCompilerForInline(private val codegen: ExpressionCodegen) {
) )
} }
val lazySourceMapper override val lazySourceMapper
get() = codegen.parentCodegen.orCreateSourceMapper get() = codegen.parentCodegen.orCreateSourceMapper
fun generateLambdaBody(adapter: MethodVisitor, override fun generateLambdaBody(adapter: MethodVisitor,
jvmMethodSignature: JvmMethodSignature, jvmMethodSignature: JvmMethodSignature,
lambdaInfo: ExpressionLambda): SMAP { lambdaInfo: ExpressionLambda): SMAP {
val invokeMethodDescriptor = lambdaInfo.invokeMethodDescriptor val invokeMethodDescriptor = lambdaInfo.invokeMethodDescriptor
@@ -179,6 +241,7 @@ class SourceCompilerForInline(private val codegen: ExpressionCodegen) {
override fun getInlineNameGenerator(): NameGenerator { override fun getInlineNameGenerator(): NameGenerator {
return delegate.inlineNameGenerator return delegate.inlineNameGenerator
} }
override //TODO: obtain name from context override //TODO: obtain name from context
fun getClassName(): String { fun getClassName(): String {
return className return className
@@ -186,7 +249,7 @@ class SourceCompilerForInline(private val codegen: ExpressionCodegen) {
} }
fun doCreateMethodNodeFromSource( override fun doCreateMethodNodeFromSource(
callableDescriptor: FunctionDescriptor, callableDescriptor: FunctionDescriptor,
jvmSignature: JvmMethodSignature, jvmSignature: JvmMethodSignature,
callDefault: Boolean, callDefault: Boolean,
@@ -236,7 +299,7 @@ class SourceCompilerForInline(private val codegen: ExpressionCodegen) {
return SMAPAndMethodNode(node, smap) return SMAPAndMethodNode(node, smap)
} }
fun generateAndInsertFinallyBlocks( override fun generateAndInsertFinallyBlocks(
intoNode: MethodNode, intoNode: MethodNode,
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>, insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
offsetForFinallyLocalVar: Int offsetForFinallyLocalVar: Int
@@ -302,29 +365,31 @@ class SourceCompilerForInline(private val codegen: ExpressionCodegen) {
//processor.substituteLocalVarTable(intoNode); //processor.substituteLocalVarTable(intoNode);
} }
fun isCallInsideSameModuleAsDeclared(functionDescriptor: FunctionDescriptor) : Boolean { override fun isCallInsideSameModuleAsDeclared(functionDescriptor: FunctionDescriptor): Boolean {
return JvmCodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext(), codegen.state.outDirectory) 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 get() = codegen.getContext().contextDescriptor
val compilationContextFunctionDescriptor override val compilationContextFunctionDescriptor
get() = codegen.getContext().functionDescriptor get() = codegen.getContext().functionDescriptor
fun getLabelOwnerDescriptor(): CallableMemberDescriptor { override fun getContextLabels(): Set<String> {
val context = codegen.getContext() val context = codegen.getContext()
val parentContext = context.parentContext val parentContext = context.parentContext
if (parentContext is ClosureContext && parentContext.originalSuspendLambdaDescriptor != null) { val descriptor = if (parentContext is ClosureContext && parentContext.originalSuspendLambdaDescriptor != null) {
return parentContext.originalSuspendLambdaDescriptor!! 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) context = getContext(functionDescriptor, state, DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile)
} }