[IR] Optimize a few hot spots to reduce total CPU time
^KT-61121
This commit is contained in:
+3
-3
@@ -284,11 +284,11 @@ class FakeOverrideBuilder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun provideFakeOverrides() {
|
fun provideFakeOverrides() {
|
||||||
val entries = fakeOverrideCandidates.entries
|
val entries = fakeOverrideCandidates.entries.toMutableList()
|
||||||
while (entries.isNotEmpty()) {
|
while (entries.isNotEmpty()) {
|
||||||
val candidate = entries.last()
|
val candidate = entries.removeLast()
|
||||||
entries.remove(candidate)
|
|
||||||
provideFakeOverrides(candidate.key, candidate.value)
|
provideFakeOverrides(candidate.key, candidate.value)
|
||||||
}
|
}
|
||||||
|
fakeOverrideCandidates.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,9 @@ data class File constructor(internal val javaPath: Path) {
|
|||||||
get() = javaPath.toAbsolutePath().toString()
|
get() = javaPath.toAbsolutePath().toString()
|
||||||
val absoluteFile: File
|
val absoluteFile: File
|
||||||
get() = File(absolutePath)
|
get() = File(absolutePath)
|
||||||
val canonicalPath: String
|
val canonicalPath: String by lazy {
|
||||||
get() = javaPath.toFile().canonicalPath
|
javaPath.toFile().canonicalPath
|
||||||
|
}
|
||||||
val canonicalFile: File
|
val canonicalFile: File
|
||||||
get() = File(canonicalPath)
|
get() = File(canonicalPath)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
|||||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||||
import org.jetbrains.kotlin.library.metadata.*
|
import org.jetbrains.kotlin.library.metadata.*
|
||||||
import org.jetbrains.kotlin.library.unresolvedDependencies
|
import org.jetbrains.kotlin.library.hasDependencies
|
||||||
import org.jetbrains.kotlin.name.NativeForwardDeclarationKind
|
import org.jetbrains.kotlin.name.NativeForwardDeclarationKind
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.name.parentOrNull
|
import org.jetbrains.kotlin.name.parentOrNull
|
||||||
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.serialization.deserialization.*
|
|||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
|
|
||||||
private val ModuleDescriptorImpl.isStdlibModule
|
private val ModuleDescriptorImpl.isStdlibModule
|
||||||
get() = (this.klibModuleOrigin as? DeserializedKlibModuleOrigin)?.library?.unresolvedDependencies?.isEmpty() ?: false
|
get() = (this.klibModuleOrigin as? DeserializedKlibModuleOrigin)?.library?.let { !it.hasDependencies } ?: false
|
||||||
|
|
||||||
class KlibMetadataModuleDescriptorFactoryImpl(
|
class KlibMetadataModuleDescriptorFactoryImpl(
|
||||||
override val descriptorFactory: KlibModuleDescriptorFactory,
|
override val descriptorFactory: KlibModuleDescriptorFactory,
|
||||||
|
|||||||
+14
-9
@@ -91,18 +91,23 @@ class KlibResolvedModuleDescriptorsFactoryImpl(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Set inter-dependencies between module descriptors, add forwarding declarations module.
|
// Set inter-dependencies between module descriptors, add forwarding declarations module.
|
||||||
|
val additionalDependencyModulesCopy = additionalDependencyModules.toSet()
|
||||||
|
val friendsForNonIncludedModule = additionalDependencyModulesCopy
|
||||||
|
val friendsForIncludedModule = buildSet<ModuleDescriptorImpl> {
|
||||||
|
this += friendsForNonIncludedModule
|
||||||
|
this += friendModuleDescriptors
|
||||||
|
this += refinesModuleDescriptors
|
||||||
|
}
|
||||||
|
val allDependencies = moduleDescriptors + additionalDependencyModulesCopy + forwardDeclarationsModule
|
||||||
for (module in moduleDescriptors) {
|
for (module in moduleDescriptors) {
|
||||||
val friends = additionalDependencyModules.toMutableSet()
|
val friends = if (module in includedLibraryDescriptors) {
|
||||||
if (module in includedLibraryDescriptors) {
|
friendsForIncludedModule
|
||||||
friends.addAll(friendModuleDescriptors)
|
} else {
|
||||||
friends.addAll(refinesModuleDescriptors)
|
friendsForNonIncludedModule
|
||||||
}
|
}
|
||||||
|
|
||||||
module.setDependencies(
|
// Yes, just to all of them.
|
||||||
// Yes, just to all of them.
|
module.setDependencies(allDependencies, friends)
|
||||||
moduleDescriptors + additionalDependencyModules + forwardDeclarationsModule,
|
|
||||||
friends
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return KotlinResolvedModuleDescriptors(
|
return KotlinResolvedModuleDescriptors(
|
||||||
|
|||||||
@@ -105,6 +105,9 @@ fun BaseKotlinLibrary.unresolvedDependencies(lenient: Boolean = false): List<Unr
|
|||||||
manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true)
|
manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true)
|
||||||
.map { UnresolvedLibrary(it, manifestProperties.getProperty("dependency_version_$it"), lenient = lenient) }
|
.map { UnresolvedLibrary(it, manifestProperties.getProperty("dependency_version_$it"), lenient = lenient) }
|
||||||
|
|
||||||
|
val BaseKotlinLibrary.hasDependencies: Boolean
|
||||||
|
get() = !manifestProperties.getProperty(KLIB_PROPERTY_DEPENDS).isNullOrBlank()
|
||||||
|
|
||||||
interface KotlinLibrary : BaseKotlinLibrary, MetadataLibrary, IrLibrary
|
interface KotlinLibrary : BaseKotlinLibrary, MetadataLibrary, IrLibrary
|
||||||
|
|
||||||
// TODO: should we move the below ones to Native?
|
// TODO: should we move the below ones to Native?
|
||||||
|
|||||||
+15
-4
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.konan.ir.konanLibrary
|
|||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.util.fileOrNull
|
import org.jetbrains.kotlin.ir.util.fileOrNull
|
||||||
|
import org.jetbrains.kotlin.backend.konan.llvm.KonanMetadata
|
||||||
import org.jetbrains.kotlin.ir.util.getPackageFragment
|
import org.jetbrains.kotlin.ir.util.getPackageFragment
|
||||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||||
|
|
||||||
@@ -28,10 +29,20 @@ internal abstract class LlvmModuleSpecificationBase(protected val cachedLibrarie
|
|||||||
override fun containsPackageFragment(packageFragment: IrPackageFragment): Boolean =
|
override fun containsPackageFragment(packageFragment: IrPackageFragment): Boolean =
|
||||||
packageFragment.konanLibrary.let { it == null || containsLibrary(it) }
|
packageFragment.konanLibrary.let { it == null || containsLibrary(it) }
|
||||||
|
|
||||||
override fun containsDeclaration(declaration: IrDeclaration): Boolean =
|
private val containsCache = mutableMapOf<IrDeclaration, Boolean>()
|
||||||
declaration.konanLibrary.let { it == null || containsLibrary(it) }
|
|
||||||
// When producing per-file caches, some declarations might be generated by the stub generator.
|
// This is essentially memoizing the IrDeclaration.konanLibrary property -- so much of the implementation
|
||||||
&& declaration.getPackageFragment() !is IrExternalPackageFragment
|
// is inlined here to take greater advantage of the cache.
|
||||||
|
override fun containsDeclaration(declaration: IrDeclaration): Boolean = containsCache.getOrPut(declaration) {
|
||||||
|
val metadata = ((declaration as? IrMetadataSourceOwner)?.metadata as? KonanMetadata)
|
||||||
|
if (metadata != null) {
|
||||||
|
(metadata.konanLibrary == null || containsLibrary(metadata.konanLibrary)) && declaration.getPackageFragment() !is IrExternalPackageFragment
|
||||||
|
} else when (val parent = declaration.parent) {
|
||||||
|
is IrPackageFragment -> parent.konanLibrary.let { it == null || containsLibrary(it) } && parent !is IrExternalPackageFragment
|
||||||
|
is IrDeclaration -> containsDeclaration(parent)
|
||||||
|
else -> TODO("Unexpected declaration parent: $parent")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class DefaultLlvmModuleSpecification(cachedLibraries: CachedLibraries)
|
internal class DefaultLlvmModuleSpecification(cachedLibraries: CachedLibraries)
|
||||||
|
|||||||
+2
-1
@@ -163,8 +163,9 @@ internal fun PsiToIrContext.psiToIr(
|
|||||||
var dependenciesCount = 0
|
var dependenciesCount = 0
|
||||||
while (true) {
|
while (true) {
|
||||||
// context.config.librariesWithDependencies could change at each iteration.
|
// context.config.librariesWithDependencies could change at each iteration.
|
||||||
|
val libsWithDeps = config.librariesWithDependencies().toSet()
|
||||||
val dependencies = moduleDescriptor.allDependencyModules.filter {
|
val dependencies = moduleDescriptor.allDependencyModules.filter {
|
||||||
config.librariesWithDependencies().contains(it.konanLibrary)
|
libsWithDeps.contains(it.konanLibrary)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sortDependencies(dependencies: List<ModuleDescriptor>): Collection<ModuleDescriptor> {
|
fun sortDependencies(dependencies: List<ModuleDescriptor>): Collection<ModuleDescriptor> {
|
||||||
|
|||||||
+2
@@ -110,6 +110,8 @@ val IrPackageFragment.konanLibrary : KotlinLibrary?
|
|||||||
}
|
}
|
||||||
return this.packageFragmentDescriptor.containingDeclaration.konanLibrary
|
return this.packageFragmentDescriptor.containingDeclaration.konanLibrary
|
||||||
}
|
}
|
||||||
|
// Any changes made to konanLibrary here should be ported to the containsDeclaration
|
||||||
|
// function in LlvmModuleSpecificationBase in LlvmModuleSpecificationImpl.kt
|
||||||
val IrDeclaration.konanLibrary: KotlinLibrary?
|
val IrDeclaration.konanLibrary: KotlinLibrary?
|
||||||
get() {
|
get() {
|
||||||
((this as? IrMetadataSourceOwner)?.metadata as? KonanMetadata)?.let { return it.konanLibrary }
|
((this as? IrMetadataSourceOwner)?.metadata as? KonanMetadata)?.let { return it.konanLibrary }
|
||||||
|
|||||||
+1
-1
@@ -1785,7 +1785,7 @@ private fun ObjCExportCodeGenerator.createDirectAdapters(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val inheritedAdapters = superClass?.getAllRequiredDirectAdapters().orEmpty()
|
val inheritedAdapters = superClass?.getAllRequiredDirectAdapters().orEmpty().toSet()
|
||||||
val requiredAdapters = typeDeclaration.getAllRequiredDirectAdapters() - inheritedAdapters
|
val requiredAdapters = typeDeclaration.getAllRequiredDirectAdapters() - inheritedAdapters
|
||||||
|
|
||||||
return requiredAdapters.distinctBy { it.base.selector }.map { createMethodAdapter(it) }
|
return requiredAdapters.distinctBy { it.base.selector }.map { createMethodAdapter(it) }
|
||||||
|
|||||||
+5
-5
@@ -43,7 +43,7 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass,
|
|||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
return when (expression.symbol) {
|
return when (expression.symbol) {
|
||||||
irBuiltins.eqeqSymbol, in ieee754EqualsSymbols() -> lowerEqeq(expression)
|
irBuiltins.eqeqSymbol, in ieee754EqualsSymbols -> lowerEqeq(expression)
|
||||||
|
|
||||||
irBuiltins.eqeqeqSymbol -> lowerEqeqeq(expression)
|
irBuiltins.eqeqeqSymbol -> lowerEqeqeq(expression)
|
||||||
|
|
||||||
@@ -70,8 +70,8 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass,
|
|||||||
return expression
|
return expression
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ieee754EqualsSymbols(): List<IrSimpleFunctionSymbol> =
|
private val ieee754EqualsSymbols: Set<IrSimpleFunctionSymbol> =
|
||||||
irBuiltins.ieee754equalsFunByOperandType.values.toList()
|
irBuiltins.ieee754equalsFunByOperandType.values.toSet()
|
||||||
|
|
||||||
private fun lowerEqeqeq(expression: IrCall): IrExpression {
|
private fun lowerEqeqeq(expression: IrCall): IrExpression {
|
||||||
val lhs = expression.getValueArgument(0)!!
|
val lhs = expression.getValueArgument(0)!!
|
||||||
@@ -191,7 +191,7 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass,
|
|||||||
// TODO: areEqualByValue and ieee754Equals intrinsics are specially treated by code generator
|
// TODO: areEqualByValue and ieee754Equals intrinsics are specially treated by code generator
|
||||||
// and thus can be declared synthetically in the compiler instead of explicitly in the runtime.
|
// and thus can be declared synthetically in the compiler instead of explicitly in the runtime.
|
||||||
fun callEquals(lhs: IrExpression, rhs: IrExpression) =
|
fun callEquals(lhs: IrExpression, rhs: IrExpression) =
|
||||||
if (symbol in ieee754EqualsSymbols())
|
if (symbol in ieee754EqualsSymbols)
|
||||||
// Find a type-compatible `konan.internal.ieee754Equals` intrinsic:
|
// Find a type-compatible `konan.internal.ieee754Equals` intrinsic:
|
||||||
irCall(selectIntrinsic(symbols.ieee754Equals, lhs.type, rhs.type, true)!!).apply {
|
irCall(selectIntrinsic(symbols.ieee754Equals, lhs.type, rhs.type, true)!!).apply {
|
||||||
putValueArgument(0, lhs)
|
putValueArgument(0, lhs)
|
||||||
@@ -206,7 +206,7 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass,
|
|||||||
val lhsIsNotNullable = !lhs.type.isNullable()
|
val lhsIsNotNullable = !lhs.type.isNullable()
|
||||||
val rhsIsNotNullable = !rhs.type.isNullable()
|
val rhsIsNotNullable = !rhs.type.isNullable()
|
||||||
|
|
||||||
return if (symbol in ieee754EqualsSymbols()) {
|
return if (symbol in ieee754EqualsSymbols) {
|
||||||
if (lhsIsNotNullable && rhsIsNotNullable)
|
if (lhsIsNotNullable && rhsIsNotNullable)
|
||||||
callEquals(lhs, rhs)
|
callEquals(lhs, rhs)
|
||||||
else irBlock {
|
else irBlock {
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ internal class PreInlineLowering(val context: Context) : BodyLoweringPass {
|
|||||||
|
|
||||||
private val symbols get() = context.ir.symbols
|
private val symbols get() = context.ir.symbols
|
||||||
|
|
||||||
private val asserts = symbols.asserts
|
private val asserts = symbols.asserts.toSet()
|
||||||
private val enableAssertions = context.config.configuration.getBoolean(KonanConfigKeys.ENABLE_ASSERTIONS)
|
private val enableAssertions = context.config.configuration.getBoolean(KonanConfigKeys.ENABLE_ASSERTIONS)
|
||||||
|
|
||||||
override fun lower(irBody: IrBody, container: IrDeclaration) = lower(irBody, container, container.file)
|
override fun lower(irBody: IrBody, container: IrDeclaration) = lower(irBody, container, container.file)
|
||||||
|
|||||||
+2
-2
@@ -179,12 +179,12 @@ internal object StaticInitializersOptimization {
|
|||||||
val functionsRequiringGlobalInitializerCall = collectFunctionsRequiringInitializerCall(
|
val functionsRequiringGlobalInitializerCall = collectFunctionsRequiringInitializerCall(
|
||||||
initializedFiles.beforeCallGlobal,
|
initializedFiles.beforeCallGlobal,
|
||||||
callSitesRequiringGlobalInitializerCall.map { it.actualCallee }
|
callSitesRequiringGlobalInitializerCall.map { it.actualCallee }
|
||||||
.toMutableSet().intersect(callSitesNotRequiringGlobalInitializerCall.map { it.actualCallee })
|
.intersect(callSitesNotRequiringGlobalInitializerCall.mapTo(mutableSetOf()) { it.actualCallee })
|
||||||
)
|
)
|
||||||
val functionsRequiringThreadLocalInitializerCall = collectFunctionsRequiringInitializerCall(
|
val functionsRequiringThreadLocalInitializerCall = collectFunctionsRequiringInitializerCall(
|
||||||
initializedFiles.beforeCallThreadLocal,
|
initializedFiles.beforeCallThreadLocal,
|
||||||
callSitesRequiringThreadLocalInitializerCall.map { it.actualCallee }
|
callSitesRequiringThreadLocalInitializerCall.map { it.actualCallee }
|
||||||
.toMutableSet().intersect(callSitesNotRequiringThreadLocalInitializerCall.map { it.actualCallee })
|
.intersect(callSitesNotRequiringThreadLocalInitializerCall.mapTo(mutableSetOf()) { it.actualCallee })
|
||||||
)
|
)
|
||||||
|
|
||||||
return AnalysisResult(functionsRequiringGlobalInitializerCall, functionsRequiringThreadLocalInitializerCall,
|
return AnalysisResult(functionsRequiringGlobalInitializerCall, functionsRequiringThreadLocalInitializerCall,
|
||||||
|
|||||||
Reference in New Issue
Block a user