From 4b7e894a397def9b14d8e3f589ec159dfb788ed8 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Thu, 14 Mar 2024 00:14:15 +0900 Subject: perf: specialize load/store instr --- benchmarks/20240314-0011.log | 4 + examples/php-on-wasm/php-wasm.php | 8 +- src/Execution/MemInst.php | 273 ++++++++++++++++++++++++++----- src/Execution/Runtime.php | 336 ++++++++++++++++++++++++++------------ traces/20240314-0011.stderr.log | 8 + 5 files changed, 482 insertions(+), 147 deletions(-) create mode 100644 benchmarks/20240314-0011.log create mode 100644 traces/20240314-0011.stderr.log 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 + + -- cgit v1.2.3-70-g09d2