stage0 重构vm使其依赖自己的地址空间不再共用宿主机 修改vm的ABI 修正相关nob构建问题

This commit is contained in:
zzy committed 2026-09-22 23:12:15 +08:00
1 parent fae017b52d
commit c0a86ea552
14 files changed
+2149 -1572

No files matched your search

+404 -28
View File
@@ -568,6 +568,18 @@ void spl_vm_init_ex(spl_vm_t *vm, int stack_size, int call_depth) {
vec_realloc(vm->frames, (usize)vm->config.max_call_depth);
vec_init(vm->breakpoints);
vec_init(vm->fn_breakpoints);
vec_init(vm->gdata_off);
vec_init(vm->regions);
/* regions[0] 保留;regions[1] = 栈区。 */
vec_push(vm->regions, ((spl_vm_region_t){NULL, 0, 0}));
vec_push(vm->regions, ((spl_vm_region_t){
(unsigned char *)vm->stacks.data,
(usize)vm->config.max_stack_depth * sizeof(spl_vm_val_t), 1}));
vm->stdio_off[0] = vm->stdio_off[1] = vm->stdio_off[2] = 0;
vm->ret_val = 0;
vm->foreign = NULL;
vm->foreign_ctx = NULL;
vm->sp = vm->fp = vm->ip = vm->cp = vm->gp = 0;
vm->steps = 0;
@@ -593,9 +605,206 @@ void spl_vm_drop(spl_vm_t *vm) {
free(vm->fn_breakpoints.data[i]);
vec_free(vm->fn_breakpoints);
vec_free(vm->breakpoints);
vec_free(vm->gdata_off);
for (usize i = 2; i < vec_size(vm->regions); i++) {
spl_vm_region_t *r = &vec_at(vm->regions, i);
if (r->used && r->base)
free(r->base);
}
vec_free(vm->regions);
spl_vm_profile_free(vm);
}
/* ================================================================
* 统一偏移地址空间:offset = (handle<<32) | 区内字节偏移
* ================================================================ */
#define SPL_ASP_HANDLE_OF(off) ((usize)((spl_vm_val_t)(off) >> 32))
#define SPL_ASP_BYTE_OF(off) ((usize)((spl_vm_val_t)(off) & 0xFFFFFFFFull))
static spl_vm_region_t *spl_vm_region_at(spl_vm_t *vm, usize handle) {
if (handle == 0 || handle >= vec_size(vm->regions))
return NULL;
return &vec_at(vm->regions, handle);
}
void *spl_vm_xlate(spl_vm_t *vm, spl_vm_val_t off, usize size) {
usize handle, byte;
spl_vm_region_t *r;
if (!vm || off == SPL_OFF_NULL)
return NULL;
handle = SPL_ASP_HANDLE_OF(off);
byte = SPL_ASP_BYTE_OF(off);
r = spl_vm_region_at(vm, handle);
if (!r || !r->used)
return NULL;
if (byte > r->size || (size > 0 && byte + size > r->size))
return NULL;
return (void *)(r->base + byte);
}
spl_vm_val_t spl_vm_to_off(spl_vm_t *vm, const void *ptr) {
if (!vm || !ptr)
return SPL_OFF_NULL;
{
unsigned char *p = (unsigned char *)ptr;
usize i;
for (i = 1; i < vec_size(vm->regions); i++) {
spl_vm_region_t *r = &vec_at(vm->regions, i);
if (r->used && r->base && p >= r->base && p < r->base + r->size)
return SPL_ASP_OFF(i, (usize)(p - r->base));
}
}
return SPL_OFF_NULL;
}
/* 返回用于存放该偏移的 handle 槽;找不到空闲/空间不足返回 0。 */
static usize spl_vm_region_new(spl_vm_t *vm, void *base, usize size) {
usize i;
for (i = 2; i < vec_size(vm->regions); i++) {
spl_vm_region_t *r = &vec_at(vm->regions, i);
if (!r->used) {
r->base = (unsigned char *)base;
r->size = size;
r->used = 1;
return i;
}
}
if (vec_size(vm->regions) >= (usize)1 << 32)
return 0;
vec_push(vm->regions, ((spl_vm_region_t){(unsigned char *)base, size, 1}));
return vec_size(vm->regions) - 1;
}
/* ---- spl_asp_t 实现 ---- */
static unsigned char *spl_vm_asp_xlate(void *ctx, uintptr_t off, uintptr_t size) {
return (unsigned char *)spl_vm_xlate((spl_vm_t *)ctx, (spl_vm_val_t)off, (usize)size);
}
static uintptr_t spl_vm_asp_alloc(void *ctx, uintptr_t size) {
spl_vm_t *vm = (spl_vm_t *)ctx;
void *p;
usize h;
if (size == 0 || size > 0xFFFFFFFFull)
return 0;
p = malloc((size_t)size);
if (!p)
return 0;
h = spl_vm_region_new(vm, p, (usize)size);
if (h == 0) {
free(p);
return 0;
}
return (uintptr_t)SPL_ASP_OFF(h, 0);
}
static uintptr_t spl_vm_asp_realloc(void *ctx, uintptr_t off, uintptr_t size) {
spl_vm_t *vm = (spl_vm_t *)ctx;
spl_vm_region_t *r;
void *np;
usize h;
if (size == 0 || size > 0xFFFFFFFFull)
return 0;
if (off == 0)
return spl_vm_asp_alloc(ctx, size);
h = SPL_ASP_HANDLE_OF(off);
r = spl_vm_region_at(vm, h);
if (!r || !r->used)
return 0;
np = realloc(r->base, (size_t)size);
if (!np)
return 0;
r->base = (unsigned char *)np;
r->size = (usize)size;
return (uintptr_t)SPL_ASP_OFF(h, SPL_ASP_BYTE_OF(off) & 0);
}
static void spl_vm_asp_free(void *ctx, uintptr_t off) {
spl_vm_t *vm = (spl_vm_t *)ctx;
usize h;
spl_vm_region_t *r;
if (off == 0 || !vm)
return;
h = SPL_ASP_HANDLE_OF(off);
if (h < 2) /* 0/1 不可释放 */
return;
r = spl_vm_region_at(vm, h);
if (!r || !r->used)
return;
free(r->base);
r->base = NULL;
r->size = 0;
r->used = 0;
}
static uintptr_t spl_vm_asp_to_off(void *ctx, const void *host, uintptr_t size) {
(void)size;
return (uintptr_t)spl_vm_to_off((spl_vm_t *)ctx, host);
}
spl_asp_t *spl_vm_asp(spl_vm_t *vm) {
if (!vm)
return NULL;
vm->asp.ctx = vm;
vm->asp.xlate = spl_vm_asp_xlate;
vm->asp.alloc = spl_vm_asp_alloc;
vm->asp.realloc = spl_vm_asp_realloc;
vm->asp.free = spl_vm_asp_free;
vm->asp.to_off = spl_vm_asp_to_off;
return &vm->asp;
}
/* ================================================================
* 动态外部回调 + 栈/结果/内存访问
* ================================================================ */
void spl_vm_set_foreign(spl_vm_t *vm, spl_vm_foreign_fn fn, void *ctx) {
if (!vm)
return;
vm->foreign = fn;
vm->foreign_ctx = ctx;
}
spl_vm_val_t spl_vm_ret_val(spl_vm_t *vm) { return vm ? vm->ret_val : 0; }
usize spl_vm_sp(spl_vm_t *vm) { return vm ? (usize)vm->sp : 0; }
usize spl_vm_fp(spl_vm_t *vm) { return vm ? (usize)vm->fp : 0; }
spl_vm_val_t spl_vm_stack_get(spl_vm_t *vm, usize index) {
if (!vm || index >= (usize)vm->config.max_stack_depth || !vm->stacks.data)
return 0;
return vm->stacks.data[index];
}
int spl_vm_stack_set(spl_vm_t *vm, usize index, spl_vm_val_t val) {
if (!vm || index >= (usize)vm->config.max_stack_depth || !vm->stacks.data)
return -1;
vm->stacks.data[index] = val;
return 0;
}
spl_vm_val_t spl_vm_mem_alloc(spl_vm_t *vm, usize size) { return spl_vm_asp_alloc(vm, size); }
int spl_vm_mem_read(spl_vm_t *vm, spl_vm_val_t off, void *dst, usize n) {
void *src = spl_vm_xlate(vm, off, n);
if ((!src || !dst) && n)
return -1;
if (n)
memcpy(dst, src, n);
return 0;
}
int spl_vm_mem_write(spl_vm_t *vm, spl_vm_val_t off, const void *src, usize n) {
void *dst = spl_vm_xlate(vm, off, n);
if ((!dst || !src) && n)
return -1;
if (n)
memcpy(dst, src, n);
return 0;
}
// FIXME
int spl_vm_addr_valid(uintptr_t p, usize size) {
if (p == 0)
@@ -685,6 +894,35 @@ int spl_vm_load_prog(spl_vm_t *vm, spl_prog_t *prog) {
if (!vm || !prog)
return -1;
vm->prog = prog;
/* 释放上一次加载的堆分配(保留 regions[0]/[1])。 */
for (usize i = 2; i < vec_size(vm->regions); i++) {
spl_vm_region_t *r = &vec_at(vm->regions, i);
if (r->used && r->base)
free(r->base);
r->base = NULL;
r->size = 0;
r->used = 0;
}
/* 把 prog 的常量段搬进本 VM 空间,并记录每个 gdata 的偏移;
* gdata 索引 0 为哨兵,偏移 0(null)。 */
vm->gdata_off.size = 0;
vec_push(vm->gdata_off, (usize)SPL_OFF_NULL);
for (usize i = 1; i < vec_size(prog->gdata); i++) {
spl_vm_gdata_t *gd = &vec_at(prog->gdata, i);
usize sz = gd->size ? gd->size : 1;
spl_vm_val_t off = spl_vm_asp_alloc(vm, sz);
unsigned char *dst;
if (off == SPL_OFF_NULL)
return -1;
dst = (unsigned char *)spl_vm_xlate(vm, off, sz);
if (!dst)
return -1;
if (gd->data && gd->size)
memcpy(dst, gd->data, gd->size);
vec_push(vm->gdata_off, (usize)off);
}
return 0;
}
@@ -707,21 +945,53 @@ void spl_vm_set_debug(spl_vm_t *vm, int enabled) {
#define STACK_CANARY(vm) (vm)->stacks.data[(vm)->fp - 1]
/* 把 C 字符串复制进 VM 空间,返回其偏移。 */
static spl_vm_val_t spl_vm_marshal_cstr(spl_vm_t *vm, const char *s) {
usize n = s ? strlen(s) + 1 : 1;
spl_vm_val_t off = spl_vm_asp_alloc(vm, n);
unsigned char *d;
if (off == 0)
return 0;
d = (unsigned char *)spl_vm_xlate(vm, off, n);
if (!d)
return 0;
if (s)
memcpy(d, s, n);
else
d[0] = 0;
return off;
}
/* 把 argv/envp 指针数组整体编组进 VM 空间,返回数组偏移。 */
static spl_vm_val_t spl_vm_marshal_argv(spl_vm_t *vm, int argc, const char **argv) {
usize bytes = (usize)(argc + 1) * sizeof(spl_vm_val_t);
spl_vm_val_t arr = spl_vm_asp_alloc(vm, bytes);
spl_vm_val_t *slots;
int i;
if (arr == 0)
return 0;
slots = (spl_vm_val_t *)spl_vm_xlate(vm, arr, bytes);
if (!slots)
return 0;
for (i = 0; i < argc; i++)
slots[i] = spl_vm_marshal_cstr(vm, argv ? argv[i] : NULL);
slots[argc] = 0;
return arr;
}
/* ABI:调用者在实参下方预留 2 个空闲 slot(PAD0/PAD1)。
* fp 指向 arg0;fp-1 为栈金丝雀槽,fp-2 为空闲槽。
* saved_sp = fp-2(调用者压参数前的 sp)。 */
#define SPL_CALL_PADS 2
static inline int spl_vm_call(spl_vm_t *vm, spl_vm_val_t addr, spl_vm_val_t nargs) {
uintptr_t saved_sp;
if (vm->cp >= vm->config.max_call_depth)
VM_ERROR("call depth exceeded");
if (vm->sp < nargs + SPL_CALL_PADS)
VM_ERROR("call: stack underflow (missing pads)");
uintptr_t saved_sp;
if (vm->debug) {
/* debug:在 fp-1 留金丝雀位,需要把实参右移一格。 */
PUSH(SPL_STACK_CANARY);
for (usize i = vm->sp; i >= vm->sp - nargs; --i)
vm->stacks.data[i] = vm->stacks.data[i - 1];
saved_sp = vm->sp - nargs - 1;
} else {
/* 非 debug:不做金丝雀搬移;实参在 sp-nargs..sp-1,fp 指向 arg0。 */
saved_sp = vm->sp - nargs;
}
saved_sp = vm->sp - nargs - SPL_CALL_PADS;
spl_callframe_t *fr = &vm->frames.data[vm->cp];
fr->saved_sp = saved_sp;
@@ -736,6 +1006,33 @@ static inline int spl_vm_call(spl_vm_t *vm, spl_vm_val_t addr, spl_vm_val_t narg
return 0;
}
/* 入口调用:按名字调用顶层函数(同 CALL 的 ABI,实参+2 pads 已由调用方压好)。 */
int spl_vm_call_entry(spl_vm_t *vm, const char *name, int nargs) {
spl_vm_func_t *func;
if (!vm || !vm->prog || !name)
return -1;
func = spl_prog_get_func(vm->prog, name);
if (!func)
return -1;
if (vm->cp >= vm->config.max_call_depth)
return -1;
if (vm->sp < (usize)nargs + SPL_CALL_PADS)
return -1;
vm->ip = (usize)-1;
vm->cp = 0;
vm->fp = 0;
vm->frames.data[0].saved_sp = vm->sp - (usize)nargs - SPL_CALL_PADS;
vm->frames.data[0].saved_fp = vm->fp;
vm->frames.data[0].saved_ip = vm->ip;
vm->frames.data[0].nargs = (spl_vm_val_t)nargs;
vm->cp = 1;
vm->ip = (usize)func->address;
vm->fp = vm->sp - (usize)nargs;
if (vm->debug && vm->fp > 0)
STACK_CANARY(vm) = SPL_STACK_CANARY;
return 0;
}
int spl_vm_prepare(spl_vm_t *vm, const char *entry, int argc, const char **argv,
const char **envp) {
if (!vm || !vm->prog) {
@@ -757,15 +1054,22 @@ int spl_vm_prepare(spl_vm_t *vm, const char *entry, int argc, const char **argv,
vm->cp = 0;
vm->ip = -1;
vm->exit_code = 0;
vm->ret_val = 0;
/* ABI:入口也在实参下方预留 2 个空闲 slot。 */
PUSH(0);
PUSH(0);
if (fn->nargs >= 1) {
PUSH(argc);
}
if (fn->nargs >= 2) {
PUSH(argv);
PUSH(spl_vm_marshal_argv(vm, argc, argv));
}
if (fn->nargs >= 3) {
PUSH(envp);
int envc = 0;
while (envp && envp[envc])
envc++;
PUSH(spl_vm_marshal_argv(vm, envc, envp));
}
if (fn->nargs >= 4) {
printf("the start symbol can't using more than 3 args");
@@ -777,6 +1081,53 @@ int spl_vm_prepare(spl_vm_t *vm, const char *entry, int argc, const char **argv,
return 0;
}
/* 外部 -> VM 的调用:保存外层状态,按当前深度建帧跑到边界,读结果后恢复。
* 可在 VM 运行中(如外部回调内)安全调用。 */
int spl_vm_invoke(spl_vm_t *vm, spl_vm_call_t *call) {
spl_vm_func_t *fn;
uintptr_t s_ip, s_fp, s_sp, s_cp;
int s_exit, i, r;
spl_vm_val_t s_ret;
if (!vm || !vm->prog || !call || !call->name)
return -1;
fn = spl_prog_get_func(vm->prog, call->name);
if (!fn)
return -1;
s_ip = vm->ip;
s_fp = vm->fp;
s_sp = vm->sp;
s_cp = vm->cp;
s_exit = vm->exit_code;
s_ret = vm->ret_val;
PUSH(0);
PUSH(0);
for (i = 0; i < (int)call->nargs; i++)
PUSH(call->args ? call->args[i] : 0);
/* sentinel:本次调用的 RET 视为边界(与入口调用一致)。 */
vm->ip = (spl_vm_val_t)-1;
if (spl_vm_call(vm, fn->address, (spl_vm_val_t)call->nargs) != 0) {
vm->ip = s_ip;
vm->fp = s_fp;
vm->sp = s_sp;
vm->cp = s_cp;
vm->exit_code = s_exit;
vm->ret_val = s_ret;
return -1;
}
r = spl_vm_run_until(vm, 0);
call->ret = vm->ret_val;
vm->ip = s_ip;
vm->fp = s_fp;
vm->sp = s_sp;
vm->cp = s_cp;
vm->exit_code = s_exit;
vm->ret_val = s_ret;
return r < 0 ? -1 : 0;
}
/* ================================================================
* spl_vm_run_once - execute one instruction
*
@@ -817,7 +1168,7 @@ static uint64_t prof_now_ns(void) {
}
static void spl_vm_sample(spl_vm_t *vm) {
spl_prof_t *p = (spl_prof_t *)vm->profile;
spl_prof_t *p = vm->profile;
spl_prog_t *prog = vm->prog;
if (!p || !prog)
return;
@@ -862,7 +1213,7 @@ static void spl_vm_sample(spl_vm_t *vm) {
usize old = 0;
if (map_get(p->stacks, buf, &old)) {
map_put(p->stacks, buf, old + 1);
map_put(p->stacks, strdup(buf), old + 1);
} else {
map_put(p->stacks, strdup(buf), (usize)1);
}
@@ -1250,6 +1601,8 @@ L_SPL_RET:
intptr_t _saved_ip = vm->frames.data[vm->cp].saved_ip;
/* entry return -> halt */
if (_saved_ip < 0) {
PUSH(_retval);
vm->ret_val = _retval;
vm->exit_code = (int)_retval;
return 1;
}
@@ -1263,6 +1616,7 @@ L_SPL_RET:
}
L_SPL_HALT:
vm->ret_val = ins->imm;
if (ins->imm)
vm->exit_code = (int)ins->imm;
return 1;
@@ -1281,7 +1635,8 @@ L_SPL_ALLOC:
}
L_SPL_LADDR:
PUSH((spl_vm_val_t)((char *)(vm->stacks.data + vm->fp) + ins->imm));
PUSH(SPL_ASP_OFF(SPL_ASP_HANDLE_STACK,
(spl_vm_val_t)vm->fp * sizeof(spl_vm_val_t) + ins->imm));
DISPATCH();
L_SPL_GADDR:
@@ -1289,20 +1644,22 @@ L_SPL_GADDR:
spl_vm_val_t _idx = ins->imm;
if (_idx == 0 || _idx >= vec_size(prog->gdata))
VM_ERROR("GADDR: global data index out of range");
spl_vm_gdata_t *gd = &vec_at(prog->gdata, _idx);
if (!gd->data)
VM_ERROR("GADDR: null gdata entry");
PUSH((spl_vm_val_t)(uintptr_t)gd->data);
if (_idx >= vec_size(vm->gdata_off))
VM_ERROR("GADDR: global data not mapped");
PUSH((spl_vm_val_t)vec_at(vm->gdata_off, _idx));
DISPATCH();
}
/* ========== Indirect Memory (load/store with types) ========== */
L_SPL_LOAD:
{
void *_addr = (void *)POP();
CHECK_ADDR(_addr, "LOAD");
spl_vm_val_t _off = POP();
void *_addr;
spl_vm_val_t _v = 0;
usize _sz = spl_type_size(ins->type);
_addr = spl_vm_xlate(vm, _off, _sz);
if (!_addr)
VM_ERROR("LOAD: invalid address");
memcpy(&_v, _addr, _sz);
/* Sign-extend signed integer types smaller than 64 bits */
if (_sz > 0 && _sz < sizeof(spl_vm_val_t) && spl_is_signed(ins->type)) {
@@ -1315,8 +1672,13 @@ L_SPL_LOAD:
L_SPL_STORE:
{
spl_vm_val_t _v = POP();
void *_addr = (void *)POP();
CHECK_ADDR(_addr, "STORE");
spl_vm_val_t _off = POP();
void *_addr = spl_vm_xlate(vm, _off, spl_type_size(ins->type));
if (!_addr) {
fprintf(stderr, "vm: STORE bad off=%zu sz=%d\n", (size_t)_off, (int)spl_type_size(ins->type));
spl_vm_backtrace(vm, vm->fp);
VM_ERROR("STORE: invalid address");
}
memcpy(_addr, &_v, spl_type_size(ins->type));
DISPATCH();
}
@@ -1374,13 +1736,23 @@ L_SPL_NCALL:
if (_nat_idx >= vec_size(prog->natives))
VM_ERROR("NCALL: native index out of range");
_nat = &vec_at(prog->natives, _nat_idx);
if (!_nat->impl_fn) {
spl_vm_val_t *_arg_base = vm->stacks.data + vm->sp - _nargs;
spl_vm_val_t _result;
if (_nat->impl_fn) {
_result = _nat->impl_fn(vm, _nargs, _arg_base);
} else if (vm->foreign) {
/* 线 1 动态:交给按名的外部函数处理器。 */
spl_vm_call_t _call;
_call.name = _nat->name ? _nat->name : "";
_call.args = _arg_base;
_call.nargs = (usize)_nargs;
_call.ret = 0;
_result = vm->foreign(vm, &_call, vm->foreign_ctx);
} else {
snprintf(vm->error_msg, sizeof(vm->error_msg),
"NCALL: NULL native function pointer expect %s", _nat->name);
VM_ERROR(vm->error_msg);
}
spl_vm_val_t *_arg_base = vm->stacks.data + vm->sp - _nargs;
spl_vm_val_t _result = _nat->impl_fn(vm, _nargs, _arg_base);
if (vm->exit_code) {
snprintf(vm->error_msg, sizeof(vm->error_msg), "NCALL %s failed (ip=%zd)",
_nat->name ? _nat->name : "?", vm->ip - 1);
@@ -1442,7 +1814,11 @@ L_default:
return -1;
}
int spl_vm_run_once(spl_vm_t *vm) { return vm_loop(vm, 1); }
int spl_vm_run_once(spl_vm_t *vm) {
if (!vm)
return -1;
return vm_loop(vm, 1);
}
int spl_vm_run_until(spl_vm_t *vm, size_t step) {
if (!vm)