compile optimization

This commit is contained in:
2026-02-10 16:37:11 -06:00
parent 3d71f4a363
commit d75ce916d7
18 changed files with 1528 additions and 113 deletions

199
mcode.cm
View File

@@ -51,6 +51,13 @@ var mcode = function(ast) {
var s_cur_col = 0
var s_filename = null
// Shared closure vars for binop helpers (avoids >4 param functions)
var _bp_dest = 0
var _bp_left = 0
var _bp_right = 0
var _bp_ln = null
var _bp_rn = null
// State save/restore for nested function compilation
var save_state = function() {
return {
@@ -260,15 +267,19 @@ var mcode = function(ast) {
}
// emit_add_decomposed: int path -> text path -> float path -> disrupt
var emit_add_decomposed = function(dest, left, right, left_node, right_node) {
// reads _bp_dest, _bp_left, _bp_right, _bp_ln, _bp_rn from closure
var emit_add_decomposed = function() {
var dest = _bp_dest
var left = _bp_left
var right = _bp_right
var t0 = 0
var t1 = 0
var left_is_int = is_known_int(left_node)
var left_is_text = is_known_text(left_node)
var left_is_num = is_known_number(left_node)
var right_is_int = is_known_int(right_node)
var right_is_text = is_known_text(right_node)
var right_is_num = is_known_number(right_node)
var left_is_int = is_known_int(_bp_ln)
var left_is_text = is_known_text(_bp_ln)
var left_is_num = is_known_number(_bp_ln)
var right_is_int = is_known_int(_bp_rn)
var right_is_text = is_known_text(_bp_rn)
var right_is_num = is_known_number(_bp_rn)
var not_int = null
var not_text = null
var done = null
@@ -346,13 +357,17 @@ var mcode = function(ast) {
}
// emit_numeric_binop: int path -> float path -> disrupt
var emit_numeric_binop = function(int_op, float_op, dest, left, right, left_node, right_node) {
// reads _bp_dest, _bp_left, _bp_right, _bp_ln, _bp_rn from closure
var emit_numeric_binop = function(int_op, float_op) {
var dest = _bp_dest
var left = _bp_left
var right = _bp_right
var t0 = 0
var t1 = 0
var left_is_int = is_known_int(left_node)
var left_is_num = is_known_number(left_node)
var right_is_int = is_known_int(right_node)
var right_is_num = is_known_number(right_node)
var left_is_int = is_known_int(_bp_ln)
var left_is_num = is_known_number(_bp_ln)
var right_is_int = is_known_int(_bp_rn)
var right_is_num = is_known_number(_bp_rn)
var not_int = null
var done = null
var err = null
@@ -404,7 +419,11 @@ var mcode = function(ast) {
}
// emit_eq_decomposed: identical -> int -> float -> text -> null -> bool -> mismatch(false)
var emit_eq_decomposed = function(dest, left, right, left_node, right_node) {
// reads _bp_dest, _bp_left, _bp_right from closure
var emit_eq_decomposed = function() {
var dest = _bp_dest
var left = _bp_left
var right = _bp_right
var t0 = 0
var t1 = 0
var done = gen_label("eq_done")
@@ -472,7 +491,11 @@ var mcode = function(ast) {
}
// emit_ne_decomposed: identical -> int -> float -> text -> null -> bool -> mismatch(true)
var emit_ne_decomposed = function(dest, left, right, left_node, right_node) {
// reads _bp_dest, _bp_left, _bp_right from closure
var emit_ne_decomposed = function() {
var dest = _bp_dest
var left = _bp_left
var right = _bp_right
var t0 = 0
var t1 = 0
var done = gen_label("ne_done")
@@ -549,15 +572,19 @@ var mcode = function(ast) {
}
// emit_relational: int -> float -> text -> disrupt
var emit_relational = function(int_op, float_op, text_op, dest, left, right, left_node, right_node) {
// reads _bp_dest, _bp_left, _bp_right, _bp_ln, _bp_rn from closure
var emit_relational = function(int_op, float_op, text_op) {
var dest = _bp_dest
var left = _bp_left
var right = _bp_right
var t0 = 0
var t1 = 0
var left_is_int = is_known_int(left_node)
var left_is_num = is_known_number(left_node)
var left_is_text = is_known_text(left_node)
var right_is_int = is_known_int(right_node)
var right_is_num = is_known_number(right_node)
var right_is_text = is_known_text(right_node)
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 not_int = null
var not_num = null
var done = null
@@ -654,29 +681,33 @@ var mcode = function(ast) {
}
// Central router: maps op string to decomposition helper
var emit_binop = function(op_str, dest, left, right, left_node, right_node) {
// Sets _bp_* closure vars then calls helper with reduced args
var emit_binop = function(op_str, dest, left, right) {
_bp_dest = dest
_bp_left = left
_bp_right = right
if (op_str == "add") {
emit_add_decomposed(dest, left, right, left_node, right_node)
emit_add_decomposed()
} else if (op_str == "subtract") {
emit_numeric_binop("sub_int", "sub_float", dest, left, right, left_node, right_node)
emit_numeric_binop("sub_int", "sub_float")
} else if (op_str == "multiply") {
emit_numeric_binop("mul_int", "mul_float", dest, left, right, left_node, right_node)
emit_numeric_binop("mul_int", "mul_float")
} else if (op_str == "divide") {
emit_numeric_binop("div_int", "div_float", dest, left, right, left_node, right_node)
emit_numeric_binop("div_int", "div_float")
} else if (op_str == "modulo") {
emit_numeric_binop("mod_int", "mod_float", dest, left, right, left_node, right_node)
emit_numeric_binop("mod_int", "mod_float")
} else if (op_str == "eq") {
emit_eq_decomposed(dest, left, right, left_node, right_node)
emit_eq_decomposed()
} else if (op_str == "ne") {
emit_ne_decomposed(dest, left, right, left_node, right_node)
emit_ne_decomposed()
} else if (op_str == "lt") {
emit_relational("lt_int", "lt_float", "lt_text", dest, left, right, left_node, right_node)
emit_relational("lt_int", "lt_float", "lt_text")
} else if (op_str == "le") {
emit_relational("le_int", "le_float", "le_text", dest, left, right, left_node, right_node)
emit_relational("le_int", "le_float", "le_text")
} else if (op_str == "gt") {
emit_relational("gt_int", "gt_float", "gt_text", dest, left, right, left_node, right_node)
emit_relational("gt_int", "gt_float", "gt_text")
} else if (op_str == "ge") {
emit_relational("ge_int", "ge_float", "ge_text", dest, left, right, left_node, right_node)
emit_relational("ge_int", "ge_float", "ge_text")
} else {
// Passthrough for bitwise, pow, in, etc.
emit_3(op_str, dest, left, right)
@@ -685,19 +716,31 @@ var mcode = function(ast) {
}
var emit_get_prop = function(dest, obj, prop) {
add_instr(["load", dest, obj, prop])
add_instr(["load_field", dest, obj, prop])
}
var emit_set_prop = function(obj, prop, val) {
add_instr(["store", obj, val, prop])
add_instr(["store_field", obj, val, prop])
}
var emit_get_elem = function(dest, obj, idx) {
emit_3("load", dest, obj, idx)
var emit_get_elem = function(dest, obj, idx, access_kind) {
if (access_kind == "index") {
emit_3("load_index", dest, obj, idx)
} else if (access_kind == "field") {
emit_3("load_field", dest, obj, idx)
} else {
emit_3("load_dynamic", dest, obj, idx)
}
}
var emit_set_elem = function(obj, idx, val) {
emit_3("store", obj, val, idx)
var emit_set_elem = function(obj, idx, val, access_kind) {
if (access_kind == "index") {
emit_3("store_index", obj, val, idx)
} else if (access_kind == "field") {
emit_3("store_field", obj, val, idx)
} else {
emit_3("store_dynamic", obj, val, idx)
}
}
var emit_call = function(dest, func_slot, args) {
@@ -718,23 +761,37 @@ var mcode = function(ast) {
}
var emit_call_method = function(dest, obj, prop, args) {
var instr = ["callmethod", dest, obj, prop]
var method_slot = alloc_slot()
add_instr(["load_field", method_slot, obj, prop])
var argc = length(args)
var frame_slot = alloc_slot()
emit_3("frame", frame_slot, method_slot, argc)
emit_3("setarg", frame_slot, 0, obj)
var arg_idx = 1
var _i = 0
while (_i < length(args)) {
push(instr, args[_i])
while (_i < argc) {
emit_3("setarg", frame_slot, arg_idx, args[_i])
arg_idx = arg_idx + 1
_i = _i + 1
}
add_instr(instr)
emit_2("invoke", frame_slot, dest)
}
var emit_call_method_dyn = function(dest, obj, key_reg, args) {
var instr = ["callmethod_dyn", dest, obj, key_reg]
var method_slot = alloc_slot()
emit_3("load_dynamic", method_slot, obj, key_reg)
var argc = length(args)
var frame_slot = alloc_slot()
emit_3("frame", frame_slot, method_slot, argc)
emit_3("setarg", frame_slot, 0, obj)
var arg_idx = 1
var _i = 0
while (_i < length(args)) {
push(instr, args[_i])
while (_i < argc) {
emit_3("setarg", frame_slot, arg_idx, args[_i])
arg_idx = arg_idx + 1
_i = _i + 1
}
add_instr(instr)
emit_2("invoke", frame_slot, dest)
}
var emit_go_call = function(func_slot, args) {
@@ -920,7 +977,9 @@ var mcode = function(ast) {
if (op == null) {
op = "add"
}
emit_binop(op, dest, left_slot, right_slot, left, right)
_bp_ln = left
_bp_rn = right
emit_binop(op, dest, left_slot, right_slot)
return dest
}
@@ -972,7 +1031,9 @@ var mcode = function(ast) {
}
right_slot = gen_expr(right, -1)
dest = alloc_slot()
emit_binop(op, dest, left_slot, right_slot, null, right)
_bp_ln = null
_bp_rn = right
emit_binop(op, dest, left_slot, right_slot)
if (level == 0) {
local = find_var(name)
if (local >= 0) {
@@ -995,7 +1056,9 @@ var mcode = function(ast) {
emit_get_prop(old_val, obj_slot, prop)
right_slot = gen_expr(right, -1)
dest = alloc_slot()
emit_binop(op, dest, old_val, right_slot, null, right)
_bp_ln = null
_bp_rn = right
emit_binop(op, dest, old_val, right_slot)
emit_set_prop(obj_slot, prop, dest)
return dest
} else if (left_kind == "[") {
@@ -1004,11 +1067,13 @@ var mcode = function(ast) {
obj_slot = gen_expr(obj, -1)
idx_slot = gen_expr(idx_expr, -1)
old_val = alloc_slot()
emit_get_elem(old_val, obj_slot, idx_slot)
emit_get_elem(old_val, obj_slot, idx_slot, left.access_kind)
right_slot = gen_expr(right, -1)
dest = alloc_slot()
emit_binop(op, dest, old_val, right_slot, null, right)
emit_set_elem(obj_slot, idx_slot, dest)
_bp_ln = null
_bp_rn = right
emit_binop(op, dest, old_val, right_slot)
emit_set_elem(obj_slot, idx_slot, dest, left.access_kind)
return dest
}
return -1
@@ -1081,7 +1146,7 @@ var mcode = function(ast) {
idx_expr = left.right
obj_slot = gen_expr(obj, -1)
idx_slot = gen_expr(idx_expr, -1)
emit_set_elem(obj_slot, idx_slot, val_slot)
emit_set_elem(obj_slot, idx_slot, val_slot, left.access_kind)
}
return val_slot
}
@@ -1301,7 +1366,7 @@ var mcode = function(ast) {
obj_slot = gen_expr(obj, -1)
idx_slot = gen_expr(idx, -1)
slot = alloc_slot()
emit_get_elem(slot, obj_slot, idx_slot)
emit_get_elem(slot, obj_slot, idx_slot, expr.access_kind)
return slot
}
@@ -1357,7 +1422,9 @@ var mcode = function(ast) {
a0 = gen_expr(args_list[0], -1)
a1 = gen_expr(args_list[1], -1)
d = alloc_slot()
emit_binop(mop, d, a0, a1, args_list[0], args_list[1])
_bp_ln = args_list[0]
_bp_rn = args_list[1]
emit_binop(mop, d, a0, a1)
return d
}
@@ -1442,7 +1509,9 @@ var mcode = function(ast) {
emit_access_intrinsic(old_slot, name)
}
new_slot = alloc_slot()
emit_binop(arith_op, new_slot, old_slot, one_slot, null, one_node)
_bp_ln = null
_bp_rn = one_node
emit_binop(arith_op, new_slot, old_slot, one_slot)
if (level == 0) {
local = find_var(name)
if (local >= 0) {
@@ -1462,7 +1531,9 @@ var mcode = function(ast) {
old_slot = alloc_slot()
emit_get_prop(old_slot, obj_slot, prop)
new_slot = alloc_slot()
emit_binop(arith_op, new_slot, old_slot, one_slot, null, one_node)
_bp_ln = null
_bp_rn = one_node
emit_binop(arith_op, new_slot, old_slot, one_slot)
emit_set_prop(obj_slot, prop, new_slot)
return postfix ? old_slot : new_slot
} else if (operand_kind == "[") {
@@ -1471,10 +1542,12 @@ var mcode = function(ast) {
obj_slot = gen_expr(obj, -1)
idx_slot = gen_expr(idx_expr, -1)
old_slot = alloc_slot()
emit_get_elem(old_slot, obj_slot, idx_slot)
emit_get_elem(old_slot, obj_slot, idx_slot, operand.access_kind)
new_slot = alloc_slot()
emit_binop(arith_op, new_slot, old_slot, one_slot, null, one_node)
emit_set_elem(obj_slot, idx_slot, new_slot)
_bp_ln = null
_bp_rn = one_node
emit_binop(arith_op, new_slot, old_slot, one_slot)
emit_set_elem(obj_slot, idx_slot, new_slot, operand.access_kind)
return postfix ? old_slot : new_slot
}
}
@@ -1911,7 +1984,9 @@ var mcode = function(ast) {
case_expr = case_node.expression
case_val = gen_expr(case_expr, -1)
cmp_slot = alloc_slot()
emit_binop("eq", cmp_slot, switch_val, case_val, null, case_expr)
_bp_ln = null
_bp_rn = case_expr
emit_binop("eq", cmp_slot, switch_val, case_val)
emit_jump_cond("jump_true", cmp_slot, case_label)
push(case_labels, case_label)
}