]> code.delx.au - gnu-emacs/blobdiff - src/alloc.c
Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs
[gnu-emacs] / src / alloc.c
index e83b3836aa478e345a882bb2eb0451b2b2f7d7af..03dacc77c6ef7e828aa87ec178adf231a563e69f 100644 (file)
@@ -1,6 +1,6 @@
 /* Storage allocation and gc for GNU Emacs Lisp interpreter.
 
-Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2015 Free Software
+Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2016 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -406,24 +406,37 @@ ALIGN (void *ptr, int alignment)
    If A is a symbol, extract the hidden pointer's offset from lispsym,
    converted to void *.  */
 
-static void *
-XPNTR_OR_SYMBOL_OFFSET (Lisp_Object a)
-{
-  intptr_t i = USE_LSB_TAG ? XLI (a) - XTYPE (a) : XLI (a) & VALMASK;
-  return (void *) i;
-}
+#define macro_XPNTR_OR_SYMBOL_OFFSET(a) \
+  ((void *) (intptr_t) (USE_LSB_TAG ? XLI (a) - XTYPE (a) : XLI (a) & VALMASK))
 
 /* Extract the pointer hidden within A.  */
 
-static void *
+#define macro_XPNTR(a) \
+  ((void *) ((intptr_t) XPNTR_OR_SYMBOL_OFFSET (a) \
+            + (SYMBOLP (a) ? (char *) lispsym : NULL)))
+
+/* For pointer access, define XPNTR and XPNTR_OR_SYMBOL_OFFSET as
+   functions, as functions are cleaner and can be used in debuggers.
+   Also, define them as macros if being compiled with GCC without
+   optimization, for performance in that case.  The macro_* names are
+   private to this section of code.  */
+
+static ATTRIBUTE_UNUSED void *
+XPNTR_OR_SYMBOL_OFFSET (Lisp_Object a)
+{
+  return macro_XPNTR_OR_SYMBOL_OFFSET (a);
+}
+static ATTRIBUTE_UNUSED void *
 XPNTR (Lisp_Object a)
 {
-  void *p = XPNTR_OR_SYMBOL_OFFSET (a);
-  if (SYMBOLP (a))
-    p = (intptr_t) p + (char *) lispsym;
-  return p;
+  return macro_XPNTR (a);
 }
 
+#if DEFINE_KEY_OPS_AS_MACROS
+# define XPNTR_OR_SYMBOL_OFFSET(a) macro_XPNTR_OR_SYMBOL_OFFSET (a)
+# define XPNTR(a) macro_XPNTR (a)
+#endif
+
 static void
 XFLOAT_INIT (Lisp_Object f, double n)
 {
@@ -2106,8 +2119,11 @@ INIT must be an integer that represents a character.  */)
     {
       nbytes = XINT (length);
       val = make_uninit_string (nbytes);
-      memset (SDATA (val), c, nbytes);
-      SDATA (val)[nbytes] = 0;
+      if (nbytes)
+       {
+         memset (SDATA (val), c, nbytes);
+         SDATA (val)[nbytes] = 0;
+       }
     }
   else
     {
@@ -2132,7 +2148,8 @@ INIT must be an integer that represents a character.  */)
              memcpy (p, beg, len);
            }
        }
-      *p = 0;
+      if (nbytes)
+       *p = 0;
     }
 
   return val;
@@ -3175,7 +3192,8 @@ allocate_vector (EMACS_INT len)
   if (min ((nbytes_max - header_size) / word_size, MOST_POSITIVE_FIXNUM) < len)
     memory_full (SIZE_MAX);
   v = allocate_vectorlike (len);
-  v->header.size = len;
+  if (len)
+    v->header.size = len;
   return v;
 }
 
@@ -3714,7 +3732,7 @@ make_event_array (ptrdiff_t nargs, Lisp_Object *args)
 #ifdef HAVE_MODULES
 /* Create a new module user ptr object.  */
 Lisp_Object
-make_user_ptr (void (*finalizer) (void*), void *p)
+make_user_ptr (void (*finalizer) (void *), void *p)
 {
   Lisp_Object obj;
   struct Lisp_User_Ptr *uptr;
@@ -4576,6 +4594,10 @@ maybe_lisp_pointer (void *p)
   return (uintptr_t) p % GCALIGNMENT == 0;
 }
 
+#ifndef HAVE_MODULES
+enum { HAVE_MODULES = false };
+#endif
+
 /* If P points to Lisp data, mark that as live if it isn't already
    marked.  */
 
@@ -4589,8 +4611,17 @@ mark_maybe_pointer (void *p)
     VALGRIND_MAKE_MEM_DEFINED (&p, sizeof (p));
 #endif
 
-  if (!maybe_lisp_pointer (p))
-    return;
+  if (sizeof (Lisp_Object) == sizeof (void *) || !HAVE_MODULES)
+    {
+      if (!maybe_lisp_pointer (p))
+        return;
+    }
+  else
+    {
+      /* For the wide-int case, also mark emacs_value tagged pointers,
+        which can be generated by emacs-module.c's value_to_lisp.  */
+      p = (void *) ((uintptr_t) p & ~(GCALIGNMENT - 1));
+    }
 
   m = mem_find (p);
   if (m != MEM_NIL)
@@ -4667,8 +4698,7 @@ mark_maybe_pointer (void *p)
 static void ATTRIBUTE_NO_SANITIZE_ADDRESS
 mark_memory (void *start, void *end)
 {
-  void **pp;
-  int i;
+  char *pp;
 
   /* Make START the pointer to the start of the memory region,
      if it isn't already.  */
@@ -4679,6 +4709,8 @@ mark_memory (void *start, void *end)
       end = tem;
     }
 
+  eassert (((uintptr_t) start) % GC_POINTER_ALIGNMENT == 0);
+
   /* Mark Lisp data pointed to.  This is necessary because, in some
      situations, the C compiler optimizes Lisp objects away, so that
      only a pointer to them remains.  Example:
@@ -4697,13 +4729,11 @@ mark_memory (void *start, void *end)
      away.  The only reference to the life string is through the
      pointer `s'.  */
 
-  for (pp = start; (void *) pp < end; pp++)
-    for (i = 0; i < sizeof *pp; i += GC_POINTER_ALIGNMENT)
-      {
-       void *p = *(void **) ((char *) pp + i);
-       mark_maybe_pointer (p);
-       mark_maybe_object (XIL ((intptr_t) p));
-      }
+  for (pp = start; (void *) pp < end; pp += GC_POINTER_ALIGNMENT)
+    {
+      mark_maybe_pointer (*(void **) pp);
+      mark_maybe_object (*(Lisp_Object *) pp);
+    }
 }
 
 #if !defined GC_SAVE_REGISTERS_ON_STACK && !defined GC_SETJMP_WORKS
@@ -5333,7 +5363,10 @@ compact_font_cache_entry (Lisp_Object entry)
       /* Consider OBJ if it is (font-spec . [font-entity font-entity ...]).  */
       if (CONSP (obj) && GC_FONT_SPEC_P (XCAR (obj))
          && !VECTOR_MARKED_P (GC_XFONT_SPEC (XCAR (obj)))
-         && VECTORP (XCDR (obj)))
+         /* Don't use VECTORP here, as that calls ASIZE, which could
+            hit assertion violation during GC.  */
+         && (VECTORLIKEP (XCDR (obj))
+             && ! (gc_asize (XCDR (obj)) & PSEUDOVECTOR_FLAG)))
        {
          ptrdiff_t i, size = gc_asize (XCDR (obj));
          Lisp_Object obj_cdr = XCDR (obj);
@@ -5492,9 +5525,16 @@ garbage_collect_1 (void *end)
      don't let that cause a recursive GC.  */
   consing_since_gc = 0;
 
-  /* Save what's currently displayed in the echo area.  */
-  message_p = push_message ();
-  record_unwind_protect_void (pop_message_unwind);
+  /* Save what's currently displayed in the echo area.  Don't do that
+     if we are GC'ing because we've run out of memory, since
+     push_message will cons, and we might have no memory for that.  */
+  if (NILP (Vmemory_full))
+    {
+      message_p = push_message ();
+      record_unwind_protect_void (pop_message_unwind);
+    }
+  else
+    message_p = false;
 
   /* Save a copy of the contents of the stack, for debugging.  */
 #if MAX_SAVE_STACK > 0
@@ -5567,10 +5607,6 @@ garbage_collect_1 (void *end)
   mark_fringe_data ();
 #endif
 
-#ifdef HAVE_MODULES
-  mark_modules ();
-#endif
-
   /* Everything is now marked, except for the data in font caches,
      undo lists, and finalizers.  The first two are compacted by
      removing an items which aren't reachable otherwise.  */
@@ -5629,7 +5665,7 @@ garbage_collect_1 (void *end)
        }
     }
 
-  if (garbage_collection_messages)
+  if (garbage_collection_messages && NILP (Vmemory_full))
     {
       if (message_p || minibuf_level > 0)
        restore_message ();