JVM IR: extract lowerings to a separate module
Together with extracting codegen to a separate (unrelated) module in the future, hopefully it'll speed up the build of JVM IR by making it more parallel, and helping incremental compilation to avoid recompiling code that depends on lowerings because of `implementation` dependency.
This commit is contained in:
@@ -238,6 +238,7 @@ val fe10CompilerModules = arrayOf(
|
||||
":compiler:frontend:cfg",
|
||||
":compiler:ir.psi2ir",
|
||||
":compiler:backend.jvm",
|
||||
":compiler:backend.jvm.lower",
|
||||
":compiler:backend.jvm:backend.jvm.entrypoint",
|
||||
":compiler:backend.js",
|
||||
":compiler:backend.wasm",
|
||||
|
||||
@@ -12,6 +12,7 @@ dependencies {
|
||||
compile(project(":compiler:backend-common"))
|
||||
compile(project(":compiler:backend"))
|
||||
compile(project(":compiler:backend.jvm"))
|
||||
implementation(project(":compiler:backend.jvm.lower"))
|
||||
implementation(project(":compiler:backend.jvm:backend.jvm.entrypoint"))
|
||||
compile(project(":compiler:ir.backend.common"))
|
||||
compile(project(":compiler:light-classes"))
|
||||
|
||||
@@ -11,7 +11,6 @@ dependencies {
|
||||
api(project(":compiler:backend.common.jvm"))
|
||||
compileOnly(project(":compiler:ir.tree.impl"))
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core", "asm-all", "guava", rootProject = rootProject) }
|
||||
compileOnly(intellijDep()) { includeJars("trove4j", rootProject = rootProject) }
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
||||
@@ -8,6 +8,7 @@ dependencies {
|
||||
api(project(":compiler:backend.jvm"))
|
||||
api(project(":compiler:ir.tree.impl"))
|
||||
api(project(":compiler:ir.serialization.jvm"))
|
||||
implementation(project(":compiler:backend.jvm.lower"))
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core", rootProject = rootProject) }
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":compiler:ir.tree"))
|
||||
api(project(":compiler:ir.backend.common"))
|
||||
api(project(":compiler:backend.jvm"))
|
||||
implementation(project(":compiler:ir.tree.impl"))
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core", rootProject = rootProject) }
|
||||
compileOnly(intellijDep()) { includeJars("trove4j", rootProject = rootProject) }
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" {
|
||||
projectDefault()
|
||||
}
|
||||
"test" {}
|
||||
}
|
||||
+1
-1
@@ -275,7 +275,7 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass
|
||||
|
||||
// Deal with existing function that override special bridge methods.
|
||||
if (!irFunction.isFakeOverride && specialBridge.methodInfo != null) {
|
||||
irFunction.rewriteSpecialMethodBody(targetMethod, specialBridge.signature, specialBridge.methodInfo)
|
||||
irFunction.rewriteSpecialMethodBody(targetMethod, specialBridge.signature, specialBridge.methodInfo!!)
|
||||
}
|
||||
|
||||
// For generic special bridge methods we need to generate bridges for generic overrides coming from Java or Kotlin interfaces.
|
||||
+1
-1
@@ -95,7 +95,7 @@ private class MoveOrCopyCompanionObjectFieldsLowering(val context: JvmBackendCon
|
||||
private val IrProperty.hasPublicVisibility: Boolean
|
||||
get() = !DescriptorVisibilities.isPrivate(visibility) && visibility != DescriptorVisibilities.PROTECTED
|
||||
|
||||
private fun makeAnonymousInitializerStatic(oldInitializer: IrAnonymousInitializer, newParent: IrClass) =
|
||||
private fun makeAnonymousInitializerStatic(oldInitializer: IrAnonymousInitializer, newParent: IrClass): IrAnonymousInitializer =
|
||||
with(oldInitializer) {
|
||||
val oldParent = parentAsClass
|
||||
val newSymbol = IrAnonymousInitializerSymbolImpl(newParent.symbol)
|
||||
+1
-1
@@ -243,7 +243,7 @@ private class ScriptsToClassesLowering(val context: JvmBackendContext) {
|
||||
|
||||
private fun IrClass.addSimplePropertyFrom(
|
||||
from: IrValueDeclaration,
|
||||
initializer: IrExpressionBodyImpl? = null
|
||||
initializer: IrExpressionBody? = null
|
||||
) {
|
||||
addProperty {
|
||||
updateFrom(from)
|
||||
@@ -37,7 +37,7 @@ object InlineClassAbi {
|
||||
* Unwraps inline class types to their underlying representation.
|
||||
* Returns null if the type cannot be unboxed.
|
||||
*/
|
||||
internal fun unboxType(type: IrType): IrType? {
|
||||
fun unboxType(type: IrType): IrType? {
|
||||
val klass = type.classOrNull?.owner ?: return null
|
||||
val representation = klass.inlineClassRepresentation ?: return null
|
||||
|
||||
@@ -118,24 +118,24 @@ object InlineClassAbi {
|
||||
get() = (this as IrSimpleFunction).correspondingPropertySymbol!!.owner.name
|
||||
}
|
||||
|
||||
internal val IrType.requiresMangling: Boolean
|
||||
val IrType.requiresMangling: Boolean
|
||||
get() {
|
||||
val irClass = erasedUpperBound
|
||||
return irClass.isInline && irClass.fqNameWhenAvailable != StandardNames.RESULT_FQ_NAME
|
||||
}
|
||||
|
||||
internal val IrFunction.fullValueParameterList: List<IrValueParameter>
|
||||
val IrFunction.fullValueParameterList: List<IrValueParameter>
|
||||
get() = listOfNotNull(extensionReceiverParameter) + valueParameters
|
||||
|
||||
internal val IrFunction.hasMangledParameters: Boolean
|
||||
val IrFunction.hasMangledParameters: Boolean
|
||||
get() = dispatchReceiverParameter != null && parentAsClass.isInline ||
|
||||
fullValueParameterList.any { it.type.requiresMangling } ||
|
||||
(this is IrConstructor && constructedClass.isInline)
|
||||
|
||||
internal val IrFunction.hasMangledReturnType: Boolean
|
||||
val IrFunction.hasMangledReturnType: Boolean
|
||||
get() = returnType.isInlineClassType() && parentClassOrNull?.isFileClass != true
|
||||
|
||||
internal val IrClass.inlineClassFieldName: Name
|
||||
val IrClass.inlineClassFieldName: Name
|
||||
get() = (inlineClassRepresentation ?: error("Not an inline class: ${render()}")).underlyingPropertyName
|
||||
|
||||
val IrFunction.isInlineClassFieldGetter: Boolean
|
||||
|
||||
@@ -65,8 +65,8 @@ class JvmBackendContext(
|
||||
val typeMapper = IrTypeMapper(this)
|
||||
val methodSignatureMapper = MethodSignatureMapper(this)
|
||||
|
||||
internal val innerClassesSupport = JvmInnerClassesSupport(irFactory)
|
||||
internal val cachedDeclarations = JvmCachedDeclarations(
|
||||
val innerClassesSupport = JvmInnerClassesSupport(irFactory)
|
||||
val cachedDeclarations = JvmCachedDeclarations(
|
||||
this, generatorExtensions.cachedFields
|
||||
)
|
||||
|
||||
@@ -82,27 +82,27 @@ class JvmBackendContext(
|
||||
|
||||
private val localClassType = ConcurrentHashMap<IrAttributeContainer, Type>()
|
||||
|
||||
internal fun getLocalClassType(container: IrAttributeContainer): Type? =
|
||||
fun getLocalClassType(container: IrAttributeContainer): Type? =
|
||||
localClassType[container.attributeOwnerId]
|
||||
|
||||
internal fun putLocalClassType(container: IrAttributeContainer, value: Type) {
|
||||
fun putLocalClassType(container: IrAttributeContainer, value: Type) {
|
||||
localClassType[container.attributeOwnerId] = value
|
||||
}
|
||||
|
||||
internal val isEnclosedInConstructor = ConcurrentHashMap.newKeySet<IrAttributeContainer>()
|
||||
val isEnclosedInConstructor = ConcurrentHashMap.newKeySet<IrAttributeContainer>()
|
||||
|
||||
internal val classCodegens = ConcurrentHashMap<IrClass, ClassCodegen>()
|
||||
|
||||
val localDelegatedProperties = ConcurrentHashMap<IrAttributeContainer, List<IrLocalDelegatedPropertySymbol>>()
|
||||
|
||||
internal val multifileFacadesToAdd = mutableMapOf<JvmClassName, MutableList<IrClass>>()
|
||||
val multifileFacadesToAdd = mutableMapOf<JvmClassName, MutableList<IrClass>>()
|
||||
val multifileFacadeForPart = mutableMapOf<IrClass, JvmClassName>()
|
||||
internal val multifileFacadeClassForPart = mutableMapOf<IrClass, IrClass>()
|
||||
internal val multifileFacadeMemberToPartMember = mutableMapOf<IrSimpleFunction, IrSimpleFunction>()
|
||||
val multifileFacadeClassForPart = mutableMapOf<IrClass, IrClass>()
|
||||
val multifileFacadeMemberToPartMember = mutableMapOf<IrSimpleFunction, IrSimpleFunction>()
|
||||
|
||||
internal val hiddenConstructors = ConcurrentHashMap<IrConstructor, IrConstructor>()
|
||||
val hiddenConstructors = ConcurrentHashMap<IrConstructor, IrConstructor>()
|
||||
|
||||
internal val collectionStubComputer = CollectionStubComputer(this)
|
||||
val collectionStubComputer = CollectionStubComputer(this)
|
||||
|
||||
private val overridesWithoutStubs = HashMap<IrSimpleFunction, List<IrSimpleFunctionSymbol>>()
|
||||
|
||||
@@ -113,8 +113,8 @@ class JvmBackendContext(
|
||||
fun getOverridesWithoutStubs(function: IrSimpleFunction): List<IrSimpleFunctionSymbol> =
|
||||
overridesWithoutStubs.getOrElse(function) { function.overriddenSymbols }
|
||||
|
||||
internal val bridgeLoweringCache = BridgeLoweringCache(this)
|
||||
internal val functionsWithSpecialBridges: MutableSet<IrFunction> = ConcurrentHashMap.newKeySet()
|
||||
val bridgeLoweringCache = BridgeLoweringCache(this)
|
||||
val functionsWithSpecialBridges: MutableSet<IrFunction> = ConcurrentHashMap.newKeySet()
|
||||
|
||||
override var inVerbosePhase: Boolean = false // TODO: needs parallelizing
|
||||
|
||||
@@ -130,7 +130,7 @@ class JvmBackendContext(
|
||||
|
||||
val inlineClassReplacements = MemoizedInlineClassReplacements(state.functionsWithInlineClassReturnTypesMangled, irFactory, this)
|
||||
|
||||
internal val continuationClassesVarsCountByType: MutableMap<IrAttributeContainer, Map<Type, Int>> = hashMapOf()
|
||||
val continuationClassesVarsCountByType: MutableMap<IrAttributeContainer, Map<Type, Int>> = hashMapOf()
|
||||
|
||||
val inlineMethodGenerationLock = Any()
|
||||
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ class MemoizedInlineClassReplacements(
|
||||
private val storageManager = LockBasedStorageManager("inline-class-replacements")
|
||||
private val propertyMap = ConcurrentHashMap<IrPropertySymbol, IrProperty>()
|
||||
|
||||
internal val originalFunctionForStaticReplacement: MutableMap<IrFunction, IrFunction> = ConcurrentHashMap()
|
||||
val originalFunctionForStaticReplacement: MutableMap<IrFunction, IrFunction> = ConcurrentHashMap()
|
||||
internal val originalFunctionForMethodReplacement: MutableMap<IrFunction, IrFunction> = ConcurrentHashMap()
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
internal class BridgeLoweringCache(private val context: JvmBackendContext) {
|
||||
class BridgeLoweringCache(private val context: JvmBackendContext) {
|
||||
private val specialBridgeMethods = SpecialBridgeMethods(context)
|
||||
|
||||
// TODO: consider moving this cache out to the backend context and using it everywhere throughout the codegen.
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.ir.util.isFromJava
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
internal class CollectionStubComputer(val context: JvmBackendContext) {
|
||||
class CollectionStubComputer(val context: JvmBackendContext) {
|
||||
private class LazyStubsForCollectionClass(
|
||||
override val readOnlyClass: IrClassSymbol,
|
||||
override val mutableClass: IrClassSymbol
|
||||
|
||||
+1
-1
@@ -450,7 +450,7 @@ private fun isBareTypeParameterWithNullableUpperBound(type: IrType): Boolean {
|
||||
|
||||
private val RETENTION_PARAMETER_NAME = Name.identifier("value")
|
||||
|
||||
internal fun IrClass.getAnnotationRetention(): KotlinRetention? {
|
||||
fun IrClass.getAnnotationRetention(): KotlinRetention? {
|
||||
val retentionArgument =
|
||||
getAnnotation(StandardNames.FqNames.retention)?.getValueArgument(RETENTION_PARAMETER_NAME)
|
||||
as? IrGetEnumValue ?: return null
|
||||
|
||||
+5
-5
@@ -108,7 +108,7 @@ internal fun IrFunction.continuationClass(): IrClass? =
|
||||
(body as? IrBlockBody)?.statements?.find { it is IrClass && it.origin == JvmLoweredDeclarationOrigin.CONTINUATION_CLASS }
|
||||
as IrClass?
|
||||
|
||||
internal fun IrFunction.continuationParameter(): IrValueParameter? = when {
|
||||
fun IrFunction.continuationParameter(): IrValueParameter? = when {
|
||||
isInvokeSuspendOfLambda() || isInvokeSuspendForInlineOfLambda() -> dispatchReceiverParameter
|
||||
else -> valueParameters.singleOrNull { it.origin == JvmLoweredDeclarationOrigin.CONTINUATION_CLASS }
|
||||
}
|
||||
@@ -120,7 +120,7 @@ private fun IrFunction.isInvokeSuspendForInlineOfLambda(): Boolean =
|
||||
origin == JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE
|
||||
&& parentAsClass.origin == JvmLoweredDeclarationOrigin.SUSPEND_LAMBDA
|
||||
|
||||
internal fun IrFunction.isInvokeSuspendOfContinuation(): Boolean =
|
||||
fun IrFunction.isInvokeSuspendOfContinuation(): Boolean =
|
||||
name.asString() == INVOKE_SUSPEND_METHOD_NAME && parentAsClass.origin == JvmLoweredDeclarationOrigin.CONTINUATION_CLASS
|
||||
|
||||
private fun IrFunction.isInvokeOfSuspendCallableReference(): Boolean =
|
||||
@@ -155,7 +155,7 @@ private val BRIDGE_ORIGINS = setOf(
|
||||
internal fun IrFunction.isNonBoxingSuspendDelegation(): Boolean =
|
||||
origin in BRIDGE_ORIGINS || isMultifileBridge() || isBridgeToSuspendImplMethod()
|
||||
|
||||
internal fun IrFunction.shouldContainSuspendMarkers(): Boolean = !isNonBoxingSuspendDelegation() &&
|
||||
fun IrFunction.shouldContainSuspendMarkers(): Boolean = !isNonBoxingSuspendDelegation() &&
|
||||
// These functions also contain a single `suspend` tail call, but if it returns an unboxed inline class value,
|
||||
// the return of it should be checked for a suspension and potentially boxed to satisfy an interface.
|
||||
origin != IrDeclarationOrigin.DELEGATED_MEMBER &&
|
||||
@@ -163,7 +163,7 @@ internal fun IrFunction.shouldContainSuspendMarkers(): Boolean = !isNonBoxingSus
|
||||
!isInvokeOfSuspendCallableReference() &&
|
||||
!isStaticInlineClassReplacementDelegatingCall()
|
||||
|
||||
internal fun IrFunction.hasContinuation(): Boolean = isInvokeSuspendOfLambda() ||
|
||||
fun IrFunction.hasContinuation(): Boolean = isInvokeSuspendOfLambda() ||
|
||||
isSuspend && shouldContainSuspendMarkers() &&
|
||||
// These are templates for the inliner; the continuation is borrowed from the caller method.
|
||||
!isEffectivelyInlineOnly() &&
|
||||
@@ -171,7 +171,7 @@ internal fun IrFunction.hasContinuation(): Boolean = isInvokeSuspendOfLambda() |
|
||||
origin != JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE &&
|
||||
origin != JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE
|
||||
|
||||
internal fun IrExpression?.isReadOfCrossinline(): Boolean = when (this) {
|
||||
fun IrExpression?.isReadOfCrossinline(): Boolean = when (this) {
|
||||
is IrGetValue -> (symbol.owner as? IrValueParameter)?.isCrossinline == true
|
||||
is IrGetField -> symbol.owner.origin == LocalDeclarationsLowering.DECLARATION_ORIGIN_FIELD_FOR_CROSSINLINE_CAPTURED_VALUE
|
||||
else -> false
|
||||
|
||||
+2
-2
@@ -308,7 +308,7 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
|
||||
|
||||
// Boxing is only necessary for 'remove(E): Boolean' of a MutableCollection<Int> implementation.
|
||||
// Otherwise this method might clash with 'remove(I): E' defined in the java.util.List JDK interface (mapped to kotlin 'removeAt').
|
||||
internal fun shouldBoxSingleValueParameterForSpecialCaseOfRemove(irFunction: IrFunction): Boolean {
|
||||
fun shouldBoxSingleValueParameterForSpecialCaseOfRemove(irFunction: IrFunction): Boolean {
|
||||
if (irFunction !is IrSimpleFunction) return false
|
||||
if (irFunction.name.asString() != "remove" && !irFunction.name.asString().startsWith("remove-")) return false
|
||||
if (irFunction.isFromJava()) return false
|
||||
@@ -425,7 +425,7 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
|
||||
return null
|
||||
}
|
||||
|
||||
internal fun mapCalleeToAsmMethod(function: IrSimpleFunction, isSuperCall: Boolean = false): Method =
|
||||
fun mapCalleeToAsmMethod(function: IrSimpleFunction, isSuperCall: Boolean = false): Method =
|
||||
mapAsmMethod(findSuperDeclaration(function, isSuperCall))
|
||||
|
||||
// Copied from KotlinTypeMapper.findSuperDeclaration.
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
|
||||
internal open class IrInlineReferenceLocator(private val context: JvmBackendContext) : IrElementVisitor<Unit, IrDeclaration?> {
|
||||
open class IrInlineReferenceLocator(private val context: JvmBackendContext) : IrElementVisitor<Unit, IrDeclaration?> {
|
||||
override fun visitElement(element: IrElement, data: IrDeclaration?) {
|
||||
element.acceptChildren(this, data)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ dependencies {
|
||||
testApi(project(":compiler:fir:entrypoint"))
|
||||
testApi(project(":compiler:cli"))
|
||||
testImplementation(project(":compiler:ir.tree.impl"))
|
||||
testImplementation(project(":compiler:backend.jvm.lower"))
|
||||
testImplementation(project(":compiler:backend.jvm:backend.jvm.entrypoint"))
|
||||
testImplementation(intellijCoreDep()) { includeJars("intellij-core") }
|
||||
|
||||
|
||||
@@ -116,6 +116,7 @@ include ":benchmarks",
|
||||
":compiler:backend.js",
|
||||
":compiler:backend.wasm",
|
||||
":compiler:backend.jvm",
|
||||
":compiler:backend.jvm.lower",
|
||||
":compiler:backend.jvm:backend.jvm.entrypoint",
|
||||
":compiler:backend-common",
|
||||
":compiler:backend",
|
||||
@@ -538,6 +539,7 @@ project(':compiler:ir.backend.common').projectDir = "$rootDir/compiler/ir/backen
|
||||
project(':compiler:backend.js').projectDir = "$rootDir/compiler/ir/backend.js" as File
|
||||
project(':compiler:backend.wasm').projectDir = "$rootDir/compiler/ir/backend.wasm" as File
|
||||
project(':compiler:backend.jvm').projectDir = "$rootDir/compiler/ir/backend.jvm" as File
|
||||
project(':compiler:backend.jvm.lower').projectDir = "$rootDir/compiler/ir/backend.jvm/lower" as File
|
||||
project(':compiler:backend.jvm:backend.jvm.entrypoint').projectDir = "$rootDir/compiler/ir/backend.jvm/entrypoint" as File
|
||||
project(':compiler:ir.serialization.common').projectDir = "$rootDir/compiler/ir/serialization.common" as File
|
||||
project(':compiler:ir.serialization.jvm').projectDir = "$rootDir/compiler/ir/serialization.jvm" as File
|
||||
|
||||
Reference in New Issue
Block a user