rm stack usage

This commit is contained in:
2026-02-11 10:17:55 -06:00
parent a252412eca
commit 259bc139fc
4 changed files with 117 additions and 140 deletions

View File

@@ -2723,20 +2723,23 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
JS_PushGCRef(ctx, &of_gc);
of_gc.val = outer_frame;
/* Protect argv and this_obj from GC by pushing onto value_stack.
argv is a C-allocated array whose JSValues may point to GC heap objects;
/* Protect argv and this_obj from GC using JSGCRef.
alloc_frame_register and js_new_register_function can trigger GC. */
int vs_save = ctx->value_stack_top;
int nargs_copy = (argc < code->arity) ? argc : code->arity;
ctx->value_stack[vs_save] = this_obj;
for (int i = 0; i < nargs_copy; i++)
ctx->value_stack[vs_save + 1 + i] = argv[i];
ctx->value_stack_top = vs_save + 1 + nargs_copy;
JSGCRef this_gc;
JS_PushGCRef(ctx, &this_gc);
this_gc.val = this_obj;
JSGCRef arg_gcs[nargs_copy > 0 ? nargs_copy : 1];
for (int i = 0; i < nargs_copy; i++) {
JS_PushGCRef(ctx, &arg_gcs[i]);
arg_gcs[i].val = argv[i];
}
/* Allocate initial frame */
JSFrameRegister *frame = alloc_frame_register(ctx, code->nr_slots);
if (!frame) {
ctx->value_stack_top = vs_save;
for (int i = nargs_copy - 1; i >= 0; i--) JS_PopGCRef(ctx, &arg_gcs[i]);
JS_PopGCRef(ctx, &this_gc);
JS_PopGCRef(ctx, &of_gc);
JS_PopGCRef(ctx, &env_gc);
return JS_EXCEPTION;
@@ -2758,13 +2761,14 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
JS_PopGCRef(ctx, &env_gc);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
frame->function = top_fn;
frame->slots[0] = ctx->value_stack[vs_save]; /* slot 0 = this (GC-safe from value_stack) */
frame->slots[0] = this_gc.val; /* slot 0 = this */
/* Copy arguments from GC-safe value_stack */
/* Copy arguments from GC-safe refs */
for (int i = 0; i < nargs_copy; i++) {
frame->slots[1 + i] = ctx->value_stack[vs_save + 1 + i];
frame->slots[1 + i] = arg_gcs[i].val;
}
ctx->value_stack_top = vs_save;
for (int i = nargs_copy - 1; i >= 0; i--) JS_PopGCRef(ctx, &arg_gcs[i]);
JS_PopGCRef(ctx, &this_gc);
uint32_t pc = code->entry_point;
JSValue result = JS_NULL;
@@ -3127,15 +3131,13 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
JSFunction *fn = JS_VALUE_GET_FUNCTION(func_val);
if (fn->kind == JS_FUNC_KIND_C) {
/* C function: push args onto value stack (C-allocated, GC-scanned) */
int vs_base = ctx->value_stack_top;
/* C function: copy args to C stack */
JSValue args[nargs > 0 ? nargs : 1];
for (int i = 0; i < nargs; i++)
ctx->value_stack[vs_base + i] = frame->slots[base + 1 + i];
ctx->value_stack_top = vs_base + nargs;
args[i] = frame->slots[base + 1 + i];
ctx->reg_current_frame = frame_ref.val;
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
JSValue ret = js_call_c_function(ctx, func_val, JS_NULL, nargs, &ctx->value_stack[vs_base]);
ctx->value_stack_top = vs_base;
JSValue ret = js_call_c_function(ctx, func_val, JS_NULL, nargs, args);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
ctx->reg_current_frame = JS_NULL;
if (JS_IsException(ret)) { goto disrupt; }
@@ -3168,13 +3170,11 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
env = fn->u.reg.env_record;
pc = code->entry_point;
} else {
/* Other function kinds (bytecode) — push args onto value stack */
int vs_base = ctx->value_stack_top;
/* Other function kinds (bytecode) — copy args to C stack */
JSValue args[nargs > 0 ? nargs : 1];
for (int i = 0; i < nargs; i++)
ctx->value_stack[vs_base + i] = frame->slots[base + 1 + i];
ctx->value_stack_top = vs_base + nargs;
JSValue ret = JS_CallInternal(ctx, func_val, JS_NULL, nargs, &ctx->value_stack[vs_base], 0);
ctx->value_stack_top = vs_base;
args[i] = frame->slots[base + 1 + i];
JSValue ret = JS_CallInternal(ctx, func_val, JS_NULL, nargs, args, 0);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
if (JS_IsException(ret)) { goto disrupt; }
if (nresults > 0) frame->slots[base] = ret;
@@ -3204,15 +3204,11 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
JS_SetPropertyUint32(ctx, frame->slots[base + 1], i, frame->slots[base + 2 + i]);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
}
/* Push proxy args onto value stack; re-read obj since GC may have moved it */
int vs_base = ctx->value_stack_top;
ctx->value_stack[vs_base] = key_ref.val;
ctx->value_stack[vs_base + 1] = frame->slots[base + 1]; /* the array */
ctx->value_stack_top = vs_base + 2;
/* Call proxy with key and array from C stack */
JSValue call_args[2] = { key_ref.val, frame->slots[base + 1] };
ctx->reg_current_frame = frame_ref.val;
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
JSValue ret = JS_CallInternal(ctx, frame->slots[base], JS_NULL, 2, &ctx->value_stack[vs_base], 0);
ctx->value_stack_top = vs_base;
JSValue ret = JS_CallInternal(ctx, frame->slots[base], JS_NULL, 2, call_args, 0);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
ctx->reg_current_frame = JS_NULL;
if (JS_IsException(ret)) { JS_PopGCRef(ctx, &key_ref); goto disrupt; }
@@ -3239,14 +3235,12 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
}
JSFunction *fn = JS_VALUE_GET_FUNCTION(method);
if (fn->kind == JS_FUNC_KIND_C) {
int vs_base = ctx->value_stack_top;
JSValue args[nargs > 0 ? nargs : 1];
for (int i = 0; i < nargs; i++)
ctx->value_stack[vs_base + i] = frame->slots[base + 2 + i];
ctx->value_stack_top = vs_base + nargs;
args[i] = frame->slots[base + 2 + i];
ctx->reg_current_frame = frame_ref.val;
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
JSValue ret = js_call_c_function(ctx, method, frame->slots[base], nargs, &ctx->value_stack[vs_base]);
ctx->value_stack_top = vs_base;
JSValue ret = js_call_c_function(ctx, method, frame->slots[base], nargs, args);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
ctx->reg_current_frame = JS_NULL;
if (JS_IsException(ret)) { JS_PopGCRef(ctx, &key_ref); goto disrupt; }
@@ -3277,12 +3271,10 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
pc = code->entry_point;
} else {
/* Bytecode or other function */
int vs_base = ctx->value_stack_top;
JSValue args[nargs > 0 ? nargs : 1];
for (int i = 0; i < nargs; i++)
ctx->value_stack[vs_base + i] = frame->slots[base + 2 + i];
ctx->value_stack_top = vs_base + nargs;
JSValue ret = JS_CallInternal(ctx, method, frame->slots[base], nargs, &ctx->value_stack[vs_base], 0);
ctx->value_stack_top = vs_base;
args[i] = frame->slots[base + 2 + i];
JSValue ret = JS_CallInternal(ctx, method, frame->slots[base], nargs, args, 0);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
if (JS_IsException(ret)) { JS_PopGCRef(ctx, &key_ref); goto disrupt; }
frame->slots[base] = ret;

View File

@@ -176,18 +176,27 @@ JSValue js_new_mcode_function(JSContext *ctx, JSMCode *code) {
/* Main MCODE interpreter — executes pre-parsed JSMCode */
JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
int argc, JSValue *argv, JSValue outer_frame) {
/* Protect argv, this_obj, outer_frame from GC by pushing onto value_stack.
/* Protect argv, this_obj, outer_frame from GC using JSGCRef.
alloc_frame_register and js_new_mcode_function can trigger GC. */
int vs_save = ctx->value_stack_top;
int nargs_copy = (argc < code->nr_args) ? argc : code->nr_args;
ctx->value_stack[vs_save] = this_obj;
ctx->value_stack[vs_save + 1] = outer_frame;
for (int i = 0; i < nargs_copy; i++)
ctx->value_stack[vs_save + 2 + i] = argv[i];
ctx->value_stack_top = vs_save + 2 + nargs_copy;
JSGCRef this_gc, of_gc;
JS_PushGCRef(ctx, &this_gc);
this_gc.val = this_obj;
JS_PushGCRef(ctx, &of_gc);
of_gc.val = outer_frame;
JSGCRef arg_gcs[nargs_copy > 0 ? nargs_copy : 1];
for (int i = 0; i < nargs_copy; i++) {
JS_PushGCRef(ctx, &arg_gcs[i]);
arg_gcs[i].val = argv[i];
}
JSFrameRegister *frame = alloc_frame_register(ctx, code->nr_slots);
if (!frame) { ctx->value_stack_top = vs_save; return JS_EXCEPTION; }
if (!frame) {
for (int i = nargs_copy - 1; i >= 0; i--) JS_PopGCRef(ctx, &arg_gcs[i]);
JS_PopGCRef(ctx, &of_gc);
JS_PopGCRef(ctx, &this_gc);
return JS_EXCEPTION;
}
/* Protect frame from GC */
JSGCRef frame_ref;
@@ -197,22 +206,26 @@ JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
/* Create a function object for the main frame so return can find the code */
JSValue main_func = js_new_mcode_function(ctx, code);
if (JS_IsException(main_func)) {
ctx->value_stack_top = vs_save;
JS_DeleteGCRef(ctx, &frame_ref);
for (int i = nargs_copy - 1; i >= 0; i--) JS_PopGCRef(ctx, &arg_gcs[i]);
JS_PopGCRef(ctx, &of_gc);
JS_PopGCRef(ctx, &this_gc);
return JS_ThrowInternalError(ctx, "failed to allocate main function for MCODE");
}
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
/* Set outer_frame AFTER allocation so it uses the post-GC value */
JSFunction *main_fn = JS_VALUE_GET_FUNCTION(main_func);
main_fn->u.mcode.outer_frame = ctx->value_stack[vs_save + 1];
main_fn->u.mcode.outer_frame = of_gc.val;
frame->function = main_func;
/* Setup initial frame from GC-safe value_stack */
frame->slots[0] = ctx->value_stack[vs_save]; /* slot 0 is this */
/* Setup initial frame from GC-safe refs */
frame->slots[0] = this_gc.val; /* slot 0 is this */
for (int i = 0; i < nargs_copy; i++) {
frame->slots[1 + i] = ctx->value_stack[vs_save + 2 + i];
frame->slots[1 + i] = arg_gcs[i].val;
}
ctx->value_stack_top = vs_save;
for (int i = nargs_copy - 1; i >= 0; i--) JS_PopGCRef(ctx, &arg_gcs[i]);
JS_PopGCRef(ctx, &of_gc);
JS_PopGCRef(ctx, &this_gc);
uint32_t pc = 0;
JSValue result = JS_NULL;
@@ -827,11 +840,8 @@ JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
int dest = (int)a1->valuedouble;
JSValue v = frame->slots[(int)a2->valuedouble];
if (!JS_IsText(v)) { goto disrupt; }
int vs_base = ctx->value_stack_top;
ctx->value_stack[vs_base] = v;
ctx->value_stack_top = vs_base + 1;
JSValue res = js_cell_text_lower(ctx, JS_NULL, 1, &ctx->value_stack[vs_base]);
ctx->value_stack_top = vs_base;
JSValue tmp = v;
JSValue res = js_cell_text_lower(ctx, JS_NULL, 1, &tmp);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
frame->slots[dest] = res;
}
@@ -839,11 +849,8 @@ JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
int dest = (int)a1->valuedouble;
JSValue v = frame->slots[(int)a2->valuedouble];
if (!JS_IsText(v)) { goto disrupt; }
int vs_base = ctx->value_stack_top;
ctx->value_stack[vs_base] = v;
ctx->value_stack_top = vs_base + 1;
JSValue res = js_cell_text_upper(ctx, JS_NULL, 1, &ctx->value_stack[vs_base]);
ctx->value_stack_top = vs_base;
JSValue tmp = v;
JSValue res = js_cell_text_upper(ctx, JS_NULL, 1, &tmp);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
frame->slots[dest] = res;
}
@@ -851,11 +858,8 @@ JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
int dest = (int)a1->valuedouble;
JSValue v = frame->slots[(int)a2->valuedouble];
if (!JS_IsNumber(v)) { goto disrupt; }
int vs_base = ctx->value_stack_top;
ctx->value_stack[vs_base] = v;
ctx->value_stack_top = vs_base + 1;
JSValue res = js_cell_character(ctx, JS_NULL, 1, &ctx->value_stack[vs_base]);
ctx->value_stack_top = vs_base;
JSValue tmp = v;
JSValue res = js_cell_character(ctx, JS_NULL, 1, &tmp);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
frame->slots[dest] = res;
}
@@ -863,11 +867,8 @@ JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
int dest = (int)a1->valuedouble;
JSValue v = frame->slots[(int)a2->valuedouble];
if (!JS_IsText(v)) { goto disrupt; }
int vs_base = ctx->value_stack_top;
ctx->value_stack[vs_base] = v;
ctx->value_stack_top = vs_base + 1;
JSValue res = js_cell_text_codepoint(ctx, JS_NULL, 1, &ctx->value_stack[vs_base]);
ctx->value_stack_top = vs_base;
JSValue tmp = v;
JSValue res = js_cell_text_codepoint(ctx, JS_NULL, 1, &tmp);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
frame->slots[dest] = res;
}
@@ -1472,18 +1473,15 @@ JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
code = fn->u.mcode.code;
pc = 0;
} else {
/* C or bytecode function — collect args on value stack (GC-safe) */
/* C or bytecode function — collect args on C stack */
int nr_slots = (int)objhdr_cap56(new_frame->hdr);
int c_argc = (nr_slots >= 2) ? nr_slots - 2 : 0;
int vs_base = ctx->value_stack_top;
for (int i = 0; i < c_argc; i++) {
ctx->value_stack[vs_base + i] = new_frame->slots[i + 1];
}
ctx->value_stack_top = vs_base + c_argc;
JSValue args[c_argc > 0 ? c_argc : 1];
for (int i = 0; i < c_argc; i++)
args[i] = new_frame->slots[i + 1];
ctx->reg_current_frame = frame_ref.val;
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
JSValue c_result = JS_Call(ctx, new_frame->function, new_frame->slots[0], c_argc, &ctx->value_stack[vs_base]);
ctx->value_stack_top = vs_base;
JSValue c_result = JS_Call(ctx, new_frame->function, new_frame->slots[0], c_argc, args);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
ctx->reg_current_frame = JS_NULL;
if (JS_IsException(c_result)) { goto disrupt; }
@@ -1507,14 +1505,13 @@ JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
if (JS_IsFunction(obj)) {
/* Proxy call: obj(name, [args...]) */
/* Store key on value stack immediately to protect from GC */
int vs_base = ctx->value_stack_top;
ctx->value_stack[vs_base] = JS_NewString(ctx, method_name);
JSGCRef key_gc;
JS_PushGCRef(ctx, &key_gc);
key_gc.val = JS_NewString(ctx, method_name);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
ctx->value_stack_top = vs_base + 1; /* protect key from GC */
JSValue arr = JS_NewArray(ctx);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
if (JS_IsException(arr)) goto disrupt;
if (JS_IsException(arr)) { JS_PopGCRef(ctx, &key_gc); goto disrupt; }
frame->slots[dest] = arr; /* protect from GC */
cJSON *p = a3->next;
for (int i = 0; i < nargs; i++, p = p->next) {
@@ -1523,14 +1520,13 @@ JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
JS_SetPropertyUint32(ctx, frame->slots[dest], i, frame->slots[areg]);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
}
ctx->value_stack[vs_base + 1] = frame->slots[dest];
ctx->value_stack_top = vs_base + 2;
JSValue call_args[2] = { key_gc.val, frame->slots[dest] };
ctx->reg_current_frame = frame_ref.val;
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
JSValue ret = JS_CallInternal(ctx, frame->slots[obj_reg], JS_NULL, 2, &ctx->value_stack[vs_base], 0);
ctx->value_stack_top = vs_base;
JSValue ret = JS_CallInternal(ctx, frame->slots[obj_reg], JS_NULL, 2, call_args, 0);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
ctx->reg_current_frame = JS_NULL;
JS_PopGCRef(ctx, &key_gc);
if (JS_IsException(ret)) goto disrupt;
frame->slots[dest] = ret;
} else {
@@ -1570,17 +1566,15 @@ JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
pc = 0;
} else {
/* C or bytecode function */
int vs_base = ctx->value_stack_top;
JSValue args[nargs > 0 ? nargs : 1];
cJSON *p = a3->next;
for (int i = 0; i < nargs; i++, p = p->next) {
if (cJSON_IsString(p)) break;
ctx->value_stack[vs_base + i] = frame->slots[(int)p->valuedouble];
args[i] = frame->slots[(int)p->valuedouble];
}
ctx->value_stack_top = vs_base + nargs;
ctx->reg_current_frame = frame_ref.val;
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
JSValue ret = JS_Call(ctx, method, frame->slots[obj_reg], nargs, &ctx->value_stack[vs_base]);
ctx->value_stack_top = vs_base;
JSValue ret = JS_Call(ctx, method, frame->slots[obj_reg], nargs, args);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
ctx->reg_current_frame = JS_NULL;
if (JS_IsException(ret)) goto disrupt;
@@ -1606,10 +1600,8 @@ JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
if (JS_IsFunction(obj) && JS_VALUE_IS_TEXT(key) &&
JS_VALUE_GET_FUNCTION(obj)->length == 2) {
/* Proxy call (arity-2 functions only): obj(key, [args...]) */
int vs_base = ctx->value_stack_top;
ctx->value_stack[vs_base] = key; /* protect key on value stack */
ctx->value_stack_top = vs_base + 1; /* protect key from GC */
/* Proxy call (arity-2 functions only): obj(key, [args...])
key lives in frame->slots[key_reg], which is GC-safe */
JSValue arr = JS_NewArray(ctx);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
if (JS_IsException(arr)) goto disrupt;
@@ -1620,12 +1612,10 @@ JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
JS_SetPropertyUint32(ctx, frame->slots[dest], i, frame->slots[areg]);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
}
ctx->value_stack[vs_base + 1] = frame->slots[dest];
ctx->value_stack_top = vs_base + 2;
JSValue call_args[2] = { frame->slots[key_reg], frame->slots[dest] };
ctx->reg_current_frame = frame_ref.val;
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
JSValue ret = JS_CallInternal(ctx, frame->slots[obj_reg], JS_NULL, 2, &ctx->value_stack[vs_base], 0);
ctx->value_stack_top = vs_base;
JSValue ret = JS_CallInternal(ctx, frame->slots[obj_reg], JS_NULL, 2, call_args, 0);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
ctx->reg_current_frame = JS_NULL;
if (JS_IsException(ret)) goto disrupt;
@@ -1667,16 +1657,14 @@ JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
code = fn->u.mcode.code;
pc = 0;
} else {
int vs_base = ctx->value_stack_top;
JSValue args[nargs > 0 ? nargs : 1];
cJSON *p = a3->next;
for (int i = 0; i < nargs; i++, p = p->next) {
ctx->value_stack[vs_base + i] = frame->slots[(int)p->valuedouble];
args[i] = frame->slots[(int)p->valuedouble];
}
ctx->value_stack_top = vs_base + nargs;
ctx->reg_current_frame = frame_ref.val;
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
JSValue ret = JS_Call(ctx, method, frame->slots[obj_reg], nargs, &ctx->value_stack[vs_base]);
ctx->value_stack_top = vs_base;
JSValue ret = JS_Call(ctx, method, frame->slots[obj_reg], nargs, args);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
ctx->reg_current_frame = JS_NULL;
if (JS_IsException(ret)) goto disrupt;
@@ -1767,17 +1755,19 @@ JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
int len = JS_IsNumber(len_val) ? (int)JS_VALUE_GET_INT(len_val) : 0;
if (len > 256) len = 256;
int vs_base = ctx->value_stack_top;
JSGCRef arg_refs[len > 0 ? len : 1];
for (int i = 0; i < len; i++) {
ctx->value_stack[vs_base + i] = JS_GetPropertyUint32(ctx, frame->slots[arr_slot], i);
JS_PushGCRef(ctx, &arg_refs[i]);
arg_refs[i].val = JS_GetPropertyUint32(ctx, frame->slots[arr_slot], i);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
}
ctx->value_stack_top = vs_base + len;
JSValue args[len > 0 ? len : 1];
for (int i = 0; i < len; i++) args[i] = arg_refs[i].val;
ctx->reg_current_frame = frame_ref.val;
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
result = JS_Call(ctx, frame->slots[func_slot], JS_NULL, len, &ctx->value_stack[vs_base]);
ctx->value_stack_top = vs_base;
result = JS_Call(ctx, frame->slots[func_slot], JS_NULL, len, args);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
for (int i = len - 1; i >= 0; i--) JS_PopGCRef(ctx, &arg_refs[i]);
if (JS_IsException(result)) { goto disrupt; }
}
@@ -1846,13 +1836,8 @@ JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
int pt_slot = (int)a1->valuedouble;
int right_slot = (int)a2->valuedouble;
if (!JS_IsText(frame->slots[pt_slot]) || !JS_IsText(frame->slots[right_slot])) { goto disrupt; }
int vs_base = ctx->value_stack_top;
ctx->value_stack[vs_base] = frame->slots[pt_slot];
ctx->value_stack[vs_base + 1] = frame->slots[right_slot];
ctx->value_stack_top = vs_base + 2;
JSText *s = JS_VALUE_GET_PTR(ctx->value_stack[vs_base]);
s = pretext_concat_value(ctx, s, ctx->value_stack[vs_base + 1]);
ctx->value_stack_top = vs_base;
JSText *s = JS_VALUE_GET_PTR(frame->slots[pt_slot]);
s = pretext_concat_value(ctx, s, frame->slots[right_slot]);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
if (!s) { goto disrupt; }
frame->slots[pt_slot] = JS_MKPTR(s);
@@ -1875,19 +1860,24 @@ JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
const char *flags_str = a3 ? a3->valuestring : "";
if (!pattern) pattern = "";
if (!flags_str) flags_str = "";
int vs_base = ctx->value_stack_top;
ctx->value_stack[vs_base] = JS_NewString(ctx, pattern); /* pat_val */
JSGCRef pat_gc, flags_gc;
JS_PushGCRef(ctx, &pat_gc);
pat_gc.val = JS_NewString(ctx, pattern);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
ctx->value_stack_top = vs_base + 1; /* protect pattern from GC */
ctx->value_stack[vs_base + 1] = *flags_str ? JS_NewString(ctx, flags_str) : JS_NULL; /* flags_val */
JS_PushGCRef(ctx, &flags_gc);
flags_gc.val = *flags_str ? JS_NewString(ctx, flags_str) : JS_NULL;
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
ctx->value_stack_top = vs_base + 2;
JSValue bc = js_compile_regexp(ctx, ctx->value_stack[vs_base], ctx->value_stack[vs_base + 1]);
JSValue bc = js_compile_regexp(ctx, pat_gc.val, flags_gc.val);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
if (JS_IsException(bc)) { ctx->value_stack_top = vs_base; goto disrupt; }
JSValue re_obj = js_regexp_constructor_internal(ctx, ctx->value_stack[vs_base], bc);
if (JS_IsException(bc)) {
JS_PopGCRef(ctx, &flags_gc);
JS_PopGCRef(ctx, &pat_gc);
goto disrupt;
}
JSValue re_obj = js_regexp_constructor_internal(ctx, pat_gc.val, bc);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
ctx->value_stack_top = vs_base;
JS_PopGCRef(ctx, &flags_gc);
JS_PopGCRef(ctx, &pat_gc);
if (JS_IsException(re_obj)) { goto disrupt; }
frame->slots[dest] = re_obj;
}

View File

@@ -336,15 +336,12 @@ JSValue cell_rt_invoke(JSContext *ctx, JSValue frame_val) {
int nr_slots = (int)objhdr_cap56(fr->hdr);
int c_argc = (nr_slots >= 2) ? nr_slots - 2 : 0;
/* Push args onto value stack (GC-safe) */
int vs_base = ctx->value_stack_top;
/* Copy args to C stack */
JSValue args[c_argc > 0 ? c_argc : 1];
for (int i = 0; i < c_argc; i++)
ctx->value_stack[vs_base + i] = fr->slots[i + 1];
ctx->value_stack_top = vs_base + c_argc;
args[i] = fr->slots[i + 1];
JSValue result = JS_Call(ctx, fr->function, fr->slots[0],
c_argc, &ctx->value_stack[vs_base]);
ctx->value_stack_top = vs_base;
JSValue result = JS_Call(ctx, fr->function, fr->slots[0], c_argc, args);
if (JS_IsException(result))
return JS_EXCEPTION;
return result;

View File

@@ -1441,7 +1441,6 @@ JSContext *JS_NewContextRawWithHeapSize (JSRuntime *rt, size_t heap_size) {
/* Initialize per-context execution state (moved from JSRuntime) */
ctx->current_exception = JS_UNINITIALIZED;
JS_UpdateStackTop (ctx);
/* Initialize stone text intern table */
ctx->st_pages = NULL;
@@ -4264,7 +4263,6 @@ JSValue js_call_c_function (JSContext *ctx, JSValue func_obj, JSValue this_obj,
JSValue ret_val;
JSValue *arg_buf;
int arg_count, i;
int saved_vs_top = -1; /* for value stack padding cleanup */
JSCFunctionEnum cproto;
f = JS_VALUE_GET_FUNCTION (func_obj);