Skip to content

Cache more results of const_eval #9722

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 5, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/etc/get-snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ def unpack_snapshot(triple, dl_path):
print("extracting " + p)
tar.extract(p, download_unpack_base)
tp = os.path.join(download_unpack_base, p)
if os.path.isdir(tp) and os.path.exists(fp):
continue
shutil.move(tp, fp)
tar.close()
shutil.rmtree(download_unpack_base)
Expand Down
227 changes: 116 additions & 111 deletions src/librustc/middle/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ pub enum constness {
non_const
}

type constness_cache = HashMap<ast::DefId, constness>;

pub fn join(a: constness, b: constness) -> constness {
match (a, b) {
(integral_const, integral_const) => integral_const,
Expand All @@ -74,102 +76,12 @@ pub fn join_all<It: Iterator<constness>>(mut cs: It) -> constness {
cs.fold(integral_const, |a, b| join(a, b))
}

pub fn classify(e: &Expr,
tcx: ty::ctxt)
-> constness {
let did = ast_util::local_def(e.id);
match tcx.ccache.find(&did) {
Some(&x) => x,
None => {
let cn =
match e.node {
ast::ExprLit(lit) => {
match lit.node {
ast::lit_str(*) |
ast::lit_float(*) => general_const,
_ => integral_const
}
}

ast::ExprUnary(_, _, inner) |
ast::ExprParen(inner) => {
classify(inner, tcx)
}

ast::ExprBinary(_, _, a, b) => {
join(classify(a, tcx),
classify(b, tcx))
}

ast::ExprTup(ref es) |
ast::ExprVec(ref es, ast::MutImmutable) => {
join_all(es.iter().map(|e| classify(*e, tcx)))
}

ast::ExprVstore(e, vstore) => {
match vstore {
ast::ExprVstoreSlice => classify(e, tcx),
ast::ExprVstoreUniq |
ast::ExprVstoreBox |
ast::ExprVstoreMutBox |
ast::ExprVstoreMutSlice => non_const
}
}

ast::ExprStruct(_, ref fs, None) => {
let cs = do fs.iter().map |f| {
classify(f.expr, tcx)
};
join_all(cs)
}

ast::ExprCast(base, _) => {
let ty = ty::expr_ty(tcx, e);
let base = classify(base, tcx);
if ty::type_is_integral(ty) {
join(integral_const, base)
} else if ty::type_is_fp(ty) {
join(general_const, base)
} else {
non_const
}
}

ast::ExprField(base, _, _) => {
classify(base, tcx)
}

ast::ExprIndex(_, base, idx) => {
join(classify(base, tcx),
classify(idx, tcx))
}

ast::ExprAddrOf(ast::MutImmutable, base) => {
classify(base, tcx)
}

// FIXME: (#3728) we can probably do something CCI-ish
// surrounding nonlocal constants. But we don't yet.
ast::ExprPath(_) => {
lookup_constness(tcx, e)
}

ast::ExprRepeat(*) => general_const,

_ => non_const
};
tcx.ccache.insert(did, cn);
cn
}
}
}

pub fn lookup_const(tcx: ty::ctxt, e: &Expr) -> Option<@Expr> {
match tcx.def_map.find(&e.id) {
Some(&ast::DefStatic(def_id, false)) => lookup_const_by_id(tcx, def_id),
Some(&ast::DefVariant(enum_def, variant_def, _)) => lookup_variant_by_id(tcx,
enum_def,
variant_def),
Some(&ast::DefStatic(def_id, false)) =>
lookup_const_by_id(tcx, def_id),
Some(&ast::DefVariant(enum_def, variant_def, _)) =>
lookup_variant_by_id(tcx, enum_def, variant_def),
_ => None
}
}
Expand Down Expand Up @@ -199,14 +111,18 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt,
Some(_) => None
}
} else {
match tcx.extern_const_variants.find(&variant_def) {
Some(&e) => return e,
None => {}
}
let maps = astencode::Maps {
root_map: @mut HashMap::new(),
method_map: @mut HashMap::new(),
vtable_map: @mut HashMap::new(),
write_guard_map: @mut HashSet::new(),
capture_map: @mut HashMap::new()
};
match csearch::maybe_get_item_ast(tcx, enum_def,
let e = match csearch::maybe_get_item_ast(tcx, enum_def,
|a, b, c, d| astencode::decode_inlined_item(a,
b,
maps,
Expand All @@ -219,7 +135,9 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt,
_ => None
},
_ => None
}
};
tcx.extern_const_variants.insert(variant_def, e);
return e;
}
}

Expand All @@ -236,49 +154,136 @@ pub fn lookup_const_by_id(tcx: ty::ctxt,
Some(_) => None
}
} else {
match tcx.extern_const_statics.find(&def_id) {
Some(&e) => return e,
None => {}
}
let maps = astencode::Maps {
root_map: @mut HashMap::new(),
method_map: @mut HashMap::new(),
vtable_map: @mut HashMap::new(),
write_guard_map: @mut HashSet::new(),
capture_map: @mut HashMap::new()
};
match csearch::maybe_get_item_ast(tcx, def_id,
let e = match csearch::maybe_get_item_ast(tcx, def_id,
|a, b, c, d| astencode::decode_inlined_item(a, b, maps, c, d)) {
csearch::found(ast::ii_item(item)) => match item.node {
item_static(_, ast::MutImmutable, const_expr) => Some(const_expr),
_ => None
},
_ => None
}
};
tcx.extern_const_statics.insert(def_id, e);
return e;
}
}

pub fn lookup_constness(tcx: ty::ctxt, e: &Expr) -> constness {
match lookup_const(tcx, e) {
Some(rhs) => {
let ty = ty::expr_ty(tcx, rhs);
if ty::type_is_integral(ty) {
integral_const
} else {
general_const
struct ConstEvalVisitor {
tcx: ty::ctxt,
ccache: constness_cache,
}

impl ConstEvalVisitor {
fn classify(&mut self, e: &Expr) -> constness {
let did = ast_util::local_def(e.id);
match self.ccache.find(&did) {
Some(&x) => return x,
None => {}
}
let cn = match e.node {
ast::ExprLit(lit) => {
match lit.node {
ast::lit_str(*) | ast::lit_float(*) => general_const,
_ => integral_const
}
}

ast::ExprUnary(_, _, inner) | ast::ExprParen(inner) =>
self.classify(inner),

ast::ExprBinary(_, _, a, b) =>
join(self.classify(a), self.classify(b)),

ast::ExprTup(ref es) |
ast::ExprVec(ref es, ast::MutImmutable) =>
join_all(es.iter().map(|e| self.classify(*e))),

ast::ExprVstore(e, vstore) => {
match vstore {
ast::ExprVstoreSlice => self.classify(e),
ast::ExprVstoreUniq |
ast::ExprVstoreBox |
ast::ExprVstoreMutBox |
ast::ExprVstoreMutSlice => non_const
}
}

ast::ExprStruct(_, ref fs, None) => {
let cs = do fs.iter().map |f| {
self.classify(f.expr)
};
join_all(cs)
}

ast::ExprCast(base, _) => {
let ty = ty::expr_ty(self.tcx, e);
let base = self.classify(base);
if ty::type_is_integral(ty) {
join(integral_const, base)
} else if ty::type_is_fp(ty) {
join(general_const, base)
} else {
non_const
}
}

ast::ExprField(base, _, _) => self.classify(base),

ast::ExprIndex(_, base, idx) =>
join(self.classify(base), self.classify(idx)),

ast::ExprAddrOf(ast::MutImmutable, base) => self.classify(base),

// FIXME: (#3728) we can probably do something CCI-ish
// surrounding nonlocal constants. But we don't yet.
ast::ExprPath(_) => self.lookup_constness(e),

ast::ExprRepeat(*) => general_const,

_ => non_const
};
self.ccache.insert(did, cn);
cn
}

fn lookup_constness(&self, e: &Expr) -> constness {
match lookup_const(self.tcx, e) {
Some(rhs) => {
let ty = ty::expr_ty(self.tcx, rhs);
if ty::type_is_integral(ty) {
integral_const
} else {
general_const
}
}
None => non_const
}
None => non_const
}
}

struct ConstEvalVisitor { tcx: ty::ctxt }
}

impl Visitor<()> for ConstEvalVisitor {
fn visit_expr_post(&mut self, e:@Expr, _:()) {
classify(e, self.tcx);
self.classify(e);
}
}

pub fn process_crate(crate: &ast::Crate,
tcx: ty::ctxt) {
let mut v = ConstEvalVisitor { tcx: tcx };
let mut v = ConstEvalVisitor {
tcx: tcx,
ccache: HashMap::new(),
};
visit::walk_crate(&mut v, crate, ());
tcx.sess.abort_if_errors();
}
Expand Down
12 changes: 8 additions & 4 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@ struct ctxt_ {
freevars: freevars::freevar_map,
tcache: type_cache,
rcache: creader_cache,
ccache: constness_cache,
short_names_cache: @mut HashMap<t, @str>,
needs_unwind_cleanup_cache: @mut HashMap<t, bool>,
tc_cache: @mut HashMap<uint, TypeContents>,
Expand Down Expand Up @@ -346,6 +345,11 @@ struct ctxt_ {
// The set of external traits whose implementations have been read. This
// is used for lazy resolution of traits.
populated_external_traits: @mut HashSet<ast::DefId>,

// These two caches are used by const_eval when decoding external statics
// and variants that are found.
extern_const_statics: @mut HashMap<ast::DefId, Option<@ast::Expr>>,
extern_const_variants: @mut HashMap<ast::DefId, Option<@ast::Expr>>,
}

pub enum tbox_flag {
Expand Down Expand Up @@ -897,8 +901,6 @@ pub struct ty_param_substs_and_ty {

type type_cache = @mut HashMap<ast::DefId, ty_param_bounds_and_ty>;

type constness_cache = @mut HashMap<ast::DefId, const_eval::constness>;

pub type node_type_table = @mut HashMap<uint,t>;

fn mk_rcache() -> creader_cache {
Expand Down Expand Up @@ -935,7 +937,6 @@ pub fn mk_ctxt(s: session::Session,
freevars: freevars,
tcache: @mut HashMap::new(),
rcache: mk_rcache(),
ccache: @mut HashMap::new(),
short_names_cache: new_ty_hash(),
needs_unwind_cleanup_cache: new_ty_hash(),
tc_cache: @mut HashMap::new(),
Expand All @@ -961,6 +962,9 @@ pub fn mk_ctxt(s: session::Session,
impl_vtables: @mut HashMap::new(),
populated_external_types: @mut HashSet::new(),
populated_external_traits: @mut HashSet::new(),

extern_const_statics: @mut HashMap::new(),
extern_const_variants: @mut HashMap::new(),
}
}

Expand Down