From d21cbfe02e5fe95266ec25155f0284edb6f0fdfb Mon Sep 17 00:00:00 2001 From: Alexander Korepanov Date: Fri, 2 Dec 2022 18:47:34 +0100 Subject: [PATCH] [JS IR] Take into account the declaration annotations in IC hash So the annotation modifications invalidate the caller. --- .../ir/backend/js/ic/HashCalculatorForIC.kt | 31 +++++++++++++------ .../js/ic/IdSignatureHashCalculator.kt | 4 +-- .../InvalidationTestGenerated.java | 5 +++ .../inlineFunctionAnnotations/lib1/l1.0.kt | 3 ++ .../inlineFunctionAnnotations/lib1/l1.1.kt | 4 +++ .../inlineFunctionAnnotations/lib1/l1.2.kt | 5 +++ .../inlineFunctionAnnotations/lib1/l1.3.kt | 5 +++ .../inlineFunctionAnnotations/lib1/l1.4.kt | 5 +++ .../lib1/module.info | 20 ++++++++++++ .../inlineFunctionAnnotations/main/m.kt | 8 +++++ .../main/module.info | 6 ++++ .../inlineFunctionAnnotations/project.info | 5 +++ .../invalidation/jsExport/main/module.info | 4 +-- .../invalidation/jsExport/project.info | 5 +-- 14 files changed, 91 insertions(+), 19 deletions(-) create mode 100644 js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.0.kt create mode 100644 js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.1.kt create mode 100644 js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.2.kt create mode 100644 js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.3.kt create mode 100644 js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.4.kt create mode 100644 js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/module.info create mode 100644 js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/main/m.kt create mode 100644 js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/main/module.info create mode 100644 js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/project.info diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/HashCalculatorForIC.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/HashCalculatorForIC.kt index 6816f94942a..4c96cf6b0ac 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/HashCalculatorForIC.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/HashCalculatorForIC.kt @@ -9,7 +9,9 @@ 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.IrAnnotationContainer import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor @@ -45,6 +47,18 @@ private class HashCalculatorForIC { update(data.toByteArray()) } + fun update(irElement: IrElement) { + irElement.accept( + visitor = DumpIrTreeVisitor( + out = object : Appendable { + override fun append(csq: CharSequence) = this.apply { update(csq.toString().toByteArray()) } + override fun append(csq: CharSequence, start: Int, end: Int) = append(csq.subSequence(start, end)) + override fun append(c: Char) = append(c.toString()) + } + ), data = "" + ) + } + inline fun updateForEach(collection: Collection, f: (T) -> Unit) { update(collection.size) collection.forEach { f(it) } @@ -90,16 +104,8 @@ internal fun CompilerConfiguration.configHashForIC() = HashCalculatorForIC().app update(languageVersionSettings.toString()) }.finalize() -internal fun IrElement.irElementHashForIC() = HashCalculatorForIC().also { - accept( - visitor = DumpIrTreeVisitor( - out = object : Appendable { - override fun append(csq: CharSequence) = this.apply { it.update(csq.toString().toByteArray()) } - override fun append(csq: CharSequence, start: Int, end: Int) = append(csq.subSequence(start, end)) - override fun append(c: Char) = append(c.toString()) - } - ), data = "" - ) +internal fun IrSimpleFunction.irSimpleFunctionHashForIC() = HashCalculatorForIC().also { + it.update(this) }.finalize() internal fun IrSymbol.irSymbolHashForIC() = HashCalculatorForIC().also { @@ -118,6 +124,11 @@ internal fun IrSymbol.irSymbolHashForIC() = HashCalculatorForIC().also { it.update(functionParam.defaultValue?.let { 1 } ?: 0) } } + (owner as? IrAnnotationContainer)?.let { annotationContainer -> + it.updateForEach(annotationContainer.annotations) { annotation -> + it.update(annotation) + } + } }.finalize() internal fun String.stringHashForIC() = HashCalculatorForIC().also { it.update(this) }.finalize() diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/IdSignatureHashCalculator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/IdSignatureHashCalculator.kt index 0c029dd6542..82dc5f140e9 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/IdSignatureHashCalculator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/IdSignatureHashCalculator.kt @@ -41,10 +41,10 @@ internal class IdSignatureHashCalculator { } flatHashes[declaration] = if (declaration.isFakeOverride) { - declaration.resolveFakeOverride()?.irElementHashForIC() + declaration.resolveFakeOverride()?.irSimpleFunctionHashForIC() ?: icError("can not resolve fake override for ${declaration.render()}") } else { - declaration.irElementHashForIC() + declaration.irSimpleFunctionHashForIC() } } // go deeper since local inline special declarations (like a reference adaptor) may appear diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/incremental/InvalidationTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/incremental/InvalidationTestGenerated.java index 2c00195a5eb..f86f6967d71 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/incremental/InvalidationTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/incremental/InvalidationTestGenerated.java @@ -190,6 +190,11 @@ public class InvalidationTestGenerated extends AbstractInvalidationTest { runTest("js/js.translator/testData/incremental/invalidation/inlineBecomeNonInline/"); } + @TestMetadata("inlineFunctionAnnotations") + public void testInlineFunctionAnnotations() throws Exception { + runTest("js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/"); + } + @TestMetadata("inlineFunctionAsFunctionReference") public void testInlineFunctionAsFunctionReference() throws Exception { runTest("js/js.translator/testData/incremental/invalidation/inlineFunctionAsFunctionReference/"); diff --git a/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.0.kt b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.0.kt new file mode 100644 index 00000000000..038c023d7b2 --- /dev/null +++ b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.0.kt @@ -0,0 +1,3 @@ +class MyClassA { + inline fun foo() = 42 +} diff --git a/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.1.kt b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.1.kt new file mode 100644 index 00000000000..6e26ddb222e --- /dev/null +++ b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.1.kt @@ -0,0 +1,4 @@ +@JsExport +class MyClassA { + inline fun foo() = 42 +} diff --git a/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.2.kt b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.2.kt new file mode 100644 index 00000000000..5e7d13099c1 --- /dev/null +++ b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.2.kt @@ -0,0 +1,5 @@ +@JsExport +class MyClassA { + @JsName("bar") + inline fun foo() = 42 +} diff --git a/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.3.kt b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.3.kt new file mode 100644 index 00000000000..f225213f022 --- /dev/null +++ b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.3.kt @@ -0,0 +1,5 @@ +@JsExport +class MyClassA { + @JsName("baz") + inline fun foo() = 42 +} diff --git a/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.4.kt b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.4.kt new file mode 100644 index 00000000000..41b33169c55 --- /dev/null +++ b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/l1.4.kt @@ -0,0 +1,5 @@ +@JsExport +class MyClassA { + @JsName("baz") + inline fun foo() = 33 +} diff --git a/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/module.info b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/module.info new file mode 100644 index 00000000000..e7cd35d3035 --- /dev/null +++ b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/lib1/module.info @@ -0,0 +1,20 @@ +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: + modifications: + U : l1.3.kt -> l1.kt + modified ir: l1.kt +STEP 4: + modifications: + U : l1.4.kt -> l1.kt + modified ir: l1.kt diff --git a/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/main/m.kt b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/main/m.kt new file mode 100644 index 00000000000..5e859e0bad7 --- /dev/null +++ b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/main/m.kt @@ -0,0 +1,8 @@ +fun box(stepId: Int): String { + when (stepId) { + 0, 1, 2, 3 -> if (MyClassA().foo() != 42) return "Fail" + 4 -> if (MyClassA().foo() != 33) return "Fail" + else -> return "Unknown" + } + return "OK" +} diff --git a/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/main/module.info b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/main/module.info new file mode 100644 index 00000000000..60fe38d07f7 --- /dev/null +++ b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/main/module.info @@ -0,0 +1,6 @@ +STEP 0: + dependencies: lib1 + added file: m.kt +STEP 1..4: + dependencies: lib1 + updated imports: m.kt diff --git a/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/project.info b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/project.info new file mode 100644 index 00000000000..8ae59518ca8 --- /dev/null +++ b/js/js.translator/testData/incremental/invalidation/inlineFunctionAnnotations/project.info @@ -0,0 +1,5 @@ +MODULES: lib1, main + +STEP 0..4: + libs: lib1, main + dirty js: lib1, main diff --git a/js/js.translator/testData/incremental/invalidation/jsExport/main/module.info b/js/js.translator/testData/incremental/invalidation/jsExport/main/module.info index d91e9052012..4885e35b738 100644 --- a/js/js.translator/testData/incremental/invalidation/jsExport/main/module.info +++ b/js/js.translator/testData/incremental/invalidation/jsExport/main/module.info @@ -1,8 +1,6 @@ STEP 0: dependencies: lib1 added file: m.kt -STEP 1..3: +STEP 1..6: dependencies: lib1 updated imports: m.kt -STEP 4..6: - dependencies: lib1 diff --git a/js/js.translator/testData/incremental/invalidation/jsExport/project.info b/js/js.translator/testData/incremental/invalidation/jsExport/project.info index 5856e82f68d..1ba33e23c15 100644 --- a/js/js.translator/testData/incremental/invalidation/jsExport/project.info +++ b/js/js.translator/testData/incremental/invalidation/jsExport/project.info @@ -1,8 +1,5 @@ MODULES: lib1, main -STEP 0..3: +STEP 0..6: libs: lib1, main dirty js: lib1, main -STEP 4..6: - libs: lib1, main - dirty js: lib1