I needed to use a generic stack, and the API in stacks.[ch] really
bothered me:

 - it relied on the caller to maintain a pointer to the top of the
   stack, rather than having a stack ADT that knows its own top. That
   meant that anyone including a stack in its structure had to keep
   around two variables and be sure to pass them together to many
   routines.

 - It used funky pointer masking to jump between the above two
   variables behind your back.

 - The main type exported was 'struct Stack_Chunk', which sounds to me
   like an internal implementation detail.

I changed its internal data structure from a doubly-linked list to a
circular, doubly-linked list (so the Stack could quickly find its own
top by looking in the its chunk->prev chunk).

The API changed quite a bit. For example:

void new_stack(struct Parrot_Interp *, struct StackChunk **, struct Stack_Entry **);
struct Stack_Entry *push_generic_entry(struct Parrot_Interp *, struct Stack_Entry 
**top, void *thing, INTVAL type,  void (*cleanup)(struct Stack_Entry *));

are now

Stack new_stack(struct Parrot_Interp *);
void stack_push(struct Parrot_Interp *, Stack,
                void *thing, INTVAL type, void (*cleanup)(Stack_Entry));

That means that interpreter->user_stack_top and ->user_stack_base have
been collapsed to ->user_stack, and likewise for ->control_stack.

And to forestall any objections based on speed, on my machine the new
version is slightly faster.

All tests pass. Well, they all pass for non-JIT runs, anyway. I
noticed that if I change test_prog in Parrot/Config.pm from
'test_parrot' to 'test_parrot -j' and do a 'make test', quite a few
things fail with or without my change. Is that bad?

Index: core.ops
===================================================================
RCS file: /home/perlcvs/parrot/core.ops,v
retrieving revision 1.72
diff -a -u -r1.72 core.ops
--- core.ops    9 Jan 2002 17:24:11 -0000       1.72
+++ core.ops    10 Jan 2002 21:51:55 -0000
@@ -2266,13 +2266,13 @@
 
 op entrytype(out INT, in INT) {
   INTVAL depth;
-  struct Stack_Entry *entry;
-  depth = stack_depth(interpreter, interpreter->user_stack_base);
+  Stack_Entry entry;
+  depth = stack_depth(interpreter, interpreter->user_stack);
   if (depth <= $2) {
     INTERNAL_EXCEPTION(99, "Stack Depth wrong");
   }
 
-  entry = stack_entry(interpreter, interpreter->user_stack_base, $2);
+  entry = stack_entry(interpreter, interpreter->user_stack, $2);
   $1 = get_entry_type(interpreter, entry);
   goto NEXT();
 }
@@ -2292,22 +2292,22 @@
 =cut
 
 inline op save(in INT) {
-  push_generic_entry(interpreter, &interpreter->user_stack_top, &($1), 
STACK_ENTRY_INT, NULL);
+  stack_push(interpreter, interpreter->user_stack, &($1), STACK_ENTRY_INT, NULL);
   goto NEXT();
 }
 
 inline op save(in NUM) {
-  push_generic_entry(interpreter, &interpreter->user_stack_top, &($1), 
STACK_ENTRY_FLOAT, NULL);
+  stack_push(interpreter, interpreter->user_stack, &($1), STACK_ENTRY_FLOAT, NULL);
   goto NEXT();
 }
 
 inline op save(in PMC) {
-  push_generic_entry(interpreter, &interpreter->user_stack_top, $1, STACK_ENTRY_PMC, 
NULL);
+  stack_push(interpreter, interpreter->user_stack, $1, STACK_ENTRY_PMC, NULL);
   goto NEXT();
 }
 
 inline op save(in STR) {
-  push_generic_entry(interpreter,  &interpreter->user_stack_top, $1, 
STACK_ENTRY_STRING, NULL);
+  stack_push(interpreter, interpreter->user_stack, $1, STACK_ENTRY_STRING, NULL);
   goto NEXT();
 }
 
@@ -2327,22 +2327,22 @@
 =cut
 
 inline op restore(out INT) {
-  pop_generic_entry(interpreter, &interpreter->user_stack_top, &($1), 
STACK_ENTRY_INT);
+  stack_pop(interpreter, interpreter->user_stack, &($1), STACK_ENTRY_INT);
   goto NEXT();
 }
 
 inline op restore(out NUM) {
-  pop_generic_entry(interpreter, &interpreter->user_stack_top, &($1), 
STACK_ENTRY_FLOAT);
+  stack_pop(interpreter, interpreter->user_stack, &($1), STACK_ENTRY_FLOAT);
   goto NEXT();
 }
 
 inline op restore(out PMC) {
-  pop_generic_entry(interpreter, &interpreter->user_stack_top, &($1), 
STACK_ENTRY_PMC);
+  stack_pop(interpreter, interpreter->user_stack, &($1), STACK_ENTRY_PMC);
   goto NEXT();
 }
 
 inline op restore(out STR) {
-  pop_generic_entry(interpreter, &interpreter->user_stack_top, &($1), 
STACK_ENTRY_STRING);
+  stack_pop(interpreter, interpreter->user_stack, &($1), STACK_ENTRY_STRING);
   goto NEXT();
 }
 
@@ -2357,7 +2357,7 @@
 =cut
 
 inline op rotate_up(in INT) {
-  rotate_entries(interpreter, interpreter->user_stack_base, 
interpreter->user_stack_top, $1);
+  rotate_entries(interpreter, interpreter->user_stack, $1);
   goto NEXT();
 }
 
@@ -2400,7 +2400,7 @@
 =cut
 
 inline op bsr (in INT) {
-  push_generic_entry(interpreter, &interpreter->control_stack_top, CUR_OPCODE + 2,  
STACK_ENTRY_DESTINATION, NULL);
+  stack_push(interpreter, interpreter->control_stack, CUR_OPCODE + 2,  
+STACK_ENTRY_DESTINATION, NULL);
   goto OFFSET($1);
 }
 
Index: interpreter.c
===================================================================
RCS file: /home/perlcvs/parrot/interpreter.c,v
retrieving revision 1.54
diff -a -u -r1.54 interpreter.c
--- interpreter.c       6 Jan 2002 02:34:04 -0000       1.54
+++ interpreter.c       10 Jan 2002 21:52:02 -0000
@@ -509,12 +509,10 @@
     Parrot_clear_p(interpreter);
     
     /* Need a user stack */
-    new_stack(interpreter, &interpreter->user_stack_base,
-              &interpreter->user_stack_top);
+    interpreter->user_stack = new_stack(interpreter);
     
     /* And a control stack */
-    new_stack(interpreter, &interpreter->control_stack_base,
-              &interpreter->control_stack_top);
+    interpreter->control_stack = new_stack(interpreter);
 
     /* Need an empty stash */
     interpreter->perl_stash = mem_allocate_new_stash();
Index: jit.c
===================================================================
RCS file: /home/perlcvs/parrot/jit.c,v
retrieving revision 1.6
diff -a -u -r1.6 jit.c
--- jit.c       2 Jan 2002 19:52:19 -0000       1.6
+++ jit.c       10 Jan 2002 21:52:03 -0000
@@ -308,10 +308,10 @@
                         address = (INTVAL *)string_compare; 
                         break;
                 case 4: 
-                        address = (INTVAL *)pop_generic_entry; 
+                        address = (INTVAL *)stack_pop;
                         break;
                 case 5: 
-                        address = (INTVAL *)push_generic_entry; 
+                        address = (INTVAL *)stack_push;
                         break;
             }
 
@@ -337,7 +337,7 @@
                         address = (INTVAL *)&interpreter; 
                         break;
                 case 1: 
-                        address = (INTVAL *)&interpreter->control_stack_top; 
+                        address = (INTVAL *)interpreter->control_stack; 
                         break;
             }
 
Index: rx.c
===================================================================
RCS file: /home/perlcvs/parrot/rx.c,v
retrieving revision 1.2
diff -a -u -r1.2 rx.c
--- rx.c        10 Jan 2002 17:10:42 -0000      1.2
+++ rx.c        10 Jan 2002 21:52:03 -0000
@@ -34,7 +34,7 @@
        rx->groupstart=pmc_new(interpreter, enum_class_PerlArray);
        rx->groupend=pmc_new(interpreter, enum_class_PerlArray);
 
-       new_stack(interpreter, &rx->stack_base, &rx->stack_top);
+       rx->stack = new_stack(interpreter);
 
        return rx;
 }
Index: rx.ops
===================================================================
RCS file: /home/perlcvs/parrot/rx.ops,v
retrieving revision 1.1
diff -a -u -r1.1 rx.ops
--- rx.ops      9 Jan 2002 22:35:40 -0000       1.1
+++ rx.ops      10 Jan 2002 21:52:05 -0000
@@ -357,7 +357,7 @@
 op rx_pushindex(in pmc) {
        RX_dUNPACK($1);
 
-       push_generic_entry(interpreter, &rx->stack_top, &rx->index, STACK_ENTRY_INT, 
NULL);
+       stack_push(interpreter, rx->stack, &rx->index, STACK_ENTRY_INT, NULL);
        
        goto NEXT();
 }
@@ -375,7 +375,7 @@
        RX_dUNPACK($1);
 
        /* Don't worry about the const warning from the next line */
-       push_generic_entry(interpreter, &rx->stack_top, &RX_MARK, STACK_ENTRY_INT, 
NULL);
+       stack_push(interpreter, rx->stack, &RX_MARK, STACK_ENTRY_INT, NULL);
        
        goto NEXT();
 }
@@ -393,7 +393,7 @@
        RX_dUNPACK($1);
        int i;
        
-       pop_generic_entry(interpreter, &rx->stack_top, &i, STACK_ENTRY_INT);
+       stack_pop(interpreter, rx->stack, &i, STACK_ENTRY_INT);
 
        if(i==RX_MARK) {
                goto OFFSET($2);
@@ -484,8 +484,8 @@
 
        rx->index=rx->startindex;
        
-       while(stack_depth(interpreter, rx->stack_base)) {
-               pop_generic_entry(interpreter, &rx->stack_top, NULL, STACK_ENTRY_INT);
+       while(stack_depth(interpreter, rx->stack)) {
+               stack_pop(interpreter, rx->stack, NULL, STACK_ENTRY_INT);
        }
        
        goto NEXT();
Index: stacks.c
===================================================================
RCS file: /home/perlcvs/parrot/stacks.c,v
retrieving revision 1.15
diff -a -u -r1.15 stacks.c
--- stacks.c    4 Jan 2002 03:37:43 -0000       1.15
+++ stacks.c    10 Jan 2002 21:52:05 -0000
@@ -5,62 +5,70 @@
  *  Overview:
  *     Stack handling routines for Parrot
  *  Data Structure and Algorithms:
+ *     The stack is stored as a circular, doubly-linked list of
+ *     chunks, where each chunk has room for STACK_CHUNK_DEPTH
+ *     entries. The invariant maintained is that there is always room
+ *     for another entry; if a chunk is filled, a new chunk is added
+ *     onto the list before returning.
  *  History:
  *  Notes:
- *  References:
- */
+ * References: */
 
+#include <assert.h>
 #include "parrot/parrot.h"
 
-void
-new_stack(struct Parrot_Interp *interpreter, struct StackChunk **base, struct 
Stack_Entry **top) {
-       (*base)=mem_allocate_aligned(sizeof(struct StackChunk));
-       (*top)=&((*base)->entry[0]);
-
-       (*base)->used=0;
-       (*base)->free=STACK_CHUNK_DEPTH;
-       (*base)->next=NULL;
-       (*base)->prev=NULL;
+#define STACK_CHUNK_BASE(x) (void *)(MASK_STACK_CHUNK_LOW_BITS & (ptrcast_t)x)
+
+Stack
+new_stack(struct Parrot_Interp *interpreter)
+{
+    Stack stack=mem_allocate_aligned(sizeof(struct Stack_chunk_t));
+    stack->used=0;
+    stack->next=stack;
+    stack->prev=stack;
+    return stack;
 }
 
 INTVAL
-stack_depth(struct Parrot_Interp *interpreter, struct StackChunk *chunk) {
-  INTVAL               depth;
+stack_depth(struct Parrot_Interp *interpreter, Stack stack)
+{
+    Stack_Chunk chunk;
+    INTVAL depth = stack->used;
 
-  depth = chunk->used;
+    for (chunk = stack->next; chunk != stack; chunk = chunk->next)
+        depth += chunk->used;
 
-  while (chunk->next) {
-    chunk = chunk->next;
-    depth += chunk->used;
-  }
-  return depth;
+    return depth;
 }
 
-struct Stack_Entry *
-stack_entry(struct Parrot_Interp *interpreter, struct StackChunk *chunk, 
-            INTVAL depth) {
-    while (chunk->next) {
-      chunk = chunk->next;
-    }
+/* Returns NULL if depth > number of entries in stack */
+Stack_Entry
+stack_entry(struct Parrot_Interp *interpreter, Stack stack, INTVAL depth)
+{
+    Stack_Chunk chunk = stack->prev; /* Start at top */
 
-    while (depth > chunk->used - 1) {
-      depth -= chunk->used;
-      chunk = chunk->prev; /* Expect caller to have checked bounds */
+    while (depth >= chunk->used && chunk != stack) {
+        depth -= chunk->used;
+        chunk = chunk->prev;
     }
-    return &(chunk->entry[chunk->used - depth - 1]);
+
+    if (depth > chunk->used) return NULL;
+
+    return &chunk->entry[chunk->used - depth - 1];
 }
 
 /* Rotate the top N entries by one */
-void rotate_entries(struct Parrot_Interp *interpreter, 
-       struct StackChunk *base_chunk, struct Stack_Entry *top, INTVAL depth) {
-    struct Stack_Entry temp;
+void
+rotate_entries(struct Parrot_Interp *interpreter, Stack stack, INTVAL depth)
+{
+    struct Stack_entry_t temp;
     INTVAL i;
 
     if (depth <= 0) {
         return;
     }
 
-    if (stack_depth(interpreter, base_chunk) < depth) {
+    if (stack_depth(interpreter, stack) < depth) {
         INTERNAL_EXCEPTION(ERROR_STACK_SHALLOW, "Stack too shallow!\n");
     }
 
@@ -68,196 +76,166 @@
         return;
     }
 
-    temp = *(top);
+    temp = *stack_entry(interpreter, stack, 0);
 
     for(i = 0; i < depth - 1; i++) {
-      *stack_entry(interpreter, base_chunk, i) = 
-                              *stack_entry(interpreter, base_chunk, i + 1);
+      *stack_entry(interpreter, stack, i) = 
+          *stack_entry(interpreter, stack, i + 1);
     }
 
-    *stack_entry(interpreter, base_chunk, depth - 1) = temp;
+    *stack_entry(interpreter, stack, depth - 1) = temp;
 }
 
-/* Push something on the generic stack. Return a pointer to the entry
+/* Push something on the generic stack.
 
    Note that the cleanup pointer, if non-NULL, points to a routine
    that'll be called when the entry is removed from the stack. This is
    handy for those cases where you need some sort of activity to take
    place when an entry is removed, such as when you push a lexical
    lock onto the call stack, or localize (or tempify, or whatever
-   we're calling it)  variable or something */
-struct Stack_Entry *push_generic_entry(struct Parrot_Interp *interpreter, 
-        struct Stack_Entry **top, void *thing, INTVAL type,  
-        void (*cleanup)(struct Stack_Entry *)) {
-    struct StackChunk *chunk_base;
-    
-    chunk_base = STACK_CHUNK_BASE(*top);
-    /* Do we have any slots left in the current chunk? */
-    if (chunk_base->free) {
-        chunk_base->used++;
-        chunk_base->free--;
-        *top = &chunk_base->entry[chunk_base->used-1];
-    }
-    /* Nope, so plan B time. Allocate a new chunk of stack entries */
-    else {
-        struct StackChunk *new_chunk;
-        new_chunk = mem_allocate_aligned(sizeof(struct StackChunk));
-        new_chunk->used = 1;
-        new_chunk->free = STACK_CHUNK_DEPTH - 1;
-        new_chunk->next = NULL;
-        new_chunk->prev = chunk_base;
-        chunk_base->next = new_chunk;
-        *top = &new_chunk->entry[0];
-        chunk_base = new_chunk;
-    }
+   we're calling it) variable or something
+ */
+void
+stack_push(struct Parrot_Interp *interpreter, Stack stack,
+           void *thing, INTVAL type, void (*cleanup)(Stack_Entry))
+{
+    Stack_Chunk chunk = stack->prev;
+    Stack_Entry entry = &chunk->entry[chunk->used];
 
     /* Remember the type */
-    chunk_base->entry[chunk_base->used-1].entry_type = type;
+    entry->entry_type = type;
     /* If we were passed a cleanup function, mark the flag entry
        for this as needing cleanup*/
-    chunk_base->entry[chunk_base->used-1].flags =
-        (cleanup ? STACK_ENTRY_CLEANUP : 0);
+    entry->flags = (cleanup ? STACK_ENTRY_CLEANUP : 0);
     /* Remember the cleanup function */
-    chunk_base->entry[chunk_base->used-1].cleanup = cleanup;
+    entry->cleanup = cleanup;
     /* Store our thing */
     switch (type) {
     case STACK_ENTRY_INT:
-        chunk_base->entry[chunk_base->used-1].entry.int_val = *(INTVAL *)thing;
+        entry->entry.int_val = *(INTVAL *)thing;
         break;
     case STACK_ENTRY_FLOAT:
-        chunk_base->entry[chunk_base->used-1].entry.num_val = 
-                                                     *(FLOATVAL *)thing;
+        entry->entry.num_val = *(FLOATVAL *)thing;
         break;
     case STACK_ENTRY_PMC:
-        chunk_base->entry[chunk_base->used-1].entry.pmc_val = thing;
+        entry->entry.pmc_val = thing;
         break;
     case STACK_ENTRY_STRING:
-        chunk_base->entry[chunk_base->used-1].entry.string_val = thing;
+        entry->entry.string_val = thing;
         break;
     case STACK_ENTRY_POINTER:
-        chunk_base->entry[chunk_base->used-1].entry.generic_pointer = thing;
+        entry->entry.generic_pointer = thing;
         break;
     case STACK_ENTRY_DESTINATION:
-        chunk_base->entry[chunk_base->used-1].entry.generic_pointer = thing;
+        entry->entry.generic_pointer = thing;
         break;
     }
 
-    return *top;
-
+    /* Register the new entry */
+    if (++chunk->used == STACK_CHUNK_DEPTH) {
+        /* Need to add a new chunk */
+        Stack_Chunk new_chunk = mem_allocate_aligned(sizeof(*new_chunk));
+        new_chunk->used = 0;
+        new_chunk->next = stack;
+        new_chunk->prev = chunk;
+        chunk->next = new_chunk;
+        stack->prev = new_chunk;
+    }
 }
 
-/* Pop off an entry and return a pointer to the contents*/
-void *pop_generic_entry(struct Parrot_Interp *interpreter, struct Stack_Entry **top, 
void *where, INTVAL type) {
-    struct StackChunk *chunk_base;
+/* Pop off an entry and return a pointer to the contents */
+void *
+stack_pop(struct Parrot_Interp *interpreter, Stack stack,
+          void *where, INTVAL type)
+{
+    Stack_Chunk chunk = stack->prev;
+    Stack_Entry entry;
+
+    /* We may have an empty chunk at the end of the list */
+    if (chunk->used == 0 && chunk != stack) {
+        /* That chunk != stack check is just to allow the empty stack case
+         * to fall through to the following exception throwing code. */
+
+        /* Need to pop off the last entry */
+        stack->prev = chunk->prev;
+        stack->prev->next = stack;
+        /* Relying on GC feels dirty... */
+        chunk = stack->prev;
+    }
     
-    chunk_base = STACK_CHUNK_BASE(*top);
     /* Quick sanity check */
-    if (chunk_base->used == 0) {
+    if (chunk->used == 0) {
         INTERNAL_EXCEPTION(ERROR_STACK_EMPTY, "No entries on stack!\n");
     }
+
+    entry = &chunk->entry[chunk->used - 1];
+
     /* Types of 0 mean we don't care */
-    if (type && (*top)->entry_type != type) {
+    if (type && entry->entry_type != type) {
         INTERNAL_EXCEPTION(ERROR_BAD_STACK_TYPE, 
                            "Wrong type on top of stack!\n");
     }
 
+    /* Cleanup routine? */
+    if (entry->flags & STACK_ENTRY_CLEANUP) {
+        (*entry->cleanup)(entry);
+    }
+
+    /* Now decrement the SP */
+    chunk->used--;
+
+    /* Sometimes the caller doesn't care what the value was */
+    if (where == NULL) return NULL;
+
     /* Snag the value */
     switch(type) {
     case STACK_ENTRY_INT:
-        *(INTVAL *)where = (*top)->entry.int_val;
+        *(INTVAL *)where = entry->entry.int_val;
         break;
     case STACK_ENTRY_FLOAT:
-        *(FLOATVAL *)where = (*top)->entry.num_val;
+        *(FLOATVAL *)where = entry->entry.num_val;
         break;
     case STACK_ENTRY_PMC:
-        *(PMC **)where = (*top)->entry.pmc_val;
+        *(PMC **)where = entry->entry.pmc_val;
         break;
     case STACK_ENTRY_STRING:
-        *(STRING **)where = (*top)->entry.string_val;
+        *(STRING **)where = entry->entry.string_val;
         break;
     case STACK_ENTRY_POINTER:
-        *(void **)where = (*top)->entry.generic_pointer;
+        *(void **)where = entry->entry.generic_pointer;
         break;
     case STACK_ENTRY_DESTINATION:
-        *(void **)where = (*top)->entry.generic_pointer;
+        *(void **)where = entry->entry.generic_pointer;
         break;
     }
-    /* Cleanup routine? */
-    if ((*top)->flags && STACK_ENTRY_CLEANUP) {
-        ((*top)->cleanup)(*top);
-    }
 
-    /* Now decrement the SP */
-    chunk_base->used--;
-    chunk_base->free++;
-    /* Can we toss a whole chunk? */
-    if (0 == chunk_base->used && chunk_base->prev) {
-        chunk_base = chunk_base->prev;
-    } 
-    if (chunk_base->used) {
-        *top = &chunk_base->entry[chunk_base->used - 1];
-    }
-    
     return where;
 }
 
 /* Pop off a destination entry and return a pointer to the contents*/
-void *pop_dest(struct Parrot_Interp *interpreter) {
-#if 0
-    /* If we didn't mind the extra call, we'd do this: */
-    void * dest;
-    pop_generic_entry(interpreter, &interpreter->control_stack_top, 
-                      &dest, STACK_ENTRY_DESTINATION)
-    return dest;
-#endif
-
-    struct StackChunk *chunk_base;
-    struct Stack_Entry **top = &interpreter->control_stack_top;
-    void * dest;
-
-    chunk_base = STACK_CHUNK_BASE(*top);
-    /* Quick sanity check */
-    if (chunk_base->used == 0) {
-        INTERNAL_EXCEPTION(ERROR_STACK_EMPTY, "No entries on stack!\n");
-    }
-
-    if ((*top)->entry_type != STACK_ENTRY_DESTINATION) {
-        INTERNAL_EXCEPTION(ERROR_BAD_STACK_TYPE, 
-                           "Wrong type on top of stack!\n");
-    }
-
-    dest = (*top)->entry.generic_pointer;
-
-    /* Cleanup routine? */
-    if ((*top)->flags && STACK_ENTRY_CLEANUP) {
-        ((*top)->cleanup)(*top);
-    }
-
-    /* Now decrement the SP */
-    chunk_base->used--;
-    chunk_base->free++;
-    /* Can we toss a whole chunk? */
-    if (0 == chunk_base->used && chunk_base->prev) {
-        chunk_base = chunk_base->prev;
-    } 
-    if (chunk_base->used) {
-        *top = &chunk_base->entry[chunk_base->used - 1];
-    }
-    
+void *
+pop_dest(struct Parrot_Interp *interpreter)
+{
+    /* We don't mind the extra call, so we do this: (previous comment
+     * said we *do* mind, but I say let the compiler decide) */
+    void* dest;
+    stack_pop(interpreter, interpreter->control_stack,
+              &dest, STACK_ENTRY_DESTINATION);
     return dest;
 }
 
-/* Pop off an entry and throw it out */
-void toss_generic_entry(struct Parrot_Interp *interpreter, 
-                        struct Stack_Entry **top, INTVAL type) {
-    void *foo;
-    pop_generic_entry(interpreter, top, &foo, type);
+void *
+stack_peek(struct Parrot_Interp *interpreter, Stack stack, INTVAL* type)
+{
+    Stack_Entry entry = stack_entry(interpreter, stack, 0);
+    if (type != NULL) *type = entry->entry_type;
+    return entry->entry.generic_pointer;
 }
 
-/* get the type of  the topmost stack entry */
-INTVAL get_entry_type(struct Parrot_Interp *interpreter, 
-                      struct Stack_Entry *entry) {
-    return( entry->entry_type);
+INTVAL
+get_entry_type(struct Parrot_Interp *interpreter, Stack_Entry entry)
+{
+    return entry->entry_type;
 }
 
 /*
Index: testparrotsizes_c.in
===================================================================
RCS file: /home/perlcvs/parrot/testparrotsizes_c.in,v
retrieving revision 1.1
diff -a -u -r1.1 testparrotsizes_c.in
--- testparrotsizes_c.in        12 Oct 2001 17:59:01 -0000      1.1
+++ testparrotsizes_c.in        10 Jan 2002 21:52:05 -0000
@@ -15,7 +15,7 @@
        printf("\tsregchunk=> %d,\n",           sizeof(struct SRegChunk));
        printf("\tnregchunk=> %d,\n",           sizeof(struct NRegChunk));
        printf("\tpregchunk=> %d,\n",           sizeof(struct PRegChunk));
-       printf("\tstackchunk=> %d,\n",          sizeof(struct StackChunk));
+       printf("\tstackchunk=> %d,\n",          sizeof(struct Stack_chunk_t));
        
        
        printf(");");
Index: include/parrot/interpreter.h
===================================================================
RCS file: /home/perlcvs/parrot/include/parrot/interpreter.h,v
retrieving revision 1.20
diff -a -u -r1.20 interpreter.h
--- include/parrot/interpreter.h        1 Jan 2002 17:22:55 -0000       1.20
+++ include/parrot/interpreter.h        10 Jan 2002 21:52:06 -0000
@@ -33,14 +33,12 @@
     struct NReg *num_reg;            /* Current top of the float reg stack */
     struct SReg *string_reg;         /* Current top of the string stack */
     struct PReg *pmc_reg;            /* Current top of the PMC stack */
-    struct Stack_Entry *user_stack_top;         /* Current top of the scratch stack */
-    struct Stack_Entry *control_stack_top;     /* Current top of the flow control 
stack */
-    struct IRegChunk *int_reg_base;            /* base of the int reg stack */
-    struct NRegChunk *num_reg_base;            /* Base of the float reg stack */
-    struct SRegChunk *string_reg_base;         /* Base of the string stack */
-    struct PRegChunk *pmc_reg_base;            /* Base of the PMC stack */
-    struct StackChunk *user_stack_base;             /* Base of the scratch stack */
-    struct StackChunk *control_stack_base;          /* Base of the flow control stack 
*/
+    struct IRegChunk *int_reg_base;       /* base of the int reg stack */
+    struct NRegChunk *num_reg_base;       /* Base of the float reg stack */
+    struct SRegChunk *string_reg_base;    /* Base of the string stack */
+    struct PRegChunk *pmc_reg_base;       /* Base of the PMC stack */
+    struct Stack_chunk_t* user_stack;     /* Base of the scratch stack */
+    struct Stack_chunk_t* control_stack;  /* Base of the flow control stack */
     struct Stash *perl_stash;             /* Pointer to the global */
                                           /* variable area */
     struct Arenas *arena_base;            /* Pointer to this */
Index: include/parrot/rx.h
===================================================================
RCS file: /home/perlcvs/parrot/include/parrot/rx.h,v
retrieving revision 1.1
diff -a -u -r1.1 rx.h
--- include/parrot/rx.h 9 Jan 2002 22:35:18 -0000       1.1
+++ include/parrot/rx.h 10 Jan 2002 21:52:06 -0000
@@ -47,8 +47,7 @@
 
        opcode_t *substfunc;
 
-       struct Stack_Entry *stack_top;
-       struct StackChunk *stack_base;
+        struct Stack_chunk_t* stack;
 } rxinfo;
 
 rxinfo * rx_allocate_info(struct Parrot_Interp *, STRING *);
Index: include/parrot/stacks.h
===================================================================
RCS file: /home/perlcvs/parrot/include/parrot/stacks.h,v
retrieving revision 1.15
diff -a -u -r1.15 stacks.h
--- include/parrot/stacks.h     4 Jan 2002 03:37:45 -0000       1.15
+++ include/parrot/stacks.h     10 Jan 2002 21:52:07 -0000
@@ -17,7 +17,7 @@
 
 #define STACK_CHUNK_DEPTH 256
 
-struct Stack_Entry {
+typedef struct Stack_entry_t {
     union {
         FLOATVAL num_val;
         INTVAL int_val;
@@ -27,28 +27,45 @@
     } entry;
     INTVAL entry_type;
     INTVAL flags;
-    void (*cleanup)(struct Stack_Entry *);
-};
+    void (*cleanup)(struct Stack_entry_t *);
+}* Stack_Entry;
 
-struct StackChunk {
+typedef struct Stack_chunk_t {
   INTVAL used;
-  INTVAL free;
-  struct StackChunk *next;
-  struct StackChunk *prev;
-  struct Stack_Entry entry[STACK_CHUNK_DEPTH];
-};
-
-void new_stack(struct Parrot_Interp *, struct StackChunk **, struct Stack_Entry **);
-
-INTVAL stack_depth(struct Parrot_Interp *,struct StackChunk *chunk);
-struct Stack_Entry *stack_entry(struct Parrot_Interp *, struct StackChunk 
*chunk,INTVAL);
-void rotate_entries(struct Parrot_Interp *, struct StackChunk *, struct Stack_Entry 
*, INTVAL);
-
-struct Stack_Entry *push_generic_entry(struct Parrot_Interp *, struct Stack_Entry 
**top, void *thing, INTVAL type,  void (*cleanup)(struct Stack_Entry *));
-void *pop_generic_entry(struct Parrot_Interp *, struct Stack_Entry **top, void 
*where, INTVAL type);
-void *pop_dest(struct Parrot_Interp *);
-void toss_generic_entry(struct Parrot_Interp *, struct Stack_Entry **top, INTVAL 
type);
-INTVAL get_entry_type(struct Parrot_Interp *, struct Stack_Entry *entry);
+  struct Stack_chunk_t *next;
+  struct Stack_chunk_t *prev;
+  struct Stack_entry_t entry[STACK_CHUNK_DEPTH];
+}* Stack_Chunk;
+
+typedef Stack_Chunk Stack;
+
+Stack
+new_stack(struct Parrot_Interp *);
+
+INTVAL
+stack_depth(struct Parrot_Interp *, Stack);
+
+Stack_Entry
+stack_entry(struct Parrot_Interp *, Stack, INTVAL);
+
+void
+rotate_entries(struct Parrot_Interp *, Stack, INTVAL depth);
+
+void
+stack_push(struct Parrot_Interp *, Stack,
+           void *thing, INTVAL type, void (*cleanup)(Stack_Entry));
+
+void *
+stack_pop(struct Parrot_Interp *, Stack, void *where, INTVAL type);
+
+void *
+pop_dest(struct Parrot_Interp *interpreter);
+
+void *
+stack_peek(struct Parrot_Interp *interpreter, Stack stack, INTVAL* type);
+
+INTVAL
+get_entry_type(struct Parrot_Interp *interpreter, Stack_Entry entry);
 
 #define STACK_ENTRY_INT 1
 #define STACK_ENTRY_FLOAT 2
@@ -58,8 +75,6 @@
 #define STACK_ENTRY_DESTINATION 6
 
 #define STACK_ENTRY_CLEANUP 0x01
-
-#define STACK_CHUNK_BASE(x) (void *)(MASK_STACK_CHUNK_LOW_BITS & (ptrcast_t)x)
 
 #define ERROR_STACK_EMPTY 1
 #define ERROR_STACK_SHALLOW 1

Reply via email to