Skip to content

Commit a4d945b

Browse files
committed
pd-vm: move JIT recorder to be SSA based
1 parent f125148 commit a4d945b

23 files changed

Lines changed: 5931 additions & 5379 deletions

pd-vm/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ use vm::{Store, VmStatus};
188188
// ... create vm ...
189189
let mut store = Store::from_vm(vm);
190190
store.set_fuel(10_000);
191-
store.set_fuel_check_interval(1)?; // exact mode: check every instruction/trace step
191+
store.set_fuel_check_interval(1)?; // exact mode: check every instruction/trace op
192192
let checkpoint = store.checkpoint();
193193

194194
loop {
@@ -215,7 +215,7 @@ Fuel charging semantics:
215215
Chunk size = `fuel_check_interval`.
216216
Default interval is `1` (exact mode).
217217
- The interpreter applies fuel checks in the VM loop before opcode fetch/execute.
218-
- Trace-JIT execution applies the same cadence before each `TraceStep`.
218+
- Trace-JIT execution applies the same cadence against recorded trace ops/blocks.
219219
- When fuel metering is enabled, native JIT execution injects fuel checks in generated machine
220220
code at the configured check cadence.
221221
- With interval `> 1`, out-of-fuel detection is coarse-grained: execution may run up to
@@ -456,8 +456,8 @@ The end-to-end stack is split into layers. Not every entrypoint uses every layer
456456
1. Type-consistency validation on legalized IR (for example rejecting known `if`/`else` branch mismatches)
457457
1. Lifetime/liveness lowering plus type metadata collection
458458
1. Bytecode backend (`Compiler` + `Assembler` -> `Program`) executed by VM
459-
1. Trace-JIT IR recording (`JitTrace` + `TraceStep`) using TraceStep IR
460-
1. Native machine code emission and execution
459+
1. Trace-JIT SSA recording (`JitTrace` + `SsaTrace`) with symbolic stack/local state
460+
1. Native machine code emission and execution from SSA traces
461461

462462
#### Type Metadata and Inference
463463

@@ -582,8 +582,8 @@ At runtime, `call` is bridged through `Vm::execute_host_call`:
582582

583583
- builtin call indices dispatch to `vm/builtin_runtime.rs`
584584
- non-builtin indices dispatch to bound host imports
585-
- trace-JIT records `TraceStep::Call`, and native traces bridge call steps through runtime helpers
586-
(with builtin fast paths where available), preserving interpreter semantics
585+
- trace-JIT records supported hot paths into SSA and falls back to the interpreter for call-heavy
586+
or otherwise unsupported traces, preserving interpreter semantics
587587

588588
#### Current Compiler Subset Limitations
589589

pd-vm/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ pub mod debugger;
99
#[cfg(feature = "runtime")]
1010
pub mod jit {
1111
pub use crate::vm::jit::{
12-
JitAttempt, JitConfig, JitNyiDoc, JitNyiReason, JitSnapshot, JitTrace, JitTraceTerminal,
13-
TraceBytesCodecKind, TraceConcatKind, TraceJitEngine, TraceStep, TraceTextBytesKind,
12+
JitAttempt, JitConfig, JitMetrics, JitNyiDoc, JitNyiReason, JitSnapshot, JitTrace,
13+
JitTraceTerminal, TraceJitEngine,
1414
};
1515
}
1616
#[cfg(feature = "runtime")]
@@ -53,8 +53,8 @@ pub use debugger::{
5353
};
5454
#[cfg(feature = "runtime")]
5555
pub use jit::{
56-
JitAttempt, JitConfig, JitNyiDoc, JitNyiReason, JitSnapshot, JitTrace, JitTraceTerminal,
57-
TraceJitEngine,
56+
JitAttempt, JitConfig, JitMetrics, JitNyiDoc, JitNyiReason, JitSnapshot, JitTrace,
57+
JitTraceTerminal, TraceJitEngine,
5858
};
5959
#[cfg(feature = "runtime")]
6060
pub use vm::diagnostics::render_vm_error;

pd-vm/src/vm/jit/deopt.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
use super::ir::{SsaExit, SsaMaterialization, SsaValue, SsaValueId, SsaValueRepr};
2+
3+
pub(crate) fn materialize_ssa_values(
4+
values: impl IntoIterator<Item = SsaValue>,
5+
) -> Vec<SsaMaterialization> {
6+
values.into_iter().map(materialize_ssa_value).collect()
7+
}
8+
9+
pub(crate) fn materialize_ssa_value(value: SsaValue) -> SsaMaterialization {
10+
match value.repr {
11+
SsaValueRepr::Tagged => SsaMaterialization::Value(value.id),
12+
SsaValueRepr::I64 => SsaMaterialization::BoxInt(value.id),
13+
SsaValueRepr::F64 => SsaMaterialization::BoxFloat(value.id),
14+
SsaValueRepr::Bool => SsaMaterialization::BoxBool(value.id),
15+
SsaValueRepr::HeapPtr(tag) => SsaMaterialization::BoxHeapPtr {
16+
value: value.id,
17+
tag,
18+
},
19+
}
20+
}
21+
22+
pub(crate) fn exit_inputs(exit: &SsaExit) -> Vec<SsaValueId> {
23+
let mut out = Vec::new();
24+
for materialization in exit.stack.iter().chain(exit.locals.iter()) {
25+
let value = match materialization {
26+
SsaMaterialization::Value(value)
27+
| SsaMaterialization::BoxInt(value)
28+
| SsaMaterialization::BoxFloat(value)
29+
| SsaMaterialization::BoxBool(value) => *value,
30+
SsaMaterialization::BoxHeapPtr { value, .. } => *value,
31+
};
32+
if !out.contains(&value) {
33+
out.push(value);
34+
}
35+
}
36+
out
37+
}

0 commit comments

Comments
 (0)