compile optimization
This commit is contained in:
199
mcode.cm
199
mcode.cm
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user