unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#28213: [bootstrap] Error 2 with -Os with gcc (GCC) 7.1.1
@ 2017-08-24  7:38 Mutiny 
  2017-08-24 16:34 ` Eli Zaretskii
  2017-08-29 22:07 ` Paul Eggert
  0 siblings, 2 replies; 3+ messages in thread
From: Mutiny  @ 2017-08-24  7:38 UTC (permalink / raw)
  To: 28213

[-- Attachment #1: Type: text/plain, Size: 4303 bytes --]

Hi,CFLAGS="-march=native -ffast-math -Os"-Os fails with gcc(GCC) 7.1.1 20170622 (Red Hat 7.1.1-3)sed -i 's/Os/O3/g' build or any other -Ox (unlike -Os)works.     ./configure                               \            --prefix=$deploy_folder               \            --sysconfdir=$sysconfdir              \          
   --enable-locallisppath=$locallisppath \            --libexecdir=$libexecdir        &nbsp
 ;     \            --localstatedir=$localstatedir        \            --enable-largefile                    \            --with-x-toolkit=gtk3                 \            --with-sound=yes                      \     &nb
 sp;      --with-modules                        \&n
 bsp;           --with-xwidgets                       \            --without-pop                         \            --with-file-notification=yes          \            --enable-link-time-optimizationDumping under the name emacs10678816 of 33554432 static heap bytes used2437614 pure bytes usedAdding name emac
 s-26.0.50.1ln -f emacs bootstrap-emacsmake[2]: Leaving directory '/usr/local/src/sdm/emacs/trunk/src'make -C lisp allmake[2]: Entering directory '/usr/local/src/sdm/emacs/trunk/l
 isp'make -C ../leim all EMACS="../src/emacs"make[3]: Entering directory '/usr/local/src/sdm/emacs/trunk/leim'make[3]: Nothing to be done for 'all'.make[3]: Leaving directory '/usr/local/src/sdm/emacs/trunk/leim'make -C ../admin/grammars all EMACS="../../src/emacs"make[3]: Entering directory '/usr/local/src/sdm/emacs/trunk/admin/grammars'make[3]: Nothing to be done for 'all'.make[3]: Leaving directory '/usr/local/src/sdm/emacs/trunk/admin/grammars'make[3]: Entering directory '/usr/local/src/sdm/emacs/trunk/lisp'  ELC      align.elc  ELC      allout.elcEager macro-expansion failure: (invalid-function [])Eager macro-expansion failure: (invalid-function [
 ])Eager macro-expansion failure: (invalid-function [])>>Error occurred processing allout.el: Invalid function (([]))make[3]: *** [Makefile:297: allout.elc] Error 1make[3]: Leaving dire
 ctory '/usr/local/src/sdm/emacs/trunk/lisp'make[2]: *** [Makefile:320: compile-main] Error 2make[2]: Leaving directory '/usr/local/src/sdm/emacs/trunk/lisp'make[1]: *** [Makefile:403: lisp] Error 2make[1]: Leaving directory '/usr/local/src/sdm/emacs/trunk'make: *** [Makefile:1099: bootstrap] Error 2 

[-- Attachment #2: Type: text/html, Size: 4609 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* bug#28213: [bootstrap] Error 2 with -Os with gcc (GCC) 7.1.1
  2017-08-24  7:38 bug#28213: [bootstrap] Error 2 with -Os with gcc (GCC) 7.1.1 Mutiny 
@ 2017-08-24 16:34 ` Eli Zaretskii
  2017-08-29 22:07 ` Paul Eggert
  1 sibling, 0 replies; 3+ messages in thread
From: Eli Zaretskii @ 2017-08-24 16:34 UTC (permalink / raw)
  To: Mutiny ; +Cc: 28213

> Date: 24 Aug 2017 07:38:15 -0000
> From: "Mutiny " <mutiny.mutiny@rediffmail.com>
> 
> CFLAGS="-march=native -ffast-math -Os"
> -Os fails with gcc(GCC) 7.1.1 20170622 (Red Hat 7.1.1-3)
> sed -i 's/Os/O3/g' build or any other -Ox (unlike -Os)
> works.

What happens if you leave -Os, but remove -ffast-math?





^ permalink raw reply	[flat|nested] 3+ messages in thread

* bug#28213: [bootstrap] Error 2 with -Os with gcc (GCC) 7.1.1
  2017-08-24  7:38 bug#28213: [bootstrap] Error 2 with -Os with gcc (GCC) 7.1.1 Mutiny 
  2017-08-24 16:34 ` Eli Zaretskii
@ 2017-08-29 22:07 ` Paul Eggert
  1 sibling, 0 replies; 3+ messages in thread
From: Paul Eggert @ 2017-08-29 22:07 UTC (permalink / raw)
  To: Mutiny; +Cc: 28213-done, Dmitry Antipov

[-- Attachment #1: Type: text/plain, Size: 626 bytes --]

Thanks for the bug report, which led to an entertaining and hair-raising 
trip through Emacs's garbage collector and let me brush up on my 
machine-level debugging skills. I installed the attached patches, which 
fix the problem for me, and I am closing the bug.

This bug report underscores that --enable-link-time-optimization is 
experimental and should not yet be recommended for production use with 
Emacs. When used, even with the attached patches I can easily get Emacs 
to dump core by exploiting bugs in GCC's code generator. The commit 
message in the last of the attached patches contains more detail about this.



[-- Attachment #2: 0001-Align-stack-bottom-properly.patch --]
[-- Type: text/x-patch, Size: 1188 bytes --]

From dc8854b3c65d8c742acec45d3ca0087262901c7a Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Tue, 29 Aug 2017 12:49:22 -0700
Subject: [PATCH 1/4] Align stack bottom properly.

This is needed for gcc -Os -flto on x86-64 (Bug#28213).
* src/emacs.c (main): Align stack-bottom variable as a pointer,
since mark_memory requires this.
---
 src/emacs.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/emacs.c b/src/emacs.c
index 0fec716758..44f6285795 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -672,7 +672,10 @@ close_output_streams (void)
 int
 main (int argc, char **argv)
 {
-  char stack_bottom_variable;
+  /* Variable near the bottom of the stack, and aligned appropriately
+     for pointers.  */
+  void *stack_bottom_variable;
+
   bool do_initial_setlocale;
   bool dumping;
   int skip_args = 0;
@@ -688,7 +691,7 @@ main (int argc, char **argv)
   char *original_pwd = 0;
 
   /* Record (approximately) where the stack begins.  */
-  stack_bottom = &stack_bottom_variable;
+  stack_bottom = (char *) &stack_bottom_variable;
 
 #ifndef CANNOT_DUMP
   dumping = !initialized && (strcmp (argv[argc - 1], "dump") == 0
-- 
2.13.5


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-Improve-stack-top-heuristic.patch --]
[-- Type: text/x-patch; name="0002-Improve-stack-top-heuristic.patch", Size: 5301 bytes --]

From 17538f342318cb804a60c392a84ae58ec716c291 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Tue, 29 Aug 2017 14:20:47 -0700
Subject: [PATCH 2/4] Improve stack-top heuristic

This is needed for gcc -Os -flto on x86-64; otherwise, GC misses part
of the stack when scanning for heap roots, causing Emacs to crash
later (Bug#28213).  The problem is that Emacs's hack for getting an
address near the stack top does not work when link-time optimization
moves stack variables around.
* configure.ac (HAVE___BUILTIN_FRAME_ADDRESS): New macro.
* lib-src/make-docfile.c (DEFUN_noinline): New constant.
(write_globals, scan_c_stream): Support noinline.
* src/alloc.c (NEAR_STACK_TOP): New macro.
(SET_STACK_TOP_ADDRESS): Use it.
(flush_stack_call_func, Fgarbage_collect): Now noinline.
---
 configure.ac           |  9 +++++++++
 lib-src/make-docfile.c |  9 +++++++--
 src/alloc.c            | 20 +++++++++++++++-----
 3 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/configure.ac b/configure.ac
index 443344de4c..3dee40704d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3958,6 +3958,15 @@ AC_DEFUN
 AC_CHECK_DECLS([aligned_alloc], [], [], [[#include <stdlib.h>]])
 
 dnl Cannot use AC_CHECK_FUNCS
+AC_CACHE_CHECK([for __builtin_frame_address],
+  [emacs_cv_func___builtin_frame_address],
+  [AC_LINK_IFELSE([AC_LANG_PROGRAM([], [__builtin_frame_address (0);])],
+     [emacs_cv_func___builtin_frame_address=yes],
+     [emacs_cv_func___builtin_frame_address=no])])
+if test $emacs_cv_func___builtin_frame_address = yes; then
+  AC_DEFINE([HAVE___BUILTIN_FRAME_ADDRESS], 1,
+	    [Define to 1 if you have the '__builtin_frame_address' function.])
+fi
 AC_CACHE_CHECK([for __builtin_unwind_init],
 	       emacs_cv_func___builtin_unwind_init,
 [AC_LINK_IFELSE([AC_LANG_PROGRAM([], [__builtin_unwind_init ();])],
diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c
index ecd6447ab7..c48f202a51 100644
--- a/lib-src/make-docfile.c
+++ b/lib-src/make-docfile.c
@@ -592,7 +592,7 @@ struct global
 };
 
 /* Bit values for FLAGS field from the above.  Applied for DEFUNs only.  */
-enum { DEFUN_noreturn = 1, DEFUN_const = 2 };
+enum { DEFUN_noreturn = 1, DEFUN_const = 2, DEFUN_noinline = 4 };
 
 /* All the variable names we saw while scanning C sources in `-g'
    mode.  */
@@ -742,6 +742,8 @@ write_globals (void)
 	{
 	  if (globals[i].flags & DEFUN_noreturn)
 	    fputs ("_Noreturn ", stdout);
+	  if (globals[i].flags & DEFUN_noinline)
+	    fputs ("NO_INLINE ", stdout);
 
 	  printf ("EXFUN (%s, ", globals[i].name);
 	  if (globals[i].v.value == -1)
@@ -1062,7 +1064,8 @@ scan_c_stream (FILE *infile)
 		   attributes: attribute1 attribute2 ...)
 	       (Lisp_Object arg...)
 
-	     Now only 'noreturn' and 'const' attributes are used.  */
+	     Now only ’const’, ’noinline’ and 'noreturn' attributes
+	     are used.  */
 
 	  /* Advance to the end of docstring.  */
 	  c = getc (infile);
@@ -1108,6 +1111,8 @@ scan_c_stream (FILE *infile)
 		g->flags |= DEFUN_noreturn;
 	      if (strstr (input_buffer, "const"))
 		g->flags |= DEFUN_const;
+	      if (strstr (input_buffer, "noinline"))
+		g->flags |= DEFUN_noinline;
 	    }
 	  continue;
 	}
diff --git a/src/alloc.c b/src/alloc.c
index 2cee646256..6e57b2024b 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -5061,22 +5061,31 @@ typedef union
 # endif
 #endif
 
+/* Yield an address close enough to the top of the stack that the
+   garbage collector need not scan above it.  Callers should be
+   declared NO_INLINE.  */
+#ifdef HAVE___BUILTIN_FRAME_ADDRESS
+# define NEAR_STACK_TOP(addr) ((void) (addr), __builtin_frame_address (0))
+#else
+# define NEAR_STACK_TOP(addr) (addr)
+#endif
+
 /* Set *P to the address of the top of the stack.  This must be a
    macro, not a function, so that it is executed in the caller’s
    environment.  It is not inside a do-while so that its storage
-   survives the macro.  */
+   survives the macro.  Callers should be declared NO_INLINE.  */
 #ifdef HAVE___BUILTIN_UNWIND_INIT
 # define SET_STACK_TOP_ADDRESS(p)	\
    stacktop_sentry sentry;		\
    __builtin_unwind_init ();		\
-   *(p) = &sentry
+   *(p) = NEAR_STACK_TOP (&sentry)
 #else
 # define SET_STACK_TOP_ADDRESS(p)		\
    stacktop_sentry sentry;			\
    __builtin_unwind_init ();			\
    test_setjmp ();				\
    sys_setjmp (sentry.j);			\
-   *(p) = &sentry + (stack_bottom < &sentry.c)
+   *(p) = NEAR_STACK_TOP (&sentry + (stack_bottom < &sentry.c))
 #endif
 
 /* Mark live Lisp objects on the C stack.
@@ -5148,7 +5157,7 @@ mark_stack (char *bottom, char *end)
    It is invalid to run any Lisp code or to allocate any GC memory
    from FUNC.  */
 
-void
+NO_INLINE void
 flush_stack_call_func (void (*func) (void *arg), void *arg)
 {
   void *end;
@@ -6097,7 +6106,8 @@ where each entry has the form (NAME SIZE USED FREE), where:
   to return them to the OS).
 However, if there was overflow in pure space, `garbage-collect'
 returns nil, because real GC can't be done.
-See Info node `(elisp)Garbage Collection'.  */)
+See Info node `(elisp)Garbage Collection'.  */
+       attributes: noinline)
   (void)
 {
   void *end;
-- 
2.13.5


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: 0003-Make-garbage-collection-more-conservative.patch --]
[-- Type: text/x-patch; name="0003-Make-garbage-collection-more-conservative.patch", Size: 18980 bytes --]

From da8dfd317be0929499f2e46f8ee4a65b109053f7 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Tue, 29 Aug 2017 14:35:37 -0700
Subject: [PATCH 3/4] Make garbage collection more conservative
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Check for a pointer anywhere within the object, as opposed to just
the start of the object.  This is needed for gcc -Os -flto on
x86-64 (Bug#28213).  This change means that the garbage collector
is more conservative, and will incorrectly keep objects that it
does not need to, but that is better than incorrectly discarding
objects that should be kept.
* src/alloc.c (ADVANCE, VINDEX): Now functions, not macros;
this is easier to debug.
(setup_on_free_list): Rename from SETUP_ON_FREE_LIST.
Now a function with two args, not a macro with three.
All callers changed.
(live_string_holding, live_cons_holding, live_symbol_holding)
(live_misc_holding, live_vector_holding, live_buffer_holding):
New functions, which check for any object containing the addressed
byte, not just for an object at the given address.
(live_string_p, live_cons_p, live_symbol_p, live_misc_p)
(live_vector_p, live_buffer_p):
Redefine in terms of the new functions.
(live_float_p): Refactor slightly to match the new functions.
(mark_maybe_object, mark_maybe_pointer): Use the new functions.
Don’t bother checking mark bits, as mark_object already does that,
and omitting the checks here simplifies the code.  Although
mark_maybe_object can continue to insist that tagged pointers
still address the start of the object, mark_maybe_pointer now is
more conservative and checks for pointers anywhere into an object.
---
 src/alloc.c | 325 ++++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 193 insertions(+), 132 deletions(-)

diff --git a/src/alloc.c b/src/alloc.c
index 6e57b2024b..300f5e420d 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -2961,25 +2961,23 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
 
 /* Common shortcut to advance vector pointer over a block data.  */
 
-#define ADVANCE(v, nbytes) ((struct Lisp_Vector *) ((char *) (v) + (nbytes)))
+static struct Lisp_Vector *
+ADVANCE (struct Lisp_Vector *v, ptrdiff_t nbytes)
+{
+  void *vv = v;
+  char *cv = vv;
+  void *p = cv + nbytes;
+  return p;
+}
 
 /* Common shortcut to calculate NBYTES-vector index in VECTOR_FREE_LISTS.  */
 
-#define VINDEX(nbytes) (((nbytes) - VBLOCK_BYTES_MIN) / roundup_size)
-
-/* Common shortcut to setup vector on a free list.  */
-
-#define SETUP_ON_FREE_LIST(v, nbytes, tmp)		\
-  do {							\
-    (tmp) = ((nbytes - header_size) / word_size);	\
-    XSETPVECTYPESIZE (v, PVEC_FREE, 0, (tmp));		\
-    eassert ((nbytes) % roundup_size == 0);		\
-    (tmp) = VINDEX (nbytes);				\
-    eassert ((tmp) < VECTOR_MAX_FREE_LIST_INDEX);	\
-    set_next_vector (v, vector_free_lists[tmp]);	\
-    vector_free_lists[tmp] = (v);			\
-    total_free_vector_slots += (nbytes) / word_size;	\
-  } while (0)
+static ptrdiff_t
+VINDEX (ptrdiff_t nbytes)
+{
+  eassume (VBLOCK_BYTES_MIN <= nbytes);
+  return (nbytes - VBLOCK_BYTES_MIN) / roundup_size;
+}
 
 /* This internal type is used to maintain the list of large vectors
    which are allocated at their own, e.g. outside of vector blocks.
@@ -3041,6 +3039,22 @@ static EMACS_INT total_vectors;
 
 static EMACS_INT total_vector_slots, total_free_vector_slots;
 
+/* Common shortcut to setup vector on a free list.  */
+
+static void
+setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t nbytes)
+{
+  eassume (header_size <= nbytes);
+  ptrdiff_t nwords = (nbytes - header_size) / word_size;
+  XSETPVECTYPESIZE (v, PVEC_FREE, 0, nwords);
+  eassert (nbytes % roundup_size == 0);
+  ptrdiff_t vindex = VINDEX (nbytes);
+  eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX);
+  set_next_vector (v, vector_free_lists[vindex]);
+  vector_free_lists[vindex] = v;
+  total_free_vector_slots += nbytes / word_size;
+}
+
 /* Get a new vector block.  */
 
 static struct vector_block *
@@ -3105,7 +3119,7 @@ allocate_vector_from_block (size_t nbytes)
 	   which should be set on an appropriate free list.  */
 	restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes;
 	eassert (restbytes % roundup_size == 0);
-	SETUP_ON_FREE_LIST (ADVANCE (vector, nbytes), restbytes, index);
+	setup_on_free_list (ADVANCE (vector, nbytes), restbytes);
 	return vector;
       }
 
@@ -3121,7 +3135,7 @@ allocate_vector_from_block (size_t nbytes)
   if (restbytes >= VBLOCK_BYTES_MIN)
     {
       eassert (restbytes % roundup_size == 0);
-      SETUP_ON_FREE_LIST (ADVANCE (vector, nbytes), restbytes, index);
+      setup_on_free_list (ADVANCE (vector, nbytes), restbytes);
     }
   return vector;
 }
@@ -3253,10 +3267,7 @@ sweep_vectors (void)
 		   space was coalesced into the only free vector.  */
 		free_this_block = 1;
 	      else
-		{
-		  size_t tmp;
-		  SETUP_ON_FREE_LIST (vector, total_bytes, tmp);
-		}
+		setup_on_free_list (vector, total_bytes);
 	    }
 	}
 
@@ -4171,7 +4182,7 @@ refill_memory_reserve (void)
    block to the red-black tree with calls to mem_insert, and function
    lisp_free removes it with mem_delete.  Functions live_string_p etc
    call mem_find to lookup information about a given pointer in the
-   tree, and use that to determine if the pointer points to a Lisp
+   tree, and use that to determine if the pointer points into a Lisp
    object or not.  */
 
 /* Initialize this part of alloc.c.  */
@@ -4549,82 +4560,113 @@ mem_delete_fixup (struct mem_node *x)
 }
 
 
-/* Value is non-zero if P is a pointer to a live Lisp string on
-   the heap.  M is a pointer to the mem_block for P.  */
+/* If P is a pointer into a live Lisp string object on the heap,
+   return the object.  Otherwise, return nil.  M is a pointer to the
+   mem_block for P.
 
-static bool
-live_string_p (struct mem_node *m, void *p)
+   This and other *_holding functions look for a pointer anywhere into
+   the object, not merely for a pointer to the start of the object,
+   because some compilers sometimes optimize away the latter.  See
+   Bug#28213.  */
+
+static Lisp_Object
+live_string_holding (struct mem_node *m, void *p)
 {
   if (m->type == MEM_TYPE_STRING)
     {
       struct string_block *b = m->start;
-      ptrdiff_t offset = (char *) p - (char *) &b->strings[0];
+      char *cp = p;
+      ptrdiff_t offset = cp - (char *) &b->strings[0];
 
-      /* P must point to the start of a Lisp_String structure, and it
+      /* P must point into a Lisp_String structure, and it
 	 must not be on the free-list.  */
-      return (offset >= 0
-	      && offset % sizeof b->strings[0] == 0
-	      && offset < (STRING_BLOCK_SIZE * sizeof b->strings[0])
-	      && ((struct Lisp_String *) p)->data != NULL);
+      if (0 <= offset && offset < STRING_BLOCK_SIZE * sizeof b->strings[0])
+	{
+	  struct Lisp_String *s = p = cp -= offset % sizeof b->strings[0];
+	  if (s->data)
+	    return make_lisp_ptr (s, Lisp_String);
+	}
     }
-  else
-    return 0;
+  return Qnil;
 }
 
+static bool
+live_string_p (struct mem_node *m, void *p)
+{
+  return !NILP (live_string_holding (m, p));
+}
 
-/* Value is non-zero if P is a pointer to a live Lisp cons on
-   the heap.  M is a pointer to the mem_block for P.  */
+/* If P is a pointer into a live Lisp cons object on the heap, return
+   the object.  Otherwise, return nil.  M is a pointer to the
+   mem_block for P.  */
 
-static bool
-live_cons_p (struct mem_node *m, void *p)
+static Lisp_Object
+live_cons_holding (struct mem_node *m, void *p)
 {
   if (m->type == MEM_TYPE_CONS)
     {
       struct cons_block *b = m->start;
-      ptrdiff_t offset = (char *) p - (char *) &b->conses[0];
+      char *cp = p;
+      ptrdiff_t offset = cp - (char *) &b->conses[0];
 
-      /* P must point to the start of a Lisp_Cons, not be
+      /* P must point into a Lisp_Cons, not be
 	 one of the unused cells in the current cons block,
 	 and not be on the free-list.  */
-      return (offset >= 0
-	      && offset % sizeof b->conses[0] == 0
-	      && offset < (CONS_BLOCK_SIZE * sizeof b->conses[0])
-	      && (b != cons_block
-		  || offset / sizeof b->conses[0] < cons_block_index)
-	      && !EQ (((struct Lisp_Cons *) p)->car, Vdead));
+      if (0 <= offset && offset < CONS_BLOCK_SIZE * sizeof b->conses[0]
+	  && (b != cons_block
+	      || offset / sizeof b->conses[0] < cons_block_index))
+	{
+	  struct Lisp_Cons *s = p = cp -= offset % sizeof b->conses[0];
+	  if (!EQ (s->car, Vdead))
+	    return make_lisp_ptr (s, Lisp_Cons);
+	}
     }
-  else
-    return 0;
+  return Qnil;
 }
 
+static bool
+live_cons_p (struct mem_node *m, void *p)
+{
+  return !NILP (live_cons_holding (m, p));
+}
 
-/* Value is non-zero if P is a pointer to a live Lisp symbol on
-   the heap.  M is a pointer to the mem_block for P.  */
 
-static bool
-live_symbol_p (struct mem_node *m, void *p)
+/* If P is a pointer into a live Lisp symbol object on the heap,
+   return the object.  Otherwise, return nil.  M is a pointer to the
+   mem_block for P.  */
+
+static Lisp_Object
+live_symbol_holding (struct mem_node *m, void *p)
 {
   if (m->type == MEM_TYPE_SYMBOL)
     {
       struct symbol_block *b = m->start;
-      ptrdiff_t offset = (char *) p - (char *) &b->symbols[0];
+      char *cp = p;
+      ptrdiff_t offset = cp - (char *) &b->symbols[0];
 
-      /* P must point to the start of a Lisp_Symbol, not be
+      /* P must point into the Lisp_Symbol, not be
 	 one of the unused cells in the current symbol block,
 	 and not be on the free-list.  */
-      return (offset >= 0
-	      && offset % sizeof b->symbols[0] == 0
-	      && offset < (SYMBOL_BLOCK_SIZE * sizeof b->symbols[0])
-	      && (b != symbol_block
-		  || offset / sizeof b->symbols[0] < symbol_block_index)
-	      && !EQ (((struct Lisp_Symbol *)p)->function, Vdead));
+      if (0 <= offset && offset < SYMBOL_BLOCK_SIZE * sizeof b->symbols[0]
+	  && (b != symbol_block
+	      || offset / sizeof b->symbols[0] < symbol_block_index))
+	{
+	  struct Lisp_Symbol *s = p = cp -= offset % sizeof b->symbols[0];
+	  if (!EQ (s->function, Vdead))
+	    return make_lisp_symbol (s);
+	}
     }
-  else
-    return 0;
+  return Qnil;
 }
 
+static bool
+live_symbol_p (struct mem_node *m, void *p)
+{
+  return !NILP (live_symbol_holding (m, p));
+}
 
-/* Value is non-zero if P is a pointer to a live Lisp float on
+
+/* Return true if P is a pointer to a live Lisp float on
    the heap.  M is a pointer to the mem_block for P.  */
 
 static bool
@@ -4633,7 +4675,8 @@ live_float_p (struct mem_node *m, void *p)
   if (m->type == MEM_TYPE_FLOAT)
     {
       struct float_block *b = m->start;
-      ptrdiff_t offset = (char *) p - (char *) &b->floats[0];
+      char *cp = p;
+      ptrdiff_t offset = cp - (char *) &b->floats[0];
 
       /* P must point to the start of a Lisp_Float and not be
 	 one of the unused cells in the current float block.  */
@@ -4648,38 +4691,48 @@ live_float_p (struct mem_node *m, void *p)
 }
 
 
-/* Value is non-zero if P is a pointer to a live Lisp Misc on
-   the heap.  M is a pointer to the mem_block for P.  */
+/* If P is a pointer to a live Lisp Misc on the heap, return the object.
+   Otherwise, return nil.  M is a pointer to the mem_block for P.  */
 
-static bool
-live_misc_p (struct mem_node *m, void *p)
+static Lisp_Object
+live_misc_holding (struct mem_node *m, void *p)
 {
   if (m->type == MEM_TYPE_MISC)
     {
       struct marker_block *b = m->start;
-      ptrdiff_t offset = (char *) p - (char *) &b->markers[0];
+      char *cp = p;
+      ptrdiff_t offset = cp - (char *) &b->markers[0];
 
-      /* P must point to the start of a Lisp_Misc, not be
+      /* P must point into a Lisp_Misc, not be
 	 one of the unused cells in the current misc block,
 	 and not be on the free-list.  */
-      return (offset >= 0
-	      && offset % sizeof b->markers[0] == 0
-	      && offset < (MARKER_BLOCK_SIZE * sizeof b->markers[0])
-	      && (b != marker_block
-		  || offset / sizeof b->markers[0] < marker_block_index)
-	      && ((union Lisp_Misc *) p)->u_any.type != Lisp_Misc_Free);
+      if (0 <= offset && offset < MARKER_BLOCK_SIZE * sizeof b->markers[0]
+	  && (b != marker_block
+	      || offset / sizeof b->markers[0] < marker_block_index))
+	{
+	  union Lisp_Misc *s = p = cp -= offset % sizeof b->markers[0];
+	  if (s->u_any.type != Lisp_Misc_Free)
+	    return make_lisp_ptr (s, Lisp_Misc);
+	}
     }
-  else
-    return 0;
+  return Qnil;
 }
 
+static bool
+live_misc_p (struct mem_node *m, void *p)
+{
+  return !NILP (live_misc_holding (m, p));
+}
 
-/* Value is non-zero if P is a pointer to a live vector-like object.
+/* If P is a pointer to a live vector-like object, return the object.
+   Otherwise, return nil.
    M is a pointer to the mem_block for P.  */
 
-static bool
-live_vector_p (struct mem_node *m, void *p)
+static Lisp_Object
+live_vector_holding (struct mem_node *m, void *p)
 {
+  struct Lisp_Vector *vp = p;
+
   if (m->type == MEM_TYPE_VECTOR_BLOCK)
     {
       /* This memory node corresponds to a vector block.  */
@@ -4691,33 +4744,59 @@ live_vector_p (struct mem_node *m, void *p)
 	 vector which is not on a free list.  FIXME: check whether
 	 some allocation patterns (probably a lot of short vectors)
 	 may cause a substantial overhead of this loop.  */
-      while (VECTOR_IN_BLOCK (vector, block)
-	     && vector <= (struct Lisp_Vector *) p)
+      while (VECTOR_IN_BLOCK (vector, block) && vector <= vp)
 	{
-	  if (!PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE) && vector == p)
-	    return true;
-	  else
-	    vector = ADVANCE (vector, vector_nbytes (vector));
+	  struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector));
+	  if (vp < next && !PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE))
+	    return make_lisp_ptr (vector, Lisp_Vectorlike);
+	  vector = next;
 	}
     }
-  else if (m->type == MEM_TYPE_VECTORLIKE && p == large_vector_vec (m->start))
-    /* This memory node corresponds to a large vector.  */
-    return 1;
-  return 0;
+  else if (m->type == MEM_TYPE_VECTORLIKE)
+    {
+      /* This memory node corresponds to a large vector.  */
+      struct Lisp_Vector *vector = large_vector_vec (m->start);
+      struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector));
+      if (vector <= vp && vp < next)
+	return make_lisp_ptr (vector, Lisp_Vectorlike);
+    }
+  return Qnil;
 }
 
+static bool
+live_vector_p (struct mem_node *m, void *p)
+{
+  return !NILP (live_vector_holding (m, p));
+}
 
-/* Value is non-zero if P is a pointer to a live buffer.  M is a
-   pointer to the mem_block for P.  */
+/* If P is a pointer into a live buffer, return the buffer.
+   Otherwise, return nil.  M is a pointer to the mem_block for P.  */
+
+static Lisp_Object
+live_buffer_holding (struct mem_node *m, void *p)
+{
+  /* P must point into the block, and the buffer
+     must not have been killed.  */
+  if (m->type == MEM_TYPE_BUFFER)
+    {
+      struct buffer *b = m->start;
+      char *cb = m->start;
+      char *cp = p;
+      ptrdiff_t offset = cp - cb;
+      if (0 <= offset && offset < sizeof *b && !NILP (b->name_))
+	{
+	  Lisp_Object obj;
+	  XSETBUFFER (obj, b);
+	  return obj;
+	}
+    }
+  return Qnil;
+}
 
 static bool
 live_buffer_p (struct mem_node *m, void *p)
 {
-  /* P must point to the start of the block, and the buffer
-     must not have been killed.  */
-  return (m->type == MEM_TYPE_BUFFER
-	  && p == m->start
-	  && !NILP (((struct buffer *) p)->name_));
+  return !NILP (live_buffer_holding (m, p));
 }
 
 /* Mark OBJ if we can prove it's a Lisp_Object.  */
@@ -4743,34 +4822,28 @@ mark_maybe_object (Lisp_Object obj)
       switch (XTYPE (obj))
 	{
 	case Lisp_String:
-	  mark_p = (live_string_p (m, po)
-		    && !STRING_MARKED_P ((struct Lisp_String *) po));
+	  mark_p = EQ (obj, live_string_holding (m, po));
 	  break;
 
 	case Lisp_Cons:
-	  mark_p = (live_cons_p (m, po) && !CONS_MARKED_P (XCONS (obj)));
+	  mark_p = EQ (obj, live_cons_holding (m, po));
 	  break;
 
 	case Lisp_Symbol:
-	  mark_p = (live_symbol_p (m, po) && !XSYMBOL (obj)->gcmarkbit);
+	  mark_p = EQ (obj, live_symbol_holding (m, po));
 	  break;
 
 	case Lisp_Float:
-	  mark_p = (live_float_p (m, po) && !FLOAT_MARKED_P (XFLOAT (obj)));
+	  mark_p = live_float_p (m, po);
 	  break;
 
 	case Lisp_Vectorlike:
-	  /* Note: can't check BUFFERP before we know it's a
-	     buffer because checking that dereferences the pointer
-	     PO which might point anywhere.  */
-	  if (live_vector_p (m, po))
-	    mark_p = !SUBRP (obj) && !VECTOR_MARKED_P (XVECTOR (obj));
-	  else if (live_buffer_p (m, po))
-	    mark_p = BUFFERP (obj) && !VECTOR_MARKED_P (XBUFFER (obj));
+	  mark_p = (EQ (obj, live_vector_holding (m, po))
+		    || EQ (obj, live_buffer_holding (m, po)));
 	  break;
 
 	case Lisp_Misc:
-	  mark_p = (live_misc_p (m, po) && !XMISCANY (obj)->gcmarkbit);
+	  mark_p = EQ (obj, live_misc_holding (m, po));
 	  break;
 
 	default:
@@ -4834,45 +4907,33 @@ mark_maybe_pointer (void *p)
 	  break;
 
 	case MEM_TYPE_BUFFER:
-	  if (live_buffer_p (m, p) && !VECTOR_MARKED_P ((struct buffer *)p))
-	    XSETVECTOR (obj, p);
+	  obj = live_buffer_holding (m, p);
 	  break;
 
 	case MEM_TYPE_CONS:
-	  if (live_cons_p (m, p) && !CONS_MARKED_P ((struct Lisp_Cons *) p))
-	    XSETCONS (obj, p);
+	  obj = live_cons_holding (m, p);
 	  break;
 
 	case MEM_TYPE_STRING:
-	  if (live_string_p (m, p)
-	      && !STRING_MARKED_P ((struct Lisp_String *) p))
-	    XSETSTRING (obj, p);
+	  obj = live_string_holding (m, p);
 	  break;
 
 	case MEM_TYPE_MISC:
-	  if (live_misc_p (m, p) && !((struct Lisp_Free *) p)->gcmarkbit)
-	    XSETMISC (obj, p);
+	  obj = live_misc_holding (m, p);
 	  break;
 
 	case MEM_TYPE_SYMBOL:
-	  if (live_symbol_p (m, p) && !((struct Lisp_Symbol *) p)->gcmarkbit)
-	    XSETSYMBOL (obj, p);
+	  obj = live_symbol_holding (m, p);
 	  break;
 
 	case MEM_TYPE_FLOAT:
-	  if (live_float_p (m, p) && !FLOAT_MARKED_P (p))
-	    XSETFLOAT (obj, p);
+	  if (live_float_p (m, p))
+	    obj = make_lisp_ptr (p, Lisp_Float);
 	  break;
 
 	case MEM_TYPE_VECTORLIKE:
 	case MEM_TYPE_VECTOR_BLOCK:
-	  if (live_vector_p (m, p))
-	    {
-	      Lisp_Object tem;
-	      XSETVECTOR (tem, p);
-	      if (!SUBRP (tem) && !VECTOR_MARKED_P (XVECTOR (tem)))
-		obj = tem;
-	    }
+	  obj = live_vector_holding (m, p);
 	  break;
 
 	default:
-- 
2.13.5


[-- Attachment #5: 0004-Be-more-conservative-in-link-time-optimization-doc.patch --]
[-- Type: text/x-patch, Size: 2973 bytes --]

From 8078980022fa6a78a4f34d2abb66d2d9b8509a5e Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Tue, 29 Aug 2017 14:52:57 -0700
Subject: [PATCH 4/4] Be more conservative in link time optimization doc

While testing --enable-link-time-optimization with GCC 7.1.1
I ran into a serious GCC code-generation bug which makes me
think that --enable-link-time-optimization should be
discouraged for typical installs (Bug#28213).  See:
https://bugzilla.redhat.com/show_bug.cgi?id=1486455
---
 INSTALL      | 18 +++++++-----------
 configure.ac |  8 ++------
 2 files changed, 9 insertions(+), 17 deletions(-)

diff --git a/INSTALL b/INSTALL
index 33084b9da3..b018055f02 100644
--- a/INSTALL
+++ b/INSTALL
@@ -339,17 +339,13 @@ Use --disable-silent-rules to cause 'make' to give more details about
 the commands it executes.  This can be helpful when debugging a build
 that goes awry.  'make V=1' also enables the extra chatter.
 
-Use --enable-link-time-optimization to enable link-time optimizer.  If
-you're using GNU compiler, this feature is supported since version 4.5.0.
-If 'configure' can determine number of online CPUS on your system, final
-link-time optimization and code generation is executed in parallel using
-one job per each available online CPU.
-
-This option is also supported for clang.  You should have GNU binutils
-with 'gold' linker and plugin support, and clang with LLVMgold.so plugin.
-Read http://llvm.org/docs/GoldPlugin.html for details.  Also note that
-this feature is still experimental, so prepare to build binutils and
-clang from the corresponding source code repositories.
+Use --enable-link-time-optimization to enable link-time optimization.
+With GCC, you need GCC 4.5.0 and later, and 'configure' arranges for
+linking to be parallelized if possible.  With Clang, you need GNU
+binutils with the gold linker and plugin support, along with the LLVM
+gold plugin <http://llvm.org/docs/GoldPlugin.html>.  Link time
+optimization is not the default as it tends to cause crashes and to
+make Emacs slower.
 
 The '--prefix=PREFIXDIR' option specifies where the installation process
 should put emacs and its data files.  This defaults to '/usr/local'.
diff --git a/configure.ac b/configure.ac
index 3dee40704d..609ecdc8f1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1041,12 +1041,8 @@ AC_DEFUN
 
 AC_ARG_ENABLE(link-time-optimization,
 [AS_HELP_STRING([--enable-link-time-optimization],
-                [build emacs with link-time optimization.
-		 This requires GCC 4.5.0 or later, or clang.
-		 (Note that clang support is experimental - see INSTALL.)
-		 It also makes Emacs harder to debug, and when we tried it
-		 with GCC 4.9.0 x86-64 it made Emacs slower, so it's not
-		 recommended for typical use.])],
+                [build with link-time optimization
+		 (experimental; see INSTALL)])])
 if test "${enableval}" != "no"; then
    ac_lto_supported=no
    if test "$emacs_cv_clang" = yes; then
-- 
2.13.5


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2017-08-29 22:07 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-08-24  7:38 bug#28213: [bootstrap] Error 2 with -Os with gcc (GCC) 7.1.1 Mutiny 
2017-08-24 16:34 ` Eli Zaretskii
2017-08-29 22:07 ` Paul Eggert

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).