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 =
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));
}
}
@@ -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<out T: BaseExpressionCodegen>(
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<Unit>? = 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 ?: "<no source>") +
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<ExpressionCodegen>(codegen, state, function, typeParameterMappings, sourceCompiler), CallGenerator {
override fun genCallInner(
callableMethod: Callable,
@@ -23,7 +23,7 @@ class RootInliningContext(
expressionMap: Map<Int, LambdaInfo>,
state: GenerationState,
nameGenerator: NameGenerator,
val callElement: KtElement,
val sourceCompilerForInline: SourceCompilerForInline,
override val callSiteInfo: InlineCallSiteInfo,
val inlineMethodReifier: ReifiedTypeInliner,
typeParameterMappings: TypeParameterMappings
@@ -37,7 +37,7 @@ abstract class ObjectTransformer<out T : TransformationInfo>(@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(
@@ -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<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<*>>()
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<MethodInliner.PointForExternalFinallyBlocks>,
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<String> {
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)
}