Skip to content

Commit

Permalink
Refactor memory (#135)
Browse files Browse the repository at this point in the history
  • Loading branch information
illarionov authored Jun 20, 2024
1 parent d35b1ed commit 70eb5b0
Show file tree
Hide file tree
Showing 17 changed files with 109 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import ru.pixnews.wasm.sqlite.open.helper.host.base.WasmPtr
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.Memory
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.readNullableNullTerminatedString
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.readPtr
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.write
import ru.pixnews.wasm.sqlite.open.helper.host.base.plus
import ru.pixnews.wasm.sqlite.open.helper.sqlite.common.api.SqliteColumnType
import ru.pixnews.wasm.sqlite.open.helper.sqlite.common.api.SqliteDb
Expand Down Expand Up @@ -46,7 +45,7 @@ public class Sqlite3StatementFunctions internal constructor(
ppStatement = memoryBindings.sqliteAllocOrThrow(WasmPtr.WASM_SIZEOF_PTR)

memory.write(sqlBytesPtr, sqlEncoded)
memory.writeByte(sqlBytesPtr + sqlEncoded.size, 0)
memory.writeI8(sqlBytesPtr + sqlEncoded.size, 0)

val errCode = sqliteExports.sqlite3_prepare_v2.executeForSqliteResultCode(
sqliteDb.addr,
Expand Down Expand Up @@ -244,6 +243,6 @@ public class Sqlite3StatementFunctions internal constructor(
statement.addr,
columnIndex,
)
return memory.readBytes(ptr, bytes)
return ByteArray(bytes).also { memory.read(ptr, it) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@ internal class ChasmMemoryAdapter(
return MemoryInstanceLongReaderImpl(memoryInstance, addr.addr, 8).getOrThrow()
}

override fun readBytes(addr: WasmPtr<*>, length: Int): ByteArray {
return ByteArray(length) { readMemory(store, memoryAddress, addr.addr + it).orThrow() }
override fun read(addr: WasmPtr<*>, destination: ByteArray, destinationOffset: Int, readBytes: Int) {
repeat(readBytes) { offset ->
destination[destinationOffset + offset] = readMemory(store, memoryAddress, addr.addr + offset).orThrow()
}
}

override fun writeByte(addr: WasmPtr<*>, data: Byte) {
override fun writeI8(addr: WasmPtr<*>, data: Byte) {
writeMemory(store, memoryAddress, addr.addr, data).orThrow()
}

Expand All @@ -59,9 +61,9 @@ internal class ChasmMemoryAdapter(
return MemoryInstanceLongWriterImpl(memoryInstance, data, addr.addr, 8).getOrThrow()
}

override fun write(addr: WasmPtr<*>, data: ByteArray, offset: Int, size: Int) {
for (addrOffset in 0 until size) {
writeMemory(store, memoryAddress, addr.addr + addrOffset, data[offset + addrOffset])
override fun write(addr: WasmPtr<*>, source: ByteArray, sourceOffset: Int, writeBytes: Int) {
for (addrOffset in 0 until writeBytes) {
writeMemory(store, memoryAddress, addr.addr + addrOffset, source[sourceOffset + addrOffset])
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ internal class ChicoryMemoryAdapter(
return wasmMemory.readI64(addr.addr).asLong()
}

override fun readBytes(addr: WasmPtr<*>, length: Int): ByteArray {
return wasmMemory.readBytes(addr.addr, length)
override fun read(addr: WasmPtr<*>, destination: ByteArray, destinationOffset: Int, readBytes: Int) {
val bytes = wasmMemory.readBytes(addr.addr, readBytes)
bytes.copyInto(destination, destinationOffset)
}

override fun writeByte(addr: WasmPtr<*>, data: Byte) {
override fun writeI8(addr: WasmPtr<*>, data: Byte) {
wasmMemory.writeByte(addr.addr, data)
}

Expand All @@ -42,7 +43,7 @@ internal class ChicoryMemoryAdapter(
wasmMemory.writeLong(addr.addr, data)
}

override fun write(addr: WasmPtr<*>, data: ByteArray, offset: Int, size: Int) {
wasmMemory.write(addr.addr, data, offset, size)
override fun write(addr: WasmPtr<*>, source: ByteArray, sourceOffset: Int, writeBytes: Int) {
wasmMemory.write(addr.addr, source, sourceOffset, writeBytes)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,17 @@ internal class GraalvmWasmHostMemoryAdapter(
return wasmMemory.load_i64(node, addr.addr.toLong())
}

override fun readBytes(addr: WasmPtr<*>, length: Int): ByteArray {
val bous = ByteArrayOutputStream(length)
wasmMemory.copyToStream(node, bous, addr.addr, length)
return bous.toByteArray()
override fun read(addr: WasmPtr<*>, destination: ByteArray, destinationOffset: Int, readBytes: Int) {
val bous = object : ByteArrayOutputStream(readBytes) {
fun copyInto(destination: ByteArray, destinationOffset: Int) {
buf.copyInto(destination, destinationOffset, 0, count)
}
}
wasmMemory.copyToStream(node, bous, addr.addr, readBytes)
bous.copyInto(destination, destinationOffset)
}

override fun writeByte(addr: WasmPtr<*>, data: Byte) {
override fun writeI8(addr: WasmPtr<*>, data: Byte) {
wasmMemory.store_i32_8(node, addr.addr.toLong(), data)
}

Expand All @@ -57,7 +61,7 @@ internal class GraalvmWasmHostMemoryAdapter(
wasmMemory.store_i64(node, addr.addr.toLong(), data)
}

override fun write(addr: WasmPtr<*>, data: ByteArray, offset: Int, size: Int) {
wasmMemory.initialize(data, offset, addr.addr.toLong(), size)
override fun write(addr: WasmPtr<*>, source: ByteArray, sourceOffset: Int, writeBytes: Int) {
wasmMemory.initialize(source, sourceOffset, addr.addr.toLong(), writeBytes)
}
}
64 changes: 60 additions & 4 deletions wasi-emscripten-host/src/commonMain/kotlin/base/memory/Memory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,32 @@

package ru.pixnews.wasm.sqlite.open.helper.host.base.memory

import okio.Buffer
import ru.pixnews.wasm.sqlite.open.helper.common.api.InternalWasmSqliteHelperApi
import ru.pixnews.wasm.sqlite.open.helper.host.base.WasmPtr
import ru.pixnews.wasm.sqlite.open.helper.host.base.isSqlite3Null

@InternalWasmSqliteHelperApi
public interface Memory {
public fun readI8(addr: WasmPtr<*>): Byte
public fun readI32(addr: WasmPtr<*>): Int
public fun readI64(addr: WasmPtr<*>): Long
public fun readBytes(addr: WasmPtr<*>, length: Int): ByteArray
public fun read(
addr: WasmPtr<*>,
destination: ByteArray,
destinationOffset: Int = 0,
readBytes: Int = destination.size,
)

public fun writeByte(addr: WasmPtr<*>, data: Byte)
public fun writeI8(addr: WasmPtr<*>, data: Byte)
public fun writeI32(addr: WasmPtr<*>, data: Int)
public fun writeI64(addr: WasmPtr<*>, data: Long)
public fun write(addr: WasmPtr<*>, data: ByteArray, offset: Int, size: Int)
public fun write(
addr: WasmPtr<*>,
source: ByteArray,
sourceOffset: Int = 0,
writeBytes: Int = source.size,
)
}

@InternalWasmSqliteHelperApi
Expand All @@ -31,6 +43,15 @@ public fun Memory.readU32(addr: WasmPtr<*>): UInt = readI32(addr).toUInt()
@InternalWasmSqliteHelperApi
public fun Memory.readU64(addr: WasmPtr<*>): ULong = readI64(addr).toULong()

@InternalWasmSqliteHelperApi
public fun Memory.writeU8(addr: WasmPtr<*>, data: UByte): Unit = writeI8(addr, data.toByte())

@InternalWasmSqliteHelperApi
public fun Memory.writeU32(addr: WasmPtr<*>, data: UInt): Unit = writeI32(addr, data.toInt())

@InternalWasmSqliteHelperApi
public fun Memory.writeU64(addr: WasmPtr<*>, data: ULong): Unit = writeI64(addr, data.toLong())

@Suppress("UNCHECKED_CAST")
@InternalWasmSqliteHelperApi
public fun <T : Any, P : WasmPtr<T>> Memory.readPtr(addr: WasmPtr<P>): P = WasmPtr<T>(readI32(addr)) as P
Expand All @@ -39,4 +60,39 @@ public fun <T : Any, P : WasmPtr<T>> Memory.readPtr(addr: WasmPtr<P>): P = WasmP
public fun Memory.writePtr(addr: WasmPtr<*>, data: WasmPtr<*>): Unit = writeI32(addr, data.addr)

@InternalWasmSqliteHelperApi
public fun Memory.write(addr: WasmPtr<*>, data: ByteArray): Unit = write(addr, data, 0, data.size)
public fun Memory.readNullableNullTerminatedString(offset: WasmPtr<Byte>): String? {
return if (!offset.isSqlite3Null()) {
readNullTerminatedString(offset)
} else {
null
}
}

@InternalWasmSqliteHelperApi
public fun Memory.readNullTerminatedString(offset: WasmPtr<Byte>): String {
check(offset.addr != 0)

val mem = Buffer()
var addr = offset.addr
do {
val byte = this.readI8(WasmPtr<Unit>(addr))
addr += 1
if (byte == 0.toByte()) {
break
}
mem.writeByte(byte.toInt())
} while (true)

return mem.readByteString().utf8()
}

@InternalWasmSqliteHelperApi
public fun Memory.writeNullTerminatedString(
offset: WasmPtr<*>,
value: String,
): Int {
val encoded = value.encodeToByteArray()
write(offset, encoded)
writeI8(WasmPtr<Unit>(offset.addr + encoded.size), 0)
return encoded.size + 1
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,9 @@ public class DefaultWasiMemoryWriter(
memory: Memory,
): List<FileSystemByteBuffer> = List(ciovecList.size) { idx ->
val ciovec = ciovecList[idx]
val bytes = memory.readBytes(
ciovec.buf,
ciovec.bufLen.value.toInt(),
)
val bytes = ByteArray(ciovec.bufLen.value.toInt()).also {
memory.read(ciovec.buf, it)
}
FileSystemByteBuffer(bytes)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ internal class FcntlHandler(
varArgs: Int?,
): Int {
val structStatPtr: WasmPtr<StructFlock> = memory.readPtr(WasmPtr(checkNotNull(varArgs)))
val flockPacked = memory.readBytes(structStatPtr, StructFlock.STRUCT_FLOCK_SIZE)
val flockPacked = ByteArray(StructFlock.STRUCT_FLOCK_SIZE).also {
memory.read(structStatPtr, it)
}
val flock = StructFlock.unpack(flockPacked)

logger.v { "F_SETLK($fd, $flock)" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import ru.pixnews.wasm.sqlite.open.helper.host.EmbedderHost
import ru.pixnews.wasm.sqlite.open.helper.host.base.WasmPtr
import ru.pixnews.wasm.sqlite.open.helper.host.base.function.HostFunctionHandle
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.Memory
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.write
import ru.pixnews.wasm.sqlite.open.helper.host.emscripten.EmscriptenHostFunction

public class GetentropyFunctionHandle(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import ru.pixnews.wasm.sqlite.open.helper.host.EmbedderHost
import ru.pixnews.wasm.sqlite.open.helper.host.base.WasmPtr
import ru.pixnews.wasm.sqlite.open.helper.host.base.function.HostFunctionHandle
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.Memory
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.write
import ru.pixnews.wasm.sqlite.open.helper.host.emscripten.EmscriptenHostFunction
import ru.pixnews.wasm.sqlite.open.helper.host.include.StructTm
import ru.pixnews.wasm.sqlite.open.helper.host.include.pack
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import ru.pixnews.wasm.sqlite.open.helper.host.EmbedderHost
import ru.pixnews.wasm.sqlite.open.helper.host.base.WasmPtr
import ru.pixnews.wasm.sqlite.open.helper.host.base.function.HostFunctionHandle
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.Memory
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.write
import ru.pixnews.wasm.sqlite.open.helper.host.emscripten.EmscriptenHostFunction
import ru.pixnews.wasm.sqlite.open.helper.host.filesystem.SysException
import ru.pixnews.wasm.sqlite.open.helper.host.include.sys.StructStat
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import ru.pixnews.wasm.sqlite.open.helper.host.EmbedderHost
import ru.pixnews.wasm.sqlite.open.helper.host.base.WasmPtr
import ru.pixnews.wasm.sqlite.open.helper.host.base.function.HostFunctionHandle
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.Memory
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.write
import ru.pixnews.wasm.sqlite.open.helper.host.emscripten.EmscriptenHostFunction
import ru.pixnews.wasm.sqlite.open.helper.host.ext.encodeToNullTerminatedByteArray
import ru.pixnews.wasm.sqlite.open.helper.host.wasi.preview1.type.Errno
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import ru.pixnews.wasm.sqlite.open.helper.host.base.function.HostFunction
import ru.pixnews.wasm.sqlite.open.helper.host.base.function.HostFunctionHandle
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.Memory
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.readNullTerminatedString
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.write
import ru.pixnews.wasm.sqlite.open.helper.host.emscripten.EmscriptenHostFunction
import ru.pixnews.wasm.sqlite.open.helper.host.filesystem.SysException
import ru.pixnews.wasm.sqlite.open.helper.host.include.sys.StructStat
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import ru.pixnews.wasm.sqlite.open.helper.host.EmbedderHost
import ru.pixnews.wasm.sqlite.open.helper.host.base.WasmPtr
import ru.pixnews.wasm.sqlite.open.helper.host.base.function.HostFunctionHandle
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.Memory
import ru.pixnews.wasm.sqlite.open.helper.host.base.memory.write
import ru.pixnews.wasm.sqlite.open.helper.host.emscripten.EmscriptenHostFunction
import ru.pixnews.wasm.sqlite.open.helper.host.ext.encodeToNullTerminatedByteArray

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import ru.pixnews.wasm.sqlite.open.helper.common.api.InternalWasmSqliteHelperApi

@InternalWasmSqliteHelperApi
public fun String.encodeToNullTerminatedByteArray(
maxDstSize: Int = Int.MAX_VALUE,
truncateAtSize: Int = Int.MAX_VALUE,
): ByteArray {
require(maxDstSize > 0)
require(truncateAtSize > 0)

val raw = this.encodeToByteArray()
val rawSize = raw.size.coerceAtMost(maxDstSize - 1)
val rawSize = raw.size.coerceAtMost(truncateAtSize - 1)
val os = ByteArray(rawSize + 1) { pos ->
if (pos < rawSize) {
raw[pos]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import ru.pixnews.wasm.sqlite.open.helper.host.test.fixtures.TestMemory
fun Assert<TestMemory>.bytesAt(
address: WasmPtr<Byte>,
size: Int,
) = transform(appendName("TestMemory{$address}", separator = ".")) {
it.readBytes(address, size)
) = transform(appendName("TestMemory{$address}", separator = ".")) { testMemory ->
ByteArray(size).also { testMemory.read(address, it) }
}

fun Assert<TestMemory>.hasBytesAt(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,16 @@ open class TestMemory(
(bytes[addr.addr + 6].toLong() and 0xffL shl 48) or
(bytes[addr.addr + 7].toLong() and 0xffL shl 56)

override fun readBytes(addr: WasmPtr<*>, length: Int): ByteArray = ByteArray(length) {
bytes[addr.addr + it]
override fun read(addr: WasmPtr<*>, destination: ByteArray, destinationOffset: Int, readBytes: Int) {
bytes.copyInto(
destination = destination,
destinationOffset = destinationOffset,
startIndex = addr.addr,
endIndex = addr.addr + readBytes,
)
}

override fun writeByte(addr: WasmPtr<*>, data: Byte) {
override fun writeI8(addr: WasmPtr<*>, data: Byte) {
bytes[addr.addr] = data
}

Expand All @@ -71,9 +76,9 @@ open class TestMemory(
bytes[addr.addr + 7] = (data ushr 56 and 0xff).toByte()
}

override fun write(addr: WasmPtr<*>, data: ByteArray, offset: Int, size: Int) {
for (i in 0 until size) {
bytes[addr.addr + i] = data[offset + i]
override fun write(addr: WasmPtr<*>, source: ByteArray, sourceOffset: Int, writeBytes: Int) {
for (i in 0 until writeBytes) {
bytes[addr.addr + i] = source[sourceOffset + i]
}
}

Expand Down

0 comments on commit 70eb5b0

Please sign in to comment.