.sub main :main loop: $P0 = new .String goto loop .end This one's fun.
One punchline's in src/gc/resources.c:153, within mem_allocate(). If it looks like there's no reclaimable memory within the allocated arena pools, there's no sense in compacting them to try to get enough memory to fulfill the current request. I'm not sure why that is. Of course, this test always allocates a new string (of size zero) from Parrot_allocate_string() in src/gc/resources.c:738. For some reason, this nibbles away at the buffers but prevents any compaction. This code looks suspicious to me: new_size = aligned_string_size(str, size); mem = (char *)mem_allocate(interp, new_size, pool); mem += sizeof (void*); PObj_bufstart(str) = str->strstart = mem; PObj_buflen(str) = new_size - sizeof (void*); If size is 0 and new_size gets aligned to 4 and (void *) is 4 bytes long, then the buflen will be 0. That may not be good at all, especially looking at compact_pool() in src/gc/resources.c:334. With a buflen of 0, the buffer's not copyable. My conjecture is that if you fill up a memory pool with buffers that have the 4-byte overhead but no actual buffer lengths, you get pools that appear uncompactable, and you have to allocate more and more new pools. Here's my solution; don't allocate zero-sized buffers. Let them be empty. All tests pass. This either means that this is the right solution or that we don't have enough tests of the String PMC. --c
=== src/gc/resources.c ================================================================== --- src/gc/resources.c (revision 3282) +++ src/gc/resources.c (local) @@ -744,6 +744,9 @@ PObj_buflen(str) = 0; PObj_bufstart(str) = NULL; + if (size == 0) + return; + pool = PObj_constant_TEST(str) ? interp->arena_base->constant_string_pool : interp->arena_base->memory_pool;