JS IR IC: add a flag for DCE hack
The deserialized PIR does not support declaration mutation. Until that's fixed the associatedObject removal optimization has to be disabled.
This commit is contained in:
committed by
teamcityserver
parent
508d3bd9c0
commit
4cee44cd6e
@@ -29,18 +29,20 @@ import java.util.*
|
||||
|
||||
fun eliminateDeadDeclarations(
|
||||
modules: Iterable<IrModuleFragment>,
|
||||
context: JsIrBackendContext
|
||||
context: JsIrBackendContext,
|
||||
removeUnusedAssociatedObjects: Boolean = true,
|
||||
) {
|
||||
|
||||
val allRoots = context.irFactory.stageController.withInitialIr { buildRoots(modules, context) }
|
||||
|
||||
val usefulDeclarations = usefulDeclarations(allRoots, context)
|
||||
val usefulDeclarations = usefulDeclarations(allRoots, context, removeUnusedAssociatedObjects)
|
||||
|
||||
context.irFactory.stageController.unrestrictDeclarationListsAccess {
|
||||
processUselessDeclarations(
|
||||
modules,
|
||||
usefulDeclarations,
|
||||
context
|
||||
context,
|
||||
removeUnusedAssociatedObjects,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -111,7 +113,8 @@ private fun buildRoots(modules: Iterable<IrModuleFragment>, context: JsIrBackend
|
||||
private fun processUselessDeclarations(
|
||||
modules: Iterable<IrModuleFragment>,
|
||||
usefulDeclarations: Set<IrDeclaration>,
|
||||
context: JsIrBackendContext
|
||||
context: JsIrBackendContext,
|
||||
removeUnusedAssociatedObjects: Boolean,
|
||||
) {
|
||||
modules.forEach { module ->
|
||||
module.files.forEach {
|
||||
@@ -136,7 +139,7 @@ private fun processUselessDeclarations(
|
||||
// Remove annotations for `findAssociatedObject` feature, which reference objects eliminated by the DCE.
|
||||
// Otherwise `JsClassGenerator.generateAssociatedKeyProperties` will try to reference the object factory (which is removed).
|
||||
// That will result in an error from the Namer. It cannot generate a name for an absent declaration.
|
||||
if (declaration.annotations.any { !it.shouldKeepAnnotation() }) {
|
||||
if (removeUnusedAssociatedObjects && declaration.annotations.any { !it.shouldKeepAnnotation() }) {
|
||||
declaration.annotations = declaration.annotations.filter { it.shouldKeepAnnotation() }
|
||||
}
|
||||
}
|
||||
@@ -216,7 +219,11 @@ private fun IrField.isKotlinPackage() =
|
||||
fqNameWhenAvailable?.asString()?.startsWith("kotlin") == true
|
||||
|
||||
// TODO refactor it, the function became too big. Please contact me (Zalim) before doing it.
|
||||
fun usefulDeclarations(roots: Iterable<IrDeclaration>, context: JsIrBackendContext): Set<IrDeclaration> {
|
||||
fun usefulDeclarations(
|
||||
roots: Iterable<IrDeclaration>,
|
||||
context: JsIrBackendContext,
|
||||
removeUnusedAssociatedObjects: Boolean,
|
||||
): Set<IrDeclaration> {
|
||||
val printReachabilityInfo =
|
||||
context.configuration.getBoolean(JSConfigurationKeys.PRINT_REACHABILITY_INFO) ||
|
||||
java.lang.Boolean.getBoolean("kotlin.js.ir.dce.print.reachability.info")
|
||||
@@ -479,11 +486,11 @@ fun usefulDeclarations(roots: Iterable<IrDeclaration>, context: JsIrBackendConte
|
||||
// Handle objects, constructed via `findAssociatedObject` annotation
|
||||
referencedJsClassesFromExpressions += constructedClasses.filterDescendantsOf(referencedJsClassesFromExpressions) // Grow the set of possible results of instance::class expression
|
||||
for (klass in classesWithObjectAssociations) {
|
||||
if (klass !in referencedJsClasses && klass !in referencedJsClassesFromExpressions) continue
|
||||
if (removeUnusedAssociatedObjects && klass !in referencedJsClasses && klass !in referencedJsClassesFromExpressions) continue
|
||||
|
||||
for (annotation in klass.annotations) {
|
||||
val annotationClass = annotation.symbol.owner.constructedClass
|
||||
if (annotationClass !in referencedJsClasses) continue
|
||||
if (removeUnusedAssociatedObjects && annotationClass !in referencedJsClasses) continue
|
||||
|
||||
annotation.associatedObject()?.let { obj ->
|
||||
context.mapping.objectToGetInstanceFunction[obj]?.enqueue(klass, "associated object factory")
|
||||
|
||||
@@ -193,6 +193,7 @@ fun icCompile(
|
||||
multiModule = multiModule,
|
||||
relativeRequirePath = relativeRequirePath,
|
||||
moduleToName = moduleToName,
|
||||
removeUnusedAssociatedObjects = false,
|
||||
)
|
||||
|
||||
irFactory.stageController = object : StageController(999) {}
|
||||
|
||||
+2
-1
@@ -41,6 +41,7 @@ class IrModuleToJsTransformer(
|
||||
private val multiModule: Boolean = false,
|
||||
private val relativeRequirePath: Boolean = false,
|
||||
private val moduleToName: Map<IrModuleFragment, String> = emptyMap(),
|
||||
private val removeUnusedAssociatedObjects: Boolean = true,
|
||||
) {
|
||||
private val generateRegionComments = backendContext.configuration.getBoolean(JSConfigurationKeys.GENERATE_REGION_COMMENTS)
|
||||
|
||||
@@ -69,7 +70,7 @@ class IrModuleToJsTransformer(
|
||||
val jsCode = if (fullJs) generateWrappedModuleBody(modules, exportedModule, namer) else null
|
||||
|
||||
val dceJsCode = if (dceJs) {
|
||||
eliminateDeadDeclarations(modules, backendContext)
|
||||
eliminateDeadDeclarations(modules, backendContext, removeUnusedAssociatedObjects)
|
||||
// Use a fresh namer for DCE so that we could compare the result with DCE-driven
|
||||
// TODO: is this mode relevant for scripting? If yes, refactor so that the external name tables are used here when needed.
|
||||
val namer = NameTables(emptyList(), context = backendContext)
|
||||
|
||||
Reference in New Issue
Block a user