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');