diff --git a/streamline.cm b/streamline.cm index ae1e0048..bb4c2c9e 100644 --- a/streamline.cm +++ b/streamline.cm @@ -457,6 +457,19 @@ var streamline = function(ir, log) { i = i + 1 continue } + if (op == "get" && func._closure_slot_types != null) { + slot = instr[1] + typ = T_UNKNOWN + src_typ = func._closure_slot_types[text(instr[2]) + "_" + text(instr[3])] + if (src_typ != null) { + typ = src_typ + } + if (slot > 0 && slot > nr_args) { + merge_backward(write_types, slot, typ) + } + i = i + 1 + continue + } rule = write_rules[op] if (rule != null) { @@ -1966,6 +1979,71 @@ var streamline = function(ir, log) { } fi = fi + 1 } + ir._parent_of = parent_of + ir._parent_fc = fc + return null + } + + // ========================================================= + // Resolve closure slot types from parent write_types. + // For each `get` in func, walk the parent chain and look up + // the ancestor's inferred write type for that closure slot. + // ========================================================= + var resolve_closure_types = function(func, fi, ir) { + var parent_of = ir._parent_of + var fc = ir._parent_fc + var instructions = func.instructions + var num_instr = 0 + var closure_types = null + var i = 0 + var instr = null + var slot = 0 + var depth = 0 + var anc = 0 + var j = 0 + var target = null + var typ = null + var key = null + + if (instructions == null || parent_of == null) { + return null + } + + num_instr = length(instructions) + closure_types = {} + i = 0 + while (i < num_instr) { + instr = instructions[i] + if (is_array(instr) && instr[0] == "get") { + slot = instr[2] + depth = instr[3] + key = text(slot) + "_" + text(depth) + if (closure_types[key] == null) { + anc = fi + j = 0 + while (j < depth && anc >= 0) { + anc = parent_of[anc] + j = j + 1 + } + if (anc >= 0) { + if (anc == fc) { + target = ir.main + } else { + target = ir.functions[anc] + } + if (target != null && target._write_types != null) { + typ = target._write_types[slot] + if (typ != null) { + closure_types[key] = typ + } + } + } + } + } + i = i + 1 + } + + func._closure_slot_types = closure_types return null } @@ -2284,6 +2362,7 @@ var streamline = function(ir, log) { run_cycle("") run_cycle("_2") + func._write_types = write_types if (ir._warn) { diagnose_function(func, {param_types: param_types, write_types: write_types}, ir) } @@ -2305,11 +2384,12 @@ var streamline = function(ir, log) { optimize_function(ir.main, log) } - // Process all sub-functions + // Process all sub-functions (resolve closure types from parent first) var fi = 0 if (ir.functions != null) { fi = 0 while (fi < length(ir.functions)) { + resolve_closure_types(ir.functions[fi], fi, ir) optimize_function(ir.functions[fi], log) fi = fi + 1 }