From 1e69599900a753e2d7275d7ba714202b7d9c843e Mon Sep 17 00:00:00 2001 From: Berke Güzel Date: Tue, 13 Oct 2026 14:46:44 +0300 Subject: Eliminate pen style and history stream parameter smuggling - Introduce struct text_pen bundling (fg, bg, sl) across screen and core - Reduce text_append from 9 to 7 parameters - Reduce text_commit from 8 to 6 parameters - Reduce hist_runs_add_pen from 5 to 3 parameters - Reduce sc_text_ascii and sc_ascii_fast from 6 to 4 parameters - Remove unused fg, bg parameters from mark_row_blank - Introduce struct hist_stream_state in src/hist.c, reducing stream_lines from 9 to 5 params and lf_rows from 10 to 6 params - Introduce struct hist_view_pos in src/hist_view.h, reducing term_hist_view_row_pos from 9 to 7 params --- src/hist.c | 172 ++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 95 insertions(+), 77 deletions(-) (limited to 'src/hist.c') diff --git a/src/hist.c b/src/hist.c index 817b0f8..7bd9d04 100644 --- a/src/hist.c +++ b/src/hist.c @@ -758,7 +758,7 @@ void term_hist_runs_emit_slow(struct hist_runs *r) static inline void runs_repeat(struct hist_runs *r) { - hist_runs_switch(r, r->pen.fg, r->pen.bg, pen_sl(&r->pen)); + hist_runs_switch(r, text_pen_from_attr(&r->pen)); } /* Emit the pending run unless it is a default tail, which readers imply. */ @@ -1144,8 +1144,8 @@ static int encode_cells(struct hist_runs *r, const struct cell *cells, int n, ui const struct cell *cu = &cells[i]; int k = uniform_utf8_prefix(cu, n - i, dst + o->bytes, &u, &runcells); if (k > 0) { - hist_runs_add_pen(r, cu->fg, cu->bg, - (uint32_t)(cu->flags & STYLE_FLAGS) | ((uint32_t)cu->pad << 16), runcells); + hist_runs_add_pen(r, (struct text_pen){ cu->fg, cu->bg, + (uint32_t)(cu->flags & STYLE_FLAGS) | ((uint32_t)cu->pad << 16) }, runcells); o->bytes += u.bytes; o->cells += u.cells; o->wide += u.wide; @@ -1760,19 +1760,28 @@ void term_hist_push_text(struct hist *h, const struct text_row *row, bool wrappe walk_advance(h); } +struct hist_stream_state { + uint64_t head; + uint64_t rows; + uint32_t text_count; + uint32_t base; + uint32_t pg; + const char *first; +}; + /* Write the narrow descriptors of ends[i..stop) in blocks, while a block * fits before the ring wraps. Return the first line left for the caller. */ #if defined(TERM_KERNEL_AVX512) TERM_TARGET_AVX512 static int lf_rows_avx512(struct hist *restrict h, const uint16_t *restrict ends, int i, int stop, - uint32_t pg, uint32_t base, uint32_t cols, uint64_t *head_io, - uint64_t *rows_io, uint32_t *text_count_io) + uint32_t cols, struct hist_stream_state *state) { struct hline *restrict ring = h->ring; struct hist_block *restrict blocks = h->blocks; uint32_t mask = h->ring_mask; - uint64_t head = *head_io, rows = *rows_io; - uint32_t text_count = *text_count_io; + uint64_t head = state->head, rows = state->rows; + uint32_t text_count = state->text_count; + uint32_t pg = state->pg, base = state->base; const __m512i recip = _mm512_set1_epi32((int)(UINT64_C(0x100000000) / cols + 1)); for (; i + 16 <= stop && (head & mask) + 16 <= mask + 1; i += 16, head += 16) { __m512i start = _mm512_cvtepu16_epi32(_mm256_loadu_si256((const __m256i *)(ends + i))); @@ -1822,9 +1831,9 @@ static int lf_rows_avx512(struct hist *restrict h, const uint16_t *restrict ends _mm512_storeu_si512(dst + 8, _mm512_shuffle_i32x4(c, d, 0x88)); _mm512_storeu_si512(dst + 12, _mm512_shuffle_i32x4(c, d, 0xdd)); } - *head_io = head; - *rows_io = rows; - *text_count_io = text_count; + state->head = head; + state->rows = rows; + state->text_count = text_count; return i; } #endif @@ -1832,14 +1841,14 @@ static int lf_rows_avx512(struct hist *restrict h, const uint16_t *restrict ends #if defined(TERM_KERNEL_AVX2) TERM_TARGET_AVX2 static int lf_rows_avx2(struct hist *restrict h, const uint16_t *restrict ends, int i, int stop, - uint32_t pg, uint32_t base, uint32_t cols, uint64_t *head_io, - uint64_t *rows_io, uint32_t *text_count_io) + uint32_t cols, struct hist_stream_state *state) { struct hline *restrict ring = h->ring; struct hist_block *restrict blocks = h->blocks; uint32_t mask = h->ring_mask; - uint64_t head = *head_io, rows = *rows_io; - uint32_t text_count = *text_count_io; + uint64_t head = state->head, rows = state->rows; + uint32_t text_count = state->text_count; + uint32_t pg = state->pg, base = state->base; uint32_t recip = (uint32_t)(UINT64_C(0x100000000) / cols + 1); uint32_t block_rows = 0, block_refs = 0; for (; i + 4 <= stop && (head & mask) + 4 <= mask + 1; i += 4, head += 4) { @@ -1881,31 +1890,31 @@ static int lf_rows_avx2(struct hist *restrict h, const uint16_t *restrict ends, block_rows = block_refs = 0; } } - *head_io = head; - *rows_io = rows; - *text_count_io = text_count; + state->head = head; + state->rows = rows; + state->text_count = text_count; return i; } #endif static inline int lf_rows(struct hist *restrict h, const uint16_t *restrict ends, int i, int stop, - uint32_t pg, uint32_t base, uint32_t cols, uint64_t *head_io, - uint64_t *rows_io, uint32_t *text_count_io) + uint32_t cols, struct hist_stream_state *state) { #if defined(TERM_KERNEL_AVX512) if (term_use_avx512()) - return lf_rows_avx512(h, ends, i, stop, pg, base, cols, head_io, rows_io, text_count_io); + return lf_rows_avx512(h, ends, i, stop, cols, state); #endif #if defined(TERM_KERNEL_AVX2) if (term_use_avx2()) - return lf_rows_avx2(h, ends, i, stop, pg, base, cols, head_io, rows_io, text_count_io); + return lf_rows_avx2(h, ends, i, stop, cols, state); #endif #if defined(__aarch64__) struct hline *restrict ring = h->ring; struct hist_block *restrict blocks = h->blocks; uint32_t mask = h->ring_mask; - uint64_t head = *head_io, rows = *rows_io; - uint32_t text_count = *text_count_io; + uint64_t head = state->head, rows = state->rows; + uint32_t text_count = state->text_count; + uint32_t pg = state->pg, base = state->base; uint32_t recip = (uint32_t)(UINT64_C(0x100000000) / cols + 1); uint32_t block_rows = 0, block_refs = 0; for (; i + 4 <= stop && (head & mask) + 4 <= mask + 1; i += 4, head += 4) { @@ -1948,12 +1957,11 @@ static inline int lf_rows(struct hist *restrict h, const uint16_t *restrict ends block_rows = block_refs = 0; } } - *head_io = head; - *rows_io = rows; - *text_count_io = text_count; + state->head = head; + state->rows = rows; + state->text_count = text_count; #else - (void)h, (void)ends, (void)stop, (void)pg, (void)base, (void)cols; - (void)head_io, (void)rows_io, (void)text_count_io; + (void)h, (void)ends, (void)stop, (void)cols, (void)state; #endif return i; } @@ -1991,42 +1999,47 @@ void term_hist_push_ascii_lf(struct hist *restrict h, const char *restrict bytes uint32_t base = (pg << 16) + off - ends[i]; uint32_t span = ends[stop] - ends[i]; memcpy(h->pages[pg] + off, bytes + ends[i], span); - uint64_t head = h->head, rows = n; + struct hist_stream_state state = { + .head = h->head, + .rows = n, + .text_count = 0, + .base = base, + .pg = pg, + }; struct hline *restrict ring = h->ring; uint32_t mask = h->ring_mask; - uint32_t text_count = 0; - while (i < stop && (head & 15)) { + while (i < stop && (state.head & 15)) { uint32_t len = ends[i + 1] - ends[i] - 1; - struct hline *dst = ring + (head & mask); + struct hline *dst = ring + (state.head & mask); if (!len) *dst = HLINE_BLANK; else { uint32_t r = rows_narrow(len, (int)cols); part_put_narrow_rows(dst, base + ends[i], len, r); - rows += r - 1; - text_count++; + state.rows += r - 1; + state.text_count++; } i++; - head++; + state.head++; } - i = lf_rows(h, ends, i, stop, pg, base, cols, &head, &rows, &text_count); - for (; i < stop; i++, head++) { + i = lf_rows(h, ends, i, stop, cols, &state); + for (; i < stop; i++, state.head++) { uint32_t len = ends[i + 1] - ends[i] - 1; - struct hline *dst = ring + (head & mask); + struct hline *dst = ring + (state.head & mask); if (!len) *dst = HLINE_BLANK; else { uint32_t r = rows_narrow(len, (int)cols); part_put_narrow_rows(dst, base + ends[i], len, r); - rows += r - 1; - text_count++; + state.rows += r - 1; + state.text_count++; } } - h->head = head; - h->page_used[pg] = off + (text_count ? span : 0); - h->page_parts[pg] += text_count; + h->head = state.head; + h->page_used[pg] = off + (state.text_count ? span : 0); + h->page_parts[pg] += state.text_count; h->lines += n; - if (text_count) h->all_blank = false; + if (state.text_count) h->all_blank = false; if (count_rows) { - h->counted_rows += rows; + h->counted_rows += state.rows; h->rows_id += n; } } @@ -2041,11 +2054,12 @@ static_assert(offsetof(struct hist_ascii_line, len) == 8, "len is in the second #if defined(TERM_KERNEL_AVX512) TERM_TARGET_AVX512 static int stream_lines_avx512(struct hist *restrict h, const struct hist_ascii_line *lines, - int i, int stream_end, const char *first, uint32_t base, - uint32_t pg, uint64_t *head_io, uint32_t *text_count_io) + int i, int stream_end, struct hist_stream_state *state) { - uint64_t head = *head_io; - uint32_t text_count = *text_count_io; + uint64_t head = state->head; + uint32_t text_count = state->text_count; + uint32_t base = state->base, pg = state->pg; + const char *first = state->first; const __m512i even = _mm512_setr_epi64(0, 2, 4, 6, 8, 10, 12, 14); const __m512i odd = _mm512_setr_epi64(1, 3, 5, 7, 9, 11, 13, 15); for (; i + 16 <= stream_end && @@ -2096,8 +2110,8 @@ static int stream_lines_avx512(struct hist *restrict h, const struct hist_ascii_ }; } } - *head_io = head; - *text_count_io = text_count; + state->head = head; + state->text_count = text_count; return i; } #endif @@ -2105,12 +2119,12 @@ static int stream_lines_avx512(struct hist *restrict h, const struct hist_ascii_ #if defined(TERM_KERNEL_AVX2) TERM_TARGET_AVX2 static int stream_lines_avx2(struct hist *restrict h, const struct hist_ascii_line *lines, - int i, int stream_end, const char *first, uint32_t base, - uint32_t pg, uint64_t *head_io, uint32_t *text_count_io) + int i, int stream_end, struct hist_stream_state *state) { - (void)pg; - uint64_t head = *head_io; - uint32_t text_count = *text_count_io; + uint64_t head = state->head; + uint32_t text_count = state->text_count; + uint32_t base = state->base; + const char *first = state->first; for (; i + 4 <= stream_end && (head & h->ring_mask) + 4 <= h->ring_mask + 1; i += 4, head += 4) { struct hline *dst = h->ring + (head & h->ring_mask); @@ -2136,28 +2150,28 @@ static int stream_lines_avx2(struct hist *restrict h, const struct hist_ascii_li _mm256_castsi128_si256(_mm_unpacklo_epi64(b, d)), _mm_unpackhi_epi64(b, d), 1)); text_count += refs; } - *head_io = head; - *text_count_io = text_count; + state->head = head; + state->text_count = text_count; return i; } #endif static inline int stream_lines(struct hist *restrict h, const struct hist_ascii_line *lines, - int i, int stream_end, const char *first, uint32_t base, - uint32_t pg, uint64_t *head_io, uint32_t *text_count_io) + int i, int stream_end, struct hist_stream_state *state) { #if defined(TERM_KERNEL_AVX512) if (term_use_avx512()) - return stream_lines_avx512(h, lines, i, stream_end, first, base, pg, head_io, text_count_io); + return stream_lines_avx512(h, lines, i, stream_end, state); #endif #if defined(TERM_KERNEL_AVX2) if (term_use_avx2()) - return stream_lines_avx2(h, lines, i, stream_end, first, base, pg, head_io, text_count_io); + return stream_lines_avx2(h, lines, i, stream_end, state); #endif #if defined(__aarch64__) - (void)pg; - uint64_t head = *head_io; - uint32_t text_count = *text_count_io; + uint64_t head = state->head; + uint32_t text_count = state->text_count; + uint32_t base = state->base; + const char *first = state->first; for (; i + 4 <= stream_end && (head & h->ring_mask) + 4 <= h->ring_mask + 1; i += 4, head += 4) { struct hline *dst = h->ring + (head & h->ring_mask); @@ -2174,11 +2188,10 @@ static inline int stream_lines(struct hist *restrict h, const struct hist_ascii_ vst4q_u32((uint32_t *)dst, parts); text_count += refs; } - *head_io = head; - *text_count_io = text_count; + state->head = head; + state->text_count = text_count; #else - (void)h, (void)lines, (void)stream_end, (void)first, (void)base, (void)pg; - (void)head_io, (void)text_count_io; + (void)h, (void)lines, (void)stream_end, (void)state; #endif return i; } @@ -2249,13 +2262,18 @@ void term_hist_push_ascii_lines(struct hist *h, const struct hist_ascii_line *li uint32_t off = h->page_used[pg]; memcpy(h->pages[pg] + off, l->ptr, span); uint32_t base = (pg << 16) | off; - uint32_t text_count = 0; - uint64_t head = h->head; + struct hist_stream_state state = { + .head = h->head, + .text_count = 0, + .base = base, + .pg = pg, + .first = l->ptr, + }; if (!extra_rows) - i = stream_lines(h, lines, i, stream_end, l->ptr, base, pg, &head, &text_count); + i = stream_lines(h, lines, i, stream_end, &state); for (; i < stream_end; i++) { uint32_t len = lines[i].len; - struct hline *dst = &h->ring[head++ & h->ring_mask]; + struct hline *dst = &h->ring[state.head++ & h->ring_mask]; if (len) { uint32_t line_off = base + (uint32_t)(lines[i].ptr - l->ptr); if (TERM_EXPECT(len <= cols, 1)) { @@ -2263,7 +2281,7 @@ void term_hist_push_ascii_lines(struct hist *h, const struct hist_ascii_line *li } else { part_put_narrow_rows(dst, line_off, len, rows_narrow(len, cols)); } - text_count++; + state.text_count++; } else { *dst = HLINE_BLANK; } @@ -2272,11 +2290,11 @@ void term_hist_push_ascii_lines(struct hist *h, const struct hist_ascii_line *li h->counted_rows += stream_rows; h->rows_id += n; } - h->head = head; + h->head = state.head; h->page_used[pg] = off + span; - h->page_parts[pg] += text_count; + h->page_parts[pg] += state.text_count; h->lines += n; - if (text_count) + if (state.text_count) h->all_blank = false; continue; } -- cgit v1.2.3