aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2020-04-11 18:35:35 -0700
committerPaul Eggert2020-04-11 19:00:27 -0700
commit43282a6772630275259dbc7560913c07f72eb06e (patch)
treeab213ea3904d25fb0142817765c501d7add95c0d /src
parent7abfb6475716e3002c30d10ead0c309b4fed6992 (diff)
downloademacs-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.c2
-rw-r--r--src/character.h55
-rw-r--r--src/composite.h9
-rw-r--r--src/dispextern.h29
-rw-r--r--src/frame.h43
-rw-r--r--src/keyboard.c10
-rw-r--r--src/lisp.h16
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
83extern 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) 131INLINE bool
132CHAR_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) 154INLINE bool
155SINGLE_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) \ 189INLINE int
180 (UNSIGNED_CMP (c, <=, MAX_1_BYTE_CHAR) \ 190CHAR_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
659extern EMACS_INT char_resolve_modifier_mask (EMACS_INT) ATTRIBUTE_CONST; 681extern EMACS_INT char_resolve_modifier_mask (EMACS_INT) ATTRIBUTE_CONST;
660extern int char_string (unsigned, unsigned char *);
661extern int string_char (const unsigned char *, 682extern 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) \ 130INLINE bool
131 (UNSIGNED_CMP (gref, <, 12) && UNSIGNED_CMP (nref, <, 12)) 131COMPOSITION_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
1456INLINE struct face *
1457FACE_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
1466INLINE struct face *
1467FACE_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
1478INLINE struct image *
1479IMAGE_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
1488INLINE struct image *
1489IMAGE_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) 1927INLINE bool
1928ASCII_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