Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion Continuations now close over register stacks
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Luke Palmer  
View profile  
 More options Jan 7 2004, 10:48 pm
Newsgroups: perl.perl6.internals
From: fibon...@babylonia.flatirons.org (Luke Palmer)
Date: Wed, 7 Jan 2004 20:10:30 -0700
Local: Wed, Jan 7 2004 10:10 pm
Subject: [PATCH] Continuations now close over register stacks
This patch re-implements the register backing stacks as PObjs (so they
can be garbage-collected), honors their COW flags, and adds them to the
interpreter context (where they should be, honest!).

As a healthy side-effect, it encapsulates their behavior nicely into
register.c, when before their guts were splattered all over the source.

Luke

Index: classes/continuation.pmc
===================================================================
RCS file: /cvs/public/parrot/classes/continuation.pmc,v
retrieving revision 1.17
diff -u -r1.17 continuation.pmc
--- classes/continuation.pmc    19 Dec 2003 10:01:36 -0000      1.17
+++ classes/continuation.pmc    8 Jan 2004 03:04:01 -0000
@@ -26,8 +26,7 @@
     void mark () {
         struct Parrot_Sub * cc
             = (struct Parrot_Sub*)PMC_sub(SELF);
-       mark_stack(INTERP, cc->ctx.user_stack);
-       mark_stack(INTERP, cc->ctx.control_stack);
+        mark_context(INTERP, &cc->ctx);
        SUPER();        /* mark pad_stack, warns in closure */
     }

Index: imcc/t/syn/pcc.t
===================================================================
RCS file: /cvs/public/parrot/imcc/t/syn/pcc.t,v
retrieving revision 1.28
diff -u -r1.28 pcc.t
--- imcc/t/syn/pcc.t    16 Dec 2003 08:53:44 -0000      1.28
+++ imcc/t/syn/pcc.t    8 Jan 2004 03:04:01 -0000
@@ -738,7 +738,7 @@
 .pcc_sub _sub1 non_prototyped
     .local pmc res1               # (visitReturn:528)
     find_lex $P2, 'g'             # (callingExpression:325)
-    newsub $P3, .Continuation, ret0 # (callingExpression:331)
+    newsub $P3, .RetContinuation, ret0 # (callingExpression:331)
     .pcc_begin non_prototyped     # (callingExpression:332)
     .pcc_call $P2, $P3            # (callingExpression:335)
 ret0:
Index: include/parrot/interpreter.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/interpreter.h,v
retrieving revision 1.114
diff -u -r1.114 interpreter.h
--- include/parrot/interpreter.h        2 Jan 2004 14:09:32 -0000       1.114
+++ include/parrot/interpreter.h        8 Jan 2004 03:04:01 -0000
@@ -125,12 +125,10 @@
 struct _imc_info_t;

 typedef struct Parrot_Context {
-    struct IRegChunk *int_reg_top;    /* Current top chunk of int reg stack */
-    struct NRegChunk *num_reg_top;    /* Current top chunk of the float reg
-                                       * stack */
-    struct SRegChunk *string_reg_top; /* Current top chunk of the string
-                                       * stack */
-    struct PRegChunk *pmc_reg_top;    /* Current top chunk of the PMC stack */
+    struct RegStack int_reg_stack;
+    struct RegStack num_reg_stack;
+    struct RegStack string_reg_stack;
+    struct RegStack pmc_reg_stack;

     struct Stack_Chunk *pad_stack;      /* Base of the lex pad stack */
     struct Stack_Chunk *user_stack;     /* Base of the scratch stack */
Index: include/parrot/register.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/register.h,v
retrieving revision 1.17
diff -u -r1.17 register.h
--- include/parrot/register.h   21 Jul 2003 18:00:42 -0000      1.17
+++ include/parrot/register.h   8 Jan 2004 03:04:01 -0000
@@ -48,38 +48,43 @@
     PMC *registers[NUM_REGISTERS/2];
 };

-struct IRegChunk {
+struct RegStack {
+    struct RegisterChunkBuf* top;
+    size_t chunk_size;
+};
+
+/* Base class for the RegChunk types */
+struct RegisterChunkBuf {
+    Buffer data;
     size_t used;
-    Stack_chunk_flags flags;
-    struct IRegChunk *next;
-    struct IRegChunk *prev;
+    struct RegisterChunkBuf* next;
+};
+
+struct IRegChunkBuf {
     struct IRegFrame IRegFrame[FRAMES_PER_CHUNK];
 };

-struct NRegChunk {
-    size_t used;
-    Stack_chunk_flags flags;
-    struct NRegChunk *next;
-    struct NRegChunk *prev;
+struct NRegChunkBuf {
     struct NRegFrame NRegFrame[FRAMES_PER_CHUNK];
 };

-struct SRegChunk {
-    size_t used;
-    Stack_chunk_flags flags;
-    struct SRegChunk *next;
-    struct SRegChunk *prev;
+struct SRegChunkBuf {
     struct SRegFrame SRegFrame[FRAMES_PER_CHUNK];
 };

-struct PRegChunk {
-    size_t used;
-    Stack_chunk_flags flags;
-    struct PRegChunk *next;
-    struct PRegChunk *prev;
+struct PRegChunkBuf {
     struct PRegFrame PRegFrame[FRAMES_PER_CHUNK];
 };

+void setup_register_stacks(struct Parrot_Interp* interpreter);
+void mark_register_stack_cow(struct Parrot_Interp* interpreter,
+                             struct RegStack* stack);
+void mark_pmc_register_stack(struct Parrot_Interp* interpreter,
+                             struct RegStack* stack);
+void mark_string_register_stack(struct Parrot_Interp* interpreter,
+                                struct RegStack* stack);
+void mark_register_stack(struct Parrot_Interp* interpreter,
+                         struct RegStack* stack);

 #endif /* PARROT_REGISTER_H */

Index: include/parrot/sub.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/sub.h,v
retrieving revision 1.25
diff -u -r1.25 sub.h
--- include/parrot/sub.h        2 Oct 2003 07:41:55 -0000       1.25
+++ include/parrot/sub.h        8 Jan 2004 03:04:01 -0000
@@ -59,6 +59,7 @@
 void cow_copy_context(struct Parrot_Interp* , struct Parrot_Context *);
 void swap_context(struct Parrot_Interp *, PMC *);
 void restore_context(struct Parrot_Interp *, struct Parrot_Context *);
+void mark_context(struct Parrot_Interp *, struct Parrot_Context *);

 PMC * scratchpad_new(struct Parrot_Interp * interp, PMC * base, INTVAL depth);

Index: src/debug.c
===================================================================
RCS file: /cvs/public/parrot/src/debug.c,v
retrieving revision 1.117
diff -u -r1.117 debug.c
--- src/debug.c 5 Jan 2004 14:44:52 -0000       1.117
+++ src/debug.c 8 Jan 2004 03:04:02 -0000
@@ -1808,9 +1808,10 @@
 PDB_print_stack_int(struct Parrot_Interp *interpreter, const char *command)
 {
     unsigned long depth = 0, i = 0;
-    struct IRegChunk *chunk = interpreter->ctx.int_reg_top;
+    struct RegisterChunkBuf *chunk = interpreter->ctx.int_reg_stack.top;

-    valid_chunk(chunk, command, depth, FRAMES_PER_INT_REG_CHUNK, i);
+    valid_chunk(chunk, command, depth,
+                FRAMES_PER_INT_REG_CHUNK, i);

     if (!chunk) {
         i = depth / FRAMES_PER_INT_REG_CHUNK;
@@ -1822,8 +1823,9 @@
                 i, depth);

     na(command);
-    PDB_print_int_frame(interpreter, &chunk->IRegFrame[depth],
-            atoi(command));
+    PDB_print_int_frame(interpreter,
+                &((struct IRegChunkBuf*)chunk->data.bufstart)->IRegFrame[depth],
+                atoi(command));
 }

 /* PDB_print_stack_num
@@ -1833,9 +1835,10 @@
 PDB_print_stack_num(struct Parrot_Interp *interpreter, const char *command)
 {
     unsigned long depth = 0, i = 0;
-    struct NRegChunk *chunk = interpreter->ctx.num_reg_top;
+    struct RegisterChunkBuf *chunk = interpreter->ctx.num_reg_stack.top;

-    valid_chunk(chunk, command, depth, FRAMES_PER_NUM_REG_CHUNK, i);
+    valid_chunk(chunk, command, depth,
+                FRAMES_PER_NUM_REG_CHUNK, i);

     if (!chunk) {
         i = depth / FRAMES_PER_NUM_REG_CHUNK;
@@ -1846,8 +1849,9 @@
     PIO_eprintf(interpreter, "Float stack, frame %li, depth %li\n", i, depth);

     na(command);
-    PDB_print_num_frame(interpreter, &chunk->NRegFrame[depth],
-            atoi(command));
+    PDB_print_num_frame(interpreter,
+                &((struct NRegChunkBuf*)chunk->data.bufstart)->NRegFrame[depth],
+                atoi(command));
 }

 /* PDB_print_stack_string
@@ -1857,9 +1861,10 @@
 PDB_print_stack_string(struct Parrot_Interp *interpreter, const char *command)
 {
     unsigned long depth = 0, i = 0;
-    struct SRegChunk *chunk = interpreter->ctx.string_reg_top;
+    struct RegisterChunkBuf *chunk = interpreter->ctx.string_reg_stack.top;

-    valid_chunk(chunk, command, depth, FRAMES_PER_STR_REG_CHUNK, i);
+    valid_chunk(chunk, command, depth,
+                FRAMES_PER_STR_REG_CHUNK, i);

     if (!chunk) {
         i = depth / FRAMES_PER_STR_REG_CHUNK;
@@ -1871,8 +1876,9 @@
                 i, depth);

     na(command);
-    PDB_print_string_frame(interpreter, &chunk->SRegFrame[depth],
-            atoi(command));
+    PDB_print_string_frame(interpreter,
+                &((struct SRegChunkBuf*)chunk->data.bufstart)->SRegFrame[depth],
+                atoi(command));
 }

 /* PDB_print_stack_pmc
@@ -1882,9 +1888,10 @@
 PDB_print_stack_pmc(struct Parrot_Interp *interpreter, const char *command)
 {
     unsigned long depth = 0, i = 0;
-    struct PRegChunk *chunk = interpreter->ctx.pmc_reg_top;
+    struct RegisterChunkBuf *chunk = interpreter->ctx.pmc_reg_stack.top;

-    valid_chunk(chunk, command, depth, FRAMES_PER_PMC_REG_CHUNK, i);
+    valid_chunk(chunk, command, depth,
+                FRAMES_PER_PMC_REG_CHUNK, i);

     if (!chunk) {
         i = depth / FRAMES_PER_PMC_REG_CHUNK;
@@ -1895,8 +1902,9 @@
     PIO_eprintf(interpreter, "PMC stack, frame %li, depth %li\n", i, depth);

     na(command);
-    PDB_print_pmc_frame(interpreter, &chunk->PRegFrame[depth],
-            atoi(command), NULL);
+    PDB_print_pmc_frame(interpreter,
+                &((struct PRegChunkBuf*)chunk->data.bufstart)->PRegFrame[depth],
+                atoi(command), NULL);
 }

 static void
Index: src/dod.c
===================================================================
RCS file: /cvs/public/parrot/src/dod.c,v
retrieving revision 1.78
diff -u -r1.78 dod.c
--- src/dod.c   2 Jan 2004 14:09:38 -0000       1.78
+++ src/dod.c   8 Jan 2004 03:04:02 -0000
@@ -130,7 +130,6 @@
      * note: adding locals here did cause increased DOD runs
      */
     unsigned int i = 0, j = 0;
-    struct PRegChunk *cur_chunk = 0;
     struct Stash *stash = 0;

     /* We have to start somewhere, the interpreter globals is a good place */
@@ -162,31 +161,8 @@
     if (interpreter->DOD_registry)
         pobject_lives(interpreter, (PObj *)interpreter->DOD_registry);

-    /* Now walk the pmc stack. Make sure to walk from top down since stack may
-     * have segments above top that we shouldn't walk. */
-    for (cur_chunk = interpreter->ctx.pmc_reg_top; cur_chunk;
-            cur_chunk = cur_chunk->prev) {
-        for (j = 0; j < cur_chunk->used; j++) {
-            for (i = 0; i < NUM_REGISTERS/2; i++) {
-                if (cur_chunk->PRegFrame[j].registers[i]) {
-                    pobject_lives(interpreter,
-                            (PObj *)cur_chunk->PRegFrame[j].registers[i]);
-                }
-            }
-        }
-    }
-
-    /* Walk all stacks: lexical pad, user and control */
-    {
-        Stack_Chunk_t *stacks[3];
-
-        stacks[0] = interpreter->ctx.pad_stack;
-        stacks[1] = interpreter->ctx.user_stack;
-        stacks[2] = interpreter->ctx.control_stack;
-        for (j = 0; j < 3; j++)
-            mark_stack(interpreter, stacks[j]);
-
-    }
+    /* Walk all stacks */
+    mark_context(interpreter, &interpreter->ctx);

     /* Walk the iodata */
     Parrot_IOData_mark(interpreter, interpreter->piodata);
@@ -262,7 +238,6 @@
 trace_active_buffers(struct Parrot_Interp *interpreter)
 {
     UINTVAL i, j;
-    struct SRegChunk *cur_chunk;

     /* First mark the current set. We assume that all pointers in S registers
      * are pointing to valid buffers. This is not a good assumption, but it'll
@@ -279,20 +254,6 @@
         pobject_lives(interpreter, (PObj *)interpreter->current_file);
     if (interpreter->current_package)
         pobject_lives(interpreter, (PObj *)interpreter->current_package);
-
-    /* Now walk the string stack. Make sure to walk from top down since stack
-     * may have segments above top that we shouldn't walk. */
-    for (cur_chunk = interpreter->ctx.string_reg_top;
-            cur_chunk; cur_chunk = cur_chunk->prev) {
-        for (j = 0; j < cur_chunk->used; j++) {
-            for (i = 0; i < NUM_REGISTERS/2; i++) {
-                Buffer *reg = (Buffer *)cur_chunk->SRegFrame[j].registers[i];
-
-                if (reg)
-                    pobject_lives(interpreter, reg);
-            }
-        }
-    }
 }

 #ifdef GC_IS_MALLOC
Index: src/interpreter.c
===================================================================
RCS file: /cvs/public/parrot/src/interpreter.c,v
retrieving revision 1.252
diff -u -r1.252 interpreter.c
--- src/interpreter.c   2 Jan 2004 14:09:38 -0000       1.252
+++ src/interpreter.c   8 Jan 2004 03:04:02 -0000
@@ -995,14 +995,7 @@
     PARROT_WARNINGS_off(interpreter, PARROT_WARNINGS_ALL_FLAG);

     /* Set up the initial register chunks */
-    interpreter->ctx.int_reg_top =
-        mem_sys_allocate_zeroed(sizeof(struct IRegChunk));
-    interpreter->ctx.num_reg_top =
-        mem_sys_allocate_zeroed(sizeof(struct NRegChunk));
-    interpreter->ctx.string_reg_top =
-        mem_sys_allocate_zeroed(sizeof(struct SRegChunk));
-    interpreter->ctx.pmc_reg_top =
-        mem_sys_allocate_zeroed(sizeof(struct PRegChunk));
+    setup_register_stacks(interpreter);

     /* the SET_NULL macros are only for systems where a NULL pointer
      * isn't represented by zeroes, so don't use these for resetting
@@ -1172,24 +1165,6 @@

     /* deinit op_lib */
     (void) PARROT_CORE_OPLIB_INIT(0);
-
-    /* XXX move this to register.c */
-    {
-        struct IRegChunk *stacks[4];
-        struct IRegChunk *top, *next;
-        stacks[0] = interpreter->ctx.int_reg_top;
-        stacks[1] = (struct IRegChunk*) interpreter->ctx.num_reg_top;
-        stacks[2] = (struct IRegChunk*) interpreter->ctx.string_reg_top;
-        stacks[3] = (struct IRegChunk*) interpreter->ctx.pmc_reg_top;
-        for (i = 0; i< 4; i++) {
-            top = stacks[i];
-            for (; top ; ) {
-                next = top->next;
-                mem_sys_free(top);
-                top = next;
-            }
-        }
-    }

     stack_destroy(interpreter->ctx.pad_stack);
     stack_destroy(interpreter->ctx.user_stack);
Index: src/register.c
===================================================================
RCS file: /cvs/public/parrot/src/register.c,v
retrieving revision 1.34
diff -u -r1.34 register.c
--- src/register.c      28 Oct 2003 03:13:06 -0000      1.34
+++ src/register.c      8 Jan 2004 03:04:02 -0000
@@ -12,62 +12,187 @@

 #include "parrot/parrot.h"

-/*=for api register Parrot_push_i
-  pushes a new integer register frame onto the corresponding frame stack
-*/
 void
-Parrot_push_i(struct Parrot_Interp *interpreter, void *where)
+setup_register_stacks(struct Parrot_Interp* interpreter)
+{
+    struct RegisterChunkBuf* buf;
+    make_bufferlike_pool(interpreter, sizeof(struct RegisterChunkBuf));
+
+    Parrot_block_DOD(interpreter);
+
+    buf = new_bufferlike_header(interpreter, sizeof(struct RegisterChunkBuf));
+    Parrot_allocate_zeroed(interpreter, (PObj*)buf, sizeof(struct IRegChunkBuf));
+    interpreter->ctx.int_reg_stack.top = buf;
+    interpreter->ctx.int_reg_stack.chunk_size = sizeof(struct IRegChunkBuf);
+    
+    buf = new_bufferlike_header(interpreter, sizeof(struct RegisterChunkBuf));
+    Parrot_allocate_zeroed(interpreter, (PObj*)buf, sizeof(struct SRegChunkBuf));
+    interpreter->ctx.string_reg_stack.top = buf;
+    interpreter->ctx.string_reg_stack.chunk_size = sizeof(struct SRegChunkBuf);
+    
+    buf = new_bufferlike_header(interpreter, sizeof(struct RegisterChunkBuf));
+    Parrot_allocate_zeroed(interpreter, (PObj*)buf, sizeof(struct NRegChunkBuf));
+    interpreter->ctx.num_reg_stack.top = buf;
+    interpreter->ctx.num_reg_stack.chunk_size = sizeof(struct NRegChunkBuf);
+    
+    buf = new_bufferlike_header(interpreter, sizeof(struct RegisterChunkBuf));
+    Parrot_allocate_zeroed(interpreter, (PObj*)buf, sizeof(struct PRegChunkBuf));
+    interpreter->ctx.pmc_reg_stack.top = buf;
+    interpreter->ctx.pmc_reg_stack.chunk_size = sizeof(struct PRegChunkBuf);
+    
+    Parrot_unblock_DOD(interpreter);
+}
+
+void
+mark_register_stack(struct Parrot_Interp* interpreter, struct RegStack* stack)
+{
+    struct RegisterChunkBuf* chunk;
+    for (chunk = stack->top; chunk; chunk = chunk->next) {
+        pobject_lives(interpreter, (PObj*)chunk);
+    }
+}
+
+void
+mark_pmc_register_stack(struct Parrot_Interp* interpreter, struct RegStack* stack)
+{
+    struct RegisterChunkBuf* chunk;
+    UINTVAL i, j;
+    for (chunk = stack->top; chunk;
+        chunk = chunk->next) {
+        pobject_lives(interpreter, (PObj*)chunk);
+        for (i = 0; i < chunk->used; i++) {
+            for (j = 0; j < NUM_REGISTERS/2; j++) {
+                if (((struct PRegChunkBuf*)chunk->data.bufstart)->PRegFrame[i].registers[j]) {
+                    pobject_lives(interpreter,
+                            (PObj*)((struct PRegChunkBuf*)chunk->data.bufstart)->
+                                PRegFrame[i].registers[j]);
+                }
+            }
+        }
+    }
+}
+
+void
+mark_string_register_stack(struct Parrot_Interp* interpreter, struct RegStack* stack)
+{
+    struct RegisterChunkBuf* chunk;
+    UINTVAL i, j;
+    for (chunk = stack->top; chunk; chunk = chunk->next) {
+        pobject_lives(interpreter, (PObj*)chunk);
+        for (i = 0; i < chunk->used; i++) {
+            for (j = 0; j < NUM_REGISTERS/2; j++) {
+                PObj* reg = (PObj*)((struct SRegChunkBuf*)chunk->data.bufstart)->
+                    SRegFrame[i].registers[j];
+                if (reg)
+                    pobject_lives(interpreter, reg);
+            }
+        }
+    }
+}
+
+void
+mark_register_stack_cow(struct Parrot_Interp* interpreter, struct RegStack* stack)
+{
+    struct RegisterChunkBuf* chunk;
+    for (chunk = stack->top; chunk; chunk = chunk->next) {
+        PObj_COW_SET((PObj*)chunk);
+    }
+}
+
+static struct RegisterChunkBuf*
+regstack_copy_chunk(struct Parrot_Interp* interpreter,
+                    struct RegisterChunkBuf* chunk,
+                    struct RegStack* stack)
+{
+    struct RegisterChunkBuf* buf =
+            new_bufferlike_header(interpreter, sizeof(struct RegisterChunkBuf));
+    *buf = *chunk;
+    
+    Parrot_block_DOD(interpreter);
+    Parrot_allocate_zeroed(interpreter, (PObj*)buf, stack->chunk_size);
+    Parrot_unblock_DOD(interpreter);
+    
+    memcpy(buf->data.bufstart, chunk->data.bufstart, stack->chunk_size);
+    return buf;
+}
+
+static void
+regstack_push_entry(struct Parrot_Interp* interpreter, struct RegStack* stack)
 {
-    /* Do we have any space in the current savestack? If so, memcpy
-     * down */
-    if (interpreter->ctx.int_reg_top->used < FRAMES_PER_CHUNK) {
-        memcpy(&interpreter->ctx.int_reg_top->
-               IRegFrame[interpreter->ctx.int_reg_top->used],
-               where, sizeof(struct IRegFrame));
-        interpreter->ctx.int_reg_top->used++;
+    struct RegisterChunkBuf* top = stack->top;
+    /* Before we change anything, is this a read-only stack? */
+    if (PObj_COW_TEST((PObj*)top))
+        top = stack->top = regstack_copy_chunk(interpreter, top, stack);
+    /* If we can stay in the current frame, we will.  Else make a new chunk */
+    if (top->used < FRAMES_PER_CHUNK) {
+        top->used++;
     }
-    /* Nope, so either move to next stack chunk or grow the stack */
     else {
-        struct IRegChunk *next_chunk;
-        if (interpreter->ctx.int_reg_top->next)
-            next_chunk = interpreter->ctx.int_reg_top->next;
+        struct RegisterChunkBuf* buf = new_bufferlike_header(interpreter,
+                                sizeof(struct RegisterChunkBuf));
+
+        Parrot_block_DOD(interpreter);
+        Parrot_allocate_zeroed(interpreter, (PObj*)buf, stack->chunk_size);
+        Parrot_unblock_DOD(interpreter);
+        
+        buf->used = 1;
+        buf->next = top;
+
+        stack->top = buf;
+    }
+}
+
+static void
+regstack_pop_entry(struct Parrot_Interp* interpreter, struct RegStack* stack)
+{
+    struct RegisterChunkBuf* top = stack->top;
+    if (top->used > 1) {
+        /* Before we change anything, is this a read-only stack? */
+        if (PObj_COW_TEST((PObj*)top))
+            top = stack->top = regstack_copy_chunk(interpreter, stack->top, stack);
+        top->used--;
+    }
+    else {
+        /* XXX: If this isn't marked COW, we should keep it around to
+         * prevent thrashing */
+        if (top->next) {
+            stack->top = top->next;
+        }
         else {
-            next_chunk = mem_sys_allocate(sizeof(struct IRegChunk));
-            next_chunk->next = NULL;
-            next_chunk->prev = interpreter->ctx.int_reg_top;
-            interpreter->ctx.int_reg_top->next = next_chunk;
+            if (PObj_COW_TEST((PObj*)top))
+                top = stack->top = regstack_copy_chunk(interpreter, stack->top, stack);
+            top->used--;
         }
-        next_chunk->used = 1;
-        interpreter->ctx.int_reg_top = next_chunk;
-        memcpy(&next_chunk->IRegFrame[0],
-               where, sizeof(struct IRegFrame));
     }
 }

+/*=for api register Parrot_push_i
+  pushes a new integer register frame onto the corresponding frame stack
+*/
+void
+Parrot_push_i(struct Parrot_Interp *interpreter, void *where)
+{    
+    struct RegisterChunkBuf* top;
+    regstack_push_entry(interpreter, &interpreter->ctx.int_reg_stack);
+    top = interpreter->ctx.int_reg_stack.top;
+    memcpy(&((struct IRegChunkBuf*)top->data.bufstart)->
+                    IRegFrame[top->used-1].registers,
+           where, sizeof(struct IRegFrame));
+}
+
 /*=for api register Parrot_pop_i
   pops an integer register frame from the corresponding frame stack
 */
 void
 Parrot_pop_i(struct Parrot_Interp *interpreter, void *where)
 {
-    struct IRegChunk *top = interpreter->ctx.int_reg_top;
+    struct RegisterChunkBuf* top = interpreter->ctx.int_reg_stack.top;
     /* Do we even have anything? */
     if (top->used > 0) {
-        top->used--;
-        memcpy(where,
-               &top->IRegFrame[top->used], sizeof(struct IRegFrame));
-        /* Empty? */
-        if (!top->used) {
-            /* Yep, drop down a frame. Maybe */
-            if (top->prev) {
-                /* Keep one stack segment spare to avoid thrashing */
-                if (top->next) {
-                    mem_sys_free(top->next);
-                    top->next = NULL;
-                }
-                interpreter->ctx.int_reg_top = top->prev;
-            }
-        }
+        memcpy(where,
+               &((struct IRegChunkBuf*)top->data.bufstart)->IRegFrame[top->used-1],
+               sizeof(struct IRegFrame));
+        regstack_pop_entry(interpreter, &interpreter->ctx.int_reg_stack);
     }
     /* Nope. So pitch a fit */
     else {
@@ -92,31 +217,13 @@
 */
 void
 Parrot_push_s(struct Parrot_Interp *interpreter, void *where)
-{
-    /* Do we have any space in the current savestack? If so, memcpy
-     * down */
-    if (interpreter->ctx.string_reg_top->used < FRAMES_PER_CHUNK) {
-        memcpy(&interpreter->ctx.string_reg_top->
-               SRegFrame[interpreter->ctx.string_reg_top->used],
-               where, sizeof(struct SRegFrame));
-        interpreter->ctx.string_reg_top->used++;
-    }
-    /* Nope, so either move to next stack chunk or grow the stack */
-    else {
-        struct SRegChunk *next_chunk;
-        if (interpreter->ctx.string_reg_top->next)
-            next_chunk = interpreter->ctx.string_reg_top->next;
-        else {
-            next_chunk = mem_sys_allocate(sizeof(struct SRegChunk));
-            next_chunk->next = NULL;
-            next_chunk->prev = interpreter->ctx.string_reg_top;
-            interpreter->ctx.string_reg_top->next = next_chunk;
-        }
-        next_chunk->used = 1;
-        interpreter->ctx.string_reg_top = next_chunk;
-        memcpy(&next_chunk->SRegFrame[0],
-               where, sizeof(struct SRegFrame));
-    }
+{    
+    struct RegisterChunkBuf* top;
+    regstack_push_entry(interpreter, &interpreter->ctx.string_reg_stack);
+    top = interpreter->ctx.string_reg_stack.top;
+    memcpy(&((struct SRegChunkBuf*)top->data.bufstart)->
+                    SRegFrame[top->used-1].registers,
+           where, sizeof(struct SRegFrame));
 }

 /*=for api register Parrot_pop_s
@@ -125,24 +232,15 @@
 void
 Parrot_pop_s(struct Parrot_Interp *interpreter, void *where)
 {
-    struct SRegChunk *top = interpreter->ctx.string_reg_top;
+    struct RegisterChunkBuf* top = interpreter->ctx.string_reg_stack.top;
     /* Do we even have anything? */
     if (top->used > 0) {
-        top->used--;
-        memcpy(where,
-               &top->SRegFrame[top->used], sizeof(struct SRegFrame));
-        /* Empty? */
-        if (!top->used) {
-            /* Yep, drop down a frame. Maybe */
-            if (top->prev) {
-                /* Keep one stack segment spare to avoid thrashing */
-                if (top->next) {
-                    mem_sys_free(top->next);
-                    top->next = NULL;
-                }
-                interpreter->ctx.string_reg_top = top->prev;
-            }
-        }
+        struct SRegFrame* irf = &((struct SRegChunkBuf*)top->data.bufstart)->
+                    SRegFrame[top->used-1];
+        memcpy(where,
+               &irf->registers,
+               sizeof(struct SRegFrame));
+        regstack_pop_entry(interpreter, &interpreter->ctx.string_reg_stack);
     }
     /* Nope. So pitch a fit */
     else {
@@ -167,31 +265,13 @@
 */
 void
 Parrot_push_n(struct Parrot_Interp *interpreter, void *where)
-{
-    /* Do we have any space in the current savestack? If so, memcpy
-     * down */
-    if (interpreter->ctx.num_reg_top->used < FRAMES_PER_CHUNK) {
-        memcpy(&interpreter->ctx.num_reg_top->
-               NRegFrame[interpreter->ctx.num_reg_top->used],
-               where, sizeof(struct NRegFrame));
-        interpreter->ctx.num_reg_top->used++;
-    }
-    /* Nope, so either move to next stack chunk or grow the stack */
-    else {
-        struct NRegChunk *next_chunk;
-        if (interpreter->ctx.num_reg_top->next)
-            next_chunk = interpreter->ctx.num_reg_top->next;
-        else {
-            next_chunk = mem_sys_allocate(sizeof(struct NRegChunk));
-            next_chunk->next = NULL;
-            next_chunk->prev = interpreter->ctx.num_reg_top;
-            interpreter->ctx.num_reg_top->next = next_chunk;
-        }
-        next_chunk->used = 1;
-        interpreter->ctx.num_reg_top = next_chunk;
-        memcpy(&next_chunk->NRegFrame[0],
-               where, sizeof(struct NRegFrame));
-    }
+{    
+    struct RegisterChunkBuf* top;
+    regstack_push_entry(interpreter, &interpreter->ctx.num_reg_stack);
+    top = interpreter->ctx.num_reg_stack.top;
+    memcpy(&((struct NRegChunkBuf*)top->data.bufstart)->
+                    NRegFrame[top->used-1].registers,
+           where, sizeof(struct NRegFrame));
 }

 /*=for api register Parrot_pop_n
@@ -200,24 +280,15 @@
 void
 Parrot_pop_n(struct Parrot_Interp *interpreter, void *where)
 {
-    struct NRegChunk *top = interpreter->ctx.num_reg_top;
+    struct RegisterChunkBuf* top = interpreter->ctx.num_reg_stack.top;
     /* Do we even have anything? */
     if (top->used > 0) {
-        top->used--;
-        memcpy(where,
-               &top->NRegFrame[top->used], sizeof(struct NRegFrame));
-        /* Empty? */
-        if (!top->used) {
-            /* Yep, drop down a frame. Maybe */
-            if (top->prev) {
-                /* Keep one stack segment spare to avoid thrashing */
-                if (top->next) {
-                    mem_sys_free(top->next);
-                    top->next = NULL;
-                }
-                interpreter->ctx.num_reg_top = top->prev;
-            }
-        }
+        struct NRegFrame* irf = &((struct NRegChunkBuf*)top->data.bufstart)->
+                    NRegFrame[top->used-1];
+        memcpy(where,
+               &irf->registers,
+               sizeof(struct NRegFrame));
+        regstack_pop_entry(interpreter, &interpreter->ctx.num_reg_stack);
     }
     /* Nope. So pitch a fit */
     else {
@@ -242,31 +313,13 @@
 */
 void
 Parrot_push_p(struct Parrot_Interp *interpreter, void *where)
-{
-    /* Do we have any space in the current savestack? If so, memcpy
-     * down */
-    if (interpreter->ctx.pmc_reg_top->used < FRAMES_PER_CHUNK) {
-        memcpy(&interpreter->ctx.pmc_reg_top->
-               PRegFrame[interpreter->ctx.pmc_reg_top->used],
-               where, sizeof(struct PRegFrame));
-        interpreter->ctx.pmc_reg_top->used++;
-    }
-    /* Nope, so either move to next stack chunk or grow the stack */
-    else {
-        struct PRegChunk *next_chunk;
-        if (interpreter->ctx.pmc_reg_top->next)
-            next_chunk = interpreter->ctx.pmc_reg_top->next;
-        else {
-            next_chunk = mem_sys_allocate(sizeof(struct PRegChunk));
-            next_chunk->next = NULL;
-            next_chunk->prev = interpreter->ctx.pmc_reg_top;
-            interpreter->ctx.pmc_reg_top->next = next_chunk;
-        }
-        next_chunk->used = 1;
-        interpreter->ctx.pmc_reg_top = next_chunk;
-        memcpy(&next_chunk->PRegFrame[0],
-               where, sizeof(struct PRegFrame));
-    }
+{    
+    struct RegisterChunkBuf* top;
+    regstack_push_entry(interpreter, &interpreter->ctx.pmc_reg_stack);
+    top = interpreter->ctx.pmc_reg_stack.top;
+    memcpy(&((struct PRegChunkBuf*)top->data.bufstart)->
+                    PRegFrame[top->used-1].registers,
+           where, sizeof(struct PRegFrame));
 }

 /*=for api register Parrot_pop_p
@@ -275,24 +328,15 @@
 void
 Parrot_pop_p(struct Parrot_Interp *interpreter, void *where)
 {
-    struct PRegChunk *top = interpreter->ctx.pmc_reg_top;
+    struct RegisterChunkBuf* top = interpreter->ctx.pmc_reg_stack.top;
     /* Do we even have anything? */
     if (top->used > 0) {
-        top->used--;
-        memcpy(where,
-               &top->PRegFrame[top->used], sizeof(struct PRegFrame));
-        /* Empty? */
-        if (!top->used) {
-            /* Yep, drop down a frame. Maybe */
-            if (top->prev) {
-                /* Keep one stack segment spare to avoid thrashing */
-                if (top->next) {
-                    mem_sys_free(top->next);
-                    top->next = NULL;
-                }
-                interpreter->ctx.pmc_reg_top = top->prev;
-            }
-        }
+        struct PRegFrame* irf = &((struct PRegChunkBuf*)top->data.bufstart)->
+                    PRegFrame[top->used-1];
+        memcpy(where,
+               &irf->registers,
+               sizeof(struct PRegFrame));
+        regstack_pop_entry(interpreter, &interpreter->ctx.pmc_reg_stack);
     }
     /* Nope. So pitch a fit */
     else {
Index: src/sub.c
===================================================================
RCS file: /cvs/public/parrot/src/sub.c,v
retrieving revision 1.40
diff -u -r1.40 sub.c
--- src/sub.c   25 Oct 2003 06:13:21 -0000      1.40
+++ src/sub.c   8 Jan 2004 03:04:02 -0000
@@ -12,6 +12,7 @@
  */

 #include "parrot/parrot.h"
+#include "parrot/method_util.h"

 /*
@@ -33,6 +34,10 @@
 cow_copy_context(struct Parrot_Interp *interp, struct Parrot_Context *ctx)
 {
     memcpy(ctx, &interp->ctx, sizeof(*ctx));
+    mark_register_stack_cow(interp, &ctx->int_reg_stack);
+    mark_register_stack_cow(interp, &ctx->num_reg_stack);
+    mark_register_stack_cow(interp, &ctx->string_reg_stack);
+    mark_register_stack_cow(interp, &ctx->pmc_reg_stack);
     stack_mark_cow(ctx->pad_stack);
     stack_mark_cow(ctx->user_stack);
     stack_mark_cow(ctx->control_stack);
@@ -46,6 +51,18 @@
 restore_context(struct Parrot_Interp *interp, struct Parrot_Context *ctx)
 {
     memcpy(&interp->ctx, ctx, sizeof(*ctx));
+}
+
+void
+mark_context(struct Parrot_Interp* interpreter, struct Parrot_Context* ctx)
+{
+    mark_stack(interpreter, ctx->pad_stack);
+    mark_stack(interpreter, ctx->user_stack);
+    mark_stack(interpreter, ctx->control_stack);
+    mark_register_stack(interpreter, &ctx->int_reg_stack);
+    mark_register_stack(interpreter, &ctx->num_reg_stack);
+    mark_string_register_stack(interpreter, &ctx->string_reg_stack);
+    mark_pmc_register_stack(interpreter, &ctx->pmc_reg_stack);
 }

 static void coro_error(Stack_Entry_t *e)
Index: t/pmc/sub.t
===================================================================
RCS file: /cvs/public/parrot/t/pmc/sub.t,v
retrieving revision 1.31
diff -u -r1.31 sub.t
--- t/pmc/sub.t 4 Dec 2003 10:30:38 -0000       1.31
+++ t/pmc/sub.t 8 Jan 2004 03:04:02 -0000
@@ -1,6 +1,6 @@
 #! perl -w

-use Parrot::Test tests => 47;
+use Parrot::Test tests => 49;
 use Test::More;
 use Parrot::Config;

@@ -708,6 +708,40 @@
 CODE
 ok 1
 ok 2
+OUTPUT
+
+output_is(<<'CODE', <<'OUTPUT', "continuation close over register stacks");
+    set S20, "ok\n"
+    savetop
+    newsub P0, .Continuation, next
+    restoretop
+    concat S20, "not ", S20
+    invoke
+    print "bad\n"
+next:
+    restoretop
+    print S20
+    end
+CODE
+ok
+OUTPUT
+
+output_is(<<'CODE', <<'OUTPUT', "DOD marks continuation's register stacks");
+    set S20, "ok\n"
+    savetop
+    newsub P0, .Continuation, next
+    restoretop
+    null S20
+    sweep 1
+    collect
+    invoke
+    print "bad\n"
+next:
+    restoretop
+    print S20
+    end
+CODE
+ok
 OUTPUT

 unlink($temp, 'temp.pbc');


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.