Keep an explicit map of things that have to be spilled

This prevents us from spilling locals more than once.

Closes #2040
This commit is contained in:
Marijn Haverbeke 2012-03-23 16:05:53 +01:00
parent 1b81c5112a
commit 84019aa0dc
7 changed files with 35 additions and 11 deletions

View File

@ -169,7 +169,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
let (copy_map, ref_map) =
time(time_passes, "alias checking",
bind middle::alias::check_crate(ty_cx, crate));
let last_uses = time(time_passes, "last use finding",
let (last_uses, spill_map) = time(time_passes, "last use finding",
bind last_use::find_last_uses(crate, def_map, ref_map, ty_cx));
time(time_passes, "kind checking",
bind kind::check_crate(ty_cx, method_map, last_uses, crate));
@ -181,7 +181,8 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
let maps = {mutbl_map: mutbl_map, copy_map: copy_map,
last_uses: last_uses, impl_map: impl_map,
method_map: method_map, vtable_map: vtable_map};
method_map: method_map, vtable_map: vtable_map,
spill_map: spill_map};
let (llmod, link_meta) =
time(time_passes, "translation",

View File

@ -512,7 +512,7 @@ impl of tr for method_origin {
impl of tr for last_use::is_last_use {
fn tr(xcx: extended_decode_ctxt) -> last_use::is_last_use {
alt self {
last_use::is_last_use | last_use::has_last_use { self }
last_use::is_last_use { self }
last_use::closes_over(ids) {
last_use::closes_over(vec::map(ids, {|id| xcx.tr_id(id)}))
}
@ -780,6 +780,12 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt,
}
}
option::may(ccx.maps.spill_map.find(id)) {|_m|
ebml_w.tag(c::tag_table_spill) {||
ebml_w.id(id);
}
}
option::may(ccx.maps.last_uses.find(id)) {|m|
ebml_w.tag(c::tag_table_last_use) {||
ebml_w.id(id);
@ -869,6 +875,8 @@ fn decode_side_tables(xcx: extended_decode_ctxt,
dcx.maps.mutbl_map.insert(id, ());
} else if tag == (c::tag_table_copy as uint) {
dcx.maps.copy_map.insert(id, ());
} else if tag == (c::tag_table_spill as uint) {
dcx.maps.spill_map.insert(id, ());
} else {
let val_doc = entry_doc[c::tag_table_val];
let val_dsr = ebml::ebml_deserializer(val_doc);

View File

@ -100,6 +100,7 @@ enum astencode_tag { // Reserves 0x50 -- 0x6f
tag_table_mutbl,
tag_table_copy,
tag_table_last_use,
tag_table_spill,
tag_table_method_map,
tag_table_vtable_map
}

View File

@ -28,10 +28,10 @@ import std::map::hashmap;
#[auto_serialize]
enum is_last_use {
is_last_use,
has_last_use,
closes_over([node_id]),
}
type last_uses = std::map::hashmap<node_id, is_last_use>;
type spill_map = std::map::hashmap<node_id, ()>;
enum seen { unset, seen(node_id), }
enum block_type { func, lp, }
@ -46,6 +46,7 @@ fn hash_use_id(id: use_id) -> uint {
}
type ctx = {last_uses: std::map::hashmap<use_id, bool>,
spill_map: std::map::hashmap<node_id, ()>,
def_map: resolve::def_map,
ref_map: alias::ref_map,
tcx: ty::ctxt,
@ -54,12 +55,14 @@ type ctx = {last_uses: std::map::hashmap<use_id, bool>,
mutable blocks: list<bl>};
fn find_last_uses(c: @crate, def_map: resolve::def_map,
ref_map: alias::ref_map, tcx: ty::ctxt) -> last_uses {
ref_map: alias::ref_map, tcx: ty::ctxt)
-> (last_uses, spill_map) {
let v = visit::mk_vt(@{visit_expr: visit_expr,
visit_stmt: visit_stmt,
visit_fn: visit_fn
with *visit::default_visitor()});
let cx = {last_uses: std::map::hashmap(hash_use_id, {|a, b| a == b}),
spill_map: std::map::int_hash(),
def_map: def_map,
ref_map: ref_map,
tcx: tcx,
@ -73,10 +76,10 @@ fn find_last_uses(c: @crate, def_map: resolve::def_map,
path(id) {
mini_table.insert(id, is_last_use);
let def_node = ast_util::def_id_of_def(def_map.get(id)).node;
mini_table.insert(def_node, has_last_use);
cx.spill_map.insert(def_node, ());
}
close(fn_id, local_id) {
mini_table.insert(local_id, has_last_use);
cx.spill_map.insert(local_id, ());
let known = alt check mini_table.find(fn_id) {
some(closes_over(ids)) { ids }
none { [] }
@ -85,7 +88,7 @@ fn find_last_uses(c: @crate, def_map: resolve::def_map,
}
}
}
ret mini_table;
ret (mini_table, cx.spill_map);
}
fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
@ -187,7 +190,11 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
expr_path(_) {
alt ty::arg_mode(cx.tcx, arg_t) {
by_ref | by_val | by_mutbl_ref {
clear_if_path(cx, arg, v, false);
let def = cx.def_map.get(arg.id);
option::may(def_is_owned_local(cx, def)) {|id|
clear_in_current(cx, id, false);
cx.spill_map.insert(id, ());
}
}
_ {}
}

View File

@ -3687,7 +3687,7 @@ fn alloc_local(cx: block, local: @ast::local) -> block {
let ccx = cx.ccx();
if option::is_some(simple_name) &&
!ccx.maps.mutbl_map.contains_key(local.node.pat.id) &&
!ccx.maps.last_uses.contains_key(local.node.pat.id) &&
!ccx.maps.spill_map.contains_key(local.node.pat.id) &&
ty::type_is_immediate(t) {
alt local.node.init {
some({op: ast::init_assign, _}) { ret cx; }

View File

@ -69,7 +69,8 @@ type maps = {
last_uses: middle::last_use::last_uses,
impl_map: middle::resolve::impl_map,
method_map: middle::typeck::method_map,
vtable_map: middle::typeck::vtable_map
vtable_map: middle::typeck::vtable_map,
spill_map: last_use::spill_map
};
// Crate context. Every crate we compile has one of these.

View File

@ -0,0 +1,6 @@
// Issue #2040
fn main() {
let foo = 1;
assert ptr::addr_of(foo) == ptr::addr_of(foo);
}