As requested, I wrote a nasty little recursive program to test strings, memory and call stacks. Immediately bad stuff happened when the stack frames outgrew a single chunk and a new one was allocated. When the frame stack reached FRAMES_PER_CHUNK, the new chunk gets allocated, etc, etc. and bad stuff happened after a pop*.
I traced it down to push* copying the register frame onto the previous stack chunk, not the new stack chunk. The following patch fixes, I went ahead and committed because seg faults are bad. :) Afterwards the test program ran with larger file sizes, eventually crashing again, but this time in the GC. <*PUNT* Dan goes back to the 10 yard line.....> ../parrot reverse.pbc < string.c <file prints out pre-reverse call> recurse depth 0 Segmentation fault (core dumped) :) So the nasty test prog has done its duty for tonite, putting it to bed. Patch follows, then the test program. Index: register.c =================================================================== RCS file: /cvs/public/parrot/register.c,v retrieving revision 1.19 diff -u -r1.19 register.c --- register.c 5 Mar 2002 05:30:17 -0000 1.19 +++ register.c 26 Mar 2002 07:30:10 -0000 @@ -30,7 +30,7 @@ else { struct IRegChunk *new_chunk; new_chunk = mem_sys_allocate(sizeof(struct IRegChunk)); - memcpy(&interpreter->int_reg_top->IReg[0], + memcpy(&new_chunk->IReg[0], &interpreter->int_reg, sizeof(struct IReg)); new_chunk->used = 1; new_chunk->free = FRAMES_PER_INT_REG_CHUNK - 1; @@ -101,7 +101,7 @@ else { struct SRegChunk *new_chunk; new_chunk = mem_sys_allocate(sizeof(struct SRegChunk)); - memcpy(&interpreter->string_reg_top->SReg[0], + memcpy(&new_chunk->SReg[0], &interpreter->string_reg, sizeof(struct SReg)); new_chunk->used = 1; new_chunk->free = FRAMES_PER_STR_REG_CHUNK - 1; @@ -171,7 +171,7 @@ else { struct NRegChunk *new_chunk; new_chunk = mem_sys_allocate(sizeof(struct NRegChunk)); - memcpy(&interpreter->num_reg_top->NReg[0], + memcpy(&new_chunk->NReg[0], &interpreter->num_reg, sizeof(struct NReg)); new_chunk->used = 1; new_chunk->free = FRAMES_PER_NUM_REG_CHUNK - 1; @@ -241,7 +241,7 @@ else { struct PRegChunk *new_chunk; new_chunk = mem_sys_allocate(sizeof(struct PRegChunk)); - memcpy(&interpreter->pmc_reg_top->PReg[0], + memcpy(&new_chunk->PReg[0], &interpreter->pmc_reg, sizeof(struct PReg)); new_chunk->used = 1; new_chunk->free = FRAMES_PER_PMC_REG_CHUNK - 1; reverse.cola (slurps in a file, then recursively swaps string 1/2s until whole buffer is reversed, then prints). Works ok on files up to 20k, then barfs with the stack trace at the end. // reverse.cola // // Reverse an input string recursively swapping. // Give it a bigger file to make the GC grind and the // call stack grow. :) // using System; public class Reverse { // Recursively reverse string halves until halves are length 1 public string Reverse(string s1, string s2, int d) { int len = strlen(s1); puts("recurse depth "); puti(d); puts("\n"); if(len > 1) s1 = Reverse(substr(s1, 0, len/2), substr(s1, len/2, len-len/2), d + 1); len = strlen(s2); if(len > 1) s2 = Reverse(substr(s2, 0, len/2), substr(s2, len/2, len-len/2), d + 1); //puts("(" + s1 + ")(" + s2 + ")\n"); return s2 + s1; } public static void Main() { string str, bstr; while(1) { bstr = gets(); if(bstr == "") break; puts(bstr); str = str + bstr; } //puts(bstr); // Reverse it with recursion puts("\n"); // Reverse the 2 halves str = Reverse(str, "", 0); puts(str); } } ***Stack trace*** (gdb) back #0 0x4012efef in memcpy (dstpp=0x402ae750, srcpp=0x40255dc0, len=15872) at ../sysdeps/generic/memcpy.c:55 #1 0x0809311f in Parrot_go_collect (interpreter=0x8170d78) at resources.c:738 #2 0x080933bf in Parrot_allocate (interpreter=0x8170d78, size=11456) at resources.c:848 #3 0x0808e6c5 in Parrot_string_make (interpreter=0x8170d78, buffer=0x0, buflen=11449, encoding=0x80aefc0, flags=0, type=0x80af388) at string.c:50 #4 0x0808ef4d in Parrot_string_substr (interpreter=0x8170d78, src=0x818cf50, offset=0, length=11449, d=0x8170f70) at string.c:396 #5 0x0805466d in Parrot_substr_s_s_i_i (cur_opcode=0x818db4c, interpreter=0x8170d78) at core.ops:1539 #6 0x0808fb5f in runops_fast_core (interpreter=0x8170d78, pc=0x818db4c) at runops_cores.c:30 #7 0x0804940e in runops_generic (core=0x808fb30 <runops_fast_core>, interpreter=0x8170d78, pc=0x818d768) at interpreter.c:77 #8 0x08049cc5 in runops (interpreter=0x8170d78, code=0x818d6d8, offset=0) at interpreter.c:463 #9 0x08093ff6 in Parrot_runcode (interpreter=0x8170d78, argc=1, argv=0xbffffb18) at embed.c:213 #10 0x080a08de in main (argc=1, argv=0xbffffb18) at test_main.c:48 #11 0x400c7306 in __libc_start_main (main=0x80a084c <main>, argc=2, ubp_av=0xbffffb14, init=0x8048dc4 <_init>, fini=0x80a0b70 <_fini>, rtld_fini=0x4000d2cc <_dl_fini>, stack_end=0xbffffb0c) at ../sysdeps/generic/libc-start.c:129 (gdb) -Melvin