Skip to content

Commit b4da6e4

Browse files
committed
Avoid slices where individuals are good enough
1 parent ecde10f commit b4da6e4

File tree

2 files changed

+49
-66
lines changed

2 files changed

+49
-66
lines changed

src/liballoc/collections/btree/node.rs

+42-57
Original file line numberDiff line numberDiff line change
@@ -388,16 +388,16 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
388388
self.as_header().is_shared_root()
389389
}
390390

391-
/// Borrows a view into the keys stored in the node.
392-
/// Unsafe because the caller must ensure that the node is not the shared root.
393-
pub unsafe fn keys(&self) -> &[K] {
394-
self.reborrow().into_key_slice()
391+
/// Borrows a reference to one of the keys stored in the node.
392+
/// Unsafe because the caller must ensure that the node has more than `idx` elements.
393+
pub unsafe fn key_at(&self, idx: usize) -> &K {
394+
self.reborrow().into_key(idx)
395395
}
396396

397-
/// Borrows a view into the values stored in the node.
398-
/// Unsafe because the caller must ensure that the node is not the shared root.
399-
unsafe fn vals(&self) -> &[V] {
400-
self.reborrow().into_val_slice()
397+
/// Borrows a reference to one of the values stored in the node.
398+
/// Unsafe because the caller must ensure that the node has more than `idx` elements.
399+
unsafe fn val_at(&self, idx: usize) -> &V {
400+
self.reborrow().into_val(idx)
401401
}
402402

403403
/// Finds the parent of the current node. Returns `Ok(handle)` if the current
@@ -525,24 +525,24 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
525525
}
526526

527527
impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
528-
/// Unsafe because the caller must ensure that the node is not the shared root.
529-
unsafe fn into_key_slice(self) -> &'a [K] {
530-
debug_assert!(!self.is_shared_root());
531-
// We cannot be the shared root, so `as_leaf` is okay.
532-
slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().keys), self.len())
528+
/// Unsafe because the caller must ensure that the node has more than `idx` elements.
529+
unsafe fn into_key(self, idx: usize) -> &'a K {
530+
debug_assert!(idx < self.len());
531+
// We cannot be empty, so we cannot be the shared root, so `as_leaf` is okay.
532+
&*MaybeUninit::first_ptr(&self.as_leaf().keys).add(idx)
533533
}
534534

535-
/// Unsafe because the caller must ensure that the node is not the shared root.
536-
unsafe fn into_val_slice(self) -> &'a [V] {
537-
debug_assert!(!self.is_shared_root());
538-
// We cannot be the shared root, so `as_leaf` is okay.
539-
slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().vals), self.len())
535+
/// Unsafe because the caller must ensure that the node has more than `idx` elements.
536+
unsafe fn into_val(self, idx: usize) -> &'a V {
537+
debug_assert!(idx < self.len());
538+
// We cannot be empty, so we cannot be the shared root, so `as_leaf` is okay.
539+
&*MaybeUninit::first_ptr(&self.as_leaf().vals).add(idx)
540540
}
541541

542-
/// Unsafe because the caller must ensure that the node is not the shared root.
543-
unsafe fn into_slices(self) -> (&'a [K], &'a [V]) {
542+
/// Unsafe because the caller must ensure that the node has more than `idx` elements.
543+
unsafe fn into_key_val(self, idx: usize) -> (&'a K, &'a V) {
544544
let k = ptr::read(&self);
545-
(k.into_key_slice(), self.into_val_slice())
545+
(k.into_key(idx), self.into_val(idx))
546546
}
547547
}
548548

@@ -572,19 +572,13 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
572572
)
573573
}
574574

575-
/// Unsafe because the caller must ensure that the node is not the shared root.
576-
unsafe fn into_slices_mut(mut self) -> (&'a mut [K], &'a mut [V]) {
577-
debug_assert!(!self.is_shared_root());
578-
// We cannot use the getters here, because calling the second one
579-
// invalidates the reference returned by the first.
580-
// More precisely, it is the call to `len` that is the culprit,
581-
// because that creates a shared reference to the header, which *can*
582-
// overlap with the keys (and even the values, for ZST keys).
583-
let len = self.len();
575+
/// Unsafe because the caller must ensure that the node has more than `idx` elements.
576+
unsafe fn into_key_val_mut(mut self, idx: usize) -> (&'a mut K, &'a mut V) {
577+
debug_assert!(idx < self.len());
584578
let leaf = self.as_leaf_mut();
585-
let keys = slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).keys), len);
586-
let vals = slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).vals), len);
587-
(keys, vals)
579+
let key = MaybeUninit::first_ptr_mut(&mut (*leaf).keys).add(idx).as_mut().unwrap();
580+
let val = MaybeUninit::first_ptr_mut(&mut (*leaf).vals).add(idx).as_mut().unwrap();
581+
(key, val)
588582
}
589583
}
590584

@@ -688,8 +682,8 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
688682
let idx = self.len() - 1;
689683

690684
unsafe {
691-
let key = ptr::read(self.keys().get_unchecked(idx));
692-
let val = ptr::read(self.vals().get_unchecked(idx));
685+
let key = ptr::read(self.key_at(idx));
686+
let val = ptr::read(self.val_at(idx));
693687
let edge = match self.reborrow_mut().force() {
694688
ForceResult::Leaf(_) => None,
695689
ForceResult::Internal(internal) => {
@@ -1039,28 +1033,19 @@ impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Internal>, marke
10391033

10401034
impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Immut<'a>, K, V, NodeType>, marker::KV> {
10411035
pub fn into_kv(self) -> (&'a K, &'a V) {
1042-
unsafe {
1043-
let (keys, vals) = self.node.into_slices();
1044-
(keys.get_unchecked(self.idx), vals.get_unchecked(self.idx))
1045-
}
1036+
unsafe { self.node.into_key_val(self.idx) }
10461037
}
10471038
}
10481039

10491040
impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV> {
10501041
pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) {
1051-
unsafe {
1052-
let (keys, vals) = self.node.into_slices_mut();
1053-
(keys.get_unchecked_mut(self.idx), vals.get_unchecked_mut(self.idx))
1054-
}
1042+
unsafe { self.node.into_key_val_mut(self.idx) }
10551043
}
10561044
}
10571045

10581046
impl<'a, K, V, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV> {
10591047
pub fn kv_mut(&mut self) -> (&mut K, &mut V) {
1060-
unsafe {
1061-
let (keys, vals) = self.node.reborrow_mut().into_slices_mut();
1062-
(keys.get_unchecked_mut(self.idx), vals.get_unchecked_mut(self.idx))
1063-
}
1048+
unsafe { self.node.reborrow_mut().into_key_val_mut(self.idx) }
10641049
}
10651050
}
10661051

@@ -1077,18 +1062,18 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>
10771062
unsafe {
10781063
let mut new_node = Box::new(LeafNode::new());
10791064

1080-
let k = ptr::read(self.node.keys().get_unchecked(self.idx));
1081-
let v = ptr::read(self.node.vals().get_unchecked(self.idx));
1065+
let k = ptr::read(self.node.key_at(self.idx));
1066+
let v = ptr::read(self.node.val_at(self.idx));
10821067

10831068
let new_len = self.node.len() - self.idx - 1;
10841069

10851070
ptr::copy_nonoverlapping(
1086-
self.node.keys().as_ptr().add(self.idx + 1),
1071+
self.node.key_at(self.idx + 1),
10871072
new_node.keys.as_mut_ptr() as *mut K,
10881073
new_len,
10891074
);
10901075
ptr::copy_nonoverlapping(
1091-
self.node.vals().as_ptr().add(self.idx + 1),
1076+
self.node.val_at(self.idx + 1),
10921077
new_node.vals.as_mut_ptr() as *mut V,
10931078
new_len,
10941079
);
@@ -1127,19 +1112,19 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
11271112
unsafe {
11281113
let mut new_node = Box::new(InternalNode::new());
11291114

1130-
let k = ptr::read(self.node.keys().get_unchecked(self.idx));
1131-
let v = ptr::read(self.node.vals().get_unchecked(self.idx));
1115+
let k = ptr::read(self.node.key_at(self.idx));
1116+
let v = ptr::read(self.node.val_at(self.idx));
11321117

11331118
let height = self.node.height;
11341119
let new_len = self.node.len() - self.idx - 1;
11351120

11361121
ptr::copy_nonoverlapping(
1137-
self.node.keys().as_ptr().add(self.idx + 1),
1122+
self.node.key_at(self.idx + 1),
11381123
new_node.data.keys.as_mut_ptr() as *mut K,
11391124
new_len,
11401125
);
11411126
ptr::copy_nonoverlapping(
1142-
self.node.vals().as_ptr().add(self.idx + 1),
1127+
self.node.val_at(self.idx + 1),
11431128
new_node.data.vals.as_mut_ptr() as *mut V,
11441129
new_len,
11451130
);
@@ -1196,7 +1181,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
11961181
slice_remove(self.node.keys_mut(), self.idx),
11971182
);
11981183
ptr::copy_nonoverlapping(
1199-
right_node.keys().as_ptr(),
1184+
right_node.key_at(0),
12001185
left_node.keys_mut().as_mut_ptr().add(left_len + 1),
12011186
right_len,
12021187
);
@@ -1205,7 +1190,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
12051190
slice_remove(self.node.vals_mut(), self.idx),
12061191
);
12071192
ptr::copy_nonoverlapping(
1208-
right_node.vals().as_ptr(),
1193+
right_node.val_at(0),
12091194
left_node.vals_mut().as_mut_ptr().add(left_len + 1),
12101195
right_len,
12111196
);

src/liballoc/collections/btree/search.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,15 @@ where
6161
{
6262
// This function is defined over all borrow types (immutable, mutable, owned),
6363
// and may be called on the shared root in each case.
64-
// Using `keys()` is fine here even if BorrowType is mutable, as all we return
64+
// Using `keys_at()` is fine here even if BorrowType is mutable, as all we return
6565
// is an index -- not a reference.
6666
let len = node.len();
67-
if len > 0 {
68-
let keys = unsafe { node.keys() }; // safe because a non-empty node cannot be the shared root
69-
for (i, k) in keys.iter().enumerate() {
70-
match key.cmp(k.borrow()) {
71-
Ordering::Greater => {}
72-
Ordering::Equal => return (i, true),
73-
Ordering::Less => return (i, false),
74-
}
67+
for i in 0..len {
68+
let key_at_i = unsafe { node.key_at(i) };
69+
match key.cmp(key_at_i.borrow()) {
70+
Ordering::Greater => {}
71+
Ordering::Equal => return (i, true),
72+
Ordering::Less => return (i, false),
7573
}
7674
}
7775
(len, false)

0 commit comments

Comments
 (0)