Documentation
¶
Overview ¶
Package vm implement a stack based virtual machine.
Index ¶
- Constants
- Variables
- func AttachPtrDerived(t *mtype.Type, newPtrRT reflect.Type)
- func CanonicalType(t *mtype.Type) *mtype.Type
- func DumpFrame(w io.Writer, mem []Value, code Code, fp, sp, narg, nret int, di *DebugInfo)
- func DumpFrameStderr(mem []Value, code Code, fp, sp, narg, nret int, di *DebugInfo)
- func Exportable(rv reflect.Value) reflect.Value
- func MaterializeRtype(t *mtype.Type) reflect.Type
- func NewRuntimeFuncSentinel() *runtime.Func
- func PointerTo(t *mtype.Type) *mtype.Type
- func RegisterNativeMethodHook(recvInstance any, methodName string, hook NativeMethodHook)
- func RegisterRuntimeFunc(rf *runtime.Func, name, file string, line int)
- func RegisterSynthIfaceTargetFunc(fn reflect.Value)
- func SymArray(n int, t *mtype.Type) *mtype.Type
- func SymChan(dir reflect.ChanDir, t *mtype.Type) *mtype.Type
- func SymMap(k, e *mtype.Type) *mtype.Type
- func SymPtr(t *mtype.Type) *mtype.Type
- func SymSlice(t *mtype.Type) *mtype.Type
- func Vstring(lv []Value) string
- type CleanExit
- type Closure
- type Code
- type DebugInfo
- type EmbeddedField
- type FuncRange
- type Iface
- type IfaceMethod
- type Instruction
- type LocalVar
- type Machine
- func (m *Machine) AttachSynthMethods(t *Type) error
- func (m *Machine) CallFunc(fval Value, funcType reflect.Type, args []reflect.Value) ([]reflect.Value, error)
- func (m *Machine) CallSitePos() Pos
- func (m *Machine) DebugInfo() *DebugInfo
- func (m *Machine) DumpCallStack(w io.Writer, di *DebugInfo)
- func (m *Machine) DumpCallStackStderr(di *DebugInfo)
- func (m *Machine) EnableGoroutineFaults()
- func (m *Machine) GoroutineFault() error
- func (m *Machine) HeapSize() int
- func (m *Machine) MakeMethodCallable(ifc Iface, method Method) Value
- func (m *Machine) MethodByName(t *Type, name string) (Method, bool)
- func (m *Machine) Out() io.Writer
- func (m *Machine) PendingGoroutineFault() error
- func (m *Machine) PopExit()
- func (m *Machine) Push(v ...Value) (l int)
- func (m *Machine) PushCode(code ...Instruction) (p int)
- func (m *Machine) Run() (err error)
- func (m *Machine) SetDebugIO(in io.Reader, out io.Writer)
- func (m *Machine) SetDebugInfo(fn func() *DebugInfo)
- func (m *Machine) SetGoroutineFaultContinue(v bool)
- func (m *Machine) SetIO(in io.Reader, out, err io.Writer)
- func (m *Machine) SetIP(ip int)
- func (m *Machine) SetTraceOps(on bool)
- func (m *Machine) SetTracing(on bool)
- func (m *Machine) StackLen() int
- func (m *Machine) Top() (v Value)
- func (m *Machine) TraceOps() bool
- func (m *Machine) Tracing() bool
- func (m *Machine) TrimStack()
- func (m *Machine) WalkCallStack(yield func(StackFrame) bool)
- type Method
- type MvmFunc
- type NativeMethodHook
- type Op
- type Opaque
- type PanicError
- type Pos
- type RuntimeFuncInfo
- type SelectCaseInfo
- type SelectMeta
- type StackFrame
- type Type
- type TypeElem
- type Value
- func (v Value) Addr() reflect.Value
- func (v Value) Bool() bool
- func (v Value) CanAddr() bool
- func (v Value) CanInt() bool
- func (v Value) CopyArray() Value
- func (v Value) Elem() reflect.Value
- func (v Value) Equal(u Value) bool
- func (v Value) Field(i int) reflect.Value
- func (v Value) FieldByIndex(index []int) reflect.Value
- func (v Value) Float() float64
- func (v Value) IfaceVal() Iface
- func (v Value) Index(i int) reflect.Value
- func (v Value) Int() int64
- func (v Value) Interface() any
- func (v Value) IsIface() bool
- func (v Value) IsValid() bool
- func (v Value) Kind() reflect.Kind
- func (v Value) Len() int
- func (v Value) MapIndex(key reflect.Value) reflect.Value
- func (v Value) Reflect() reflect.Value
- func (v Value) Seq() iter.Seq[reflect.Value]
- func (v Value) Seq2() iter.Seq2[reflect.Value, reflect.Value]
- func (v Value) Set(x reflect.Value)
- func (v Value) SetMapIndex(key, elem reflect.Value)
- func (v Value) Slice(i, j int) reflect.Value
- func (v Value) Slice3(i, j, k int) reflect.Value
- func (v Value) Type() reflect.Type
- func (v Value) Uint() uint64
- func (v Value) UnwrapType() (reflect.Type, bool)
Constants ¶
const ( Global = 0 Local = 1 )
Memory attributes.
const CallSpreadFlag int32 = 1 << 15
CallSpreadFlag is set in the B operand of Call to indicate a spread call (f(s...)), so the VM uses reflect.CallSlice instead of reflect.Call for native variadic functions.
const DeferSpreadFlag = 4
DeferSpreadFlag marks that the call's final argument is a variadic slice, so native defers use reflect.CallSlice. Set in the DeferPush B operand alongside isX. Defer header layout: isX bits 0-1, spread bit 2, narg bits 3-62, started 63.
const ValueSize = int(unsafe.Sizeof(Value{}))
ValueSize is the in-memory footprint of a Value on the current platform. Used by stat reporters to convert slot counts to bytes.
Variables ¶
var ( TypeOf = mtype.TypeOf FuncOf = mtype.FuncOf StructOf = mtype.StructOf NewStructType = mtype.NewStructType )
Symbolic type constructors re-exported from mtype. The derived-type constructors and reserve/fill helpers (SymPtr/SymSlice/..., PointerTo, CanonicalType, AttachPtrDerived, ...) are runtime materialization and live in vm (derive.go), not mtype.
Symbolic (Rtype-nil) leaf/aggregate constructors goparser uses post-flip; comp materializes the rtype later (see MaterializeRtype). The derived constructors (SymPtr/SymSlice/SymArray/SymChan/SymMap) live in derive.go: they memoize and register the derived *Type in the cache, leaving Rtype nil for comp to fill.
var AnyRtype = mtype.AnyRtype
AnyRtype is the empty-interface rtype, re-exported from mtype.
var ErrGoroutineFault = errors.New("vm: unrecovered goroutine panic")
ErrGoroutineFault aborts a Run that was waiting on a channel when a goroutine panicked elsewhere; recoverPanic returns it and the top-level Eval maps it to a non-zero exit.
var NumKindOffset [reflect.Float64 + 1]int
NumKindOffset maps a reflect.Kind to a 0-based offset into per-type opcode blocks. Returns -1 for non-numeric kinds.
var OpaqueRtype = reflect.TypeFor[Opaque]()
OpaqueRtype is the reflect.Type for Opaque.
Functions ¶
func AttachPtrDerived ¶ added in v0.4.0
AttachPtrDerived records newPtrRT (a *T-with-methods rtype) as t's derived pointer type, materializing the slot if absent so a later PointerTo(t) returns it instead of a fresh methodless *T. The reserve path wires the *T identity once at materialize, so an existing slot just adopts newPtrRT.
func CanonicalType ¶ added in v0.4.0
CanonicalType walks the Base chain to the source *Type a struct-field copy derived from (t itself if Base is nil); depth-capped against cyclic Base. Used by symbol resolution to match a clone against its defining identity.
func DumpFrame ¶
DumpFrame decodes and pretty-prints the call frame at the given fp. di is optional (may be nil); when set, slots are annotated with variable names.
func DumpFrameStderr ¶
DumpFrameStderr is a convenience wrapper that prints to stderr.
func Exportable ¶ added in v0.2.0
Exportable returns rv with its read-only flag cleared so that .Interface() and .Call() do not panic on values obtained from unexported struct fields.
func MaterializeRtype ¶ added in v0.4.0
MaterializeRtype builds and caches t.Rtype from t's symbolic graph (Kind + ElemType/KeyType/Fields/Params/Returns + ArrayLen/ChanDir/Variadic/Tags) when it is not already set, recursing into children first. This is the comp-side materialization that lets goparser build a *Type without an rtype.
A named leaf (a primitive or struct that carries methods) must already hold its rtype so an un-materialized leaf here yields nil.
func NewRuntimeFuncSentinel ¶ added in v0.2.0
NewRuntimeFuncSentinel returns a fresh *runtime.Func whose address is unique. Use it together with RegisterRuntimeFunc to mark a PC as virtualized.
func RegisterNativeMethodHook ¶ added in v0.3.0
func RegisterNativeMethodHook(recvInstance any, methodName string, hook NativeMethodHook)
RegisterNativeMethodHook installs hook for recvInstance's named method. recvInstance is a typed nil (e.g. (*testing.T)(nil)); the function keys on reflect.TypeOf(recvInstance).
func RegisterRuntimeFunc ¶ added in v0.2.0
RegisterRuntimeFunc associates Name/File/Line metadata with rf so that interpreted code calling rf.Name() / rf.FileLine() observes the recorded values instead of the host runtime's lookup. rf must be a non-nil pointer obtained from NewRuntimeFuncSentinel so the address is distinct from any other registered sentinel.
func RegisterSynthIfaceTargetFunc ¶ added in v0.4.0
RegisterSynthIfaceTargetFunc allowlists fn for synth-interface target retyping. Call from package init.
func SymArray ¶ added in v0.4.0
SymArray returns the canonical [n]t, registered in t's derived cache, Rtype nil.
func SymChan ¶ added in v0.4.0
SymChan returns the canonical chan-t, registered in t's derived cache, Rtype nil.
func SymMap ¶ added in v0.4.0
SymMap returns the canonical map[k]e, registered in k's derived cache, Rtype nil.
func SymPtr ¶ added in v0.4.0
SymPtr returns the canonical *t, registered in t's derived cache, Rtype nil.
Types ¶
type CleanExit ¶ added in v0.3.0
type CleanExit interface {
CleanExit()
}
CleanExit marks an error value as an intentional, non-crash program termination signal. Such a value bypasses interpreted recover(), and propagates to the top-level Run.
type Closure ¶
type Closure struct {
Code int // code address (same as the plain-int function value)
Heap []*Value // heap-allocated cells, one per captured variable
}
Closure bundles a function code address with its captured variables.
type DebugInfo ¶
type DebugInfo struct {
Sources scan.Sources // source position registry (multi-file / REPL)
Labels map[int]string // code address -> label/function name
Funcs []FuncRange // function bytecode ranges, used by FuncAt to pick the innermost frame
Globals map[int]string // data index -> symbol name
Locals map[string][]LocalVar // function name -> local variable list
}
DebugInfo holds symbolic information for annotating debug output. Built by the compiler from the symbol table and source registry.
func NewDebugInfo ¶
func NewDebugInfo() *DebugInfo
NewDebugInfo returns an empty DebugInfo ready to be populated.
func (*DebugInfo) FuncAt ¶ added in v0.2.0
FuncAt returns the name of the innermost function whose bytecode range contains ip. Falls back to a "largest start <= ip" scan over Labels when Funcs is empty (e.g. snapshots produced before BuildDebugInfo started populating ranges). Returns "" when no function qualifies.
type EmbeddedField ¶
type EmbeddedField = mtype.EmbeddedField
EmbeddedField is re-exported from mtype.
type FuncRange ¶ added in v0.2.0
FuncRange describes the bytecode range of a function (or anonymous closure). End is one past the last instruction of the body (i.e. an exclusive bound). Closures are emitted inline within their outer function so ranges nest; FuncAt picks the innermost containing range.
type Iface ¶
type Iface struct {
Typ *Type // concrete mvm type (carries Name for method lookup)
Val Value // the concrete value
}
Iface represents a boxed interface value at runtime. It preserves the concrete mvm type identity for dynamic method dispatch.
type Instruction ¶
Instruction represents a virtual machine bytecode instruction (16 bytes). Fields A, B hold up to 2 immediate operands (0 when unused).
func (Instruction) String ¶
func (i Instruction) String() (s string)
type LocalVar ¶
type LocalVar struct {
Offset int // offset from fp (1-based, as in Get Local N)
Name string // variable name (short, without scope prefix)
}
LocalVar describes a local variable within a function frame.
type Machine ¶
type Machine struct {
MethodNames []string // names by global method ID
MethodFuncTypes []reflect.Type // bound-method func type (no receiver) by global method ID
// contains filtered or unexported fields
}
Machine is a stack-based virtual machine that executes bytecode instructions.
func ActiveMachine ¶ added in v0.2.0
func ActiveMachine() *Machine
ActiveMachine returns the Machine currently set via SetActiveMachine on the calling goroutine, or nil if none. Prefer reaching the Machine through an explicit parameter or closure capture; ActiveMachine is reserved for native bridge closures installed at package patch time with no other route to the runtime.
func SetActiveMachine ¶ added in v0.2.0
SetActiveMachine records m as the running Machine for the current goroutine and returns the previous value (nil if none). Pair with `defer SetActiveMachine(prev)` to restore on return. Passing m == nil (the restore step at goroutine top of stack) deletes the slot so the map doesn't accumulate stale entries from short-lived goroutines.
func (*Machine) AttachSynthMethods ¶ added in v0.4.0
AttachSynthMethods fills t's interpreted methods into the synth rtype that was reserved for t at materialize (via runtype + stdlib/stubs), in place -- t.Rtype and any composite that captured it keep their identity. Native code that asserts the rtype to an interface (fmt.Stringer, error, json.Marshaler, json.Unmarshaler, etc.) then dispatches the method directly, with no bridge proxy.
Handles any combination of the supported method shapes (see detectShape) on any supported kind, plus pointer-receiver variants on *T via attachPtrRecv. Up to synth's per-attach method cap (currently 16); excess methods of the same receiver kind are silently dropped.
func (*Machine) CallFunc ¶
func (m *Machine) CallFunc(fval Value, funcType reflect.Type, args []reflect.Value) ([]reflect.Value, error)
CallFunc executes a mvm function value with the given arguments and returns the results. It saves and restores per-frame execution state so it can be called from native Go callbacks (reflect.MakeFunc wrappers) even while Run is in progress (single-threaded re-entrancy). Globals are NOT isolated: a callback's package-var write is visible to the outer Run, matching Go callback semantics and the goroutine model documented in ADR-008.
func (*Machine) CallSitePos ¶ added in v0.3.0
CallSitePos returns the source Pos of the instruction that triggered the currently executing native call. Returns 0 when the IP is out of range.
func (*Machine) DebugInfo ¶ added in v0.2.0
DebugInfo returns the current DebugInfo, or nil if no builder was registered with SetDebugInfo.
func (*Machine) DumpCallStack ¶
DumpCallStack walks the frame pointer chain and prints every frame.
func (*Machine) DumpCallStackStderr ¶
DumpCallStackStderr is a convenience wrapper that prints to stderr.
func (*Machine) EnableGoroutineFaults ¶ added in v0.4.0
func (m *Machine) EnableGoroutineFaults()
EnableGoroutineFaults arms goroutine-panic capture on the root machine before it runs, so runner machines and goroutine children share the sink. Idempotent.
func (*Machine) GoroutineFault ¶ added in v0.4.0
GoroutineFault reports the first recorded goroutine panic regardless of policy. Under the continue policy the suite still runs to the end; the driver calls this afterward to fail the run.
func (*Machine) HeapSize ¶ added in v0.3.0
HeapSize returns the number of heap-allocated cells currently held by the machine's active closure context. Typically 0 between Run() calls; nonzero only mid-execution. Reported by FormatStats when nonzero.
func (*Machine) MakeMethodCallable ¶
MakeMethodCallable returns a mvm func Value suitable for Machine.CallFunc. The receiver cell is constructed with method.Path applied.
func (*Machine) MethodByName ¶
MethodByName returns the first resolved method named `name` reachable from t. For pointer types, methods declared on the element type are also searched. Returns (Method, true) on hit.
func (*Machine) PendingGoroutineFault ¶ added in v0.4.0
PendingGoroutineFault reports a recorded goroutine panic that should propagate (nil when none, or under the continue policy).
func (*Machine) PopExit ¶
func (m *Machine) PopExit()
PopExit removes the last machine code instruction if is Exit.
func (*Machine) Push ¶
Push pushes data values into the machine's global storage. Globals are always loaded via Push before Run is called.
func (*Machine) PushCode ¶
func (m *Machine) PushCode(code ...Instruction) (p int)
PushCode adds instructions to the machine code (with zero source positions).
func (*Machine) SetDebugIO ¶
SetDebugIO sets the I/O streams for the interactive debug mode.
func (*Machine) SetDebugInfo ¶
SetDebugInfo registers a function that builds DebugInfo on demand and invalidates the trace-step cache so the next traceStep call rebuilds.
func (*Machine) SetGoroutineFaultContinue ¶ added in v0.4.0
SetGoroutineFaultContinue picks the policy for a later goroutine panic: false (default) propagates it as a non-zero exit; true records+logs only and lets execution continue (mvm test keeps running the suite). Call before the run.
func (*Machine) SetTraceOps ¶ added in v0.2.0
SetTraceOps enables or disables bytecode-level tracing.
func (*Machine) SetTracing ¶ added in v0.2.0
SetTracing enables or disables `set -x`-style line tracing. Toggles take effect at the next Run().
func (*Machine) StackLen ¶ added in v0.4.0
StackLen returns the number of values left on the data stack.
func (*Machine) TraceOps ¶ added in v0.2.0
TraceOps reports whether bytecode-level tracing is enabled.
func (*Machine) TrimStack ¶
func (m *Machine) TrimStack()
TrimStack removes leftover stack values from a previous Run. Call before pushing new global data on re-entry.
func (*Machine) WalkCallStack ¶ added in v0.2.0
func (m *Machine) WalkCallStack(yield func(StackFrame) bool)
WalkCallStack invokes yield for each call frame from innermost (the currently running function) to outermost. The first yielded frame's IP is m.ip-1 (the just-executed or about-to-execute instruction); each subsequent frame's IP is the call instruction in the caller (retIP-1 of the inner frame). yield returns false to stop early.
type MvmFunc ¶
type MvmFunc struct {
Val Value // mvm func (int code addr or Closure)
GF reflect.Value // reflect.MakeFunc wrapper for native Go callbacks
}
MvmFunc bundles a mvm func value with its native Go reflect.MakeFunc wrapper. Stored when a mvm func is assigned to a struct field of func type: GF is callable from native Go (HTTP handlers, callbacks, etc.); Val is the original mvm func dispatched directly by the VM.
type NativeMethodHook ¶ added in v0.3.0
NativeMethodHook intercepts a native method call. The returned values are the replacement results. Whether a hook is installed for the (rtype, name) pair is reported separately by hasNativeMethodHook.
type Op ¶
type Op int32
Op is a VM opcode (bytecode instruction).
const ( // Instruction effect on stack: values consumed -- values produced. Nop Op = iota // -- Addr // a -- &a ; AddrLocal // -- &local ; push pointer to mem[fp-1+$1]; promotes slot to addressable storage so writes via the pointer propagate back; $2!=0 retypes a func slot to func type globals[$2-1] Append // slice [v0..vn-1] -- slice' ; append $0 values to slice AppendSlice // slice [v0..vn-1] -- slice' ; pack $0 values into []T, reflect.AppendSlice; elem type at mem[$1]; $0=0 means spread mode: append(a, b...) Call // f [a1 .. ai] -- [r1 .. rj] ; r1, ... = prog[f](a1, ...); B bit 15 = spread flag CallImm // [a1 .. ai] -- [r1 .. rj] ; $1=dataIdx of func, $2=narg<<16|nret CallImmFast // like CallImm; emitted when no callee param has reflect Kind Struct or Array so detachByValueArgs can be elided Cap // -- x ; x = cap(mem[sp-$0]) Clear // x -- ; clear(x): delete all map entries or zero all slice elements Convert // v -- v' ; v' = convert(v, type at mem[$1]); optional $2 = stack depth offset CopySlice // dst src -- n ; n = copy(dst, src) DeferPush // func [a0..an-1] -- func [a0..an-1] [packed prevHead retIP] ; register deferred call on stack; $0=narg, $1=1 if native DeferRet // -- ; sentinel: restore outer frame after a deferred call returns DeleteMap // map key -- ; delete(map, key) Deref // x -- *x ; DerefSet // ptr val -- ; *ptr = val Equal // n1 n2 -- cond ; cond = n1 == n2 EqualSet // n1 n2 -- n1 cond ; cond = n1 == n2 Exit // -- ; Field // s -- f ; f = s.FieldIndex($1, ...) FieldFset // s i v -- s; s.FieldIndex(i) = v FieldRefSet // fref v -- ; fref = v (via setFuncField) FieldSet // s d -- s ; s.FieldIndex($1, ...) = d Fnew // -- x; x = new mem[$1] FnewE // -- x; x = new mem[$1].Elem() Get // addr -- value ; value = mem[addr] Grow // -- ; sp += $1 HeapAlloc // -- &cell ; cell = new(Value), push its pointer HeapGet // -- v ; v = *State.Heap[$1] HeapPtr // -- &cell ; push State.Heap[$1] itself (transitive capture) HeapSet // v -- ; *State.Heap[$1] = v CellGet // -- v ; cell = mem[fp-1+$1].(*Value); push *cell CellSet // v -- ; cell = mem[fp-1+$1].(*Value); *cell = v IfaceCall // iface -- closure ; dynamic dispatch method $1 on iface IfaceWrap // v -- iface ; wrap v in Iface{type at $1, v} Index // a i -- a[i] ; IndexAddr // a i -- &a[i] ; pointer to element IndexSet // a i v -- a; a[i] = v Jump // -- ; ip += $1 JumpFalse // cond -- ; if cond { ip += $1 } JumpSetFalse // JumpSetTrue // JumpTrue // cond -- ; if cond { ip += $1 } Len // -- x; x = mem[sp-$1] MapIndex // a i -- a[i] MapIndexOk // a i -- v ok ; v, ok = a[i] MapSet // a i v -- a; a[i] = v MkClosure // code [&c0..&cn-1] -- clo ; clo = Closure{code, heap} MkMap // -- map ; create map[K]V, key type at mem[$0], val type at mem[$1] MkSlice // [v0..vn-1] -- slice ; collect $0 values into []T, elem type at mem[$1] New // -- x; mem[fp+$1] = new mem[$2] Next // -- ; iterator next, set K Next0 // -- ; iterator next, no variable Next2 // -- ; iterator next, set K V Not // c -- r ; r = !c Panic // v -- ; pop value, start stack unwinding PanicUnwind // -- ; sentinel: handle panic stack unwinding Pop // v -- PtrNew // -- ptr ; ptr = new(T), type at mem[$0] Pull // a -- a s n; pull iterator next and stop function Pull2 // a -- a s n; pull iterator next and stop function Push // -- v Recover // -- v ; push recovered value (or nil if not panicking in a deferred call) Return // [r1 .. ri] -- ; exit frame, nret and frameBase from frames SetGlobal // v -- ; mem[$1] = v (globals) SetLocal // v -- ; mem[fp-1+$1] = v SetS // dest val -- ; dest.Set(val) Slice // a l h -- a; a = a [l:h] Slice3 // a l h m -- a; a = a[l:h:m] Stop // -- iterator stop; sp -= 3 + $1 Swap // -- Trap // -- ; pause VM execution and enter debug mode TypeAssert // iface -- v [ok] ; assert iface holds type at mem[$1]; $2=0 panics, $2=1 ok form TypeBranch // iface -- ; pop iface; if iface doesn't hold type at mem[$2] (or $2==-1 for nil), ip += $1 WrapFunc // mvmFuncVal -- MvmFunc ; wrap mvm func in reflect.MakeFunc for native callbacks; $0=typeIdx, $1=depth from sp (0=top) MkMethodExpr // -- f ; push func value for interpreted method expression T.M; $0=method code global, $1=method-expr (recv-first) typeIdx // Goroutine and channel opcodes. GoCall // f [a1..ai] -- ; spawn goroutine; $0=narg GoCallImm // [a1..ai] -- ; spawn goroutine to known func; $0=dataIdx, $1=narg MkChan // -- ch ; create channel; $0=elemTypeIdx, $1=bufsize (-1=from stack) ChanSend // ch v -- ; send to channel ChanRecv // ch -- v [ok] ; receive from channel; $0=1 for ok-form ChanClose // ch -- ; close channel SelectExec // ch0 [v0] .. chN [vN] -- chosenIdx ; $0=metaIdx, $1=ncase; calls reflect.Select Print // [v0..vn-1] -- ; print $0 values to m.out Println // [v0..vn-1] -- ; println $0 values to m.out, space-separated, trailing newline Min // [v0..vn-1] -- min ; find min of $0 values; $1 = reflect.Kind for dispatch Max // [v0..vn-1] -- max ; find max of $0 values; $1 = reflect.Kind for dispatch Complex // f1 f2 -- c ; c = complex(f1, f2); $0 = reflect.Kind for dispatch Real // c -- f ; f = real(c); $0 = reflect.Kind for dispatch Imag // c -- f ; f = imag(c); $0 = reflect.Kind for dispatch AddStr // s1 s2 -- s ; s = s1 + s2 (string concatenation) GreaterStr // s1 s2 -- cond ; cond = s1 > s2 LowerStr // s1 s2 -- cond ; cond = s1 < s2 AddInt // n1 n2 -- sum AddInt8 AddInt16 AddInt32 AddInt64 AddUint AddUint8 AddUint16 AddUint32 AddUint64 AddFloat32 AddFloat64 SubInt // n1 n2 -- diff SubInt8 SubInt16 SubInt32 SubInt64 SubUint SubUint8 SubUint16 SubUint32 SubUint64 SubFloat32 SubFloat64 MulInt // n1 n2 -- prod MulInt8 MulInt16 MulInt32 MulInt64 MulUint MulUint8 MulUint16 MulUint32 MulUint64 MulFloat32 MulFloat64 NegInt // n -- -n NegInt8 NegInt16 NegInt32 NegInt64 NegUint NegUint8 NegUint16 NegUint32 NegUint64 NegFloat32 NegFloat64 GreaterInt // n1 n2 -- cond GreaterInt8 GreaterInt16 GreaterInt32 GreaterInt64 GreaterUint GreaterUint8 GreaterUint16 GreaterUint32 GreaterUint64 GreaterFloat32 GreaterFloat64 LowerInt // n1 n2 -- cond LowerInt8 LowerInt16 LowerInt32 LowerInt64 LowerUint LowerUint8 LowerUint16 LowerUint32 LowerUint64 LowerFloat32 LowerFloat64 DivInt // n1 n2 -- quot DivInt8 DivInt16 DivInt32 DivInt64 DivUint DivUint8 DivUint16 DivUint32 DivUint64 DivFloat32 DivFloat64 RemInt // n1 n2 -- rem (integer only) RemInt8 RemInt16 RemInt32 RemInt64 RemUint RemUint8 RemUint16 RemUint32 RemUint64 RemFloat32 // unused, but keeps NumTypes alignment RemFloat64 // unused, but keeps NumTypes alignment // Bitwise opcodes (generic, operate on raw uint64 bits). BitAnd // n1 n2 -- n1 & n2 BitOr // n1 n2 -- n1 | n2 BitXor // n1 n2 -- n1 ^ n2 BitAndNot // n1 n2 -- n1 &^ n2 BitShl // n1 n2 -- n1 << n2 BitShr // n1 n2 -- n1 >> n2 (arithmetic for signed) BitComp // n -- ^n // Bit manipulation opcodes (32-bit and 64-bit variants). Clz32 // n -- count ; count leading zeros (32-bit) Clz64 // n -- count ; count leading zeros (64-bit) Ctz32 // n -- count ; count trailing zeros (32-bit) Ctz64 // n -- count ; count trailing zeros (64-bit) Popcnt32 // n -- count ; population count (32-bit) Popcnt64 // n -- count ; population count (64-bit) Rotl32 // n k -- result ; rotate left (32-bit) Rotl64 // n k -- result ; rotate left (64-bit) Rotr32 // n k -- result ; rotate right (32-bit) Rotr64 // n k -- result ; rotate right (64-bit) // Float math opcodes (unary: 1 operand; binary: 2 operands). AbsFloat32 // n -- |n| AbsFloat64 // n -- |n| SqrtFloat32 // n -- sqrt(n) SqrtFloat64 // n -- sqrt(n) CeilFloat32 // n -- ceil(n) CeilFloat64 // n -- ceil(n) FloorFloat32 // n -- floor(n) FloorFloat64 // n -- floor(n) TruncFloat32 // n -- trunc(n) TruncFloat64 // n -- trunc(n) NearestFloat32 // n -- nearest(n) NearestFloat64 // n -- nearest(n) MinFloat32 // a b -- min(a,b) MinFloat64 // a b -- min(a,b) MaxFloat32 // a b -- max(a,b) MaxFloat64 // a b -- max(a,b) CopysignFloat32 // a b -- copysign(a,b) CopysignFloat64 // a b -- copysign(a,b) // Immediate operand variants: fold Push+BinOp into one instruction. // Arg[0] holds the right-hand constant (int, sign-extended to int64). AddIntImm // n -- n+$1 SubIntImm // n -- n-$1 MulIntImm // n -- n*$1 GreaterIntImm // n -- n>$1 (signed) GreaterUintImm // n -- n>$1 (unsigned) LowerIntImm // n -- n<$1 (signed) LowerUintImm // n -- n<$1 (unsigned) GetGlobal // -- value ; value = mem[$1] (global variable, syncs num from ref if needed) GetLocal // -- value ; value = mem[$1+fp-1] (local variable, no scope check) GetLocalSync // -- value ; value = mem[$1+fp-1] and re-read num from ref (used after AddrLocal) NextLocal // -- ; iterator next, set K (local scope); like Next but scope is always Local Next2Local // -- ; iterator next, set K V (local scope); like Next2 but scope is always Local // Fused GetLocal + operation superinstructions. // $1 = local offset (as in GetLocal), $2 = immediate operand. GetLocal2 // -- v1 v2 ; push two locals: mem[$1+fp-1] then mem[$2+fp-1] GetLocalAddIntImm // -- n+$2 ; push local $1 then add immediate $2 GetLocalSubIntImm // -- n-$2 ; push local $1 then subtract immediate $2 GetLocalMulIntImm // -- n*$2 ; push local $1 then multiply by immediate $2 GetLocalLowerIntImm // -- cond ; push local $1 then compare < immediate $2 (signed) GetLocalLowerUintImm // -- cond ; push local $1 then compare < immediate $2 (unsigned) GetLocalGreaterIntImm // -- cond ; push local $1 then compare > immediate $2 (signed) GetLocalGreaterUintImm // -- cond ; push local $1 then compare > immediate $2 (unsigned) GetLocalReturn // -- ; push local $1 then return (nret/frameBase from frame) // Fused compare + conditional-jump superinstructions. // Only LowerInt variants are needed, compiler rewrites Greater comparisons // using the identity: (a > imm) same as !(a < imm+1). LowerIntImmJumpFalse // n -- ; if n >= $2 { ip += $1 } ; sp-- LowerIntImmJumpTrue // n -- ; if n < $2 { ip += $1 } ; sp-- GetLocalLowerIntImmJumpFalse // -- ; if local[$1.lo] >= $2 { ip += $1.hi } ($1 = jumpOff_int16<<16 | localOff_int16, $2 = imm32) GetLocalLowerIntImmJumpTrue // -- ; if local[$1.lo] < $2 { ip += $1.hi } ($1 = jumpOff_int16<<16 | localOff_int16, $2 = imm32) // In-place local update super-instructions for `x op= y` and `x op= n`, // collapsing the GetLocal2+RHS+SetLocal+Pop sequence. No stack effect. AddLocalLocal // -- ; local[$1] += local[$2] SubLocalLocal // -- ; local[$1] -= local[$2] AddLocalIntImm // -- ; local[$1] += $2 (signed, fits int32) SubLocalIntImm // -- ; local[$1] -= $2 (signed, fits int32) IndexSetBool // a i -- ; a[i] = bool($1) (fuses Push/GetGlobal bool + IndexSet + Pop) MarkNamedRet // -- ; flag this frame as having captured named returns (set bit in retIPInfo) )
Byte-code instruction set.
type Opaque ¶
type Opaque struct{}
Opaque stands in for an external type which could not be resolved at parse time.
type PanicError ¶ added in v0.3.0
type PanicError struct {
Raw any // original panic value
Pos Pos // source position of the panicking instruction
IP int // bytecode IP at panic time
Frames []StackFrame // captured before frame unwinding
DI *DebugInfo // captured DebugInfo for formatting; may be nil
}
PanicError wraps a raw Go panic that escaped the VM with mvm-level diagnostic context.
func (*PanicError) Error ¶ added in v0.3.0
func (e *PanicError) Error() string
Error renders the verbose layout (header + snippet + mvm stack) using the DebugInfo captured at panic time. Falls back to "panic: <raw>" if no DebugInfo was captured.
type RuntimeFuncInfo ¶ added in v0.2.0
RuntimeFuncInfo holds the synthesized Name/FileLine for a *runtime.Func sentinel allocated by the bridged runtime.FuncForPC. The sentinel is a fresh &runtime.Func{} pointer; the host runtime never sees it because nativeMethodLookup intercepts Name and FileLine before any host method runs.
func LookupRuntimeFunc ¶ added in v0.2.0
func LookupRuntimeFunc(rf *runtime.Func) *RuntimeFuncInfo
LookupRuntimeFunc returns the registered metadata for rf, or nil if rf was not produced by the mvm bridge.
func LookupRuntimeFuncByPC ¶ added in v0.2.0
func LookupRuntimeFuncByPC(pc uintptr) (*runtime.Func, *RuntimeFuncInfo)
LookupRuntimeFuncByPC resolves a host-style PC value to a registered sentinel and its metadata. It tries pc-1 first (pkg/errors stores PC = sentinel+1 and looks up via pc-1) and falls back to pc for callers that skipped the +1 convention. Returns nil/nil when pc does not name a virtualized frame.
Compared to the previous (*runtime.Func)(unsafe.Pointer(pc - 1)) idiom, this form does no pointer arithmetic on a uintptr that came from a host pointer, so it is safe under -race / checkptr.
type SelectCaseInfo ¶
type SelectCaseInfo struct {
Dir reflect.SelectDir // SelectSend, SelectRecv, or SelectDefault
Slot int // local/global index for received value (-1 if unused)
OkSlot int // local/global index for ok bool (-1 if unused)
Local bool // true if slots are local (frame-relative), false for global
}
SelectCaseInfo describes one case of a select statement.
type SelectMeta ¶
type SelectMeta struct {
Cases []SelectCaseInfo
TotalPop int // precomputed number of stack slots consumed by channel/value entries
}
SelectMeta holds metadata for a select statement, stored in the data section.
type StackFrame ¶ added in v0.2.0
type StackFrame struct {
IP int // bytecode position within the frame's function
Pos Pos // source position from m.code[IP], 0 if out of range
TopLevel bool // synthetic frame for the top-level entry sequence (init / Eval driver)
Native bool // synthetic boundary row: a native call separating two interpreted segments
Name string // for Native rows, the native func mvm invoked at the boundary
}
StackFrame is a single entry yielded by WalkCallStack.
type Value ¶
type Value struct {
// contains filtered or unexported fields
}
Value is the VM runtime value. Numeric types (bool, int*, uint*, float*) store their value inline in num. ref carries reflect.Zero(t) for type metadata on numeric types. Composite types (string, slice, map, struct, ptr, func, interface) use ref.
func FromReflect ¶
FromReflect wraps a reflect.Value into a Value.
func TypeValue ¶
TypeValue returns a zero value for use as a type descriptor in the data table. Preserves the exact reflect.Type for all kinds so opcodes like MkChan can recover it via ref.Type().
func (Value) CopyArray ¶
CopyArray returns a Value holding a copy of the array in v, so that range iterates over a snapshot (Go spec: range over array uses a copy).
func (Value) Elem ¶
Elem returns the value that the interface v contains or the pointer v points to.
func (Value) FieldByIndex ¶
FieldByIndex returns the nested field corresponding to index.
func (Value) Reflect ¶
Reflect reconstructs a reflect.Value from an inline numeric Value. For composite types, returns ref directly. This may allocate for numeric types; use only at reflect boundaries.
func (Value) SetMapIndex ¶
SetMapIndex sets the element associated with key in the map v.