Help us shape the future of Go! Take the 2026 Go Developer Survey

vm

package
v0.14.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 22, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package vm 实现了 JavaScript 的栈式字节码虚拟机。

VM 核心包含三个组件:

  • 操作数栈 (Stack): 计算过程中的临时值栈
  • 调用帧 (Frame): 每个函数调用创建一个帧,保存局部变量和 PC
  • 全局环境 (Environment): 存储全局变量 (通过 OP_LOAD_GLOBAL 访问)

执行流程:

  1. 编译器输出字节码 + 常量池
  2. VM 创建主帧,开始取指-解码-执行循环
  3. 每条指令: 读取 1 字节 opcode + 2 字节 operand, 执行对应操作
  4. PC 前进 3 字节,取下一条指令
  5. OP_CALL 创建新帧, OP_RETURN 弹出帧并返回值

Index

Constants

View Source
const MaxFrames = 2048
View Source
const StackSize = 2048

StackSize 是操作数栈的初始容量。

Variables

This section is empty.

Functions

func Eval

func Eval(input string) (object.Value, error)

func EvalFile

func EvalFile(path string) (object.Value, error)

func EvalWithGlobals

func EvalWithGlobals(input string, globals *runtime.Environment) (object.Value, error)

Types

type Frame

type Frame struct {
	Instructions bytecode.Instructions
	PC           int
	Locals       []object.Value
	Closure      *object.Closure
	// This 是本帧**生效**的 this 绑定 (已按 sloppy 规则归一)。callClosure 在
	// 装配帧时写入: 箭头帧取其词法捕获的 this, 非箭头帧把 undefined/null 归一
	// 为 globalThis。主帧 (frame.Closure == nil) 保持 nil, 由 OP_THIS 按
	// script/module 决定取值。与 Closure.This (创建时携带的原始绑定) 区分开。
	This object.Value
	// NewTarget 是本帧的 `new.target` 绑定 (构造目标)。callClosure 装配帧时:
	//   - 构造调用 (OP_NEW): 写被 new 的构造器;
	//   - super() 调用 (OP_NEW_TARGET_MARK 传递): 写调用者帧的 NewTarget
	//     —— 派生类构造器里 super() 父构造器看到的 new.target 是最初被 new 的那个;
	//   - 其余 (普通调用/箭头): nil, 由 OP_NEW_TARGET 归一为 undefined。
	NewTarget       object.Value
	Constants       *bytecode.ConstantPool
	ModifiedSlots   map[int]bool      // 修改过的 slot (用于 popFrame 传播)
	CreatedClosures []*object.Closure // 本帧创建的闭包 (用于 STORE 传播)
	SharedCells     []object.Value    // 外层 binding cell (== 创建它的帧的 Locals 数组)

	// ===== 迭代边界的共享前缀模型 (rUm0q6) =====
	//
	// OP_ITER_BOUNDARY 只应"定版"**每轮新建的词法绑定** (循环变量 + 循环体内
	// 的 let/const), 而 var (函数作用域) 与外层 let 是**单实例**, 所有轮次的
	// 闭包必须共享同一颗 cell。旧实现直接清空 CreatedClosures + 克隆整个 Locals
	// 数组, 把不该定版的共享绑定也一并封死 ⇒ 闭包看到的是各自轮次的快照
	// (for(var x of …) 得到 [1,2,3] 而非规范要求的 [3,3,3])。
	//
	// 现模型: 迭代边界携带 sealFrom (块作用域内首个新槽位), 只把该边界之后的
	// 写入视为"新 cell"; 边界之前的 slot (< sealFrom) 视为共享, 照常传播给
	// 全部已创建闭包。Epoch 每过一次边界 +1; 闭包记录创建时的 Epoch。
	Epoch     int        // 已执行的迭代边界次数
	SealMarks []sealMark // 各边界的 (sealFrom → 过界后的 Epoch), 按 sealFrom 去重取最新
	StackBase int        // 进入本帧时栈高度 (返回时截断到此处)

	// PendingGen 非 nil 表示本帧是生成器/异步生成器的"形参前导帧":
	// 帧内指令只覆盖形参绑定前导段 [0, StopPC)。执行到 PC >= StopPC 时
	// 冻结为 Generator (见 runFrom/freezeGenPrologue), 函数体随后才在
	// 首次 next() 时运行。规范要求形参绑定在调用时同步完成。
	PendingGen *object.Generator
	StopPC     int
}

Frame 表示 VM 调用栈中的一个帧。 每次函数调用创建一个新帧,函数返回时弹出。

帧包含:

  • Instructions: 当前正在执行的字节码
  • PC: 程序计数器 (字节偏移,每条指令 3 字节)
  • Locals: 局部变量数组 (通过 OP_LOAD/OP_STORE 按 slot 索引)
  • Closure: 如果是闭包调用,关联的闭包对象
  • Constants: 常量池引用 (所有帧共享同一个)
  • ModifiedSlots: 本帧中修改过的 slot 集合 (用于 popFrame 时向上一帧传播闭包变量修改)
  • CreatedClosures: 在本帧中创建的闭包列表 (用于 OP_STORE 时向子闭包传播外层变量修改)

func NewClosureFrame

func NewClosureFrame(meta *bytecode.FunctionMetadata, constants *bytecode.ConstantPool, captured []object.Value, closure *object.Closure) *Frame

NewClosureFrame 为闭包调用创建新帧。 captured 是从创建闭包的帧中捕获的局部变量。

func NewFrame

func NewFrame(ins bytecode.Instructions, constants *bytecode.ConstantPool, numLocals int) *Frame

NewFrame 创建新的调用帧。

Locals 刻意保持零值 (nil): nil 表示"该绑定尚未初始化",OP_LOAD 读到它时 抛 ReferenceError —— 这就是 let/const 的 TDZ (暂时性死区)。 若像以前那样预填 undefined,声明前访问会静默得到 undefined。

type FrameError added in v0.8.0

type FrameError struct {
	Inner error
	Frame string
}

FrameError 是附带源码帧的错误。Error() 把帧渲染在原错误消息之后。

func (*FrameError) Error added in v0.8.0

func (e *FrameError) Error() string

func (*FrameError) Unwrap added in v0.8.0

func (e *FrameError) Unwrap() error

type ModuleExports

type ModuleExports struct {
	Default object.Value
	Named   map[string]object.Value
	// contains filtered or unexported fields
}

type Stack

type Stack struct {
	// contains filtered or unexported fields
}

Stack 是 VM 的操作数栈。 所有计算中间结果都暂存在这里。

func NewStack

func NewStack() *Stack

NewStack 创建空的操作数栈。

func (*Stack) Len

func (s *Stack) Len() int

Len 返回栈中当前元素数。

func (*Stack) Peek

func (s *Stack) Peek() object.Value

Peek 返回栈顶值但不弹出。

func (*Stack) PeekAt

func (s *Stack) PeekAt(n int) object.Value

PeekAt 返回栈中指定偏移的值 (0 = 栈顶)。

func (*Stack) Pop

func (s *Stack) Pop() object.Value

Pop 弹出并返回栈顶值。调用前必须确保栈非空。

func (*Stack) Push

func (s *Stack) Push(v object.Value)

Push 将值压入栈顶。

func (*Stack) Reset

func (s *Stack) Reset()

Reset 清空栈。

func (*Stack) Truncate

func (s *Stack) Truncate(n int)

Truncate 将栈截断到指定高度 n (丢弃 n 以上的值)。

type ThrowError

type ThrowError struct {
	Value object.Value
}

func (*ThrowError) Error

func (e *ThrowError) Error() string

type VM

type VM struct {
	// contains filtered or unexported fields
}

func EvalFileVM

func EvalFileVM(path string) (*VM, error)

func EvalFileVMModuleEarlyErrors added in v0.10.0

func EvalFileVMModuleEarlyErrors(path string) (*VM, error)

func EvalFileVMT262 added in v0.10.0

func EvalFileVMT262(path string) (*VM, error)

EvalFileVMT262 与 EvalFileVM 相同,但额外注入 test262 宿主约定所需的 $262 全局对象($262.detachArrayBuffer)。仅供 cmd/gox 的 test262 runner 使用 —— 常规脚本执行不应看到 $262。

func EvalModuleFileVM added in v0.10.0

func EvalModuleFileVM(path string) (*VM, error)

func EvalModuleFileVMWithGlobals added in v0.10.0

func EvalModuleFileVMWithGlobals(path string, globals *runtime.Environment) (*VM, error)

func EvalVM

func EvalVM(input string) (*VM, error)

func New

func New(ins bytecode.Instructions, constants *bytecode.ConstantPool, numLocals int) *VM

func NewWithGlobals

func NewWithGlobals(ins bytecode.Instructions, constants *bytecode.ConstantPool, numLocals int, globals *runtime.Environment) *VM

func (*VM) AttachFrame added in v0.8.0

func (vm *VM) AttachFrame(err error) error

AttachFrame 给运行时错误附加源码帧 (尽力而为): 无位置信息或找不到 匹配语句时原样返回。模块/eval 等无源码场景不受影响。

func (*VM) Globals

func (vm *VM) Globals() *runtime.Environment

func (*VM) LastPopped

func (vm *VM) LastPopped() object.Value

func (*VM) Run

func (vm *VM) Run() error

func (*VM) RunCompiled

func (vm *VM) RunCompiled(c *compiler.Compiler) error

func (*VM) RunCompiledAsync added in v0.10.0

func (vm *VM) RunCompiledAsync(c *compiler.Compiler) error

func (*VM) RunTimers

func (vm *VM) RunTimers() error

func (*VM) RunTimersUntil

func (vm *VM) RunTimersUntil(until time.Time) error

func (*VM) RunTimersWithPump

func (vm *VM) RunTimersWithPump(pump func(maxWait time.Duration) bool) error

func (*VM) SetModuleBase

func (vm *VM) SetModuleBase(path string)

func (*VM) SetSourceInfo added in v0.8.0

func (vm *VM) SetSourceInfo(file, text string)

SetSourceInfo 注入当前脚本的文件名与文本 (EvalFileVM / loadModuleFile 接线)。 text 对 .ts/.tsx 是**用户原文**, JS 文件就是 JS 本身。

func (*VM) SetStmtPositions added in v0.8.0

func (vm *VM) SetStmtPositions(tbl map[int]ast.Pos)

SetStmtPositions 注入主脚本的语句位置表并建立升序索引。

func (*VM) SetTranspileMap added in v0.10.0

func (vm *VM) SetTranspileMap(lm *tstransform.LineMap, jsText string)

SetTranspileMap 注入 TS 转译的行映射与转译后 JS 文本。

调用约定: 先 SetSourceInfo(file, tsText) (给原文), 再调用本方法 (补映射与 JS)。 jsText 即使映射缺失也要给 —— 它是回退展示的素材。

type YieldSignal

type YieldSignal struct {
	// contains filtered or unexported fields
}

func (*YieldSignal) Error

func (e *YieldSignal) Error() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL