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")}
|
||||
%r =l call $cell_rt_frame(l %ctx, l %a, l %nargs)
|
||||
${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)
|
||||
@@ -1023,6 +1032,18 @@ var qbe_emit = function(ir, qbe, export_name) {
|
||||
var jnn_lbl = null
|
||||
var jnn_idx = null
|
||||
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 lhs_d = null
|
||||
var rhs_d = null
|
||||
@@ -2625,8 +2646,8 @@ var qbe_emit = function(ir, qbe, export_name) {
|
||||
jt_lbl = sanitize(a2)
|
||||
jt_idx = label_pos[jt_lbl]
|
||||
jt_backedge = jt_idx != null && jt_idx < instr_idx
|
||||
truthy = emit_truthy_w(v)
|
||||
emit(` jnz ${truthy}, @${p}_take, @${p}_f`)
|
||||
emit(` %${p}_take =w ceql ${v}, ${text(qbe.js_true)}`)
|
||||
emit(` jnz %${p}_take, @${p}_take, @${p}_f`)
|
||||
emit(`@${p}_take`)
|
||||
if (jt_backedge) {
|
||||
emit_backedge_branch(jt_lbl)
|
||||
@@ -2642,8 +2663,8 @@ var qbe_emit = function(ir, qbe, export_name) {
|
||||
jf_lbl = sanitize(a2)
|
||||
jf_idx = label_pos[jf_lbl]
|
||||
jf_backedge = jf_idx != null && jf_idx < instr_idx
|
||||
truthy = emit_truthy_w(v)
|
||||
emit(` jnz ${truthy}, @${p}_t, @${p}_take`)
|
||||
emit(` %${p}_take =w ceql ${v}, ${text(qbe.js_false)}`)
|
||||
emit(` jnz %${p}_take, @${p}_take, @${p}_t`)
|
||||
emit(`@${p}_take`)
|
||||
if (jf_backedge) {
|
||||
emit_backedge_branch(jf_lbl)
|
||||
@@ -2653,6 +2674,74 @@ var qbe_emit = function(ir, qbe, export_name) {
|
||||
emit(`@${p}_t`)
|
||||
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") {
|
||||
v = s_read(a1)
|
||||
p = fresh()
|
||||
@@ -2678,6 +2767,11 @@ var qbe_emit = function(ir, qbe, export_name) {
|
||||
emit_exc_check()
|
||||
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") {
|
||||
v = s_read(a1)
|
||||
lhs = s_read(a3)
|
||||
|
||||
@@ -639,6 +639,30 @@ static int cell_check_call_arity(JSContext *ctx, JSFunction *fn, int argc) {
|
||||
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) {
|
||||
/* fp[0] is `this`; copy args into fp[1..4] */
|
||||
switch (copy) {
|
||||
|
||||
Reference in New Issue
Block a user