mcode->mach

This commit is contained in:
2026-02-12 04:28:14 -06:00
parent 8a84be65e1
commit 3a8a17ab60
19 changed files with 635 additions and 4320 deletions

View File

@@ -1139,10 +1139,6 @@ void gc_scan_object (JSContext *ctx, void *ptr, uint8_t *from_base, uint8_t *fro
nested->name = gc_copy_value (ctx, nested->name, from_base, from_end, to_base, to_free, to_end);
}
}
} else if (fn->kind == JS_FUNC_KIND_MCODE) {
/* MCODE function - scan outer_frame and env_record */
fn->u.mcode.outer_frame = gc_copy_value (ctx, fn->u.mcode.outer_frame, from_base, from_end, to_base, to_free, to_end);
fn->u.mcode.env_record = gc_copy_value (ctx, fn->u.mcode.env_record, from_base, from_end, to_base, to_free, to_end);
}
break;
}
@@ -4630,8 +4626,6 @@ JSValue JS_CallInternal (JSContext *ctx, JSValue func_obj, JSValue this_obj,
case JS_FUNC_KIND_REGISTER:
return JS_CallRegisterVM (ctx, f->u.reg.code, this_obj, argc, argv,
f->u.reg.env_record, f->u.reg.outer_frame);
case JS_FUNC_KIND_MCODE:
return mcode_exec (ctx, f->u.mcode.code, this_obj, argc, argv, f->u.mcode.outer_frame);
default:
return JS_ThrowTypeError (ctx, "not a function");
}
@@ -4653,8 +4647,6 @@ JSValue JS_Call (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, J
case JS_FUNC_KIND_REGISTER:
return JS_CallRegisterVM (ctx, f->u.reg.code, this_obj, argc, argv,
f->u.reg.env_record, f->u.reg.outer_frame);
case JS_FUNC_KIND_MCODE:
return mcode_exec (ctx, f->u.mcode.code, this_obj, argc, argv, f->u.mcode.outer_frame);
default:
return JS_ThrowTypeError (ctx, "not a function");
}
@@ -10117,83 +10109,6 @@ int js_is_blob (JSContext *js, JSValue v) {
* ============================================================================
*/
/* mach_eval_ast(name, ast_json, env?) - compile pre-parsed AST and run */
static JSValue js_mach_eval_ast (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
if (argc < 2 || !JS_IsText (argv[0]) || !JS_IsText (argv[1]))
return JS_ThrowTypeError (ctx, "mach_eval_ast requires (name, ast_json) text arguments");
const char *name = JS_ToCString (ctx, argv[0]);
if (!name) return JS_EXCEPTION;
const char *json_str = JS_ToCString (ctx, argv[1]);
if (!json_str) {
JS_FreeCString (ctx, name);
return JS_EXCEPTION;
}
cJSON *ast = cJSON_Parse (json_str);
JS_FreeCString (ctx, json_str);
if (!ast) {
JS_FreeCString (ctx, name);
return JS_ThrowSyntaxError (ctx, "mach_eval_ast: failed to parse AST JSON");
}
/* Set the filename on the AST root */
cJSON_DeleteItemFromObjectCaseSensitive (ast, "filename");
cJSON_AddStringToObject (ast, "filename", name);
JSValue env = (argc >= 3 && JS_IsObject (argv[2])) ? argv[2] : JS_NULL;
JSValue result = JS_RunMachTree (ctx, ast, env);
cJSON_Delete (ast);
JS_FreeCString (ctx, name);
return result;
}
/* mach_compile_ast(name, ast_json) - compile pre-parsed AST to binary blob */
static JSValue js_mach_compile_ast (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
if (argc < 2 || !JS_IsText (argv[0]) || !JS_IsText (argv[1]))
return JS_ThrowTypeError (ctx, "mach_compile_ast requires (name, ast_json) text arguments");
const char *name = JS_ToCString (ctx, argv[0]);
if (!name) return JS_EXCEPTION;
const char *json_str = JS_ToCString (ctx, argv[1]);
if (!json_str) {
JS_FreeCString (ctx, name);
return JS_EXCEPTION;
}
cJSON *ast = cJSON_Parse (json_str);
JS_FreeCString (ctx, json_str);
if (!ast) {
JS_FreeCString (ctx, name);
return JS_ThrowSyntaxError (ctx, "mach_compile_ast: failed to parse AST JSON");
}
cJSON_DeleteItemFromObjectCaseSensitive (ast, "filename");
cJSON_AddStringToObject (ast, "filename", name);
MachCode *mc = JS_CompileMachTree (ast);
cJSON_Delete (ast);
JS_FreeCString (ctx, name);
if (!mc)
return JS_ThrowSyntaxError (ctx, "mach_compile_ast: failed to compile AST");
size_t blob_size;
uint8_t *buf = JS_SerializeMachCode (mc, &blob_size);
JS_FreeMachCode (mc);
if (!buf)
return JS_ThrowInternalError (ctx, "mach_compile_ast: serialization failed");
JSValue result = js_new_blob_stoned_copy (ctx, buf, blob_size);
sys_free (buf);
return result;
}
/* mach_load(blob, env?) - deserialize and execute binary blob */
static JSValue js_mach_load (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
if (argc < 1)
@@ -10207,6 +10122,11 @@ static JSValue js_mach_load (JSContext *ctx, JSValue this_val, int argc, JSValue
if (!mc)
return JS_ThrowSyntaxError (ctx, "mach_load: failed to deserialize bytecode");
{
extern void verify_getup(MachCode *mc, const char *path);
verify_getup(mc, "MACH_LOAD");
}
JSValue env = (argc >= 2 && JS_IsObject (argv[1])) ? argv[1] : JS_NULL;
JSGCRef env_ref;
@@ -10220,35 +10140,6 @@ static JSValue js_mach_load (JSContext *ctx, JSValue this_val, int argc, JSValue
return result;
}
/* mcode_run(name, mcode_json, env?) - run pre-compiled mcode JSON */
static JSValue js_mcode_run (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
if (argc < 2 || !JS_IsText (argv[0]) || !JS_IsText (argv[1]))
return JS_ThrowTypeError (ctx, "mcode_run requires (name, mcode_json) text arguments");
const char *name = JS_ToCString (ctx, argv[0]);
if (!name) return JS_EXCEPTION;
const char *json_str = JS_ToCString (ctx, argv[1]);
if (!json_str) {
JS_FreeCString (ctx, name);
return JS_EXCEPTION;
}
cJSON *mcode = cJSON_Parse (json_str);
JS_FreeCString (ctx, json_str);
if (!mcode) {
JS_FreeCString (ctx, name);
return JS_ThrowSyntaxError (ctx, "mcode_run: failed to parse mcode JSON");
}
JSValue env = (argc >= 3 && JS_IsObject (argv[2])) ? argv[2] : JS_NULL;
JSValue result = JS_CallMcodeTreeEnv (ctx, mcode, env);
/* mcode tree ownership transferred to JS_CallMcodeTreeEnv — do not free */
JS_FreeCString (ctx, name);
return result;
}
/* mach_eval_mcode(name, mcode_json, env?) - compile mcode IR and run via register VM */
static JSValue js_mach_eval_mcode (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
if (argc < 2 || !JS_IsText (argv[0]) || !JS_IsText (argv[1]))
@@ -10298,6 +10189,61 @@ static JSValue js_mach_eval_mcode (JSContext *ctx, JSValue this_val, int argc, J
return result;
}
/* mach_compile_mcode_bin(name, mcode_json) - compile mcode IR to serialized binary blob */
static JSValue js_mach_compile_mcode_bin (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
if (argc < 2 || !JS_IsText (argv[0]) || !JS_IsText (argv[1]))
return JS_ThrowTypeError (ctx, "mach_compile_mcode_bin requires (name, mcode_json) text arguments");
const char *name = JS_ToCString (ctx, argv[0]);
if (!name) return JS_EXCEPTION;
const char *json_str = JS_ToCString (ctx, argv[1]);
if (!json_str) {
JS_FreeCString (ctx, name);
return JS_EXCEPTION;
}
cJSON *mcode = cJSON_Parse (json_str);
JS_FreeCString (ctx, json_str);
if (!mcode) {
JS_FreeCString (ctx, name);
return JS_ThrowSyntaxError (ctx, "mach_compile_mcode_bin: failed to parse mcode JSON");
}
if (!cJSON_GetObjectItemCaseSensitive (mcode, "filename"))
cJSON_AddStringToObject (mcode, "filename", name);
MachCode *mc = mach_compile_mcode (mcode);
cJSON_Delete (mcode);
JS_FreeCString (ctx, name);
if (!mc)
return JS_ThrowInternalError (ctx, "mach_compile_mcode_bin: compilation failed");
size_t size = 0;
uint8_t *data = JS_SerializeMachCode (mc, &size);
/* DEBUG: verify round-trip */
{
MachCode *mc2 = JS_DeserializeMachCode (data, size);
if (mc2) {
extern void verify_getup(MachCode *mc, const char *path);
verify_getup(mc2, "ROUNDTRIP");
JS_FreeMachCode (mc2);
}
}
JS_FreeMachCode (mc);
if (!data)
return JS_ThrowInternalError (ctx, "mach_compile_mcode_bin: serialization failed");
JSValue blob = js_new_blob_stoned_copy (ctx, data, size);
sys_free (data);
return blob;
}
/* ============================================================================
* stone() function - deep freeze with blob support
* ============================================================================
@@ -11398,11 +11344,9 @@ static void JS_AddIntrinsicBaseObjects (JSContext *ctx) {
}
/* Core functions - using GC-safe helper */
js_set_global_cfunc(ctx, "mach_eval_ast", js_mach_eval_ast, 3);
js_set_global_cfunc(ctx, "mcode_run", js_mcode_run, 3);
js_set_global_cfunc(ctx, "mach_compile_ast", js_mach_compile_ast, 2);
js_set_global_cfunc(ctx, "mach_load", js_mach_load, 2);
js_set_global_cfunc(ctx, "mach_eval_mcode", js_mach_eval_mcode, 3);
js_set_global_cfunc(ctx, "mach_compile_mcode_bin", js_mach_compile_mcode_bin, 2);
js_set_global_cfunc(ctx, "stone", js_cell_stone, 1);
js_set_global_cfunc(ctx, "length", js_cell_length, 1);
js_set_global_cfunc(ctx, "call", js_cell_call, 3);
@@ -13150,17 +13094,6 @@ cJSON *JS_GetStack(JSContext *ctx) {
line = code->line_table[pc].line;
col = code->line_table[pc].col;
}
} else if (fn->kind == JS_FUNC_KIND_MCODE && fn->u.mcode.code) {
JSMCode *code = fn->u.mcode.code;
file = code->filename;
func_name = code->name;
if (!is_first) {
pc = (uint32_t)(JS_VALUE_GET_INT(frame->address) >> 16);
}
if (code->line_table && pc < code->instr_count) {
line = code->line_table[pc].line;
col = code->line_table[pc].col;
}
}
cJSON *entry = cJSON_CreateObject();