cgen, scanner: reduce allocations for the most common cases (#22142)

This commit is contained in:
Delyan Angelov 2024-09-01 07:56:08 +03:00 committed by GitHub
parent 217b191492
commit 8a9abbb14d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 42 additions and 33 deletions

View File

@ -1820,31 +1820,33 @@ pub fn (mut g Gen) write_multi_return_types() {
g.type_definitions.writeln('// END_multi_return_structs\n') g.type_definitions.writeln('// END_multi_return_structs\n')
} }
@[inline]
fn prefix_with_counter(prefix string, counter int) string {
mut sb := strings.new_builder(prefix.len + 5)
sb.write_string(prefix)
sb.write_decimal(counter)
return sb.str()
}
pub fn (mut g Gen) new_tmp_var() string { pub fn (mut g Gen) new_tmp_var() string {
g.tmp_count++ g.tmp_count++
return '_t${g.tmp_count}' return prefix_with_counter('_t', g.tmp_count)
} }
pub fn (mut g Gen) new_global_tmp_var() string { pub fn (mut g Gen) new_global_tmp_var() string {
g.global_tmp_count++ g.global_tmp_count++
return '_t${g.global_tmp_count}' return prefix_with_counter('_t', g.global_tmp_count)
} }
pub fn (mut g Gen) new_tmp_declaration_name() string { pub fn (mut g Gen) new_tmp_declaration_name() string {
g.tmp_count_declarations++ g.tmp_count_declarations++
return '_d${g.tmp_count_declarations}' return prefix_with_counter('_d', g.tmp_count_declarations)
} }
pub fn (mut g Gen) current_tmp_var() string { pub fn (mut g Gen) current_tmp_var() string {
return '_t${g.tmp_count}' return prefix_with_counter('_t', g.tmp_count)
} }
/*
pub fn (mut g Gen) new_tmp_var2() string {
g.tmp_count_af++
return '_tt$g.tmp_count_af'
}
*/
pub fn (mut g Gen) reset_tmp_count() { pub fn (mut g Gen) reset_tmp_count() {
g.tmp_count = 0 g.tmp_count = 0
} }

View File

@ -61,6 +61,13 @@ pub mut:
warnings []errors.Warning warnings []errors.Warning
notices []errors.Notice notices []errors.Notice
should_abort bool // when too many errors/warnings/notices are accumulated, should_abort becomes true, and the scanner should stop should_abort bool // when too many errors/warnings/notices are accumulated, should_abort becomes true, and the scanner should stop
// the following are used only inside ident_string, but are here to avoid allocating new arrays for the most common case of strings without escapes
all_pos []int
u16_escapes_pos []int // pos list of \uXXXX
u32_escapes_pos []int // pos list of \UXXXXXXXX
h_escapes_pos []int // pos list of \xXX
str_segments []string
} }
/* /*
@ -1231,9 +1238,9 @@ pub fn (mut s Scanner) ident_string() string {
s.inc_line_number() s.inc_line_number()
} }
s.is_inside_string = false s.is_inside_string = false
mut u16_escapes_pos := []int{} // pos list of \uXXXX s.u16_escapes_pos.clear()
mut u32_escapes_pos := []int{} // pos list of \UXXXXXXXX s.u32_escapes_pos.clear()
mut h_escapes_pos := []int{} // pos list of \xXX s.h_escapes_pos.clear()
mut backslash_count := if start_char == scanner.backslash { 1 } else { 0 } mut backslash_count := if start_char == scanner.backslash { 1 } else { 0 }
for { for {
s.pos++ s.pos++
@ -1271,7 +1278,7 @@ pub fn (mut s Scanner) ident_string() string {
&& s.text[s.pos + 2].is_hex_digit()) { && s.text[s.pos + 2].is_hex_digit()) {
s.error(r'`\x` used without two following hex digits') s.error(r'`\x` used without two following hex digits')
} }
h_escapes_pos << s.pos - 1 s.h_escapes_pos << s.pos - 1
} }
// Escape `\u` // Escape `\u`
if c == `u` { if c == `u` {
@ -1281,7 +1288,7 @@ pub fn (mut s Scanner) ident_string() string {
|| !s.text[s.pos + 3].is_hex_digit() || !s.text[s.pos + 4].is_hex_digit() { || !s.text[s.pos + 3].is_hex_digit() || !s.text[s.pos + 4].is_hex_digit() {
s.error(r'`\u` incomplete 16 bit unicode character value') s.error(r'`\u` incomplete 16 bit unicode character value')
} }
u16_escapes_pos << s.pos - 1 s.u16_escapes_pos << s.pos - 1
} }
// Escape `\U` // Escape `\U`
if c == `U` { if c == `U` {
@ -1295,7 +1302,7 @@ pub fn (mut s Scanner) ident_string() string {
|| !s.text[s.pos + 7].is_hex_digit() || !s.text[s.pos + 8].is_hex_digit() { || !s.text[s.pos + 7].is_hex_digit() || !s.text[s.pos + 8].is_hex_digit() {
s.error(r'`\U` incomplete 32 bit unicode character value') s.error(r'`\U` incomplete 32 bit unicode character value')
} }
u32_escapes_pos << s.pos - 1 s.u32_escapes_pos << s.pos - 1
} }
// Unknown escape sequence // Unknown escape sequence
if !util.is_escape_sequence(c) && !c.is_digit() && c != `\n` { if !util.is_escape_sequence(c) && !c.is_digit() && c != `\n` {
@ -1336,41 +1343,41 @@ pub fn (mut s Scanner) ident_string() string {
mut string_so_far := s.text[start..end] mut string_so_far := s.text[start..end]
if !s.is_fmt { if !s.is_fmt {
mut segment_idx := 0 mut segment_idx := 0
mut str_segments := []string{} s.str_segments.clear()
if u16_escapes_pos.len + h_escapes_pos.len + u32_escapes_pos.len > 0 { if s.u16_escapes_pos.len + s.h_escapes_pos.len + s.u32_escapes_pos.len > 0 {
mut all_pos := []int{} s.all_pos.clear()
all_pos << u16_escapes_pos s.all_pos << s.u16_escapes_pos
all_pos << u32_escapes_pos s.all_pos << s.u32_escapes_pos
all_pos << h_escapes_pos s.all_pos << s.h_escapes_pos
all_pos.sort() s.all_pos.sort()
for pos in all_pos { for pos in s.all_pos {
str_segments << string_so_far[segment_idx..(pos - start)] s.str_segments << string_so_far[segment_idx..(pos - start)]
segment_idx = pos - start segment_idx = pos - start
if pos in u16_escapes_pos { if pos in s.u16_escapes_pos {
end_idx, segment := s.decode_u16_escape_single(string_so_far, end_idx, segment := s.decode_u16_escape_single(string_so_far,
segment_idx) segment_idx)
str_segments << segment s.str_segments << segment
segment_idx = end_idx segment_idx = end_idx
} }
if pos in u32_escapes_pos { if pos in s.u32_escapes_pos {
end_idx, segment := s.decode_u32_escape_single(string_so_far, end_idx, segment := s.decode_u32_escape_single(string_so_far,
segment_idx) segment_idx)
str_segments << segment s.str_segments << segment
segment_idx = end_idx segment_idx = end_idx
} }
if pos in h_escapes_pos { if pos in s.h_escapes_pos {
end_idx, segment := s.decode_h_escape_single(string_so_far, segment_idx) end_idx, segment := s.decode_h_escape_single(string_so_far, segment_idx)
str_segments << segment s.str_segments << segment
segment_idx = end_idx segment_idx = end_idx
} }
} }
} }
if segment_idx < string_so_far.len { if segment_idx < string_so_far.len {
str_segments << string_so_far[segment_idx..] s.str_segments << string_so_far[segment_idx..]
} }
string_so_far = str_segments.join('') string_so_far = s.str_segments.join('')
} }
if n_cr_chars > 0 { if n_cr_chars > 0 {