[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 // Type aliases are not material
} }
private val jsCodeCounter = mutableMapOf<String, Int>()
private fun jsCodeName(declaration: IrFunction): String { private fun jsCodeName(declaration: IrFunction): String {
require(declaration is IrSimpleFunction) require(declaration is IrSimpleFunction)
val fqName = declaration.fqNameWhenAvailable!!.asString() val key = declaration.fqNameWhenAvailable.toString()
val hashCode = declaration.wasmSignature(irBuiltIns).hashCode() + declaration.file.path.hashCode() // counter is used to resolve fqName clashes
return "${fqName}_$hashCode" 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) { override fun visitFunction(declaration: IrFunction) {
@@ -79,11 +84,10 @@ class DeclarationGenerator(
wasmImportModule wasmImportModule
} }
jsCode != null -> { jsCode != null -> {
// TODO: check consistency (currently fails with generated __convertKotlinClosureToJsClosure)
// check(declaration.isExternal) { "Non-external fun with @JsFun ${declaration.fqNameWhenAvailable}"} // check(declaration.isExternal) { "Non-external fun with @JsFun ${declaration.fqNameWhenAvailable}"}
val jsCodeName = jsCodeName(declaration) val jsCodeName = jsCodeName(declaration)
context.addJsFun(jsCodeName, jsCode) context.addJsFun(jsCodeName, jsCode)
WasmImportDescriptor("js_code", jsCodeName(declaration)) WasmImportDescriptor("js_code", jsCodeName)
} }
else -> { else -> {
null null
@@ -201,6 +201,10 @@ class ComplexExternalDeclarationsToTopLevelFunctionsLowering(val context: WasmBa
return return
} }
if (function.isFakeOverride) {
return
}
val jsFunctionReference = when { val jsFunctionReference = when {
jsFun != null -> "($jsFun)" jsFun != null -> "($jsFun)"
function.isTopLevelDeclaration -> referenceTopLevelExternalDeclaration(function) 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.ir.addDispatchReceiver
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder 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.WasmBackendContext
import org.jetbrains.kotlin.backend.wasm.ir2wasm.isBuiltInWasmRefType import org.jetbrains.kotlin.backend.wasm.ir2wasm.isBuiltInWasmRefType
import org.jetbrains.kotlin.backend.wasm.ir2wasm.isExported import org.jetbrains.kotlin.backend.wasm.ir2wasm.isExported
@@ -621,7 +622,8 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
} }
val hashString: String = 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> = val originalParameterTypes: List<IrType> =
functionType.arguments.dropLast(1).map { (it as IrTypeProjection).type } functionType.arguments.dropLast(1).map { (it as IrTypeProjection).type }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// EXPECTED_REACHABLE_NODES: 1310 // EXPECTED_REACHABLE_NODES: 1310
package foo package foo