1
Fork 0
mirror of https://github.com/RGBCube/cstree synced 2025-07-27 09:07:44 +00:00

Version 0.6.1

This commit is contained in:
DQ 2021-06-23 18:13:42 +02:00 committed by GitHub
parent 1728df28f8
commit 40d3e96fb1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 60 deletions

View file

@ -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());
} }

View file

@ -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