[Wasm] Improve class type checks
Use wasm ref.test instad of manual type info linked list traversal
This commit is contained in:
@@ -113,6 +113,7 @@ class WasmSymbols(
|
|||||||
val booleanAnd = getInternalFunction("wasm_i32_and")
|
val booleanAnd = getInternalFunction("wasm_i32_and")
|
||||||
val refEq = getInternalFunction("wasm_ref_eq")
|
val refEq = getInternalFunction("wasm_ref_eq")
|
||||||
val refIsNull = getInternalFunction("wasm_ref_is_null")
|
val refIsNull = getInternalFunction("wasm_ref_is_null")
|
||||||
|
val refTest = getInternalFunction("wasm_ref_test")
|
||||||
val intToLong = getInternalFunction("wasm_i64_extend_i32_s")
|
val intToLong = getInternalFunction("wasm_i64_extend_i32_s")
|
||||||
|
|
||||||
val wasmRefCast = getInternalFunction("wasm_ref_cast")
|
val wasmRefCast = getInternalFunction("wasm_ref_cast")
|
||||||
|
|||||||
+21
-2
@@ -258,7 +258,7 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
|
|||||||
call: IrFunctionAccessExpression,
|
call: IrFunctionAccessExpression,
|
||||||
function: IrFunction
|
function: IrFunction
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (tryToGenerateWasmOpIntrinsicCall(function)) {
|
if (tryToGenerateWasmOpIntrinsicCall(call, function)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,7 +489,7 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return true if function is recognized as intrinsic.
|
// Return true if function is recognized as intrinsic.
|
||||||
fun tryToGenerateWasmOpIntrinsicCall(function: IrFunction): Boolean {
|
fun tryToGenerateWasmOpIntrinsicCall(call: IrFunctionAccessExpression, function: IrFunction): Boolean {
|
||||||
if (function.hasWasmReinterpretAnnotation()) {
|
if (function.hasWasmReinterpretAnnotation()) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -513,6 +513,25 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
2 -> {
|
||||||
|
when (op) {
|
||||||
|
WasmOp.REF_TEST -> {
|
||||||
|
val fromIrType = call.getValueArgument(0)!!.type
|
||||||
|
val fromWasmType = context.transformBoxedType(fromIrType)
|
||||||
|
val toIrType = call.getTypeArgument(0)!!
|
||||||
|
val toWasmType = context.transformBoxedType(toIrType)
|
||||||
|
immediates = arrayOf(
|
||||||
|
WasmImmediate.HeapType(fromWasmType),
|
||||||
|
WasmImmediate.HeapType(toWasmType),
|
||||||
|
)
|
||||||
|
|
||||||
|
// ref.test takes RTT as a second operand
|
||||||
|
generateTypeRTT(toIrType)
|
||||||
|
}
|
||||||
|
else ->
|
||||||
|
error("Op $opString is unsupported")
|
||||||
|
}
|
||||||
|
}
|
||||||
else ->
|
else ->
|
||||||
error("Op $opString is unsupported")
|
error("Op $opString is unsupported")
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-5
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
|||||||
import org.jetbrains.kotlin.backend.common.lower.irNot
|
import org.jetbrains.kotlin.backend.common.lower.irNot
|
||||||
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
|
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.wasm.ir2wasm.erasedUpperBound
|
import org.jetbrains.kotlin.backend.wasm.ir2wasm.erasedUpperBound
|
||||||
import org.jetbrains.kotlin.ir.util.isPure
|
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||||
@@ -276,12 +275,25 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateIsSubClass(argument: IrExpression, toType: IrType): IrExpression {
|
private fun generateIsSubClass(argument: IrExpression, toType: IrType): IrExpression {
|
||||||
val classId = builder.irCall(symbols.wasmClassId).apply {
|
val fromType = argument.type
|
||||||
putTypeArgument(0, toType)
|
val fromTypeErased = fromType.erasedType
|
||||||
|
val toTypeErased = toType.erasedType
|
||||||
|
if (fromTypeErased.isSubtypeOfClass(toTypeErased.classOrNull!!)) {
|
||||||
|
return builder.irComposite {
|
||||||
|
+argument
|
||||||
|
+builder.irTrue()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return builder.irCall(symbols.isSubClass).apply {
|
if (!toTypeErased.isSubtypeOfClass(fromTypeErased.classOrNull!!)) {
|
||||||
|
return builder.irComposite {
|
||||||
|
+argument
|
||||||
|
+builder.irFalse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.irCall(symbols.refTest).apply {
|
||||||
putValueArgument(0, argument)
|
putValueArgument(0, argument)
|
||||||
putValueArgument(1, classId)
|
putTypeArgument(0, toType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,6 +254,8 @@ public external fun wasm_ref_is_null(a: Any?): Boolean
|
|||||||
@WasmOp(WasmOp.REF_EQ)
|
@WasmOp(WasmOp.REF_EQ)
|
||||||
public external fun wasm_ref_eq(a: Any?, b: Any?): Boolean
|
public external fun wasm_ref_eq(a: Any?, b: Any?): Boolean
|
||||||
|
|
||||||
|
@WasmOp(WasmOp.REF_TEST)
|
||||||
|
public external fun <T> wasm_ref_test(a: Any?): Boolean
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user