cvsuser     03/06/27 03:09:33

  Modified:    .        debug.c dod.c interpreter.c method_util.c stacks.c
  Log:
  COW stacks by chunk
  
  Revision  Changes    Path
  1.83      +2 -2      parrot/debug.c
  
  Index: debug.c
  ===================================================================
  RCS file: /cvs/public/parrot/debug.c,v
  retrieving revision 1.82
  retrieving revision 1.83
  diff -u -w -r1.82 -r1.83
  --- debug.c   21 Jun 2003 10:40:29 -0000      1.82
  +++ debug.c   27 Jun 2003 10:09:33 -0000      1.83
  @@ -2,7 +2,7 @@
    * debug.c
    *
    * CVS Info
  - *    $Id: debug.c,v 1.82 2003/06/21 10:40:29 leo Exp $
  + *    $Id: debug.c,v 1.83 2003/06/27 10:09:33 leo Exp $
    * Overview:
    *    Parrot debugger
    * History:
  @@ -1928,7 +1928,7 @@
   
       valid_chunk(chunk, command, depth, STACK_CHUNK_DEPTH, i);
   
  -    entry = (Stack_Entry_t *)(chunk->buffer->bufstart) + depth;
  +    entry = (Stack_Entry_t *)(chunk->items.bufstart) + depth;
   
       switch (entry->entry_type) {
           case STACK_ENTRY_INT:
  
  
  
  1.61      +5 -6      parrot/dod.c
  
  Index: dod.c
  ===================================================================
  RCS file: /cvs/public/parrot/dod.c,v
  retrieving revision 1.60
  retrieving revision 1.61
  diff -u -w -r1.60 -r1.61
  --- dod.c     14 Jun 2003 17:48:31 -0000      1.60
  +++ dod.c     27 Jun 2003 10:09:33 -0000      1.61
  @@ -1,7 +1,7 @@
   /* dod.c
    *  Copyright: (When this is determined...it will go here)
    *  CVS Info
  - *     $Id: dod.c,v 1.60 2003/06/14 17:48:31 dan Exp $
  + *     $Id: dod.c,v 1.61 2003/06/27 10:09:33 leo Exp $
    *  Overview:
    *     Handles dead object destruction of the various headers
    *  Data Structure and Algorithms:
  @@ -290,8 +290,7 @@
       Buffer *b;
       int *refcount;
   
  -    /* clear refcount for COWable objects. As these are STRINGs only these
  -     * have _is_string_FLAG set */
  +    /* clear refcount for COWable objects. */
       for (cur_arena = pool->last_Arena;
               NULL != cur_arena; cur_arena = cur_arena->prev) {
           b = cur_arena->start_objects;
  @@ -308,7 +307,7 @@
                       PObj_live_CLEAR(b);
                   }
   
  -                if (PObj_is_string_TEST(b) && b->bufstart &&
  +                if (PObj_COW_TEST(b) && b->bufstart &&
                           !PObj_external_TEST(b)) {
                       refcount = ((int *)b->bufstart);
                       *refcount = 0;
  @@ -335,7 +334,7 @@
           b = cur_arena->start_objects;
           for (i = 0; i < cur_arena->used; i++) {
               if (!PObj_on_free_list_TEST(b) &&
  -                    PObj_is_string_TEST(b) &&
  +                    PObj_COW_TEST(b) &&
                       b->bufstart &&
                       !PObj_external_TEST(b)) {
                   refcount = ((int *)b->bufstart);
  @@ -533,7 +532,7 @@
                        * but not if it is used COW or external
                        */
                       if (b->bufstart && !PObj_is_external_or_free_TESTALL(b)) {
  -                        if (PObj_is_string_TEST(b)) {
  +                        if (PObj_COW_TEST(b)) {
                               int *refcount = ((int *)b->bufstart);
   
                               if (!--(*refcount))
  
  
  
  1.162     +2 -5      parrot/interpreter.c
  
  Index: interpreter.c
  ===================================================================
  RCS file: /cvs/public/parrot/interpreter.c,v
  retrieving revision 1.161
  retrieving revision 1.162
  diff -u -w -r1.161 -r1.162
  --- interpreter.c     24 Jun 2003 08:35:18 -0000      1.161
  +++ interpreter.c     27 Jun 2003 10:09:33 -0000      1.162
  @@ -1,7 +1,7 @@
   /* interpreter.c
    *  Copyright: (When this is determined...it will go here)
    *  CVS Info
  - *     $Id: interpreter.c,v 1.161 2003/06/24 08:35:18 leo Exp $
  + *     $Id: interpreter.c,v 1.162 2003/06/27 10:09:33 leo Exp $
    *  Overview:
    *     The interpreter api handles running the operations
    *  Data Structure and Algorithms:
  @@ -542,18 +542,15 @@
       Parrot_clear_s(interpreter);
       Parrot_clear_p(interpreter);
   
  +    stack_system_init(interpreter);
       /* Stack for lexical pads */
       interpreter->ctx.pad_stack = new_stack(interpreter, "Pad");
   
       /* Need a user stack */
       interpreter->ctx.user_stack = new_stack(interpreter, "User");
  -    assert(interpreter->ctx.user_stack->buffer !=
  -            interpreter->ctx.pad_stack->buffer);
   
       /* And a control stack */
       interpreter->ctx.control_stack = new_stack(interpreter, "Control");
  -    assert(interpreter->ctx.control_stack->buffer !=
  -            interpreter->ctx.user_stack->buffer);
   
       /* A regex stack would be nice too. */
       interpreter->ctx.intstack = intstack_new(interpreter);
  
  
  
  1.14      +3 -5      parrot/method_util.c
  
  Index: method_util.c
  ===================================================================
  RCS file: /cvs/public/parrot/method_util.c,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -w -r1.13 -r1.14
  --- method_util.c     14 Jun 2003 17:48:31 -0000      1.13
  +++ method_util.c     27 Jun 2003 10:09:33 -0000      1.14
  @@ -1,7 +1,7 @@
   /* method_util.c
    *  Copyright: (When this is determined...it will go here)
    *  CVS Info
  - *     $Id: method_util.c,v 1.13 2003/06/14 17:48:31 dan Exp $
  + *     $Id: method_util.c,v 1.14 2003/06/27 10:09:33 leo Exp $
    *  Overview:
    *     Utility functions to handle Parrot calling conventions, lookup
    *     methods, etc.
  @@ -152,11 +152,9 @@
       size_t i;
   
       for (; cur_stack; cur_stack = cur_stack->prev) {
  -        if (cur_stack->buffer == NULL)
  -            continue;
   
  -        pobject_lives(interpreter, (PObj *)cur_stack->buffer);
  -        entry = (Stack_Entry_t *)(cur_stack->buffer->bufstart);
  +        pobject_lives(interpreter, (PObj *)cur_stack);
  +        entry = (Stack_Entry_t *)(cur_stack->items.bufstart);
           for (i = 0; i < cur_stack->used; i++) {
               if ((STACK_ENTRY_PMC == entry[i].entry_type ||
                   STACK_ENTRY_STRING == entry[i].entry_type) &&
  
  
  
  1.56      +95 -120   parrot/stacks.c
  
  Index: stacks.c
  ===================================================================
  RCS file: /cvs/public/parrot/stacks.c,v
  retrieving revision 1.55
  retrieving revision 1.56
  diff -u -w -r1.55 -r1.56
  --- stacks.c  24 Jun 2003 08:35:18 -0000      1.55
  +++ stacks.c  27 Jun 2003 10:09:33 -0000      1.56
  @@ -1,7 +1,7 @@
   /* stacks.c
    *  Copyright: (When this is determined...it will go here)
    *  CVS Info
  - *     $Id: stacks.c,v 1.55 2003/06/24 08:35:18 leo Exp $
  + *     $Id: stacks.c,v 1.56 2003/06/27 10:09:33 leo Exp $
    *  Overview:
    *     Stack handling routines for Parrot
    *  Data Structure and Algorithms:
  @@ -10,6 +10,11 @@
    *     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.
  + *
  + *     A stack chunk is a bufferlike structure and may be GCed or COWed.
  + *     As top chunks are COWed on usage, its only safe to walk the stack
  + *     from top down via the prev pointers.
  + *
    *  History:
    *  Notes:
    * References: */
  @@ -17,28 +22,28 @@
   #include "parrot/parrot.h"
   #include <assert.h>
   
  +void stack_system_init(Interp *interpreter)
  +{
  +    make_bufferlike_pool(interpreter, sizeof(Stack_Chunk_t));
  +}
  +
   Stack_Chunk_t *
   new_stack(Interp *interpreter, const char *name)
   {
   
  -    Stack_Chunk_t *chunk = mem_sys_allocate_zeroed(sizeof(Stack_Chunk_t));
  -    Stack_t *stack = mem_sys_allocate_zeroed(sizeof(Stack_t));
  +    Stack_Chunk_t *chunk = new_bufferlike_header(interpreter,
  +            sizeof(Stack_Chunk_t));
   
  -    chunk->flags = NO_STACK_CHUNK_FLAGS;
  +    SET_NULL(chunk->items);
       SET_NULL(chunk->next);
       SET_NULL(chunk->prev);
  -    SET_NULL(chunk->buffer);
  -    chunk->stack = stack;
  -    stack->top = stack->base = chunk;
  -    stack->n_chunks = 1;
  -    stack->chunk_limit = STACK_CHUNK_LIMIT;
  -    stack->name = name;
  +    chunk->n_chunks = 1;
  +    chunk->chunk_limit = STACK_CHUNK_LIMIT;
  +    chunk->name = name;
   
  -    chunk->buffer = new_buffer_header(interpreter);
  -
  -    /* Block DOD from murdering our newly allocated stack->buffer. */
  +    /* Block DOD from murdering our newly allocated stack buffer. */
       Parrot_block_DOD(interpreter);
  -    Parrot_allocate(interpreter, chunk->buffer,
  +    Parrot_allocate(interpreter, (Buffer *)chunk,
                       sizeof(Stack_Entry_t) * STACK_CHUNK_DEPTH);
       Parrot_unblock_DOD(interpreter);
   
  @@ -48,27 +53,15 @@
   void
   stack_destroy(Stack_Chunk_t * top)
   {
  -    mem_sys_free(top->stack);
  -    while (top->next)
  -        top = top->next;
  -    while(top) {
  -        Stack_Chunk_t *next = top->prev;
  -        mem_sys_free(top);
  -        top = next;
  -    }
  +   /* GC does it all */
   }
   
  +/* mark a stack COW */
   void
  -stack_mark_cow(Stack_Chunk_t *stack)
  +stack_mark_cow(Stack_Chunk_t *top)
   {
  -    Stack_Chunk_t *chunk = stack;
  -    /* Skip it all if we're already COW'd */
  -    if (chunk->flags & STACK_CHUNK_COW_FLAG) {
  -        return;
  -    }
  -    chunk->flags |= STACK_CHUNK_COW_FLAG;
  -    for (chunk = chunk->prev; chunk && !(chunk->flags& STACK_CHUNK_COW_FLAG); chunk 
= chunk->prev)
  -        chunk->flags |= STACK_CHUNK_COW_FLAG;
  +    for ( ; top ; top = top->prev)
  +        PObj_COW_SET( (Buffer *) top);
   }
   
   /* Returns the height of the stack.  The maximum "depth" is height - 1 */
  @@ -80,28 +73,24 @@
   
       for (chunk = top->prev; chunk; chunk = chunk->prev)
           height += chunk->used;
  -    assert(height == (top->stack->n_chunks - 1) * STACK_CHUNK_DEPTH +
  +    assert(height == (top->n_chunks - 1) * STACK_CHUNK_DEPTH +
               top->used);
   
       return height;
   }
   
  -/* Copy a stack (probably with COW flag) to a private writable stack.
  - * We currently copy the whole stack. After we get rid of the circular
  - * references, fix this to do COW by chunk.
  +/* Copy COWed chunk(s) from top down depth entries
  + * return new top of stack
    */
  -Stack_Chunk_t *
  -stack_copy(struct Parrot_Interp *interp, Stack_Chunk_t *old_top)
  +static Stack_Chunk_t *
  +chunk_copy(struct Parrot_Interp *interp, Stack_Chunk_t *old_top, int depth)
   {
       Stack_Chunk_t *old_chunk = old_top;
       Stack_Chunk_t *new_chunk;
       Stack_Chunk_t *new_top = NULL;
       Stack_Chunk_t *last = NULL;
  -    Stack_t *stack = mem_sys_allocate_zeroed(sizeof(Stack_t));
  -    stack->n_chunks = 0;
  -    stack->name = old_top->stack->name;
       do {
  -        new_chunk = mem_sys_allocate(sizeof(Stack_Chunk_t));
  +        new_chunk = new_bufferlike_header(interp, sizeof(Stack_Chunk_t));
           if (new_top == NULL) {
               new_top = new_chunk;
               new_top->next = NULL;
  @@ -115,25 +104,21 @@
               last = new_chunk;
           }
           new_chunk->used = old_chunk->used;
  -
  -        /* Can't do bit arithmetic directly on enums, must cast via ints. */
  -        new_chunk->flags = (Stack_chunk_flags)((int)old_chunk->flags
  -                                               & ~(int)STACK_CHUNK_COW_FLAG);
  -
  -        /* Copy stack buffer */
  -        new_chunk->buffer = NULL;
  -        new_chunk->buffer = new_buffer_header(interp);
  -        Parrot_allocate(interp, new_chunk->buffer,
  +        new_chunk->n_chunks = old_chunk->n_chunks;
  +        new_chunk->chunk_limit = old_chunk->chunk_limit;
  +        new_chunk->name = old_chunk->name;
  +        depth -= new_chunk->used;
  +
  +        SET_NULL(new_chunk->items);
  +        Parrot_block_DOD(interp);
  +        Parrot_allocate(interp, (Buffer *)new_chunk,
                           sizeof(Stack_Entry_t) * STACK_CHUNK_DEPTH);
  -        memcpy(new_chunk->buffer->bufstart, old_chunk->buffer->bufstart,
  -               old_chunk->buffer->buflen);
  +        Parrot_unblock_DOD(interp);
  +        memcpy(new_chunk->items.bufstart, old_chunk->items.bufstart,
  +                old_chunk->items.buflen);
           old_chunk = old_chunk->prev;
  -        stack->n_chunks++;
  -        stack->base = new_chunk;
       }
  -    while (old_chunk);
  -    new_top->stack = stack;
  -    stack->top = new_top;
  +    while (old_chunk && depth >= 0);
       return new_top;
   }
   
  @@ -164,7 +149,7 @@
       if (chunk == NULL)
           return NULL;
       if (offset < chunk->used) {
  -        entry = (Stack_Entry_t *)chunk->buffer->bufstart +
  +        entry = (Stack_Entry_t *)chunk->items.bufstart +
               chunk->used - offset - 1;
       }
       return entry;
  @@ -185,10 +170,6 @@
       if (num_entries >= -1 && num_entries <= 1) {
           return;
       }
  -    /* If stack is copy-on-write, copy it before we can execute on it */
  -    if (stack->flags & STACK_CHUNK_COW_FLAG) {
  -        *stack_p = stack = stack_copy(interpreter, stack);
  -    }
   
       if (num_entries < 0) {
           num_entries = -num_entries;
  @@ -197,6 +178,9 @@
           if (stack_height(interpreter, stack) < (size_t)num_entries) {
               internal_exception(ERROR_STACK_SHALLOW, "Stack too shallow!\n");
           }
  +        /* If stack is copy-on-write, copy it before we can execute on it */
  +        if (PObj_COW_TEST( (Buffer *) stack))
  +            *stack_p = stack = chunk_copy(interpreter, stack, depth);
   
           temp = *stack_entry(interpreter, stack, depth);
           for (i = depth; i > 0; i--) {
  @@ -211,6 +195,8 @@
           if (stack_height(interpreter, stack) < (size_t)num_entries) {
               internal_exception(ERROR_STACK_SHALLOW, "Stack too shallow!\n");
           }
  +        if (PObj_COW_TEST( (Buffer *) stack))
  +            *stack_p = stack = chunk_copy(interpreter, stack, depth);
   
           temp = *stack_entry(interpreter, stack, 0);
           for (i = 0; i < depth; i++) {
  @@ -235,48 +221,45 @@
   stack_push(Interp *interpreter, Stack_Chunk_t **stack_p,
              void *thing, Stack_entry_type type, Stack_cleanup_method cleanup)
   {
  -    Stack_Chunk_t *stack = *stack_p;
  -    Stack_Chunk_t *chunk;
  +    Stack_Chunk_t *chunk = *stack_p;
       Stack_Entry_t *entry;
   
  -    /* If stack is copy-on-write, copy it before we can execute on it */
  -    if (stack->flags & STACK_CHUNK_COW_FLAG) {
  -        *stack_p = stack = stack_copy(interpreter, stack);
  -    }
  -
  -    chunk = stack;
   
       /* Do we need a new chunk? */
       if (chunk->used == STACK_CHUNK_DEPTH) {
           if (chunk->next == NULL) {
               /* Need to add a new chunk */
  -            Stack_Chunk_t *new_chunk = mem_sys_allocate_zeroed(
  -                    sizeof(Stack_Chunk_t));
  +            Stack_Chunk_t *new_chunk =
  +                new_bufferlike_header(interpreter, sizeof(Stack_Chunk_t));
               SET_NULL(new_chunk->next);
               new_chunk->prev = chunk;
               chunk->next = new_chunk;
  -            new_chunk->stack = chunk->stack;
  -            new_chunk->stack->n_chunks++;
  -            if (new_chunk->stack->n_chunks == new_chunk->stack->chunk_limit)
  +            new_chunk->n_chunks = chunk->n_chunks + 1;
  +            new_chunk->chunk_limit = chunk->chunk_limit;
  +            new_chunk->name = chunk->name;
  +            if (new_chunk->n_chunks == new_chunk->chunk_limit)
                   internal_exception(1, "Stack '%s' too deep\n",
  -                        chunk->stack->name);
  +                        chunk->name);
               *stack_p = chunk = new_chunk;
  -            SET_NULL(new_chunk->buffer);
  -            new_chunk->buffer = new_buffer_header(interpreter);
  +            SET_NULL(new_chunk->items);
   
  -            Parrot_allocate(interpreter, new_chunk->buffer,
  +            Parrot_block_DOD(interpreter);
  +            Parrot_allocate(interpreter, (Buffer *)new_chunk,
                               sizeof(Stack_Entry_t) * STACK_CHUNK_DEPTH);
  +            Parrot_unblock_DOD(interpreter);
           }
           else {
               /* Reuse the spare chunk we kept */
               chunk = chunk->next;
  +            assert(!PObj_COW_TEST( (Buffer *) chunk));
               *stack_p = chunk;
  -            chunk->stack->n_chunks++;
           }
  -        chunk->stack->top = chunk;
       }
  +    /* If stack is copy-on-write, copy it before we can execute on it */
  +    else if (PObj_COW_TEST( (Buffer *) chunk))
  +        *stack_p = chunk = chunk_copy(interpreter, chunk, 0);
   
  -    entry = (Stack_Entry_t *)(chunk->buffer->bufstart) + chunk->used;
  +    entry = (Stack_Entry_t *)(chunk->items.bufstart) + chunk->used++;
   
       /* Remember the type */
       entry->entry_type = type;
  @@ -307,8 +290,6 @@
                              "Invalid Stack_Entry_type!\n");
           break;
       }
  -
  -    chunk->used++;
   }
   
   /* Pop off an entry and return a pointer to the contents */
  @@ -316,16 +297,12 @@
   stack_pop(Interp *interpreter, Stack_Chunk_t **stack_p,
             void *where, Stack_entry_type type)
   {
  -    Stack_Chunk_t *stack = *stack_p;
  +    Stack_Chunk_t *chunk = *stack_p;
       Stack_Entry_t *entry;
  -    Stack_Chunk_t *chunk;
   
       /* If stack is copy-on-write, copy it before we can execute on it */
  -    if (stack->flags & STACK_CHUNK_COW_FLAG) {
  -        *stack_p = stack = stack_copy(interpreter, stack);
  -    }
  -
  -    chunk = stack;
  +    if (PObj_COW_TEST( (Buffer *) chunk))
  +        *stack_p = chunk = chunk_copy(interpreter, chunk, 0);
   
       /* We may have an empty chunk at the end of the list */
       if (chunk->used == 0 && chunk->prev != NULL) {
  @@ -336,8 +313,7 @@
            * on the stack then we make it the last chunk - the GC will clean
            * up any chunks that are discarded by this operation. */
           if (chunk->next) {
  -            /* FIXME: Free this while GC isn't collecting stacks */
  -            mem_sys_free(chunk->next);
  +            /* GC will collect it */
               chunk->next = NULL;
           }
   
  @@ -345,19 +321,18 @@
            * just emptied around for now in case we need it again. */
           chunk = chunk->prev;
           *stack_p = chunk;
  -        chunk->stack->top = chunk;
  -        chunk->stack->n_chunks--;
       }
   
       /* Quick sanity check */
       if (chunk->used == 0) {
           internal_exception(ERROR_STACK_EMPTY, "No entries on stack!\n");
       }
  +    assert(!PObj_COW_TEST( (Buffer *) chunk));
   
       /* Now decrement the SP */
       chunk->used--;
   
  -    entry = (Stack_Entry_t *)(chunk->buffer->bufstart) + chunk->used;
  +    entry = (Stack_Entry_t *)(chunk->items.bufstart) + chunk->used;
   
       /* Types of 0 mean we don't care */
       if (type && entry->entry_type != type) {
  
  
  

Reply via email to