[Wasm] Change externRefToAny to make it compatible with SpiderMonkey and V8
It's hard to achieve that without implementing part of `externRefToAny` using an intrinsic. It should be rewritten when all VMs and tools update to the latest spec. Also, stop using (deprecated) instructions unsupported by SpiderMonkey. #KT-56166 In-Progress
This commit is contained in:
@@ -211,6 +211,7 @@ class WasmSymbols(
|
|||||||
val nullableDoubleIeee754Equals = getInternalFunction("nullableDoubleIeee754Equals")
|
val nullableDoubleIeee754Equals = getInternalFunction("nullableDoubleIeee754Equals")
|
||||||
|
|
||||||
val unsafeGetScratchRawMemory = getInternalFunction("unsafeGetScratchRawMemory")
|
val unsafeGetScratchRawMemory = getInternalFunction("unsafeGetScratchRawMemory")
|
||||||
|
val returnArgumentIfItIsKotlinAny = getInternalFunction("returnArgumentIfItIsKotlinAny")
|
||||||
|
|
||||||
val newJsArray = getInternalFunction("newJsArray")
|
val newJsArray = getInternalFunction("newJsArray")
|
||||||
val jsArrayPush = getInternalFunction("jsArrayPush")
|
val jsArrayPush = getInternalFunction("jsArrayPush")
|
||||||
|
|||||||
+14
-2
@@ -594,11 +594,23 @@ class BodyGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
wasmSymbols.unsafeGetScratchRawMemory -> {
|
wasmSymbols.unsafeGetScratchRawMemory -> {
|
||||||
|
|
||||||
body.buildConstI32Symbol(context.scratchMemAddr, location)
|
body.buildConstI32Symbol(context.scratchMemAddr, location)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wasmSymbols.returnArgumentIfItIsKotlinAny -> {
|
||||||
|
body.buildBlock("returnIfAny", WasmAnyRef) { innerLabel ->
|
||||||
|
body.buildGetLocal(functionContext.referenceLocal(0), location)
|
||||||
|
body.buildInstr(WasmOp.EXTERN_INTERNALIZE, location)
|
||||||
|
body.buildBrInstr(WasmOp.BR_ON_NON_DATA_DEPRECATED, innerLabel, location)
|
||||||
|
body.buildBrInstr(
|
||||||
|
WasmOp.BR_ON_CAST_FAIL_DEPRECATED,
|
||||||
|
innerLabel,
|
||||||
|
context.referenceGcType(backendContext.irBuiltIns.anyClass),
|
||||||
|
location
|
||||||
|
)
|
||||||
|
body.buildInstr(WasmOp.RETURN, location)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wasmSymbols.wasmArrayCopy -> {
|
wasmSymbols.wasmArrayCopy -> {
|
||||||
val immediate = WasmImmediate.GcType(
|
val immediate = WasmImmediate.GcType(
|
||||||
|
|||||||
@@ -139,6 +139,22 @@ private fun Any.asWasmExternRef(): ExternalInterfaceType =
|
|||||||
@JsFun("(ref) => ref == null")
|
@JsFun("(ref) => ref == null")
|
||||||
internal external fun isNullish(ref: ExternalInterfaceType?): Boolean
|
internal external fun isNullish(ref: ExternalInterfaceType?): Boolean
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
|
@ExcludedFromCodegen
|
||||||
|
/*
|
||||||
|
* Compiler generates inplace next code:
|
||||||
|
* ```
|
||||||
|
* block (result anyref) {
|
||||||
|
* local.get 0
|
||||||
|
* extern.internalize
|
||||||
|
* br_on_non_data_fail 0
|
||||||
|
* br_on_cast_fail 0 (type $kotlin.Any)
|
||||||
|
* return
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
internal fun returnArgumentIfItIsKotlinAny(ref: ExternalInterfaceType): Unit = implementedAsIntrinsic
|
||||||
|
|
||||||
internal fun externRefToAny(ref: ExternalInterfaceType): Any? {
|
internal fun externRefToAny(ref: ExternalInterfaceType): Any? {
|
||||||
// TODO rewrite it so to get something like:
|
// TODO rewrite it so to get something like:
|
||||||
// block {
|
// block {
|
||||||
@@ -147,13 +163,7 @@ internal fun externRefToAny(ref: ExternalInterfaceType): Any? {
|
|||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
// If ref is an instance of kotlin class -- return it casted to Any
|
// If ref is an instance of kotlin class -- return it casted to Any
|
||||||
val refAsAnyref = ref.externAsWasmAnyref()
|
returnArgumentIfItIsKotlinAny(ref)
|
||||||
if (wasm_ref_is_data_deprecated(refAsAnyref)) {
|
|
||||||
val refAsDataRef = wasm_ref_as_data_deprecated(refAsAnyref)
|
|
||||||
if (wasm_ref_test_deprecated<Any>(refAsDataRef)) {
|
|
||||||
return wasm_ref_cast_deprecated<Any>(refAsDataRef)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have Null in notNullRef -- return null
|
// If we have Null in notNullRef -- return null
|
||||||
// If we already have a box -- return it,
|
// If we already have a box -- return it,
|
||||||
|
|||||||
@@ -387,9 +387,3 @@ internal external fun wasm_i64_ctz(a: Long): Long
|
|||||||
|
|
||||||
@WasmOp(WasmOp.REF_IS_NULL)
|
@WasmOp(WasmOp.REF_IS_NULL)
|
||||||
internal external fun wasm_externref_is_null(a: ExternalInterfaceType?): Boolean
|
internal external fun wasm_externref_is_null(a: ExternalInterfaceType?): Boolean
|
||||||
|
|
||||||
@WasmOp(WasmOp.REF_AS_DATA_DEPRECATED)
|
|
||||||
internal external fun wasm_ref_as_data_deprecated(x: anyref): dataref
|
|
||||||
|
|
||||||
@WasmOp(WasmOp.REF_IS_DATA_DEPRECATED)
|
|
||||||
internal external fun wasm_ref_is_data_deprecated(x: anyref): Boolean
|
|
||||||
|
|||||||
@@ -243,7 +243,6 @@ internal annotation class WasmOp(val name: String) {
|
|||||||
const val ARRAY_COPY = "ARRAY_COPY"
|
const val ARRAY_COPY = "ARRAY_COPY"
|
||||||
const val ARRAY_NEW_DATA = "ARRAY_NEW_DATA"
|
const val ARRAY_NEW_DATA = "ARRAY_NEW_DATA"
|
||||||
const val ARRAY_NEW_FIXED = "ARRAY_NEW_FIXED"
|
const val ARRAY_NEW_FIXED = "ARRAY_NEW_FIXED"
|
||||||
const val ARRAY_NEW_ELEM = "ARRAY_NEW_ELEM"
|
|
||||||
const val I31_NEW = "I31_NEW"
|
const val I31_NEW = "I31_NEW"
|
||||||
const val I31_GET_S = "I31_GET_S"
|
const val I31_GET_S = "I31_GET_S"
|
||||||
const val I31_GET_U = "I31_GET_U"
|
const val I31_GET_U = "I31_GET_U"
|
||||||
@@ -252,9 +251,11 @@ internal annotation class WasmOp(val name: String) {
|
|||||||
const val EXTERN_EXTERNALIZE = "EXTERN_EXTERNALIZE"
|
const val EXTERN_EXTERNALIZE = "EXTERN_EXTERNALIZE"
|
||||||
const val REF_TEST_DEPRECATED = "REF_TEST_DEPRECATED"
|
const val REF_TEST_DEPRECATED = "REF_TEST_DEPRECATED"
|
||||||
const val REF_CAST_DEPRECATED = "REF_CAST_DEPRECATED"
|
const val REF_CAST_DEPRECATED = "REF_CAST_DEPRECATED"
|
||||||
const val REF_IS_DATA_DEPRECATED = "REF_IS_DATA_DEPRECATED"
|
|
||||||
const val REF_AS_DATA_DEPRECATED = "REF_AS_DATA_DEPRECATED"
|
|
||||||
const val BR_ON_CAST_FAIL_DEPRECATED = "BR_ON_CAST_FAIL_DEPRECATED"
|
const val BR_ON_CAST_FAIL_DEPRECATED = "BR_ON_CAST_FAIL_DEPRECATED"
|
||||||
|
const val BR_ON_NON_DATA_DEPRECATED = "BR_ON_NON_DATA_DEPRECATED"
|
||||||
const val GET_UNIT = "GET_UNIT"
|
const val GET_UNIT = "GET_UNIT"
|
||||||
|
const val PSEUDO_COMMENT_PREVIOUS_INSTR = "PSEUDO_COMMENT_PREVIOUS_INSTR"
|
||||||
|
const val PSEUDO_COMMENT_GROUP_START = "PSEUDO_COMMENT_GROUP_START"
|
||||||
|
const val PSEUDO_COMMENT_GROUP_END = "PSEUDO_COMMENT_GROUP_END"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -397,10 +397,8 @@ enum class WasmOp(
|
|||||||
REF_TEST_DEPRECATED("ref.test", 0xFB_44, STRUCT_TYPE_IDX),
|
REF_TEST_DEPRECATED("ref.test", 0xFB_44, STRUCT_TYPE_IDX),
|
||||||
REF_CAST_DEPRECATED("ref.cast", 0xFB_45, STRUCT_TYPE_IDX),
|
REF_CAST_DEPRECATED("ref.cast", 0xFB_45, STRUCT_TYPE_IDX),
|
||||||
|
|
||||||
REF_IS_DATA_DEPRECATED("ref.is_data", 0xFB_51),
|
|
||||||
REF_AS_DATA_DEPRECATED("ref.as_data", 0xFB_59),
|
|
||||||
|
|
||||||
BR_ON_CAST_FAIL_DEPRECATED("br_on_cast_fail", 0xFB_47, listOf(LABEL_IDX, STRUCT_TYPE_IDX)),
|
BR_ON_CAST_FAIL_DEPRECATED("br_on_cast_fail", 0xFB_47, listOf(LABEL_IDX, STRUCT_TYPE_IDX)),
|
||||||
|
BR_ON_NON_DATA_DEPRECATED("br_on_non_data_fail", 0xFB_64, listOf(LABEL_IDX)),
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Pseudo-instruction, just alias for a normal call. It's used to easily spot get_unit on the wasm level.
|
// Pseudo-instruction, just alias for a normal call. It's used to easily spot get_unit on the wasm level.
|
||||||
|
|||||||
Reference in New Issue
Block a user