aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDmitry Antipov2014-09-09 07:44:06 +0400
committerDmitry Antipov2014-09-09 07:44:06 +0400
commitc7dfea947eba1980fe3a23ad13f04dd40c6c0d68 (patch)
tree3927b309d9773c54a06d7590e0dd6017a8c3bfc8 /src
parent80465f41d7fc67d40f0a233504e295b127ad2c6b (diff)
downloademacs-c7dfea947eba1980fe3a23ad13f04dd40c6c0d68.tar.gz
emacs-c7dfea947eba1980fe3a23ad13f04dd40c6c0d68.zip
Add macros to allocate temporary Lisp objects with alloca.
Respect MAX_ALLOCA and fall back to regular GC for large objects. * character.h (parse_str_as_multibyte): Move prototype to ... * lisp.h (parse_str_as_multibyte): ... here. (struct Lisp_Cons): Add GCALIGNED attribute if supported. (scoped_cons, scoped_list2, build_local_vector, build_local_string): New macros. (scoped_cons_init, pointer_valid_for_lisp_object, local_vector_init) (local_string_init): New functions. * alloc.c (verify_alloca) [ENABLE_CHECKING]: New function. (init_alloc_once): Call it.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog12
-rw-r--r--src/alloc.c27
-rw-r--r--src/character.h2
-rw-r--r--src/lisp.h122
4 files changed, 158 insertions, 5 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index a01c753161c..d1e8314b172 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -5,6 +5,18 @@
5 (x_delete_terminal): Do not close X connection fd (Bug#18403). 5 (x_delete_terminal): Do not close X connection fd (Bug#18403).
6 Add eassert and mark dpyinfo as dead only if it was alive. 6 Add eassert and mark dpyinfo as dead only if it was alive.
7 7
8 Add macros to allocate temporary Lisp objects with alloca.
9 Respect MAX_ALLOCA and fall back to regular GC for large objects.
10 * character.h (parse_str_as_multibyte): Move prototype to ...
11 * lisp.h (parse_str_as_multibyte): ... here.
12 (struct Lisp_Cons): Add GCALIGNED attribute if supported.
13 (scoped_cons, scoped_list2, build_local_vector, build_local_string):
14 New macros.
15 (scoped_cons_init, pointer_valid_for_lisp_object, local_vector_init)
16 (local_string_init): New functions.
17 * alloc.c (verify_alloca) [ENABLE_CHECKING]: New function.
18 (init_alloc_once): Call it.
19
82014-09-08 Eli Zaretskii <eliz@gnu.org> 202014-09-08 Eli Zaretskii <eliz@gnu.org>
9 21
10 * dispnew.c (prepare_desired_row): When MODE_LINE_P is zero, 22 * dispnew.c (prepare_desired_row): When MODE_LINE_P is zero,
diff --git a/src/alloc.c b/src/alloc.c
index 31b0644c285..13043d6d9d7 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -7117,8 +7117,29 @@ die (const char *msg, const char *file, int line)
7117 file, line, msg); 7117 file, line, msg);
7118 terminate_due_to_signal (SIGABRT, INT_MAX); 7118 terminate_due_to_signal (SIGABRT, INT_MAX);
7119} 7119}
7120#endif 7120
7121 7121/* Stress alloca with inconveniently sized requests and check
7122 whether all allocated areas may be used for Lisp_Object. */
7123
7124NO_INLINE static void
7125verify_alloca (void)
7126{
7127 int i;
7128 enum { ALLOCA_CHECK_MAX = 256 };
7129 /* Start from size of the smallest Lisp object. */
7130 for (i = sizeof (struct Lisp_Cons); i <= ALLOCA_CHECK_MAX; i++)
7131 {
7132 char *ptr = alloca (i);
7133 eassert (pointer_valid_for_lisp_object (ptr));
7134 }
7135}
7136
7137#else /* not ENABLE_CHECKING */
7138
7139#define verify_alloca() ((void) 0)
7140
7141#endif /* ENABLE_CHECKING */
7142
7122/* Initialization. */ 7143/* Initialization. */
7123 7144
7124void 7145void
@@ -7128,6 +7149,8 @@ init_alloc_once (void)
7128 purebeg = PUREBEG; 7149 purebeg = PUREBEG;
7129 pure_size = PURESIZE; 7150 pure_size = PURESIZE;
7130 7151
7152 verify_alloca ();
7153
7131#if GC_MARK_STACK || defined GC_MALLOC_CHECK 7154#if GC_MARK_STACK || defined GC_MALLOC_CHECK
7132 mem_init (); 7155 mem_init ();
7133 Vdead = make_pure_string ("DEAD", 4, 4, 0); 7156 Vdead = make_pure_string ("DEAD", 4, 4, 0);
diff --git a/src/character.h b/src/character.h
index 66cd4e47ef8..624f4fff3f0 100644
--- a/src/character.h
+++ b/src/character.h
@@ -644,8 +644,6 @@ extern int string_char (const unsigned char *,
644 const unsigned char **, int *); 644 const unsigned char **, int *);
645 645
646extern int translate_char (Lisp_Object, int c); 646extern int translate_char (Lisp_Object, int c);
647extern void parse_str_as_multibyte (const unsigned char *,
648 ptrdiff_t, ptrdiff_t *, ptrdiff_t *);
649extern ptrdiff_t count_size_as_multibyte (const unsigned char *, ptrdiff_t); 647extern ptrdiff_t count_size_as_multibyte (const unsigned char *, ptrdiff_t);
650extern ptrdiff_t str_as_multibyte (unsigned char *, ptrdiff_t, ptrdiff_t, 648extern ptrdiff_t str_as_multibyte (unsigned char *, ptrdiff_t, ptrdiff_t,
651 ptrdiff_t *); 649 ptrdiff_t *);
diff --git a/src/lisp.h b/src/lisp.h
index 15c459c9fdb..a89e80729cd 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -298,6 +298,13 @@ error !;
298# endif 298# endif
299#endif 299#endif
300 300
301/* Stolen from gnulib. */
302#if (__GNUC__ || __HP_cc || __HP_aCC || __IBMC__ \
303 || __IBMCPP__ || __ICC || 0x5110 <= __SUNPRO_C)
304#define GCALIGNED __attribute__ ((aligned (GCALIGNMENT)))
305#else
306#define GCALIGNED /* empty */
307#endif
301 308
302/* Some operations are so commonly executed that they are implemented 309/* Some operations are so commonly executed that they are implemented
303 as macros, not functions, because otherwise runtime performance would 310 as macros, not functions, because otherwise runtime performance would
@@ -1016,7 +1023,7 @@ LISP_MACRO_DEFUN_VOID (CHECK_TYPE,
1016 1023
1017typedef struct interval *INTERVAL; 1024typedef struct interval *INTERVAL;
1018 1025
1019struct Lisp_Cons 1026struct GCALIGNED Lisp_Cons
1020 { 1027 {
1021 /* Car of this cons cell. */ 1028 /* Car of this cons cell. */
1022 Lisp_Object car; 1029 Lisp_Object car;
@@ -3622,6 +3629,10 @@ extern void syms_of_xsettings (void);
3622/* Defined in vm-limit.c. */ 3629/* Defined in vm-limit.c. */
3623extern void memory_warnings (void *, void (*warnfun) (const char *)); 3630extern void memory_warnings (void *, void (*warnfun) (const char *));
3624 3631
3632/* Defined in character.c. */
3633extern void parse_str_as_multibyte (const unsigned char *, ptrdiff_t,
3634 ptrdiff_t *, ptrdiff_t *);
3635
3625/* Defined in alloc.c. */ 3636/* Defined in alloc.c. */
3626extern void check_pure_size (void); 3637extern void check_pure_size (void);
3627extern void free_misc (Lisp_Object); 3638extern void free_misc (Lisp_Object);
@@ -4535,6 +4546,115 @@ extern void *record_xmalloc (size_t) ATTRIBUTE_ALLOC_SIZE ((1));
4535 memory_full (SIZE_MAX); \ 4546 memory_full (SIZE_MAX); \
4536 } while (false) 4547 } while (false)
4537 4548
4549/* Use the following functions to allocate temporary (function-
4550 or block-scoped) conses, vectors, and strings. These objects
4551 are not managed by GC, and passing them out of their scope
4552 most likely causes an immediate crash at next GC. */
4553
4554#if (__GNUC__ || __HP_cc || __HP_aCC || __IBMC__ \
4555 || __IBMCPP__ || __ICC || 0x5110 <= __SUNPRO_C)
4556
4557/* Allocate temporary block-scoped cons. This version assumes
4558 that stack-allocated Lisp_Cons is always aligned properly. */
4559
4560#define scoped_cons(car, cdr) \
4561 make_lisp_ptr (&((struct Lisp_Cons) { car, { cdr } }), Lisp_Cons)
4562
4563#else /* not __GNUC__ etc... */
4564
4565/* Helper function for an alternate scoped cons, see below. */
4566
4567INLINE Lisp_Object
4568scoped_cons_init (void *ptr, Lisp_Object x, Lisp_Object y)
4569{
4570 struct Lisp_Cons *c = (struct Lisp_Cons *)
4571 (((uintptr_t) ptr + (GCALIGNMENT - 1)) & ~(GCALIGNMENT - 1));
4572 c->car = x;
4573 c->u.cdr = y;
4574 return make_lisp_ptr (c, Lisp_Cons);
4575}
4576
4577/* This version uses explicit alignment. */
4578
4579#define scoped_cons(car, cdr) \
4580 scoped_cons_init ((char[sizeof (struct Lisp_Cons) \
4581 + (GCALIGNMENT - 1)]) {}, (car), (cdr))
4582
4583#endif /* __GNUC__ etc... */
4584
4585/* Convenient utility macro similar to list2. */
4586
4587#define scoped_list2(x, y) scoped_cons (x, scoped_cons (y, Qnil))
4588
4589/* True if Lisp_Object may be placed at P. Used only
4590 under ENABLE_CHECKING and optimized away otherwise. */
4591
4592INLINE bool
4593pointer_valid_for_lisp_object (void *p)
4594{
4595 uintptr_t v = (uintptr_t) p;
4596 return !(USE_LSB_TAG ? (v & ~VALMASK) : v >> VALBITS);
4597}
4598
4599/* Helper function for build_local_vector, see below. */
4600
4601INLINE Lisp_Object
4602local_vector_init (uintptr_t addr, ptrdiff_t length, Lisp_Object init)
4603{
4604 ptrdiff_t i;
4605 struct Lisp_Vector *v = (struct Lisp_Vector *) addr;
4606
4607 eassert (pointer_valid_for_lisp_object (v));
4608 v->header.size = length;
4609 for (i = 0; i < length; i++)
4610 v->contents[i] = init;
4611 return make_lisp_ptr (v, Lisp_Vectorlike);
4612}
4613
4614/* If size permits, create temporary function-scoped vector OBJ of
4615 length SIZE, with each element being INIT. Otherwise create
4616 regular GC-managed vector. */
4617
4618#define build_local_vector(obj, size, init) \
4619 (MAX_ALLOCA < (size) * word_size + header_size \
4620 ? obj = Fmake_vector (make_number (size), (init)) \
4621 : (obj = XIL ((uintptr_t) alloca \
4622 ((size) * word_size + header_size)), \
4623 obj = local_vector_init ((uintptr_t) XLI (obj), (size), (init))))
4624
4625/* Helper function for build_local_string, see below. */
4626
4627INLINE Lisp_Object
4628local_string_init (uintptr_t addr, const char *data, ptrdiff_t size)
4629{
4630 ptrdiff_t nchars, nbytes;
4631 struct Lisp_String *s = (struct Lisp_String *) addr;
4632
4633 eassert (pointer_valid_for_lisp_object (s));
4634 parse_str_as_multibyte ((const unsigned char *) data,
4635 size, &nchars, &nbytes);
4636 s->data = (unsigned char *) (addr + sizeof *s);
4637 s->intervals = NULL;
4638 memcpy (s->data, data, size);
4639 s->data[size] = '\0';
4640 if (size == nchars || size != nbytes)
4641 s->size = size, s->size_byte = -1;
4642 else
4643 s->size = nchars, s->size_byte = nbytes;
4644 return make_lisp_ptr (s, Lisp_String);
4645}
4646
4647/* If size permits, create temporary function-scoped string OBJ
4648 with contents DATA of length NBYTES. Otherwise create regular
4649 GC-managed string. */
4650
4651#define build_local_string(obj, data, nbytes) \
4652 (MAX_ALLOCA < (nbytes) + sizeof (struct Lisp_String) \
4653 ? obj = make_string ((data), (nbytes)) \
4654 : (obj = XIL ((uintptr_t) alloca \
4655 ((nbytes) + sizeof (struct Lisp_String))), \
4656 obj = local_string_init ((uintptr_t) XLI (obj), data, nbytes)))
4657
4538/* Loop over all tails of a list, checking for cycles. 4658/* Loop over all tails of a list, checking for cycles.
4539 FIXME: Make tortoise and n internal declarations. 4659 FIXME: Make tortoise and n internal declarations.
4540 FIXME: Unroll the loop body so we don't need `n'. */ 4660 FIXME: Unroll the loop body so we don't need `n'. */