2006-11-23 19:38:26 -05:00
|
|
|
|
|
|
|
#include "ikarus.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <assert.h>
|
2006-11-23 19:44:29 -05:00
|
|
|
#include <errno.h>
|
2006-11-23 19:38:26 -05:00
|
|
|
|
|
|
|
#define forward_ptr ((ikp)-1)
|
|
|
|
#define minimum_heap_size (pagesize * 1024 * 4)
|
|
|
|
#define maximum_heap_size (pagesize * 1024 * 8)
|
|
|
|
#define minimum_stack_size (pagesize * 128)
|
|
|
|
|
2006-11-23 19:42:39 -05:00
|
|
|
#define accounting 0
|
2006-11-23 19:40:06 -05:00
|
|
|
|
2006-12-16 19:00:34 -05:00
|
|
|
#if accounting
|
2006-11-23 19:40:06 -05:00
|
|
|
static int pair_count = 0;
|
|
|
|
static int symbol_count = 0;
|
|
|
|
static int closure_count = 0;
|
|
|
|
static int vector_count = 0;
|
|
|
|
static int record_count = 0;
|
|
|
|
static int continuation_count = 0;
|
|
|
|
static int string_count = 0;
|
|
|
|
static int htable_count = 0;
|
2006-12-16 19:00:34 -05:00
|
|
|
#endif
|
2006-11-23 19:40:06 -05:00
|
|
|
|
2006-11-23 19:38:26 -05:00
|
|
|
typedef struct qupages_t{
|
|
|
|
ikp p; /* pointer to the scan start */
|
|
|
|
ikp q; /* pointer to the scan end */
|
|
|
|
struct qupages_t* next;
|
|
|
|
} qupages_t;
|
|
|
|
|
2006-11-23 19:42:39 -05:00
|
|
|
|
|
|
|
typedef struct{
|
|
|
|
ikp ap;
|
|
|
|
ikp aq;
|
|
|
|
ikp ep;
|
|
|
|
ikp base;
|
|
|
|
} meta_t;
|
|
|
|
|
|
|
|
|
|
|
|
#define meta_ptrs 0
|
|
|
|
#define meta_code 1
|
|
|
|
#define meta_data 2
|
|
|
|
#define meta_weak 3
|
2006-11-23 19:44:29 -05:00
|
|
|
#define meta_pair 4
|
2007-02-25 21:29:28 -05:00
|
|
|
#define meta_symbol 5
|
|
|
|
#define meta_count 6
|
2006-11-23 19:42:39 -05:00
|
|
|
|
|
|
|
static int extension_amount[meta_count] = {
|
|
|
|
1 * pagesize,
|
2007-02-22 21:58:38 -05:00
|
|
|
1 * pagesize,
|
|
|
|
1 * pagesize,
|
2006-11-23 19:44:29 -05:00
|
|
|
1 * pagesize,
|
2007-02-25 21:29:28 -05:00
|
|
|
1 * pagesize,
|
2006-11-23 19:42:39 -05:00
|
|
|
1 * pagesize
|
|
|
|
};
|
|
|
|
|
|
|
|
static unsigned int meta_mt[meta_count] = {
|
|
|
|
pointers_mt,
|
|
|
|
code_mt,
|
|
|
|
data_mt,
|
2006-11-23 19:44:29 -05:00
|
|
|
weak_pairs_mt,
|
2007-02-25 21:29:28 -05:00
|
|
|
pointers_mt,
|
|
|
|
symbols_mt
|
2006-11-23 19:42:39 -05:00
|
|
|
};
|
|
|
|
|
2006-12-19 11:41:13 -05:00
|
|
|
typedef struct gc_t{
|
2006-11-23 19:42:39 -05:00
|
|
|
meta_t meta[generation_count][meta_count];
|
|
|
|
qupages_t* queues [meta_count];
|
|
|
|
ikpcb* pcb;
|
|
|
|
unsigned int* segment_vector;
|
|
|
|
int collect_gen;
|
|
|
|
ikp tconc_ap;
|
|
|
|
ikp tconc_ep;
|
|
|
|
ikp tconc_base;
|
|
|
|
ikpages* tconc_queue;
|
2006-12-19 11:41:13 -05:00
|
|
|
ik_guardian_table* final_guardians;
|
2006-11-23 19:38:26 -05:00
|
|
|
} gc_t;
|
|
|
|
|
2006-11-23 19:42:39 -05:00
|
|
|
static unsigned int
|
|
|
|
next_gen_tag[generation_count] = {
|
|
|
|
(4 << meta_dirty_shift) | 1 | new_gen_tag,
|
|
|
|
(2 << meta_dirty_shift) | 2 | new_gen_tag,
|
|
|
|
(1 << meta_dirty_shift) | 3 | new_gen_tag,
|
|
|
|
(0 << meta_dirty_shift) | 4 | new_gen_tag,
|
|
|
|
(0 << meta_dirty_shift) | 4 | new_gen_tag
|
|
|
|
};
|
|
|
|
|
|
|
|
static ikp
|
|
|
|
meta_alloc_extending(int size, int old_gen, gc_t* gc, int meta_id){
|
|
|
|
int mapsize = align_to_next_page(size);
|
|
|
|
if(mapsize < extension_amount[meta_id]){
|
|
|
|
mapsize = extension_amount[meta_id];
|
|
|
|
}
|
|
|
|
meta_t* meta = &gc->meta[old_gen][meta_id];
|
|
|
|
if((meta_id != meta_data) && meta->base){
|
2006-11-23 19:38:26 -05:00
|
|
|
qupages_t* p = ik_malloc(sizeof(qupages_t));
|
2006-11-23 19:42:39 -05:00
|
|
|
ikp aq = meta->aq;
|
|
|
|
ikp ap = meta->ap;
|
|
|
|
ikp ep = meta->ep;
|
|
|
|
p->p = aq;
|
|
|
|
p->q = ap;
|
|
|
|
p->next = gc->queues[meta_id];
|
|
|
|
gc->queues[meta_id] = p;
|
|
|
|
ikp x = ap;
|
|
|
|
while(x < ep){
|
|
|
|
ref(x, 0) = 0;
|
|
|
|
x += wordsize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ikp mem = ik_mmap_typed(
|
|
|
|
mapsize,
|
|
|
|
meta_mt[meta_id] | next_gen_tag[old_gen],
|
|
|
|
gc->pcb);
|
|
|
|
gc->segment_vector = gc->pcb->segment_vector;
|
|
|
|
meta->ap = mem + size;
|
|
|
|
meta->aq = mem;
|
|
|
|
meta->ep = mem + mapsize;
|
|
|
|
meta->base = mem;
|
|
|
|
return mem;
|
2006-11-23 19:38:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-11-23 19:42:39 -05:00
|
|
|
static inline ikp
|
|
|
|
meta_alloc(int size, int old_gen, gc_t* gc, int meta_id){
|
2006-11-23 19:38:26 -05:00
|
|
|
assert(size == align(size));
|
2006-11-23 19:42:39 -05:00
|
|
|
meta_t* meta = &gc->meta[old_gen][meta_id];
|
|
|
|
ikp ap = meta->ap;
|
|
|
|
ikp ep = meta->ep;
|
2006-11-23 19:38:26 -05:00
|
|
|
ikp nap = ap + size;
|
2006-11-23 19:42:39 -05:00
|
|
|
if(nap > ep){
|
|
|
|
return meta_alloc_extending(size, old_gen, gc, meta_id);
|
2006-11-23 19:38:26 -05:00
|
|
|
} else {
|
2006-11-23 19:42:39 -05:00
|
|
|
meta->ap = nap;
|
2006-11-23 19:38:26 -05:00
|
|
|
return ap;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-23 19:42:39 -05:00
|
|
|
static inline ikp
|
|
|
|
gc_alloc_new_ptr(int size, int old_gen, gc_t* gc){
|
2006-11-23 19:38:26 -05:00
|
|
|
assert(size == align(size));
|
2006-11-23 19:42:39 -05:00
|
|
|
return meta_alloc(size, old_gen, gc, meta_ptrs);
|
|
|
|
}
|
|
|
|
|
2007-05-15 08:56:22 -04:00
|
|
|
#if 0
|
2007-02-25 21:29:28 -05:00
|
|
|
static inline ikp
|
|
|
|
gc_alloc_new_symbol(int old_gen, gc_t* gc){
|
|
|
|
assert(symbol_size == align(symbol_size));
|
|
|
|
return meta_alloc(symbol_size, old_gen, gc, meta_symbol);
|
|
|
|
}
|
2007-05-15 08:56:22 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
static inline ikp
|
|
|
|
gc_alloc_new_symbol_record(int old_gen, gc_t* gc){
|
|
|
|
assert(symbol_record_size == align(symbol_record_size));
|
|
|
|
return meta_alloc(symbol_record_size, old_gen, gc, meta_symbol);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-02-25 21:29:28 -05:00
|
|
|
|
2006-11-23 19:42:39 -05:00
|
|
|
static inline ikp
|
2006-11-23 19:44:29 -05:00
|
|
|
gc_alloc_new_pair(int old_gen, gc_t* gc){
|
|
|
|
return meta_alloc(pair_size, old_gen, gc, meta_pair);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static inline ikp
|
|
|
|
gc_alloc_new_weak_pair(int old_gen, gc_t* gc){
|
|
|
|
meta_t* meta = &gc->meta[old_gen][meta_weak];
|
|
|
|
ikp ap = meta->ap;
|
|
|
|
ikp ep = meta->ep;
|
|
|
|
ikp nap = ap + pair_size;
|
|
|
|
if(nap > ep){
|
|
|
|
ikp mem = ik_mmap_typed(
|
|
|
|
pagesize,
|
|
|
|
meta_mt[meta_weak] | next_gen_tag[old_gen],
|
|
|
|
gc->pcb);
|
|
|
|
gc->segment_vector = gc->pcb->segment_vector;
|
|
|
|
meta->ap = mem + pair_size;
|
|
|
|
meta->aq = mem;
|
|
|
|
meta->ep = mem + pagesize;
|
|
|
|
meta->base = mem;
|
|
|
|
return mem;
|
|
|
|
} else {
|
|
|
|
meta->ap = nap;
|
|
|
|
return ap;
|
|
|
|
}
|
2006-11-23 19:42:39 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline ikp
|
|
|
|
gc_alloc_new_data(int size, int old_gen, gc_t* gc){
|
|
|
|
assert(size == align(size));
|
|
|
|
return meta_alloc(size, old_gen, gc, meta_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline ikp
|
|
|
|
gc_alloc_new_code(int size, int old_gen, gc_t* gc){
|
2007-02-22 21:58:38 -05:00
|
|
|
assert(size == align(size));
|
2006-11-23 19:44:29 -05:00
|
|
|
if(size < pagesize){
|
|
|
|
return meta_alloc(size, old_gen, gc, meta_code);
|
|
|
|
} else {
|
|
|
|
int memreq = align_to_next_page(size);
|
|
|
|
ikp mem = ik_mmap_code(memreq, next_gen_tag[old_gen], gc->pcb);
|
|
|
|
gc->segment_vector = gc->pcb->segment_vector;
|
|
|
|
qupages_t* p = ik_malloc(sizeof(qupages_t));
|
|
|
|
p->p = mem;
|
|
|
|
p->q = mem+size;
|
2007-02-22 21:58:38 -05:00
|
|
|
bzero(mem+size, memreq-size);
|
2006-11-23 19:44:29 -05:00
|
|
|
p->next = gc->queues[meta_code];
|
|
|
|
gc->queues[meta_code] = p;
|
|
|
|
return mem;
|
|
|
|
}
|
2006-11-23 19:42:39 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gc_tconc_push_extending(gc_t* gc, ikp tcbucket){
|
|
|
|
if(gc->tconc_base){
|
|
|
|
ikpages* p = ik_malloc(sizeof(ikpages));
|
|
|
|
p->base = gc->tconc_base;
|
|
|
|
p->size = pagesize;
|
|
|
|
p->next = gc->tconc_queue;
|
|
|
|
gc->tconc_queue = p;
|
2006-11-23 19:38:26 -05:00
|
|
|
}
|
2006-11-23 19:42:39 -05:00
|
|
|
ikp ap = ik_mmap(pagesize);
|
|
|
|
ikp nap = ap + wordsize;
|
|
|
|
gc->tconc_base = ap;
|
|
|
|
gc->tconc_ap = nap;
|
|
|
|
gc->tconc_ep = ap + pagesize;
|
|
|
|
ref(ap,0) = tcbucket;
|
2006-11-23 19:38:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-23 19:42:39 -05:00
|
|
|
static inline void
|
|
|
|
gc_tconc_push(gc_t* gc, ikp tcbucket){
|
|
|
|
ikp ap = gc->tconc_ap;
|
|
|
|
ikp nap = ap + wordsize;
|
|
|
|
if(nap > gc->tconc_ep){
|
|
|
|
gc_tconc_push_extending(gc, tcbucket);
|
|
|
|
} else {
|
|
|
|
gc->tconc_ap = nap;
|
|
|
|
ref(ap,0) = tcbucket;
|
|
|
|
}
|
|
|
|
}
|
2006-11-23 19:38:26 -05:00
|
|
|
|
2006-12-16 19:00:34 -05:00
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
static ikp add_object_proc(gc_t* gc, ikp x, char* caller);
|
|
|
|
#define add_object(gc,x,caller) add_object_proc(gc,x,caller)
|
|
|
|
#else
|
|
|
|
static ikp add_object_proc(gc_t* gc, ikp x);
|
|
|
|
#define add_object(gc,x,caller) add_object_proc(gc,x)
|
|
|
|
#endif
|
|
|
|
|
2006-11-23 19:38:26 -05:00
|
|
|
static void collect_stack(gc_t*, ikp top, ikp base);
|
|
|
|
static void collect_loop(gc_t*);
|
2006-12-18 15:08:33 -05:00
|
|
|
static void guardians_loop(gc_t*);
|
2006-11-23 19:42:39 -05:00
|
|
|
static void fix_weak_pointers(gc_t*);
|
|
|
|
static void gc_add_tconcs(gc_t*);
|
2006-12-19 11:41:13 -05:00
|
|
|
static void gc_add_guardians(gc_t*);
|
2006-11-23 19:38:26 -05:00
|
|
|
|
|
|
|
/* ik_collect is called from scheme under the following conditions:
|
|
|
|
* 1. An attempt is made to allocate a small object and the ap is above
|
|
|
|
* the red line.
|
|
|
|
* 2. The current frame of the call is dead, so, upon return from ik_collect,
|
|
|
|
* the caller returns to its caller.
|
|
|
|
* 3. The frame-pointer of the caller to S_collect is saved at
|
|
|
|
* pcb->frame_pointer. No variables are live at that frame except for
|
|
|
|
* the return point (at *(pcb->frame_pointer)).
|
|
|
|
* 4. S_collect must return a new ap (in pcb->allocation_pointer) that has
|
|
|
|
* at least 2 pages of memory free.
|
|
|
|
* 5. S_collect must also update pcb->allocaton_redline to be 2 pages below
|
|
|
|
* the real end of heap.
|
|
|
|
* 6. ik_collect should not move the stack.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
ikpcb* ik_collect(int req, ikpcb* pcb);
|
|
|
|
ikpcb* ik_collect_vararg(int req, ikpcb* pcb){
|
|
|
|
return ik_collect(req, pcb);
|
|
|
|
}
|
|
|
|
|
2006-11-23 19:42:39 -05:00
|
|
|
static int collection_id_to_gen(int id){
|
|
|
|
if((id & 255) == 255) { return 4; }
|
|
|
|
if((id & 63) == 63) { return 3; }
|
|
|
|
if((id & 15) == 15) { return 2; }
|
|
|
|
if((id & 3) == 3) { return 1; }
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
|
2006-11-23 19:42:39 -05:00
|
|
|
static void scan_dirty_pages(gc_t*);
|
|
|
|
|
|
|
|
static void deallocate_unused_pages(gc_t*);
|
|
|
|
|
|
|
|
static void fix_new_pages(gc_t* gc);
|
|
|
|
|
2007-02-22 21:58:38 -05:00
|
|
|
extern void verify_integrity(ikpcb* pcb, char*);
|
2006-11-23 19:42:39 -05:00
|
|
|
|
2006-11-23 19:38:26 -05:00
|
|
|
ikpcb*
|
2006-12-06 10:08:34 -05:00
|
|
|
ik_collect(int mem_req, ikpcb* pcb){
|
2007-02-22 21:58:38 -05:00
|
|
|
#ifndef NDEBUG
|
|
|
|
verify_integrity(pcb, "entry");
|
|
|
|
#endif
|
2006-12-29 05:45:30 -05:00
|
|
|
{ /* ACCOUNTING */
|
|
|
|
int bytes = ((int)pcb->allocation_pointer) -
|
|
|
|
((int)pcb->heap_base);
|
|
|
|
int minor = bytes + pcb->allocation_count_minor;
|
|
|
|
while(minor >= most_bytes_in_minor){
|
|
|
|
minor -= most_bytes_in_minor;
|
|
|
|
pcb->allocation_count_major++;
|
|
|
|
}
|
|
|
|
pcb->allocation_count_minor = minor;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-23 19:44:29 -05:00
|
|
|
struct rusage t0, t1;
|
|
|
|
|
|
|
|
getrusage(RUSAGE_SELF, &t0);
|
|
|
|
|
2006-11-23 19:38:26 -05:00
|
|
|
gc_t gc;
|
2006-11-23 19:42:39 -05:00
|
|
|
bzero(&gc, sizeof(gc_t));
|
|
|
|
gc.pcb = pcb;
|
|
|
|
gc.segment_vector = pcb->segment_vector;
|
2006-11-23 19:38:26 -05:00
|
|
|
|
2006-11-23 19:42:39 -05:00
|
|
|
gc.collect_gen = collection_id_to_gen(pcb->collection_id);
|
|
|
|
pcb->collection_id++;
|
|
|
|
#ifndef NDEBUG
|
2006-11-23 19:44:29 -05:00
|
|
|
fprintf(stderr, "ik_collect entry %d free=%d (collect gen=%d/id=%d)\n",
|
2006-12-06 10:08:34 -05:00
|
|
|
mem_req,
|
2006-11-23 19:44:29 -05:00
|
|
|
(unsigned int) pcb->allocation_redline
|
|
|
|
- (unsigned int) pcb->allocation_pointer,
|
|
|
|
gc.collect_gen, pcb->collection_id-1);
|
2006-11-23 19:42:39 -05:00
|
|
|
#endif
|
2006-11-23 19:38:26 -05:00
|
|
|
|
2007-01-19 18:13:44 -05:00
|
|
|
/* cache heap-pages to delete later */
|
|
|
|
ikpages* old_heap_pages = pcb->heap_pages;
|
|
|
|
pcb->heap_pages = 0;
|
2006-11-23 19:38:26 -05:00
|
|
|
|
|
|
|
/* the roots are:
|
2006-11-23 19:42:39 -05:00
|
|
|
* 0. dirty pages not collected in this run
|
2006-11-23 19:38:26 -05:00
|
|
|
* 1. the stack
|
|
|
|
* 2. the next continuation
|
2006-12-25 01:28:53 -05:00
|
|
|
* 3. the symbol-table
|
2006-11-23 19:38:26 -05:00
|
|
|
*/
|
2007-01-19 18:13:44 -05:00
|
|
|
|
2006-11-23 19:42:39 -05:00
|
|
|
scan_dirty_pages(&gc);
|
2006-11-23 19:38:26 -05:00
|
|
|
collect_stack(&gc, pcb->frame_pointer, pcb->frame_base - wordsize);
|
2006-12-01 09:52:12 -05:00
|
|
|
pcb->next_k = add_object(&gc, pcb->next_k, "next_k");
|
2006-12-25 01:28:53 -05:00
|
|
|
pcb->symbol_table = add_object(&gc, pcb->symbol_table, "symbol_table");
|
2006-12-25 02:25:40 -05:00
|
|
|
pcb->gensym_table = add_object(&gc, pcb->gensym_table, "gensym_table");
|
2006-12-16 19:00:34 -05:00
|
|
|
pcb->arg_list = add_object(&gc, pcb->arg_list, "args_list_foo");
|
2007-05-05 22:42:26 -04:00
|
|
|
pcb->base_rtd = add_object(&gc, pcb->base_rtd, "base_rtd");
|
2006-11-23 19:38:26 -05:00
|
|
|
/* now we trace all live objects */
|
|
|
|
collect_loop(&gc);
|
2006-12-18 15:08:33 -05:00
|
|
|
|
|
|
|
/* next we trace all guardian/guarded objects,
|
|
|
|
the procedure does a collect_loop at the end */
|
|
|
|
guardians_loop(&gc);
|
2006-11-23 19:38:26 -05:00
|
|
|
|
2006-12-18 15:08:33 -05:00
|
|
|
/* does not allocate, only bwp's dead pointers */
|
|
|
|
fix_weak_pointers(&gc);
|
2006-11-23 19:42:39 -05:00
|
|
|
/* now deallocate all unused pages */
|
|
|
|
deallocate_unused_pages(&gc);
|
2006-11-23 19:38:26 -05:00
|
|
|
|
2006-11-23 19:42:39 -05:00
|
|
|
fix_new_pages(&gc);
|
2006-11-23 19:38:26 -05:00
|
|
|
pcb->allocation_pointer = pcb->heap_base;
|
2006-11-23 19:42:39 -05:00
|
|
|
gc_add_tconcs(&gc);
|
2006-12-19 11:41:13 -05:00
|
|
|
gc_add_guardians(&gc);
|
2006-11-23 19:42:39 -05:00
|
|
|
pcb->weak_pairs_ap = 0;
|
|
|
|
pcb->weak_pairs_ep = 0;
|
2006-11-23 19:40:06 -05:00
|
|
|
|
2006-12-16 19:00:34 -05:00
|
|
|
#if accounting
|
2006-11-23 19:40:06 -05:00
|
|
|
fprintf(stderr,
|
|
|
|
"[%d cons|%d sym|%d cls|%d vec|%d rec|%d cck|%d str|%d htb]\n",
|
|
|
|
pair_count,
|
|
|
|
symbol_count,
|
|
|
|
closure_count,
|
|
|
|
vector_count,
|
|
|
|
record_count,
|
|
|
|
continuation_count,
|
|
|
|
string_count,
|
|
|
|
htable_count);
|
|
|
|
pair_count = 0;
|
|
|
|
symbol_count = 0;
|
|
|
|
closure_count = 0;
|
|
|
|
vector_count = 0;
|
|
|
|
record_count = 0;
|
|
|
|
continuation_count = 0;
|
|
|
|
string_count = 0;
|
|
|
|
htable_count = 0;
|
2006-12-16 19:00:34 -05:00
|
|
|
#endif
|
2006-11-23 19:42:39 -05:00
|
|
|
//ik_dump_metatable(pcb);
|
2006-11-23 19:44:29 -05:00
|
|
|
#ifndef NDEBUG
|
|
|
|
fprintf(stderr, "collect done\n");
|
|
|
|
#endif
|
|
|
|
getrusage(RUSAGE_SELF, &t1);
|
|
|
|
pcb->collect_utime.tv_usec += t1.ru_utime.tv_usec - t0.ru_utime.tv_usec;
|
|
|
|
pcb->collect_utime.tv_sec += t1.ru_utime.tv_sec - t0.ru_utime.tv_sec;
|
|
|
|
if (pcb->collect_utime.tv_usec >= 1000000){
|
|
|
|
pcb->collect_utime.tv_usec -= 1000000;
|
|
|
|
pcb->collect_utime.tv_sec += 1;
|
|
|
|
}
|
|
|
|
else if (pcb->collect_utime.tv_usec < 0){
|
|
|
|
pcb->collect_utime.tv_usec += 1000000;
|
|
|
|
pcb->collect_utime.tv_sec -= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pcb->collect_stime.tv_usec += t1.ru_stime.tv_usec - t0.ru_stime.tv_usec;
|
|
|
|
pcb->collect_stime.tv_sec += t1.ru_stime.tv_sec - t0.ru_stime.tv_sec;
|
|
|
|
if (pcb->collect_stime.tv_usec >= 1000000){
|
|
|
|
pcb->collect_stime.tv_usec -= 1000000;
|
|
|
|
pcb->collect_stime.tv_sec += 1;
|
|
|
|
}
|
|
|
|
else if (pcb->collect_stime.tv_usec < 0){
|
|
|
|
pcb->collect_stime.tv_usec += 1000000;
|
|
|
|
pcb->collect_stime.tv_sec -= 1;
|
|
|
|
}
|
|
|
|
|
2006-12-06 10:08:34 -05:00
|
|
|
/* delete all old heap pages */
|
2007-01-19 18:13:44 -05:00
|
|
|
if(old_heap_pages){
|
|
|
|
ikpages* p = old_heap_pages;
|
2006-12-06 10:08:34 -05:00
|
|
|
do{
|
|
|
|
ikpages* next = p->next;
|
|
|
|
ik_munmap_from_segment(p->base, p->size, pcb);
|
|
|
|
ik_free(p, sizeof(ikpages));
|
|
|
|
p=next;
|
|
|
|
} while(p);
|
2007-01-19 18:13:44 -05:00
|
|
|
old_heap_pages = 0;
|
2006-12-06 10:08:34 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
int free_space =
|
|
|
|
((unsigned int)pcb->allocation_redline) -
|
|
|
|
((unsigned int)pcb->allocation_pointer);
|
|
|
|
if(free_space <= mem_req){
|
|
|
|
#ifndef NDEBUG
|
|
|
|
fprintf(stderr, "REQ=%d, got %d\n", mem_req, free_space);
|
|
|
|
#endif
|
|
|
|
int memsize = align_to_next_page(mem_req);
|
|
|
|
ik_munmap_from_segment(
|
|
|
|
pcb->heap_base,
|
|
|
|
pcb->heap_size,
|
|
|
|
pcb);
|
|
|
|
ikp ptr = ik_mmap_mixed(memsize+2*pagesize, pcb);
|
|
|
|
pcb->allocation_pointer = ptr;
|
|
|
|
pcb->allocation_redline = ptr+memsize;
|
|
|
|
pcb->heap_base = ptr;
|
|
|
|
pcb->heap_size = memsize+2*pagesize;
|
|
|
|
}
|
2006-11-23 19:44:29 -05:00
|
|
|
|
2006-12-30 14:52:37 -05:00
|
|
|
#ifndef NDEBUG
|
|
|
|
ikp x = pcb->allocation_pointer;
|
|
|
|
while(x < pcb->allocation_redline){
|
|
|
|
ref(x, 0) = (ikp)(0x1234FFFF);
|
|
|
|
x+=wordsize;
|
|
|
|
}
|
2007-02-22 21:58:38 -05:00
|
|
|
#endif
|
|
|
|
#ifndef NDEBUG
|
|
|
|
verify_integrity(pcb, "exit");
|
2006-12-30 14:52:37 -05:00
|
|
|
#endif
|
2006-11-23 19:38:26 -05:00
|
|
|
return pcb;
|
|
|
|
}
|
|
|
|
|
2006-12-19 11:41:13 -05:00
|
|
|
static inline int
|
|
|
|
is_live(ikp x, gc_t* gc){
|
|
|
|
if(is_fixnum(x)){
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
int tag = tagof(x);
|
|
|
|
if(tag == immediate_tag){
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if(ref(x, -tag) == forward_ptr){
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
unsigned int t = gc->segment_vector[page_index(x)];
|
|
|
|
int gen = t & gen_mask;
|
|
|
|
if(gen > gc->collect_gen){
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ik_guardian_table*
|
|
|
|
move_guardian(ikp tc, ikp obj, ik_guardian_table* t){
|
|
|
|
if(t && (t->count < ik_guardian_table_size)){
|
|
|
|
ik_guardian_pair* p = &t->p[t->count];
|
|
|
|
p->tc = tc;
|
|
|
|
p->obj = obj;
|
|
|
|
t->count++;
|
|
|
|
return t;
|
|
|
|
} else {
|
|
|
|
ik_guardian_table* nt =
|
|
|
|
(ik_guardian_table*)ik_mmap(sizeof(ik_guardian_table));
|
|
|
|
nt->next = t;
|
|
|
|
nt->count = 1;
|
|
|
|
nt->p[0].tc = tc;
|
|
|
|
nt->p[0].obj = obj;
|
|
|
|
return nt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
next_gen(int i){
|
|
|
|
return ((i == generation_count) ? generation_count : (i+1));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-12-18 15:08:33 -05:00
|
|
|
static void
|
|
|
|
guardians_loop(gc_t* gc){
|
2006-12-19 11:41:13 -05:00
|
|
|
ikpcb* pcb = gc->pcb;
|
|
|
|
int gen = gc->collect_gen;
|
|
|
|
ik_guardian_table* pending_hold[generation_count];
|
|
|
|
ik_guardian_table* pending_final = 0;
|
|
|
|
ik_guardian_table* final = 0;
|
|
|
|
/* reset all pending_hold and pending_fina lists. */
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i=0; i<=gen; i++){
|
|
|
|
pending_hold[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* move all guardian tc/objects to either pending_hold */
|
|
|
|
/* or pending_fina depending on whether the object is */
|
|
|
|
/* live or dead respectively. */
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i=0; i<=gen; i++){
|
|
|
|
ik_guardian_table* t = pcb->guardians[i];
|
|
|
|
while(t){
|
|
|
|
int j;
|
2006-12-19 12:14:31 -05:00
|
|
|
int count = t->count;
|
|
|
|
for(j=0; j<count; j++){
|
|
|
|
ikp tc = t->p[j].tc;
|
2006-12-19 11:41:13 -05:00
|
|
|
ikp obj = t->p[j].obj;
|
|
|
|
if(is_live(obj, gc)){
|
|
|
|
pending_hold[i] =
|
2006-12-19 12:14:31 -05:00
|
|
|
move_guardian(tc, obj, pending_hold[i]);
|
2006-12-19 11:41:13 -05:00
|
|
|
} else {
|
|
|
|
pending_final =
|
2006-12-19 12:14:31 -05:00
|
|
|
move_guardian(tc, obj, pending_final);
|
2006-12-19 11:41:13 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
ik_guardian_table* next = t->next;
|
|
|
|
ik_munmap(t, sizeof(ik_guardian_table));
|
|
|
|
t = next;
|
|
|
|
}
|
|
|
|
pcb->guardians[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int more;
|
|
|
|
do{
|
|
|
|
/* for each tc/obj in pending_final, if tc is live, then */
|
|
|
|
/* we add tc/obj to final list. */
|
|
|
|
ik_guardian_table* t = pending_final;
|
|
|
|
more = 0;
|
|
|
|
while(t){
|
|
|
|
int j;
|
|
|
|
int k=0;
|
|
|
|
int count = t->count;
|
|
|
|
for(j=0; j < count; j++){
|
|
|
|
ikp tc = t->p[j].tc;
|
|
|
|
ikp obj = t->p[j].obj;
|
|
|
|
if(is_live(tc, gc)){
|
|
|
|
final = move_guardian(tc, obj, final);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
t->p[k].tc = tc;
|
|
|
|
t->p[k].obj = obj;
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(k != count){
|
|
|
|
t->count = k;
|
|
|
|
more = 1;
|
|
|
|
}
|
|
|
|
t = t->next;
|
|
|
|
}
|
|
|
|
if(more){
|
|
|
|
ik_guardian_table* t = final;
|
|
|
|
while(t){
|
|
|
|
int i;
|
|
|
|
int count = final->count;
|
|
|
|
for(i=0; i<count; i++){
|
|
|
|
gc->final_guardians = move_guardian(
|
|
|
|
add_object(gc, final->p[i].tc, "guardian_tc"),
|
|
|
|
add_object(gc, final->p[i].obj, "guardian_obj"),
|
|
|
|
gc->final_guardians);
|
|
|
|
}
|
|
|
|
t = t->next;
|
|
|
|
}
|
|
|
|
while(final){
|
|
|
|
t = final->next;
|
|
|
|
ik_munmap(final, sizeof(ik_guardian_table));
|
|
|
|
final = t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
collect_loop(gc);
|
|
|
|
} while (more);
|
|
|
|
/* */
|
|
|
|
while(pending_final){
|
|
|
|
ik_guardian_table* next = pending_final->next;
|
|
|
|
ik_munmap(pending_final, sizeof(ik_guardian_table));
|
|
|
|
pending_final = next;
|
|
|
|
}
|
|
|
|
/* */
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i=0; i<=gen; i++){
|
|
|
|
int ni = next_gen(i);
|
|
|
|
ik_guardian_table* t = pending_hold[i];
|
|
|
|
while(t){
|
|
|
|
int count = t->count;
|
|
|
|
int j;
|
|
|
|
for(j=0; j<count; j++){
|
|
|
|
ikp tc = t->p[j].tc;
|
|
|
|
ikp obj = t->p[j].obj;
|
|
|
|
if(is_live(tc, gc)){
|
|
|
|
pcb->guardians[ni] = move_guardian(
|
|
|
|
add_object(gc, tc, "guardian_tc2"),
|
|
|
|
add_object(gc, obj, "guardian_obj2"),
|
|
|
|
pcb->guardians[ni]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ik_guardian_table* next = t->next;
|
|
|
|
ik_munmap(t, sizeof(ik_guardian_table));
|
|
|
|
t = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-11-23 19:38:26 -05:00
|
|
|
|
2006-12-18 15:08:33 -05:00
|
|
|
|
2006-12-19 11:41:13 -05:00
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
while(1){
|
|
|
|
int i;
|
|
|
|
/* for every tc/obj in the queues,
|
|
|
|
- if tc is live and obj is live, move them to guard_move
|
|
|
|
- if tc is live and obj is dead, move them to guard_dead
|
|
|
|
- else keep tc, obj in guard_wait.
|
|
|
|
*/
|
|
|
|
for(i=0; i<=gen; i++){
|
|
|
|
ik_guardian_table* t = guard_wait[i];
|
|
|
|
while (t){
|
|
|
|
int j = 0;
|
|
|
|
int k = 0;
|
|
|
|
int count = t->count;
|
|
|
|
while(j < count){
|
|
|
|
ikp tc = t->p[j].tc;
|
|
|
|
ikp obj = t->p[j].obj;
|
|
|
|
if(is_live(tc, gc)){
|
|
|
|
if(is_live(obj, gc)){
|
|
|
|
guard_move[i] = move_guardian(tc, obj, guard_move[i]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
guard_dead[i] = move_guardian(tc, obj, guard_dead[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
t->p[k].tc = tc;
|
|
|
|
t->p[k].obj = obj;
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
t->count = k;
|
|
|
|
t = t->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* now all things in guard_move are moved to next-gen's
|
|
|
|
* guardians */
|
|
|
|
}
|
2006-12-18 15:08:33 -05:00
|
|
|
}
|
2006-12-19 11:41:13 -05:00
|
|
|
#endif
|
|
|
|
|
2006-11-23 19:38:26 -05:00
|
|
|
#define disp_frame_offset -13
|
|
|
|
#define disp_multivalue_rp -9
|
|
|
|
|
2006-11-23 19:42:39 -05:00
|
|
|
|
|
|
|
#define CODE_EXTENSION_SIZE (pagesize)
|
|
|
|
|
|
|
|
static int alloc_code_count = 0;
|
|
|
|
|
2006-11-23 19:38:26 -05:00
|
|
|
|
|
|
|
static ikp
|
|
|
|
add_code_entry(gc_t* gc, ikp entry){
|
2006-11-23 19:42:39 -05:00
|
|
|
ikp x = entry - disp_code_data;
|
|
|
|
if(ref(x,0) == forward_ptr){
|
|
|
|
return ref(x,wordsize) + off_code_data;
|
|
|
|
}
|
|
|
|
int idx = page_index(x);
|
|
|
|
unsigned int t = gc->segment_vector[idx];
|
|
|
|
int gen = t & gen_mask;
|
|
|
|
if(gen > gc->collect_gen){
|
2006-11-23 19:38:26 -05:00
|
|
|
return entry;
|
|
|
|
}
|
2006-11-23 19:44:29 -05:00
|
|
|
int code_size = unfix(ref(x, disp_code_code_size));
|
|
|
|
ikp reloc_vec = ref(x, disp_code_reloc_vector);
|
|
|
|
ikp freevars = ref(x, disp_code_freevars);
|
|
|
|
int required_mem = align(disp_code_data + code_size);
|
|
|
|
if(required_mem >= pagesize){
|
|
|
|
int new_tag = next_gen_tag[gen];
|
|
|
|
int idx = page_index(x);
|
|
|
|
gc->segment_vector[idx] = new_tag | code_mt;
|
|
|
|
int i;
|
|
|
|
for(i=pagesize, idx++; i<required_mem; i+=pagesize, idx++){
|
|
|
|
gc->segment_vector[idx] = new_tag | data_mt;
|
2006-11-23 19:38:26 -05:00
|
|
|
}
|
2006-11-23 19:44:29 -05:00
|
|
|
qupages_t* p = ik_malloc(sizeof(qupages_t));
|
|
|
|
p->p = x;
|
|
|
|
p->q = x+required_mem;
|
|
|
|
p->next = gc->queues[meta_code];
|
|
|
|
gc->queues[meta_code] = p;
|
|
|
|
return entry;
|
|
|
|
} else {
|
|
|
|
ikp y = gc_alloc_new_code(required_mem, gen, gc);
|
|
|
|
ref(y, 0) = code_tag;
|
|
|
|
ref(y, disp_code_code_size) = fix(code_size);
|
|
|
|
ref(y, disp_code_reloc_vector) = reloc_vec;
|
|
|
|
ref(y, disp_code_freevars) = freevars;
|
|
|
|
memcpy(y+disp_code_data, x+disp_code_data, code_size);
|
|
|
|
ref(x, 0) = forward_ptr;
|
|
|
|
ref(x, wordsize) = y + vector_tag;
|
|
|
|
return y+disp_code_data;
|
2006-11-23 19:38:26 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-23 19:44:29 -05:00
|
|
|
|
2006-11-23 19:38:26 -05:00
|
|
|
#define DEBUG_STACK 0
|
|
|
|
|
|
|
|
static void collect_stack(gc_t* gc, ikp top, ikp end){
|
|
|
|
if(DEBUG_STACK){
|
|
|
|
fprintf(stderr, "collecting stack from 0x%08x .. 0x%08x\n",
|
|
|
|
(int) top, (int) end);
|
|
|
|
}
|
|
|
|
while(top < end){
|
|
|
|
if(DEBUG_STACK){
|
|
|
|
fprintf(stderr, "collecting frame at 0x%08x: ", (int) top);
|
|
|
|
}
|
|
|
|
ikp rp = ref(top, 0);
|
|
|
|
int rp_offset = unfix(ref(rp, disp_frame_offset));
|
|
|
|
if(DEBUG_STACK){
|
|
|
|
fprintf(stderr, "rp_offset=%d\n", rp_offset);
|
|
|
|
}
|
|
|
|
if(rp_offset <= 0){
|
|
|
|
fprintf(stderr, "invalid rp_offset %d\n", rp_offset);
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
/* since the return point is alive, we need to find the code
|
|
|
|
* object containing it and mark it live as well. the rp is
|
|
|
|
* updated to reflect the new code object. */
|
|
|
|
|
|
|
|
int code_offset = rp_offset - disp_frame_offset;
|
|
|
|
ikp code_entry = rp - code_offset;
|
|
|
|
ikp new_code_entry = add_code_entry(gc, code_entry);
|
|
|
|
ikp new_rp = new_code_entry + code_offset;
|
|
|
|
ref(top, 0) = new_rp;
|
|
|
|
|
|
|
|
/* now for some livemask action.
|
|
|
|
* every return point has a live mark above it. the live mask
|
|
|
|
* is a sequence of bytes (every byte for 8 frame cells). the
|
|
|
|
* size of the live mask is determined by the size of the frame.
|
|
|
|
* this is how the call frame instruction sequence looks like:
|
|
|
|
*
|
|
|
|
* | ... |
|
|
|
|
* | code junk |
|
|
|
|
* +------------+
|
|
|
|
* | byte 0 | for fv0 .. fv7
|
|
|
|
* | byte 1 | for fv8 .. fv15
|
|
|
|
* | ... | ...
|
|
|
|
* +------------+
|
|
|
|
* | framesize |
|
|
|
|
* | word |
|
|
|
|
* +------------+
|
|
|
|
* | multivalue |
|
|
|
|
* | word |
|
|
|
|
* +------------+
|
|
|
|
* | frameoffst | the frame offset determined how far its
|
|
|
|
* | word | address is off from the start of the code
|
|
|
|
* +------------+
|
|
|
|
* | padding | the size of this part is fixed so that we
|
|
|
|
* | and call | can correlate the frame info (above) with rp
|
|
|
|
* +------------+
|
|
|
|
* | code junk | <---- rp
|
|
|
|
* | ... |
|
|
|
|
*
|
|
|
|
* WITH ONE EXCEPTION:
|
|
|
|
* if the framesize is 0, then the actual frame size is stored
|
|
|
|
* on the stack immediately below the return point.
|
|
|
|
* there is no live mask in this case, instead all values in the
|
|
|
|
* frame are live.
|
|
|
|
*/
|
|
|
|
int framesize = (int) ref(rp, disp_frame_size);
|
|
|
|
if(DEBUG_STACK){
|
|
|
|
fprintf(stderr, "fs=%d\n", framesize);
|
|
|
|
}
|
|
|
|
if(framesize < 0){
|
|
|
|
fprintf(stderr, "invalid frame size %d\n", framesize);
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
else if(framesize == 0){
|
|
|
|
framesize = (int)ref(top, wordsize);
|
|
|
|
if(framesize <= 0){
|
|
|
|
fprintf(stderr, "invalid redirected framesize=%d\n", framesize);
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
ikp base = top + framesize - wordsize;
|
|
|
|
while(base > top){
|
2006-11-29 17:06:16 -05:00
|
|
|
ikp new_obj = add_object(gc,ref(base,0), "frame");
|
2006-11-23 19:38:26 -05:00
|
|
|
ref(base,0) = new_obj;
|
|
|
|
base -= wordsize;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
int frame_cells = framesize >> fx_shift;
|
|
|
|
int bytes_in_mask = (frame_cells+7) >> 3;
|
|
|
|
unsigned char* mask = rp + disp_frame_size - bytes_in_mask;
|
|
|
|
|
|
|
|
ikp* fp = (ikp*)(top + framesize);
|
|
|
|
int i;
|
|
|
|
for(i=0; i<bytes_in_mask; i++, fp-=8){
|
|
|
|
unsigned char m = mask[i];
|
2006-11-29 17:06:16 -05:00
|
|
|
#if DEBUG_STACK
|
2006-11-29 18:45:13 -05:00
|
|
|
fprintf(stderr, "m[%d]=0x%x\n", i, m);
|
2006-11-29 17:06:16 -05:00
|
|
|
#endif
|
2006-11-29 18:45:13 -05:00
|
|
|
if(m & 0x01) { fp[-0] = add_object(gc, fp[-0], "frame0"); }
|
|
|
|
if(m & 0x02) { fp[-1] = add_object(gc, fp[-1], "frame1"); }
|
|
|
|
if(m & 0x04) { fp[-2] = add_object(gc, fp[-2], "frame2"); }
|
|
|
|
if(m & 0x08) { fp[-3] = add_object(gc, fp[-3], "frame3"); }
|
|
|
|
if(m & 0x10) { fp[-4] = add_object(gc, fp[-4], "frame4"); }
|
|
|
|
if(m & 0x20) { fp[-5] = add_object(gc, fp[-5], "frame5"); }
|
|
|
|
if(m & 0x40) { fp[-6] = add_object(gc, fp[-6], "frame6"); }
|
|
|
|
if(m & 0x80) { fp[-7] = add_object(gc, fp[-7], "frame7"); }
|
2006-11-23 19:38:26 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
top += framesize;
|
|
|
|
}
|
|
|
|
if(top != end){
|
|
|
|
fprintf(stderr, "frames did not match up 0x%08x .. 0x%08x\n",
|
|
|
|
(int) top, (int) end);
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
if(DEBUG_STACK){
|
|
|
|
fprintf(stderr, "done with stack!\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
static void
|
|
|
|
add_list(gc_t* gc, unsigned int t, int gen, ikp x, ikp* loc){
|
|
|
|
int collect_gen = gc->collect_gen;
|
|
|
|
while(1){
|
|
|
|
ikp fst = ref(x, off_car);
|
|
|
|
ikp snd = ref(x, off_cdr);
|
|
|
|
ikp y;
|
|
|
|
if((t & type_mask) != weak_pairs_type){
|
|
|
|
y = gc_alloc_new_pair(gen, gc) + pair_tag;
|
|
|
|
} else {
|
|
|
|
y = gc_alloc_new_weak_pair(gen, gc) + pair_tag;
|
|
|
|
}
|
|
|
|
*loc = y;
|
|
|
|
ref(x,off_car) = forward_ptr;
|
|
|
|
ref(x,off_cdr) = y;
|
|
|
|
ref(y,off_car) = fst;
|
|
|
|
int stag = tagof(snd);
|
|
|
|
if(stag == pair_tag){
|
|
|
|
if(ref(snd, -pair_tag) == forward_ptr){
|
|
|
|
ref(y, off_cdr) = ref(snd, wordsize-pair_tag);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
t = gc->segment_vector[page_index(snd)];
|
|
|
|
gen = t & gen_mask;
|
|
|
|
if(gen > collect_gen){
|
|
|
|
ref(y, off_cdr) = snd;
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
x = snd;
|
|
|
|
loc = (ikp*)(y + off_cdr);
|
|
|
|
/* don't return */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( (stag == immediate_tag)
|
|
|
|
|| (stag == 0)
|
|
|
|
|| (stag == (1<<fx_shift))) {
|
|
|
|
ref(y,off_cdr) = snd;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (ref(snd, -stag) == forward_ptr){
|
|
|
|
ref(y, off_cdr) = ref(snd, wordsize-stag);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
2006-11-29 17:06:16 -05:00
|
|
|
ref(y, off_cdr) = add_object(gc, snd, "add_list");
|
2006-11-23 19:44:29 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-23 19:38:26 -05:00
|
|
|
static ikp
|
2006-12-16 19:00:34 -05:00
|
|
|
#ifndef NDEBUG
|
|
|
|
add_object_proc(gc_t* gc, ikp x, char* caller)
|
|
|
|
#else
|
|
|
|
add_object_proc(gc_t* gc, ikp x)
|
|
|
|
#endif
|
|
|
|
{
|
2006-11-23 19:38:26 -05:00
|
|
|
if(is_fixnum(x)){
|
|
|
|
return x;
|
|
|
|
}
|
2007-02-22 21:58:38 -05:00
|
|
|
assert(x != forward_ptr);
|
2006-11-23 19:38:26 -05:00
|
|
|
int tag = tagof(x);
|
|
|
|
if(tag == immediate_tag){
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
ikp fst = ref(x, -tag);
|
|
|
|
if(fst == forward_ptr){
|
|
|
|
/* already moved */
|
|
|
|
return ref(x, wordsize-tag);
|
|
|
|
}
|
2006-11-23 19:42:39 -05:00
|
|
|
unsigned int t = gc->segment_vector[page_index(x)];
|
|
|
|
int gen = t & gen_mask;
|
|
|
|
if(gen > gc->collect_gen){
|
|
|
|
return x;
|
|
|
|
}
|
2006-11-23 19:38:26 -05:00
|
|
|
if(tag == pair_tag){
|
2006-11-23 19:42:39 -05:00
|
|
|
ikp y;
|
2006-11-23 19:44:29 -05:00
|
|