Skip to content

Commit

Permalink
globally cache statics and promoteds
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Jun 3, 2016
1 parent dc85b11 commit 4c833a5
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 38 deletions.
48 changes: 37 additions & 11 deletions src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ struct GlobalEvalContext<'a, 'tcx: 'a> {
/// The virtual memory system.
memory: Memory,

/// Precomputed statics and constants
statics: DefIdMap<Pointer>,
/// Precomputed statics, constants and promoteds
statics: HashMap<ConstantId<'tcx>, Pointer>,
}

struct FnEvalContext<'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> {
Expand Down Expand Up @@ -92,9 +92,6 @@ struct Frame<'a, 'tcx: 'a> {
/// The offset of the first temporary in `self.locals`.
temp_offset: usize,

/// List of precomputed promoted constants
promoted: HashMap<usize, Pointer>,

/// The index of the currently evaluated statment
stmt: usize,

Expand Down Expand Up @@ -136,10 +133,28 @@ enum TerminatorTarget {

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
enum ConstantId<'tcx> {
Promoted { index: usize },
Promoted { def_id: DefId, substs: &'tcx Substs<'tcx>, index: usize },
Static { def_id: DefId, substs: &'tcx Substs<'tcx> },
}

impl<'tcx> ConstantId<'tcx> {
fn substs(&self) -> &'tcx Substs<'tcx> {
use self::ConstantId::*;
match *self {
Promoted { substs, .. } |
Static { substs, .. } => substs
}
}

fn def_id(&self) -> DefId {
use self::ConstantId::*;
match *self {
Promoted { def_id, .. } |
Static { def_id, .. } => def_id,
}
}
}


impl<'a, 'tcx> GlobalEvalContext<'a, 'tcx> {
fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir_map: &'a MirMap<'tcx>) -> Self {
Expand All @@ -152,7 +167,7 @@ impl<'a, 'tcx> GlobalEvalContext<'a, 'tcx> {
.uint_type
.bit_width()
.expect("Session::target::uint_type was usize")/8),
statics: DefIdMap(),
statics: HashMap::new(),
}
}

Expand Down Expand Up @@ -248,7 +263,6 @@ impl<'a, 'b, 'mir, 'tcx> FnEvalContext<'a, 'b, 'mir, 'tcx> {
locals: Vec::new(),
var_offset: num_args,
temp_offset: num_args + num_vars,
promoted: HashMap::new(),
span: span,
def_id: def_id,
substs: substs,
Expand Down Expand Up @@ -1025,10 +1039,18 @@ impl<'a, 'b, 'mir, 'tcx> FnEvalContext<'a, 'b, 'mir, 'tcx> {
if item_ty.ty.is_fn() {
Err(EvalError::Unimplemented("unimplemented: mentions of function items".to_string()))
} else {
Ok(*self.statics.get(&def_id).expect("static should have been cached (rvalue)"))
let cid = ConstantId::Static{ def_id: def_id, substs: substs };
Ok(*self.statics.get(&cid).expect("static should have been cached (rvalue)"))
}
},
Promoted { index } => Ok(*self.frame().promoted.get(&index).expect("a promoted constant hasn't been precomputed")),
Promoted { index } => {
let cid = ConstantId::Promoted {
def_id: self.frame().def_id,
substs: self.substs(),
index: index,
};
Ok(*self.statics.get(&cid).expect("a promoted constant hasn't been precomputed"))
},
}
}
}
Expand All @@ -1043,7 +1065,11 @@ impl<'a, 'b, 'mir, 'tcx> FnEvalContext<'a, 'b, 'mir, 'tcx> {
Var(i) => self.frame().locals[self.frame().var_offset + i as usize],
Temp(i) => self.frame().locals[self.frame().temp_offset + i as usize],

Static(def_id) => *self.gecx.statics.get(&def_id).expect("static should have been cached (lvalue)"),
Static(def_id) => {
let substs = self.tcx.mk_substs(subst::Substs::empty());
let cid = ConstantId::Static{ def_id: def_id, substs: substs };
*self.gecx.statics.get(&cid).expect("static should have been cached (lvalue)")
},

Projection(ref proj) => {
let base = self.eval_lvalue(&proj.base)?;
Expand Down
47 changes: 20 additions & 27 deletions src/interpreter/stepper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use rustc::ty::subst::{self, Subst};
use rustc::hir::def_id::DefId;
use rustc::mir::visit::{Visitor, LvalueContext};
use syntax::codemap::Span;
use memory::Pointer;
use std::rc::Rc;

pub enum Event {
Expand Down Expand Up @@ -73,23 +72,11 @@ impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx
}

fn constant(&mut self) -> EvalResult<()> {
match self.fncx.frame_mut().constants.pop() {
Some((ConstantId::Promoted { index }, span, return_ptr, mir)) => {
trace!("adding promoted constant {}, {:?}", index, span);
let substs = self.fncx.substs();
// FIXME: somehow encode that this is a promoted constant's frame
let def_id = self.fncx.frame().def_id;
self.fncx.push_stack_frame(def_id, span, mir, substs, Some(return_ptr));
self.mir = self.fncx.mir();
},
Some((ConstantId::Static { def_id, substs }, span, return_ptr, mir)) => {
trace!("adding static {:?}, {:?}", def_id, span);
self.fncx.gecx.statics.insert(def_id, return_ptr);
self.fncx.push_stack_frame(def_id, span, mir, substs, Some(return_ptr));
self.mir = self.fncx.mir();
},
None => unreachable!(),
}
let (cid, span, return_ptr, mir) = self.fncx.frame_mut().constants.pop().expect("state machine broken");
let def_id = cid.def_id();
let substs = cid.substs();
self.fncx.push_stack_frame(def_id, span, mir, substs, Some(return_ptr));
self.mir = self.fncx.mir();
Ok(())
}

Expand Down Expand Up @@ -164,16 +151,17 @@ struct ConstantExtractor<'a: 'c, 'b: 'a + 'mir + 'c, 'c, 'mir: 'c, 'tcx: 'a + 'b
}

impl<'a, 'b, 'c, 'mir, 'tcx> ConstantExtractor<'a, 'b, 'c, 'mir, 'tcx> {
fn constant(&mut self, def_id: DefId, substs: &'tcx subst::Substs<'tcx>, span: Span) {
if self.fncx.gecx.statics.contains_key(&def_id) {
return;
}
fn static_item(&mut self, def_id: DefId, substs: &'tcx subst::Substs<'tcx>, span: Span) {
let cid = ConstantId::Static {
def_id: def_id,
substs: substs,
};
if self.fncx.gecx.statics.contains_key(&cid) {
return;
}
let mir = self.fncx.load_mir(def_id);
let ptr = self.fncx.alloc_ret_ptr(mir.return_ty).expect("there's no such thing as an unreachable static");
self.fncx.statics.insert(cid.clone(), ptr);
self.fncx.frame_mut().constants.push((cid, span, ptr, mir));
}
}
Expand All @@ -189,19 +177,24 @@ impl<'a, 'b, 'c, 'mir, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'c, 'mi
if item_ty.ty.is_fn() {
// unimplemented
} else {
self.constant(def_id, substs, constant.span);
self.static_item(def_id, substs, constant.span);
}
},
mir::Literal::Promoted { index } => {
if self.fncx.frame().promoted.contains_key(&index) {
let cid = ConstantId::Promoted {
def_id: self.fncx.frame().def_id,
substs: self.fncx.substs(),
index: index,
};
if self.fncx.statics.contains_key(&cid) {
return;
}
let mir = self.mir.promoted[index].clone();
let return_ty = mir.return_ty;
let return_ptr = self.fncx.alloc_ret_ptr(return_ty).expect("there's no such thing as an unreachable static");
self.fncx.frame_mut().promoted.insert(index, return_ptr);
let mir = CachedMir::Owned(Rc::new(mir));
self.fncx.frame_mut().constants.push((ConstantId::Promoted { index: index }, constant.span, return_ptr, mir));
self.fncx.statics.insert(cid.clone(), return_ptr);
self.fncx.frame_mut().constants.push((cid, constant.span, return_ptr, mir));
}
}
}
Expand All @@ -211,7 +204,7 @@ impl<'a, 'b, 'c, 'mir, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'c, 'mi
if let mir::Lvalue::Static(def_id) = *lvalue {
let substs = self.fncx.tcx.mk_substs(subst::Substs::empty());
let span = self.span;
self.constant(def_id, substs, span);
self.static_item(def_id, substs, span);
}
}
}

0 comments on commit 4c833a5

Please sign in to comment.