[svn:parrot] r49069 - in trunk: . config/gen/makefiles src src/gc

bacek at svn.parrot.org bacek at svn.parrot.org
Thu Sep 16 20:47:06 UTC 2010


Author: bacek
Date: Thu Sep 16 20:47:05 2010
New Revision: 49069
URL: https://trac.parrot.org/parrot/changeset/49069

Log:
Merge branch 'string_gc'

Added:
   trunk/src/gc/string_gc.c
      - copied, changed from r49067, trunk/src/gc/alloc_resources.c
Modified:
   trunk/MANIFEST
   trunk/config/gen/makefiles/root.in
   trunk/src/debug.c
   trunk/src/gc/alloc_resources.c
   trunk/src/gc/gc_ms.c
   trunk/src/gc/gc_private.h
   trunk/src/gc/mark_sweep.c

Modified: trunk/MANIFEST
==============================================================================
--- trunk/MANIFEST	Thu Sep 16 20:38:57 2010	(r49068)
+++ trunk/MANIFEST	Thu Sep 16 20:47:05 2010	(r49069)
@@ -1,7 +1,7 @@
 # ex: set ro:
 # $Id$
 #
-# generated by tools/dev/mk_manifest_and_skip.pl Tue Sep 14 05:49:01 2010 UT
+# generated by tools/dev/mk_manifest_and_skip.pl Thu Sep 16 15:48:25 2010 UT
 #
 # See below for documentation on the format of this file.
 #
@@ -1288,6 +1288,7 @@
 src/gc/malloc.c                                             []
 src/gc/malloc_trace.c                                       []
 src/gc/mark_sweep.c                                         []
+src/gc/string_gc.c                                          []
 src/gc/system.c                                             []
 src/global_setup.c                                          []
 src/hash.c                                                  []

Modified: trunk/config/gen/makefiles/root.in
==============================================================================
--- trunk/config/gen/makefiles/root.in	Thu Sep 16 20:38:57 2010	(r49068)
+++ trunk/config/gen/makefiles/root.in	Thu Sep 16 20:47:05 2010	(r49069)
@@ -464,6 +464,7 @@
     src/gc/gc_inf$(O) \
     src/gc/mark_sweep$(O) \
     src/gc/system$(O) \
+    src/gc/string_gc$(O) \
     src/global_setup$(O) \
     src/hash$(O) \
     src/hll$(O) \
@@ -1300,6 +1301,9 @@
 src/gc/alloc_resources$(O) : $(PARROT_H_HEADERS) \
 	src/gc/gc_private.h src/gc/alloc_resources.c
 
+src/gc/string_gc$(O) : $(PARROT_H_HEADERS) \
+	src/gc/gc_private.h src/gc/string_gc.c
+
 src/hll$(O) : $(PARROT_H_HEADERS) src/hll.str $(INC_DIR)/dynext.h src/hll.c
 
 src/platform$(O) : $(PARROT_H_HEADERS) src/platform.c

Modified: trunk/src/debug.c
==============================================================================
--- trunk/src/debug.c	Thu Sep 16 20:38:57 2010	(r49068)
+++ trunk/src/debug.c	Thu Sep 16 20:47:05 2010	(r49069)
@@ -82,7 +82,8 @@
 static void debugger_cmdline(PARROT_INTERP)
         __attribute__nonnull__(1);
 
-static void display_breakpoint(ARGIN(PDB_t *pdb),
+static void display_breakpoint(
+    ARGIN(PDB_t *pdb),
     ARGIN(const PDB_breakpoint_t *breakpoint))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);

Modified: trunk/src/gc/alloc_resources.c
==============================================================================
--- trunk/src/gc/alloc_resources.c	Thu Sep 16 20:38:57 2010	(r49068)
+++ trunk/src/gc/alloc_resources.c	Thu Sep 16 20:47:05 2010	(r49069)
@@ -30,10 +30,6 @@
 #define RESOURCE_DEBUG 0
 #define RESOURCE_DEBUG_SIZE 1000000
 
-#define POOL_SIZE (65536 * 2)
-
-typedef void (*compact_f) (Interp *, Memory_Pools * const, Variable_Size_Pool *);
-
 typedef struct string_callback_data {
     Memory_Block *new_block;     /* A pointer to our working block */
     char         *cur_spot;      /* Where we're currently copying to */
@@ -44,17 +40,6 @@
 /* HEADERIZER BEGIN: static */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 
-static void alloc_new_block(
-     ARGMOD(Memory_Pools *mem_pools),
-    size_t size,
-    ARGMOD(Variable_Size_Pool *pool),
-    ARGIN(const char *why))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(3)
-        __attribute__nonnull__(4)
-        FUNC_MODIFIES(*mem_pools)
-        FUNC_MODIFIES(*pool);
-
 PARROT_CANNOT_RETURN_NULL
 PARROT_WARN_UNUSED_RESULT
 static const char * buffer_location(PARROT_INTERP, ARGIN(const Buffer *b))
@@ -81,54 +66,10 @@
         __attribute__nonnull__(2)
         FUNC_MODIFIES(*dest_interp);
 
-static void free_memory_pool(ARGFREE(Variable_Size_Pool *pool));
-static void free_old_mem_blocks(
-     ARGMOD(Memory_Pools *mem_pools),
-    ARGMOD(Variable_Size_Pool *pool),
-    ARGMOD(Memory_Block *new_block),
-    UINTVAL total_size)
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(3)
-        FUNC_MODIFIES(*mem_pools)
-        FUNC_MODIFIES(*pool)
-        FUNC_MODIFIES(*new_block);
-
 static void free_pool(ARGFREE(Fixed_Size_Pool *pool));
 static int is_block_almost_full(ARGIN(const Memory_Block *block))
         __attribute__nonnull__(1);
 
-static void move_buffer_callback(PARROT_INTERP,
-    ARGIN(Buffer *b),
-    ARGIN(void *data))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(3);
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-static char * move_one_buffer(PARROT_INTERP,
-    ARGIN(Memory_Block *pool),
-    ARGMOD(Buffer *old_buf),
-    ARGMOD(char *new_pool_ptr))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(3)
-        __attribute__nonnull__(4)
-        FUNC_MODIFIES(*old_buf)
-        FUNC_MODIFIES(*new_pool_ptr);
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_MALLOC
-PARROT_CANNOT_RETURN_NULL
-static Variable_Size_Pool * new_memory_pool(
-    size_t min_block,
-    NULLOK(compact_f compact));
-
-PARROT_CANNOT_RETURN_NULL
-static UINTVAL pad_pool_size(ARGIN(const Variable_Size_Pool *pool))
-        __attribute__nonnull__(1);
-
 static void Parrot_gc_merge_buffer_pools(PARROT_INTERP,
     ARGMOD(Memory_Pools *mem_pools),
     ARGMOD(Fixed_Size_Pool *dest),
@@ -160,10 +101,6 @@
         FUNC_MODIFIES(*mem_pools)
         FUNC_MODIFIES(*pool);
 
-#define ASSERT_ARGS_alloc_new_block __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(mem_pools) \
-    , PARROT_ASSERT_ARG(pool) \
-    , PARROT_ASSERT_ARG(why))
 #define ASSERT_ARGS_buffer_location __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(b))
@@ -179,26 +116,9 @@
 #define ASSERT_ARGS_fix_pmc_syncs __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(dest_interp) \
     , PARROT_ASSERT_ARG(pool))
-#define ASSERT_ARGS_free_memory_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
-#define ASSERT_ARGS_free_old_mem_blocks __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(mem_pools) \
-    , PARROT_ASSERT_ARG(pool) \
-    , PARROT_ASSERT_ARG(new_block))
 #define ASSERT_ARGS_free_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
 #define ASSERT_ARGS_is_block_almost_full __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(block))
-#define ASSERT_ARGS_move_buffer_callback __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(b) \
-    , PARROT_ASSERT_ARG(data))
-#define ASSERT_ARGS_move_one_buffer __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(pool) \
-    , PARROT_ASSERT_ARG(old_buf) \
-    , PARROT_ASSERT_ARG(new_pool_ptr))
-#define ASSERT_ARGS_new_memory_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
-#define ASSERT_ARGS_pad_pool_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(pool))
 #define ASSERT_ARGS_Parrot_gc_merge_buffer_pools __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(mem_pools) \
@@ -217,165 +137,6 @@
 
 /*
 
-=item C<static void alloc_new_block( Memory_Pools *mem_pools, size_t size,
-Variable_Size_Pool *pool, const char *why)>
-
-Allocate a new memory block. We allocate either the requested size or the
-default size, whichever is larger. Add the new block to the given memory
-pool. The given C<char *why> text is used for debugging.
-
-=cut
-
-*/
-
-static void
-alloc_new_block(
-        ARGMOD(Memory_Pools *mem_pools),
-        size_t size,
-        ARGMOD(Variable_Size_Pool *pool),
-        ARGIN(const char *why))
-{
-    ASSERT_ARGS(alloc_new_block)
-    Memory_Block *new_block;
-
-    const size_t alloc_size = (size > pool->minimum_block_size)
-            ? size : pool->minimum_block_size;
-
-#if RESOURCE_DEBUG
-    fprintf(stderr, "new_block (%s) size %u -> %u\n",
-        why, size, alloc_size);
-#else
-    UNUSED(why)
-#endif
-
-    /* Allocate a new block. Header info's on the front */
-    new_block = (Memory_Block *)mem_internal_allocate_zeroed(
-        sizeof (Memory_Block) + alloc_size);
-
-    if (!new_block) {
-        fprintf(stderr, "out of mem allocsize = %d\n", (int)alloc_size);
-        exit(EXIT_FAILURE);
-    }
-
-    new_block->free  = alloc_size;
-    new_block->size  = alloc_size;
-
-    new_block->next  = NULL;
-    new_block->start = (char *)new_block + sizeof (Memory_Block);
-    new_block->top   = new_block->start;
-
-    /* Note that we've allocated it */
-    mem_pools->memory_allocated += alloc_size;
-
-    /* If this is for a public pool, add it to the list */
-    new_block->prev = pool->top_block;
-
-    /* If we're not first, then tack us on the list */
-    if (pool->top_block)
-        pool->top_block->next = new_block;
-
-    pool->top_block        = new_block;
-    pool->total_allocated += alloc_size;
-}
-
-/*
-
-=item C<void * mem_allocate(PARROT_INTERP, Memory_Pools *mem_pools, size_t size,
-Variable_Size_Pool *pool)>
-
-Allocates memory for headers.
-
-Alignment problems history:
-
-See L<http://archive.develooper.com/perl6-internals%40perl.org/msg12310.html>
-for details.
-
-- return aligned pointer *if needed*
-- return strings et al at unaligned i.e. void* boundaries
-- remember alignment in a buffer header bit
-  use this in compaction code
-- reduce alignment to a reasonable value i.e. MALLOC_ALIGNMENT
-  aka 2*sizeof (size_t) or just 8 (TODO make a config hint)
-
-See pobj.h for a discussion of the Buffer descriptor and the buffer itself,
-including its header.
-
-=cut
-
-*/
-
-PARROT_MALLOC
-PARROT_CANNOT_RETURN_NULL
-void *
-mem_allocate(PARROT_INTERP,
-        ARGMOD(Memory_Pools *mem_pools),
-        size_t size,
-        ARGMOD(Variable_Size_Pool *pool))
-{
-    ASSERT_ARGS(mem_allocate)
-    void *return_val;
-
-    /* we always should have one block at least */
-    PARROT_ASSERT(pool->top_block);
-
-    /* If not enough room, try to find some */
-    if (pool->top_block->free < size) {
-        /*
-         * force a GC mark run to get live flags set
-         * for incremental M&S collection is run from there
-         * but only if there may be something worth collecting!
-         * TODO pass required allocation size to the GC system,
-         *      so that collection can be skipped if needed
-         */
-        size_t new_mem = mem_pools->memory_used -
-                         mem_pools->mem_used_last_collect;
-        if (!mem_pools->gc_mark_block_level
-            && new_mem > (mem_pools->mem_used_last_collect >> 2)
-            && new_mem > GC_SIZE_THRESHOLD) {
-            Parrot_gc_mark_and_sweep(interp, GC_trace_stack_FLAG);
-
-            if (interp->gc_sys->sys_type != INF) {
-                /* Compact the pool if allowed and worthwhile */
-                if (pool->compact) {
-                    /* don't bother reclaiming if it's only a small amount */
-                    if ((pool->possibly_reclaimable * pool->reclaim_factor +
-                         pool->guaranteed_reclaimable) > size) {
-                        (*pool->compact) (interp, mem_pools, pool);
-                    }
-                }
-            }
-        }
-        if (pool->top_block->free < size) {
-            if (pool->minimum_block_size < 65536 * 16)
-                pool->minimum_block_size *= 2;
-            /*
-             * TODO - Big blocks
-             *
-             * Mark the block as big block (it has just one item)
-             * And don't set big blocks as the top_block.
-             */
-            alloc_new_block(mem_pools, size, pool, "compact failed");
-
-            ++mem_pools->mem_allocs_since_last_collect;
-
-            if (pool->top_block->free < size) {
-                fprintf(stderr, "out of mem\n");
-                exit(EXIT_FAILURE);
-            }
-        }
-    }
-
-    /* TODO inline the fast path */
-    return_val             = pool->top_block->top;
-    pool->top_block->top  += size;
-    pool->top_block->free -= size;
-    mem_pools->memory_used += size;
-
-    return return_val;
-}
-
-/*
-
 =item C<static const char * buffer_location(PARROT_INTERP, const Buffer *b)>
 
 Recturns a constant string representing the location of the given
@@ -432,386 +193,8 @@
 
 =back
 
-=head2 Compaction Code
-
-=over 4
-
-=item C<void compact_pool(PARROT_INTERP, Memory_Pools *mem_pools,
-Variable_Size_Pool *pool)>
-
-Compact the string buffer pool. Does not perform a GC scan, or mark items
-as being alive in any way.
-
-=cut
-
-*/
-
-void
-compact_pool(PARROT_INTERP,
-        ARGMOD(Memory_Pools *mem_pools),
-        ARGMOD(Variable_Size_Pool *pool))
-{
-    ASSERT_ARGS(compact_pool)
-    INTVAL        j;
-    UINTVAL       total_size;
-
-    Fixed_Size_Arena *cur_buffer_arena;
-
-    /* Contains new_block and cur_spot */
-    string_callback_data cb_data;
-
-
-    /* Bail if we're blocked */
-    if (mem_pools->gc_sweep_block_level)
-        return;
-
-    ++mem_pools->gc_sweep_block_level;
-
-    /* We're collecting */
-    mem_pools->mem_allocs_since_last_collect    = 0;
-    mem_pools->header_allocs_since_last_collect = 0;
-    ++mem_pools->gc_collect_runs;
-
-    /* Snag a block big enough for everything */
-    total_size = pad_pool_size(pool);
-
-    if (total_size == 0) {
-        free_old_mem_blocks(mem_pools, pool, pool->top_block, total_size);
-        --mem_pools->gc_sweep_block_level;
-        return;
-    }
-
-    alloc_new_block(mem_pools, total_size, pool, "inside compact");
-
-    cb_data.new_block = pool->top_block;
-
-    /* Start at the beginning */
-    cb_data.cur_spot  = cb_data.new_block->start;
-
-    /* Run through all the Buffer header pools and copy */
-    interp->gc_sys->iterate_live_strings(interp, move_buffer_callback, &cb_data);
-
-    /* Okay, we're done with the copy. Set the bits in the pool struct */
-    /* First, where we allocate next */
-    cb_data.new_block->top = cb_data.cur_spot;
-
-    PARROT_ASSERT(cb_data.new_block->size
-                  >=
-                  (size_t)cb_data.new_block->top - (size_t)cb_data.new_block->start);
-
-    /* How much is free. That's the total size minus the amount we used */
-    cb_data.new_block->free     = cb_data.new_block->size
-                                  - (cb_data.cur_spot - cb_data.new_block->start);
-    mem_pools->memory_collected += (cb_data.cur_spot - cb_data.new_block->start);
-    mem_pools->memory_used      += (cb_data.cur_spot - cb_data.new_block->start);
-
-    free_old_mem_blocks(mem_pools, pool, cb_data.new_block, total_size);
-
-    --mem_pools->gc_sweep_block_level;
-}
-
-/*
-=item C<static void move_buffer_callback(PARROT_INTERP, Buffer *b, void *data)>
-
-Callback for live STRING/Buffer for compating.
-
-=cut
-*/
-static void
-move_buffer_callback(PARROT_INTERP, ARGIN(Buffer *b), ARGIN(void *data))
-{
-    ASSERT_ARGS(move_buffer_callback)
-    string_callback_data *cb = (string_callback_data*)data;
-
-    if (Buffer_buflen(b) && PObj_is_movable_TESTALL(b)) {
-        Memory_Block *old_block = Buffer_pool(b);
-
-        if (!is_block_almost_full(old_block))
-            cb->cur_spot = move_one_buffer(interp, cb->new_block, b, cb->cur_spot);
-    }
-
-}
-
-/*
-
-=item C<static UINTVAL pad_pool_size(const Variable_Size_Pool *pool)>
-
-Calculate the size of the new pool. The currently used size equals the total
-size minus the reclaimable size. Add a minimum block to the current amount, so
-we can avoid having to allocate it in the future.
-
-Returns 0 if all blocks below the top block are almost full. In this case
-compacting is not needed.
-
-TODO - Big blocks
-
-Currently all available blocks are compacted into one new
-block with total_size. This is suboptimal, if the block has
-just one live item from a big allocation.
-
-But currently it's unknown if the buffer memory is alive
-as the live bits are in Buffer headers. We have to run the
-compaction loop to check liveness. OTOH if this compaction
-is running through all the buffer headers, there is no
-relation to the block.
-
-Moving the live bit into the buffer thus also solves this
-problem easily.
-
-=cut
-
-*/
-
-PARROT_CANNOT_RETURN_NULL
-static UINTVAL
-pad_pool_size(ARGIN(const Variable_Size_Pool *pool))
-{
-    ASSERT_ARGS(pad_pool_size)
-    Memory_Block *cur_block = pool->top_block->prev;
-
-    UINTVAL total_size   = 0;
-#if RESOURCE_DEBUG
-    size_t  total_blocks = 1;
-#endif
-
-    while (cur_block) {
-        if (!is_block_almost_full(cur_block))
-            total_size += cur_block->size - cur_block->freed - cur_block->free;
-        cur_block   = cur_block->prev;
-#if RESOURCE_DEBUG
-        ++total_blocks;
-#endif
-    }
-
-    if (total_size == 0)
-        return 0;
-
-    cur_block = pool->top_block;
-    if (!is_block_almost_full(cur_block))
-        total_size += cur_block->size - cur_block->freed - cur_block->free;
-
-    /* this makes for ever increasing allocations but fewer collect runs */
-#if WE_WANT_EVER_GROWING_ALLOCATIONS
-    total_size += pool->minimum_block_size;
-#endif
-
-#if RESOURCE_DEBUG
-    fprintf(stderr, "Total blocks: %d\n", total_blocks);
-#endif
-
-    return total_size;
-}
-
-/*
-
-=item C<static char * move_one_buffer(PARROT_INTERP, Memory_Block *pool, Buffer
-*old_buf, char *new_pool_ptr)>
-
-The compact_pool operation collects disjointed blocks of memory allocated on a
-given pool's free list into one large block of memory. Once the new larger
-memory block has been allocated, this function moves one buffer from the old
-memory block to the new memory block and marks that it has been moved.
-
-=cut
-
 */
 
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-static char *
-move_one_buffer(PARROT_INTERP, ARGIN(Memory_Block *pool),
-        ARGMOD(Buffer *old_buf), ARGMOD(char *new_pool_ptr))
-{
-    ASSERT_ARGS(move_one_buffer)
-
-    INTVAL       *flags     = NULL;
-    ptrdiff_t     offset    = 0;
-    Memory_Block *old_block = NULL;
-#if RESOURCE_DEBUG
-    if (Buffer_buflen(old_buf) >= RESOURCE_DEBUG_SIZE)
-        debug_print_buf(interp, old_buf);
-#else
-    UNUSED(interp);
-#endif
-
-    /* we can't perform the math all the time, because
-        * strstart might be in unallocated memory */
-    if (PObj_is_COWable_TEST(old_buf)) {
-        flags = Buffer_bufflagsptr(old_buf);
-        old_block = Buffer_pool(old_buf);
-
-        if (PObj_is_string_TEST(old_buf)) {
-            offset = (ptrdiff_t)((STRING *)old_buf)->strstart -
-                (ptrdiff_t)Buffer_bufstart(old_buf);
-        }
-    }
-
-    /* buffer has already been moved; just change the header */
-    if (flags && (*flags & Buffer_shared_FLAG)
-              && (*flags & Buffer_moved_FLAG)) {
-        /* Find out who else references our data */
-        Buffer * const hdr = *((Buffer **)Buffer_bufstart(old_buf));
-
-        PARROT_ASSERT(PObj_is_COWable_TEST(old_buf));
-
-        /* Make sure they know that we own it too */
-        /* Set Buffer_shared_FLAG in new buffer */
-        *Buffer_bufflagsptr(hdr) |= Buffer_shared_FLAG;
-
-        /* Now make sure we point to where the other guy does */
-        Buffer_bufstart(old_buf) = Buffer_bufstart(hdr);
-
-        /* And if we're a string, update strstart */
-        /* Somewhat of a hack, but if we get per-pool
-            * collections, it should help ease the pain */
-        if (PObj_is_string_TEST(old_buf))
-            ((STRING *)old_buf)->strstart =
-                (char *)Buffer_bufstart(old_buf) + offset;
-    }
-    else {
-        new_pool_ptr = aligned_mem(old_buf, new_pool_ptr);
-
-        /* Copy our memory to the new pool */
-        memcpy(new_pool_ptr, Buffer_bufstart(old_buf),
-                                Buffer_buflen(old_buf));
-
-        /* If we're shared */
-        if (flags && (*flags & Buffer_shared_FLAG)) {
-            PARROT_ASSERT(PObj_is_COWable_TEST(old_buf));
-
-            /* Let the old buffer know how to find us */
-            *((Buffer **)Buffer_bufstart(old_buf)) = old_buf;
-
-            /* Finally, let the tail know that we've moved, so
-                * that any other references can know to look for
-                * us and not re-copy */
-            *flags |= Buffer_moved_FLAG;
-        }
-
-        Buffer_bufstart(old_buf) = new_pool_ptr;
-
-        /* Remember new pool inside */
-        *Buffer_poolptr(old_buf) = pool;
-
-        if (PObj_is_string_TEST(old_buf))
-            ((STRING *)old_buf)->strstart =
-                    (char *)Buffer_bufstart(old_buf) + offset;
-
-        new_pool_ptr += Buffer_buflen(old_buf);
-    }
-
-    return new_pool_ptr;
-}
-
-/*
-
-=item C<static void free_old_mem_blocks( Memory_Pools *mem_pools,
-Variable_Size_Pool *pool, Memory_Block *new_block, UINTVAL total_size)>
-
-The compact_pool operation collects disjointed blocks of memory allocated on a
-given pool's free list into one large block of memory, setting it as the new
-top block for the pool. Once that is done, and all items have been moved into
-the new block of memory, this function iterates through the old blocks and
-frees each one. It also performs the necessary housekeeping to record the
-freed memory blocks. At the end of this function, the pool will have only one
-block of memory on its free list.
-
-=cut
-
-*/
-
-static void
-free_old_mem_blocks(
-        ARGMOD(Memory_Pools *mem_pools),
-        ARGMOD(Variable_Size_Pool *pool),
-        ARGMOD(Memory_Block *new_block),
-        UINTVAL total_size)
-{
-    ASSERT_ARGS(free_old_mem_blocks)
-    Memory_Block *prev_block = new_block;
-    Memory_Block *cur_block  = new_block->prev;
-
-    PARROT_ASSERT(new_block == pool->top_block);
-
-    while (cur_block) {
-        Memory_Block * const next_block = cur_block->prev;
-
-        if (is_block_almost_full(cur_block)) {
-            /* Skip block */
-            prev_block = cur_block;
-            cur_block  = next_block;
-        }
-        else {
-            /* Note that we don't have it any more */
-            mem_pools->memory_allocated -= cur_block->size;
-            mem_pools->memory_used -= cur_block->size - cur_block->free;
-
-            /* We know the pool body and pool header are a single chunk, so
-             * this is enough to get rid of 'em both */
-            mem_internal_free(cur_block);
-            cur_block        = next_block;
-
-            /* Unlink it from list */
-            prev_block->prev = next_block;
-        }
-    }
-
-    /* Terminate list */
-    prev_block->prev = NULL;
-
-
-    /* ANR: I suspect this should be set to new_block->size, instead of passing
-     * in the raw value of total_size, because alloc_new_block pads the size of
-     * the new block under certain conditions. Leaving it unmodified for now,
-     * so this refactor has no functionality changes, only code cleanups.*/
-    pool->total_allocated        = total_size;
-    pool->guaranteed_reclaimable = 0;
-    pool->possibly_reclaimable   = 0;
-}
-
-/*
-
-=item C<static int is_block_almost_full(const Memory_Block *block)>
-
-Tests if the block is almost full and should be skipped during compacting.
-
-Returns true if less that 20% of block is available
-
-=cut
-
-*/
-
-static int
-is_block_almost_full(ARGIN(const Memory_Block *block))
-{
-    ASSERT_ARGS(is_block_almost_full)
-    return 5 * (block->free + block->freed) < block->size;
-}
-
-/*
-
-=item C<char * aligned_mem(const Buffer *buffer, char *mem)>
-
-Returns a pointer to the aligned allocated storage for Buffer C<buffer>,
-which might not be the same as the pointer to C<buffer> because of
-memory alignment.
-
-=cut
-
-*/
-
-PARROT_CANNOT_RETURN_NULL
-PARROT_WARN_UNUSED_RESULT
-char *
-aligned_mem(SHIM(const Buffer *buffer), ARGIN(char *mem))
-{
-    ASSERT_ARGS(aligned_mem)
-    mem += sizeof (void *);
-    mem  = (char *)(((unsigned long)(mem + WORD_ALIGN_1)) & WORD_ALIGN_MASK);
-
-    return mem;
-}
-
 /*
 
 =back
@@ -820,63 +203,8 @@
 
 =over 4
 
-=item C<static Variable_Size_Pool * new_memory_pool(size_t min_block, compact_f
-compact)>
-
-Allocate a new C<Variable_Size_Pool> structures, and set some initial values.
-return a pointer to the new pool.
-
-=cut
-
-*/
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_MALLOC
-PARROT_CANNOT_RETURN_NULL
-static Variable_Size_Pool *
-new_memory_pool(size_t min_block, NULLOK(compact_f compact))
-{
-    ASSERT_ARGS(new_memory_pool)
-    Variable_Size_Pool * const pool = mem_internal_allocate_typed(Variable_Size_Pool);
-
-    pool->top_block              = NULL;
-    pool->compact                = compact;
-    pool->minimum_block_size     = min_block;
-    pool->total_allocated        = 0;
-    pool->guaranteed_reclaimable = 0;
-    pool->possibly_reclaimable   = 0;
-    pool->reclaim_factor         = RECLAMATION_FACTOR;
-
-    return pool;
-}
-
-/*
-
-=item C<void initialize_var_size_pools(PARROT_INTERP, Memory_Pools *mem_pools)>
-
-Initialize the managed memory pools. Parrot maintains two C<Variable_Size_Pool>
-structures, the general memory pool and the constant string pool. Create
-and initialize both pool structures, and allocate initial blocks of memory
-for both.
-
-=cut
-
 */
 
-void
-initialize_var_size_pools(SHIM_INTERP, ARGMOD(Memory_Pools *mem_pools))
-{
-    ASSERT_ARGS(initialize_var_size_pools)
-
-    mem_pools->memory_pool   = new_memory_pool(POOL_SIZE, &compact_pool);
-    alloc_new_block(mem_pools, POOL_SIZE, mem_pools->memory_pool, "init");
-
-    /* Constant strings - not compacted */
-    mem_pools->constant_string_pool = new_memory_pool(POOL_SIZE, NULL);
-    alloc_new_block(mem_pools, POOL_SIZE, mem_pools->constant_string_pool, "init");
-}
-
-
 /*
 
 =item C<void merge_pools(Variable_Size_Pool *dest, Variable_Size_Pool *source)>
@@ -938,8 +266,9 @@
     ASSERT_ARGS(check_memory_system)
     size_t i;
 
-    check_var_size_obj_pool(mem_pools->memory_pool);
-    check_var_size_obj_pool(mem_pools->constant_string_pool);
+    check_var_size_obj_pool(mem_pools->string_gc.memory_pool);
+    check_var_size_obj_pool(mem_pools->string_gc.constant_string_pool);
+
     check_fixed_size_obj_pool(mem_pools->pmc_pool);
     check_fixed_size_obj_pool(mem_pools->constant_pmc_pool);
     check_fixed_size_obj_pool(mem_pools->string_header_pool);
@@ -1000,10 +329,6 @@
                     PARROT_ASSERT(PObj_on_free_list_TEST((PObj*)pobj_walker));
                 }
             }
-            else if (pool->mem_pool != NULL) {
-                /*then it means we are a buffer*/
-                check_buffer_ptr((Buffer*)object, pool->mem_pool);
-            }
             object = (PObj*)((char *)object + pool->object_size);
             PARROT_ASSERT(--count);
         }
@@ -1262,54 +587,6 @@
 }
 
 
-/*
-
-=item C<static void free_memory_pool(Variable_Size_Pool *pool)>
-
-Frees a memory pool; helper function for C<Parrot_gc_destroy_memory_pools>.
-
-=cut
-
-*/
-
-static void
-free_memory_pool(ARGFREE(Variable_Size_Pool *pool))
-{
-    ASSERT_ARGS(free_memory_pool)
-
-    Memory_Block *cur_block = pool->top_block;
-
-    while (cur_block) {
-        Memory_Block * const next_block = cur_block->prev;
-        mem_internal_free(cur_block);
-        cur_block = next_block;
-    }
-
-    mem_internal_free(pool);
-}
-
-
-/*
-
-=item C<void Parrot_gc_destroy_memory_pools(PARROT_INTERP, Memory_Pools
-*mem_pools)>
-
-Destroys the memory pool and the constant string pool. Loop through both
-pools and destroy all memory blocks contained in them. Once all the
-blocks are freed, free the pools themselves.
-
-=cut
-
-*/
-
-void
-Parrot_gc_destroy_memory_pools(SHIM_INTERP, ARGMOD(Memory_Pools *mem_pools))
-{
-    ASSERT_ARGS(Parrot_gc_destroy_memory_pools)
-
-    free_memory_pool(mem_pools->constant_string_pool);
-    free_memory_pool(mem_pools->memory_pool);
-}
 
 /*
 

Modified: trunk/src/gc/gc_ms.c
==============================================================================
--- trunk/src/gc/gc_ms.c	Thu Sep 16 20:38:57 2010	(r49068)
+++ trunk/src/gc/gc_ms.c	Thu Sep 16 20:47:05 2010	(r49069)
@@ -61,13 +61,6 @@
         __attribute__nonnull__(3)
         FUNC_MODIFIES(*pool);
 
-static void gc_ms_allocate_buffer_storage(PARROT_INTERP,
-    ARGOUT(Buffer *buffer),
-    size_t size)
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*buffer);
-
 PARROT_CANNOT_RETURN_NULL
 PARROT_WARN_UNUSED_RESULT
 static Buffer * gc_ms_allocate_bufferlike_header(PARROT_INTERP, size_t size)
@@ -186,13 +179,6 @@
         __attribute__nonnull__(2)
         FUNC_MODIFIES(*pool);
 
-static void gc_ms_reallocate_buffer_storage(PARROT_INTERP,
-    ARGMOD(Buffer *buffer),
-    size_t newsize)
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*buffer);
-
 PARROT_MALLOC
 PARROT_CANNOT_RETURN_NULL
 static void * gc_ms_reallocate_memory_chunk(SHIM_INTERP,
@@ -206,13 +192,6 @@
     size_t newsize,
     size_t oldsize);
 
-static void gc_ms_reallocate_string_storage(PARROT_INTERP,
-    ARGMOD(STRING *str),
-    size_t newsize)
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*str);
-
 static int gc_ms_sweep_cb(PARROT_INTERP,
     ARGIN(Memory_Pools *mem_pools),
     ARGMOD(Fixed_Size_Pool *pool),
@@ -280,9 +259,6 @@
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(mem_pools) \
     , PARROT_ASSERT_ARG(pool))
-#define ASSERT_ARGS_gc_ms_allocate_buffer_storage __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(buffer))
 #define ASSERT_ARGS_gc_ms_allocate_bufferlike_header \
      __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
@@ -345,17 +321,9 @@
     , PARROT_ASSERT_ARG(pool))
 #define ASSERT_ARGS_gc_ms_pool_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(pool))
-#define ASSERT_ARGS_gc_ms_reallocate_buffer_storage \
-     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(buffer))
 #define ASSERT_ARGS_gc_ms_reallocate_memory_chunk __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
 #define ASSERT_ARGS_gc_ms_reallocate_memory_chunk_zeroed \
      __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
-#define ASSERT_ARGS_gc_ms_reallocate_string_storage \
-     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(str))
 #define ASSERT_ARGS_gc_ms_sweep_cb __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(mem_pools) \
@@ -435,10 +403,10 @@
     interp->gc_sys->allocate_pmc_attributes = gc_ms_allocate_pmc_attributes;
     interp->gc_sys->free_pmc_attributes     = gc_ms_free_pmc_attributes;
 
-    interp->gc_sys->allocate_string_storage = gc_ms_allocate_string_storage;
+    interp->gc_sys->allocate_string_storage   = gc_ms_allocate_string_storage;
     interp->gc_sys->reallocate_string_storage = gc_ms_reallocate_string_storage;
 
-    interp->gc_sys->allocate_buffer_storage = gc_ms_allocate_buffer_storage;
+    interp->gc_sys->allocate_buffer_storage   = gc_ms_allocate_buffer_storage;
     interp->gc_sys->reallocate_buffer_storage = gc_ms_reallocate_buffer_storage;
 
     interp->gc_sys->allocate_fixed_size_storage = gc_ms_allocate_fixed_size_storage;
@@ -465,7 +433,7 @@
 
     interp->gc_sys->iterate_live_strings = gc_ms_iterate_live_strings;
 
-    initialize_var_size_pools(interp, interp->mem_pools);
+    Parrot_gc_str_initialize(interp, &interp->mem_pools->string_gc);
     initialize_fixed_size_pools(interp, interp->mem_pools);
     Parrot_gc_initialize_fixed_size_pools(interp, interp->mem_pools,
                                           GC_NUM_INITIAL_FIXED_SIZE_POOLS);
@@ -489,7 +457,7 @@
     Parrot_gc_destroy_header_pools(interp, interp->mem_pools);
 
     /* memory pools in resources */
-    Parrot_gc_destroy_memory_pools(interp, interp->mem_pools);
+    Parrot_gc_str_finalize(interp, &interp->mem_pools->string_gc);
 
     /* mem subsystem is dead now */
     mem_internal_free(interp->mem_pools);
@@ -606,7 +574,54 @@
 gc_ms_compact_memory_pool(PARROT_INTERP)
 {
     ASSERT_ARGS(gc_ms_compact_memory_pool)
-    compact_pool(interp, interp->mem_pools, interp->mem_pools->memory_pool);
+    Parrot_gc_str_compact_pool(interp, &interp->mem_pools->string_gc);
+}
+
+/*
+
+=item C<void gc_ms_allocate_string_storage(PARROT_INTERP, STRING *str, size_t
+size)>
+
+=item C<void gc_ms_reallocate_string_storage(PARROT_INTERP, STRING *str, size_t
+size)>
+
+=item C<void gc_ms_allocate_buffer_storage(PARROT_INTERP, Buffer *str, size_t
+size)>
+
+=item C<void gc_ms_reallocate_buffer_storage(PARROT_INTERP, Buffer *str, size_t
+size)>
+
+Functions for allocating strings/buffers storage.
+
+=cut
+*/
+
+void
+gc_ms_allocate_string_storage(PARROT_INTERP, ARGIN(STRING *str), size_t size)
+{
+    ASSERT_ARGS(gc_ms_allocate_string_storage)
+    Parrot_gc_str_allocate_string_storage(interp, &interp->mem_pools->string_gc, str, size);
+}
+
+void
+gc_ms_reallocate_string_storage(PARROT_INTERP, ARGIN(STRING *str), size_t size)
+{
+    ASSERT_ARGS(gc_ms_reallocate_string_storage)
+    Parrot_gc_str_reallocate_string_storage(interp, &interp->mem_pools->string_gc, str, size);
+}
+
+void
+gc_ms_allocate_buffer_storage(PARROT_INTERP, ARGIN(Buffer *str), size_t size)
+{
+    ASSERT_ARGS(gc_ms_allocate_buffer_storage)
+    Parrot_gc_str_allocate_buffer_storage(interp, &interp->mem_pools->string_gc, str, size);
+}
+
+void
+gc_ms_reallocate_buffer_storage(PARROT_INTERP, ARGIN(Buffer *str), size_t size)
+{
+    ASSERT_ARGS(gc_ms_reallocate_buffer_storage)
+    Parrot_gc_str_reallocate_buffer_storage(interp, &interp->mem_pools->string_gc, str, size);
 }
 
 /*
@@ -1086,233 +1101,6 @@
 
 /*
 
-=item C<static void gc_ms_allocate_buffer_storage(PARROT_INTERP, Buffer *buffer,
-size_t size)>
-
-Allocates a chunk of memory of at least size C<size> for the given Buffer.
-buffer is guaranteed to be properly aligned for things like C<FLOATVALS>,
-so the size may be rounded up or down to guarantee that this alignment holds.
-
-=cut
-
-*/
-
-static void
-gc_ms_allocate_buffer_storage(PARROT_INTERP,
-    ARGOUT(Buffer *buffer), size_t size)
-{
-    ASSERT_ARGS(gc_ms_allocate_buffer_storage)
-    const size_t new_size   = ALIGNED_STRING_SIZE(size);
-
-    Buffer_bufstart(buffer) = (void *)aligned_mem(buffer,
-        (char *)mem_allocate(interp,
-        interp->mem_pools, new_size, interp->mem_pools->memory_pool));
-
-    /* Save pool used to allocate into buffer header */
-    *Buffer_poolptr(buffer) = interp->mem_pools->memory_pool->top_block;
-
-    Buffer_buflen(buffer)   = new_size - sizeof (void *);
-}
-
-/*
-
-=item C<static void gc_ms_reallocate_buffer_storage(PARROT_INTERP, Buffer
-*buffer, size_t newsize)>
-
-Reallocate the Buffer's buffer memory to the given size. The
-allocated buffer will not shrink. If the buffer was allocated with
-L<Parrot_allocate_aligned> the new buffer will also be aligned. As with
-all reallocation, the new buffer might have moved and the additional
-memory is not cleared.
-
-=cut
-
-*/
-
-static void
-gc_ms_reallocate_buffer_storage(PARROT_INTERP, ARGMOD(Buffer *buffer),
-    size_t newsize)
-{
-    ASSERT_ARGS(gc_ms_reallocate_buffer_storage)
-    size_t copysize;
-    char  *mem;
-    Variable_Size_Pool * const pool = interp->mem_pools->memory_pool;
-    size_t new_size, needed, old_size;
-
-    /* we don't shrink buffers */
-    if (newsize <= Buffer_buflen(buffer))
-        return;
-
-    /*
-     * same as below but barely used and tested - only 3 list related
-     * tests do use true reallocation
-     *
-     * list.c, which does _reallocate, has 2 reallocations
-     * normally, which play ping pong with buffers.
-     * The normal case is therefore always to allocate a new block
-     */
-    new_size = ALIGNED_STRING_SIZE(newsize);
-    old_size = ALIGNED_STRING_SIZE(Buffer_buflen(buffer));
-    needed   = new_size - old_size;
-
-    if ((pool->top_block->free >= needed)
-    &&  (pool->top_block->top  == (char *)Buffer_bufstart(buffer) + old_size)) {
-        pool->top_block->free -= needed;
-        pool->top_block->top  += needed;
-        interp->mem_pools->memory_used += needed;
-        Buffer_buflen(buffer)  = newsize;
-        return;
-    }
-
-    copysize = Buffer_buflen(buffer);
-
-    mem = (char *)mem_allocate(interp, interp->mem_pools, new_size, pool);
-    mem = aligned_mem(buffer, mem);
-
-    /* We shouldn't ever have a 0 from size, but we do. If we can track down
-     * those bugs, this can be removed which would make things cheaper */
-    if (copysize)
-        memcpy(mem, Buffer_bufstart(buffer), copysize);
-
-    Buffer_bufstart(buffer) = mem;
-
-    new_size -= sizeof (void *);
-
-    Buffer_buflen(buffer) = new_size;
-
-    /* Save pool used to allocate into buffer header */
-    *Buffer_poolptr(buffer) = interp->mem_pools->memory_pool->top_block;
-}
-
-/*
-
-=item C<void gc_ms_allocate_string_storage(PARROT_INTERP, STRING *str, size_t
-size)>
-
-Allocate the STRING's buffer memory to the given size. The allocated
-buffer maybe slightly bigger than the given C<size>. This function
-sets also C<< str->strstart >> to the new buffer location, C<< str->bufused >>
-is B<not> changed.
-
-=cut
-
-*/
-
-void
-gc_ms_allocate_string_storage(PARROT_INTERP, ARGOUT(STRING *str),
-    size_t size)
-{
-    ASSERT_ARGS(gc_ms_allocate_string_storage)
-    size_t       new_size;
-    Variable_Size_Pool *pool;
-    char        *mem;
-
-    Buffer_buflen(str)   = 0;
-    Buffer_bufstart(str) = NULL;
-
-    if (size == 0)
-        return;
-
-    pool     = PObj_constant_TEST(str)
-                ? interp->mem_pools->constant_string_pool
-                : interp->mem_pools->memory_pool;
-
-    new_size = ALIGNED_STRING_SIZE(size);
-    mem      = (char *)mem_allocate(interp, interp->mem_pools, new_size, pool);
-    mem     += sizeof (void *);
-
-    Buffer_bufstart(str) = str->strstart = mem;
-    Buffer_buflen(str)   = new_size - sizeof (void *);
-
-    /* Save pool used to allocate into buffer header */
-    *Buffer_poolptr(str) = pool->top_block;
-}
-
-/*
-
-=item C<static void gc_ms_reallocate_string_storage(PARROT_INTERP, STRING *str,
-size_t newsize)>
-
-Reallocate the STRING's buffer memory to the given size. The allocated
-buffer will not shrink. This function sets also C<str-E<gt>strstart> to the
-new buffer location, C<str-E<gt>bufused> is B<not> changed.
-
-=cut
-
-*/
-
-static void
-gc_ms_reallocate_string_storage(PARROT_INTERP, ARGMOD(STRING *str),
-    size_t newsize)
-{
-    ASSERT_ARGS(gc_ms_reallocate_string_storage)
-    size_t copysize;
-    char *mem, *oldmem;
-    size_t new_size, needed, old_size;
-
-    Variable_Size_Pool * const pool =
-        PObj_constant_TEST(str)
-            ? interp->mem_pools->constant_string_pool
-            : interp->mem_pools->memory_pool;
-
-    /* if the requested size is smaller then buflen, we are done */
-    if (newsize <= Buffer_buflen(str))
-        return;
-
-    /*
-     * first check, if we can reallocate:
-     * - if the passed strings buffer is the last string in the pool and
-     * - if there is enough size, we can just move the pool's top pointer
-     */
-    new_size = ALIGNED_STRING_SIZE(newsize);
-    old_size = ALIGNED_STRING_SIZE(Buffer_buflen(str));
-    needed   = new_size - old_size;
-
-    if (pool->top_block->free >= needed
-    &&  pool->top_block->top  == (char *)Buffer_bufstart(str) + old_size) {
-        pool->top_block->free -= needed;
-        pool->top_block->top  += needed;
-        interp->mem_pools->memory_used += needed;
-        Buffer_buflen(str) = new_size - sizeof (void *);
-        return;
-    }
-
-    PARROT_ASSERT(str->bufused <= newsize);
-
-    /* only copy used memory, not total string buffer */
-    copysize = str->bufused;
-
-    mem = (char *)mem_allocate(interp, interp->mem_pools, new_size, pool);
-    mem += sizeof (void *);
-
-    /* Update Memory_Block usage */
-    /* We must not reallocate non-movable buffers! */
-    PARROT_ASSERT(PObj_is_movable_TESTALL(str));
-
-    /* We must not reallocate shared buffers! */
-    PARROT_ASSERT(!(*Buffer_bufflagsptr(str) & Buffer_shared_FLAG));
-
-    /* Decrease usage */
-    PARROT_ASSERT(Buffer_pool(str));
-    Buffer_pool(str)->freed += old_size;
-
-    /* copy mem from strstart, *not* bufstart */
-    oldmem             = str->strstart;
-    Buffer_bufstart(str) = (void *)mem;
-    str->strstart      = mem;
-    Buffer_buflen(str)   = new_size - sizeof (void *);
-
-    /* We shouldn't ever have a 0 from size, but we do. If we can track down
-     * those bugs, this can be removed which would make things cheaper */
-    if (copysize)
-        memcpy(mem, oldmem, copysize);
-
-    /* Save pool used to allocate into buffer header */
-    *Buffer_poolptr(str) = pool->top_block;
-}
-
-/*
-
 =item C<void * gc_ms_allocate_fixed_size_storage(PARROT_INTERP, size_t size)>
 
 Allocates a fixed-size chunk of memory for use. This memory is not manually

Modified: trunk/src/gc/gc_private.h
==============================================================================
--- trunk/src/gc/gc_private.h	Thu Sep 16 20:38:57 2010	(r49068)
+++ trunk/src/gc/gc_private.h	Thu Sep 16 20:47:05 2010	(r49069)
@@ -165,6 +165,8 @@
      */
 } GC_Subsystem;
 
+
+
 /* This header structure describes a block of memory that is part of a
    variable-size pool. The allocatable memory follows the header. */
 
@@ -245,9 +247,6 @@
    hang off the Memory_Pools root structure. */
 
 typedef struct Fixed_Size_Pool {
-
-    struct Variable_Size_Pool *mem_pool; /* Pointer to associated variable-size
-                                            pool, or NULL. */
     size_t object_size;                 /* Size in bytes of an individual pool
                                            object. This size may include
                                            a GC system-specific GC header. */
@@ -290,15 +289,22 @@
 
 } Fixed_Size_Pool;
 
+/* String GC subsystem data */
+typedef struct String_GC {
+    Variable_Size_Pool  *memory_pool;           /* General memory pool. */
+    Variable_Size_Pool  *constant_string_pool;  /* Constant string pool (not
+                                                   compacted */
+} String_GC;
+
 /* This structure acts as the root for all the various memory pools:
    variable-sized, fixed-size, and PMC attributes. It also contains
    various GC-related items. It hangs off the Interp structure. */
 
 typedef struct Memory_Pools {
     /* Pointers to pools */
-    Variable_Size_Pool  *memory_pool;           /* General memory pool. */
-    Variable_Size_Pool  *constant_string_pool;  /* Constant string pool (not
-                                                   compacted). */
+    String_GC            string_gc;             /* TEMPORARY */
+                                                /* String GC susbsytem pointer */
+
     Fixed_Size_Pool     *string_header_pool;    /* String header pool. */
     Fixed_Size_Pool     *pmc_pool;              /* PMC object pool. */
     Fixed_Size_Pool     *constant_pmc_pool;     /* And one for constant PMCs. */
@@ -355,10 +361,9 @@
     UINTVAL gc_sweep_block_level; /* How many outstanding GC block
                                      requests are there? */
 
-    /* private data for the GC subsystem */
-    void *gc_private;             /* GC subsystem data */
 } Memory_Pools;
 
+
 /* HEADERIZER BEGIN: src/gc/system.c */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 
@@ -503,11 +508,6 @@
 /* HEADERIZER BEGIN: src/gc/alloc_resources.c */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 
-PARROT_CANNOT_RETURN_NULL
-PARROT_WARN_UNUSED_RESULT
-char * aligned_mem(SHIM(const Buffer *buffer), ARGIN(char *mem))
-        __attribute__nonnull__(2);
-
 void check_buffer_ptr(
     ARGMOD(Buffer * pobj),
     ARGMOD(Variable_Size_Pool * pool))
@@ -516,31 +516,6 @@
         FUNC_MODIFIES(* pobj)
         FUNC_MODIFIES(* pool);
 
-void compact_pool(PARROT_INTERP,
-    ARGMOD(Memory_Pools *mem_pools),
-    ARGMOD(Variable_Size_Pool *pool))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(3)
-        FUNC_MODIFIES(*mem_pools)
-        FUNC_MODIFIES(*pool);
-
-void initialize_var_size_pools(SHIM_INTERP, ARGMOD(Memory_Pools *mem_pools))
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*mem_pools);
-
-PARROT_MALLOC
-PARROT_CANNOT_RETURN_NULL
-void * mem_allocate(PARROT_INTERP,
-    ARGMOD(Memory_Pools *mem_pools),
-    size_t size,
-    ARGMOD(Variable_Size_Pool *pool))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(4)
-        FUNC_MODIFIES(*mem_pools)
-        FUNC_MODIFIES(*pool);
-
 void merge_pools(
     ARGMOD(Variable_Size_Pool *dest),
     ARGMOD(Variable_Size_Pool *source))
@@ -555,11 +530,6 @@
         __attribute__nonnull__(2)
         FUNC_MODIFIES(*mem_pools);
 
-void Parrot_gc_destroy_memory_pools(SHIM_INTERP,
-    ARGMOD(Memory_Pools *mem_pools))
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*mem_pools);
-
 void Parrot_gc_merge_memory_pools(
     ARGMOD(Interp *dest_interp),
     ARGMOD(Memory_Pools *dest_arena),
@@ -570,21 +540,9 @@
         FUNC_MODIFIES(*dest_interp)
         FUNC_MODIFIES(*dest_arena);
 
-#define ASSERT_ARGS_aligned_mem __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(mem))
 #define ASSERT_ARGS_check_buffer_ptr __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(pobj) \
     , PARROT_ASSERT_ARG(pool))
-#define ASSERT_ARGS_compact_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(mem_pools) \
-    , PARROT_ASSERT_ARG(pool))
-#define ASSERT_ARGS_initialize_var_size_pools __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(mem_pools))
-#define ASSERT_ARGS_mem_allocate __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(mem_pools) \
-    , PARROT_ASSERT_ARG(pool))
 #define ASSERT_ARGS_merge_pools __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(dest) \
     , PARROT_ASSERT_ARG(source))
@@ -592,9 +550,6 @@
      __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(mem_pools))
-#define ASSERT_ARGS_Parrot_gc_destroy_memory_pools \
-     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(mem_pools))
 #define ASSERT_ARGS_Parrot_gc_merge_memory_pools __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(dest_interp) \
     , PARROT_ASSERT_ARG(dest_arena) \
@@ -606,16 +561,21 @@
 /* HEADERIZER BEGIN: src/gc/gc_ms.c */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 
+void gc_ms_allocate_buffer_storage(PARROT_INTERP,
+    ARGIN(Buffer *str),
+    size_t size)
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2);
+
 PARROT_CANNOT_RETURN_NULL
 void * gc_ms_allocate_fixed_size_storage(PARROT_INTERP, size_t size)
         __attribute__nonnull__(1);
 
 void gc_ms_allocate_string_storage(PARROT_INTERP,
-    ARGOUT(STRING *str),
+    ARGIN(STRING *str),
     size_t size)
         __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*str);
+        __attribute__nonnull__(2);
 
 void gc_ms_compact_memory_pool(PARROT_INTERP)
         __attribute__nonnull__(1);
@@ -637,9 +597,24 @@
         __attribute__nonnull__(2)
         FUNC_MODIFIES(*pmc);
 
+void gc_ms_reallocate_buffer_storage(PARROT_INTERP,
+    ARGIN(Buffer *str),
+    size_t size)
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2);
+
+void gc_ms_reallocate_string_storage(PARROT_INTERP,
+    ARGIN(STRING *str),
+    size_t size)
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2);
+
 void Parrot_gc_ms_init(PARROT_INTERP)
         __attribute__nonnull__(1);
 
+#define ASSERT_ARGS_gc_ms_allocate_buffer_storage __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(str))
 #define ASSERT_ARGS_gc_ms_allocate_fixed_size_storage \
      __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
@@ -658,6 +633,14 @@
      __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(pmc))
+#define ASSERT_ARGS_gc_ms_reallocate_buffer_storage \
+     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(str))
+#define ASSERT_ARGS_gc_ms_reallocate_string_storage \
+     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(str))
 #define ASSERT_ARGS_Parrot_gc_ms_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
@@ -674,6 +657,116 @@
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: src/gc/gc_inf.c */
 
+
+/* HEADERIZER BEGIN: src/gc/string_gc.c */
+/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
+
+void Parrot_gc_str_alloc_new_block(
+     ARGMOD(Memory_Pools *mem_pools),
+    size_t size,
+    ARGMOD(Variable_Size_Pool *pool),
+    ARGIN(const char *why))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(3)
+        __attribute__nonnull__(4)
+        FUNC_MODIFIES(*mem_pools)
+        FUNC_MODIFIES(*pool);
+
+void Parrot_gc_str_allocate_buffer_storage(PARROT_INTERP,
+    ARGIN(String_GC *gc),
+    ARGOUT(Buffer *buffer),
+    size_t size)
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3)
+        FUNC_MODIFIES(*buffer);
+
+void Parrot_gc_str_allocate_string_storage(PARROT_INTERP,
+    ARGIN(String_GC *gc),
+    ARGOUT(STRING *str),
+    size_t size)
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3)
+        FUNC_MODIFIES(*str);
+
+void Parrot_gc_str_compact_pool(PARROT_INTERP, ARGIN(String_GC *gc))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2);
+
+void Parrot_gc_str_finalize(SHIM_INTERP, ARGMOD(String_GC *gc))
+        __attribute__nonnull__(2)
+        FUNC_MODIFIES(*gc);
+
+void Parrot_gc_str_free_buffer_storage(SHIM_INTERP,
+    ARGIN(String_GC *gc),
+    ARGMOD(Buffer *b))
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3)
+        FUNC_MODIFIES(*b);
+
+void Parrot_gc_str_initialize(PARROT_INTERP, ARGMOD(String_GC *gc))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        FUNC_MODIFIES(*gc);
+
+void Parrot_gc_str_reallocate_buffer_storage(PARROT_INTERP,
+    ARGIN(String_GC *gc),
+    ARGMOD(Buffer *buffer),
+    size_t newsize)
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3)
+        FUNC_MODIFIES(*buffer);
+
+void Parrot_gc_str_reallocate_string_storage(PARROT_INTERP,
+    ARGIN(String_GC *gc),
+    ARGMOD(STRING *str),
+    size_t newsize)
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3)
+        FUNC_MODIFIES(*str);
+
+#define ASSERT_ARGS_Parrot_gc_str_alloc_new_block __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(mem_pools) \
+    , PARROT_ASSERT_ARG(pool) \
+    , PARROT_ASSERT_ARG(why))
+#define ASSERT_ARGS_Parrot_gc_str_allocate_buffer_storage \
+     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(gc) \
+    , PARROT_ASSERT_ARG(buffer))
+#define ASSERT_ARGS_Parrot_gc_str_allocate_string_storage \
+     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(gc) \
+    , PARROT_ASSERT_ARG(str))
+#define ASSERT_ARGS_Parrot_gc_str_compact_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(gc))
+#define ASSERT_ARGS_Parrot_gc_str_finalize __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(gc))
+#define ASSERT_ARGS_Parrot_gc_str_free_buffer_storage \
+     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(gc) \
+    , PARROT_ASSERT_ARG(b))
+#define ASSERT_ARGS_Parrot_gc_str_initialize __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(gc))
+#define ASSERT_ARGS_Parrot_gc_str_reallocate_buffer_storage \
+     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(gc) \
+    , PARROT_ASSERT_ARG(buffer))
+#define ASSERT_ARGS_Parrot_gc_str_reallocate_string_storage \
+     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(gc) \
+    , PARROT_ASSERT_ARG(str))
+/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
+/* HEADERIZER END: src/gc/string_gc.c */
+
 #endif /* PARROT_GC_PRIVATE_H_GUARD */
 
 /*

Modified: trunk/src/gc/mark_sweep.c
==============================================================================
--- trunk/src/gc/mark_sweep.c	Thu Sep 16 20:38:57 2010	(r49068)
+++ trunk/src/gc/mark_sweep.c	Thu Sep 16 20:47:05 2010	(r49069)
@@ -31,13 +31,13 @@
 /* HEADERIZER BEGIN: static */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 
-static void free_buffer(SHIM_INTERP,
-    SHIM(Memory_Pools *mem_pools),
-    ARGMOD(Fixed_Size_Pool *pool),
+static void free_buffer(PARROT_INTERP,
+    ARGIN(Memory_Pools *mem_pools),
+    SHIM(Fixed_Size_Pool *pool),
     ARGMOD(Buffer *b))
-        __attribute__nonnull__(3)
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
         __attribute__nonnull__(4)
-        FUNC_MODIFIES(*pool)
         FUNC_MODIFIES(*b);
 
 static void free_pmc_in_pool(PARROT_INTERP,
@@ -78,7 +78,8 @@
         FUNC_MODIFIES(*mem_pools);
 
 #define ASSERT_ARGS_free_buffer __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(pool) \
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(mem_pools) \
     , PARROT_ASSERT_ARG(b))
 #define ASSERT_ARGS_free_pmc_in_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
@@ -509,7 +510,6 @@
     Fixed_Size_Pool * const pmc_pool =
         new_fixed_size_obj_pool(sizeof (PMC), num_headers);
 
-    pmc_pool->mem_pool   = NULL;
     pmc_pool->gc_object  = free_pmc_in_pool;
 
     (interp->gc_sys->init_pool)(interp, pmc_pool);
@@ -574,7 +574,6 @@
 
     pool->gc_object = (gc_object_fn_type)free_buffer;
 
-    pool->mem_pool  = mem_pools->memory_pool;
     (interp->gc_sys->init_pool)(interp, pool);
     return pool;
 }
@@ -603,7 +602,6 @@
 
     pool->last_Arena        = NULL;
     pool->free_list         = NULL;
-    pool->mem_pool          = NULL;
     pool->newfree           = NULL;
     pool->newlast           = NULL;
     pool->object_size       = object_size;
@@ -634,7 +632,6 @@
     if (constant) {
         pool           = new_bufferlike_pool(interp, mem_pools, sizeof (STRING));
         pool->gc_object = NULL;
-        pool->mem_pool = mem_pools->constant_string_pool;
     }
     else
         pool = get_bufferlike_pool(interp, mem_pools, sizeof (STRING));
@@ -657,39 +654,18 @@
 */
 
 static void
-free_buffer(SHIM_INTERP,
-        SHIM(Memory_Pools *mem_pools),
-        ARGMOD(Fixed_Size_Pool *pool),
+free_buffer(PARROT_INTERP,
+        ARGIN(Memory_Pools *mem_pools),
+        SHIM(Fixed_Size_Pool *pool),
         ARGMOD(Buffer *b))
 {
     ASSERT_ARGS(free_buffer)
-    Variable_Size_Pool * const mem_pool = (Variable_Size_Pool *)pool->mem_pool;
 
     /* If there is no allocated buffer - bail out */
     if (!Buffer_buflen(b))
         return;
 
-    /* XXX Jarkko reported that on irix pool->mem_pool was NULL, which really
-     * shouldn't happen */
-    if (mem_pool) {
-        /* Update Memory_Block usage */
-        if (PObj_is_movable_TESTALL(b)) {
-            INTVAL *buffer_flags = Buffer_bufflagsptr(b);
-
-            /* Mask low 2 bits used for flags */
-            Memory_Block * block = Buffer_pool(b);
-
-            PARROT_ASSERT(block);
-
-            /* We can have shared buffers. Don't count them (yet) */
-            if (!(*buffer_flags & Buffer_shared_FLAG)) {
-                block->freed  += ALIGNED_STRING_SIZE(Buffer_buflen(b));
-            }
-
-        }
-    }
-
-    Buffer_buflen(b) = 0;
+    Parrot_gc_str_free_buffer_storage(interp, &mem_pools->string_gc, b);
 }
 
 

Copied and modified: trunk/src/gc/string_gc.c (from r49067, trunk/src/gc/alloc_resources.c)
==============================================================================
--- trunk/src/gc/alloc_resources.c	Thu Sep 16 20:35:44 2010	(r49067, copy source)
+++ trunk/src/gc/string_gc.c	Thu Sep 16 20:47:05 2010	(r49069)
@@ -1,15 +1,14 @@
 /*
-Copyright (C) 2001-2010, Parrot Foundation.
+Copyright (C) 2010, Parrot Foundation.
 $Id$
 
 =head1 NAME
 
-src/gc/alloc_resources.c - Allocate and deallocate buffer resources such as
-STRINGS.
+src/gc/string_gc.c - String GC subsystem.
 
 =head1 DESCRIPTION
 
-Functions to manage non-PObj memory, including strings and buffers.
+GC subsystem to manage STRINGs.
 
 =head2 Parrot Memory Management Code
 
@@ -22,17 +21,16 @@
 #include "parrot/parrot.h"
 #include "gc_private.h"
 
+typedef void (*compact_f) (Interp *, Memory_Pools * const, Variable_Size_Pool *);
 
-#define RECLAMATION_FACTOR 0.20
-#define WE_WANT_EVER_GROWING_ALLOCATIONS 0
+#define POOL_SIZE (65536 * 2)
 
 /* show allocated blocks on stderr */
 #define RESOURCE_DEBUG 0
 #define RESOURCE_DEBUG_SIZE 1000000
 
-#define POOL_SIZE (65536 * 2)
-
-typedef void (*compact_f) (Interp *, Memory_Pools * const, Variable_Size_Pool *);
+#define RECLAMATION_FACTOR 0.20
+#define WE_WANT_EVER_GROWING_ALLOCATIONS 0
 
 typedef struct string_callback_data {
     Memory_Block *new_block;     /* A pointer to our working block */
@@ -44,6 +42,11 @@
 /* HEADERIZER BEGIN: static */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 
+PARROT_CANNOT_RETURN_NULL
+PARROT_WARN_UNUSED_RESULT
+static char * aligned_mem(SHIM(const Buffer *buffer), ARGIN(char *mem))
+        __attribute__nonnull__(2);
+
 static void alloc_new_block(
      ARGMOD(Memory_Pools *mem_pools),
     size_t size,
@@ -61,26 +64,19 @@
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
-static void check_fixed_size_obj_pool(ARGIN(const Fixed_Size_Pool *pool))
-        __attribute__nonnull__(1);
-
-static void check_memory_system(ARGIN(const Memory_Pools *mem_pools))
-        __attribute__nonnull__(1);
-
-static void check_var_size_obj_pool(ARGIN(const Variable_Size_Pool *pool))
-        __attribute__nonnull__(1);
+static void compact_pool(PARROT_INTERP,
+    ARGMOD(Memory_Pools *mem_pools),
+    ARGMOD(Variable_Size_Pool *pool))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3)
+        FUNC_MODIFIES(*mem_pools)
+        FUNC_MODIFIES(*pool);
 
 static void debug_print_buf(PARROT_INTERP, ARGIN(const Buffer *b))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
-static void fix_pmc_syncs(
-    ARGMOD(Interp *dest_interp),
-    ARGIN(const Fixed_Size_Pool *pool))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*dest_interp);
-
 static void free_memory_pool(ARGFREE(Variable_Size_Pool *pool));
 static void free_old_mem_blocks(
      ARGMOD(Memory_Pools *mem_pools),
@@ -94,10 +90,21 @@
         FUNC_MODIFIES(*pool)
         FUNC_MODIFIES(*new_block);
 
-static void free_pool(ARGFREE(Fixed_Size_Pool *pool));
 static int is_block_almost_full(ARGIN(const Memory_Block *block))
         __attribute__nonnull__(1);
 
+PARROT_MALLOC
+PARROT_CANNOT_RETURN_NULL
+static void * mem_allocate(PARROT_INTERP,
+    ARGMOD(Memory_Pools *mem_pools),
+    size_t size,
+    ARGMOD(Variable_Size_Pool *pool))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(4)
+        FUNC_MODIFIES(*mem_pools)
+        FUNC_MODIFIES(*pool);
+
 static void move_buffer_callback(PARROT_INTERP,
     ARGIN(Buffer *b),
     ARGIN(void *data))
@@ -129,37 +136,8 @@
 static UINTVAL pad_pool_size(ARGIN(const Variable_Size_Pool *pool))
         __attribute__nonnull__(1);
 
-static void Parrot_gc_merge_buffer_pools(PARROT_INTERP,
-    ARGMOD(Memory_Pools *mem_pools),
-    ARGMOD(Fixed_Size_Pool *dest),
-    ARGMOD(Fixed_Size_Pool *source))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(3)
-        __attribute__nonnull__(4)
-        FUNC_MODIFIES(*mem_pools)
-        FUNC_MODIFIES(*dest)
-        FUNC_MODIFIES(*source);
-
-static int sweep_cb_buf(PARROT_INTERP,
-    ARGIN(Memory_Pools *mem_pools),
-    ARGFREE(Fixed_Size_Pool *pool),
-    SHIM(int flag),
-    SHIM(void *arg))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
-
-static int sweep_cb_pmc(PARROT_INTERP,
-    ARGMOD(Memory_Pools *mem_pools),
-    ARGMOD(Fixed_Size_Pool *pool),
-    SHIM(int flag),
-    SHIM(void *arg))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(3)
-        FUNC_MODIFIES(*mem_pools)
-        FUNC_MODIFIES(*pool);
-
+#define ASSERT_ARGS_aligned_mem __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(mem))
 #define ASSERT_ARGS_alloc_new_block __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(mem_pools) \
     , PARROT_ASSERT_ARG(pool) \
@@ -167,26 +145,24 @@
 #define ASSERT_ARGS_buffer_location __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(b))
-#define ASSERT_ARGS_check_fixed_size_obj_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(pool))
-#define ASSERT_ARGS_check_memory_system __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(mem_pools))
-#define ASSERT_ARGS_check_var_size_obj_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(pool))
+#define ASSERT_ARGS_compact_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(mem_pools) \
+    , PARROT_ASSERT_ARG(pool))
 #define ASSERT_ARGS_debug_print_buf __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(b))
-#define ASSERT_ARGS_fix_pmc_syncs __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(dest_interp) \
-    , PARROT_ASSERT_ARG(pool))
 #define ASSERT_ARGS_free_memory_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
 #define ASSERT_ARGS_free_old_mem_blocks __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(mem_pools) \
     , PARROT_ASSERT_ARG(pool) \
     , PARROT_ASSERT_ARG(new_block))
-#define ASSERT_ARGS_free_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
 #define ASSERT_ARGS_is_block_almost_full __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(block))
+#define ASSERT_ARGS_mem_allocate __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(mem_pools) \
+    , PARROT_ASSERT_ARG(pool))
 #define ASSERT_ARGS_move_buffer_callback __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(b) \
@@ -199,1272 +175,1026 @@
 #define ASSERT_ARGS_new_memory_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
 #define ASSERT_ARGS_pad_pool_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(pool))
-#define ASSERT_ARGS_Parrot_gc_merge_buffer_pools __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(mem_pools) \
-    , PARROT_ASSERT_ARG(dest) \
-    , PARROT_ASSERT_ARG(source))
-#define ASSERT_ARGS_sweep_cb_buf __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(mem_pools))
-#define ASSERT_ARGS_sweep_cb_pmc __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(mem_pools) \
-    , PARROT_ASSERT_ARG(pool))
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: static */
 
-
 /*
 
-=item C<static void alloc_new_block( Memory_Pools *mem_pools, size_t size,
-Variable_Size_Pool *pool, const char *why)>
+=item C<void Parrot_gc_str_initialize(PARROT_INTERP, String_GC *gc)>
 
-Allocate a new memory block. We allocate either the requested size or the
-default size, whichever is larger. Add the new block to the given memory
-pool. The given C<char *why> text is used for debugging.
+Initialize the managed memory pools. Parrot maintains two C<Variable_Size_Pool>
+structures, the general memory pool and the constant string pool. Create
+and initialize both pool structures, and allocate initial blocks of memory
+for both.
 
 =cut
 
 */
 
-static void
-alloc_new_block(
-        ARGMOD(Memory_Pools *mem_pools),
-        size_t size,
-        ARGMOD(Variable_Size_Pool *pool),
-        ARGIN(const char *why))
+void
+Parrot_gc_str_initialize(PARROT_INTERP, ARGMOD(String_GC *gc))
 {
-    ASSERT_ARGS(alloc_new_block)
-    Memory_Block *new_block;
+    ASSERT_ARGS(Parrot_gc_str_initialize)
 
-    const size_t alloc_size = (size > pool->minimum_block_size)
-            ? size : pool->minimum_block_size;
-
-#if RESOURCE_DEBUG
-    fprintf(stderr, "new_block (%s) size %u -> %u\n",
-        why, size, alloc_size);
-#else
-    UNUSED(why)
-#endif
+    gc->memory_pool   = new_memory_pool(POOL_SIZE, &compact_pool);
+    alloc_new_block(interp->mem_pools, POOL_SIZE, gc->memory_pool, "init");
 
-    /* Allocate a new block. Header info's on the front */
-    new_block = (Memory_Block *)mem_internal_allocate_zeroed(
-        sizeof (Memory_Block) + alloc_size);
+    /* Constant strings - not compacted */
+    gc->constant_string_pool = new_memory_pool(POOL_SIZE, NULL);
+    alloc_new_block(interp->mem_pools, POOL_SIZE, gc->constant_string_pool, "init");
+}
 
-    if (!new_block) {
-        fprintf(stderr, "out of mem allocsize = %d\n", (int)alloc_size);
-        exit(EXIT_FAILURE);
-    }
+/*
 
-    new_block->free  = alloc_size;
-    new_block->size  = alloc_size;
+=item C<void Parrot_gc_str_finalize(PARROT_INTERP, String_GC *gc)>
 
-    new_block->next  = NULL;
-    new_block->start = (char *)new_block + sizeof (Memory_Block);
-    new_block->top   = new_block->start;
+Destroys the memory pool and the constant string pool. Loop through both
+pools and destroy all memory blocks contained in them. Once all the
+blocks are freed, free the pools themselves.
 
-    /* Note that we've allocated it */
-    mem_pools->memory_allocated += alloc_size;
+=cut
 
-    /* If this is for a public pool, add it to the list */
-    new_block->prev = pool->top_block;
+*/
 
-    /* If we're not first, then tack us on the list */
-    if (pool->top_block)
-        pool->top_block->next = new_block;
+void
+Parrot_gc_str_finalize(SHIM_INTERP, ARGMOD(String_GC *gc))
+{
+    ASSERT_ARGS(Parrot_gc_str_finalize)
 
-    pool->top_block        = new_block;
-    pool->total_allocated += alloc_size;
+    free_memory_pool(gc->constant_string_pool);
+    free_memory_pool(gc->memory_pool);
 }
 
 /*
 
-=item C<void * mem_allocate(PARROT_INTERP, Memory_Pools *mem_pools, size_t size,
-Variable_Size_Pool *pool)>
-
-Allocates memory for headers.
-
-Alignment problems history:
-
-See L<http://archive.develooper.com/perl6-internals%40perl.org/msg12310.html>
-for details.
+=item C<void Parrot_gc_str_alloc_new_block( Memory_Pools *mem_pools, size_t
+size, Variable_Size_Pool *pool, const char *why)>
 
-- return aligned pointer *if needed*
-- return strings et al at unaligned i.e. void* boundaries
-- remember alignment in a buffer header bit
-  use this in compaction code
-- reduce alignment to a reasonable value i.e. MALLOC_ALIGNMENT
-  aka 2*sizeof (size_t) or just 8 (TODO make a config hint)
-
-See pobj.h for a discussion of the Buffer descriptor and the buffer itself,
-including its header.
+Allocate a new string block
 
 =cut
 
 */
 
-PARROT_MALLOC
-PARROT_CANNOT_RETURN_NULL
-void *
-mem_allocate(PARROT_INTERP,
+void
+Parrot_gc_str_alloc_new_block(
         ARGMOD(Memory_Pools *mem_pools),
         size_t size,
-        ARGMOD(Variable_Size_Pool *pool))
+        ARGMOD(Variable_Size_Pool *pool),
+        ARGIN(const char *why))
 {
-    ASSERT_ARGS(mem_allocate)
-    void *return_val;
+    ASSERT_ARGS(Parrot_gc_str_alloc_new_block)
 
-    /* we always should have one block at least */
-    PARROT_ASSERT(pool->top_block);
+    alloc_new_block(mem_pools, size, pool, why);
+}
 
-    /* If not enough room, try to find some */
-    if (pool->top_block->free < size) {
-        /*
-         * force a GC mark run to get live flags set
-         * for incremental M&S collection is run from there
-         * but only if there may be something worth collecting!
-         * TODO pass required allocation size to the GC system,
-         *      so that collection can be skipped if needed
-         */
-        size_t new_mem = mem_pools->memory_used -
-                         mem_pools->mem_used_last_collect;
-        if (!mem_pools->gc_mark_block_level
-            && new_mem > (mem_pools->mem_used_last_collect >> 2)
-            && new_mem > GC_SIZE_THRESHOLD) {
-            Parrot_gc_mark_and_sweep(interp, GC_trace_stack_FLAG);
+/*
 
-            if (interp->gc_sys->sys_type != INF) {
-                /* Compact the pool if allowed and worthwhile */
-                if (pool->compact) {
-                    /* don't bother reclaiming if it's only a small amount */
-                    if ((pool->possibly_reclaimable * pool->reclaim_factor +
-                         pool->guaranteed_reclaimable) > size) {
-                        (*pool->compact) (interp, mem_pools, pool);
-                    }
-                }
-            }
-        }
-        if (pool->top_block->free < size) {
-            if (pool->minimum_block_size < 65536 * 16)
-                pool->minimum_block_size *= 2;
-            /*
-             * TODO - Big blocks
-             *
-             * Mark the block as big block (it has just one item)
-             * And don't set big blocks as the top_block.
-             */
-            alloc_new_block(mem_pools, size, pool, "compact failed");
+=item C<void Parrot_gc_str_allocate_buffer_storage(PARROT_INTERP, String_GC *gc,
+Buffer *buffer, size_t size)>
 
-            ++mem_pools->mem_allocs_since_last_collect;
+Allocates a chunk of memory of at least size C<size> for the given Buffer.
+buffer is guaranteed to be properly aligned for things like C<FLOATVALS>,
+so the size may be rounded up or down to guarantee that this alignment holds.
 
-            if (pool->top_block->free < size) {
-                fprintf(stderr, "out of mem\n");
-                exit(EXIT_FAILURE);
-            }
-        }
-    }
+=cut
 
-    /* TODO inline the fast path */
-    return_val             = pool->top_block->top;
-    pool->top_block->top  += size;
-    pool->top_block->free -= size;
-    mem_pools->memory_used += size;
+*/
 
-    return return_val;
+void
+Parrot_gc_str_allocate_buffer_storage(PARROT_INTERP,
+        ARGIN(String_GC *gc),
+        ARGOUT(Buffer *buffer),
+        size_t size)
+{
+    ASSERT_ARGS(Parrot_gc_str_allocate_buffer_storage)
+    const size_t new_size   = ALIGNED_STRING_SIZE(size);
+
+    Buffer_bufstart(buffer) = (void *)aligned_mem(buffer,
+        (char *)mem_allocate(interp,
+        interp->mem_pools, new_size, gc->memory_pool));
+
+    /* Save pool used to allocate into buffer header */
+    *Buffer_poolptr(buffer) = gc->memory_pool->top_block;
+
+    Buffer_buflen(buffer)   = new_size - sizeof (void *);
 }
 
 /*
 
-=item C<static const char * buffer_location(PARROT_INTERP, const Buffer *b)>
+=item C<void Parrot_gc_str_reallocate_buffer_storage(PARROT_INTERP, String_GC
+*gc, Buffer *buffer, size_t newsize)>
 
-Recturns a constant string representing the location of the given
-Buffer C<b> in one of the PMC registers. If the PMC is not located
-in one of the PMC registers of the current context, returns the
-string C<"???">.
+Reallocate the Buffer's buffer memory to the given size. The
+allocated buffer will not shrink. If the buffer was allocated with
+L<Parrot_allocate_aligned> the new buffer will also be aligned. As with
+all reallocation, the new buffer might have moved and the additional
+memory is not cleared.
 
 =cut
 
 */
 
-#if RESOURCE_DEBUG
-PARROT_CANNOT_RETURN_NULL
-PARROT_WARN_UNUSED_RESULT
-static const char *
-buffer_location(PARROT_INTERP, ARGIN(const Buffer *b))
-{
-    ASSERT_ARGS(buffer_location)
-    Parrot_Context * const ctx = CONTEXT(interp);
-    static char reg[10];
-    UINTVAL i;
+void
+Parrot_gc_str_reallocate_buffer_storage(PARROT_INTERP,
+        ARGIN(String_GC *gc),
+        ARGMOD(Buffer *buffer),
+        size_t newsize)
+{
+    ASSERT_ARGS(Parrot_gc_str_reallocate_buffer_storage)
+    size_t copysize;
+    char  *mem;
+    Variable_Size_Pool * const pool = gc->memory_pool;
+    size_t new_size, needed, old_size;
 
-    for (i = 0; i < ctx->n_regs_used[REGNO_STR]; ++i) {
-        PObj * const obj = (PObj *)Parrot_pcc_get_STRING_reg(interp, ctx, i);
-        if ((PObj *)obj == b) {
-            sprintf(reg, "S%d", (int)i);
-            return reg;
-        }
+    /* we don't shrink buffers */
+    if (newsize <= Buffer_buflen(buffer))
+        return;
+
+    /*
+     * same as below but barely used and tested - only 3 list related
+     * tests do use true reallocation
+     *
+     * list.c, which does _reallocate, has 2 reallocations
+     * normally, which play ping pong with buffers.
+     * The normal case is therefore always to allocate a new block
+     */
+    new_size = ALIGNED_STRING_SIZE(newsize);
+    old_size = ALIGNED_STRING_SIZE(Buffer_buflen(buffer));
+    needed   = new_size - old_size;
+
+    if ((pool->top_block->free >= needed)
+    &&  (pool->top_block->top  == (char *)Buffer_bufstart(buffer) + old_size)) {
+        pool->top_block->free -= needed;
+        pool->top_block->top  += needed;
+        interp->mem_pools->memory_used += needed;
+        Buffer_buflen(buffer)  = newsize;
+        return;
     }
 
-    return "???";
-}
+    copysize = Buffer_buflen(buffer);
 
-/*
+    mem = (char *)mem_allocate(interp, interp->mem_pools, new_size, pool);
+    mem = aligned_mem(buffer, mem);
 
-=item C<static void debug_print_buf(PARROT_INTERP, const Buffer *b)>
+    /* We shouldn't ever have a 0 from size, but we do. If we can track down
+     * those bugs, this can be removed which would make things cheaper */
+    if (copysize)
+        memcpy(mem, Buffer_bufstart(buffer), copysize);
 
-Prints a debug statement with information about the given PObj C<b>.
-=cut
+    Buffer_bufstart(buffer) = mem;
 
-*/
+    new_size -= sizeof (void *);
 
-static void
-debug_print_buf(PARROT_INTERP, ARGIN(const Buffer *b))
-{
-    ASSERT_ARGS(debug_print_buf)
-    fprintf(stderr, "found %p, len %d, flags 0x%08x at %s\n",
-            b, (int)Buffer_buflen(b), (uint)PObj_get_FLAGS(b),
-            buffer_location(interp, b));
+    Buffer_buflen(buffer) = new_size;
+
+    /* Save pool used to allocate into buffer header */
+    *Buffer_poolptr(buffer) = gc->memory_pool->top_block;
 }
-#endif
 
 /*
 
-=back
+=item C<void Parrot_gc_str_allocate_string_storage(PARROT_INTERP, String_GC *gc,
+STRING *str, size_t size)>
 
-=head2 Compaction Code
-
-=over 4
-
-=item C<void compact_pool(PARROT_INTERP, Memory_Pools *mem_pools,
-Variable_Size_Pool *pool)>
-
-Compact the string buffer pool. Does not perform a GC scan, or mark items
-as being alive in any way.
+Allocate the STRING's buffer memory to the given size. The allocated
+buffer maybe slightly bigger than the given C<size>. This function
+sets also C<< str->strstart >> to the new buffer location, C<< str->bufused >>
+is B<not> changed.
 
 =cut
 
 */
 
 void
-compact_pool(PARROT_INTERP,
-        ARGMOD(Memory_Pools *mem_pools),
-        ARGMOD(Variable_Size_Pool *pool))
-{
-    ASSERT_ARGS(compact_pool)
-    INTVAL        j;
-    UINTVAL       total_size;
-
-    Fixed_Size_Arena *cur_buffer_arena;
-
-    /* Contains new_block and cur_spot */
-    string_callback_data cb_data;
-
-
-    /* Bail if we're blocked */
-    if (mem_pools->gc_sweep_block_level)
-        return;
-
-    ++mem_pools->gc_sweep_block_level;
-
-    /* We're collecting */
-    mem_pools->mem_allocs_since_last_collect    = 0;
-    mem_pools->header_allocs_since_last_collect = 0;
-    ++mem_pools->gc_collect_runs;
+Parrot_gc_str_allocate_string_storage(PARROT_INTERP,
+        ARGIN(String_GC *gc),
+        ARGOUT(STRING *str),
+        size_t size)
+{
+    ASSERT_ARGS(Parrot_gc_str_allocate_string_storage)
+    size_t       new_size;
+    Variable_Size_Pool *pool;
+    char        *mem;
 
-    /* Snag a block big enough for everything */
-    total_size = pad_pool_size(pool);
+    Buffer_buflen(str)   = 0;
+    Buffer_bufstart(str) = NULL;
 
-    if (total_size == 0) {
-        free_old_mem_blocks(mem_pools, pool, pool->top_block, total_size);
-        --mem_pools->gc_sweep_block_level;
+    if (size == 0)
         return;
-    }
 
-    alloc_new_block(mem_pools, total_size, pool, "inside compact");
+    pool     = PObj_constant_TEST(str)
+                ? gc->constant_string_pool
+                : gc->memory_pool;
 
-    cb_data.new_block = pool->top_block;
+    new_size = ALIGNED_STRING_SIZE(size);
+    mem      = (char *)mem_allocate(interp, interp->mem_pools, new_size, pool);
+    mem     += sizeof (void *);
 
-    /* Start at the beginning */
-    cb_data.cur_spot  = cb_data.new_block->start;
+    Buffer_bufstart(str) = str->strstart = mem;
+    Buffer_buflen(str)   = new_size - sizeof (void *);
 
-    /* Run through all the Buffer header pools and copy */
-    interp->gc_sys->iterate_live_strings(interp, move_buffer_callback, &cb_data);
-
-    /* Okay, we're done with the copy. Set the bits in the pool struct */
-    /* First, where we allocate next */
-    cb_data.new_block->top = cb_data.cur_spot;
-
-    PARROT_ASSERT(cb_data.new_block->size
-                  >=
-                  (size_t)cb_data.new_block->top - (size_t)cb_data.new_block->start);
-
-    /* How much is free. That's the total size minus the amount we used */
-    cb_data.new_block->free     = cb_data.new_block->size
-                                  - (cb_data.cur_spot - cb_data.new_block->start);
-    mem_pools->memory_collected += (cb_data.cur_spot - cb_data.new_block->start);
-    mem_pools->memory_used      += (cb_data.cur_spot - cb_data.new_block->start);
-
-    free_old_mem_blocks(mem_pools, pool, cb_data.new_block, total_size);
-
-    --mem_pools->gc_sweep_block_level;
+    /* Save pool used to allocate into buffer header */
+    *Buffer_poolptr(str) = pool->top_block;
 }
 
 /*
-=item C<static void move_buffer_callback(PARROT_INTERP, Buffer *b, void *data)>
 
-Callback for live STRING/Buffer for compating.
+=item C<void Parrot_gc_str_reallocate_string_storage(PARROT_INTERP, String_GC
+*gc, STRING *str, size_t newsize)>
 
-=cut
-*/
-static void
-move_buffer_callback(PARROT_INTERP, ARGIN(Buffer *b), ARGIN(void *data))
-{
-    ASSERT_ARGS(move_buffer_callback)
-    string_callback_data *cb = (string_callback_data*)data;
-
-    if (Buffer_buflen(b) && PObj_is_movable_TESTALL(b)) {
-        Memory_Block *old_block = Buffer_pool(b);
-
-        if (!is_block_almost_full(old_block))
-            cb->cur_spot = move_one_buffer(interp, cb->new_block, b, cb->cur_spot);
-    }
-
-}
-
-/*
-
-=item C<static UINTVAL pad_pool_size(const Variable_Size_Pool *pool)>
+Reallocate the STRING's buffer memory to the given size. The allocated
+buffer will not shrink. This function sets also C<str-E<gt>strstart> to the
+new buffer location, C<str-E<gt>bufused> is B<not> changed.
 
-Calculate the size of the new pool. The currently used size equals the total
-size minus the reclaimable size. Add a minimum block to the current amount, so
-we can avoid having to allocate it in the future.
-
-Returns 0 if all blocks below the top block are almost full. In this case
-compacting is not needed.
-
-TODO - Big blocks
+=cut
 
-Currently all available blocks are compacted into one new
-block with total_size. This is suboptimal, if the block has
-just one live item from a big allocation.
+*/
 
-But currently it's unknown if the buffer memory is alive
-as the live bits are in Buffer headers. We have to run the
-compaction loop to check liveness. OTOH if this compaction
-is running through all the buffer headers, there is no
-relation to the block.
+void
+Parrot_gc_str_reallocate_string_storage(PARROT_INTERP,
+        ARGIN(String_GC *gc),
+        ARGMOD(STRING *str),
+        size_t newsize)
+{
+    ASSERT_ARGS(Parrot_gc_str_reallocate_string_storage)
+    size_t copysize;
+    char *mem, *oldmem;
+    size_t new_size, needed, old_size;
+
+    Variable_Size_Pool * const pool =
+        PObj_constant_TEST(str)
+            ? gc->constant_string_pool
+            : gc->memory_pool;
 
-Moving the live bit into the buffer thus also solves this
-problem easily.
+    /* if the requested size is smaller then buflen, we are done */
+    if (newsize <= Buffer_buflen(str))
+        return;
 
-=cut
+    /*
+     * first check, if we can reallocate:
+     * - if the passed strings buffer is the last string in the pool and
+     * - if there is enough size, we can just move the pool's top pointer
+     */
+    new_size = ALIGNED_STRING_SIZE(newsize);
+    old_size = ALIGNED_STRING_SIZE(Buffer_buflen(str));
+    needed   = new_size - old_size;
+
+    if (pool->top_block->free >= needed
+    &&  pool->top_block->top  == (char *)Buffer_bufstart(str) + old_size) {
+        pool->top_block->free -= needed;
+        pool->top_block->top  += needed;
+        interp->mem_pools->memory_used += needed;
+        Buffer_buflen(str) = new_size - sizeof (void *);
+        return;
+    }
 
-*/
+    PARROT_ASSERT(str->bufused <= newsize);
 
-PARROT_CANNOT_RETURN_NULL
-static UINTVAL
-pad_pool_size(ARGIN(const Variable_Size_Pool *pool))
-{
-    ASSERT_ARGS(pad_pool_size)
-    Memory_Block *cur_block = pool->top_block->prev;
+    /* only copy used memory, not total string buffer */
+    copysize = str->bufused;
 
-    UINTVAL total_size   = 0;
-#if RESOURCE_DEBUG
-    size_t  total_blocks = 1;
-#endif
+    mem = (char *)mem_allocate(interp, interp->mem_pools, new_size, pool);
+    mem += sizeof (void *);
 
-    while (cur_block) {
-        if (!is_block_almost_full(cur_block))
-            total_size += cur_block->size - cur_block->freed - cur_block->free;
-        cur_block   = cur_block->prev;
-#if RESOURCE_DEBUG
-        ++total_blocks;
-#endif
-    }
+    /* Update Memory_Block usage */
+    /* We must not reallocate non-movable buffers! */
+    PARROT_ASSERT(PObj_is_movable_TESTALL(str));
 
-    if (total_size == 0)
-        return 0;
+    /* We must not reallocate shared buffers! */
+    PARROT_ASSERT(!(*Buffer_bufflagsptr(str) & Buffer_shared_FLAG));
 
-    cur_block = pool->top_block;
-    if (!is_block_almost_full(cur_block))
-        total_size += cur_block->size - cur_block->freed - cur_block->free;
+    /* Decrease usage */
+    PARROT_ASSERT(Buffer_pool(str));
+    Buffer_pool(str)->freed += old_size;
 
-    /* this makes for ever increasing allocations but fewer collect runs */
-#if WE_WANT_EVER_GROWING_ALLOCATIONS
-    total_size += pool->minimum_block_size;
-#endif
+    /* copy mem from strstart, *not* bufstart */
+    oldmem             = str->strstart;
+    Buffer_bufstart(str) = (void *)mem;
+    str->strstart      = mem;
+    Buffer_buflen(str)   = new_size - sizeof (void *);
 
-#if RESOURCE_DEBUG
-    fprintf(stderr, "Total blocks: %d\n", total_blocks);
-#endif
+    /* We shouldn't ever have a 0 from size, but we do. If we can track down
+     * those bugs, this can be removed which would make things cheaper */
+    if (copysize)
+        memcpy(mem, oldmem, copysize);
 
-    return total_size;
+    /* Save pool used to allocate into buffer header */
+    *Buffer_poolptr(str) = pool->top_block;
 }
 
 /*
+=item C<void Parrot_gc_str_compact_pool(PARROT_INTERP, String_GC *gc)>
 
-=item C<static char * move_one_buffer(PARROT_INTERP, Memory_Block *pool, Buffer
-*old_buf, char *new_pool_ptr)>
-
-The compact_pool operation collects disjointed blocks of memory allocated on a
-given pool's free list into one large block of memory. Once the new larger
-memory block has been allocated, this function moves one buffer from the old
-memory block to the new memory block and marks that it has been moved.
+Compact string pool.
 
 =cut
-
 */
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-static char *
-move_one_buffer(PARROT_INTERP, ARGIN(Memory_Block *pool),
-        ARGMOD(Buffer *old_buf), ARGMOD(char *new_pool_ptr))
+void
+Parrot_gc_str_compact_pool(PARROT_INTERP, ARGIN(String_GC *gc))
 {
-    ASSERT_ARGS(move_one_buffer)
-
-    INTVAL       *flags     = NULL;
-    ptrdiff_t     offset    = 0;
-    Memory_Block *old_block = NULL;
-#if RESOURCE_DEBUG
-    if (Buffer_buflen(old_buf) >= RESOURCE_DEBUG_SIZE)
-        debug_print_buf(interp, old_buf);
-#else
-    UNUSED(interp);
-#endif
-
-    /* we can't perform the math all the time, because
-        * strstart might be in unallocated memory */
-    if (PObj_is_COWable_TEST(old_buf)) {
-        flags = Buffer_bufflagsptr(old_buf);
-        old_block = Buffer_pool(old_buf);
-
-        if (PObj_is_string_TEST(old_buf)) {
-            offset = (ptrdiff_t)((STRING *)old_buf)->strstart -
-                (ptrdiff_t)Buffer_bufstart(old_buf);
-        }
-    }
-
-    /* buffer has already been moved; just change the header */
-    if (flags && (*flags & Buffer_shared_FLAG)
-              && (*flags & Buffer_moved_FLAG)) {
-        /* Find out who else references our data */
-        Buffer * const hdr = *((Buffer **)Buffer_bufstart(old_buf));
-
-        PARROT_ASSERT(PObj_is_COWable_TEST(old_buf));
-
-        /* Make sure they know that we own it too */
-        /* Set Buffer_shared_FLAG in new buffer */
-        *Buffer_bufflagsptr(hdr) |= Buffer_shared_FLAG;
-
-        /* Now make sure we point to where the other guy does */
-        Buffer_bufstart(old_buf) = Buffer_bufstart(hdr);
-
-        /* And if we're a string, update strstart */
-        /* Somewhat of a hack, but if we get per-pool
-            * collections, it should help ease the pain */
-        if (PObj_is_string_TEST(old_buf))
-            ((STRING *)old_buf)->strstart =
-                (char *)Buffer_bufstart(old_buf) + offset;
-    }
-    else {
-        new_pool_ptr = aligned_mem(old_buf, new_pool_ptr);
-
-        /* Copy our memory to the new pool */
-        memcpy(new_pool_ptr, Buffer_bufstart(old_buf),
-                                Buffer_buflen(old_buf));
-
-        /* If we're shared */
-        if (flags && (*flags & Buffer_shared_FLAG)) {
-            PARROT_ASSERT(PObj_is_COWable_TEST(old_buf));
-
-            /* Let the old buffer know how to find us */
-            *((Buffer **)Buffer_bufstart(old_buf)) = old_buf;
-
-            /* Finally, let the tail know that we've moved, so
-                * that any other references can know to look for
-                * us and not re-copy */
-            *flags |= Buffer_moved_FLAG;
-        }
-
-        Buffer_bufstart(old_buf) = new_pool_ptr;
-
-        /* Remember new pool inside */
-        *Buffer_poolptr(old_buf) = pool;
-
-        if (PObj_is_string_TEST(old_buf))
-            ((STRING *)old_buf)->strstart =
-                    (char *)Buffer_bufstart(old_buf) + offset;
-
-        new_pool_ptr += Buffer_buflen(old_buf);
-    }
-
-    return new_pool_ptr;
+    ASSERT_ARGS(Parrot_gc_str_compact_pool)
+    compact_pool(interp, interp->mem_pools, gc->memory_pool);
 }
 
 /*
 
-=item C<static void free_old_mem_blocks( Memory_Pools *mem_pools,
-Variable_Size_Pool *pool, Memory_Block *new_block, UINTVAL total_size)>
+=item C<void Parrot_gc_str_free_buffer_storage(PARROT_INTERP, String_GC *gc,
+Buffer *b)>
 
-The compact_pool operation collects disjointed blocks of memory allocated on a
-given pool's free list into one large block of memory, setting it as the new
-top block for the pool. Once that is done, and all items have been moved into
-the new block of memory, this function iterates through the old blocks and
-frees each one. It also performs the necessary housekeeping to record the
-freed memory blocks. At the end of this function, the pool will have only one
-block of memory on its free list.
+Frees a buffer, returning it to the memory pool for Parrot to possibly
+reuse later.
 
 =cut
 
 */
 
-static void
-free_old_mem_blocks(
-        ARGMOD(Memory_Pools *mem_pools),
-        ARGMOD(Variable_Size_Pool *pool),
-        ARGMOD(Memory_Block *new_block),
-        UINTVAL total_size)
+void
+Parrot_gc_str_free_buffer_storage(SHIM_INTERP,
+        ARGIN(String_GC *gc),
+        ARGMOD(Buffer *b))
 {
-    ASSERT_ARGS(free_old_mem_blocks)
-    Memory_Block *prev_block = new_block;
-    Memory_Block *cur_block  = new_block->prev;
-
-    PARROT_ASSERT(new_block == pool->top_block);
+    ASSERT_ARGS(Parrot_gc_str_free_buffer_storage)
+    Variable_Size_Pool * const mem_pool = gc->memory_pool;
 
-    while (cur_block) {
-        Memory_Block * const next_block = cur_block->prev;
-
-        if (is_block_almost_full(cur_block)) {
-            /* Skip block */
-            prev_block = cur_block;
-            cur_block  = next_block;
-        }
-        else {
-            /* Note that we don't have it any more */
-            mem_pools->memory_allocated -= cur_block->size;
-            mem_pools->memory_used -= cur_block->size - cur_block->free;
+    /* If there is no allocated buffer - bail out */
+    if (!Buffer_buflen(b))
+        return;
 
-            /* We know the pool body and pool header are a single chunk, so
-             * this is enough to get rid of 'em both */
-            mem_internal_free(cur_block);
-            cur_block        = next_block;
+    if (mem_pool) {
+        /* Update Memory_Block usage */
+        if (PObj_is_movable_TESTALL(b)) {
+            INTVAL *buffer_flags = Buffer_bufflagsptr(b);
+
+            /* Mask low 2 bits used for flags */
+            Memory_Block * block = Buffer_pool(b);
+
+            PARROT_ASSERT(block);
+
+            /* We can have shared buffers. Don't count them (yet) */
+            if (!(*buffer_flags & Buffer_shared_FLAG)) {
+                block->freed  += ALIGNED_STRING_SIZE(Buffer_buflen(b));
+            }
 
-            /* Unlink it from list */
-            prev_block->prev = next_block;
         }
     }
 
-    /* Terminate list */
-    prev_block->prev = NULL;
-
-
-    /* ANR: I suspect this should be set to new_block->size, instead of passing
-     * in the raw value of total_size, because alloc_new_block pads the size of
-     * the new block under certain conditions. Leaving it unmodified for now,
-     * so this refactor has no functionality changes, only code cleanups.*/
-    pool->total_allocated        = total_size;
-    pool->guaranteed_reclaimable = 0;
-    pool->possibly_reclaimable   = 0;
+    Buffer_buflen(b) = 0;
 }
 
 /*
+=item C<static Variable_Size_Pool * new_memory_pool(size_t min_block, compact_f
+compact)>
 
-=item C<static int is_block_almost_full(const Memory_Block *block)>
-
-Tests if the block is almost full and should be skipped during compacting.
-
-Returns true if less that 20% of block is available
-
-=cut
-
-*/
-
-static int
-is_block_almost_full(ARGIN(const Memory_Block *block))
-{
-    ASSERT_ARGS(is_block_almost_full)
-    return 5 * (block->free + block->freed) < block->size;
-}
-
-/*
-
-=item C<char * aligned_mem(const Buffer *buffer, char *mem)>
-
-Returns a pointer to the aligned allocated storage for Buffer C<buffer>,
-which might not be the same as the pointer to C<buffer> because of
-memory alignment.
+Allocate a new C<Variable_Size_Pool> structures, and set some initial values.
+return a pointer to the new pool.
 
 =cut
 
 */
 
-PARROT_CANNOT_RETURN_NULL
 PARROT_WARN_UNUSED_RESULT
-char *
-aligned_mem(SHIM(const Buffer *buffer), ARGIN(char *mem))
+PARROT_MALLOC
+PARROT_CANNOT_RETURN_NULL
+static Variable_Size_Pool *
+new_memory_pool(size_t min_block, NULLOK(compact_f compact))
 {
-    ASSERT_ARGS(aligned_mem)
-    mem += sizeof (void *);
-    mem  = (char *)(((unsigned long)(mem + WORD_ALIGN_1)) & WORD_ALIGN_MASK);
+    ASSERT_ARGS(new_memory_pool)
+    Variable_Size_Pool * const pool = mem_internal_allocate_typed(Variable_Size_Pool);
 
-    return mem;
+    pool->top_block              = NULL;
+    pool->compact                = compact;
+    pool->minimum_block_size     = min_block;
+    pool->total_allocated        = 0;
+    pool->guaranteed_reclaimable = 0;
+    pool->possibly_reclaimable   = 0;
+    pool->reclaim_factor         = RECLAMATION_FACTOR;
+
+    return pool;
 }
 
 /*
 
-=back
-
-=head2 Parrot Re/Allocate Code
-
-=over 4
-
-=item C<static Variable_Size_Pool * new_memory_pool(size_t min_block, compact_f
-compact)>
+=item C<static void alloc_new_block( Memory_Pools *mem_pools, size_t size,
+Variable_Size_Pool *pool, const char *why)>
 
-Allocate a new C<Variable_Size_Pool> structures, and set some initial values.
-return a pointer to the new pool.
+Allocate a new memory block. We allocate either the requested size or the
+default size, whichever is larger. Add the new block to the given memory
+pool. The given C<char *why> text is used for debugging.
 
 =cut
 
 */
 
-PARROT_WARN_UNUSED_RESULT
-PARROT_MALLOC
-PARROT_CANNOT_RETURN_NULL
-static Variable_Size_Pool *
-new_memory_pool(size_t min_block, NULLOK(compact_f compact))
+static void
+alloc_new_block(
+        ARGMOD(Memory_Pools *mem_pools),
+        size_t size,
+        ARGMOD(Variable_Size_Pool *pool),
+        ARGIN(const char *why))
 {
-    ASSERT_ARGS(new_memory_pool)
-    Variable_Size_Pool * const pool = mem_internal_allocate_typed(Variable_Size_Pool);
+    ASSERT_ARGS(alloc_new_block)
+    Memory_Block *new_block;
 
-    pool->top_block              = NULL;
-    pool->compact                = compact;
-    pool->minimum_block_size     = min_block;
-    pool->total_allocated        = 0;
-    pool->guaranteed_reclaimable = 0;
-    pool->possibly_reclaimable   = 0;
-    pool->reclaim_factor         = RECLAMATION_FACTOR;
+    const size_t alloc_size = (size > pool->minimum_block_size)
+            ? size : pool->minimum_block_size;
 
-    return pool;
-}
+#if RESOURCE_DEBUG
+    fprintf(stderr, "new_block (%s) size %u -> %u\n",
+        why, size, alloc_size);
+#else
+    UNUSED(why)
+#endif
 
-/*
+    /* Allocate a new block. Header info's on the front */
+    new_block = (Memory_Block *)mem_internal_allocate_zeroed(
+        sizeof (Memory_Block) + alloc_size);
 
-=item C<void initialize_var_size_pools(PARROT_INTERP, Memory_Pools *mem_pools)>
+    if (!new_block) {
+        fprintf(stderr, "out of mem allocsize = %d\n", (int)alloc_size);
+        exit(EXIT_FAILURE);
+    }
 
-Initialize the managed memory pools. Parrot maintains two C<Variable_Size_Pool>
-structures, the general memory pool and the constant string pool. Create
-and initialize both pool structures, and allocate initial blocks of memory
-for both.
+    new_block->free  = alloc_size;
+    new_block->size  = alloc_size;
 
-=cut
+    new_block->next  = NULL;
+    new_block->start = (char *)new_block + sizeof (Memory_Block);
+    new_block->top   = new_block->start;
 
-*/
+    /* Note that we've allocated it */
+    mem_pools->memory_allocated += alloc_size;
 
-void
-initialize_var_size_pools(SHIM_INTERP, ARGMOD(Memory_Pools *mem_pools))
-{
-    ASSERT_ARGS(initialize_var_size_pools)
+    /* If this is for a public pool, add it to the list */
+    new_block->prev = pool->top_block;
 
-    mem_pools->memory_pool   = new_memory_pool(POOL_SIZE, &compact_pool);
-    alloc_new_block(mem_pools, POOL_SIZE, mem_pools->memory_pool, "init");
+    /* If we're not first, then tack us on the list */
+    if (pool->top_block)
+        pool->top_block->next = new_block;
 
-    /* Constant strings - not compacted */
-    mem_pools->constant_string_pool = new_memory_pool(POOL_SIZE, NULL);
-    alloc_new_block(mem_pools, POOL_SIZE, mem_pools->constant_string_pool, "init");
+    pool->top_block        = new_block;
+    pool->total_allocated += alloc_size;
 }
 
-
 /*
 
-=item C<void merge_pools(Variable_Size_Pool *dest, Variable_Size_Pool *source)>
+=item C<static void * mem_allocate(PARROT_INTERP, Memory_Pools *mem_pools,
+size_t size, Variable_Size_Pool *pool)>
+
+Allocates memory for headers.
+
+Alignment problems history:
+
+See L<http://archive.develooper.com/perl6-internals%40perl.org/msg12310.html>
+for details.
+
+- return aligned pointer *if needed*
+- return strings et al at unaligned i.e. void* boundaries
+- remember alignment in a buffer header bit
+  use this in compaction code
+- reduce alignment to a reasonable value i.e. MALLOC_ALIGNMENT
+  aka 2*sizeof (size_t) or just 8 (TODO make a config hint)
 
-Merge two memory pools together. Do this by moving all memory blocks
-from the C<*source> pool into the C<*dest> pool. The C<source> pool
-is emptied, but is not destroyed here.
+See pobj.h for a discussion of the Buffer descriptor and the buffer itself,
+including its header.
 
 =cut
 
 */
 
-void
-merge_pools(ARGMOD(Variable_Size_Pool *dest), ARGMOD(Variable_Size_Pool *source))
+PARROT_MALLOC
+PARROT_CANNOT_RETURN_NULL
+static void *
+mem_allocate(PARROT_INTERP,
+        ARGMOD(Memory_Pools *mem_pools),
+        size_t size,
+        ARGMOD(Variable_Size_Pool *pool))
 {
-    ASSERT_ARGS(merge_pools)
-    Memory_Block *cur_block;
+    ASSERT_ARGS(mem_allocate)
+    void *return_val;
 
-    cur_block = source->top_block;
+    /* we always should have one block at least */
+    PARROT_ASSERT(pool->top_block);
 
-    while (cur_block) {
-        Memory_Block * const next_block = cur_block->prev;
+    /* If not enough room, try to find some */
+    if (pool->top_block->free < size) {
+        /*
+         * force a GC mark run to get live flags set
+         * for incremental M&S collection is run from there
+         * but only if there may be something worth collecting!
+         * TODO pass required allocation size to the GC system,
+         *      so that collection can be skipped if needed
+         */
+        size_t new_mem = mem_pools->memory_used -
+                         mem_pools->mem_used_last_collect;
+        if (!mem_pools->gc_mark_block_level
+            && new_mem > (mem_pools->mem_used_last_collect >> 2)
+            && new_mem > GC_SIZE_THRESHOLD) {
+            Parrot_gc_mark_and_sweep(interp, GC_trace_stack_FLAG);
 
-        if (cur_block->free == cur_block->size)
-            mem_internal_free(cur_block);
-        else {
-            cur_block->next        = NULL;
-            cur_block->prev        = dest->top_block;
+            if (interp->gc_sys->sys_type != INF) {
+                /* Compact the pool if allowed and worthwhile */
+                if (pool->compact) {
+                    /* don't bother reclaiming if it's only a small amount */
+                    if ((pool->possibly_reclaimable * pool->reclaim_factor +
+                         pool->guaranteed_reclaimable) > size) {
+                        (*pool->compact) (interp, mem_pools, pool);
+                    }
+                }
+            }
+        }
+        if (pool->top_block->free < size) {
+            if (pool->minimum_block_size < 65536 * 16)
+                pool->minimum_block_size *= 2;
+            /*
+             * TODO - Big blocks
+             *
+             * Mark the block as big block (it has just one item)
+             * And don't set big blocks as the top_block.
+             */
+            Parrot_gc_str_alloc_new_block(mem_pools, size, pool, "compact failed");
+
+            ++mem_pools->mem_allocs_since_last_collect;
 
-            dest->top_block        = cur_block;
-            dest->total_allocated += cur_block->size;
+            if (pool->top_block->free < size) {
+                fprintf(stderr, "out of mem\n");
+                exit(EXIT_FAILURE);
+            }
         }
-        cur_block = next_block;
     }
 
-    dest->guaranteed_reclaimable += source->guaranteed_reclaimable;
-    dest->possibly_reclaimable   += source->possibly_reclaimable;
+    /* TODO inline the fast path */
+    return_val             = pool->top_block->top;
+    pool->top_block->top  += size;
+    pool->top_block->free -= size;
+    mem_pools->memory_used += size;
 
-    source->top_block              = NULL;
-    source->total_allocated        = 0;
-    source->possibly_reclaimable   = 0;
-    source->guaranteed_reclaimable = 0;
+    return return_val;
 }
 
 /*
 
-=item C<static void check_memory_system(const Memory_Pools *mem_pools)>
+=item C<static char * aligned_mem(const Buffer *buffer, char *mem)>
 
-Checks the memory system of parrot on any corruptions, including
-the string system.
+Returns a pointer to the aligned allocated storage for Buffer C<buffer>,
+which might not be the same as the pointer to C<buffer> because of
+memory alignment.
 
 =cut
 
 */
 
-static void
-check_memory_system(ARGIN(const Memory_Pools *mem_pools))
+PARROT_CANNOT_RETURN_NULL
+PARROT_WARN_UNUSED_RESULT
+static char *
+aligned_mem(SHIM(const Buffer *buffer), ARGIN(char *mem))
 {
-    ASSERT_ARGS(check_memory_system)
-    size_t i;
+    ASSERT_ARGS(aligned_mem)
+    mem += sizeof (void *);
+    mem  = (char *)(((unsigned long)(mem + WORD_ALIGN_1)) & WORD_ALIGN_MASK);
 
-    check_var_size_obj_pool(mem_pools->memory_pool);
-    check_var_size_obj_pool(mem_pools->constant_string_pool);
-    check_fixed_size_obj_pool(mem_pools->pmc_pool);
-    check_fixed_size_obj_pool(mem_pools->constant_pmc_pool);
-    check_fixed_size_obj_pool(mem_pools->string_header_pool);
-    check_fixed_size_obj_pool(mem_pools->constant_string_header_pool);
-
-    for (i = 0; i < mem_pools->num_sized; ++i) {
-        const Fixed_Size_Pool * const pool = mem_pools->sized_header_pools[i];
-        if (pool != NULL && pool != mem_pools->string_header_pool)
-            check_fixed_size_obj_pool(pool);
-    }
+    return mem;
 }
 
 /*
 
-=item C<static void check_fixed_size_obj_pool(const Fixed_Size_Pool *pool)>
+=item C<static const char * buffer_location(PARROT_INTERP, const Buffer *b)>
 
-Checks a small object pool, if it contains buffer it checks the buffers also.
+Recturns a constant string representing the location of the given
+Buffer C<b> in one of the PMC registers. If the PMC is not located
+in one of the PMC registers of the current context, returns the
+string C<"???">.
 
 =cut
 
 */
 
-static void
-check_fixed_size_obj_pool(ARGIN(const Fixed_Size_Pool *pool))
+#if RESOURCE_DEBUG
+PARROT_CANNOT_RETURN_NULL
+PARROT_WARN_UNUSED_RESULT
+static const char *
+buffer_location(PARROT_INTERP, ARGIN(const Buffer *b))
 {
-    ASSERT_ARGS(check_fixed_size_obj_pool)
-    size_t total_objects;
-    size_t last_free_list_count;
-    Fixed_Size_Arena * arena_walker;
-    size_t free_objects;
-    size_t count;
-    GC_MS_PObj_Wrapper * pobj_walker;
-
-    count = 10000000; /*detect unendless loop just use big enough number*/
-
-    total_objects = pool->total_objects;
-    last_free_list_count = 1;
-    free_objects = 0;
-
-    arena_walker = pool->last_Arena;
-    while (arena_walker != NULL) {
-        size_t i;
-        PObj * object;
-
-        total_objects -= arena_walker->total_objects;
-        object = (PObj*)arena_walker->start_objects;
-
-        for (i = 0; i < arena_walker->total_objects; ++i) {
-            if (PObj_on_free_list_TEST(object)) {
-                ++free_objects;
-                pobj_walker = (GC_MS_PObj_Wrapper*)object;
-                if (pobj_walker->next_ptr == NULL)
-                    /* should happen only once at the end */
-                    --last_free_list_count;
-                else {
-                    /* next item on free list should also be flaged as free item */
-                    pobj_walker = (GC_MS_PObj_Wrapper*)pobj_walker->next_ptr;
-                    PARROT_ASSERT(PObj_on_free_list_TEST((PObj*)pobj_walker));
-                }
-            }
-            else if (pool->mem_pool != NULL) {
-                /*then it means we are a buffer*/
-                check_buffer_ptr((Buffer*)object, pool->mem_pool);
-            }
-            object = (PObj*)((char *)object + pool->object_size);
-            PARROT_ASSERT(--count);
-        }
-        /*check the list*/
-        if (arena_walker->prev != NULL)
-            PARROT_ASSERT(arena_walker->prev->next == arena_walker);
-        arena_walker = arena_walker->prev;
-        PARROT_ASSERT(--count);
-    }
-
-    count = 10000000;
-
-    PARROT_ASSERT(free_objects == pool->num_free_objects);
+    ASSERT_ARGS(buffer_location)
+    Parrot_Context * const ctx = CONTEXT(interp);
+    static char reg[10];
+    UINTVAL i;
 
-    pobj_walker = (GC_MS_PObj_Wrapper*)pool->free_list;
-    while (pobj_walker != NULL) {
-        PARROT_ASSERT(pool->start_arena_memory <= (size_t)pobj_walker);
-        PARROT_ASSERT(pool->end_arena_memory > (size_t)pobj_walker);
-        PARROT_ASSERT(PObj_on_free_list_TEST((PObj*)pobj_walker));
-        --free_objects;
-        pobj_walker = (GC_MS_PObj_Wrapper*)pobj_walker->next_ptr;
-        PARROT_ASSERT(--count);
+    for (i = 0; i < ctx->n_regs_used[REGNO_STR]; ++i) {
+        PObj * const obj = (PObj *)Parrot_pcc_get_STRING_reg(interp, ctx, i);
+        if ((PObj *)obj == b) {
+            sprintf(reg, "S%d", (int)i);
+            return reg;
+        }
     }
 
-    PARROT_ASSERT(total_objects == 0);
-    PARROT_ASSERT(last_free_list_count == 0 || pool->num_free_objects == 0);
-    PARROT_ASSERT(free_objects == 0);
+    return "???";
 }
 
 /*
 
-=item C<static void check_var_size_obj_pool(const Variable_Size_Pool *pool)>
-
-Checks a memory pool, containing buffer data
+=item C<static void debug_print_buf(PARROT_INTERP, const Buffer *b)>
 
+Prints a debug statement with information about the given PObj C<b>.
 =cut
 
 */
 
 static void
-check_var_size_obj_pool(ARGIN(const Variable_Size_Pool *pool))
+debug_print_buf(PARROT_INTERP, ARGIN(const Buffer *b))
 {
-    ASSERT_ARGS(check_var_size_obj_pool)
-    size_t count;
-    Memory_Block * block_walker;
-    count = 10000000; /*detect unendless loop just use big enough number*/
-
-    block_walker = (Memory_Block *)pool->top_block;
-    while (block_walker != NULL) {
-        PARROT_ASSERT(block_walker->start == (char *)block_walker +
-            sizeof (Memory_Block));
-        PARROT_ASSERT((size_t)(block_walker->top -
-            block_walker->start) == block_walker->size - block_walker->free);
-
-        /*check the list*/
-        if (block_walker->prev != NULL)
-            PARROT_ASSERT(block_walker->prev->next == block_walker);
-        block_walker = block_walker->prev;
-        PARROT_ASSERT(--count);
-    }
+    ASSERT_ARGS(debug_print_buf)
+    fprintf(stderr, "found %p, len %d, flags 0x%08x at %s\n",
+            b, (int)Buffer_buflen(b), (uint)PObj_get_FLAGS(b),
+            buffer_location(interp, b));
 }
+#endif
 
 /*
 
-=item C<void check_buffer_ptr(Buffer * pobj, Variable_Size_Pool * pool)>
+=back
+
+=head2 Compaction Code
+
+=over 4
+
+=item C<static void compact_pool(PARROT_INTERP, Memory_Pools *mem_pools,
+Variable_Size_Pool *pool)>
 
-Checks wether the buffer is within the bounds of the memory pool
+Compact the string buffer pool. Does not perform a GC scan, or mark items
+as being alive in any way.
 
 =cut
 
 */
 
-void
-check_buffer_ptr(ARGMOD(Buffer * pobj), ARGMOD(Variable_Size_Pool * pool))
+static void
+compact_pool(PARROT_INTERP,
+        ARGMOD(Memory_Pools *mem_pools),
+        ARGMOD(Variable_Size_Pool *pool))
 {
-    ASSERT_ARGS(check_buffer_ptr)
-    Memory_Block * cur_block = pool->top_block;
-    char * bufstart;
+    ASSERT_ARGS(compact_pool)
+    INTVAL        j;
+    UINTVAL       total_size;
+
+    Fixed_Size_Arena *cur_buffer_arena;
 
-    bufstart = (char*)Buffer_bufstart(pobj);
+    /* Contains new_block and cur_spot */
+    string_callback_data cb_data;
 
-    if (bufstart == NULL && Buffer_buflen(pobj) == 0)
-        return;
 
-    if (PObj_external_TEST(pobj) || PObj_sysmem_TEST(pobj)) {
-        /*buffer does not come from the memory pool*/
-        if (PObj_is_string_TEST(pobj)) {
-            PARROT_ASSERT(((STRING *) pobj)->strstart >=
-                (char *) Buffer_bufstart(pobj));
-            PARROT_ASSERT(((STRING *) pobj)->strstart +
-                ((STRING *) pobj)->strlen <=
-                (char *) Buffer_bufstart(pobj) + Buffer_buflen(pobj));
-        }
+    /* Bail if we're blocked */
+    if (mem_pools->gc_sweep_block_level)
         return;
-    }
 
-    if (PObj_is_COWable_TEST(pobj))
-        bufstart -= sizeof (void*);
+    ++mem_pools->gc_sweep_block_level;
 
-    while (cur_block) {
-        if ((char *)bufstart >= cur_block->start &&
-            (char *)Buffer_bufstart(pobj) +
-            Buffer_buflen(pobj) < cur_block->start + cur_block->size) {
-            if (PObj_is_string_TEST(pobj)) {
-                PARROT_ASSERT(((STRING *)pobj)->strstart >=
-                    (char *)Buffer_bufstart(pobj));
-                PARROT_ASSERT(((STRING *)pobj)->strstart +
-                    ((STRING *)pobj)->strlen <= (char *)Buffer_bufstart(pobj) +
-                    Buffer_buflen(pobj));
-            }
-            return;
-        }
-        cur_block = cur_block->prev;
-    }
-    PARROT_ASSERT(0);
-}
+    /* We're collecting */
+    mem_pools->mem_allocs_since_last_collect    = 0;
+    mem_pools->header_allocs_since_last_collect = 0;
+    ++mem_pools->gc_collect_runs;
 
+    /* Snag a block big enough for everything */
+    total_size = pad_pool_size(pool);
 
-/*
+    if (total_size == 0) {
+        free_old_mem_blocks(mem_pools, pool, pool->top_block, total_size);
+        --mem_pools->gc_sweep_block_level;
+        return;
+    }
 
-=item C<void Parrot_gc_destroy_header_pools(PARROT_INTERP, Memory_Pools
-*mem_pools)>
+    Parrot_gc_str_alloc_new_block(mem_pools, total_size, pool, "inside compact");
 
-Performs a garbage collection sweep on all pools, then frees them.  Calls
-C<header_pools_iterate_callback> to loop over all the pools, passing
-C<sweep_cb_pmc> and C<sweep_cb_buf> callback routines. Frees the array of sized
-header pointers in the C<Memory_Pools> structure too.
+    cb_data.new_block = pool->top_block;
 
-=cut
+    /* Start at the beginning */
+    cb_data.cur_spot  = cb_data.new_block->start;
 
-*/
+    /* Run through all the Buffer header pools and copy */
+    interp->gc_sys->iterate_live_strings(interp, move_buffer_callback, &cb_data);
 
-void
-Parrot_gc_destroy_header_pools(PARROT_INTERP, ARGMOD(Memory_Pools *mem_pools))
-{
-    ASSERT_ARGS(Parrot_gc_destroy_header_pools)
+    /* Okay, we're done with the copy. Set the bits in the pool struct */
+    /* First, where we allocate next */
+    cb_data.new_block->top = cb_data.cur_spot;
 
-    /* const/non const COW strings life in different pools
-     * so in first pass
-     * COW refcount is done, in 2. refcounting
-     * in 3rd freeing
-     */
-    const INTVAL start = 2;
+    PARROT_ASSERT(cb_data.new_block->size
+                  >=
+                  (size_t)cb_data.new_block->top - (size_t)cb_data.new_block->start);
 
-    header_pools_iterate_callback(interp, mem_pools, POOL_PMC, NULL, sweep_cb_pmc);
-    header_pools_iterate_callback(interp, mem_pools, POOL_PMC | POOL_CONST, NULL,
-            sweep_cb_pmc);
+    /* How much is free. That's the total size minus the amount we used */
+    cb_data.new_block->free     = cb_data.new_block->size
+                                  - (cb_data.cur_spot - cb_data.new_block->start);
+    mem_pools->memory_collected += (cb_data.cur_spot - cb_data.new_block->start);
+    mem_pools->memory_used      += (cb_data.cur_spot - cb_data.new_block->start);
 
-    header_pools_iterate_callback(interp, mem_pools, POOL_BUFFER | POOL_CONST,
-            (void *)start, sweep_cb_buf);
+    free_old_mem_blocks(mem_pools, pool, cb_data.new_block, total_size);
 
-    mem_internal_free(mem_pools->sized_header_pools);
+    --mem_pools->gc_sweep_block_level;
+}
 
-    if (mem_pools->attrib_pools) {
-        unsigned int i;
-        for (i = 0; i < mem_pools->num_attribs; ++i) {
-            PMC_Attribute_Pool  *pool  = mem_pools->attrib_pools[i];
-            PMC_Attribute_Arena *arena;
+/*
+=item C<static void move_buffer_callback(PARROT_INTERP, Buffer *b, void *data)>
 
-            if (!pool)
-                continue;
+Callback for live STRING/Buffer for compating.
 
-            arena = pool->top_arena;
+=cut
+*/
+static void
+move_buffer_callback(PARROT_INTERP, ARGIN(Buffer *b), ARGIN(void *data))
+{
+    ASSERT_ARGS(move_buffer_callback)
+    string_callback_data *cb = (string_callback_data*)data;
 
-            while (arena) {
-                PMC_Attribute_Arena *next = arena->next;
-                mem_internal_free(arena);
-                arena = next;
-            }
-            mem_internal_free(pool);
-        }
+    if (Buffer_buflen(b) && PObj_is_movable_TESTALL(b)) {
+        Memory_Block *old_block = Buffer_pool(b);
 
-        mem_internal_free(mem_pools->attrib_pools);
+        if (!is_block_almost_full(old_block))
+            cb->cur_spot = move_one_buffer(interp, cb->new_block, b, cb->cur_spot);
     }
 
-    mem_pools->attrib_pools       = NULL;
-    mem_pools->sized_header_pools = NULL;
 }
 
 /*
 
-=item C<static int sweep_cb_pmc(PARROT_INTERP, Memory_Pools *mem_pools,
-Fixed_Size_Pool *pool, int flag, void *arg)>
-
-Performs a garbage collection sweep of the given pmc pool, then frees it. Calls
-C<Parrot_gc_sweep_pool> to perform the sweep, and C<free_pool> to free the pool and
-all its arenas. Always returns C<0>.
+=item C<static UINTVAL pad_pool_size(const Variable_Size_Pool *pool)>
 
-=cut
+Calculate the size of the new pool. The currently used size equals the total
+size minus the reclaimable size. Add a minimum block to the current amount, so
+we can avoid having to allocate it in the future.
 
-*/
+Returns 0 if all blocks below the top block are almost full. In this case
+compacting is not needed.
 
-static int
-sweep_cb_pmc(PARROT_INTERP,
-        ARGMOD(Memory_Pools *mem_pools),
-        ARGMOD(Fixed_Size_Pool *pool),
-        SHIM(int flag), SHIM(void *arg))
-{
-    ASSERT_ARGS(sweep_cb_pmc)
-    Parrot_gc_sweep_pool(interp, mem_pools, pool);
-    free_pool(pool);
-    return 0;
-}
+TODO - Big blocks
 
-/*
+Currently all available blocks are compacted into one new
+block with total_size. This is suboptimal, if the block has
+just one live item from a big allocation.
 
-=item C<static int sweep_cb_buf(PARROT_INTERP, Memory_Pools *mem_pools,
-Fixed_Size_Pool *pool, int flag, void *arg)>
+But currently it's unknown if the buffer memory is alive
+as the live bits are in Buffer headers. We have to run the
+compaction loop to check liveness. OTOH if this compaction
+is running through all the buffer headers, there is no
+relation to the block.
 
-Performs a final garbage collection sweep, then frees the pool. Calls
-C<Parrot_gc_sweep_pool> to perform the sweep, and C<free_pool> to free the pool and
-all its arenas.
+Moving the live bit into the buffer thus also solves this
+problem easily.
 
 =cut
 
 */
 
-static int
-sweep_cb_buf(PARROT_INTERP,
-        ARGIN(Memory_Pools *mem_pools),
-        ARGFREE(Fixed_Size_Pool *pool),
-        SHIM(int flag), SHIM(void *arg))
+PARROT_CANNOT_RETURN_NULL
+static UINTVAL
+pad_pool_size(ARGIN(const Variable_Size_Pool *pool))
 {
-    ASSERT_ARGS(sweep_cb_buf)
-
-    Parrot_gc_sweep_pool(interp, mem_pools, pool);
-    free_pool(pool);
-
-    return 0;
-}
+    ASSERT_ARGS(pad_pool_size)
+    Memory_Block *cur_block = pool->top_block->prev;
 
-/*
+    UINTVAL total_size   = 0;
+#if RESOURCE_DEBUG
+    size_t  total_blocks = 1;
+#endif
 
-=item C<static void free_pool(Fixed_Size_Pool *pool)>
+    while (cur_block) {
+        if (!is_block_almost_full(cur_block))
+            total_size += cur_block->size - cur_block->freed - cur_block->free;
+        cur_block   = cur_block->prev;
+#if RESOURCE_DEBUG
+        ++total_blocks;
+#endif
+    }
 
-Frees a pool and all of its arenas. Loops through the list of arenas backwards
-and returns each to the memory manager. Then, frees the pool structure itself.
+    if (total_size == 0)
+        return 0;
 
-=cut
+    cur_block = pool->top_block;
+    if (!is_block_almost_full(cur_block))
+        total_size += cur_block->size - cur_block->freed - cur_block->free;
 
-*/
+    /* this makes for ever increasing allocations but fewer collect runs */
+#if WE_WANT_EVER_GROWING_ALLOCATIONS
+    total_size += pool->minimum_block_size;
+#endif
 
-static void
-free_pool(ARGFREE(Fixed_Size_Pool *pool))
-{
-    ASSERT_ARGS(free_pool)
-    Fixed_Size_Arena *cur_arena;
+#if RESOURCE_DEBUG
+    fprintf(stderr, "Total blocks: %d\n", total_blocks);
+#endif
 
-    for (cur_arena = pool->last_Arena; cur_arena;) {
-        Fixed_Size_Arena * const next = cur_arena->prev;
-        mem_internal_free(cur_arena->start_objects);
-        mem_internal_free(cur_arena);
-        cur_arena = next;
-    }
-    mem_internal_free(pool);
+    return total_size;
 }
 
-
 /*
 
-=item C<static void free_memory_pool(Variable_Size_Pool *pool)>
+=item C<static char * move_one_buffer(PARROT_INTERP, Memory_Block *pool, Buffer
+*old_buf, char *new_pool_ptr)>
 
-Frees a memory pool; helper function for C<Parrot_gc_destroy_memory_pools>.
+The compact_pool operation collects disjointed blocks of memory allocated on a
+given pool's free list into one large block of memory. Once the new larger
+memory block has been allocated, this function moves one buffer from the old
+memory block to the new memory block and marks that it has been moved.
 
 =cut
 
 */
 
-static void
-free_memory_pool(ARGFREE(Variable_Size_Pool *pool))
+PARROT_WARN_UNUSED_RESULT
+PARROT_CANNOT_RETURN_NULL
+static char *
+move_one_buffer(PARROT_INTERP, ARGIN(Memory_Block *pool),
+        ARGMOD(Buffer *old_buf), ARGMOD(char *new_pool_ptr))
 {
-    ASSERT_ARGS(free_memory_pool)
-
-    Memory_Block *cur_block = pool->top_block;
-
-    while (cur_block) {
-        Memory_Block * const next_block = cur_block->prev;
-        mem_internal_free(cur_block);
-        cur_block = next_block;
-    }
+    ASSERT_ARGS(move_one_buffer)
 
-    mem_internal_free(pool);
-}
+    INTVAL       *flags     = NULL;
+    ptrdiff_t     offset    = 0;
+    Memory_Block *old_block = NULL;
+#if RESOURCE_DEBUG
+    if (Buffer_buflen(old_buf) >= RESOURCE_DEBUG_SIZE)
+        debug_print_buf(interp, old_buf);
+#else
+    UNUSED(interp);
+#endif
 
+    /* we can't perform the math all the time, because
+        * strstart might be in unallocated memory */
+    if (PObj_is_COWable_TEST(old_buf)) {
+        flags = Buffer_bufflagsptr(old_buf);
+        old_block = Buffer_pool(old_buf);
 
-/*
+        if (PObj_is_string_TEST(old_buf)) {
+            offset = (ptrdiff_t)((STRING *)old_buf)->strstart -
+                (ptrdiff_t)Buffer_bufstart(old_buf);
+        }
+    }
 
-=item C<void Parrot_gc_destroy_memory_pools(PARROT_INTERP, Memory_Pools
-*mem_pools)>
+    /* buffer has already been moved; just change the header */
+    if (flags && (*flags & Buffer_shared_FLAG)
+              && (*flags & Buffer_moved_FLAG)) {
+        /* Find out who else references our data */
+        Buffer * const hdr = *((Buffer **)Buffer_bufstart(old_buf));
 
-Destroys the memory pool and the constant string pool. Loop through both
-pools and destroy all memory blocks contained in them. Once all the
-blocks are freed, free the pools themselves.
+        PARROT_ASSERT(PObj_is_COWable_TEST(old_buf));
 
-=cut
+        /* Make sure they know that we own it too */
+        /* Set Buffer_shared_FLAG in new buffer */
+        *Buffer_bufflagsptr(hdr) |= Buffer_shared_FLAG;
 
-*/
+        /* Now make sure we point to where the other guy does */
+        Buffer_bufstart(old_buf) = Buffer_bufstart(hdr);
 
-void
-Parrot_gc_destroy_memory_pools(SHIM_INTERP, ARGMOD(Memory_Pools *mem_pools))
-{
-    ASSERT_ARGS(Parrot_gc_destroy_memory_pools)
+        /* And if we're a string, update strstart */
+        /* Somewhat of a hack, but if we get per-pool
+            * collections, it should help ease the pain */
+        if (PObj_is_string_TEST(old_buf))
+            ((STRING *)old_buf)->strstart =
+                (char *)Buffer_bufstart(old_buf) + offset;
+    }
+    else {
+        new_pool_ptr = aligned_mem(old_buf, new_pool_ptr);
 
-    free_memory_pool(mem_pools->constant_string_pool);
-    free_memory_pool(mem_pools->memory_pool);
-}
+        /* Copy our memory to the new pool */
+        memcpy(new_pool_ptr, Buffer_bufstart(old_buf),
+                                Buffer_buflen(old_buf));
 
-/*
+        /* If we're shared */
+        if (flags && (*flags & Buffer_shared_FLAG)) {
+            PARROT_ASSERT(PObj_is_COWable_TEST(old_buf));
 
-=item C<void Parrot_gc_merge_memory_pools(Interp *dest_interp, Memory_Pools
-*dest_arena, const Memory_Pools *source_arena)>
+            /* Let the old buffer know how to find us */
+            *((Buffer **)Buffer_bufstart(old_buf)) = old_buf;
 
-Merges the header pools of C<source_interp> into those of C<dest_interp>.
-(Used to deal with shared objects left after interpreter destruction.)
+            /* Finally, let the tail know that we've moved, so
+                * that any other references can know to look for
+                * us and not re-copy */
+            *flags |= Buffer_moved_FLAG;
+        }
 
-=cut
+        Buffer_bufstart(old_buf) = new_pool_ptr;
 
-*/
+        /* Remember new pool inside */
+        *Buffer_poolptr(old_buf) = pool;
 
-void
-Parrot_gc_merge_memory_pools(ARGMOD(Interp *dest_interp),
-    ARGMOD(Memory_Pools *dest_arena),
-    ARGIN(const Memory_Pools *source_arena))
-{
-    ASSERT_ARGS(Parrot_gc_merge_memory_pools)
-
-    UINTVAL        i;
-
-    /* heavily borrowed from forall_header_pools */
-    fix_pmc_syncs(dest_interp, source_arena->constant_pmc_pool);
-    Parrot_gc_merge_buffer_pools(dest_interp, dest_arena,
-            dest_arena->constant_pmc_pool, source_arena->constant_pmc_pool);
-
-    fix_pmc_syncs(dest_interp, source_arena->pmc_pool);
-    Parrot_gc_merge_buffer_pools(dest_interp, dest_arena,
-            dest_arena->pmc_pool, source_arena->pmc_pool);
-
-    Parrot_gc_merge_buffer_pools(dest_interp, dest_arena,
-            dest_arena->constant_string_header_pool,
-            source_arena->constant_string_header_pool);
-
-    for (i = 0; i < source_arena->num_sized; ++i) {
-        if (!source_arena->sized_header_pools[i])
-            continue;
-
-        if (i >= dest_arena->num_sized
-        || !dest_arena->sized_header_pools[i]) {
-            Fixed_Size_Pool *ignored = get_bufferlike_pool(dest_interp,
-                    dest_arena, i * sizeof (void *));
-            UNUSED(ignored);
-            PARROT_ASSERT(dest_arena->sized_header_pools[i]);
-        }
+        if (PObj_is_string_TEST(old_buf))
+            ((STRING *)old_buf)->strstart =
+                    (char *)Buffer_bufstart(old_buf) + offset;
 
-        Parrot_gc_merge_buffer_pools(dest_interp, dest_arena,
-            dest_arena->sized_header_pools[i],
-            source_arena->sized_header_pools[i]);
+        new_pool_ptr += Buffer_buflen(old_buf);
     }
+
+    return new_pool_ptr;
 }
 
 /*
 
-=item C<static void Parrot_gc_merge_buffer_pools(PARROT_INTERP, Memory_Pools
-*mem_pools, Fixed_Size_Pool *dest, Fixed_Size_Pool *source)>
+=item C<static void free_old_mem_blocks( Memory_Pools *mem_pools,
+Variable_Size_Pool *pool, Memory_Block *new_block, UINTVAL total_size)>
 
-Merge pool C<source> into pool C<dest>. Combines the free lists directly,
-moves all arenas to the new pool, and remove the old pool. To merge, the
-two pools must have the same object size, and the same name (if they have
-names).
+The compact_pool operation collects disjointed blocks of memory allocated on a
+given pool's free list into one large block of memory, setting it as the new
+top block for the pool. Once that is done, and all items have been moved into
+the new block of memory, this function iterates through the old blocks and
+frees each one. It also performs the necessary housekeeping to record the
+freed memory blocks. At the end of this function, the pool will have only one
+block of memory on its free list.
 
 =cut
 
 */
 
 static void
-Parrot_gc_merge_buffer_pools(PARROT_INTERP,
+free_old_mem_blocks(
         ARGMOD(Memory_Pools *mem_pools),
-        ARGMOD(Fixed_Size_Pool *dest), ARGMOD(Fixed_Size_Pool *source))
+        ARGMOD(Variable_Size_Pool *pool),
+        ARGMOD(Memory_Block *new_block),
+        UINTVAL total_size)
 {
-    ASSERT_ARGS(Parrot_gc_merge_buffer_pools)
-    Fixed_Size_Arena  *cur_arena;
+    ASSERT_ARGS(free_old_mem_blocks)
+    Memory_Block *prev_block = new_block;
+    Memory_Block *cur_block  = new_block->prev;
 
-    PARROT_ASSERT(dest->object_size == source->object_size);
-    PARROT_ASSERT((dest->name == NULL && source->name == NULL)
-                || STREQ(dest->name, source->name));
+    PARROT_ASSERT(new_block == pool->top_block);
 
-    dest->total_objects += source->total_objects;
+    while (cur_block) {
+        Memory_Block * const next_block = cur_block->prev;
 
-    /* append new free_list to old */
-    /* XXX this won't work with, e.g., gc_gms */
-    if (dest->free_list == NULL)
-        dest->free_list = source->free_list;
-    else {
-        GC_MS_PObj_Wrapper  *free_list_end = dest->free_list;
-        while (free_list_end->next_ptr)
-            free_list_end = free_list_end->next_ptr;
+        if (is_block_almost_full(cur_block)) {
+            /* Skip block */
+            prev_block = cur_block;
+            cur_block  = next_block;
+        }
+        else {
+            /* Note that we don't have it any more */
+            mem_pools->memory_allocated -= cur_block->size;
+            mem_pools->memory_used -= cur_block->size - cur_block->free;
 
-        free_list_end->next_ptr = source->free_list;
+            /* We know the pool body and pool header are a single chunk, so
+             * this is enough to get rid of 'em both */
+            mem_internal_free(cur_block);
+            cur_block        = next_block;
+
+            /* Unlink it from list */
+            prev_block->prev = next_block;
+        }
     }
 
-    /* now append source arenas */
-    cur_arena = source->last_Arena;
+    /* Terminate list */
+    prev_block->prev = NULL;
+
+
+    /* ANR: I suspect this should be set to new_block->size, instead of passing
+     * in the raw value of total_size, because alloc_new_block pads the size of
+     * the new block under certain conditions. Leaving it unmodified for now,
+     * so this refactor has no functionality changes, only code cleanups.*/
+    pool->total_allocated        = total_size;
+    pool->guaranteed_reclaimable = 0;
+    pool->possibly_reclaimable   = 0;
+}
+
+/*
 
-    while (cur_arena) {
-        Fixed_Size_Arena * const next_arena = cur_arena->prev;
-        const size_t total_objects          = cur_arena->total_objects;
+=item C<static int is_block_almost_full(const Memory_Block *block)>
 
-        cur_arena->next = cur_arena->prev = NULL;
+Tests if the block is almost full and should be skipped during compacting.
 
-        Parrot_append_arena_in_pool(interp, mem_pools, dest, cur_arena,
-            cur_arena->total_objects);
+Returns true if less that 20% of block is available
 
-        /* XXX needed? */
-        cur_arena->total_objects = total_objects;
+=cut
 
-        cur_arena = next_arena;
-    }
+*/
 
-    /* remove things from source */
-    source->last_Arena       = NULL;
-    source->free_list        = NULL;
-    source->total_objects    = 0;
-    source->num_free_objects = 0;
+static int
+is_block_almost_full(ARGIN(const Memory_Block *block))
+{
+    ASSERT_ARGS(is_block_almost_full)
+    return 5 * (block->free + block->freed) < block->size;
 }
 
 /*
 
-=item C<static void fix_pmc_syncs(Interp *dest_interp, const Fixed_Size_Pool
-*pool)>
+=item C<static void free_memory_pool(Variable_Size_Pool *pool)>
 
-Walks through the given arena, looking for all live and shared PMCs,
-transferring their sync values to the destination interpreter.
+Frees a memory pool; helper function for C<Parrot_gc_destroy_memory_pools>.
 
 =cut
 
 */
 
 static void
-fix_pmc_syncs(ARGMOD(Interp *dest_interp), ARGIN(const Fixed_Size_Pool *pool))
+free_memory_pool(ARGFREE(Variable_Size_Pool *pool))
 {
-    ASSERT_ARGS(fix_pmc_syncs)
-    Fixed_Size_Arena *cur_arena;
-    const UINTVAL       object_size = pool->object_size;
-
-    for (cur_arena = pool->last_Arena; cur_arena; cur_arena = cur_arena->prev) {
-        PMC   *p = (PMC *)((char*)cur_arena->start_objects);
-        size_t i;
-
-        for (i = 0; i < cur_arena->used; ++i) {
-            if (!PObj_on_free_list_TEST(p) && PObj_is_PMC_TEST(p)) {
-                Parrot_ex_throw_from_c_args(dest_interp, NULL,
-                    EXCEPTION_INTERP_ERROR,
-                    "Unshared PMC still alive after interpreter"
-                    "destruction. address=%p, base_type=%d\n",
-                    p, p->vtable->base_type);
-            }
+    ASSERT_ARGS(free_memory_pool)
 
-            p = (PMC *)((char *)p + object_size);
-        }
+    Memory_Block *cur_block = pool->top_block;
+
+    while (cur_block) {
+        Memory_Block * const next_block = cur_block->prev;
+        mem_internal_free(cur_block);
+        cur_block = next_block;
     }
-}
 
+    mem_internal_free(pool);
+}
 
 /*
 
@@ -1473,6 +1203,7 @@
 =head1 SEE ALSO
 
 F<src/gc/memory.c>.
+F<src/gc/alloc_resources.c>.
 
 =cut
 


More information about the parrot-commits mailing list