+
Skip to content
This repository was archived by the owner on Aug 31, 2023. It is now read-only.

feat(rome_service): recycle the node cache across parsing sessions #4138

Merged
merged 3 commits into from
Feb 12, 2023
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 12 additions & 3 deletions crates/rome_js_parser/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rome_parser::event::Event;
use rome_parser::token_source::Trivia;
use rome_parser::AnyParse;

use rome_rowan::AstNode;
use rome_rowan::{AstNode, NodeCache};
use std::marker::PhantomData;

/// A utility struct for managing the result of a parser job
Expand Down Expand Up @@ -193,15 +193,24 @@ pub fn parse_module(text: &str) -> Parse<JsModule> {

/// Parses the provided string as a EcmaScript program using the provided syntax features.
pub fn parse(text: &str, source_type: SourceType) -> Parse<AnyJsRoot> {
let mut cache = NodeCache::default();
parse_js_with_cache(text, source_type, &mut cache)
}

/// Parses the provided string as a EcmaScript program using the provided syntax features and node cache.
pub fn parse_js_with_cache(
text: &str,
source_type: SourceType,
cache: &mut NodeCache,
) -> Parse<AnyJsRoot> {
tracing::debug_span!("parse").in_scope(move || {
let (events, errors, tokens) = parse_common(text, source_type);
let mut tree_sink = JsLosslessTreeSink::new(text, &tokens);
let mut tree_sink = JsLosslessTreeSink::with_cache(text, &tokens, cache);
rome_parser::event::process(&mut tree_sink, events, errors);
let (green, parse_errors) = tree_sink.finish();
Parse::new(green, parse_errors)
})
}

/// Losslessly Parse text into an expression [`Parse`](Parse) which can then be turned into an untyped root [`JsSyntaxNode`](JsSyntaxNode).
/// Or turned into a typed [`JsExpressionSnipped`](JsExpressionSnipped) with [`tree`](Parse::tree).
pub fn parse_expression(text: &str) -> Parse<JsExpressionSnipped> {
Expand Down
10 changes: 8 additions & 2 deletions crates/rome_json_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use rome_json_syntax::{JsonLanguage, JsonRoot, JsonSyntaxNode};
pub use rome_parser::prelude::*;
use rome_parser::tree_sink::LosslessTreeSink;
use rome_parser::AnyParse;
use rome_rowan::AstNode;
use rome_rowan::{AstNode, NodeCache};

mod lexer;
mod parser;
Expand All @@ -19,14 +19,20 @@ pub(crate) type JsonLosslessTreeSink<'source> =
LosslessTreeSink<'source, JsonLanguage, JsonSyntaxFactory>;

pub fn parse_json(source: &str) -> JsonParse {
let mut cache = NodeCache::default();
parse_json_with_cache(source, &mut cache)
}

/// Parses the provided string as JSON program using the provided node cache.
pub fn parse_json_with_cache(source: &str, cache: &mut NodeCache) -> JsonParse {
tracing::debug_span!("parse").in_scope(move || {
let mut parser = JsonParser::new(source);

parse_root(&mut parser);

let (events, diagnostics, trivia) = parser.finish();

let mut tree_sink = JsonLosslessTreeSink::new(source, &trivia);
let mut tree_sink = JsonLosslessTreeSink::with_cache(source, &trivia, cache);
rome_parser::event::process(&mut tree_sink, events, diagnostics);
let (green, diagnostics) = tree_sink.finish();

Expand Down
21 changes: 19 additions & 2 deletions crates/rome_parser/src/tree_sink.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::prelude::*;
use crate::token_source::Trivia;
use rome_rowan::{
Language, SyntaxFactory, SyntaxKind, SyntaxNode, TextRange, TextSize, TreeBuilder, TriviaPiece,
Language, NodeCache, SyntaxFactory, SyntaxKind, SyntaxNode, TextRange, TextSize, TreeBuilder,
TriviaPiece,
};

/// An abstraction for syntax tree implementations
Expand Down Expand Up @@ -37,7 +38,7 @@ where
trivia_pos: usize,
parents_count: usize,
errors: Vec<ParseDiagnostic>,
inner: TreeBuilder<'static, L, Factory>,
inner: TreeBuilder<'a, L, Factory>,
/// Signal that the sink must generate an EOF token when its finishing. See [LosslessTreeSink::finish] for more details.
needs_eof: bool,
trivia_pieces: Vec<TriviaPiece>,
Expand Down Expand Up @@ -93,6 +94,22 @@ where
}
}

/// Reusing `NodeCache` between different [LosslessTreeSink]s saves memory.
/// It allows to structurally share underlying trees.
pub fn with_cache(text: &'a str, trivia: &'a [Trivia], cache: &'a mut NodeCache) -> Self {
Self {
text,
trivia_list: trivia,
text_pos: 0.into(),
trivia_pos: 0,
parents_count: 0,
inner: TreeBuilder::with_cache(cache),
errors: vec![],
needs_eof: true,
trivia_pieces: Vec::with_capacity(128),
}
}

/// Finishes the tree and return the root node with possible parser errors.
///
/// If tree is finished without a [rome_rowan::SyntaxKind::EOF], one will be generated and all pending trivia
Expand Down
9 changes: 8 additions & 1 deletion crates/rome_rowan/src/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
marker::PhantomData,
mem::{self, ManuallyDrop},
ops::Deref,
ptr,
ptr::{self, NonNull},
sync::atomic::{
self,
Ordering::{Acquire, Relaxed, Release},
Expand Down Expand Up @@ -92,6 +92,13 @@ impl<T: ?Sized> Arc<T> {
pub(crate) fn ptr(&self) -> *mut ArcInner<T> {
self.p.as_ptr()
}

#[inline]
pub(crate) fn into_raw(self) -> NonNull<T> {
let ptr = NonNull::from(&self.inner().data);
mem::forget(self);
ptr
}
}

impl<T: ?Sized> Clone for Arc<T> {
Expand Down
7 changes: 7 additions & 0 deletions crates/rome_rowan/src/green/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,13 @@ impl GreenNode {
GreenNode { ptr: data }
}

#[inline]
pub(crate) fn into_raw(self) -> ptr::NonNull<GreenNodeData> {
// SAFETY: casting from `HeaderSlice<GreenNodeHead, [green::node::Slot]>` to `GreenNodeData`
// if safe since `GreenNodeData` is marked as `repr(transparent)`
Arc::from_thin(self.ptr).into_raw().cast()
}

#[inline]
pub(crate) unsafe fn from_raw(ptr: ptr::NonNull<GreenNodeData>) -> GreenNode {
let arc = Arc::from_raw(&ptr.as_ref().data as *const ReprThin);
Expand Down
Loading
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载