.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;