Skip to content

Commit 8b25bc8

Browse files
committed
directly push stackframes for constants when they are encountered
1 parent 6b939bb commit 8b25bc8

File tree

2 files changed

+42
-35
lines changed

2 files changed

+42
-35
lines changed

src/interpreter/mod.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use std::rc::Rc;
1414
use std::{iter, mem};
1515
use syntax::ast;
1616
use syntax::attr;
17-
use syntax::codemap::{self, DUMMY_SP, Span};
17+
use syntax::codemap::{self, DUMMY_SP};
1818

1919
use error::{EvalError, EvalResult};
2020
use memory::{Memory, Pointer};
@@ -94,9 +94,6 @@ struct Frame<'a, 'tcx: 'a> {
9494

9595
/// The index of the currently evaluated statment
9696
stmt: usize,
97-
98-
// Constants that need to be evaluated before the next statement can be evaluated
99-
constants: Vec<(ConstantId<'tcx>, Span, Pointer, CachedMir<'a, 'tcx>)>,
10097
}
10198

10299
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@@ -409,7 +406,7 @@ impl<'a, 'b, 'mir, 'tcx> FnEvalContext<'a, 'b, 'mir, 'tcx> {
409406

410407
loop {
411408
match stepper.step()? {
412-
Constant => trace!("next statement requires the computation of a constant"),
409+
Constant => trace!("computing a constant"),
413410
Assignment => trace!("{:?}", stepper.stmt()),
414411
Terminator => {
415412
trace!("{:?}", stepper.term().kind);
@@ -444,7 +441,6 @@ impl<'a, 'b, 'mir, 'tcx> FnEvalContext<'a, 'b, 'mir, 'tcx> {
444441
def_id: def_id,
445442
substs: substs,
446443
stmt: 0,
447-
constants: Vec::new(),
448444
});
449445

450446
let locals: Vec<Pointer> = arg_tys.chain(var_tys).chain(temp_tys).map(|ty| {

src/interpreter/stepper.rs

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use super::{
44
TerminatorTarget,
55
ConstantId,
66
GlobalEvalContext,
7-
Frame,
87
};
98
use error::EvalResult;
109
use rustc::mir::repr as mir;
@@ -13,6 +12,7 @@ use rustc::hir::def_id::DefId;
1312
use rustc::mir::visit::{Visitor, LvalueContext};
1413
use syntax::codemap::Span;
1514
use std::rc::Rc;
15+
use memory::Pointer;
1616

1717
pub enum Event {
1818
Constant,
@@ -24,13 +24,18 @@ pub enum Event {
2424
pub struct Stepper<'fncx, 'a: 'fncx, 'b: 'a + 'mir, 'mir: 'fncx, 'tcx: 'b>{
2525
fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>,
2626
process: fn (&mut Stepper<'fncx, 'a, 'b, 'mir, 'tcx>) -> EvalResult<()>,
27+
28+
// a cache of the constants to be computed before the next statement/terminator
29+
// this is an optimization, so we don't have to allocate a new vector for every statement
30+
constants: Vec<(ConstantId<'tcx>, Span, Pointer, CachedMir<'mir, 'tcx>)>,
2731
}
2832

2933
impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx> {
3034
pub(super) fn new(fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>) -> Self {
3135
Stepper {
3236
fncx: fncx,
3337
process: Self::dummy,
38+
constants: Vec::new(),
3439
}
3540
}
3641

@@ -60,22 +65,13 @@ impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx
6065
match term {
6166
TerminatorTarget::Block => {},
6267
TerminatorTarget::Return => {
63-
assert!(self.fncx.frame().constants.is_empty());
6468
self.fncx.pop_stack_frame();
6569
},
6670
TerminatorTarget::Call => {},
6771
}
6872
Ok(())
6973
}
7074

71-
fn constant(&mut self) -> EvalResult<()> {
72-
let (cid, span, return_ptr, mir) = self.fncx.frame_mut().constants.pop().expect("state machine broken");
73-
let def_id = cid.def_id();
74-
let substs = cid.substs();
75-
self.fncx.push_stack_frame(def_id, span, mir, substs, Some(return_ptr));
76-
Ok(())
77-
}
78-
7975
pub fn step(&mut self) -> EvalResult<Event> {
8076
(self.process)(self)?;
8177

@@ -85,48 +81,60 @@ impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx
8581
return Ok(Event::Done);
8682
}
8783

88-
if !self.fncx.frame().constants.is_empty() {
89-
self.process = Self::constant;
90-
return Ok(Event::Constant);
91-
}
92-
9384
let block = self.fncx.frame().next_block;
9485
let stmt = self.fncx.frame().stmt;
9586
let mir = self.fncx.mir();
9687
let basic_block = mir.basic_block_data(block);
9788

9889
if let Some(ref stmt) = basic_block.statements.get(stmt) {
99-
assert!(self.fncx.frame().constants.is_empty());
90+
assert!(self.constants.is_empty());
10091
ConstantExtractor {
10192
span: stmt.span,
93+
substs: self.fncx.substs(),
94+
def_id: self.fncx.frame().def_id,
10295
gecx: self.fncx.gecx,
103-
frame: self.fncx.stack.last_mut().expect("stack empty"),
96+
constants: &mut self.constants,
97+
mir: &mir,
10498
}.visit_statement(block, stmt);
105-
if self.fncx.frame().constants.is_empty() {
99+
if self.constants.is_empty() {
106100
self.process = Self::statement;
107101
return Ok(Event::Assignment);
108102
} else {
109-
self.process = Self::constant;
103+
self.process = Self::statement;
104+
self.extract_constants();
110105
return Ok(Event::Constant);
111106
}
112107
}
113108

114109
let terminator = basic_block.terminator();
115-
assert!(self.fncx.frame().constants.is_empty());
110+
assert!(self.constants.is_empty());
116111
ConstantExtractor {
117112
span: terminator.span,
113+
substs: self.fncx.substs(),
114+
def_id: self.fncx.frame().def_id,
118115
gecx: self.fncx.gecx,
119-
frame: self.fncx.stack.last_mut().expect("stack empty"),
116+
constants: &mut self.constants,
117+
mir: &mir,
120118
}.visit_terminator(block, terminator);
121-
if self.fncx.frame().constants.is_empty() {
119+
if self.constants.is_empty() {
122120
self.process = Self::terminator;
123121
Ok(Event::Terminator)
124122
} else {
125-
self.process = Self::constant;
123+
self.process = Self::statement;
124+
self.extract_constants();
126125
Ok(Event::Constant)
127126
}
128127
}
129128

129+
fn extract_constants(&mut self) {
130+
assert!(!self.constants.is_empty());
131+
for (cid, span, return_ptr, mir) in self.constants.drain(..) {
132+
let def_id = cid.def_id();
133+
let substs = cid.substs();
134+
self.fncx.push_stack_frame(def_id, span, mir, substs, Some(return_ptr));
135+
}
136+
}
137+
130138
/// returns the statement that will be processed next
131139
pub fn stmt(&self) -> &mir::Statement {
132140
&self.fncx.basic_block().statements[self.fncx.frame().stmt]
@@ -144,8 +152,11 @@ impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx
144152

145153
struct ConstantExtractor<'a, 'b: 'mir, 'mir: 'a, 'tcx: 'b> {
146154
span: Span,
147-
frame: &'a mut Frame<'mir, 'tcx>,
155+
constants: &'a mut Vec<(ConstantId<'tcx>, Span, Pointer, CachedMir<'mir, 'tcx>)>,
148156
gecx: &'a mut GlobalEvalContext<'b, 'tcx>,
157+
mir: &'a mir::Mir<'tcx>,
158+
def_id: DefId,
159+
substs: &'tcx subst::Substs<'tcx>,
149160
}
150161

151162
impl<'a, 'b, 'mir, 'tcx> ConstantExtractor<'a, 'b, 'mir, 'tcx> {
@@ -160,7 +171,7 @@ impl<'a, 'b, 'mir, 'tcx> ConstantExtractor<'a, 'b, 'mir, 'tcx> {
160171
let mir = self.gecx.load_mir(def_id);
161172
let ptr = self.gecx.alloc_ret_ptr(mir.return_ty, substs).expect("there's no such thing as an unreachable static");
162173
self.gecx.statics.insert(cid.clone(), ptr);
163-
self.frame.constants.push((cid, span, ptr, mir));
174+
self.constants.push((cid, span, ptr, mir));
164175
}
165176
}
166177

@@ -180,19 +191,19 @@ impl<'a, 'b, 'mir, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'mir, 'tcx>
180191
},
181192
mir::Literal::Promoted { index } => {
182193
let cid = ConstantId::Promoted {
183-
def_id: self.frame.def_id,
184-
substs: self.frame.substs,
194+
def_id: self.def_id,
195+
substs: self.substs,
185196
index: index,
186197
};
187198
if self.gecx.statics.contains_key(&cid) {
188199
return;
189200
}
190-
let mir = self.frame.mir.promoted[index].clone();
201+
let mir = self.mir.promoted[index].clone();
191202
let return_ty = mir.return_ty;
192203
let return_ptr = self.gecx.alloc_ret_ptr(return_ty, cid.substs()).expect("there's no such thing as an unreachable static");
193204
let mir = CachedMir::Owned(Rc::new(mir));
194205
self.gecx.statics.insert(cid.clone(), return_ptr);
195-
self.frame.constants.push((cid, constant.span, return_ptr, mir));
206+
self.constants.push((cid, constant.span, return_ptr, mir));
196207
}
197208
}
198209
}

0 commit comments

Comments
 (0)