rm stack usage
This commit is contained in:
@@ -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;
|
||||
|
||||
170
source/mcode.c
170
source/mcode.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user