# New Ticket Created by  Mike Lambert 
# Please include the string:  [perl #809]
# in the subject line of all future correspondence about this issue. 
# <URL: http://bugs6.perl.org/rt2/Ticket/Display.html?id=809 >


Okay, patch is included below. Here are the relevant times from the gc
bench suite:
gc_alloc_reuse.pbc      12.058001       12.056999
gc_generations.pbc      3.964999        5.769
gc_header_new.pbc       3.924999        3.924999
gc_waves_headers.pbc    0.871997        0.871999
gc_waves_sizeable_data.pbc      7.059   7.140001
gc_waves_sizeable_headers.pbc   5.316999        5.358

I believe gc_generations is slower due to the many DOD calls that are
performed (and each DOD requires a stack walk). In general,
the stack-walk makes the new version a little bit slower, or perhaps the
same, in all cases.

Note that the patch implementation is a bit ugly because of the seperation
of pmc and header pools. I have another GC refactoring patch in the wings
which should remedy this situation.

Also note the problem I mentioned earlier, which may very well crop it's
head up with this patch under 'real-world' conditions. See below sig.

Mike Lambert

> Also, I think I've discovered a situation which might not be
> resolvable. How do we determine id a given buffer is alive? We walk the
> stack and check for potential pointers into buffer memory. If the stack
> contains garbage pointers, we might have bad references into buffer
> memory. I can check for alignment within the buffer pool, and so it should
> be safe to set the BUFFER_live_FLAG on them.
>
> However, when we perform a collection, that means that we could be taking
> a garbage pointer in the buffer, and attempting to copy the memory it
> pointed to, into new memory.
>
> This could give us GPFs if we access bad memory, I think. Even if we check
> to ensure the buffer points into valid collectable memory (making it
> slower), we still have the issue of buflen being set to MAX_INT or
> something, and killing the system. :|
>
> The same caveats apply to pmc headers which happen to have
> PMC_buffer_ptr_FLAG set.
>
> How should we get around this particular problem, or is it spelling the
> doom of this particular solution?
>
> Thanks,
> Mike Lambert


-- attachment  1 ------------------------------------------------------
url: http://bugs6.perl.org/rt2/attach/3798/3520/778163/diff.txt

? vc60.pdb

? parrot.pdb

? classes/vc60.pdb

? lib/Parrot/PakFile2.def

Index: interpreter.c

===================================================================

RCS file: /cvs/public/parrot/interpreter.c,v

retrieving revision 1.91

diff -u -r1.91 interpreter.c

--- interpreter.c       4 Jul 2002 20:39:44 -0000       1.91

+++ interpreter.c       13 Jul 2002 09:10:52 -0000

@@ -404,6 +404,8 @@

 runops(struct Parrot_Interp *interpreter, struct PackFile *code, size_t offset)

 {

     opcode_t *(*core) (struct Parrot_Interp *, opcode_t *);

+    void *dummy_ptr;

+    interpreter->lo_var_ptr = &dummy_ptr;

 

     interpreter->code = code;

     interpreter->resume_offset = offset;

Index: resources.c

===================================================================

RCS file: /cvs/public/parrot/resources.c,v

retrieving revision 1.72

diff -u -r1.72 resources.c

--- resources.c 4 Jul 2002 20:39:44 -0000       1.72

+++ resources.c 13 Jul 2002 09:10:56 -0000

@@ -123,6 +123,7 @@

         mem_sys_allocate(sizeof(PMC) * pool->units_per_alloc);

     memset(new_arena->start_PMC, 0, sizeof(PMC) * pool->units_per_alloc);

     new_arena->used = pool->units_per_alloc;

+    new_arena->total = pool->units_per_alloc;

     new_arena->next = NULL;

     new_arena->prev = pool->last_Arena;

     /* Is there a previous arena */

@@ -132,6 +133,12 @@

 

     pool->last_Arena = new_arena;

 

+    if (pool->start_arena_memory > new_arena->start_PMC)

+        pool->start_arena_memory = new_arena->start_PMC;

+

+    if (pool->end_arena_memory < new_arena->start_PMC + sizeof(PMC) * 
+pool->units_per_alloc)

+        pool->end_arena_memory = new_arena->start_PMC + sizeof(PMC) * 
+pool->units_per_alloc;

+

     /* Note it in our stats */

     interpreter->total_PMCs += pool->units_per_alloc;

 

@@ -200,6 +207,7 @@

     memset(new_arena->start_Buffer, 0, 

            pool->unit_size * pool->units_per_alloc);

     new_arena->used = pool->units_per_alloc;

+    new_arena->total = pool->units_per_alloc;

     new_arena->next = NULL;

     new_arena->prev = pool->last_Arena;

     /* Is there a previous arena */

@@ -209,6 +217,12 @@

 

     pool->last_Arena = new_arena;

 

+    if (pool->start_arena_memory > new_arena->start_Buffer)

+        pool->start_arena_memory = new_arena->start_Buffer;

+

+    if (pool->end_arena_memory < new_arena->start_Buffer + sizeof(Buffer) * 
+pool->units_per_alloc)

+        pool->end_arena_memory = new_arena->start_Buffer + sizeof(Buffer) * 
+pool->units_per_alloc;

+

     /* Note it in our stats */

     interpreter->total_Buffers += pool->units_per_alloc;

 

@@ -298,6 +312,92 @@

     buffer->flags |= BUFFER_live_FLAG;

 }

 

+size_t

+get_max_buffer_address(struct Parrot_Interp *interpreter)

+{

+       UINTVAL i;

+    size_t max = interpreter->arena_base->string_header_pool->end_arena_memory;

+

+    if (max < interpreter->arena_base->buffer_header_pool->end_arena_memory)

+        max = interpreter->arena_base->buffer_header_pool->end_arena_memory;

+

+    if (max < interpreter->arena_base->constant_string_header_pool->end_arena_memory)
+
+        max = interpreter->arena_base->constant_string_header_pool->end_arena_memory;
+
+

+    for(i = 0; i<interpreter->arena_base->num_sized; i++) {

+        if (interpreter->arena_base->sized_header_pools[i]) {

+            if (max < 
+interpreter->arena_base->sized_header_pools[i]->end_arena_memory)

+                max = 
+interpreter->arena_base->sized_header_pools[i]->end_arena_memory;

+        }

+    }

+    

+    return max;

+}

+size_t

+get_min_buffer_address(struct Parrot_Interp *interpreter)

+{

+       UINTVAL i;

+    size_t min = interpreter->arena_base->string_header_pool->end_arena_memory;

+

+    if (min > interpreter->arena_base->buffer_header_pool->end_arena_memory)

+        min = interpreter->arena_base->buffer_header_pool->end_arena_memory;

+

+    if (min > interpreter->arena_base->constant_string_header_pool->end_arena_memory)
+
+        min = interpreter->arena_base->constant_string_header_pool->end_arena_memory;
+
+

+    for(i = 0; i<interpreter->arena_base->num_sized; i++) {

+        if (interpreter->arena_base->sized_header_pools[i]) {

+            if (min > 
+interpreter->arena_base->sized_header_pools[i]->end_arena_memory)

+                min = 
+interpreter->arena_base->sized_header_pools[i]->end_arena_memory;

+        }

+    }

+    

+    return min;

+}

+

+size_t

+get_max_pmc_address(struct Parrot_Interp *interpreter)

+{

+    return interpreter->arena_base->pmc_pool->end_arena_memory;

+}

+size_t

+get_min_pmc_address(struct Parrot_Interp *interpreter)

+{

+    return interpreter->arena_base->pmc_pool->start_arena_memory;

+}

+

+#ifndef PLATFORM_STACK_WALK

+PMC*

+trace_system_stack(struct Parrot_Interp *interpreter, PMC *last)

+{

+    size_t lo_var_ptr = (size_t)interpreter->lo_var_ptr;

+    size_t hi_var_ptr = (size_t)&lo_var_ptr;

+    size_t cur_var_ptr;

+    size_t direction = (hi_var_ptr > lo_var_ptr) ? 1 : -1;

+

+    size_t buffer_min = get_min_buffer_address(interpreter);

+    size_t buffer_max = get_max_buffer_address(interpreter);

+    size_t pmc_min = get_min_pmc_address(interpreter);

+    size_t pmc_max = get_max_pmc_address(interpreter);

+

+    if (!lo_var_ptr)

+        return last;

+    

+    for (cur_var_ptr = lo_var_ptr;

+         cur_var_ptr*direction<hi_var_ptr*direction;

+         cur_var_ptr += direction

+         ) {

+        size_t ptr = *(size_t *)cur_var_ptr;

+        if (pmc_min < ptr && ptr < pmc_max && is_pmc_ptr(interpreter,(void *)ptr)) {

+            last = mark_used((PMC *)ptr, last);

+        } else if (buffer_min < ptr && ptr < buffer_max && 
+is_buffer_ptr(interpreter,(void *)ptr)) {

+            buffer_lives((Buffer *)ptr);

+        }

+    }

+    return last;

+}

+#endif

+

 /* Do a full trace run and mark all the PMCs as active if they are */

 static void

 trace_active_PMCs(struct Parrot_Interp *interpreter)

@@ -318,6 +418,9 @@

     /* mark it as used and get an updated end of list */

     last = mark_used(current, last);

 

+       /* Find important stuff on the system stack */

+       last = trace_system_stack(interpreter,last);

+

     /* Now, go run through the PMC registers and mark them as live */

     /* First mark the current set. */

     for (i = 0; i < NUM_REGISTERS; i++) {

@@ -407,6 +510,61 @@

         prev = current;

     }

 }

+

+INTVAL

+contained_in_buffer_pool(struct Parrot_Interp *interpreter,

+            struct Resource_Pool *pool, void *ptr)

+{

+    struct Buffer_Arena *arena;

+    

+    for (arena = pool->last_Arena; arena; arena = arena->prev) {

+        size_t ptr_diff = (size_t)ptr - (size_t)arena->start_Buffer;

+        if (0 <= ptr_diff && ptr_diff < arena->total * sizeof(Buffer)

+        &&  ptr_diff % sizeof(Buffer) == 0)

+            return 1;

+    }

+    return 0;

+}

+INTVAL

+contained_in_pmc_pool(struct Parrot_Interp *interpreter,

+            struct Resource_Pool *pool, void *ptr)

+{

+    struct PMC_Arena *arena;

+    

+    for (arena = pool->last_Arena; arena; arena = arena->prev) {

+        size_t ptr_diff = (size_t)ptr - (size_t)arena->start_PMC;

+        if (0 <= ptr_diff && ptr_diff < arena->total * sizeof(PMC)

+        &&  ptr_diff % sizeof(PMC) == 0)

+            return 1;

+    }

+    return 0;

+}

+

+int

+is_buffer_ptr(struct Parrot_Interp *interpreter, void *ptr)

+{

+    UINTVAL i;

+    

+    if (contained_in_buffer_pool(interpreter, 

+                          interpreter->arena_base->string_header_pool, ptr))

+        return 1;

+    if (contained_in_buffer_pool(interpreter, 

+                          interpreter->arena_base->buffer_header_pool, ptr))

+        return 1;

+    if (contained_in_buffer_pool(interpreter, 

+                          interpreter->arena_base->constant_string_header_pool, ptr))
+
+        return 1;

+

+    return 0;

+}

+

+int

+is_pmc_ptr(struct Parrot_Interp *interpreter, void *ptr)

+{

+    return contained_in_pmc_pool(interpreter, 

+                             interpreter->arena_base->pmc_pool, ptr);

+}

+

 

 /* Scan any buffers in S registers and other non-PMC places and mark

  * them as active */

Index: include/parrot/interpreter.h

===================================================================

RCS file: /cvs/public/parrot/include/parrot/interpreter.h,v

retrieving revision 1.49

diff -u -r1.49 interpreter.h

--- include/parrot/interpreter.h        4 Jul 2002 20:40:32 -0000       1.49

+++ include/parrot/interpreter.h        13 Jul 2002 09:10:58 -0000

@@ -175,6 +175,8 @@

                                    requests are there? */

 

     PDB_t *pdb;                 /* Debug system */

+

+    void *lo_var_ptr;           /* Pointer to memory on runops system stack */

 } Interp;

 

 #define PCONST(i) PF_CONST(interpreter->code, (i))

Index: include/parrot/resources.h

===================================================================

RCS file: /cvs/public/parrot/include/parrot/resources.h,v

retrieving revision 1.33

diff -u -r1.33 resources.h

--- include/parrot/resources.h  4 Jun 2002 19:37:02 -0000       1.33

+++ include/parrot/resources.h  13 Jul 2002 09:10:58 -0000

@@ -45,6 +45,15 @@

 void *Parrot_allocate(struct Parrot_Interp *, void *, size_t size);

 void *Parrot_allocate_string(struct Parrot_Interp *, STRING *, size_t size);

 

+size_t get_min_buffer_address(struct Parrot_Interp *);

+size_t get_max_buffer_address(struct Parrot_Interp *);

+size_t get_min_pmc_address(struct Parrot_Interp *);

+size_t get_max_pmc_address(struct Parrot_Interp *);

+int is_buffer_ptr(struct Parrot_Interp *, void *);

+int is_pmc_ptr(struct Parrot_Interp *, void *);

+int contained_in_pool(struct Parrot_Interp *,struct Resource_Pool *, void *);

+PMC *trace_system_stack(struct Parrot_Interp *, PMC *);

+

 void Parrot_do_dod_run(struct Parrot_Interp *);

 void Parrot_go_collect(struct Parrot_Interp *);

 

@@ -65,6 +74,7 @@

 

 struct PMC_Arena {

     size_t used;         /* Count of PMCs in this arena */

+    size_t total;

     struct PMC_Arena *prev;

     struct PMC_Arena *next;

     PMC *start_PMC;      /* Pointer to array of PMCs */

@@ -73,6 +83,7 @@

 

 struct Buffer_Arena {

     size_t used;

+    size_t total;

     struct Buffer_Arena *prev;

     struct Buffer_Arena *next;

     Buffer *start_Buffer;

@@ -88,6 +99,8 @@

     size_t replenish_level; /* minimum free entries before replenishing */

     void (*replenish)(struct Parrot_Interp *, struct Resource_Pool *);

     struct Memory_Pool *mem_pool;

+    size_t start_arena_memory;

+    size_t end_arena_memory;

 };

         

 struct Arenas {

Reply via email to