faster mach compile
This commit is contained in:
104
source/mach.c
104
source/mach.c
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user