optimize
This commit is contained in:
105
mcode.cm
105
mcode.cm
@@ -88,6 +88,7 @@ var mcode = function(ast) {
|
||||
var s_cur_col = 0
|
||||
var s_filename = null
|
||||
var s_has_disruption = false
|
||||
var s_slot_types = {}
|
||||
|
||||
// Shared closure vars for binop helpers (avoids >4 param functions)
|
||||
var _bp_dest = 0
|
||||
@@ -116,7 +117,8 @@ var mcode = function(ast) {
|
||||
intrinsic_cache: s_intrinsic_cache,
|
||||
cur_line: s_cur_line,
|
||||
cur_col: s_cur_col,
|
||||
has_disruption: s_has_disruption
|
||||
has_disruption: s_has_disruption,
|
||||
slot_types: s_slot_types
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +140,7 @@ var mcode = function(ast) {
|
||||
s_cur_line = saved.cur_line
|
||||
s_cur_col = saved.cur_col
|
||||
s_has_disruption = saved.has_disruption
|
||||
s_slot_types = saved.slot_types
|
||||
}
|
||||
|
||||
// Slot allocation
|
||||
@@ -330,20 +333,47 @@ var mcode = function(ast) {
|
||||
return node.kind == "null"
|
||||
}
|
||||
|
||||
// Slot-type tracking helpers
|
||||
var slot_is_num = function(slot) {
|
||||
var t = s_slot_types[text(slot)]
|
||||
return t == "num" || t == "int"
|
||||
}
|
||||
|
||||
var slot_is_int = function(slot) {
|
||||
return s_slot_types[text(slot)] == "int"
|
||||
}
|
||||
|
||||
var slot_is_text = function(slot) {
|
||||
return s_slot_types[text(slot)] == "text"
|
||||
}
|
||||
|
||||
var mark_slot = function(slot, typ) {
|
||||
s_slot_types[text(slot)] = typ
|
||||
}
|
||||
|
||||
// emit_add_decomposed: emit type-dispatched add (text → concat, num → add)
|
||||
// reads _bp_dest, _bp_left, _bp_right, _bp_ln, _bp_rn from closure
|
||||
var emit_add_decomposed = function() {
|
||||
if (is_known_text(_bp_ln) && is_known_text(_bp_rn)) {
|
||||
emit_3("concat", _bp_dest, _bp_left, _bp_right)
|
||||
mark_slot(_bp_dest, "text")
|
||||
return null
|
||||
}
|
||||
if (is_known_number(_bp_ln) && is_known_number(_bp_rn)) {
|
||||
emit_3("add", _bp_dest, _bp_left, _bp_right)
|
||||
mark_slot(_bp_dest, "num")
|
||||
return null
|
||||
}
|
||||
// If either operand is a known number, concat is impossible
|
||||
if (is_known_number(_bp_ln) || is_known_number(_bp_rn)) {
|
||||
// If either operand is a known number (AST or slot), concat is impossible
|
||||
if (is_known_number(_bp_ln) || is_known_number(_bp_rn)
|
||||
|| slot_is_num(_bp_left) || slot_is_num(_bp_right)) {
|
||||
emit_numeric_binop("add")
|
||||
mark_slot(_bp_dest, "num")
|
||||
return null
|
||||
}
|
||||
if (slot_is_text(_bp_left) && slot_is_text(_bp_right)) {
|
||||
emit_3("concat", _bp_dest, _bp_left, _bp_right)
|
||||
mark_slot(_bp_dest, "text")
|
||||
return null
|
||||
}
|
||||
// Unknown types: emit full dispatch
|
||||
@@ -380,8 +410,10 @@ var mcode = function(ast) {
|
||||
// emit_numeric_binop: emit type-guarded numeric binary op
|
||||
// reads _bp_dest, _bp_left, _bp_right, _bp_ln, _bp_rn from closure
|
||||
var emit_numeric_binop = function(op_str) {
|
||||
if (is_known_number(_bp_ln) && is_known_number(_bp_rn)) {
|
||||
if ((is_known_number(_bp_ln) && is_known_number(_bp_rn))
|
||||
|| (slot_is_num(_bp_left) && slot_is_num(_bp_right))) {
|
||||
emit_3(op_str, _bp_dest, _bp_left, _bp_right)
|
||||
mark_slot(_bp_dest, "num")
|
||||
return null
|
||||
}
|
||||
var t0 = alloc_slot()
|
||||
@@ -399,6 +431,7 @@ var mcode = function(ast) {
|
||||
emit_log_error("cannot apply '" + _bp_op_sym + "': operands must be numbers")
|
||||
emit_0("disrupt")
|
||||
emit_label(done)
|
||||
mark_slot(_bp_dest, "num")
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -410,6 +443,26 @@ var mcode = function(ast) {
|
||||
var right = _bp_right
|
||||
var t0 = 0
|
||||
var t1 = 0
|
||||
|
||||
// Known-int fast path
|
||||
if ((is_known_int(_bp_ln) || slot_is_int(left))
|
||||
&& (is_known_int(_bp_rn) || slot_is_int(right))) {
|
||||
emit_3("eq_int", dest, left, right)
|
||||
return null
|
||||
}
|
||||
// Known-num fast path
|
||||
if ((is_known_number(_bp_ln) || slot_is_num(left))
|
||||
&& (is_known_number(_bp_rn) || slot_is_num(right))) {
|
||||
emit_3("eq_float", dest, left, right)
|
||||
return null
|
||||
}
|
||||
// Known-text fast path
|
||||
if ((is_known_text(_bp_ln) || slot_is_text(left))
|
||||
&& (is_known_text(_bp_rn) || slot_is_text(right))) {
|
||||
emit_3("eq_text", dest, left, right)
|
||||
return null
|
||||
}
|
||||
|
||||
var done = gen_label("eq_done")
|
||||
var not_int = gen_label("eq_ni")
|
||||
var not_num = gen_label("eq_nn")
|
||||
@@ -482,6 +535,26 @@ var mcode = function(ast) {
|
||||
var right = _bp_right
|
||||
var t0 = 0
|
||||
var t1 = 0
|
||||
|
||||
// Known-int fast path
|
||||
if ((is_known_int(_bp_ln) || slot_is_int(left))
|
||||
&& (is_known_int(_bp_rn) || slot_is_int(right))) {
|
||||
emit_3("ne_int", dest, left, right)
|
||||
return null
|
||||
}
|
||||
// Known-num fast path
|
||||
if ((is_known_number(_bp_ln) || slot_is_num(left))
|
||||
&& (is_known_number(_bp_rn) || slot_is_num(right))) {
|
||||
emit_3("ne_float", dest, left, right)
|
||||
return null
|
||||
}
|
||||
// Known-text fast path
|
||||
if ((is_known_text(_bp_ln) || slot_is_text(left))
|
||||
&& (is_known_text(_bp_rn) || slot_is_text(right))) {
|
||||
emit_3("ne_text", dest, left, right)
|
||||
return null
|
||||
}
|
||||
|
||||
var done = gen_label("ne_done")
|
||||
var not_ident = gen_label("ne_nid")
|
||||
var not_int = gen_label("ne_ni")
|
||||
@@ -563,12 +636,12 @@ var mcode = function(ast) {
|
||||
var right = _bp_right
|
||||
var t0 = 0
|
||||
var t1 = 0
|
||||
var left_is_int = is_known_int(_bp_ln)
|
||||
var left_is_num = is_known_number(_bp_ln)
|
||||
var left_is_text = is_known_text(_bp_ln)
|
||||
var right_is_int = is_known_int(_bp_rn)
|
||||
var right_is_num = is_known_number(_bp_rn)
|
||||
var right_is_text = is_known_text(_bp_rn)
|
||||
var left_is_int = is_known_int(_bp_ln) || slot_is_int(left)
|
||||
var left_is_num = is_known_number(_bp_ln) || slot_is_num(left)
|
||||
var left_is_text = is_known_text(_bp_ln) || slot_is_text(left)
|
||||
var right_is_int = is_known_int(_bp_rn) || slot_is_int(right)
|
||||
var right_is_num = is_known_number(_bp_rn) || slot_is_num(right)
|
||||
var right_is_text = is_known_text(_bp_rn) || slot_is_text(right)
|
||||
var not_num = null
|
||||
var done = null
|
||||
var err = null
|
||||
@@ -619,8 +692,9 @@ var mcode = function(ast) {
|
||||
|
||||
// emit_neg_decomposed: emit type-guarded negate
|
||||
var emit_neg_decomposed = function(dest, src, src_node) {
|
||||
if (is_known_number(src_node)) {
|
||||
if (is_known_number(src_node) || slot_is_num(src)) {
|
||||
emit_2("negate", dest, src)
|
||||
mark_slot(dest, "num")
|
||||
return null
|
||||
}
|
||||
var t0 = alloc_slot()
|
||||
@@ -635,6 +709,7 @@ var mcode = function(ast) {
|
||||
emit_log_error("cannot negate: operand must be a number")
|
||||
emit_0("disrupt")
|
||||
emit_label(done)
|
||||
mark_slot(dest, "num")
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -1794,6 +1869,7 @@ var mcode = function(ast) {
|
||||
if (kind == "number") {
|
||||
slot = target >= 0 ? target : alloc_slot()
|
||||
emit_const_num(slot, expr.number)
|
||||
mark_slot(slot, is_integer(expr.number) ? "int" : "num")
|
||||
return slot
|
||||
}
|
||||
if (kind == "text") {
|
||||
@@ -1803,6 +1879,7 @@ var mcode = function(ast) {
|
||||
val = ""
|
||||
}
|
||||
emit_const_str(slot, val)
|
||||
mark_slot(slot, "text")
|
||||
return slot
|
||||
}
|
||||
// Template literal
|
||||
@@ -1839,6 +1916,7 @@ var mcode = function(ast) {
|
||||
// Call format(fmt_str, array)
|
||||
result_slot = target >= 0 ? target : alloc_slot()
|
||||
emit_call(result_slot, fmt_func_slot, [fmt_str_slot, arr_slot])
|
||||
mark_slot(result_slot, "text")
|
||||
return result_slot
|
||||
}
|
||||
if (kind == "regexp") {
|
||||
@@ -1857,16 +1935,19 @@ var mcode = function(ast) {
|
||||
if (kind == "true") {
|
||||
slot = target >= 0 ? target : alloc_slot()
|
||||
emit_const_bool(slot, true)
|
||||
mark_slot(slot, "bool")
|
||||
return slot
|
||||
}
|
||||
if (kind == "false") {
|
||||
slot = target >= 0 ? target : alloc_slot()
|
||||
emit_const_bool(slot, false)
|
||||
mark_slot(slot, "bool")
|
||||
return slot
|
||||
}
|
||||
if (kind == "null") {
|
||||
slot = target >= 0 ? target : alloc_slot()
|
||||
emit_const_null(slot)
|
||||
mark_slot(slot, null)
|
||||
return slot
|
||||
}
|
||||
if (kind == "this") {
|
||||
@@ -2760,6 +2841,7 @@ var mcode = function(ast) {
|
||||
s_instructions = []
|
||||
s_vars = []
|
||||
s_intrinsic_cache = []
|
||||
s_slot_types = {}
|
||||
s_loop_break = null
|
||||
s_loop_continue = null
|
||||
s_label_map = {}
|
||||
@@ -2951,6 +3033,7 @@ var mcode = function(ast) {
|
||||
s_max_slot = 1
|
||||
s_label_counter = 0
|
||||
s_func_counter = 0
|
||||
s_slot_types = {}
|
||||
s_loop_break = null
|
||||
s_loop_continue = null
|
||||
s_label_map = {}
|
||||
|
||||
Reference in New Issue
Block a user