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

From: Paul Eggert <[email-masked]>
Date: Mon, 23 Jul 2012 19:20:07 -0700

On 07/16/2012 08:04 PM, Eli Zaretskii wrote:
> we need a facility for doing this
> only with a few functions that affect performance.

It turns out that when compiling with -O0, always_inline
functions are often slower than macros, as the inlined code
also contains unnecessary instructions to copy arguments and
results.  So instead of using always_inline, it's better to
do this performance-critical inlining by hand.  I did that
(patch relative to trunk bzr 109195 attached), inlining
enough so that CPU performance improved by 8.7% compared to
the current trunk, when compiled with gcc -O0.  (This is the
same benchmark as before, on x86-64 with GCC 4.7.1.)  The
performance win is because I inlined a bit more cleverly
than the current code does.

Like the earlier version, this patch should improve
performance slightly in the default-optimization case too,
since this patch is identical to the earlier one when
default optimization is used.

In short, it should take only a relatively small amount of
hand-inlining to address the -O0 performance issue.

=== modified file 'ChangeLog'
--- ChangeLog	2012-07-17 07:30:25 +0000
+++ ChangeLog	2012-07-24 02:00:33 +0000
@@ -1,3 +1,9 @@
+2012-07-24  Paul Eggert  <[email-masked]>
+
+	Use functions, not macros, for XINT etc. (Bug#11935).
+	* configure.ac (WARN_CFLAGS): Remove -Wbad-function-cast,
+	as it generates bogus warnings about reasonable casts of calls.
+
 2012-07-17  Dmitry Antipov  <[email-masked]>
 
 	Fix toolkit configuration report.

=== modified file 'configure.ac'
--- configure.ac	2012-07-17 07:30:25 +0000
+++ configure.ac	2012-07-17 16:27:20 +0000
@@ -675,6 +675,7 @@
   nw="$nw -Winline"                 # OK to ignore 'inline'
   nw="$nw -Wsync-nand"              # irrelevant here, and provokes ObjC warning
   nw="$nw -Wunsafe-loop-optimizations" # OK to suppress unsafe optimizations
+  nw="$nw -Wbad-function-cast"      # These casts are no worse than others.
 
   # Emacs doesn't care about shadowing; see
   # <http://lists.gnu.org/archive/html/emacs-diffs/2011-11/msg00265.html>.

=== modified file 'src/ChangeLog'
--- src/ChangeLog	2012-07-23 16:57:20 +0000
+++ src/ChangeLog	2012-07-24 02:00:33 +0000
@@ -1,3 +1,132 @@
+2012-07-24  Paul Eggert  <[email-masked]>
+
+	Use functions, not macros, for XINT etc. (Bug#11935).
+	In lisp.h, prefer functions to function-like macros, and
+	constants to object-like macros, when either will do.  This:
+	 . makes the code easier to debug, as the symbols are visible to GDB.
+	 . simplifies use, as there's no more need to worry about
+	   arguments' side effects being evaluated multiple times.
+	 . shrinks the size of Emacs's text segment by 0.5%
+	   on my platform (x86-64, GCC 4.7.1).
+	* buffer.c (Qoverlap):
+	* data.c (Qsubrp):
+	* fns.c (Qhash_table_p):
+	Now extern, so lisp.h can use these symbols.
+	* dispextern.h: Include character.h, for MAX_CHAR etc.
+	(GLYPH, GLYPH_CHAR, GLYPH_FACE, SET_GLYPH_CHAR, SET_GLYPH_FACE)
+	(SET_GLYPH, GLYPH_CODE_CHAR, GLYPH_CODE_FACE)
+	(SET_GLYPH_FROM_GLYPH_CODE, GLYPH_MODE_LINE_FACE, GLYPH_CHAR_VALID_P)
+	(GLYPH_CODE_P): Move here from lisp.h.
+	(GLYPH_CHAR, GLYPH_FACE, GLYPH_CODE_CHAR, GLYPH_CODE_FACE)
+	(GLYPH_CHAR_VALID_P, GLYPH_CODE_P): Now functions, not macros.
+	(GLYPH_MODE_LINE_FACE): Now enums, not macros.
+	* eval.c (Fautoload): Cast XUNTAG output to intptr_t, since
+	XUNTAG now returns void *.
+	* 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.
+	(CHECK_CONS_LIST, LISP_INT_TAG_P, XLI, XIL, XHASH, XTYPE)
+	(XINT, XFASTINT, XUINT, make_number, XPNTR, XUNTAG, EQ, XCONS, XVECTOR)
+	(XSTRING, XSYMBOL, XFLOAT, XPROCESS, XWINDOW, XTERMINAL, XSUBR)
+	(XBUFFER, XCHAR_TABLE, XSUB_CHAR_TABLE, XBOOL_VECTOR, CHECK_TYPE)
+	(CHECK_STRING_OR_BUFFER, XCAR, XCDR, XSETCAR, XSETCDR, CAR, CDR)
+	(CAR_SAFE, CDR_SAFE, STRING_MULTIBYTE, STRING_INTERVALS)
+	(STRING_SET_INTERVALS, SDATA, SSDATA, SREF, SSET, SCHARS)
+	(STRING_BYTES, SBYTES, STRING_SET_CHARS, ASIZE, ASET)
+	(CHAR_TABLE_EXTRA_SLOTS, CHAR_TABLE_REF_ASCII, CHAR_TABLE_REF)
+	(CHAR_TABLE_TRANSLATE, CHAR_TABLE_SET, SYMBOL_VAL, SYMBOL_ALIAS)
+	(SYMBOL_BLV, SYMBOL_FWD, SET_SYMBOL_VAL, SET_SYMBOL_ALIAS)
+	(SET_SYMBOL_BLV, SET_SYMBOL_FWD, SYMBOL_NAME, SYMBOL_INTERNED_P)
+	(SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P, SYMBOL_CONSTANT_P)
+	(XHASH_TABLE, HASH_TABLE_P, CHECK_HASH_TABLE, HASH_TABLE_SIZE)
+	(XMISC, XMISCANY, XMARKER, XOVERLAY, XSAVE_VALUE, XSETMISCTYPE)
+	(BLV_FOUND, SET_BLV_FOUND, BLV_VALUE, SET_BLV_VALUE, XFWDTYPE)
+	(XINTFWD, XBOOLFWD, XOBJFWD, XBUFFER_OBJFWD, XKBOARD_OBJFWD)
+	(XFLOAT_DATA, XFLOAT_INIT, NILP, NUMBERP, NATNUMP)
+	(RANGED_INTEGERP, CONSP, FLOATP, MISCP, STRINGP, SYMBOLP)
+	(INTEGERP, VECTORLIKEP, VECTORP, OVERLAYP)
+	(MARKERP, SAVE_VALUEP, INTFWDP, BOOLFWDP, OBJFWDP)
+	(BUFFER_OBJFWDP, KBOARD_OBJFWDP)
+	(PSEUDOVECTORP, WINDOW_CONFIGURATIONP, PROCESSP, WINDOWP)
+	(TERMINALP, SUBRP, COMPILEDP, BUFFERP, CHAR_TABLE_P)
+	(SUB_CHAR_TABLE_P, BOOL_VECTOR_P, FRAMEP, IMAGEP, ARRAYP)
+	(CHECK_LIST, CHECK_LIST_CONS, CHECK_LIST_END, CHECK_STRING)
+	(CHECK_STRING_CAR, CHECK_CONS, CHECK_SYMBOL, CHECK_CHAR_TABLE)
+	(CHECK_VECTOR, CHECK_VECTOR_OR_STRING, CHECK_ARRAY)
+	(CHECK_VECTOR_OR_CHAR_TABLE, CHECK_BUFFER, CHECK_WINDOW)
+	(CHECK_WINDOW_CONFIGURATION, CHECK_PROCESS, CHECK_SUBR)
+	(CHECK_NUMBER, CHECK_NATNUM, CHECK_MARKER, XFLOATINT)
+	(CHECK_FLOAT, CHECK_NUMBER_OR_FLOAT, CHECK_OVERLAY)
+	(CHECK_NUMBER_CAR, CHECK_NUMBER_CDR, CHECK_NATNUM_CAR)
+	(CHECK_NATNUM_CDR, FUNCTIONP, SPECPDL_INDEX, LOADHIST_ATTACH)
+	(IS_DIRECTORY_SEP, IS_DEVICE_SEP, IS_ANY_SEP):
+	Now static inline functions.
+	(PSEUDOVECTOR_SIZE_TYPEP) New static inline function, replacing ...
+	(PSEUDOVECTOR_TYPEP): Remove macro.  All uses changed to the new API.
+	(check_cons_list) [!GC_CHECK_CONS_LIST]: New empty function.
+	(EMACS_INT, EMACS_UINT): Now typedefs, not macros.
+	(VALBITS, INTTYPEBITS, FIXNUM_BITS, LISP_INT_TAG)
+	(PSEUDOVECTOR_SIZE_BITS, PSEUDOVECTOR_SIZE_MASK, PVEC_TYPE_MASK)
+	(BOOL_VECTOR_BITS_PER_CHAR, CHAR_TABLE_STANDARD_SLOTS)
+	(CHARTAB_SIZE_BITS_0, CHARTAB_SIZE_BITS_1)
+	(CHARTAB_SIZE_BITS_2, CHARTAB_SIZE_BITS_3, DEFAULT_HASH_SIZE)
+	(COMPILED_ARGLIST, COMPILED_BYTECODE, COMPILED_CONSTANTS)
+	(COMPILED_STACK_DEPTH, COMPILED_DOC_STRING, COMPILED_INTERACTIVE)
+	(CHAR_ALT, CHAR_SUPER, CHAR_HYPER, CHAR_SHIFT, CHAR_CTL, CHAR_META)
+	(CHAR_MODIFIER_MASK, MANY, UNEVALLED, FLOAT_TO_STRING_BUFSIZE):
+	(DIRECTORY_SEP, MAX_ALLOCA):
+	Now constants, not macros.
+	(LISP_INT1_TAG, LISP_STRING_TAG, LISP_MAKE_RVALUE, TYPEMASK):
+	Remove; no longer needed.
+	(DATA_SEG_BITS): Default to 0, as this simplifies the rest of the code.
+	(VALMASK): Define in one place rather than in two, merging the
+	USE_LSB_TAG parts; this is simpler.
+	(MOST_POSITIVE_FIXNUM, MOST_NEGATIVE_FIXNUM, max, min)
+	(struct Lisp_String, UNSIGNED_CMP, ASCII_CHAR_P):
+	Move up, to avoid use before definition.
+	Also include "globals.h" earlier, for the same reason.
+	(make_natnum, xtag): New functions.
+	(XUNTAG): Now returns void *, not intptr_t, as this means fewer casts.
+	(union Lisp_Fwd, BOOLFWDP, BOOL_VECTOR_P, BUFFER_OBJFWDP, BUFFERP)
+	(CHAR_TABLE_P, CHAR_TABLE_REF_ASCII, CONSP, FLOATP, INTEGERP, INTFWDP)
+	(KBOARD_OBJFWDP, MARKERP, MISCP, NILP, OBJFWDP, OVERLAYP, PROCESSP)
+	(PSEUDOVECTORP, SAVE_VALUEP, STRINGP, SUB_CHAR_TABLE_P, SUBRP, SYMBOLP)
+	(VECTORLIKEP, WINDOWP, Qoverlayp, char_table_ref, char_table_set)
+	(char_table_translate, Qarrayp, Qbufferp, Qbuffer_or_string_p)
+	(Qchar_table_p, Qconsp, Qfloatp, Qintegerp, Qlambda, Qlistp, Qmarkerp)
+	(Qnil, Qnumberp, Qsubrp, Qstringp, Qsymbolp, Qvectorp)
+	(Qvector_or_char_table_p, Qwholenump, Ffboundp, wrong_type_argument)
+	(initialized, Qhash_table_p, extract_float, Qprocessp, Qwindowp)
+	(Qwindow_configuration_p, Qimage): New forward declarations.
+	(XSET): Simplify by rewriting in terms of xtag.
+	(XSETFASTINT): Simplify by rewriting in terms of make_natnum.
+	(STRING_COPYIN): Remove; unused.
+	(GLYPH, GLYPH_CHAR, GLYPH_FACE, SET_GLYPH_CHAR, SET_GLYPH_FACE)
+	(SET_GLYPH, GLYPH_CODE_CHAR, GLYPH_CODE_FACE)
+	(SET_GLYPH_FROM_GLYPH_CODE, GLYPH_MODE_LINE_FACE, GLYPH_CHAR_VALID_P)
+	(GLYPH_CODE_P): Move to dispextern.h, to avoid define-before-use.
+	(TYPE_RANGED_INTEGERP): Simplify.
+	(PSEUDOVECTOR_SIZE_TYPEP): Rename from PSEUDOVECTORP_TYPEP and
+	change the first arg to be a size rather than a pointer,
+	to make it usable as a function.  All uses changed.
+	(Qsubrp, Qhash_table_p, Qoverlayp): New extern decls.
+	(setlocale, fixup_locale, synchronize_system_messages_locale)
+	(synchronize_system_time_locale) [!HAVE_SETLOCALE]:
+	Now empty functions, not macros.
+	* mem-limits.h (EXCEEDS_LISP_PTR) [!defined DATA_SEG_BITS]:
+	Remove, as DATA_SEG_BITS is always defined now, if only to zero.
+	* window.c (Qwindow_configuration_p):
+	Now extern, so window.h can use it.
+	* window.h (Qwindowp): Move decl back to lisp.h.
+	(CHECK_LIVE_WINDOW): Move here from lisp.h, so window.h internals
+	need not be moved to lisp.h.  Now a function, not a macro.
+
 2012-07-23  Eli Zaretskii  <[email-masked]>
 
 	* print.c (print_object): Don't crash when a frame's name is nil

=== modified file 'src/alloc.c'
--- src/alloc.c	2012-07-23 11:15:43 +0000
+++ src/alloc.c	2012-07-23 21:58:10 +0000
@@ -3074,12 +3074,12 @@
    + VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN)
 
 /* Number of bytes used by vector-block-allocated object.  This is the only
-   place where we actually use the `nbytes' field of the vector-header.
-   I.e. we could get rid of the `nbytes' field by computing it based on the
+   place where we actually use the 'size' field of the vector-header.
+   I.e. we could get rid of the 'size' field by computing it based on the
    vector-type.  */
 
 #define PSEUDOVECTOR_NBYTES(vector) \
-  (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE)	\
+  (PSEUDOVECTOR_SIZE_TYPEP (vector->header.size, PVEC_FREE)	\
    ? vector->header.size & PSEUDOVECTOR_SIZE_MASK	\
    : vector->header.next.nbytes)
 
@@ -3171,7 +3171,8 @@
 	      /* All non-bool pseudovectors are small enough to be allocated
 		 from vector blocks.  This code should be redesigned if some
 		 pseudovector type grows beyond VBLOCK_BYTES_MAX.  */
-	      eassert (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR));
+	      eassert (PSEUDOVECTOR_SIZE_TYPEP (vector->header.size,
+						PVEC_BOOL_VECTOR));
 
 	      total_vector_slots
 		+= (bool_header_size
@@ -4392,7 +4393,7 @@
       while (VECTOR_IN_BLOCK (vector, block)
 	     && vector <= (struct Lisp_Vector *) p)
 	{
-	  if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE))
+	  if (PSEUDOVECTOR_SIZE_TYPEP (vector->header.size, PVEC_FREE))
 	    vector = ADVANCE (vector, (vector->header.size
 				       & PSEUDOVECTOR_SIZE_MASK));
 	  else if (vector == p)

=== modified file 'src/buffer.c'
--- src/buffer.c	2012-07-23 11:15:43 +0000
+++ src/buffer.c	2012-07-23 21:50:36 +0000
@@ -139,7 +139,7 @@
 
 static Lisp_Object Qget_file_buffer;
 
-static Lisp_Object Qoverlayp;
+Lisp_Object Qoverlayp;
 
 Lisp_Object Qpriority, Qbefore_string, Qafter_string;

=== modified file 'src/data.c'
--- src/data.c	2012-07-19 22:35:58 +0000
+++ src/data.c	2012-07-23 21:50:36 +0000
@@ -91,7 +91,8 @@
 static Lisp_Object Qcompiled_function, Qframe;
 Lisp_Object Qbuffer;
 static Lisp_Object Qchar_table, Qbool_vector, Qhash_table;
-static Lisp_Object Qsubrp, Qmany, Qunevalled;
+Lisp_Object Qsubrp;
+static Lisp_Object Qmany, Qunevalled;
 Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
 static Lisp_Object Qdefun;

=== modified file 'src/dispextern.h'
--- src/dispextern.h	2012-07-13 03:50:58 +0000
+++ src/dispextern.h	2012-07-13 03:52:53 +0000
@@ -22,6 +22,8 @@
 #ifndef DISPEXTERN_H_INCLUDED
 #define DISPEXTERN_H_INCLUDED
 
+#include "character.h"
+
 #ifdef HAVE_X_WINDOWS
 
 #include <X11/Xlib.h>
@@ -265,6 +267,55 @@
 				Glyphs
  ***********************************************************************/
 
+/* The glyph datatype, used to represent characters on the display.
+   It consists of a char code and a face id.  */
+
+typedef struct {
+  int ch;
+  int face_id;
+} GLYPH;
+
+/* Return a glyph's character code.  */
+static inline int GLYPH_CHAR (GLYPH glyph) { return glyph.ch; }
+
+/* Return a glyph's face ID.  */
+static inline int GLYPH_FACE (GLYPH glyph) { return glyph.face_id; }
+
+#define SET_GLYPH_CHAR(glyph, char) ((glyph).ch = (char))
+#define SET_GLYPH_FACE(glyph, face) ((glyph).face_id = (face))
+#define SET_GLYPH(glyph, char, face) \
+  ((glyph).ch = (char), (glyph).face_id = (face))
+
+/* The following are valid only if GLYPH_CODE_P (gc).  */
+
+static inline int
+GLYPH_CODE_CHAR (Lisp_Object gc)
+{
+  return (CONSP (gc)
+	  ? XINT (XCAR (gc))
+	  : XINT (gc) & MAX_CHAR);
+}
+
+static inline int
+GLYPH_CODE_FACE (Lisp_Object gc)
+{
+  return CONSP (gc) ? XINT (XCDR (gc)) : XINT (gc) >> CHARACTERBITS;
+}
+
+#define SET_GLYPH_FROM_GLYPH_CODE(glyph, gc)				\
+  do									\
+    {									\
+      if (CONSP (gc))							\
+	SET_GLYPH (glyph, XINT (XCAR (gc)), XINT (XCDR (gc)));		\
+      else								\
+	SET_GLYPH (glyph, (XINT (gc) & ((1 << CHARACTERBITS)-1)),	\
+		   (XINT (gc) >> CHARACTERBITS));			\
+    }									\
+  while (0)
+
+/* The ID of the mode line highlighting face.  */
+enum { GLYPH_MODE_LINE_FACE = 1 };
+
 /* Enumeration of glyph types.  Glyph structures contain a type field
    containing one of the enumerators defined here.  */
 
@@ -1763,6 +1814,30 @@
 
 #endif /* not HAVE_WINDOW_SYSTEM */
 
+/* Return 1 if G contains a valid character code.  */
+static inline int
+GLYPH_CHAR_VALID_P (GLYPH g)
+{
+  return CHAR_VALID_P (GLYPH_CHAR (g));
+}
+
+/* The glyph code from a display vector may either be an integer which
+   encodes a char code in the lower CHARACTERBITS bits and a (very small)
+   face-id in the upper bits, or it may be a cons (CHAR . FACE-ID).  */
+
+static inline int
+GLYPH_CODE_P (Lisp_Object gc)
+{
+  return (CONSP (gc)
+	  ? (CHARACTERP (XCAR (gc))
+	     && RANGED_INTEGERP (0, XCDR (gc), MAX_FACE_ID))
+	  : (RANGED_INTEGERP
+	     (0, gc,
+	      (MAX_FACE_ID < TYPE_MAXIMUM (EMACS_INT) >> CHARACTERBITS
+	       ? ((EMACS_INT) MAX_FACE_ID << CHARACTERBITS) | MAX_CHAR
+	       : TYPE_MAXIMUM (EMACS_INT)))));
+}
+
 /* Non-zero means face attributes have been changed since the last
    redisplay.  Used in redisplay_internal.  */

=== modified file 'src/eval.c'
--- src/eval.c	2012-07-20 05:28:00 +0000
+++ src/eval.c	2012-07-23 21:50:36 +0000
@@ -1919,7 +1919,7 @@
        and assumed the docstring will be provided by Snarf-documentation, so it
        passed us 0 instead.  But that leads to accidental sharing in purecopy's
        hash-consing, so we use a (hopefully) unique integer instead.  */
-    docstring = make_number (XUNTAG (function, Lisp_Symbol));
+    docstring = make_number ((intptr_t) XUNTAG (function, Lisp_Symbol));
   return Ffset (function,
 		Fpurecopy (list5 (Qautoload, file, docstring,
 				  interactive, type)));

=== modified file 'src/fns.c'
--- src/fns.c	2012-07-20 07:29:04 +0000
+++ src/fns.c	2012-07-23 21:50:36 +0000
@@ -3354,7 +3354,8 @@
 
 /* Various symbols.  */
 
-static Lisp_Object Qhash_table_p, Qkey, Qvalue;
+Lisp_Object Qhash_table_p;
+static Lisp_Object Qkey, Qvalue;
 Lisp_Object Qeq, Qeql, Qequal;
 Lisp_Object QCtest, QCsize, QCrehash_size, QCrehash_threshold, QCweakness;
 static Lisp_Object Qhash_table_test, Qkey_or_value, Qkey_and_value;

=== modified file 'src/lisp.h'
--- src/lisp.h	2012-07-23 11:15:43 +0000
+++ src/lisp.h	2012-07-24 01:57:18 +0000
@@ -32,10 +32,10 @@
 
 #ifdef GC_CHECK_CONS_LIST
 extern void check_cons_list (void);
-#define CHECK_CONS_LIST() check_cons_list ()
 #else
-#define CHECK_CONS_LIST() ((void) 0)
+static inline void check_cons_list (void) { }
 #endif
+static inline void CHECK_CONS_LIST (void) { check_cons_list (); }
 
 /* Temporarily disable wider-than-pointer integers until they're tested more.
    Build with CFLAGS='-DWIDE_EMACS_INT' to try them out.  */
@@ -45,22 +45,24 @@
    EMACS_INT_MAX - maximum value of EMACS_INT; can be used in #if
    pI - printf length modifier for EMACS_INT
    EMACS_UINT - unsigned variant of EMACS_INT */
-#ifndef EMACS_INT
+#ifndef EMACS_INT_MAX
 # if LONG_MAX < LLONG_MAX && defined WIDE_EMACS_INT
-#  define EMACS_INT long long
+typedef long long int EMACS_INT;
+typedef unsigned long long int EMACS_UINT;
 #  define EMACS_INT_MAX LLONG_MAX
 #  define pI "ll"
 # elif INT_MAX < LONG_MAX
-#  define EMACS_INT long
+typedef long int EMACS_INT;
+typedef unsigned long int EMACS_UINT;
 #  define EMACS_INT_MAX LONG_MAX
 #  define pI "l"
 # else
-#  define EMACS_INT int
+typedef int EMACS_INT;
+typedef unsigned int EMACS_UINT;
 #  define EMACS_INT_MAX INT_MAX
 #  define pI ""
 # endif
 #endif
-#define EMACS_UINT unsigned EMACS_INT
 
 /* Number of bits in some machine integer types.  */
 enum
@@ -153,8 +155,10 @@
    variable VAR of type TYPE with the added requirement that it be
    TYPEBITS-aligned.  */
 
+/* Number of bits in a Lisp_Obect tag.  This can be used in #if.  */
 #define GCTYPEBITS 3
-#define VALBITS (BITS_PER_EMACS_INT - GCTYPEBITS)
+
+enum { VALBITS = BITS_PER_EMACS_INT - GCTYPEBITS };
 
 /* The maximum value that can be stored in a EMACS_INT, assuming all
    bits other than the type bits contribute to a nonnegative signed value.
@@ -210,20 +214,72 @@
 #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.  */
 
 /* Lisp integers use 2 tags, to give them one extra bit, thus
    extending their range from, e.g., -2^28..2^28-1 to -2^29..2^29-1.  */
-#define INTTYPEBITS (GCTYPEBITS - 1)
-#define FIXNUM_BITS (VALBITS + 1)
+enum { INTTYPEBITS = GCTYPEBITS - 1 };
+enum { FIXNUM_BITS = VALBITS + 1 };
 #define INTMASK (EMACS_INT_MAX >> (INTTYPEBITS - 1))
-#define LISP_INT_TAG Lisp_Int0
 #define case_Lisp_Int case Lisp_Int0: case Lisp_Int1
-#define LISP_INT1_TAG (USE_LSB_TAG ? 1 << INTTYPEBITS : 1)
-#define LISP_STRING_TAG (5 - LISP_INT1_TAG)
-#define LISP_INT_TAG_P(x) (((x) & ~LISP_INT1_TAG) == 0)
 
 /* Stolen from GDB.  The only known compiler that doesn't support
    enums in bitfields is MSVC.  */
@@ -238,7 +294,7 @@
   {
     /* Integer.  XINT (obj) is the integer value.  */
     Lisp_Int0 = 0,
-    Lisp_Int1 = LISP_INT1_TAG,
+    Lisp_Int1 = USE_LSB_TAG ? 4 : 1,
 
     /* Symbol.  XSYMBOL (object) points to a struct Lisp_Symbol.  */
     Lisp_Symbol = 2,
@@ -249,7 +305,7 @@
 
     /* String.  XSTRING (object) points to a struct Lisp_String.
        The length of the string, and its contents, are stored therein.  */
-    Lisp_String = LISP_STRING_TAG,
+    Lisp_String = USE_LSB_TAG ? 1 : 4,
 
     /* Vector of Lisp objects, or something resembling it.
        XVECTOR (object) points to a struct Lisp_Vector, which contains
@@ -263,6 +319,11 @@
     Lisp_Float = 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; }
+
 /* 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.
    The enum values are arbitrary, but we'll use large numbers to make it
@@ -297,20 +358,15 @@
 
 typedef struct { EMACS_INT i; } Lisp_Object;
 
-#define XLI(o) (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;
 }
 
-static inline Lisp_Object
-LISP_MAKE_RVALUE (Lisp_Object o)
-{
-    return o;
-}
-
 #define LISP_INITIALLY_ZERO {0}
 
 #else /* CHECK_LISP_OBJECT_TYPE */
@@ -318,9 +374,8 @@
 /* If a struct type is not wanted, define Lisp_Object as just a number.  */
 
 typedef EMACS_INT Lisp_Object;
-#define XLI(o) (o)
-#define XIL(i) (i)
-#define LISP_MAKE_RVALUE(o) (0+(o))
+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 */
 
@@ -368,89 +423,119 @@
    only the number of Lisp_Object fields (that need to be traced by the GC).
    The distinction is used e.g. by Lisp_Process which places extra
    non-Lisp_Object fields at the end of the structure.  */
-#define PSEUDOVECTOR_SIZE_BITS 16
-#define PSEUDOVECTOR_SIZE_MASK ((1 << PSEUDOVECTOR_SIZE_BITS) - 1)
-#define PVEC_TYPE_MASK (0x0fff << PSEUDOVECTOR_SIZE_BITS)
+enum
+  {
+    PSEUDOVECTOR_SIZE_BITS = 16,
+    PSEUDOVECTOR_SIZE_MASK = (1 << PSEUDOVECTOR_SIZE_BITS) - 1,
+    PVEC_TYPE_MASK = 0xfff << PSEUDOVECTOR_SIZE_BITS
+  };
 
 /* Number of bits to put in each character in the internal representation
    of bool vectors.  This should not vary across implementations.  */
-#define BOOL_VECTOR_BITS_PER_CHAR 8
-
-/* These macros extract various sorts of values from a Lisp_Object.
+enum { BOOL_VECTOR_BITS_PER_CHAR = 8 };
+
+/* DATA_SEG_BITS forces extra bits to be or'd in with any pointers
+   which were stored in a Lisp_Object */
+#ifndef DATA_SEG_BITS
+# define DATA_SEG_BITS 0
+#endif
+
+/* These functions extract various sorts of values from a Lisp_Object.
  For example, if tem is a Lisp_Object whose type is Lisp_Cons,
  XCONS (tem) is the struct Lisp_Cons * pointing to the memory for that cons.  */
 
 /* Return a perfect hash of the Lisp_Object representation.  */
-#define XHASH(a) XLI (a)
-
-#if USE_LSB_TAG
-
-#define TYPEMASK ((1 << GCTYPEBITS) - 1)
-#define XTYPE(a) ((enum Lisp_Type) (XLI (a) & TYPEMASK))
-#define XINT(a) (XLI (a) >> INTTYPEBITS)
-#define XUINT(a) ((EMACS_UINT) XLI (a) >> INTTYPEBITS)
-#define make_number(N) XIL ((EMACS_INT) (N) << INTTYPEBITS)
-#define XSET(var, type, ptr)						   \
-  (eassert (XTYPE (XIL ((intptr_t) (ptr))) == 0), /* Check alignment.  */  \
-   (var) = XIL ((type) | (intptr_t) (ptr)))
-
-#define XPNTR(a) ((intptr_t) (XLI (a) & ~TYPEMASK))
-#define XUNTAG(a, type) ((intptr_t) (XLI (a) - (type)))
-
-#else  /* not USE_LSB_TAG */
-
-#define VALMASK VAL_MAX
-
-#define XTYPE(a) ((enum Lisp_Type) ((EMACS_UINT) XLI (a) >> VALBITS))
-
-/* For integers known to be positive, XFASTINT provides fast retrieval
-   and XSETFASTINT provides fast storage.  This takes advantage of the
-   fact that Lisp integers have zero-bits in their tags.  */
-#define XFASTINT(a) (XLI (a) + 0)
-#define XSETFASTINT(a, b) ((a) = XIL (b))
-
-/* Extract the value of a Lisp_Object as a (un)signed integer.  */
-
-#define XINT(a) (XLI (a) << INTTYPEBITS >> INTTYPEBITS)
-#define XUINT(a) ((EMACS_UINT) (XLI (a) & INTMASK))
-#define make_number(N) XIL ((EMACS_INT) (N) & INTMASK)
-
-#define XSET(var, type, ptr)				      \
-  ((var) = XIL ((EMACS_INT) ((EMACS_UINT) (type) << VALBITS)  \
-		+ ((intptr_t) (ptr) & VALMASK)))
-
-#ifdef DATA_SEG_BITS
-/* DATA_SEG_BITS forces extra bits to be or'd in with any pointers
-   which were stored in a Lisp_Object */
-#define XPNTR(a) ((uintptr_t) ((XLI (a) & VALMASK)) | DATA_SEG_BITS))
-#else
-#define XPNTR(a) ((uintptr_t) (XLI (a) & VALMASK))
-#endif
-
-#endif /* not USE_LSB_TAG */
-
-/* For integers known to be positive, XFASTINT sometimes provides
-   faster retrieval and XSETFASTINT provides faster storage.
-   If not, fallback on the non-accelerated path.  */
-#ifndef XFASTINT
-# define XFASTINT(a) (XINT (a))
-# define XSETFASTINT(a, b) (XSETINT (a, b))
-#endif
-
-/* Extract the pointer value of the Lisp object A, under the
-   assumption that A's type is TYPE.  This is a fallback
-   implementation if nothing faster is available.  */
-#ifndef XUNTAG
-# define XUNTAG(a, type) XPNTR (a)
-#endif
-
-#define EQ(x, y) (XHASH (x) == XHASH (y))
+static inline EMACS_INT (XHASH) (Lisp_Object o) { return XLI (o); }
+
+#define VALMASK (USE_LSB_TAG ? - (1 << GCTYPEBITS) : VAL_MAX)
 
 /* Largest and smallest representable fixnum values.  These are the C
    values.  */
 #define MOST_POSITIVE_FIXNUM (EMACS_INT_MAX >> INTTYPEBITS)
 #define MOST_NEGATIVE_FIXNUM (-1 - MOST_POSITIVE_FIXNUM)
 
+static inline enum Lisp_Type
+(XTYPE) (Lisp_Object a)
+{
+  EMACS_UINT i = XLI (a);
+  return USE_LSB_TAG ? i & ~VALMASK : i >> VALBITS;
+}
+
+/* Extract the value of a Lisp_Object as a signed integer.  */
+static inline EMACS_INT
+(XINT) (Lisp_Object a)
+{
+  EMACS_INT i = XLI (a);
+  return (USE_LSB_TAG ? i : i << INTTYPEBITS) >> INTTYPEBITS;
+}
+
+/* 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)
+{
+  EMACS_INT n = USE_LSB_TAG ? XINT (a) : XLI (a) >> INTTYPEBITS;
+  eassert (0 <= n);
+  return n;
+}
+
+/* Extract the value of a Lisp_Object as an unsigned integer.  */
+static inline EMACS_UINT
+XUINT (Lisp_Object a)
+{
+  EMACS_UINT i = XLI (a);
+  return USE_LSB_TAG ? i >> INTTYPEBITS : i & INTMASK;
+}
+
+static inline Lisp_Object
+(make_number) (EMACS_INT n)
+{
+  return XIL (USE_LSB_TAG ? n << INTTYPEBITS : n & INTMASK);
+}
+
+/* Like make_number (N), but may be faster.  N must be in nonnegative range.  */
+static inline Lisp_Object
+make_natnum (EMACS_INT n)
+{
+  eassert (0 <= n && n <= MOST_POSITIVE_FIXNUM);
+  return USE_LSB_TAG ? make_number (n) : XIL (n);
+}
+
+static inline void *
+(XPNTR) (Lisp_Object a)
+{
+  intptr_t i = (XLI (a) & VALMASK) | DATA_SEG_BITS;
+  return (void *) i;
+}
+
+/* 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)
+{
+  if (USE_LSB_TAG)
+    {
+      intptr_t i = XLI (a) - type;
+      return (void *) i;
+    }
+  return XPNTR (a);
+}
+
+static inline int
+(EQ) (Lisp_Object a, Lisp_Object b)
+{
+  return XHASH (a) == XHASH (b);
+}
+
+/* The ubiquitous min and max macros.  */
+
+#ifdef max
+#undef max
+#undef min
+#endif
+#define min(a, b)	((a) < (b) ? (a) : (b))
+#define max(a, b)	((a) > (b) ? (a) : (b))
+
 /* Value is non-zero if I doesn't fit into a Lisp fixnum.  It is
    written this way so that it also works if I is of unsigned
    type or if I is a NaN.  */
@@ -463,64 +548,181 @@
 {
   return num < lower ? lower : num <= upper ? num : upper;
 }
+
+/* Forward declarations.  */
+
+/* Defined in this file.  */
+union Lisp_Fwd;
+static int BOOLFWDP (union Lisp_Fwd *);
+static int BOOL_VECTOR_P (Lisp_Object);
+static int BUFFER_OBJFWDP (union Lisp_Fwd *);
+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 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 OBJFWDP (union Lisp_Fwd *);
+static int OVERLAYP (Lisp_Object);
+static int PROCESSP (Lisp_Object);
+static int PSEUDOVECTORP (Lisp_Object, int);
+static int SAVE_VALUEP (Lisp_Object);
+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 WINDOWP (Lisp_Object);
+
+/* Defined in buffer.c.  */
+extern Lisp_Object Qoverlayp;
+
+/* Defined in chartab.c.  */
+extern Lisp_Object char_table_ref (Lisp_Object, int);
+extern Lisp_Object char_table_set (Lisp_Object, int, Lisp_Object);
+extern int char_table_translate (Lisp_Object, int);
+
+/* Defined in data.c.  */
+extern Lisp_Object Qarrayp, Qbufferp, Qbuffer_or_string_p, Qchar_table_p;
+extern Lisp_Object Qconsp, Qfloatp, Qintegerp, Qlambda, Qlistp, Qmarkerp, Qnil;
+extern Lisp_Object Qnumberp, Qsubrp, Qstringp, Qsymbolp, Qvectorp;
+extern Lisp_Object Qvector_or_char_table_p, Qwholenump;
+extern Lisp_Object Ffboundp (Lisp_Object);
+extern _Noreturn Lisp_Object wrong_type_argument (Lisp_Object, Lisp_Object);
+
+/* Defined in emacs.c.  */
+extern int initialized;
+
+/* Defined in fns.c  */
+extern Lisp_Object Qhash_table_p;
+
+/* Defined in floatfns.c.  */
+extern double extract_float (Lisp_Object);
+
+/* Defined in process.c.  */
+extern Lisp_Object Qprocessp;
+
+/* Defined in window.c.  */
+extern Lisp_Object Qwindowp, Qwindow_configuration_p;
+
+/* Defined in xdisp.c.  */
+extern Lisp_Object Qimage;
+
 
 /* Extract a value or address from a Lisp_Object.  */
 
-#define XCONS(a)   (eassert (CONSP (a)), \
-		    (struct Lisp_Cons *) XUNTAG (a, Lisp_Cons))
-#define XVECTOR(a) (eassert (VECTORLIKEP (a)), \
-		    (struct Lisp_Vector *) XUNTAG (a, Lisp_Vectorlike))
-#define XSTRING(a) (eassert (STRINGP (a)), \
-		    (struct Lisp_String *) XUNTAG (a, Lisp_String))
-#define XSYMBOL(a) (eassert (SYMBOLP (a)), \
-		    (struct Lisp_Symbol *) XUNTAG (a, Lisp_Symbol))
-#define XFLOAT(a)  (eassert (FLOATP (a)), \
-		    (struct Lisp_Float *) XUNTAG (a, Lisp_Float))
-
-/* Misc types.  */
-
-#define XMISC(a)	((union Lisp_Misc *) XUNTAG (a, Lisp_Misc))
-#define XMISCANY(a)	(eassert (MISCP (a)), &(XMISC (a)->u_any))
-#define XMISCTYPE(a)   (XMISCANY (a)->type)
-#define XMARKER(a)	(eassert (MARKERP (a)), &(XMISC (a)->u_marker))
-#define XOVERLAY(a)	(eassert (OVERLAYP (a)), &(XMISC (a)->u_overlay))
-#define XSAVE_VALUE(a)	(eassert (SAVE_VALUEP (a)), &(XMISC (a)->u_save_value))
-
-/* Forwarding object types.  */
-
-#define XFWDTYPE(a)     (a->u_intfwd.type)
-#define XINTFWD(a)	(eassert (INTFWDP (a)), &((a)->u_intfwd))
-#define XBOOLFWD(a)	(eassert (BOOLFWDP (a)), &((a)->u_boolfwd))
-#define XOBJFWD(a)	(eassert (OBJFWDP (a)), &((a)->u_objfwd))
-#define XBUFFER_OBJFWD(a) \
-  (eassert (BUFFER_OBJFWDP (a)), &((a)->u_buffer_objfwd))
-#define XKBOARD_OBJFWD(a) \
-  (eassert (KBOARD_OBJFWDP (a)), &((a)->u_kboard_objfwd))
+static inline struct Lisp_Cons *
+(XCONS) (Lisp_Object a)
+{
+  eassert (CONSP (a));
+  return XUNTAG (a, Lisp_Cons);
+}
+
+static inline struct Lisp_Vector *
+XVECTOR (Lisp_Object a)
+{
+  eassert (VECTORLIKEP (a));
+  return XUNTAG (a, Lisp_Vectorlike);
+}
+
+static inline struct Lisp_String *
+XSTRING (Lisp_Object a)
+{
+  eassert (STRINGP (a));
+  return XUNTAG (a, Lisp_String);
+}
+
+static inline struct Lisp_Symbol *
+(XSYMBOL) (Lisp_Object a)
+{
+  eassert (SYMBOLP (a));
+  return XUNTAG (a, Lisp_Symbol);
+}
+
+static inline struct Lisp_Float *
+XFLOAT (Lisp_Object a)
+{
+  eassert (FLOATP (a));
+  return XUNTAG (a, Lisp_Float);
+}
 
 /* Pseudovector types.  */
 
-#define XPROCESS(a) (eassert (PROCESSP (a)), \
-		     (struct Lisp_Process *) XUNTAG (a, Lisp_Vectorlike))
-#define XWINDOW(a) (eassert (WINDOWP (a)), \
-		    (struct window *) XUNTAG (a, Lisp_Vectorlike))
-#define XTERMINAL(a) (eassert (TERMINALP (a)), \
-		      (struct terminal *) XUNTAG (a, Lisp_Vectorlike))
-#define XSUBR(a) (eassert (SUBRP (a)), \
-		  (struct Lisp_Subr *) XUNTAG (a, Lisp_Vectorlike))
-#define XBUFFER(a) (eassert (BUFFERP (a)), \
-		    (struct buffer *) XUNTAG (a, Lisp_Vectorlike))
-#define XCHAR_TABLE(a) (eassert (CHAR_TABLE_P (a)), \
-			(struct Lisp_Char_Table *) XUNTAG (a, Lisp_Vectorlike))
-#define XSUB_CHAR_TABLE(a) (eassert (SUB_CHAR_TABLE_P (a)), \
-			    ((struct Lisp_Sub_Char_Table *) \
-			     XUNTAG (a, Lisp_Vectorlike)))
-#define XBOOL_VECTOR(a) (eassert (BOOL_VECTOR_P (a)), \
-			 ((struct Lisp_Bool_Vector *) \
-			  XUNTAG (a, Lisp_Vectorlike)))
+static inline struct Lisp_Process *
+XPROCESS (Lisp_Object a)
+{
+  eassert (PROCESSP (a));
+  return XUNTAG (a, Lisp_Vectorlike);
+}
+
+static inline struct window *
+XWINDOW (Lisp_Object a)
+{
+  eassert (WINDOWP (a));
+  return XUNTAG (a, Lisp_Vectorlike);
+}
+
+static inline struct terminal *
+XTERMINAL (Lisp_Object a)
+{
+  return XUNTAG (a, Lisp_Vectorlike);
+}
+
+static inline struct Lisp_Subr *
+XSUBR (Lisp_Object a)
+{
+  eassert (SUBRP (a));
+  return XUNTAG (a, Lisp_Vectorlike);
+}
+
+static inline struct buffer *
+XBUFFER (Lisp_Object a)
+{
+  eassert (BUFFERP (a));
+  return XUNTAG (a, Lisp_Vectorlike);
+}
+
+static inline struct Lisp_Char_Table *
+XCHAR_TABLE (Lisp_Object a)
+{
+  eassert (CHAR_TABLE_P (a));
+  return XUNTAG (a, Lisp_Vectorlike);
+}
+
+static inline struct Lisp_Sub_Char_Table *
+XSUB_CHAR_TABLE (Lisp_Object a)
+{
+  eassert (SUB_CHAR_TABLE_P (a));
+  return XUNTAG (a, Lisp_Vectorlike);
+}
+
+static inline struct Lisp_Bool_Vector *
+XBOOL_VECTOR (Lisp_Object a)
+{
+  eassert (BOOL_VECTOR_P (a));
+  return XUNTAG (a, Lisp_Vectorlike);
+}
 
 /* Construct a Lisp_Object from a value or address.  */
 
+static inline Lisp_Object
+xtag (enum Lisp_Type type, void *ptr)
+{
+  EMACS_UINT utype = type;
+  EMACS_INT typebits = USE_LSB_TAG ? type : utype << VALBITS;
+  Lisp_Object a = XIL (typebits | (intptr_t) ptr);
+  eassert (XUNTAG (a, type) == ptr);  /* Check alignment.  */
+  return a;
+}
+
+#define XSET(var, type, ptr) ((var) = xtag (type, ptr))
 #define XSETINT(a, b) (a) = make_number (b)
+#define XSETFASTINT(a, b) ((a) = make_natnum (b))
 #define XSETCONS(a, b) XSET (a, Lisp_Cons, b)
 #define XSETVECTOR(a, b) XSET (a, Lisp_Vectorlike, b)
 #define XSETSTRING(a, b) XSET (a, Lisp_String, b)
@@ -568,48 +770,25 @@
 #define XSETBOOL_VECTOR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BOOL_VECTOR))
 #define XSETSUB_CHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUB_CHAR_TABLE))
 
-/* Convenience macros for dealing with Lisp arrays.  */
-
-#define AREF(ARRAY, IDX)	XVECTOR ((ARRAY))->contents[IDX]
-#define ASIZE(ARRAY)		XVECTOR ((ARRAY))->header.size
-/* The IDX==IDX tries to detect when the macro argument is side-effecting.  */
-#define ASET(ARRAY, IDX, VAL)	\
-  (eassert ((IDX) == (IDX)),				\
-   eassert ((IDX) >= 0 && (IDX) < ASIZE (ARRAY)),	\
-   AREF ((ARRAY), (IDX)) = (VAL))
-
-/* Convenience macros for dealing with Lisp strings.  */
-
-#define SDATA(string)		(XSTRING (string)->data + 0)
-#define SREF(string, index)	(SDATA (string)[index] + 0)
-#define SSET(string, index, new) (SDATA (string)[index] = (new))
-#define SCHARS(string)		(XSTRING (string)->size + 0)
-#define SBYTES(string)		(STRING_BYTES (XSTRING (string)) + 0)
-
-/* Avoid "differ in sign" warnings.  */
-#define SSDATA(x)  ((char *) SDATA (x))
-
-#define STRING_SET_CHARS(string, newsize) \
-    (XSTRING (string)->size = (newsize))
-
-#define STRING_COPYIN(string, index, new, count) \
-    memcpy (SDATA (string) + index, new, count)
-
 /* Type checking.  */
 
-#define CHECK_TYPE(ok, Qxxxp, x) \
-  do { if (!(ok)) wrong_type_argument (Qxxxp, (x)); } while (0)
-
-
+static inline void
+(CHECK_TYPE) (int ok, Lisp_Object Qxxxp, Lisp_Object x)
+{
+  if (!ok)
+    wrong_type_argument (Qxxxp, x);
+}
 
 /* See the macros in intervals.h.  */
 
 typedef struct interval *INTERVAL;
 
 /* Complain if object is not string or buffer type */
-#define CHECK_STRING_OR_BUFFER(x) \
-  CHECK_TYPE (STRINGP (x) || BUFFERP (x), Qbuffer_or_string_p, x)
-
+static inline void
+CHECK_STRING_OR_BUFFER (Lisp_Object x)
+{
+  CHECK_TYPE (STRINGP (x) || BUFFERP (x), Qbuffer_or_string_p, x);
+}
 
 /* In a cons, the markbit of the car is the gc mark bit */
 
@@ -650,54 +829,68 @@
 #endif
 
 /* Use these from normal code.  */
-#define XCAR(c)	LISP_MAKE_RVALUE (XCAR_AS_LVALUE (c))
-#define XCDR(c) LISP_MAKE_RVALUE (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.
 
    Note that both arguments may refer to the same object, so 'n'
-   should not be read after 'c' is first modified.  Also, neither
-   argument should be evaluated more than once; side effects are
-   especially common in the second argument.  */
-#define XSETCAR(c,n) (XCAR_AS_LVALUE (c) = (n))
-#define XSETCDR(c,n) (XCDR_AS_LVALUE (c) = (n))
-
-/* Take the car or cdr of something whose type is not known.  */
-#define CAR(c)					\
- (CONSP ((c)) ? XCAR ((c))			\
-  : NILP ((c)) ? Qnil				\
-  : wrong_type_argument (Qlistp, (c)))
-
-#define CDR(c)					\
- (CONSP ((c)) ? XCDR ((c))			\
-  : NILP ((c)) ? Qnil				\
-  : wrong_type_argument (Qlistp, (c)))
-
-/* Take the car or cdr of something whose type is not known.  */
-#define CAR_SAFE(c)				\
-  (CONSP ((c)) ? XCAR ((c)) : Qnil)
-
-#define CDR_SAFE(c)				\
-  (CONSP ((c)) ? XCDR ((c)) : Qnil)
+   should not be read after 'c' is first modified.  */
+static inline void
+XSETCAR (Lisp_Object c, Lisp_Object n)
+{
+  XCAR_AS_LVALUE (c) = n;
+}
+static inline void
+XSETCDR (Lisp_Object c, Lisp_Object n)
+{
+  XCDR_AS_LVALUE (c) = n;
+}
+
+/* Take the car or cdr of something whose type is not known.  */
+static inline Lisp_Object
+CAR (Lisp_Object c)
+{
+  return (CONSP (c) ? XCAR (c)
+	  : NILP (c) ? Qnil
+	  : wrong_type_argument (Qlistp, c));
+}
+static inline Lisp_Object
+CDR (Lisp_Object c)
+{
+  return (CONSP (c) ? XCDR (c)
+	  : NILP (c) ? Qnil
+	  : wrong_type_argument (Qlistp, c));
+}
+
+/* Take the car or cdr of something whose type is not known.  */
+static inline Lisp_Object
+CAR_SAFE (Lisp_Object c)
+{
+  return CONSP (c) ? XCAR (c) : Qnil;
+}
+static inline Lisp_Object
+CDR_SAFE (Lisp_Object c)
+{
+  return CONSP (c) ? XCDR (c) : Qnil;
+}
+
+/* In a string or vector, the sign bit of the `size' is the gc mark bit.  */
+
+struct Lisp_String
+  {
+    ptrdiff_t size;
+    ptrdiff_t size_byte;
+    INTERVAL intervals;		/* Text properties in this string.  */
+    unsigned char *data;
+  };
 
 /* Nonzero if STR is a multibyte string.  */
-#define STRING_MULTIBYTE(STR)  \
-  (XSTRING (STR)->size_byte >= 0)
-
-/* Return the length in bytes of STR.  */
-
-#ifdef GC_CHECK_STRING_BYTES
-
-struct Lisp_String;
-extern ptrdiff_t string_bytes (struct Lisp_String *);
-#define STRING_BYTES(S) string_bytes ((S))
-
-#else /* not GC_CHECK_STRING_BYTES */
-
-#define STRING_BYTES(STR)  \
-  ((STR)->size_byte < 0 ? (STR)->size : (STR)->size_byte)
-
-#endif /* not GC_CHECK_STRING_BYTES */
+static inline int
+STRING_MULTIBYTE (Lisp_Object str)
+{
+  return 0 <= XSTRING (str)->size_byte;
+}
 
 /* An upper bound on the number of bytes in a Lisp string, not
    counting the terminating null.  This a tight enough bound to
@@ -727,25 +920,72 @@
     else XSTRING (STR)->size_byte = XSTRING (STR)->size; } while (0)
 
 /* Get text properties.  */
-#define STRING_INTERVALS(STR)  (XSTRING (STR)->intervals + 0)
+static inline INTERVAL
+STRING_INTERVALS (Lisp_Object str)
+{
+  return XSTRING (str)->intervals;
+}
 
 /* Set text properties.  */
-#define STRING_SET_INTERVALS(STR, INT) (XSTRING (STR)->intervals = (INT))
-
-/* In a string or vector, the sign bit of the `size' is the gc mark bit.  */
-
-struct Lisp_String
-  {
-    ptrdiff_t size;
-    ptrdiff_t size_byte;
-    INTERVAL intervals;		/* Text properties in this string.  */
-    unsigned char *data;
-  };
+static inline void
+STRING_SET_INTERVALS (Lisp_Object str, INTERVAL intervals)
+{
+  XSTRING (str)->intervals = intervals;
+}
+
+/* Convenience functions for dealing with Lisp strings.  */
+
+static inline unsigned char *
+SDATA (Lisp_Object string)
+{
+  return XSTRING (string)->data;
+}
+static inline char *
+SSDATA (Lisp_Object string)
+{
+  /* Avoid "differ in sign" warnings.  */
+  return (char *) SDATA (string);
+}
+static inline unsigned char
+SREF (Lisp_Object string, ptrdiff_t index)
+{
+  return SDATA (string)[index];
+}
+static inline void
+SSET (Lisp_Object string, ptrdiff_t index, unsigned char new)
+{
+  SDATA (string)[index] = new;
+}
+static inline ptrdiff_t
+SCHARS (Lisp_Object string)
+{
+  return XSTRING (string)->size;
+}
+static inline ptrdiff_t
+STRING_BYTES (struct Lisp_String *s)
+{
+#ifdef GC_CHECK_STRING_BYTES
+  extern ptrdiff_t string_bytes (struct Lisp_String *);
+  return string_bytes (s);
+#else
+  return s->size_byte < 0 ? s->size : s->size_byte;
+#endif
+}
+static inline ptrdiff_t
+SBYTES (Lisp_Object string)
+{
+  return STRING_BYTES (XSTRING (string));
+}
+static inline void
+STRING_SET_CHARS (Lisp_Object string, ptrdiff_t newsize)
+{
+  XSTRING (string)->size = newsize;
+}
 
 /* Header of vector-like objects.  This documents the layout constraints on
    vectors and pseudovectors other than struct Lisp_Subr.  It also prevents
-   compilers from being fooled by Emacs's type punning: the XSETPSEUDOVECTOR
-   and PSEUDOVECTORP macros cast their pointers to struct vectorlike_header *,
+   compilers from being fooled by Emacs's type punning: XSETPSEUDOVECTOR
+   and PSEUDOVECTORP cast their pointers to struct vectorlike_header *,
    because when two such pointers potentially alias, a compiler won't
    incorrectly reorder loads and stores to their size fields.  See
    <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8546>.  */
@@ -796,6 +1036,23 @@
     Lisp_Object contents[1];
   };
 
+/* Conveniences for dealing with Lisp arrays.  */
+
+/* A macro because it is also used as an lvalue.  FIXME: Use ASET instead.  */
+#define AREF(ARRAY, IDX)	XVECTOR ((ARRAY))->contents[IDX]
+
+static inline ptrdiff_t
+ASIZE (Lisp_Object array)
+{
+  return XVECTOR (array)->header.size;
+}
+
+static inline void
+ASET (Lisp_Object array, ptrdiff_t idx, Lisp_Object val)
+{
+  XVECTOR (array)->contents[idx] = val;
+}
+
 /* If a struct is made to look like a vector, this macro returns the length
    of the shortest vector that would hold that struct.  */
 #define VECSIZE(type) ((sizeof (type)					  \
@@ -810,53 +1067,6 @@
   ((offsetof (type, nonlispfield) - offsetof (struct Lisp_Vector, contents[0])) \
    / sizeof (Lisp_Object))
 
-/* A char-table is a kind of vectorlike, with contents are like a
-   vector but with a few other slots.  For some purposes, it makes
-   sense to handle a char-table with type struct Lisp_Vector.  An
-   element of a char table can be any Lisp objects, but if it is a sub
-   char-table, we treat it a table that contains information of a
-   specific range of characters.  A sub char-table has the same
-   structure as a vector.  A sub char table appears only in an element
-   of a char-table, and there's no way to access it directly from
-   Emacs Lisp program.  */
-
-/* This is the number of slots that every char table must have.  This
-   counts the ordinary slots and the top, defalt, parent, and purpose
-   slots.  */
-#define CHAR_TABLE_STANDARD_SLOTS (VECSIZE (struct Lisp_Char_Table) - 1)
-
-/* Return the number of "extra" slots in the char table CT.  */
-
-#define CHAR_TABLE_EXTRA_SLOTS(CT)	\
-  (((CT)->header.size & PSEUDOVECTOR_SIZE_MASK) - CHAR_TABLE_STANDARD_SLOTS)
-
-#ifdef __GNUC__
-
-#define CHAR_TABLE_REF_ASCII(CT, IDX)					\
-  ({struct Lisp_Char_Table *_tbl = NULL;				\
-    Lisp_Object _val;							\
-    do {								\
-      _tbl = _tbl ? XCHAR_TABLE (_tbl->parent) : XCHAR_TABLE (CT);	\
-      _val = (! SUB_CHAR_TABLE_P (_tbl->ascii) ? _tbl->ascii		\
-	      : XSUB_CHAR_TABLE (_tbl->ascii)->contents[IDX]);		\
-      if (NILP (_val))							\
-	_val = _tbl->defalt;						\
-    } while (NILP (_val) && ! NILP (_tbl->parent));			\
-    _val; })
-
-#else  /* not __GNUC__ */
-
-#define CHAR_TABLE_REF_ASCII(CT, IDX)					  \
-  (! NILP (XCHAR_TABLE (CT)->ascii)					  \
-   ? (! SUB_CHAR_TABLE_P (XCHAR_TABLE (CT)->ascii)			  \
-      ? XCHAR_TABLE (CT)->ascii						  \
-      : ! NILP (XSUB_CHAR_TABLE (XCHAR_TABLE (CT)->ascii)->contents[IDX]) \
-      ? XSUB_CHAR_TABLE (XCHAR_TABLE (CT)->ascii)->contents[IDX]	  \
-      : char_table_ref ((CT), (IDX)))					  \
-   :  char_table_ref ((CT), (IDX)))
-
-#endif	/* not __GNUC__ */
-
 /* Compute A OP B, using the unsigned comparison operator OP.  A and B
    should be integer expressions.  This is not the same as
    mathematical comparison; for example, UNSIGNED_CMP (0, <, -1)
@@ -870,31 +1080,23 @@
 /* Nonzero iff C is an ASCII character.  */
 #define ASCII_CHAR_P(c) UNSIGNED_CMP (c, <, 0x80)
 
-/* Almost equivalent to Faref (CT, IDX) with optimization for ASCII
-   characters.  Do not check validity of CT.  */
-#define CHAR_TABLE_REF(CT, IDX)					\
-  (ASCII_CHAR_P (IDX) ? CHAR_TABLE_REF_ASCII ((CT), (IDX))	\
-   : char_table_ref ((CT), (IDX)))
-
-/* Almost equivalent to Faref (CT, IDX).  However, if the result is
-   not a character, return IDX.
-
-   For these characters, do not check validity of CT
-   and do not follow parent.  */
-#define CHAR_TABLE_TRANSLATE(CT, IDX)	\
-  char_table_translate (CT, IDX)
-
-/* Equivalent to Faset (CT, IDX, VAL) with optimization for ASCII and
-   8-bit European characters.  Do not check validity of CT.  */
-#define CHAR_TABLE_SET(CT, IDX, VAL)					\
-  (ASCII_CHAR_P (IDX) && SUB_CHAR_TABLE_P (XCHAR_TABLE (CT)->ascii)	\
-   ? XSUB_CHAR_TABLE (XCHAR_TABLE (CT)->ascii)->contents[IDX] = VAL	\
-   : char_table_set (CT, IDX, VAL))
-
-#define CHARTAB_SIZE_BITS_0 6
-#define CHARTAB_SIZE_BITS_1 4
-#define CHARTAB_SIZE_BITS_2 5
-#define CHARTAB_SIZE_BITS_3 7
+/* A char-table is a kind of vectorlike, with contents are like a
+   vector but with a few other slots.  For some purposes, it makes
+   sense to handle a char-table with type struct Lisp_Vector.  An
+   element of a char table can be any Lisp objects, but if it is a sub
+   char-table, we treat it a table that contains information of a
+   specific range of characters.  A sub char-table has the same
+   structure as a vector.  A sub char table appears only in an element
+   of a char-table, and there's no way to access it directly from
+   Emacs Lisp program.  */
+
+enum
+  {
+    CHARTAB_SIZE_BITS_0 = 6,
+    CHARTAB_SIZE_BITS_1 = 4,
+    CHARTAB_SIZE_BITS_2 = 5,
+    CHARTAB_SIZE_BITS_3 = 7
+  };
 
 extern const int chartab_size[4];
 
@@ -951,6 +1153,70 @@
     Lisp_Object contents[1];
   };
 
+/* This is the number of slots that every char table must have.  This
+   counts the ordinary slots and the top, defalt, parent, and purpose
+   slots.  */
+enum { CHAR_TABLE_STANDARD_SLOTS = VECSIZE (struct Lisp_Char_Table) - 1 };
+
+/* Return the number of "extra" slots in the char table CT.  */
+
+static inline int
+CHAR_TABLE_EXTRA_SLOTS (struct Lisp_Char_Table *ct)
+{
+  return ((ct->header.size & PSEUDOVECTOR_SIZE_MASK)
+	  - CHAR_TABLE_STANDARD_SLOTS);
+}
+
+static inline Lisp_Object
+CHAR_TABLE_REF_ASCII (Lisp_Object ct, ptrdiff_t idx)
+{
+  struct Lisp_Char_Table *tbl = NULL;
+  Lisp_Object val;
+  do
+    {
+      tbl = tbl ? XCHAR_TABLE (tbl->parent) : XCHAR_TABLE (ct);
+      val = (! SUB_CHAR_TABLE_P (tbl->ascii) ? tbl->ascii
+	     : XSUB_CHAR_TABLE (tbl->ascii)->contents[idx]);
+      if (NILP (val))
+	val = tbl->defalt;
+    }
+  while (NILP (val) && ! NILP (tbl->parent));
+
+  return val;
+}
+
+/* Almost equivalent to Faref (CT, IDX) with optimization for ASCII
+   characters.  Do not check validity of CT.  */
+static inline Lisp_Object
+CHAR_TABLE_REF (Lisp_Object ct, int idx)
+{
+  return (ASCII_CHAR_P (idx)
+	  ? CHAR_TABLE_REF_ASCII (ct, idx)
+	  : char_table_ref (ct, idx));
+}
+
+/* Almost equivalent to Faref (CT, IDX).  However, if the result is
+   not a character, return IDX.
+
+   For these characters, do not check validity of CT
+   and do not follow parent.  */
+static inline int
+CHAR_TABLE_TRANSLATE (Lisp_Object ct, int idx)
+{
+  return char_table_translate (ct, idx);
+}
+
+/* Equivalent to Faset (CT, IDX, VAL) with optimization for ASCII and
+   8-bit European characters.  Do not check validity of CT.  */
+static inline void
+CHAR_TABLE_SET (Lisp_Object ct, int idx, Lisp_Object val)
+{
+  if (ASCII_CHAR_P (idx) && SUB_CHAR_TABLE_P (XCHAR_TABLE (ct)->ascii))
+    XSUB_CHAR_TABLE (XCHAR_TABLE (ct)->ascii)->contents[idx] = val;
+  else
+    char_table_set (ct, idx, val);
+}
+
 /* A boolvector is a kind of vectorlike, with contents are like a string.  */
 struct Lisp_Bool_Vector
   {
@@ -1065,41 +1331,86 @@
 
 /* Value is name of symbol.  */
 
-#define SYMBOL_VAL(sym)   \
-  (eassert ((sym)->redirect == SYMBOL_PLAINVAL),  (sym)->val.value)
-#define SYMBOL_ALIAS(sym) \
-  (eassert ((sym)->redirect == SYMBOL_VARALIAS),  (sym)->val.alias)
-#define SYMBOL_BLV(sym)   \
-  (eassert ((sym)->redirect == SYMBOL_LOCALIZED), (sym)->val.blv)
-#define SYMBOL_FWD(sym)   \
-  (eassert ((sym)->redirect == SYMBOL_FORWARDED), (sym)->val.fwd)
-#define SET_SYMBOL_VAL(sym, v)     \
-  (eassert ((sym)->redirect == SYMBOL_PLAINVAL),  (sym)->val.value = (v))
-#define SET_SYMBOL_ALIAS(sym, v)   \
-  (eassert ((sym)->redirect == SYMBOL_VARALIAS),  (sym)->val.alias = (v))
-#define SET_SYMBOL_BLV(sym, v)     \
-  (eassert ((sym)->redirect == SYMBOL_LOCALIZED), (sym)->val.blv = (v))
-#define SET_SYMBOL_FWD(sym, v) \
-  (eassert ((sym)->redirect == SYMBOL_FORWARDED), (sym)->val.fwd = (v))
+static inline Lisp_Object
+(SYMBOL_VAL) (struct Lisp_Symbol *sym)
+{
+  eassert (sym->redirect == SYMBOL_PLAINVAL);
+  return sym->val.value;
+}
+static inline struct Lisp_Symbol *
+SYMBOL_ALIAS (struct Lisp_Symbol *sym)
+{
+  eassert (sym->redirect == SYMBOL_VARALIAS);
+  return sym->val.alias;
+}
+static inline struct Lisp_Buffer_Local_Value *
+SYMBOL_BLV (struct Lisp_Symbol *sym)
+{
+  eassert (sym->redirect == SYMBOL_LOCALIZED);
+  return sym->val.blv;
+}
+static inline union Lisp_Fwd *
+SYMBOL_FWD (struct Lisp_Symbol *sym)
+{
+  eassert (sym->redirect == SYMBOL_FORWARDED);
+  return sym->val.fwd;
+}
+static inline void
+(SET_SYMBOL_VAL) (struct Lisp_Symbol *sym, Lisp_Object v)
+{
+  eassert (sym->redirect == SYMBOL_PLAINVAL);
+  sym->val.value = v;
+}
+static inline void
+SET_SYMBOL_ALIAS (struct Lisp_Symbol *sym, struct Lisp_Symbol *v)
+{
+  eassert (sym->redirect == SYMBOL_VARALIAS);
+  sym->val.alias = v;
+}
+static inline void
+SET_SYMBOL_BLV (struct Lisp_Symbol *sym, struct Lisp_Buffer_Local_Value *v)
+{
+  eassert (sym->redirect == SYMBOL_LOCALIZED);
+  sym->val.blv = v;
+}
+static inline void
+SET_SYMBOL_FWD (struct Lisp_Symbol *sym, union Lisp_Fwd *v)
+{
+  eassert (sym->redirect == SYMBOL_FORWARDED);
+  sym->val.fwd = v;
+}
 
-#define SYMBOL_NAME(sym)  \
-     LISP_MAKE_RVALUE (XSYMBOL (sym)->xname)
+static inline Lisp_Object
+SYMBOL_NAME (Lisp_Object sym)
+{
+  return XSYMBOL (sym)->xname;
+}
 
 /* Value is non-zero if SYM is an interned symbol.  */
 
-#define SYMBOL_INTERNED_P(sym)  \
-     (XSYMBOL (sym)->interned != SYMBOL_UNINTERNED)
+static inline int
+SYMBOL_INTERNED_P (Lisp_Object sym)
+{
+  return XSYMBOL (sym)->interned != SYMBOL_UNINTERNED;
+}
 
 /* Value is non-zero if SYM is interned in initial_obarray.  */
 
-#define SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P(sym) \
-     (XSYMBOL (sym)->interned == SYMBOL_INTERNED_IN_INITIAL_OBARRAY)
+static inline int
+SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P (Lisp_Object sym)
+{
+  return XSYMBOL (sym)->interned == SYMBOL_INTERNED_IN_INITIAL_OBARRAY;
+}
 
 /* Value is non-zero if symbol is considered a constant, i.e. its
    value cannot be changed (there is an exception for keyword symbols,
    whose value can be set to the keyword symbol itself).  */
 
-#define SYMBOL_CONSTANT_P(sym)   XSYMBOL (sym)->constant
+static inline int
+(SYMBOL_CONSTANT_P) (Lisp_Object sym)
+{
+  return XSYMBOL (sym)->constant;
+}
 
 #define DEFSYM(sym, name)	\
   do { (sym) = intern_c_string ((name)); staticpro (&(sym)); } while (0)
@@ -1181,16 +1492,25 @@
 };

-#define XHASH_TABLE(OBJ) \
-     ((struct Lisp_Hash_Table *) XUNTAG (OBJ, Lisp_Vectorlike))
+static inline struct Lisp_Hash_Table *
+XHASH_TABLE (Lisp_Object a)
+{
+  return XUNTAG (a, Lisp_Vectorlike);
+}
 
 #define XSET_HASH_TABLE(VAR, PTR) \
      (XSETPSEUDOVECTOR (VAR, PTR, PVEC_HASH_TABLE))
 
-#define HASH_TABLE_P(OBJ)  PSEUDOVECTORP (OBJ, PVEC_HASH_TABLE)
-
-#define CHECK_HASH_TABLE(x) \
-  CHECK_TYPE (HASH_TABLE_P (x), Qhash_table_p, x)
+static inline int
+HASH_TABLE_P (Lisp_Object a)
+{
+  return PSEUDOVECTORP (a, PVEC_HASH_TABLE);
+}
+static inline void
+CHECK_HASH_TABLE (Lisp_Object x)
+{
+  return CHECK_TYPE (HASH_TABLE_P (x), Qhash_table_p, x);
+}
 
 /* Value is the key part of entry IDX in hash table H.  */
 
@@ -1215,12 +1535,14 @@
 #define HASH_INDEX(H, IDX)  AREF ((H)->index, (IDX))
 
 /* Value is the size of hash table H.  */
-
-#define HASH_TABLE_SIZE(H) ASIZE ((H)->next)
+static inline ptrdiff_t
+HASH_TABLE_SIZE (struct Lisp_Hash_Table *h)
+{
+  return ASIZE (h->next);
+}
 
 /* Default size for hash tables if not specified.  */
-
-#define DEFAULT_HASH_SIZE 65
+enum { DEFAULT_HASH_SIZE = 65 };
 
 /* Default threshold specifying when to resize a hash table.  The
    value gives the ratio of current entries in the hash table and the
@@ -1330,6 +1652,43 @@
     struct Lisp_Save_Value u_save_value;
   };
 
+static inline union Lisp_Misc *
+XMISC (Lisp_Object a)
+{
+  return XUNTAG (a, Lisp_Misc);
+}
+
+static inline struct Lisp_Misc_Any *
+XMISCANY (Lisp_Object a)
+{
+  eassert (MISCP (a));
+  return & XMISC (a)->u_any;
+}
+
+/* A macro because it is also used as an lvalue.  FIXME: clean this up.  */
+#define XMISCTYPE(a)   (XMISCANY (a)->type)
+
+static inline struct Lisp_Marker *
+XMARKER (Lisp_Object a)
+{
+  eassert (MARKERP (a));
+  return & XMISC (a)->u_marker;
+}
+
+static inline struct Lisp_Overlay *
+XOVERLAY (Lisp_Object a)
+{
+  eassert (OVERLAYP (a));
+  return & XMISC (a)->u_overlay;
+}
+
+static inline struct Lisp_Save_Value *
+XSAVE_VALUE (Lisp_Object a)
+{
+  eassert (SAVE_VALUEP (a));
+  return & XMISC (a)->u_save_value;
+}
+
 /* Forwarding pointer to an int variable.
    This is allowed only in the value cell of a symbol,
    and it means that the symbol's value really lives in the
@@ -1419,13 +1778,29 @@
     Lisp_Object valcell;
   };
 
-#define BLV_FOUND(blv) \
-  (eassert ((blv)->found == !EQ ((blv)->defcell, (blv)->valcell)), (blv)->found)
-#define SET_BLV_FOUND(blv, v) \
-  (eassert ((v) == !EQ ((blv)->defcell, (blv)->valcell)), (blv)->found = (v))
+static inline int
+BLV_FOUND (struct Lisp_Buffer_Local_Value *blv)
+{
+  eassert (blv->found == !EQ (blv->defcell, blv->valcell));
+  return blv->found;
+}
+static inline void
+SET_BLV_FOUND (struct Lisp_Buffer_Local_Value *blv, int v)
+{
+  eassert (v == !EQ (blv->defcell, blv->valcell));
+  blv->found = v;
+}
 
-#define BLV_VALUE(blv) (XCDR ((blv)->valcell))
-#define SET_BLV_VALUE(blv, v) (XSETCDR ((blv)->valcell, v))
+static inline Lisp_Object
+BLV_VALUE (struct Lisp_Buffer_Local_Value *blv)
+{
+  return XCDR (blv->valcell);
+}
+static inline void
+SET_BLV_VALUE (struct Lisp_Buffer_Local_Value *blv, Lisp_Object v)
+{
+  XSETCDR (blv->valcell, v);
+}
 
 /* Like Lisp_Objfwd except that value lives in a slot in the
    current kboard.  */
@@ -1443,6 +1818,47 @@
     struct Lisp_Buffer_Objfwd u_buffer_objfwd;
     struct Lisp_Kboard_Objfwd u_kboard_objfwd;
   };
+
+static inline enum Lisp_Fwd_Type
+XFWDTYPE (union Lisp_Fwd *a)
+{
+  return a->u_intfwd.type;
+}
+
+static inline struct Lisp_Intfwd *
+XINTFWD (union Lisp_Fwd *a)
+{
+  eassert (INTFWDP (a));
+  return &a->u_intfwd;
+}
+
+static inline struct Lisp_Boolfwd *
+XBOOLFWD (union Lisp_Fwd *a)
+{
+  eassert (BOOLFWDP (a));
+  return &a->u_boolfwd;
+}
+
+static inline struct Lisp_Objfwd *
+XOBJFWD (union Lisp_Fwd *a)
+{
+  eassert (OBJFWDP (a));
+  return &a->u_objfwd;
+}
+
+static inline struct Lisp_Buffer_Objfwd *
+XBUFFER_OBJFWD (union Lisp_Fwd *a)
+{
+  eassert (BUFFER_OBJFWDP (a));
+  return &a->u_buffer_objfwd;
+}
+
+static inline struct Lisp_Kboard_Objfwd *
+XKBOARD_OBJFWD (union Lisp_Fwd *a)
+{
+  eassert (KBOARD_OBJFWDP (a));
+  return &a->u_kboard_objfwd;
+}
 
 /* Lisp floating point type.  */
 struct Lisp_Float
@@ -1458,13 +1874,24 @@
     } u;
   };
 
+static inline double
+XFLOAT_DATA (Lisp_Object f)
+{
 #ifdef HIDE_LISP_IMPLEMENTATION
-#define XFLOAT_DATA(f)	(0 ? XFLOAT (f)->u.data_ : XFLOAT (f)->u.data_)
+  return XFLOAT (f)->u.data_;
 #else
-#define XFLOAT_DATA(f)	(0 ? XFLOAT (f)->u.data :  XFLOAT (f)->u.data)
+  return XFLOAT (f)->u.data;
+#endif
+}
+
+#ifndef HIDE_LISP_IMPLEMENTATION
 /* This should be used only in alloc.c, which always disables
    HIDE_LISP_IMPLEMENTATION.  */
-#define XFLOAT_INIT(f,n) (XFLOAT (f)->u.data = (n))
+static inline void
+XFLOAT_INIT (Lisp_Object f, double n)
+{
+  XFLOAT (f)->u.data = n;
+}
 #endif
 
 /* A character, declared with the following typedef, is a member
@@ -1475,91 +1902,36 @@
 #endif
 
 /* Meanings of slots in a Lisp_Compiled:  */
-
-#define COMPILED_ARGLIST 0
-#define COMPILED_BYTECODE 1
-#define COMPILED_CONSTANTS 2
-#define COMPILED_STACK_DEPTH 3
-#define COMPILED_DOC_STRING 4
-#define COMPILED_INTERACTIVE 5
+enum
+  {
+    COMPILED_ARGLIST,
+    COMPILED_BYTECODE,
+    COMPILED_CONSTANTS,
+    COMPILED_STACK_DEPTH,
+    COMPILED_DOC_STRING,
+    COMPILED_INTERACTIVE
+  };
 
 /* Flag bits in a character.  These also get used in termhooks.h.
    Richard Stallman <[email-masked]> thinks that MULE
    (MUlti-Lingual Emacs) might need 22 bits for the character value
    itself, so we probably shouldn't use any bits lower than 0x0400000.  */
-#define CHAR_ALT   (0x0400000)
-#define CHAR_SUPER (0x0800000)
-#define CHAR_HYPER (0x1000000)
-#define CHAR_SHIFT (0x2000000)
-#define CHAR_CTL   (0x4000000)
-#define CHAR_META  (0x8000000)
-
-#define CHAR_MODIFIER_MASK \
-  (CHAR_ALT | CHAR_SUPER | CHAR_HYPER  | CHAR_SHIFT | CHAR_CTL | CHAR_META)
-
+enum
+  {
+    CHAR_ALT   = 0x0400000,
+    CHAR_SUPER = 0x0800000,
+    CHAR_HYPER = 0x1000000,
+    CHAR_SHIFT = 0x2000000,
+    CHAR_CTL   = 0x4000000,
+    CHAR_META  = 0x8000000,
+    CHAR_MODIFIER_MASK =
+      CHAR_ALT | CHAR_SUPER | CHAR_HYPER  | CHAR_SHIFT | CHAR_CTL | CHAR_META
+  };
 
 /* Actually, the current Emacs uses 22 bits for the character value
    itself.  */
-#define CHARACTERBITS 22
-
-
-/* The glyph datatype, used to represent characters on the display.
-   It consists of a char code and a face id.  */
-
-typedef struct {
-  int ch;
-  int face_id;
-} GLYPH;
-
-/* Return a glyph's character code.  */
-#define GLYPH_CHAR(glyph) ((glyph).ch)
-
-/* Return a glyph's face ID.  */
-#define GLYPH_FACE(glyph) ((glyph).face_id)
-
-#define SET_GLYPH_CHAR(glyph, char) ((glyph).ch = (char))
-#define SET_GLYPH_FACE(glyph, face) ((glyph).face_id = (face))
-#define SET_GLYPH(glyph, char, face) ((glyph).ch = (char), (glyph).face_id = (face))
-
-/* Return 1 if GLYPH contains valid character code.  */
-#define GLYPH_CHAR_VALID_P(glyph) CHAR_VALID_P (GLYPH_CHAR (glyph))
-
-
-/* Glyph Code from a display vector may either be an integer which
-   encodes a char code in the lower CHARACTERBITS bits and a (very small)
-   face-id in the upper bits, or it may be a cons (CHAR . FACE-ID).  */
-
-#define GLYPH_CODE_P(gc)						\
-  (CONSP (gc)								\
-   ? (CHARACTERP (XCAR (gc))						\
-      && RANGED_INTEGERP (0, XCDR (gc), MAX_FACE_ID))			\
-   : (RANGED_INTEGERP							\
-      (0, gc,								\
-       (MAX_FACE_ID < TYPE_MAXIMUM (EMACS_INT) >> CHARACTERBITS		\
-	? ((EMACS_INT) MAX_FACE_ID << CHARACTERBITS) | MAX_CHAR		\
-	: TYPE_MAXIMUM (EMACS_INT)))))
-
-/* The following are valid only if GLYPH_CODE_P (gc).  */
-
-#define GLYPH_CODE_CHAR(gc) \
-  (CONSP (gc) ? XINT (XCAR (gc)) : XINT (gc) & ((1 << CHARACTERBITS) - 1))
-
-#define GLYPH_CODE_FACE(gc) \
-  (CONSP (gc) ? XINT (XCDR (gc)) : XINT (gc) >> CHARACTERBITS)
-
-#define SET_GLYPH_FROM_GLYPH_CODE(glyph, gc)				\
-  do									\
-    {									\
-      if (CONSP (gc))							\
-	SET_GLYPH (glyph, XINT (XCAR (gc)), XINT (XCDR (gc)));		\
-      else								\
-	SET_GLYPH (glyph, (XINT (gc) & ((1 << CHARACTERBITS)-1)),	\
-		   (XINT (gc) >> CHARACTERBITS));			\
-    }									\
-  while (0)
-
-/* The ID of the mode line highlighting face.  */
-#define GLYPH_MODE_LINE_FACE 1
+enum { CHARACTERBITS = 22 };
+
 
 /* Structure to hold mouse highlight data.  This is here because other
    header files need it for defining struct x_output etc.  */
@@ -1598,140 +1970,308 @@
 
 /* Data type checking */
 
-#define NILP(x)  EQ (x, Qnil)
-
-#define NUMBERP(x) (INTEGERP (x) || FLOATP (x))
-#define NATNUMP(x) (INTEGERP (x) && XINT (x) >= 0)
-
-#define RANGED_INTEGERP(lo, x, hi) \
-  (INTEGERP (x) && (lo) <= XINT (x) && XINT (x) <= (hi))
+static inline int
+(NILP) (Lisp_Object x)
+{
+  return EQ (x, Qnil);
+}
+
+static inline int
+NUMBERP (Lisp_Object x)
+{
+  return INTEGERP (x) || FLOATP (x);
+}
+static inline int
+NATNUMP (Lisp_Object x)
+{
+  return INTEGERP (x) && 0 <= XINT (x);
+}
+
+static inline int
+RANGED_INTEGERP (intmax_t lo, Lisp_Object x, intmax_t hi)
+{
+  return INTEGERP (x) && lo <= XINT (x) && XINT (x) <= hi;
+}
+
 #define TYPE_RANGED_INTEGERP(type, x) \
-  (TYPE_SIGNED (type)							\
-   ? RANGED_INTEGERP (TYPE_MINIMUM (type), x, TYPE_MAXIMUM (type))	\
-   : RANGED_INTEGERP (0, x, TYPE_MAXIMUM (type)))
-
-#define INTEGERP(x) (LISP_INT_TAG_P (XTYPE ((x))))
-#define SYMBOLP(x) (XTYPE ((x)) == Lisp_Symbol)
-#define MISCP(x) (XTYPE ((x)) == Lisp_Misc)
-#define VECTORLIKEP(x) (XTYPE ((x)) == Lisp_Vectorlike)
-#define STRINGP(x) (XTYPE ((x)) == Lisp_String)
-#define CONSP(x) (XTYPE ((x)) == Lisp_Cons)
-
-#define FLOATP(x) (XTYPE ((x)) == Lisp_Float)
-#define VECTORP(x) (VECTORLIKEP (x) && !(ASIZE (x) & PSEUDOVECTOR_FLAG))
-#define OVERLAYP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay)
-#define MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
-#define SAVE_VALUEP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Save_Value)
-
-#define INTFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Int)
-#define BOOLFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Bool)
-#define OBJFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Obj)
-#define BUFFER_OBJFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Buffer_Obj)
-#define KBOARD_OBJFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Kboard_Obj)
-
-/* True if object X is a pseudovector whose code is CODE.  The cast to struct
-   vectorlike_header * avoids aliasing issues.  */
-#define PSEUDOVECTORP(x, code)					\
-  TYPED_PSEUDOVECTORP (x, vectorlike_header, code)
-
-#define PSEUDOVECTOR_TYPEP(v, code)					\
-  (((v)->size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK))			\
-   == (PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_SIZE_BITS)))
-
-/* True if object X, with internal type struct T *, is a pseudovector whose
-   code is CODE.  */
-#define TYPED_PSEUDOVECTORP(x, t, code)				\
-  (VECTORLIKEP (x)						\
-   && PSEUDOVECTOR_TYPEP ((struct t *) XUNTAG (x, Lisp_Vectorlike), code))
+  (INTEGERP (x)			      \
+   && (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 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)
+{
+  return LISP_INT_TAG_P (XTYPE (x));
+}
+static inline int
+(VECTORLIKEP) (Lisp_Object x)
+{
+  return XTYPE (x) == Lisp_Vectorlike;
+}
+static inline int
+VECTORP (Lisp_Object x)
+{
+  return VECTORLIKEP (x) && ! (ASIZE (x) & PSEUDOVECTOR_FLAG);
+}
+static inline int
+OVERLAYP (Lisp_Object x)
+{
+  return MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay;
+}
+static inline int
+(MARKERP) (Lisp_Object x)
+{
+  return MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker;
+}
+static inline int
+SAVE_VALUEP (Lisp_Object x)
+{
+  return MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Save_Value;
+}
+
+static inline int
+INTFWDP (union Lisp_Fwd *a)
+{
+  return XFWDTYPE (a) == Lisp_Fwd_Int;
+}
+static inline int
+BOOLFWDP (union Lisp_Fwd *a)
+{
+  return XFWDTYPE (a) == Lisp_Fwd_Bool;
+}
+static inline int
+OBJFWDP (union Lisp_Fwd *a)
+{
+  return XFWDTYPE (a) == Lisp_Fwd_Obj;
+}
+static inline int
+BUFFER_OBJFWDP (union Lisp_Fwd *a)
+{
+  return XFWDTYPE (a) == Lisp_Fwd_Buffer_Obj;
+}
+static inline int
+KBOARD_OBJFWDP (union Lisp_Fwd *a)
+{
+  return XFWDTYPE (a) == Lisp_Fwd_Kboard_Obj;
+}
+
+/* True if the size field SIZE of a pseudovector is that of a
+   pseudovector whose code is CODE.  */
+static inline int
+PSEUDOVECTOR_SIZE_TYPEP (ptrdiff_t size, int code)
+{
+  return ((size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK))
+	  == (PSEUDOVECTOR_FLAG | (code << PSEUDOVECTOR_SIZE_BITS)));
+}
+
+/* True if A is a pseudovector whose code is CODE.  */
+static inline int
+PSEUDOVECTORP (Lisp_Object a, int code)
+{
+  if (! VECTORLIKEP (a))
+    return 0;
+  else
+    {
+      /* Converting to struct vectorlike_header * avoids aliasing issues.  */
+      struct vectorlike_header *h = XUNTAG (a, Lisp_Vectorlike);
+      return PSEUDOVECTOR_SIZE_TYPEP (h->size, code);
+    }
+}
+
 
 /* Test for specific pseudovector types.  */
-#define WINDOW_CONFIGURATIONP(x) PSEUDOVECTORP (x, PVEC_WINDOW_CONFIGURATION)
-#define PROCESSP(x) PSEUDOVECTORP (x, PVEC_PROCESS)
-#define WINDOWP(x) PSEUDOVECTORP (x, PVEC_WINDOW)
-#define TERMINALP(x) PSEUDOVECTORP (x, PVEC_TERMINAL)
+
+static inline int
+WINDOW_CONFIGURATIONP (Lisp_Object a)
+{
+  return PSEUDOVECTORP (a, PVEC_WINDOW_CONFIGURATION);
+}
+
+static inline int
+PROCESSP (Lisp_Object a)
+{
+  return PSEUDOVECTORP (a, PVEC_PROCESS);
+}
+
+static inline int
+WINDOWP (Lisp_Object a)
+{
+  return PSEUDOVECTORP (a, PVEC_WINDOW);
+}
+
+static inline int
+TERMINALP (Lisp_Object a)
+{
+  return PSEUDOVECTORP (a, PVEC_TERMINAL);
+}
+
 /* SUBRP is special since Lisp_Subr lacks struct vectorlike_header.  */
-#define SUBRP(x) TYPED_PSEUDOVECTORP (x, Lisp_Subr, PVEC_SUBR)
-#define COMPILEDP(x) PSEUDOVECTORP (x, PVEC_COMPILED)
-#define BUFFERP(x) PSEUDOVECTORP (x, PVEC_BUFFER)
-#define CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_CHAR_TABLE)
-#define SUB_CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_SUB_CHAR_TABLE)
-#define BOOL_VECTOR_P(x) PSEUDOVECTORP (x, PVEC_BOOL_VECTOR)
-#define FRAMEP(x) PSEUDOVECTORP (x, PVEC_FRAME)
+static inline int
+SUBRP (Lisp_Object a)
+{
+  if (! VECTORLIKEP (a))
+    return 0;
+  else
+    {
+      struct Lisp_Subr *h = XUNTAG (a, Lisp_Vectorlike);
+      return PSEUDOVECTOR_SIZE_TYPEP (h->size, PVEC_SUBR);
+    }
+}
+
+static inline int
+COMPILEDP (Lisp_Object a)
+{
+  return PSEUDOVECTORP (a, PVEC_COMPILED);
+}
+
+static inline int
+BUFFERP (Lisp_Object a)
+{
+  return PSEUDOVECTORP (a, PVEC_BUFFER);
+}
+
+static inline int
+CHAR_TABLE_P (Lisp_Object a)
+{
+  return PSEUDOVECTORP (a, PVEC_CHAR_TABLE);
+}
+
+static inline int
+SUB_CHAR_TABLE_P (Lisp_Object a)
+{
+  return PSEUDOVECTORP (a, PVEC_SUB_CHAR_TABLE);
+}
+
+static inline int
+BOOL_VECTOR_P (Lisp_Object a)
+{
+  return PSEUDOVECTORP (a, PVEC_BOOL_VECTOR);
+}
+
+static inline int
+FRAMEP (Lisp_Object a)
+{
+  return PSEUDOVECTORP (a, PVEC_FRAME);
+}
 
 /* Test for image (image . spec)  */
-#define IMAGEP(x) (CONSP (x) && EQ (XCAR (x), Qimage))
+static inline int
+IMAGEP (Lisp_Object x)
+{
+  return CONSP (x) && EQ (XCAR (x), Qimage);
+}
 
 /* Array types.  */
-
-#define ARRAYP(x) \
-  (VECTORP (x) || STRINGP (x) || CHAR_TABLE_P (x) || BOOL_VECTOR_P (x))
+static inline int
+ARRAYP (Lisp_Object x)
+{
+  return VECTORP (x) || STRINGP (x) || CHAR_TABLE_P (x) || BOOL_VECTOR_P (x);
+}
 
-#define CHECK_LIST(x) \
-  CHECK_TYPE (CONSP (x) || NILP (x), Qlistp, x)
-
-#define CHECK_LIST_CONS(x, y) \
-  CHECK_TYPE (CONSP (x), Qlistp, y)
-
-#define CHECK_LIST_END(x, y) \
-  CHECK_TYPE (NILP (x), Qlistp, y)
-
-#define CHECK_STRING(x) \
-  CHECK_TYPE (STRINGP (x), Qstringp, x)
-
-#define CHECK_STRING_CAR(x) \
-  CHECK_TYPE (STRINGP (XCAR (x)), Qstringp, XCAR (x))
-
-#define CHECK_CONS(x) \
-  CHECK_TYPE (CONSP (x), Qconsp, x)
-
-#define CHECK_SYMBOL(x) \
-  CHECK_TYPE (SYMBOLP (x), Qsymbolp, x)
-
-#define CHECK_CHAR_TABLE(x) \
-  CHECK_TYPE (CHAR_TABLE_P (x), Qchar_table_p, x)
-
-#define CHECK_VECTOR(x) \
-  CHECK_TYPE (VECTORP (x), Qvectorp, x)
-
-#define CHECK_VECTOR_OR_STRING(x) \
-  CHECK_TYPE (VECTORP (x) || STRINGP (x), Qarrayp, x)
-
-#define CHECK_ARRAY(x, Qxxxp) \
-  CHECK_TYPE (ARRAYP (x), Qxxxp, x)
-
-#define CHECK_VECTOR_OR_CHAR_TABLE(x) \
-  CHECK_TYPE (VECTORP (x) || CHAR_TABLE_P (x), Qvector_or_char_table_p, x)
-
-#define CHECK_BUFFER(x) \
-  CHECK_TYPE (BUFFERP (x), Qbufferp, x)
-
-#define CHECK_WINDOW(x) \
-  CHECK_TYPE (WINDOWP (x), Qwindowp, x)
-
-#define CHECK_WINDOW_CONFIGURATION(x) \
-  CHECK_TYPE (WINDOW_CONFIGURATIONP (x), Qwindow_configuration_p, x)
-
-/* This macro rejects windows on the interior of the window tree as
-   "dead", which is what we want; this is an argument-checking macro, and
-   the user should never get access to interior windows.
-
-   A window of any sort, leaf or interior, is dead if the buffer,
-   vchild, and hchild members are all nil.  */
-
-#define CHECK_LIVE_WINDOW(x) \
-  CHECK_TYPE (WINDOWP (x) && !NILP (XWINDOW (x)->buffer), Qwindow_live_p, x)
-
-#define CHECK_PROCESS(x) \
-  CHECK_TYPE (PROCESSP (x), Qprocessp, x)
-
-#define CHECK_SUBR(x) \
-  CHECK_TYPE (SUBRP (x), Qsubrp, x)
-
-#define CHECK_NUMBER(x) \
-  CHECK_TYPE (INTEGERP (x), Qintegerp, x)
-
-#define CHECK_NATNUM(x) \
-  CHECK_TYPE (NATNUMP (x), Qwholenump, x)
+static inline void
+CHECK_LIST (Lisp_Object x)
+{
+  CHECK_TYPE (CONSP (x) || NILP (x), Qlistp, x);
+}
+static inline void
+(CHECK_LIST_CONS) (Lisp_Object x, Lisp_Object y)
+{
+  CHECK_TYPE (CONSP (x), Qlistp, y);
+}
+static inline void
+CHECK_LIST_END (Lisp_Object x, Lisp_Object y)
+{
+  CHECK_TYPE (NILP (x), Qlistp, y);
+}
+static inline void
+CHECK_STRING (Lisp_Object x)
+{
+  CHECK_TYPE (STRINGP (x), Qstringp, x);
+}
+static inline void
+CHECK_STRING_CAR (Lisp_Object x)
+{
+  CHECK_TYPE (STRINGP (XCAR (x)), Qstringp, XCAR (x));
+}
+static inline void
+CHECK_CONS (Lisp_Object x)
+{
+  CHECK_TYPE (CONSP (x), Qconsp, x);
+}
+static inline void
+(CHECK_SYMBOL) (Lisp_Object x)
+{
+  CHECK_TYPE (SYMBOLP (x), Qsymbolp, x);
+}
+static inline void
+CHECK_CHAR_TABLE (Lisp_Object x)
+{
+  CHECK_TYPE (CHAR_TABLE_P (x), Qchar_table_p, x);
+}
+static inline void
+CHECK_VECTOR (Lisp_Object x)
+{
+  CHECK_TYPE (VECTORP (x), Qvectorp, x);
+}
+static inline void
+CHECK_VECTOR_OR_STRING (Lisp_Object x)
+{
+  CHECK_TYPE (VECTORP (x) || STRINGP (x), Qarrayp, x);
+}
+static inline void
+CHECK_ARRAY (Lisp_Object x, Lisp_Object Qxxxp)
+{
+  CHECK_TYPE (ARRAYP (x), Qxxxp, x);
+}
+static inline void
+CHECK_VECTOR_OR_CHAR_TABLE (Lisp_Object x)
+{
+  CHECK_TYPE (VECTORP (x) || CHAR_TABLE_P (x), Qvector_or_char_table_p, x);
+}
+static inline void
+CHECK_BUFFER (Lisp_Object x)
+{
+  CHECK_TYPE (BUFFERP (x), Qbufferp, x);
+}
+static inline void
+CHECK_WINDOW (Lisp_Object x)
+{
+  CHECK_TYPE (WINDOWP (x), Qwindowp, x);
+}
+static inline void
+CHECK_WINDOW_CONFIGURATION (Lisp_Object x)
+{
+  CHECK_TYPE (WINDOW_CONFIGURATIONP (x), Qwindow_configuration_p, x);
+}
+static inline void
+CHECK_PROCESS (Lisp_Object x)
+{
+  CHECK_TYPE (PROCESSP (x), Qprocessp, x);
+}
+static inline void
+CHECK_SUBR (Lisp_Object x)
+{
+  CHECK_TYPE (SUBRP (x), Qsubrp, x);
+}
+static inline void
+(CHECK_NUMBER) (Lisp_Object x)
+{
+  CHECK_TYPE (INTEGERP (x), Qintegerp, x);
+}
+static inline void
+CHECK_NATNUM (Lisp_Object x)
+{
+  CHECK_TYPE (NATNUMP (x), Qwholenump, x);
+}
 
 #define CHECK_RANGED_INTEGER(x, lo, hi)					\
   do {									\
@@ -1752,57 +2292,76 @@
       CHECK_RANGED_INTEGER (x, 0, TYPE_MAXIMUM (type));			\
   } while (0)
 
-#define CHECK_MARKER(x) \
-  CHECK_TYPE (MARKERP (x), Qmarkerp, x)
+static inline void
+CHECK_MARKER (Lisp_Object x)
+{
+  CHECK_TYPE (MARKERP (x), Qmarkerp, x);
+}
 
 #define CHECK_NUMBER_COERCE_MARKER(x) \
   do { if (MARKERP ((x))) XSETFASTINT (x, marker_position (x)); \
     else CHECK_TYPE (INTEGERP (x), Qinteger_or_marker_p, x); } while (0)
 
-#define XFLOATINT(n) extract_float((n))
-
-#define CHECK_FLOAT(x) \
-  CHECK_TYPE (FLOATP (x), Qfloatp, x)
-
-#define CHECK_NUMBER_OR_FLOAT(x) \
-  CHECK_TYPE (FLOATP (x) || INTEGERP (x), Qnumberp, x)
+static inline double
+XFLOATINT (Lisp_Object n)
+{
+  return extract_float (n);
+}
+
+static inline void
+CHECK_FLOAT (Lisp_Object x)
+{
+  CHECK_TYPE (FLOATP (x), Qfloatp, x);
+}
+static inline void
+CHECK_NUMBER_OR_FLOAT (Lisp_Object x)
+{
+  CHECK_TYPE (FLOATP (x) || INTEGERP (x), Qnumberp, x);
+}
 
 #define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER(x) \
   do { if (MARKERP (x)) XSETFASTINT (x, marker_position (x)); \
     else CHECK_TYPE (INTEGERP (x) || FLOATP (x), Qnumber_or_marker_p, x); } while (0)
 
-#define CHECK_OVERLAY(x) \
-  CHECK_TYPE (OVERLAYP (x), Qoverlayp, x)
+static inline void
+CHECK_OVERLAY (Lisp_Object x)
+{
+  CHECK_TYPE (OVERLAYP (x), Qoverlayp, x);
+}
 
 /* Since we can't assign directly to the CAR or CDR fields of a cons
    cell, use these when checking that those fields contain numbers.  */
-#define CHECK_NUMBER_CAR(x) \
-  do {					\
-    Lisp_Object tmp = XCAR (x);		\
-    CHECK_NUMBER (tmp);			\
-    XSETCAR ((x), tmp);			\
-  } while (0)
-
-#define CHECK_NUMBER_CDR(x) \
-  do {					\
-    Lisp_Object tmp = XCDR (x);		\
-    CHECK_NUMBER (tmp);			\
-    XSETCDR ((x), tmp);			\
-  } while (0)
-
-#define CHECK_NATNUM_CAR(x) \
-  do {					\
-    Lisp_Object tmp = XCAR (x);		\
-    CHECK_NATNUM (tmp);			\
-    XSETCAR ((x), tmp);			\
-  } while (0)
-
-#define CHECK_NATNUM_CDR(x) \
-  do {					\
-    Lisp_Object tmp = XCDR (x);		\
-    CHECK_NATNUM (tmp);			\
-    XSETCDR ((x), tmp);			\
-  } while (0)
+static inline void
+CHECK_NUMBER_CAR (Lisp_Object x)
+{
+  Lisp_Object tmp = XCAR (x);
+  CHECK_NUMBER (tmp);
+  XSETCAR (x, tmp);
+}
+
+static inline void
+CHECK_NUMBER_CDR (Lisp_Object x)
+{
+  Lisp_Object tmp = XCDR (x);
+  CHECK_NUMBER (tmp);
+  XSETCDR (x, tmp);
+}
+
+static inline void
+CHECK_NATNUM_CAR (Lisp_Object x)
+{
+  Lisp_Object tmp = XCAR (x);
+  CHECK_NATNUM (tmp);
+  XSETCAR (x, tmp);
+}
+
+static inline void
+CHECK_NATNUM_CDR (Lisp_Object x)
+{
+  Lisp_Object tmp = XCDR (x);
+  CHECK_NATNUM (tmp);
+  XSETCDR (x, tmp);
+}
 
 /* Define a built-in function for calling from Lisp.
  `lname' should be the name to give the function in Lisp,
@@ -1869,18 +2428,20 @@
 			 Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object)
 
 /* Non-zero if OBJ is a Lisp function.  */
-#define FUNCTIONP(OBJ)					\
-     ((CONSP (OBJ) && EQ (XCAR (OBJ), Qlambda))		\
-      || (SYMBOLP (OBJ) && !NILP (Ffboundp (OBJ)))	\
-      || COMPILEDP (OBJ)				\
-      || SUBRP (OBJ))
+static inline int
+FUNCTIONP (Lisp_Object obj)
+{
+  return ((CONSP (obj) && EQ (XCAR (obj), Qlambda))
+	  || (SYMBOLP (obj) && !NILP (Ffboundp (obj)))
+	  || COMPILEDP (obj)
+	  || SUBRP (obj));
+}
 
 /* defsubr (Sname);
    is how we define the symbol for function `name' at start-up time.  */
 extern void defsubr (struct Lisp_Subr *);
 
-#define MANY -2
-#define UNEVALLED -1
+enum { MANY = -2, UNEVALLED = -1 };
 
 extern void defvar_lisp (struct Lisp_Objfwd *, const char *, Lisp_Object *);
 extern void defvar_lisp_nopro (struct Lisp_Objfwd *, const char *, Lisp_Object *);
@@ -1973,7 +2534,11 @@
 extern struct specbinding *specpdl_ptr;
 extern ptrdiff_t specpdl_size;
 
-#define SPECPDL_INDEX()	(specpdl_ptr - specpdl)
+static inline ptrdiff_t
+SPECPDL_INDEX (void)
+{
+  return specpdl_ptr - specpdl;
+}
 
 /* Everything needed to describe an active condition case.  */
 struct handler
@@ -2283,6 +2848,8 @@
 #define EXFUN(fnname, maxargs) \
   extern Lisp_Object fnname DEFUN_ARGS_ ## maxargs
 
+#include "globals.h"
+
 /* Forward declarations for prototypes.  */
 struct window;
 struct frame;
@@ -2317,6 +2884,7 @@
 extern Lisp_Object Qinteger, Qinterval, Qsymbol, Qstring;
 extern Lisp_Object Qmisc, Qvector, Qfloat, Qcons, Qbuffer;
 
+extern Lisp_Object Qsubrp;
 extern Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
 
 EXFUN (Fbyteorder, 0) ATTRIBUTE_CONST;
@@ -2411,6 +2979,7 @@
 extern Lisp_Object Qcursor_in_echo_area;
 extern Lisp_Object Qstring_lessp;
 extern Lisp_Object QCsize, QCtest, QCweakness, Qequal, Qeq, Qeql;
+extern Lisp_Object Qhash_table_p;
 EMACS_UINT hash_string (char const *, ptrdiff_t);
 EMACS_UINT sxhash (Lisp_Object, int);
 Lisp_Object make_hash_table (Lisp_Object, Lisp_Object, Lisp_Object,
@@ -2706,7 +3275,7 @@
 				 Lisp_Object);
 extern Lisp_Object internal_with_output_to_temp_buffer
         (const char *, Lisp_Object (*) (Lisp_Object), Lisp_Object);
-#define FLOAT_TO_STRING_BUFSIZE 350
+enum { FLOAT_TO_STRING_BUFSIZE = 350 };
 extern int float_to_string (char *, double);
 extern void syms_of_print (void);
 
@@ -2729,10 +3298,12 @@
 extern Lisp_Object intern_1 (const char *, ptrdiff_t);
 extern Lisp_Object intern_c_string_1 (const char *, ptrdiff_t);
 extern Lisp_Object oblookup (Lisp_Object, const char *, ptrdiff_t, ptrdiff_t);
-#define LOADHIST_ATTACH(x) \
-  do {									\
-    if (initialized) Vcurrent_load_list = Fcons (x, Vcurrent_load_list); \
-  } while (0)
+static inline void
+LOADHIST_ATTACH (Lisp_Object x)
+{
+  if (initialized)
+    Vcurrent_load_list = Fcons (x, Vcurrent_load_list);
+}
 extern int openp (Lisp_Object, Lisp_Object, Lisp_Object,
                   Lisp_Object *, Lisp_Object);
 Lisp_Object string_to_number (char const *, int, int);
@@ -2850,6 +3421,7 @@
 extern Lisp_Object Vbuffer_alist;
 extern Lisp_Object set_buffer_if_live (Lisp_Object);
 extern Lisp_Object other_buffer_safely (Lisp_Object);
+extern Lisp_Object Qoverlayp;
 extern Lisp_Object Qpriority, Qwindow, Qbefore_string, Qafter_string;
 extern Lisp_Object get_truename_buffer (Lisp_Object);
 extern void init_buffer_once (void);
@@ -3007,10 +3579,10 @@
 void synchronize_system_messages_locale (void);
 void synchronize_system_time_locale (void);
 #else
-#define setlocale(category, locale)
-#define fixup_locale()
-#define synchronize_system_messages_locale()
-#define synchronize_system_time_locale()
+static inline char *setlocale (int cat, char const *locale) { return 0; }
+static inline void fixup_locale (void) {}
+static inline void synchronize_system_messages_locale (void) {}
+static inline void synchronize_system_time_locale (void) {}
 #endif
 void shut_down_emacs (int, int, Lisp_Object);
 /* Nonzero means don't do interactive redisplay and don't change tty modes.  */
@@ -3271,19 +3843,19 @@
    in addition to a device separator.  Set the path separator
    to '/', and don't test for a device separator in IS_ANY_SEP.  */
 
-#define DIRECTORY_SEP '/'
+enum { DIRECTORY_SEP = '/' };
 #ifndef IS_DIRECTORY_SEP
-#define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP)
+static inline int IS_DIRECTORY_SEP (int c) { return c == DIRECTORY_SEP; }
 #endif
 #ifndef IS_DEVICE_SEP
 #ifndef DEVICE_SEP
-#define IS_DEVICE_SEP(_c_) 0
+static inline int IS_DEVICE_SEP (int c) { return 0; }
 #else
-#define IS_DEVICE_SEP(_c_) ((_c_) == DEVICE_SEP)
+static inline int IS_DEVICE_SEP (int c) { return c == DEVICE_SEP; }
 #endif
 #endif
 #ifndef IS_ANY_SEP
-#define IS_ANY_SEP(_c_) (IS_DIRECTORY_SEP (_c_))
+static inline int IS_ANY_SEP (int c) { return IS_DIRECTORY_SEP (c); }
 #endif
 
 #define SWITCH_ENUM_CAST(x) (x)
@@ -3303,15 +3875,6 @@
 # define lint_assume(cond) ((void) (0 && (cond)))
 #endif
 
-/* The ubiquitous min and max macros.  */
-
-#ifdef max
-#undef max
-#undef min
-#endif
-#define min(a, b)	((a) < (b) ? (a) : (b))
-#define max(a, b)	((a) > (b) ? (a) : (b))
-
 /* We used to use `abs', but that clashes with system headers on some
    platforms, and using a name reserved by Standard C is a bad idea
    anyway.  */
@@ -3354,7 +3917,7 @@
 /* SAFE_ALLOCA normally allocates memory on the stack, but if size is
    larger than MAX_ALLOCA, use xmalloc to avoid overflowing the stack.  */
 
-#define MAX_ALLOCA 16*1024
+enum { MAX_ALLOCA = 16*1024 };
 
 extern Lisp_Object safe_alloca_unwind (Lisp_Object);
 
@@ -3424,8 +3987,6 @@
   } while (0)

-#include "globals.h"
-
 /* Check whether it's time for GC, and run it if so.  */
 
 static inline void

=== modified file 'src/mem-limits.h'
--- src/mem-limits.h	2012-07-09 16:38:45 +0000
+++ src/mem-limits.h	2012-07-13 03:37:42 +0000
@@ -36,9 +36,7 @@
 extern char *start_of_data (void) ATTRIBUTE_CONST;
 #if USE_LSB_TAG || UINTPTR_MAX <= VAL_MAX
 #define EXCEEDS_LISP_PTR(ptr) 0
-#elif defined DATA_SEG_BITS
+#else
 #define EXCEEDS_LISP_PTR(ptr) \
   (((uintptr_t) (ptr) & ~DATA_SEG_BITS) >> VALBITS)
-#else
-#define EXCEEDS_LISP_PTR(ptr) ((uintptr_t) (ptr) >> VALBITS)
 #endif

=== modified file 'src/window.c'
--- src/window.c	2012-07-23 16:57:20 +0000
+++ src/window.c	2012-07-23 21:50:36 +0000
@@ -51,8 +51,8 @@
 #include "nsterm.h"
 #endif
 
-Lisp_Object Qwindowp, Qwindow_live_p;
-static Lisp_Object Qwindow_configuration_p, Qrecord_window_buffer;
+Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
+static Lisp_Object Qrecord_window_buffer;
 static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer;
 static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
 static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically;

=== modified file 'src/window.h'
--- src/window.h	2012-07-05 15:20:12 +0000
+++ src/window.h	2012-07-13 03:37:42 +0000
@@ -885,7 +885,7 @@
 
 /* These used to be in lisp.h.  */
 
-extern Lisp_Object Qwindowp, Qwindow_live_p;
+extern Lisp_Object Qwindow_live_p;
 extern Lisp_Object Vwindow_list;
 
 extern int compare_window_configurations (Lisp_Object, Lisp_Object, int);
@@ -900,4 +900,17 @@
 extern void syms_of_window (void);
 extern void keys_of_window (void);
 
+/* CHECK_LIVE_WINDOW rejects windows on the interior of the window tree as
+   "dead", which is what we want; this is an argument-checking function, and
+   the user should never get access to interior windows.
+
+   A window of any sort, leaf or interior, is dead if the buffer,
+   vchild, and hchild members are all nil.  */
+static inline void
+CHECK_LIVE_WINDOW (Lisp_Object x)
+{
+  CHECK_TYPE (WINDOWP (x) && !NILP (XWINDOW (x)->buffer), Qwindow_live_p, x);
+}
+
+
 #endif /* not WINDOW_H_INCLUDED */