wary jumps
This commit is contained in:
102
qbe_emit.cm
102
qbe_emit.cm
@@ -633,6 +633,15 @@ ${sr("gc", "%idx_slot")}
|
|||||||
${sr("a", "%fn_slot")}
|
${sr("a", "%fn_slot")}
|
||||||
%r =l call $cell_rt_frame(l %ctx, l %a, l %nargs)
|
%r =l call $cell_rt_frame(l %ctx, l %a, l %nargs)
|
||||||
${alloc_tail("%r")}
|
${alloc_tail("%r")}
|
||||||
|
}`
|
||||||
|
|
||||||
|
// apply(ctx, fp, dest, fn_slot, arg_slot)
|
||||||
|
h[] = `export function l $__apply_ss(l %ctx, l %fp, l %dest, l %fn_slot, l %arg_slot) ${lb}
|
||||||
|
@entry
|
||||||
|
${sr("a", "%fn_slot")}
|
||||||
|
${sr("b", "%arg_slot")}
|
||||||
|
%r =l call $cell_rt_apply(l %ctx, l %a, l %b)
|
||||||
|
${alloc_tail("%r")}
|
||||||
}`
|
}`
|
||||||
|
|
||||||
// goframe(ctx, fp, dest, fn_slot, nargs)
|
// goframe(ctx, fp, dest, fn_slot, nargs)
|
||||||
@@ -1023,6 +1032,18 @@ var qbe_emit = function(ir, qbe, export_name) {
|
|||||||
var jnn_lbl = null
|
var jnn_lbl = null
|
||||||
var jnn_idx = null
|
var jnn_idx = null
|
||||||
var jnn_backedge = false
|
var jnn_backedge = false
|
||||||
|
var wt_lbl = null
|
||||||
|
var wt_idx = null
|
||||||
|
var wt_backedge = false
|
||||||
|
var wf_lbl = null
|
||||||
|
var wf_idx = null
|
||||||
|
var wf_backedge = false
|
||||||
|
var jn_lbl = null
|
||||||
|
var jn_idx = null
|
||||||
|
var jn_backedge = false
|
||||||
|
var je_lbl = null
|
||||||
|
var je_idx = null
|
||||||
|
var je_backedge = false
|
||||||
var truthy = null
|
var truthy = null
|
||||||
var lhs_d = null
|
var lhs_d = null
|
||||||
var rhs_d = null
|
var rhs_d = null
|
||||||
@@ -2625,8 +2646,8 @@ var qbe_emit = function(ir, qbe, export_name) {
|
|||||||
jt_lbl = sanitize(a2)
|
jt_lbl = sanitize(a2)
|
||||||
jt_idx = label_pos[jt_lbl]
|
jt_idx = label_pos[jt_lbl]
|
||||||
jt_backedge = jt_idx != null && jt_idx < instr_idx
|
jt_backedge = jt_idx != null && jt_idx < instr_idx
|
||||||
truthy = emit_truthy_w(v)
|
emit(` %${p}_take =w ceql ${v}, ${text(qbe.js_true)}`)
|
||||||
emit(` jnz ${truthy}, @${p}_take, @${p}_f`)
|
emit(` jnz %${p}_take, @${p}_take, @${p}_f`)
|
||||||
emit(`@${p}_take`)
|
emit(`@${p}_take`)
|
||||||
if (jt_backedge) {
|
if (jt_backedge) {
|
||||||
emit_backedge_branch(jt_lbl)
|
emit_backedge_branch(jt_lbl)
|
||||||
@@ -2642,8 +2663,8 @@ var qbe_emit = function(ir, qbe, export_name) {
|
|||||||
jf_lbl = sanitize(a2)
|
jf_lbl = sanitize(a2)
|
||||||
jf_idx = label_pos[jf_lbl]
|
jf_idx = label_pos[jf_lbl]
|
||||||
jf_backedge = jf_idx != null && jf_idx < instr_idx
|
jf_backedge = jf_idx != null && jf_idx < instr_idx
|
||||||
truthy = emit_truthy_w(v)
|
emit(` %${p}_take =w ceql ${v}, ${text(qbe.js_false)}`)
|
||||||
emit(` jnz ${truthy}, @${p}_t, @${p}_take`)
|
emit(` jnz %${p}_take, @${p}_take, @${p}_t`)
|
||||||
emit(`@${p}_take`)
|
emit(`@${p}_take`)
|
||||||
if (jf_backedge) {
|
if (jf_backedge) {
|
||||||
emit_backedge_branch(jf_lbl)
|
emit_backedge_branch(jf_lbl)
|
||||||
@@ -2653,6 +2674,74 @@ var qbe_emit = function(ir, qbe, export_name) {
|
|||||||
emit(`@${p}_t`)
|
emit(`@${p}_t`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if (op == "wary_true") {
|
||||||
|
v = s_read(a1)
|
||||||
|
p = fresh()
|
||||||
|
wt_lbl = sanitize(a2)
|
||||||
|
wt_idx = label_pos[wt_lbl]
|
||||||
|
wt_backedge = wt_idx != null && wt_idx < instr_idx
|
||||||
|
truthy = emit_truthy_w(v)
|
||||||
|
emit(` jnz ${truthy}, @${p}_take, @${p}_f`)
|
||||||
|
emit(`@${p}_take`)
|
||||||
|
if (wt_backedge) {
|
||||||
|
emit_backedge_branch(wt_lbl)
|
||||||
|
} else {
|
||||||
|
emit(` jmp @${wt_lbl}`)
|
||||||
|
}
|
||||||
|
emit(`@${p}_f`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (op == "wary_false") {
|
||||||
|
v = s_read(a1)
|
||||||
|
p = fresh()
|
||||||
|
wf_lbl = sanitize(a2)
|
||||||
|
wf_idx = label_pos[wf_lbl]
|
||||||
|
wf_backedge = wf_idx != null && wf_idx < instr_idx
|
||||||
|
truthy = emit_truthy_w(v)
|
||||||
|
emit(` jnz ${truthy}, @${p}_t, @${p}_take`)
|
||||||
|
emit(`@${p}_take`)
|
||||||
|
if (wf_backedge) {
|
||||||
|
emit_backedge_branch(wf_lbl)
|
||||||
|
} else {
|
||||||
|
emit(` jmp @${wf_lbl}`)
|
||||||
|
}
|
||||||
|
emit(`@${p}_t`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (op == "jump_null") {
|
||||||
|
v = s_read(a1)
|
||||||
|
p = fresh()
|
||||||
|
jn_lbl = sanitize(a2)
|
||||||
|
jn_idx = label_pos[jn_lbl]
|
||||||
|
jn_backedge = jn_idx != null && jn_idx < instr_idx
|
||||||
|
emit(` %${p} =w ceql ${v}, ${text(qbe.js_null)}`)
|
||||||
|
if (jn_backedge) {
|
||||||
|
emit(` jnz %${p}, @${p}_bn, @${p}_n`)
|
||||||
|
emit(`@${p}_bn`)
|
||||||
|
emit_backedge_branch(jn_lbl)
|
||||||
|
} else {
|
||||||
|
emit(` jnz %${p}, @${jn_lbl}, @${p}_n`)
|
||||||
|
}
|
||||||
|
emit(`@${p}_n`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (op == "jump_empty") {
|
||||||
|
v = s_read(a1)
|
||||||
|
p = fresh()
|
||||||
|
je_lbl = sanitize(a2)
|
||||||
|
je_idx = label_pos[je_lbl]
|
||||||
|
je_backedge = je_idx != null && je_idx < instr_idx
|
||||||
|
emit(` %${p} =w ceql ${v}, ${text(qbe.js_empty_text)}`)
|
||||||
|
if (je_backedge) {
|
||||||
|
emit(` jnz %${p}, @${p}_bn, @${p}_n`)
|
||||||
|
emit(`@${p}_bn`)
|
||||||
|
emit_backedge_branch(je_lbl)
|
||||||
|
} else {
|
||||||
|
emit(` jnz %${p}, @${je_lbl}, @${p}_n`)
|
||||||
|
}
|
||||||
|
emit(`@${p}_n`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
if (op == "jump_not_null") {
|
if (op == "jump_not_null") {
|
||||||
v = s_read(a1)
|
v = s_read(a1)
|
||||||
p = fresh()
|
p = fresh()
|
||||||
@@ -2678,6 +2767,11 @@ var qbe_emit = function(ir, qbe, export_name) {
|
|||||||
emit_exc_check()
|
emit_exc_check()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if (op == "apply") {
|
||||||
|
emit(` %fp =l call $__apply_ss(l %ctx, l %fp, l ${text(a1)}, l ${text(a2)}, l ${text(a3)})`)
|
||||||
|
emit_exc_check()
|
||||||
|
continue
|
||||||
|
}
|
||||||
if (op == "setarg") {
|
if (op == "setarg") {
|
||||||
v = s_read(a1)
|
v = s_read(a1)
|
||||||
lhs = s_read(a3)
|
lhs = s_read(a3)
|
||||||
|
|||||||
@@ -639,6 +639,30 @@ static int cell_check_call_arity(JSContext *ctx, JSFunction *fn, int argc) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSValue cell_rt_apply(JSContext *ctx, JSValue fn_val, JSValue arg_val) {
|
||||||
|
if (!mist_is_function(fn_val))
|
||||||
|
return fn_val;
|
||||||
|
|
||||||
|
JSFunction *fn = JS_VALUE_GET_FUNCTION(fn_val);
|
||||||
|
if (!mist_is_array(arg_val)) {
|
||||||
|
if (!cell_check_call_arity(ctx, fn, 1))
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
return JS_CallInternal(ctx, fn_val, JS_NULL, 1, &arg_val, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSArray *arr = JS_VALUE_GET_ARRAY(arg_val);
|
||||||
|
int len = arr->len;
|
||||||
|
if (!cell_check_call_arity(ctx, fn, len))
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
if (len == 0)
|
||||||
|
return JS_CallInternal(ctx, fn_val, JS_NULL, 0, NULL, 0);
|
||||||
|
|
||||||
|
JSValue args[len];
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
args[i] = arr->values[i];
|
||||||
|
return JS_CallInternal(ctx, fn_val, JS_NULL, len, args, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void cell_copy_args_0_4(JSValue *fp, JSValue *argv, int copy) {
|
static inline void cell_copy_args_0_4(JSValue *fp, JSValue *argv, int copy) {
|
||||||
/* fp[0] is `this`; copy args into fp[1..4] */
|
/* fp[0] is `this`; copy args into fp[1..4] */
|
||||||
switch (copy) {
|
switch (copy) {
|
||||||
|
|||||||
Reference in New Issue
Block a user