aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2017-12-12 12:59:57 -0800
committerPaul Eggert2017-12-12 15:17:12 -0800
commit244346c744a6700d320a0a0fe8c796be3b3ff023 (patch)
tree145dc0ba87fcf82de44e62ecbdeb70fe86c28c7a /src
parentc705f7250d6f17f1682ee5ad7eec516dbf6c3916 (diff)
downloademacs-244346c744a6700d320a0a0fe8c796be3b3ff023.tar.gz
emacs-244346c744a6700d320a0a0fe8c796be3b3ff023.zip
Reimplement Lisp_Object as pointer-to-incomplete
This makes Lisp_Object values opaque pointers instead of integers, which helps avoid the same sort of typos that CHECK_LISP_OBJECT_TYPE helps to avoid, without having to wrap pointers inside structures. This also looks forward to supporting -fcheck-pointer-bounds. * etc/DEBUG: * src/.gdbinit (Lisp_Object_Printer.to_string): Lisp_Object can be a pointer type now. * src/alloc.c (macro_XPNTR, XPNTR): * src/emacs-module.c (value_to_lisp_bits, lisp_to_value_bits): * src/lisp.h (lisp_h_XLI, lisp_h_XIL): (lisp_h_XUNTAG) [USE_LSB_TAG]: (XUNTAG) [!USE_LSB_TAG]: (Lisp_Object, TAG_PTR, make_lisp_symbol): Support new Lisp_Object implementation as a pointer to an incomplete type. Keep pointers pointers, as much as possible. * src/alloc.c (macro_XPNTR_OR_SYMBOL_OFFSET, XPNTR_OR_SYMBOL_OFFSET): Remove. All uses replaced by plain XPNTR. * src/emacs-module.c: Work around GCC bug 83162. * src/lisp.h (LISP_WORDS_ARE_POINTERS, lisp_h_XLP, lisp_h_XPL): (XLP, XPL) [DEFINE_KEY_OPS_AS_MACROS]: New macros. (Lisp_Word, untagged_ptr, Lisp_Word_tag): New types. (XLP, XPL): New inline functions. (TAG_PTR): Now expands to an initializer, not an expression. All uses changed. (TAG_SYMOFFSET, XLI_BUILTIN_LISPSYM): Remove. All uses removed. (LISPSYM_INITIALLY): Redo in terms of the new TAG_PTR. (NIL_IS_ZERO): Redo without XLI_BUILTIN_LISPSYM. * src/xwidget.c (webkit_javascript_finished_cb): Use XPL instead of XIL with a non-EMACS_INT arg. (Fxwidget_webkit_execute_script): Use XLP instead of XLI followed by two conversions.
Diffstat (limited to 'src')
-rw-r--r--src/.gdbinit16
-rw-r--r--src/alloc.c39
-rw-r--r--src/emacs-module.c30
-rw-r--r--src/lisp.h154
-rw-r--r--src/xwidget.c5
5 files changed, 156 insertions, 88 deletions
diff --git a/src/.gdbinit b/src/.gdbinit
index e22d03ea476..0eb2c73591f 100644
--- a/src/.gdbinit
+++ b/src/.gdbinit
@@ -1321,19 +1321,26 @@ if hasattr(gdb, 'printing'):
1321 Lisp_Int0 = 2 1321 Lisp_Int0 = 2
1322 Lisp_Int1 = 6 if USE_LSB_TAG else 3 1322 Lisp_Int1 = 6 if USE_LSB_TAG else 3
1323 1323
1324 # Unpack the Lisp value from its containing structure, if necessary.
1325 val = self.val 1324 val = self.val
1326 basic_type = gdb.types.get_basic_type (val.type) 1325 basic_type = gdb.types.get_basic_type (val.type)
1326
1327 # Unpack VAL from its containing structure, if necessary.
1327 if (basic_type.code == gdb.TYPE_CODE_STRUCT 1328 if (basic_type.code == gdb.TYPE_CODE_STRUCT
1328 and gdb.types.has_field (basic_type, "i")): 1329 and gdb.types.has_field (basic_type, "i")):
1329 val = val["i"] 1330 val = val["i"]
1330 1331
1332 # Convert VAL to a Python integer. Convert by hand, as this is
1333 # simpler and works regardless of whether VAL is a pointer or
1334 # integer. Also, val.cast (gdb.lookup.type ("EMACS_UINT"))
1335 # would have problems with GDB 7.12.1; see
1336 # <http://patchwork.sourceware.org/patch/11557/>.
1337 ival = int (val)
1338
1331 # For nil, yield "XIL(0)", which is easier to read than "XIL(0x0)". 1339 # For nil, yield "XIL(0)", which is easier to read than "XIL(0x0)".
1332 if not val: 1340 if not ival:
1333 return "XIL(0)" 1341 return "XIL(0)"
1334 1342
1335 # Extract the integer representation of the value and its Lisp type. 1343 # Extract the integer representation of the value and its Lisp type.
1336 ival = int(val)
1337 itype = ival >> (0 if USE_LSB_TAG else VALBITS) 1344 itype = ival >> (0 if USE_LSB_TAG else VALBITS)
1338 itype = itype & ((1 << GCTYPEBITS) - 1) 1345 itype = itype & ((1 << GCTYPEBITS) - 1)
1339 1346
@@ -1352,8 +1359,7 @@ if hasattr(gdb, 'printing'):
1352 # integers even when Lisp_Object is an integer. 1359 # integers even when Lisp_Object is an integer.
1353 # Perhaps some day the pretty-printing could be fancier. 1360 # Perhaps some day the pretty-printing could be fancier.
1354 # Prefer the unsigned representation to negative values, converting 1361 # Prefer the unsigned representation to negative values, converting
1355 # by hand as val.cast(gdb.lookup_type("EMACS_UINT") does not work in 1362 # by hand as val.cast does not work in GDB 7.12.1 as noted above.
1356 # GDB 7.12.1; see <http://patchwork.sourceware.org/patch/11557/>.
1357 if ival < 0: 1363 if ival < 0:
1358 ival = ival + (1 << EMACS_INT_WIDTH) 1364 ival = ival + (1 << EMACS_INT_WIDTH)
1359 return "XIL(0x%x)" % ival 1365 return "XIL(0x%x)" % ival
diff --git a/src/alloc.c b/src/alloc.c
index 4f3928a4824..38daee065ae 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -502,30 +502,20 @@ pointer_align (void *ptr, int alignment)
502 return (void *) ROUNDUP ((uintptr_t) ptr, alignment); 502 return (void *) ROUNDUP ((uintptr_t) ptr, alignment);
503} 503}
504 504
505/* Extract the pointer hidden within A, if A is not a symbol. 505/* Extract the pointer hidden within O. Define this as a function, as
506 If A is a symbol, extract the hidden pointer's offset from lispsym, 506 functions are cleaner and can be used in debuggers. Also, define
507 converted to void *. */ 507 it as a macro if being compiled with GCC without optimization, for
508 performance in that case. macro_XPNTR is private to this section
509 of code. */
510
511#define macro_XPNTR(o) \
512 ((void *) \
513 (SYMBOLP (o) \
514 ? ((char *) lispsym \
515 - ((EMACS_UINT) Lisp_Symbol << (USE_LSB_TAG ? 0 : VALBITS)) \
516 + XLI (o)) \
517 : (char *) XLP (o) - (XLI (o) & ~VALMASK)))
508 518
509#define macro_XPNTR_OR_SYMBOL_OFFSET(a) \
510 ((void *) (intptr_t) (USE_LSB_TAG ? XLI (a) - XTYPE (a) : XLI (a) & VALMASK))
511
512/* Extract the pointer hidden within A. */
513
514#define macro_XPNTR(a) \
515 ((void *) ((intptr_t) XPNTR_OR_SYMBOL_OFFSET (a) \
516 + (SYMBOLP (a) ? (char *) lispsym : NULL)))
517
518/* For pointer access, define XPNTR and XPNTR_OR_SYMBOL_OFFSET as
519 functions, as functions are cleaner and can be used in debuggers.
520 Also, define them as macros if being compiled with GCC without
521 optimization, for performance in that case. The macro_* names are
522 private to this section of code. */
523
524static ATTRIBUTE_UNUSED void *
525XPNTR_OR_SYMBOL_OFFSET (Lisp_Object a)
526{
527 return macro_XPNTR_OR_SYMBOL_OFFSET (a);
528}
529static ATTRIBUTE_UNUSED void * 519static ATTRIBUTE_UNUSED void *
530XPNTR (Lisp_Object a) 520XPNTR (Lisp_Object a)
531{ 521{
@@ -533,7 +523,6 @@ XPNTR (Lisp_Object a)
533} 523}
534 524
535#if DEFINE_KEY_OPS_AS_MACROS 525#if DEFINE_KEY_OPS_AS_MACROS
536# define XPNTR_OR_SYMBOL_OFFSET(a) macro_XPNTR_OR_SYMBOL_OFFSET (a)
537# define XPNTR(a) macro_XPNTR (a) 526# define XPNTR(a) macro_XPNTR (a)
538#endif 527#endif
539 528
@@ -5605,7 +5594,7 @@ static Lisp_Object
5605purecopy (Lisp_Object obj) 5594purecopy (Lisp_Object obj)
5606{ 5595{
5607 if (INTEGERP (obj) 5596 if (INTEGERP (obj)
5608 || (! SYMBOLP (obj) && PURE_P (XPNTR_OR_SYMBOL_OFFSET (obj))) 5597 || (! SYMBOLP (obj) && PURE_P (XPNTR (obj)))
5609 || SUBRP (obj)) 5598 || SUBRP (obj))
5610 return obj; /* Already pure. */ 5599 return obj; /* Already pure. */
5611 5600
diff --git a/src/emacs-module.c b/src/emacs-module.c
index b351515c3bd..9a02e7d4821 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -36,6 +36,11 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
36#include <intprops.h> 36#include <intprops.h>
37#include <verify.h> 37#include <verify.h>
38 38
39/* Work around GCC bug 83162. */
40#if GNUC_PREREQ (4, 3, 0)
41# pragma GCC diagnostic ignored "-Wclobbered"
42#endif
43
39/* We use different strategies for allocating the user-visible objects 44/* We use different strategies for allocating the user-visible objects
40 (struct emacs_runtime, emacs_env, emacs_value), depending on 45 (struct emacs_runtime, emacs_env, emacs_value), depending on
41 whether the user supplied the -module-assertions flag. If 46 whether the user supplied the -module-assertions flag. If
@@ -915,9 +920,8 @@ static Lisp_Object ltv_mark;
915static Lisp_Object 920static Lisp_Object
916value_to_lisp_bits (emacs_value v) 921value_to_lisp_bits (emacs_value v)
917{ 922{
918 intptr_t i = (intptr_t) v;
919 if (plain_values || USE_LSB_TAG) 923 if (plain_values || USE_LSB_TAG)
920 return XIL (i); 924 return XPL (v);
921 925
922 /* With wide EMACS_INT and when tag bits are the most significant, 926 /* With wide EMACS_INT and when tag bits are the most significant,
923 reassembling integers differs from reassembling pointers in two 927 reassembling integers differs from reassembling pointers in two
@@ -926,6 +930,7 @@ value_to_lisp_bits (emacs_value v)
926 integer when restoring, but zero-extend pointers because that 930 integer when restoring, but zero-extend pointers because that
927 makes TAG_PTR faster. */ 931 makes TAG_PTR faster. */
928 932
933 intptr_t i = (intptr_t) v;
929 EMACS_UINT tag = i & (GCALIGNMENT - 1); 934 EMACS_UINT tag = i & (GCALIGNMENT - 1);
930 EMACS_UINT untagged = i - tag; 935 EMACS_UINT untagged = i - tag;
931 switch (tag) 936 switch (tag)
@@ -989,13 +994,22 @@ value_to_lisp (emacs_value v)
989static emacs_value 994static emacs_value
990lisp_to_value_bits (Lisp_Object o) 995lisp_to_value_bits (Lisp_Object o)
991{ 996{
992 EMACS_UINT u = XLI (o); 997 if (plain_values || USE_LSB_TAG)
998 return XLP (o);
993 999
994 /* Compress U into the space of a pointer, possibly losing information. */ 1000 /* Compress O into the space of a pointer, possibly losing information. */
995 uintptr_t p = (plain_values || USE_LSB_TAG 1001 EMACS_UINT u = XLI (o);
996 ? u 1002 if (INTEGERP (o))
997 : (INTEGERP (o) ? u << VALBITS : u & VALMASK) + XTYPE (o)); 1003 {
998 return (emacs_value) p; 1004 uintptr_t i = (u << VALBITS) + XTYPE (o);
1005 return (emacs_value) i;
1006 }
1007 else
1008 {
1009 char *p = XLP (o);
1010 void *v = p - (u & ~VALMASK) + XTYPE (o);
1011 return v;
1012 }
999} 1013}
1000 1014
1001/* Convert O to an emacs_value. Allocate storage if needed; this can 1015/* Convert O to an emacs_value. Allocate storage if needed; this can
diff --git a/src/lisp.h b/src/lisp.h
index 91ed14fa4c9..54103d4bebc 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -277,6 +277,18 @@ DEFINE_GDB_SYMBOL_END (VALMASK)
277error !; 277error !;
278#endif 278#endif
279 279
280/* Lisp_Word is a scalar word suitable for holding a tagged pointer or
281 integer. Usually it is a pointer to a deliberately-incomplete type
282 'union Lisp_X'. However, it is EMACS_INT when Lisp_Objects and
283 pointers differ in width. */
284
285#define LISP_WORDS_ARE_POINTERS (EMACS_INT_MAX == INTPTR_MAX)
286#if LISP_WORDS_ARE_POINTERS
287typedef union Lisp_X *Lisp_Word;
288#else
289typedef EMACS_INT Lisp_Word;
290#endif
291
280/* Some operations are so commonly executed that they are implemented 292/* Some operations are so commonly executed that they are implemented
281 as macros, not functions, because otherwise runtime performance would 293 as macros, not functions, because otherwise runtime performance would
282 suffer too much when compiling with GCC without optimization. 294 suffer too much when compiling with GCC without optimization.
@@ -302,16 +314,37 @@ error !;
302 functions, once "gcc -Og" (new to GCC 4.8) works well enough for 314 functions, once "gcc -Og" (new to GCC 4.8) works well enough for
303 Emacs developers. Maybe in the year 2020. See Bug#11935. 315 Emacs developers. Maybe in the year 2020. See Bug#11935.
304 316
305 Commentary for these macros can be found near their corresponding 317 For the macros that have corresponding functions (defined later),
306 functions, below. */ 318 see these functions for commentary. */
307 319
308#if CHECK_LISP_OBJECT_TYPE 320/* Convert among the various Lisp-related types: I for EMACS_INT, L
309# define lisp_h_XLI(o) ((o).i) 321 for Lisp_Object, P for void *. */
310# define lisp_h_XIL(i) ((Lisp_Object) { i }) 322#if !CHECK_LISP_OBJECT_TYPE
323# if LISP_WORDS_ARE_POINTERS
324# define lisp_h_XLI(o) ((EMACS_INT) (o))
325# define lisp_h_XIL(i) ((Lisp_Object) (i))
326# define lisp_h_XLP(o) ((void *) (o))
327# define lisp_h_XPL(p) ((Lisp_Object) (p))
328# else
329# define lisp_h_XLI(o) (o)
330# define lisp_h_XIL(i) (i)
331# define lisp_h_XLP(o) ((void *) (uintptr_t) (o))
332# define lisp_h_XPL(p) ((Lisp_Object) (uintptr_t) (p))
333# endif
311#else 334#else
312# define lisp_h_XLI(o) (o) 335# if LISP_WORDS_ARE_POINTERS
313# define lisp_h_XIL(i) (i) 336# define lisp_h_XLI(o) ((EMACS_INT) (o).i)
337# define lisp_h_XIL(i) ((Lisp_Object) {(Lisp_Word) (i)})
338# define lisp_h_XLP(o) ((void *) (o).i)
339# define lisp_h_XPL(p) lisp_h_XIL (p)
340# else
341# define lisp_h_XLI(o) ((o).i)
342# define lisp_h_XIL(i) ((Lisp_Object) {i})
343# define lisp_h_XLP(o) ((void *) (uintptr_t) (o).i)
344# define lisp_h_XPL(p) ((Lisp_Object) {(uintptr_t) (p)})
345# endif
314#endif 346#endif
347
315#define lisp_h_CHECK_NUMBER(x) CHECK_TYPE (INTEGERP (x), Qintegerp, x) 348#define lisp_h_CHECK_NUMBER(x) CHECK_TYPE (INTEGERP (x), Qintegerp, x)
316#define lisp_h_CHECK_SYMBOL(x) CHECK_TYPE (SYMBOLP (x), Qsymbolp, x) 349#define lisp_h_CHECK_SYMBOL(x) CHECK_TYPE (SYMBOLP (x), Qsymbolp, x)
317#define lisp_h_CHECK_TYPE(ok, predicate, x) \ 350#define lisp_h_CHECK_TYPE(ok, predicate, x) \
@@ -352,8 +385,7 @@ error !;
352 + (char *) lispsym)) 385 + (char *) lispsym))
353# define lisp_h_XTYPE(a) ((enum Lisp_Type) (XLI (a) & ~VALMASK)) 386# define lisp_h_XTYPE(a) ((enum Lisp_Type) (XLI (a) & ~VALMASK))
354# define lisp_h_XUNTAG(a, type) \ 387# define lisp_h_XUNTAG(a, type) \
355 __builtin_assume_aligned ((void *) (intptr_t) (XLI (a) - (type)), \ 388 __builtin_assume_aligned ((char *) XLP (a) - (type), GCALIGNMENT)
356 GCALIGNMENT)
357#endif 389#endif
358 390
359/* When compiling via gcc -O0, define the key operations as macros, as 391/* When compiling via gcc -O0, define the key operations as macros, as
@@ -370,6 +402,8 @@ error !;
370#if DEFINE_KEY_OPS_AS_MACROS 402#if DEFINE_KEY_OPS_AS_MACROS
371# define XLI(o) lisp_h_XLI (o) 403# define XLI(o) lisp_h_XLI (o)
372# define XIL(i) lisp_h_XIL (i) 404# define XIL(i) lisp_h_XIL (i)
405# define XLP(o) lisp_h_XLP (o)
406# define XPL(p) lisp_h_XPL (p)
373# define CHECK_NUMBER(x) lisp_h_CHECK_NUMBER (x) 407# define CHECK_NUMBER(x) lisp_h_CHECK_NUMBER (x)
374# define CHECK_SYMBOL(x) lisp_h_CHECK_SYMBOL (x) 408# define CHECK_SYMBOL(x) lisp_h_CHECK_SYMBOL (x)
375# define CHECK_TYPE(ok, predicate, x) lisp_h_CHECK_TYPE (ok, predicate, x) 409# define CHECK_TYPE(ok, predicate, x) lisp_h_CHECK_TYPE (ok, predicate, x)
@@ -543,22 +577,24 @@ enum Lisp_Fwd_Type
543 your object -- this way, the same object could be used to represent 577 your object -- this way, the same object could be used to represent
544 several disparate C structures. */ 578 several disparate C structures. */
545 579
546#ifdef CHECK_LISP_OBJECT_TYPE
547 580
548typedef struct Lisp_Object { EMACS_INT i; } Lisp_Object; 581/* A Lisp_Object is a tagged pointer or integer. Ordinarily it is a
582 Lisp_Word. However, if CHECK_LISP_OBJECT_TYPE, it is a wrapper
583 around Lisp_Word, to help catch thinkos like 'Lisp_Object x = 0;'.
549 584
550#define LISP_INITIALLY(i) {i} 585 LISP_INITIALLY (W) initializes a Lisp object with a tagged value
586 that is a Lisp_Word W. It can be used in a static initializer. */
551 587
552#undef CHECK_LISP_OBJECT_TYPE 588#ifdef CHECK_LISP_OBJECT_TYPE
589typedef struct Lisp_Object { Lisp_Word i; } Lisp_Object;
590# define LISP_INITIALLY(w) {w}
591# undef CHECK_LISP_OBJECT_TYPE
553enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = true }; 592enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = true };
554#else /* CHECK_LISP_OBJECT_TYPE */ 593#else
555 594typedef Lisp_Word Lisp_Object;
556/* If a struct type is not wanted, define Lisp_Object as just a number. */ 595# define LISP_INITIALLY(w) (w)
557
558typedef EMACS_INT Lisp_Object;
559#define LISP_INITIALLY(i) (i)
560enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = false }; 596enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = false };
561#endif /* CHECK_LISP_OBJECT_TYPE */ 597#endif
562 598
563/* Forward declarations. */ 599/* Forward declarations. */
564 600
@@ -590,8 +626,10 @@ extern double extract_float (Lisp_Object);
590 626
591/* Low-level conversion and type checking. */ 627/* Low-level conversion and type checking. */
592 628
593/* Convert a Lisp_Object to the corresponding EMACS_INT and vice versa. 629/* Convert among various types use to implement Lisp_Object. At the
594 At the machine level, these operations are no-ops. */ 630 machine level, these operations may widen or narrow their arguments
631 if pointers differ in width from EMACS_INT; otherwise they are
632 no-ops. */
595 633
596INLINE EMACS_INT 634INLINE EMACS_INT
597(XLI) (Lisp_Object o) 635(XLI) (Lisp_Object o)
@@ -605,6 +643,18 @@ INLINE Lisp_Object
605 return lisp_h_XIL (i); 643 return lisp_h_XIL (i);
606} 644}
607 645
646INLINE void *
647(XLP) (Lisp_Object o)
648{
649 return lisp_h_XLP (o);
650}
651
652INLINE Lisp_Object
653(XPL) (void *p)
654{
655 return lisp_h_XPL (p);
656}
657
608/* Extract A's type. */ 658/* Extract A's type. */
609 659
610INLINE enum Lisp_Type 660INLINE enum Lisp_Type
@@ -632,8 +682,9 @@ INLINE void *
632#if USE_LSB_TAG 682#if USE_LSB_TAG
633 return lisp_h_XUNTAG (a, type); 683 return lisp_h_XUNTAG (a, type);
634#else 684#else
635 intptr_t i = USE_LSB_TAG ? XLI (a) - type : XLI (a) & VALMASK; 685 EMACS_UINT utype = type;
636 return (void *) i; 686 char *p = XLP (a);
687 return p - (utype << (USE_LSB_TAG ? 0 : VALBITS));
637#endif 688#endif
638} 689}
639 690
@@ -744,28 +795,34 @@ verify (alignof (struct Lisp_Symbol) % GCALIGNMENT == 0);
744#define DEFUN_ARGS_8 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ 795#define DEFUN_ARGS_8 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \
745 Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object) 796 Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object)
746 797
747/* Yield a signed integer that contains TAG along with PTR. 798/* Typedefs useful for implementing TAG_PTR. untagged_ptr represents
799 a pointer before tagging, and Lisp_Word_tag contains a
800 possibly-shifted tag to be added to an untagged_ptr to convert it
801 to a Lisp_Word. */
802#if LISP_WORDS_ARE_POINTERS
803/* untagged_ptr is a pointer so that the compiler knows that TAG_PTR
804 yields a pointer; this can help with gcc -fcheck-pointer-bounds.
805 It is char * so that adding a tag uses simple machine addition. */
806typedef char *untagged_ptr;
807typedef uintptr_t Lisp_Word_tag;
808#else
809/* untagged_ptr is an unsigned integer instead of a pointer, so that
810 it can be added to the possibly-wider Lisp_Word_tag type without
811 losing information. */
812typedef uintptr_t untagged_ptr;
813typedef EMACS_UINT Lisp_Word_tag;
814#endif
748 815
749 Sign-extend pointers when USE_LSB_TAG (this simplifies emacs-module.c), 816/* An initializer for a Lisp_Object that contains TAG along with PTR. */
750 and zero-extend otherwise (that’s a bit faster here).
751 Sign extension matters only when EMACS_INT is wider than a pointer. */
752#define TAG_PTR(tag, ptr) \ 817#define TAG_PTR(tag, ptr) \
753 (USE_LSB_TAG \ 818 LISP_INITIALLY ((Lisp_Word) \
754 ? (intptr_t) (ptr) + (tag) \ 819 ((untagged_ptr) (ptr) \
755 : (EMACS_INT) (((EMACS_UINT) (tag) << VALBITS) + (uintptr_t) (ptr))) 820 + ((Lisp_Word_tag) (tag) << (USE_LSB_TAG ? 0 : VALBITS))))
756
757/* Yield an integer that contains a symbol tag along with OFFSET.
758 OFFSET should be the offset in bytes from 'lispsym' to the symbol. */
759#define TAG_SYMOFFSET(offset) TAG_PTR (Lisp_Symbol, offset)
760
761/* XLI_BUILTIN_LISPSYM (iQwhatever) is equivalent to
762 XLI (builtin_lisp_symbol (Qwhatever)),
763 except the former expands to an integer constant expression. */
764#define XLI_BUILTIN_LISPSYM(iname) TAG_SYMOFFSET ((iname) * sizeof *lispsym)
765 821
766/* LISPSYM_INITIALLY (Qfoo) is equivalent to Qfoo except it is 822/* LISPSYM_INITIALLY (Qfoo) is equivalent to Qfoo except it is
767 designed for use as an initializer, even for a constant initializer. */ 823 designed for use as an initializer, even for a constant initializer. */
768#define LISPSYM_INITIALLY(name) LISP_INITIALLY (XLI_BUILTIN_LISPSYM (i##name)) 824#define LISPSYM_INITIALLY(name) \
825 TAG_PTR (Lisp_Symbol, (char *) (intptr_t) ((i##name) * sizeof *lispsym))
769 826
770/* Declare extern constants for Lisp symbols. These can be helpful 827/* Declare extern constants for Lisp symbols. These can be helpful
771 when using a debugger like GDB, on older platforms where the debug 828 when using a debugger like GDB, on older platforms where the debug
@@ -843,7 +900,8 @@ INLINE struct Lisp_Symbol *
843INLINE Lisp_Object 900INLINE Lisp_Object
844make_lisp_symbol (struct Lisp_Symbol *sym) 901make_lisp_symbol (struct Lisp_Symbol *sym)
845{ 902{
846 Lisp_Object a = XIL (TAG_SYMOFFSET ((char *) sym - (char *) lispsym)); 903 intptr_t symoffset = (char *) sym - (char *) lispsym;
904 Lisp_Object a = TAG_PTR (Lisp_Symbol, (char *) symoffset);
847 eassert (XSYMBOL (a) == sym); 905 eassert (XSYMBOL (a) == sym);
848 return a; 906 return a;
849} 907}
@@ -1061,7 +1119,7 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
1061INLINE Lisp_Object 1119INLINE Lisp_Object
1062make_lisp_ptr (void *ptr, enum Lisp_Type type) 1120make_lisp_ptr (void *ptr, enum Lisp_Type type)
1063{ 1121{
1064 Lisp_Object a = XIL (TAG_PTR (type, ptr)); 1122 Lisp_Object a = TAG_PTR (type, ptr);
1065 eassert (XTYPE (a) == type && XUNTAG (a, type) == ptr); 1123 eassert (XTYPE (a) == type && XUNTAG (a, type) == ptr);
1066 return a; 1124 return a;
1067} 1125}
@@ -1132,7 +1190,7 @@ XINTPTR (Lisp_Object a)
1132INLINE Lisp_Object 1190INLINE Lisp_Object
1133make_pointer_integer (void *p) 1191make_pointer_integer (void *p)
1134{ 1192{
1135 Lisp_Object a = XIL (TAG_PTR (Lisp_Int0, p)); 1193 Lisp_Object a = TAG_PTR (Lisp_Int0, p);
1136 eassert (INTEGERP (a) && XINTPTR (a) == p); 1194 eassert (INTEGERP (a) && XINTPTR (a) == p);
1137 return a; 1195 return a;
1138} 1196}
@@ -1644,8 +1702,10 @@ gc_aset (Lisp_Object array, ptrdiff_t idx, Lisp_Object val)
1644 1702
1645/* True, since Qnil's representation is zero. Every place in the code 1703/* True, since Qnil's representation is zero. Every place in the code
1646 that assumes Qnil is zero should verify (NIL_IS_ZERO), to make it easy 1704 that assumes Qnil is zero should verify (NIL_IS_ZERO), to make it easy
1647 to find such assumptions later if we change Qnil to be nonzero. */ 1705 to find such assumptions later if we change Qnil to be nonzero.
1648enum { NIL_IS_ZERO = XLI_BUILTIN_LISPSYM (iQnil) == 0 }; 1706 Test iQnil and Lisp_Symbol instead of Qnil directly, since the latter
1707 is not suitable for use in an integer constant expression. */
1708enum { NIL_IS_ZERO = iQnil == 0 && Lisp_Symbol == 0 };
1649 1709
1650/* Clear the object addressed by P, with size NBYTES, so that all its 1710/* Clear the object addressed by P, with size NBYTES, so that all its
1651 bytes are zero and all its Lisp values are nil. */ 1711 bytes are zero and all its Lisp values are nil. */
diff --git a/src/xwidget.c b/src/xwidget.c
index a67dc0ecf4d..c7f0594728c 100644
--- a/src/xwidget.c
+++ b/src/xwidget.c
@@ -392,8 +392,7 @@ webkit_javascript_finished_cb (GObject *webview,
392 /* FIXME: This might lead to disaster if LISP_CALLBACK’s object 392 /* FIXME: This might lead to disaster if LISP_CALLBACK’s object
393 was garbage collected before now. See the FIXME in 393 was garbage collected before now. See the FIXME in
394 Fxwidget_webkit_execute_script. */ 394 Fxwidget_webkit_execute_script. */
395 store_xwidget_js_callback_event (xw, XIL ((intptr_t) lisp_callback), 395 store_xwidget_js_callback_event (xw, XPL (lisp_callback), lisp_value);
396 lisp_value);
397} 396}
398 397
399 398
@@ -723,7 +722,7 @@ argument procedure FUN.*/)
723 /* FIXME: This hack might lead to disaster if FUN is garbage 722 /* FIXME: This hack might lead to disaster if FUN is garbage
724 collected before store_xwidget_js_callback_event makes it visible 723 collected before store_xwidget_js_callback_event makes it visible
725 to Lisp again. See the FIXME in webkit_javascript_finished_cb. */ 724 to Lisp again. See the FIXME in webkit_javascript_finished_cb. */
726 gpointer callback_arg = (gpointer) (intptr_t) XLI (fun); 725 gpointer callback_arg = XLP (fun);
727 726
728 /* JavaScript execution happens asynchronously. If an elisp 727 /* JavaScript execution happens asynchronously. If an elisp
729 callback function is provided we pass it to the C callback 728 callback function is provided we pass it to the C callback