[Wasm] Improve interface method dispatch
- Use typed Wasm tables for each interface method to avoid runtime function type check - Use linear search by implemented interface rather than by individual virtual function signature
This commit is contained in:
@@ -76,7 +76,7 @@ class WasmData(
|
||||
) : WasmNamedModuleField()
|
||||
|
||||
class WasmTable(
|
||||
val limits: WasmLimits = WasmLimits(1u, null),
|
||||
var limits: WasmLimits = WasmLimits(1u, null),
|
||||
val elementType: WasmType,
|
||||
val importPair: WasmImportPair? = null
|
||||
) : WasmNamedModuleField() {
|
||||
|
||||
@@ -73,7 +73,9 @@ sealed class WasmImmediate {
|
||||
}
|
||||
|
||||
class DataIdx(val value: Int) : WasmImmediate()
|
||||
class TableIdx(val value: Int) : WasmImmediate()
|
||||
class TableIdx(val value: WasmSymbolReadOnly<Int>) : WasmImmediate() {
|
||||
constructor(value: Int) : this(WasmSymbol(value))
|
||||
}
|
||||
|
||||
class LabelIdx(val value: Int) : WasmImmediate()
|
||||
class LabelIdxVector(val value: List<Int>) : WasmImmediate()
|
||||
|
||||
@@ -33,3 +33,10 @@ class WasmSymbol<out T : Any>(owner: T? = null) : WasmSymbolReadOnly<T> {
|
||||
override fun toString(): String =
|
||||
_owner?.toString() ?: "UNBOUND-WASM-SYMBOL"
|
||||
}
|
||||
|
||||
class WasmSymbolIntWrapper(val symbol: WasmSymbol<WasmNamedModuleField>) : WasmSymbolReadOnly<Int> {
|
||||
override val owner: Int
|
||||
get() = symbol.owner.id!!
|
||||
|
||||
override fun toString() = owner.toString()
|
||||
}
|
||||
|
||||
@@ -82,11 +82,14 @@ abstract class WasmExpressionBuilder {
|
||||
buildInstr(WasmOp.CALL, WasmImmediate.FuncIdx(symbol))
|
||||
}
|
||||
|
||||
fun buildCallIndirect(symbol: WasmSymbol<WasmFunctionType>) {
|
||||
fun buildCallIndirect(
|
||||
symbol: WasmSymbol<WasmFunctionType>,
|
||||
tableIdx: WasmSymbolReadOnly<Int> = WasmSymbol(0),
|
||||
) {
|
||||
buildInstr(
|
||||
WasmOp.CALL_INDIRECT,
|
||||
WasmImmediate.TypeIdx(symbol),
|
||||
WasmImmediate.TableIdx(0)
|
||||
WasmImmediate.TableIdx(tableIdx)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -23,3 +23,9 @@ class WasmIrExpressionBuilder(
|
||||
override val lastInstr: WasmOp?
|
||||
get() = expression.lastOrNull()?.operator
|
||||
}
|
||||
|
||||
inline fun buildWasmExpression(body: WasmExpressionBuilder.() -> Unit): MutableList<WasmInstr> {
|
||||
val res = mutableListOf<WasmInstr>()
|
||||
WasmIrExpressionBuilder(res).body()
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ class WasmIrToBinary(outputStream: OutputStream, val module: WasmModule) {
|
||||
is WasmImmediate.TypeIdx -> appendModuleFieldReference(x.value.owner)
|
||||
is WasmImmediate.MemoryIdx -> appendModuleFieldReference(x.value.owner)
|
||||
is WasmImmediate.DataIdx -> b.writeVarUInt32(x.value)
|
||||
is WasmImmediate.TableIdx -> b.writeVarUInt32(x.value)
|
||||
is WasmImmediate.TableIdx -> b.writeVarUInt32(x.value.owner)
|
||||
is WasmImmediate.LabelIdx -> b.writeVarUInt32(x.value)
|
||||
is WasmImmediate.LabelIdxVector -> {
|
||||
b.writeVarUInt32(x.value.size)
|
||||
@@ -243,7 +243,7 @@ class WasmIrToBinary(outputStream: OutputStream, val module: WasmModule) {
|
||||
b.writeByte(1)
|
||||
}
|
||||
|
||||
b.writeVarInt7(table.elementType.code)
|
||||
appendType(table.elementType)
|
||||
appendLimits(table.limits)
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ class WasmIrToBinary(outputStream: OutputStream, val module: WasmModule) {
|
||||
}
|
||||
|
||||
private fun appendElement(element: WasmElement) {
|
||||
val isFuncIndices = element.values.all { it is WasmTable.Value.Function }
|
||||
val isFuncIndices = element.values.all { it is WasmTable.Value.Function } && element.type == WasmFuncRef
|
||||
|
||||
val funcIndices = if (isFuncIndices) {
|
||||
element.values.map { (it as WasmTable.Value.Function).function.owner.id!! }
|
||||
|
||||
Reference in New Issue
Block a user