[JS IR] Fix IC invalidation for fake override inline functions

The patch enables the direct dependency between
 fake override inline function and its implementation from the base class.

 Because klibs do not keep a signature of fake override implementation,
 incremental cache can not use the signature index,
 therefore the signature is serialized to a cache file as is.

^KT-51896 Fixed
This commit is contained in:
Alexander Korepanov
2022-06-14 14:56:10 +02:00
committed by Space
parent c6299ee277
commit 644447db84
43 changed files with 524 additions and 36 deletions
@@ -0,0 +1,3 @@
abstract class AbstractClassA {
inline fun funA() = "a-0"
}
@@ -0,0 +1,3 @@
abstract class AbstractClassA {
inline fun funA() = "a-1"
}
@@ -0,0 +1,3 @@
abstract class AbstractClassB : AbstractClassA() {
inline fun funB() = "b-0 ${funA()}"
}
@@ -0,0 +1,3 @@
abstract class AbstractClassB : AbstractClassA() {
inline fun funB() = "b-2"
}
@@ -0,0 +1,3 @@
abstract class AbstractClassC : AbstractClassB() {
inline fun funC() = "c-0 ${funB()}"
}
@@ -0,0 +1,30 @@
STEP 0:
modifications:
U : A.0.kt -> A.kt
U : B.0.kt -> B.kt
U : C.0.kt -> C.kt
added file: A.kt, B.kt, C.kt
STEP 1:
modifications:
U : A.1.kt -> A.kt
modified ir: A.kt
updated inline imports: B.kt, C.kt
STEP 2:
modifications:
U : B.2.kt -> B.kt
modified ir: B.kt
updated inline imports: C.kt
STEP 3:
modifications:
U : A.0.kt -> A.kt
modified ir: A.kt
STEP 4:
modifications:
U : B.0.kt -> B.kt
modified ir: B.kt
updated inline imports: C.kt
STEP 5:
modifications:
U : A.1.kt -> A.kt
modified ir: A.kt
updated inline imports: B.kt, C.kt
@@ -0,0 +1,5 @@
class ClassABC: AbstractClassC() {
inline fun testA() = funA()
inline fun testB() = funB()
inline fun testC() = funC()
}
@@ -0,0 +1,27 @@
fun box(stepId: Int): String {
val a = ClassABC()
when (stepId) {
0, 4 -> {
if (a.testA() != "a-0") return "Fail testA()"
if (a.testB() != "b-0 a-0") return "Fail testB()"
if (a.testC() != "c-0 b-0 a-0") return "Fail testC()"
}
1, 5 -> {
if (a.testA() != "a-1") return "Fail testA()"
if (a.testB() != "b-0 a-1") return "Fail testB()"
if (a.testC() != "c-0 b-0 a-1") return "Fail testC()"
}
2 -> {
if (a.testA() != "a-1") return "Fail testA()"
if (a.testB() != "b-2") return "Fail testB()"
if (a.testC() != "c-0 b-2") return "Fail testC()"
}
3 -> {
if (a.testA() != "a-0") return "Fail testA()"
if (a.testB() != "b-2") return "Fail testB()"
if (a.testC() != "c-0 b-2") return "Fail testC()"
}
else -> return "Unknown"
}
return "OK"
}
@@ -0,0 +1,6 @@
STEP 0:
dependencies: lib1
added file: m.kt, classABC.kt
STEP 1..5:
dependencies: lib1
updated inline imports: m.kt, classABC.kt
@@ -0,0 +1,8 @@
MODULES: lib1, main
STEP 0:
libs: lib1, main
dirty js: lib1, main
STEP 1..5:
libs: lib1, main
dirty js: lib1, main
@@ -0,0 +1,14 @@
abstract class AbstractClassA {
inline fun String.fakeOverrideExtension() = "${this} fakeOverrideExtension 0"
inline val String.fakeOverrideGetProperty
get() = "${this} fakeOverrideGetProperty 0"
inline var String.fakeOverrideSetProperty: String
get() = "${savedString} fakeOverrideSetProperty getter 0"
set(str) {
savedString = "${str} fakeOverrideSetProperty setter 0"
}
var savedString = ""
}
@@ -0,0 +1,14 @@
abstract class AbstractClassA {
inline fun String.fakeOverrideExtension() = "${this} fakeOverrideExtension 1"
inline val String.fakeOverrideGetProperty
get() = "${this} fakeOverrideGetProperty 0"
inline var String.fakeOverrideSetProperty: String
get() = "${savedString} fakeOverrideSetProperty getter 0"
set(str) {
savedString = "${str} fakeOverrideSetProperty setter 0"
}
var savedString = ""
}
@@ -0,0 +1,14 @@
abstract class AbstractClassA {
inline fun String.fakeOverrideExtension() = "${this} fakeOverrideExtension 1"
inline val String.fakeOverrideGetProperty
get() = "${this} fakeOverrideGetProperty 2"
inline var String.fakeOverrideSetProperty: String
get() = "${savedString} fakeOverrideSetProperty getter 0"
set(str) {
savedString = "${str} fakeOverrideSetProperty setter 0"
}
var savedString = ""
}
@@ -0,0 +1,14 @@
abstract class AbstractClassA {
inline fun String.fakeOverrideExtension() = "${this} fakeOverrideExtension 1"
inline val String.fakeOverrideGetProperty
get() = "${this} fakeOverrideGetProperty 2"
inline var String.fakeOverrideSetProperty: String
get() = "${savedString} fakeOverrideSetProperty getter 0"
set(str) {
savedString = "${str} fakeOverrideSetProperty setter 3"
}
var savedString = "empty"
}
@@ -0,0 +1,14 @@
abstract class AbstractClassA {
inline fun String.fakeOverrideExtension() = "${this} fakeOverrideExtension 1"
inline val String.fakeOverrideGetProperty
get() = "${this} fakeOverrideGetProperty 2"
inline var String.fakeOverrideSetProperty: String
get() = "${savedString} fakeOverrideSetProperty getter 4"
set(str) {
savedString = "${str} fakeOverrideSetProperty setter 3"
}
var savedString = ""
}
@@ -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
@@ -0,0 +1,11 @@
class ClassA: AbstractClassA() {
inline fun testExtension() = "testExtension".fakeOverrideExtension()
inline fun testGetProperty() = "testGetProperty".fakeOverrideGetProperty
inline fun testSetPropertySetter(): String {
"test".fakeOverrideSetProperty = "testSetPropertySetter"
return savedString;
}
inline fun testSetPropertyGetter() = "test".fakeOverrideSetProperty
}
@@ -0,0 +1,37 @@
fun box(stepId: Int): String {
val a = ClassA()
when (stepId) {
0 -> {
if (a.testExtension() != "testExtension fakeOverrideExtension 0") return "Fail extension"
if (a.testGetProperty() != "testGetProperty fakeOverrideGetProperty 0") return "Fail getProperty"
if (a.testSetPropertySetter() != "testSetPropertySetter fakeOverrideSetProperty setter 0") return "Fail setPropertySetter"
if (a.testSetPropertyGetter() != "testSetPropertySetter fakeOverrideSetProperty setter 0 fakeOverrideSetProperty getter 0") return a.testSetPropertyGetter()
}
1 -> {
if (a.testExtension() != "testExtension fakeOverrideExtension 1") return "Fail extension"
if (a.testGetProperty() != "testGetProperty fakeOverrideGetProperty 0") return "Fail getProperty"
if (a.testSetPropertySetter() != "testSetPropertySetter fakeOverrideSetProperty setter 0") return "Fail setPropertySetter"
if (a.testSetPropertyGetter() != "testSetPropertySetter fakeOverrideSetProperty setter 0 fakeOverrideSetProperty getter 0") return a.testSetPropertyGetter()
}
2 -> {
if (a.testExtension() != "testExtension fakeOverrideExtension 1") return "Fail extension"
if (a.testGetProperty() != "testGetProperty fakeOverrideGetProperty 2") return "Fail getProperty"
if (a.testSetPropertySetter() != "testSetPropertySetter fakeOverrideSetProperty setter 0") return "Fail setPropertySetter"
if (a.testSetPropertyGetter() != "testSetPropertySetter fakeOverrideSetProperty setter 0 fakeOverrideSetProperty getter 0") return a.testSetPropertyGetter()
}
3 -> {
if (a.testExtension() != "testExtension fakeOverrideExtension 1") return "Fail extension"
if (a.testGetProperty() != "testGetProperty fakeOverrideGetProperty 2") return "Fail getProperty"
if (a.testSetPropertySetter() != "testSetPropertySetter fakeOverrideSetProperty setter 3") return "Fail setPropertySetter"
if (a.testSetPropertyGetter() != "testSetPropertySetter fakeOverrideSetProperty setter 3 fakeOverrideSetProperty getter 0") return a.testSetPropertyGetter()
}
4 -> {
if (a.testExtension() != "testExtension fakeOverrideExtension 1") return "Fail extension"
if (a.testGetProperty() != "testGetProperty fakeOverrideGetProperty 2") return "Fail getProperty"
if (a.testSetPropertySetter() != "testSetPropertySetter fakeOverrideSetProperty setter 3") return "Fail setPropertySetter"
if (a.testSetPropertyGetter() != "testSetPropertySetter fakeOverrideSetProperty setter 3 fakeOverrideSetProperty getter 4") return a.testSetPropertyGetter()
}
else -> return "Unknown"
}
return "OK"
}
@@ -0,0 +1,6 @@
STEP 0:
dependencies: lib1
added file: m.kt, classA.kt
STEP 1..4:
dependencies: lib1
updated inline imports: m.kt, classA.kt
@@ -0,0 +1,8 @@
MODULES: lib1, main
STEP 0:
libs: lib1, main
dirty js: lib1, main
STEP 1..4:
libs: lib1, main
dirty js: lib1, main
@@ -1,5 +1,8 @@
STEP 0:
dependencies: lib1
added file: l2.kt
STEP 1..2:
STEP 1:
dependencies: lib1
updated inline imports: l2.kt
STEP 2:
dependencies: lib1
@@ -23,12 +23,12 @@ fun box(stepId: Int): String {
if (callIt(b::fakeOverrideFunction) != 0) return "Fail 0-6"
}
1 -> {
if (a.test2() != null) return "Fail 1-1" // TODO: test2() must return "OTHER 2", should be fixed in KT-51896
if (b.test2() != null) return "Fail 1-2" // TODO: test2() must return "OTHER 1", should be fixed in KT-51896
if (a.test2() != "OTHER 2") return "Fail 1-1"
if (b.test2() != "OTHER 1") return "Fail 1-2"
}
2 -> {
if (a.fakeOverrideFunction() != 0) return "Fail 2-1" // TODO: fakeOverrideFunction() must return 2, should be fixed in KT-51896
if (b.fakeOverrideFunction() != 0) return "Fail 2-2" // TODO: fakeOverrideFunction() must return 2, should be fixed in KT-51896
if (a.fakeOverrideFunction() != 2) return "Fail 2-1"
if (b.fakeOverrideFunction() != 2) return "Fail 2-2"
if (callIt(a::fakeOverrideFunction) != 2) return "Fail 2-3"
if (callIt(b::fakeOverrideFunction) != 2) return "Fail 2-4"
@@ -3,3 +3,4 @@ STEP 0:
added file: m.kt
STEP 1..2:
dependencies: lib1, lib2
updated inline imports: m.kt
@@ -3,6 +3,9 @@ MODULES: lib1, lib2, main
STEP 0:
libs: lib1, lib2, main
dirty js: lib1, lib2, main
STEP 1..2:
STEP 1:
libs: lib1, lib2, main
dirty js: lib1
dirty js: lib1, lib2, main
STEP 2:
libs: lib1, lib2, main
dirty js: lib1, main
@@ -0,0 +1,12 @@
abstract class AbstractClassA {
inline val propertyWithGetter: String
get() = "0"
inline var propertyWithSetter: String
get() = savedStr
set(str) {
savedStr = "$str 0"
}
var savedStr = "empty"
}
@@ -0,0 +1,12 @@
abstract class AbstractClassA {
inline val propertyWithGetter: String
get() = "1"
inline var propertyWithSetter: String
get() = savedStr
set(str) {
savedStr = "$str 0"
}
var savedStr = "empty"
}
@@ -0,0 +1,12 @@
abstract class AbstractClassA {
inline val propertyWithGetter: String
get() = "1"
inline var propertyWithSetter: String
get() = savedStr
set(str) {
savedStr = "$str 2"
}
var savedStr = "empty"
}
@@ -0,0 +1,12 @@
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
@@ -0,0 +1,8 @@
class ClassA: AbstractClassA() {
inline fun testPropertyWithGetter() = propertyWithGetter
inline fun testPropertyWithSetter(): String {
propertyWithSetter = "test"
return savedStr
}
}
@@ -0,0 +1,19 @@
fun box(stepId: Int): String {
val a = ClassA()
when (stepId) {
0 -> {
if (a.testPropertyWithGetter() != "0") return "Fail testPropertyWithGetter()"
if (a.testPropertyWithSetter() != "test 0") return "Fail testPropertyWithSetter()"
}
1 -> {
if (a.testPropertyWithGetter() != "1") return "Fail testPropertyWithGetter()"
if (a.testPropertyWithSetter() != "test 0") return "Fail testPropertyWithSetter()"
}
2 -> {
if (a.testPropertyWithGetter() != "1") return "Fail testPropertyWithGetter()"
if (a.testPropertyWithSetter() != "test 2") return "Fail testPropertyWithSetter()"
}
else -> return "Unknown"
}
return "OK"
}
@@ -0,0 +1,6 @@
STEP 0:
dependencies: lib1
added file: m.kt, classA.kt
STEP 1..2:
dependencies: lib1
updated inline imports: m.kt, classA.kt
@@ -0,0 +1,8 @@
MODULES: lib1, main
STEP 0:
libs: lib1, main
dirty js: lib1, main
STEP 1..2:
libs: lib1, main
dirty js: lib1, main