fix crash related to allocating in context heap
This commit is contained in:
@@ -30730,6 +30730,17 @@ typedef struct MachVarInfo {
|
||||
int is_const; /* 1 for def, function args; 0 for var */
|
||||
} MachVarInfo;
|
||||
|
||||
/* ---- Compile-time constant pool entry ---- */
|
||||
/* Stores raw data during compilation; converted to JSValues when building JSCodeRegister */
|
||||
typedef enum { MACH_CP_IMM, MACH_CP_STR } MachCPType;
|
||||
typedef struct {
|
||||
MachCPType type;
|
||||
union {
|
||||
JSValue val; /* immediate value (int, float) - no GC alloc */
|
||||
char *str; /* owned C string */
|
||||
};
|
||||
} MachCPoolEntry;
|
||||
|
||||
/* ---- Compiler state ---- */
|
||||
|
||||
typedef struct MachCompState {
|
||||
@@ -30740,8 +30751,8 @@ typedef struct MachCompState {
|
||||
int code_count;
|
||||
int code_capacity;
|
||||
|
||||
/* Constant pool */
|
||||
JSValue *cpool;
|
||||
/* Constant pool (raw entries, no GC objects) */
|
||||
MachCPoolEntry *cpool;
|
||||
int cpool_count;
|
||||
int cpool_capacity;
|
||||
|
||||
@@ -30811,54 +30822,64 @@ static void mach_free_reg_to(MachCompState *cs, int saved) {
|
||||
|
||||
/* Add a constant to the pool, return its index */
|
||||
static int mach_cpool_add(MachCompState *cs, JSValue val) {
|
||||
/* Check for duplicates (simple linear scan) */
|
||||
/* Check for duplicates (immediate values only) */
|
||||
for (int i = 0; i < cs->cpool_count; i++) {
|
||||
JSValue existing = cs->cpool[i];
|
||||
/* Compare by tag and value */
|
||||
if (JS_IsInt(val) && JS_IsInt(existing)) {
|
||||
if (JS_VALUE_GET_INT(val) == JS_VALUE_GET_INT(existing))
|
||||
MachCPoolEntry *e = &cs->cpool[i];
|
||||
if (e->type != MACH_CP_IMM) continue;
|
||||
if (JS_IsInt(val) && JS_IsInt(e->val)) {
|
||||
if (JS_VALUE_GET_INT(val) == JS_VALUE_GET_INT(e->val))
|
||||
return i;
|
||||
} else if (JS_VALUE_IS_TEXT(val) && JS_VALUE_IS_TEXT(existing)) {
|
||||
const char *a = JS_ToCString(cs->ctx, val);
|
||||
const char *b = JS_ToCString(cs->ctx, existing);
|
||||
int eq = a && b && strcmp(a, b) == 0;
|
||||
JS_FreeCString(cs->ctx, a);
|
||||
JS_FreeCString(cs->ctx, b);
|
||||
if (eq) return i;
|
||||
} else if (e->val == val) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (cs->cpool_count >= cs->cpool_capacity) {
|
||||
int new_cap = cs->cpool_capacity ? cs->cpool_capacity * 2 : 16;
|
||||
cs->cpool = sys_realloc(cs->cpool, new_cap * sizeof(JSValue));
|
||||
cs->cpool = sys_realloc(cs->cpool, new_cap * sizeof(MachCPoolEntry));
|
||||
cs->cpool_capacity = new_cap;
|
||||
}
|
||||
cs->cpool[cs->cpool_count] = val;
|
||||
cs->cpool[cs->cpool_count] = (MachCPoolEntry){ .type = MACH_CP_IMM, .val = val };
|
||||
return cs->cpool_count++;
|
||||
}
|
||||
|
||||
/* Add a string constant, return its cpool index */
|
||||
static int mach_cpool_add_str(MachCompState *cs, const char *str) {
|
||||
/* Check for existing identical string first (before allocating) */
|
||||
/* Check for existing identical string */
|
||||
for (int i = 0; i < cs->cpool_count; i++) {
|
||||
JSValue existing = cs->cpool[i];
|
||||
if (JS_VALUE_IS_TEXT(existing)) {
|
||||
const char *s = JS_ToCString(cs->ctx, existing);
|
||||
int eq = s && strcmp(s, str) == 0;
|
||||
JS_FreeCString(cs->ctx, s);
|
||||
if (eq) return i;
|
||||
}
|
||||
MachCPoolEntry *e = &cs->cpool[i];
|
||||
if (e->type == MACH_CP_STR && strcmp(e->str, str) == 0)
|
||||
return i;
|
||||
}
|
||||
JSValue val = JS_NewString(cs->ctx, str);
|
||||
if (cs->cpool_count >= cs->cpool_capacity) {
|
||||
int new_cap = cs->cpool_capacity ? cs->cpool_capacity * 2 : 16;
|
||||
cs->cpool = sys_realloc(cs->cpool, new_cap * sizeof(JSValue));
|
||||
cs->cpool = sys_realloc(cs->cpool, new_cap * sizeof(MachCPoolEntry));
|
||||
cs->cpool_capacity = new_cap;
|
||||
}
|
||||
cs->cpool[cs->cpool_count] = val;
|
||||
char *dup = sys_malloc(strlen(str) + 1);
|
||||
memcpy(dup, str, strlen(str) + 1);
|
||||
cs->cpool[cs->cpool_count] = (MachCPoolEntry){ .type = MACH_CP_STR, .str = dup };
|
||||
return cs->cpool_count++;
|
||||
}
|
||||
|
||||
/* Convert compile-time cpool entries to JSValue array for JSCodeRegister.
|
||||
Caller takes ownership of the returned array. Frees the raw entries.
|
||||
Strings are interned into stone memory (no GC allocation). */
|
||||
static JSValue *mach_materialize_cpool(JSContext *ctx, MachCPoolEntry *entries, int count) {
|
||||
if (count == 0) { sys_free(entries); return NULL; }
|
||||
JSValue *cpool = js_malloc_rt(count * sizeof(JSValue));
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (entries[i].type == MACH_CP_STR) {
|
||||
cpool[i] = js_key_new(ctx, entries[i].str);
|
||||
sys_free(entries[i].str);
|
||||
} else {
|
||||
cpool[i] = entries[i].val;
|
||||
}
|
||||
}
|
||||
sys_free(entries);
|
||||
return cpool;
|
||||
}
|
||||
|
||||
/* Add a variable */
|
||||
static void mach_add_var(MachCompState *cs, const char *name, int slot, int is_const) {
|
||||
if (cs->var_count >= cs->var_capacity) {
|
||||
@@ -31450,14 +31471,13 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
|
||||
fn_code->instr_count = child.code_count;
|
||||
fn_code->instructions = child.code;
|
||||
fn_code->cpool_count = child.cpool_count;
|
||||
fn_code->cpool = child.cpool;
|
||||
fn_code->cpool = mach_materialize_cpool(cs->ctx, child.cpool, child.cpool_count);
|
||||
fn_code->func_count = child.func_count;
|
||||
fn_code->functions = child.functions;
|
||||
|
||||
cJSON *fname = cJSON_GetObjectItem(node, "name");
|
||||
if (fname && cJSON_IsString(fname)) {
|
||||
fn_code->name = JS_NewString(cs->ctx, cJSON_GetStringValue(fname));
|
||||
fn_code->name = JS_CellStone(cs->ctx, fn_code->name);
|
||||
fn_code->name = js_key_new(cs->ctx, cJSON_GetStringValue(fname));
|
||||
} else {
|
||||
fn_code->name = JS_NULL;
|
||||
}
|
||||
@@ -31765,7 +31785,7 @@ static JSCodeRegister *mach_compile_program(MachCompState *cs, cJSON *ast, JSVal
|
||||
code->instr_count = cs->code_count;
|
||||
code->instructions = cs->code;
|
||||
code->cpool_count = cs->cpool_count;
|
||||
code->cpool = cs->cpool;
|
||||
code->cpool = mach_materialize_cpool(cs->ctx, cs->cpool, cs->cpool_count);
|
||||
code->func_count = cs->func_count;
|
||||
code->functions = cs->functions;
|
||||
code->name = JS_NULL;
|
||||
|
||||
Reference in New Issue
Block a user