Skip to content

Commit ac21ef4

Browse files
authored
Merge pull request rust-lang#91 from oli-obk/master
rustup and small fixes
2 parents c076321 + 5dd01c3 commit ac21ef4

File tree

4 files changed

+54
-41
lines changed

4 files changed

+54
-41
lines changed

Diff for: src/interpreter/mod.rs

+17-23
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ pub struct Frame<'tcx> {
8282
/// Before being initialized, a local is simply marked as None.
8383
pub locals: Vec<Option<Value>>,
8484

85+
/// Temporary allocations introduced to save stackframes
86+
/// This is pure interpreter magic and has nothing to do with how rustc does it
87+
/// An example is calling an FnMut closure that has been converted to a FnOnce closure
88+
/// The memory will be freed when the stackframe finishes
89+
pub interpreter_temporaries: Vec<Pointer>,
90+
8591
////////////////////////////////////////////////////////////////////////////////
8692
// Current position within the function
8793
////////////////////////////////////////////////////////////////////////////////
@@ -327,6 +333,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
327333
substs: &'tcx Substs<'tcx>,
328334
return_lvalue: Lvalue<'tcx>,
329335
return_to_block: StackPopCleanup,
336+
temporaries: Vec<Pointer>,
330337
) -> EvalResult<'tcx, ()> {
331338
::log_settings::settings().indentation += 1;
332339

@@ -341,6 +348,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
341348
return_to_block: return_to_block,
342349
return_lvalue: return_lvalue,
343350
locals: locals,
351+
interpreter_temporaries: temporaries,
344352
span: span,
345353
def_id: def_id,
346354
substs: substs,
@@ -385,9 +393,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
385393
StackPopCleanup::None => {},
386394
}
387395
// deallocate all locals that are backed by an allocation
388-
for (i, local) in frame.locals.into_iter().enumerate() {
396+
for local in frame.locals.into_iter() {
389397
if let Some(Value::ByRef(ptr)) = local {
390-
trace!("deallocating local {}: {:?}", i + 1, ptr);
398+
trace!("deallocating local");
391399
self.memory.dump(ptr.alloc_id);
392400
match self.memory.deallocate(ptr) {
393401
// Any frozen memory means that it belongs to a constant or something referenced
@@ -399,6 +407,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
399407
}
400408
}
401409
}
410+
// deallocate all temporary allocations
411+
for ptr in frame.interpreter_temporaries {
412+
trace!("deallocating temporary allocation");
413+
self.memory.dump(ptr.alloc_id);
414+
self.memory.deallocate(ptr)?;
415+
}
402416
Ok(())
403417
}
404418

@@ -1131,27 +1145,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
11311145
Ok(new_lvalue)
11321146
}
11331147

1134-
// FIXME(solson): This method unnecessarily allocates and should not be necessary. We can
1135-
// remove it as soon as PrimVal can represent fat pointers.
1136-
fn value_to_ptr_dont_use(&mut self, value: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, Pointer> {
1137-
match value {
1138-
Value::ByRef(ptr) => Ok(ptr),
1139-
1140-
Value::ByVal(primval) => {
1141-
let ptr = self.alloc_ptr(ty)?;
1142-
let kind = self.ty_to_primval_kind(ty)?;
1143-
self.memory.write_primval(ptr, primval, kind)?;
1144-
Ok(ptr)
1145-
}
1146-
1147-
Value::ByValPair(a, b) => {
1148-
let ptr = self.alloc_ptr(ty)?;
1149-
self.write_pair_to_ptr(a, b, ptr, ty)?;
1150-
Ok(ptr)
1151-
}
1152-
}
1153-
}
1154-
11551148
/// ensures this Value is not a ByRef
11561149
fn follow_by_ref_value(&mut self, value: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
11571150
match value {
@@ -1719,6 +1712,7 @@ pub fn eval_main<'a, 'tcx: 'a>(
17191712
tcx.intern_substs(&[]),
17201713
Lvalue::from_ptr(Pointer::zst_ptr()),
17211714
StackPopCleanup::None,
1715+
Vec::new(),
17221716
).expect("could not allocate first stack frame");
17231717

17241718
loop {

Diff for: src/interpreter/step.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ impl<'a, 'b, 'tcx> ConstantExtractor<'a, 'b, 'tcx> {
145145
} else {
146146
StackPopCleanup::None
147147
};
148-
this.ecx.push_stack_frame(def_id, span, mir, substs, Lvalue::Global(cid), cleanup)
148+
this.ecx.push_stack_frame(def_id, span, mir, substs, Lvalue::Global(cid), cleanup, Vec::new())
149149
});
150150
}
151151
fn try<F: FnOnce(&mut Self) -> EvalResult<'tcx, ()>>(&mut self, f: F) {
@@ -194,7 +194,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'tcx> {
194194
mir,
195195
this.substs,
196196
Lvalue::Global(cid),
197-
StackPopCleanup::Freeze)
197+
StackPopCleanup::Freeze,
198+
Vec::new())
198199
});
199200
}
200201
}

Diff for: src/interpreter/terminator/intrinsics.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
190190
};
191191
let mut drops = Vec::new();
192192
self.drop(lvalue, ty, &mut drops)?;
193+
let span = {
194+
let frame = self.frame();
195+
frame.mir[frame.block].terminator().source_info.span
196+
};
193197
// need to change the block before pushing the drop impl stack frames
194198
// we could do this for all intrinsics before evaluating the intrinsics, but if
195199
// the evaluation fails, we should not have moved forward
196200
self.goto_block(target);
197-
return self.eval_drop_impls(drops);
201+
return self.eval_drop_impls(drops, span);
198202
}
199203

200204
"fabsf32" => {

Diff for: src/interpreter/terminator/mod.rs

+29-15
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
118118
let mut drops = Vec::new();
119119
self.drop(lval, ty, &mut drops)?;
120120
self.goto_block(target);
121-
self.eval_drop_impls(drops)?;
121+
self.eval_drop_impls(drops, terminator.source_info.span)?;
122122
}
123123

124124
Assert { ref cond, expected, ref msg, target, .. } => {
@@ -151,12 +151,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
151151
Ok(())
152152
}
153153

154-
pub fn eval_drop_impls(&mut self, drops: Vec<(DefId, Value, &'tcx Substs<'tcx>)>) -> EvalResult<'tcx, ()> {
155-
let span = self.frame().span;
154+
pub fn eval_drop_impls(&mut self, drops: Vec<(DefId, Value, &'tcx Substs<'tcx>)>, span: Span) -> EvalResult<'tcx, ()> {
156155
// add them to the stack in reverse order, because the impl that needs to run the last
157156
// is the one that needs to be at the bottom of the stack
158157
for (drop_def_id, self_arg, substs) in drops.into_iter().rev() {
159-
// FIXME: supply a real span
160158
let mir = self.load_mir(drop_def_id)?;
161159
trace!("substs for drop glue: {:?}", substs);
162160
self.push_stack_frame(
@@ -166,6 +164,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
166164
substs,
167165
Lvalue::from_ptr(Pointer::zst_ptr()),
168166
StackPopCleanup::None,
167+
Vec::new(),
169168
)?;
170169
let mut arg_locals = self.frame().mir.args_iter();
171170
let first = arg_locals.next().expect("drop impl has self arg");
@@ -213,11 +212,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
213212
}
214213

215214
// Only trait methods can have a Self parameter.
216-
let (resolved_def_id, resolved_substs) =
215+
let (resolved_def_id, resolved_substs, temporaries) =
217216
if let Some(trait_id) = self.tcx.trait_of_item(def_id) {
218217
self.trait_method(trait_id, def_id, substs, &mut args)?
219218
} else {
220-
(def_id, substs)
219+
(def_id, substs, Vec::new())
221220
};
222221

223222
let mir = self.load_mir(resolved_def_id)?;
@@ -237,6 +236,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
237236
resolved_substs,
238237
return_lvalue,
239238
return_to_block,
239+
temporaries,
240240
)?;
241241

242242
let arg_locals = self.frame().mir.args_iter();
@@ -432,7 +432,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
432432
def_id: DefId,
433433
substs: &'tcx Substs<'tcx>,
434434
args: &mut Vec<(Value, Ty<'tcx>)>,
435-
) -> EvalResult<'tcx, (DefId, &'tcx Substs<'tcx>)> {
435+
) -> EvalResult<'tcx, (DefId, &'tcx Substs<'tcx>, Vec<Pointer>)> {
436436
let trait_ref = ty::TraitRef::from_method(self.tcx, trait_id, substs);
437437
let trait_ref = self.tcx.normalize_associated_type(&ty::Binder(trait_ref));
438438

@@ -444,7 +444,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
444444
// and those from the method:
445445
let (did, substs) = find_method(self.tcx, substs, impl_did, vtable_impl.substs, mname);
446446

447-
Ok((did, substs))
447+
Ok((did, substs, Vec::new()))
448448
}
449449

450450
traits::VtableClosure(vtable_closure) => {
@@ -455,6 +455,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
455455
let closure_kind = self.tcx.closure_kind(vtable_closure.closure_def_id);
456456
trace!("closures {:?}, {:?}", closure_kind, trait_closure_kind);
457457
self.unpack_fn_args(args)?;
458+
let mut temporaries = Vec::new();
458459
match (closure_kind, trait_closure_kind) {
459460
(ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
460461
(ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
@@ -474,23 +475,36 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
474475

475476
// Interpreter magic: insert an intermediate pointer, so we can skip the
476477
// intermediate function call.
477-
// FIXME: this is a memory leak, should probably add the pointer to the
478-
// current stack.
479-
let first = self.value_to_ptr_dont_use(args[0].0, args[0].1)?;
480-
args[0].0 = Value::ByVal(PrimVal::from_ptr(first));
478+
let ptr = match args[0].0 {
479+
Value::ByRef(ptr) => ptr,
480+
Value::ByVal(primval) => {
481+
let ptr = self.alloc_ptr(args[0].1)?;
482+
let kind = self.ty_to_primval_kind(args[0].1)?;
483+
self.memory.write_primval(ptr, primval, kind)?;
484+
temporaries.push(ptr);
485+
ptr
486+
},
487+
Value::ByValPair(a, b) => {
488+
let ptr = self.alloc_ptr(args[0].1)?;
489+
self.write_pair_to_ptr(a, b, ptr, args[0].1)?;
490+
temporaries.push(ptr);
491+
ptr
492+
},
493+
};
494+
args[0].0 = Value::ByVal(PrimVal::from_ptr(ptr));
481495
args[0].1 = self.tcx.mk_mut_ptr(args[0].1);
482496
}
483497

484498
_ => bug!("cannot convert {:?} to {:?}", closure_kind, trait_closure_kind),
485499
}
486-
Ok((vtable_closure.closure_def_id, vtable_closure.substs.substs))
500+
Ok((vtable_closure.closure_def_id, vtable_closure.substs.substs, temporaries))
487501
}
488502

489503
traits::VtableFnPointer(vtable_fn_ptr) => {
490504
if let ty::TyFnDef(did, ref substs, _) = vtable_fn_ptr.fn_ty.sty {
491505
args.remove(0);
492506
self.unpack_fn_args(args)?;
493-
Ok((did, substs))
507+
Ok((did, substs, Vec::new()))
494508
} else {
495509
bug!("VtableFnPointer did not contain a concrete function: {:?}", vtable_fn_ptr)
496510
}
@@ -506,7 +520,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
506520
let fn_ptr = self.memory.read_ptr(vtable.offset(offset))?;
507521
let (def_id, substs, _abi, sig) = self.memory.get_fn(fn_ptr.alloc_id)?;
508522
*first_ty = sig.inputs[0];
509-
Ok((def_id, substs))
523+
Ok((def_id, substs, Vec::new()))
510524
} else {
511525
Err(EvalError::VtableForArgumentlessMethod)
512526
}

0 commit comments

Comments
 (0)