Skip to content

Commit

Permalink
perf(es/parser): Do not track raw by hand (#9047)
Browse files Browse the repository at this point in the history
**Description:**

We can skip this logic completely, as it's `raw`.

~I'm under the impression that I'm super stupid~
  • Loading branch information
kdy1 authored Jun 14, 2024
1 parent 0a3265e commit 60fe5f0
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 81 deletions.
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

0 comments on commit 60fe5f0

Please sign in to comment.