From 8ee1c851a1c5f0f790c358c074438c51a12ef8a5 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 26 Aug 2017 13:05:18 +0530 Subject: [PATCH] Optimize the bit twiddling in sprite_position_for --- kitty/data-types.h | 3 +++ kitty/sprites.c | 9 ++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/kitty/data-types.h b/kitty/data-types.h index f0feafd1f..89c7b8842 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -14,6 +14,8 @@ #include #define UNUSED __attribute__ ((unused)) #define EXPORTED __attribute__ ((visibility ("default"))) +#define LIKELY(x) __builtin_expect (!!(x), 1) +#define UNLIKELY(x) __builtin_expect (!!(x), 0) #define MAX(x, y) (((x) > (y)) ? (x) : (y)) #define MIN(x, y) (((x) > (y)) ? (y) : (x)) #define xstr(s) str(s) @@ -45,6 +47,7 @@ typedef unsigned int index_type; #define DECORATION_MASK 3 #define BOLD_SHIFT 4 #define ITALIC_SHIFT 5 +#define POSCHAR_MASK 0x30FFFFFF #define REVERSE_SHIFT 6 #define STRIKE_SHIFT 7 #define COL_MASK 0xFFFFFFFF diff --git a/kitty/sprites.c b/kitty/sprites.c index f04274657..bb2000187 100644 --- a/kitty/sprites.c +++ b/kitty/sprites.c @@ -77,12 +77,11 @@ do_increment(SpriteMap *self, int *error) { static SpritePosition* sprite_position_for(SpriteMap *self, char_type ch, combining_type cc, bool is_second, int *error) { - char_type attrs = ch >> ATTRS_SHIFT, pos_char; - uint8_t bold = (attrs >> BOLD_SHIFT) & 1, italic = (attrs >> ITALIC_SHIFT) & 1; - size_t idx = (ch & 0xff) | (bold << 8) | (italic << 9); - attrs = bold << BOLD_SHIFT | italic << ITALIC_SHIFT; - pos_char = (ch & CHAR_MASK) | (attrs << ATTRS_SHIFT); + char_type pos_char = ch & POSCHAR_MASK; // Includes only the char and bold and italic bits + unsigned int idx = ((ch >> (ATTRS_SHIFT - 6)) & 0x300) | (ch & 0xFF); // Includes only italic, bold and lowest byte of ch SpritePosition *s = &(self->cache[idx]); + // Optimize for the common case of an ASCII char already in the cache + if (LIKELY(s->ch == pos_char && s->filled && s->cc == cc && s->is_second == is_second)) return s; // Cache hit while(true) { if (s->filled) { if (s->ch == pos_char && s->cc == cc && s->is_second == is_second) return s; // Cache hit