Author: allison
Date: Mon Apr 16 18:42:39 2007
New Revision: 18249
Modified:
trunk/src/pmc/resizablebooleanarray.pmc
trunk/t/pmc/resizablebooleanarray.t
Log:
Fix ResizableBooleanArray's shift and unshift allocation and memory copy, and
make the tests check for the contents of shifted arrays, not just the number of
elements (having the right number of elements, but with the wrong values isn't
good enough).
Modified: trunk/src/pmc/resizablebooleanarray.pmc
==============================================================================
--- trunk/src/pmc/resizablebooleanarray.pmc (original)
+++ trunk/src/pmc/resizablebooleanarray.pmc Mon Apr 16 18:42:39 2007
@@ -58,13 +58,12 @@
"ResizableBooleanArray: index out of bounds!");
}
- /* Adjust key for the current head position */
- key += PMC_int_val2(SELF);
-
- if (key >= PMC_int_val(SELF))
+ /* Check if key is greater than allocated size */
+ INTVAL offsetkey = key + PMC_int_val2(SELF);
+ if (offsetkey >= PMC_int_val(SELF))
DYNSELF.set_integer_native(key+1);
- return SUPER(key);
+ return SUPER(offsetkey);
}
/*
@@ -88,13 +87,12 @@
"ResizableBooleanArray: index out of bounds!");
}
- /* Adjust key for the current head position */
- key += PMC_int_val2(SELF);
-
- if (key >= PMC_int_val(SELF))
+ /* Check if key is greater than allocated size */
+ INTVAL offsetkey = key + PMC_int_val2(SELF);
+ if (offsetkey >= PMC_int_val(SELF))
DYNSELF.set_integer_native(key+1);
- SUPER(key, value);
+ SUPER(offsetkey, value);
}
/*
@@ -108,12 +106,15 @@
*/
void set_integer_native(INTVAL size) {
- INTVAL newallocbits, curallocbits, memsize;
- const INTVAL cursize = PMC_int_val(SELF) - PMC_int_val2(SELF);
+ 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);
/* We are already at the requested size. Yay */
- if (size == cursize)
+ if (newsize == cursize)
return;
@@ -121,7 +122,7 @@
real_exception(interp, NULL, E_IndexError,
"ResizableBooleanArray: Can't resize!");
- newallocbits = (size / MIN_ALLOC + 1) * MIN_ALLOC;
+ newallocbits = (newsize / MIN_ALLOC + 1) * MIN_ALLOC;
curallocbits = (cursize / MIN_ALLOC + 1) * MIN_ALLOC;
memsize = newallocbits / BITS_PER_CHAR;
@@ -129,14 +130,13 @@
if (! PMC_data(SELF)) {
PMC_data(SELF) = mem_sys_allocate_zeroed(memsize);
}
- /* The size is different, but and doesn't fit within the current
allocation */
+ /* 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);
}
- PMC_int_val2(SELF) = 0;
- PMC_int_val(SELF) = size;
+ PMC_int_val(SELF) = newsize;
}
/*
@@ -191,19 +191,31 @@
*/
void unshift_integer(INTVAL value) {
- /* If int_val2 is smaller than 0, size this thing up */
+ /* If the current head position offset is 0, size this thing up by one
+ * allocation unit */
if (PMC_int_val2(SELF) <= 0) {
Parrot_UInt1 * const sdOld = PMC_data(SELF);
- Parrot_UInt1 * const sdNew = mem_sys_allocate_zeroed(
- ((PMC_int_val2(SELF) / MIN_ALLOC) * MIN_ALLOC)
- + PMC_int_val(SELF)
- + ((PMC_int_val(SELF) / MIN_ALLOC + 1) * MIN_ALLOC));
- mem_sys_memmove(sdNew, sdOld + PMC_int_val2(SELF),
- PMC_int_val(SELF));
- mem_sys_free(sdOld);
+
+ /* Allocate an extra allocation unit of space in new array */
+ INTVAL oldbitalloc, oldmemsize, newbitalloc, newmemsize;
+ newbitalloc = ((PMC_int_val(SELF) + MIN_ALLOC) / MIN_ALLOC + 1) *
MIN_ALLOC;
+ newmemsize = newbitalloc / BITS_PER_CHAR;
+ Parrot_UInt1 * const sdNew = mem_sys_allocate_zeroed(newmemsize);
+
+ /* Copy contents of old array to new array, moving the head
+ * position forward by one allocation unit (in bytes). */
+ oldbitalloc = (PMC_int_val(SELF) / MIN_ALLOC + 1) * MIN_ALLOC;
+ oldmemsize = oldbitalloc / BITS_PER_CHAR;
+ mem_sys_memmove(sdNew + (MIN_ALLOC / BITS_PER_CHAR), sdOld,
oldmemsize);
+
+ /* Replace old array with new array, and free old array */
PMC_data(SELF) = sdNew;
+ mem_sys_free(sdOld);
+
+ /* Added one allocation unit to the head position offset */
PMC_int_val2(SELF) += MIN_ALLOC;
- PMC_int_val(SELF) += MIN_ALLOC;
+ PMC_int_val(SELF) += MIN_ALLOC;
+
}
/* Move the head position */
@@ -236,18 +248,28 @@
/* Move the head position */
PMC_int_val2(SELF)++;
- /* If int_val2 is bigger than our allocation unit size, size
- this thing down */
+ /* If the head position offset is greater than our allocation unit
+ * size, size this thing down */
if (PMC_int_val2(SELF) >= MIN_ALLOC) {
+ /* Allocate one allocation unit less of space in new array */
+ INTVAL oldbitalloc, oldmemsize, newbitalloc, newmemsize;
+ newbitalloc = ((PMC_int_val(SELF) - MIN_ALLOC) / MIN_ALLOC + 1) *
MIN_ALLOC;
+ newmemsize = newbitalloc / BITS_PER_CHAR;
+ Parrot_UInt1 * const sdNew = mem_sys_allocate_zeroed(newmemsize);
+
+ /* Copy contents of old array to new array, move the head position
+ * offset back by one allocation unit (in bytes) */
Parrot_UInt1 * const sdOld = PMC_data(SELF);
- Parrot_UInt1 * const sdNew = mem_sys_allocate_zeroed(
- ((PMC_int_val2(SELF) / MIN_ALLOC) * MIN_ALLOC)
- + PMC_int_val(SELF)
- + ((PMC_int_val(SELF) / MIN_ALLOC + 1) * MIN_ALLOC));
- mem_sys_memmove(sdNew, sdOld + PMC_int_val2(SELF),
- PMC_int_val(SELF));
- mem_sys_free(sdOld);
+ mem_sys_memmove(sdNew, sdOld + (MIN_ALLOC / BITS_PER_CHAR),
newmemsize);
+
+ /* Replace old array with new array, and free old array */
PMC_data(SELF) = sdNew;
+ mem_sys_free(sdOld);
+
+ /* Removed one allocation unit from the head position offset */
+ PMC_int_val2(SELF) -= MIN_ALLOC;
+ PMC_int_val(SELF) -= MIN_ALLOC;
+
}
return value;
Modified: trunk/t/pmc/resizablebooleanarray.t
==============================================================================
--- trunk/t/pmc/resizablebooleanarray.t (original)
+++ trunk/t/pmc/resizablebooleanarray.t Mon Apr 16 18:42:39 2007
@@ -420,42 +420,72 @@
.local int elements
i= 1
- pmc_arr= new ResizableBooleanArray
+ pmc_arr = new ResizableBooleanArray
+ # No elements are set
print_num_elements( pmc_arr )
+ # Set two of the first three elements
+ pmc_arr[0] = 1
+ pmc_arr[2] = 1
+ print_num_elements( pmc_arr )
+
+ # Unshift a "1" element on
unshift pmc_arr, i
print i
print_num_elements( pmc_arr )
+ # Unshift a "0" element on
unshift pmc_arr, 0
print 0
print_num_elements( pmc_arr )
- print_num_elements( pmc_arr )
-
+ # Shift an element off
i_elem= shift pmc_arr
print i_elem
print_num_elements( pmc_arr )
+ # Shift an element off
i_elem= shift pmc_arr
print i_elem
print_num_elements( pmc_arr )
- pmc_arr = 62
- unshift pmc_arr, 0
- unshift pmc_arr, 1
- unshift pmc_arr, 0
- unshift pmc_arr, 1
- i_elem = shift pmc_arr
- i_elem = shift pmc_arr
- i_elem = shift pmc_arr
- print i_elem
- print_num_elements(pmc_arr)
-
- # Set same size array is currently
- pmc_arr = 63
- print_num_elements(pmc_arr)
+ # Resize the array
+ pmc_arr = 62
+ print_num_elements(pmc_arr)
+
+ # Unshift 4 elements on
+ unshift pmc_arr, 1
+ unshift pmc_arr, 1
+ unshift pmc_arr, 0
+ unshift pmc_arr, 1
+ print_num_elements(pmc_arr)
+
+ # Shift 3 elements off
+ i_elem = shift pmc_arr
+ i_elem = shift pmc_arr
+ i_elem = shift pmc_arr
+ print i_elem
+ print_num_elements(pmc_arr)
+
+ # Set same size array is currently
+ pmc_arr = 63
+ print_num_elements(pmc_arr)
+
+ # Set 101th element
+ pmc_arr[100] = 1
+ print_num_elements(pmc_arr)
+
+ # Shift off 99 elements
+ .local int counter
+ counter = 98
+shift_loop:
+ i_elem = shift pmc_arr
+ dec counter
+ if counter > 0 goto shift_loop
+
+ print i_elem
+ print_num_elements(pmc_arr)
.end
.sub print_num_elements
@@ -465,18 +495,43 @@
print '['
print elements
print "]\n"
+ $I0 = pmc_arr[0]
+ print $I0
+ print ', '
+ $I0 = pmc_arr[1]
+ print $I0
+ print ', '
+ $I0 = pmc_arr[2]
+ print $I0
+ print "\n"
.return()
.end
CODE
[0]
-1[1]
-0[2]
-[2]
-0[1]
-1[0]
+0, 0, 0
+[3]
+1, 0, 1
+1[4]
+1, 1, 0
+0[5]
+0, 1, 1
+0[4]
+1, 1, 0
+1[3]
+1, 0, 1
+[62]
+1, 0, 1
+[66]
+1, 0, 1
1[63]
+1, 1, 0
[63]
+1, 1, 0
+[101]
+1, 1, 0
+0[3]
+0, 0, 1
OUTPUT
pir_output_like( << 'CODE', << 'OUTPUT', "shift bounds checking" );
@@ -772,11 +827,11 @@
set I10, 100
set I0, 0
# push some values at start
-lp1:
+loop1:
mod I5, I0, 2
push P0, I5
inc I0
- lt I0, I10, lp1
+ lt I0, I10, loop1
# create sparse
set I0, 100000
@@ -785,12 +840,12 @@
#set P0[I0], I1
set P0[I0], I5
inc I1
-lp2:
+loop2:
# push some values after hole
mod I5, I1, 2
push P0, I5
inc I1
- le I1, 1100, lp2
+ le I1, 1100, loop2
dec I1
set I3, P0