Subject: bug#11935: XINT etc. should be functions

From: Paul Eggert <[email-masked]>
Date: Tue, 24 Jul 2012 06:45:27 -0700

On 07/24/2012 02:07 AM, Stefan Monnier wrote:
> Could you separate this part of the patch, since I don't know what you
> mean by "inlining by hand".

Sure, attached; this assumes the earlier patch in
<http://debbugs.gnu.org/cgi/bugreport.cgi?bug=11935#5>
has been applied and merged.

2012-07-24  Paul Eggert  <[email-masked]>
 
	* lisp.h (XLI, XIL, CHECK_TYPE, CHECK_LIST_CONS, CHECK_NUMBER)
	(CHECK_SYMBOL, CONSP, EQ, FLOATP, INTEGERP, LISP_INT_TAG_P, MARKERP)
	(MISCP, NILP, SET_SYMBOL_VAL, SYMBOL_CONSTANT_P, SYMBOL_VAL, SYMBOLP)
	(VECTORLIKEP, XCAR, XCDR, XCONS, XHASH, XPNTR, XSYMBOL):
	If compiling via GCC without optimization, inline these functions
	manually, by defining macros in addition to inline functions.
	To disable this, compile with -DINLINING=0.
	(make_number, XFASTINT, XINT, XTYPE, XUNTAG): Likewise, but
	hand-optimize only in the USE_LSB_TAG case, as GNUish hosts do that.

=== modified file 'src/lisp.h'
--- src/lisp.h	2012-07-23 21:58:10 +0000
+++ src/lisp.h	2012-07-24 01:57:18 +0000
@@ -214,6 +214,62 @@
 #endif

+/* When compiling via GCC without optimization, inline a few functions
+   manually, as Emacs is too slow otherwise.  There's no need to
+   inline everything, just the functions that would cause a serious
+   performance problem when debugging.  To disable this hand-optimization,
+   compile with -DINLINING=0.
+
+   Commentary for these macros can be found near their corresponding
+   functions, below.  */
+#if (defined __NO_INLINE__ \
+     && ! defined __OPTIMIZE__ && ! defined __OPTIMIZE_SIZE__ \
+     && ! (defined INLINING && ! INLINING))
+# if CHECK_LISP_OBJECT_TYPE
+#  define XLI(o) (o).i
+#  define XIL(i) (Lisp_Object) { i }
+# else
+#  define XLI(o) (o)
+#  define XIL(i) (i)
+# endif
+# define CHECK_TYPE(ok, Qxxxp, x) \
+    ((void) ((ok) || wrong_type_argument (Qxxxp, x)))
+# define CHECK_LIST_CONS(x, y) CHECK_TYPE (CONSP (x), Qlistp, y)
+# define CHECK_NUMBER(x) CHECK_TYPE (INTEGERP (x), Qintegerp, x)
+# define CHECK_SYMBOL(x) CHECK_TYPE (SYMBOLP (x), Qsymbolp, x)
+# define CONSP(x) (XTYPE (x) == Lisp_Cons)
+# define EQ(a, b) (XHASH (a) == XHASH (b))
+# define FLOATP(x) (XTYPE (x) == Lisp_Float)
+# define INTEGERP(x) LISP_INT_TAG_P (XTYPE (x))
+# define LISP_INT_TAG_P(x) (((x) & ~Lisp_Int1) == 0)
+# define MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
+# define MISCP(x) (XTYPE (x) == Lisp_Misc)
+# define NILP(x) EQ (x, Qnil)
+# define SET_SYMBOL_VAL(sym, v) \
+    (eassert ((sym)->redirect == SYMBOL_PLAINVAL), (sym)->val.value = (v))
+# define SYMBOL_CONSTANT_P(sym) (XSYMBOL (sym)->constant)
+# define SYMBOL_VAL(sym)						\
+    (eassert ((sym)->redirect == SYMBOL_PLAINVAL), (sym)->val.value)
+# define SYMBOLP(x) (XTYPE (x) == Lisp_Symbol)
+# define VECTORLIKEP(x) (XTYPE (x) == Lisp_Vectorlike)
+# define XCAR(c) XCAR_AS_LVALUE (c)
+# define XCDR(c) XCDR_AS_LVALUE (c)
+# define XCONS(a) \
+    (eassert (CONSP (a)), (struct Lisp_Cons *) XUNTAG (a, Lisp_Cons))
+# define XHASH(o) XLI (o)
+# define XPNTR(a) ((void *) (intptr_t) ((XLI (a) & VALMASK) | DATA_SEG_BITS))
+# define XSYMBOL(a) \
+    (eassert (SYMBOLP (a)), (struct Lisp_Symbol *) XUNTAG (a, Lisp_Symbol))
+# if USE_LSB_TAG
+#  define make_number(n) XIL ((EMACS_INT) (n) << INTTYPEBITS)
+#  define XFASTINT(a) XINT (a)
+#  define XINT(a) (XLI (a) >> INTTYPEBITS)
+#  define XTYPE(a) ((enum Lisp_Type) (XLI (a) & ~VALMASK))
+#  define XUNTAG(a, type) ((void *) (XLI (a) - (type)))
+# endif
+#endif
+
+
 /* Define the fundamental Lisp data structures.  */
 
 /* This is the set of Lisp data types.  */
@@ -266,7 +322,7 @@
 /* An older name for Lisp_Int0.  */
 enum { LISP_INT_TAG = Lisp_Int0 };
 
-static inline int LISP_INT_TAG_P (int x) { return (x & ~Lisp_Int1) == 0; }
+static inline int (LISP_INT_TAG_P) (int x) { return (x & ~Lisp_Int1) == 0; }
 
 /* This is the set of data types that share a common structure.
    The first member of the structure is a type code from this set.
@@ -302,10 +358,10 @@
 
 typedef struct { EMACS_INT i; } Lisp_Object;
 
-static inline EMACS_INT XLI (Lisp_Object o) { return o.i; }
+static inline EMACS_INT (XLI) (Lisp_Object o) { return o.i; }
 
 static inline Lisp_Object
-XIL (EMACS_INT i)
+(XIL) (EMACS_INT i)
 {
   Lisp_Object o = { i };
   return o;
@@ -318,8 +374,8 @@
 /* If a struct type is not wanted, define Lisp_Object as just a number.  */
 
 typedef EMACS_INT Lisp_Object;
-static inline EMACS_INT XLI (Lisp_Object o) { return o; }
-static inline Lisp_Object XIL (EMACS_INT i) { return i; }
+static inline EMACS_INT (XLI) (Lisp_Object o) { return o; }
+static inline Lisp_Object (XIL) (EMACS_INT i) { return i; }
 #define LISP_INITIALLY_ZERO 0
 #endif /* CHECK_LISP_OBJECT_TYPE */
 
@@ -389,7 +445,7 @@
  XCONS (tem) is the struct Lisp_Cons * pointing to the memory for that cons.  */
 
 /* Return a perfect hash of the Lisp_Object representation.  */
-static inline EMACS_INT XHASH (Lisp_Object o) { return XLI (o); }
+static inline EMACS_INT (XHASH) (Lisp_Object o) { return XLI (o); }
 
 #define VALMASK (USE_LSB_TAG ? - (1 << GCTYPEBITS) : VAL_MAX)
 
@@ -399,7 +455,7 @@
 #define MOST_NEGATIVE_FIXNUM (-1 - MOST_POSITIVE_FIXNUM)
 
 static inline enum Lisp_Type
-XTYPE (Lisp_Object a)
+(XTYPE) (Lisp_Object a)
 {
   EMACS_UINT i = XLI (a);
   return USE_LSB_TAG ? i & ~VALMASK : i >> VALBITS;
@@ -407,7 +463,7 @@
 
 /* Extract the value of a Lisp_Object as a signed integer.  */
 static inline EMACS_INT
-XINT (Lisp_Object a)
+(XINT) (Lisp_Object a)
 {
   EMACS_INT i = XLI (a);
   return (USE_LSB_TAG ? i : i << INTTYPEBITS) >> INTTYPEBITS;
@@ -416,7 +472,7 @@
 /* Like XINT (A), but may be faster.  A must be nonnegative.  This takes
    advantage of the fact that Lisp integers have zero-bits in their tags.  */
 static inline EMACS_INT
-XFASTINT (Lisp_Object a)
+(XFASTINT) (Lisp_Object a)
 {
   EMACS_INT n = USE_LSB_TAG ? XINT (a) : XLI (a) >> INTTYPEBITS;
   eassert (0 <= n);
@@ -432,7 +488,7 @@
 }
 
 static inline Lisp_Object
-make_number (EMACS_INT n)
+(make_number) (EMACS_INT n)
 {
   return XIL (USE_LSB_TAG ? n << INTTYPEBITS : n & INTMASK);
 }
@@ -446,7 +502,7 @@
 }
 
 static inline void *
-XPNTR (Lisp_Object a)
+(XPNTR) (Lisp_Object a)
 {
   intptr_t i = (XLI (a) & VALMASK) | DATA_SEG_BITS;
   return (void *) i;
@@ -455,7 +511,7 @@
 /* Extract the pointer value of the Lisp object A, under the
    assumption that A's type is TYPE.  */
 static inline void *
-XUNTAG (Lisp_Object a, int type)
+(XUNTAG) (Lisp_Object a, int type)
 {
   if (USE_LSB_TAG)
     {
@@ -466,7 +522,7 @@
 }
 
 static inline int
-EQ (Lisp_Object a, Lisp_Object b)
+(EQ) (Lisp_Object a, Lisp_Object b)
 {
   return XHASH (a) == XHASH (b);
 }
@@ -503,14 +559,14 @@
 static int BUFFERP (Lisp_Object);
 static int CHAR_TABLE_P (Lisp_Object);
 static Lisp_Object CHAR_TABLE_REF_ASCII (Lisp_Object, ptrdiff_t);
-static int CONSP (Lisp_Object);
-static int FLOATP (Lisp_Object);
-static int INTEGERP (Lisp_Object);
+static int (CONSP) (Lisp_Object);
+static int (FLOATP) (Lisp_Object);
+static int (INTEGERP) (Lisp_Object);
 static int INTFWDP (union Lisp_Fwd *);
 static int KBOARD_OBJFWDP (union Lisp_Fwd *);
-static int MARKERP (Lisp_Object);
-static int MISCP (Lisp_Object);
-static int NILP (Lisp_Object);
+static int (MARKERP) (Lisp_Object);
+static int (MISCP) (Lisp_Object);
+static int (NILP) (Lisp_Object);
 static int OBJFWDP (union Lisp_Fwd *);
 static int OVERLAYP (Lisp_Object);
 static int PROCESSP (Lisp_Object);
@@ -519,8 +575,8 @@
 static int STRINGP (Lisp_Object);
 static int SUB_CHAR_TABLE_P (Lisp_Object);
 static int SUBRP (Lisp_Object);
-static int SYMBOLP (Lisp_Object);
-static int VECTORLIKEP (Lisp_Object);
+static int (SYMBOLP) (Lisp_Object);
+static int (VECTORLIKEP) (Lisp_Object);
 static int WINDOWP (Lisp_Object);
 
 /* Defined in buffer.c.  */
@@ -561,7 +617,7 @@
 /* Extract a value or address from a Lisp_Object.  */
 
 static inline struct Lisp_Cons *
-XCONS (Lisp_Object a)
+(XCONS) (Lisp_Object a)
 {
   eassert (CONSP (a));
   return XUNTAG (a, Lisp_Cons);
@@ -582,7 +638,7 @@
 }
 
 static inline struct Lisp_Symbol *
-XSYMBOL (Lisp_Object a)
+(XSYMBOL) (Lisp_Object a)
 {
   eassert (SYMBOLP (a));
   return XUNTAG (a, Lisp_Symbol);
@@ -717,7 +773,7 @@
 /* Type checking.  */
 
 static inline void
-CHECK_TYPE (int ok, Lisp_Object Qxxxp, Lisp_Object x)
+(CHECK_TYPE) (int ok, Lisp_Object Qxxxp, Lisp_Object x)
 {
   if (!ok)
     wrong_type_argument (Qxxxp, x);
@@ -773,8 +829,8 @@
 #endif
 
 /* Use these from normal code.  */
-static inline Lisp_Object XCAR (Lisp_Object c) { return XCAR_AS_LVALUE (c); }
-static inline Lisp_Object XCDR (Lisp_Object c) { return XCDR_AS_LVALUE (c); }
+static inline Lisp_Object (XCAR) (Lisp_Object c) { return XCAR_AS_LVALUE (c); }
+static inline Lisp_Object (XCDR) (Lisp_Object c) { return XCDR_AS_LVALUE (c); }
 
 /* Use these to set the fields of a cons cell.
 
@@ -1276,7 +1332,7 @@
 /* Value is name of symbol.  */
 
 static inline Lisp_Object
-SYMBOL_VAL (struct Lisp_Symbol *sym)
+(SYMBOL_VAL) (struct Lisp_Symbol *sym)
 {
   eassert (sym->redirect == SYMBOL_PLAINVAL);
   return sym->val.value;
@@ -1300,7 +1356,7 @@
   return sym->val.fwd;
 }
 static inline void
-SET_SYMBOL_VAL (struct Lisp_Symbol *sym, Lisp_Object v)
+(SET_SYMBOL_VAL) (struct Lisp_Symbol *sym, Lisp_Object v)
 {
   eassert (sym->redirect == SYMBOL_PLAINVAL);
   sym->val.value = v;
@@ -1351,7 +1407,7 @@
    whose value can be set to the keyword symbol itself).  */
 
 static inline int
-SYMBOL_CONSTANT_P (Lisp_Object sym)
+(SYMBOL_CONSTANT_P) (Lisp_Object sym)
 {
   return XSYMBOL (sym)->constant;
 }
@@ -1915,7 +1971,7 @@
 /* Data type checking */
 
 static inline int
-NILP (Lisp_Object x)
+(NILP) (Lisp_Object x)
 {
   return EQ (x, Qnil);
 }
@@ -1942,18 +1998,22 @@
    && (TYPE_SIGNED (type) ? TYPE_MINIMUM (type) <= XINT (x) : 0 <= XINT (x)) \
    && XINT (x) <= TYPE_MAXIMUM (type))
 
-static inline int CONSP (Lisp_Object x) { return XTYPE (x) == Lisp_Cons; }
-static inline int FLOATP (Lisp_Object x) { return XTYPE (x) == Lisp_Float; }
-static inline int MISCP (Lisp_Object x) { return XTYPE (x) == Lisp_Misc; }
+static inline int (CONSP) (Lisp_Object x) { return XTYPE (x) == Lisp_Cons; }
+static inline int (FLOATP) (Lisp_Object x) { return XTYPE (x) == Lisp_Float; }
+static inline int (MISCP) (Lisp_Object x) { return XTYPE (x) == Lisp_Misc; }
 static inline int STRINGP (Lisp_Object x) { return XTYPE (x) == Lisp_String; }
-static inline int SYMBOLP (Lisp_Object x) { return XTYPE (x) == Lisp_Symbol; }
-static inline int
-INTEGERP (Lisp_Object x)
+static inline int
+(SYMBOLP) (Lisp_Object x)
+{
+  return XTYPE (x) == Lisp_Symbol;
+}
+static inline int
+(INTEGERP) (Lisp_Object x)
 {
   return LISP_INT_TAG_P (XTYPE (x));
 }
 static inline int
-VECTORLIKEP (Lisp_Object x)
+(VECTORLIKEP) (Lisp_Object x)
 {
   return XTYPE (x) == Lisp_Vectorlike;
 }
@@ -1968,7 +2028,7 @@
   return MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay;
 }
 static inline int
-MARKERP (Lisp_Object x)
+(MARKERP) (Lisp_Object x)
 {
   return MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker;
 }
@@ -2123,7 +2183,7 @@
   CHECK_TYPE (CONSP (x) || NILP (x), Qlistp, x);
 }
 static inline void
-CHECK_LIST_CONS (Lisp_Object x, Lisp_Object y)
+(CHECK_LIST_CONS) (Lisp_Object x, Lisp_Object y)
 {
   CHECK_TYPE (CONSP (x), Qlistp, y);
 }
@@ -2148,7 +2208,7 @@
   CHECK_TYPE (CONSP (x), Qconsp, x);
 }
 static inline void
-CHECK_SYMBOL (Lisp_Object x)
+(CHECK_SYMBOL) (Lisp_Object x)
 {
   CHECK_TYPE (SYMBOLP (x), Qsymbolp, x);
 }
@@ -2203,7 +2263,7 @@
   CHECK_TYPE (SUBRP (x), Qsubrp, x);
 }
 static inline void
-CHECK_NUMBER (Lisp_Object x)
+(CHECK_NUMBER) (Lisp_Object x)
 {
   CHECK_TYPE (INTEGERP (x), Qintegerp, x);
 }