diff options
| author | Paul Eggert | 2014-09-29 19:43:23 -0700 |
|---|---|---|
| committer | Paul Eggert | 2014-09-29 19:43:23 -0700 |
| commit | dc4525691c2c236abdb6c074438223413f80091c (patch) | |
| tree | 86305e7415bcf1b5cc6ddad6879e922f9e5e163c /src/lisp.h | |
| parent | a19f0977a96ee74b96410b41a8ea793c86f64b58 (diff) | |
| download | emacs-dc4525691c2c236abdb6c074438223413f80091c.tar.gz emacs-dc4525691c2c236abdb6c074438223413f80091c.zip | |
Simplify stack-allocated Lisp objects, and make them more portable.
The build_local_string macro was used in two ways: (1) string
literals for which scoped allocation suffices, and (2) file name
components, where it's not safe in general to assume bounded-size
ASCII data. Simplify by defining a new macro SCOPED_STRING that
allocates a block-scope string, and by using SCOPED_STRING for (1)
and build_string for (2). Furthermore, actually use stack
allocation only for objects known to have sufficient alignment.
This simpler implementation means Emacs can make
USE_STACK_LISP_OBJECTS the default unless GC_MARK_STACK !=
GC_MAKE_GCPROS_NOOPS.
* lisp.h (GCALIGNED): Align even if !USE_STACK_LISP_OBJECTS,
for fewer differences among implementations.
(struct Lisp_String): Now GCALIGNED.
(USE_STACK_LISP_OBJECTS): Default to true, since the
implementation no longer insists on a nonempty GCALIGNED.
But make it false if GC_MARK_STACK != GC_MAKE_GCPROS_NOOPS.
(SCOPED_CONS_INITIALIZER): Remove, since it's no longer needed
separately. Move definiens to scoped_cons. The old definition
was incorrect when GCALIGNED was defined to be empty.
(union Aligned_String): New type.
(USE_STACK_CONS, USE_STACK_STRING): New constants, so that the
implementation ports to compilers that don't align strictly enough.
Don't worry about the union sizes; it's not worth bothering about.
(scoped_cons, scoped_list1, scoped_list3, scoped_list4):
Rewrite using USE_STACK_CONS.
(scoped_cons): Assume the use of union Aligned_Cons.
(lisp_string_size, make_local_string, build_local_string): Remove.
Unless otherwise specified, all callers of build_local_string
changed to use SCOPED_STRING.
(SCOPED_STRING): New macro.
* data.c (wrong_choice):
* menu.c (single_menu_item):
* process.c (Fformat_network_address):
Hoist use of SCOPED_STRING out of a scope, so that its returned
object lives long enough.
* fileio.c (Fexpand_file_name): Use build_string, not SCOPED_STRING,
as the string might be long or might not be ASCII.
Diffstat (limited to 'src/lisp.h')
| -rw-r--r-- | src/lisp.h | 166 |
1 files changed, 61 insertions, 105 deletions
diff --git a/src/lisp.h b/src/lisp.h index d2cac17fbc7..27751af2f5b 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -282,23 +282,7 @@ error !; | |||
| 282 | # endif | 282 | # endif |
| 283 | #endif | 283 | #endif |
| 284 | 284 | ||
| 285 | /* This should work with GCC. Clang has known problems; see | 285 | #ifdef HAVE_STRUCT_ATTRIBUTE_ALIGNED |
| 286 | http://lists.gnu.org/archive/html/emacs-devel/2014-09/msg00506.html. */ | ||
| 287 | #ifndef USE_STACK_LISP_OBJECTS | ||
| 288 | # if defined __GNUC__ && !defined __clang__ | ||
| 289 | /* 32-bit MinGW builds need at least GCC 4.2 to support this. */ | ||
| 290 | # if defined __MINGW32__ && !defined _W64 \ | ||
| 291 | && __GNUC__ + (__GNUC_MINOR__ > 1) < 5 | ||
| 292 | # define USE_STACK_LISP_OBJECTS false | ||
| 293 | # else /* !(__MINGW32__ && __GNUC__ < 4.2) */ | ||
| 294 | # define USE_STACK_LISP_OBJECTS true | ||
| 295 | # endif | ||
| 296 | # else | ||
| 297 | # define USE_STACK_LISP_OBJECTS false | ||
| 298 | # endif | ||
| 299 | #endif | ||
| 300 | |||
| 301 | #if defined HAVE_STRUCT_ATTRIBUTE_ALIGNED && USE_STACK_LISP_OBJECTS | ||
| 302 | # define GCALIGNED __attribute__ ((aligned (GCALIGNMENT))) | 286 | # define GCALIGNED __attribute__ ((aligned (GCALIGNMENT))) |
| 303 | #else | 287 | #else |
| 304 | # define GCALIGNED /* empty */ | 288 | # define GCALIGNED /* empty */ |
| @@ -1088,7 +1072,7 @@ CDR_SAFE (Lisp_Object c) | |||
| 1088 | 1072 | ||
| 1089 | /* In a string or vector, the sign bit of the `size' is the gc mark bit. */ | 1073 | /* In a string or vector, the sign bit of the `size' is the gc mark bit. */ |
| 1090 | 1074 | ||
| 1091 | struct Lisp_String | 1075 | struct GCALIGNED Lisp_String |
| 1092 | { | 1076 | { |
| 1093 | ptrdiff_t size; | 1077 | ptrdiff_t size; |
| 1094 | ptrdiff_t size_byte; | 1078 | ptrdiff_t size_byte; |
| @@ -4598,27 +4582,26 @@ lisp_word_count (ptrdiff_t nbytes) | |||
| 4598 | 4582 | ||
| 4599 | 4583 | ||
| 4600 | /* If USE_STACK_LISP_OBJECTS, define macros that and functions that allocate | 4584 | /* If USE_STACK_LISP_OBJECTS, define macros that and functions that allocate |
| 4601 | block-scoped conses and function-scoped strings. These objects are not | 4585 | block-scoped conses and strings. These objects are not |
| 4602 | managed by the garbage collector, so they are dangerous: passing them | 4586 | managed by the garbage collector, so they are dangerous: passing them |
| 4603 | out of their scope (e.g., to user code) results in undefined behavior. | 4587 | out of their scope (e.g., to user code) results in undefined behavior. |
| 4604 | Conversely, they have better performance because GC is not involved. | 4588 | Conversely, they have better performance because GC is not involved. |
| 4605 | 4589 | ||
| 4606 | This feature is experimental and requires careful debugging. It's enabled | 4590 | This feature is experimental and requires careful debugging. |
| 4607 | by default if GCC or a compiler that mimics GCC well (like Intel C/C++) is | 4591 | Build with CPPFLAGS='-DUSE_STACK_LISP_OBJECTS=0' to disable it. */ |
| 4608 | used, except clang (see notice above). For other compilers, brave users can | ||
| 4609 | compile with CPPFLAGS='-DUSE_STACK_LISP_OBJECTS=1' to get into the game. | ||
| 4610 | Note that this feature requires GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS. */ | ||
| 4611 | 4592 | ||
| 4612 | #ifdef GCALIGNED | 4593 | #ifndef USE_STACK_LISP_OBJECTS |
| 4613 | 4594 | # define USE_STACK_LISP_OBJECTS true | |
| 4614 | /* No tricks if struct Lisp_Cons is always aligned. */ | 4595 | #endif |
| 4615 | 4596 | ||
| 4616 | # define SCOPED_CONS_INITIALIZER(a, b) &((struct Lisp_Cons) { a, { b } }) | 4597 | /* USE_STACK_LISP_OBJECTS requires GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS. */ |
| 4617 | 4598 | ||
| 4618 | #else /* not GCALIGNED */ | 4599 | #if GC_MARK_STACK != GC_MAKE_GCPROS_NOOPS |
| 4600 | # undef USE_STACK_LISP_OBJECTS | ||
| 4601 | # define USE_STACK_LISP_OBJECTS false | ||
| 4602 | #endif | ||
| 4619 | 4603 | ||
| 4620 | /* A struct Lisp_Cons inside a union that is no larger and may be | 4604 | /* Struct inside unions that are typically no larger and aligned enough. */ |
| 4621 | better-aligned. */ | ||
| 4622 | 4605 | ||
| 4623 | union Aligned_Cons | 4606 | union Aligned_Cons |
| 4624 | { | 4607 | { |
| @@ -4626,88 +4609,61 @@ union Aligned_Cons | |||
| 4626 | double d; intmax_t i; void *p; | 4609 | double d; intmax_t i; void *p; |
| 4627 | }; | 4610 | }; |
| 4628 | 4611 | ||
| 4629 | verify (alignof (union Aligned_Cons) % GCALIGNMENT == 0); | 4612 | union Aligned_String |
| 4630 | verify (sizeof (struct Lisp_Cons) == sizeof (union Aligned_Cons)); | 4613 | { |
| 4631 | 4614 | struct Lisp_String s; | |
| 4632 | # define SCOPED_CONS_INITIALIZER(a, b) \ | 4615 | double d; intmax_t i; void *p; |
| 4633 | &((union Aligned_Cons) { { a, { b } } }.s) | 4616 | }; |
| 4634 | |||
| 4635 | #endif /* GCALIGNED */ | ||
| 4636 | |||
| 4637 | /* Basic stack-based cons allocation. */ | ||
| 4638 | |||
| 4639 | #if USE_STACK_LISP_OBJECTS | ||
| 4640 | # define scoped_cons(a, b) \ | ||
| 4641 | make_lisp_ptr (SCOPED_CONS_INITIALIZER (a, b), Lisp_Cons) | ||
| 4642 | # define scoped_list1(a) scoped_cons (a, Qnil) | ||
| 4643 | # define scoped_list2(a, b) scoped_cons (a, scoped_list1 (b)) | ||
| 4644 | # define scoped_list3(a, b, c) scoped_cons (a, scoped_list2 (b, c)) | ||
| 4645 | # define scoped_list4(a, b, c, d) scoped_cons (a, scoped_list3 (b, c, d)) | ||
| 4646 | #else | ||
| 4647 | # define scoped_cons(a, b) Fcons (a, b) | ||
| 4648 | # define scoped_list1(a) list1 (a) | ||
| 4649 | # define scoped_list2(a, b) list2 (a, b) | ||
| 4650 | # define scoped_list3(a, b, c) list3 (a, b, c) | ||
| 4651 | # define scoped_list4(a, b, c, d) list4 (a, b, c, d) | ||
| 4652 | #endif | ||
| 4653 | 4617 | ||
| 4654 | /* On-stack string allocation requires __builtin_constant_p, statement | 4618 | /* True for stack-based cons and string implementations. */ |
| 4655 | expressions and GCALIGNMENT-aligned alloca. All from the above is | ||
| 4656 | assumed for GCC. At least for clang < 3.6, alloca isn't properly | ||
| 4657 | aligned in some cases. In the absence of solid information, play | ||
| 4658 | it safe for other non-GCC compilers. */ | ||
| 4659 | 4619 | ||
| 4660 | #if USE_STACK_LISP_OBJECTS && __GNUC__ && !__clang__ | 4620 | enum |
| 4621 | { | ||
| 4622 | USE_STACK_CONS = (USE_STACK_LISP_OBJECTS | ||
| 4623 | && alignof (union Aligned_Cons) % GCALIGNMENT == 0), | ||
| 4624 | USE_STACK_STRING = (USE_STACK_LISP_OBJECTS | ||
| 4625 | && alignof (union Aligned_String) % GCALIGNMENT == 0) | ||
| 4626 | }; | ||
| 4661 | 4627 | ||
| 4662 | /* Used to check whether stack-allocated strings are ASCII-only. */ | 4628 | /* Build a stack-based Lisp cons or short list if possible, a GC-based |
| 4629 | one otherwise. The resulting object should not be modified or made | ||
| 4630 | visible to user code. */ | ||
| 4631 | |||
| 4632 | #define scoped_cons(a, b) \ | ||
| 4633 | (USE_STACK_CONS \ | ||
| 4634 | ? make_lisp_ptr (&(union Aligned_Cons) { { a, { b } } }.s, Lisp_Cons) \ | ||
| 4635 | : Fcons (a, b)) | ||
| 4636 | #define scoped_list1(a) \ | ||
| 4637 | (USE_STACK_CONS ? scoped_cons (a, Qnil) : list1 (a)) | ||
| 4638 | #define scoped_list2(a, b) \ | ||
| 4639 | (USE_STACK_CONS ? scoped_cons (a, scoped_list1 (b)) : list2 (a,b)) | ||
| 4640 | #define scoped_list3(a, b, c) \ | ||
| 4641 | (USE_STACK_CONS ? scoped_cons (a, scoped_list2 (b, c)) : list3 (a, b, c)) | ||
| 4642 | #define scoped_list4(a, b, c, d) \ | ||
| 4643 | (USE_STACK_CONS \ | ||
| 4644 | ? scoped_cons (a, scoped_list3 (b, c, d)) : \ | ||
| 4645 | list4 (a, b, c, d)) | ||
| 4646 | |||
| 4647 | /* Check whether stack-allocated strings are ASCII-only. */ | ||
| 4663 | 4648 | ||
| 4664 | #ifdef ENABLE_CHECKING | 4649 | #ifdef ENABLE_CHECKING |
| 4665 | extern const char * verify_ascii (const char *); | 4650 | extern const char *verify_ascii (const char *); |
| 4666 | #else | 4651 | #else |
| 4667 | #define verify_ascii(str) (str) | 4652 | # define verify_ascii(str) (str) |
| 4668 | #endif | 4653 | #endif |
| 4669 | 4654 | ||
| 4670 | /* Return number of bytes needed for Lisp string of length NBYTES. */ | 4655 | /* Build a stack-based Lisp string from STR if possible, a GC-based |
| 4671 | 4656 | one if not. STR is not necessarily copied and should contain only | |
| 4672 | INLINE ptrdiff_t | 4657 | ASCII characters. The resulting Lisp string should not be modified |
| 4673 | lisp_string_size (ptrdiff_t nbytes) | 4658 | or made visible to user code. */ |
| 4674 | { | 4659 | |
| 4675 | return sizeof (struct Lisp_String) + nbytes + 1; | 4660 | #define SCOPED_STRING(str) \ |
| 4676 | } | 4661 | (USE_STACK_STRING \ |
| 4677 | 4662 | ? (make_lisp_ptr \ | |
| 4678 | /* Return function-scoped unibyte Lisp string with contents STR of length | 4663 | ((&(union Aligned_String) \ |
| 4679 | NBYTES and memory footprint of MEMSIZE bytes if the latter doesn't exceed | 4664 | { { strlen (str), -1, 0, (unsigned char *) verify_ascii (str) } }.s), \ |
| 4680 | MAX_ALLOCA, abort otherwise. */ | 4665 | Lisp_String)) \ |
| 4681 | 4666 | : build_string (verify_ascii (str))) | |
| 4682 | # define make_local_string(str, memsize, nbytes) \ | ||
| 4683 | ((memsize < MAX_ALLOCA) \ | ||
| 4684 | ? ({ struct Lisp_String *s_ = alloca (memsize); \ | ||
| 4685 | s_->data = (unsigned char *) (s_ + 1); \ | ||
| 4686 | memcpy (s_->data, verify_ascii (str), nbytes + 1); \ | ||
| 4687 | s_->size = nbytes, s_->size_byte = -1; \ | ||
| 4688 | s_->intervals = NULL; \ | ||
| 4689 | make_lisp_ptr (s_, Lisp_String); }) \ | ||
| 4690 | : (emacs_abort (), Qnil)) | ||
| 4691 | |||
| 4692 | /* If STR is a compile-time string constant, build function-scoped Lisp string | ||
| 4693 | from it, fall back to regular Lisp string otherwise. We assume compile-time | ||
| 4694 | string constants never exceeds MAX_ALLOCA - sizeof (Lisp_String) - 1. */ | ||
| 4695 | |||
| 4696 | # define build_local_string(str) \ | ||
| 4697 | (__builtin_constant_p (str) \ | ||
| 4698 | ? make_local_string \ | ||
| 4699 | (str, lisp_string_size (strlen (str)), strlen (str)) \ | ||
| 4700 | : build_string (str)) | ||
| 4701 | |||
| 4702 | #else /* not USE_STACK_LISP_OBJECTS && __GNUC__ && !__clang__ */ | ||
| 4703 | |||
| 4704 | INLINE Lisp_Object | ||
| 4705 | build_local_string (const char *str) | ||
| 4706 | { | ||
| 4707 | return build_string (str); | ||
| 4708 | } | ||
| 4709 | |||
| 4710 | #endif /* not USE_STACK_LISP_OBJECTS && __GNUC__ && !__clang__ */ | ||
| 4711 | 4667 | ||
| 4712 | /* Loop over all tails of a list, checking for cycles. | 4668 | /* Loop over all tails of a list, checking for cycles. |
| 4713 | FIXME: Make tortoise and n internal declarations. | 4669 | FIXME: Make tortoise and n internal declarations. |