run with mcode

This commit is contained in:
2026-02-12 16:14:46 -06:00
parent 0ba2783b48
commit 1efb0b1bc9
24 changed files with 738012 additions and 50 deletions

134805
fold.cm.mcode Normal file

File diff suppressed because it is too large Load Diff

BIN
fold.mach

Binary file not shown.

View File

@@ -24,15 +24,21 @@ function use_basic(path) {
return result
}
// Load a module from .mach bytecode (bootstrap modules have no source fallback)
// Load a module from .mach/.mcode bytecode (bootstrap modules have no source fallback)
function boot_load(name, env) {
var mach_path = core_path + '/' + name + ".mach"
var mach_path = core_path + '/' + name + ".cm.mach"
var mcode_path = core_path + '/' + name + ".cm.mcode"
var data = null
var mcode_json = null
if (fd.is_file(mach_path)) {
data = fd.slurp(mach_path)
return mach_load(data, env)
}
print("error: missing bootstrap bytecode: " + mach_path + "\n")
if (fd.is_file(mcode_path)) {
mcode_json = text(fd.slurp(mcode_path))
return mach_eval_mcode(name, mcode_json, env)
}
print("error: missing bootstrap bytecode: " + name + "\n")
disrupt
}
@@ -50,33 +56,45 @@ use_cache['mcode'] = mcode_mod
var streamline_mod = null
var qbe_emit_mod = null
// Warn if any .cm source is newer than its .mach bytecode
// Warn if any .cm source is newer than its compiled bytecode
function check_mach_stale() {
var pairs = [
["tokenize.cm", "tokenize.mach"],
["parse.cm", "parse.mach"],
["fold.cm", "fold.mach"],
["mcode.cm", "mcode.mach"],
["streamline.cm", "streamline.mach"],
["qbe.cm", "qbe.mach"],
["qbe_emit.cm", "qbe_emit.mach"],
["internal/bootstrap.cm", "internal/bootstrap.mach"],
["internal/engine.cm", "internal/engine.mach"]
var sources = [
"tokenize.cm",
"parse.cm",
"fold.cm",
"mcode.cm",
"streamline.cm",
"qbe.cm",
"qbe_emit.cm",
"internal/bootstrap.cm",
"internal/engine.cm"
]
var stale = []
var _i = 0
var cm_path = null
var mach_path = null
var mcode_path = null
var cm_stat = null
var mach_stat = null
while (_i < length(pairs)) {
cm_path = core_path + '/' + pairs[_i][0]
mach_path = core_path + '/' + pairs[_i][1]
if (fd.is_file(cm_path) && fd.is_file(mach_path)) {
var compiled_stat = null
var best_mtime = null
while (_i < length(sources)) {
cm_path = core_path + '/' + sources[_i]
mach_path = cm_path + '.mach'
mcode_path = cm_path + '.mcode'
best_mtime = null
if (fd.is_file(mach_path)) {
best_mtime = fd.stat(mach_path).mtime
}
if (fd.is_file(mcode_path)) {
compiled_stat = fd.stat(mcode_path)
if (best_mtime == null || compiled_stat.mtime > best_mtime) {
best_mtime = compiled_stat.mtime
}
}
if (best_mtime != null && fd.is_file(cm_path)) {
cm_stat = fd.stat(cm_path)
mach_stat = fd.stat(mach_path)
if (cm_stat.mtime > mach_stat.mtime) {
push(stale, pairs[_i][0])
if (cm_stat.mtime > best_mtime) {
push(stale, sources[_i])
}
}
_i = _i + 1
@@ -123,10 +141,12 @@ function analyze(src, filename) {
return ast
}
// Load a module from .mach bytecode, falling back to source compilation
// Load a module from .mach/.mcode bytecode, falling back to source compilation
function load_module(name, env) {
var mach_path = core_path + '/' + name + ".mach"
var mach_path = core_path + '/' + name + ".cm.mach"
var mcode_path = core_path + '/' + name + ".cm.mcode"
var data = null
var mcode_json = null
var src_path = null
var src = null
var ast = null
@@ -136,6 +156,10 @@ function load_module(name, env) {
data = fd.slurp(mach_path)
return mach_load(data, env)
}
if (fd.is_file(mcode_path)) {
mcode_json = text(fd.slurp(mcode_path))
return mach_eval_mcode(name, mcode_json, env)
}
src_path = core_path + '/' + name + ".cm"
src = text(fd.slurp(src_path))
ast = analyze(src, src_path)
@@ -176,6 +200,8 @@ function run_ast(name, ast, env) {
function use_fn(path) {
var file_path = null
var mach_path = null
var mcode_path = null
var mcode_json = null
var data = null
var script = null
var ast = null
@@ -183,10 +209,10 @@ function use_fn(path) {
if (use_cache[path])
return use_cache[path]
// Try .mach bytecode first (CWD then core_path)
mach_path = path + '.mach'
// Try .cm.mach bytecode first (CWD then core_path)
mach_path = path + '.cm.mach'
if (!fd.is_file(mach_path))
mach_path = core_path + '/' + path + '.mach'
mach_path = core_path + '/' + path + '.cm.mach'
if (fd.is_file(mach_path)) {
data = fd.slurp(mach_path)
result = mach_load(data, {use: use_fn})
@@ -194,6 +220,17 @@ function use_fn(path) {
return result
}
// Try .cm.mcode JSON IR (CWD then core_path)
mcode_path = path + '.cm.mcode'
if (!fd.is_file(mcode_path))
mcode_path = core_path + '/' + path + '.cm.mcode'
if (fd.is_file(mcode_path)) {
mcode_json = text(fd.slurp(mcode_path))
result = mach_eval_mcode(path, mcode_json, {use: use_fn})
use_cache[path] = result
return result
}
// Try .cm source (CWD then core_path)
file_path = path + '.cm'
if (!fd.is_file(file_path))
@@ -215,14 +252,20 @@ function use_fn(path) {
// Helper to load engine.cm and run it with given env
function load_engine(env) {
var engine_path = core_path + '/internal/engine.mach'
var engine_path = core_path + '/internal/engine.cm.mach'
var mcode_path = core_path + '/internal/engine.cm.mcode'
var data = null
var mcode_json = null
var engine_src = null
var engine_ast = null
if (fd.is_file(engine_path)) {
data = fd.slurp(engine_path)
return mach_load(data, env)
}
if (fd.is_file(mcode_path)) {
mcode_json = text(fd.slurp(mcode_path))
return mach_eval_mcode('engine', mcode_json, env)
}
engine_path = core_path + '/internal/engine.cm'
engine_src = text(fd.slurp(engine_path))
engine_ast = analyze(engine_src, engine_path)

20621
internal/bootstrap.cm.mcode Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -76,14 +76,22 @@ function use_core(path) {
arrfor(array(core_extras), function(k) { env[k] = core_extras[k] })
if (sym) env.native = sym
// Check for pre-compiled .mach file first
var mach_path = core_path + '/' + path + '.mach'
// Check for pre-compiled .cm.mach file first
var mach_path = core_path + '/' + path + '.cm.mach'
if (fd.is_file(mach_path)) {
result = mach_load(fd.slurp(mach_path), env)
use_cache[cache_key] = result
return result
}
// Check for .cm.mcode JSON IR
var mcode_path = core_path + '/' + path + '.cm.mcode'
if (fd.is_file(mcode_path)) {
result = mach_eval_mcode('core:' + path, text(fd.slurp(mcode_path)), env)
use_cache[cache_key] = result
return result
}
// Fall back to source .cm file — compile at runtime
var file_path = core_path + '/' + path + MOD_EXT
if (fd.is_file(file_path)) {

41635
internal/engine.cm.mcode Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

139605
mcode.cm.mcode Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

168633
parse.cm.mcode Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

12003
qbe.cm.mcode Normal file

File diff suppressed because it is too large Load Diff

BIN
qbe.mach

Binary file not shown.

71286
qbe_emit.cm.mcode Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -1,4 +1,4 @@
// regen.cm — regenerate .mach bytecode files
// regen.cm — regenerate .cm.mcode files
// Run with: ./cell --core . regen.cm
var fd = use("fd")
@@ -10,15 +10,15 @@ var mcode = use("mcode")
var streamline = use("streamline")
var files = [
{src: "tokenize.cm", name: "tokenize", out: "tokenize.mach"},
{src: "parse.cm", name: "parse", out: "parse.mach"},
{src: "fold.cm", name: "fold", out: "fold.mach"},
{src: "mcode.cm", name: "mcode", out: "mcode.mach"},
{src: "streamline.cm", name: "streamline", out: "streamline.mach"},
{src: "qbe.cm", name: "qbe", out: "qbe.mach"},
{src: "qbe_emit.cm", name: "qbe_emit", out: "qbe_emit.mach"},
{src: "internal/bootstrap.cm", name: "bootstrap", out: "internal/bootstrap.mach"},
{src: "internal/engine.cm", name: "engine", out: "internal/engine.mach"}
{src: "tokenize.cm", name: "tokenize", out: "tokenize.cm.mcode"},
{src: "parse.cm", name: "parse", out: "parse.cm.mcode"},
{src: "fold.cm", name: "fold", out: "fold.cm.mcode"},
{src: "mcode.cm", name: "mcode", out: "mcode.cm.mcode"},
{src: "streamline.cm", name: "streamline", out: "streamline.cm.mcode"},
{src: "qbe.cm", name: "qbe", out: "qbe.cm.mcode"},
{src: "qbe_emit.cm", name: "qbe_emit", out: "qbe_emit.cm.mcode"},
{src: "internal/bootstrap.cm", name: "bootstrap", out: "internal/bootstrap.cm.mcode"},
{src: "internal/engine.cm", name: "engine", out: "internal/engine.cm.mcode"}
]
var i = 0
@@ -29,8 +29,7 @@ var ast = null
var folded = null
var compiled = null
var optimized = null
var mcode_json = null
var bytecode = null
var mcode_text = null
var f = null
var errs = null
var ei = 0
@@ -62,10 +61,9 @@ while (i < length(files)) {
folded = fold(ast)
compiled = mcode(folded)
optimized = streamline(compiled)
mcode_json = json.encode(optimized)
bytecode = mach_compile_mcode_bin(entry.name, mcode_json)
mcode_text = json.encode(optimized, null, 2)
f = fd.open(entry.out, "w")
fd.write(f, bytecode)
fd.write(f, mcode_text)
fd.close(f)
print(`wrote ${entry.out}`)
i = i + 1

View File

@@ -11,8 +11,9 @@
#include "cell_internal.h"
#include "cJSON.h"
#define BOOTSTRAP_MACH "internal/bootstrap.mach"
#define BOOTSTRAP_SRC "internal/bootstrap.cm"
#define BOOTSTRAP_MACH "internal/bootstrap.cm.mach"
#define BOOTSTRAP_MCODE "internal/bootstrap.cm.mcode"
#define BOOTSTRAP_SRC "internal/bootstrap.cm"
#define CELL_SHOP_DIR ".cell"
#define CELL_CORE_DIR "packages/core"
@@ -178,9 +179,14 @@ void script_startup(cell_rt *prt)
cell_rt *crt = JS_GetContextOpaque(js);
JS_FreeValue(js, js_blob_use(js));
// Load pre-compiled bootstrap bytecode (.mach)
// Load pre-compiled bootstrap (.cm.mach or .cm.mcode)
size_t boot_size;
char *boot_data = load_core_file(BOOTSTRAP_MACH, &boot_size);
int boot_is_mcode = 0;
if (!boot_data) {
boot_data = load_core_file(BOOTSTRAP_MCODE, &boot_size);
boot_is_mcode = 1;
}
if (!boot_data) {
printf("ERROR: Could not load bootstrap from %s!\n", core_path);
return;
@@ -218,7 +224,9 @@ void script_startup(cell_rt *prt)
// Run through MACH VM
crt->state = ACTOR_RUNNING;
JSValue v = JS_RunMachBin(js, (const uint8_t *)boot_data, boot_size, hidden_env);
JSValue v = boot_is_mcode
? JS_RunMachMcode(js, boot_data, boot_size, hidden_env)
: JS_RunMachBin(js, (const uint8_t *)boot_data, boot_size, hidden_env);
free(boot_data);
uncaught_exception(js, v);
crt->state = ACTOR_IDLE;
@@ -349,6 +357,11 @@ int cell_init(int argc, char **argv)
size_t boot_size;
char *boot_data = load_core_file(BOOTSTRAP_MACH, &boot_size);
int boot_is_mcode = 0;
if (!boot_data) {
boot_data = load_core_file(BOOTSTRAP_MCODE, &boot_size);
boot_is_mcode = 1;
}
if (!boot_data) {
printf("ERROR: Could not load bootstrap from %s\n", core_path);
return 1;
@@ -417,7 +430,9 @@ 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_RunMachBin(ctx, (const uint8_t *)boot_data, boot_size, hidden_env);
JSValue result = boot_is_mcode
? JS_RunMachMcode(ctx, boot_data, boot_size, hidden_env)
: JS_RunMachBin(ctx, (const uint8_t *)boot_data, boot_size, hidden_env);
free(boot_data);
int exit_code = 0;

View File

@@ -3166,6 +3166,29 @@ JSValue JS_RunMachBin(JSContext *ctx, const uint8_t *data, size_t size, JSValue
return result;
}
JSValue JS_RunMachMcode(JSContext *ctx, const char *json_str, size_t len, JSValue env) {
(void)len;
cJSON *mcode = cJSON_Parse(json_str);
if (!mcode)
return JS_ThrowSyntaxError(ctx, "failed to parse mcode JSON");
MachCode *mc = mach_compile_mcode(mcode);
cJSON_Delete(mcode);
if (!mc)
return JS_ThrowInternalError(ctx, "mcode compilation failed");
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;
}
void JS_DumpMachBin(JSContext *ctx, const uint8_t *data, size_t size, JSValue env) {
MachCode *mc = JS_DeserializeMachCode(data, size);
if (!mc) {

View File

@@ -995,6 +995,9 @@ struct JSCodeRegister *JS_LoadMachCode(JSContext *ctx, MachCode *mc, JSValue env
/* Deserialize and execute pre-compiled MACH binary bytecode. */
JSValue JS_RunMachBin(JSContext *ctx, const uint8_t *data, size_t size, JSValue env);
/* Parse mcode JSON IR, compile, and execute via register VM. */
JSValue JS_RunMachMcode(JSContext *ctx, const char *json_str, size_t len, JSValue env);
/* Dump disassembly of pre-compiled MACH binary bytecode. */
void JS_DumpMachBin(JSContext *ctx, const uint8_t *data, size_t size, JSValue env);

84002
streamline.cm.mcode Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

65282
tokenize.cm.mcode Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.