Merge branch 'bytecode_cleanup' into mach
This commit is contained in:
122
mcode.cm
122
mcode.cm
@@ -43,6 +43,8 @@ var mcode = function(ast) {
|
||||
var s_func_counter = 0
|
||||
var s_loop_break = null
|
||||
var s_loop_continue = null
|
||||
var s_label_map = {}
|
||||
var s_pending_label = null
|
||||
var s_is_arrow = false
|
||||
var s_function_nr = 0
|
||||
var s_scopes = null
|
||||
@@ -71,6 +73,7 @@ var mcode = function(ast) {
|
||||
max_slot: s_max_slot,
|
||||
loop_break: s_loop_break,
|
||||
loop_continue: s_loop_continue,
|
||||
label_map: s_label_map,
|
||||
is_arrow: s_is_arrow,
|
||||
function_nr: s_function_nr,
|
||||
intrinsic_cache: s_intrinsic_cache,
|
||||
@@ -90,6 +93,7 @@ var mcode = function(ast) {
|
||||
s_max_slot = saved.max_slot
|
||||
s_loop_break = saved.loop_break
|
||||
s_loop_continue = saved.loop_continue
|
||||
s_label_map = saved.label_map
|
||||
s_is_arrow = saved.is_arrow
|
||||
s_function_nr = saved.function_nr
|
||||
s_intrinsic_cache = saved.intrinsic_cache
|
||||
@@ -761,37 +765,114 @@ var mcode = function(ast) {
|
||||
}
|
||||
|
||||
var emit_call_method = function(dest, obj, prop, args) {
|
||||
var argc = length(args)
|
||||
var check = alloc_slot()
|
||||
var record_path = gen_label("record_path")
|
||||
var done_label = gen_label("call_done")
|
||||
var _i = 0
|
||||
var arg_idx = 0
|
||||
|
||||
// Check if obj is a proxy function (arity 2)
|
||||
emit_2("is_proxy", check, obj)
|
||||
emit_jump_cond("jump_false", check, record_path)
|
||||
|
||||
// Function proxy path: call obj(prop_name, [args...]) with this=null
|
||||
var null_slot = alloc_slot()
|
||||
emit_const_null(null_slot)
|
||||
var name_str = alloc_slot()
|
||||
emit_const_str(name_str, prop)
|
||||
var args_arr = alloc_slot()
|
||||
var arr_instr = ["array", args_arr, argc]
|
||||
_i = 0
|
||||
while (_i < argc) {
|
||||
push(arr_instr, args[_i])
|
||||
_i = _i + 1
|
||||
}
|
||||
add_instr(arr_instr)
|
||||
var pf = alloc_slot()
|
||||
emit_3("frame", pf, obj, 2)
|
||||
emit_3("setarg", pf, 0, null_slot)
|
||||
emit_3("setarg", pf, 1, name_str)
|
||||
emit_3("setarg", pf, 2, args_arr)
|
||||
emit_2("invoke", pf, dest)
|
||||
emit_jump(done_label)
|
||||
|
||||
// Record path: load method, call with this=obj
|
||||
emit_label(record_path)
|
||||
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
|
||||
arg_idx = 1
|
||||
_i = 0
|
||||
while (_i < argc) {
|
||||
emit_3("setarg", frame_slot, arg_idx, args[_i])
|
||||
arg_idx = arg_idx + 1
|
||||
_i = _i + 1
|
||||
}
|
||||
emit_2("invoke", frame_slot, dest)
|
||||
|
||||
emit_label(done_label)
|
||||
}
|
||||
|
||||
var emit_call_method_dyn = function(dest, obj, key_reg, args) {
|
||||
var argc = length(args)
|
||||
var check = alloc_slot()
|
||||
var record_path = gen_label("dyn_record_path")
|
||||
var done_label = gen_label("dyn_call_done")
|
||||
var _i = 0
|
||||
var arg_idx = 0
|
||||
|
||||
// Check if obj is a proxy function (arity 2)
|
||||
emit_2("is_proxy", check, obj)
|
||||
emit_jump_cond("jump_false", check, record_path)
|
||||
|
||||
// Function proxy path (dynamic key): must be text
|
||||
var key_ok = alloc_slot()
|
||||
var error_path = gen_label("dyn_error")
|
||||
emit_2("is_text", key_ok, key_reg)
|
||||
emit_jump_cond("jump_false", key_ok, error_path)
|
||||
var null_slot = alloc_slot()
|
||||
emit_const_null(null_slot)
|
||||
var args_arr = alloc_slot()
|
||||
var arr_instr = ["array", args_arr, argc]
|
||||
_i = 0
|
||||
while (_i < argc) {
|
||||
push(arr_instr, args[_i])
|
||||
_i = _i + 1
|
||||
}
|
||||
add_instr(arr_instr)
|
||||
var pf = alloc_slot()
|
||||
emit_3("frame", pf, obj, 2)
|
||||
emit_3("setarg", pf, 0, null_slot)
|
||||
emit_3("setarg", pf, 1, key_reg)
|
||||
emit_3("setarg", pf, 2, args_arr)
|
||||
emit_2("invoke", pf, dest)
|
||||
emit_jump(done_label)
|
||||
|
||||
// Error path: non-text key on function disrupts
|
||||
emit_label(error_path)
|
||||
emit_0("disrupt")
|
||||
emit_jump(done_label)
|
||||
|
||||
// Record path: load method dynamically, call with this=obj
|
||||
emit_label(record_path)
|
||||
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
|
||||
arg_idx = 1
|
||||
_i = 0
|
||||
while (_i < argc) {
|
||||
emit_3("setarg", frame_slot, arg_idx, args[_i])
|
||||
arg_idx = arg_idx + 1
|
||||
_i = _i + 1
|
||||
}
|
||||
emit_2("invoke", frame_slot, dest)
|
||||
|
||||
emit_label(done_label)
|
||||
}
|
||||
|
||||
var emit_go_call = function(func_slot, args) {
|
||||
@@ -1859,6 +1940,13 @@ var mcode = function(ast) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (kind == "label") {
|
||||
s_pending_label = stmt.name
|
||||
gen_statement(stmt.statement)
|
||||
s_pending_label = null
|
||||
return null
|
||||
}
|
||||
|
||||
if (kind == "while") {
|
||||
cond = stmt.expression
|
||||
stmts = stmt.statements
|
||||
@@ -1868,6 +1956,10 @@ var mcode = function(ast) {
|
||||
old_continue = s_loop_continue
|
||||
s_loop_break = end_label
|
||||
s_loop_continue = start_label
|
||||
if (s_pending_label != null) {
|
||||
s_label_map[s_pending_label] = {break_target: end_label, continue_target: start_label}
|
||||
s_pending_label = null
|
||||
}
|
||||
emit_label(start_label)
|
||||
cond_slot = gen_expr(cond, -1)
|
||||
emit_jump_cond("jump_false", cond_slot, end_label)
|
||||
@@ -1893,6 +1985,10 @@ var mcode = function(ast) {
|
||||
old_continue = s_loop_continue
|
||||
s_loop_break = end_label
|
||||
s_loop_continue = cond_label
|
||||
if (s_pending_label != null) {
|
||||
s_label_map[s_pending_label] = {break_target: end_label, continue_target: cond_label}
|
||||
s_pending_label = null
|
||||
}
|
||||
emit_label(start_label)
|
||||
_i = 0
|
||||
while (_i < length(stmts)) {
|
||||
@@ -1920,6 +2016,10 @@ var mcode = function(ast) {
|
||||
old_continue = s_loop_continue
|
||||
s_loop_break = end_label
|
||||
s_loop_continue = update_label
|
||||
if (s_pending_label != null) {
|
||||
s_label_map[s_pending_label] = {break_target: end_label, continue_target: update_label}
|
||||
s_pending_label = null
|
||||
}
|
||||
if (init != null) {
|
||||
init_kind = init.kind
|
||||
if (init_kind == "var" || init_kind == "def") {
|
||||
@@ -1995,14 +2095,18 @@ var mcode = function(ast) {
|
||||
}
|
||||
|
||||
if (kind == "break") {
|
||||
if (s_loop_break != null) {
|
||||
if (stmt.name != null && s_label_map[stmt.name] != null) {
|
||||
emit_jump(s_label_map[stmt.name].break_target)
|
||||
} else if (s_loop_break != null) {
|
||||
emit_jump(s_loop_break)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
if (kind == "continue") {
|
||||
if (s_loop_continue != null) {
|
||||
if (stmt.name != null && s_label_map[stmt.name] != null) {
|
||||
emit_jump(s_label_map[stmt.name].continue_target)
|
||||
} else if (s_loop_continue != null) {
|
||||
emit_jump(s_loop_continue)
|
||||
}
|
||||
return null
|
||||
@@ -2128,6 +2232,7 @@ var mcode = function(ast) {
|
||||
s_intrinsic_cache = []
|
||||
s_loop_break = null
|
||||
s_loop_continue = null
|
||||
s_label_map = {}
|
||||
|
||||
s_is_arrow = is_arrow
|
||||
|
||||
@@ -2321,6 +2426,7 @@ var mcode = function(ast) {
|
||||
s_func_counter = 0
|
||||
s_loop_break = null
|
||||
s_loop_continue = null
|
||||
s_label_map = {}
|
||||
s_function_nr = 0
|
||||
|
||||
// Scan scope
|
||||
|
||||
Reference in New Issue
Block a user