Skip to content

Commit af0f4f3

Browse files
committed
tokenizer: Source positions are always at char boundaries, so avoid overhead when slicing.
These show up in profiles: https://share.firefox.dev/45Gh2s7
1 parent a5ba6dd commit af0f4f3

File tree

1 file changed

+13
-10
lines changed

1 file changed

+13
-10
lines changed

src/tokenizer.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ impl<'a> Tokenizer<'a> {
274274

275275
#[inline]
276276
pub fn position(&self) -> SourcePosition {
277+
debug_assert!(self.input.is_char_boundary(self.position));
277278
SourcePosition(self.position)
278279
}
279280

@@ -313,24 +314,26 @@ impl<'a> Tokenizer<'a> {
313314
}
314315

315316
#[inline]
316-
pub fn slice_from(&self, start_pos: SourcePosition) -> &'a str {
317-
&self.input[start_pos.0..self.position]
317+
pub(crate) fn slice_from(&self, start_pos: SourcePosition) -> &'a str {
318+
self.slice(start_pos..self.position())
318319
}
319320

320321
#[inline]
321-
pub fn slice(&self, range: Range<SourcePosition>) -> &'a str {
322-
&self.input[range.start.0..range.end.0]
322+
pub(crate) fn slice(&self, range: Range<SourcePosition>) -> &'a str {
323+
debug_assert!(self.input.is_char_boundary(range.start.0));
324+
debug_assert!(self.input.is_char_boundary(range.end.0));
325+
unsafe { self.input.get_unchecked(range.start.0..range.end.0) }
323326
}
324327

325328
pub fn current_source_line(&self) -> &'a str {
326-
let current = self.position;
327-
let start = self.input[0..current]
329+
let current = self.position();
330+
let start = self.slice(SourcePosition(0)..current)
328331
.rfind(|c| matches!(c, '\r' | '\n' | '\x0C'))
329332
.map_or(0, |start| start + 1);
330-
let end = self.input[current..]
333+
let end = self.slice(current..SourcePosition(self.input.len()))
331334
.find(|c| matches!(c, '\r' | '\n' | '\x0C'))
332-
.map_or(self.input.len(), |end| current + end);
333-
&self.input[start..end]
335+
.map_or(self.input.len(), |end| current.0 + end);
336+
self.slice(SourcePosition(start)..SourcePosition(end))
334337
}
335338

336339
#[inline]
@@ -426,7 +429,7 @@ impl<'a> Tokenizer<'a> {
426429

427430
#[inline]
428431
fn next_char(&self) -> char {
429-
self.input[self.position..].chars().next().unwrap()
432+
unsafe { self.input.get_unchecked(self.position().0..) }.chars().next().unwrap()
430433
}
431434

432435
// Given that a newline has been seen, advance over the newline

0 commit comments

Comments
 (0)