diff options
| author | Paul Eggert | 2020-04-11 18:35:35 -0700 |
|---|---|---|
| committer | Paul Eggert | 2020-04-11 19:00:27 -0700 |
| commit | 43282a6772630275259dbc7560913c07f72eb06e (patch) | |
| tree | ab213ea3904d25fb0142817765c501d7add95c0d /src | |
| parent | 7abfb6475716e3002c30d10ead0c309b4fed6992 (diff) | |
| download | emacs-43282a6772630275259dbc7560913c07f72eb06e.tar.gz emacs-43282a6772630275259dbc7560913c07f72eb06e.zip | |
Remove UNSIGNED_CMP
I added this macro in 2011 to fix some signedness comparison bugs.
However, it’s a weird macro and the bugs can be fixed in a
more-straightforward way. This helps performance slightly (0.5%) on my
platform (Fedora 31 x86-64, GCC 9.3.1 with -O2).
* src/casefiddle.c (do_casify_natnum): Use simple comparison
instead of UNSIGNED_CMP.
* src/character.h (CHAR_VALID_P, SINGLE_BYTE_CHAR_P, CHAR_STRING):
* src/composite.h (COMPOSITION_ENCODE_RULE_VALID):
* src/lisp.h (ASCII_CHAR_P):
Now an inline function, and uses simple comparison instead of
UNSIGNED_CMP.
* src/dispextern.h (FACE_FROM_ID, FACE_FROM_ID_OR_NULL)
(IMAGE_FROM_ID, IMAGE_OPT_FROM_ID): Move these to ...
* src/frame.h (FACE_FROM_ID, FACE_FROM_ID_OR_NULL)
(IMAGE_FROM_ID, IMAGE_OPT_FROM_ID): ... here, and make them
inline functions that no longer use UNSIGNED_CMP.
* src/keyboard.c (read_char): UNSIGNED_CMP is not needed here
since XFIXNAT always returns a nonnegative value.
* src/lisp.h (UNSIGNED_CMP): Remove; no longer used.
Diffstat (limited to 'src')
| -rw-r--r-- | src/casefiddle.c | 2 | ||||
| -rw-r--r-- | src/character.h | 55 | ||||
| -rw-r--r-- | src/composite.h | 9 | ||||
| -rw-r--r-- | src/dispextern.h | 29 | ||||
| -rw-r--r-- | src/frame.h | 43 | ||||
| -rw-r--r-- | src/keyboard.c | 10 | ||||
| -rw-r--r-- | src/lisp.h | 16 |
7 files changed, 97 insertions, 67 deletions
diff --git a/src/casefiddle.c b/src/casefiddle.c index 1945aa15e71..5018b7bb1cd 100644 --- a/src/casefiddle.c +++ b/src/casefiddle.c | |||
| @@ -229,7 +229,7 @@ do_casify_natnum (struct casing_context *ctx, Lisp_Object obj) | |||
| 229 | 229 | ||
| 230 | /* If the character has higher bits set above the flags, return it unchanged. | 230 | /* If the character has higher bits set above the flags, return it unchanged. |
| 231 | It is not a real character. */ | 231 | It is not a real character. */ |
| 232 | if (UNSIGNED_CMP (ch, >, flagbits)) | 232 | if (! (0 <= ch && ch <= flagbits)) |
| 233 | return obj; | 233 | return obj; |
| 234 | 234 | ||
| 235 | int flags = ch & flagbits; | 235 | int flags = ch & flagbits; |
diff --git a/src/character.h b/src/character.h index 3642a540448..7639b018cb0 100644 --- a/src/character.h +++ b/src/character.h | |||
| @@ -80,6 +80,8 @@ enum | |||
| 80 | OBJECT_REPLACEMENT_CHARACTER = 0xFFFC, | 80 | OBJECT_REPLACEMENT_CHARACTER = 0xFFFC, |
| 81 | }; | 81 | }; |
| 82 | 82 | ||
| 83 | extern int char_string (unsigned, unsigned char *); | ||
| 84 | |||
| 83 | /* UTF-8 encodings. Use \x escapes, so they are portable to pre-C11 | 85 | /* UTF-8 encodings. Use \x escapes, so they are portable to pre-C11 |
| 84 | compilers and can be concatenated with ordinary string literals. */ | 86 | compilers and can be concatenated with ordinary string literals. */ |
| 85 | #define uLSQM "\xE2\x80\x98" /* U+2018 LEFT SINGLE QUOTATION MARK */ | 87 | #define uLSQM "\xE2\x80\x98" /* U+2018 LEFT SINGLE QUOTATION MARK */ |
| @@ -126,7 +128,11 @@ enum | |||
| 126 | #define CHARACTERP(x) (FIXNATP (x) && XFIXNAT (x) <= MAX_CHAR) | 128 | #define CHARACTERP(x) (FIXNATP (x) && XFIXNAT (x) <= MAX_CHAR) |
| 127 | 129 | ||
| 128 | /* Nonzero iff C is valid as a character code. */ | 130 | /* Nonzero iff C is valid as a character code. */ |
| 129 | #define CHAR_VALID_P(c) UNSIGNED_CMP (c, <=, MAX_CHAR) | 131 | INLINE bool |
| 132 | CHAR_VALID_P (intmax_t c) | ||
| 133 | { | ||
| 134 | return 0 <= c && c <= MAX_CHAR; | ||
| 135 | } | ||
| 130 | 136 | ||
| 131 | /* Check if Lisp object X is a character or not. */ | 137 | /* Check if Lisp object X is a character or not. */ |
| 132 | #define CHECK_CHARACTER(x) \ | 138 | #define CHECK_CHARACTER(x) \ |
| @@ -145,7 +151,11 @@ enum | |||
| 145 | } while (false) | 151 | } while (false) |
| 146 | 152 | ||
| 147 | /* Nonzero iff C is a character of code less than 0x100. */ | 153 | /* Nonzero iff C is a character of code less than 0x100. */ |
| 148 | #define SINGLE_BYTE_CHAR_P(c) UNSIGNED_CMP (c, <, 0x100) | 154 | INLINE bool |
| 155 | SINGLE_BYTE_CHAR_P (intmax_t c) | ||
| 156 | { | ||
| 157 | return 0 <= c && c < 0x100; | ||
| 158 | } | ||
| 149 | 159 | ||
| 150 | /* Nonzero if character C has a printable glyph. */ | 160 | /* Nonzero if character C has a printable glyph. */ |
| 151 | #define CHAR_PRINTABLE_P(c) \ | 161 | #define CHAR_PRINTABLE_P(c) \ |
| @@ -176,20 +186,32 @@ enum | |||
| 176 | allocate at least MAX_MULTIBYTE_LENGTH bytes area at P in advance. | 186 | allocate at least MAX_MULTIBYTE_LENGTH bytes area at P in advance. |
| 177 | Returns the length of the multibyte form. */ | 187 | Returns the length of the multibyte form. */ |
| 178 | 188 | ||
| 179 | #define CHAR_STRING(c, p) \ | 189 | INLINE int |
| 180 | (UNSIGNED_CMP (c, <=, MAX_1_BYTE_CHAR) \ | 190 | CHAR_STRING (int c, unsigned char *p) |
| 181 | ? ((p)[0] = (c), \ | 191 | { |
| 182 | 1) \ | 192 | eassume (0 <= c); |
| 183 | : UNSIGNED_CMP (c, <=, MAX_2_BYTE_CHAR) \ | 193 | if (c <= MAX_1_BYTE_CHAR) |
| 184 | ? ((p)[0] = (0xC0 | ((c) >> 6)), \ | 194 | { |
| 185 | (p)[1] = (0x80 | ((c) & 0x3F)), \ | 195 | p[0] = c; |
| 186 | 2) \ | 196 | return 1; |
| 187 | : UNSIGNED_CMP (c, <=, MAX_3_BYTE_CHAR) \ | 197 | } |
| 188 | ? ((p)[0] = (0xE0 | ((c) >> 12)), \ | 198 | if (c <= MAX_2_BYTE_CHAR) |
| 189 | (p)[1] = (0x80 | (((c) >> 6) & 0x3F)), \ | 199 | { |
| 190 | (p)[2] = (0x80 | ((c) & 0x3F)), \ | 200 | p[0] = 0xC0 | (c >> 6); |
| 191 | 3) \ | 201 | p[1] = 0x80 | (c & 0x3F); |
| 192 | : verify_expr (sizeof (c) <= sizeof (unsigned), char_string (c, p))) | 202 | return 2; |
| 203 | } | ||
| 204 | if (c <= MAX_3_BYTE_CHAR) | ||
| 205 | { | ||
| 206 | p[0] = 0xE0 | (c >> 12); | ||
| 207 | p[1] = 0x80 | ((c >> 6) & 0x3F); | ||
| 208 | p[2] = 0x80 | (c & 0x3F); | ||
| 209 | return 3; | ||
| 210 | } | ||
| 211 | int len = char_string (c, p); | ||
| 212 | eassume (0 < len && len <= MAX_MULTIBYTE_LENGTH); | ||
| 213 | return len; | ||
| 214 | } | ||
| 193 | 215 | ||
| 194 | /* Store multibyte form of byte B in P. The caller should allocate at | 216 | /* Store multibyte form of byte B in P. The caller should allocate at |
| 195 | least MAX_MULTIBYTE_LENGTH bytes area at P in advance. Returns the | 217 | least MAX_MULTIBYTE_LENGTH bytes area at P in advance. Returns the |
| @@ -657,7 +679,6 @@ typedef enum { | |||
| 657 | } unicode_category_t; | 679 | } unicode_category_t; |
| 658 | 680 | ||
| 659 | extern EMACS_INT char_resolve_modifier_mask (EMACS_INT) ATTRIBUTE_CONST; | 681 | extern EMACS_INT char_resolve_modifier_mask (EMACS_INT) ATTRIBUTE_CONST; |
| 660 | extern int char_string (unsigned, unsigned char *); | ||
| 661 | extern int string_char (const unsigned char *, | 682 | extern int string_char (const unsigned char *, |
| 662 | const unsigned char **, int *); | 683 | const unsigned char **, int *); |
| 663 | 684 | ||
diff --git a/src/composite.h b/src/composite.h index 62c4de40e3b..239f1e531ef 100644 --- a/src/composite.h +++ b/src/composite.h | |||
| @@ -125,10 +125,13 @@ composition_registered_p (Lisp_Object prop) | |||
| 125 | COMPOSITION_DECODE_REFS (rule_code, gref, nref); \ | 125 | COMPOSITION_DECODE_REFS (rule_code, gref, nref); \ |
| 126 | } while (false) | 126 | } while (false) |
| 127 | 127 | ||
| 128 | /* Nonzero if the global reference point GREF and new reference point NREF are | 128 | /* True if the global reference point GREF and new reference point NREF are |
| 129 | valid. */ | 129 | valid. */ |
| 130 | #define COMPOSITION_ENCODE_RULE_VALID(gref, nref) \ | 130 | INLINE bool |
| 131 | (UNSIGNED_CMP (gref, <, 12) && UNSIGNED_CMP (nref, <, 12)) | 131 | COMPOSITION_ENCODE_RULE_VALID (int gref, int nref) |
| 132 | { | ||
| 133 | return 0 <= gref && gref < 12 && 0 <= nref && nref < 12; | ||
| 134 | } | ||
| 132 | 135 | ||
| 133 | /* Return encoded composition rule for the pair of global reference | 136 | /* Return encoded composition rule for the pair of global reference |
| 134 | point GREF and new reference point NREF. Arguments must be valid. */ | 137 | point GREF and new reference point NREF. Arguments must be valid. */ |
diff --git a/src/dispextern.h b/src/dispextern.h index 555946f84cb..ae994d7f9bc 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -1855,20 +1855,6 @@ struct face_cache | |||
| 1855 | bool_bf menu_face_changed_p : 1; | 1855 | bool_bf menu_face_changed_p : 1; |
| 1856 | }; | 1856 | }; |
| 1857 | 1857 | ||
| 1858 | /* Return a non-null pointer to the cached face with ID on frame F. */ | ||
| 1859 | |||
| 1860 | #define FACE_FROM_ID(F, ID) \ | ||
| 1861 | (eassert (UNSIGNED_CMP (ID, <, FRAME_FACE_CACHE (F)->used)), \ | ||
| 1862 | FRAME_FACE_CACHE (F)->faces_by_id[ID]) | ||
| 1863 | |||
| 1864 | /* Return a pointer to the face with ID on frame F, or null if such a | ||
| 1865 | face doesn't exist. */ | ||
| 1866 | |||
| 1867 | #define FACE_FROM_ID_OR_NULL(F, ID) \ | ||
| 1868 | (UNSIGNED_CMP (ID, <, FRAME_FACE_CACHE (F)->used) \ | ||
| 1869 | ? FRAME_FACE_CACHE (F)->faces_by_id[ID] \ | ||
| 1870 | : NULL) | ||
| 1871 | |||
| 1872 | #define FACE_EXTENSIBLE_P(F) \ | 1858 | #define FACE_EXTENSIBLE_P(F) \ |
| 1873 | (!NILP (F->lface[LFACE_EXTEND_INDEX])) | 1859 | (!NILP (F->lface[LFACE_EXTEND_INDEX])) |
| 1874 | 1860 | ||
| @@ -3163,21 +3149,6 @@ struct image_cache | |||
| 3163 | ptrdiff_t refcount; | 3149 | ptrdiff_t refcount; |
| 3164 | }; | 3150 | }; |
| 3165 | 3151 | ||
| 3166 | |||
| 3167 | /* A non-null pointer to the image with id ID on frame F. */ | ||
| 3168 | |||
| 3169 | #define IMAGE_FROM_ID(F, ID) \ | ||
| 3170 | (eassert (UNSIGNED_CMP (ID, <, FRAME_IMAGE_CACHE (F)->used)), \ | ||
| 3171 | FRAME_IMAGE_CACHE (F)->images[ID]) | ||
| 3172 | |||
| 3173 | /* Value is a pointer to the image with id ID on frame F, or null if | ||
| 3174 | no image with that id exists. */ | ||
| 3175 | |||
| 3176 | #define IMAGE_OPT_FROM_ID(F, ID) \ | ||
| 3177 | (UNSIGNED_CMP (ID, <, FRAME_IMAGE_CACHE (F)->used) \ | ||
| 3178 | ? FRAME_IMAGE_CACHE (F)->images[ID] \ | ||
| 3179 | : NULL) | ||
| 3180 | |||
| 3181 | /* Size of bucket vector of image caches. Should be prime. */ | 3152 | /* Size of bucket vector of image caches. Should be prime. */ |
| 3182 | 3153 | ||
| 3183 | #define IMAGE_CACHE_BUCKETS_SIZE 1001 | 3154 | #define IMAGE_CACHE_BUCKETS_SIZE 1001 |
diff --git a/src/frame.h b/src/frame.h index 641bb430d0e..476bac67faf 100644 --- a/src/frame.h +++ b/src/frame.h | |||
| @@ -1450,6 +1450,49 @@ FRAME_BOTTOM_DIVIDER_WIDTH (struct frame *f) | |||
| 1450 | { | 1450 | { |
| 1451 | return frame_dimension (f->bottom_divider_width); | 1451 | return frame_dimension (f->bottom_divider_width); |
| 1452 | } | 1452 | } |
| 1453 | |||
| 1454 | /* Return a non-null pointer to the cached face with ID on frame F. */ | ||
| 1455 | |||
| 1456 | INLINE struct face * | ||
| 1457 | FACE_FROM_ID (struct frame *f, int id) | ||
| 1458 | { | ||
| 1459 | eassert (0 <= id && id < FRAME_FACE_CACHE (f)->used); | ||
| 1460 | return FRAME_FACE_CACHE (f)->faces_by_id[id]; | ||
| 1461 | } | ||
| 1462 | |||
| 1463 | /* Return a pointer to the face with ID on frame F, or null if such a | ||
| 1464 | face doesn't exist. */ | ||
| 1465 | |||
| 1466 | INLINE struct face * | ||
| 1467 | FACE_FROM_ID_OR_NULL (struct frame *f, int id) | ||
| 1468 | { | ||
| 1469 | int used = FRAME_FACE_CACHE (f)->used; | ||
| 1470 | eassume (0 <= used); | ||
| 1471 | return 0 <= id && id < used ? FRAME_FACE_CACHE (f)->faces_by_id[id] : NULL; | ||
| 1472 | } | ||
| 1473 | |||
| 1474 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 1475 | |||
| 1476 | /* A non-null pointer to the image with id ID on frame F. */ | ||
| 1477 | |||
| 1478 | INLINE struct image * | ||
| 1479 | IMAGE_FROM_ID (struct frame *f, int id) | ||
| 1480 | { | ||
| 1481 | eassert (0 <= id && id < FRAME_IMAGE_CACHE (f)->used); | ||
| 1482 | return FRAME_IMAGE_CACHE (f)->images[id]; | ||
| 1483 | } | ||
| 1484 | |||
| 1485 | /* Value is a pointer to the image with id ID on frame F, or null if | ||
| 1486 | no image with that id exists. */ | ||
| 1487 | |||
| 1488 | INLINE struct image * | ||
| 1489 | IMAGE_OPT_FROM_ID (struct frame *f, int id) | ||
| 1490 | { | ||
| 1491 | int used = FRAME_IMAGE_CACHE (f)->used; | ||
| 1492 | eassume (0 <= used); | ||
| 1493 | return 0 <= id && id < used ? FRAME_IMAGE_CACHE (f)->images[id] : NULL; | ||
| 1494 | } | ||
| 1495 | #endif | ||
| 1453 | 1496 | ||
| 1454 | /*********************************************************************** | 1497 | /*********************************************************************** |
| 1455 | Conversion between canonical units and pixels | 1498 | Conversion between canonical units and pixels |
diff --git a/src/keyboard.c b/src/keyboard.c index 9ce168c6dd0..b4e62c3bb49 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -2927,13 +2927,11 @@ read_char (int commandflag, Lisp_Object map, | |||
| 2927 | goto exit; | 2927 | goto exit; |
| 2928 | 2928 | ||
| 2929 | if ((STRINGP (KVAR (current_kboard, Vkeyboard_translate_table)) | 2929 | if ((STRINGP (KVAR (current_kboard, Vkeyboard_translate_table)) |
| 2930 | && UNSIGNED_CMP (XFIXNAT (c), <, | 2930 | && XFIXNAT (c) < SCHARS (KVAR (current_kboard, |
| 2931 | SCHARS (KVAR (current_kboard, | 2931 | Vkeyboard_translate_table))) |
| 2932 | Vkeyboard_translate_table)))) | ||
| 2933 | || (VECTORP (KVAR (current_kboard, Vkeyboard_translate_table)) | 2932 | || (VECTORP (KVAR (current_kboard, Vkeyboard_translate_table)) |
| 2934 | && UNSIGNED_CMP (XFIXNAT (c), <, | 2933 | && XFIXNAT (c) < ASIZE (KVAR (current_kboard, |
| 2935 | ASIZE (KVAR (current_kboard, | 2934 | Vkeyboard_translate_table))) |
| 2936 | Vkeyboard_translate_table)))) | ||
| 2937 | || (CHAR_TABLE_P (KVAR (current_kboard, Vkeyboard_translate_table)) | 2935 | || (CHAR_TABLE_P (KVAR (current_kboard, Vkeyboard_translate_table)) |
| 2938 | && CHARACTERP (c))) | 2936 | && CHARACTERP (c))) |
| 2939 | { | 2937 | { |
diff --git a/src/lisp.h b/src/lisp.h index c3efabaf528..706ca6b9a82 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -1923,18 +1923,12 @@ memclear (void *p, ptrdiff_t nbytes) | |||
| 1923 | (offsetof (type, lastlispfield) + word_size < header_size \ | 1923 | (offsetof (type, lastlispfield) + word_size < header_size \ |
| 1924 | ? 0 : (offsetof (type, lastlispfield) + word_size - header_size) / word_size) | 1924 | ? 0 : (offsetof (type, lastlispfield) + word_size - header_size) / word_size) |
| 1925 | 1925 | ||
| 1926 | /* Compute A OP B, using the unsigned comparison operator OP. A and B | ||
| 1927 | should be integer expressions. This is not the same as | ||
| 1928 | mathematical comparison; for example, UNSIGNED_CMP (0, <, -1) | ||
| 1929 | returns true. For efficiency, prefer plain unsigned comparison if A | ||
| 1930 | and B's sizes both fit (after integer promotion). */ | ||
| 1931 | #define UNSIGNED_CMP(a, op, b) \ | ||
| 1932 | (max (sizeof ((a) + 0), sizeof ((b) + 0)) <= sizeof (unsigned) \ | ||
| 1933 | ? ((a) + (unsigned) 0) op ((b) + (unsigned) 0) \ | ||
| 1934 | : ((a) + (uintmax_t) 0) op ((b) + (uintmax_t) 0)) | ||
| 1935 | |||
| 1936 | /* True iff C is an ASCII character. */ | 1926 | /* True iff C is an ASCII character. */ |
| 1937 | #define ASCII_CHAR_P(c) UNSIGNED_CMP (c, <, 0x80) | 1927 | INLINE bool |
| 1928 | ASCII_CHAR_P (intmax_t c) | ||
| 1929 | { | ||
| 1930 | return 0 <= c && c < 0x80; | ||
| 1931 | } | ||
| 1938 | 1932 | ||
| 1939 | /* A char-table is a kind of vectorlike, with contents are like a | 1933 | /* A char-table is a kind of vectorlike, with contents are like a |
| 1940 | vector but with a few other slots. For some purposes, it makes | 1934 | vector but with a few other slots. For some purposes, it makes |