From 439f50d187492a8584d7abd177fe62edacaf131c Mon Sep 17 00:00:00 2001 From: esrrhs Date: Mon, 14 Sep 2026 23:37:20 +0800 Subject: [PATCH] docs: refresh README for bytecode VM and native libraries Document JIT_INTERP alongside GCC/TCC, update the pipeline and native module overview, and expose --jit_type=2 in flua help. --- README.md | 56 +++++++++++++++++++++++++++++----------------------- README.zh.md | 56 +++++++++++++++++++++++++++++----------------------- cmd/main.cpp | 2 +- 3 files changed, 63 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 11f2b8d..b42a7f3 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [中文](README.zh.md) | English -FakeLua is an embeddable Lua-subset compilation engine: it compiles Lua scripts into C code and dynamically compiles them into native machine code via the GCC backend for execution. It provides a C++23 interface with high-performance interop between scripts and native code. +FakeLua is an embeddable Lua-subset runtime for high-performance hosts: it compiles scripts to a bytecode VM and optionally to native code via GCC/TCC JIT, ships a large C++ native standard library (net/http/db/crypto/…), and uses an arena allocator with frame reset so there is no GC pause. ## Design Philosophy & Memory Model @@ -28,18 +28,19 @@ This design allows FakeLua to fully eliminate GC pause impact on frame rates whi ## Core Features -### Dual JIT Backends +### Three Execution Backends -Supports two JIT modes with a seamless API switch: +The same `Call` API can target any registered backend: -- **JIT_GCC**: Invokes system GCC (`-O3`) to generate high-quality native code. This is the primary backend for production use. -- **JIT_TCC**: Embeds TinyCC for extremely fast compilation. Primarily used for development, debugging, and testing (TCC source is automatically fetched during CMake configuration — no system installation needed). +- **JIT_GCC**: Invokes system GCC (`-O3`) to generate high-quality native code. Primary backend for production. +- **JIT_TCC**: Embeds TinyCC for extremely fast compilation. Best for development, debugging, and tests (TCC is fetched automatically by CMake). +- **JIT_INTERP**: Compiles to FakeLua bytecode and runs on the built-in interpreter (`src/interp/`). No external C compiler required; useful for portability, tooling, and mixed JIT↔interp closures. ```cpp int ret = 0; -// Same Call API, switching between JIT_GCC and JIT_TCC on demand -Call(s, JIT_GCC, "add", ret, 10, 20); // Production: GCC backend (-O3 high performance) -Call(s, JIT_TCC, "add", ret, 10, 20); // Development: TCC backend (ultra-fast compilation) +Call(s, JIT_GCC, "add", ret, 10, 20); // Production: GCC (-O3) +Call(s, JIT_TCC, "add", ret, 10, 20); // Dev/test: TCC (fast compile) +Call(s, JIT_INTERP, "add", ret, 10, 20); // Bytecode VM (no host C compiler) ``` ### Numeric Specialization @@ -140,20 +141,20 @@ FL_SPEC(Table_Spec_1, point, x) = NativeAdd(FL_SPEC(Table_Spec_1, point, x), (CV ## Built-in Standard Libraries -FakeLua provides 29 independent C++ native modules under `src/native/`, covering math, string, table, IO, networking, timers, events, random, containers, compression, encryption, serialization, databases, protobuf, config formats, logging, and subprocesses. +FakeLua provides 30+ independent C++ native modules under `src/native/` (registered automatically on each `State`), covering math, string, table, IO, networking, timers, events, random, containers, compression, cryptography, serialization, databases, protobuf, config formats, logging, and subprocesses. > **Full API reference:** [src/native/README.md](src/native/README.md) / [中文](src/native/README.zh.md) | Category | Modules | |----------|---------| -| Core Lua | `math`, `table`, `string`, `os`, `utf8`, `io`, `random` | -| Networking | `net` (TCP/UDP server/client), `http` (Beast HTTP/1.1), `url`, `timer`, `event` | +| Core Lua | `basic`, `math`, `table`, `string`, `os`, `utf8`, `io`, `random` | +| Runtime / I/O | `runtime` (`runtime.tick()`), `net` (TCP/UDP), `http` (HTTP/1.1), `url`, `timer`, `event` | | Data | `json`, `csv`, `serialize`, `protobuf`, `container` (Boost.Container deque/vector/list/map/set) | | Config | `yaml`, `toml`, `xml`, `ini` | | Database | `mysql` (async + pool), `redis` (async), `sqlite` (synchronous) | -| Crypto | `compress` (LZ4/zlib/gzip/Zstd), `crypto` (MD5/SHA/AES/RC4/Blowfish/DES, UUID, CRC-32, xxHash) | +| Crypto / compress | `compress` (LZ4/zlib/gzip/Zstd), `crypto` (OpenSSL digests/ciphers, UUID, CRC-32, xxHash) | | Process | `process` (`process.run`; does not replace `os.execute`) | -| Logging | `log` (7 levels, tagged output, file rotation) | +| Logging | `log` (levels, tagged output, file rotation) | | Object | `object` (NativeObject Lua-side API) | **Regex note:** `string.find`/`match`/`gmatch`/`gsub` use **ECMAScript regex** (`boost::regex::ECMAScript`), not Lua patterns. See [Regex Guide](#regex-matching-ecmascript-syntax-not-lua-patterns) below for migration tips. @@ -230,13 +231,13 @@ ctest --test-dir build -V ### CLI Tool `flua` ```bash -./build/bin/flua --entry= --jit_type=<0|1> --repeat= +./build/bin/flua --entry= --jit_type=<0|1|2> --repeat= ``` - `--entry`: Entry function name (default `main`) -- `--jit_type`: `0`=TCC, `1`=GCC +- `--jit_type`: `0`=TCC, `1`=GCC, `2`=INTERP (bytecode VM) - `--repeat`: Repeat call count (for performance measurement) -- `--debug`: Enable debug mode (default `false`; when `true`, outputs generated C source) +- `--debug`: Enable debug mode (default `false`; when `true`, outputs generated C source / richer diagnostics) ## Performance Benchmarks @@ -333,11 +334,14 @@ Lua source ↓ [Type inference] → type hints (type_inferencer) ↓ -[C code generation] → C source (c_gen) - ↓ -[JIT compilation] → machine code (tcc_jit / gcc_jit) - ↓ -[Load & execute] → result + ┌─────────────────────────────┬──────────────────────────────┐ + ↓ ↓ ↓ +[C code generation] [Bytecode codegen] (shared AST) + (c_gen) (interp/codegen) + ↓ ↓ +[JIT TCC / GCC] [Interpreter VM] + native code (interp/interpreter) + └───────────── Call(s, JIT_*, …) ─────────────┘ ``` ### Key Components @@ -350,8 +354,10 @@ Lua source | `semantic_analysis` | Semantic and control flow analysis | | `type_inferencer` | Static type inference and specialization decisions | | `c_gen` | C code generation and type-driven optimization | +| `interp/*` | Bytecode codegen, opcodes, and interpreter VM | | `compile_common` | Common type inference and codegen utilities | -| `jit/*` | TCC and GCC backend integration | +| `jit/*` | TCC/GCC backends plus `Vm` function registry | +| `native/*` | Built-in standard libraries (net, http, db, crypto, …) | | `state` | FakeLua runtime state management | | `var` | Dynamic value CVar and conversion utilities | @@ -360,11 +366,11 @@ Lua source ### Q: Why choose a Lua subset over full Lua? A: Certain dynamic features of full Lua (e.g., metatables) are difficult to compile efficiently. The subset focuses on statically analyzable common patterns, achieving near-C performance through type inference and JIT compilation. -### Q: How to choose between TCC and GCC backends? -A: **GCC** is the primary backend for production (with `-O3` optimization); **TCC** compiles extremely fast, primarily for development and testing. +### Q: How to choose among TCC, GCC, and INTERP? +A: **GCC** is the primary production backend (`-O3`). **TCC** compiles extremely fast for development and CI. **INTERP** runs bytecode without a host C compiler — good for constrained environments, tooling, and validating script semantics; hot paths can still call JIT closures when mixed. ### Q: Can it be used in embedded or constrained environments? -A: Yes — the TCC backend is small and fast. The core library has minimal dependencies (C++ standard library only) and is cross-compilable. +A: Yes — use **JIT_INTERP** (no GCC/TCC required at runtime) or the small **TCC** backend. Native modules that need OpenSSL/MySQL/etc. are optional at the dependency level for your build. ### Q: How to debug generated C code? A: Enable `CompileConfig::debug_mode` to inspect logs and C code; use `GetLastRecordedCCode()` to export C code for analysis. diff --git a/README.zh.md b/README.zh.md index 48d1713..c992263 100644 --- a/README.zh.md +++ b/README.zh.md @@ -8,7 +8,7 @@ 中文 | [English](README.md) -FakeLua 是一个可嵌入的 Lua 子集编译引擎:将 Lua 脚本编译为 C 代码,通过 GCC 后端动态编译为原生机器码执行。提供 C++23 接口,支持脚本与原生代码高效互操作。 +FakeLua 是面向高性能宿主的可嵌入 Lua 子集运行时:脚本可编译为字节码由内置虚拟机执行,也可经 GCC/TCC JIT 生成原生机器码;并内置大量 C++ native 标准库(网络/HTTP/数据库/加密等),采用 Arena 内存池 + 帧重置,无 GC 停顿。 ## 设计初衷与内存设计哲学 @@ -28,18 +28,19 @@ FakeLua 的设计初衷是为了在**高性能游戏服务器**或类似的实 ## 核心特性 -### 双 JIT 后端 +### 三种执行后端 -支持两种 JIT 模式,同一套 API 无缝切换: +同一套 `Call` API 可切换任意已注册后端: -- **JIT_GCC**:调用系统 GCC(`-O3`),生成高质量原生代码。这是 FakeLua 实际运行和生产环境采用的主力后端。 -- **JIT_TCC**:内嵌 TinyCC,编译速度极快。主要用于开发调试和测试验证(TCC 源码在 CMake 配置阶段自动拉取,无需系统预装)。 +- **JIT_GCC**:调用系统 GCC(`-O3`)生成高质量原生代码,生产环境主力。 +- **JIT_TCC**:内嵌 TinyCC,编译极快,适合开发调试与测试(CMake 自动拉取 TCC,无需系统预装)。 +- **JIT_INTERP**:编译为 FakeLua 字节码,由内置解释器执行(`src/interp/`)。无需宿主 C 编译器,便于移植、工具链以及 JIT↔解释器混合闭包。 ```cpp int ret = 0; -// 同一套 Call API,可按需指定 JIT_GCC 或 JIT_TCC 后端 -Call(s, JIT_GCC, "add", ret, 10, 20); // 生产环境推荐:GCC 后端 (-O3 高性能) -Call(s, JIT_TCC, "add", ret, 10, 20); // 开发调试推荐:TCC 后端 (极速编译) +Call(s, JIT_GCC, "add", ret, 10, 20); // 生产:GCC (-O3) +Call(s, JIT_TCC, "add", ret, 10, 20); // 开发/测试:TCC(极速编译) +Call(s, JIT_INTERP, "add", ret, 10, 20); // 字节码虚拟机(无需宿主 C 编译器) ``` ### 数值参数特化(Numeric Specialization) @@ -140,20 +141,20 @@ FL_SPEC(Table_Spec_1, point, x) = NativeAdd(FL_SPEC(Table_Spec_1, point, x), (CV ## 标准内置扩展库 -FakeLua 在 `src/native/` 下提供 29 个独立 C++ 原生模块,覆盖数学、字符串、表、IO、网络、定时器、事件、随机数、容器、压缩、加密、序列化、数据库、Protobuf、配置解析、日志、子进程等领域。 +FakeLua 在 `src/native/` 下提供 30+ 个独立 C++ 原生模块(每个 `State` 创建时自动注册),覆盖数学、字符串、表、IO、网络、定时器、事件、随机数、容器、压缩、加密、序列化、数据库、Protobuf、配置解析、日志、子进程等领域。 > **完整 API 文档:** [src/native/README.zh.md](src/native/README.zh.md) / [English](src/native/README.md) | 分类 | 模块 | |------|------| -| 核心 Lua | `math`、`table`、`string`、`os`、`utf8`、`io`、`random` | -| 网络 | `net`(TCP/UDP 服务端/客户端)、`http`(Beast HTTP/1.1)、`url`、`timer`、`event` | +| 核心 Lua | `basic`、`math`、`table`、`string`、`os`、`utf8`、`io`、`random` | +| 运行时 / IO | `runtime`(`runtime.tick()`)、`net`(TCP/UDP)、`http`(HTTP/1.1)、`url`、`timer`、`event` | | 数据 | `json`、`csv`、`serialize`、`protobuf`、`container`(Boost.Container deque/vector/list/map/set) | | 配置解析 | `yaml`、`toml`、`xml`、`ini` | | 数据库 | `mysql`(异步 + 连接池)、`redis`(异步)、`sqlite`(同步) | -| 加解密 | `compress`(LZ4/zlib/gzip/Zstd)、`crypto`(MD5/SHA/AES/RC4/Blowfish/DES、UUID、CRC-32、xxHash) | +| 加解密 / 压缩 | `compress`(LZ4/zlib/gzip/Zstd)、`crypto`(OpenSSL 摘要/对称加密、UUID、CRC-32、xxHash) | | 进程 | `process`(`process.run`;不替换 `os.execute`) | -| 日志 | `log`(7 级别,分类标签输出,文件滚动) | +| 日志 | `log`(级别、分类标签输出、文件滚动) | | 对象 | `object`(NativeObject Lua 侧 API) | > ⚠️ `string.find`/`match`/`gmatch`/`gsub` 底层使用 **ECMAScript 正则**(`boost::regex::ECMAScript`),而非 Lua pattern。从标准 Lua 迁移时需改写模式串。 @@ -229,13 +230,13 @@ ctest --test-dir build -V ### 命令行工具 `flua` ```bash -./build/bin/flua --entry= --jit_type=<0|1> --repeat= +./build/bin/flua --entry= --jit_type=<0|1|2> --repeat= ``` - `--entry`:入口函数名(默认 `main`) -- `--jit_type`:`0`=TCC,`1`=GCC +- `--jit_type`:`0`=TCC,`1`=GCC,`2`=INTERP(字节码虚拟机) - `--repeat`:重复调用次数(用于性能测量) -- `--debug`:是否启用调试模式(默认 `false`,若为 `true` 则输出生成的 C 源码) +- `--debug`:是否启用调试模式(默认 `false`,若为 `true` 则输出生成的 C 源码 / 更详细诊断) ## 性能基准 @@ -332,11 +333,14 @@ Lua 源码 ↓ [类型推导] → type hints (type_inferencer) ↓ -[C 代码生成] → C 源码 (c_gen) - ↓ -[JIT 编译] → 机器码 (tcc_jit / gcc_jit) - ↓ -[加载执行] → 结果 + ┌─────────────────────────────┬──────────────────────────────┐ + ↓ ↓ ↓ +[C 代码生成] [字节码生成] (共享 AST) + (c_gen) (interp/codegen) + ↓ ↓ +[JIT TCC / GCC] [解释器虚拟机] + 原生机器码 (interp/interpreter) + └───────────── Call(s, JIT_*, …) ─────────────┘ ``` ### 关键组件 @@ -349,8 +353,10 @@ Lua 源码 | `semantic_analysis` | 语义和控制流分析 | | `type_inferencer` | 静态类型推导和 specialization 决策 | | `c_gen` | C 代码生成和类型驱动优化 | +| `interp/*` | 字节码生成、指令集与解释器虚拟机 | | `compile_common` | 公共类型推导和代码生成工具 | -| `jit/*` | TCC 和 GCC 后端集成 | +| `jit/*` | TCC/GCC 后端与 `Vm` 函数注册表 | +| `native/*` | 内置标准库(net、http、db、crypto 等) | | `state` | FakeLua 运行时状态管理 | | `var` | 动态值 CVar 和转换工具 | @@ -359,11 +365,11 @@ Lua 源码 ### Q: 为什么选择 Lua 子集而不是完整 Lua? A: 完整 Lua 的某些动态特性(如 metatable)很难高效编译。子集实现聚焦于可静态分析的常见模式,通过类型推导和 JIT 编译获得接近 C 的性能。 -### Q: TCC 和 GCC 后端如何选择? -A: **GCC** 是生产环境主力后端(`-O3` 生成高质量原生代码);**TCC** 编译极快,主要用于开发调试和测试。 +### Q: TCC、GCC 与 INTERP 如何选择? +A: **GCC** 是生产环境主力(`-O3`)。**TCC** 编译极快,适合开发与 CI。**INTERP** 跑字节码、无需宿主 C 编译器,适合受限环境、工具链与语义校验;热路径仍可与 JIT 闭包混合调用。 ### Q: 可以在嵌入式环境中使用吗? -A: 可以,TCC 后端体积小、编译速度快。核心库依赖极少(仅 C++ 标准库),可交叉编译。 +A: 可以——用 **JIT_INTERP**(运行时不依赖 GCC/TCC)或体积很小的 **TCC** 后端。OpenSSL/MySQL 等 native 依赖可按构建需求裁剪。 ### Q: 如何调试生成的 C 代码? A: 启用 `CompileConfig::debug_mode` 查看日志和 C 代码;使用 `GetLastRecordedCCode()` 导出 C 代码进行分析。 diff --git a/cmd/main.cpp b/cmd/main.cpp index 895fc9c..2159bec 100644 --- a/cmd/main.cpp +++ b/cmd/main.cpp @@ -8,7 +8,7 @@ using namespace fakelua; DEFINE_bool(debug, false, "enable debug mode"); DEFINE_string(entry, "main", "entry function name, entry must return code(int) and has no parameter"); DEFINE_int32(repeat, 1, "the repeat run main function times"); -DEFINE_int32(jit_type, 0, "jit type, 0 for tcc, 1 for gcc"); +DEFINE_int32(jit_type, 0, "jit type: 0=tcc, 1=gcc, 2=interp"); int main(int argc, char **argv) { gflags::SetUsageMessage("usage: ./flua --help\n"