stage0 新增内存复制指令 重构vm交互

This commit is contained in:
zzy committed 2026-09-29 21:11:15 +08:00
1 parent 0b8f649818
commit 40cffa9cb5
22 files changed
+626 -158

No files matched your search

+58 -33
View File
@@ -615,33 +615,51 @@ static spl_vm_val_t vm_timestamp(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
* nested-VM syscalls
* ================================================================= */
/* ---- 配置层的“外部函数处理器”:把某个 VM 未解析的 native 交给调用者 VM。
* 这是配置策略,不属于 VM 库 API;VM 本身只有通用 foreign 钩子。 ---- */
/* 通用双向桥(配置层策略,非 VM 平台 API):
* 在子 VM 上安装「未解析 native 处理器」,把子 VM 的未解析调用按名转发到
* 宿主(调用者)VM 中由 `entry` 指定的函数。宿主函数收到:
* (ctx, name_off, name_len, nested_vm, arg_base, nargs)
* 平台/C 侧**纯转发**:不复制实参、不限元数、不了解类型;聚合读写由宿主用
* vm_stack_get / vm_mem_read / vm_mem_alloc / vm_mem_write 自行完成。
* `entry` 由宿主显式给出,平台不预设任何函数名。 */
typedef struct {
spl_vm_t *caller;
spl_vm_t *host;
void *ctx;
} spl_foreign_t;
char entry[128];
} spl_bridge_t;
static spl_vm_val_t spl_foreign_reenter(spl_vm_t *vm, const spl_vm_call_t *call, void *user) {
spl_foreign_t *f = (spl_foreign_t *)user;
spl_vm_val_t tmp[20];
spl_vm_call_t c2;
int i;
(void)vm;
if (!f || !f->caller || !call || !call->name)
static spl_vm_val_t spl_bridge_forward(spl_vm_t *nested, const spl_vm_call_t *call, void *user) {
spl_bridge_t *b = (spl_bridge_t *)user;
spl_vm_val_t name_off;
spl_vm_val_t args[6];
spl_vm_call_t back;
usize n;
usize arg_base;
if (!b || !b->host || !call || !call->name || b->entry[0] == '\0')
return 0;
if (call->nargs + 1 > (usize)(sizeof(tmp) / sizeof(tmp[0])))
n = strlen(call->name);
/* 名拷进宿主 VM 内存,宿主按偏移读取。 */
name_off = spl_vm_mem_alloc(b->host, n + 1);
if (!name_off)
return 0;
tmp[0] = (spl_vm_val_t)(uintptr_t)f->ctx;
for (i = 0; i < (int)call->nargs; i++)
tmp[1 + i] = call->args ? call->args[i] : 0;
c2.name = call->name;
c2.args = tmp;
c2.nargs = call->nargs + 1;
c2.ret = 0;
if (spl_vm_invoke(f->caller, &c2) != 0)
if (spl_vm_mem_write(b->host, name_off, call->name, n + 1) != 0)
return 0;
return c2.ret;
arg_base = spl_vm_call_arg_base(nested, call);
if (arg_base == (usize)-1)
return 0;
args[0] = (spl_vm_val_t)(uintptr_t)b->ctx;
args[1] = name_off;
args[2] = (spl_vm_val_t)n;
args[3] = (spl_vm_val_t)(uintptr_t)nested;
args[4] = (spl_vm_val_t)arg_base;
args[5] = (spl_vm_val_t)call->nargs;
back.name = b->entry;
back.args = args;
back.nargs = 6;
back.ret = 0;
if (spl_vm_invoke(b->host, &back) != 0)
return 0;
return back.ret;
}
static spl_vm_val_t vm_new(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
@@ -655,25 +673,32 @@ static spl_vm_val_t vm_new(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
return (spl_vm_val_t)(uintptr_t)vm;
}
/* 配置入口:vm_set_foreign(vm, handler, ctx)。handler=0:把未解析 native 重入
* 当前调用者(_vm),ctx 透传前置。名与语义由配置层定义;VM 库不认识 foreign handler。 */
/* vm_set_foreign(vm, entry, ctx):宿主显式指定处理器函数名。 */
static spl_vm_val_t sc_vm_set_foreign(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
spl_vm_t *vm;
spl_foreign_t *f;
spl_bridge_t *b;
const spl_vm_val_t *entry;
const char *eptr;
usize elen;
CHECK_NARGS("vm_set_foreign", 3);
vm = (spl_vm_t *)(uintptr_t)args[0];
if (!vm || !_vm)
return -1;
if (args[1] != 0) /* 仅注册 handler 0(重入调用者) */
entry = (const spl_vm_val_t *)VM_XN(_vm, args[1], 2 * sizeof(spl_vm_val_t));
if (!entry)
return -1;
if (vm->foreign == spl_foreign_reenter && vm->foreign_ctx)
free(vm->foreign_ctx);
f = (spl_foreign_t *)malloc(sizeof(*f));
if (!f)
eptr = (const char *)VM_X(_vm, entry[0]);
elen = (usize)entry[1];
if (!eptr || elen == 0 || elen >= sizeof(((spl_bridge_t *)0)->entry))
return -1;
f->caller = _vm;
f->ctx = (void *)(uintptr_t)args[2];
spl_vm_set_foreign(vm, spl_foreign_reenter, f);
b = (spl_bridge_t *)malloc(sizeof(*b));
if (!b)
return -1;
b->host = _vm;
b->ctx = (void *)(uintptr_t)args[2];
memcpy(b->entry, eptr, elen);
b->entry[elen] = '\0';
spl_vm_set_foreign(vm, spl_bridge_forward, b);
return 0;
}
@@ -683,7 +708,7 @@ static spl_vm_val_t vm_drop(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
if (!vm)
return 0;
if (vm->foreign == spl_foreign_reenter && vm->foreign_ctx)
if (vm->foreign == spl_bridge_forward && vm->foreign_ctx)
free(vm->foreign_ctx);
if (vm->prog) {
spl_prog_drop(vm->prog);