Skip to content

Commit 8d2bc97

Browse files
authored
Merge pull request #553 from solson/rustup
Stacked Borrow: Barriers
2 parents 559ad2d + 3999db1 commit 8d2bc97

14 files changed

+368
-237
lines changed

rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
nightly-2018-11-26
1+
nightly-2018-11-30

src/lib.rs

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ impl<'tcx> Evaluator<'tcx> {
289289
env_vars: HashMap::default(),
290290
tls: TlsData::default(),
291291
validate,
292-
stacked_borrows: stacked_borrows::State::new(),
292+
stacked_borrows: stacked_borrows::State::default(),
293293
}
294294
}
295295
}
@@ -301,6 +301,8 @@ type MiriEvalContext<'a, 'mir, 'tcx> = EvalContext<'a, 'mir, 'tcx, Evaluator<'tc
301301
impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
302302
type MemoryKinds = MiriMemoryKind;
303303

304+
type FrameExtra = stacked_borrows::CallId;
305+
type MemoryExtra = stacked_borrows::MemoryState;
304306
type AllocExtra = stacked_borrows::Stacks;
305307
type PointerTag = Borrow;
306308

@@ -317,7 +319,6 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
317319
// We walk up the stack a few frames to also cover their callees.
318320
const WHITELIST: &[(&str, &str)] = &[
319321
// Uses mem::uninitialized
320-
("std::ptr::read", ""),
321322
("std::sys::windows::mutex::Mutex::", ""),
322323
];
323324
for frame in ecx.stack().iter()
@@ -405,8 +406,9 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
405406
}
406407

407408
fn find_foreign_static(
408-
tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
409409
def_id: DefId,
410+
tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
411+
memory_extra: &Self::MemoryExtra,
410412
) -> EvalResult<'tcx, Cow<'tcx, Allocation<Borrow, Self::AllocExtra>>> {
411413
let attrs = tcx.get_attrs(def_id);
412414
let link_name = match attr::first_attr_value_str_by_name(&attrs, "link_name") {
@@ -417,8 +419,10 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
417419
let alloc = match &link_name[..] {
418420
"__cxa_thread_atexit_impl" => {
419421
// This should be all-zero, pointer-sized
420-
let data = vec![0; tcx.data_layout.pointer_size.bytes() as usize];
421-
Allocation::from_bytes(&data[..], tcx.data_layout.pointer_align.abi)
422+
let size = tcx.data_layout.pointer_size;
423+
let data = vec![0; size.bytes() as usize];
424+
let extra = AllocationExtra::memory_allocated(size, memory_extra);
425+
Allocation::from_bytes(&data[..], tcx.data_layout.pointer_align.abi, extra)
422426
}
423427
_ => return err!(Unimplemented(
424428
format!("can't access foreign static: {}", link_name),
@@ -434,9 +438,14 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
434438
Ok(())
435439
}
436440

437-
fn adjust_static_allocation(
438-
alloc: &'_ Allocation
439-
) -> Cow<'_, Allocation<Borrow, Self::AllocExtra>> {
441+
fn adjust_static_allocation<'b>(
442+
alloc: &'b Allocation,
443+
memory_extra: &Self::MemoryExtra,
444+
) -> Cow<'b, Allocation<Borrow, Self::AllocExtra>> {
445+
let extra = AllocationExtra::memory_allocated(
446+
Size::from_bytes(alloc.bytes.len() as u64),
447+
memory_extra,
448+
);
440449
let alloc: Allocation<Borrow, Self::AllocExtra> = Allocation {
441450
bytes: alloc.bytes.clone(),
442451
relocations: Relocations::from_presorted(
@@ -447,7 +456,7 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
447456
undef_mask: alloc.undef_mask.clone(),
448457
align: alloc.align,
449458
mutability: alloc.mutability,
450-
extra: Self::AllocExtra::default(),
459+
extra,
451460
};
452461
Cow::Owned(alloc)
453462
}
@@ -529,4 +538,19 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
529538
ecx.retag(fn_entry, place)
530539
}
531540
}
541+
542+
#[inline(always)]
543+
fn stack_push(
544+
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
545+
) -> EvalResult<'tcx, stacked_borrows::CallId> {
546+
Ok(ecx.memory().extra.borrow_mut().new_call())
547+
}
548+
549+
#[inline(always)]
550+
fn stack_pop(
551+
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
552+
extra: stacked_borrows::CallId,
553+
) -> EvalResult<'tcx> {
554+
Ok(ecx.memory().extra.borrow_mut().end_call(extra))
555+
}
532556
}

src/range_map.rs

Lines changed: 29 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,6 @@ pub struct RangeMap<T> {
1616
map: BTreeMap<Range, T>,
1717
}
1818

19-
impl<T> Default for RangeMap<T> {
20-
#[inline(always)]
21-
fn default() -> Self {
22-
RangeMap::new()
23-
}
24-
}
25-
2619
// The derived `Ord` impl sorts first by the first field, then, if the fields are the same,
2720
// by the second field.
2821
// This is exactly what we need for our purposes, since a range query on a BTReeSet/BTreeMap will give us all
@@ -73,9 +66,15 @@ impl Range {
7366
}
7467

7568
impl<T> RangeMap<T> {
69+
/// Create a new RangeMap for the given size, and with the given initial value used for
70+
/// the entire range.
7671
#[inline(always)]
77-
pub fn new() -> RangeMap<T> {
78-
RangeMap { map: BTreeMap::new() }
72+
pub fn new(size: Size, init: T) -> RangeMap<T> {
73+
let mut map = RangeMap { map: BTreeMap::new() };
74+
if size.bytes() > 0 {
75+
map.map.insert(Range { start: 0, end: size.bytes() }, init);
76+
}
77+
map
7978
}
8079

8180
fn iter_with_range<'a>(
@@ -95,6 +94,9 @@ impl<T> RangeMap<T> {
9594
)
9695
}
9796

97+
/// Provide read-only iteration over everything in the given range. This does
98+
/// *not* split items if they overlap with the edges. Do not use this to mutate
99+
/// through interior mutability.
98100
pub fn iter<'a>(&'a self, offset: Size, len: Size) -> impl Iterator<Item = &'a T> + 'a {
99101
self.iter_with_range(offset.bytes(), len.bytes()).map(|(_, data)| data)
100102
}
@@ -140,8 +142,7 @@ impl<T> RangeMap<T> {
140142
/// Provide mutable iteration over everything in the given range. As a side-effect,
141143
/// this will split entries in the map that are only partially hit by the given range,
142144
/// to make sure that when they are mutated, the effect is constrained to the given range.
143-
/// If there are gaps, leave them be.
144-
pub fn iter_mut_with_gaps<'a>(
145+
pub fn iter_mut<'a>(
145146
&'a mut self,
146147
offset: Size,
147148
len: Size,
@@ -174,93 +175,34 @@ impl<T> RangeMap<T> {
174175
},
175176
)
176177
}
177-
178-
/// Provide a mutable iterator over everything in the given range, with the same side-effects as
179-
/// iter_mut_with_gaps. Furthermore, if there are gaps between ranges, fill them with the given default
180-
/// before yielding them in the iterator.
181-
/// This is also how you insert.
182-
pub fn iter_mut<'a>(&'a mut self, offset: Size, len: Size) -> impl Iterator<Item = &'a mut T> + 'a
183-
where
184-
T: Clone + Default,
185-
{
186-
if len.bytes() > 0 {
187-
let offset = offset.bytes();
188-
let len = len.bytes();
189-
190-
// Do a first iteration to collect the gaps
191-
let mut gaps = Vec::new();
192-
let mut last_end = offset;
193-
for (range, _) in self.iter_with_range(offset, len) {
194-
if last_end < range.start {
195-
gaps.push(Range {
196-
start: last_end,
197-
end: range.start,
198-
});
199-
}
200-
last_end = range.end;
201-
}
202-
if last_end < offset + len {
203-
gaps.push(Range {
204-
start: last_end,
205-
end: offset + len,
206-
});
207-
}
208-
209-
// Add default for all gaps
210-
for gap in gaps {
211-
let old = self.map.insert(gap, Default::default());
212-
assert!(old.is_none());
213-
}
214-
}
215-
216-
// Now provide mutable iteration
217-
self.iter_mut_with_gaps(offset, len)
218-
}
219-
220-
pub fn retain<F>(&mut self, mut f: F)
221-
where
222-
F: FnMut(&T) -> bool,
223-
{
224-
let mut remove = Vec::new();
225-
for (range, data) in &self.map {
226-
if !f(data) {
227-
remove.push(*range);
228-
}
229-
}
230-
231-
for range in remove {
232-
self.map.remove(&range);
233-
}
234-
}
235178
}
236179

237180
#[cfg(test)]
238181
mod tests {
239182
use super::*;
240183

241184
/// Query the map at every offset in the range and collect the results.
242-
fn to_vec<T: Copy>(map: &RangeMap<T>, offset: u64, len: u64, default: Option<T>) -> Vec<T> {
185+
fn to_vec<T: Copy>(map: &RangeMap<T>, offset: u64, len: u64) -> Vec<T> {
243186
(offset..offset + len)
244187
.into_iter()
245188
.map(|i| map
246189
.iter(Size::from_bytes(i), Size::from_bytes(1))
247190
.next()
248191
.map(|&t| t)
249-
.or(default)
250192
.unwrap()
251193
)
252194
.collect()
253195
}
254196

255197
#[test]
256198
fn basic_insert() {
257-
let mut map = RangeMap::<i32>::new();
199+
let mut map = RangeMap::<i32>::new(Size::from_bytes(20), -1);
258200
// Insert
259201
for x in map.iter_mut(Size::from_bytes(10), Size::from_bytes(1)) {
260202
*x = 42;
261203
}
262204
// Check
263-
assert_eq!(to_vec(&map, 10, 1, None), vec![42]);
205+
assert_eq!(to_vec(&map, 10, 1), vec![42]);
264206

265207
// Insert with size 0
266208
for x in map.iter_mut(Size::from_bytes(10), Size::from_bytes(0)) {
@@ -269,34 +211,42 @@ mod tests {
269211
for x in map.iter_mut(Size::from_bytes(11), Size::from_bytes(0)) {
270212
*x = 19;
271213
}
272-
assert_eq!(to_vec(&map, 10, 2, Some(-1)), vec![42, -1]);
214+
assert_eq!(to_vec(&map, 10, 2), vec![42, -1]);
273215
}
274216

275217
#[test]
276218
fn gaps() {
277-
let mut map = RangeMap::<i32>::new();
219+
let mut map = RangeMap::<i32>::new(Size::from_bytes(20), -1);
278220
for x in map.iter_mut(Size::from_bytes(11), Size::from_bytes(1)) {
279221
*x = 42;
280222
}
281223
for x in map.iter_mut(Size::from_bytes(15), Size::from_bytes(1)) {
282224
*x = 43;
283225
}
284226
assert_eq!(
285-
to_vec(&map, 10, 10, Some(-1)),
227+
to_vec(&map, 10, 10),
286228
vec![-1, 42, -1, -1, -1, 43, -1, -1, -1, -1]
287229
);
288230

289-
// Now request a range that needs three gaps filled
290231
for x in map.iter_mut(Size::from_bytes(10), Size::from_bytes(10)) {
291232
if *x < 42 {
292233
*x = 23;
293234
}
294235
}
295236

296237
assert_eq!(
297-
to_vec(&map, 10, 10, None),
238+
to_vec(&map, 10, 10),
298239
vec![23, 42, 23, 23, 23, 43, 23, 23, 23, 23]
299240
);
300-
assert_eq!(to_vec(&map, 13, 5, None), vec![23, 23, 43, 23, 23]);
241+
assert_eq!(to_vec(&map, 13, 5), vec![23, 23, 43, 23, 23]);
242+
243+
// Now request a range that goes beyond the initial size
244+
for x in map.iter_mut(Size::from_bytes(15), Size::from_bytes(10)) {
245+
*x = 19;
246+
}
247+
assert_eq!(map.iter(Size::from_bytes(19), Size::from_bytes(1))
248+
.map(|&t| t).collect::<Vec<_>>(), vec![19]);
249+
assert_eq!(map.iter(Size::from_bytes(20), Size::from_bytes(1))
250+
.map(|&t| t).collect::<Vec<_>>(), vec![]);
301251
}
302252
}

0 commit comments

Comments
 (0)