aot compile vm_suite

This commit is contained in:
2026-02-17 03:33:21 -06:00
parent c9dad91ea1
commit 9e42a28d55
7 changed files with 684 additions and 52 deletions

View File

@@ -2084,6 +2084,7 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
env = fn->u.reg.env_record;
pc = code->disruption_pc;
ctx->disruption_reported = FALSE;
ctx->current_exception = JS_NULL;
break;
}
if (JS_IsNull(frame->caller)) {
@@ -2123,7 +2124,7 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
}
ctx->disruption_reported = TRUE;
}
result = JS_Throw(ctx, JS_NULL);
result = JS_Throw(ctx, JS_TRUE);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
goto done;
}

View File

@@ -282,12 +282,25 @@ void cell_rt_set_native_env(JSContext *ctx, JSValue env) {
}
JSValue cell_rt_get_intrinsic(JSContext *ctx, const char *name) {
/* Check native env first (runtime-provided functions like starts_with) */
/* Check native env first (runtime-provided functions like log) */
if (g_has_native_env) {
JSValue v = JS_GetPropertyStr(ctx, g_native_env_ref.val, name);
if (!JS_IsNull(v)) return v;
if (!JS_IsNull(v))
return v;
}
return JS_GetPropertyStr(ctx, ctx->global_obj, name);
/* Linear scan of global object — avoids hash mismatch issues with
stoned records whose keys may be in cold storage */
JSValue gobj = ctx->global_obj;
if (JS_IsRecord(gobj)) {
JSRecord *rec = (JSRecord *)chase(gobj);
uint64_t mask = objhdr_cap56(rec->mist_hdr);
for (uint64_t i = 1; i <= mask; i++) {
if (js_key_equal_str(rec->slots[i].key, name))
return rec->slots[i].val;
}
}
JS_ThrowReferenceError(ctx, "'%s' is not defined", name);
return JS_EXCEPTION;
}
/* --- Closure access ---
@@ -349,8 +362,36 @@ JSValue *cell_rt_enter_frame(JSContext *ctx, int64_t nr_slots) {
JSValue *cell_rt_refresh_fp(JSContext *ctx) {
(void)ctx;
JSFrameRegister *frame = (JSFrameRegister *)JS_VALUE_GET_PTR(
g_aot_gc_refs[g_aot_depth - 1].val);
if (g_aot_depth <= 0) {
fprintf(stderr, "[BUG] cell_rt_refresh_fp: g_aot_depth=%d\n", g_aot_depth);
abort();
}
JSValue val = g_aot_gc_refs[g_aot_depth - 1].val;
JSFrameRegister *frame = (JSFrameRegister *)JS_VALUE_GET_PTR(val);
if (!frame) {
fprintf(stderr, "[BUG] cell_rt_refresh_fp: frame is NULL at depth=%d val=%lld\n",
g_aot_depth, (long long)val);
abort();
}
return (JSValue *)frame->slots;
}
/* Combined refresh + exception check in a single call.
Returns the refreshed fp, or NULL if there is a pending exception.
This avoids QBE register-allocation issues from two consecutive calls. */
JSValue *cell_rt_refresh_fp_checked(JSContext *ctx) {
if (JS_HasException(ctx))
return NULL;
if (g_aot_depth <= 0) {
fprintf(stderr, "[BUG] cell_rt_refresh_fp_checked: g_aot_depth=%d\n", g_aot_depth);
abort();
}
JSValue val = g_aot_gc_refs[g_aot_depth - 1].val;
JSFrameRegister *frame = (JSFrameRegister *)JS_VALUE_GET_PTR(val);
if (!frame) {
fprintf(stderr, "[BUG] cell_rt_refresh_fp_checked: frame is NULL\n");
abort();
}
return (JSValue *)frame->slots;
}
@@ -464,12 +505,13 @@ JSValue cell_rt_frame(JSContext *ctx, JSValue fn, int64_t nargs) {
}
void cell_rt_setarg(JSValue frame_val, int64_t idx, JSValue val) {
if (frame_val == JS_EXCEPTION) return;
if (frame_val == JS_EXCEPTION || frame_val == JS_NULL) return;
JSFrameRegister *fr = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_val);
fr->slots[idx] = val;
}
JSValue cell_rt_invoke(JSContext *ctx, JSValue frame_val) {
if (frame_val == JS_EXCEPTION) return JS_EXCEPTION;
JSFrameRegister *fr = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_val);
int nr_slots = (int)objhdr_cap56(fr->header);
int c_argc = (nr_slots >= 2) ? nr_slots - 2 : 0;
@@ -580,6 +622,15 @@ JSValue cell_rt_or(JSContext *ctx, JSValue left, JSValue right) {
return JS_ToBool(ctx, left) ? left : right;
}
/* --- Exception checking ---
After potentially-throwing runtime calls, QBE-generated code needs to
check for pending exceptions and branch to the disruption handler. */
void cell_rt_clear_exception(JSContext *ctx) {
if (JS_HasException(ctx))
JS_GetException(ctx);
}
/* --- Disruption --- */
void cell_rt_disrupt(JSContext *ctx) {
@@ -630,6 +681,10 @@ JSValue cell_rt_native_module_load(JSContext *ctx, void *dl_handle, JSValue env)
return JS_ThrowTypeError(ctx, "frame allocation failed");
}
/* Clear any stale exception left by a previous interpreted run */
if (JS_HasException(ctx))
JS_GetException(ctx);
JSValue result = fn(ctx, fp);
cell_rt_leave_frame(ctx); /* safe — closures have independent GC refs */
g_current_dl_handle = prev_handle;

View File

@@ -3076,7 +3076,7 @@ JSValue JS_ThrowError2 (JSContext *ctx, JSErrorEnum error_num, const char *fmt,
if (add_backtrace) {
print_backtrace (ctx, NULL, 0, 0);
}
return JS_Throw (ctx, JS_NULL);
return JS_Throw (ctx, JS_TRUE);
}
static JSValue JS_ThrowError (JSContext *ctx, JSErrorEnum error_num, const char *fmt, va_list ap) {