Author: allison
Date: Mon Apr 16 21:30:02 2007
New Revision: 18252

Modified:
   trunk/src/pmc/resizablebooleanarray.pmc
   trunk/t/pmc/resizablebooleanarray.t

Log:
ResizableBooleanArray: fix reallocation bug in old code revealed by new tests
(only on some platforms). Also fixes two TODO tests. (Pair debugging session
with chromatic.)


Modified: trunk/src/pmc/resizablebooleanarray.pmc
==============================================================================
--- trunk/src/pmc/resizablebooleanarray.pmc     (original)
+++ trunk/src/pmc/resizablebooleanarray.pmc     Mon Apr 16 21:30:02 2007
@@ -108,37 +108,44 @@
 */
 
     void set_integer_native(INTVAL size) {
-        INTVAL newsize, newallocbits, curallocbits, memsize;
-        const INTVAL cursize = PMC_int_val(SELF);
-
         /* Size respects any existing head position offset from unshift */
-        newsize = size + PMC_int_val2(SELF);
+        INTVAL newsize = size + PMC_int_val2(SELF);
+        INTVAL oldsize = PMC_int_val(SELF);
 
+        INTVAL new_bitsize, new_bytesize, old_bitsize, old_bytesize;
 
         /* We are already at the requested size. Yay */
-        if (newsize == cursize)
+        if (newsize == oldsize)
             return;
 
-
         if (size < 0)
             real_exception(interp, NULL, E_IndexError,
                 "ResizableBooleanArray: Can't resize!");
 
-        newallocbits = (newsize / MIN_ALLOC + 1) * MIN_ALLOC;
-        curallocbits = (cursize / MIN_ALLOC + 1) * MIN_ALLOC;
-        memsize = newallocbits / BITS_PER_CHAR;
+        /* now set the new size, in bits */
+        PMC_int_val(SELF) = newsize;
+
+        /* convert sizes to bytes */
+        new_bitsize  = (newsize / MIN_ALLOC + 1) * MIN_ALLOC;
+        old_bitsize  = (oldsize / MIN_ALLOC + 1) * MIN_ALLOC;
+        new_bytesize = new_bitsize / BITS_PER_CHAR;
+        old_bytesize = old_bitsize / BITS_PER_CHAR;
 
         /* Nothing allocated yet */
-        if (! PMC_data(SELF)) {
-            PMC_data(SELF) = mem_sys_allocate_zeroed(memsize);
-        }
-        /* The size is different, and doesn't fit within the current 
allocation */
-        else if (newallocbits != curallocbits) {
-            Parrot_UInt1 * const sd = PMC_data(SELF);
-            PMC_data(SELF) = mem_sys_realloc(sd, memsize);
-        }
+        if (! PMC_data(SELF))
+            PMC_data(SELF) = mem_sys_allocate_zeroed(new_bytesize);
 
-        PMC_int_val(SELF) = newsize;
+        /* The size is different, and doesn't fit within the current
+         * allocation */
+        else if (new_bitsize != old_bitsize) {
+            Parrot_UInt1 * old_store = PMC_data(SELF);
+            Parrot_UInt1 * new_store = mem_sys_allocate_zeroed(newsize);
+            INTVAL         copy_size = new_bytesize < old_bytesize ? 
new_bytesize : old_bytesize;
+
+            /* Replace old array with new array, and free old array */
+            PMC_data(SELF) = mem_sys_memmove(new_store, old_store, copy_size);
+            mem_sys_free(old_store);
+        }
     }
 
 /*

Modified: trunk/t/pmc/resizablebooleanarray.t
==============================================================================
--- trunk/t/pmc/resizablebooleanarray.t (original)
+++ trunk/t/pmc/resizablebooleanarray.t Mon Apr 16 21:30:02 2007
@@ -790,10 +790,8 @@
 ok 2
 OUTPUT
 
-TODO: {
-    local $TODO = "this is broken";
 
-    pasm_output_is( <<'CODE', <<'OUTPUT', "check for zeroedness" );
+pasm_output_is( <<'CODE', <<'OUTPUT', "check for zeroedness" );
     new P0, .ResizableBooleanArray
     set I0, 0
 lp1:
@@ -822,7 +820,7 @@
 ok
 OUTPUT
 
-    pasm_output_is( <<'CODE', <<'OUTPUT', "pop into sparse" );
+pasm_output_is( <<'CODE', <<'OUTPUT', "pop into sparse" );
     new P0, .ResizableBooleanArray
        set I10, 100
        set I0, 0
@@ -894,6 +892,9 @@
 ok
 OUTPUT
 
+TODO: {
+    local $TODO = "this is broken";
+
     pasm_output_is( <<'CODE', <<'OUTPUT', "clone" );
     new P0, .ResizableBooleanArray
        set P0[0], 1

Reply via email to