pub enum MicroOp {
Show 61 variants
LoadConst {
dst: Slot,
value: i64,
},
Move {
dst: Slot,
src: Slot,
},
Add {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
Sub {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
Mul {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
Lt {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
Gt {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
Eq {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
Div {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
DivPow2 {
dst: Slot,
lhs: Slot,
k: u32,
},
MagicDivU {
dst: Slot,
lhs: Slot,
magic: u64,
more: u8,
mul_back: i64,
},
Mod {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
LtEq {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
GtEq {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
Neq {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
Branch {
cmp: Cmp,
lhs: Slot,
rhs: Slot,
target: usize,
},
BitAnd {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
BitOr {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
BitXor {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
Shl {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
Shr {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
NotInt {
dst: Slot,
src: Slot,
},
NotBool {
dst: Slot,
src: Slot,
},
AddF {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
SubF {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
MulF {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
DivF {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
LtF {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
GtF {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
LtEqF {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
GtEqF {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
EqF {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
NeqF {
dst: Slot,
lhs: Slot,
rhs: Slot,
},
BranchF {
cmp: Cmp,
lhs: Slot,
rhs: Slot,
target: usize,
},
IntToFloat {
dst: Slot,
src: Slot,
},
SqrtF {
dst: Slot,
src: Slot,
},
MapGet {
dst: Slot,
key: Slot,
map_slot: Slot,
helper_addr: i64,
},
MapSet {
src: Slot,
key: Slot,
map_slot: Slot,
helper_addr: i64,
},
CallSelf {
dst: Slot,
args_start: Slot,
depth_addr: i64,
status_addr: i64,
limit_slot: Slot,
frame_size: i64,
},
CallSelfCopy {
dst: Slot,
args_start: Slot,
src_start: Slot,
arg_count: u16,
depth_addr: i64,
status_addr: i64,
limit_slot: Slot,
frame_size: i64,
},
NewList {
vec_slot: Slot,
ptr_slot: Slot,
len_slot: Slot,
helper_addr: i64,
},
ListTriple {
handle_slot: Slot,
vec_slot: Slot,
ptr_slot: Slot,
len_slot: Slot,
helper_addr: i64,
},
MapHas {
dst: Slot,
key: Slot,
map_slot: Slot,
helper_addr: i64,
},
Call {
dst: Slot,
args_start: Slot,
table_addr: i64,
depth_addr: i64,
status_addr: i64,
limit_slot: Slot,
depth_limit: i64,
},
ArrPush {
src: Slot,
vec_slot: Slot,
ptr_slot: Slot,
len_slot: Slot,
helper_addr: i64,
byte: bool,
narrow32: bool,
},
ListClear {
vec_slot: Slot,
ptr_slot: Slot,
len_slot: Slot,
helper_addr: i64,
},
StrAppend {
text_handle_slot: Slot,
src: StrSrc,
helper_addr: i64,
},
MemMem {
h_ptr_slot: Slot,
h_len_slot: Slot,
n_ptr_slot: Slot,
n_len_slot: Slot,
needle_len_slot: Slot,
i_slot: Slot,
count_slot: Slot,
helper_addr: i64,
},
ArrLoad {
dst: Slot,
idx: Slot,
ptr_slot: Slot,
len_slot: Slot,
byte: bool,
narrow32: bool,
checked: bool,
},
ArrLoadAffine {
dst: Slot,
a: Slot,
op: AffOp,
b: Slot,
const_offset: i64,
ptr_slot: Slot,
len_slot: Slot,
checked: bool,
},
ArrLoad2F {
dst: Slot,
i: Slot,
j: Slot,
ptr_slot: Slot,
len_slot: Slot,
op: FOp,
},
ArrLoad2 {
dst: Slot,
i: Slot,
j: Slot,
ptr_a: Slot,
len_a: Slot,
ptr_b: Slot,
len_b: Slot,
op: IOp,
checked: bool,
},
ArrStore {
src: Slot,
idx: Slot,
ptr_slot: Slot,
len_slot: Slot,
byte: bool,
narrow32: bool,
checked: bool,
},
ArrRMW {
idx: Slot,
operand: Slot,
ptr_slot: Slot,
len_slot: Slot,
op: RmwOp,
checked: bool,
},
ArrCondSwap {
idx1: Slot,
idx2: Slot,
ptr_slot: Slot,
len_slot: Slot,
cmp: Cmp,
checked: bool,
},
ArrSwap {
idx1: Slot,
idx2: Slot,
ptr_slot: Slot,
len_slot: Slot,
checked: bool,
},
FmaF {
dst: Slot,
a: Slot,
b: Slot,
c: Slot,
},
Jump {
target: usize,
},
JumpIfFalse {
cond: Slot,
target: usize,
},
JumpIfTrue {
cond: Slot,
target: usize,
},
Return {
src: Slot,
},
}Expand description
The integer straight-line subset the J1 compiler accepts.
Variants§
LoadConst
frame[dst] = value.
Move
frame[dst] = frame[src].
Add
frame[dst] = frame[lhs] + frame[rhs] (wrapping).
Sub
frame[dst] = frame[lhs] - frame[rhs] (wrapping).
Mul
frame[dst] = frame[lhs] * frame[rhs] (wrapping).
Lt
frame[dst] = (frame[lhs] < frame[rhs]) as i64.
Gt
frame[dst] = (frame[lhs] > frame[rhs]) as i64.
Eq
frame[dst] = (frame[lhs] == frame[rhs]) as i64.
Div
frame[dst] = frame[lhs] / frame[rhs] (wrapping; MIN / -1 = MIN).
A zero divisor SIDE-EXITS the chain (ChainOutcome::Deopt) before
any effect — the caller replays on bytecode, where the kernel raises
the exact “Division by zero” error.
DivPow2
frame[dst] = frame[lhs] / 2^k (signed, round toward zero) via a
sign-correcting shift — bit-exact with MicroOp::Div but with NO
side-exit (a power-of-two divisor is never 0 or -1). Emitted in
place of Div when the divisor is a region-constant power of two and
the dividend is integer-typed.
Fields
MagicDivU
frame[dst] = frame[lhs] / c (mul_back == 0) or frame[lhs] % c
(mul_back == c) by the Granlund–Montgomery / libdivide UNSIGNED
magic-reciprocal sequence (mulhi(magic, x) + add-fixup + shift, then
x - q*c for the remainder) — a mul+shr (~3 cycles) instead of
idiv (~25). NO side-exit (a literal c > 0 is never 0 or -1).
Emitted in place of Div/Mod when the divisor is a compile-time
constant non-power-of-two and the dividend is proven Int and NON-NEGATIVE
(the unsigned magic equals the signed truncating result only there). The
more byte is the logicaffeine_data::LogosDivU64 encoding (low 6 bits
= shift, 0x40 = the 65-bit add-marker path, 0x80 = pure-shift pow2).
Fields
Mod
frame[dst] = frame[lhs] % frame[rhs] (wrapping; MIN % -1 = 0).
Zero divisor side-exits exactly like MicroOp::Div.
LtEq
frame[dst] = (frame[lhs] <= frame[rhs]) as i64.
GtEq
frame[dst] = (frame[lhs] >= frame[rhs]) as i64.
Neq
frame[dst] = (frame[lhs] != frame[rhs]) as i64.
Branch
Fused compare-and-branch: transfer to target when cmp(lhs, rhs) is
FALSE (the JumpIfFalse-on-a-fresh-comparison shape); fall through
when TRUE. No comparison value is materialized — the adapter proves
the scratch dead before fusing.
Fields
BitAnd
frame[dst] = frame[lhs] & frame[rhs] (bitwise; logical for 0/1 Bools).
BitOr
frame[dst] = frame[lhs] | frame[rhs] (bitwise; logical for 0/1 Bools).
BitXor
frame[dst] = frame[lhs] ^ frame[rhs].
Shl
frame[dst] = frame[lhs].wrapping_shl(frame[rhs] as u32) — the
kernel’s locked shift spec (count truncates to u32, masks mod 64).
Shr
frame[dst] = frame[lhs].wrapping_shr(frame[rhs] as u32) (arithmetic).
NotInt
frame[dst] = !frame[src] — bitwise NOT (the kernel’s Int not).
NotBool
frame[dst] = frame[src] ^ 1 — logical NOT over 0/1 Bools.
AddF
Float ops: f64 values as raw bits in the i64 slots. Arithmetic is IEEE; equality is the kernel’s EPSILON rule.
SubF
bits(f(lhs) - f(rhs)).
MulF
bits(f(lhs) * f(rhs)).
DivF
bits(f(lhs) / f(rhs)); divisor == 0.0 side-exits like MicroOp::Div.
LtF
(f(lhs) < f(rhs)) as i64 (IEEE, NaN → 0).
GtF
(f(lhs) > f(rhs)) as i64.
LtEqF
(f(lhs) <= f(rhs)) as i64.
GtEqF
(f(lhs) >= f(rhs)) as i64.
EqF
The kernel’s epsilon equality as a value.
NeqF
Negated epsilon equality as a value.
BranchF
Fused FLOAT compare-and-branch: transfer to target when
cmp(f(lhs), f(rhs)) is FALSE — which, under IEEE, includes every
NaN-unordered comparison (matching the kernel’s relations exactly).
Fields
IntToFloat
frame[dst] = bits(frame[src] as f64) — the kernel’s Int→Float
promotion.
SqrtF
frame[dst] = bits(sqrt(f(frame[src]))) — the kernel’s Float sqrt
builtin (IEEE: negative → NaN, no error path).
MapGet
Map get through the pinned storage: an Int hit lands in dst; a
miss or non-Int value side-exits (the replay raises the kernel’s
exact error or re-runs the boxed path).
Fields
MapSet
Map insert (always succeeds; same storage, same iteration order).
Fields
CallSelf
DIRECT self-call (mode A): entry patched post-layout into the literal pool; static frame-size bound; plain replay deopt.
Fields
CallSelfCopy
DIRECT self-call with a FUSED argument copy (Lever A: the pinned-arg
self-call ABI). Same model as MicroOp::CallSelf, but it stages the
arg_count contiguous scalar arguments from src_start.. into the
callee window itself rather than relying on arg_count separate
Move pieces before the call — one piece replaces arg_count + 1.
Emitted only for all-scalar (Int/Bool/Float) self-calls; list-param
and pin-triple staging stay on the per-Move path.
Fields
NewList
Allocate a registry-owned fresh list and plant its pin triple.
Fields
ListTriple
Plant a pin triple from a list handle already in handle_slot
(a self-call’s returned list, seen from the caller).
Fields
MapHas
Map membership into dst (0/1).
Fields
Call
Native SELF-CALL through the program’s entry table (callee frame
windowed at base + args_start like the VM). Missing entry, a
MAX_CALL_DEPTH crossing, or arena overflow side-exits the WHOLE
native stack via the shared status cell.
Fields
ArrPush
Pinned-array push. The contiguous regalloc backend lowers this to an
INLINE fast path — len < cap ? buffer[len++] = v straight in registers,
reading the capacity from the live *mut Vec (a codegen-probed field
offset, never a hardcoded layout) — and calls the runtime helper ONLY on
the cold realloc boundary (len == cap), where it reallocates and
refreshes the pinned pointer/length slots. The per-piece stencil tier
always calls the helper.
Fields
ListClear
Pinned-array in-place clear through a runtime helper: truncate the buffer
to empty (keep capacity) and refresh the pinned pointer/length slots
(length → 0). Lowers an in-region NewEmptyList on a pinned array; an
in-place mutation, so a PRECISE region resumes over it soundly.
Fields
StrAppend
Pinned MUTABLE-Text append (Set text to text + <s>) through a runtime
helper. text_handle_slot holds a *mut Value to the VM register cell
holding the accumulator (planted at region entry); the helper grows the
accumulator THROUGH that cell with EXACTLY the VM’s add_assign
semantics — in place when the Rc<String> is sole-owned, copy-on-write
(a fresh Rc written back into the cell, the alias untouched) otherwise.
src is the appended operand (a 1-char frame byte, or a baked constant
slice). Bit-identical to the tree-walker for every alias case. The buffer
reaches into the VM register file, so — like the other helper calls — it
clobbers the caller-saved registers (the residents are spilled/reloaded).
Fields
MemMem
COUNT OVERLAPPING SUBSTRING MATCHES through a runtime helper — the whole
naive-search nest (string_search) collapsed to one piece. The helper
reads the pinned haystack/needle byte buffers, counts overlapping needle
occurrences over the outer range [frame[i_slot], textLen - needleLen + 1]
(1-based, matching the nest), ADDS the count into frame[count_slot], and
advances frame[i_slot] to the loop’s exit value. On a recoverable
disagreement (a checked needle index past the needle buffer) it touches
nothing and takes the deopt continuation, so the VM replays the exact
nest on bytecode and raises the same error. Holes: 0 = haystack ptr slot,
1 = haystack len slot, 2 = needle ptr slot, 3 = needle len slot, 4 =
needleLen value slot, 5 = i (start) slot, 6 = count accumulator slot,
7 = helper address.
Fields
ArrLoad
Pinned-array load: frame[dst] = buffer[frame[idx] - 1] (1-based;
bits regardless of element kind). Out-of-bounds (incl. 0/negative)
SIDE-EXITS before any effect.
Fields
ArrLoadAffine
FUSED affine-index load: frame[dst] = buffer[idx - 1] where the 1-based
idx = (frame[a] OP frame[b]).wrapping_add(const_offset) (or
frame[a] + const_offset for AffOp::None) is computed INSIDE the
stencil — the peephole collapses the index-arithmetic chain
(<binop>(t = a OP b); [Add(t2 = t + Kc);] ArrLoad(t2), or
Add(t = a + Kc); ArrLoad(t)) plus the load into ONE piece when the
intermediate index temps are single-use scratch. The dominant indexed
inner loops (matrix_mult i*n+k+1, knapsack w - wi + 1, the w + 1
row read) lose worst to V8 precisely on this per-op dispatch; folding the
2-3 index ops into the load is a direct dispatch-reduction win. Out of
bounds (incl. the 0/negative index the wrapping-sub trick catches)
SIDE-EXITS before any effect, exactly like MicroOp::ArrLoad.
Fields
b: SlotSecond index operand slot (ignored for AffOp::None).
ArrLoad2F
FUSED two-load float binop: frame[dst] = bits(f(buf[i-1]) <op> f(buf[j-1])), BOTH elements from the SAME pinned 8-byte buffer (one
pointer slot, one length slot). The peephole collapses ArrLoad(t1 = arr[i]); ArrLoad(t2 = arr[j]); {Add,Sub,Mul}F(dst = t1 OP t2) when both
loads hit the same array and the two scratch loads are single-use — so
the two f64s never round-trip through the frame. EITHER index out of
bounds SIDE-EXITS before any effect, exactly like MicroOp::ArrLoad.
Fields
ArrLoad2
FUSED two-load INTEGER binop: frame[dst] = a[i-1] <op> b[j-1], the two
8-byte elements loaded from TWO (possibly distinct) pinned int buffers
(each with its own pointer + length slot). The peephole collapses
ArrLoad(t1 = a[i]); ArrLoad(t2 = b[j]); {Add,Sub,Mul}(dst = t1 OP t2)
— the matrix-multiply / dot-product idiom c += a[..] * b[..] — when the
two scratch loads are single-use, so the loaded i64s never round-trip the
frame and three dispatches collapse to one. EITHER index out of bounds
SIDE-EXITS before any effect, exactly like MicroOp::ArrLoad. The two
buffers may be the SAME (one self-referential dot product) or distinct.
Fields
ArrStore
Pinned-array store: buffer[frame[idx] - 1] = frame[src]; bounds
side-exit BEFORE the store.
Fields
ArrRMW
FUSED read-modify-write on a pinned 8-byte int array:
buffer[frame[idx] - 1] = buffer[frame[idx] - 1] <op> frame[operand]
in ONE stencil. The peephole collapses ArrLoad(t = arr[idx]); <int ALU>(t2 = t OP operand); ArrStore(arr[idx] = t2) when both array
ops hit the SAME pinned buffer + index and the two scratch values
(t, t2) are single-use — so the element never round-trips the frame
and ONE bounds check covers the load+store. Out-of-bounds (incl.
0/negative) SIDE-EXITS before any effect, exactly like MicroOp::ArrStore.
Fields
ArrCondSwap
FUSED conditional adjacent swap on a pinned 8-byte int array:
let a = buf[idx1-1]; let b = buf[idx2-1]; if cmp(a, b) { buf[idx1-1] = b; buf[idx2-1] = a } in ONE stencil. The peephole collapses the sort
inner-loop idiom ArrLoad(a,i1); ArrLoad(b,i2); Branch(cmp,a,b,skip); ArrStore(i1,b); ArrStore(i2,a) (bubble/insertion/quick sort) — 5 ops → 1,
the two loaded values never round-trip the frame, the compare-branch is
gone. The swap is ATOMIC (both writes or neither); a checked variant
bounds-checks BOTH indices up front and SIDE-EXITS before any effect, the
unchecked variant (Oracle-proven indices) has no side-exit.
Fields
ArrSwap
FUSED unconditional adjacent swap on a pinned 8-byte int array:
let a = buf[idx1-1]; let b = buf[idx2-1]; buf[idx1-1] = b; buf[idx2-1] = a in ONE stencil. The peephole collapses the Let tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp exchange (quicksort/heap_sort/mergesort partition &
sift) — ArrLoad(a,i); ArrLoad(b,j); ArrStore(i,b); ArrStore(j,a) — 4 ops
→ 1. The swap is ATOMIC; a checked variant bounds-checks BOTH indices up
front and SIDE-EXITS before any effect.
Fields
FmaF
FUSED float multiply-add: frame[dst] = bits((f(a) * f(b)) + f(c)) — the
peephole collapses MulF(t = a*b); AddF(d = t + c) (the product t
single-use) into one stencil, cutting a dispatch on the float arithmetic
chains that dominate the float cluster (nbody’s dz*dz + s, dot
products). The product and the add round SEPARATELY ((a*b)+c, two
roundings) — NOT a hardware single-rounding FMA — so it stays bit-identical
to the unfused MulF+AddF. Mem-form: every operand reads from the frame,
so it preserves the threaded XMM pins (the caller only fuses when the
operands are frame-resident, keeping it a spill-free win).
Fields
Jump
Unconditional transfer to the micro-op at target (an index into the
program; forward or backward).
JumpIfFalse
Transfer to target when frame[cond] is ZERO; fall through otherwise.
JumpIfTrue
Transfer to target when frame[cond] is NONZERO; fall through
otherwise (the same brz stencil with swapped continuations).
Return
Terminate the chain, returning frame[src].