Skip to content

Commit 751c14f

Browse files
committed
BTree: initialize node on the heap through initialized header
1 parent ee88f46 commit 751c14f

File tree

2 files changed

+36
-34
lines changed

2 files changed

+36
-34
lines changed

library/alloc/src/collections/btree/node.rs

+35-33
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ const KV_IDX_CENTER: usize = B - 1;
4747
const EDGE_IDX_LEFT_OF_CENTER: usize = B - 1;
4848
const EDGE_IDX_RIGHT_OF_CENTER: usize = B;
4949

50-
/// The underlying representation of leaf nodes and part of the representation of internal nodes.
51-
struct LeafNode<K, V> {
50+
/// Header of any node, defined separately to optimize initialization.
51+
struct Head<K, V> {
5252
/// We want to be covariant in `K` and `V`.
5353
parent: Option<NonNull<InternalNode<K, V>>>,
5454

@@ -59,6 +59,11 @@ struct LeafNode<K, V> {
5959

6060
/// The number of keys and values this node stores.
6161
len: u16,
62+
}
63+
64+
/// The underlying representation of leaf nodes and part of the representation of internal nodes.
65+
struct LeafNode<K, V> {
66+
head: Head<K, V>,
6267

6368
/// The arrays storing the actual data of the node. Only the first `len` elements of each
6469
/// array are initialized and valid.
@@ -72,15 +77,16 @@ impl<K, V> LeafNode<K, V> {
7277
// As a general policy, we leave fields uninitialized if they can be, as this should
7378
// be both slightly faster and easier to track in Valgrind.
7479
unsafe {
75-
// parent_idx, keys, and vals are all MaybeUninit
76-
ptr::addr_of_mut!((*this).parent).write(None);
77-
ptr::addr_of_mut!((*this).len).write(0);
80+
ptr::addr_of_mut!((*this).head).write(Head {
81+
parent: None,
82+
parent_idx: MaybeUninit::uninit(),
83+
len: 0,
84+
});
7885
}
7986
}
8087

81-
/// Creates a new boxed `LeafNode`. Unsafe because all nodes should really be hidden behind
82-
/// `BoxedNode`, preventing accidental dropping of uninitialized keys and values.
83-
unsafe fn new() -> Box<Self> {
88+
/// Creates a new boxed `LeafNode`.
89+
fn new() -> Box<Self> {
8490
unsafe {
8591
let mut leaf = Box::new_uninit();
8692
LeafNode::init(leaf.as_mut_ptr());
@@ -108,15 +114,14 @@ struct InternalNode<K, V> {
108114
impl<K, V> InternalNode<K, V> {
109115
/// Creates a new boxed `InternalNode`.
110116
///
111-
/// This is unsafe for two reasons. First, it returns an owned `InternalNode` in a box, risking
112-
/// dropping of uninitialized fields. Second, an invariant of internal nodes is that `len + 1`
113-
/// edges are initialized and valid, meaning that even when the node is empty (having a
114-
/// `len` of 0), there must be one initialized and valid edge. This function does not set up
117+
/// # Safety
118+
/// An invariant of internal nodes is it has at least one
119+
/// initialized and valid edge. This function does not set up
115120
/// such an edge.
116121
unsafe fn new() -> Box<Self> {
117122
unsafe {
118123
let mut node = Box::<Self>::new_uninit();
119-
// We only need to initialize the data; the edges are MaybeUninit.
124+
// We only need to initialize the leaf data; the edges are MaybeUninit.
120125
LeafNode::init(ptr::addr_of_mut!((*node.as_mut_ptr()).data));
121126
node.assume_init()
122127
}
@@ -145,7 +150,7 @@ impl<K, V> Root<K, V> {
145150

146151
impl<K, V> NodeRef<marker::Owned, K, V, marker::Leaf> {
147152
fn new_leaf() -> Self {
148-
Self::from_new_leaf(unsafe { LeafNode::new() })
153+
Self::from_new_leaf(LeafNode::new())
149154
}
150155

151156
fn from_new_leaf(leaf: Box<LeafNode<K, V>>) -> Self {
@@ -341,7 +346,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
341346
pub fn len(&self) -> usize {
342347
// Crucially, we only access the `len` field here. If BorrowType is marker::ValMut,
343348
// there might be outstanding mutable references to values that we must not invalidate.
344-
unsafe { usize::from((*Self::as_leaf_ptr(self)).len) }
349+
unsafe { usize::from((*Self::as_leaf_ptr(self)).head.len) }
345350
}
346351

347352
/// Returns the number of levels that the node and leaves are apart. Zero
@@ -386,11 +391,11 @@ impl<BorrowType: marker::BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type>
386391
// We need to use raw pointers to nodes because, if BorrowType is marker::ValMut,
387392
// there might be outstanding mutable references to values that we must not invalidate.
388393
let leaf_ptr: *const _ = Self::as_leaf_ptr(&self);
389-
unsafe { (*leaf_ptr).parent }
394+
unsafe { (*leaf_ptr).head.parent }
390395
.as_ref()
391396
.map(|parent| Handle {
392397
node: NodeRef::from_internal(*parent, self.height + 1),
393-
idx: unsafe { usize::from((*leaf_ptr).parent_idx.assume_init()) },
398+
idx: unsafe { usize::from((*leaf_ptr).head.parent_idx.assume_init()) },
394399
_marker: PhantomData,
395400
})
396401
.ok_or(self)
@@ -431,9 +436,8 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
431436
/// Borrows a view into the keys stored in the node.
432437
pub fn keys(&self) -> &[K] {
433438
let leaf = self.into_leaf();
434-
unsafe {
435-
MaybeUninit::slice_assume_init_ref(leaf.keys.get_unchecked(..usize::from(leaf.len)))
436-
}
439+
let len = usize::from(leaf.head.len);
440+
unsafe { MaybeUninit::slice_assume_init_ref(leaf.keys.get_unchecked(..len)) }
437441
}
438442
}
439443

@@ -571,17 +575,17 @@ impl<'a, K, V, Type> NodeRef<marker::ValMut<'a>, K, V, Type> {
571575
impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
572576
/// Borrows exclusive access to the length of the node.
573577
pub fn len_mut(&mut self) -> &mut u16 {
574-
&mut self.as_leaf_mut().len
578+
&mut self.as_leaf_mut().head.len
575579
}
576580
}
577581

578582
impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
579583
/// Sets the node's link to its parent edge,
580584
/// without invalidating other references to the node.
581585
fn set_parent_link(&mut self, parent: NonNull<InternalNode<K, V>>, parent_idx: usize) {
582-
let leaf = Self::as_leaf_ptr(self);
583-
unsafe { (*leaf).parent = Some(parent) };
584-
unsafe { (*leaf).parent_idx.write(parent_idx as u16) };
586+
let head = unsafe { &mut (*Self::as_leaf_ptr(self)).head };
587+
head.parent = Some(parent);
588+
head.parent_idx.write(parent_idx as u16);
585589
}
586590
}
587591

@@ -590,7 +594,7 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
590594
fn clear_parent_link(&mut self) {
591595
let mut root_node = self.borrow_mut();
592596
let leaf = root_node.as_leaf_mut();
593-
leaf.parent = None;
597+
leaf.head.parent = None;
594598
}
595599
}
596600

@@ -1057,7 +1061,7 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>
10571061
debug_assert!(self.idx < self.node.len());
10581062
let old_len = self.node.len();
10591063
let new_len = old_len - self.idx - 1;
1060-
new_node.len = new_len as u16;
1064+
new_node.head.len = new_len as u16;
10611065
unsafe {
10621066
let k = self.node.key_area_mut(self.idx).assume_init_read();
10631067
let v = self.node.val_area_mut(self.idx).assume_init_read();
@@ -1086,14 +1090,12 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
10861090
/// - All the key-value pairs to the right of this handle are put into a newly
10871091
/// allocated node.
10881092
pub fn split(mut self) -> SplitResult<'a, K, V, marker::Leaf> {
1089-
unsafe {
1090-
let mut new_node = LeafNode::new();
1093+
let mut new_node = LeafNode::new();
10911094

1092-
let kv = self.split_leaf_data(&mut new_node);
1095+
let kv = self.split_leaf_data(&mut new_node);
10931096

1094-
let right = NodeRef::from_new_leaf(new_node);
1095-
SplitResult { left: self.node, kv, right }
1096-
}
1097+
let right = NodeRef::from_new_leaf(new_node);
1098+
SplitResult { left: self.node, kv, right }
10971099
}
10981100

10991101
/// Removes the key-value pair pointed to by this handle and returns it, along with the edge
@@ -1124,7 +1126,7 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>,
11241126
unsafe {
11251127
let mut new_node = InternalNode::new();
11261128
let kv = self.split_leaf_data(&mut new_node.data);
1127-
let new_len = usize::from(new_node.data.len);
1129+
let new_len = usize::from(new_node.data.head.len);
11281130
move_to_slice(
11291131
self.node.edge_area_mut(self.idx + 1..old_len + 1),
11301132
&mut new_node.edges[..new_len + 1],

src/etc/gdb_providers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ def cast_to_internal(node):
223223
keys = leaf["keys"]
224224
vals = leaf["vals"]
225225
edges = cast_to_internal(node_ptr)["edges"] if height > 0 else None
226-
length = leaf["len"]
226+
length = leaf["head"]["len"]
227227

228228
for i in xrange(0, length + 1):
229229
if height > 0:

0 commit comments

Comments
 (0)