@@ -2,7 +2,6 @@ use std::path::Path;
22
33use nonmax:: NonMaxU32 ;
44
5- use oxc_data_structures:: slice_iter:: SliceIter ;
65use oxc_index:: { Idx , IndexVec } ;
76use oxc_span:: Span ;
87use oxc_syntax:: identifier:: { LS , PS } ;
@@ -247,56 +246,78 @@ impl<'a> SourcemapBuilder<'a> {
247246
248247 #[ expect( clippy:: cast_possible_truncation) ]
249248 fn update_generated_line_and_column ( & mut self , output : & [ u8 ] ) {
250- let remaining = & output[ self . last_generated_update ..] ;
249+ const BATCH_SIZE : usize = 32 ;
250+
251+ let start_index = self . last_generated_update ;
251252
252253 // Find last line break
253- let mut line_start_ptr = remaining. as_ptr ( ) ;
254+ let mut line_start_index = start_index;
255+ let mut idx = line_start_index;
254256 let mut last_line_is_ascii = true ;
255- let mut iter = remaining. iter ( ) ;
256- while let Some ( & b) = iter. next ( ) {
257- match b {
258- b'\n' => { }
259- b'\r' => {
260- // Handle Windows-specific "\r\n" newlines
261- if iter. peek ( ) == Some ( & b'\n' ) {
262- iter. next ( ) ;
257+
258+ macro_rules! handle_byte {
259+ ( $byte: ident) => {
260+ match $byte {
261+ b'\n' => { }
262+ b'\r' => {
263+ // Handle Windows-specific "\r\n" newlines
264+ if output. get( idx + 1 ) == Some ( & b'\n' ) {
265+ idx += 1 ;
266+ }
263267 }
264- }
265- _ if b. is_ascii ( ) => {
266- continue ;
267- }
268- LS_OR_PS_FIRST_BYTE => {
269- let next_byte = * iter. next ( ) . unwrap ( ) ;
270- let next_next_byte = * iter. next ( ) . unwrap ( ) ;
271- if !matches ! ( [ next_byte, next_next_byte] , LS_LAST_2_BYTES | PS_LAST_2_BYTES ) {
268+ _ if $byte. is_ascii( ) => {
269+ idx += 1 ;
270+ continue ;
271+ }
272+ LS_OR_PS_FIRST_BYTE => {
273+ let next_byte = output[ idx + 1 ] ;
274+ let next_next_byte = output[ idx + 2 ] ;
275+ if !matches!( [ next_byte, next_next_byte] , LS_LAST_2_BYTES | PS_LAST_2_BYTES )
276+ {
277+ last_line_is_ascii = false ;
278+ idx += 1 ;
279+ continue ;
280+ }
281+ }
282+ _ => {
283+ // Unicode char
272284 last_line_is_ascii = false ;
285+ idx += 1 ;
273286 continue ;
274287 }
275288 }
276- _ => {
277- // Unicode char
278- last_line_is_ascii = false ;
279- continue ;
280- }
281- }
282289
283- // Line break found.
284- // `iter` is now positioned after line break.
285- line_start_ptr = iter. ptr ( ) ;
286- self . generated_line += 1 ;
287- self . generated_column = 0 ;
288- last_line_is_ascii = true ;
290+ // Line break found.
291+ // `iter` is now positioned after line break.
292+ line_start_index = idx + 1 ;
293+ self . generated_line += 1 ;
294+ self . generated_column = 0 ;
295+ last_line_is_ascii = true ;
296+ idx += 1 ;
297+ } ;
298+ }
299+
300+ while let ( end, overflow) = idx. overflowing_add ( BATCH_SIZE )
301+ && !overflow
302+ && end < output. len ( )
303+ {
304+ while idx < end {
305+ let b = output[ idx] ;
306+ handle_byte ! ( b) ;
307+ }
308+ }
309+ while idx < output. len ( ) {
310+ let b = output[ idx] ;
311+ handle_byte ! ( b) ;
289312 }
290313
291314 // Calculate column
292315 self . generated_column += if last_line_is_ascii {
293- // `iter` is now exhausted, so `iter.ptr()` is pointer to end of `output`
294- ( iter. ptr ( ) as usize - line_start_ptr as usize ) as u32
316+ ( output. len ( ) - line_start_index) as u32
295317 } else {
296- let line_byte_offset = line_start_ptr as usize - remaining. as_ptr ( ) as usize ;
297318 // TODO: It'd be better if could use `from_utf8_unchecked` here, but we'd need to make this
298319 // function unsafe and caller guarantees `output` contains a valid UTF-8 string
299- let last_line = std:: str:: from_utf8 ( & remaining [ line_byte_offset ..] ) . unwrap ( ) ;
320+ let last_line = std:: str:: from_utf8 ( & output [ line_start_index ..] ) . unwrap ( ) ;
300321 // Mozilla's "source-map" library counts columns using UTF-16 code units
301322 last_line. encode_utf16 ( ) . count ( ) as u32
302323 } ;
0 commit comments