mirror of
https://github.com/RGBCube/cstree
synced 2025-07-27 17:17:45 +00:00
Version 0.6.1
This commit is contained in:
parent
1728df28f8
commit
40d3e96fb1
2 changed files with 55 additions and 60 deletions
|
@ -99,12 +99,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node<It>(&mut self, kind: SyntaxKind, children: It) -> GreenNode
|
fn node(&mut self, kind: SyntaxKind, children: &[GreenElement]) -> GreenNode {
|
||||||
where
|
let mut hasher = FxHasher32::default();
|
||||||
It: IntoIterator<Item = GreenElement>,
|
let mut text_len: TextSize = 0.into();
|
||||||
It::IntoIter: ExactSizeIterator,
|
for child in children {
|
||||||
{
|
text_len += child.text_len();
|
||||||
let children = children.into_iter();
|
child.hash(&mut hasher);
|
||||||
|
}
|
||||||
|
let child_hash = hasher.finish() as u32;
|
||||||
|
|
||||||
// Green nodes are fully immutable, so it's ok to deduplicate them.
|
// Green nodes are fully immutable, so it's ok to deduplicate them.
|
||||||
// This is the same optimization that Roslyn does
|
// This is the same optimization that Roslyn does
|
||||||
|
@ -114,70 +116,30 @@ where
|
||||||
// For `libsyntax/parse/parser.rs`, measurements show that deduping saves
|
// For `libsyntax/parse/parser.rs`, measurements show that deduping saves
|
||||||
// 17% of the memory for green nodes!
|
// 17% of the memory for green nodes!
|
||||||
if children.len() <= CHILDREN_CACHE_THRESHOLD {
|
if children.len() <= CHILDREN_CACHE_THRESHOLD {
|
||||||
self.get_cached_node(kind, children)
|
self.get_cached_node(kind, children, text_len, child_hash)
|
||||||
} else {
|
} else {
|
||||||
GreenNode::new(kind, children)
|
GreenNode::new_with_len_and_hash(kind, children.iter().cloned(), text_len, child_hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a [`GreenNode`] by looking inside the cache or inserting
|
/// Creates a [`GreenNode`] by looking inside the cache or inserting
|
||||||
/// a new node into the cache if it's a cache miss.
|
/// a new node into the cache if it's a cache miss.
|
||||||
fn get_cached_node<It>(&mut self, kind: SyntaxKind, children: It) -> GreenNode
|
#[inline]
|
||||||
where
|
fn get_cached_node(
|
||||||
It: IntoIterator<Item = GreenElement>,
|
&mut self,
|
||||||
It::IntoIter: ExactSizeIterator,
|
kind: SyntaxKind,
|
||||||
{
|
children: &[GreenElement],
|
||||||
#[derive(Clone)]
|
text_len: TextSize,
|
||||||
struct ChildrenIter {
|
child_hash: u32,
|
||||||
data: [Option<GreenElement>; CHILDREN_CACHE_THRESHOLD],
|
) -> GreenNode {
|
||||||
idx: usize,
|
|
||||||
len: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ChildrenIter {
|
|
||||||
fn new() -> Self {
|
|
||||||
ChildrenIter {
|
|
||||||
data: [None, None, None],
|
|
||||||
idx: 0,
|
|
||||||
len: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Iterator for ChildrenIter {
|
|
||||||
type Item = GreenElement;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
let item = self.data.get_mut(self.idx)?;
|
|
||||||
self.idx += 1;
|
|
||||||
item.take()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ExactSizeIterator for ChildrenIter {
|
|
||||||
fn len(&self) -> usize {
|
|
||||||
self.len - self.idx
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut new_children = ChildrenIter::new();
|
|
||||||
let mut hasher = FxHasher32::default();
|
|
||||||
let mut text_len: TextSize = 0.into();
|
|
||||||
for (i, child) in children.into_iter().enumerate() {
|
|
||||||
text_len += child.text_len();
|
|
||||||
child.hash(&mut hasher);
|
|
||||||
new_children.data[i] = Some(child);
|
|
||||||
new_children.len += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let head = GreenNodeHead {
|
let head = GreenNodeHead {
|
||||||
kind,
|
kind,
|
||||||
text_len,
|
text_len,
|
||||||
child_hash: hasher.finish() as u32,
|
child_hash,
|
||||||
};
|
};
|
||||||
self.nodes
|
self.nodes
|
||||||
.entry(head)
|
.entry(head)
|
||||||
.or_insert_with_key(|head| GreenNode::from_head_and_children(head.clone(), new_children))
|
.or_insert_with_key(|head| GreenNode::from_head_and_children(head.clone(), children.iter().cloned()))
|
||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,8 +277,8 @@ where
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn finish_node(&mut self) {
|
pub fn finish_node(&mut self) {
|
||||||
let (kind, first_child) = self.parents.pop().unwrap();
|
let (kind, first_child) = self.parents.pop().unwrap();
|
||||||
let children = self.children.drain(first_child..);
|
let node = self.cache.node(kind, &self.children[first_child..]);
|
||||||
let node = self.cache.node(kind, children);
|
self.children.truncate(first_child);
|
||||||
self.children.push(node.into());
|
self.children.push(node.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,39 @@ impl GreenNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new Node.
|
||||||
|
#[inline]
|
||||||
|
pub(super) fn new_with_len_and_hash<I>(
|
||||||
|
kind: SyntaxKind,
|
||||||
|
children: I,
|
||||||
|
text_len: TextSize,
|
||||||
|
child_hash: u32,
|
||||||
|
) -> GreenNode
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = GreenElement>,
|
||||||
|
I::IntoIter: ExactSizeIterator,
|
||||||
|
{
|
||||||
|
let children = children.into_iter().map(PackedGreenElement::from);
|
||||||
|
let header = HeaderWithLength::new(
|
||||||
|
GreenNodeHead {
|
||||||
|
kind,
|
||||||
|
text_len: 0.into(),
|
||||||
|
child_hash: 0,
|
||||||
|
},
|
||||||
|
children.len(),
|
||||||
|
);
|
||||||
|
let mut data = Arc::from_header_and_iter(header, children);
|
||||||
|
|
||||||
|
// XXX: fixup `text_len` and `child_hash` after construction, because
|
||||||
|
// we can't iterate `children` twice.
|
||||||
|
let header = &mut Arc::get_mut(&mut data).unwrap().header.header;
|
||||||
|
header.text_len = text_len;
|
||||||
|
header.child_hash = child_hash;
|
||||||
|
GreenNode {
|
||||||
|
data: Arc::into_thin(data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn from_head_and_children<I>(header: GreenNodeHead, children: I) -> GreenNode
|
pub(super) fn from_head_and_children<I>(header: GreenNodeHead, children: I) -> GreenNode
|
||||||
where
|
where
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue