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