fix intrinsics and env
This commit is contained in:
File diff suppressed because it is too large
Load Diff
37804
boot/fold.cm.mcode
37804
boot/fold.cm.mcode
File diff suppressed because it is too large
Load Diff
52242
boot/mcode.cm.mcode
52242
boot/mcode.cm.mcode
File diff suppressed because it is too large
Load Diff
62291
boot/parse.cm.mcode
62291
boot/parse.cm.mcode
File diff suppressed because it is too large
Load Diff
21132
boot/tokenize.cm.mcode
21132
boot/tokenize.cm.mcode
File diff suppressed because it is too large
Load Diff
@@ -229,7 +229,6 @@ Function calls are decomposed into three instructions:
|
||||
| Instruction | Operands | Description |
|
||||
|-------------|----------|-------------|
|
||||
| `access` | `dest, name` | Load variable (intrinsic or module environment) |
|
||||
| `set_var` | `name, src` | Set top-level variable by name |
|
||||
| `get` | `dest, level, slot` | Get closure variable from parent scope |
|
||||
| `put` | `level, slot, src` | Set closure variable in parent scope |
|
||||
|
||||
|
||||
@@ -22,33 +22,6 @@ function use_embed(name) {
|
||||
return load_internal("js_core_" + name + "_use")
|
||||
}
|
||||
|
||||
// These duplicate C builtins from runtime.c, but are needed because the GC can
|
||||
// lose properties on the global object after compaction. The runtime_env provides
|
||||
// a stable way for modules to access them via env_record linking.
|
||||
function logical(val1) {
|
||||
if (val1 == 0 || val1 == false || val1 == "false" || val1 == null)
|
||||
return false;
|
||||
if (val1 == 1 || val1 == true || val1 == "true")
|
||||
return true;
|
||||
return null;
|
||||
}
|
||||
|
||||
function some(arr, pred) {
|
||||
return find(arr, pred) != null
|
||||
}
|
||||
|
||||
function every(arr, pred) {
|
||||
return find(arr, x => not(pred(x))) == null
|
||||
}
|
||||
|
||||
function starts_with(str, prefix) {
|
||||
return search(str, prefix) == 0
|
||||
}
|
||||
|
||||
function ends_with(str, suffix) {
|
||||
return search(str, suffix, -length(suffix)) != null
|
||||
}
|
||||
|
||||
var fd = use_embed('internal_fd')
|
||||
var js = use_embed('js')
|
||||
var crypto = use_embed('crypto')
|
||||
@@ -87,7 +60,7 @@ function boot_load(name) {
|
||||
}
|
||||
mcode_blob = fd.slurp(mcode_path)
|
||||
mach_blob = mach_compile_mcode_bin(name, text(mcode_blob))
|
||||
return mach_load(mach_blob, {use: use_embed})
|
||||
return mach_load(mach_blob, stone({use: use_embed}))
|
||||
}
|
||||
|
||||
// Load a pipeline module from cache; on miss compile from source via boot chain
|
||||
@@ -451,14 +424,6 @@ var parallel = pronto.parallel
|
||||
var race = pronto.race
|
||||
var sequence = pronto.sequence
|
||||
|
||||
// Fill runtime_env — includes duplicates of C builtins because the GC can
|
||||
// lose global object properties after compaction. Modules resolve these via
|
||||
// env_record, not the global.
|
||||
runtime_env.logical = logical
|
||||
runtime_env.some = some
|
||||
runtime_env.every = every
|
||||
runtime_env.starts_with = starts_with
|
||||
runtime_env.ends_with = ends_with
|
||||
runtime_env.actor = actor
|
||||
runtime_env.is_actor = is_actor
|
||||
runtime_env.log = log
|
||||
|
||||
5
mcode.cm
5
mcode.cm
@@ -1384,8 +1384,6 @@ var mcode = function(ast) {
|
||||
pstate = parent_states[length(parent_states) - 1 - _lv]
|
||||
pslot = find_var_in_saved(pstate, name)
|
||||
emit_3("put", dest, pslot, level)
|
||||
} else {
|
||||
add_instr(["set_var", name, dest])
|
||||
}
|
||||
return dest
|
||||
} else if (left_kind == ".") {
|
||||
@@ -1486,9 +1484,6 @@ var mcode = function(ast) {
|
||||
return val_slot
|
||||
}
|
||||
val_slot = gen_expr(right, -1)
|
||||
if (level == -1) {
|
||||
add_instr(["set_var", name, val_slot])
|
||||
}
|
||||
} else {
|
||||
val_slot = gen_expr(right, -1)
|
||||
if (level > 0) {
|
||||
|
||||
11
qbe_emit.cm
11
qbe_emit.cm
@@ -976,17 +976,6 @@ var qbe_emit = function(ir, qbe, export_name) {
|
||||
continue
|
||||
}
|
||||
|
||||
// --- set_var [G] ---
|
||||
|
||||
if (op == "set_var") {
|
||||
// IR: ["set_var", name_string, value_slot]
|
||||
v = s_read(a2)
|
||||
sl = intern_str(a1)
|
||||
emit(` call $cell_rt_set_var(l %ctx, l ${v}, l ${sl})`)
|
||||
refresh_fp()
|
||||
continue
|
||||
}
|
||||
|
||||
// --- in [G] ---
|
||||
|
||||
if (op == "in") {
|
||||
|
||||
@@ -86,9 +86,10 @@ static JSValue *mach_materialize_cpool(JSContext *ctx, MachCPoolEntry *entries,
|
||||
|
||||
static void mach_link_code(JSContext *ctx, JSCodeRegister *code, JSValue env) {
|
||||
if (!JS_IsNull(env) && !JS_IsStone(env)) {
|
||||
fprintf(stderr, "mach_link_code: WARNING env not stone (code=%s file=%s)\n",
|
||||
fprintf(stderr, "mach_link_code: ERROR env not stone (code=%s file=%s)\n",
|
||||
code->name_cstr ? code->name_cstr : "<unknown>",
|
||||
code->filename_cstr ? code->filename_cstr : "<unknown>");
|
||||
abort();
|
||||
}
|
||||
JSGCRef env_ref;
|
||||
JS_PushGCRef(ctx, &env_ref);
|
||||
@@ -864,7 +865,7 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
DT(MACH_GOINVOKE),
|
||||
DT(MACH_JMPNOTNULL),
|
||||
DT(MACH_DISRUPT),
|
||||
DT(MACH_SET_VAR), DT(MACH_IN),
|
||||
DT(MACH_IN),
|
||||
DT(MACH_IS_ARRAY), DT(MACH_IS_FUNC),
|
||||
DT(MACH_IS_RECORD), DT(MACH_IS_STONE),
|
||||
DT(MACH_LENGTH), DT(MACH_IS_PROXY),
|
||||
@@ -2048,21 +2049,6 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
VM_CASE(MACH_DISRUPT):
|
||||
goto disrupt;
|
||||
|
||||
/* Variable storage: env/global[K(Bx)] = R(A) */
|
||||
VM_CASE(MACH_SET_VAR): {
|
||||
int bx = MACH_GET_Bx(instr);
|
||||
JSValue key = code->cpool[bx];
|
||||
JSValue val = frame->slots[a];
|
||||
JSValue cur_env = JS_VALUE_GET_FUNCTION(frame->function)->u.reg.env_record;
|
||||
if (!JS_IsNull(cur_env)) {
|
||||
JS_SetProperty(ctx, cur_env, key, val);
|
||||
} else {
|
||||
JS_SetProperty(ctx, ctx->global_obj, key, val);
|
||||
}
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
VM_BREAK();
|
||||
}
|
||||
|
||||
/* Has-property check (mcode name) */
|
||||
VM_CASE(MACH_IN): {
|
||||
JSValue key = frame->slots[b];
|
||||
@@ -2301,9 +2287,6 @@ static int mcode_reg_items(cJSON *it, cJSON **out) {
|
||||
/* goinvoke: [1]=frame only (no result) */
|
||||
if (!strcmp(op, "goinvoke")) { ADD(1); return c; }
|
||||
|
||||
/* set_var: [1]=name(string), [2]=val */
|
||||
if (!strcmp(op, "set_var")) { ADD(2); return c; }
|
||||
|
||||
/* setarg: [1]=call, [2]=arg_idx(const), [3]=val */
|
||||
if (!strcmp(op, "setarg")) { ADD(1); ADD(3); return c; }
|
||||
|
||||
@@ -2873,12 +2856,6 @@ static MachCode *mcode_lower_func(cJSON *fobj, const char *filename) {
|
||||
else if (strcmp(op, "disrupt") == 0) {
|
||||
EM(MACH_ABC(MACH_DISRUPT, 0, 0, 0));
|
||||
}
|
||||
/* Variable storage */
|
||||
else if (strcmp(op, "set_var") == 0) {
|
||||
const char *vname = cJSON_GetArrayItem(it, 1)->valuestring;
|
||||
int val_reg = A2;
|
||||
EM(MACH_ABx(MACH_SET_VAR, val_reg, ml_cpool_str(&s, vname)));
|
||||
}
|
||||
/* Misc */
|
||||
else if (strcmp(op, "in") == 0) {
|
||||
EM(MACH_ABC(MACH_IN, A1, A2, A3));
|
||||
|
||||
@@ -267,7 +267,8 @@ static int g_has_native_env = 0;
|
||||
|
||||
void cell_rt_set_native_env(JSContext *ctx, JSValue env) {
|
||||
if (!JS_IsNull(env) && !JS_IsStone(env)) {
|
||||
fprintf(stderr, "cell_rt_set_native_env: WARNING env not stone\n");
|
||||
fprintf(stderr, "cell_rt_set_native_env: ERROR env not stone\n");
|
||||
abort();
|
||||
}
|
||||
if (g_has_native_env)
|
||||
JS_DeleteGCRef(ctx, &g_native_env_ref);
|
||||
@@ -585,13 +586,6 @@ void cell_rt_disrupt(JSContext *ctx) {
|
||||
JS_ThrowTypeError(ctx, "type error in native code");
|
||||
}
|
||||
|
||||
/* --- set_var: set a variable in env_record or global --- */
|
||||
|
||||
void cell_rt_set_var(JSContext *ctx, JSValue val, const char *name) {
|
||||
JSValue key = JS_NewString(ctx, name);
|
||||
JS_SetProperty(ctx, ctx->global_obj, key, val);
|
||||
}
|
||||
|
||||
/* --- in: key in obj --- */
|
||||
|
||||
JSValue cell_rt_in(JSContext *ctx, JSValue key, JSValue obj) {
|
||||
|
||||
@@ -639,9 +639,6 @@ typedef enum MachOpcode {
|
||||
/* Error handling */
|
||||
MACH_DISRUPT, /* trigger disruption (A only) */
|
||||
|
||||
/* Variable storage */
|
||||
MACH_SET_VAR, /* env/global[K(Bx)] = R(A) — store to var (ABx) */
|
||||
|
||||
/* Misc */
|
||||
MACH_IN, /* R(A) = (R(B) in R(C)) — has property (ABC) */
|
||||
|
||||
@@ -764,7 +761,6 @@ static const char *mach_opcode_names[MACH_OP_COUNT] = {
|
||||
[MACH_GOINVOKE] = "goinvoke",
|
||||
[MACH_JMPNOTNULL] = "jmpnotnull",
|
||||
[MACH_DISRUPT] = "disrupt",
|
||||
[MACH_SET_VAR] = "set_var",
|
||||
[MACH_IN] = "in",
|
||||
/* Extended type checks */
|
||||
[MACH_IS_ARRAY] = "is_array",
|
||||
|
||||
@@ -1688,6 +1688,34 @@ int ctx_gc (JSContext *ctx, int allow_grow, size_t alloc_size) {
|
||||
scan += obj_size;
|
||||
}
|
||||
|
||||
#ifdef VALIDATE_GC
|
||||
{
|
||||
JSRecord *grec = JS_VALUE_GET_RECORD(ctx->global_obj);
|
||||
uint32_t mask = (uint32_t)objhdr_cap56(grec->mist_hdr);
|
||||
for (uint32_t i = 1; i <= mask; i++) {
|
||||
JSValue k = grec->slots[i].key;
|
||||
if (!rec_key_is_empty(k) && !rec_key_is_tomb(k)) {
|
||||
if (!JS_IsPtr(k)) {
|
||||
fprintf(stderr, "VALIDATE_GC: global slot[%u] key is not a pointer (tag=0x%llx)\n",
|
||||
i, (unsigned long long)k);
|
||||
} else {
|
||||
void *kp = JS_VALUE_GET_PTR(k);
|
||||
if (!ptr_in_range(kp, to_base, to_free) && !is_ct_ptr(ctx, kp)) {
|
||||
fprintf(stderr, "VALIDATE_GC: global slot[%u] key=%p outside valid ranges\n", i, kp);
|
||||
}
|
||||
}
|
||||
JSValue v = grec->slots[i].val;
|
||||
if (JS_IsPtr(v)) {
|
||||
void *vp = JS_VALUE_GET_PTR(v);
|
||||
if (!ptr_in_range(vp, to_base, to_free) && !is_ct_ptr(ctx, vp)) {
|
||||
fprintf(stderr, "VALIDATE_GC: global slot[%u] val=%p outside valid ranges\n", i, vp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return old block (in poison mode, just poison it and leak) */
|
||||
heap_block_free (rt, from_base, old_heap_size);
|
||||
|
||||
@@ -1960,6 +1988,7 @@ JSContext *JS_NewContext (JSRuntime *rt) {
|
||||
if (!ctx) return NULL;
|
||||
JS_AddIntrinsicBaseObjects (ctx);
|
||||
JS_AddIntrinsicRegExp (ctx);
|
||||
obj_set_stone (JS_VALUE_GET_RECORD (ctx->global_obj));
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@@ -1967,7 +1996,8 @@ JSContext *JS_NewContextWithHeapSize (JSRuntime *rt, size_t heap_size) {
|
||||
JSContext *ctx = JS_NewContextRawWithHeapSize (rt, heap_size);
|
||||
if (!ctx) return NULL;
|
||||
JS_AddIntrinsicBaseObjects (ctx);
|
||||
JS_AddIntrinsicRegExp (ctx);
|
||||
JS_AddIntrinsicRegExp (ctx);
|
||||
obj_set_stone (JS_VALUE_GET_RECORD (ctx->global_obj));
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user