Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BTree: remove dead data needlessly complicating insert #94699

Merged
merged 1 commit into from
Mar 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions library/alloc/src/collections/btree/map/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use core::marker::PhantomData;
use core::mem;

use super::super::borrow::DormantMutRef;
use super::super::node::{marker, Handle, InsertResult::*, NodeRef};
use super::super::node::{marker, Handle, NodeRef};
use super::BTreeMap;

use Entry::*;
Expand Down Expand Up @@ -313,13 +313,13 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn insert(self, value: V) -> &'a mut V {
let out_ptr = match self.handle.insert_recursing(self.key, value) {
(Fit(_), val_ptr) => {
(None, val_ptr) => {
// SAFETY: We have consumed self.handle and the handle returned.
let map = unsafe { self.dormant_map.awaken() };
map.length += 1;
val_ptr
}
(Split(ins), val_ptr) => {
(Some(ins), val_ptr) => {
drop(ins.left);
// SAFETY: We have consumed self.handle and the reference returned.
let map = unsafe { self.dormant_map.awaken() };
Expand Down
53 changes: 16 additions & 37 deletions library/alloc/src/collections/btree/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -861,11 +861,10 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
/// this edge. This method splits the node if there isn't enough room.
///
/// The returned pointer points to the inserted value.
fn insert(mut self, key: K, val: V) -> (InsertResult<'a, K, V, marker::Leaf>, *mut V) {
fn insert(mut self, key: K, val: V) -> (Option<SplitResult<'a, K, V, marker::Leaf>>, *mut V) {
if self.node.len() < CAPACITY {
let val_ptr = self.insert_fit(key, val);
let kv = unsafe { Handle::new_kv(self.node, self.idx) };
(InsertResult::Fit(kv), val_ptr)
(None, val_ptr)
} else {
let (middle_kv_idx, insertion) = splitpoint(self.idx);
let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) };
Expand All @@ -879,7 +878,7 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
},
};
let val_ptr = insertion_edge.insert_fit(key, val);
(InsertResult::Split(result), val_ptr)
(Some(result), val_ptr)
}
}
}
Expand Down Expand Up @@ -923,13 +922,12 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>,
key: K,
val: V,
edge: Root<K, V>,
) -> InsertResult<'a, K, V, marker::Internal> {
) -> Option<SplitResult<'a, K, V, marker::Internal>> {
assert!(edge.height == self.node.height - 1);

if self.node.len() < CAPACITY {
self.insert_fit(key, val, edge);
let kv = unsafe { Handle::new_kv(self.node, self.idx) };
InsertResult::Fit(kv)
None
} else {
let (middle_kv_idx, insertion) = splitpoint(self.idx);
let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) };
Expand All @@ -943,7 +941,7 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>,
},
};
insertion_edge.insert_fit(key, val, edge);
InsertResult::Split(result)
Some(result)
}
}
}
Expand All @@ -953,32 +951,26 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
/// this edge. This method splits the node if there isn't enough room, and tries to
/// insert the split off portion into the parent node recursively, until the root is reached.
///
/// If the returned result is a `Fit`, its handle's node can be this edge's node or an ancestor.
/// If the returned result is a `Split`, the `left` field will be the root node.
/// The returned pointer points to the inserted value.
/// If the returned result is some `SplitResult`, the `left` field will be the root node.
/// The returned pointer points to the inserted value, which in the case of `SplitResult`
/// is in the `left` or `right` tree.
pub fn insert_recursing(
self,
key: K,
value: V,
) -> (InsertResult<'a, K, V, marker::LeafOrInternal>, *mut V) {
) -> (Option<SplitResult<'a, K, V, marker::LeafOrInternal>>, *mut V) {
let (mut split, val_ptr) = match self.insert(key, value) {
(InsertResult::Fit(handle), ptr) => {
return (InsertResult::Fit(handle.forget_node_type()), ptr);
}
(InsertResult::Split(split), val_ptr) => (split.forget_node_type(), val_ptr),
(None, val_ptr) => return (None, val_ptr),
(Some(split), val_ptr) => (split.forget_node_type(), val_ptr),
};

loop {
split = match split.left.ascend() {
Ok(parent) => match parent.insert(split.kv.0, split.kv.1, split.right) {
InsertResult::Fit(handle) => {
return (InsertResult::Fit(handle.forget_node_type()), val_ptr);
}
InsertResult::Split(split) => split.forget_node_type(),
None => return (None, val_ptr),
Some(split) => split.forget_node_type(),
},
Err(root) => {
return (InsertResult::Split(SplitResult { left: root, ..split }), val_ptr);
}
Err(root) => return (Some(SplitResult { left: root, ..split }), val_ptr),
};
}
}
Expand Down Expand Up @@ -1529,14 +1521,6 @@ impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::K
}
}

impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::KV> {
pub fn forget_node_type(
self,
) -> Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, marker::KV> {
unsafe { Handle::new_kv(self.node.forget_type(), self.idx) }
}
}

impl<BorrowType, K, V, Type> Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, Type> {
/// Checks whether the underlying node is an `Internal` node or a `Leaf` node.
pub fn force(
Expand Down Expand Up @@ -1621,7 +1605,7 @@ pub enum ForceResult<Leaf, Internal> {
pub struct SplitResult<'a, K, V, NodeType> {
// Altered node in existing tree with elements and edges that belong to the left of `kv`.
pub left: NodeRef<marker::Mut<'a>, K, V, NodeType>,
// Some key and value split off, to be inserted elsewhere.
// Some key and value that existed before and were split off, to be inserted elsewhere.
pub kv: (K, V),
// Owned, unattached, new node with elements and edges that belong to the right of `kv`.
pub right: NodeRef<marker::Owned, K, V, NodeType>,
Expand All @@ -1639,11 +1623,6 @@ impl<'a, K, V> SplitResult<'a, K, V, marker::Internal> {
}
}

pub enum InsertResult<'a, K, V, NodeType> {
Fit(Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV>),
Split(SplitResult<'a, K, V, NodeType>),
}

pub mod marker {
use core::marker::PhantomData;

Expand Down