rustc: Purge of HashMap, fixing segfaulting cases

Various FIXME comments added around to denote copies which when removed cause
the compiler to segfault at some point before stage2. None of these copies
should even be necessary.
This commit is contained in:
Alex Crichton 2013-03-23 18:55:58 -04:00
parent 6f812fef1b
commit 17459d0bd3
17 changed files with 83 additions and 61 deletions

View File

@ -61,7 +61,7 @@ pub fn enc_ty(w: @io::Writer, cx: @ctxt, t: ty::t) {
match cx.abbrevs {
ac_no_abbrevs => {
let result_str = match cx.tcx.short_names_cache.find(&t) {
Some(s) => /*bad*/copy *s,
Some(&s) => /*bad*/copy *s,
None => {
let s = do io::with_str_writer |wr| {
enc_sty(wr, cx, /*bad*/copy ty::get(t).sty);

View File

@ -856,7 +856,9 @@ fn encode_side_tables_for_id(ecx: @e::EncodeContext,
do ebml_w.tag(c::tag_table_node_type_subst) {
ebml_w.id(id);
do ebml_w.tag(c::tag_table_val) {
ebml_w.emit_tys(ecx, /*bad*/copy *tys)
// FIXME(#5562): removing this copy causes a segfault
// before stage2
ebml_w.emit_tys(ecx, /*bad*/copy **tys)
}
}
}
@ -922,7 +924,7 @@ fn encode_side_tables_for_id(ecx: @e::EncodeContext,
}
}
for maps.method_map.find(&id).each |mme| {
for maps.method_map.find(&id).each |&mme| {
do ebml_w.tag(c::tag_table_method_map) {
ebml_w.id(id);
do ebml_w.tag(c::tag_table_val) {

View File

@ -17,7 +17,6 @@ use middle;
use core::float;
use core::vec;
use std::oldmap::HashMap;
use syntax::{ast, ast_map, ast_util, visit};
use syntax::ast::*;
@ -194,7 +193,7 @@ pub fn lookup_const_by_id(tcx: ty::ctxt,
mutbl_map: @mut LinearSet::new(),
root_map: @mut LinearMap::new(),
last_use_map: @mut LinearMap::new(),
method_map: HashMap(),
method_map: @mut LinearMap::new(),
vtable_map: @mut LinearMap::new(),
write_guard_map: @mut LinearSet::new(),
moves_map: @mut LinearSet::new(),

View File

@ -274,6 +274,8 @@ pub fn check_expr(e: @expr, cx: Context, v: visit::vt<Context>) {
_ => e.id
};
for cx.tcx.node_type_substs.find(&type_parameter_id).each |ts| {
// FIXME(#5562): removing this copy causes a segfault before stage2
let ts = /*bad*/ copy **ts;
let bounds = match e.node {
expr_path(_) => {
let did = ast_util::def_id_of_def(*cx.tcx.def_map.get(&e.id));
@ -289,15 +291,15 @@ pub fn check_expr(e: @expr, cx: Context, v: visit::vt<Context>) {
~"non path/method call expr has type substs??")
}
};
if vec::len(*ts) != vec::len(*bounds) {
if ts.len() != bounds.len() {
// Fail earlier to make debugging easier
fail!(fmt!("internal error: in kind::check_expr, length \
mismatch between actual and declared bounds: actual = \
%s (%u tys), declared = %? (%u tys)",
tys_to_str(cx.tcx, *ts), ts.len(),
*bounds, (*bounds).len()));
tys_to_str(cx.tcx, ts), ts.len(),
*bounds, bounds.len()));
}
for vec::each2(*ts, *bounds) |ty, bound| {
for vec::each2(ts, *bounds) |ty, bound| {
check_bounds(cx, type_parameter_id, e.span, *ty, *bound)
}
}
@ -335,9 +337,11 @@ fn check_ty(aty: @Ty, cx: Context, v: visit::vt<Context>) {
match aty.node {
ty_path(_, id) => {
for cx.tcx.node_type_substs.find(&id).each |ts| {
// FIXME(#5562): removing this copy causes a segfault before stage2
let ts = /*bad*/ copy **ts;
let did = ast_util::def_id_of_def(*cx.tcx.def_map.get(&id));
let bounds = ty::lookup_item_type(cx.tcx, did).bounds;
for vec::each2(*ts, *bounds) |ty, bound| {
for vec::each2(ts, *bounds) |ty, bound| {
check_bounds(cx, aty.id, aty.span, *ty, *bound)
}
}

View File

@ -72,8 +72,7 @@ use core::int;
use core::io;
use core::libc::{c_uint, c_ulonglong};
use core::uint;
use std::oldmap::HashMap;
use std::{oldmap, time, list};
use std::{time, list};
use syntax::ast::ident;
use syntax::ast_map::{path, path_elt_to_str, path_mod, path_name};
use syntax::ast_util::{def_id_of_def, local_def, path_to_ident};
@ -170,7 +169,10 @@ pub fn get_extern_fn(externs: ExternMap,
name: @str,
cc: lib::llvm::CallConv,
ty: TypeRef) -> ValueRef {
if externs.contains_key(&name) { return externs.get(&name); }
match externs.find(&name) {
Some(n) => return copy *n,
None => ()
}
let f = decl_fn(llmod, name, cc, ty);
externs.insert(name, f);
return f;
@ -178,8 +180,11 @@ pub fn get_extern_fn(externs: ExternMap,
pub fn get_extern_const(externs: ExternMap, llmod: ModuleRef,
name: @str, ty: TypeRef) -> ValueRef {
match externs.find(&name) {
Some(n) => return copy *n,
None => ()
}
unsafe {
if externs.contains_key(&name) { return externs.get(&name); }
let c = str::as_c_str(name, |buf| {
llvm::LLVMAddGlobal(llmod, ty, buf)
});
@ -3061,7 +3066,7 @@ pub fn trans_crate(sess: session::Session,
llmod: llmod,
td: td,
tn: tn,
externs: HashMap(),
externs: @mut LinearMap::new(),
intrinsics: intrinsics,
item_vals: @mut LinearMap::new(),
exp_map2: emap2,
@ -3082,8 +3087,8 @@ pub fn trans_crate(sess: session::Session,
const_globals: @mut LinearMap::new(),
const_values: @mut LinearMap::new(),
module_data: @mut LinearMap::new(),
lltypes: ty::new_ty_hash(),
llsizingtypes: ty::new_ty_hash(),
lltypes: @mut LinearMap::new(),
llsizingtypes: @mut LinearMap::new(),
adt_reprs: @mut LinearMap::new(),
names: new_namegen(sess.parse_sess.interner),
next_addrspace: new_addrspace_gen(),

View File

@ -82,9 +82,12 @@ pub fn trans(bcx: block, expr: @ast::expr) -> Callee {
}
ast::expr_field(base, _, _) => {
match bcx.ccx().maps.method_map.find(&expr.id) {
Some(ref origin) => { // An impl method
Some(origin) => { // An impl method
// FIXME(#5562): removing this copy causes a segfault
// before stage2
let origin = /*bad*/ copy *origin;
return meth::trans_method_callee(bcx, expr.id,
base, (*origin));
base, origin);
}
None => {} // not a method, just a field
}
@ -343,11 +346,14 @@ pub fn trans_method_call(in_cx: block,
expr_ty(in_cx, call_ex),
|cx| {
match cx.ccx().maps.method_map.find(&call_ex.id) {
Some(ref origin) => {
Some(origin) => {
// FIXME(#5562): removing this copy causes a segfault
// before stage2
let origin = /*bad*/ copy *origin;
meth::trans_method_callee(cx,
call_ex.callee_id,
rcvr,
(*origin))
origin)
}
None => {
cx.tcx().sess.span_bug(call_ex.span,

View File

@ -52,7 +52,6 @@ use core::str;
use core::to_bytes;
use core::vec::raw::to_ptr;
use core::vec;
use std::oldmap::{HashMap, Set};
use syntax::ast::ident;
use syntax::ast_map::{path, path_elt};
use syntax::codemap::span;
@ -156,7 +155,7 @@ pub fn BuilderRef_res(B: BuilderRef) -> BuilderRef_res {
}
}
pub type ExternMap = HashMap<@str, ValueRef>;
pub type ExternMap = @mut LinearMap<@str, ValueRef>;
// Crate context. Every crate we compile has one of these.
pub struct CrateContext {
@ -203,8 +202,8 @@ pub struct CrateContext {
// Cache of emitted const values
const_values: @mut LinearMap<ast::node_id, ValueRef>,
module_data: @mut LinearMap<~str, ValueRef>,
lltypes: HashMap<ty::t, TypeRef>,
llsizingtypes: HashMap<ty::t, TypeRef>,
lltypes: @mut LinearMap<ty::t, TypeRef>,
llsizingtypes: @mut LinearMap<ty::t, TypeRef>,
adt_reprs: @mut LinearMap<ty::t, @adt::Repr>,
names: namegen,
next_addrspace: addrspace_gen,

View File

@ -1647,7 +1647,7 @@ fn trans_overloaded_op(bcx: block,
dest: Dest,
+autoref_arg: AutorefArg) -> block
{
let origin = bcx.ccx().maps.method_map.get(&expr.id);
let origin = *bcx.ccx().maps.method_map.get(&expr.id);
let fty = node_id_type(bcx, expr.callee_id);
return callee::trans_call_inner(
bcx, expr.info(), fty,

View File

@ -402,7 +402,7 @@ pub fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) {
let mut bcx = bcx;
let ty_visitor_name = special_idents::ty_visitor;
fail_unless!(bcx.ccx().tcx.intrinsic_defs.contains_key(&ty_visitor_name));
let (trait_id, ty) = bcx.ccx().tcx.intrinsic_defs.get(&ty_visitor_name);
let (trait_id, ty) = *bcx.ccx().tcx.intrinsic_defs.get(&ty_visitor_name);
let v = PointerCast(bcx, v, T_ptr(type_of::type_of(bcx.ccx(), ty)));
bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, v, trait_id);
build_return(bcx);

View File

@ -193,7 +193,7 @@ fn traverse_inline_body(cx: ctx, body: &blk) {
}
expr_field(_, _, _) => {
match cx.method_map.find(&e.id) {
Some(typeck::method_map_entry {
Some(&typeck::method_map_entry {
origin: typeck::method_static(did),
_
}) => {
@ -204,7 +204,7 @@ fn traverse_inline_body(cx: ctx, body: &blk) {
}
expr_method_call(*) => {
match cx.method_map.find(&e.id) {
Some(typeck::method_map_entry {
Some(&typeck::method_map_entry {
origin: typeck::method_static(did),
_
}) => {

View File

@ -337,7 +337,7 @@ pub fn emit_calls_to_trait_visit_ty(bcx: block,
use syntax::parse::token::special_idents::tydesc;
let final = sub_block(bcx, ~"final");
fail_unless!(bcx.ccx().tcx.intrinsic_defs.contains_key(&tydesc));
let (_, tydesc_ty) = bcx.ccx().tcx.intrinsic_defs.get(&tydesc);
let (_, tydesc_ty) = *bcx.ccx().tcx.intrinsic_defs.get(&tydesc);
let tydesc_ty = type_of(bcx.ccx(), tydesc_ty);
let mut r = Reflector {
visitor_val: visitor_val,

View File

@ -101,8 +101,10 @@ pub fn type_of_non_gc_box(cx: @CrateContext, t: ty::t) -> TypeRef {
// behavior.
pub fn sizing_type_of(cx: @CrateContext, t: ty::t) -> TypeRef {
if cx.llsizingtypes.contains_key(&t) {
return cx.llsizingtypes.get(&t);
match cx.llsizingtypes.find(&t) {
// FIXME(#5562): removing this copy causes a segfault in stage1 core
Some(t) => return /*bad*/ copy *t,
None => ()
}
let llsizingty = match ty::get(t).sty {
@ -161,7 +163,11 @@ pub fn type_of(cx: @CrateContext, t: ty::t) -> TypeRef {
debug!("type_of %?: %?", t, ty::get(t));
// Check the cache.
if cx.lltypes.contains_key(&t) { return cx.lltypes.get(&t); }
match cx.lltypes.find(&t) {
// FIXME(#5562): removing this copy causes a segfault in stage1 core
Some(t) => return /*bad*/ copy *t,
None => ()
}
// Replace any typedef'd types with their equivalent non-typedef
// type. This ensures that all LLVM nominal types that contain

View File

@ -250,8 +250,11 @@ pub fn mark_for_method_call(cx: Context, e_id: node_id, callee_id: node_id) {
match mth.origin {
typeck::method_static(did) => {
for cx.ccx.tcx.node_type_substs.find(&callee_id).each |ts| {
// FIXME(#5562): removing this copy causes a segfault
// before stage2
let ts = /*bad*/ copy **ts;
let type_uses = type_uses_for(cx.ccx, did, ts.len());
for vec::each2(type_uses, *ts) |uses, subst| {
for vec::each2(type_uses, ts) |uses, subst| {
type_needs(cx, *uses, *subst)
}
}
@ -296,9 +299,11 @@ pub fn mark_for_expr(cx: Context, e: @expr) {
}
expr_path(_) => {
for cx.ccx.tcx.node_type_substs.find(&e.id).each |ts| {
// FIXME(#5562): removing this copy causes a segfault before stage2
let ts = copy **ts;
let id = ast_util::def_id_of_def(*cx.ccx.tcx.def_map.get(&e.id));
let uses_for_ts = type_uses_for(cx.ccx, id, ts.len());
for vec::each2(uses_for_ts, *ts) |uses, subst| {
for vec::each2(uses_for_ts, ts) |uses, subst| {
type_needs(cx, *uses, *subst)
}
}

View File

@ -38,8 +38,6 @@ use core::to_bytes;
use core::uint;
use core::vec;
use core::hashmap::linear::{LinearMap, LinearSet};
use std::oldmap::HashMap;
use std::oldmap;
use std::smallintmap::SmallIntMap;
use syntax::ast::*;
use syntax::ast_util::{is_local, local_def};
@ -265,16 +263,16 @@ struct ctxt_ {
// of this node. This only applies to nodes that refer to entities
// parameterized by type parameters, such as generic fns, types, or
// other items.
node_type_substs: HashMap<node_id, ~[t]>,
node_type_substs: @mut LinearMap<node_id, ~[t]>,
items: ast_map::map,
intrinsic_defs: HashMap<ast::ident, (ast::def_id, t)>,
intrinsic_defs: @mut LinearMap<ast::ident, (ast::def_id, t)>,
freevars: freevars::freevar_map,
tcache: type_cache,
rcache: creader_cache,
ccache: constness_cache,
short_names_cache: HashMap<t, @~str>,
needs_unwind_cleanup_cache: HashMap<t, bool>,
short_names_cache: @mut LinearMap<t, @~str>,
needs_unwind_cleanup_cache: @mut LinearMap<t, bool>,
tc_cache: @mut LinearMap<uint, TypeContents>,
ast_ty_to_ty_cache: @mut LinearMap<node_id, ast_ty_to_ty_cache_entry>,
enum_var_cache: @mut LinearMap<def_id, @~[VariantInfo]>,
@ -282,7 +280,7 @@ struct ctxt_ {
ty_param_bounds: @mut LinearMap<ast::node_id, param_bounds>,
inferred_modes: @mut LinearMap<ast::node_id, ast::mode>,
adjustments: @mut LinearMap<ast::node_id, @AutoAdjustment>,
normalized_cache: HashMap<t, t>,
normalized_cache: @mut LinearMap<t, t>,
lang_items: middle::lang_items::LanguageItems,
// A mapping from an implementation ID to the method info and trait
// method ID of the provided (a.k.a. default) methods in the traits that
@ -788,8 +786,8 @@ fn mk_rcache() -> creader_cache {
return @mut LinearMap::new();
}
pub fn new_ty_hash<V:Copy>() -> oldmap::HashMap<t, V> {
oldmap::HashMap()
pub fn new_ty_hash<V:Copy>() -> @mut LinearMap<t, V> {
@mut LinearMap::new()
}
pub fn mk_ctxt(s: session::Session,
@ -826,9 +824,9 @@ pub fn mk_ctxt(s: session::Session,
region_map: region_map,
region_paramd_items: region_paramd_items,
node_types: @mut SmallIntMap::new(),
node_type_substs: oldmap::HashMap(),
node_type_substs: @mut LinearMap::new(),
items: amap,
intrinsic_defs: oldmap::HashMap(),
intrinsic_defs: @mut LinearMap::new(),
freevars: freevars,
tcache: @mut LinearMap::new(),
rcache: mk_rcache(),
@ -1621,25 +1619,24 @@ pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
// cleanups.
pub fn type_needs_unwind_cleanup(cx: ctxt, ty: t) -> bool {
match cx.needs_unwind_cleanup_cache.find(&ty) {
Some(result) => return result,
Some(&result) => return result,
None => ()
}
let tycache = new_ty_hash();
let mut tycache = LinearSet::new();
let needs_unwind_cleanup =
type_needs_unwind_cleanup_(cx, ty, tycache, false);
type_needs_unwind_cleanup_(cx, ty, &mut tycache, false);
cx.needs_unwind_cleanup_cache.insert(ty, needs_unwind_cleanup);
return needs_unwind_cleanup;
}
fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
tycache: oldmap::HashMap<t, ()>,
tycache: &mut LinearSet<t>,
encountered_box: bool) -> bool {
// Prevent infinite recursion
match tycache.find(&ty) {
Some(_) => return false,
None => { tycache.insert(ty, ()); }
if !tycache.insert(ty) {
return false;
}
let mut encountered_box = encountered_box;
@ -2724,7 +2721,7 @@ pub fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t {
pub fn node_id_to_type_params(cx: ctxt, id: ast::node_id) -> ~[t] {
match cx.node_type_substs.find(&id) {
None => return ~[],
Some(ts) => return ts
Some(ts) => return /*bad*/ copy *ts
}
}
@ -4164,7 +4161,7 @@ pub fn normalize_ty(cx: ctxt, t: t) -> t {
}
match cx.normalized_cache.find(&t) {
Some(t) => return t,
Some(&t) => return t,
None => ()
}

View File

@ -3453,8 +3453,8 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
let ty_visitor_name = tcx.sess.ident_of(~"TyVisitor");
fail_unless!(tcx.intrinsic_defs.contains_key(&tydesc_name));
fail_unless!(ccx.tcx.intrinsic_defs.contains_key(&ty_visitor_name));
let (_, tydesc_ty) = tcx.intrinsic_defs.get(&tydesc_name);
let (_, visitor_trait) = tcx.intrinsic_defs.get(&ty_visitor_name);
let (_, tydesc_ty) = *tcx.intrinsic_defs.get(&tydesc_name);
let (_, visitor_trait) = *tcx.intrinsic_defs.get(&ty_visitor_name);
let visitor_trait = match ty::get(visitor_trait).sty {
ty::ty_trait(trait_def_id, ref trait_substs, _) => {

View File

@ -66,7 +66,7 @@ fn resolve_method_map_entry(fcx: @mut FnCtxt, sp: span, id: ast::node_id) {
// Resolve any method map entry
match fcx.inh.method_map.find(&id) {
None => {}
Some(ref mme) => {
Some(mme) => {
for resolve_type_vars_in_type(fcx, sp, mme.self_arg.ty).each |t| {
let method_map = fcx.ccx.method_map;
let new_entry = method_map_entry {

View File

@ -60,7 +60,6 @@ use core::result;
use core::vec;
use std::list::{List, Nil, Cons};
use std::list;
use std::oldmap::HashMap;
use syntax::codemap::{span, spanned, respan};
use syntax::print::pprust::*;
use syntax::{ast, ast_util, ast_map};
@ -130,7 +129,7 @@ pub struct method_map_entry {
// maps from an expression id that corresponds to a method call to the details
// of the method to be invoked
pub type method_map = HashMap<ast::node_id, method_map_entry>;
pub type method_map = @mut LinearMap<ast::node_id, method_map_entry>;
// Resolutions for bounds of all parameters, left to right, for a given path.
pub type vtable_res = @~[vtable_origin];
@ -343,7 +342,7 @@ pub fn check_crate(tcx: ty::ctxt,
let time_passes = tcx.sess.time_passes();
let ccx = @mut CrateCtxt {
trait_map: trait_map,
method_map: HashMap(),
method_map: @mut LinearMap::new(),
vtable_map: @mut LinearMap::new(),
coherence_info: @coherence::CoherenceInfo(),
tcx: tcx