diff options
| author | Paul Eggert | 2017-12-12 12:59:57 -0800 |
|---|---|---|
| committer | Paul Eggert | 2017-12-12 15:17:12 -0800 |
| commit | 244346c744a6700d320a0a0fe8c796be3b3ff023 (patch) | |
| tree | 145dc0ba87fcf82de44e62ecbdeb70fe86c28c7a /src | |
| parent | c705f7250d6f17f1682ee5ad7eec516dbf6c3916 (diff) | |
| download | emacs-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/.gdbinit | 16 | ||||
| -rw-r--r-- | src/alloc.c | 39 | ||||
| -rw-r--r-- | src/emacs-module.c | 30 | ||||
| -rw-r--r-- | src/lisp.h | 154 | ||||
| -rw-r--r-- | src/xwidget.c | 5 |
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 | |||
| 524 | static ATTRIBUTE_UNUSED void * | ||
| 525 | XPNTR_OR_SYMBOL_OFFSET (Lisp_Object a) | ||
| 526 | { | ||
| 527 | return macro_XPNTR_OR_SYMBOL_OFFSET (a); | ||
| 528 | } | ||
| 529 | static ATTRIBUTE_UNUSED void * | 519 | static ATTRIBUTE_UNUSED void * |
| 530 | XPNTR (Lisp_Object a) | 520 | XPNTR (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 | |||
| 5605 | purecopy (Lisp_Object obj) | 5594 | purecopy (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; | |||
| 915 | static Lisp_Object | 920 | static Lisp_Object |
| 916 | value_to_lisp_bits (emacs_value v) | 921 | value_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) | |||
| 989 | static emacs_value | 994 | static emacs_value |
| 990 | lisp_to_value_bits (Lisp_Object o) | 995 | lisp_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) | |||
| 277 | error !; | 277 | error !; |
| 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 | ||
| 287 | typedef union Lisp_X *Lisp_Word; | ||
| 288 | #else | ||
| 289 | typedef 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 | ||
| 548 | typedef 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 |
| 589 | typedef struct Lisp_Object { Lisp_Word i; } Lisp_Object; | ||
| 590 | # define LISP_INITIALLY(w) {w} | ||
| 591 | # undef CHECK_LISP_OBJECT_TYPE | ||
| 553 | enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = true }; | 592 | enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = true }; |
| 554 | #else /* CHECK_LISP_OBJECT_TYPE */ | 593 | #else |
| 555 | 594 | typedef 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 | |||
| 558 | typedef EMACS_INT Lisp_Object; | ||
| 559 | #define LISP_INITIALLY(i) (i) | ||
| 560 | enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = false }; | 596 | enum 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 | ||
| 596 | INLINE EMACS_INT | 634 | INLINE 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 | ||
| 646 | INLINE void * | ||
| 647 | (XLP) (Lisp_Object o) | ||
| 648 | { | ||
| 649 | return lisp_h_XLP (o); | ||
| 650 | } | ||
| 651 | |||
| 652 | INLINE 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 | ||
| 610 | INLINE enum Lisp_Type | 660 | INLINE 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. */ | ||
| 806 | typedef char *untagged_ptr; | ||
| 807 | typedef 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. */ | ||
| 812 | typedef uintptr_t untagged_ptr; | ||
| 813 | typedef 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 * | |||
| 843 | INLINE Lisp_Object | 900 | INLINE Lisp_Object |
| 844 | make_lisp_symbol (struct Lisp_Symbol *sym) | 901 | make_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) | |||
| 1061 | INLINE Lisp_Object | 1119 | INLINE Lisp_Object |
| 1062 | make_lisp_ptr (void *ptr, enum Lisp_Type type) | 1120 | make_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) | |||
| 1132 | INLINE Lisp_Object | 1190 | INLINE Lisp_Object |
| 1133 | make_pointer_integer (void *p) | 1191 | make_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. |
| 1648 | enum { 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. */ | ||
| 1708 | enum { 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 |