[Wasm] Improve stability of wasm import names across compiler runs

Remove code generation for external fake overrides
Fake overrides are resolved to real declaration on call sites
This also removes generation of unused
"equals", "hashCode" and "toString" methods.
Avoid using hashes of IrType in generated code
because they are unstable

Merge-request: KT-MR-8658
Merged-by: Svyatoslav Kuzmich <svyatoslav.kuzmich@jetbrains.com>
This commit is contained in:
Svyatoslav Kuzmich
2023-02-03 06:55:59 +00:00
committed by Space Team
parent 35e39e9e10
commit 2e26b0956e
4 changed files with 16 additions and 7 deletions
@@ -53,11 +53,16 @@ class DeclarationGenerator(
// Type aliases are not material
}
private val jsCodeCounter = mutableMapOf<String, Int>()
private fun jsCodeName(declaration: IrFunction): String {
require(declaration is IrSimpleFunction)
val fqName = declaration.fqNameWhenAvailable!!.asString()
val hashCode = declaration.wasmSignature(irBuiltIns).hashCode() + declaration.file.path.hashCode()
return "${fqName}_$hashCode"
val key = declaration.fqNameWhenAvailable.toString()
// counter is used to resolve fqName clashes
val counterValue = jsCodeCounter.getOrPut(key, defaultValue = { 0 })
jsCodeCounter[key] = counterValue + 1
val counterSuffix = if (counterValue == 0 && key.lastOrNull()?.isDigit() == false) "" else "_$counterValue"
return "$key$counterSuffix"
}
override fun visitFunction(declaration: IrFunction) {
@@ -79,11 +84,10 @@ class DeclarationGenerator(
wasmImportModule
}
jsCode != null -> {
// TODO: check consistency (currently fails with generated __convertKotlinClosureToJsClosure)
// check(declaration.isExternal) { "Non-external fun with @JsFun ${declaration.fqNameWhenAvailable}"}
val jsCodeName = jsCodeName(declaration)
context.addJsFun(jsCodeName, jsCode)
WasmImportDescriptor("js_code", jsCodeName(declaration))
WasmImportDescriptor("js_code", jsCodeName)
}
else -> {
null
@@ -201,6 +201,10 @@ class ComplexExternalDeclarationsToTopLevelFunctionsLowering(val context: WasmBa
return
}
if (function.isFakeOverride) {
return
}
val jsFunctionReference = when {
jsFun != null -> "($jsFun)"
function.isTopLevelDeclaration -> referenceTopLevelExternalDeclaration(function)
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.backend.common.ir.addDispatchReceiver
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.serialization.cityHash64
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
import org.jetbrains.kotlin.backend.wasm.ir2wasm.isBuiltInWasmRefType
import org.jetbrains.kotlin.backend.wasm.ir2wasm.isExported
@@ -621,7 +622,8 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
}
val hashString: String =
functionType.hashCode().absoluteValue.toString(Character.MAX_RADIX)
// Rendering type to improve hash stability across compiler runs
functionType.render().cityHash64().toULong().toString(Character.MAX_RADIX)
val originalParameterTypes: List<IrType> =
functionType.arguments.dropLast(1).map { (it as IrTypeProjection).type }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// EXPECTED_REACHABLE_NODES: 1310
package foo