@@ -4,7 +4,6 @@ use super::{
44 TerminatorTarget ,
55 ConstantId ,
66 GlobalEvalContext ,
7- Frame ,
87} ;
98use error:: EvalResult ;
109use rustc:: mir:: repr as mir;
@@ -13,6 +12,7 @@ use rustc::hir::def_id::DefId;
1312use rustc:: mir:: visit:: { Visitor , LvalueContext } ;
1413use syntax:: codemap:: Span ;
1514use std:: rc:: Rc ;
15+ use memory:: Pointer ;
1616
1717pub enum Event {
1818 Constant ,
@@ -24,13 +24,18 @@ pub enum Event {
2424pub 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
2933impl < ' 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
145153struct 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
151162impl < ' 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