virtual-machine 0.7.2 → 0.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,7 @@ A complete RISC-V 64-bit (RV64GC) virtual machine implementation in Rust, capabl
4
4
 
5
5
  ## Features
6
6
 
7
- - **Core**: Full RV64GC instruction set implementation (IMAFDC + Zicsr + Zifencei).
7
+ - **Core**: RV64GC instruction set implementation (IMAFDC + Zicsr + Zifencei). Integer, atomic and compressed instructions run in a superblock engine with a devirtualized memory fast path; F/D floating-point executes in the interpreter (NaN boxing, all rounding modes for conversions, fcsr flags). Misaligned scalar accesses to RAM are handled in hardware style (no trap).
8
8
  - **Memory**: Sv39 Virtual Memory Management Unit (MMU) with TLB.
9
9
  - **Peripherals**:
10
10
  - **UART**: 16550-compatible serial console.
@@ -217,17 +217,17 @@ if (!("encodeInto" in cachedTextEncoder)) {
217
217
  };
218
218
  }
219
219
  var WASM_VECTOR_LEN = 0;
220
- function wasm_bindgen__convert__closures_____invoke__h4e3f98878f091896(arg0, arg1) {
221
- wasm.wasm_bindgen__convert__closures_____invoke__h4e3f98878f091896(arg0, arg1);
220
+ function wasm_bindgen__convert__closures_____invoke__h10fd13f77519f00f(arg0, arg1, arg2) {
221
+ wasm.wasm_bindgen__convert__closures_____invoke__h10fd13f77519f00f(arg0, arg1, arg2);
222
222
  }
223
- function wasm_bindgen__convert__closures_____invoke__h260170fb96639bcf(arg0, arg1, arg2) {
224
- wasm.wasm_bindgen__convert__closures_____invoke__h260170fb96639bcf(arg0, arg1, arg2);
223
+ function wasm_bindgen__convert__closures_____invoke__hdc1b3e8ae3d0b1f6(arg0, arg1) {
224
+ wasm.wasm_bindgen__convert__closures_____invoke__hdc1b3e8ae3d0b1f6(arg0, arg1);
225
225
  }
226
- function wasm_bindgen__convert__closures_____invoke__h658bde57dcf0e58b(arg0, arg1) {
227
- wasm.wasm_bindgen__convert__closures_____invoke__h658bde57dcf0e58b(arg0, arg1);
226
+ function wasm_bindgen__convert__closures_____invoke__h00ee2f3d4900533a(arg0, arg1) {
227
+ wasm.wasm_bindgen__convert__closures_____invoke__h00ee2f3d4900533a(arg0, arg1);
228
228
  }
229
- function wasm_bindgen__convert__closures_____invoke__h5006ec25729b138d(arg0, arg1, arg2) {
230
- wasm.wasm_bindgen__convert__closures_____invoke__h5006ec25729b138d(arg0, arg1, arg2);
229
+ function wasm_bindgen__convert__closures_____invoke__he310f2359e2413f2(arg0, arg1, arg2) {
230
+ wasm.wasm_bindgen__convert__closures_____invoke__he310f2359e2413f2(arg0, arg1, arg2);
231
231
  }
232
232
  var __wbindgen_enum_WorkerType = ["classic", "module"];
233
233
  var WasmVmFinalization = typeof FinalizationRegistry === "undefined" ? { register: () => {
@@ -647,6 +647,16 @@ var WasmVm = class _WasmVm {
647
647
  const ret = wasm.wasmvm_get_gpu_dirty_rect(this.__wbg_ptr);
648
648
  return ret;
649
649
  }
650
+ /**
651
+ * Reset hart 0 to bare machine mode at the entry point.
652
+ *
653
+ * Benchmark workloads (see `bench_workload`) are M-mode programs; this
654
+ * undoes the S-mode boot setup that `new_with_harts` applies so they
655
+ * run exactly like under the native bench runner.
656
+ */
657
+ reset_machine_mode() {
658
+ wasm.wasmvm_reset_machine_mode(this.__wbg_ptr);
659
+ }
650
660
  /**
651
661
  * Check if cancellation has been requested.
652
662
  * @returns {boolean}
@@ -684,10 +694,14 @@ var WasmVm = class _WasmVm {
684
694
  * Get a direct zero-copy view into the framebuffer in SharedArrayBuffer.
685
695
  *
686
696
  * This eliminates all memory copies by creating a Uint8Array view directly
687
- * into the SharedArrayBuffer at the framebuffer offset. The browser can
688
- * pass this directly to WebGPU's writeTexture for zero-copy rendering.
697
+ * into guest memory at the framebuffer offset. The browser can pass this
698
+ * directly to WebGPU's writeTexture for zero-copy rendering.
689
699
  *
690
- * Returns None if SharedArrayBuffer is not available (single-threaded mode).
700
+ * Works in both memory modes:
701
+ * - SMP (SharedArrayBuffer): stable view into the SAB.
702
+ * - Single-hart (linear memory): view into WASM linear memory. This view
703
+ * is invalidated whenever WASM memory grows, so consume it immediately
704
+ * and call this again each frame (do not cache it JS-side).
691
705
  * @returns {Uint8Array | undefined}
692
706
  */
693
707
  get_framebuffer_view() {
@@ -860,10 +874,13 @@ var WasmVm = class _WasmVm {
860
874
  return ret !== 0;
861
875
  }
862
876
  /**
863
- * Execute up to N instructions in a batch.
864
- * Returns the number of instructions actually executed.
865
- * This is more efficient than calling step() N times due to reduced
866
- * JS-WASM boundary crossings.
877
+ * Execute up to N instructions by looping `step()`.
878
+ *
879
+ * DEPRECATED for hot paths: prefer `run_batch`, which hoists device
880
+ * polling and CLINT sync out of the instruction loop and returns early
881
+ * on WFI. `step_n` keeps the historical contract that a return value
882
+ * less than `count` means the VM halted (it never stops early on WFI),
883
+ * which existing consumers rely on for halt detection.
867
884
  * @param {number} count
868
885
  * @returns {number}
869
886
  */
@@ -871,6 +888,17 @@ var WasmVm = class _WasmVm {
871
888
  const ret = wasm.wasmvm_step_n(this.__wbg_ptr, count);
872
889
  return ret >>> 0;
873
890
  }
891
+ /**
892
+ * Total retired guest instructions on hart 0.
893
+ *
894
+ * Unlike step counts, this reflects real instructions (superblock
895
+ * execution retires many instructions per step). Use for MIPS metrics.
896
+ * @returns {number}
897
+ */
898
+ instret() {
899
+ const ret = wasm.wasmvm_instret(this.__wbg_ptr);
900
+ return ret;
901
+ }
874
902
  /**
875
903
  * Get the entry PC address for workers.
876
904
  * This is the address where secondary harts should start executing.
@@ -940,6 +968,25 @@ var WasmVm = class _WasmVm {
940
968
  const ret = wasm.wasmvm_num_harts(this.__wbg_ptr);
941
969
  return ret >>> 0;
942
970
  }
971
+ /**
972
+ * Execute up to N instructions in a batch with device polling, CLINT
973
+ * sync, and RTC updates hoisted to chunk boundaries.
974
+ *
975
+ * This is the fast path for hart 0: the inner loop is a tight
976
+ * `cpu.step()` with no per-instruction bookkeeping. Interrupt latency
977
+ * is bounded by IRQ_SYNC_INTERVAL (shared-CLINT sync) and the CPU's own
978
+ * internal 256-instruction interrupt poll.
979
+ *
980
+ * Returns the number of dispatcher steps executed (superblocks count as
981
+ * one step; use `instret()` for true instruction counts). Returns early
982
+ * on halt or WFI so the JS caller can pace execution.
983
+ * @param {number} max_steps
984
+ * @returns {number}
985
+ */
986
+ run_batch(max_steps) {
987
+ const ret = wasm.wasmvm_run_batch(this.__wbg_ptr, max_steps);
988
+ return ret >>> 0;
989
+ }
943
990
  };
944
991
  if (Symbol.dispose) WasmVm.prototype[Symbol.dispose] = WasmVm.prototype.free;
945
992
  var WorkerState = class {
@@ -1055,6 +1102,17 @@ var WorkerStepResult = Object.freeze({
1055
1102
  Wfi: 4,
1056
1103
  "4": "Wfi"
1057
1104
  });
1105
+ function bench_workload(name) {
1106
+ const ptr0 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1107
+ const len0 = WASM_VECTOR_LEN;
1108
+ const ret = wasm.bench_workload(ptr0, len0);
1109
+ if (ret[3]) {
1110
+ throw takeFromExternrefTable0(ret[2]);
1111
+ }
1112
+ var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
1113
+ wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
1114
+ return v2;
1115
+ }
1058
1116
  function worker_check_interrupts(hart_id, shared_mem) {
1059
1117
  const ret = wasm.worker_check_interrupts(hart_id, shared_mem);
1060
1118
  return BigInt.asUintN(64, ret);
@@ -1358,10 +1416,6 @@ function __wbg_get_imports() {
1358
1416
  return ret;
1359
1417
  }, arguments);
1360
1418
  };
1361
- imports.wbg.__wbg_new_with_shared_array_buffer_f801846979192910 = function(arg0, arg1, arg2) {
1362
- const ret = new DataView(arg0, arg1 >>> 0, arg2 >>> 0);
1363
- return ret;
1364
- };
1365
1419
  imports.wbg.__wbg_notify_65c8811cd7c0cdea = function() {
1366
1420
  return handleError(function(arg0, arg1, arg2) {
1367
1421
  const ret = Atomics.notify(arg0, arg1 >>> 0, arg2 >>> 0);
@@ -1530,24 +1584,28 @@ function __wbg_get_imports() {
1530
1584
  const ret = getStringFromWasm0(arg0, arg1);
1531
1585
  return ret;
1532
1586
  };
1533
- imports.wbg.__wbindgen_cast_808b97cce14173bb = function(arg0, arg1) {
1534
- const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h16ea2e7332e3f0d8, wasm_bindgen__convert__closures_____invoke__h658bde57dcf0e58b);
1587
+ imports.wbg.__wbindgen_cast_37ec172324e9c759 = function(arg0, arg1) {
1588
+ const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h166ac8bd1a99e49c, wasm_bindgen__convert__closures_____invoke__h00ee2f3d4900533a);
1535
1589
  return ret;
1536
1590
  };
1537
- imports.wbg.__wbindgen_cast_97885f52609c7a81 = function(arg0, arg1) {
1538
- const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h16ea2e7332e3f0d8, wasm_bindgen__convert__closures_____invoke__h5006ec25729b138d);
1591
+ imports.wbg.__wbindgen_cast_5d29676ef6c3e85f = function(arg0, arg1) {
1592
+ const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h166ac8bd1a99e49c, wasm_bindgen__convert__closures_____invoke__he310f2359e2413f2);
1539
1593
  return ret;
1540
1594
  };
1541
- imports.wbg.__wbindgen_cast_9d58885f229d7092 = function(arg0, arg1) {
1542
- const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h612f8e24953b61d5, wasm_bindgen__convert__closures_____invoke__h260170fb96639bcf);
1595
+ imports.wbg.__wbindgen_cast_5f9a13552260be22 = function(arg0, arg1) {
1596
+ const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h98fb6f0c0578da12, wasm_bindgen__convert__closures_____invoke__h10fd13f77519f00f);
1543
1597
  return ret;
1544
1598
  };
1545
- imports.wbg.__wbindgen_cast_d6cd19b81560fd6e = function(arg0) {
1546
- const ret = arg0;
1599
+ imports.wbg.__wbindgen_cast_c6620a1285ea2988 = function(arg0, arg1) {
1600
+ const ret = makeClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h166ac8bd1a99e49c, wasm_bindgen__convert__closures_____invoke__hdc1b3e8ae3d0b1f6);
1601
+ return ret;
1602
+ };
1603
+ imports.wbg.__wbindgen_cast_cb9088102bce6b30 = function(arg0, arg1) {
1604
+ const ret = getArrayU8FromWasm0(arg0, arg1);
1547
1605
  return ret;
1548
1606
  };
1549
- imports.wbg.__wbindgen_cast_e7df37cfbf20cf37 = function(arg0, arg1) {
1550
- const ret = makeClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h16ea2e7332e3f0d8, wasm_bindgen__convert__closures_____invoke__h4e3f98878f091896);
1607
+ imports.wbg.__wbindgen_cast_d6cd19b81560fd6e = function(arg0) {
1608
+ const ret = arg0;
1551
1609
  return ret;
1552
1610
  };
1553
1611
  imports.wbg.__wbindgen_init_externref_table = function() {
@@ -1609,6 +1667,7 @@ export {
1609
1667
  WasmVm,
1610
1668
  WorkerState,
1611
1669
  WorkerStepResult,
1670
+ bench_workload,
1612
1671
  worker_check_interrupts,
1613
1672
  worker_entry,
1614
1673
  initSync,