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 |
|
| Instruction | Operands | Description |
|
||||||
|-------------|----------|-------------|
|
|-------------|----------|-------------|
|
||||||
| `access` | `dest, name` | Load variable (intrinsic or module environment) |
|
| `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 |
|
| `get` | `dest, level, slot` | Get closure variable from parent scope |
|
||||||
| `put` | `level, slot, src` | Set closure variable in 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")
|
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 fd = use_embed('internal_fd')
|
||||||
var js = use_embed('js')
|
var js = use_embed('js')
|
||||||
var crypto = use_embed('crypto')
|
var crypto = use_embed('crypto')
|
||||||
@@ -87,7 +60,7 @@ function boot_load(name) {
|
|||||||
}
|
}
|
||||||
mcode_blob = fd.slurp(mcode_path)
|
mcode_blob = fd.slurp(mcode_path)
|
||||||
mach_blob = mach_compile_mcode_bin(name, text(mcode_blob))
|
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
|
// 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 race = pronto.race
|
||||||
var sequence = pronto.sequence
|
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.actor = actor
|
||||||
runtime_env.is_actor = is_actor
|
runtime_env.is_actor = is_actor
|
||||||
runtime_env.log = log
|
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]
|
pstate = parent_states[length(parent_states) - 1 - _lv]
|
||||||
pslot = find_var_in_saved(pstate, name)
|
pslot = find_var_in_saved(pstate, name)
|
||||||
emit_3("put", dest, pslot, level)
|
emit_3("put", dest, pslot, level)
|
||||||
} else {
|
|
||||||
add_instr(["set_var", name, dest])
|
|
||||||
}
|
}
|
||||||
return dest
|
return dest
|
||||||
} else if (left_kind == ".") {
|
} else if (left_kind == ".") {
|
||||||
@@ -1486,9 +1484,6 @@ var mcode = function(ast) {
|
|||||||
return val_slot
|
return val_slot
|
||||||
}
|
}
|
||||||
val_slot = gen_expr(right, -1)
|
val_slot = gen_expr(right, -1)
|
||||||
if (level == -1) {
|
|
||||||
add_instr(["set_var", name, val_slot])
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
val_slot = gen_expr(right, -1)
|
val_slot = gen_expr(right, -1)
|
||||||
if (level > 0) {
|
if (level > 0) {
|
||||||
|
|||||||
11
qbe_emit.cm
11
qbe_emit.cm
@@ -976,17 +976,6 @@ var qbe_emit = function(ir, qbe, export_name) {
|
|||||||
continue
|
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] ---
|
// --- in [G] ---
|
||||||
|
|
||||||
if (op == "in") {
|
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) {
|
static void mach_link_code(JSContext *ctx, JSCodeRegister *code, JSValue env) {
|
||||||
if (!JS_IsNull(env) && !JS_IsStone(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->name_cstr ? code->name_cstr : "<unknown>",
|
||||||
code->filename_cstr ? code->filename_cstr : "<unknown>");
|
code->filename_cstr ? code->filename_cstr : "<unknown>");
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
JSGCRef env_ref;
|
JSGCRef env_ref;
|
||||||
JS_PushGCRef(ctx, &env_ref);
|
JS_PushGCRef(ctx, &env_ref);
|
||||||
@@ -864,7 +865,7 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
|||||||
DT(MACH_GOINVOKE),
|
DT(MACH_GOINVOKE),
|
||||||
DT(MACH_JMPNOTNULL),
|
DT(MACH_JMPNOTNULL),
|
||||||
DT(MACH_DISRUPT),
|
DT(MACH_DISRUPT),
|
||||||
DT(MACH_SET_VAR), DT(MACH_IN),
|
DT(MACH_IN),
|
||||||
DT(MACH_IS_ARRAY), DT(MACH_IS_FUNC),
|
DT(MACH_IS_ARRAY), DT(MACH_IS_FUNC),
|
||||||
DT(MACH_IS_RECORD), DT(MACH_IS_STONE),
|
DT(MACH_IS_RECORD), DT(MACH_IS_STONE),
|
||||||
DT(MACH_LENGTH), DT(MACH_IS_PROXY),
|
DT(MACH_LENGTH), DT(MACH_IS_PROXY),
|
||||||
@@ -2048,21 +2049,6 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
|||||||
VM_CASE(MACH_DISRUPT):
|
VM_CASE(MACH_DISRUPT):
|
||||||
goto 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) */
|
/* Has-property check (mcode name) */
|
||||||
VM_CASE(MACH_IN): {
|
VM_CASE(MACH_IN): {
|
||||||
JSValue key = frame->slots[b];
|
JSValue key = frame->slots[b];
|
||||||
@@ -2301,9 +2287,6 @@ static int mcode_reg_items(cJSON *it, cJSON **out) {
|
|||||||
/* goinvoke: [1]=frame only (no result) */
|
/* goinvoke: [1]=frame only (no result) */
|
||||||
if (!strcmp(op, "goinvoke")) { ADD(1); return c; }
|
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 */
|
/* setarg: [1]=call, [2]=arg_idx(const), [3]=val */
|
||||||
if (!strcmp(op, "setarg")) { ADD(1); ADD(3); return c; }
|
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) {
|
else if (strcmp(op, "disrupt") == 0) {
|
||||||
EM(MACH_ABC(MACH_DISRUPT, 0, 0, 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 */
|
/* Misc */
|
||||||
else if (strcmp(op, "in") == 0) {
|
else if (strcmp(op, "in") == 0) {
|
||||||
EM(MACH_ABC(MACH_IN, A1, A2, A3));
|
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) {
|
void cell_rt_set_native_env(JSContext *ctx, JSValue env) {
|
||||||
if (!JS_IsNull(env) && !JS_IsStone(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)
|
if (g_has_native_env)
|
||||||
JS_DeleteGCRef(ctx, &g_native_env_ref);
|
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");
|
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 --- */
|
/* --- in: key in obj --- */
|
||||||
|
|
||||||
JSValue cell_rt_in(JSContext *ctx, JSValue key, JSValue obj) {
|
JSValue cell_rt_in(JSContext *ctx, JSValue key, JSValue obj) {
|
||||||
|
|||||||
@@ -639,9 +639,6 @@ typedef enum MachOpcode {
|
|||||||
/* Error handling */
|
/* Error handling */
|
||||||
MACH_DISRUPT, /* trigger disruption (A only) */
|
MACH_DISRUPT, /* trigger disruption (A only) */
|
||||||
|
|
||||||
/* Variable storage */
|
|
||||||
MACH_SET_VAR, /* env/global[K(Bx)] = R(A) — store to var (ABx) */
|
|
||||||
|
|
||||||
/* Misc */
|
/* Misc */
|
||||||
MACH_IN, /* R(A) = (R(B) in R(C)) — has property (ABC) */
|
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_GOINVOKE] = "goinvoke",
|
||||||
[MACH_JMPNOTNULL] = "jmpnotnull",
|
[MACH_JMPNOTNULL] = "jmpnotnull",
|
||||||
[MACH_DISRUPT] = "disrupt",
|
[MACH_DISRUPT] = "disrupt",
|
||||||
[MACH_SET_VAR] = "set_var",
|
|
||||||
[MACH_IN] = "in",
|
[MACH_IN] = "in",
|
||||||
/* Extended type checks */
|
/* Extended type checks */
|
||||||
[MACH_IS_ARRAY] = "is_array",
|
[MACH_IS_ARRAY] = "is_array",
|
||||||
|
|||||||
@@ -1688,6 +1688,34 @@ int ctx_gc (JSContext *ctx, int allow_grow, size_t alloc_size) {
|
|||||||
scan += obj_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) */
|
/* Return old block (in poison mode, just poison it and leak) */
|
||||||
heap_block_free (rt, from_base, old_heap_size);
|
heap_block_free (rt, from_base, old_heap_size);
|
||||||
|
|
||||||
@@ -1960,6 +1988,7 @@ JSContext *JS_NewContext (JSRuntime *rt) {
|
|||||||
if (!ctx) return NULL;
|
if (!ctx) return NULL;
|
||||||
JS_AddIntrinsicBaseObjects (ctx);
|
JS_AddIntrinsicBaseObjects (ctx);
|
||||||
JS_AddIntrinsicRegExp (ctx);
|
JS_AddIntrinsicRegExp (ctx);
|
||||||
|
obj_set_stone (JS_VALUE_GET_RECORD (ctx->global_obj));
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1967,7 +1996,8 @@ JSContext *JS_NewContextWithHeapSize (JSRuntime *rt, size_t heap_size) {
|
|||||||
JSContext *ctx = JS_NewContextRawWithHeapSize (rt, heap_size);
|
JSContext *ctx = JS_NewContextRawWithHeapSize (rt, heap_size);
|
||||||
if (!ctx) return NULL;
|
if (!ctx) return NULL;
|
||||||
JS_AddIntrinsicBaseObjects (ctx);
|
JS_AddIntrinsicBaseObjects (ctx);
|
||||||
JS_AddIntrinsicRegExp (ctx);
|
JS_AddIntrinsicRegExp (ctx);
|
||||||
|
obj_set_stone (JS_VALUE_GET_RECORD (ctx->global_obj));
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user