aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--benchmarks/20240314-0011.log4
-rw-r--r--examples/php-on-wasm/php-wasm.php8
-rw-r--r--src/Execution/MemInst.php273
-rw-r--r--src/Execution/Runtime.php336
-rw-r--r--traces/20240314-0011.stderr.log8
5 files changed, 482 insertions, 147 deletions
diff --git a/benchmarks/20240314-0011.log b/benchmarks/20240314-0011.log
new file mode 100644
index 0000000..2298f1c
--- /dev/null
+++ b/benchmarks/20240314-0011.log
@@ -0,0 +1,4 @@
+Benchmark 1: make run
+ Time (mean ± σ): 6.562 s ± 0.056 s [User: 6.477 s, System: 0.084 s]
+ Range (min … max): 6.495 s … 6.671 s 10 runs
+
diff --git a/examples/php-on-wasm/php-wasm.php b/examples/php-on-wasm/php-wasm.php
index 6443107..54f6561 100644
--- a/examples/php-on-wasm/php-wasm.php
+++ b/examples/php-on-wasm/php-wasm.php
@@ -619,9 +619,9 @@ function hostFunc__wasi_snapshot_preview1__fd_write(Runtime $runtime): void {
$nWritten = 0;
for ($i = 0; $i < $iovcnt; $i++) {
- $ptr = $mem->loadI32($iov + $i * 8, 4, true);
+ $ptr = $mem->loadI32_s32($iov + $i * 8);
assert($ptr !== null);
- $len = $mem->loadI32($iov + $i * 8 + 4, 4, true);
+ $len = $mem->loadI32_s32($iov + $i * 8 + 4);
assert($len !== null);
$buf = '';
for ($j = 0; $j < $len; $j++) {
@@ -636,7 +636,7 @@ function hostFunc__wasi_snapshot_preview1__fd_write(Runtime $runtime): void {
}
$nWritten += $len;
}
- $mem->storeI32($pnum, $nWritten, 4);
+ $mem->storeI32_s32($pnum, $nWritten);
$runtime->stack->pushValue(0);
}
@@ -724,7 +724,7 @@ function hostFunc__env____syscall_openat(Runtime $runtime): void {
assert($mem !== null);
if ($varargs !== 0) {
- $mode = $mem->loadI32($varargs, 4, true);
+ $mode = $mem->loadI32_s32($varargs);
$varargs += 4;
} else {
$mode = 0;
diff --git a/src/Execution/MemInst.php b/src/Execution/MemInst.php
index 20a0e29..338c1a0 100644
--- a/src/Execution/MemInst.php
+++ b/src/Execution/MemInst.php
@@ -47,19 +47,73 @@ final class MemInst
/**
* @return ?S32
*/
- public function loadI32(int $ptr, int $n, bool $signed): ?int
+ public function loadI32_s8(int $ptr): ?int
{
- assert($n !== 4 || $signed);
- $buf = $this->sliceNBytes($ptr, $n);
+ if ($this->size() < $ptr) {
+ return null;
+ }
+ $page = $this->data[intdiv($ptr, self::PAGE_SIZE)];
+ $result = unpack('c', $page, $ptr % self::PAGE_SIZE);
+ assert($result !== false);
+ $c = $result[1];
+ assert(-0x80 <= $c && $c <= 0x7F);
+ return $c;
+ }
+
+ /**
+ * @return ?S32
+ */
+ public function loadI32_u8(int $ptr): ?int
+ {
+ if ($this->size() < $ptr) {
+ return null;
+ }
+ $page = $this->data[intdiv($ptr, self::PAGE_SIZE)];
+ $result = unpack('C', $page, $ptr % self::PAGE_SIZE);
+ assert($result !== false);
+ $c = $result[1];
+ assert(0x00 <= $c && $c <= 0xFF);
+ return $c;
+ }
+
+ /**
+ * @return ?S32
+ */
+ public function loadI32_s16(int $ptr): ?int
+ {
+ $buf = $this->sliceNBytes($ptr, 2);
+ if ($buf === null) {
+ return null;
+ }
+ $result = unpack('s', $buf);
+ assert($result !== false);
+ return $result[1];
+ }
+
+ /**
+ * @return ?S32
+ */
+ public function loadI32_u16(int $ptr): ?int
+ {
+ $buf = $this->sliceNBytes($ptr, 2);
+ if ($buf === null) {
+ return null;
+ }
+ $result = unpack('S', $buf);
+ assert($result !== false);
+ return $result[1];
+ }
+
+ /**
+ * @return ?S32
+ */
+ public function loadI32_s32(int $ptr): ?int
+ {
+ $buf = $this->sliceNBytes($ptr, 4);
if ($buf === null) {
return null;
}
- $result = unpack(match ($n) {
- 1 => $signed ? 'c' : 'C',
- 2 => $signed ? 's' : 'S',
- 4 => 'l',
- default => throw new \LogicException('Invalid byte length'),
- }, $buf);
+ $result = unpack('l', $buf);
assert($result !== false);
return $result[1];
}
@@ -67,20 +121,101 @@ final class MemInst
/**
* @return ?S64
*/
- public function loadI64(int $ptr, int $n, bool $signed): ?int
+ public function loadI64_s8(int $ptr): ?int
+ {
+ if ($this->size() < $ptr) {
+ return null;
+ }
+ $page = $this->data[intdiv($ptr, self::PAGE_SIZE)];
+ $result = unpack('c', $page, $ptr % self::PAGE_SIZE);
+ assert($result !== false);
+ $c = $result[1];
+ assert(-0x80 <= $c && $c <= 0x7F);
+ return $c;
+ }
+
+ /**
+ * @return ?S64
+ */
+ public function loadI64_u8(int $ptr): ?int
{
- assert($n !== 8 || $signed);
- $buf = $this->sliceNBytes($ptr, $n);
+ if ($this->size() < $ptr) {
+ return null;
+ }
+ $page = $this->data[intdiv($ptr, self::PAGE_SIZE)];
+ $result = unpack('C', $page, $ptr % self::PAGE_SIZE);
+ assert($result !== false);
+ $c = $result[1];
+ assert(0x00 <= $c && $c <= 0xFF);
+ return $c;
+ }
+
+ /**
+ * @return ?S64
+ */
+ public function loadI64_s16(int $ptr): ?int
+ {
+ $buf = $this->sliceNBytes($ptr, 2);
if ($buf === null) {
return null;
}
- $result = unpack(match ($n) {
- 1 => $signed ? 'c' : 'C',
- 2 => $signed ? 's' : 'S',
- 4 => $signed ? 'l' : 'L',
- 8 => 'q',
- default => throw new \LogicException('Invalid byte length'),
- }, $buf);
+ $result = unpack('s', $buf);
+ assert($result !== false);
+ return $result[1];
+ }
+
+ /**
+ * @return ?S64
+ */
+ public function loadI64_u16(int $ptr): ?int
+ {
+ $buf = $this->sliceNBytes($ptr, 2);
+ if ($buf === null) {
+ return null;
+ }
+ $result = unpack('S', $buf);
+ assert($result !== false);
+ return $result[1];
+ }
+
+ /**
+ * @return ?S64
+ */
+ public function loadI64_s32(int $ptr): ?int
+ {
+ $buf = $this->sliceNBytes($ptr, 4);
+ if ($buf === null) {
+ return null;
+ }
+ $result = unpack('l', $buf);
+ assert($result !== false);
+ return $result[1];
+ }
+
+ /**
+ * @return ?S64
+ */
+ public function loadI64_u32(int $ptr): ?int
+ {
+ $buf = $this->sliceNBytes($ptr, 4);
+ if ($buf === null) {
+ return null;
+ }
+ $result = unpack('L', $buf);
+ assert($result !== false);
+ return $result[1];
+ }
+
+ /**
+ * @return ?S64
+ */
+ public function loadI64_s64(int $ptr): ?int
+ {
+ $buf = $this->sliceNBytes($ptr, 8);
+ if ($buf === null) {
+ return null;
+ }
+ $result = unpack('q', $buf);
assert($result !== false);
return $result[1];
}
@@ -147,18 +282,70 @@ final class MemInst
* @param S32 $c
* @return bool
*/
- public function storeI32(int $ptr, int $c, int $n): bool
+ public function storeI32_s8(int $ptr, int $c): bool
{
- if ($this->size() < $ptr + $n) {
+ if ($this->size() < $ptr + 1) {
return false;
}
- $buf = pack(match ($n) {
- 1 => 'c',
- 2 => 's',
- 4 => 'l',
- default => throw new \LogicException('Invalid byte length'),
- }, $c);
- for ($i = 0; $i < $n; $i++) {
+ $buf = pack('s', $c);
+ for ($i = 0; $i < 1; $i++) {
+ $this->storeByte($ptr + $i, ord($buf[$i]));
+ }
+ return true;
+ }
+
+ /**
+ * @param S32 $c
+ * @return bool
+ */
+ public function storeI32_s16(int $ptr, int $c): bool
+ {
+ if ($this->size() < $ptr + 2) {
+ return false;
+ }
+ $buf = pack('s', $c);
+ for ($i = 0; $i < 2; $i++) {
+ $this->storeByte($ptr + $i, ord($buf[$i]));
+ }
+ return true;
+ }
+
+ /**
+ * @param S32 $c
+ * @return bool
+ */
+ public function storeI32_s32(int $ptr, int $c): bool
+ {
+ if ($this->size() < $ptr + 4) {
+ return false;
+ }
+ $buf = pack('l', $c);
+ for ($i = 0; $i < 4; $i++) {
+ $this->storeByte($ptr + $i, ord($buf[$i]));
+ }
+ return true;
+ }
+
+ /**
+ * @param S64 $c
+ * @return bool
+ */
+ public function storeI64_s8(int $ptr, int $c): bool
+ {
+ return $this->storeByte($ptr, $c);
+ }
+
+ /**
+ * @param S64 $c
+ * @return bool
+ */
+ public function storeI64_s16(int $ptr, int $c): bool
+ {
+ if ($this->size() < $ptr + 2) {
+ return false;
+ }
+ $buf = pack('s', $c);
+ for ($i = 0; $i < 2; $i++) {
$this->storeByte($ptr + $i, ord($buf[$i]));
}
return true;
@@ -168,19 +355,29 @@ final class MemInst
* @param S64 $c
* @return bool
*/
- public function storeI64(int $ptr, int $c, int $n): bool
+ public function storeI64_s32(int $ptr, int $c): bool
{
- if ($this->size() < $ptr + $n) {
+ if ($this->size() < $ptr + 4) {
return false;
}
- $buf = pack(match ($n) {
- 1 => 'c',
- 2 => 's',
- 4 => 'l',
- 8 => 'q',
- default => throw new \LogicException('Invalid byte length'),
- }, $c);
- for ($i = 0; $i < $n; $i++) {
+ $buf = pack('l', $c);
+ for ($i = 0; $i < 4; $i++) {
+ $this->storeByte($ptr + $i, ord($buf[$i]));
+ }
+ return true;
+ }
+
+ /**
+ * @param S64 $c
+ * @return bool
+ */
+ public function storeI64_s64(int $ptr, int $c): bool
+ {
+ if ($this->size() < $ptr + 8) {
+ return false;
+ }
+ $buf = pack('q', $c);
+ for ($i = 0; $i < 8; $i++) {
$this->storeByte($ptr + $i, ord($buf[$i]));
}
return true;
diff --git a/src/Execution/Runtime.php b/src/Execution/Runtime.php
index 798209d..5f04978 100644
--- a/src/Execution/Runtime.php
+++ b/src/Execution/Runtime.php
@@ -1686,7 +1686,17 @@ final class Runtime
private function execInstrMemoryF32Store(Instrs\Memory\F32Store $instr): void
{
- $this->doStoreF32($instr->offset, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popFloat();
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $ok = $mem->storeF32($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
}
private function execInstrMemoryF64Load(Instrs\Memory\F64Load $instr): void
@@ -1696,102 +1706,302 @@ final class Runtime
private function execInstrMemoryF64Store(Instrs\Memory\F64Store $instr): void
{
- $this->doStoreF64($instr->offset, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popFloat();
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $ok = $mem->storeF64($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
}
private function execInstrMemoryI32Load(Instrs\Memory\I32Load $instr): void
{
- $this->doLoadI32($instr->offset, 4, true, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $c = $mem->loadI32_s32($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
+ $this->stack->pushValue($c);
}
private function execInstrMemoryI32Load16S(Instrs\Memory\I32Load16S $instr): void
{
- $this->doLoadI32($instr->offset, 2, true, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $c = $mem->loadI32_s16($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
+ $this->stack->pushValue($c);
}
private function execInstrMemoryI32Load16U(Instrs\Memory\I32Load16U $instr): void
{
- $this->doLoadI32($instr->offset, 2, false, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $c = $mem->loadI32_u16($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
+ $this->stack->pushValue($c);
}
private function execInstrMemoryI32Load8S(Instrs\Memory\I32Load8S $instr): void
{
- $this->doLoadI32($instr->offset, 1, true, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $c = $mem->loadI32_s8($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
+ $this->stack->pushValue($c);
}
private function execInstrMemoryI32Load8U(Instrs\Memory\I32Load8U $instr): void
{
- $this->doLoadI32($instr->offset, 1, false, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $c = $mem->loadI32_u8($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
+ $this->stack->pushValue($c);
}
private function execInstrMemoryI32Store(Instrs\Memory\I32Store $instr): void
{
- $this->doStoreI32($instr->offset, 4, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popInt();
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $ok = $mem->storeI32_s32($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
}
private function execInstrMemoryI32Store16(Instrs\Memory\I32Store16 $instr): void
{
- $this->doStoreI32($instr->offset, 2, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popInt();
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $ok = $mem->storeI32_s16($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
}
private function execInstrMemoryI32Store8(Instrs\Memory\I32Store8 $instr): void
{
- $this->doStoreI32($instr->offset, 1, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popInt();
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $ok = $mem->storeI32_s8($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
}
private function execInstrMemoryI64Load(Instrs\Memory\I64Load $instr): void
{
- $this->doLoadI64($instr->offset, 8, true, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $c = $mem->loadI64_s64($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
+ $this->stack->pushValue($c);
}
private function execInstrMemoryI64Load16S(Instrs\Memory\I64Load16S $instr): void
{
- $this->doLoadI64($instr->offset, 2, true, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $c = $mem->loadI64_s16($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
+ $this->stack->pushValue($c);
}
private function execInstrMemoryI64Load16U(Instrs\Memory\I64Load16U $instr): void
{
- $this->doLoadI64($instr->offset, 2, false, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $c = $mem->loadI64_u16($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
+ $this->stack->pushValue($c);
}
private function execInstrMemoryI64Load32S(Instrs\Memory\I64Load32S $instr): void
{
- $this->doLoadI64($instr->offset, 4, true, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $c = $mem->loadI64_s32($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
+ $this->stack->pushValue($c);
}
private function execInstrMemoryI64Load32U(Instrs\Memory\I64Load32U $instr): void
{
- $this->doLoadI64($instr->offset, 4, false, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $c = $mem->loadI64_u32($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
+ $this->stack->pushValue($c);
}
private function execInstrMemoryI64Load8S(Instrs\Memory\I64Load8S $instr): void
{
- $this->doLoadI64($instr->offset, 1, true, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $c = $mem->loadI64_s8($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
+ $this->stack->pushValue($c);
}
private function execInstrMemoryI64Load8U(Instrs\Memory\I64Load8U $instr): void
{
- $this->doLoadI64($instr->offset, 1, false, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $c = $mem->loadI64_u8($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds");
+ }
+ $this->stack->pushValue($c);
}
private function execInstrMemoryI64Store(Instrs\Memory\I64Store $instr): void
{
- $this->doStoreI64($instr->offset, 8, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popInt();
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $ok = $mem->storeI64_s64($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds: $ea >= " . $mem->size());
+ }
}
private function execInstrMemoryI64Store16(Instrs\Memory\I64Store16 $instr): void
{
- $this->doStoreI64($instr->offset, 2, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popInt();
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $ok = $mem->storeI64_s16($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds: $ea >= " . $mem->size());
+ }
}
private function execInstrMemoryI64Store32(Instrs\Memory\I64Store32 $instr): void
{
- $this->doStoreI64($instr->offset, 4, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popInt();
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $ok = $mem->storeI64_s32($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds: $ea >= " . $mem->size());
+ }
}
private function execInstrMemoryI64Store8(Instrs\Memory\I64Store8 $instr): void
{
- $this->doStoreI64($instr->offset, 1, $instr::opName());
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popInt();
+ $i = $this->stack->popInt();
+ $ea = $i + $offset;
+ $ok = $mem->storeI64_s8($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds: $ea >= " . $mem->size());
+ }
}
private function execInstrMemoryMemoryCopy(Instrs\Memory\MemoryCopy $instr): void
@@ -2009,34 +2219,6 @@ final class Runtime
throw new TrapException("unreachable");
}
- private function doLoadI32(int $offset, int $n, bool $signed, string $instrOpName): void
- {
- $f = $this->stack->currentFrame();
- $a = $f->module->memAddrs[0];
- $mem = $this->store->mems[$a];
- $i = $this->stack->popInt();
- $ea = $i + $offset;
- $c = $mem->loadI32($ea, $n, $signed);
- if ($c === null) {
- throw new TrapException("$instrOpName: out of bounds");
- }
- $this->stack->pushValue($c);
- }
-
- private function doLoadI64(int $offset, int $n, bool $signed, string $instrOpName): void
- {
- $f = $this->stack->currentFrame();
- $a = $f->module->memAddrs[0];
- $mem = $this->store->mems[$a];
- $i = $this->stack->popInt();
- $ea = $i + $offset;
- $c = $mem->loadI64($ea, $n, $signed);
- if ($c === null) {
- throw new TrapException("$instrOpName: out of bounds");
- }
- $this->stack->pushValue($c);
- }
-
private function doLoadF32(int $offset, string $instrOpName): void
{
$f = $this->stack->currentFrame();
@@ -2065,62 +2247,6 @@ final class Runtime
$this->stack->pushValue($c);
}
- private function doStoreI32(int $offset, int $n, string $instrOpName): void
- {
- $f = $this->stack->currentFrame();
- $a = $f->module->memAddrs[0];
- $mem = $this->store->mems[$a];
- $c = $this->stack->popInt();
- $i = $this->stack->popInt();
- $ea = $i + $offset;
- $ok = $mem->storeI32($ea, $c, $n);
- if (!$ok) {
- throw new TrapException("$instrOpName: out of bounds");
- }
- }
-
- private function doStoreI64(int $offset, int $n, string $instrOpName): void
- {
- $f = $this->stack->currentFrame();
- $a = $f->module->memAddrs[0];
- $mem = $this->store->mems[$a];
- $c = $this->stack->popInt();
- $i = $this->stack->popInt();
- $ea = $i + $offset;
- $ok = $mem->storeI64($ea, $c, $n);
- if (!$ok) {
- throw new TrapException("$instrOpName: out of bounds: $ea >= " . $mem->size());
- }
- }
-
- private function doStoreF32(int $offset, string $instrOpName): void
- {
- $f = $this->stack->currentFrame();
- $a = $f->module->memAddrs[0];
- $mem = $this->store->mems[$a];
- $c = $this->stack->popFloat();
- $i = $this->stack->popInt();
- $ea = $i + $offset;
- $ok = $mem->storeF32($ea, $c);
- if (!$ok) {
- throw new TrapException("$instrOpName: out of bounds");
- }
- }
-
- private function doStoreF64(int $offset, string $instrOpName): void
- {
- $f = $this->stack->currentFrame();
- $a = $f->module->memAddrs[0];
- $mem = $this->store->mems[$a];
- $c = $this->stack->popFloat();
- $i = $this->stack->popInt();
- $ea = $i + $offset;
- $ok = $mem->storeF64($ea, $c);
- if (!$ok) {
- throw new TrapException("$instrOpName: out of bounds");
- }
- }
-
private static function defaultValueFromValType(ValType $type): int|float|Ref
{
return match ($type::class) {
diff --git a/traces/20240314-0011.stderr.log b/traces/20240314-0011.stderr.log
new file mode 100644
index 0000000..102a060
--- /dev/null
+++ b/traces/20240314-0011.stderr.log
@@ -0,0 +1,8 @@
+Decoding...
+Instantiating...
+Executing...
+
+Exit code: 0
+Memory peak usage: 195984632
+
+