mirror of
https://github.com/rust-lang/rust.git
synced 2026-06-01 14:10:03 +03:00
globally cache statics and promoteds
This commit is contained in:
+37
-11
@@ -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> {
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
@@ -152,7 +167,7 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir_map: &'a MirMap<'tcx>) -> Self {
|
||||
.uint_type
|
||||
.bit_width()
|
||||
.expect("Session::target::uint_type was usize")/8),
|
||||
statics: DefIdMap(),
|
||||
statics: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +263,6 @@ fn push_stack_frame(&mut self, def_id: DefId, span: codemap::Span, mir: CachedMi
|
||||
locals: Vec::new(),
|
||||
var_offset: num_args,
|
||||
temp_offset: num_args + num_vars,
|
||||
promoted: HashMap::new(),
|
||||
span: span,
|
||||
def_id: def_id,
|
||||
substs: substs,
|
||||
@@ -1025,10 +1039,18 @@ fn eval_operand(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<Pointer> {
|
||||
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"))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1043,7 +1065,11 @@ fn eval_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>) -> EvalResult<Lvalue> {
|
||||
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)?;
|
||||
|
||||
+20
-27
@@ -10,7 +10,6 @@
|
||||
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 {
|
||||
@@ -73,23 +72,11 @@ fn terminator(&mut self) -> EvalResult<()> {
|
||||
}
|
||||
|
||||
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(())
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -189,19 +177,24 @@ fn visit_constant(&mut self, constant: &mir::Constant<'tcx>) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -211,7 +204,7 @@ fn visit_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>, context: LvalueContext) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user