[WASM] Caching string literals in global pool

This commit is contained in:
Igor Yakovlev
2022-10-07 19:03:04 +02:00
committed by teamcity
parent f95bfccf59
commit 033e2c45f1
21 changed files with 206 additions and 126 deletions
@@ -9,7 +9,7 @@ import kotlin.wasm.internal.reftypes.anyref
internal external interface ExternalInterfaceType
internal class JsExternalBox(val ref: ExternalInterfaceType) {
internal class JsExternalBox @WasmPrimitiveConstructor constructor(val ref: ExternalInterfaceType) {
override fun toString(): String =
externrefToString(ref)
@@ -20,8 +20,13 @@ internal class JsExternalBox(val ref: ExternalInterfaceType) {
false
}
override fun hashCode(): Int =
externrefHashCode(ref)
override fun hashCode(): Int {
var hashCode = _hashCode
if (hashCode != 0) return hashCode
hashCode = externrefHashCode(ref)
_hashCode = hashCode
return hashCode
}
}
//language=js
@@ -218,7 +223,7 @@ internal fun jsToKotlinStringAdapter(x: ExternalInterfaceType): String {
val stringLength = stringLength(x)
val dstArray = WasmCharArray(stringLength)
if (stringLength == 0) {
return String(dstArray)
return dstArray.createString()
}
val maxStringLength = unsafeGetScratchRawMemorySize() / CHAR_SIZE_BYTES
@@ -233,7 +238,7 @@ internal fun jsToKotlinStringAdapter(x: ExternalInterfaceType): String {
jsExportStringToWasm(x, srcStartIndex, stringLength - srcStartIndex, memBuffer)
unsafeRawMemoryToWasmCharArray(memBuffer, srcStartIndex, stringLength - srcStartIndex, dstArray)
return String(dstArray)
return dstArray.createString()
}
@@ -64,7 +64,7 @@ internal fun itoa32(inputValue: Int, radix: Int): String {
if (sign == 1)
buf.set(0, CharCodes.MINUS.code.toChar())
return String(buf)
return buf.createString()
}
private fun utoaDecSimple(buffer: WasmCharArray, numInput: Int, offsetInput: Int) {
@@ -144,7 +144,7 @@ internal fun itoa64(inputValue: Long, radix: Int): String {
if (sign == 1)
buf.set(0, CharCodes.MINUS.code.toChar())
return String(buf)
return buf.createString()
}
// Count number of decimals for u64 values
@@ -178,7 +178,7 @@ internal fun dtoa(value: Double): String {
val size = dtoaCore(buf, value)
val ret = WasmCharArray(size)
buf.copyInto(ret, 0, 0, size)
return String(ret)
return ret.createString()
}
private fun dtoaCore(buffer: WasmCharArray, valueInp: Double): Int {
@@ -80,4 +80,12 @@ internal class Void private constructor()
// This is the only way to introduce Void type.
@WasmOp(WasmOp.DROP)
internal fun consumeAnyIntoVoid(a: Any?): Void =
implementedAsIntrinsic
implementedAsIntrinsic
@ExcludedFromCodegen
internal fun stringGetPoolSize(): Int =
implementedAsIntrinsic
// This initializer is a special case in FieldInitializersLowering
@EagerInitialization
internal val stringPool: Array<String?> = arrayOfNulls(stringGetPoolSize())
@@ -10,9 +10,11 @@ package kotlin.wasm.internal
internal const val TYPE_INFO_ELEMENT_SIZE = 4
internal const val TYPE_INFO_TYPE_PACKAGE_NAME_LENGTH_OFFSET = 0
internal const val TYPE_INFO_TYPE_PACKAGE_NAME_PRT_OFFSET = TYPE_INFO_TYPE_PACKAGE_NAME_LENGTH_OFFSET + TYPE_INFO_ELEMENT_SIZE
internal const val TYPE_INFO_TYPE_PACKAGE_NAME_ID_OFFSET = TYPE_INFO_TYPE_PACKAGE_NAME_LENGTH_OFFSET + TYPE_INFO_ELEMENT_SIZE
internal const val TYPE_INFO_TYPE_PACKAGE_NAME_PRT_OFFSET = TYPE_INFO_TYPE_PACKAGE_NAME_ID_OFFSET + TYPE_INFO_ELEMENT_SIZE
internal const val TYPE_INFO_TYPE_SIMPLE_NAME_LENGTH_OFFSET = TYPE_INFO_TYPE_PACKAGE_NAME_PRT_OFFSET + TYPE_INFO_ELEMENT_SIZE
internal const val TYPE_INFO_TYPE_SIMPLE_NAME_PRT_OFFSET = TYPE_INFO_TYPE_SIMPLE_NAME_LENGTH_OFFSET + TYPE_INFO_ELEMENT_SIZE
internal const val TYPE_INFO_TYPE_SIMPLE_NAME_ID_OFFSET = TYPE_INFO_TYPE_SIMPLE_NAME_LENGTH_OFFSET + TYPE_INFO_ELEMENT_SIZE
internal const val TYPE_INFO_TYPE_SIMPLE_NAME_PRT_OFFSET = TYPE_INFO_TYPE_SIMPLE_NAME_ID_OFFSET + TYPE_INFO_ELEMENT_SIZE
internal const val TYPE_INFO_SUPER_TYPE_OFFSET = TYPE_INFO_TYPE_SIMPLE_NAME_PRT_OFFSET + TYPE_INFO_ELEMENT_SIZE
internal const val TYPE_INFO_ITABLE_SIZE_OFFSET = TYPE_INFO_SUPER_TYPE_OFFSET + TYPE_INFO_ELEMENT_SIZE
internal const val TYPE_INFO_ITABLE_OFFSET = TYPE_INFO_ITABLE_SIZE_OFFSET + TYPE_INFO_ELEMENT_SIZE
@@ -21,11 +23,13 @@ internal class TypeInfoData(val typeId: Int, val isInterface: Boolean, val packa
internal fun getTypeInfoTypeDataByPtr(typeInfoPtr: Int): TypeInfoData {
val fqNameLength = wasm_i32_load(typeInfoPtr + TYPE_INFO_TYPE_PACKAGE_NAME_LENGTH_OFFSET)
val fqNameLengthPtr = wasm_i32_load(typeInfoPtr + TYPE_INFO_TYPE_PACKAGE_NAME_PRT_OFFSET)
val fqNameId = wasm_i32_load(typeInfoPtr + TYPE_INFO_TYPE_PACKAGE_NAME_ID_OFFSET)
val fqNamePtr = wasm_i32_load(typeInfoPtr + TYPE_INFO_TYPE_PACKAGE_NAME_PRT_OFFSET)
val simpleNameLength = wasm_i32_load(typeInfoPtr + TYPE_INFO_TYPE_SIMPLE_NAME_LENGTH_OFFSET)
val simpleNameId = wasm_i32_load(typeInfoPtr + TYPE_INFO_TYPE_SIMPLE_NAME_ID_OFFSET)
val simpleNamePtr = wasm_i32_load(typeInfoPtr + TYPE_INFO_TYPE_SIMPLE_NAME_PRT_OFFSET)
val packageName = stringLiteral(fqNameLengthPtr, fqNameLength)
val simpleName = stringLiteral(simpleNamePtr, simpleNameLength)
val packageName = stringLiteral(fqNameId, fqNamePtr, fqNameLength, 0)
val simpleName = stringLiteral(simpleNameId, simpleNamePtr, simpleNameLength, 0)
return TypeInfoData(typeInfoPtr, isInterface = false, packageName, simpleName)
}
@@ -48,4 +48,13 @@ internal annotation class WasmAutoboxed
@ExcludedFromCodegen
internal val implementedAsIntrinsic: Nothing
get() = null!!
get() = null!!
/**
* Indicates that annotated constructor is primitive
* i.e. has direct layout from it's parameters to object fields (except any's fields) and has no code
* In this case no need to call it during an object creation.
*/
@Target(AnnotationTarget.CONSTRUCTOR)
@Retention(AnnotationRetention.BINARY)
internal annotation class WasmPrimitiveConstructor