]> code.delx.au - gnu-emacs/blobdiff - src/alloc.c
Make Fnext_read_file_uses_dialog_p compatible with recent DEFUN change.
[gnu-emacs] / src / alloc.c
index 1dbd46d6f892cc11a23d0cfd7e4251efedd50447..7c9373324075991f000f8f086f4f729fd12230d4 100644 (file)
@@ -1,6 +1,6 @@
 /* Storage allocation and gc for GNU Emacs Lisp interpreter.
 
-Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2014 Free Software
+Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2015 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -263,23 +263,6 @@ no_sanitize_memcpy (void *dest, void const *src, size_t size)
 
 #endif /* MAX_SAVE_STACK > 0 */
 
-static Lisp_Object Qconses;
-static Lisp_Object Qsymbols;
-static Lisp_Object Qmiscs;
-static Lisp_Object Qstrings;
-static Lisp_Object Qvectors;
-static Lisp_Object Qfloats;
-static Lisp_Object Qintervals;
-static Lisp_Object Qbuffers;
-static Lisp_Object Qstring_bytes, Qvector_slots, Qheap;
-static Lisp_Object Qgc_cons_threshold;
-Lisp_Object Qautomatic_gc;
-Lisp_Object Qchar_table_extra_slots;
-
-/* Hook run after GC has finished.  */
-
-static Lisp_Object Qpost_gc_hook;
-
 static void mark_terminals (void);
 static void gc_sweep (void);
 static Lisp_Object make_pure_vector (ptrdiff_t);
@@ -453,7 +436,7 @@ mmap_lisp_allowed_p (void)
   /* If we can't store all memory addresses in our lisp objects, it's
      risky to let the heap use mmap and give us addresses from all
      over our address space.  We also can't use mmap for lisp objects
-     if we might dump: unexec doesn't preserve the contents of mmaped
+     if we might dump: unexec doesn't preserve the contents of mmapped
      regions.  */
   return pointers_fit_in_lispobj_p () && !might_dump;
 }
@@ -534,8 +517,7 @@ buffer_memory_full (ptrdiff_t nbytes)
 /* Define XMALLOC_OVERRUN_SIZE_SIZE so that (1) it's large enough to
    hold a size_t value and (2) the header size is a multiple of the
    alignment that Emacs needs for C types and for USE_LSB_TAG.  */
-#define XMALLOC_BASE_ALIGNMENT                         \
-  alignof (union { long double d; intmax_t i; void *p; })
+#define XMALLOC_BASE_ALIGNMENT alignof (max_align_t)
 
 #if USE_LSB_TAG
 # define XMALLOC_HEADER_ALIGNMENT \
@@ -2226,34 +2208,7 @@ make_string (const char *contents, ptrdiff_t nbytes)
   return val;
 }
 
-#ifdef USE_LOCAL_ALLOCATORS
-
-/* Initialize the string S from DATA and SIZE.  S must be followed by
-   SIZE + 1 bytes of memory that can be used.  Return S tagged as a
-   Lisp object.  */
-
-Lisp_Object
-local_string_init (struct Lisp_String *s, char const *data, ptrdiff_t size)
-{
-  unsigned char *data_copy = (unsigned char *) (s + 1);
-  parse_str_as_multibyte ((unsigned char const *) data,
-                         size, &s->size, &s->size_byte);
-  if (size == s->size || size != s->size_byte)
-    {
-      s->size = size;
-      s->size_byte = -1;
-    }
-  s->intervals = NULL;
-  s->data = data_copy;
-  memcpy (data_copy, data, size);
-  data_copy[size] = '\0';
-  return make_lisp_ptr (s, Lisp_String);
-}
-
-#endif
-
-
-/* Make an unibyte string from LENGTH bytes at CONTENTS.  */
+/* Make a unibyte string from LENGTH bytes at CONTENTS.  */
 
 Lisp_Object
 make_unibyte_string (const char *contents, ptrdiff_t length)
@@ -2322,7 +2277,7 @@ make_specified_string (const char *contents,
 }
 
 
-/* Return an unibyte Lisp_String set up to hold LENGTH characters
+/* Return a unibyte Lisp_String set up to hold LENGTH characters
    occupying LENGTH bytes.  */
 
 Lisp_Object
@@ -2747,13 +2702,13 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0,
 static struct Lisp_Vector *
 next_vector (struct Lisp_Vector *v)
 {
-  return XUNTAG (v->contents[0], 0);
+  return XUNTAG (v->contents[0], Lisp_Int0);
 }
 
 static void
 set_next_vector (struct Lisp_Vector *v, struct Lisp_Vector *p)
 {
-  v->contents[0] = make_lisp_ptr (p, 0);
+  v->contents[0] = make_lisp_ptr (p, Lisp_Int0);
 }
 
 /* This value is balanced well enough to avoid too much internal overhead
@@ -3314,23 +3269,6 @@ See also the function `vector'.  */)
   return vector;
 }
 
-#ifdef USE_LOCAL_ALLOCATORS
-
-/* Initialize V with LENGTH objects each with value INIT,
-   and return it tagged as a Lisp Object.  */
-
-INLINE Lisp_Object
-local_vector_init (struct Lisp_Vector *v, ptrdiff_t length, Lisp_Object init)
-{
-  v->header.size = length;
-  for (ptrdiff_t i = 0; i < length; i++)
-    v->contents[i] = init;
-  return make_lisp_ptr (v, Lisp_Vectorlike);
-}
-
-#endif
-
-
 DEFUN ("vector", Fvector, Svector, 0, MANY, 0,
        doc: /* Return a newly created vector with specified arguments as elements.
 Any number of arguments, even zero arguments, are allowed.
@@ -3455,13 +3393,29 @@ set_symbol_name (Lisp_Object sym, Lisp_Object name)
   XSYMBOL (sym)->name = name;
 }
 
+void
+init_symbol (Lisp_Object val, Lisp_Object name)
+{
+  struct Lisp_Symbol *p = XSYMBOL (val);
+  set_symbol_name (val, name);
+  set_symbol_plist (val, Qnil);
+  p->redirect = SYMBOL_PLAINVAL;
+  SET_SYMBOL_VAL (p, Qunbound);
+  set_symbol_function (val, Qnil);
+  set_symbol_next (val, NULL);
+  p->gcmarkbit = false;
+  p->interned = SYMBOL_UNINTERNED;
+  p->constant = 0;
+  p->declared_special = false;
+  p->pinned = false;
+}
+
 DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0,
        doc: /* Return a newly allocated uninterned symbol whose name is NAME.
 Its value is void, and its function definition and property list are nil.  */)
   (Lisp_Object name)
 {
-  register Lisp_Object val;
-  register struct Lisp_Symbol *p;
+  Lisp_Object val;
 
   CHECK_STRING (name);
 
@@ -3489,18 +3443,7 @@ Its value is void, and its function definition and property list are nil.  */)
 
   MALLOC_UNBLOCK_INPUT;
 
-  p = XSYMBOL (val);
-  set_symbol_name (val, name);
-  set_symbol_plist (val, Qnil);
-  p->redirect = SYMBOL_PLAINVAL;
-  SET_SYMBOL_VAL (p, Qunbound);
-  set_symbol_function (val, Qnil);
-  set_symbol_next (val, NULL);
-  p->gcmarkbit = false;
-  p->interned = SYMBOL_UNINTERNED;
-  p->constant = 0;
-  p->declared_special = false;
-  p->pinned = false;
+  init_symbol (val, name);
   consing_since_gc += sizeof (struct Lisp_Symbol);
   symbols_consed++;
   total_free_symbols--;
@@ -3651,17 +3594,6 @@ make_save_ptr_int (void *a, ptrdiff_t b)
   return val;
 }
 
-Lisp_Object
-make_save_int_obj (ptrdiff_t a, Lisp_Object b)
-{
-  Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
-  struct Lisp_Save_Value *p = XSAVE_VALUE (val);
-  p->save_type = SAVE_TYPE_INT_OBJ;
-  p->data[0].integer = a;
-  p->data[1].object = b;
-  return val;
-}
-
 #if ! (defined USE_X_TOOLKIT || defined USE_GTK)
 Lisp_Object
 make_save_ptr_ptr (void *a, void *b)
@@ -4981,6 +4913,14 @@ mark_stack (void *end)
 
 #endif /* GC_MARK_STACK != 0 */
 
+static bool
+c_symbol_p (struct Lisp_Symbol *sym)
+{
+  char *lispsym_ptr = (char *) lispsym;
+  char *sym_ptr = (char *) sym;
+  ptrdiff_t lispsym_offset = sym_ptr - lispsym_ptr;
+  return 0 <= lispsym_offset && lispsym_offset < sizeof lispsym;
+}
 
 /* Determine whether it is safe to access memory at address P.  */
 static int
@@ -4989,6 +4929,10 @@ valid_pointer_p (void *p)
 #ifdef WINDOWSNT
   return w32_valid_pointer_p (p, 16);
 #else
+
+  if (ADDRESS_SANITIZER)
+    return p ? -1 : 0;
+
   int fd[2];
 
   /* Obviously, we cannot just access it (we would SEGV trying), so we
@@ -5004,7 +4948,7 @@ valid_pointer_p (void *p)
       return valid;
     }
 
-    return -1;
+  return -1;
 #endif
 }
 
@@ -5030,6 +4974,9 @@ valid_lisp_object_p (Lisp_Object obj)
   if (PURE_POINTER_P (p))
     return 1;
 
+  if (SYMBOLP (obj) && c_symbol_p (p))
+    return ((char *) p - (char *) lispsym) % sizeof lispsym[0] == 0;
+
   if (p == &buffer_defaults || p == &buffer_local_symbols)
     return 2;
 
@@ -5103,8 +5050,8 @@ relocatable_string_data_p (const char *str)
       struct sdata *sdata
        = (struct sdata *) (str - offsetof (struct sdata, data));
 
-      if (valid_pointer_p (sdata)
-         && valid_pointer_p (sdata->string)
+      if (0 < valid_pointer_p (sdata)
+         && 0 < valid_pointer_p (sdata->string)
          && maybe_lisp_pointer (sdata->string))
        return (valid_lisp_object_p
                (make_lisp_ptr (sdata->string, Lisp_String))
@@ -5395,7 +5342,7 @@ purecopy (Lisp_Object obj)
     }
   else if (SYMBOLP (obj))
     {
-      if (!XSYMBOL (obj)->pinned)
+      if (!XSYMBOL (obj)->pinned && !c_symbol_p (XSYMBOL (obj)))
        { /* We can't purify them, but they appear in many pure objects.
             Mark them as `pinned' so we know to mark them at every GC cycle.  */
          XSYMBOL (obj)->pinned = true;
@@ -5584,7 +5531,7 @@ mark_pinned_symbols (void)
       union aligned_Lisp_Symbol *sym = sblk->symbols, *end = sym + lim;
       for (; sym < end; ++sym)
        if (sym->s.pinned)
-         mark_object (make_lisp_ptr (&sym->s, Lisp_Symbol));
+         mark_object (make_lisp_symbol (&sym->s));
 
       lim = SYMBOL_BLOCK_SIZE;
     }
@@ -5618,7 +5565,7 @@ garbage_collect_1 (void *end)
     return Qnil;
 
   /* Record this function, so it appears on the profiler's backtraces.  */
-  record_in_backtrace (Qautomatic_gc, &Qnil, 0);
+  record_in_backtrace (Qautomatic_gc, 0, 0);
 
   check_cons_list ();
 
@@ -5682,6 +5629,9 @@ garbage_collect_1 (void *end)
   mark_buffer (&buffer_defaults);
   mark_buffer (&buffer_local_symbols);
 
+  for (i = 0; i < ARRAYELTS (lispsym); i++)
+    mark_object (builtin_lisp_symbol (i));
+
   for (i = 0; i < staticidx; i++)
     mark_object (*staticvec[i]);
 
@@ -6070,8 +6020,9 @@ mark_overlay (struct Lisp_Overlay *ptr)
   for (; ptr && !ptr->gcmarkbit; ptr = ptr->next)
     {
       ptr->gcmarkbit = 1;
-      mark_object (ptr->start);
-      mark_object (ptr->end);
+      /* These two are always markers and can be marked fast.  */
+      XMARKER (ptr->start)->gcmarkbit = 1;
+      XMARKER (ptr->end)->gcmarkbit = 1;
       mark_object (ptr->plist);
     }
 }
@@ -6206,15 +6157,16 @@ void
 mark_object (Lisp_Object arg)
 {
   register Lisp_Object obj = arg;
-#ifdef GC_CHECK_MARKED_OBJECTS
   void *po;
+#ifdef GC_CHECK_MARKED_OBJECTS
   struct mem_node *m;
 #endif
   ptrdiff_t cdr_count = 0;
 
  loop:
 
-  if (PURE_POINTER_P (XPNTR (obj)))
+  po = XPNTR (obj);
+  if (PURE_POINTER_P (po))
     return;
 
   last_marked[last_marked_index++] = obj;
@@ -6226,8 +6178,6 @@ mark_object (Lisp_Object arg)
      by ~80%, and requires compilation with GC_MARK_STACK != 0.  */
 #ifdef GC_CHECK_MARKED_OBJECTS
 
-  po = (void *) XPNTR (obj);
-
   /* Check that the object pointed to by PO is known to be a Lisp
      structure allocated from the heap.  */
 #define CHECK_ALLOCATED()                      \
@@ -6245,17 +6195,28 @@ mark_object (Lisp_Object arg)
       emacs_abort ();                          \
   } while (0)
 
-  /* Check both of the above conditions.  */
+  /* Check both of the above conditions, for non-symbols.  */
 #define CHECK_ALLOCATED_AND_LIVE(LIVEP)                \
   do {                                         \
     CHECK_ALLOCATED ();                                \
     CHECK_LIVE (LIVEP);                                \
   } while (0)                                  \
 
+  /* Check both of the above conditions, for symbols.  */
+#define CHECK_ALLOCATED_AND_LIVE_SYMBOL()      \
+  do {                                         \
+    if (!c_symbol_p (ptr))                     \
+      {                                                \
+       CHECK_ALLOCATED ();                     \
+       CHECK_LIVE (live_symbol_p);             \
+      }                                                \
+  } while (0)                                  \
+
 #else /* not GC_CHECK_MARKED_OBJECTS */
 
-#define CHECK_LIVE(LIVEP)              (void) 0
-#define CHECK_ALLOCATED_AND_LIVE(LIVEP)        (void) 0
+#define CHECK_LIVE(LIVEP)                      ((void) 0)
+#define CHECK_ALLOCATED_AND_LIVE(LIVEP)                ((void) 0)
+#define CHECK_ALLOCATED_AND_LIVE_SYMBOL()      ((void) 0)
 
 #endif /* not GC_CHECK_MARKED_OBJECTS */
 
@@ -6415,10 +6376,10 @@ mark_object (Lisp_Object arg)
       nextsym:
        if (ptr->gcmarkbit)
          break;
-       CHECK_ALLOCATED_AND_LIVE (live_symbol_p);
+       CHECK_ALLOCATED_AND_LIVE_SYMBOL ();
        ptr->gcmarkbit = 1;
        /* Attempt to catch bogus objects.  */
-        eassert (valid_lisp_object_p (ptr->function) >= 1);
+        eassert (valid_lisp_object_p (ptr->function));
        mark_object (ptr->function);
        mark_object (ptr->plist);
        switch (ptr->redirect)
@@ -6772,13 +6733,16 @@ NO_INLINE /* For better stack traces */
 static void
 sweep_symbols (void)
 {
-  register struct symbol_block *sblk;
+  struct symbol_block *sblk;
   struct symbol_block **sprev = &symbol_block;
-  register int lim = symbol_block_index;
-  EMACS_INT num_free = 0, num_used = 0;
+  int lim = symbol_block_index;
+  EMACS_INT num_free = 0, num_used = ARRAYELTS (lispsym);
 
   symbol_free_list = NULL;
 
+  for (int i = 0; i < ARRAYELTS (lispsym); i++)
+    lispsym[i].gcmarkbit = 0;
+
   for (sblk = symbol_block; sblk; sblk = *sprev)
     {
       int this_free = 0;
@@ -6803,7 +6767,7 @@ sweep_symbols (void)
               ++num_used;
               sym->s.gcmarkbit = 0;
               /* Attempt to catch bogus objects.  */
-              eassert (valid_lisp_object_p (sym->s.function) >= 1);
+              eassert (valid_lisp_object_p (sym->s.function));
             }
         }
 
@@ -7026,6 +6990,21 @@ Frames, windows, buffers, and subprocesses count as vectors
                bounded_number (strings_consed));
 }
 
+static bool
+symbol_uses_obj (Lisp_Object symbol, Lisp_Object obj)
+{
+  struct Lisp_Symbol *sym = XSYMBOL (symbol);
+  Lisp_Object val = find_symbol_value (symbol);
+  return (EQ (val, obj)
+         || EQ (sym->function, obj)
+         || (!NILP (sym->function)
+             && COMPILEDP (sym->function)
+             && EQ (AREF (sym->function, COMPILED_BYTECODE), obj))
+         || (!NILP (val)
+             && COMPILEDP (val)
+             && EQ (AREF (val, COMPILED_BYTECODE), obj)));
+}
+
 /* Find at most FIND_MAX symbols which have OBJ as their value or
    function.  This is used in gdbinit's `xwhichsymbols' command.  */
 
@@ -7038,6 +7017,17 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max)
 
    if (! DEADP (obj))
      {
+       for (int i = 0; i < ARRAYELTS (lispsym); i++)
+        {
+          Lisp_Object sym = builtin_lisp_symbol (i);
+          if (symbol_uses_obj (sym, obj))
+            {
+              found = Fcons (sym, found);
+              if (--find_max == 0)
+                goto out;
+            }
+        }
+
        for (sblk = symbol_block; sblk; sblk = sblk->next)
         {
           union aligned_Lisp_Symbol *aligned_sym = sblk->symbols;
@@ -7045,25 +7035,13 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max)
 
           for (bn = 0; bn < SYMBOL_BLOCK_SIZE; bn++, aligned_sym++)
             {
-              struct Lisp_Symbol *sym = &aligned_sym->s;
-              Lisp_Object val;
-              Lisp_Object tem;
-
               if (sblk == symbol_block && bn >= symbol_block_index)
                 break;
 
-              XSETSYMBOL (tem, sym);
-              val = find_symbol_value (tem);
-              if (EQ (val, obj)
-                  || EQ (sym->function, obj)
-                  || (!NILP (sym->function)
-                      && COMPILEDP (sym->function)
-                      && EQ (AREF (sym->function, COMPILED_BYTECODE), obj))
-                  || (!NILP (val)
-                      && COMPILEDP (val)
-                      && EQ (AREF (val, COMPILED_BYTECODE), obj)))
+              Lisp_Object sym = make_lisp_symbol (&aligned_sym->s);
+              if (symbol_uses_obj (sym, obj))
                 {
-                  found = Fcons (tem, found);
+                  found = Fcons (sym, found);
                   if (--find_max == 0)
                     goto out;
                 }
@@ -7131,7 +7109,7 @@ detect_suspicious_free (void* ptr)
 
 DEFUN ("suspicious-object", Fsuspicious_object, Ssuspicious_object, 1, 1, 0,
        doc: /* Return OBJ, maybe marking it for extra scrutiny.
-If Emacs is compiled with suspicous object checking, capture
+If Emacs is compiled with suspicious object checking, capture
 a stack trace when OBJ is freed in order to help track down
 garbage collection bugs.  Otherwise, do nothing and return OBJ.   */)
    (Lisp_Object obj)
@@ -7162,7 +7140,22 @@ die (const char *msg, const char *file, int line)
 
 #endif /* ENABLE_CHECKING */
 
-#if defined (ENABLE_CHECKING) && defined (USE_STACK_LISP_OBJECTS)
+#if defined (ENABLE_CHECKING) && USE_STACK_LISP_OBJECTS
+
+/* Debugging check whether STR is ASCII-only.  */
+
+const char *
+verify_ascii (const char *str)
+{
+  const unsigned char *ptr = (unsigned char *) str, *end = ptr + strlen (str);
+  while (ptr < end)
+    {
+      int c = STRING_CHAR_ADVANCE (ptr);
+      if (!ASCII_CHAR_P (c))
+       emacs_abort ();
+    }
+  return str;
+}
 
 /* Stress alloca with inconveniently sized requests and check
    whether all allocated areas may be used for Lisp_Object.  */
@@ -7180,7 +7173,7 @@ verify_alloca (void)
     }
 }
 
-#else /* not (ENABLE_CHECKING && USE_STACK_LISP_OBJECTS) */
+#else /* not ENABLE_CHECKING && USE_STACK_LISP_OBJECTS */
 
 #define verify_alloca() ((void) 0)
 
@@ -7191,7 +7184,9 @@ verify_alloca (void)
 void
 init_alloc_once (void)
 {
-  /* Used to do Vpurify_flag = Qt here, but Qt isn't set up yet!  */
+  /* Even though Qt's contents are not set up, its address is known.  */
+  Vpurify_flag = Qt;
+
   purebeg = PUREBEG;
   pure_size = PURESIZE;
 
@@ -7267,6 +7262,7 @@ If this portion is smaller than `gc-cons-threshold', this is ignored.  */);
 
   DEFVAR_INT ("symbols-consed", symbols_consed,
              doc: /* Number of symbols that have been consed so far.  */);
+  symbols_consed += ARRAYELTS (lispsym);
 
   DEFVAR_INT ("string-chars-consed", string_chars_consed,
              doc: /* Number of string characters that have been consed so far.  */);