cvsuser     03/06/06 01:29:18

  Modified:    .        MANIFEST MANIFEST.detailed dod.c headers.c
                        interpreter.c jit_debug.c pmc.c resources.c
                        smallobject.c
  Log:
  arena-dod-flags: s. notes on p6i
  
  Revision  Changes    Path
  1.350     +2 -0      parrot/MANIFEST
  
  Index: MANIFEST
  ===================================================================
  RCS file: /cvs/public/parrot/MANIFEST,v
  retrieving revision 1.349
  retrieving revision 1.350
  diff -u -w -r1.349 -r1.350
  --- MANIFEST  30 May 2003 17:17:00 -0000      1.349
  +++ MANIFEST  6 Jun 2003 08:29:18 -0000       1.350
  @@ -71,6 +71,7 @@
   config/auto/jit/test_c.in
   config/auto/memalign.pl
   config/auto/memalign/test_c.in
  +config/auto/memalign/test_c2.in
   config/auto/pack.pl
   config/auto/sizes.pl
   config/auto/sizes/test_c.in
  @@ -107,6 +108,7 @@
   config/gen/platform/generic.c
   config/gen/platform/generic.h
   config/gen/platform/ia64.s
  +config/gen/platform/platform_interface.h
   config/gen/platform/win32.c
   config/gen/platform/win32.h
   config/init/data.pl
  
  
  
  1.23      +2 -0      parrot/MANIFEST.detailed
  
  Index: MANIFEST.detailed
  ===================================================================
  RCS file: /cvs/public/parrot/MANIFEST.detailed,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -w -r1.22 -r1.23
  --- MANIFEST.detailed 28 May 2003 14:56:29 -0000      1.22
  +++ MANIFEST.detailed 6 Jun 2003 08:29:18 -0000       1.23
  @@ -70,6 +70,7 @@
   []           config/auto/jit/test_c.in
   []           config/auto/memalign.pl
   []           config/auto/memalign/test_c.in
  +[]           config/auto/memalign/test_c2.in
   []           config/auto/pack.pl
   []           config/auto/sizes.pl
   []           config/auto/sizes/test_c.in
  @@ -106,6 +107,7 @@
   []           config/gen/platform/generic.c
   []           config/gen/platform/generic.h
   []           config/gen/platform/ia64.s
  +[]           config/gen/platform/platform_interface.h
   []           config/gen/platform/win32.c
   []           config/gen/platform/win32.h
   []           config/init/data.pl
  
  
  
  1.55      +229 -31   parrot/dod.c
  
  Index: dod.c
  ===================================================================
  RCS file: /cvs/public/parrot/dod.c,v
  retrieving revision 1.54
  retrieving revision 1.55
  diff -u -w -r1.54 -r1.55
  --- dod.c     1 Jun 2003 00:17:43 -0000       1.54
  +++ dod.c     6 Jun 2003 08:29:18 -0000       1.55
  @@ -1,7 +1,7 @@
   /* dod.c
    *  Copyright: (When this is determined...it will go here)
    *  CVS Info
  - *     $Id: dod.c,v 1.54 2003/06/01 00:17:43 josh Exp $
  + *     $Id: dod.c,v 1.55 2003/06/06 08:29:18 leo Exp $
    *  Overview:
    *     Handles dead object destruction of the various headers
    *  Data Structure and Algorithms:
  @@ -12,6 +12,7 @@
    *  References:
    */
   
  +#define DOD_C_SOURCE
   #include "parrot/parrot.h"
   #include "parrot/method_util.h"
   #include <assert.h>
  @@ -31,6 +32,37 @@
   
   static size_t find_common_mask(size_t val1, size_t val2);
   
  +#if ARENA_DOD_FLAGS
  +
  +void pobject_lives(struct Parrot_Interp *interpreter, PObj *obj)
  +{
  +
  +    struct Small_Object_Arena *arena = GET_ARENA(obj);
  +    size_t n = GET_OBJ_N(arena, obj);
  +    size_t ns = n >> ARENA_FLAG_SHIFT;
  +    UINTVAL nm = (n & ARENA_FLAG_MASK) << 2;
  +    UINTVAL *dod_flags = arena->dod_flags + ns;
  +    if (*dod_flags & ((PObj_on_free_list_FLAG | PObj_live_FLAG) << nm))
  +        return;
  +    ++arena->live_objects;
  +    *dod_flags |= PObj_live_FLAG << nm;
  +
  +    if (*dod_flags & (PObj_is_special_PMC_FLAG << nm)) {
  +        if (((PMC*)obj)->pmc_ext) {
  +            /* put it on the end of the list */
  +            interpreter->mark_ptr->next_for_GC = (PMC *)obj;
  +            /* Explicitly make the tail of the linked list be
  +             * self-referential */
  +            interpreter->mark_ptr = ((PMC*)obj)->next_for_GC = (PMC *)obj;
  +        }
  +        else if (PObj_custom_mark_TEST(obj))
  +            VTABLE_mark(interpreter, (PMC *) obj);
  +        return;
  +    }
  +}
  +
  +#else
  +
   /* Tag a buffer header as alive. Used by the GC system when tracing
    * the root set, and used by the PMC GC handling routines to tag their
    * individual pieces if they have private ones */
  @@ -55,16 +87,16 @@
       /* if object is a PMC and contains buffers or PMCs, then attach
        * the PMC to the chained mark list
        */
  -    if (PObj_is_PMC_TEST(obj)) {
  -        UINTVAL mask = PObj_is_PMC_ptr_FLAG | PObj_is_buffer_ptr_FLAG
  -            | PObj_custom_mark_FLAG;
  -        if ( (PObj_get_FLAGS(obj) & mask) || ((PMC*)obj)->metadata) {
  +    if (PObj_is_special_PMC_TEST(obj)) {
  +        if (((PMC*)obj)->pmc_ext) {
               /* put it on the end of the list */
               interpreter->mark_ptr->next_for_GC = (PMC *)obj;
               /* Explicitly make the tail of the linked list be
                * self-referential */
               interpreter->mark_ptr = ((PMC*)obj)->next_for_GC = (PMC *)obj;
           }
  +        else if (PObj_custom_mark_TEST(obj))
  +            VTABLE_mark(interpreter, (PMC *) obj);
           return;
       }
   #if GC_VERBOSE
  @@ -79,6 +111,8 @@
   #endif
   }
   
  +#endif
  +
   
   /* Do a full trace run and mark all the PMCs as active if they are */
   static void
  @@ -317,6 +351,75 @@
   }
   #endif /* GC_IS_MALLOC */
   
  +#if ARENA_DOD_FLAGS
  +static void
  +clear_live_counter(struct Parrot_Interp *interpreter,
  +        struct Small_Object_Pool *pool)
  +{
  +    struct Small_Object_Arena *arena;
  +    for (arena = pool->last_Arena; arena; arena = arena->prev)
  +        arena->live_objects = 0;
  +}
  +
  +# define REDUCE_ARENAS 0
  +
  +#  if REDUCE_ARENAS
  +/* -lt:
  + * count free objects per arena
  + * - if we find more then one totally unused arena
  + *   free all but one arena - this is the only possibility to
  + *   reduce the amount of free objects
  + *
  + * doesn't really work or speed things up - disabled
  + */
  +# define REDUCE_ARENA_DEBUG 0
  +
  +#if REDUCE_ARENA_DEBUG
  +#define debug(x) printf x
  +#else
  +#define debug(x)
  +#endif
  +
  +static void
  +reduce_arenas(struct Parrot_Interp *interpreter,
  +        struct Small_Object_Pool *pool, UINTVAL free_arenas)
  +{
  +    struct Small_Object_Arena *arena, *next, *prev;
  +    int i;
  +    PObj * o;
  +
  +    /* debugging stuff */
  +    for (i = 0, arena = pool->last_Arena; arena; arena = arena->prev)
  +        i++;
  +    debug(("\ttotal %d arenas - ", i));
  +
  +    for (next = arena = pool->last_Arena; arena; ) {
  +        prev = arena->prev;
  +        if (arena->live_objects == 0) {
  +            if (--free_arenas <= 0)
  +                break;
  +            next->prev = prev;
  +            pool->total_objects -= arena->used;
  +#if ! ARENA_DOD_FLAGS
  +            mem_sys_free(arena->start_objects);
  +#endif
  +            mem_sys_free(arena);
  +
  +        }
  +        else {
  +            next = arena;
  +        }
  +        arena = prev;
  +    }
  +    for (i = 0, arena = pool->last_Arena; arena; arena = arena->prev)
  +        i++;
  +    debug(("now %d arenas\n", i));
  +
  +}
  +
  +#  endif
  +#endif
  +
   /* Put any buffers/PMCs that are now unused, on to the pools free list.
    * If GC_IS_MALLOC bufstart gets freed too if possible.
    * Avoid buffers that are immune from collection (ie, constant) */
  @@ -327,7 +430,10 @@
       struct Small_Object_Arena *cur_arena;
       UINTVAL i, total_used = 0;
       UINTVAL object_size = pool->object_size;
  -    UINTVAL wash_size = object_size - sizeof(Buffer);
  +    size_t nm;
  +#if REDUCE_ARENAS
  +    UINTVAL free_arenas = 0, old_total_used = 0;
  +#endif
   
       /* We have no impatient things. Yet. */
       interpreter->impatient_things = 0;
  @@ -337,12 +443,53 @@
               NULL != cur_arena; cur_arena = cur_arena->prev) {
           Buffer *b = cur_arena->start_objects;
   
  -        for (i = 0; i < cur_arena->used; i++) {
  +#if ARENA_DOD_FLAGS
  +        UINTVAL * dod_flags = cur_arena->dod_flags - 1;
  +#endif
  +        for (i = nm = 0; i < cur_arena->used; i++) {
  +#if ARENA_DOD_FLAGS
  +            if (! (i & ARENA_FLAG_MASK)) {
  +                /* reset live bits for previous bunch of objects */
  +                if (i)
  +                    *dod_flags &= ~ALL_LIVE_MASK;
  +                ++dod_flags;
  +                /* if all are on free list, skip one bunch */
  +                if (*dod_flags == ALL_FREE_MASK) {  /* all on free list */
  +                    i += ARENA_FLAG_MASK;       /* + 1 in loop */
  +                    b = (Buffer *)((char *)b + object_size*(ARENA_FLAG_MASK+1));
  +                    continue;
  +                }
  +                nm = 0;
  +            }
  +            else
  +                nm += 4;
               /* If it's not live or on the free list, put it on the free list.
                * Note that it is technically possible to have a Buffer be both
                * on_free_list and live, because of our conservative stack-walk
                * collection. We must be wary of this case. */
  -            if (!PObj_is_live_or_free_TESTALL(b)) {
  +
  +            if ((*dod_flags & (PObj_on_free_list_FLAG << nm)))
  +                ; /* if its on free list, do nothing */
  +            else if ((*dod_flags & (PObj_live_FLAG << nm)))
  +#else
  +            if (PObj_on_free_list_TEST(b))
  +                ; /* if its on free list, do nothing */
  +            else if (PObj_is_live_TEST(b))
  +#endif
  +            {
  +                /* its live */
  +                total_used++;
  +#if ARENA_DOD_FLAGS
  +                if ((*dod_flags & (PObj_is_impatient_FLAG << nm)))
  +                    interpreter->impatient_things = 1;
  +#else
  +                PObj_live_CLEAR(b);
  +                if (PObj_is_impatient_TEST(b))
  +                    interpreter->impatient_things = 1;
  +#endif
  +            }
  +            else {
  +                /* it must be dead */
   #if GC_VERBOSE
                   if (GC_DEBUG(interpreter) && PObj_report_TEST(b))
                       fprintf(stderr, "Freeing pobject %p -> %p\n",
  @@ -350,17 +497,35 @@
   #endif
                   /* if object is a PMC and needs destroying */
                   if (PObj_is_PMC_TEST(b)) {
  -                    /* then destroy it here, add_free_pmc is called from
  -                     * more_objects too
  +                    /* then destroy it here
                        */
                       if (PObj_active_destroy_TEST(b))
                           VTABLE_destroy(interpreter, (PMC *)b);
  +
  +                    if (PObj_is_PMC_EXT_TEST(b)) {
  +                        /* if the PMC has a PMC_EXT structure,
  +                         * return it to the pool/arena
  +                         */
  +#if ARENA_DOD_FLAGS
  +                        struct Small_Object_Arena *ext_arena =
  +                            GET_ARENA(((PMC *)b)->pmc_ext);
  +                        ext_arena->pool->
  +                            add_free_object(interpreter, ext_arena,
  +                                    ((PMC *)b)->pmc_ext);
  +#else
  +                        struct Small_Object_Pool *ext_pool =
  +                            interpreter->arena_base->pmc_ext_pool;
  +                        ext_pool->add_free_object(interpreter, ext_pool,
  +                                ((PMC *)b)->pmc_ext);
  +#endif
  +                    }
                   }
                   /* else object is a buffer(like) */
                   else if (PObj_sysmem_TEST(b) && b->bufstart) {
                       /* has sysmem allocated, e.g. string_pin */
                       mem_sys_free(b->bufstart);
  -                    memset(b + 1, 0, wash_size);
  +                    b->bufstart = NULL;
  +                    b->buflen = 0;
                   }
                   else {
   #ifdef GC_IS_MALLOC
  @@ -385,28 +550,53 @@
                       ((struct Memory_Pool *)
                        pool->mem_pool)->possibly_reclaimable += b->buflen;
   #endif
  -                    /*
  -                     * clean memory for buffer_likes
  -                     * this is the slow thing in the whole sub, so PMCs
  -                     * have their own add_free function, which clears
  -                     * PMC specific data members
  -                     */
  -                    memset(b + 1, 0, wash_size);
  +                    b->buflen = 0;
                   }
  +#if ARENA_DOD_FLAGS
  +                *dod_flags |= PObj_on_free_list_FLAG << nm;
  +                pool->add_free_object(interpreter, cur_arena, b);
  +#else
                   pool->add_free_object(interpreter, pool, b);
  -            }
  -            else if (!PObj_on_free_list_TEST(b)) {
  -                /* should be live then */
  -                total_used++;
  -                PObj_live_CLEAR(b);
  -                if (PObj_is_impatient_TEST(b)) {
  -                    interpreter->impatient_things++;
  -                }
  +#endif
               }
               b = (Buffer *)((char *)b + object_size);
           }
  +#if ARENA_DOD_FLAGS
  +        /* reset live bits on last bunch of objects */
  +        *dod_flags &= ~ALL_LIVE_MASK;
  +#  if REDUCE_ARENAS
  +        /* not strictly only for ARENA_DOD_FLAGS, but
  +         * live_objects is only defined there
  +         */
  +        if ( (cur_arena->live_objects = total_used - old_total_used) == 0)
  +            ++free_arenas;
  +        old_total_used = total_used;
  +#  endif
  +#endif
       }
       pool->num_free_objects = pool->total_objects - total_used;
  +#if ARENA_DOD_FLAGS
  +#  if REDUCE_ARENAS
  +#define REPLENISH_LEVEL_FACTOR 0.3
  +    if (free_arenas > 1) {
  +        debug(("pool %s: %d free_arenas\n", pool->name, (int)free_arenas));
  +        pool->replenish_level =
  +            (size_t)(pool->total_objects * REPLENISH_LEVEL_FACTOR);
  +        i = 0;
  +        while (pool->num_free_objects - i * pool->last_Arena->used *
  +                REPLENISH_LEVEL_FACTOR > pool->replenish_level &&
  +                i < free_arenas)
  +            ++i;
  +        debug(("\t may free %d\n", (int)i));
  +        reduce_arenas(interpreter, pool, i-1);
  +        pool->replenish_level =
  +            (size_t)(pool->total_objects * REPLENISH_LEVEL_FACTOR);
  +        pool->num_free_objects = pool->total_objects - total_used;
  +        pool->skip = 0;
  +    }
  +#  undef debug
  +#  endif
  +#endif
   }
   
   #ifndef PLATFORM_STACK_WALK
  @@ -503,6 +693,14 @@
       }
       Parrot_block_DOD(interpreter);
   
  +#if ARENA_DOD_FLAGS
  +    clear_live_counter(interpreter, interpreter->arena_base->pmc_pool);
  +    for (j = 0; j < (INTVAL)interpreter->arena_base->num_sized; j++) {
  +        header_pool = interpreter->arena_base->sized_header_pools[j];
  +        if (header_pool)
  +            clear_live_counter(interpreter, header_pool);
  +    }
  +#endif
       /* Now go trace the PMCs */
       trace_active_PMCs(interpreter);
   
  
  
  
  1.34      +57 -10    parrot/headers.c
  
  Index: headers.c
  ===================================================================
  RCS file: /cvs/public/parrot/headers.c,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -w -r1.33 -r1.34
  --- headers.c 13 Jan 2003 17:04:48 -0000      1.33
  +++ headers.c 6 Jun 2003 08:29:18 -0000       1.34
  @@ -1,7 +1,7 @@
   /* headers.c
    *  Copyright: (When this is determined...it will go here)
    *  CVS Info
  - *     $Id: headers.c,v 1.33 2003/01/13 17:04:48 leo Exp $
  + *     $Id: headers.c,v 1.34 2003/06/06 08:29:18 leo Exp $
    *  Overview:
    *     Header management functions. Handles getting of various headers,
    *     and pool creation
  @@ -39,8 +39,8 @@
       /* clear flags, set is_PMC_FLAG */
       PObj_flags_SETTO(pmc, PObj_is_PMC_FLAG);
       ((PMC *)pmc)->data = NULL;
  -    ((PMC *)pmc)->metadata = NULL;
  -    ((PMC *)pmc)->synchronize = NULL;
  +    ((PMC *)pmc)->pmc_ext = NULL;
  +    /* TODO check PMCs init method, if they clear the cache */
       return pmc;
   }
   
  @@ -52,11 +52,8 @@
   {
       Buffer *buffer = get_free_object(interpreter, pool);
   
  -    /* Don't let it point to garbage memory */
  -    buffer->bufstart = NULL;
  -    buffer->buflen = 0;
  -    /* Clear the flagpole (especially _on_free_list_FLAG) */
  -    PObj_flags_CLEARALL(buffer);
  +    memset(buffer, 0, pool->object_size);
  +    SET_NULL(buffer->bufstart);
       return buffer;
   }
   
  @@ -169,6 +166,24 @@
       return get_free_pmc(interpreter, interpreter->arena_base->pmc_pool);
   }
   
  +
  +PMC_EXT *
  +new_pmc_ext(struct Parrot_Interp *interpreter)
  +{
  +    struct Small_Object_Pool *pool = interpreter->arena_base->pmc_ext_pool;
  +    void *ptr = get_free_object(interpreter, pool);
  +    memset(ptr, 0, sizeof(PMC_EXT));
  +    return ptr;
  +}
  +
  +void
  +add_pmc_ext(struct Parrot_Interp *interpreter, PMC *pmc)
  +{
  +    pmc->pmc_ext = new_pmc_ext(interpreter);
  +    PObj_is_PMC_EXT_SET(pmc);
  +}
  +
  +
   STRING *
   new_string_header(struct Parrot_Interp *interpreter, UINTVAL flags)
   {
  @@ -308,6 +323,8 @@
       /* Init the constant string header pool */
       interpreter->arena_base->constant_string_header_pool =
               new_string_pool(interpreter, 1);
  +    interpreter->arena_base->constant_string_header_pool->name =
  +        "constant_string_header";
   
   
       /* Init the buffer header pool
  @@ -317,14 +334,23 @@
        * here for faster access in new_*_header
        */
       interpreter->arena_base->buffer_header_pool = new_buffer_pool(interpreter);
  +    interpreter->arena_base->buffer_header_pool->name = "buffer_header";
   
       /* Init the string header pool */
       interpreter->arena_base->string_header_pool =
               new_string_pool(interpreter, 0);
  +    interpreter->arena_base->string_header_pool->name = "string_header";
   
       /* Init the PMC header pool */
       interpreter->arena_base->pmc_pool = new_pmc_pool(interpreter);
  +    interpreter->arena_base->pmc_pool->name = "pmc";
  +    interpreter->arena_base->pmc_ext_pool =
  +        new_small_object_pool(interpreter, sizeof(struct PMC_EXT), 1024);
  +    interpreter->arena_base->pmc_ext_pool->more_objects =
  +        alloc_objects;
  +    interpreter->arena_base->pmc_ext_pool->name = "pmc_ext";
       interpreter->arena_base->constant_pmc_pool = new_pmc_pool(interpreter);
  +    interpreter->arena_base->constant_pmc_pool->name = "constant_pmc";
       interpreter->arena_base->constant_pmc_pool->objects_per_alloc =
          CONSTANT_PMC_HEADERS_PER_ALLOC;
   }
  @@ -336,8 +362,17 @@
       struct Small_Object_Arena *cur_arena, *next;
       int i, j, start;
   
  -    /* const/non const COW strings live in different pools * so in first pass
  -     * * * * COW refcount is done, in 2. refcounting * in 3rd freeing */
  +    /* TODO: -lt make a command line option for cleaning up:
  +     * - the last interpreter may just die
  +     * - created interpreters should always get destroyed
  +     * - move the check to interpreter.c
  +    */
  +    return;
  +    /* const/non const COW strings life in different pools
  +     * so in first pass
  +     * COW refcount is done, in 2. refcounting
  +     * in 3rd freeing
  +     */
   #ifdef GC_IS_MALLOC
       start = 0;
   #else
  @@ -372,7 +407,9 @@
               if (i == 2 && pool) {
                   for (cur_arena = pool->last_Arena; cur_arena;) {
                       next = cur_arena->prev;
  +#if ! ARENA_DOD_FLAGS
                       mem_sys_free(cur_arena->start_objects);
  +#endif
                       mem_sys_free(cur_arena);
                       cur_arena = next;
                   }
  @@ -381,6 +418,16 @@
   
           }
       }
  +    pool = interpreter->arena_base->pmc_ext_pool;
  +    for (cur_arena = pool->last_Arena; cur_arena;) {
  +        next = cur_arena->prev;
  +#if ! ARENA_DOD_FLAGS
  +        mem_sys_free(cur_arena->start_objects);
  +#endif
  +        mem_sys_free(cur_arena);
  +        cur_arena = next;
  +    }
  +    mem_sys_free(interpreter->arena_base->pmc_ext_pool);
       mem_sys_free(interpreter->arena_base->sized_header_pools);
   }
   
  
  
  
  1.154     +17 -13    parrot/interpreter.c
  
  Index: interpreter.c
  ===================================================================
  RCS file: /cvs/public/parrot/interpreter.c,v
  retrieving revision 1.153
  retrieving revision 1.154
  diff -u -w -r1.153 -r1.154
  --- interpreter.c     1 Jun 2003 00:17:44 -0000       1.153
  +++ interpreter.c     6 Jun 2003 08:29:18 -0000       1.154
  @@ -1,7 +1,7 @@
   /* interpreter.c
    *  Copyright: (When this is determined...it will go here)
    *  CVS Info
  - *     $Id: interpreter.c,v 1.153 2003/06/01 00:17:44 josh Exp $
  + *     $Id: interpreter.c,v 1.154 2003/06/06 08:29:18 leo Exp $
    *  Overview:
    *     The interpreter api handles running the operations
    *  Data Structure and Algorithms:
  @@ -28,6 +28,9 @@
   
   #define ATEXIT_DESTROY
   
  +#define PREDEREF_NORMAL         0
  +#define PREDEREF_FOR_CGP        1
  +#define PREDEREF_FOR_SWITCH     2
   
   static void setup_default_compreg(Parrot_Interp interpreter);
   
  @@ -124,7 +127,8 @@
               break;
   
           case PARROT_ARG_S:
  -            pc_prederef[i] = (void *)&interpreter->ctx.string_reg.registers[pc[i]];
  +            pc_prederef[i] =
  +                (void *)&interpreter->ctx.string_reg.registers[pc[i]];
               break;
   
           case PARROT_ARG_KIC:
  @@ -159,7 +163,7 @@
               break;
           }
   
  -        if (opinfo->types[i] != PARROT_ARG_IC && pc_prederef[i] == 0) {
  +        if (pc_prederef[i] == 0) {
               internal_exception(INTERP_ERROR,
                                  "Prederef generated a NULL pointer for arg of type 
%d!\n",
                                  opinfo->types[i]);
  @@ -197,8 +201,8 @@
       if (!interpreter->prederef_code) {
           size_t N = interpreter->code->cur_cs->base.size;
           size_t i;
  -        /* void **temp = (void **)mem_sys_allocate(N * sizeof(void *)); */
  -        void **temp = (void **)Parrot_memalign(256, N * sizeof(void *));
  +        void **temp = (void **)Parrot_memalign_if_possible(256,
  +                N * sizeof(void *));
   
           for (i = 0; i < N; i++) {
               temp[i] = (void *)(ptrcast_t)prederef;
  @@ -206,7 +210,7 @@
   
           interpreter->prederef_code = temp;
           interpreter->code->cur_cs->prederef_code = temp;
  -        if (cgp == 2) {
  +        if (cgp == PREDEREF_FOR_SWITCH) {
               opcode_t *pc = interpreter->code->cur_cs->base.data;
               size_t n;
               for (i = 0; i < N; ) {
  @@ -219,7 +223,7 @@
               }
           }
   #ifdef HAVE_COMPUTED_GOTO
  -        if (cgp == 1) {
  +        if (cgp == PREDEREF_FOR_CGP) {
               opcode_t *pc = interpreter->code->cur_cs->base.data;
               size_t n;
               for (i = 0; i < N; ) {
  @@ -261,7 +265,7 @@
   #  ifdef HAVE_COMPUTED_GOTO
   #    ifdef __GNUC__
   #      ifdef I386
  -    init_prederef(interpreter, 1);
  +    init_prederef(interpreter, PREDEREF_FOR_CGP);
   #      endif
   #    endif
   #  endif
  @@ -298,7 +302,7 @@
       opcode_t *code_start = (opcode_t *)interpreter->code->byte_code;
       void **pc_prederef;
   
  -    init_prederef(interpreter, 0);
  +    init_prederef(interpreter, PREDEREF_NORMAL);
       pc_prederef = interpreter->prederef_code + (pc - code_start);
   
       while (pc_prederef) {
  @@ -317,7 +321,7 @@
   #ifdef HAVE_COMPUTED_GOTO
       opcode_t *code_start = (opcode_t *)interpreter->code->byte_code;
       void **pc_prederef;
  -    init_prederef(interpreter, 1);
  +    init_prederef(interpreter, PREDEREF_FOR_CGP);
       pc_prederef = interpreter->prederef_code + (pc - code_start);
       pc = cgp_core((opcode_t*)pc_prederef, interpreter);
       return pc;
  @@ -334,7 +338,7 @@
   {
       opcode_t *code_start = (opcode_t *)interpreter->code->byte_code;
       void **pc_prederef;
  -    init_prederef(interpreter, 2);
  +    init_prederef(interpreter, PREDEREF_FOR_SWITCH);
       pc_prederef = interpreter->prederef_code + (pc - code_start);
       pc = switch_core((opcode_t*)pc_prederef, interpreter);
       return pc;
  
  
  
  1.12      +4 -4      parrot/jit_debug.c
  
  Index: jit_debug.c
  ===================================================================
  RCS file: /cvs/public/parrot/jit_debug.c,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -w -r1.11 -r1.12
  --- jit_debug.c       1 Jun 2003 00:17:44 -0000       1.11
  +++ jit_debug.c       6 Jun 2003 08:29:18 -0000       1.12
  @@ -1,7 +1,7 @@
   /*
    * jit_debug.c
    *
  - * $Id: jit_debug.c,v 1.11 2003/06/01 00:17:44 josh Exp $
  + * $Id: jit_debug.c,v 1.12 2003/06/06 08:29:18 leo Exp $
    *
    * write stabs file for jit code
    * when debugging jit code with gdb, do:
  @@ -149,8 +149,8 @@
               i + 3, BIT_OFFSET(PMC, vtable), BIT_SIZE(void*));
       fprintf(stabs, "data:(0,14),%d,%d;",
               BIT_OFFSET(PMC, data), BIT_SIZE(void*));
  -    fprintf(stabs, "metadata:*(0,%d),%d,%d;",
  -            i, BIT_OFFSET(PMC, metadata), BIT_SIZE(void*));
  +    fprintf(stabs, "pmc_ext:*(0,%d),%d,%d;",
  +            i, BIT_OFFSET(PMC, pmc_ext), BIT_SIZE(void*));
       fprintf(stabs, ";\"");
       fprintf(stabs, "," N_LSYM ",0,0,0\n");
   
  
  
  
  1.23      +16 -2     parrot/pmc.c
  
  Index: pmc.c
  ===================================================================
  RCS file: /cvs/public/parrot/pmc.c,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -w -r1.22 -r1.23
  --- pmc.c     19 May 2003 13:06:52 -0000      1.22
  +++ pmc.c     6 Jun 2003 08:29:18 -0000       1.23
  @@ -1,7 +1,7 @@
   /* pmc.c
    *  Copyright: (When this is determined...it will go here)
    *  CVS Info
  - *     $Id: pmc.c,v 1.22 2003/05/19 13:06:52 leo Exp $
  + *     $Id: pmc.c,v 1.23 2003/06/06 08:29:18 leo Exp $
    *  Overview:
    *     The base vtable calling functions.
    *  Data Structure and Algorithms:
  @@ -73,8 +73,22 @@
   PMC *
   pmc_new_noinit(struct Parrot_Interp *interpreter, INTVAL base_type)
   {
  -    return get_new_pmc_header(interpreter, base_type,
  +    PMC *pmc = get_new_pmc_header(interpreter, base_type,
               interpreter->arena_base->pmc_pool);
  +    switch (base_type) {
  +        case enum_class_PerlInt:
  +        case enum_class_PerlNum:
  +        case enum_class_PerlString:
  +        case enum_class_PerlUndef:
  +            break;
  +        default:
  +            /* TODO optimize this, mainly only aggregates need
  +             * the extra header part
  +             */
  +            add_pmc_ext(interpreter, pmc);
  +            break;
  +    }
  +    return pmc;
   }
   
   /*=for api pmc constant_pmc_new_noinit
  
  
  
  1.106     +4 -4      parrot/resources.c
  
  Index: resources.c
  ===================================================================
  RCS file: /cvs/public/parrot/resources.c,v
  retrieving revision 1.105
  retrieving revision 1.106
  diff -u -w -r1.105 -r1.106
  --- resources.c       10 Feb 2003 15:29:15 -0000      1.105
  +++ resources.c       6 Jun 2003 08:29:18 -0000       1.106
  @@ -1,7 +1,7 @@
   /* resources.c
    *  Copyright: (When this is determined...it will go here)
    *  CVS Info
  - *     $Id: resources.c,v 1.105 2003/02/10 15:29:15 scog Exp $
  + *     $Id: resources.c,v 1.106 2003/06/06 08:29:18 leo Exp $
    *  Overview:
    *     Allocate and deallocate tracked resources
    *  Data Structure and Algorithms:
  @@ -213,7 +213,7 @@
   
               for (i = 0; i < cur_buffer_arena->used; i++) {
                   /* ! (immobile | on_free_list | constant | external) */
  -                if (b->bufstart && PObj_is_movable_TESTALL(b)) {
  +                if (b->buflen && PObj_is_movable_TESTALL(b)) {
                       struct Buffer_Tail *tail =
                               (struct Buffer_Tail *)((char *)b->bufstart +
                               b->buflen);
  
  
  
  1.22      +187 -19   parrot/smallobject.c
  
  Index: smallobject.c
  ===================================================================
  RCS file: /cvs/public/parrot/smallobject.c,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -w -r1.21 -r1.22
  --- smallobject.c     13 Jan 2003 17:04:48 -0000      1.21
  +++ smallobject.c     6 Jun 2003 08:29:18 -0000       1.22
  @@ -1,7 +1,7 @@
   /* resources.c
    *  Copyright: (When this is determined...it will go here)
    *  CVS Info
  - *     $Id: smallobject.c,v 1.21 2003/01/13 17:04:48 leo Exp $
  + *     $Id: smallobject.c,v 1.22 2003/06/06 08:29:18 leo Exp $
    *  Overview:
    *     Handles the accessing of small object pools (header pools)
    *  Data Structure and Algorithms:
  @@ -13,6 +13,7 @@
    */
   
   #include "parrot/parrot.h"
  +#include <assert.h>
   
   #define GC_DEBUG_REPLENISH_LEVEL_FACTOR 0.0
   #define GC_DEBUG_UNITS_PER_ALLOC_GROWTH_FACTOR 1
  @@ -33,24 +34,39 @@
   
           if (0 <= ptr_diff
                   && ptr_diff <
  -                (ptrdiff_t)(arena->total_objects * pool->object_size)
  +                (ptrdiff_t)(arena->used * pool->object_size)
                   && ptr_diff % pool->object_size == 0)
               return 1;
       }
       return 0;
   }
   
  +static int find_free_list(struct Small_Object_Pool *pool);
  +
   /* We're out of traceable objects. Try a DOD, then get some more if needed */
   void
   more_traceable_objects(struct Parrot_Interp *interpreter,
           struct Small_Object_Pool *pool)
   {
  +    if (pool->skip)
  +        pool->skip = 0;
  +    else {
       Parrot_do_dod_run(interpreter);
  +        if (pool->num_free_objects <= pool->replenish_level)
  +            pool->skip = 1;
  +    }
  +
       /* requires that num_free_objects be updated in Parrot_do_dod_run. If dod
        * is disabled, then we must check the free list directly. */
  -    if (!pool->free_list || pool->num_free_objects <= pool->replenish_level) {
  +#if  ARENA_DOD_FLAGS
  +    if (!find_free_list(pool)) {
  +        (*pool->alloc_objects) (interpreter, pool);
  +    }
  +#else
  +    if (!pool->free_list) {
           (*pool->alloc_objects) (interpreter, pool);
       }
  +#endif
   }
   
   /* We're out of non-traceable objects. Get some more */
  @@ -61,6 +77,59 @@
       (*pool->alloc_objects) (interpreter, pool);
   }
   
  +#if  ARENA_DOD_FLAGS
  +static int
  +find_free_list(struct Small_Object_Pool *pool)
  +{
  +    struct Small_Object_Arena *arena;
  +
  +    for (arena = pool->last_Arena; arena; arena = arena->prev) {
  +        if (arena->free_list) {
  +            pool->free_arena = arena;
  +            return 1;
  +        }
  +    }
  +    return 0;
  +}
  +
  +void
  +add_free_object(struct Parrot_Interp *interpreter,
  +        struct Small_Object_Arena *arena, void *to_add)
  +{
  +    *(void **)to_add = arena->free_list;
  +    arena->free_list = to_add;
  +}
  +
  +/* Get a new object from the free pool and return it */
  +void *
  +get_free_object(struct Parrot_Interp *interpreter,
  +        struct Small_Object_Pool *pool)
  +{
  +    void *ptr;
  +    struct Small_Object_Arena *arena;
  +    size_t n;
  +
  +    /* if we don't have any objects */
  +    if (!pool->free_arena)
  +        (*pool->alloc_objects) (interpreter, pool);
  +    if (!pool->free_arena->free_list)
  +        if (!find_free_list(pool))
  +            (*pool->more_objects) (interpreter, pool);
  +
  +    arena = pool->free_arena;
  +    ptr = arena->free_list;
  +    arena->free_list = *(void **)ptr;
  +    n = GET_OBJ_N(arena, ptr);
  +    arena->dod_flags[ n >> ARENA_FLAG_SHIFT ] &=
  +         ~((PObj_on_free_list_FLAG << (( n & ARENA_FLAG_MASK ) << 2)));
  +#if ! DISABLE_GC_DEBUG
  +    if (GC_DEBUG(interpreter))
  +        ((Buffer*)ptr)->version++;
  +#endif
  +    return ptr;
  +}
  +
  +#else
   /* Add an unused object back to the free pool for later reuse */
   void
   add_free_object(struct Parrot_Interp *interpreter,
  @@ -69,7 +138,6 @@
       PObj_flags_SETTO((PObj *)to_add, PObj_on_free_list_FLAG);
       *(void **)to_add = pool->free_list;
       pool->free_list = to_add;
  -    pool->num_free_objects++;
   }
   
   /* Get a new object from the free pool and return it */
  @@ -85,13 +153,56 @@
   
       ptr = pool->free_list;
       pool->free_list = *(void **)ptr;
  -    pool->num_free_objects--;
   #if ! DISABLE_GC_DEBUG
       if (GC_DEBUG(interpreter))
           ((Buffer*)ptr)->version++;
   #endif
       return ptr;
   }
  +#endif
  +
  +
  +static void
  +add_to_free_list(struct Parrot_Interp *interpreter,
  +        struct Small_Object_Pool *pool,
  +        struct Small_Object_Arena *arena,
  +        UINTVAL start,
  +        UINTVAL end)
  +{
  +#if ARENA_DOD_FLAGS
  +    UINTVAL *dod_flags;
  +#endif
  +    UINTVAL i;
  +    void *object;
  +
  +    pool->total_objects += end - start;
  +    arena->used = end;
  +
  +    /* Move all the new objects into the free list */
  +    object = (void *)((char *)arena->start_objects +
  +            start * pool->object_size);
  +#if ARENA_DOD_FLAGS
  +    pool->replenish_level =
  +                (size_t)(pool->total_objects * REPLENISH_LEVEL_FACTOR);
  +    dod_flags = arena->dod_flags + (start >> ARENA_FLAG_SHIFT);
  +#endif
  +    for (i = start; i < end; i++) {
  +#if ARENA_DOD_FLAGS
  +        if (! (i & ARENA_FLAG_MASK)) {
  +            *dod_flags = ALL_FREE_MASK;
  +            ++dod_flags;
  +        }
  +        pool->add_free_object (interpreter, arena, object);
  +#else
  +        pool->add_free_object (interpreter, pool, object);
  +#endif
  +        object = (void *)((char *)object + pool->object_size);
  +    }
  +#if ARENA_DOD_FLAGS
  +    /* set last */
  +    *dod_flags = ALL_FREE_MASK;
  +#endif
  +}
   
   /* We have no more headers on the free header pool. Go allocate more
    * and put them on */
  @@ -100,14 +211,60 @@
           struct Small_Object_Pool *pool)
   {
       struct Small_Object_Arena *new_arena;
  -    void *object;
  -    UINTVAL i;
  -    size_t size = pool->object_size * pool->objects_per_alloc;
  -
  -    new_arena = mem_sys_allocate(sizeof(struct Small_Object_Arena));
  +    size_t size;
  +    UINTVAL start, end;
   
       /* Setup memory for the new objects */
  +#if ARENA_DOD_FLAGS
  +    size_t offset;
  +
  +    /* check old arena first */
  +    if (pool->last_Arena &&
  +            pool->last_Arena->used < pool->last_Arena->total_objects) {
  +        start = pool->last_Arena->used;
  +        end = start << 2;
  +        if (end > pool->last_Arena->total_objects)
  +            end = pool->last_Arena->total_objects;
  +        add_to_free_list(interpreter, pool, pool->last_Arena, start, end);
  +        return;
  +    }
  +
  +    size = ARENA_SIZE;
  +    /*
  +     * [ Note: Linux ]
  +     * Albeit we reserve 8 pools with 4MB each, the memory footprint
  +     * of a running program is much smaller, if only a few objects per pool
  +     * are used. The unused pages of the arenas are only mapped (they use space
  +     * in the page tables, but no physical memory).
  +     * Because of the COW pages strategy of the kernel, there shouldn't
  +     * be a problem with many running instances too at least if these get
  +     * fork'ed or were created as threads.
  +     * For many unique parrot processes, you might either reduce ARENA_SIZE
  +     * or turn off ARENA_DOD_FLAGS.
  +     */
  +    new_arena = Parrot_memalign(ARENA_ALIGN, size);
  +    /* offset in bytes of whole Objects */
  +    offset = ( 1 + sizeof(struct Small_Object_Arena) / pool->object_size) *
  +        pool->object_size;
  +    new_arena->start_objects = (char *)new_arena + offset;
  +    size -= offset;
  +    pool->objects_per_alloc = size / pool->object_size;
  +    new_arena->object_size = pool->object_size;
  +#ifdef SIMULATE_DIRTY_AND_RUN_SLOW
  +    /* memory gets washed in get_free_*, so we don't need zeroed
  +     * memory here
  +     */
  +    memset(new_arena->start_objects, 0xff, size); /* simulate dirty */
  +#endif
  +    new_arena->dod_flags = mem_sys_allocate(ARENA_FLAG_SIZE(pool));
  +    new_arena->pool = pool;
  +    new_arena->free_list = NULL;
  +#else
  +    new_arena = mem_sys_allocate(sizeof(struct Small_Object_Arena));
  +    size = pool->object_size * pool->objects_per_alloc;
  +    /* could be mem_sys_allocate too, but calloc is fast */
       new_arena->start_objects = mem_sys_allocate_zeroed(size);
  +#endif
   
       /* Maintain the *_arena_memory invariant for stack walking code. Set it
        * regardless if we're the first pool to be added. */
  @@ -120,7 +277,22 @@
           pool->end_arena_memory = (size_t)new_arena->start_objects + size;
   
       /* Hook up the new object block into the object pool */
  -    new_arena->used = pool->objects_per_alloc;
  +#if ARENA_DOD_FLAGS
  +    /* not the first one - put all on free list */
  +    if (pool->last_Arena) {
  +        start = 0;
  +        end = pool->objects_per_alloc;
  +    }
  +    else {
  +        /* first arena, start with x objects */
  +        start = 0;
  +        end = 1024;
  +    }
  +    pool->free_arena = new_arena;
  +#else
  +    start = 0;
  +    end = pool->objects_per_alloc;
  +#endif
       new_arena->total_objects = pool->objects_per_alloc;
       new_arena->next = NULL;
       new_arena->prev = pool->last_Arena;
  @@ -130,14 +302,9 @@
       pool->last_Arena = new_arena;
       interpreter->header_allocs_since_last_collect++;
   
  -    /* Move all the new objects into the free list */
  -    object = new_arena->start_objects;
  -    for (i = 0; i < pool->objects_per_alloc; i++) {
  -        add_free_object (interpreter, pool, object);
  -        object = (void *)((char *)object + pool->object_size);
  -    }
  -    pool->total_objects += pool->objects_per_alloc;
  +    add_to_free_list(interpreter, pool, new_arena, start, end);
   
  +#if ! ARENA_DOD_FLAGS
       /* Allocate more next time */
       if (GC_DEBUG(interpreter)) {
           pool->objects_per_alloc *= GC_DEBUG_UNITS_PER_ALLOC_GROWTH_FACTOR;
  @@ -156,6 +323,7 @@
       if (size > POOL_MAX_BYTES) {
           pool->objects_per_alloc = POOL_MAX_BYTES / pool->object_size;
       }
  +#endif
   }
   
   struct Small_Object_Pool *
  
  
  

Reply via email to