emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r110830: Shrink struct vectorlike_hea


From: Dmitry Antipov
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r110830: Shrink struct vectorlike_header to the only size field.
Date: Thu, 08 Nov 2012 18:10:28 +0400
User-agent: Bazaar (2.5.0)

------------------------------------------------------------
revno: 110830
committer: Dmitry Antipov <address@hidden>
branch nick: trunk
timestamp: Thu 2012-11-08 18:10:28 +0400
message:
  Shrink struct vectorlike_header to the only size field.
  * lisp.h (enum pvec_type): Avoid explicit enum member values.
  Adjust comment.
  (enum More_Lisp_Bits): Change PSEUDOVECTOR_SIZE_BITS and
  PVEC_TYPE_MASK to arrange new bitfield in the vector header.
  (PSEUDOVECTOR_REST_BITS, PSEUDOVECTOR_REST_MASK): New members.
  (PSEUDOVECTOR_AREA_BITS): New member used to extract subtype
  information from the vector header.  Adjust comment.
  (XSETPVECTYPE, XSETPVECTYPESIZE, XSETTYPED_PSEUDOVECTOR)
  (PSEUDOVECTOR_TYPEP, DEFUN): Adjust to match new vector header
  layout.
  (XSETSUBR, SUBRP): Adjust to match new Lisp_Subr layout.
  (struct vectorlike_header): Remove next member.  Adjust comment.
  (struct Lisp_Subr): Add convenient header.  Adjust comment.
  (allocate_pseudovector): Adjust prototype.
  * alloc.c (mark_glyph_matrix, mark_face_cache, allocate_string)
  (sweep_string, lisp_malloc): Remove useless prototypes.
  (enum mem_type): Adjust comment.
  (NEXT_IN_FREE_LIST): New macro.
  (SETUP_ON_FREE_LIST): Adjust XSETPVECTYPESIZE usage.
  (Fmake_bool_vector): Likewise.
  (struct large_vector): New type to represent allocation unit for
  the vectors with the memory footprint more than VBLOOCK_BYTES_MAX.
  (large_vectors): Change type to struct large_vector.
  (allocate_vector_from_block): Simplify.
  (PSEUDOVECTOR_NBYTES): Replace with...
  (vector_nbytes): ...new function.  Adjust users.
  (sweep_vectors): Adjust processing of large vectors.
  (allocate_vectorlike): Likewise.
  (allocate_pseudovector): Change type of 3rd arg to enum pvec_type.
  Add easserts.  Adjust XSETPVECTYPESIZE usage.
  (allocate_buffer): Use BUFFER_PVEC_INIT.
  (live_vector_p): Adjust to match large vector.
  * buffer.c (init_buffer_once): Use BUFFER_PVEC_INIT.
  * buffer.h (struct buffer): Add next member.
  (BUFFER_LISP_SIZE, BUFFER_REST_SIZE, BUFFER_PVEC_INIT):
  New macros.
  (FOR_EACH_BUFFER): Adjust to match struct buffer change.
  * fns.c (internal_equal): Adjust to match enum pvec_type change.
  (copy_hash_table): Adjust to match vector header change.
  * lread.c (defsubr): Use XSETPVECTYPE.
  * .gdbinit (xpr, xbacktrace): Adjust to match vector header change.
  (xvectype): Likewise.  Print PVEC_NORMAL_VECTOR for regular vectors.
  (xvecsize): New command.
modified:
  src/.gdbinit
  src/ChangeLog
  src/alloc.c
  src/buffer.c
  src/buffer.h
  src/fns.c
  src/lisp.h
  src/lread.c
=== modified file 'src/.gdbinit'
--- a/src/.gdbinit      2012-09-30 20:06:20 +0000
+++ b/src/.gdbinit      2012-11-08 14:10:28 +0000
@@ -654,13 +654,30 @@
   xgetptr $
   set $size = ((struct Lisp_Vector *) $ptr)->header.size
   if ($size & PSEUDOVECTOR_FLAG)
-    output (enum pvec_type) (($size & PVEC_TYPE_MASK) >> 
PSEUDOVECTOR_SIZE_BITS)
+    output (enum pvec_type) (($size & PVEC_TYPE_MASK) >> 
PSEUDOVECTOR_AREA_BITS)
   else
-    output $size & ~ARRAY_MARK_FLAG
+    output PVEC_NORMAL_VECTOR
   end
   echo \n
 end
 document xvectype
+Print the type or vector subtype of $.
+This command assumes that $ is a vector or pseudovector.
+end
+
+define xvecsize
+  xgetptr $
+  set $size = ((struct Lisp_Vector *) $ptr)->header.size
+  if ($size & PSEUDOVECTOR_FLAG)
+    output ($size & PSEUDOVECTOR_SIZE_MASK)
+    echo \n
+    output (($size & PSEUDOVECTOR_REST_MASK) >> PSEUDOVECTOR_SIZE_BITS)
+  else
+    output ($size & ~ARRAY_MARK_FLAG)
+  end
+  echo \n
+end
+document xvecsize
 Print the size or vector subtype of $.
 This command assumes that $ is a vector or pseudovector.
 end
@@ -996,7 +1013,7 @@
   if $type == Lisp_Vectorlike
     set $size = ((struct Lisp_Vector *) $ptr)->header.size
     if ($size & PSEUDOVECTOR_FLAG)
-      set $vec = (enum pvec_type) (($size & PVEC_TYPE_MASK) >> 
PSEUDOVECTOR_SIZE_BITS)
+      set $vec = (enum pvec_type) (($size & PVEC_TYPE_MASK) >> 
PSEUDOVECTOR_AREA_BITS)
       if $vec == PVEC_NORMAL_VECTOR
        xvector
       end
@@ -1132,7 +1149,7 @@
        xgetptr ($bt->function)
         set $size = ((struct Lisp_Vector *) $ptr)->header.size
         if ($size & PSEUDOVECTOR_FLAG)
-         output (enum pvec_type) (($size & PVEC_TYPE_MASK) >> 
PSEUDOVECTOR_SIZE_BITS)
+         output (enum pvec_type) (($size & PVEC_TYPE_MASK) >> 
PSEUDOVECTOR_AREA_BITS)
        else
          output $size & ~ARRAY_MARK_FLAG
        end

=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2012-11-08 09:26:40 +0000
+++ b/src/ChangeLog     2012-11-08 14:10:28 +0000
@@ -1,5 +1,52 @@
 2012-11-08  Dmitry Antipov  <address@hidden>
 
+       Shrink struct vectorlike_header to the only size field.
+       * lisp.h (enum pvec_type): Avoid explicit enum member values.
+       Adjust comment.
+       (enum More_Lisp_Bits): Change PSEUDOVECTOR_SIZE_BITS and
+       PVEC_TYPE_MASK to arrange new bitfield in the vector header.
+       (PSEUDOVECTOR_REST_BITS, PSEUDOVECTOR_REST_MASK): New members.
+       (PSEUDOVECTOR_AREA_BITS): New member used to extract subtype
+       information from the vector header.  Adjust comment.
+       (XSETPVECTYPE, XSETPVECTYPESIZE, XSETTYPED_PSEUDOVECTOR)
+       (PSEUDOVECTOR_TYPEP, DEFUN): Adjust to match new vector header
+       layout.
+       (XSETSUBR, SUBRP): Adjust to match new Lisp_Subr layout.
+       (struct vectorlike_header): Remove next member.  Adjust comment.
+       (struct Lisp_Subr): Add convenient header.  Adjust comment.
+       (allocate_pseudovector): Adjust prototype.
+       * alloc.c (mark_glyph_matrix, mark_face_cache, allocate_string)
+       (sweep_string, lisp_malloc): Remove useless prototypes.
+       (enum mem_type): Adjust comment.
+       (NEXT_IN_FREE_LIST): New macro.
+       (SETUP_ON_FREE_LIST): Adjust XSETPVECTYPESIZE usage.
+       (Fmake_bool_vector): Likewise.
+       (struct large_vector): New type to represent allocation unit for
+       the vectors with the memory footprint more than VBLOOCK_BYTES_MAX.
+       (large_vectors): Change type to struct large_vector.
+       (allocate_vector_from_block): Simplify.
+       (PSEUDOVECTOR_NBYTES): Replace with...
+       (vector_nbytes): ...new function.  Adjust users.
+       (sweep_vectors): Adjust processing of large vectors.
+       (allocate_vectorlike): Likewise.
+       (allocate_pseudovector): Change type of 3rd arg to enum pvec_type.
+       Add easserts.  Adjust XSETPVECTYPESIZE usage.
+       (allocate_buffer): Use BUFFER_PVEC_INIT.
+       (live_vector_p): Adjust to match large vector.
+       * buffer.c (init_buffer_once): Use BUFFER_PVEC_INIT.
+       * buffer.h (struct buffer): Add next member.
+       (BUFFER_LISP_SIZE, BUFFER_REST_SIZE, BUFFER_PVEC_INIT):
+       New macros.
+       (FOR_EACH_BUFFER): Adjust to match struct buffer change.
+       * fns.c (internal_equal): Adjust to match enum pvec_type change.
+       (copy_hash_table): Adjust to match vector header change.
+       * lread.c (defsubr): Use XSETPVECTYPE.
+       * .gdbinit (xpr, xbacktrace): Adjust to match vector header change.
+       (xvectype): Likewise.  Print PVEC_NORMAL_VECTOR for regular vectors.
+       (xvecsize): New command.
+
+2012-11-08  Dmitry Antipov  <address@hidden>
+
        * keyboard.c (event_to_kboard): Do not dereference
        frame_or_window field of SELECTION_REQUEST_EVENT
        and SELECTION_CLEAR_EVENT events (Bug#12814).

=== modified file 'src/alloc.c'
--- a/src/alloc.c       2012-10-19 06:43:12 +0000
+++ b/src/alloc.c       2012-11-08 14:10:28 +0000
@@ -216,23 +216,19 @@
 static void mark_terminals (void);
 static void gc_sweep (void);
 static Lisp_Object make_pure_vector (ptrdiff_t);
-static void mark_glyph_matrix (struct glyph_matrix *);
-static void mark_face_cache (struct face_cache *);
 static void mark_buffer (struct buffer *);
 
 #if !defined REL_ALLOC || defined SYSTEM_MALLOC
 static void refill_memory_reserve (void);
 #endif
-static struct Lisp_String *allocate_string (void);
 static void compact_small_strings (void);
 static void free_large_strings (void);
-static void sweep_strings (void);
 static void free_misc (Lisp_Object);
 extern Lisp_Object which_symbols (Lisp_Object, EMACS_INT) EXTERNALLY_VISIBLE;
 
-/* When scanning the C stack for live Lisp objects, Emacs keeps track
-   of what memory allocated via lisp_malloc is intended for what
-   purpose.  This enumeration specifies the type of memory.  */
+/* When scanning the C stack for live Lisp objects, Emacs keeps track of
+   what memory allocated via lisp_malloc and lisp_align_malloc is intended
+   for what purpose.  This enumeration specifies the type of memory.  */
 
 enum mem_type
 {
@@ -243,10 +239,9 @@
   MEM_TYPE_MISC,
   MEM_TYPE_SYMBOL,
   MEM_TYPE_FLOAT,
-  /* We used to keep separate mem_types for subtypes of vectors such as
-     process, hash_table, frame, terminal, and window, but we never made
-     use of the distinction, so it only caused source-code complexity
-     and runtime slowdown.  Minor but pointless.  */
+  /* Since all non-bool pseudovectors are small enough to be
+     allocated from vector blocks, this memory type denotes
+     large regular vectors and large bool pseudovectors.  */
   MEM_TYPE_VECTORLIKE,
   /* Special type to denote vector blocks.  */
   MEM_TYPE_VECTOR_BLOCK,
@@ -254,9 +249,6 @@
   MEM_TYPE_SPARE
 };
 
-static void *lisp_malloc (size_t, enum mem_type);
-
-
 #if GC_MARK_STACK || defined GC_MALLOC_CHECK
 
 #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
@@ -2040,7 +2032,7 @@
   val = Fmake_vector (make_number (length_in_elts + extra_bool_elts), Qnil);
 
   /* No Lisp_Object to trace in there.  */
-  XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0);
+  XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0);
 
   p = XBOOL_VECTOR (val);
   p->size = XFASTINT (length);
@@ -2619,19 +2611,49 @@
 
 #define VINDEX(nbytes) (((nbytes) - VBLOCK_BYTES_MIN) / roundup_size)
 
+/* When V is on the free list, first word after header is used as a pointer
+   to next vector on the free list.  It might be done in a better way with:
+
+   (*(struct Lisp_Vector **)&(v->contents[0]))
+
+   but this breaks GCC's strict-aliasing rules (which looks more relaxed
+   for char and void pointers).  */
+
+#define NEXT_IN_FREE_LIST(v)                           \
+  (*(struct Lisp_Vector **)((char *) v + header_size))
+
 /* Common shortcut to setup vector on a free list.  */
 
-#define SETUP_ON_FREE_LIST(v, nbytes, index)                   \
-  do {                                                         \
-    XSETPVECTYPESIZE (v, PVEC_FREE, nbytes);                   \
-    eassert ((nbytes) % roundup_size == 0);                    \
-    (index) = VINDEX (nbytes);                                 \
-    eassert ((index) < VECTOR_MAX_FREE_LIST_INDEX);            \
-    (v)->header.next.vector = vector_free_lists[index];                \
-    vector_free_lists[index] = (v);                            \
-    total_free_vector_slots += (nbytes) / word_size;           \
+#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);      \
+    NEXT_IN_FREE_LIST (v) = vector_free_lists[tmp];    \
+    vector_free_lists[tmp] = (v);                      \
+    total_free_vector_slots += (nbytes) / word_size;   \
   } while (0)
 
+/* This internal type is used to maintain the list of large vectors
+   which are allocated at their own, e.g. outside of vector blocks.  */
+
+struct large_vector
+{
+  union {
+    struct large_vector *vector;
+#if USE_LSB_TAG
+    /* We need to maintain ROUNDUP_SIZE alignment for the vector member.  */
+    unsigned char c[vroundup (sizeof (struct large_vector *))];
+#endif
+  } next;
+  struct Lisp_Vector v;
+};
+
+/* This internal type is used to maintain an underlying storage
+   for small vectors.  */
+
 struct vector_block
 {
   char data[VECTOR_BLOCK_BYTES];
@@ -2649,7 +2671,7 @@
 
 /* Singly-linked list of large vectors.  */
 
-static struct Lisp_Vector *large_vectors;
+static struct large_vector *large_vectors;
 
 /* The only vector with 0 slots, allocated from pure space.  */
 
@@ -2693,7 +2715,7 @@
 static struct Lisp_Vector *
 allocate_vector_from_block (size_t nbytes)
 {
-  struct Lisp_Vector *vector, *rest;
+  struct Lisp_Vector *vector;
   struct vector_block *block;
   size_t index, restbytes;
 
@@ -2706,8 +2728,7 @@
   if (vector_free_lists[index])
     {
       vector = vector_free_lists[index];
-      vector_free_lists[index] = vector->header.next.vector;
-      vector->header.next.nbytes = nbytes;
+      vector_free_lists[index] = NEXT_IN_FREE_LIST (vector);
       total_free_vector_slots -= nbytes / word_size;
       return vector;
     }
@@ -2721,16 +2742,14 @@
       {
        /* This vector is larger than requested.  */
        vector = vector_free_lists[index];
-       vector_free_lists[index] = vector->header.next.vector;
-       vector->header.next.nbytes = nbytes;
+       vector_free_lists[index] = NEXT_IN_FREE_LIST (vector);
        total_free_vector_slots -= nbytes / word_size;
 
        /* Excess bytes are used for the smaller vector,
           which should be set on an appropriate free list.  */
        restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes;
        eassert (restbytes % roundup_size == 0);
-       rest = ADVANCE (vector, nbytes);
-       SETUP_ON_FREE_LIST (rest, restbytes, index);
+       SETUP_ON_FREE_LIST (ADVANCE (vector, nbytes), restbytes, index);
        return vector;
       }
 
@@ -2739,7 +2758,6 @@
 
   /* New vector will be at the beginning of this block.  */
   vector = (struct Lisp_Vector *) block->data;
-  vector->header.next.nbytes = nbytes;
 
   /* If the rest of space from this block is large enough
      for one-slot vector at least, set up it on a free list.  */
@@ -2747,11 +2765,10 @@
   if (restbytes >= VBLOCK_BYTES_MIN)
     {
       eassert (restbytes % roundup_size == 0);
-      rest = ADVANCE (vector, nbytes);
-      SETUP_ON_FREE_LIST (rest, restbytes, index);
+      SETUP_ON_FREE_LIST (ADVANCE (vector, nbytes), restbytes, index);
     }
   return vector;
- }
+}
 
 /* Nonzero if VECTOR pointer is valid pointer inside BLOCK.  */
 
@@ -2759,15 +2776,30 @@
   ((char *) (vector) <= (block)->data          \
    + VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN)
 
-/* Number of bytes used by vector-block-allocated object.  This is the only
-   place where we actually use the `nbytes' field of the vector-header.
-   I.e. we could get rid of the `nbytes' field by computing it based on the
-   vector-type.  */
-
-#define PSEUDOVECTOR_NBYTES(vector) \
-  (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE)     \
-   ? vector->header.size & PSEUDOVECTOR_SIZE_MASK      \
-   : vector->header.next.nbytes)
+/* Return the memory footprint of V in bytes.  */
+
+static ptrdiff_t
+vector_nbytes (struct Lisp_Vector *v)
+{
+  ptrdiff_t size = v->header.size & ~ARRAY_MARK_FLAG;
+
+  if (size & PSEUDOVECTOR_FLAG)
+    {
+      if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR))
+       size = (bool_header_size
+               + (((struct Lisp_Bool_Vector *) v)->size
+                  + BOOL_VECTOR_BITS_PER_CHAR - 1)
+               / BOOL_VECTOR_BITS_PER_CHAR);
+      else
+       size = (header_size
+               + ((size & PSEUDOVECTOR_SIZE_MASK)
+                  + ((size & PSEUDOVECTOR_REST_MASK)
+                     >> PSEUDOVECTOR_SIZE_BITS)) * word_size);
+    }
+  else
+    size = header_size + size * word_size;
+  return vroundup (size);
+}
 
 /* Reclaim space used by unmarked vectors.  */
 
@@ -2775,7 +2807,8 @@
 sweep_vectors (void)
 {
   struct vector_block *block = vector_blocks, **bprev = &vector_blocks;
-  struct Lisp_Vector *vector, *next, **vprev = &large_vectors;
+  struct large_vector *lv, **lvprev = &large_vectors;
+  struct Lisp_Vector *vector, *next;
 
   total_vectors = total_vector_slots = total_free_vector_slots = 0;
   memset (vector_free_lists, 0, sizeof (vector_free_lists));
@@ -2785,6 +2818,7 @@
   for (block = vector_blocks; block; block = *bprev)
     {
       bool free_this_block = 0;
+      ptrdiff_t nbytes;
 
       for (vector = (struct Lisp_Vector *) block->data;
           VECTOR_IN_BLOCK (vector, block); vector = next)
@@ -2793,14 +2827,16 @@
            {
              VECTOR_UNMARK (vector);
              total_vectors++;
-             total_vector_slots += vector->header.next.nbytes / word_size;
-             next = ADVANCE (vector, vector->header.next.nbytes);
+             nbytes = vector_nbytes (vector);
+             total_vector_slots += nbytes / word_size;
+             next = ADVANCE (vector, nbytes);
            }
          else
            {
-             ptrdiff_t nbytes = PSEUDOVECTOR_NBYTES (vector);
-             ptrdiff_t total_bytes = nbytes;
+             ptrdiff_t total_bytes;
 
+             nbytes = vector_nbytes (vector);
+             total_bytes = nbytes;
              next = ADVANCE (vector, nbytes);
 
              /* While NEXT is not marked, try to coalesce with VECTOR,
@@ -2810,7 +2846,7 @@
                {
                  if (VECTOR_MARKED_P (next))
                    break;
-                 nbytes = PSEUDOVECTOR_NBYTES (next);
+                 nbytes = vector_nbytes (next);
                  total_bytes += nbytes;
                  next = ADVANCE (next, nbytes);
                }
@@ -2844,8 +2880,9 @@
 
   /* Sweep large vectors.  */
 
-  for (vector = large_vectors; vector; vector = *vprev)
+  for (lv = large_vectors; lv; lv = *lvprev)
     {
+      vector = &lv->v;
       if (VECTOR_MARKED_P (vector))
        {
          VECTOR_UNMARK (vector);
@@ -2867,12 +2904,12 @@
          else
            total_vector_slots
              += header_size / word_size + vector->header.size;
-         vprev = &vector->header.next.vector;
+         lvprev = &lv->next.vector;
        }
       else
        {
-         *vprev = vector->header.next.vector;
-         lisp_free (vector);
+         *lvprev = lv->next.vector;
+         lisp_free (lv);
        }
     }
 }
@@ -2904,9 +2941,12 @@
        p = allocate_vector_from_block (vroundup (nbytes));
       else
        {
-         p = lisp_malloc (nbytes, MEM_TYPE_VECTORLIKE);
-         p->header.next.vector = large_vectors;
-         large_vectors = p;
+         struct large_vector *lv
+           = lisp_malloc (sizeof (*lv) + (len - 1) * word_size,
+                          MEM_TYPE_VECTORLIKE);
+         lv->next.vector = large_vectors;
+         large_vectors = lv;
+         p = &lv->v;
        }
 
 #ifdef DOUG_LEA_MALLOC
@@ -2943,16 +2983,21 @@
 /* Allocate other vector-like structures.  */
 
 struct Lisp_Vector *
-allocate_pseudovector (int memlen, int lisplen, int tag)
+allocate_pseudovector (int memlen, int lisplen, enum pvec_type tag)
 {
   struct Lisp_Vector *v = allocate_vectorlike (memlen);
   int i;
 
+  /* Catch bogus values.  */
+  eassert (tag <= PVEC_FONT);
+  eassert (memlen - lisplen <= (1 << PSEUDOVECTOR_REST_BITS) - 1);
+  eassert (lisplen <= (1 << PSEUDOVECTOR_SIZE_BITS) - 1);
+
   /* Only the first lisplen slots will be traced normally by the GC.  */
   for (i = 0; i < lisplen; ++i)
     v->contents[i] = Qnil;
 
-  XSETPVECTYPESIZE (v, tag, lisplen);
+  XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen);
   return v;
 }
 
@@ -2961,10 +3006,9 @@
 {
   struct buffer *b = lisp_malloc (sizeof *b, MEM_TYPE_BUFFER);
 
-  XSETPVECTYPESIZE (b, PVEC_BUFFER, (offsetof (struct buffer, own_text)
-                                    - header_size) / word_size);
+  BUFFER_PVEC_INIT (b);
   /* Put B on the chain of all buffers including killed ones.  */
-  b->header.next.buffer = all_buffers;
+  b->next = all_buffers;
   all_buffers = b;
   /* Note that the rest fields of B are not initialized.  */
   return b;
@@ -4068,16 +4112,15 @@
       while (VECTOR_IN_BLOCK (vector, block)
             && vector <= (struct Lisp_Vector *) p)
        {
-         if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE))
-           vector = ADVANCE (vector, (vector->header.size
-                                      & PSEUDOVECTOR_SIZE_MASK));
-         else if (vector == p)
+         if (!PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE) && vector == p)
            return 1;
          else
-           vector = ADVANCE (vector, vector->header.next.nbytes);
+           vector = ADVANCE (vector, vector_nbytes (vector));
        }
     }
-  else if (m->type == MEM_TYPE_VECTORLIKE && p == m->start)
+  else if (m->type == MEM_TYPE_VECTORLIKE
+          && (char *) p == ((char *) m->start
+                            + offsetof (struct large_vector, v)))
     /* This memory node corresponds to a large vector.  */
     return 1;
   return 0;
@@ -5687,7 +5730,7 @@
 
        if (ptr->header.size & PSEUDOVECTOR_FLAG)
          pvectype = ((ptr->header.size & PVEC_TYPE_MASK)
-                     >> PSEUDOVECTOR_SIZE_BITS);
+                     >> PSEUDOVECTOR_AREA_BITS);
        else
          pvectype = PVEC_NORMAL_VECTOR;
 
@@ -6317,7 +6360,7 @@
     for (buffer = all_buffers; buffer; buffer = *bprev)
       if (!VECTOR_MARKED_P (buffer))
        {
-         *bprev = buffer->header.next.buffer;
+         *bprev = buffer->next;
          lisp_free (buffer);
        }
       else
@@ -6326,7 +6369,7 @@
          /* Do not use buffer_(set|get)_intervals here.  */
          buffer->text->intervals = balance_intervals (buffer->text->intervals);
          total_buffers++;
-         bprev = &buffer->header.next.buffer;
+         bprev = &buffer->next;
        }
   }
 

=== modified file 'src/buffer.c'
--- a/src/buffer.c      2012-11-06 17:40:07 +0000
+++ b/src/buffer.c      2012-11-08 14:10:28 +0000
@@ -5105,11 +5105,6 @@
 init_buffer_once (void)
 {
   int idx;
-  /* If you add, remove, or reorder Lisp_Objects in a struct buffer, make
-     sure that this is still correct.  Otherwise, mark_vectorlike may not
-     trace all Lisp_Objects in buffer_defaults and buffer_local_symbols.  */
-  const int pvecsize
-    = (offsetof (struct buffer, own_text) - header_size) / word_size;
 
   memset (buffer_permanent_local_flags, 0, sizeof 
buffer_permanent_local_flags);
 
@@ -5132,8 +5127,8 @@
   /* This is not strictly necessary, but let's make them initialized.  */
   bset_name (&buffer_defaults, build_pure_c_string (" *buffer-defaults*"));
   bset_name (&buffer_local_symbols, build_pure_c_string (" 
*buffer-local-symbols*"));
-  XSETPVECTYPESIZE (&buffer_defaults, PVEC_BUFFER, pvecsize);
-  XSETPVECTYPESIZE (&buffer_local_symbols, PVEC_BUFFER, pvecsize);
+  BUFFER_PVEC_INIT (&buffer_defaults);
+  BUFFER_PVEC_INIT (&buffer_local_symbols);
 
   /* Set up the default values of various buffer slots.  */
   /* Must do these before making the first buffer! */

=== modified file 'src/buffer.h'
--- a/src/buffer.h      2012-10-17 04:58:15 +0000
+++ b/src/buffer.h      2012-11-08 14:10:28 +0000
@@ -482,11 +482,6 @@
 
 struct buffer
 {
-  /* HEADER.NEXT is the next buffer, in chain of all buffers, including killed
-     buffers.  This chain, starting from all_buffers, is used only for garbage
-     collection, in order to collect killed buffers properly.  Note that large
-     vectors and large pseudo-vector objects are all on another chain starting
-     from large_vectors.  */
   struct vectorlike_header header;
 
   /* The name of this buffer.  */
@@ -750,6 +745,9 @@
      In an indirect buffer, this is the own_text field of another buffer.  */
   struct buffer_text *text;
 
+  /* Next buffer, in chain of all buffers, including killed ones.  */
+  struct buffer *next;
+
   /* Char position of point in buffer.  */
   ptrdiff_t pt;
 
@@ -959,6 +957,27 @@
   b->INTERNAL_FIELD (width_table) = val;
 }
 
+/* Number of Lisp_Objects at the beginning of struct buffer.
+   If you add, remove, or reorder Lisp_Objects within buffer
+   structure, make sure that this is still correct.  */
+
+#define BUFFER_LISP_SIZE                                               \
+  ((offsetof (struct buffer, own_text) - header_size) / word_size)
+
+/* Size of the struct buffer part beyond leading Lisp_Objects, in word_size
+   units.  Rounding is needed for --with-wide-int configuration.  */
+
+#define BUFFER_REST_SIZE                                               \
+  ((((sizeof (struct buffer) - offsetof (struct buffer, own_text))     \
+     + (word_size - 1)) & ~(word_size - 1)) / word_size)
+
+/* Initialize the pseudovector header of buffer object.  BUFFER_LISP_SIZE
+   is required for GC, but BUFFER_REST_SIZE is set up just to be consistent
+   with other pseudovectors.  */
+
+#define BUFFER_PVEC_INIT(b)                                    \
+  XSETPVECTYPESIZE (b, PVEC_BUFFER, BUFFER_LISP_SIZE, BUFFER_REST_SIZE)
+
 /* Convenient check whether buffer B is live.  */
 
 #define BUFFER_LIVE_P(b) (!NILP (BVAR (b, name)))
@@ -986,7 +1005,7 @@
 /* Used to iterate over the chain above.  */
 
 #define FOR_EACH_BUFFER(b) \
-  for ((b) = all_buffers; (b); (b) = (b)->header.next.buffer)
+  for ((b) = all_buffers; (b); (b) = (b)->next)
 
 /* This points to the current buffer.  */
 

=== modified file 'src/fns.c'
--- a/src/fns.c 2012-10-19 00:54:35 +0000
+++ b/src/fns.c 2012-11-08 14:10:28 +0000
@@ -2076,9 +2076,8 @@
           are sensible to compare, so eliminate the others now.  */
        if (size & PSEUDOVECTOR_FLAG)
          {
-           if (!(size & ((PVEC_COMPILED | PVEC_CHAR_TABLE
-                          | PVEC_SUB_CHAR_TABLE | PVEC_FONT)
-                         << PSEUDOVECTOR_SIZE_BITS)))
+           if (((size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_AREA_BITS)
+               < PVEC_COMPILED)
              return 0;
            size &= PSEUDOVECTOR_SIZE_MASK;
          }
@@ -3661,12 +3660,9 @@
 {
   Lisp_Object table;
   struct Lisp_Hash_Table *h2;
-  struct Lisp_Vector *next;
 
   h2 = allocate_hash_table ();
-  next = h2->header.next.vector;
   *h2 = *h1;
-  h2->header.next.vector = next;
   h2->key_and_value = Fcopy_sequence (h1->key_and_value);
   h2->hash = Fcopy_sequence (h1->hash);
   h2->next = Fcopy_sequence (h1->next);

=== modified file 'src/lisp.h'
--- a/src/lisp.h        2012-11-06 20:48:35 +0000
+++ b/src/lisp.h        2012-11-08 14:10:28 +0000
@@ -408,14 +408,11 @@
   PVEC_WINDOW_CONFIGURATION,
   PVEC_SUBR,
   PVEC_OTHER,
-  /* These last 4 are special because we OR them in fns.c:internal_equal,
-     so they have to use a disjoint bit pattern:
-     if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE
-                   | PVEC_SUB_CHAR_TABLE | PVEC_FONT))) */
-  PVEC_COMPILED                        = 0x10,
-  PVEC_CHAR_TABLE              = 0x20,
-  PVEC_SUB_CHAR_TABLE          = 0x30,
-  PVEC_FONT                    = 0x40
+  /* These should be last, check internal_equal to see why.  */
+  PVEC_COMPILED,
+  PVEC_CHAR_TABLE,
+  PVEC_SUB_CHAR_TABLE,
+  PVEC_FONT /* Should be last because it's used for range checking.  */
 };
 
 /* DATA_SEG_BITS forces extra bits to be or'd in with any pointers
@@ -435,9 +432,18 @@
        only the number of Lisp_Object fields (that need to be traced by GC).
        The distinction is used, e.g., by Lisp_Process, which places extra
        non-Lisp_Object fields at the end of the structure.  */
-    PSEUDOVECTOR_SIZE_BITS = 16,
+    PSEUDOVECTOR_SIZE_BITS = 12,
     PSEUDOVECTOR_SIZE_MASK = (1 << PSEUDOVECTOR_SIZE_BITS) - 1,
-    PVEC_TYPE_MASK = 0x0fff << PSEUDOVECTOR_SIZE_BITS,
+
+    /* To calculate the memory footprint of the pseudovector, it's useful
+       to store the size of non-Lisp area in word_size units here.  */
+    PSEUDOVECTOR_REST_BITS = 12,
+    PSEUDOVECTOR_REST_MASK = (((1 << PSEUDOVECTOR_REST_BITS) - 1) 
+                             << PSEUDOVECTOR_SIZE_BITS),
+
+    /* Used to extract pseudovector subtype information.  */
+    PSEUDOVECTOR_AREA_BITS = PSEUDOVECTOR_SIZE_BITS + PSEUDOVECTOR_REST_BITS,
+    PVEC_TYPE_MASK = 0x3f << PSEUDOVECTOR_AREA_BITS,
 
     /* Number of bits to put in each character in the internal representation
        of bool vectors.  This should not vary across implementations.  */
@@ -608,13 +614,13 @@
 
 /* Pseudovector types.  */
 
-#define XSETPVECTYPE(v, code) XSETTYPED_PVECTYPE (v, header.size, code)
-#define XSETTYPED_PVECTYPE(v, size_member, code) \
-  ((v)->size_member |= PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_SIZE_BITS))
-#define XSETPVECTYPESIZE(v, code, sizeval) \
+#define XSETPVECTYPE(v, code)                                          \
+  ((v)->header.size |= PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_AREA_BITS))
+#define XSETPVECTYPESIZE(v, code, lispsize, restsize)          \
   ((v)->header.size = (PSEUDOVECTOR_FLAG                       \
-                      | ((code) << PSEUDOVECTOR_SIZE_BITS)     \
-                      | (sizeval)))
+                      | ((code) << PSEUDOVECTOR_AREA_BITS)     \
+                      | ((restsize) << PSEUDOVECTOR_SIZE_BITS) \
+                      | (lispsize)))
 
 /* The cast to struct vectorlike_header * avoids aliasing issues.  */
 #define XSETPSEUDOVECTOR(a, b, code) \
@@ -626,16 +632,14 @@
 #define XSETTYPED_PSEUDOVECTOR(a, b, size, code)                       \
   (XSETVECTOR (a, b),                                                  \
    eassert ((size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK))              \
-           == (PSEUDOVECTOR_FLAG | (code << PSEUDOVECTOR_SIZE_BITS))))
+           == (PSEUDOVECTOR_FLAG | (code << PSEUDOVECTOR_AREA_BITS))))
 
 #define XSETWINDOW_CONFIGURATION(a, b) \
   (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW_CONFIGURATION))
 #define XSETPROCESS(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_PROCESS))
 #define XSETWINDOW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW))
 #define XSETTERMINAL(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_TERMINAL))
-/* XSETSUBR is special since Lisp_Subr lacks struct vectorlike_header.  */
-#define XSETSUBR(a, b) \
-  XSETTYPED_PSEUDOVECTOR (a, b, XSUBR (a)->size, PVEC_SUBR)
+#define XSETSUBR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUBR))
 #define XSETCOMPILED(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_COMPILED))
 #define XSETBUFFER(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BUFFER))
 #define XSETCHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE))
@@ -802,7 +806,7 @@
   };
 
 /* Header of vector-like objects.  This documents the layout constraints on
-   vectors and pseudovectors other than struct Lisp_Subr.  It also prevents
+   vectors and pseudovectors (objects of PVEC_xxx subtype).  It also prevents
    compilers from being fooled by Emacs's type punning: the XSETPSEUDOVECTOR
    and PSEUDOVECTORP macros cast their pointers to struct vectorlike_header *,
    because when two such pointers potentially alias, a compiler won't
@@ -810,43 +814,26 @@
    <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8546>.  */
 struct vectorlike_header
   {
-    /* This field contains various pieces of information:
+    /* The only field contains various pieces of information:
        - The MSB (ARRAY_MARK_FLAG) holds the gcmarkbit.
        - The next bit (PSEUDOVECTOR_FLAG) indicates whether this is a plain
          vector (0) or a pseudovector (1).
        - If PSEUDOVECTOR_FLAG is 0, the rest holds the size (number
          of slots) of the vector.
-       - If PSEUDOVECTOR_FLAG is 1, the rest is subdivided into
-         a "pvec type" tag held in PVEC_TYPE_MASK and a size held in the lowest
-         PSEUDOVECTOR_SIZE_BITS.  That size normally indicates the number of
-         Lisp_Object slots at the beginning of the object that need to be
-         traced by the GC, tho some types use it slightly differently.
-       - E.g. if the pvec type is PVEC_FREE it means this is an unallocated
-         vector on a free-list and PSEUDOVECTOR_SIZE_BITS indicates its size
-         in bytes.  */
+       - If PSEUDOVECTOR_FLAG is 1, the rest is subdivided into three fields:
+        - a) pseudovector subtype held in PVEC_TYPE_MASK field;
+        - b) number of Lisp_Objects slots at the beginning of the object
+          held in PSEUDOVECTOR_SIZE_MASK field.  These objects are always
+          traced by the GC;
+        - c) size of the rest fields held in PSEUDOVECTOR_REST_MASK and
+          measured in word_size units.  Rest fields may also include
+          Lisp_Objects, but these objects usually needs some special treatment
+          during GC.
+        There are some exceptions.  For PVEC_FREE, b) is always zero.  For
+        PVEC_BOOL_VECTOR and PVEC_SUBR, both b) and c) are always zero.
+        Current layout limits the pseudovectors to 63 PVEC_xxx subtypes,
+        4095 Lisp_Objects in GC-ed area and 4095 word-sized other slots.  */
     ptrdiff_t size;
-
-    /* When the vector is allocated from a vector block, NBYTES is used
-       if the vector is not on a free list, and VECTOR is used otherwise.
-       For large vector-like objects, BUFFER or VECTOR is used as a pointer
-       to the next vector-like object.  It is generally a buffer or a
-       Lisp_Vector alias, so for convenience it is a union instead of a
-       pointer: this way, one can write P->next.vector instead of ((struct
-       Lisp_Vector *) P->next).  */
-    union {
-      /* This is only needed for small vectors that are not free because the
-        `size' field only gives us the number of Lisp_Object slots, whereas we
-        need to know the total size, including non-Lisp_Object data.
-        FIXME: figure out a way to store this info elsewhere so we can
-        finally get rid of this extra word of overhead.  */
-      ptrdiff_t nbytes;
-      struct buffer *buffer;
-      /* FIXME: This can be removed: For large vectors, this field could be
-        placed *before* the vector itself.  And for small vectors on a free
-        list, this field could be stored in the vector's bytes, since the
-        empty vector is handled specially anyway.  */
-      struct Lisp_Vector *vector;
-    } next;
   };
 
 /* Regular vector is just a header plus array of Lisp_Objects.  */
@@ -1020,15 +1007,11 @@
 
 /* This structure describes a built-in function.
    It is generated by the DEFUN macro only.
-   defsubr makes it into a Lisp object.
-
-   This type is treated in most respects as a pseudovector,
-   but since we never dynamically allocate or free them,
-   we don't need a struct vectorlike_header and its 'next' field.  */
+   defsubr makes it into a Lisp object.  */
 
 struct Lisp_Subr
   {
-    ptrdiff_t size;
+    struct vectorlike_header header;
     union {
       Lisp_Object (*a0) (void);
       Lisp_Object (*a1) (Lisp_Object);
@@ -1709,7 +1692,7 @@
 
 #define PSEUDOVECTOR_TYPEP(v, code)                                    \
   (((v)->size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK))                  \
-   == (PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_SIZE_BITS)))
+   == (PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_AREA_BITS)))
 
 /* True if object X, with internal type struct T *, is a pseudovector whose
    code is CODE.  */
@@ -1722,8 +1705,7 @@
 #define PROCESSP(x) PSEUDOVECTORP (x, PVEC_PROCESS)
 #define WINDOWP(x) PSEUDOVECTORP (x, PVEC_WINDOW)
 #define TERMINALP(x) PSEUDOVECTORP (x, PVEC_TERMINAL)
-/* SUBRP is special since Lisp_Subr lacks struct vectorlike_header.  */
-#define SUBRP(x) TYPED_PSEUDOVECTORP (x, Lisp_Subr, PVEC_SUBR)
+#define SUBRP(x) PSEUDOVECTORP (x, PVEC_SUBR)
 #define COMPILEDP(x) PSEUDOVECTORP (x, PVEC_COMPILED)
 #define BUFFERP(x) PSEUDOVECTORP (x, PVEC_BUFFER)
 #define CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_CHAR_TABLE)
@@ -1898,8 +1880,8 @@
 #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc)    \
    Lisp_Object fnname DEFUN_ARGS_ ## maxargs ;                         \
    static struct Lisp_Subr alignas (GCALIGNMENT) sname =               \
-   { (PVEC_SUBR << PSEUDOVECTOR_SIZE_BITS)                             \
-     | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)),               \
+   { { (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS)                           \
+       | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)) },           \
       { (Lisp_Object (__cdecl *)(void))fnname },                        \
        minargs, maxargs, lname, intspec, 0};                           \
    Lisp_Object fnname
@@ -1907,8 +1889,8 @@
 #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc)    \
    Lisp_Object fnname DEFUN_ARGS_ ## maxargs ;                         \
    static struct Lisp_Subr alignas (GCALIGNMENT) sname =               \
-     { PVEC_SUBR << PSEUDOVECTOR_SIZE_BITS,                            \
-      { .a ## maxargs = fnname },                                      \
+     { { PVEC_SUBR << PSEUDOVECTOR_AREA_BITS },                                
\
+       { .a ## maxargs = fnname },                                     \
        minargs, maxargs, lname, intspec, 0};                           \
    Lisp_Object fnname
 #endif
@@ -2952,7 +2934,7 @@
 extern Lisp_Object Qautomatic_gc;
 extern Lisp_Object Qchar_table_extra_slots;
 extern struct Lisp_Vector *allocate_vector (EMACS_INT);
-extern struct Lisp_Vector *allocate_pseudovector (int memlen, int lisplen, int 
tag);
+extern struct Lisp_Vector *allocate_pseudovector (int, int, enum pvec_type);
 #define ALLOCATE_PSEUDOVECTOR(typ,field,tag)                           \
   ((typ*)                                                              \
    allocate_pseudovector                                               \

=== modified file 'src/lread.c'
--- a/src/lread.c       2012-10-20 12:50:49 +0000
+++ b/src/lread.c       2012-11-08 14:10:28 +0000
@@ -3981,7 +3981,7 @@
 {
   Lisp_Object sym, tem;
   sym = intern_c_string (sname->symbol_name);
-  XSETTYPED_PVECTYPE (sname, size, PVEC_SUBR);
+  XSETPVECTYPE (sname, PVEC_SUBR);
   XSETSUBR (tem, sname);
   set_symbol_function (sym, tem);
 }


reply via email to

[Prev in Thread] Current Thread [Next in Thread]