docs: update design proposal architecture
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,754 @@
|
|||||||
|
# 面向 AI Agent 的轻量级 JavaScript 执行引擎设计方案
|
||||||
|
|
||||||
|
> 项目名称:OxideJS
|
||||||
|
> 技术路线:Rust + 自研字节码编译器 + 寄存器式虚拟机 + 单 Kernel 多 VM 运行时
|
||||||
|
> 目标场景:短时、高频、即时执行的 JavaScript 代码运行环境
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、设计思路
|
||||||
|
|
||||||
|
### 1.1 问题背景
|
||||||
|
|
||||||
|
在 AI Agent、自动化工具调用、脚本沙箱和数据转换流水线中,JavaScript 代码的执行模式与传统浏览器场景不同:
|
||||||
|
|
||||||
|
- **执行时间短**:单次脚本通常只执行一个表达式、一段数据处理逻辑或一次工具调用;
|
||||||
|
- **调用频率高**:Agent 可能连续发起大量短脚本执行请求;
|
||||||
|
- **代码结构重复**:由大模型生成的代码往往存在相似模板;
|
||||||
|
- **上下文隔离要求高**:不同请求需要独立寄存器、调用栈、临时对象和异常状态;
|
||||||
|
- **公共信息可复用**:字符串、对象 Shape、内置对象、编译缓存等可以跨请求复用;
|
||||||
|
- **不适合重量级 Runtime**:传统 JS 引擎面向浏览器或长期运行应用,启动、GC、上下文管理都较重。
|
||||||
|
|
||||||
|
因此,OxideJS 的设计核心不是简单复刻浏览器 JavaScript 引擎,而是围绕“**轻量、可复用、可隔离、可测试**”四个目标,构建面向短时执行场景的 JS runtime。
|
||||||
|
|
||||||
|
### 1.2 总体设计目标
|
||||||
|
|
||||||
|
OxideJS 的总体目标是实现一个基于 Rust 的轻量级 JS 执行引擎,提供完整的源码解析、字节码编译、虚拟机执行和兼容性测试链路。
|
||||||
|
|
||||||
|
设计目标如下:
|
||||||
|
|
||||||
|
| 目标 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| 轻量执行 | 避免引入 V8/QuickJS 等外部执行引擎,保持 runtime 可控 |
|
||||||
|
| 多请求隔离 | 每个 VM 拥有独立寄存器、调用栈、临时内存和异常状态 |
|
||||||
|
| 跨 VM 复用 | Kernel 保存字符串、Shape、编译缓存、内置对象等共享状态 |
|
||||||
|
| 低 GC 干扰 | 临时对象优先进入会话 arena,减少短时执行中的全局回收压力 |
|
||||||
|
| test262 驱动 | 使用 ECMAScript Test Suite 持续验证语义正确性 |
|
||||||
|
| 可扩展架构 | parser、compiler、types、kernel、vm、cli、test262 runner 分 crate 组织 |
|
||||||
|
|
||||||
|
### 1.3 创新点 1: 单 Kernel 多 VM
|
||||||
|
|
||||||
|
OxideJS 最重要的运行时结构是 **单 Kernel 多 VM**。
|
||||||
|
|
||||||
|
```text
|
||||||
|
Process / Engine Instance
|
||||||
|
|
||||||
|
+===================================================================================+
|
||||||
|
| OxideKernel |
|
||||||
|
| |
|
||||||
|
| Shared, long-lived, cross-request runtime state |
|
||||||
|
| |
|
||||||
|
| +----------------+ +----------------+ +----------------+ +----------------+ |
|
||||||
|
| | StringForge | | ShapeForge | | CodeForge | | PropForge | |
|
||||||
|
| |----------------| |----------------| |----------------| |----------------| |
|
||||||
|
| | intern strings | | hidden classes | | bytecode cache | | IC templates | |
|
||||||
|
| | string handles | | property layout| | structural hash| | shape -> slot | |
|
||||||
|
| +----------------+ +----------------+ +----------------+ +----------------+ |
|
||||||
|
| |
|
||||||
|
| +----------------+ +----------------+ +----------------+ +----------------+ |
|
||||||
|
| | BuiltinWorld | | Global Shapes | | Kernel Config | | Runtime Logs | |
|
||||||
|
| |----------------| |----------------| |----------------| |----------------| |
|
||||||
|
| | Object/Array | | builtin shape | | pool limits | | trace/debug | |
|
||||||
|
| | Function/etc. | | root layouts | | step limits | | diagnostics | |
|
||||||
|
| +----------------+ +----------------+ +----------------+ +----------------+ |
|
||||||
|
+==========================================+========================================+
|
||||||
|
|
|
||||||
|
| Arc<OxideKernel>
|
||||||
|
|
|
||||||
|
+-------------------------------+-------------------------------+
|
||||||
|
| | |
|
||||||
|
v v v
|
||||||
|
+----------------------+ +----------------------+ +----------------------+
|
||||||
|
| VM #1 | | VM #2 | | VM #N |
|
||||||
|
|----------------------| |----------------------| |----------------------|
|
||||||
|
| registers[256] | | registers[256] | | registers[256] |
|
||||||
|
| pc | | pc | | pc |
|
||||||
|
| bytecode view | | bytecode view | | bytecode view |
|
||||||
|
| constants view | | constants view | .... | constants view |
|
||||||
|
| call frames | | call frames | | call frames |
|
||||||
|
| try/catch stack | | try/catch stack | | try/catch stack |
|
||||||
|
| exception state | | exception state | | exception state |
|
||||||
|
| local session arena | | local session arena | | local session arena |
|
||||||
|
| session GC metadata | | session GC metadata | | session GC metadata |
|
||||||
|
+----------+-----------+ +----------+-----------+ +----------+-----------+
|
||||||
|
| | |
|
||||||
|
v v v
|
||||||
|
Request Result Request Result Request Result
|
||||||
|
```
|
||||||
|
|
||||||
|
该结构将运行时状态分为两类:
|
||||||
|
|
||||||
|
| 状态类型 | 所在位置 | 生命周期 | 示例 |
|
||||||
|
|----------|----------|----------|------|
|
||||||
|
| 共享状态 | `OxideKernel` | 进程级、长生命周期 | 字符串表、Shape 表、Code cache、内置对象 |
|
||||||
|
| 私有状态 | `Vm` | 请求级、短生命周期 | 寄存器、PC、调用栈、异常、临时对象 |
|
||||||
|
|
||||||
|
这种分层使得 OxideJS 能够同时满足两类需求:
|
||||||
|
|
||||||
|
1. **隔离性**:每个 VM 独立执行,不共享寄存器和临时对象;
|
||||||
|
2. **复用性**:多个 VM 共享 Kernel,避免重复构建字符串、Shape、内置对象和编译结果。
|
||||||
|
|
||||||
|
### 1.4 创新点 2: 短生命周期内存与 GC
|
||||||
|
|
||||||
|
AI Agent 场景中的大部分对象具有明显的短生命周期特征:对象在一次脚本执行中创建,在执行结束后立即失效。OxideJS 因此将运行时内存分为多个层级:
|
||||||
|
|
||||||
|
```text
|
||||||
|
+====================================================================================+
|
||||||
|
| Memory Model |
|
||||||
|
+====================================================================================+
|
||||||
|
|
||||||
|
Long-lived / shared memory
|
||||||
|
┌──────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ OxideKernel │
|
||||||
|
│ │
|
||||||
|
│ StringForge ShapeForge CodeForge BuiltinWorld │
|
||||||
|
│ interned strs shape records bytecode cache builtin prototypes │
|
||||||
|
│ │
|
||||||
|
│ 生命周期:随 Kernel 存活,跨 VM 共享 │
|
||||||
|
└──────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
▲
|
||||||
|
│ shared references
|
||||||
|
│
|
||||||
|
Per-VM / per-session memory │
|
||||||
|
┌───────────────────────────────────┴──────────────────────────────────────────┐
|
||||||
|
│ Vm │
|
||||||
|
│ │
|
||||||
|
│ registers / call frames / exception state │
|
||||||
|
│ │
|
||||||
|
│ +----------------------------+ │
|
||||||
|
│ | Session Arena | bump allocation for short-lived objects │
|
||||||
|
│ |----------------------------| │
|
||||||
|
│ | object allocations | │
|
||||||
|
│ | arrays / temporary values | │
|
||||||
|
│ | execution-local metadata | │
|
||||||
|
│ +----------------------------+ │
|
||||||
|
│ │
|
||||||
|
│ +----------------------------+ │
|
||||||
|
│ | Session GC Metadata | mark/sweep metadata for session objects │
|
||||||
|
│ |----------------------------| │
|
||||||
|
│ | tracked allocations | │
|
||||||
|
│ | roots from registers | │
|
||||||
|
│ | roots from frames | │
|
||||||
|
│ +----------------------------+ │
|
||||||
|
│ │
|
||||||
|
│ 生命周期: 单 VM / 单执行会话,执行结束后可批量释放或回收 │
|
||||||
|
└──────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
内存与 GC 设计的关键点:
|
||||||
|
|
||||||
|
- **短命对象进入 VM 本地 session arena**:降低通用堆分配压力;
|
||||||
|
- **VM 拥有自己的 session GC 元数据**:寄存器、调用栈、异常对象都可作为 root;
|
||||||
|
- **Kernel 对象与 session 对象分层**:内置对象、Shape、字符串等长生命周期数据不随单次执行销毁;
|
||||||
|
- **执行结束可快速清理 session 内存**:避免每次短脚本执行都触发重型全局 GC;
|
||||||
|
- **Map / Set / Array / Object 等容器需要参与 GC 追踪**:防止 session 对象在容器中被错误释放。
|
||||||
|
|
||||||
|
### 1.5 创新点 3: 自研字节码与寄存器式 VM
|
||||||
|
|
||||||
|
OxideJS 不直接解释 AST,而是先将 AST 编译为自定义字节码,再由寄存器式 VM 执行。
|
||||||
|
|
||||||
|
```text
|
||||||
|
AST
|
||||||
|
|
|
||||||
|
| compiler pass
|
||||||
|
v
|
||||||
|
+-------------------------------+
|
||||||
|
| CompiledModule |
|
||||||
|
|-------------------------------|
|
||||||
|
| bytecode: Vec<Instr> |
|
||||||
|
| constants: Vec<Constant> |
|
||||||
|
| n_registers |
|
||||||
|
| sub_modules for functions |
|
||||||
|
+-------------------------------+
|
||||||
|
|
|
||||||
|
| run(module)
|
||||||
|
v
|
||||||
|
+-------------------------------+
|
||||||
|
| VM |
|
||||||
|
|-------------------------------|
|
||||||
|
| r0 r1 r2 ... r255 |
|
||||||
|
| pc |
|
||||||
|
| frames |
|
||||||
|
| current bytecode |
|
||||||
|
| current constants |
|
||||||
|
+-------------------------------+
|
||||||
|
```
|
||||||
|
|
||||||
|
采用寄存器式 VM 的原因:
|
||||||
|
|
||||||
|
- 表达式中间结果可以直接保存在寄存器中;
|
||||||
|
- 对象属性访问和函数参数传递更直接;
|
||||||
|
- 相比栈式 VM,减少大量 push/pop 指令;
|
||||||
|
- 便于后续加入类型反馈、inline cache 和局部优化。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、实现描述
|
||||||
|
|
||||||
|
### 2.1 完整工作流程
|
||||||
|
|
||||||
|
OxideJS 的一次执行请求从输入 JS 源码到返回结果,经过以下流程:
|
||||||
|
|
||||||
|
```text
|
||||||
|
┌────────────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ One Evaluation Request │
|
||||||
|
└────────────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
1. Source Input
|
||||||
|
│
|
||||||
|
│ JavaScript source string / file
|
||||||
|
▼
|
||||||
|
┌───────────────────────┐
|
||||||
|
│ oxide_parser │
|
||||||
|
│-----------------------│
|
||||||
|
│ - create allocator │
|
||||||
|
│ - parse source │
|
||||||
|
│ - produce AST Program │
|
||||||
|
└──────────┬────────────┘
|
||||||
|
│ AST
|
||||||
|
▼
|
||||||
|
┌────────────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ oxide_compiler │
|
||||||
|
│------------------------------------------------------------------------------------│
|
||||||
|
│ │
|
||||||
|
│ Pass 1: counter / symbol projection │
|
||||||
|
│ - walk statements and expressions │
|
||||||
|
│ - allocate registers │
|
||||||
|
│ - assign labels for jumps, loops, try/catch, switch │
|
||||||
|
│ - build lexical binding information │
|
||||||
|
│ │
|
||||||
|
│ Pass 2: emitter │
|
||||||
|
│ - emit fixed-width bytecode │
|
||||||
|
│ - build constant pool │
|
||||||
|
│ - compile function bodies into sub-modules │
|
||||||
|
│ - encode property access / call / control-flow instructions │
|
||||||
|
│ │
|
||||||
|
│ Hash: structural_hash │
|
||||||
|
│ - normalize AST structure │
|
||||||
|
│ - generate cache key for CodeForge │
|
||||||
|
│ │
|
||||||
|
└──────────┬─────────────────────────────────────────────────────────────────────────┘
|
||||||
|
│ CompiledModule
|
||||||
|
▼
|
||||||
|
┌────────────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ OxideKernel.CodeForge │
|
||||||
|
│------------------------------------------------------------------------------------│
|
||||||
|
│ if cache hit: │
|
||||||
|
│ reuse Arc<CompiledModule> │
|
||||||
|
│ else: │
|
||||||
|
│ insert newly compiled module │
|
||||||
|
└──────────┬─────────────────────────────────────────────────────────────────────────┘
|
||||||
|
│ Arc<CompiledModule>
|
||||||
|
▼
|
||||||
|
┌────────────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ VmPool / VM Selection │
|
||||||
|
│------------------------------------------------------------------------------------│
|
||||||
|
│ - obtain an idle VM │
|
||||||
|
│ - VM references the same Arc<OxideKernel> │
|
||||||
|
│ - reset request-local state │
|
||||||
|
│ - prepare registers, bytecode, constants, frames │
|
||||||
|
└──────────┬─────────────────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌────────────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ VM Dispatch Loop │
|
||||||
|
│------------------------------------------------------------------------------------│
|
||||||
|
│ while pc < bytecode.len(): │
|
||||||
|
│ instr = bytecode[pc] │
|
||||||
|
│ decode opcode / rd / a / b │
|
||||||
|
│ dispatch opcode │
|
||||||
|
│ │
|
||||||
|
│ examples: │
|
||||||
|
│ LOAD_CONST -> load constant to register │
|
||||||
|
│ ADD / SUB -> numeric or string operation │
|
||||||
|
│ GET_PROP -> property lookup through Shape / object model │
|
||||||
|
│ CALL -> push CallFrame and enter sub-module │
|
||||||
|
│ CALL_NATIVE -> call Rust builtin │
|
||||||
|
│ THROW -> build exception and unwind │
|
||||||
|
│ RETURN -> restore caller frame │
|
||||||
|
│ HALT -> finish execution │
|
||||||
|
└──────────┬─────────────────────────────────────────────────────────────────────────┘
|
||||||
|
│ JsValue
|
||||||
|
▼
|
||||||
|
6. Result Formatting / API Return
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 Parser 层
|
||||||
|
|
||||||
|
Parser 层负责将 JavaScript 源码转换为 AST。它不承载运行时语义,而是为 compiler 提供标准化输入。
|
||||||
|
|
||||||
|
职责:
|
||||||
|
|
||||||
|
- 接收源码字符串;
|
||||||
|
- 创建 AST allocator;
|
||||||
|
- 调用 parser 得到 Program;
|
||||||
|
- 将 parser error 转换为项目内部错误。
|
||||||
|
|
||||||
|
对应模块:
|
||||||
|
|
||||||
|
```text
|
||||||
|
crates/oxide_parser/
|
||||||
|
├── src/lib.rs
|
||||||
|
└── src/error.rs
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 Compiler 层
|
||||||
|
|
||||||
|
Compiler 层是 AST 到字节码的核心转换阶段。
|
||||||
|
|
||||||
|
```text
|
||||||
|
crates/oxide_compiler/src/
|
||||||
|
├── compiler.rs # 编译入口和上下文
|
||||||
|
├── counter.rs # 第一遍:寄存器、标签、符号统计
|
||||||
|
├── emitter.rs # 第二遍:生成字节码
|
||||||
|
├── hash.rs # structural hash,用于 CodeForge 缓存
|
||||||
|
├── module.rs # CompiledModule / Constant
|
||||||
|
├── opcode.rs # OpCode 和 32-bit 指令编码
|
||||||
|
└── symbol_table.rs # 词法绑定与作用域信息
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.3.1 两遍编译
|
||||||
|
|
||||||
|
第一遍编译搞清:
|
||||||
|
|
||||||
|
- 函数需要多少寄存器;
|
||||||
|
- 跳转标签位置;
|
||||||
|
- 局部变量和词法绑定;
|
||||||
|
- control-flow 结构边界;
|
||||||
|
- 函数子模块结构。
|
||||||
|
|
||||||
|
第二遍编译正式工作:
|
||||||
|
|
||||||
|
- 将表达式编译为寄存器操作;
|
||||||
|
- 将控制流编译为跳转;
|
||||||
|
- 将对象/数组字面量编译为构造指令;
|
||||||
|
- 将函数体编译为子模块;
|
||||||
|
- 将常量写入常量池。
|
||||||
|
|
||||||
|
#### 2.3.2 字节码格式
|
||||||
|
|
||||||
|
OxideJS 使用固定 32-bit 指令:
|
||||||
|
|
||||||
|
```text
|
||||||
|
32-bit Instr
|
||||||
|
|
||||||
|
+----------+----------+----------+----------+
|
||||||
|
| opcode | rd | a | b |
|
||||||
|
+----------+----------+----------+----------+
|
||||||
|
8 bits 8 bits 8 bits 8 bits
|
||||||
|
```
|
||||||
|
|
||||||
|
其中:
|
||||||
|
|
||||||
|
- `opcode` 表示操作类型;
|
||||||
|
- `rd` 通常表示目标寄存器;
|
||||||
|
- `a` / `b` 表示源寄存器、立即数低高位或其他操作数。
|
||||||
|
|
||||||
|
主要操作码类别:
|
||||||
|
|
||||||
|
| 类别 | 示例 |
|
||||||
|
|------|------|
|
||||||
|
| 算术 | ADD、SUB、MUL、DIV、MOD |
|
||||||
|
| 位运算 | BIT_AND、BIT_OR、BIT_XOR、SHL、SHR |
|
||||||
|
| 比较 | EQ、STRICT_EQ、LT、GTE |
|
||||||
|
| 控制流 | JMP、JMP_IF_FALSE、SWITCH_TABLE |
|
||||||
|
| 异常 | THROW、TRY_BEGIN、TRY_END |
|
||||||
|
| 变量 | LOAD_VAR、STORE_VAR、LOAD_CONST |
|
||||||
|
| 函数 | CALL、RETURN、CALL_NATIVE |
|
||||||
|
| 对象 | NEW_OBJECT、GET_PROP、SET_PROP |
|
||||||
|
| 数组 | NEW_ARRAY、SET_ELEM |
|
||||||
|
| 成员更新 | MEMBER_INC、COMPOUND_MEMBER_ADD 等 |
|
||||||
|
| 结束 | HALT |
|
||||||
|
|
||||||
|
### 2.4 VM 层
|
||||||
|
|
||||||
|
VM 是字节码执行核心。每个 VM 是一个独立执行上下文。
|
||||||
|
|
||||||
|
```text
|
||||||
|
+------------------------------------------------------------------------------------+
|
||||||
|
| Vm |
|
||||||
|
+------------------------------------------------------------------------------------+
|
||||||
|
| registers[256] 固定寄存器文件 |
|
||||||
|
| pc 当前程序计数器 |
|
||||||
|
| bytecode 当前执行字节码 |
|
||||||
|
| constants 当前常量池 |
|
||||||
|
| frames 函数调用栈 |
|
||||||
|
| try_stack 异常处理栈 |
|
||||||
|
| exception_value 当前异常值 |
|
||||||
|
| pending_error_kind 当前错误类型 |
|
||||||
|
| for_in_iters for-in 迭代状态 |
|
||||||
|
| session_arena 短生命周期对象分配区 |
|
||||||
|
| session_gc 当前 VM 的 session GC 元数据 |
|
||||||
|
| kernel: Arc<Kernel> 指向共享 Kernel |
|
||||||
|
+------------------------------------------------------------------------------------+
|
||||||
|
```
|
||||||
|
|
||||||
|
VM 的执行循环大致如下:
|
||||||
|
|
||||||
|
```text
|
||||||
|
loop:
|
||||||
|
instr = bytecode[pc]
|
||||||
|
pc += 1
|
||||||
|
|
||||||
|
match opcode(instr):
|
||||||
|
LOAD_CONST => regs[rd] = constants[idx]
|
||||||
|
ADD => regs[rd] = add(regs[a], regs[b])
|
||||||
|
GET_PROP => object property lookup
|
||||||
|
SET_PROP => object property write
|
||||||
|
CALL => push frame and enter function
|
||||||
|
CALL_NATIVE => call Rust builtin function
|
||||||
|
RETURN => restore caller frame
|
||||||
|
THROW => unwind try stack
|
||||||
|
HALT => return regs[0]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.5 Kernel 层
|
||||||
|
|
||||||
|
Kernel 是单进程内的共享运行时核心。它不保存某一次执行请求的寄存器和调用栈,而是保存可跨请求复用的结构。
|
||||||
|
|
||||||
|
```text
|
||||||
|
+------------------------------------------------------------------------------------+
|
||||||
|
| OxideKernel |
|
||||||
|
+------------------------------------------------------------------------------------+
|
||||||
|
| KernelConfig |
|
||||||
|
| StringForge 全局字符串驻留池 |
|
||||||
|
| ShapeForge 全局 Shape / Hidden Class 表 |
|
||||||
|
| CodeForge 编译结果缓存 |
|
||||||
|
| PropForge 属性访问模板 / IC 相关缓存 |
|
||||||
|
| BuiltinWorld Object / Array / Function / String / Number 等内置对象结构 |
|
||||||
|
| Global object 全局对象及其基础属性 |
|
||||||
|
+------------------------------------------------------------------------------------+
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.5.1 单 Kernel 多 VM 的执行优势
|
||||||
|
|
||||||
|
| 问题 | 普通每 VM 独立 runtime | OxideJS 单 Kernel 多 VM |
|
||||||
|
|------|------------------------|--------------------------|
|
||||||
|
| 内置对象初始化 | 每个 VM 重复构造 | Kernel 中集中构造与复用 |
|
||||||
|
| 字符串驻留 | 每个 VM 各自保存 | StringForge 统一保存 |
|
||||||
|
| 对象 Shape | 每个 VM 重复生成 | ShapeForge 跨 VM 共享 |
|
||||||
|
| 编译结果 | 每次请求重新编译 | CodeForge 按结构复用 |
|
||||||
|
| 属性访问模板 | 每个 VM 冷启动 | PropForge 可共享访问模板 |
|
||||||
|
| 请求隔离 | 需要小心拆分 | VM 自带寄存器、栈、arena,天然隔离 |
|
||||||
|
|
||||||
|
#### 2.5.2 多 VM 执行示例
|
||||||
|
|
||||||
|
```text
|
||||||
|
Request A: "items.map(x => x.id)"
|
||||||
|
Request B: "users.map(u => u.name)"
|
||||||
|
Request C: "orders.map(o => o.price)"
|
||||||
|
|
||||||
|
+-------------------+
|
||||||
|
| OxideKernel |
|
||||||
|
|-------------------|
|
||||||
|
| CodeForge | 结构相似代码可命中编译缓存
|
||||||
|
| ShapeForge | 相似对象布局共享 Shape
|
||||||
|
| StringForge | id/name/price 等字符串驻留
|
||||||
|
+---------+---------+
|
||||||
|
|
|
||||||
|
+---------------+---------------+
|
||||||
|
| | |
|
||||||
|
v v v
|
||||||
|
VM #1 VM #2 VM #3
|
||||||
|
Request A Request B Request C
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.6 对象模型与属性访问
|
||||||
|
|
||||||
|
对象通过 Shape 描述属性布局。
|
||||||
|
|
||||||
|
```text
|
||||||
|
EMPTY_SHAPE
|
||||||
|
|
|
||||||
|
| add "x"
|
||||||
|
v
|
||||||
|
Shape #2: property="x", offset=0
|
||||||
|
|
|
||||||
|
| add "y"
|
||||||
|
v
|
||||||
|
Shape #3: property="y", offset=1
|
||||||
|
```
|
||||||
|
|
||||||
|
对象自身保存:
|
||||||
|
|
||||||
|
- 当前 Shape ID;
|
||||||
|
- 原型指针;
|
||||||
|
- 属性存储区;
|
||||||
|
- 函数 / 数组等标志位;
|
||||||
|
- native 函数指针或子模块索引。
|
||||||
|
|
||||||
|
属性访问流程:
|
||||||
|
|
||||||
|
```text
|
||||||
|
GET_PROP obj, key
|
||||||
|
|
|
||||||
|
| 1. 读取对象 shape_id
|
||||||
|
| 2. 查询属性 key 对应 offset
|
||||||
|
| 3. 命中 Shape / PropForge 缓存则直接取 slot
|
||||||
|
| 4. 未命中则沿原型链查找
|
||||||
|
v
|
||||||
|
返回属性值或 undefined
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.7 内置对象
|
||||||
|
|
||||||
|
内置对象由 Rust 原生实现,并通过 Kernel / BuiltinWorld 进行注册。
|
||||||
|
|
||||||
|
```text
|
||||||
|
crates/oxide_vm/src/builtins/
|
||||||
|
├── array.rs
|
||||||
|
├── array_buffer.rs
|
||||||
|
├── boolean.rs
|
||||||
|
├── data_view.rs
|
||||||
|
├── date.rs
|
||||||
|
├── error.rs
|
||||||
|
├── function.rs
|
||||||
|
├── global/
|
||||||
|
├── iterator.rs
|
||||||
|
├── json.rs
|
||||||
|
├── map.rs
|
||||||
|
├── math.rs
|
||||||
|
├── number.rs
|
||||||
|
├── object.rs
|
||||||
|
├── reflect.rs
|
||||||
|
├── regexp.rs
|
||||||
|
├── set.rs
|
||||||
|
├── string.rs
|
||||||
|
├── symbol.rs
|
||||||
|
└── typed_array.rs
|
||||||
|
```
|
||||||
|
|
||||||
|
绑定层位于:
|
||||||
|
|
||||||
|
```text
|
||||||
|
crates/oxide_vm/src/bindings/
|
||||||
|
```
|
||||||
|
|
||||||
|
其职责是将 Rust native 函数挂载到对应构造器、原型对象或全局对象上。
|
||||||
|
|
||||||
|
### 2.8 test262 Runner
|
||||||
|
|
||||||
|
`oxide_test262` 用于自动运行 ECMAScript Test Suite。
|
||||||
|
|
||||||
|
```text
|
||||||
|
+------------------------------------------------------------------------------------+
|
||||||
|
| oxide_test262 |
|
||||||
|
+------------------------------------------------------------------------------------+
|
||||||
|
| discover tests |
|
||||||
|
| parse YAML metadata |
|
||||||
|
| load harness includes |
|
||||||
|
| apply skip / feature policy |
|
||||||
|
| run parser -> compiler -> VM |
|
||||||
|
| catch panic / runtime error |
|
||||||
|
| classify pass / fail / skip |
|
||||||
|
| summarize totals and failure categories |
|
||||||
|
+------------------------------------------------------------------------------------+
|
||||||
|
```
|
||||||
|
|
||||||
|
runner 的输出可以用于:
|
||||||
|
|
||||||
|
- 统计当前兼容性;
|
||||||
|
- 找出失败最多的语义类别;
|
||||||
|
- 指导下一阶段实现;
|
||||||
|
- 对比 QuickJS、Boa、JerryScript 等 baseline。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、代码说明
|
||||||
|
|
||||||
|
### 3.1 顶层目录
|
||||||
|
|
||||||
|
```text
|
||||||
|
project-root/
|
||||||
|
├── Cargo.toml
|
||||||
|
├── Cargo.lock
|
||||||
|
├── crates/
|
||||||
|
├── tests/
|
||||||
|
├── docs/
|
||||||
|
├── README.md
|
||||||
|
└── 设计方案文档.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 Crate 说明
|
||||||
|
|
||||||
|
| Crate | 作用 |
|
||||||
|
|-------|------|
|
||||||
|
| `oxide_parser` | JavaScript parser 接入层,输出 AST Program |
|
||||||
|
| `oxide_compiler` | AST 到字节码的编译器 |
|
||||||
|
| `oxide_types` | JS runtime 基础类型,如 JsValue、JsObject、Shape、Error、Arena |
|
||||||
|
| `oxide_kernel` | 单 Kernel 多 VM 架构中的共享运行时核心 |
|
||||||
|
| `oxide_vm` | 字节码解释器、内置对象、VM pool、session arena / GC |
|
||||||
|
| `oxide_api` | 对外 API 预留层 |
|
||||||
|
| `oxide_cli` | 命令行工具,支持 eval / run / compile / REPL |
|
||||||
|
| `oxide_test262` | test262 自动化测试运行器 |
|
||||||
|
|
||||||
|
### 3.3 `oxide_types`
|
||||||
|
|
||||||
|
关键文件:
|
||||||
|
|
||||||
|
```text
|
||||||
|
crates/oxide_types/src/
|
||||||
|
├── value.rs # JsValue, NaN-boxing 值表示
|
||||||
|
├── object.rs # JsObject, 对象头、属性存储、函数/数组标记
|
||||||
|
├── shape.rs # Shape, ShapeId, 属性布局信息
|
||||||
|
├── mem.rs # P<T>, arena / persistent object 相关基础结构
|
||||||
|
├── error.rs # 内部错误类型
|
||||||
|
└── private_key.rs # class private field / private name 支持结构
|
||||||
|
```
|
||||||
|
|
||||||
|
该 crate 处于依赖图底层,尽量不依赖上层模块。
|
||||||
|
|
||||||
|
### 3.4 `oxide_kernel`
|
||||||
|
|
||||||
|
关键文件:
|
||||||
|
|
||||||
|
```text
|
||||||
|
crates/oxide_kernel/src/
|
||||||
|
├── kernel.rs # OxideKernel, KernelConfig, global object
|
||||||
|
├── string_forge.rs # 字符串驻留和索引
|
||||||
|
├── shape_forge.rs # Shape 创建、复用和查询
|
||||||
|
├── code_forge.rs # CompiledModule 缓存
|
||||||
|
├── prop_forge.rs # 属性访问模板缓存
|
||||||
|
├── builtin.rs # BuiltinWorld 与内置对象结构
|
||||||
|
└── logging.rs # 结构化日志支持
|
||||||
|
```
|
||||||
|
|
||||||
|
`oxide_kernel` 是单 Kernel 多 VM 的中心。它保存长期共享状态,而 VM 保存短期执行状态。
|
||||||
|
|
||||||
|
### 3.5 `oxide_compiler`
|
||||||
|
|
||||||
|
关键文件:
|
||||||
|
|
||||||
|
```text
|
||||||
|
crates/oxide_compiler/src/
|
||||||
|
├── compiler.rs # 编译入口与上下文
|
||||||
|
├── counter.rs # 第一遍 AST 遍历,计算寄存器和标签
|
||||||
|
├── emitter.rs # 第二遍 AST 遍历,生成字节码
|
||||||
|
├── opcode.rs # OpCode 和指令编码
|
||||||
|
├── module.rs # CompiledModule / Constant
|
||||||
|
├── hash.rs # structural hash
|
||||||
|
└── symbol_table.rs # 词法作用域和变量绑定
|
||||||
|
```
|
||||||
|
|
||||||
|
编译器输出 `CompiledModule`,交由 VM 执行或写入 CodeForge 缓存。
|
||||||
|
|
||||||
|
### 3.6 `oxide_vm`
|
||||||
|
|
||||||
|
关键文件与目录:
|
||||||
|
|
||||||
|
```text
|
||||||
|
crates/oxide_vm/src/
|
||||||
|
├── vm.rs # VM 主结构与执行入口
|
||||||
|
├── vm_runtime.rs # 运行时入口和状态恢复
|
||||||
|
├── vm_support.rs # VM 辅助逻辑
|
||||||
|
├── vm_props.rs # 属性访问辅助逻辑
|
||||||
|
├── vm_pool.rs # VM pool,多 VM 复用
|
||||||
|
├── session_arena.rs # 会话级 arena
|
||||||
|
├── session_gc.rs # 会话级 GC / 标记清扫辅助
|
||||||
|
├── coercion.rs # ToNumber / ToString / ToBoolean 等类型转换
|
||||||
|
├── native.rs # Native function 调用接口
|
||||||
|
├── dispatch/ # opcode 分发实现
|
||||||
|
├── builtins/ # 内置对象实现
|
||||||
|
└── bindings/ # 内置对象绑定到 BuiltinWorld / global object
|
||||||
|
```
|
||||||
|
|
||||||
|
VM 层是代码量最大的模块,包含:
|
||||||
|
|
||||||
|
- 字节码 dispatch;
|
||||||
|
- 函数调用;
|
||||||
|
- 异常处理;
|
||||||
|
- 原型链属性访问;
|
||||||
|
- 内置对象 native call;
|
||||||
|
- session arena 与 GC;
|
||||||
|
- VM pool。
|
||||||
|
|
||||||
|
### 3.7 `oxide_cli`
|
||||||
|
|
||||||
|
关键功能:
|
||||||
|
|
||||||
|
```text
|
||||||
|
cargo run --release -p oxide_cli -- eval "1 + 2"
|
||||||
|
cargo run --release -p oxide_cli -- run file.js
|
||||||
|
cargo run --release -p oxide_cli -- compile -e "1 + 2"
|
||||||
|
cargo run --release -p oxide_cli
|
||||||
|
```
|
||||||
|
|
||||||
|
CLI 主要用于:
|
||||||
|
|
||||||
|
- 手工运行 JS 片段;
|
||||||
|
- 打印编译后的字节码;
|
||||||
|
- 执行文件;
|
||||||
|
- 进行 smoke test。
|
||||||
|
|
||||||
|
### 3.8 `oxide_test262`
|
||||||
|
|
||||||
|
关键文件:
|
||||||
|
|
||||||
|
```text
|
||||||
|
crates/oxide_test262/src/main.rs
|
||||||
|
```
|
||||||
|
|
||||||
|
职责:
|
||||||
|
|
||||||
|
- 遍历 test262 测试目录;
|
||||||
|
- 解析 metadata;
|
||||||
|
- 注入 harness;
|
||||||
|
- 根据 feature / flag 进行跳过或执行;
|
||||||
|
- 捕获 panic;
|
||||||
|
- 输出 pass / fail / skip;
|
||||||
|
- 统计失败类别。
|
||||||
|
|
||||||
|
### 3.9 代码工作流总结
|
||||||
|
|
||||||
|
```text
|
||||||
|
Developer / CLI / test262
|
||||||
|
|
|
||||||
|
v
|
||||||
|
oxide_parser
|
||||||
|
|
|
||||||
|
v
|
||||||
|
oxide_compiler -----> OxideKernel.CodeForge
|
||||||
|
| |
|
||||||
|
v |
|
||||||
|
CompiledModule <---------------+
|
||||||
|
|
|
||||||
|
v
|
||||||
|
VmPool selects Vm
|
||||||
|
|
|
||||||
|
v
|
||||||
|
Vm executes bytecode -----> OxideKernel.StringForge / ShapeForge / PropForge / BuiltinWorld
|
||||||
|
|
|
||||||
|
v
|
||||||
|
JsValue / Error / TestResult
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.10 创新点到代码快速导航
|
||||||
|
|
||||||
|
| 创新点 | 代码位置 | 说明 |
|
||||||
|
|--------|----------|------|
|
||||||
|
| 单 Kernel 多 VM | `oxide_kernel::kernel`, `oxide_vm::vm_pool`, `oxide_vm::vm` | Kernel 共享,VM 隔离 |
|
||||||
|
| 共享字符串驻留 | `string_forge.rs` | 跨 VM 字符串复用 |
|
||||||
|
| 共享 Shape | `shape_forge.rs`, `shape.rs` | 跨 VM 对象布局复用 |
|
||||||
|
| 编译缓存 | `code_forge.rs`, `hash.rs` | structural hash -> CompiledModule |
|
||||||
|
| 属性访问缓存 | `prop_forge.rs`, `vm_props.rs`, `dispatch/property.rs` | Shape / offset 快速路径 |
|
||||||
|
| 会话内存与 GC | `session_arena.rs`, `session_gc.rs`, `vm.rs` | VM 本地短命对象管理 |
|
||||||
|
| NaN-boxing | `value.rs` | 64-bit 统一值表示 |
|
||||||
|
| 寄存器式 VM | `opcode.rs`, `vm.rs`, `dispatch/` | 固定寄存器执行模型 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[TODO] 研发过程遇到的问题和解决方法
|
||||||
|
|
||||||
|
[TODO] 各平台 Benchmark 与竞争产品对比
|
||||||
|
|
||||||
|
[TODO] AI 使用情况说明
|
||||||
Reference in New Issue
Block a user