Index: PLATFORMS
===================================================================
RCS file: /cvs/public/parrot/PLATFORMS,v
retrieving revision 1.18
diff -u -r1.18 PLATFORMS
--- PLATFORMS	3 Mar 2004 08:47:31 -0000	1.18
+++ PLATFORMS	19 Mar 2004 03:09:49 -0000
@@ -12,7 +12,6 @@
 ?-ia64
 irix6.5                                      Y          Y       Y/2
 irix64                   8                              Y       Y/22
-linux-amd64-gcc3.3.3     8        -    -     Y   Y      Y       Y/422
 linux-ppc-gcc2.95.3     B    Y    Y    Y     Y   Y      Y       Y
 linux-ppc-gcc3.2.3      B    Y    Y/9  Y     Y   Y      Y       Y
 linux-sparc-gcc3.3.3    B    Y    -    -     Y   Y      Y       Y
@@ -21,6 +20,7 @@
 linux-x86-gcc3.3.3           Y    Y    Y     Y   Y      Y       Y
 linux-x86-gcc3.3.3 *3        Y    Y    Y     Y   Y      Y       Y*3
 linux-x86-icc8               Y    Y    Y     Y   Y      Y       Y
+linux-x86_64-gcc3.3.3    8   Y    -    -     Y   Y      Y       Y
 netbsd                                 Y                Y       Y*1
 openbsd                      Y    Y/5  Y     Y   -      Y       Y
 os2
Index: config/gen/config_h/feature_h.in
===================================================================
RCS file: /cvs/public/parrot/config/gen/config_h/feature_h.in,v
retrieving revision 1.1
diff -u -r1.1 feature_h.in
--- config/gen/config_h/feature_h.in	10 Mar 2004 02:06:27 -0000	1.1
+++ config/gen/config_h/feature_h.in	19 Mar 2004 03:09:50 -0000
@@ -54,7 +54,7 @@
 
     print OUT <<'END';
 
-#ifdef __powerpc__
+#if defined __powerpc__ || defined __x86_64__
 #  define PARROT_VA_TO_VAPTR(x) (x)
 #else
 #  define PARROT_VA_TO_VAPTR(x) (&(x))
Index: docs/memory_internals.pod
===================================================================
RCS file: /cvs/public/parrot/docs/memory_internals.pod,v
retrieving revision 1.7
diff -u -r1.7 memory_internals.pod
--- docs/memory_internals.pod	28 Feb 2004 00:30:39 -0000	1.7
+++ docs/memory_internals.pod	19 Mar 2004 03:09:50 -0000
@@ -108,15 +108,16 @@
 
 =head2 ARENA_DOD_FLAGS
 
-Only four flags need to be checked during a DOD run: C<PObj_live_FLAG>,
-C<PObj_on_free_list_FLAG>, C<PObj_is_special_PMC_FLAG> and 
-C<PObj_needs_early_DOD_FLAG>. Normally these flags are stored in 
-C<PObj->flags>, meaning that each PMC must be accessed during the DOD run.
+Only three flags need to be checked during a DOD run: C<PObj_live_FLAG>,
+C<PObj_on_free_list_FLAG>, and C<PObj_is_special_PMC_FLAG>.  Normally these
+flags are stored in C<PObj-E<gt>flags>, meaning that each PMC must be accessed
+during the DOD run.
 
 An alternative approach is to store the DOD-Flags in the Arenas as a packed
-array of bits. This approach will be used if the preprocessor variable 
-C<ARENA_DOD_FLAGS> is defined to 1. Here the C<struct Small_Object_Arena> is
-extended with a pointer to the packed bitarray
+array of bits. This approach will be used if the preprocessor variable
+C<ARENA_DOD_FLAGS> is defined to 1, which happens by default if the system
+provides a memory alignment primitive such as C<memalign>. In this case the
+C<struct Small_Object_Arena> is extended with a pointer to the packed bitarray
 
     struct Small_Object_Arena {
         UINTVAL *dod_flags;
@@ -125,26 +126,68 @@
     };
 
 The memory for this Small_Object_Arena is allocated at the beginning of a 
-large aligned block of memory (currently 4MiB) and the objects in this arena 
+large aligned block of memory (currently 4Mib) and the objects in this arena 
 come from this memory block. Therefore the arena of an object can be found by 
 simply masking out the lower bits of the pointer to the object:
 
     arena = object & ARENA_MASK;
 
-The macro C<GET_ARENA> does the exactly this, including the necessary type
-casts to remove warnings. The dod_flags are accessed by getting the element
-number in the arena (this is possible because the C<object_size> is fixed and
-stored in the C<struct Small_Object_Arena>), creating the appropriate
-bitmask by shifting and accessing the right element of C<dod_flags[]>.
+The macro C<GET_ARENA> does exactly this, including the necessary type casts
+to remove warnings. The dod_flags are accessed by getting the element number
+in the arena (this is possible because the C<object_size> is fixed and stored
+in the C<struct Small_Object_Arena>), creating the appropriate bitmask by
+shifting and accessing the right element of C<dod_flags[]>.
 
     n = (object - arena->start_objects) / arena->object_size;
     arena->dod_flags[n >> ARENA_FLAG_SHIFT] 
         & flag << ((n & ARENA_FLAG_MASK) << 2)
 
-To simplify this, the macros C<DOD_flag_SET>, C<DOD_flag_CLEAR> and
-C<DOD_flag_TEST> are introduced. As these macros are also defined in the case
-without ARENA_DOD_FLAGS, these macros are a portable way of manipulating the 
-DOD flags.
+
+F<pobj.h> provides macros to facilitate referencing individual object flags:
+C<DOD_flag_SET>, C<DOD_flag_CLEAR> and C<DOD_flag_TEST>. They are also defined
+in the case without ARENA_DOD_FLAGS, so they make up a portable way of
+manipulating the DOD-relevant object flags.
+
+=head3 Flag packing format
+
+The three object flags consulted during DOD are packed into one 4-bit nibble
+per object (one bit is currently unused).  Since C<arena-E<gt>dod_flags[]> is
+an array of native-sized UINTVALs ("words"), the number of nibbles per array
+entry varies depending on the platform. 
+
+To reference a particular flag in a test, set, or clear operation, we require
+both the word containing the object's flags and a bitmask to isolate the flag.
+
+The flag word for object o is found as follows:
+
+- Get the C<dod_flags[]> array for the object's arena
+    [GET_ARENA(o)->dod_flags]
+
+- Get the index of the object in its arena
+    [n=GET_OBJ_N(arena,o)]
+
+- Determine which word in dod_flags contains the needed flag nibble
+    [(obj index)/(obj flag sets per word) = n>>ARENA_FLAG_SHIFT]
+
+The composite expression to reference the flag word is then
+  GET_ARENA(o)->dod_flags[ GET_OBJ_N(GET_ARENA(o), o) >> ARENA_FLAG_SHIFT ]
+
+The bitmask for the desired flag is constructed as follows:
+
+- Determine the index into the flag word of the object's nibble
+    [(obj index)%(nibbles per word) = n & ARENA_FLAG_MASK]
+
+- Convert nibble index into bit index
+    [(nibble index)*(bits per nibble) = (n & ARENA_FLAG_MASK) << 2]
+
+- Create bitmask for desired flag by shifting base flag by bit index
+    [d_PObj_whatever_FLAG << (nibble index)]
+
+The composite expression to form the bitmask is then
+  (d_PObj_ ## flag ## _FLAG << (( GET_OBJ_N(GET_ARENA(o), o) &
+     ARENA_FLAG_MASK ) << 2))
+
+The DOD_flag_* macros combine these constructions to access the flags.
 
 =head1 Variable sized items
 
@@ -283,4 +326,4 @@
 
 =head1 VERSION
 
-0.0.9 Dec 2002
+0.1.0 Mar 2004
Index: include/parrot/pobj.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/pobj.h,v
retrieving revision 1.37
diff -u -r1.37 pobj.h
--- include/parrot/pobj.h	6 Feb 2004 08:19:04 -0000	1.37
+++ include/parrot/pobj.h	19 Mar 2004 03:09:50 -0000
@@ -7,7 +7,7 @@
  *  Data Structure and Algorithms:
  *  History:
  *  Notes:
- *  References:
+ *  References: memory_internals.pod
  */
 
 #if !defined(PARROT_POBJ_H_GUARD)
@@ -276,11 +276,11 @@
 
 #if ARENA_DOD_FLAGS
 /*
- * these 4 flags are kept in one nibble
+ * these flags are stored in one nibble per object. 0x08 is unused.
  */
-#  define d_PObj_live_FLAG              0x01
-#  define d_PObj_on_free_list_FLAG      0x02
-#  define d_PObj_is_special_PMC_FLAG    0x04
+#  define d_PObj_live_FLAG              ((UINTVAL)0x01)
+#  define d_PObj_on_free_list_FLAG      ((UINTVAL)0x02)
+#  define d_PObj_is_special_PMC_FLAG    ((UINTVAL)0x04)
 
 /*
  * arenas are constant sized ~32 byte object size, ~16K objects
@@ -288,6 +288,16 @@
 # define ARENA_SIZE (32*1024*16)
 # define ARENA_ALIGN ARENA_SIZE
 # define ARENA_MASK (~ (ARENA_SIZE-1) )
+
+/*
+ * ARENA_FLAG_SHIFT is log2 of the number of nibbles per UINTVAL, i.e. how
+ * many object flag sets fit into a frame of arena->dod_flags.
+ * ARENA_FLAG_MASK has its lowest ARENA_FLAG_SHIFT bits set.
+ *
+ * 32-bit systems have 32/4=8=2<<3 nibbles per word
+ * 64-bit systems have 64/4=16=2<<4 nibbles per word
+ */
+
 #if INTVAL_SIZE == 4
 # define ARENA_FLAG_SHIFT 3
 # define ARENA_FLAG_MASK 0x7
@@ -295,7 +305,7 @@
 # define ALL_FREE_MASK 0x22222222
 #elif INTVAL_SIZE == 8
 # define ARENA_FLAG_SHIFT 4
-# define ARENA_FLAG_MASK 0x0f
+# define ARENA_FLAG_MASK 0xf
 # define ALL_LIVE_MASK 0x1111111111111111
 # define ALL_FREE_MASK 0x2222222222222222
 #else
@@ -306,12 +316,24 @@
      (4*sizeof(INTVAL) + sizeof(INTVAL) * \
       ((ARENA_OBJECTS(_pool) >> ARENA_FLAG_SHIFT )) )
 
+/*
+ * since arenas are memaligned, the beginning of one can be found by zeroing
+ * the low bits of any object in it
+ */
 # define GET_ARENA(o) \
      ((struct Small_Object_Arena *) (PTR2UINTVAL(o) & ARENA_MASK))
+
+/*
+ * objects are all same size, so to determine one's index we need only divide
+ * its offset in the arena by that size
+ */
 # define GET_OBJ_N(arena, o) \
      ((PTR2UINTVAL(o) - PTR2UINTVAL((arena)->start_objects)) \
           / (arena)->object_size)
 
+/*
+ * see memory_internals.pod for discussion of flag packing format
+ */
 # define DOD_flag_TEST(flag, o) \
       GET_ARENA(o)->dod_flags[ GET_OBJ_N(GET_ARENA(o), o) >> \
       ARENA_FLAG_SHIFT ] & ((d_PObj_ ## flag ## _FLAG << \
Index: src/dod.c
===================================================================
RCS file: /cvs/public/parrot/src/dod.c,v
retrieving revision 1.97
diff -u -r1.97 dod.c
--- src/dod.c	17 Mar 2004 14:39:20 -0000	1.97
+++ src/dod.c	19 Mar 2004 03:09:51 -0000
@@ -658,11 +658,11 @@
             }
             else
                 nm += 4;
+
             /* If it's not live or on the free list, put it on the free list.
              * Note that it is technically possible to have a Buffer be both
              * on_free_list and live, because of our conservative stack-walk
              * collection. We must be wary of this case. */
-
             if ((*dod_flags & (PObj_on_free_list_FLAG << nm)))
                 ; /* if its on free list, do nothing */
             else if ((*dod_flags & (PObj_live_FLAG << nm)))
@@ -735,7 +735,7 @@
                      * XXX Jarkko did report that on irix pool->mem_pool
                      *     was NULL, which really shouldn't happen
                      */
-		    if (pool->mem_pool) {
+                    if (pool->mem_pool) {
                         if (!PObj_COW_TEST(b)) {
                             ((struct Memory_Pool *)
                              pool->mem_pool)->guaranteed_reclaimable +=
