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

perf(es/parser): Do not track raw by hand #9047

Merged
merged 7 commits into from
Jun 14, 2024
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
2 changes: 2 additions & 0 deletions crates/swc_ecma_ast/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,8 @@ pub struct TplElement {
/// don't have to worry about this value.
pub cooked: Option<Atom>,

/// You may need to perform. `.replace("\r\n", "\n").replace('\r', "\n")` on
/// this value.
pub raw: Atom,
}

Expand Down
5 changes: 3 additions & 2 deletions crates/swc_ecma_codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1965,11 +1965,12 @@ where
fn emit_quasi(&mut self, node: &TplElement) -> Result {
srcmap!(node, true);

let raw = node.raw.replace("\r\n", "\n").replace('\r', "\n");
if self.cfg.minify || (self.cfg.ascii_only && !node.raw.is_ascii()) {
let v = get_template_element_from_raw(&node.raw, self.cfg.ascii_only);
let v = get_template_element_from_raw(&raw, self.cfg.ascii_only);
self.wr.write_str_lit(DUMMY_SP, &v)?;
} else {
self.wr.write_str_lit(DUMMY_SP, &node.raw)?;
self.wr.write_str_lit(DUMMY_SP, &raw)?;
}

srcmap!(node, false);
Expand Down
19 changes: 2 additions & 17 deletions crates/swc_ecma_codegen/tests/test262.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use std::{
env,
fs::read_to_string,
io::{self, Write},
path::{Path, PathBuf},
sync::{Arc, RwLock},
};

use swc_common::comments::SingleThreadedComments;
Expand Down Expand Up @@ -105,7 +102,7 @@ fn do_test(entry: &Path, minify: bool) {
"\n\n========== Running codegen test {}\nSource:\n{}\n",
file_name, input
);
let mut wr = Buf(Arc::new(RwLock::new(vec![])));
let mut wr = vec![];

::testing::run_test(false, |cm, handler| {
let src = cm.load_file(entry).expect("failed to load file");
Expand Down Expand Up @@ -168,23 +165,11 @@ fn do_test(entry: &Path, minify: bool) {
}
let ref_file = format!("{}", ref_dir.join(&file_name).display());

let code_output = wr.0.read().unwrap();
let code_output = wr;
let with_srcmap =
NormalizedOutput::from(String::from_utf8_lossy(&code_output).into_owned());
with_srcmap.compare_to_file(ref_file).unwrap();
Ok(())
})
.expect("failed to run test");
}

#[derive(Debug, Clone)]
struct Buf(Arc<RwLock<Vec<u8>>>);
impl Write for Buf {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
self.0.write().unwrap().write(data)
}

fn flush(&mut self) -> io::Result<()> {
self.0.write().unwrap().flush()
}
}
18 changes: 6 additions & 12 deletions crates/swc_ecma_parser/src/lexer/jsx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,7 @@ impl<'a> Lexer<'a> {
pub(super) fn read_jsx_str(&mut self, quote: char) -> LexResult<Token> {
debug_assert!(self.syntax.jsx());

let mut raw = String::new();

raw.push(quote);
let start = self.input.cur_pos();

unsafe {
// Safety: cur() was Some(quote)
Expand Down Expand Up @@ -243,8 +241,6 @@ impl<'a> Lexer<'a> {

out.push_str(value);
out.push('\\');
raw.push_str(value);
raw.push('\\');

self.bump();

Expand All @@ -264,12 +260,10 @@ impl<'a> Lexer<'a> {
};

out.push_str(value);
raw.push_str(value);

let jsx_entity = self.read_jsx_entity()?;

out.push(jsx_entity.0);
raw.push_str(&jsx_entity.1);

chunk_start = self.input.cur_pos();
} else if ch.is_line_terminator() {
Expand All @@ -279,16 +273,13 @@ impl<'a> Lexer<'a> {
};

out.push_str(value);
raw.push_str(value);

match self.read_jsx_new_line(false)? {
Either::Left(s) => {
out.push_str(s);
raw.push_str(s);
}
Either::Right(c) => {
out.push(c);
raw.push(c);
}
}

Expand All @@ -308,7 +299,6 @@ impl<'a> Lexer<'a> {
};

out.push_str(value);
raw.push_str(value);

// it might be at the end of the file when
// the string literal is unterminated
Expand All @@ -319,7 +309,11 @@ impl<'a> Lexer<'a> {
}
}

raw.push(quote);
let end = self.input.cur_pos();
let raw = unsafe {
// Safety: Both of `start` and `end` are generated from `cur_pos()`
self.input.slice(start, end)
};

Ok(Token::Str {
value: self.atoms.atom(out),
Expand Down
61 changes: 24 additions & 37 deletions crates/swc_ecma_parser/src/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1000,11 +1000,8 @@ impl<'a> Lexer<'a> {
fn read_str_lit(&mut self) -> LexResult<Token> {
debug_assert!(self.cur() == Some('\'') || self.cur() == Some('"'));
let start = self.cur_pos();
let mut raw = String::new();
let quote = self.cur().unwrap();

raw.push(quote);

self.bump(); // '"'

self.with_buf(|l, out| {
Expand All @@ -1015,42 +1012,40 @@ impl<'a> Lexer<'a> {
.input
.uncons_while(|c| c != quote && c != '\\' && !c.is_line_break());
out.push_str(s);
raw.push_str(s);
}
l.cur()
} {
match c {
c if c == quote => {
raw.push(c);

l.bump();

let end = l.cur_pos();

let raw = unsafe {
// Safety: start and end are valid position because we got them from
// `self.input`
l.input.slice(start, end)
};

return Ok(Token::Str {
value: l.atoms.atom(&*out),
raw: l.atoms.atom(raw),
});
}
'\\' => {
raw.push(c);

let mut wrapped = Raw(Some(Default::default()));

if let Some(chars) = l.read_escaped_char(&mut wrapped, false)? {
for c in chars {
out.extend(c);
}
}

raw.push_str(&wrapped.0.unwrap());
}
c if c.is_line_break() => {
raw.push(c);

break;
}
_ => {
out.push(c);
raw.push(c);

l.bump();
}
Expand All @@ -1059,6 +1054,13 @@ impl<'a> Lexer<'a> {

l.emit_error(start, SyntaxError::UnterminatedStrLit);

let end = l.cur_pos();

let raw = unsafe {
// Safety: start and end are valid position because we got them from
// `self.input`
l.input.slice(start, end)
};
Ok(Token::Str {
value: l.atoms.atom(&*out),
raw: l.atoms.atom(raw),
Expand Down Expand Up @@ -1160,19 +1162,7 @@ impl<'a> Lexer<'a> {

let mut cooked = Ok(String::new());
let mut cooked_slice_start = start;
let mut raw = SmartString::new();
let mut raw_slice_start = start;

macro_rules! consume_raw {
() => {{
let last_pos = self.cur_pos();
raw.push_str(unsafe {
// Safety: Both of start and last_pos are valid position because we got them
// from `self.input`
self.input.slice(raw_slice_start, last_pos)
});
}};
}
let raw_slice_start = start;

macro_rules! consume_cooked {
() => {{
Expand Down Expand Up @@ -1201,21 +1191,24 @@ impl<'a> Lexer<'a> {
}

consume_cooked!();
consume_raw!();

// TODO: Handle error
let end = self.input.cur_pos();
let raw = unsafe {
// Safety: Both of start and last_pos are valid position because we got them
// from `self.input`
self.input.slice(raw_slice_start, end)
};
return Ok(Token::Template {
cooked: cooked.map(Atom::from),
raw: self.atoms.atom(&*raw),
raw: self.atoms.atom(raw),
});
}

if c == '\\' {
consume_cooked!();
consume_raw!();

raw.push('\\');
let mut wrapped = Raw(Some(raw));
let mut wrapped = Raw(None);

match self.read_escaped_char(&mut wrapped, true) {
Ok(Some(chars)) => {
Expand All @@ -1231,17 +1224,13 @@ impl<'a> Lexer<'a> {
}
}

raw = wrapped.0.unwrap();
raw_slice_start = self.cur_pos();
cooked_slice_start = self.cur_pos();
} else if c.is_line_terminator() {
self.state.had_line_break = true;

consume_cooked!();
consume_raw!();

let c = if c == '\r' && self.peek() == Some('\n') {
raw.push('\r');
self.bump(); // '\r'
'\n'
} else {
Expand All @@ -1259,8 +1248,6 @@ impl<'a> Lexer<'a> {
if let Ok(ref mut cooked) = cooked {
cooked.push(c);
}
raw.push(c);
raw_slice_start = self.cur_pos();
cooked_slice_start = self.cur_pos();
} else {
self.bump();
Expand Down
20 changes: 7 additions & 13 deletions crates/swc_ecma_parser/src/lexer/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ impl<'a> Lexer<'a> {

let start = self.cur_pos();
let mut raw_val = SmartString::<LazyCompact>::new();
let mut raw_str = SmartString::<LazyCompact>::new();

let val = if starts_with_dot {
// first char is '.'
Expand All @@ -69,8 +68,6 @@ impl<'a> Lexer<'a> {

write!(raw_val, "{}", &s.value).unwrap();

raw_str.push_str(&raw);

if starts_with_zero {
// TODO: I guess it would be okay if I don't use -ffast-math
// (or something like that), but needs review.
Expand Down Expand Up @@ -132,7 +129,6 @@ impl<'a> Lexer<'a> {
// `.1.a`, `.1e-4.a` are valid,
if self.cur() == Some('.') {
raw_val.push('.');
raw_str.push('.');

self.bump();

Expand All @@ -145,8 +141,6 @@ impl<'a> Lexer<'a> {
// Read numbers after dot
let dec_val = self.read_int::<10>(0, &mut raw)?;

raw_str.push_str(raw.0.as_ref().unwrap());

val = {
if dec_val.is_some() {
raw_val.push_str(raw.0.as_ref().unwrap());
Expand All @@ -170,7 +164,7 @@ impl<'a> Lexer<'a> {
// 1e+2 = 100
// 1e-2 = 0.01
match self.cur() {
Some(e @ 'e') | Some(e @ 'E') => {
Some('e') | Some('E') => {
self.bump();

let next = match self.cur() {
Expand All @@ -182,13 +176,10 @@ impl<'a> Lexer<'a> {
};

raw_val.push('e');
raw_str.push(e);

let positive = if next == '+' || next == '-' {
self.bump(); // remove '+', '-'

raw_str.push(next);

next == '+'
} else {
true
Expand All @@ -197,8 +188,6 @@ impl<'a> Lexer<'a> {
let mut raw = Raw(Some(Default::default()));
let exp = self.read_number_no_dot::<10>(&mut raw)?;

raw_str.push_str(&raw.0.take().unwrap());

val = if exp == f64::INFINITY {
if positive && val != 0.0 {
f64::INFINITY
Expand Down Expand Up @@ -226,7 +215,12 @@ impl<'a> Lexer<'a> {

self.ensure_not_ident()?;

Ok(Either::Left((val, self.atoms.atom(&*raw_str))))
let end = self.cur_pos();
let raw_str = unsafe {
// Safety: We got both start and end position from `self.input`
self.input.slice(start, end)
};
Ok(Either::Left((val, raw_str.into())))
}

/// Returns `Left(value)` or `Right(BigInt)`
Expand Down
Loading