diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt index abf7e3c5c96..ce66cdb567f 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt @@ -215,7 +215,8 @@ class DeclarationGenerator( val struct = WasmStructDeclaration( name = "classITable", fields = fields, - superType = null + superType = null, + isFinal = true, ) iFacesUnion.forEach { @@ -227,6 +228,7 @@ class DeclarationGenerator( methods: List, name: String, superType: WasmSymbolReadOnly? = null, + isFinal: Boolean, ): WasmStructDeclaration { val tableFields = methods.map { WasmStructFieldDeclaration( @@ -240,6 +242,7 @@ class DeclarationGenerator( name = name, fields = tableFields, superType = superType, + isFinal = isFinal ) } @@ -250,7 +253,8 @@ class DeclarationGenerator( val vtableStruct = createVirtualTableStruct( metadata.virtualMethods, vtableName, - superType = metadata.superClass?.klass?.symbol?.let(context::referenceVTableGcType) + superType = metadata.superClass?.klass?.symbol?.let(context::referenceVTableGcType), + isFinal = klass.modality == Modality.FINAL ) context.defineVTableGcType(metadata.klass.symbol, vtableStruct) @@ -357,7 +361,8 @@ class DeclarationGenerator( if (symbol in hierarchyDisjointUnions) { val vtableStruct = createVirtualTableStruct( methods = context.getInterfaceMetadata(symbol).methods, - name = "$nameStr.itable" + name = "$nameStr.itable", + isFinal = true, ) context.defineVTableGcType(symbol, vtableStruct) } @@ -384,7 +389,8 @@ class DeclarationGenerator( val structType = WasmStructDeclaration( name = nameStr, fields = fields, - superType = superClass?.let { context.referenceGcType(superClass.klass.symbol) } + superType = superClass?.let { context.referenceGcType(superClass.klass.symbol) }, + isFinal = declaration.modality == Modality.FINAL ) context.defineGcType(symbol, structType) context.generateTypeInfo(symbol, binaryDataStruct(metadata)) diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt index 8eb805cd8e9..ade1718a588 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt @@ -155,7 +155,8 @@ data class WasmFunctionType( class WasmStructDeclaration( name: String, val fields: List, - val superType: WasmSymbolReadOnly? + val superType: WasmSymbolReadOnly?, + val isFinal: Boolean ) : WasmTypeDeclaration(name) class WasmArrayDeclaration( diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt index d487aa9935e..d147ad3062b 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt @@ -62,8 +62,8 @@ class WasmIrToBinary( private var b: ByteWriter = ByteWriter.OutputStream(outputStream) // "Stack" of offsets waiting initialization. - // Since blocks has as a prefix variable length number encoding its size we can't calculate absolute offsets inside those blocks - // until we generate whole block and generate size. So, we put them into "stack" and initialize as soo as we have all required data. + // Since blocks have as a prefix variable length number encoding its size, we can't calculate absolute offsets inside those blocks + // until we generate the whole block and generate size. So, we put them into "stack" and initialize as soon as we have all required data. private var offsets = persistentListOf() fun appendWasmModule() { @@ -76,7 +76,7 @@ class WasmIrToBinary( val numRecGroups = if (recGroupTypes.isEmpty()) 0 else 1 appendVectorSize(functionTypes.size + numRecGroups) functionTypes.forEach { appendFunctionTypeDeclaration(it) } - if (!recGroupTypes.isEmpty()) { + if (recGroupTypes.isNotEmpty()) { b.writeVarInt7(WasmBinary.REC_GROUP) appendVectorSize(recGroupTypes.size) recGroupTypes.forEach { @@ -361,14 +361,26 @@ class WasmIrToBinary( } private fun appendStructTypeDeclaration(type: WasmStructDeclaration) { - b.writeVarInt7(WasmBinary.SUB_TYPE) - val superType = type.superType - if (superType != null) { - appendVectorSize(1) - appendModuleFieldReference(superType.owner) + + // https://webassembly.github.io/gc/core/binary/types.html#binary-subtype + if (superType == null && type.isFinal) { + // Short encoding form for final types without subtypes. } else { - appendVectorSize(0) + // General encoding + b.writeVarInt7( + if (type.isFinal) + WasmBinary.SUB_FINAL_TYPE + else + WasmBinary.SUB_TYPE + ) + + if (superType != null) { + appendVectorSize(1) + appendModuleFieldReference(superType.owner) + } else { + appendVectorSize(0) + } } b.writeVarInt7(WasmBinary.STRUCT_TYPE)