summaryrefslogtreecommitdiff
path: root/src/hist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/hist.c')
-rw-r--r--src/hist.c172
1 files changed, 95 insertions, 77 deletions
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;
}