Fix failure to compile on Windows due to 2012-07-27T06:04:35Z!dmantipov@yandex.ru.
[bpt/emacs.git] / src / alloc.c
index 166f5b7..27426cd 100644 (file)
@@ -161,6 +161,10 @@ static pthread_mutex_t alloc_mutex;
 
 #define GC_STRING_BYTES(S)     (STRING_BYTES (S))
 
+/* Default value of gc_cons_threshold (see below).  */
+
+#define GC_DEFAULT_THRESHOLD (100000 * sizeof (Lisp_Object))
+
 /* Global variables.  */
 struct emacs_globals globals;
 
@@ -258,6 +262,7 @@ static char *stack_copy;
 static ptrdiff_t stack_copy_size;
 #endif
 
+static Lisp_Object Qstring_bytes, Qvector_slots, Qheap;
 static Lisp_Object Qgc_cons_threshold;
 Lisp_Object Qchar_table_extra_slots;
 
@@ -2710,6 +2715,7 @@ free_cons (struct Lisp_Cons *ptr)
   ptr->car = Vdead;
 #endif
   cons_free_list = ptr;
+  consing_since_gc -= sizeof *ptr;
   total_free_conses++;
 }
 
@@ -2805,6 +2811,38 @@ list5 (Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, Lisp_Object arg4, L
                                                       Fcons (arg5, Qnil)))));
 }
 
+/* Make a list of COUNT Lisp_Objects, where ARG is the
+   first one.  Allocate conses from pure space if TYPE
+   is CONSTYPE_PURE, or allocate as usual if type is CONSTYPE_HEAP.  */
+
+Lisp_Object
+listn (enum constype type, ptrdiff_t count, Lisp_Object arg, ...)
+{
+  va_list ap;
+  ptrdiff_t i;
+  Lisp_Object val, *objp;
+
+  /* Change to SAFE_ALLOCA if you hit this eassert.  */
+  eassert (count <= MAX_ALLOCA / sizeof (Lisp_Object));
+
+  objp = alloca (count * sizeof (Lisp_Object));
+  objp[0] = arg;
+  va_start (ap, arg);
+  for (i = 1; i < count; i++)
+    objp[i] = va_arg (ap, Lisp_Object);
+  va_end (ap);
+
+  for (i = 0, val = Qnil; i < count; i++)
+    {
+      if (type == CONSTYPE_PURE)
+       val = pure_cons (objp[i], val);
+      else if (type == CONSTYPE_HEAP)
+       val = Fcons (objp[i], val);
+      else
+       abort ();
+    }
+  return val;
+}
 
 DEFUN ("list", Flist, Slist, 0, MANY, 0,
        doc: /* Return a newly created list with specified arguments as elements.
@@ -2937,7 +2975,7 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
     eassert ((index) < VECTOR_MAX_FREE_LIST_INDEX);            \
     (v)->header.next.vector = vector_free_lists[index];                \
     vector_free_lists[index] = (v);                            \
-    total_free_vector_bytes += (nbytes);                       \
+    total_free_vector_slots += (nbytes) / word_size;           \
   } while (0)
 
 struct vector_block
@@ -2967,9 +3005,9 @@ Lisp_Object zero_vector;
 
 static EMACS_INT total_vectors;
 
-/* Number of bytes used by live and free vectors.  */
+/* Total size of live and free vectors, in Lisp_Object units.  */
 
-static EMACS_INT total_vector_bytes, total_free_vector_bytes;
+static EMACS_INT total_vector_slots, total_free_vector_slots;
 
 /* Get a new vector block.  */
 
@@ -3016,7 +3054,7 @@ allocate_vector_from_block (size_t nbytes)
       vector = vector_free_lists[index];
       vector_free_lists[index] = vector->header.next.vector;
       vector->header.next.nbytes = nbytes;
-      total_free_vector_bytes -= nbytes;
+      total_free_vector_slots -= nbytes / word_size;
       return vector;
     }
 
@@ -3031,7 +3069,7 @@ allocate_vector_from_block (size_t nbytes)
        vector = vector_free_lists[index];
        vector_free_lists[index] = vector->header.next.vector;
        vector->header.next.nbytes = nbytes;
-       total_free_vector_bytes -= nbytes;
+       total_free_vector_slots -= nbytes / word_size;
 
        /* Excess bytes are used for the smaller vector,
           which should be set on an appropriate free list.  */
@@ -3085,7 +3123,7 @@ sweep_vectors (void)
   struct vector_block *block = vector_blocks, **bprev = &vector_blocks;
   struct Lisp_Vector *vector, *next, **vprev = &large_vectors;
 
-  total_vectors = total_vector_bytes = total_free_vector_bytes = 0;
+  total_vectors = total_vector_slots = total_free_vector_slots = 0;
   memset (vector_free_lists, 0, sizeof (vector_free_lists));
 
   /* Looking through vector blocks.  */
@@ -3101,7 +3139,7 @@ sweep_vectors (void)
            {
              VECTOR_UNMARK (vector);
              total_vectors++;
-             total_vector_bytes += vector->header.next.nbytes;
+             total_vector_slots += vector->header.next.nbytes / word_size;
              next = ADVANCE (vector, vector->header.next.nbytes);
            }
          else
@@ -3167,14 +3205,14 @@ sweep_vectors (void)
                 pseudovector type grows beyond VBLOCK_BYTES_MAX.  */
              eassert (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR));
 
-             total_vector_bytes
+             total_vector_slots
                += (bool_header_size
                    + ((b->size + BOOL_VECTOR_BITS_PER_CHAR - 1)
-                      / BOOL_VECTOR_BITS_PER_CHAR));
+                      / BOOL_VECTOR_BITS_PER_CHAR)) / word_size;
            }
          else
-           total_vector_bytes += (header_size
-                                  + vector->header.size * word_size);
+           total_vector_slots
+             += header_size / word_size + vector->header.size;
          vprev = &vector->header.next.vector;
        }
       else
@@ -3558,10 +3596,10 @@ static int marker_block_index = MARKER_BLOCK_SIZE;
 
 static union Lisp_Misc *marker_free_list;
 
-/* Return a newly allocated Lisp_Misc object, with no substructure.  */
+/* Return a newly allocated Lisp_Misc object of specified TYPE.  */
 
-Lisp_Object
-allocate_misc (void)
+static Lisp_Object
+allocate_misc (enum Lisp_Misc_Type type)
 {
   Lisp_Object val;
 
@@ -3593,6 +3631,7 @@ allocate_misc (void)
   --total_free_markers;
   consing_since_gc += sizeof (union Lisp_Misc);
   misc_objects_consed++;
+  XMISCTYPE (val) = type;
   XMISCANY (val)->gcmarkbit = 0;
   return val;
 }
@@ -3605,7 +3644,7 @@ free_misc (Lisp_Object misc)
   XMISCTYPE (misc) = Lisp_Misc_Free;
   XMISC (misc)->u_free.chain = marker_free_list;
   marker_free_list = XMISC (misc);
-
+  consing_since_gc -= sizeof (union Lisp_Misc);
   total_free_markers++;
 }
 
@@ -3619,8 +3658,7 @@ make_save_value (void *pointer, ptrdiff_t integer)
   register Lisp_Object val;
   register struct Lisp_Save_Value *p;
 
-  val = allocate_misc ();
-  XMISCTYPE (val) = Lisp_Misc_Save_Value;
+  val = allocate_misc (Lisp_Misc_Save_Value);
   p = XSAVE_VALUE (val);
   p->pointer = pointer;
   p->integer = integer;
@@ -3628,6 +3666,21 @@ make_save_value (void *pointer, ptrdiff_t integer)
   return val;
 }
 
+/* Return a Lisp_Misc_Overlay object with specified START, END and PLIST.  */
+
+Lisp_Object
+build_overlay (Lisp_Object start, Lisp_Object end, Lisp_Object plist)
+{
+  register Lisp_Object overlay;
+
+  overlay = allocate_misc (Lisp_Misc_Overlay);
+  OVERLAY_START (overlay) = start;
+  OVERLAY_END (overlay) = end;
+  OVERLAY_PLIST (overlay) = plist;
+  XOVERLAY (overlay)->next = NULL;
+  return overlay;
+}
+
 DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0,
        doc: /* Return a newly allocated marker which does not point at any place.  */)
   (void)
@@ -3635,8 +3688,7 @@ DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0,
   register Lisp_Object val;
   register struct Lisp_Marker *p;
 
-  val = allocate_misc ();
-  XMISCTYPE (val) = Lisp_Misc_Marker;
+  val = allocate_misc (Lisp_Misc_Marker);
   p = XMARKER (val);
   p->buffer = 0;
   p->bytepos = 0;
@@ -3661,8 +3713,7 @@ build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos)
   /* Every character is at least one byte.  */
   eassert (charpos <= bytepos);
 
-  obj = allocate_misc ();
-  XMISCTYPE (obj) = Lisp_Misc_Marker;
+  obj = allocate_misc (Lisp_Misc_Marker);
   m = XMARKER (obj);
   m->buffer = buf;
   m->charpos = charpos;
@@ -5377,15 +5428,14 @@ DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "",
        doc: /* Reclaim storage for Lisp objects no longer needed.
 Garbage collection happens automatically if you cons more than
 `gc-cons-threshold' bytes of Lisp data since previous garbage collection.
-`garbage-collect' normally returns a list with info on amount of space in use:
- ((CONS INTERNAL-SIZE USED-CONSES FREE-CONSES)
-  (SYMBOL INTERNAL-SIZE USED-SYMBOLS FREE-SYMBOLS)
-  (MISC INTERNAL-SIZE USED-MISCS FREE-MISCS)
-  (STRING INTERNAL-SIZE USED-STRINGS USED-STRING-BYTES FREE-STRING)
-  (VECTOR INTERNAL-SIZE USED-VECTORS USED-VECTOR-BYTES FREE-VECTOR-BYTES)
-  (FLOAT INTERNAL-SIZE USED-FLOATS FREE-FLOATS)
-  (INTERVAL INTERNAL-SIZE USED-INTERVALS FREE-INTERVALS)
-  (BUFFER INTERNAL-SIZE USED-BUFFERS))
+`garbage-collect' normally returns a list with info on amount of space in use,
+where each entry has the form (NAME SIZE USED FREE), where:
+- NAME is a symbol describing the kind of objects this entry represents,
+- SIZE is the number of bytes used by each one,
+- USED is the number of those objects that were found live in the heap,
+- FREE is the number of those objects that are not live but that Emacs
+  keeps around for future allocations (maybe because it does not know how
+  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'.  */)
@@ -5396,7 +5446,7 @@ See Info node `(elisp)Garbage Collection'.  */)
   char stack_top_variable;
   ptrdiff_t i;
   int message_p;
-  Lisp_Object total[8];
+  Lisp_Object total[11];
   ptrdiff_t count = SPECPDL_INDEX ();
   EMACS_TIME t1;
 
@@ -5412,34 +5462,8 @@ See Info node `(elisp)Garbage Collection'.  */)
 
   /* Don't keep undo information around forever.
      Do this early on, so it is no problem if the user quits.  */
-  for_each_buffer (nextb)
-    {
-      /* If a buffer's undo list is Qt, that means that undo is
-        turned off in that buffer.  Calling truncate_undo_list on
-        Qt tends to return NULL, which effectively turns undo back on.
-        So don't call truncate_undo_list if undo_list is Qt.  */
-      if (! NILP (nextb->BUFFER_INTERNAL_FIELD (name))
-         && ! EQ (nextb->BUFFER_INTERNAL_FIELD (undo_list), Qt))
-       truncate_undo_list (nextb);
-
-      /* Shrink buffer gaps, but skip indirect and dead buffers.  */
-      if (nextb->base_buffer == 0 && !NILP (nextb->BUFFER_INTERNAL_FIELD (name))
-         && ! nextb->text->inhibit_shrinking)
-       {
-         /* If a buffer's gap size is more than 10% of the buffer
-            size, or larger than 2000 bytes, then shrink it
-            accordingly.  Keep a minimum size of 20 bytes.  */
-         int size = min (2000, max (20, (nextb->text->z_byte / 10)));
-
-         if (nextb->text->gap_size > size)
-           {
-             struct buffer *save_current = current_buffer;
-             current_buffer = nextb;
-             make_gap (-(nextb->text->gap_size - size));
-             current_buffer = save_current;
-           }
-       }
-    }
+  FOR_EACH_BUFFER (nextb)
+    compact_buffer (nextb);
 
   t1 = current_emacs_time ();
 
@@ -5488,8 +5512,6 @@ See Info node `(elisp)Garbage Collection'.  */)
 
   gc_in_progress = 1;
 
-  /* clear_marks (); */
-
   /* Mark all the special slots that serve as the roots of accessibility.  */
 
   for (i = 0; i < staticidx; i++)
@@ -5553,7 +5575,7 @@ See Info node `(elisp)Garbage Collection'.  */)
      Look thru every buffer's undo list
      for elements that update markers that were not marked,
      and delete them.  */
-  for_each_buffer (nextb)
+  FOR_EACH_BUFFER (nextb)
     {
       /* If a buffer's undo list is Qt, that means that undo is
         turned off in that buffer.  Calling truncate_undo_list on
@@ -5606,12 +5628,11 @@ See Info node `(elisp)Garbage Collection'.  */)
 
   CHECK_CONS_LIST ();
 
-  /* clear_marks (); */
   gc_in_progress = 0;
 
   consing_since_gc = 0;
-  if (gc_cons_threshold < 10000)
-    gc_cons_threshold = 10000;
+  if (gc_cons_threshold < GC_DEFAULT_THRESHOLD / 10)
+    gc_cons_threshold = GC_DEFAULT_THRESHOLD / 10;
 
   gc_relative_threshold = 0;
   if (FLOATP (Vgc_cons_percentage))
@@ -5622,7 +5643,7 @@ See Info node `(elisp)Garbage Collection'.  */)
       tot += total_symbols * sizeof (struct Lisp_Symbol);
       tot += total_markers * sizeof (union Lisp_Misc);
       tot += total_string_bytes;
-      tot += total_vector_bytes;
+      tot += total_vector_slots * word_size;
       tot += total_floats  * sizeof (struct Lisp_Float);
       tot += total_intervals * sizeof (struct interval);
       tot += total_strings * sizeof (struct Lisp_String);
@@ -5659,27 +5680,40 @@ See Info node `(elisp)Garbage Collection'.  */)
                    bounded_number (total_markers),
                    bounded_number (total_free_markers));
 
-  total[3] = list5 (Qstring, make_number (sizeof (struct Lisp_String)),
+  total[3] = list4 (Qstring, make_number (sizeof (struct Lisp_String)),
                    bounded_number (total_strings),
-                   bounded_number (total_string_bytes),
                    bounded_number (total_free_strings));
 
-  total[4] = list5 (Qvector, make_number (sizeof (struct Lisp_Vector)),
-                   bounded_number (total_vectors),
-                   bounded_number (total_vector_bytes),
-                   bounded_number (total_free_vector_bytes));
+  total[4] = list3 (Qstring_bytes, make_number (1),
+                   bounded_number (total_string_bytes));
 
-  total[5] = list4 (Qfloat, make_number (sizeof (struct Lisp_Float)),
+  total[5] = list3 (Qvector, make_number (sizeof (struct Lisp_Vector)),
+                   bounded_number (total_vectors));
+
+  total[6] = list4 (Qvector_slots, make_number (word_size),
+                   bounded_number (total_vector_slots),
+                   bounded_number (total_free_vector_slots));
+
+  total[7] = list4 (Qfloat, make_number (sizeof (struct Lisp_Float)),
                    bounded_number (total_floats),
                     bounded_number (total_free_floats));
 
-  total[6] = list4 (Qinterval, make_number (sizeof (struct interval)),
+  total[8] = list4 (Qinterval, make_number (sizeof (struct interval)),
                    bounded_number (total_intervals),
                     bounded_number (total_free_intervals));
 
-  total[7] = list3 (Qbuffer, make_number (sizeof (struct buffer)),
+  total[9] = list3 (Qbuffer, make_number (sizeof (struct buffer)),
                    bounded_number (total_buffers));
 
+  total[10] = list4 (Qheap, make_number (1024),
+#ifdef DOUG_LEA_MALLOC
+                    bounded_number ((mallinfo ().uordblks + 1023) >> 10),
+                    bounded_number ((mallinfo ().fordblks + 1023) >> 10)
+#else
+                    Qnil, Qnil
+#endif
+                    );
+
 #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
   {
     /* Compute average percentage of zombies.  */
@@ -5977,7 +6011,7 @@ mark_object (Lisp_Object arg)
            if (po != &buffer_defaults && po != &buffer_local_symbols)
              {
                struct buffer *b;
-               for_each_buffer (b)
+               FOR_EACH_BUFFER (b)
                  if (b == po)
                    break;
                if (b == NULL)
@@ -6627,33 +6661,6 @@ We divide the value by 1024 to make sure it fits in a Lisp integer.  */)
   return end;
 }
 
-DEFUN ("memory-free", Fmemory_free, Smemory_free, 0, 0, 0,
-       doc: /* Return a list (E H) of two measures of free memory.
-E counts free lists maintained by Emacs itself.  H counts the heap,
-freed by Emacs but not released to the operating system; this is zero
-if heap statistics are not available.  Both counters are in units of
-1024 bytes, rounded up.  */)
-     (void)
-{
-  /* Make the return value first, so that its storage is accounted for.  */
-  Lisp_Object val = Fmake_list (make_number (2), make_number (0));
-
-  XSETCAR (val,
-          bounded_number
-          ((total_free_conses * sizeof (struct Lisp_Cons)
-            + total_free_markers * sizeof (union Lisp_Misc)
-            + total_free_symbols * sizeof (struct Lisp_Symbol)
-            + total_free_floats * sizeof (struct Lisp_Float)
-            + total_free_intervals * sizeof (struct interval)
-            + total_free_strings * sizeof (struct Lisp_String)
-            + total_free_vector_bytes
-            + 1023) >> 10));
-#ifdef DOUG_LEA_MALLOC
-  XSETCAR (XCDR (val), bounded_number ((mallinfo ().fordblks + 1023) >> 10));
-#endif
-  return val;
-}
-
 DEFUN ("memory-use-counts", Fmemory_use_counts, Smemory_use_counts, 0, 0, 0,
        doc: /* Return a list of counters that measure how much consing there has been.
 Each of these counters increments for a certain kind of object.
@@ -6669,18 +6676,15 @@ Frames, windows, buffers, and subprocesses count as vectors
   (but the contents of a buffer's text do not count here).  */)
   (void)
 {
-  Lisp_Object consed[8];
-
-  consed[0] = bounded_number (cons_cells_consed);
-  consed[1] = bounded_number (floats_consed);
-  consed[2] = bounded_number (vector_cells_consed);
-  consed[3] = bounded_number (symbols_consed);
-  consed[4] = bounded_number (string_chars_consed);
-  consed[5] = bounded_number (misc_objects_consed);
-  consed[6] = bounded_number (intervals_consed);
-  consed[7] = bounded_number (strings_consed);
-
-  return Flist (8, consed);
+  return listn (CONSTYPE_HEAP, 8,
+               bounded_number (cons_cells_consed),
+               bounded_number (floats_consed),
+               bounded_number (vector_cells_consed),
+               bounded_number (symbols_consed),
+               bounded_number (string_chars_consed),
+               bounded_number (misc_objects_consed),
+               bounded_number (intervals_consed),
+               bounded_number (strings_consed));
 }
 
 /* Find at most FIND_MAX symbols which have OBJ as their value or
@@ -6774,7 +6778,7 @@ init_alloc_once (void)
 #endif
 
   refill_memory_reserve ();
-  gc_cons_threshold = 100000 * sizeof (Lisp_Object);
+  gc_cons_threshold = GC_DEFAULT_THRESHOLD;
 }
 
 void
@@ -6861,13 +6865,17 @@ do hash-consing of the objects allocated to pure space.  */);
   /* We build this in advance because if we wait until we need it, we might
      not be able to allocate the memory to hold it.  */
   Vmemory_signal_data
-    = pure_cons (Qerror,
-                pure_cons (build_pure_c_string ("Memory exhausted--use M-x save-some-buffers then exit and restart Emacs"), Qnil));
+    = listn (CONSTYPE_PURE, 2, Qerror,
+            build_pure_c_string ("Memory exhausted--use M-x save-some-buffers then exit and restart Emacs"));
 
   DEFVAR_LISP ("memory-full", Vmemory_full,
               doc: /* Non-nil means Emacs cannot get much more Lisp memory.  */);
   Vmemory_full = Qnil;
 
+  DEFSYM (Qstring_bytes, "string-bytes");
+  DEFSYM (Qvector_slots, "vector-slots");
+  DEFSYM (Qheap, "heap");
+
   DEFSYM (Qgc_cons_threshold, "gc-cons-threshold");
   DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots");
 
@@ -6890,10 +6898,48 @@ The time is in seconds as a floating point value.  */);
   defsubr (&Spurecopy);
   defsubr (&Sgarbage_collect);
   defsubr (&Smemory_limit);
-  defsubr (&Smemory_free);
   defsubr (&Smemory_use_counts);
 
 #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
   defsubr (&Sgc_status);
 #endif
 }
+
+/* Make some symbols visible to GDB.  This section is last, so that
+   the #undef lines don't mess up later code.  */
+
+/* When compiled with GCC, GDB might say "No enum type named
+   pvec_type" if we don't have at least one symbol with that type, and
+   then xbacktrace could fail.  Similarly for the other enums and
+   their values.  */
+union
+{
+  enum CHECK_LISP_OBJECT_TYPE CHECK_LISP_OBJECT_TYPE;
+  enum enum_USE_LSB_TAG enum_USE_LSB_TAG;
+  enum Lisp_Bits Lisp_Bits;
+  enum More_Lisp_Bits More_Lisp_Bits;
+  enum pvec_type pvec_type;
+} const EXTERNALLY_VISIBLE gdb_make_enums_visible = {0};
+
+/* These symbols cannot be done as enums, since values might not be
+   in 'int' range.  Each symbol X has a corresponding X_VAL symbol,
+   verified to have the correct value.  */
+
+#define ARRAY_MARK_FLAG_VAL PTRDIFF_MIN
+#define PSEUDOVECTOR_FLAG_VAL (PTRDIFF_MAX - PTRDIFF_MAX / 2)
+#define VALMASK_VAL (USE_LSB_TAG ? -1 << GCTYPEBITS : VAL_MAX)
+
+verify (ARRAY_MARK_FLAG_VAL == ARRAY_MARK_FLAG);
+verify (PSEUDOVECTOR_FLAG_VAL == PSEUDOVECTOR_FLAG);
+verify (VALMASK_VAL == VALMASK);
+
+#undef ARRAY_MARK_FLAG
+#undef PSEUDOVECTOR_FLAG
+#undef VALMASK
+
+ptrdiff_t const EXTERNALLY_VISIBLE
+  ARRAY_MARK_FLAG = ARRAY_MARK_FLAG_VAL,
+  PSEUDOVECTOR_FLAG = PSEUDOVECTOR_FLAG_VAL;
+
+EMACS_INT const EXTERNALLY_VISIBLE
+  VALMASK = VALMASK_VAL;