mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
perf(codegen): simplify print_space_before_identifier (#27841)
Perf optimization. `print_space_before_identifier` is called before printing every identifier and keyword. Simplify it to reduce its size, so it's more likely to be inlined. Previously it had a branch for when last character is non-ASCII. In that case, it collected the last character of the output (many instructions) and then called `is_identifier_part` which performs 2 table lookups and several more arithmetic/bitwise operations. This branch is extremely rarely taken, so the computation cost of these operations doesn't matter, but they do bloat the code significantly. All this code is unnecessary. Non-ASCII characters can appear in various places (e.g. in strings), but in such cases an ASCII character (e.g. `"`) is always printed after them. The only case in which last byte of output can be non-ASCII is when what was last printed was an identifier ending with a non-ASCII character. Therefore, if the last byte printed is not ASCII, it must be the end of an identifier. All that's needed is a simple `byte.is_ascii()` check.
This commit is contained in:
1 parent
29caafd7bc
commit
eeff416a60
1 file changed
+8
-13
@@ -16,7 +16,7 @@ use oxc_span::{GetSpan, SourceType, Span};
|
||||
use oxc_str::CompactStr;
|
||||
use oxc_syntax::{
|
||||
class::ClassId,
|
||||
identifier::{is_identifier_part, is_identifier_part_ascii},
|
||||
identifier::is_identifier_part_ascii,
|
||||
operator::{BinaryOperator, UnaryOperator, UpdateOperator},
|
||||
precedence::Precedence,
|
||||
};
|
||||
@@ -684,13 +684,13 @@ impl<'a> Codegen<'a> {
|
||||
let Some(byte) = self.last_byte() else { return };
|
||||
|
||||
if self.need_space_before_identifier != self.code.len() {
|
||||
let is_identifier = if byte.is_ascii() {
|
||||
// Fast path for ASCII (very common case)
|
||||
is_identifier_part_ascii(byte as char)
|
||||
} else {
|
||||
is_identifier_part(self.last_char().unwrap())
|
||||
};
|
||||
if !is_identifier {
|
||||
// Non-ASCII characters can appear in various places (e.g. in strings),
|
||||
// but in such cases an ASCII character (e.g. `"`) is always printed after them.
|
||||
// Only case in which last byte of output can be non-ASCII when printing an identifier
|
||||
// or keyword (when this function is called) is when what was last printed was
|
||||
// an identifier ending with a non-ASCII character.
|
||||
// So non-ASCII must be an identifier, and a space is required.
|
||||
if byte.is_ascii() && !is_identifier_part_ascii(byte as char) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -703,11 +703,6 @@ impl<'a> Codegen<'a> {
|
||||
self.code.last_byte()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last_char(&self) -> Option<char> {
|
||||
self.code.last_char()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn indent(&mut self) {
|
||||
if !self.options.minify {
|
||||
|
||||
Reference in new issue
Block a user