From c0b4e70eb2a5c602e26ee7578479c52f0ed3a83b Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Mon, 9 Feb 2026 18:32:41 -0600 Subject: [PATCH] fix two gc bugs --- mcode.cm | 550 ++++++++++++++++++++++++++++------------------- source/mach.c | 1 + source/runtime.c | 10 +- 3 files changed, 343 insertions(+), 218 deletions(-) diff --git a/mcode.cm b/mcode.cm index 6bf8c2ba..6b444b85 100644 --- a/mcode.cm +++ b/mcode.cm @@ -134,8 +134,9 @@ var mcode = function(ast) { return null } var _i = 0 + var scope = null while (_i < length(s_scopes)) { - var scope = s_scopes[_i] + scope = s_scopes[_i] if (scope.function_nr == fn_nr) { return scope } @@ -319,8 +320,11 @@ var mcode = function(ast) { return null } var _i = 0 + var name = null + var slot = 0 + var lit = null while (_i < length(intrinsics)) { - var name = intrinsics[_i] + name = intrinsics[_i] if (name == null || length(s_intrinsic_cache) >= 64) { _i = _i + 1 continue @@ -329,8 +333,8 @@ var mcode = function(ast) { _i = _i + 1 continue } - var slot = alloc_slot() - var lit = {kind: "name", name: name, make: "intrinsic"} + slot = alloc_slot() + lit = {kind: "name", name: name, make: "intrinsic"} add_instr(["access", slot, lit]) push(s_intrinsic_cache, {name: name, slot: slot}) _i = _i + 1 @@ -345,21 +349,26 @@ var mcode = function(ast) { } var keys = array(scope) var _i = 0 + var name = null + var v = null + var make = null + var is_const = false + var slot = 0 while (_i < length(keys)) { - var name = keys[_i] + name = keys[_i] if (name == "function_nr" || name == "nr_close_slots") { _i = _i + 1 continue } - var v = scope[name] - var make = v.make + v = scope[name] + make = v.make if (make == null || make == "input") { _i = _i + 1 continue } if (find_var(name) < 0) { - var is_const = (make == "def" || make == "function") - var slot = 1 + s_nr_args + s_nr_local_slots + is_const = (make == "def" || make == "function") + slot = 1 + s_nr_args + s_nr_local_slots s_nr_local_slots = s_nr_local_slots + 1 add_var(name, slot, is_const) if (v.closure == true) { @@ -398,38 +407,43 @@ var mcode = function(ast) { var kind = node.kind var left = node.left var right = node.right + var end_label = null + var left_slot = 0 + var right_slot = 0 + var dest = 0 + var op = null if (kind == "&&") { - var end_label = gen_label("and_end") - var left_slot = gen_expr(left, -1) - var dest = alloc_slot() + end_label = gen_label("and_end") + left_slot = gen_expr(left, -1) + dest = alloc_slot() emit_2("move", dest, left_slot) emit_jump_cond("jump_false", dest, end_label) - var right_slot = gen_expr(right, -1) + right_slot = gen_expr(right, -1) emit_2("move", dest, right_slot) emit_label(end_label) return dest } if (kind == "||") { - var end_label = gen_label("or_end") - var left_slot = gen_expr(left, -1) - var dest = alloc_slot() + end_label = gen_label("or_end") + left_slot = gen_expr(left, -1) + dest = alloc_slot() emit_2("move", dest, left_slot) emit_jump_cond("jump_true", dest, end_label) - var right_slot = gen_expr(right, -1) + right_slot = gen_expr(right, -1) emit_2("move", dest, right_slot) emit_label(end_label) return dest } if (kind == "??") { - var end_label = gen_label("nullish_end") - var left_slot = gen_expr(left, -1) - var dest = alloc_slot() + end_label = gen_label("nullish_end") + left_slot = gen_expr(left, -1) + dest = alloc_slot() emit_2("move", dest, left_slot) emit_jump_cond("jump_not_null", dest, end_label) - var right_slot = gen_expr(right, -1) + right_slot = gen_expr(right, -1) emit_2("move", dest, right_slot) emit_label(end_label) return dest @@ -442,10 +456,10 @@ var mcode = function(ast) { } // Standard binary ops - var left_slot = gen_expr(left, -1) - var right_slot = gen_expr(right, -1) - var dest = alloc_slot() - var op = binop_map[kind] + left_slot = gen_expr(left, -1) + right_slot = gen_expr(right, -1) + dest = alloc_slot() + op = binop_map[kind] if (op == null) { op = "add" } @@ -461,66 +475,81 @@ var mcode = function(ast) { var left = node.left var right = node.right var left_kind = left.kind + var name = null + var level = 0 + var left_slot = 0 + var local = 0 + var _lv = 0 + var pstate = null + var pslot = 0 + var right_slot = 0 + var dest = 0 + var obj = null + var prop = null + var obj_slot = 0 + var old_val = 0 + var idx_expr = null + var idx_slot = 0 if (left_kind == "name") { - var name = left.name - var level = left.level + name = left.name + level = left.level if (level == null) { level = -1 } - var left_slot = alloc_slot() + left_slot = alloc_slot() if (level == 0 || level == -1) { - var local = find_var(name) + local = find_var(name) if (local >= 0) { emit_2("move", left_slot, local) level = 0 } } if (level > 0) { - var _lv = level - 1 - var pstate = parent_states[length(parent_states) - 1 - _lv] - var pslot = find_var_in_saved(pstate, name) + _lv = level - 1 + pstate = parent_states[length(parent_states) - 1 - _lv] + pslot = find_var_in_saved(pstate, name) emit_3("get", left_slot, pslot, level) } else if (level == -1) { emit_access_intrinsic(left_slot, name) } - var right_slot = gen_expr(right, -1) - var dest = alloc_slot() + right_slot = gen_expr(right, -1) + dest = alloc_slot() emit_3(op, dest, left_slot, right_slot) if (level == 0) { - var local = find_var(name) + local = find_var(name) if (local >= 0) { emit_2("move", local, dest) } } else if (level > 0) { - var _lv = level - 1 - var pstate = parent_states[length(parent_states) - 1 - _lv] - var pslot = find_var_in_saved(pstate, name) + _lv = level - 1 + pstate = parent_states[length(parent_states) - 1 - _lv] + pslot = find_var_in_saved(pstate, name) emit_3("put", dest, pslot, level) } else { add_instr(["set_var", name, dest]) } return dest } else if (left_kind == ".") { - var obj = left.left - var prop = left.right - var obj_slot = gen_expr(obj, -1) - var old_val = alloc_slot() + obj = left.left + prop = left.right + obj_slot = gen_expr(obj, -1) + old_val = alloc_slot() emit_get_prop(old_val, obj_slot, prop) - var right_slot = gen_expr(right, -1) - var dest = alloc_slot() + right_slot = gen_expr(right, -1) + dest = alloc_slot() emit_3(op, dest, old_val, right_slot) emit_set_prop(obj_slot, prop, dest) return dest } else if (left_kind == "[") { - var obj = left.left - var idx_expr = left.right - var obj_slot = gen_expr(obj, -1) - var idx_slot = gen_expr(idx_expr, -1) - var old_val = alloc_slot() + obj = left.left + idx_expr = left.right + 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) - var right_slot = gen_expr(right, -1) - var dest = alloc_slot() + right_slot = gen_expr(right, -1) + dest = alloc_slot() emit_3(op, dest, old_val, right_slot) emit_set_elem(obj_slot, idx_slot, dest) return dest @@ -533,53 +562,68 @@ var mcode = function(ast) { var kind = node.kind var left = node.left var right = node.right - var cop = compound_map[kind] + var arr_expr = null + var arr_slot = 0 + var val_slot = 0 + var left_kind = null + var name = null + var level = 0 + var slot = 0 + var _lv = 0 + var pstate = null + var pslot = 0 + var obj = null + var prop = null + var obj_slot = 0 + var idx_expr = null + var idx_slot = 0 + if (cop != null) { return gen_compound_assign(node, cop) } // Push syntax: arr[] = val if (node.push == true) { - var arr_expr = left.left - var arr_slot = gen_expr(arr_expr, -1) - var val_slot = gen_expr(right, -1) + arr_expr = left.left + arr_slot = gen_expr(arr_expr, -1) + val_slot = gen_expr(right, -1) emit_2("push", arr_slot, val_slot) return val_slot } - var val_slot = gen_expr(right, -1) - var left_kind = left.kind + val_slot = gen_expr(right, -1) + left_kind = left.kind if (left_kind == "name") { - var name = left.name - var level = left.level + name = left.name + level = left.level if (level == null) { level = -1 } if (level == 0 || level == -1) { - var slot = find_var(name) + slot = find_var(name) if (slot >= 0) { emit_2("move", slot, val_slot) } else if (level == -1) { add_instr(["set_var", name, val_slot]) } } else if (level > 0) { - var _lv = level - 1 - var pstate = parent_states[length(parent_states) - 1 - _lv] - var pslot = find_var_in_saved(pstate, name) + _lv = level - 1 + pstate = parent_states[length(parent_states) - 1 - _lv] + pslot = find_var_in_saved(pstate, name) emit_3("put", val_slot, pslot, level) } } else if (left_kind == ".") { - var obj = left.left - var prop = left.right - var obj_slot = gen_expr(obj, -1) + obj = left.left + prop = left.right + obj_slot = gen_expr(obj, -1) emit_set_prop(obj_slot, prop, val_slot) } else if (left_kind == "[") { - var obj = left.left - var idx_expr = left.right - var obj_slot = gen_expr(obj, -1) - var idx_slot = gen_expr(idx_expr, -1) + obj = left.left + 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) } return val_slot @@ -587,24 +631,96 @@ var mcode = function(ast) { // Expression compilation gen_expr = function(expr, target) { + var kind = null + var slot = 0 + var val = null + var list = null + var nexpr = 0 + var expr_slots = null + var _i = 0 + var arr_slot = 0 + var arr_instr = null + var fmt_func_slot = 0 + var fmt = null + var fmt_str_slot = 0 + var result_slot = 0 + var pattern = null + var flags = null + var name = null + var level = 0 + var cached = 0 + var dest = 0 + var _lv = 0 + var pstate = null + var parent_slot = 0 + var obj = null + var prop = null + var obj_slot = 0 + var idx = null + var idx_slot = 0 + var callee = null + var args_list = null + var callee_kind = null + var fname = null + var mop = null + var nargs = 0 + var a0 = 0 + var a1 = 0 + var a2 = 0 + var d = 0 + var top = null + var arg_slots = null + var key_expr = null + var key_slot = 0 + var func_slot = 0 + var operand_slot = 0 + var operand = null + var postfix = false + var arith_op = null + var operand_kind = null + var one_slot = 0 + var old_slot = 0 + var local = 0 + var new_slot = 0 + var pslot = 0 + var idx_expr = null + var cond = null + var then_expr = null + var else_expr = null + var else_label = null + var end_label = null + var cond_slot = 0 + var then_slot = 0 + var else_slot = 0 + var count = 0 + var elem_slots = null + var instr = null + var pair = null + var key = null + var val_slot = 0 + var key_kind = null + var kname = null + var func = null + var func_id = 0 + if (expr == null) { return -1 } set_pos(expr) - var kind = expr.kind + kind = expr.kind if (kind == null) { return -1 } // Literals if (kind == "number") { - var slot = target >= 0 ? target : alloc_slot() + slot = target >= 0 ? target : alloc_slot() emit_const_num(slot, expr.number) return slot } if (kind == "text") { - var slot = target >= 0 ? target : alloc_slot() - var val = expr.value + slot = target >= 0 ? target : alloc_slot() + val = expr.value if (val == null) { val = "" } @@ -613,17 +729,17 @@ var mcode = function(ast) { } // Template literal if (kind == "text literal") { - var list = expr.list - var nexpr = list != null ? length(list) : 0 - var expr_slots = [] - var _i = 0 + list = expr.list + nexpr = list != null ? length(list) : 0 + expr_slots = [] + _i = 0 while (_i < nexpr) { push(expr_slots, gen_expr(list[_i], -1)) _i = _i + 1 } // Create array from expression results - var arr_slot = alloc_slot() - var arr_instr = ["array", arr_slot, nexpr] + arr_slot = alloc_slot() + arr_instr = ["array", arr_slot, nexpr] _i = 0 while (_i < nexpr) { push(arr_instr, expr_slots[_i]) @@ -631,30 +747,30 @@ var mcode = function(ast) { } add_instr(arr_instr) // Load format intrinsic - var fmt_func_slot = find_intrinsic("format") + fmt_func_slot = find_intrinsic("format") if (fmt_func_slot < 0) { fmt_func_slot = alloc_slot() emit_access_intrinsic(fmt_func_slot, "format") } // Load format string - var fmt = expr.value + fmt = expr.value if (fmt == null) { fmt = "" } - var fmt_str_slot = alloc_slot() + fmt_str_slot = alloc_slot() emit_const_str(fmt_str_slot, fmt) // Call format(fmt_str, array) - var result_slot = target >= 0 ? target : alloc_slot() + result_slot = target >= 0 ? target : alloc_slot() emit_call(result_slot, fmt_func_slot, [fmt_str_slot, arr_slot]) return result_slot } if (kind == "regexp") { - var slot = target >= 0 ? target : alloc_slot() - var pattern = expr.pattern + slot = target >= 0 ? target : alloc_slot() + pattern = expr.pattern if (pattern == null) { pattern = "" } - var flags = expr.flags + flags = expr.flags if (flags == null) { flags = "" } @@ -662,17 +778,17 @@ var mcode = function(ast) { return slot } if (kind == "true") { - var slot = target >= 0 ? target : alloc_slot() + slot = target >= 0 ? target : alloc_slot() emit_const_bool(slot, true) return slot } if (kind == "false") { - var slot = target >= 0 ? target : alloc_slot() + slot = target >= 0 ? target : alloc_slot() emit_const_bool(slot, false) return slot } if (kind == "null") { - var slot = target >= 0 ? target : alloc_slot() + slot = target >= 0 ? target : alloc_slot() emit_const_null(slot) return slot } @@ -682,133 +798,133 @@ var mcode = function(ast) { // Variable reference if (kind == "name") { - var name = expr.name - var level = expr.level + name = expr.name + level = expr.level if (level == null) { level = -1 } if (level == 0 || level == -1) { - var slot = find_var(name) + slot = find_var(name) if (slot >= 0) { return slot } } else if (level > 0) { - var _lv = level - 1 - var pstate = parent_states[length(parent_states) - 1 - _lv] - var parent_slot = find_var_in_saved(pstate, name) - var dest = alloc_slot() + _lv = level - 1 + pstate = parent_states[length(parent_states) - 1 - _lv] + parent_slot = find_var_in_saved(pstate, name) + dest = alloc_slot() emit_3("get", dest, parent_slot, level) return dest } // Unbound — check intrinsic cache - var cached = find_intrinsic(name) + cached = find_intrinsic(name) if (cached >= 0) { return cached } - var dest = alloc_slot() + dest = alloc_slot() emit_access_intrinsic(dest, name) return dest } // Property access if (kind == ".") { - var obj = expr.left - var prop = expr.right - var obj_slot = gen_expr(obj, -1) - var slot = alloc_slot() + obj = expr.left + prop = expr.right + obj_slot = gen_expr(obj, -1) + slot = alloc_slot() emit_get_prop(slot, obj_slot, prop) return slot } // Element access if (kind == "[") { - var obj = expr.left - var idx = expr.right - var obj_slot = gen_expr(obj, -1) - var idx_slot = gen_expr(idx, -1) - var slot = alloc_slot() + obj = expr.left + idx = expr.right + obj_slot = gen_expr(obj, -1) + idx_slot = gen_expr(idx, -1) + slot = alloc_slot() emit_get_elem(slot, obj_slot, idx_slot) return slot } // Function call if (kind == "(") { - var callee = expr.expression - var args_list = expr.list - var callee_kind = callee.kind + callee = expr.expression + args_list = expr.list + callee_kind = callee.kind // Functino: inline operator call if (callee_kind == "name" && callee.make == "functino") { - var fname = callee.name - var mop = functino_map[fname] - var nargs = args_list != null ? length(args_list) : 0 + fname = callee.name + mop = functino_map[fname] + nargs = args_list != null ? length(args_list) : 0 if (fname == "~!") { - var a0 = gen_expr(args_list[0], -1) - var d = alloc_slot() + a0 = gen_expr(args_list[0], -1) + d = alloc_slot() emit_2(mop, d, a0) return d } if (fname == "[]!") { - var a0 = gen_expr(args_list[0], -1) - var a1 = gen_expr(args_list[1], -1) - var d = alloc_slot() + a0 = gen_expr(args_list[0], -1) + a1 = gen_expr(args_list[1], -1) + d = alloc_slot() emit_get_elem(d, a0, a1) return d } if ((fname == "=!" || fname == "!=!") && nargs == 3) { - var a0 = gen_expr(args_list[0], -1) - var a1 = gen_expr(args_list[1], -1) - var a2 = gen_expr(args_list[2], -1) - var d = alloc_slot() - var top = fname == "=!" ? "eq_tol" : "ne_tol" + a0 = gen_expr(args_list[0], -1) + a1 = gen_expr(args_list[1], -1) + a2 = gen_expr(args_list[2], -1) + d = alloc_slot() + top = fname == "=!" ? "eq_tol" : "ne_tol" emit_4_full(top, [d, a0, a1, a2]) return d } if (fname == "&&!") { - var a0 = gen_expr(args_list[0], -1) - var a1 = gen_expr(args_list[1], -1) - var d = alloc_slot() + a0 = gen_expr(args_list[0], -1) + a1 = gen_expr(args_list[1], -1) + d = alloc_slot() emit_3("and", d, a0, a1) return d } if (fname == "||!") { - var a0 = gen_expr(args_list[0], -1) - var a1 = gen_expr(args_list[1], -1) - var d = alloc_slot() + a0 = gen_expr(args_list[0], -1) + a1 = gen_expr(args_list[1], -1) + d = alloc_slot() emit_3("or", d, a0, a1) return d } // Standard 2-arg binary functino - var a0 = gen_expr(args_list[0], -1) - var a1 = gen_expr(args_list[1], -1) - var d = alloc_slot() + a0 = gen_expr(args_list[0], -1) + a1 = gen_expr(args_list[1], -1) + d = alloc_slot() emit_3(mop, d, a0, a1) return d } // Collect arg slots - var arg_slots = [] - var _i = 0 - var nargs = args_list != null ? length(args_list) : 0 + arg_slots = [] + _i = 0 + nargs = args_list != null ? length(args_list) : 0 while (_i < nargs) { push(arg_slots, gen_expr(args_list[_i], -1)) _i = _i + 1 } - var dest = alloc_slot() + dest = alloc_slot() if (callee_kind == ".") { - var obj = callee.left - var prop = callee.right - var obj_slot = gen_expr(obj, -1) + obj = callee.left + prop = callee.right + obj_slot = gen_expr(obj, -1) emit_call_method(dest, obj_slot, prop, arg_slots) } else if (callee_kind == "[") { - var obj = callee.left - var key_expr = callee.right - var obj_slot = gen_expr(obj, -1) - var key_slot = gen_expr(key_expr, -1) + obj = callee.left + key_expr = callee.right + obj_slot = gen_expr(obj, -1) + key_slot = gen_expr(key_expr, -1) emit_call_method_dyn(dest, obj_slot, key_slot, arg_slots) } else { - var func_slot = gen_expr(callee, -1) + func_slot = gen_expr(callee, -1) emit_call(dest, func_slot, arg_slots) } return dest @@ -816,20 +932,20 @@ var mcode = function(ast) { // Unary operators if (kind == "!") { - var operand_slot = gen_expr(expr.expression, -1) - var slot = alloc_slot() + operand_slot = gen_expr(expr.expression, -1) + slot = alloc_slot() emit_2("not", slot, operand_slot) return slot } if (kind == "~") { - var operand_slot = gen_expr(expr.expression, -1) - var slot = alloc_slot() + operand_slot = gen_expr(expr.expression, -1) + slot = alloc_slot() emit_2("bitnot", slot, operand_slot) return slot } if (kind == "-unary") { - var operand_slot = gen_expr(expr.expression, -1) - var slot = alloc_slot() + operand_slot = gen_expr(expr.expression, -1) + slot = alloc_slot() emit_2("neg", slot, operand_slot) return slot } @@ -839,65 +955,65 @@ var mcode = function(ast) { // Increment/Decrement if (kind == "++" || kind == "--") { - var operand = expr.expression - var postfix = expr.postfix == true - var arith_op = kind == "++" ? "add" : "subtract" - var operand_kind = operand.kind - var one_slot = alloc_slot() + operand = expr.expression + postfix = expr.postfix == true + arith_op = kind == "++" ? "add" : "subtract" + operand_kind = operand.kind + one_slot = alloc_slot() emit_2("int", one_slot, 1) if (operand_kind == "name") { - var name = operand.name - var level = operand.level + name = operand.name + level = operand.level if (level == null) { level = -1 } - var old_slot = alloc_slot() + old_slot = alloc_slot() if (level == 0) { - var local = find_var(name) + local = find_var(name) if (local >= 0) { emit_2("move", old_slot, local) } } else if (level > 0) { - var _lv = level - 1 - var pstate = parent_states[length(parent_states) - 1 - _lv] - var pslot = find_var_in_saved(pstate, name) + _lv = level - 1 + pstate = parent_states[length(parent_states) - 1 - _lv] + pslot = find_var_in_saved(pstate, name) emit_3("get", old_slot, pslot, level) } else { emit_access_intrinsic(old_slot, name) } - var new_slot = alloc_slot() + new_slot = alloc_slot() emit_3(arith_op, new_slot, old_slot, one_slot) if (level == 0) { - var local = find_var(name) + local = find_var(name) if (local >= 0) { emit_2("move", local, new_slot) } } else if (level > 0) { - var _lv = level - 1 - var pstate = parent_states[length(parent_states) - 1 - _lv] - var pslot = find_var_in_saved(pstate, name) + _lv = level - 1 + pstate = parent_states[length(parent_states) - 1 - _lv] + pslot = find_var_in_saved(pstate, name) emit_3("put", new_slot, pslot, level) } return postfix ? old_slot : new_slot } else if (operand_kind == ".") { - var obj = operand.left - var prop = operand.right - var obj_slot = gen_expr(obj, -1) - var old_slot = alloc_slot() + obj = operand.left + prop = operand.right + obj_slot = gen_expr(obj, -1) + old_slot = alloc_slot() emit_get_prop(old_slot, obj_slot, prop) - var new_slot = alloc_slot() + new_slot = alloc_slot() emit_3(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 == "[") { - var obj = operand.left - var idx_expr = operand.right - var obj_slot = gen_expr(obj, -1) - var idx_slot = gen_expr(idx_expr, -1) - var old_slot = alloc_slot() + obj = operand.left + idx_expr = operand.right + 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) - var new_slot = alloc_slot() + new_slot = alloc_slot() emit_3(arith_op, new_slot, old_slot, one_slot) emit_set_elem(obj_slot, idx_slot, new_slot) return postfix ? old_slot : new_slot @@ -906,19 +1022,19 @@ var mcode = function(ast) { // Delete operator if (kind == "delete") { - var operand = expr.expression - var operand_kind = operand.kind - var slot = alloc_slot() + operand = expr.expression + operand_kind = operand.kind + slot = alloc_slot() if (operand_kind == ".") { - var obj = operand.left - var prop = operand.right - var obj_slot = gen_expr(obj, -1) + obj = operand.left + prop = operand.right + obj_slot = gen_expr(obj, -1) push(s_instructions, ["delete", slot, obj_slot, prop]) } else if (operand_kind == "[") { - var obj = operand.left - var idx = operand.right - var obj_slot = gen_expr(obj, -1) - var idx_slot = gen_expr(idx, -1) + obj = operand.left + idx = operand.right + obj_slot = gen_expr(obj, -1) + idx_slot = gen_expr(idx, -1) emit_3("delete", slot, obj_slot, idx_slot) } else { emit_const_bool(slot, true) @@ -928,19 +1044,19 @@ var mcode = function(ast) { // Ternary if (kind == "then") { - var cond = expr.expression - var then_expr = expr.then - var else_expr = expr["else"] - var else_label = gen_label("tern_else") - var end_label = gen_label("tern_end") - var cond_slot = gen_expr(cond, -1) + cond = expr.expression + then_expr = expr.then + else_expr = expr["else"] + else_label = gen_label("tern_else") + end_label = gen_label("tern_end") + cond_slot = gen_expr(cond, -1) emit_jump_cond("jump_false", cond_slot, else_label) - var dest = alloc_slot() - var then_slot = gen_expr(then_expr, -1) + dest = alloc_slot() + then_slot = gen_expr(then_expr, -1) emit_2("move", dest, then_slot) emit_jump(end_label) emit_label(else_label) - var else_slot = gen_expr(else_expr, -1) + else_slot = gen_expr(else_expr, -1) emit_2("move", dest, else_slot) emit_label(end_label) return dest @@ -948,16 +1064,16 @@ var mcode = function(ast) { // Array literal if (kind == "array") { - var list = expr.list - var count = length(list) - var elem_slots = [] - var _i = 0 + list = expr.list + count = length(list) + elem_slots = [] + _i = 0 while (_i < count) { push(elem_slots, gen_expr(list[_i], -1)) _i = _i + 1 } - var dest = alloc_slot() - var instr = ["array", dest, count] + dest = alloc_slot() + instr = ["array", dest, count] _i = 0 while (_i < count) { push(instr, elem_slots[_i]) @@ -969,26 +1085,26 @@ var mcode = function(ast) { // Object literal if (kind == "record") { - var list = expr.list - var dest = alloc_slot() + list = expr.list + dest = alloc_slot() push(s_instructions, ["record", dest, 0]) - var _i = 0 + _i = 0 while (_i < length(list)) { - var pair = list[_i] - var key = pair.left - var val = pair.right - var val_slot = gen_expr(val, -1) - var key_kind = key.kind + pair = list[_i] + key = pair.left + val = pair.right + val_slot = gen_expr(val, -1) + key_kind = key.kind if (key_kind == "name") { emit_set_prop(dest, key.name, val_slot) } else if (key_kind == "text") { - var kname = key.value + kname = key.value if (kname == null) { kname = "" } emit_set_prop(dest, kname, val_slot) } else { - var key_slot = gen_expr(key, -1) + key_slot = gen_expr(key, -1) emit_set_elem(dest, key_slot, val_slot) } _i = _i + 1 @@ -998,11 +1114,11 @@ var mcode = function(ast) { // Function expression if (kind == "function") { - var func = gen_function(expr) - var func_id = s_func_counter + func = gen_function(expr) + func_id = s_func_counter s_func_counter = s_func_counter + 1 push(s_functions, func) - var dest = alloc_slot() + dest = alloc_slot() emit_2("function", dest, func_id) return dest } diff --git a/source/mach.c b/source/mach.c index 96847544..cfaadfa9 100644 --- a/source/mach.c +++ b/source/mach.c @@ -2289,6 +2289,7 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code, int b = MACH_GET_B(instr); int c = MACH_GET_C(instr); + switch (op) { case MACH_NOP: break; diff --git a/source/runtime.c b/source/runtime.c index 268e06f1..6ea2e76d 100644 --- a/source/runtime.c +++ b/source/runtime.c @@ -2515,8 +2515,16 @@ static int js_intrinsic_array_push (JSContext *ctx, JSValue *arr_ptr, JSValue va } if (arr->len >= js_array_cap (arr)) { - if (js_array_grow (ctx, arr_ptr, arr->len + 1) < 0) + /* Root val across js_array_grow which can trigger GC */ + JSGCRef val_ref; + JS_PushGCRef (ctx, &val_ref); + val_ref.val = val; + if (js_array_grow (ctx, arr_ptr, arr->len + 1) < 0) { + JS_PopGCRef (ctx, &val_ref); return -1; + } + val = val_ref.val; + JS_PopGCRef (ctx, &val_ref); arr = JS_VALUE_GET_ARRAY (*arr_ptr); /* re-chase after grow */ }