fix mach vm suite errors
This commit is contained in:
@@ -1707,20 +1707,24 @@ static void mach_compile_stmt(MachCompState *cs, cJSON *stmt) {
|
||||
/* ---- Link pass: resolve GETNAME to GETINTRINSIC or GETENV ---- */
|
||||
|
||||
static void mach_link_code(JSContext *ctx, JSCodeRegister *code, JSValue env) {
|
||||
JSGCRef env_ref;
|
||||
JS_PushGCRef(ctx, &env_ref);
|
||||
env_ref.val = env;
|
||||
for (uint32_t i = 0; i < code->instr_count; i++) {
|
||||
MachInstr32 instr = code->instructions[i];
|
||||
if (MACH_GET_OP(instr) != MACH_GETNAME) continue;
|
||||
int a = MACH_GET_A(instr);
|
||||
int bx = MACH_GET_Bx(instr);
|
||||
int in_env = 0;
|
||||
if (!JS_IsNull(env) && (uint32_t)bx < code->cpool_count) {
|
||||
JSValue val = JS_GetProperty(ctx, env, code->cpool[bx]);
|
||||
if (!JS_IsNull(env_ref.val) && (uint32_t)bx < code->cpool_count) {
|
||||
JSValue val = JS_GetProperty(ctx, env_ref.val, code->cpool[bx]);
|
||||
in_env = !JS_IsNull(val) && !JS_IsException(val);
|
||||
}
|
||||
code->instructions[i] = MACH_ABx(in_env ? MACH_GETENV : MACH_GETINTRINSIC, a, bx);
|
||||
}
|
||||
for (uint32_t i = 0; i < code->func_count; i++)
|
||||
if (code->functions[i]) mach_link_code(ctx, code->functions[i], env);
|
||||
if (code->functions[i]) mach_link_code(ctx, code->functions[i], env_ref.val);
|
||||
JS_PopGCRef(ctx, &env_ref);
|
||||
}
|
||||
|
||||
/* ---- Top-level compiler ---- */
|
||||
@@ -1832,6 +1836,11 @@ void JS_FreeMachCode(MachCode *mc) {
|
||||
|
||||
/* Load a MachCode into a JSCodeRegister (materializes JSValues, needs ctx) */
|
||||
JSCodeRegister *JS_LoadMachCode(JSContext *ctx, MachCode *mc, JSValue env) {
|
||||
/* Protect env from GC — materialize/link calls can trigger collection */
|
||||
JSGCRef env_ref;
|
||||
JS_PushGCRef(ctx, &env_ref);
|
||||
env_ref.val = env;
|
||||
|
||||
JSCodeRegister *code = js_mallocz_rt(sizeof(JSCodeRegister));
|
||||
code->arity = mc->arity;
|
||||
code->nr_close_slots = mc->nr_close_slots;
|
||||
@@ -1849,7 +1858,7 @@ JSCodeRegister *JS_LoadMachCode(JSContext *ctx, MachCode *mc, JSValue env) {
|
||||
if (mc->func_count > 0) {
|
||||
code->functions = js_malloc_rt(mc->func_count * sizeof(JSCodeRegister *));
|
||||
for (uint32_t i = 0; i < mc->func_count; i++)
|
||||
code->functions[i] = JS_LoadMachCode(ctx, mc->functions[i], env);
|
||||
code->functions[i] = JS_LoadMachCode(ctx, mc->functions[i], env_ref.val);
|
||||
} else {
|
||||
code->functions = NULL;
|
||||
}
|
||||
@@ -1866,8 +1875,9 @@ JSCodeRegister *JS_LoadMachCode(JSContext *ctx, MachCode *mc, JSValue env) {
|
||||
code->disruption_pc = mc->disruption_pc;
|
||||
|
||||
/* Link: resolve GETNAME to GETENV/GETINTRINSIC */
|
||||
mach_link_code(ctx, code, env);
|
||||
mach_link_code(ctx, code, env_ref.val);
|
||||
|
||||
JS_PopGCRef(ctx, &env_ref);
|
||||
return code;
|
||||
}
|
||||
|
||||
@@ -2229,6 +2239,7 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
returning from a called register function can read code/env from frame */
|
||||
JSValue top_fn = js_new_register_function(ctx, code, env_gc.val, of_gc.val);
|
||||
JS_PopGCRef(ctx, &of_gc);
|
||||
env = env_gc.val; /* refresh — GC may have moved env during allocation */
|
||||
JS_PopGCRef(ctx, &env_gc);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
frame->function = top_fn;
|
||||
@@ -2499,9 +2510,11 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
}
|
||||
|
||||
case MACH_GETENV: {
|
||||
/* Read env fresh from frame->function — C local env can go stale after GC */
|
||||
int bx = MACH_GET_Bx(instr);
|
||||
JSValue key = code->cpool[bx];
|
||||
JSValue val = JS_GetProperty(ctx, env, key);
|
||||
JSValue cur_env = JS_VALUE_GET_FUNCTION(frame->function)->u.reg.env_record;
|
||||
JSValue val = JS_GetProperty(ctx, cur_env, key);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
frame->slots[a] = val;
|
||||
break;
|
||||
@@ -2512,8 +2525,9 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
int bx = MACH_GET_Bx(instr);
|
||||
JSValue key = code->cpool[bx];
|
||||
JSValue val = JS_NULL;
|
||||
if (!JS_IsNull(env)) {
|
||||
val = JS_GetProperty(ctx, env, key);
|
||||
JSValue cur_env = JS_VALUE_GET_FUNCTION(frame->function)->u.reg.env_record;
|
||||
if (!JS_IsNull(cur_env)) {
|
||||
val = JS_GetProperty(ctx, cur_env, key);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
}
|
||||
if (JS_IsNull(val) || JS_IsException(val)) {
|
||||
@@ -2661,8 +2675,9 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
JS_PushGCRef(ctx, &key_ref);
|
||||
key_ref.val = (c == 0xFF) ? frame->slots[base + 1] : code->cpool[c];
|
||||
|
||||
if (JS_IsFunction(frame->slots[base]) && JS_IsText(key_ref.val)) {
|
||||
/* Proxy call: obj(name, [args...]) */
|
||||
if (JS_IsFunction(frame->slots[base]) && JS_IsText(key_ref.val) &&
|
||||
JS_VALUE_GET_FUNCTION(frame->slots[base])->length == 2) {
|
||||
/* Proxy call (arity-2 functions only): obj(name, [args...]) */
|
||||
JSValue arr = JS_NewArray(ctx);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
if (JS_IsException(arr)) { JS_PopGCRef(ctx, &key_ref); goto disrupt; }
|
||||
@@ -2816,7 +2831,9 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
int bx = MACH_GET_Bx(instr);
|
||||
if ((uint32_t)bx < code->func_count) {
|
||||
JSCodeRegister *fn_code = code->functions[bx];
|
||||
JSValue fn_val = js_new_register_function(ctx, fn_code, env, frame_ref.val);
|
||||
/* Read env fresh from frame->function — C local can be stale */
|
||||
JSValue cur_env = JS_VALUE_GET_FUNCTION(frame->function)->u.reg.env_record;
|
||||
JSValue fn_val = js_new_register_function(ctx, fn_code, cur_env, frame_ref.val);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
frame->slots[a] = fn_val;
|
||||
} else {
|
||||
@@ -3251,8 +3268,14 @@ JSValue JS_RunMachTree(JSContext *ctx, cJSON *ast, JSValue env) {
|
||||
return JS_ThrowSyntaxError(ctx, "failed to compile AST to MACH bytecode");
|
||||
}
|
||||
|
||||
JSCodeRegister *code = JS_LoadMachCode(ctx, mc, env);
|
||||
JSValue result = JS_CallRegisterVM(ctx, code, ctx->global_obj, 0, NULL, env, JS_NULL);
|
||||
/* Protect env from GC — JS_LoadMachCode allocates on GC heap */
|
||||
JSGCRef env_ref;
|
||||
JS_PushGCRef(ctx, &env_ref);
|
||||
env_ref.val = env;
|
||||
|
||||
JSCodeRegister *code = JS_LoadMachCode(ctx, mc, env_ref.val);
|
||||
JSValue result = JS_CallRegisterVM(ctx, code, ctx->global_obj, 0, NULL, env_ref.val, JS_NULL);
|
||||
JS_PopGCRef(ctx, &env_ref);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user