[JS IR] Take default params into account for calculating an IC hash

^KT-54895 Fixed
This commit is contained in:
Alexander Korepanov
2022-11-10 14:10:19 +01:00
committed by Space Team
parent f7063555ca
commit f4b5f5ff5d
19 changed files with 176 additions and 0 deletions
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.CrossModuleReferences
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
@@ -110,6 +111,13 @@ internal fun IrSymbol.irSymbolHashForIC() = HashCalculatorForIC().also {
it.update(typeParameter.symbol.toString())
}
}
(owner as? IrFunction)?.let { irFunction ->
it.updateForEach(irFunction.valueParameters) { functionParam ->
// symbol rendering doesn't print default params information
// it is important to understand if default params were added or removed
it.update(functionParam.defaultValue?.let { 1 } ?: 0)
}
}
}.finalize()
internal fun String.stringHashForIC() = HashCalculatorForIC().also { it.update(this) }.finalize()
@@ -200,6 +200,11 @@ public class InvalidationTestGenerated extends AbstractInvalidationTest {
runTest("js/js.translator/testData/incremental/invalidation/inlineFunctionWithObject/");
}
@TestMetadata("interfaceWithDefaultParams")
public void testInterfaceWithDefaultParams() throws Exception {
runTest("js/js.translator/testData/incremental/invalidation/interfaceWithDefaultParams/");
}
@TestMetadata("jsCode")
public void testJsCode() throws Exception {
runTest("js/js.translator/testData/incremental/invalidation/jsCode/");
@@ -0,0 +1,3 @@
interface InterfaceA {
fun functionA(x: Int, s: String, b: Boolean? = null): Int
}
@@ -0,0 +1,3 @@
interface InterfaceA {
fun functionA(x: Int, s: String, b: Boolean?): Int
}
@@ -0,0 +1,3 @@
interface InterfaceA {
fun functionA(x: Int, s: String, b: Boolean? = true): Int
}
@@ -0,0 +1,3 @@
interface InterfaceA {
fun functionA(x: Int, s: String, b: Boolean? = true, i: Int = 1): Int
}
@@ -0,0 +1,3 @@
interface InterfaceA {
fun functionA(x: Int, s: String = "xy", b: Boolean? = true, i: Int): Int
}
@@ -0,0 +1,3 @@
interface InterfaceA {
fun functionA(x: Int, s: String = "xyz!", b: Boolean? = false, i: Int): Int
}
@@ -0,0 +1,27 @@
STEP 0:
modifications:
U : l1.0.kt -> l1.kt
added file: l1.kt
STEP 1:
modifications:
U : l1.1.kt -> l1.kt
modified ir: l1.kt
STEP 2:
modifications:
U : l1.2.kt -> l1.kt
modified ir: l1.kt
STEP 3:
STEP 4:
modifications:
U : l1.4.kt -> l1.kt
modified ir: l1.kt
STEP 5:
STEP 6:
modifications:
U : l1.6.kt -> l1.kt
modified ir: l1.kt
STEP 7:
STEP 8:
modifications:
U : l1.8.kt -> l1.kt
modified ir: l1.kt
@@ -0,0 +1,5 @@
class ClassA : InterfaceA {
override fun functionA(x: Int, s: String, b: Boolean?): Int {
return x + s.length + if (b == true) 1 else 0
}
}
@@ -0,0 +1,5 @@
class ClassA : InterfaceA {
override fun functionA(x: Int, s: String, b: Boolean?, i: Int): Int {
return i - 1 + x + s.length + if (b == true) 1 else 0
}
}
@@ -0,0 +1,7 @@
private fun test(setepId: Int, i: InterfaceA): Int {
return i.functionA(setepId, "", false)
}
fun testDefaltParam(setepId: Int): Int {
return test(setepId, ClassA())
}
@@ -0,0 +1,7 @@
private fun test(setepId: Int, i: InterfaceA): Int {
return i.functionA(setepId - 1, "")
}
fun testDefaltParam(setepId: Int): Int {
return test(setepId, ClassA())
}
@@ -0,0 +1,12 @@
private fun test(setepId: Int, i: InterfaceA): Int {
return i.functionA(
x = setepId - 2,
s = "s",
b = false,
i = 2
)
}
fun testDefaltParam(setepId: Int): Int {
return test(setepId, ClassA())
}
@@ -0,0 +1,10 @@
private fun test(setepId: Int, i: InterfaceA): Int {
return i.functionA(
x = 3,
i = 2
)
}
fun testDefaltParam(setepId: Int): Int {
return test(setepId, ClassA())
}
@@ -0,0 +1,34 @@
STEP 0:
dependencies: lib1
modifications:
U : l2.0.kt -> l2.kt
U : l2test.0.kt -> l2test.kt
added file: l2.kt, l2test.kt
STEP 1..2:
dependencies: lib1
updated imports: l2test.kt, l2.kt
STEP 3:
dependencies: lib1
modifications:
U : l2test.3.kt -> l2test.kt
modified ir: l2test.kt
STEP 4:
dependencies: lib1
modifications:
U : l2.4.kt -> l2.kt
modified ir: l2.kt, l2test.kt
STEP 5:
dependencies: lib1
modifications:
U : l2test.5.kt -> l2test.kt
modified ir: l2test.kt
STEP 6:
dependencies: lib1
updated imports: l2.kt, l2test.kt
STEP 7:
dependencies: lib1
modifications:
U : l2test.7.kt -> l2test.kt
modified ir: l2test.kt
STEP 8:
dependencies: lib1
@@ -0,0 +1,7 @@
fun box(stepId: Int): String {
val x = testDefaltParam(stepId)
if (x != stepId) {
return "Fail, got $x, expected $stepId"
}
return "OK"
}
@@ -0,0 +1,5 @@
STEP 0:
dependencies: lib1, lib2
added file: m.kt
STEP 1..8:
dependencies: lib1, lib2
@@ -0,0 +1,26 @@
MODULES: lib1, lib2, main
STEP 0:
libs: lib1, lib2, main
dirty js: lib1, lib2, main
STEP 1..2:
libs: lib1, lib2, main
dirty js: lib1, lib2
STEP 3:
libs: lib1, lib2, main
dirty js: lib2
STEP 4:
libs: lib1, lib2, main
dirty js: lib1, lib2
STEP 5:
libs: lib1, lib2, main
dirty js: lib2
STEP 6:
libs: lib1, lib2, main
dirty js: lib1, lib2
STEP 7:
libs: lib1, lib2, main
dirty js: lib2
STEP 8:
libs: lib1, lib2, main
dirty js: lib1