fix two gc bugs
This commit is contained in:
550
mcode.cm
550
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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user