Author: allison
Date: Sat May 12 12:00:14 2007
New Revision: 18518

Modified:
   trunk/config/gen/makefiles/root.in
   trunk/include/parrot/pobj.h
   trunk/src/gc/dod.c
   trunk/src/gc/res_lea.c
   trunk/src/string.c

Log:
Refactor src/gc/res_lea.c to allow "Configure.pl --gc=libc" to compile.
Patch from Andy Dougherty, resolves RT #42774.


Modified: trunk/config/gen/makefiles/root.in
==============================================================================
--- trunk/config/gen/makefiles/root.in  (original)
+++ trunk/config/gen/makefiles/root.in  Sat May 12 12:00:14 2007
@@ -1014,6 +1014,8 @@
 
 $(SRC_DIR)/gc/resources$(O) : $(GENERAL_H_FILES)
 
+$(SRC_DIR)/gc/res_lea$(O) : $(GENERAL_H_FILES)
+
 $(SRC_DIR)/headers$(O) : $(GENERAL_H_FILES)
 
 $(SRC_DIR)/hll$(O) : $(GENERAL_H_FILES)

Modified: trunk/include/parrot/pobj.h
==============================================================================
--- trunk/include/parrot/pobj.h (original)
+++ trunk/include/parrot/pobj.h Sat May 12 12:00:14 2007
@@ -61,6 +61,54 @@
 #define PMC_num_val(pmc)      (pmc)->obj.u._num_val
 #define PMC_str_val(pmc)      (pmc)->obj.u._string_val
 
+/* See src/gc/resources.c. the basic idea is that buffer memory is
+   set up as follows:
+                    +-----------------+
+                    |  ref_count   |f |    # GC header
+  obj->bufstart  -> +-----------------+
+                    |  data           |
+                    v                 v
+
+The actual set-up is more involved because of padding.  obj->bufstart must
+be suitably aligned for any UnionVal.  (Perhaps it should be a Buffer
+there instead.)  The start of the memory region (as returned by malloc()
+is also suitably aligned for any use.  If, for example, malloc() returns
+objects aligned on 8-byte boundaries, and obj->bufstart is also aligned
+on 8-byte boundaries, then there should be 4 bytes of padding.  It is
+handled differently in the two files resources.c and res_lea.c.  (I have
+not yet figured out how the 'possible padding' is handled in resources.c.
+--A.D.  2007-05-11.)
+
+                     src/gc/resources.c:       src/gc/res_lea.c:
+
+ptr from malloc ->  +------------------+      +------------------+
+                    | possible padding |      | INTVAL ref_count |
+                    | INTVAL ref_count |      | possible padding |
+obj->bufstart   ->  +------------------+      +------------------+
+                    |     data         |      |      data        |
+                    v                  v      v                  v
+
+*/
+typedef struct Buffer_alloc_unit {
+    INTVAL ref_count;
+    UnionVal buffer[1]; /* Guarantee it's suitably aligned */
+} Buffer_alloc_unit;
+
+/* Given a pointer to the buffer, find the ref_count and the actual start of
+   the allocated space. Setting ref_count is clunky because we avoid lvalue
+   casts. */
+#ifdef GC_IS_MALLOC       /* see src/gc/res_lea.c */
+#  define Buffer_alloc_offset    (offsetof(Buffer_alloc_unit, buffer))
+#  define PObj_bufallocstart(b)  ((char *)PObj_bufstart(b) - 
Buffer_alloc_offset)
+#  define PObj_bufrefcount(b)    (((Buffer_alloc_unit 
*)PObj_bufallocstart(b))->ref_count)
+#  define PObj_bufrefcountptr(b) (&PObj_bufrefcount(b))
+#else                     /* see src/gc/resources.c */
+#  define Buffer_alloc_offset sizeof(INTVAL)
+#  define PObj_bufallocstart(b)  ((char *)PObj_bufstart(b) - 
Buffer_alloc_offset)
+#  define PObj_bufrefcount(b)    (*(INTVAL *)PObj_bufallocstart(b))
+#  define PObj_bufrefcountptr(b) ((INTVAL *)PObj_bufallocstart(b))
+#endif
+
 /* BEGIN DEPRECATED BUFFER ACCESSORS */
 /* macros for accessing old buffer members
  * #define bufstart obj.u._b._bufstart

Modified: trunk/src/gc/dod.c
==============================================================================
--- trunk/src/gc/dod.c  (original)
+++ trunk/src/gc/dod.c  Sat May 12 12:00:14 2007
@@ -465,7 +465,7 @@
 
                 if (PObj_COW_TEST(b) && PObj_bufstart(b) &&
                         !PObj_external_TEST(b)) {
-                    INTVAL * const refcount = (INTVAL *) PObj_bufstart(b) - 1;
+                    INTVAL * const refcount = PObj_bufrefcountptr(b);
                     *refcount               = 0;
                 }
             }
@@ -503,7 +503,7 @@
                     PObj_bufstart(b) &&
                    !PObj_external_TEST(b)) {
 
-                INTVAL * const refcount = (INTVAL *) PObj_bufstart(b) - 1;
+                INTVAL * const refcount = PObj_bufrefcountptr(b);
 
                 /* mark users of this bufstart by incrementing refcount */
                 if (PObj_live_TEST(b))

Modified: trunk/src/gc/res_lea.c
==============================================================================
--- trunk/src/gc/res_lea.c      (original)
+++ trunk/src/gc/res_lea.c      Sat May 12 12:00:14 2007
@@ -115,57 +115,70 @@
 =item C<void
 Parrot_reallocate(Interp *interp, Buffer *from, size_t tosize)>
 
-COWable objects (strings or Buffers) use an INTVAL at C<bufstart> for
-refcounting in DOD. C<bufstart> is incremented by that C<INTVAL>.
+COWable objects (strings or Buffers) use an INTVAL before C<bufstart> for
+refcounting in DOD.
 
 =cut
 
 */
 
 void
-Parrot_reallocate(Interp *interp, Buffer *from, size_t tosize)
+Parrot_reallocate(Interp *interp, Buffer *buffer, size_t tosize)
 {
-    Buffer * const buffer = from;
     const size_t oldlen = PObj_buflen(buffer);
-    void *p;
+    Buffer_alloc_unit *p;
 
     if (!PObj_bufstart(buffer)) {
-        p = 1 + (INTVAL *)xcalloc(1, sizeof (INTVAL) + tosize);
+        Parrot_allocate_aligned(interp, buffer, tosize);
+        /* The previous version zeroed the memory here, but I'm not
+           sure why. */
+        memset(PObj_bufstart(buffer), 0, tosize);
     }
     else {
         if (!tosize) {    /* realloc(3) does free, if tosize == 0 here */
             return;    /* do nothing */
         }
-        p = 1 + (INTVAL *)xrealloc((INTVAL *)PObj_bufstart(buffer) - 1,
-                                   sizeof (INTVAL) + tosize);
+        p = (Buffer_alloc_unit *) xrealloc(PObj_bufallocstart(buffer),
+                                           Buffer_alloc_offset + tosize);
         if (tosize > oldlen)
-            memset(p + oldlen, 0, tosize - oldlen);
+            memset((char *)p->buffer + oldlen, 0, tosize - oldlen);
+        PObj_bufstart(buffer) = p->buffer;
+        PObj_buflen(buffer) = tosize;
     }
-    PObj_bufstart(buffer) = p;
-    PObj_buflen(buffer) = tosize;
 }
 
+
 /*
 
 =item C<void
 Parrot_allocate(Interp *interp, Buffer *buffer, size_t size)>
 
-Allocates and returns the required memory. C<size> is the number of
-bytes of memory required.
+Allocate buffer memory for the given Buffer pointer. The C<size>
+has to be a multiple of the word size.
+C<PObj_buflen> will be set to exactly the given C<size>.
+See the comments and diagram in resources.c.
+
+This was never called anyway, so it isn't implemented here.
+
+=item C<void
+Parrot_allocate_aligned(Interp *interp, Buffer *buffer, size_t size)>
+
+Like above, except the address of the buffer is guaranteed to be
+suitably aligned for holding anything contained in UnionVal
+(such as FLOATVAL).
 
 =cut
 
 */
 
 void
-Parrot_allocate(Interp *interp, Buffer *buffer, size_t size)
+Parrot_allocate_aligned(Interp *interp, Buffer *buffer, size_t size)
 {
-    Buffer * const b = buffer;
-    void * const p = xmalloc(sizeof (INTVAL) + size);
-
-    *(INTVAL *)p = 0;
-    PObj_bufstart(b) = 1 + (INTVAL *)p;
-    PObj_buflen(b) = size;
+    Buffer_alloc_unit *p;
+    p = (Buffer_alloc_unit *) xmalloc(Buffer_alloc_offset + size);
+    p->ref_count = 0;
+    PObj_bufstart(buffer) = p->buffer;
+    PObj_buflen(buffer) = size;
 }
 
 /*
@@ -183,16 +196,17 @@
 void
 Parrot_reallocate_string(Interp *interp, STRING *str, size_t tosize)
 {
-    if (!PObj_bufstart(str))
+    const size_t oldlen = PObj_buflen(str);
+    Buffer_alloc_unit *p;
+
+    if (!PObj_bufstart(str)) {
         Parrot_allocate_string(interp, str, tosize);
+    }
     else if (tosize) {
-        const size_t pad = BUFFER_ALIGNMENT - 1;
-        void *p;
-        tosize = ((tosize + pad + sizeof (INTVAL)) & ~pad);
-        p = xrealloc((char *)((INTVAL*)PObj_bufstart(str) - 1), tosize);
-        PObj_bufstart(str) = str->strstart = (char *)p + sizeof (INTVAL);
-        /* usable size at bufstart */
-        PObj_buflen(str) = tosize - sizeof (INTVAL);
+        p = (Buffer_alloc_unit *) xrealloc(PObj_bufallocstart(str),
+                                           Buffer_alloc_offset + tosize);
+        PObj_bufstart(str) = str->strstart = (char *) p->buffer;
+        PObj_buflen(str) = tosize;
     }
 }
 
@@ -211,14 +225,11 @@
 void
 Parrot_allocate_string(Interp *interp, STRING *str, size_t size)
 {
-    void *p;
-    const size_t pad = BUFFER_ALIGNMENT - 1;
-
-    size = ((size + pad + sizeof (INTVAL)) & ~pad);
-    p = xcalloc(1, size);
-    *(INTVAL*)p = 0;
-    PObj_bufstart(str) = str->strstart = (char *)p + sizeof (INTVAL);
-    PObj_buflen(str) = size - sizeof (INTVAL);
+    Buffer_alloc_unit *p;
+    p = (Buffer_alloc_unit *) xcalloc(Buffer_alloc_offset + size, 1);
+    p->ref_count = 0;
+    PObj_bufstart(str) = str->strstart = (char *) p->buffer;
+    PObj_buflen(str) = size;
 }
 
 /*
@@ -240,6 +251,21 @@
 /*
 
 =item C<void
+Parrot_merge_memory_pools(Interp *dest, Interp *source)>
+
+Does nothing.
+
+=cut
+
+*/
+void
+Parrot_merge_memory_pools(Interp *dest, Interp *source)
+{
+}
+
+/*
+
+=item C<void
 Parrot_destroy_memory_pools(Interp *interp)>
 
 Does nothing.

Modified: trunk/src/string.c
==============================================================================
--- trunk/src/string.c  (original)
+++ trunk/src/string.c  Sat May 12 12:00:14 2007
@@ -206,7 +206,7 @@
     /* TODO create string_free API for reusing string headers */
 #ifdef GC_IS_MALLOC
         if (!PObj_is_cowed_TESTALL(dest) && PObj_bufstart(dest)) {
-            mem_sys_free((INTVAL*)PObj_bufstart(dest) - 1);
+            mem_sys_free(PObj_bufallocstart(dest));
         }
 #endif
         dest = Parrot_reuse_COW_reference(interp, src, dest);

Reply via email to