fix two gc bugs

This commit is contained in:
2026-02-09 18:32:41 -06:00
parent 7f691fd52b
commit c0b4e70eb2
3 changed files with 343 additions and 218 deletions

550
mcode.cm
View File

@@ -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
}

View File

@@ -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;

View File

@@ -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 */
}