bootstrap with serialized mach

This commit is contained in:
2026-02-09 22:54:42 -06:00
parent 930dcfba36
commit b8b110b616
17 changed files with 89 additions and 247144 deletions

View File

@@ -11,7 +11,8 @@
#include "cell_internal.h"
#include "cJSON.h"
#define BOOTSTRAP_AST "internal/bootstrap.ast.json"
#define BOOTSTRAP_MACH "internal/bootstrap.mach"
#define BOOTSTRAP_AST "internal/bootstrap.ast.json"
#define CELL_SHOP_DIR ".cell"
#define CELL_CORE_DIR "packages/core"
@@ -150,18 +151,16 @@ void script_startup(cell_rt *prt)
cell_rt *crt = JS_GetContextOpaque(js);
JS_FreeValue(js, js_blob_use(js));
// Load pre-compiled bootstrap AST
// Load pre-compiled bootstrap bytecode (.mach), fall back to AST JSON
size_t boot_size;
char *boot_json = load_core_file(BOOTSTRAP_AST, &boot_size);
if (!boot_json) {
printf("ERROR: Could not load %s from %s!\n", BOOTSTRAP_AST, core_path);
return;
int boot_is_bin = 1;
char *boot_data = load_core_file(BOOTSTRAP_MACH, &boot_size);
if (!boot_data) {
boot_is_bin = 0;
boot_data = load_core_file(BOOTSTRAP_AST, &boot_size);
}
cJSON *ast = cJSON_Parse(boot_json);
free(boot_json);
if (!ast) {
printf("ERROR: Failed to parse %s\n", BOOTSTRAP_AST);
if (!boot_data) {
printf("ERROR: Could not load bootstrap from %s!\n", core_path);
return;
}
@@ -193,8 +192,17 @@ void script_startup(cell_rt *prt)
// Run through MACH VM
crt->state = ACTOR_RUNNING;
JSValue v = JS_RunMachTree(js, ast, hidden_env);
cJSON_Delete(ast);
JSValue v;
if (boot_is_bin) {
v = JS_RunMachBin(js, (const uint8_t *)boot_data, boot_size, hidden_env);
free(boot_data);
} else {
cJSON *ast = cJSON_Parse(boot_data);
free(boot_data);
if (!ast) { printf("ERROR: Failed to parse bootstrap AST\n"); return; }
v = JS_RunMachTree(js, ast, hidden_env);
cJSON_Delete(ast);
}
uncaught_exception(js, v);
crt->state = ACTOR_IDLE;
set_actor_state(crt);
@@ -286,29 +294,27 @@ int cell_init(int argc, char **argv)
if (!find_cell_shop()) return 1;
size_t boot_size;
char *boot_json = load_core_file(BOOTSTRAP_AST, &boot_size);
if (!boot_json) {
printf("ERROR: Could not load %s from %s\n", BOOTSTRAP_AST, core_path);
return 1;
int boot_is_bin = 1;
char *boot_data = load_core_file(BOOTSTRAP_MACH, &boot_size);
if (!boot_data) {
boot_is_bin = 0;
boot_data = load_core_file(BOOTSTRAP_AST, &boot_size);
}
cJSON *boot_ast = cJSON_Parse(boot_json);
free(boot_json);
if (!boot_ast) {
printf("Failed to parse %s\n", BOOTSTRAP_AST);
if (!boot_data) {
printf("ERROR: Could not load bootstrap from %s\n", core_path);
return 1;
}
JSRuntime *rt = JS_NewRuntime();
if (!rt) {
printf("Failed to create JS runtime\n");
cJSON_Delete(boot_ast);
free(boot_data);
return 1;
}
JSContext *ctx = JS_NewContextWithHeapSize(rt, 16 * 1024 * 1024);
if (!ctx) {
printf("Failed to create JS context\n");
cJSON_Delete(boot_ast); JS_FreeRuntime(rt);
free(boot_data); JS_FreeRuntime(rt);
return 1;
}
@@ -326,8 +332,17 @@ int cell_init(int argc, char **argv)
JS_SetPropertyStr(ctx, hidden_env, "args", args_arr);
hidden_env = JS_Stone(ctx, hidden_env);
JSValue result = JS_RunMachTree(ctx, boot_ast, hidden_env);
cJSON_Delete(boot_ast);
JSValue result;
if (boot_is_bin) {
result = JS_RunMachBin(ctx, (const uint8_t *)boot_data, boot_size, hidden_env);
free(boot_data);
} else {
cJSON *ast = cJSON_Parse(boot_data);
free(boot_data);
if (!ast) { printf("Failed to parse bootstrap AST\n"); JS_FreeContext(ctx); JS_FreeRuntime(rt); return 1; }
result = JS_RunMachTree(ctx, ast, hidden_env);
cJSON_Delete(ast);
}
int exit_code = 0;
if (JS_IsException(result)) {

View File

@@ -3525,6 +3525,22 @@ JSValue JS_RunMachTree(JSContext *ctx, cJSON *ast, JSValue env) {
return result;
}
JSValue JS_RunMachBin(JSContext *ctx, const uint8_t *data, size_t size, JSValue env) {
MachCode *mc = JS_DeserializeMachCode(data, size);
if (!mc)
return JS_ThrowSyntaxError(ctx, "failed to deserialize MACH bytecode");
JSGCRef env_ref;
JS_PushGCRef(ctx, &env_ref);
env_ref.val = env;
JSCodeRegister *code = JS_LoadMachCode(ctx, mc, env_ref.val);
JS_FreeMachCode(mc);
JSValue result = JS_CallRegisterVM(ctx, code, ctx->global_obj, 0, NULL, env_ref.val, JS_NULL);
JS_PopGCRef(ctx, &env_ref);
return result;
}
JSValue JS_RunMach(JSContext *ctx, const char *ast_json, JSValue env) {
cJSON *ast = cJSON_Parse(ast_json);
if (!ast) {

View File

@@ -1103,6 +1103,9 @@ JSValue JS_RunMachTree (JSContext *ctx, struct cJSON *ast, JSValue env);
/* Compile and execute MACH bytecode from AST JSON string. */
JSValue JS_RunMach (JSContext *ctx, const char *ast_json, JSValue env);
/* Deserialize and execute pre-compiled MACH binary bytecode. */
JSValue JS_RunMachBin(JSContext *ctx, const uint8_t *data, size_t size, JSValue env);
/* Execute MCODE from cJSON tree. Takes ownership of root. */
JSValue JS_CallMcodeTree (JSContext *ctx, struct cJSON *root);

View File

@@ -10424,47 +10424,6 @@ static JSValue js_mach_eval_ast (JSContext *ctx, JSValue this_val, int argc, JSV
return result;
}
/* mach_compile(name, source) - parse and compile to binary blob */
static JSValue js_mach_compile (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 requires (name, source) text arguments");
const char *name = JS_ToCString (ctx, argv[0]);
if (!name) return JS_EXCEPTION;
const char *source = JS_ToCString (ctx, argv[1]);
if (!source) {
JS_FreeCString (ctx, name);
return JS_EXCEPTION;
}
cJSON *ast = JS_ASTTree (source, strlen (source), name);
JS_FreeCString (ctx, source);
if (!ast) {
JS_FreeCString (ctx, name);
return JS_ThrowSyntaxError (ctx, "mach_compile: failed to parse source");
}
MachCode *mc = JS_CompileMachTree (ast);
cJSON_Delete (ast);
JS_FreeCString (ctx, name);
if (!mc)
return JS_ThrowSyntaxError (ctx, "mach_compile: 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: serialization failed");
JSValue result = js_new_blob_stoned_copy (ctx, buf, blob_size);
sys_free (buf);
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]))
@@ -11657,7 +11616,6 @@ 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", js_mach_compile, 2);
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, "stone", js_cell_stone, 1);