fix functions and closures in mach
This commit is contained in:
@@ -2126,10 +2126,18 @@ void *js_malloc (JSContext *ctx, size_t size) {
|
||||
JS_ThrowOutOfMemory(ctx);
|
||||
return NULL;
|
||||
}
|
||||
/* Check if we have space after GC */
|
||||
/* Check if we have space after GC — the GC may have doubled
|
||||
next_block_size but allocated the old size. Fall through to
|
||||
the normal grow path so we get a bigger block. */
|
||||
if ((uint8_t *)ctx->heap_free + size > (uint8_t *)ctx->heap_end) {
|
||||
JS_ThrowOutOfMemory(ctx);
|
||||
return NULL;
|
||||
if (ctx_gc(ctx, 1) < 0) {
|
||||
JS_ThrowOutOfMemory(ctx);
|
||||
return NULL;
|
||||
}
|
||||
if ((uint8_t *)ctx->heap_free + size > (uint8_t *)ctx->heap_end) {
|
||||
JS_ThrowOutOfMemory(ctx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* Check if we have space in current block */
|
||||
@@ -31459,6 +31467,7 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
|
||||
/* Register parameters */
|
||||
cJSON *params = cJSON_GetObjectItem(node, "params");
|
||||
if (!params) params = cJSON_GetObjectItem(node, "parameters");
|
||||
if (!params) params = cJSON_GetObjectItem(node, "list");
|
||||
int nparams = params ? cJSON_GetArraySize(params) : 0;
|
||||
child.nr_args = nparams;
|
||||
for (int i = 0; i < nparams; i++) {
|
||||
@@ -31476,7 +31485,8 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
|
||||
|
||||
/* Compile body */
|
||||
cJSON *body = cJSON_GetObjectItem(node, "body");
|
||||
if (body) {
|
||||
if (!body) body = node; /* statements may be directly on the function node */
|
||||
{
|
||||
cJSON *stmts = cJSON_GetObjectItem(body, "statements");
|
||||
if (!stmts) stmts = body; /* body might be the statements array directly */
|
||||
if (cJSON_IsArray(stmts)) {
|
||||
@@ -31557,6 +31567,19 @@ static void mach_compile_stmt(MachCompState *cs, cJSON *stmt) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Function declaration statement */
|
||||
if (strcmp(kind, "function") == 0) {
|
||||
const char *name = cJSON_GetStringValue(cJSON_GetObjectItem(stmt, "name"));
|
||||
if (!name) return;
|
||||
int slot = mach_find_var(cs, name);
|
||||
if (slot < 0) {
|
||||
slot = mach_reserve_reg(cs);
|
||||
mach_add_var(cs, name, slot, 1);
|
||||
}
|
||||
mach_compile_expr(cs, stmt, slot);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Expression statement (call) */
|
||||
if (strcmp(kind, "call") == 0) {
|
||||
cJSON *expr = cJSON_GetObjectItem(stmt, "expression");
|
||||
@@ -31796,6 +31819,20 @@ static MachCode *mach_compile_program(MachCompState *cs, cJSON *ast) {
|
||||
/* Scan scope record for declarations */
|
||||
mach_scan_scope(cs);
|
||||
|
||||
/* Hoist function declarations */
|
||||
cJSON *functions = cJSON_GetObjectItem(ast, "functions");
|
||||
if (functions && cJSON_IsArray(functions)) {
|
||||
int fcount = cJSON_GetArraySize(functions);
|
||||
for (int i = 0; i < fcount; i++) {
|
||||
cJSON *fn_node = cJSON_GetArrayItem(functions, i);
|
||||
const char *fn_name = cJSON_GetStringValue(cJSON_GetObjectItem(fn_node, "name"));
|
||||
if (!fn_name) continue;
|
||||
int slot = mach_find_var(cs, fn_name);
|
||||
if (slot < 0) continue;
|
||||
mach_compile_expr(cs, fn_node, slot);
|
||||
}
|
||||
}
|
||||
|
||||
/* Compile each statement */
|
||||
int count = cJSON_GetArraySize(stmts);
|
||||
for (int i = 0; i < count; i++) {
|
||||
@@ -32092,7 +32129,11 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
JS_AddGCRef(ctx, &frame_ref);
|
||||
frame_ref.val = JS_MKPTR(frame);
|
||||
|
||||
/* Setup initial frame */
|
||||
/* Setup initial frame — wrap top-level code in a function object so that
|
||||
returning from a called register function can read code/env from frame */
|
||||
JSValue top_fn = js_new_register_function(ctx, code, env, outer_frame);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
frame->function = top_fn;
|
||||
frame->slots[0] = this_obj; /* slot 0 = this */
|
||||
|
||||
/* Copy arguments */
|
||||
@@ -32116,11 +32157,11 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
if (JS_IsNull(frame->caller)) goto done;
|
||||
|
||||
/* Pop frame */
|
||||
int ret_info = JS_VALUE_GET_INT(frame->address);
|
||||
JSFrameRegister *caller = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->caller);
|
||||
frame->caller = JS_NULL;
|
||||
frame = caller;
|
||||
frame_ref.val = JS_MKPTR(frame);
|
||||
int ret_info = JS_VALUE_GET_INT(frame->address);
|
||||
JSFunction *fn = JS_VALUE_GET_FUNCTION(frame->function);
|
||||
code = fn->u.reg.code;
|
||||
env = fn->u.reg.env_record;
|
||||
@@ -32420,7 +32461,10 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
JSCodeRegister *fn_code = fn->u.reg.code;
|
||||
JSFrameRegister *new_frame = alloc_frame_register(ctx, fn_code->nr_slots);
|
||||
if (!new_frame) { result = JS_EXCEPTION; goto done; }
|
||||
/* Re-read pointers — GC may have moved them */
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
func_val = frame->slots[base];
|
||||
fn = JS_VALUE_GET_FUNCTION(func_val);
|
||||
new_frame->function = func_val;
|
||||
new_frame->slots[0] = JS_NULL; /* this */
|
||||
for (int i = 0; i < nargs && i < fn_code->arity; i++)
|
||||
@@ -32450,11 +32494,11 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
result = frame->slots[a];
|
||||
if (JS_IsNull(frame->caller)) goto done;
|
||||
{
|
||||
int ret_info = JS_VALUE_GET_INT(frame->address);
|
||||
JSFrameRegister *caller = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->caller);
|
||||
frame->caller = JS_NULL;
|
||||
frame = caller;
|
||||
frame_ref.val = JS_MKPTR(frame);
|
||||
int ret_info = JS_VALUE_GET_INT(frame->address);
|
||||
JSFunction *fn = JS_VALUE_GET_FUNCTION(frame->function);
|
||||
code = fn->u.reg.code;
|
||||
env = fn->u.reg.env_record;
|
||||
@@ -32468,11 +32512,11 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
result = JS_NULL;
|
||||
if (JS_IsNull(frame->caller)) goto done;
|
||||
{
|
||||
int ret_info = JS_VALUE_GET_INT(frame->address);
|
||||
JSFrameRegister *caller = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->caller);
|
||||
frame->caller = JS_NULL;
|
||||
frame = caller;
|
||||
frame_ref.val = JS_MKPTR(frame);
|
||||
int ret_info = JS_VALUE_GET_INT(frame->address);
|
||||
JSFunction *fn = JS_VALUE_GET_FUNCTION(frame->function);
|
||||
code = fn->u.reg.code;
|
||||
env = fn->u.reg.env_record;
|
||||
|
||||
Reference in New Issue
Block a user