faster mach compile

This commit is contained in:
2026-02-14 14:02:15 -06:00
parent f49ca530bb
commit e5fc04fecd
13 changed files with 11404 additions and 11404 deletions

View File

@@ -2068,8 +2068,8 @@ static int *mcode_compress_regs(cJSON *fobj, int *out_old_nr_slots,
int pinned = 1 + nr_args;
for (int i = 0; i < pinned; i++) { first_ref[i] = 0; last_ref[i] = n; }
for (int i = 0; i < n; i++) {
cJSON *it = cJSON_GetArrayItem(instrs, i);
{ cJSON *it = instrs ? instrs->child : NULL;
for (int i = 0; it; i++, it = it->next) {
if (!cJSON_IsArray(it)) continue;
cJSON *regs[MAX_REG_ITEMS];
int rc = mcode_reg_items(it, regs);
@@ -2079,7 +2079,7 @@ static int *mcode_compress_regs(cJSON *fobj, int *out_old_nr_slots,
if (first_ref[s] < 0) first_ref[s] = i;
last_ref[s] = i;
}
}
} }
/* Step 1a: extend live ranges for closure-captured slots.
If a child function captures a parent slot via get/put, that slot must
@@ -2101,8 +2101,8 @@ static int *mcode_compress_regs(cJSON *fobj, int *out_old_nr_slots,
typedef struct { const char *name; int pos; } LabelPos;
int lbl_cap = 32, lbl_n = 0;
LabelPos *lbls = sys_malloc(lbl_cap * sizeof(LabelPos));
for (int i = 0; i < n; i++) {
cJSON *it = cJSON_GetArrayItem(instrs, i);
{ cJSON *it = instrs ? instrs->child : NULL;
for (int i = 0; it; i++, it = it->next) {
if (cJSON_IsString(it)) {
if (lbl_n >= lbl_cap) {
lbl_cap *= 2;
@@ -2110,23 +2110,23 @@ static int *mcode_compress_regs(cJSON *fobj, int *out_old_nr_slots,
}
lbls[lbl_n++] = (LabelPos){it->valuestring, i};
}
}
} }
/* Find backward jumps and extend live ranges */
int changed = 1;
while (changed) {
changed = 0;
for (int i = 0; i < n; i++) {
cJSON *it = cJSON_GetArrayItem(instrs, i);
cJSON *it = instrs ? instrs->child : NULL;
for (int i = 0; it; i++, it = it->next) {
if (!cJSON_IsArray(it)) continue;
int sz = cJSON_GetArraySize(it);
if (sz < 3) continue;
const char *op = cJSON_GetArrayItem(it, 0)->valuestring;
const char *op = it->child->valuestring;
const char *target = NULL;
if (!strcmp(op, "jump")) {
target = cJSON_GetArrayItem(it, 1)->valuestring;
target = it->child->next->valuestring;
} else if (!strcmp(op, "jump_true") || !strcmp(op, "jump_false") ||
!strcmp(op, "jump_not_null")) {
target = cJSON_GetArrayItem(it, 2)->valuestring;
target = it->child->next->next->valuestring;
}
if (!target) continue;
/* Find label position */
@@ -2232,8 +2232,8 @@ static int *mcode_compress_regs(cJSON *fobj, int *out_old_nr_slots,
}
/* Step 3: apply remap to instructions */
for (int i = 0; i < n; i++) {
cJSON *it = cJSON_GetArrayItem(instrs, i);
{ cJSON *it = instrs ? instrs->child : NULL;
for (int i = 0; it; i++, it = it->next) {
if (!cJSON_IsArray(it)) continue;
cJSON *regs[MAX_REG_ITEMS];
int rc = mcode_reg_items(it, regs);
@@ -2243,7 +2243,7 @@ static int *mcode_compress_regs(cJSON *fobj, int *out_old_nr_slots,
cJSON_SetNumberValue(regs[j], remap[old]);
}
}
}
} }
/* Update nr_slots in the JSON */
cJSON_SetNumberValue(nr_slots_j, new_max);
@@ -2275,8 +2275,8 @@ static MachCode *mcode_lower_func(cJSON *fobj, const char *filename) {
s.flat_to_pc = sys_malloc((n + 1) * sizeof(int));
s.flat_count = n;
for (int i = 0; i < n; i++) {
cJSON *it = cJSON_GetArrayItem(instrs, i);
{ cJSON *it = instrs ? instrs->child : NULL;
for (int i = 0; it; i++, it = it->next) {
s.flat_to_pc[i] = s.code_count;
if (cJSON_IsString(it)) {
ml_label(&s, it->valuestring);
@@ -2576,7 +2576,7 @@ static MachCode *mcode_lower_func(cJSON *fobj, const char *filename) {
/* Unknown opcode — emit NOP */
EM(MACH_ABC(MACH_NOP, 0, 0, 0));
}
}
} }
/* Sentinel for flat_to_pc */
s.flat_to_pc[n] = s.code_count;
@@ -2715,34 +2715,32 @@ MachCode *mach_compile_mcode(cJSON *mcode_json) {
/* Scan main's instructions */
{
cJSON *main_instrs = cJSON_GetObjectItemCaseSensitive(main_obj, "instructions");
int mn = main_instrs ? cJSON_GetArraySize(main_instrs) : 0;
for (int i = 0; i < mn; i++) {
cJSON *it = cJSON_GetArrayItem(main_instrs, i);
cJSON *it = main_instrs ? main_instrs->child : NULL;
for (; it; it = it->next) {
if (!cJSON_IsArray(it) || cJSON_GetArraySize(it) < 3) continue;
const char *op = cJSON_GetArrayItem(it, 0)->valuestring;
const char *op = it->child->valuestring;
if (!strcmp(op, "function")) {
int child_idx = (int)cJSON_GetArrayItem(it, 2)->valuedouble;
int child_idx = (int)it->child->next->next->valuedouble;
if (child_idx >= 0 && child_idx < func_count)
parent_of[child_idx] = func_count; /* main */
}
}
}
/* Scan each function's instructions */
for (int fi = 0; fi < func_count; fi++) {
cJSON *fobj = cJSON_GetArrayItem(funcs_arr, fi);
{ cJSON *fobj = funcs_arr ? funcs_arr->child : NULL;
for (int fi = 0; fobj; fi++, fobj = fobj->next) {
cJSON *finstrs = cJSON_GetObjectItemCaseSensitive(fobj, "instructions");
int fn = finstrs ? cJSON_GetArraySize(finstrs) : 0;
for (int i = 0; i < fn; i++) {
cJSON *it = cJSON_GetArrayItem(finstrs, i);
cJSON *it = finstrs ? finstrs->child : NULL;
for (; it; it = it->next) {
if (!cJSON_IsArray(it) || cJSON_GetArraySize(it) < 3) continue;
const char *op = cJSON_GetArrayItem(it, 0)->valuestring;
const char *op = it->child->valuestring;
if (!strcmp(op, "function")) {
int child_idx = (int)cJSON_GetArrayItem(it, 2)->valuedouble;
int child_idx = (int)it->child->next->next->valuedouble;
if (child_idx >= 0 && child_idx < func_count)
parent_of[child_idx] = fi;
}
}
}
} }
/* Build per-function capture sets: for each function F, which of its slots
are captured by descendant functions via get/put. Captured slots must
@@ -2752,17 +2750,16 @@ MachCode *mach_compile_mcode(cJSON *mcode_json) {
memset(cap_slots, 0, (func_count + 1) * sizeof(int *));
memset(cap_counts, 0, (func_count + 1) * sizeof(int));
for (int fi = 0; fi < func_count; fi++) {
cJSON *fobj = cJSON_GetArrayItem(funcs_arr, fi);
{ cJSON *fobj = funcs_arr ? funcs_arr->child : NULL;
for (int fi = 0; fobj; fi++, fobj = fobj->next) {
cJSON *finstrs = cJSON_GetObjectItemCaseSensitive(fobj, "instructions");
int fn = finstrs ? cJSON_GetArraySize(finstrs) : 0;
for (int i = 0; i < fn; i++) {
cJSON *it = cJSON_GetArrayItem(finstrs, i);
cJSON *it = finstrs ? finstrs->child : NULL;
for (; it; it = it->next) {
if (!cJSON_IsArray(it) || cJSON_GetArraySize(it) < 4) continue;
const char *op = cJSON_GetArrayItem(it, 0)->valuestring;
const char *op = it->child->valuestring;
if (strcmp(op, "get") && strcmp(op, "put")) continue;
int slot = (int)cJSON_GetArrayItem(it, 2)->valuedouble;
int level = (int)cJSON_GetArrayItem(it, 3)->valuedouble;
int slot = (int)it->child->next->next->valuedouble;
int level = (int)it->child->next->next->next->valuedouble;
/* Walk up parent chain to find the ancestor whose slot is referenced */
int ancestor = fi;
for (int l = 0; l < level && ancestor >= 0; l++)
@@ -2778,7 +2775,7 @@ MachCode *mach_compile_mcode(cJSON *mcode_json) {
cap_slots[ancestor][cap_counts[ancestor]++] = slot;
}
}
}
} }
/* Compress registers for functions that exceed 8-bit slot limits.
Save remap tables so we can fix get/put parent_slot references. */
@@ -2786,9 +2783,11 @@ MachCode *mach_compile_mcode(cJSON *mcode_json) {
int *remap_sizes = sys_malloc((func_count + 1) * sizeof(int));
memset(remaps, 0, (func_count + 1) * sizeof(int *));
for (int i = 0; i < func_count; i++)
remaps[i] = mcode_compress_regs(cJSON_GetArrayItem(funcs_arr, i),
{ cJSON *fobj = funcs_arr ? funcs_arr->child : NULL;
for (int i = 0; fobj; i++, fobj = fobj->next)
remaps[i] = mcode_compress_regs(fobj,
&remap_sizes[i], cap_slots[i], cap_counts[i]);
}
/* main is stored at index func_count in our arrays */
remaps[func_count] = mcode_compress_regs(main_obj,
&remap_sizes[func_count], cap_slots[func_count], cap_counts[func_count]);
@@ -2800,16 +2799,15 @@ MachCode *mach_compile_mcode(cJSON *mcode_json) {
sys_free(cap_counts);
/* Fix up get/put parent_slot references using ancestor remap tables */
for (int fi = 0; fi < func_count; fi++) {
cJSON *fobj = cJSON_GetArrayItem(funcs_arr, fi);
{ cJSON *fobj = funcs_arr ? funcs_arr->child : NULL;
for (int fi = 0; fobj; fi++, fobj = fobj->next) {
cJSON *finstrs = cJSON_GetObjectItemCaseSensitive(fobj, "instructions");
int fn = finstrs ? cJSON_GetArraySize(finstrs) : 0;
for (int i = 0; i < fn; i++) {
cJSON *it = cJSON_GetArrayItem(finstrs, i);
cJSON *it = finstrs ? finstrs->child : NULL;
for (; it; it = it->next) {
if (!cJSON_IsArray(it) || cJSON_GetArraySize(it) < 4) continue;
const char *op = cJSON_GetArrayItem(it, 0)->valuestring;
const char *op = it->child->valuestring;
if (strcmp(op, "get") && strcmp(op, "put")) continue;
int level = (int)cJSON_GetArrayItem(it, 3)->valuedouble;
int level = (int)it->child->next->next->next->valuedouble;
/* Walk up parent chain 'level' times to find ancestor */
int ancestor = fi;
for (int l = 0; l < level && ancestor >= 0; l++) {
@@ -2818,14 +2816,14 @@ MachCode *mach_compile_mcode(cJSON *mcode_json) {
if (ancestor < 0) continue; /* unknown parent — leave as is */
int *anc_remap = remaps[ancestor];
if (!anc_remap) continue; /* ancestor wasn't compressed */
cJSON *slot_item = cJSON_GetArrayItem(it, 2);
cJSON *slot_item = it->child->next->next;
int old_slot = (int)slot_item->valuedouble;
if (old_slot >= 0 && old_slot < remap_sizes[ancestor]) {
int new_slot = anc_remap[old_slot];
cJSON_SetNumberValue(slot_item, new_slot);
}
}
}
} }
/* Free remap tables */
for (int i = 0; i <= func_count; i++)
@@ -2839,8 +2837,10 @@ MachCode *mach_compile_mcode(cJSON *mcode_json) {
if (func_count > 0) {
compiled = sys_malloc(func_count * sizeof(MachCode *));
memset(compiled, 0, func_count * sizeof(MachCode *));
for (int i = 0; i < func_count; i++)
compiled[i] = mcode_lower_func(cJSON_GetArrayItem(funcs_arr, i), filename);
{ cJSON *fobj = funcs_arr->child;
for (int i = 0; fobj; i++, fobj = fobj->next)
compiled[i] = mcode_lower_func(fobj, filename);
}
}
/* Compile main */