[JS IR] Support function type interfaces in incremental cache infrastructure

The patch removes logic of generating extra IrFiles (fake file) into
 IrModuleFragment for the function type interfaces during klib deserialization,
 because IC infrastructure can not process files which do not exist in klib.

 Instead of adding extra IrFiles during deserialization, the empty files
 with required packages are added into Kotlin/JS stdlib physically.
 These files are used as containers for function type interface declarations.

 Since Kotlin/WASM uses the same klib loading infrastructure as Kotlin/JS,
 the the empty files are added into Kotlin/WASM stdlib as well.

 The patch also adds a check that IrModuleFagment has files only from klib.

^KT-55720 Fixed
This commit is contained in:
Alexander Korepanov
2023-02-03 12:23:48 +00:00
committed by Space Team
parent 1c3c5417ad
commit 9324cf3360
46 changed files with 574 additions and 81 deletions
@@ -0,0 +1,3 @@
inline fun <reified T> getTypeName(s: T): String {
return "${T::class}"
}
@@ -0,0 +1,3 @@
inline fun <reified T> getTypeName(s: T): String {
return "_"
}
@@ -0,0 +1,3 @@
inline fun <reified T> getTypeName(s: T): String {
return "_${T::class}"
}
@@ -0,0 +1,17 @@
STEP 0:
modifications:
U : l1.0.kt -> l1.kt
added file: l1.kt
STEP 1..8:
STEP 9:
modifications:
U : l1.9.kt -> l1.kt
modified ir: l1.kt
STEP 10:
STEP 11:
modifications:
U : l1.11.kt -> l1.kt
modified ir: l1.kt
STEP 12:
updated exports: l1.kt
STEP 13..15:
@@ -0,0 +1,4 @@
fun getString(): String {
val s: suspend () -> Unit = {}
return getTypeName(s)
}
@@ -0,0 +1,4 @@
fun getString(): String {
val s: suspend (Any) -> Unit = { _ -> }
return getTypeName(s)
}
@@ -0,0 +1,4 @@
fun getString(): String {
val s: (Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Unit = { _, _, _, _, _, _, _, _, _ -> }
return getTypeName(s)
}
@@ -0,0 +1,4 @@
fun getString(): String {
val s: (Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Unit = { _, _, _, _, _, _, _, _, _ -> }
return "${s::class}"
}
@@ -0,0 +1,5 @@
fun getString(): String {
val s1: (Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Unit = { _, _, _, _, _, _, _, _, _ -> }
val s2: (Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Unit = { _, _, _, _, _, _, _, _, _ -> }
return "${s1::class.hashCode() == s2::class.hashCode()}"
}
@@ -0,0 +1,5 @@
fun getString(): String {
val s1: (Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Unit = { _, _, _, _, _, _, _, _, _ -> }
val s2: (Int, Int, Int, Int) -> Unit = { _, _, _, _ -> }
return "${s1::class == s2::class}"
}
@@ -0,0 +1,4 @@
fun getString(): String {
val s: suspend (Any, Any, Any, Any, Any) -> Unit = { _, _, _, _, _ -> }
return "${s::class}"
}
@@ -0,0 +1,4 @@
fun getString(): String {
val s: suspend (Any, Any, Any, Any, Any, Any, Any) -> Unit = { _, _, _, _, _, _, _ -> }
return getTypeName(s)
}
@@ -0,0 +1,4 @@
fun getString(): String {
val s: (Any, Any, Any) -> Unit = { _, _, _ -> }
return getTypeName(s)
}
@@ -0,0 +1,4 @@
fun getString(): String {
val s: (Any, Any, Any, Any, Any, Any) -> Unit = { _, _, _, _, _, _ -> }
return getTypeName(s)
}
@@ -0,0 +1,4 @@
fun getString(): String {
val s: suspend (Any, Any, Any, Any, Any, Any) -> Unit = { _, _, _, _, _, _ -> }
return getTypeName(s)
}
@@ -0,0 +1,4 @@
fun getString(): String {
val s: Any = 123
return getTypeName(s)
}
@@ -0,0 +1,4 @@
fun getString(): String {
val s: suspend (Int, Int, Int, Int, Int, Int, Int, Int) -> Unit = { _, _, _, _, _, _, _, _ -> }
return getTypeName(s)
}
@@ -0,0 +1,3 @@
fun doTest(): String {
return getString()
}
@@ -0,0 +1,3 @@
fun doTest(): String {
return getString() + "_"
}
@@ -0,0 +1,77 @@
STEP 0:
dependencies: lib1
modifications:
U : l2a.0.kt -> l2a.kt
U : l2b.0.kt -> l2b.kt
added file: l2a.kt, l2b.kt
STEP 1:
dependencies: lib1
modifications:
U : l2a.1.kt -> l2a.kt
modified ir: l2a.kt
STEP 2:
dependencies: lib1
modifications:
U : l2a.2.kt -> l2a.kt
modified ir: l2a.kt
STEP 3:
dependencies: lib1
modifications:
U : l2a.3.kt -> l2a.kt
modified ir: l2a.kt
STEP 4:
dependencies: lib1
modifications:
U : l2a.4.kt -> l2a.kt
modified ir: l2a.kt
STEP 5:
dependencies: lib1
modifications:
U : l2b.5.kt -> l2b.kt
modified ir: l2b.kt
STEP 6:
dependencies: lib1
modifications:
U : l2a.6.kt -> l2a.kt
modified ir: l2a.kt
STEP 7:
dependencies: lib1
modifications:
U : l2a.7.kt -> l2a.kt
modified ir: l2a.kt
STEP 8:
dependencies: lib1
modifications:
U : l2a.8.kt -> l2a.kt
modified ir: l2a.kt
STEP 9:
dependencies: lib1
updated imports: l2a.kt
STEP 10:
dependencies: lib1
modifications:
U : l2a.10.kt -> l2a.kt
modified ir: l2a.kt
STEP 11:
dependencies: lib1
updated imports: l2a.kt
STEP 12:
dependencies: lib1
modifications:
U : l2a.12.kt -> l2a.kt
modified ir: l2a.kt
STEP 13:
dependencies: lib1
modifications:
U : l2a.13.kt -> l2a.kt
modified ir: l2a.kt
STEP 14:
dependencies: lib1
modifications:
U : l2a.14.kt -> l2a.kt
modified ir: l2a.kt
STEP 15:
dependencies: lib1
modifications:
U : l2a.15.kt -> l2a.kt
modified ir: l2a.kt
@@ -0,0 +1,26 @@
fun box(stepId: Int): String {
val s = doTest()
when (stepId) {
0 -> if (s == "class SuspendFunction0") return "OK"
1 -> if (s == "class SuspendFunction1") return "OK"
2 -> if (s == "class SuspendFunction7") return "OK"
3 -> if (s == "class Function3") return "OK"
4 -> if (s == "class Function6") return "OK"
5 -> if (s == "class Function6_") return "OK"
6 -> if (s == "class SuspendFunction6_") return "OK"
7 -> if (s == "class Any_") return "OK"
8 -> if (s == "class SuspendFunction8_") return "OK"
9 -> if (s == "_class SuspendFunction8_") return "OK"
10 -> if (s == "_class Function9_") return "OK"
11 -> if (s == "__") return "OK"
12 -> if (s == "class Function9_") return "OK"
13 -> if (s == "true_") return "OK"
14 -> if (s == "false_") return "OK"
// TODO: I would expect, that it should be SuspendFunction5_,
// but it seems a feature of Kotlin/JS runtime.
// In Kotlin/JVM it also gives different strings.
15 -> if (s == "class Function6_") return "OK"
else -> return "Unknown"
}
return "Fail; got $s"
}
@@ -0,0 +1,5 @@
STEP 0:
dependencies: lib1, lib2
added file: m.kt
STEP 1..15:
dependencies: lib1, lib2
@@ -0,0 +1,20 @@
MODULES: lib1, lib2, main
STEP 0:
libs: lib1, lib2, main
dirty js: lib1, lib2, main
STEP 1..8:
libs: lib1, lib2, main
dirty js: lib2
STEP 9:
libs: lib1, lib2, main
dirty js: lib1, lib2
STEP 10:
libs: lib1, lib2, main
dirty js: lib2
STEP 11..12:
libs: lib1, lib2, main
dirty js: lib1, lib2
STEP 13..15:
libs: lib1, lib2, main
dirty js: lib2