chore: initial commit.
diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/CompilerPhase.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/CompilerPhase.kt
index 35676cd..32d1a63 100644
--- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/CompilerPhase.kt
+++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/CompilerPhase.kt
@@ -36,6 +36,10 @@
val stickyPostconditions: Set<Checker<Output>> get() = emptySet()
}
+interface RepeatableCompilerPhase<in Context : CommonBackendContext, Input, Output> : CompilerPhase<Context, Input, Output> {
+ val changesAppeared: Boolean
+}
+
fun <Context : CommonBackendContext, Input, Output> CompilerPhase<Context, Input, Output>.invokeToplevel(
phaseConfig: PhaseConfig,
context: Context,
@@ -66,7 +70,7 @@
other(phaseState, data, context)
}
-class NamedCompilerPhase<in Context : CommonBackendContext, Data>(
+open class NamedCompilerPhase<in Context : CommonBackendContext, Data>(
val name: String,
val description: String,
val prerequisite: Set<NamedCompilerPhase<Context, *>> = emptySet(),
@@ -143,3 +147,24 @@
override fun toString() = "Compiler Phase @$name"
}
+
+open class RepeatableNamedCompilerPhase<in Context : CommonBackendContext, Data>(
+ name: String,
+ description: String,
+ prerequisite: Set<NamedCompilerPhase<Context, *>> = emptySet(),
+ private val lower: RepeatableCompilerPhase<Context, Data, Data>,
+ preconditions: Set<Checker<Data>> = emptySet(),
+ postconditions: Set<Checker<Data>> = emptySet(),
+) : RepeatableCompilerPhase<Context, Data, Data>, NamedCompilerPhase<Context, Data>(name, description, prerequisite, lower, preconditions, postconditions) {
+ final override var changesAppeared: Boolean = false
+
+ override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Data>, context: Context, input: Data): Data {
+ return super.invoke(phaseConfig, phaserState, context, input).also {
+ if (lower.changesAppeared) {
+ changesAppeared = true
+ }
+ }
+ }
+
+ fun reset() { changesAppeared = false }
+}
diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt
index 8b0e649..ca77879 100644
--- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt
+++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt
@@ -29,7 +29,7 @@
private fun ClassLoweringPass.runOnFilesPostfix(moduleFragment: IrModuleFragment) = moduleFragment.files.forEach { runOnFilePostfix(it) }
-private fun makeJsModulePhase(
+fun makeJsModulePhase(
lowering: (JsIrBackendContext) -> FileLoweringPass,
name: String,
description: String,
@@ -41,7 +41,7 @@
prerequisite = prerequisite
)
-private fun makeCustomJsModulePhase(
+fun makeCustomJsModulePhase(
op: (JsIrBackendContext, IrModuleFragment) -> Unit,
description: String,
name: String,
@@ -108,7 +108,7 @@
prerequisite: Set<Lowering> = emptySet()
) = DeclarationLowering(name, description, prerequisite.map { it.modulePhase }.toSet(), lowering)
-private fun makeBodyLoweringPhase(
+fun makeBodyLoweringPhase(
lowering: (JsIrBackendContext) -> BodyLoweringPass,
name: String,
description: String,
@@ -432,19 +432,6 @@
description = "Lowering which wrap boolean in external declarations with Boolean() call and add diagnostic for such cases"
)
-private val foldConstantLoweringPhase = makeBodyLoweringPhase(
- { FoldConstantLowering(it, true) },
- name = "FoldConstantLowering",
- description = "[Optimization] Constant Folding",
- prerequisite = setOf(propertyAccessorInlinerLoweringPhase)
-)
-
-private val computeStringTrimPhase = makeJsModulePhase(
- ::StringTrimLowering,
- name = "StringTrimLowering",
- description = "Compute trimIndent and trimMargin operations on constant strings"
-).toModuleLowering()
-
private val localDelegatedPropertiesLoweringPhase = makeBodyLoweringPhase(
{ LocalDelegatedPropertiesLowering() },
name = "LocalDelegatedPropertiesLowering",
@@ -885,8 +872,6 @@
propertyAccessorInlinerLoweringPhase,
copyPropertyAccessorBodiesLoweringPass,
booleanPropertyInExternalLowering,
- foldConstantLoweringPhase,
- computeStringTrimPhase,
privateMembersLoweringPhase,
privateMemberUsagesLoweringPhase,
defaultArgumentStubGeneratorPhase,
diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsOptimizationPhases.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsOptimizationPhases.kt
new file mode 100644
index 0000000..f9b9ab1
--- /dev/null
+++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsOptimizationPhases.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.ir.backend.js
+
+import org.jetbrains.kotlin.backend.common.lower.StringTrimLowering
+import org.jetbrains.kotlin.backend.common.lower.optimizations.FoldConstantLowering
+import org.jetbrains.kotlin.backend.common.phaser.*
+import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
+
+private val computeStringTrimPhase = makeJsModulePhase(
+ ::StringTrimLowering,
+ name = "StringTrimLowering",
+ description = "Compute trimIndent and trimMargin operations on constant strings"
+).toModuleLowering()
+
+private val jsPrefixOptimizations = NamedCompilerPhase(
+ name = "IrOptimizationPrefix",
+ description = "IR lowerings with one-time optimizations before main optimization loop",
+ lower = computeStringTrimPhase.modulePhase
+)
+
+private val foldConstantLoweringPhase = makeBodyLoweringPhase(
+ { FoldConstantLowering(it, true) },
+ name = "FoldConstantLowering",
+ description = "[Optimization] Constant Folding",
+)
+
+private val jsMainOptimizations = NamedCompilerPhase(
+ name = "IrOptimizations",
+ description = "IR lowerings with one-time optimizations before main optimization loop",
+ lower = foldConstantLoweringPhase.modulePhase
+)
+
+private val validateIrAfterLowering = makeCustomJsModulePhase(
+ { context, module -> validationCallback(context, module) },
+ name = "ValidateIrAfterLowering",
+ description = "Validate IR after lowering"
+).toModuleLowering()
+
+private val jsPostfixOptimizations = NamedCompilerPhase(
+ name = "IrOptimizationPostifx",
+ description = "IR lowerings with one-time optimizations after main optimization loop",
+ lower = validateIrAfterLowering.modulePhase
+)
+
+const val MAX_NUMBER_OF_OPTIMIZATION_ITERATIONS = 10
+
+fun runOptimizationsLoop(
+ modules: Iterable<IrModuleFragment>,
+ context: JsIrBackendContext
+) {
+ // Run prefix optimizations
+ jsPrefixOptimizations.invokeToplevel(PhaseConfig(jsPrefixOptimizations), context, modules)
+
+ for (i in 0 until MAX_NUMBER_OF_OPTIMIZATION_ITERATIONS) {
+ jsMainOptimizations.invokeToplevel(PhaseConfig(jsMainOptimizations), context, modules)
+ }
+
+ // Run postfix optimizations with validations
+ jsPostfixOptimizations.invokeToplevel(PhaseConfig(jsPostfixOptimizations), context, modules)
+}
\ No newline at end of file
diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformerTmp.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformerTmp.kt
index efbfbf9..94e7f24 100644
--- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformerTmp.kt
+++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformerTmp.kt
@@ -144,6 +144,7 @@
if (modes.any { it.dce }) {
eliminateDeadDeclarations(modules, backendContext, removeUnusedAssociatedObjects)
+ runOptimizationsLoop(modules, backendContext)
}
modes.filter { it.dce }.forEach {
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/transform.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/transform.kt
index e1e8d4a..8a49603 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/transform.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/transform.kt
@@ -36,6 +36,10 @@
}
}
+interface Notifier {
+ fun notifyAboutChanges(): Unit
+}
+
/**
* Transforms a mutable list in place.
* Each element `it` is replaced with a result of `transformation(it)`,
@@ -50,6 +54,22 @@
}
}
+
+/**
+ * The same method as `transformFlat` but also, notify about changes
+ */
+inline fun <T> MutableList<T>.transformFlatWithNotification(
+ notifier: Notifier? = null,
+ transformation: (T) -> List<T>?
+) {
+ var i = 0
+ while (i < size) {
+ val item = get(i)
+
+ i = replaceInPlace(transformation(item), i, notifier)
+ }
+}
+
/**
* Transforms a subset of a mutable list in place.
* Each element `it` that has a type S is replaced with a result of `transformation(it)`,
@@ -69,7 +89,11 @@
}
}
-@PublishedApi internal fun <T> MutableList<T>.replaceInPlace(transformed: List<T>?, atIndex: Int): Int {
+@PublishedApi internal fun <T> MutableList<T>.replaceInPlace(
+ transformed: List<T>?,
+ atIndex: Int,
+ notifier: Notifier? = null
+): Int {
var i = atIndex
when (transformed?.size) {
null -> i++
@@ -81,7 +105,11 @@
removeAt(i)
}
}
- return i
+ return i.also {
+ if (notifier != null && transformed != null) {
+ notifier.notifyAboutChanges()
+ }
+ }
}
/**