svn: r2272
This commit is contained in:
Matthew Flatt 2006-02-17 21:23:21 +00:00
parent 865d7a4945
commit aad0d1e81b
28 changed files with 3191 additions and 2527 deletions

View File

@ -30,7 +30,6 @@ typedef struct {
#if ALIST_USEAPPEARANCEMGR && TARGET_RT_MAC_CFM #if ALIST_USEAPPEARANCEMGR && TARGET_RT_MAC_CFM
ThemeDrawingState themeState; /* This is only needed if we're running under CFM. */ ThemeDrawingState themeState; /* This is only needed if we're running under CFM. */
#endif #endif
/* PixPatHandle backPixPatH, penPixPatH; /* These may still memory leak like a sieve if you have patterns. */
PenState penState; PenState penState;
RGBColor backColor, foreColor; RGBColor backColor, foreColor;
TextStyle textStyle; TextStyle textStyle;

View File

@ -38,6 +38,7 @@ OBJS = salloc.@LTO@ \
fun.@LTO@ \ fun.@LTO@ \
hash.@LTO@ \ hash.@LTO@ \
image.@LTO@ \ image.@LTO@ \
jit.@LTO@ \
list.@LTO@ \ list.@LTO@ \
module.@LTO@ \ module.@LTO@ \
network.@LTO@ \ network.@LTO@ \
@ -78,6 +79,7 @@ XSRCS = $(XSRCDIR)/salloc.c \
$(XSRCDIR)/fun.c \ $(XSRCDIR)/fun.c \
$(XSRCDIR)/hash.c \ $(XSRCDIR)/hash.c \
$(XSRCDIR)/image.c \ $(XSRCDIR)/image.c \
$(XSRCDIR)/jit.c \
$(XSRCDIR)/list.c \ $(XSRCDIR)/list.c \
$(XSRCDIR)/module.c \ $(XSRCDIR)/module.c \
$(XSRCDIR)/network.c \ $(XSRCDIR)/network.c \
@ -144,6 +146,8 @@ $(XSRCDIR)/hash.c: ../src/hash.@LTO@ $(XFORMDEP)
$(XFORM) $(XSRCDIR)/hash.c $(SRCDIR)/hash.c $(XFORM) $(XSRCDIR)/hash.c $(SRCDIR)/hash.c
$(XSRCDIR)/image.c: ../src/image.@LTO@ $(XFORMDEP) $(XSRCDIR)/image.c: ../src/image.@LTO@ $(XFORMDEP)
$(XFORM) $(XSRCDIR)/image.c $(SRCDIR)/image.c $(XFORM) $(XSRCDIR)/image.c $(SRCDIR)/image.c
$(XSRCDIR)/jit.c: ../src/jit.@LTO@ $(XFORMDEP)
$(XFORM) $(XSRCDIR)/jit.c $(SRCDIR)/jit.c
$(XSRCDIR)/module.c: ../src/module.@LTO@ $(XFORMDEP) $(XSRCDIR)/module.c: ../src/module.@LTO@ $(XFORMDEP)
$(XFORM) $(XSRCDIR)/module.c $(SRCDIR)/module.c $(XFORM) $(XSRCDIR)/module.c $(SRCDIR)/module.c
$(XSRCDIR)/list.c: ../src/list.@LTO@ $(XFORMDEP) $(XSRCDIR)/list.c: ../src/list.@LTO@ $(XFORMDEP)
@ -224,6 +228,8 @@ hash.@LTO@: $(XSRCDIR)/hash.c
$(CC) $(CFLAGS) -c $(XSRCDIR)/hash.c -o hash.@LTO@ $(CC) $(CFLAGS) -c $(XSRCDIR)/hash.c -o hash.@LTO@
image.@LTO@: $(XSRCDIR)/image.c image.@LTO@: $(XSRCDIR)/image.c
$(CC) $(CFLAGS) -c $(XSRCDIR)/image.c -o image.@LTO@ $(CC) $(CFLAGS) -c $(XSRCDIR)/image.c -o image.@LTO@
jit.@LTO@: $(XSRCDIR)/jit.c
$(CC) $(CFLAGS) -c $(XSRCDIR)/jit.c -o jit.@LTO@
list.@LTO@: $(XSRCDIR)/list.c list.@LTO@: $(XSRCDIR)/list.c
$(CC) $(CFLAGS) -c $(XSRCDIR)/list.c -o list.@LTO@ $(CC) $(CFLAGS) -c $(XSRCDIR)/list.c -o list.@LTO@
module.@LTO@: $(XSRCDIR)/module.c module.@LTO@: $(XSRCDIR)/module.c
@ -277,7 +283,7 @@ main.@LTO@: $(XSRCDIR)/main.c
gc2.@LTO@: $(srcdir)/gc2.c $(srcdir)/newgc.c $(srcdir)/compact.c $(srcdir)/newgc.c $(srcdir)/gc2.h \ gc2.@LTO@: $(srcdir)/gc2.c $(srcdir)/newgc.c $(srcdir)/compact.c $(srcdir)/newgc.c $(srcdir)/gc2.h \
$(srcdir)/vm_osx.c $(srcdir)/vm_mmap.c $(srcdir)/vm_osk.c $(srcdir)/alloc_cache.c $(srcdir)/my_qsort.c \ $(srcdir)/vm_osx.c $(srcdir)/vm_mmap.c $(srcdir)/vm_osk.c $(srcdir)/alloc_cache.c $(srcdir)/my_qsort.c \
$(srcdir)/weak.c $(srcdir)/../include/scheme.h $(srcdir)/../src/schpriv.h $(srcdir)/weak.c $(srcdir)/fnls.c $(srcdir)/../include/scheme.h $(srcdir)/../src/schpriv.h
$(CC) $(CFLAGS) -c $(srcdir)/gc2.c -o gc2.@LTO@ $(CC) $(CFLAGS) -c $(srcdir)/gc2.c -o gc2.@LTO@
FOREIGN_OBJS = ../../foreign/gcc/libffi/src/*.@LTO@ ../../foreign/gcc/libffi/src/*/*.@LTO@ FOREIGN_OBJS = ../../foreign/gcc/libffi/src/*.@LTO@ ../../foreign/gcc/libffi/src/*/*.@LTO@

View File

@ -370,7 +370,6 @@ static long mark_stackoflw;
#endif #endif
static int fnl_weak_link_count; static int fnl_weak_link_count;
static int num_fnls;
static int ran_final; static int ran_final;
static int running_finals; static int running_finals;
@ -488,7 +487,7 @@ void GC_register_traversers(Type_Tag tag, Size_Proc size, Mark_Proc mark, Fixup_
/* root table */ /* root table */
/******************************************************************************/ /******************************************************************************/
#include "roots.inc" #include "roots.c"
void GC_register_thread(void *p, void *c) void GC_register_thread(void *p, void *c)
{ {
@ -566,19 +565,16 @@ static int is_marked(void *p);
/* finalization */ /* finalization */
/******************************************************************************/ /******************************************************************************/
typedef struct Fnl { static int is_finalizable_page(void *p)
char eager_level; {
char tagged; MPage *page;
void *p; page = find_page(p);
void (*f)(void *p, void *data); return page && page->type;
void *data; }
#if CHECKS
long size;
#endif
struct Fnl *next;
} Fnl;
static Fnl *fnls, *run_queue, *last_in_queue; #include "fnls.c"
static Fnl *run_queue, *last_in_queue;
static void mark_finalizer(Fnl *fnl) static void mark_finalizer(Fnl *fnl)
{ {
@ -618,102 +614,6 @@ static void fixup_finalizer(Fnl *fnl)
#endif #endif
} }
void GC_set_finalizer(void *p, int tagged, int level, void (*f)(void *p, void *data),
void *data, void (**oldf)(void *p, void *data),
void **olddata)
{
Fnl *fnl, *prev;
{
MPage *page;
page = find_page(p);
if (!page || !page->type) {
/* Never collected. Don't finalize it. */
if (oldf) *oldf = NULL;
if (olddata) *olddata = NULL;
return;
}
}
fnl = fnls;
prev = NULL;
while (fnl) {
if (fnl->p == p) {
if (oldf) *oldf = fnl->f;
if (olddata) *olddata = fnl->data;
if (f) {
fnl->f = f;
fnl->data = data;
fnl->eager_level = level;
} else {
if (prev)
prev->next = fnl->next;
else
fnls = fnl->next;
--num_fnls;
return;
}
return;
} else {
prev = fnl;
fnl = fnl->next;
}
}
if (oldf) *oldf = NULL;
if (olddata) *olddata = NULL;
if (!f)
return;
/* Allcation might trigger GC, so we use park: */
park[0] = p;
park[1] = data;
fnl = (Fnl *)GC_malloc_atomic(sizeof(Fnl));
p = park[0];
park[0] = NULL;
data = park[1];
park[1] = NULL;
fnl->next = fnls;
fnl->p = p;
fnl->f = f;
fnl->data = data;
fnl->eager_level = level;
fnl->tagged = tagged;
#if CHECKS
{
MPage *m;
m = find_page(p);
if (tagged) {
if (m->type != MTYPE_TAGGED) {
GCPRINT(GCOUTF, "Not tagged: %lx (%d)\n",
(long)p, m->type);
CRASH(4);
}
} else {
if (m->type != MTYPE_XTAGGED) {
GCPRINT(GCOUTF, "Not xtagged: %lx (%d)\n",
(long)p, m->type);
CRASH(5);
}
if (m->flags & MFLAG_BIGBLOCK)
fnl->size = m->u.size;
else
fnl->size = ((long *)p)[-1];
}
}
#endif
fnls = fnl;
num_fnls++;
}
typedef struct Fnl_Weak_Link { typedef struct Fnl_Weak_Link {
void *p; void *p;
int offset; int offset;
@ -823,7 +723,7 @@ static int is_marked(void *p)
} }
#if SEARCH #if SEARCH
void *search_for, *search_mark; void *search_for, *search_mark = 0x7;
long search_size; long search_size;
void stop() void stop()
@ -841,6 +741,7 @@ void stop()
#if CHECKS #if CHECKS
static void **prev_ptr, **prev_prev_ptr, **prev_prev_prev_ptr; static void **prev_ptr, **prev_prev_ptr, **prev_prev_prev_ptr;
static void **prev_prev_prev_prev_ptr, **prev_prev_prev_prev_prev_ptr;
static void **prev_var_stack; static void **prev_var_stack;
#endif #endif
@ -882,6 +783,8 @@ static void init_tagged_mpage(void **p, MPage *page)
GCFLUSHOUT(); GCFLUSHOUT();
CRASH(7); CRASH(7);
} }
prev_prev_prev_prev_prev_ptr = prev_prev_prev_prev_ptr;
prev_prev_prev_prev_ptr = prev_prev_prev_ptr;
prev_prev_prev_ptr = prev_prev_ptr; prev_prev_prev_ptr = prev_prev_ptr;
prev_prev_ptr = prev_ptr; prev_prev_ptr = prev_ptr;
prev_ptr = p; prev_ptr = p;
@ -898,6 +801,12 @@ static void init_tagged_mpage(void **p, MPage *page)
size = size_proc(p); size = size_proc(p);
} }
#if CHECKS
if (size < 1) {
CRASH(57);
}
#endif
OFFSET_SET_SIZE_UNMASKED(offsets, offset, size); OFFSET_SET_SIZE_UNMASKED(offsets, offset, size);
offset += size; offset += size;
@ -3044,7 +2953,7 @@ static void init(void)
#if USE_FREELIST #if USE_FREELIST
GC_register_traversers(gc_on_free_list_tag, size_on_free_list, size_on_free_list, size_on_free_list, 0, 0); GC_register_traversers(gc_on_free_list_tag, size_on_free_list, size_on_free_list, size_on_free_list, 0, 0);
#endif #endif
GC_add_roots(&fnls, (char *)&fnls + sizeof(fnls) + 1); GC_add_roots(&finalizers, (char *)&finalizers + sizeof(finalizers) + 1);
GC_add_roots(&fnl_weaks, (char *)&fnl_weaks + sizeof(fnl_weaks) + 1); GC_add_roots(&fnl_weaks, (char *)&fnl_weaks + sizeof(fnl_weaks) + 1);
GC_add_roots(&run_queue, (char *)&run_queue + sizeof(run_queue) + 1); GC_add_roots(&run_queue, (char *)&run_queue + sizeof(run_queue) + 1);
GC_add_roots(&last_in_queue, (char *)&last_in_queue + sizeof(last_in_queue) + 1); GC_add_roots(&last_in_queue, (char *)&last_in_queue + sizeof(last_in_queue) + 1);
@ -3250,7 +3159,7 @@ static void gcollect(int full)
{ {
Fnl *f; Fnl *f;
for (f = fnls; f; f = f->next) { for (f = finalizers; f; f = f->next) {
#if RECORD_MARK_SRC #if RECORD_MARK_SRC
mark_src = f; mark_src = f;
mark_type = MTYPE_FINALIZER; mark_type = MTYPE_FINALIZER;
@ -3309,7 +3218,7 @@ static void gcollect(int full)
/* Propagate all marks. */ /* Propagate all marks. */
propagate_all_mpages(); propagate_all_mpages();
if ((did_fnls >= 3) || !fnls) { if ((did_fnls >= 3) || !finalizers) {
if (did_fnls == 3) { if (did_fnls == 3) {
/* Finish up ordered finalization */ /* Finish up ordered finalization */
Fnl *f, *next, *prev; Fnl *f, *next, *prev;
@ -3318,7 +3227,7 @@ static void gcollect(int full)
/* Enqueue and mark level 3 finalizers that still haven't been marked. */ /* Enqueue and mark level 3 finalizers that still haven't been marked. */
/* (Recursive marking is already done, though.) */ /* (Recursive marking is already done, though.) */
prev = NULL; prev = NULL;
for (f = fnls; f; f = next) { for (f = finalizers; f; f = next) {
next = f->next; next = f->next;
if (f->eager_level == 3) { if (f->eager_level == 3) {
if (!is_marked(f->p)) { if (!is_marked(f->p)) {
@ -3332,7 +3241,7 @@ static void gcollect(int full)
if (prev) if (prev)
prev->next = next; prev->next = next;
else else
fnls = next; finalizers = next;
f->eager_level = 0; /* indicates queued */ f->eager_level = 0; /* indicates queued */
@ -3394,7 +3303,7 @@ static void gcollect(int full)
/* Mark content of not-yet-marked finalized objects, /* Mark content of not-yet-marked finalized objects,
but don't mark the finalized objects themselves. */ but don't mark the finalized objects themselves. */
for (f = fnls; f; f = f->next) { for (f = finalizers; f; f = f->next) {
if (f->eager_level == 3) { if (f->eager_level == 3) {
#if RECORD_MARK_SRC #if RECORD_MARK_SRC
mark_src = f; mark_src = f;
@ -3420,7 +3329,7 @@ static void gcollect(int full)
/* Unordered finalization */ /* Unordered finalization */
Fnl *f, *prev, *queue; Fnl *f, *prev, *queue;
f = fnls; f = finalizers;
prev = NULL; prev = NULL;
queue = NULL; queue = NULL;
@ -3433,7 +3342,7 @@ static void gcollect(int full)
if (prev) if (prev)
prev->next = next; prev->next = next;
else else
fnls = next; finalizers = next;
f->eager_level = 0; /* indicates queued */ f->eager_level = 0; /* indicates queued */
@ -3480,7 +3389,7 @@ static void gcollect(int full)
{ {
Fnl *f; Fnl *f;
/* All finalized objects must be marked at this point. */ /* All finalized objects must be marked at this point. */
for (f = fnls; f; f = f->next) { for (f = finalizers; f; f = f->next) {
if (!is_marked(f->p)) if (!is_marked(f->p))
CRASH(35); CRASH(35);
} }
@ -3609,7 +3518,7 @@ static void gcollect(int full)
{ {
Fnl *f; Fnl *f;
for (f = fnls; f; f = f->next) { for (f = finalizers; f; f = f->next) {
#if CHECKS #if CHECKS
fnl_count++; fnl_count++;
#endif #endif
@ -3655,6 +3564,8 @@ static void gcollect(int full)
protect_old_mpages(); protect_old_mpages();
reset_finalizer_tree();
#if (COMPACTING == NEVER_COMPACT) #if (COMPACTING == NEVER_COMPACT)
# define THRESH_FREE_LIST_DELTA (FREE_LIST_DELTA >> LOG_WORD_SIZE) # define THRESH_FREE_LIST_DELTA (FREE_LIST_DELTA >> LOG_WORD_SIZE)
#else #else
@ -4177,6 +4088,11 @@ void GC_free(void *p)
} }
} }
long GC_malloc_atomic_stays_put_threshold()
{
return BIGBLOCK_MIN_SIZE;
}
void GC_gcollect() void GC_gcollect()
{ {
gcollect(1); gcollect(1);
@ -4834,7 +4750,7 @@ void GC_dump(void)
Fnl *f; Fnl *f;
avoid_collection++; avoid_collection++;
GCPRINT(GCOUTF, "Begin Finalizations\n"); GCPRINT(GCOUTF, "Begin Finalizations\n");
for (f = fnls; f; f = f->next) { for (f = finalizers; f; f = f->next) {
print_out_pointer("==@ ", f->p); print_out_pointer("==@ ", f->p);
} }
GCPRINT(GCOUTF, "End Finalizations\n"); GCPRINT(GCOUTF, "End Finalizations\n");

145
src/mzscheme/gc2/fnls.c Normal file
View File

@ -0,0 +1,145 @@
/*
Provides:
struct finalizer { ... } Fnl
GC_set_finalizer
reset_finalizer_tree
finalizers
Requires:
GC_weak_array_tag
is_finalizable_page(p)
park
*/
typedef struct finalizer {
char eager_level;
char tagged;
void *p;
GC_finalization_proc f;
void *data;
#if CHECKS
long size;
#endif
struct finalizer *next;
/* Patched after GC: */
struct finalizer *prev, *left, *right;
} Fnl;
static Fnl *finalizers, *splayed_finalizers;
static int num_fnls;
#define Tree Fnl
#define Splay_Item(t) ((unsigned long)t->p)
#include "../sgc/splay.c"
void GC_set_finalizer(void *p, int tagged, int level, void (*f)(void *p, void *data),
void *data, void (**oldf)(void *p, void *data),
void **olddata)
{
Fnl *fnl;
if (!is_finalizable_page(p)) {
/* Never collected. Don't finalize it. */
if (oldf) *oldf = NULL;
if (olddata) *olddata = NULL;
return;
}
splayed_finalizers = splay((unsigned long)p, splayed_finalizers);
fnl = splayed_finalizers;
if (fnl && (fnl->p == p)) {
if (oldf) *oldf = fnl->f;
if (olddata) *olddata = fnl->data;
if (f) {
fnl->f = f;
fnl->data = data;
fnl->eager_level = level;
} else {
if (fnl->prev)
fnl->prev->next = fnl->next;
else
finalizers = fnl->next;
if (fnl->next)
fnl->next->prev = fnl->prev;
--num_fnls;
splayed_finalizers = splay_delete((unsigned long)p, splayed_finalizers);
}
return;
}
if (oldf) *oldf = NULL;
if (olddata) *olddata = NULL;
if (!f)
return;
/* Allcation might trigger GC, so we use park: */
park[0] = p;
park[1] = data;
fnl = (Fnl *)GC_malloc_atomic(sizeof(Fnl));
p = park[0];
park[0] = NULL;
data = park[1];
park[1] = NULL;
fnl->next = finalizers;
fnl->prev = NULL;
if (finalizers) {
finalizers->prev = fnl;
}
fnl->p = p;
fnl->f = f;
fnl->data = data;
fnl->eager_level = level;
fnl->tagged = tagged;
#if CHECKS
{
MPage *m;
m = find_page(p);
if (tagged) {
if (m->type != MTYPE_TAGGED) {
GCPRINT(GCOUTF, "Not tagged: %lx (%d)\n",
(long)p, m->type);
CRASH(4);
}
} else {
if (m->type != MTYPE_XTAGGED) {
GCPRINT(GCOUTF, "Not xtagged: %lx (%d)\n",
(long)p, m->type);
CRASH(5);
}
if (m->flags & MFLAG_BIGBLOCK)
fnl->size = m->u.size;
else
fnl->size = ((long *)p)[-1];
}
}
#endif
finalizers = fnl;
splayed_finalizers = splay_insert((unsigned long)p, fnl, splayed_finalizers);
num_fnls++;
}
static void reset_finalizer_tree()
/* After a GC, rebuild the splay tree, since object addresses
have moved. */
{
Fnl *fnl, *prev = NULL;
splayed_finalizers = NULL;
for (fnl = finalizers; fnl; fnl = fnl->next) {
fnl->prev = prev;
splayed_finalizers = splay_insert((unsigned long)fnl->p, fnl, splayed_finalizers);
prev = fnl;
}
}

View File

@ -188,6 +188,11 @@ GC2_EXTERN void GC_free_immobile_box(void **b);
Allocate (or free) a non-GCed box containing a pointer to a GCed Allocate (or free) a non-GCed box containing a pointer to a GCed
value. The pointer is stored as the first longword of the box. */ value. The pointer is stored as the first longword of the box. */
GC2_EXTERN long GC_malloc_atomic_stays_put_threshold();
/*
Returns a minimum size for which atomic allocations generate
objects that never move. */
/***************************************************************************/ /***************************************************************************/
/* Memory tracing */ /* Memory tracing */
/***************************************************************************/ /***************************************************************************/

View File

@ -402,6 +402,8 @@ void *GC_malloc_atomic_uncollectable(size_t s) { return malloc(s); }
void *GC_malloc_allow_interior(size_t s) {return allocate_big(s, PAGE_ARRAY);} void *GC_malloc_allow_interior(size_t s) {return allocate_big(s, PAGE_ARRAY);}
void GC_free(void *p) {} void GC_free(void *p) {}
long GC_malloc_atomic_stays_put_threshold() { return gcWORDS_TO_BYTES(MAX_OBJECT_SIZEW); }
/* this function resizes generation 0 to the closest it can get (erring high) /* this function resizes generation 0 to the closest it can get (erring high)
to the size we've computed as ideal */ to the size we've computed as ideal */
inline static void resize_gen0(unsigned long new_size) inline static void resize_gen0(unsigned long new_size)
@ -728,7 +730,7 @@ void GC_fixup_variable_stack(void **var_stack, long delta, void *limit)
/* Routines for root sets */ /* Routines for root sets */
/*****************************************************************************/ /*****************************************************************************/
#include "roots.inc" #include "roots.c"
#define traverse_roots(gcMUCK) { \ #define traverse_roots(gcMUCK) { \
unsigned long j; \ unsigned long j; \
@ -806,58 +808,15 @@ inline static void repair_immobiles(void)
/*****************************************************************************/ /*****************************************************************************/
/* finalizers */ /* finalizers */
/*****************************************************************************/ /*****************************************************************************/
struct finalizer {
char eager_level;
char tagged;
void *p;
GC_finalization_proc f;
void *data;
struct finalizer *next;
};
static struct finalizer *finalizers = NULL; static int is_finalizable_page(void *p)
static struct finalizer *run_queue = NULL, *last_in_queue = NULL;
void GC_set_finalizer(void *p, int tagged, int level,
GC_finalization_proc f, void *data,
GC_finalization_proc *oldf, void **olddata)
{ {
struct mpage *page = find_page(p); return (find_page(p) ? 1 : 0);
struct finalizer *fnl, *prev;
if(!page) {
if(oldf) *oldf = NULL;
if(olddata) *olddata = NULL;
return;
} }
for(fnl = finalizers, prev = NULL; fnl; prev = fnl, fnl = fnl->next) #include "fnls.c"
if(fnl->p == p) {
if(oldf) *oldf = fnl->f;
if(olddata) *olddata = fnl->data;
if(f) { static Fnl *run_queue, *last_in_queue;
fnl->f = f;
fnl->data = data;
fnl->eager_level = level;
} else {
if(prev) prev->next = fnl->next;
if(!prev) finalizers = fnl->next;
}
return;
}
if(oldf) *oldf = NULL;
if(olddata) *olddata = NULL;
if(!f) return;
park[0] = p; park[1] = data;
fnl = GC_malloc_atomic(sizeof(struct finalizer));
p = park[0]; data = park[1]; park[0] = park[1] = NULL;
fnl->p = p; fnl->f = f; fnl->data = data; fnl->eager_level = level;
fnl->tagged = tagged; fnl->next = finalizers;
finalizers = fnl;
}
inline static void mark_finalizer_structs(void) inline static void mark_finalizer_structs(void)
{ {
@ -2390,6 +2349,7 @@ static void garbage_collect(int force_full)
if (generations_available) if (generations_available)
protect_old_pages(); protect_old_pages();
flush_freed_pages(); flush_freed_pages();
reset_finalizer_tree();
/* new we do want the allocator freaking if we go over half */ /* new we do want the allocator freaking if we go over half */
in_unsafe_allocation_mode = 0; in_unsafe_allocation_mode = 0;

View File

@ -1,4 +1,13 @@
/*
Provides:
GC_add_roots
my_qsort
roots, roots_count
Requires:
WORD_SIZE
*/
#define ROOTS_PTR_ALIGNMENT WORD_SIZE #define ROOTS_PTR_ALIGNMENT WORD_SIZE
#define ROOTS_PTR_TO_INT(x) ((unsigned long)x) #define ROOTS_PTR_TO_INT(x) ((unsigned long)x)

View File

@ -62,8 +62,8 @@ static int mark_weak_array(void *p)
data = a->data; data = a->data;
for (i = a->count; i--; ) { for (i = a->count; i--; ) {
if (data[i] if (data[i]
&& (*(short *)(data[i]) != 45) && (*(short *)(data[i]) != 46)
&& (*(short *)(data[i]) != 55)) && (*(short *)(data[i]) != 56))
CRASH(1); CRASH(1);
} }
} }

View File

@ -156,11 +156,9 @@ typedef struct FSSpec mzFSSpec;
#define MZ_EXTERN extern MZ_DLLSPEC #define MZ_EXTERN extern MZ_DLLSPEC
#ifndef MZ_PRECISE_GC
#if defined(MZ_USE_JIT_PPC) || defined(MZ_USE_JIT_I386) #if defined(MZ_USE_JIT_PPC) || defined(MZ_USE_JIT_I386)
# define MZ_USE_JIT # define MZ_USE_JIT
#endif #endif
#endif
/* Define _W64 for MSC if needed. */ /* Define _W64 for MSC if needed. */
#if defined(_MSC_VER) && !defined(_W64) #if defined(_MSC_VER) && !defined(_W64)
@ -790,7 +788,10 @@ typedef long mz_pre_jmp_buf[8];
#endif #endif
#ifdef MZ_USE_JIT #ifdef MZ_USE_JIT
typedef struct { mz_pre_jmp_buf jb; void *stack_frame; } mz_one_jit_jmp_buf; typedef struct {
mz_pre_jmp_buf jb;
unsigned long stack_frame; /* declared as `long' to hide pointer from 3m xform */
} mz_one_jit_jmp_buf;
typedef mz_one_jit_jmp_buf mz_jit_jmp_buf[1]; typedef mz_one_jit_jmp_buf mz_jit_jmp_buf[1];
#else #else
# define mz_jit_jmp_buf mz_pre_jmp_buf # define mz_jit_jmp_buf mz_pre_jmp_buf
@ -799,7 +800,7 @@ typedef mz_one_jit_jmp_buf mz_jit_jmp_buf[1];
#ifdef MZ_PRECISE_GC #ifdef MZ_PRECISE_GC
typedef struct { typedef struct {
mz_jit_jmp_buf jb; mz_jit_jmp_buf jb;
long gcvs; /* declared as `long' so it isn't pushed when on the stack! */ long gcvs; /* declared as `long' to hide pointer from 3m xform */
long gcvs_cnt; long gcvs_cnt;
} mz_jmp_buf; } mz_jmp_buf;
#else #else
@ -880,6 +881,7 @@ typedef struct Scheme_Thread {
mz_jmp_buf *error_buf; mz_jmp_buf *error_buf;
Scheme_Continuation_Jump_State cjs; Scheme_Continuation_Jump_State cjs;
Scheme_Object *current_escape_cont_key;
Scheme_Thread_Cell_Table *cell_values; Scheme_Thread_Cell_Table *cell_values;
Scheme_Config *init_config; Scheme_Config *init_config;

View File

@ -606,40 +606,40 @@ static Tree *next(Tree *node)
static void remove_freepage(SectorFreepage *fp) static void remove_freepage(SectorFreepage *fp)
{ {
/* Remove fp from freelists: */ /* Remove fp from freelists: */
sector_freepage_by_start = delete(fp->start, sector_freepage_by_start); sector_freepage_by_start = splay_delete(fp->start, sector_freepage_by_start);
sector_freepage_by_end = delete(fp->end, sector_freepage_by_end); sector_freepage_by_end = splay_delete(fp->end, sector_freepage_by_end);
sector_freepage_by_size = splay(fp->size, sector_freepage_by_size); sector_freepage_by_size = splay(fp->size, sector_freepage_by_size);
if (TREE_FP(sector_freepage_by_size) == fp) { if (TREE_FP(sector_freepage_by_size) == fp) {
/* This was the representative for its size; remove it. */ /* This was the representative for its size; remove it. */
sector_freepage_by_size = delete(fp->size, sector_freepage_by_size); sector_freepage_by_size = splay_delete(fp->size, sector_freepage_by_size);
if (fp->same_size) { if (fp->same_size) {
SectorFreepage *same; SectorFreepage *same;
same = TREE_FP(fp->same_size); same = TREE_FP(fp->same_size);
same->same_size = delete(same->start, fp->same_size); same->same_size = splay_delete(same->start, fp->same_size);
sector_freepage_by_size = insert(same->size, &same->by_size, sector_freepage_by_size); sector_freepage_by_size = splay_insert(same->size, &same->by_size, sector_freepage_by_size);
} }
} else { } else {
/* Not the top-level representative; remove it from the representative's /* Not the top-level representative; remove it from the representative's
same_size tree */ same_size tree */
SectorFreepage *same; SectorFreepage *same;
same = TREE_FP(sector_freepage_by_size); same = TREE_FP(sector_freepage_by_size);
same->same_size = delete(fp->start, same->same_size); same->same_size = splay_delete(fp->start, same->same_size);
} }
} }
static void add_freepage(SectorFreepage *naya) static void add_freepage(SectorFreepage *naya)
{ {
naya->by_start.data = (void *)naya; naya->by_start.data = (void *)naya;
sector_freepage_by_start = insert(naya->start, &naya->by_start, sector_freepage_by_start); sector_freepage_by_start = splay_insert(naya->start, &naya->by_start, sector_freepage_by_start);
naya->by_end.data = (void *)naya; naya->by_end.data = (void *)naya;
sector_freepage_by_end = insert(naya->end, &naya->by_end, sector_freepage_by_end); sector_freepage_by_end = splay_insert(naya->end, &naya->by_end, sector_freepage_by_end);
naya->by_size.data = (void *)naya; naya->by_size.data = (void *)naya;
sector_freepage_by_size = insert(naya->size, &naya->by_size, sector_freepage_by_size); sector_freepage_by_size = splay_insert(naya->size, &naya->by_size, sector_freepage_by_size);
if (TREE_FP(sector_freepage_by_size) != naya) { if (TREE_FP(sector_freepage_by_size) != naya) {
/* This size was already in the tree; add it to the next_size list, instead */ /* This size was already in the tree; add it to the next_size list, instead */
SectorFreepage *already = TREE_FP(sector_freepage_by_size); SectorFreepage *already = TREE_FP(sector_freepage_by_size);
naya->by_start_per_size.data = (void *)naya; naya->by_start_per_size.data = (void *)naya;
already->same_size = insert(naya->start, &naya->by_start_per_size, already->same_size); already->same_size = splay_insert(naya->start, &naya->by_start_per_size, already->same_size);
} else } else
naya->same_size = NULL; naya->same_size = NULL;
} }

View File

@ -41,12 +41,15 @@
Addison-Wesley, 1993, pp 367-375. Addison-Wesley, 1993, pp 367-375.
*/ */
#ifndef Tree
typedef struct tree_node Tree; typedef struct tree_node Tree;
struct tree_node { struct tree_node {
Tree * left, * right; Tree * left, * right;
unsigned long item; unsigned long item;
void *data; void *data;
}; };
# define Splay_Item(t) t->item
#endif
static Tree * splay (unsigned long i, Tree * t) { static Tree * splay (unsigned long i, Tree * t) {
/* Simple top down splay, not requiring i to be in the tree t. */ /* Simple top down splay, not requiring i to be in the tree t. */
@ -57,9 +60,9 @@ static Tree * splay (unsigned long i, Tree * t) {
l = r = &N; l = r = &N;
for (;;) { for (;;) {
if (i < t->item) { if (i < Splay_Item(t)) {
if (t->left == NULL) break; if (t->left == NULL) break;
if (i < t->left->item) { if (i < Splay_Item(t->left)) {
y = t->left; /* rotate right */ y = t->left; /* rotate right */
t->left = y->right; t->left = y->right;
y->right = t; y->right = t;
@ -69,9 +72,9 @@ static Tree * splay (unsigned long i, Tree * t) {
r->left = t; /* link right */ r->left = t; /* link right */
r = t; r = t;
t = t->left; t = t->left;
} else if (i > t->item) { } else if (i > Splay_Item(t)) {
if (t->right == NULL) break; if (t->right == NULL) break;
if (i > t->right->item) { if (i > Splay_Item(t->right)) {
y = t->right; /* rotate left */ y = t->right; /* rotate left */
t->right = y->left; t->right = y->left;
y->left = t; y->left = t;
@ -92,21 +95,21 @@ static Tree * splay (unsigned long i, Tree * t) {
return t; return t;
} }
static Tree * insert(unsigned long i, Tree * new, Tree * t) { static Tree * splay_insert(unsigned long i, Tree * new, Tree * t) {
/* Insert i into the tree t, unless it's already there. */ /* Insert i into the tree t, unless it's already there. */
/* Return a pointer to the resulting tree. */ /* Return a pointer to the resulting tree. */
new->item = i; Splay_Item(new) = i;
if (t == NULL) { if (t == NULL) {
new->left = new->right = NULL; new->left = new->right = NULL;
return new; return new;
} }
t = splay(i,t); t = splay(i,t);
if (i < t->item) { if (i < Splay_Item(t)) {
new->left = t->left; new->left = t->left;
new->right = t; new->right = t;
t->left = NULL; t->left = NULL;
return new; return new;
} else if (i > t->item) { } else if (i > Splay_Item(t)) {
new->right = t->right; new->right = t->right;
new->left = t; new->left = t;
t->right = NULL; t->right = NULL;
@ -117,13 +120,13 @@ static Tree * insert(unsigned long i, Tree * new, Tree * t) {
} }
} }
static Tree * delete(unsigned long i, Tree * t) { static Tree * splay_delete(unsigned long i, Tree * t) {
/* Deletes i from the tree if it's there. */ /* Deletes i from the tree if it's there. */
/* Return a pointer to the resulting tree. */ /* Return a pointer to the resulting tree. */
Tree * x; Tree * x;
if (t==NULL) return NULL; if (t==NULL) return NULL;
t = splay(i,t); t = splay(i,t);
if (i == t->item) { /* found it */ if (i == Splay_Item(t)) { /* found it */
if (t->left == NULL) { if (t->left == NULL) {
x = t->right; x = t->right;
} else { } else {

View File

@ -258,7 +258,7 @@ hash.@LTO@: $(srcdir)/schpriv.h $(srcdir)/schexn.h $(SCONFIG) $(srcdir)/../inclu
image.@LTO@: $(srcdir)/schpriv.h $(srcdir)/schexn.h $(SCONFIG) $(srcdir)/../include/scheme.h \ image.@LTO@: $(srcdir)/schpriv.h $(srcdir)/schexn.h $(SCONFIG) $(srcdir)/../include/scheme.h \
$(srcdir)/../src/stypes.h $(srcdir)/schvers.h $(srcdir)/../src/stypes.h $(srcdir)/schvers.h
jit.@LTO@: $(srcdir)/schpriv.h $(srcdir)/schexn.h $(SCONFIG) $(srcdir)/../include/scheme.h \ jit.@LTO@: $(srcdir)/schpriv.h $(srcdir)/schexn.h $(SCONFIG) $(srcdir)/../include/scheme.h \
$(srcdir)/../src/stypes.h $(srcdir)/schvers.h $(srcdir)/codetab.inc $(srcdir)/../src/stypes.h $(srcdir)/schvers.h $(srcdir)/codetab.inc $(srcdir)/mzmark.c
list.@LTO@: $(srcdir)/schpriv.h $(srcdir)/schexn.h $(SCONFIG) $(srcdir)/../include/scheme.h \ list.@LTO@: $(srcdir)/schpriv.h $(srcdir)/schexn.h $(SCONFIG) $(srcdir)/../include/scheme.h \
$(srcdir)/../src/stypes.h $(srcdir)/../src/stypes.h
module.@LTO@: $(srcdir)/schpriv.h $(srcdir)/schexn.h $(SCONFIG) $(srcdir)/../include/scheme.h \ module.@LTO@: $(srcdir)/schpriv.h $(srcdir)/schexn.h $(SCONFIG) $(srcdir)/../include/scheme.h \

View File

@ -2,23 +2,26 @@
/* Implementation of the "symbol table" for mapping code /* Implementation of the "symbol table" for mapping code
pointers to function names. */ pointers to function names. */
#ifndef MZ_PRECISE_GC
# ifdef USE_SENORA_GC # ifdef USE_SENORA_GC
# define GC_is_marked(p) GC_base(p) # define GC_is_marked(p) GC_base(p)
# else # else
extern MZ_DLLIMPORT int GC_is_marked(void *); extern MZ_DLLIMPORT int GC_is_marked(void *);
# endif # endif
#endif
#define LOG_KEY_SIZE 4 #define LOG_KEY_SIZE 4
#define KEY_MASK ((1 << LOG_KEY_SIZE) - 1) #define KEY_MASK ((1 << LOG_KEY_SIZE) - 1)
#define KEY_COUNT (1 << LOG_KEY_SIZE) #define KEY_COUNT (1 << LOG_KEY_SIZE)
#define NODE_HEADER_SIZE 2 /* In words: */
#define NODE_HEADER_SIZE 3
#define NODE_STARTS_OFFSET 1 #define NODE_STARTS_OFFSET 1
#define NODE_GCABLE_OFFSET 2 #define NODE_GCABLE_OFFSET 2
static void **tree; static void **tree;
static int do_clear_symbols(void **t, unsigned long start, int offset, unsigned long addr, int clearing);
static int during_set; static int during_set;
static void *find_symbol(unsigned long v) static void *find_symbol(unsigned long v)
@ -44,6 +47,19 @@ static void *find_symbol(unsigned long v)
return NULL; return NULL;
} }
static void **malloc_node()
{
void **v;
v = (void **)scheme_malloc((KEY_COUNT + NODE_HEADER_SIZE) * sizeof(void *));
/* Set low bit in each of STARTS and GCABLE so that they're not confused
for pointers: */
((unsigned long *)v)[NODE_STARTS_OFFSET] = 0x1;
((unsigned long *)v)[NODE_GCABLE_OFFSET] = 0x1;
return v;
}
static void add_symbol(unsigned long start, unsigned long end, void *value, int gc_able) static void add_symbol(unsigned long start, unsigned long end, void *value, int gc_able)
{ {
unsigned long k1, k2, split_t_start = 0, split_t_end = 0, i; unsigned long k1, k2, split_t_start = 0, split_t_end = 0, i;
@ -53,7 +69,7 @@ static void add_symbol(unsigned long start, unsigned long end, void *value, int
if (!tree) { if (!tree) {
REGISTER_SO(tree); REGISTER_SO(tree);
tree = (void **)scheme_malloc((KEY_COUNT + NODE_HEADER_SIZE) * sizeof(void *)); tree = malloc_node();
} }
during_set++; during_set++;
@ -67,7 +83,7 @@ static void add_symbol(unsigned long start, unsigned long end, void *value, int
if (offset) { if (offset) {
val1 = t1[k1]; val1 = t1[k1];
if (!val1) { if (!val1) {
val1 = (void **)scheme_malloc((KEY_COUNT + NODE_HEADER_SIZE) * sizeof(void *)); val1 = malloc_node();
t1[k1] = val1; t1[k1] = val1;
} }
} else } else
@ -78,7 +94,7 @@ static void add_symbol(unsigned long start, unsigned long end, void *value, int
/* Need to go deeper... */ /* Need to go deeper... */
val2 = t2[k2]; val2 = t2[k2];
if (!val2) { if (!val2) {
val2 = (void **)scheme_malloc((KEY_COUNT + NODE_HEADER_SIZE) * sizeof(void *)); val2 = malloc_node();
t2[k2] = val2; t2[k2] = val2;
} }
} else } else
@ -103,10 +119,17 @@ static void add_symbol(unsigned long start, unsigned long end, void *value, int
} }
/* Mark start bit: */ /* Mark start bit: */
m = (1 << (k1 - NODE_HEADER_SIZE)); m = (1 << (k1 - NODE_HEADER_SIZE + 1));
((unsigned short *)t1)[NODE_STARTS_OFFSET] |= m; ((unsigned long *)t1)[NODE_STARTS_OFFSET] |= m;
#ifndef MZ_PRECISE_GC
/* GCABLE flag indicates whether to check for GC later */
if (gc_able) if (gc_able)
((unsigned short *)t1)[NODE_GCABLE_OFFSET] |= m; ((unsigned long *)t1)[NODE_GCABLE_OFFSET] |= m;
#else
/* GCABLE flag indicates whether it's been GCed: */
if (!value)
((unsigned long *)t1)[NODE_GCABLE_OFFSET] |= m;
#endif
/* Fill in start and end: */ /* Fill in start and end: */
t1[k1] = value; t1[k1] = value;
@ -145,9 +168,19 @@ static void add_symbol(unsigned long start, unsigned long end, void *value, int
} }
--during_set; --during_set;
#ifdef MZ_PRECISE_GC
if (!value) {
/* Prune empty branches in the tree. Only do this if this
object is mapped deeply enough in the tree, otherwise
we end up scanning the whole tree. */
do_clear_symbols(tree, start, 0, 0, 0);
}
#endif
} }
static int do_clear_symbols(void **t, int offset, unsigned long addr, int clearing) static int do_clear_symbols(void **t, unsigned long start, int offset, unsigned long addr, int clearing)
/* If MZ_PRECISE_GC, then offset and addr are not used. */
{ {
int i, m, j; int i, m, j;
void *p, *val, **subt; void *p, *val, **subt;
@ -155,26 +188,44 @@ static int do_clear_symbols(void **t, int offset, unsigned long addr, int cleari
/* Note: this function might be called (via a GC callback) /* Note: this function might be called (via a GC callback)
while add_symbol is running. */ while add_symbol is running. */
for (i = 0; i < KEY_COUNT; i++) { for (i = ((start >> offset) & KEY_MASK); i < KEY_COUNT; i++) {
m = (1 << i); m = (1 << (i + 1));
if (((unsigned short *)t)[NODE_STARTS_OFFSET] & m) { if (((unsigned long *)t)[NODE_STARTS_OFFSET] & m) {
clearing = 0; clearing = 0;
if (((unsigned short *)t)[NODE_GCABLE_OFFSET] & m) { if (((unsigned long *)t)[NODE_GCABLE_OFFSET] & m) {
/* GCable pointer starts here */ /* GCable pointer starts here */
#ifndef MZ_PRECISE_GC
/* Conservative GC: GCable flag means use GC_is_marked */
p = (void *)(addr + (i << offset)); p = (void *)(addr + (i << offset));
if (!GC_is_marked(p)) { if (!GC_is_marked(p))
/* Collected... */
((unsigned short *)t)[NODE_STARTS_OFFSET] -= m;
((unsigned short *)t)[NODE_GCABLE_OFFSET] -= m;
clearing = 1; clearing = 1;
#else
/* Precise GC: GCable flag means it's gone */
clearing = 1;
#endif
if (clearing) {
/* Collected... */
((unsigned long *)t)[NODE_STARTS_OFFSET] -= m;
((unsigned long *)t)[NODE_GCABLE_OFFSET] -= m;
}
} else {
#ifdef MZ_PRECISE_GC
return 0;
#endif
} }
} }
}
#ifdef MZ_PRECISE_GC
if (!clearing)
val = NULL;
else
#endif
val = t[i + NODE_HEADER_SIZE]; val = t[i + NODE_HEADER_SIZE];
if (val) { if (val) {
if (!*(Scheme_Type *)val) { if (!*(Scheme_Type *)val) {
subt = (void **)val; subt = (void **)val;
clearing = do_clear_symbols(subt, clearing = do_clear_symbols(subt, start,
offset - LOG_KEY_SIZE, offset - LOG_KEY_SIZE,
(addr + (i << offset)), (addr + (i << offset)),
clearing); clearing);
@ -188,6 +239,12 @@ static int do_clear_symbols(void **t, int offset, unsigned long addr, int cleari
t[i + NODE_HEADER_SIZE] = NULL; t[i + NODE_HEADER_SIZE] = NULL;
} }
} }
#ifdef MZ_PRECISE_GC
if (!clearing) {
/* Finished clearing the one item, so return. */
return 0;
}
#endif
} else if (clearing) } else if (clearing)
t[i + NODE_HEADER_SIZE] = NULL; t[i + NODE_HEADER_SIZE] = NULL;
} }
@ -196,13 +253,17 @@ static int do_clear_symbols(void **t, int offset, unsigned long addr, int cleari
return clearing; return clearing;
} }
#ifndef MZ_PRECISE_GC
static void clear_symbols_for_collected() static void clear_symbols_for_collected()
{ {
if (tree) { if (tree) {
do_clear_symbols(tree, (JIT_WORD_SIZE * 8) - LOG_KEY_SIZE, 0, 0); do_clear_symbols(tree, 0, (JIT_WORD_SIZE * 8) - LOG_KEY_SIZE, 0, 0);
} }
} }
#endif
/*============================================================*/ /*============================================================*/
/* testing */ /* testing */
/*============================================================*/ /*============================================================*/

File diff suppressed because it is too large Load Diff

View File

@ -239,7 +239,7 @@ scheme_init_fun (Scheme_Env *env)
o = scheme_make_prim_w_arity2(scheme_call_ec, o = scheme_make_prim_w_arity2(scheme_call_ec,
"call-with-escape-continuation", "call-with-escape-continuation",
1, 1, 1, 1,
0, -1), 0, -1);
scheme_add_global_constant("call-with-escape-continuation", o, env); scheme_add_global_constant("call-with-escape-continuation", o, env);
scheme_add_global_constant("call/ec", o, env); scheme_add_global_constant("call/ec", o, env);
@ -2575,6 +2575,32 @@ static void copy_cjs(Scheme_Continuation_Jump_State *a, Scheme_Continuation_Jump
a->is_kill = b->is_kill; a->is_kill = b->is_kill;
} }
static Scheme_Object *get_ec_marks_prefix()
{
Scheme_Thread *p = scheme_current_thread;
Scheme_Object *pr = scheme_null;
long findpos;
Scheme_Cont_Mark *find;
findpos = (long)MZ_CONT_MARK_STACK;
while (findpos--) {
long pos;
find = p->cont_mark_stack_segments[findpos >> SCHEME_LOG_MARK_SEGMENT_SIZE];
pos = findpos & SCHEME_MARK_SEGMENT_MASK;
if (find[pos].pos != MZ_CONT_MARK_POS)
break;
pr = scheme_make_pair(scheme_make_pair(find[pos].key,
find[pos].val),
pr);
}
return pr;
}
Scheme_Object * Scheme_Object *
scheme_call_ec (int argc, Scheme_Object *argv[]) scheme_call_ec (int argc, Scheme_Object *argv[])
{ {
@ -2583,12 +2609,37 @@ scheme_call_ec (int argc, Scheme_Object *argv[])
Scheme_Thread *p1 = scheme_current_thread; Scheme_Thread *p1 = scheme_current_thread;
Scheme_Object * volatile v; Scheme_Object * volatile v;
Scheme_Object *mark_key, *a[1]; Scheme_Object *mark_key, *a[1];
Scheme_Cont_Frame_Data volatile cframe;
scheme_check_proc_arity("call-with-escaping-continuation", 1, scheme_check_proc_arity("call-with-escaping-continuation", 1,
0, argc, argv); 0, argc, argv);
mark_key = scheme_make_pair(scheme_false, scheme_false); /* In tail position with respect to an existing
escape continuation? */
mark_key = p1->current_escape_cont_key;
if (mark_key && SAME_OBJ((Scheme_Object *)MZ_CONT_MARK_POS,
SCHEME_CAR(mark_key))) {
/* Yes - reuse the old continuation */
cont = (Scheme_Escaping_Cont *)SCHEME_CDR(mark_key);
v = get_ec_marks_prefix();
if (!scheme_equal(v, cont->marks_prefix)) {
/* The continuation marks are different this time.
We need to clone the continuation, then change mark prefix. */
Scheme_Escaping_Cont *c2;
c2 = MALLOC_ONE_TAGGED(Scheme_Escaping_Cont);
memcpy(c2, cont, sizeof(Scheme_Escaping_Cont));
c2->marks_prefix = v;
cont = c2;
}
a[0] = (Scheme_Object *)cont;
SCHEME_USE_FUEL(1);
return scheme_tail_apply(argv[0], 1, a);
}
mark_key = scheme_make_pair((Scheme_Object *)MZ_CONT_MARK_POS,
scheme_false);
cont = MALLOC_ONE_TAGGED(Scheme_Escaping_Cont); cont = MALLOC_ONE_TAGGED(Scheme_Escaping_Cont);
cont->so.type = scheme_escaping_cont_type; cont->so.type = scheme_escaping_cont_type;
@ -2596,17 +2647,26 @@ scheme_call_ec (int argc, Scheme_Object *argv[])
cont->suspend_break = p1->suspend_break; cont->suspend_break = p1->suspend_break;
copy_cjs(&cont->cjs, &p1->cjs); copy_cjs(&cont->cjs, &p1->cjs);
SCHEME_CDR(mark_key) = (Scheme_Object *)cont;
v = get_ec_marks_prefix();
cont->marks_prefix = v;
cont->saveerr = p1->error_buf; cont->saveerr = p1->error_buf;
p1->error_buf = &newbuf; p1->error_buf = &newbuf;
scheme_save_env_stack_w_thread(cont->envss, p1); scheme_save_env_stack_w_thread(cont->envss, p1);
scheme_push_continuation_frame((Scheme_Cont_Frame_Data *)&cframe); /* Don't push a continuation frame; argument function
is called as tail. */
scheme_set_cont_mark(mark_key, scheme_true); scheme_set_cont_mark(mark_key, scheme_true);
p1->current_escape_cont_key = mark_key;
if (scheme_setjmp(newbuf)) { if (scheme_setjmp(newbuf)) {
Scheme_Thread *p2 = scheme_current_thread; Scheme_Thread *p2 = scheme_current_thread;
if ((void *)p2->cjs.jumping_to_continuation == cont) { if (p2->cjs.jumping_to_continuation
&& SAME_OBJ(p2->cjs.jumping_to_continuation->mark_key,
cont->mark_key)) {
int n = p2->cjs.num_vals; int n = p2->cjs.num_vals;
Scheme_Object **vs = p2->cjs.u.vals; Scheme_Object **vs = p2->cjs.u.vals;
v = p2->cjs.u.val; v = p2->cjs.u.val;
@ -2619,15 +2679,22 @@ scheme_call_ec (int argc, Scheme_Object *argv[])
scheme_longjmp(*cont->saveerr, 1); scheme_longjmp(*cont->saveerr, 1);
} }
} else { } else {
/* Adjusting MZ_CONT_MARK_POS, we make the application appear to
be in tail position. The actual non-tailness is limited to a
single frame, since call_ec checks the current escape-cont key
as a continuation mark before getting here. */
MZ_CONT_MARK_POS -= 2;
a[0] = (Scheme_Object *)cont; a[0] = (Scheme_Object *)cont;
v = _scheme_apply_multi(argv[0], 1, a); v = _scheme_apply_multi(argv[0], 1, a);
MZ_CONT_MARK_POS += 2;
} }
p1 = scheme_current_thread; p1 = scheme_current_thread;
p1->error_buf = cont->saveerr; p1->error_buf = cont->saveerr;
p1->current_escape_cont_key = cont->envss.current_escape_cont_key;
scheme_pop_continuation_frame((Scheme_Cont_Frame_Data *)&cframe);
return v; return v;
} }
@ -3022,10 +3089,23 @@ internal_call_cc (int argc, Scheme_Object *argv[])
sub_cont = NULL; sub_cont = NULL;
if (sub_cont && (sub_cont->ss.cont_mark_pos == MZ_CONT_MARK_POS)) { if (sub_cont && (sub_cont->ss.cont_mark_pos == MZ_CONT_MARK_POS)) {
Scheme_Object *argv2[1]; Scheme_Object *argv2[1];
#ifdef MZ_USE_JIT
ret = scheme_native_stack_trace();
#endif
/* Old cont is the same as this one, except that it may /* Old cont is the same as this one, except that it may
have different marks (not counting cont_key). */ have different marks (not counting cont_key). */
if ((sub_cont->cont_mark_shareable == (long)sub_cont->ss.cont_mark_stack) if ((sub_cont->cont_mark_shareable == (long)sub_cont->ss.cont_mark_stack)
&& (find_shareable_marks() == MZ_CONT_MARK_STACK)) { && (find_shareable_marks() == MZ_CONT_MARK_STACK)
#ifdef MZ_USE_JIT
&& (SAME_OBJ(ret, sub_cont->native_trace)
/* Maybe a single-function loop, where we re-allocated the
last pair in the trace, but it's the same name: */
|| (SCHEME_PAIRP(ret)
&& SCHEME_PAIRP(sub_cont->native_trace)
&& SAME_OBJ(SCHEME_CAR(ret), SCHEME_CAR(sub_cont->native_trace))
&& SAME_OBJ(SCHEME_CDR(ret), SCHEME_CDR(sub_cont->native_trace))))
#endif
) {
/* Just use this one. */ /* Just use this one. */
cont = sub_cont; cont = sub_cont;
} else { } else {
@ -3045,6 +3125,9 @@ internal_call_cc (int argc, Scheme_Object *argv[])
cont->cont_mark_offset = offset; cont->cont_mark_offset = offset;
offset = find_shareable_marks(); offset = find_shareable_marks();
cont->cont_mark_shareable = offset; cont->cont_mark_shareable = offset;
#ifdef MZ_USE_JIT
cont->native_trace = ret;
#endif
} }
argv2[0] = (Scheme_Object *)cont; argv2[0] = (Scheme_Object *)cont;
@ -3095,6 +3178,11 @@ internal_call_cc (int argc, Scheme_Object *argv[])
} }
} }
#ifdef MZ_USE_JIT
ret = scheme_native_stack_trace();
cont->native_trace = ret;
#endif
saved = copy_out_runstack(p, MZ_RUNSTACK, MZ_RUNSTACK_START, sub_cont); saved = copy_out_runstack(p, MZ_RUNSTACK, MZ_RUNSTACK_START, sub_cont);
cont->runstack_copied = saved; cont->runstack_copied = saved;
{ {
@ -3425,6 +3513,10 @@ static Scheme_Object *continuation_marks(Scheme_Thread *p,
find = seg; find = seg;
} }
/* For econt, skip positions that match cmpos; the econt
record has a prefix to use, instead. */
if (!econt || (find[pos].pos != cmpos)) {
cache = find[pos].cache; cache = find[pos].cache;
if (cache) { if (cache) {
if (SCHEME_FALSEP(cache)) if (SCHEME_FALSEP(cache))
@ -3463,11 +3555,32 @@ static Scheme_Object *continuation_marks(Scheme_Thread *p,
last = pr; last = pr;
} }
} }
}
if (econt) {
Scheme_Object *l, *a;
for (l = ((Scheme_Escaping_Cont *)econt)->marks_prefix; SCHEME_PAIRP(l); l = SCHEME_CDR(l)) {
Scheme_Cont_Mark_Chain *pr;
pr = MALLOC_ONE_RT(Scheme_Cont_Mark_Chain);
pr->so.type = scheme_cont_mark_chain_type;
a = SCHEME_CAR(l);
pr->key = SCHEME_CAR(a);
pr->val = SCHEME_CDR(a);
pr->pos = cmpos;
pr->next = first;
first = pr;
}
}
if (just_chain) if (just_chain)
return (Scheme_Object *)first; return (Scheme_Object *)first;
#ifdef MZ_USE_JIT #ifdef MZ_USE_JIT
if (cont)
nt = cont->native_trace;
else if (econt)
nt = ((Scheme_Escaping_Cont *)econt)->native_trace;
else
nt = scheme_native_stack_trace(); nt = scheme_native_stack_trace();
#else #else
nt = NULL; nt = NULL;

View File

@ -26,6 +26,17 @@
# define _CALL_DARWIN # define _CALL_DARWIN
#endif #endif
/* Separate JIT_PRECISE_GC lets us test some 3m support
in non-3m mode: */
#ifdef MZ_PRECISE_GC
# define JIT_PRECISE_GC
#endif
/* IMPORTANT! 3m arithmetic checking disabled for the whole file! */
#ifdef MZ_PRECISE_GC
END_XFORM_ARITH;
#endif
#include "lightning/lightning.h" #include "lightning/lightning.h"
#define JIT_LOG_WORD_SIZE 2 #define JIT_LOG_WORD_SIZE 2
@ -65,7 +76,8 @@ static void *get_stack_pointer_code;
static void *stack_cache_pop_code; static void *stack_cache_pop_code;
typedef struct { typedef struct {
jit_state js; MZTAG_IF_REQUIRED
GC_CAN_IGNORE jit_state js;
char *limit; char *limit;
int extra_pushed, max_extra_pushed; int extra_pushed, max_extra_pushed;
int depth, max_depth; int depth, max_depth;
@ -98,6 +110,11 @@ static void on_demand();
static int generate_non_tail_mark_pos_prefix(mz_jit_state *jitter); static int generate_non_tail_mark_pos_prefix(mz_jit_state *jitter);
static void generate_non_tail_mark_pos_suffix(mz_jit_state *jitter); static void generate_non_tail_mark_pos_suffix(mz_jit_state *jitter);
#ifdef MZ_PRECISE_GC
static void register_traversers(void);
static void release_native_code(void *fnlized, void *p);
#endif
/* Tracking statistics: */ /* Tracking statistics: */
#if 0 #if 0
# define NUM_CATEGORIES 23 # define NUM_CATEGORIES 23
@ -173,11 +190,11 @@ static int mz_retain_it(mz_jit_state *jitter, void *v)
return jitter->retained; return jitter->retained;
} }
#ifdef MZ_PRECISE_GC #ifdef JIT_PRECISE_GC
static void mz_load_retained(mz_jit_state *jitter, int rs, int retptr) static void mz_load_retained(mz_jit_state *jitter, int rs, int retptr)
{ {
void *p; void *p;
p = jitter->retain_start + retptr; p = jitter->retain_start + retptr - 1;
(void)jit_movi_p(rs, p); (void)jit_movi_p(rs, p);
jit_ldr_p(rs, rs); jit_ldr_p(rs, rs);
} }
@ -187,7 +204,8 @@ static void *generate_one(mz_jit_state *old_jitter,
Generate_Proc generate, Generate_Proc generate,
void *data, void *data,
int gcable, int gcable,
void *save_ptr) void *save_ptr,
Scheme_Native_Closure_Data *ndata)
{ {
mz_jit_state _jitter; mz_jit_state _jitter;
mz_jit_state *jitter = &_jitter; mz_jit_state *jitter = &_jitter;
@ -197,11 +215,24 @@ static void *generate_one(mz_jit_state *old_jitter,
long size = JIT_BUFFER_INIT_SIZE, known_size = 0, size_pre_retained = 0, num_retained = 0, padding; long size = JIT_BUFFER_INIT_SIZE, known_size = 0, size_pre_retained = 0, num_retained = 0, padding;
int mappings_size = JIT_INIT_MAPPINGS_SIZE; int mappings_size = JIT_INIT_MAPPINGS_SIZE;
int ok, max_extra_pushed = 0; int ok, max_extra_pushed = 0;
#ifdef MZ_PRECISE_GC
Scheme_Object *fnl_obj;
if (ndata) {
/* When fnl_obj becomes inaccessible, code generated
here can be freed. */
fnl_obj = scheme_box(scheme_false);
} else
fnl_obj = NULL;
#endif
if (!jit_buffer_cache_registered) { if (!jit_buffer_cache_registered) {
jit_buffer_cache_registered = 1; jit_buffer_cache_registered = 1;
REGISTER_SO(jit_buffer_cache); REGISTER_SO(jit_buffer_cache);
REGISTER_SO(stack_cache_stack); REGISTER_SO(stack_cache_stack);
#ifdef MZ_PRECISE_GC
register_traversers();
#endif
/* printf("zap!\n"); */ /* printf("zap!\n"); */
} }
@ -216,7 +247,11 @@ static void *generate_one(mz_jit_state *old_jitter,
size = size_pre_retained + WORDS_TO_BYTES(num_retained); size = size_pre_retained + WORDS_TO_BYTES(num_retained);
padding = 0; padding = 0;
if (gcable) { if (gcable) {
#ifdef MZ_PRECISE_GC
buffer = malloc(size);
#else
buffer = scheme_malloc(size); buffer = scheme_malloc(size);
#endif
} else { } else {
buffer = malloc(size); buffer = malloc(size);
} }
@ -242,16 +277,35 @@ static void *generate_one(mz_jit_state *old_jitter,
size = jit_buffer_cache_size; size = jit_buffer_cache_size;
jit_buffer_cache = NULL; jit_buffer_cache = NULL;
} else { } else {
#ifdef MZ_PRECISE_GC
long minsz;
minsz = GC_malloc_atomic_stays_put_threshold();
if (size < minsz)
size = minsz;
buffer = (char *)scheme_malloc_atomic(size);
#else
buffer = scheme_malloc(size); buffer = scheme_malloc(size);
#endif
} }
size_pre_retained = size; size_pre_retained = size;
} }
(void)jit_set_ip(buffer).ptr; (void)jit_set_ip(buffer).ptr;
jitter->limit = (char *)buffer + size_pre_retained - padding; jitter->limit = (char *)buffer + size_pre_retained - padding;
if (known_size) if (known_size) {
jitter->retain_start = (void *)jitter->limit; jitter->retain_start = (void *)jitter->limit;
else #ifdef MZ_PRECISE_GC
if (ndata) {
memset(jitter->retain_start, 0, num_retained * sizeof(void*));
ndata->retained = jitter->retain_start;
ndata->retain_count = num_retained;
SCHEME_BOX_VAL(fnl_obj) = scheme_make_integer(size_pre_retained);
GC_set_finalizer(fnl_obj, 1, 1,
release_native_code, buffer,
NULL, NULL);
}
#endif
} else
jitter->retain_start = NULL; jitter->retain_start = NULL;
jitter->mappings = mappings; jitter->mappings = mappings;
@ -265,6 +319,11 @@ static void *generate_one(mz_jit_state *old_jitter,
if (save_ptr) { if (save_ptr) {
mz_retain_it(jitter, save_ptr); mz_retain_it(jitter, save_ptr);
} }
#ifdef MZ_PRECISE_GC
if (fnl_obj) {
mz_retain_it(jitter, fnl_obj);
}
#endif
jitter->limit = (char *)jitter->limit + padding; jitter->limit = (char *)jitter->limit + padding;
if (PAST_LIMIT() || (jitter->retain_start if (PAST_LIMIT() || (jitter->retain_start
@ -1217,7 +1276,7 @@ static void *generate_shared_call(int num_rands, mz_jit_state *old_jitter, int m
data.direct_prim = direct_prim; data.direct_prim = direct_prim;
data.direct_native = direct_native; data.direct_native = direct_native;
return generate_one(old_jitter, do_generate_shared_call, &data, 0, NULL); return generate_one(old_jitter, do_generate_shared_call, &data, 0, NULL, NULL);
} }
static int generate_app(Scheme_App_Rec *app, Scheme_Object **alt_rands, int num_rands, static int generate_app(Scheme_App_Rec *app, Scheme_Object **alt_rands, int num_rands,
@ -2019,7 +2078,7 @@ static int generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
__START_SHORT_JUMPS__(branch_short); __START_SHORT_JUMPS__(branch_short);
#ifdef MZ_PRECISE_GC #ifdef JIT_PRECISE_GC
if (retptr) { if (retptr) {
mz_load_retained(jitter, JIT_R1, retptr); mz_load_retained(jitter, JIT_R1, retptr);
ref = jit_bner_p(jit_forward(), JIT_R0, JIT_R1); ref = jit_bner_p(jit_forward(), JIT_R0, JIT_R1);
@ -2207,7 +2266,7 @@ static int generate_closure(Scheme_Closure_Data *data,
JIT_UPDATE_THREAD_RSPTR_IF_NEEDED(); JIT_UPDATE_THREAD_RSPTR_IF_NEEDED();
mz_prepare(1); mz_prepare(1);
retptr = mz_retain(code); retptr = mz_retain(code);
#ifdef MZ_PRECISE_GC #ifdef JIT_PRECISE_GC
mz_load_retained(jitter, JIT_R0, retptr); mz_load_retained(jitter, JIT_R0, retptr);
#else #else
(void)jit_movi_p(JIT_R0, code); /* !! */ (void)jit_movi_p(JIT_R0, code); /* !! */
@ -2245,6 +2304,9 @@ Scheme_Native_Closure_Data *scheme_generate_case_lambda(Scheme_Case_Lambda *c)
int max_let_depth = 0, i, count, is_method = 0; int max_let_depth = 0, i, count, is_method = 0;
ndata = MALLOC_ONE_RT(Scheme_Native_Closure_Data); ndata = MALLOC_ONE_RT(Scheme_Native_Closure_Data);
#ifdef MZTAG_REQUIRED
ndata->type = scheme_rt_native_code;
#endif
name = c->name; name = c->name;
if (name && SCHEME_BOXP(name)) { if (name && SCHEME_BOXP(name)) {
name = SCHEME_BOX_VAL(name); name = SCHEME_BOX_VAL(name);
@ -2300,7 +2362,7 @@ static int generate_case_closure(Scheme_Object *obj, mz_jit_state *jitter)
JIT_UPDATE_THREAD_RSPTR_IF_NEEDED(); JIT_UPDATE_THREAD_RSPTR_IF_NEEDED();
mz_prepare(1); mz_prepare(1);
retptr = mz_retain(ndata); retptr = mz_retain(ndata);
#ifdef MZ_PRECISE_GC #ifdef JIT_PRECISE_GC
mz_load_retained(jitter, JIT_R0, retptr); mz_load_retained(jitter, JIT_R0, retptr);
#else #else
(void)jit_movi_p(JIT_R0, ndata); /* !! */ (void)jit_movi_p(JIT_R0, ndata); /* !! */
@ -2442,9 +2504,11 @@ static int generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int m
Scheme_Thread *p = scheme_current_thread; Scheme_Thread *p = scheme_current_thread;
mz_jit_state *jitter_copy; mz_jit_state *jitter_copy;
/* 3m FIXME: need precise handling of this copy: */ jitter_copy = MALLOC_ONE_RT(mz_jit_state);
jitter_copy = (mz_jit_state *)scheme_malloc(sizeof(jitter_copy));
memcpy(jitter_copy, jitter, sizeof(mz_jit_state)); memcpy(jitter_copy, jitter, sizeof(mz_jit_state));
#ifdef MZTAG_REQUIRED
jitter_copy->type = scheme_rt_jitter_data;
#endif
p->ku.k.p1 = (void *)obj; p->ku.k.p1 = (void *)obj;
p->ku.k.p2 = (void *)jitter_copy; p->ku.k.p2 = (void *)jitter_copy;
@ -3191,7 +3255,7 @@ static int generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int m
} else } else
retptr = 0; retptr = 0;
#ifdef MZ_PRECISE_GC #ifdef JIT_PRECISE_GC
if (retptr) if (retptr)
mz_load_retained(jitter, JIT_R0, retptr); mz_load_retained(jitter, JIT_R0, retptr);
else else
@ -3378,7 +3442,7 @@ static int do_generate_common(mz_jit_state *jitter, void *_data)
__START_SHORT_JUMPS__(1); __START_SHORT_JUMPS__(1);
/* Load global array: */ /* Load global array: */
jit_ldxr_p(JIT_V1, JIT_RUNSTACK, JIT_R0); jit_ldxr_p(JIT_V1, JIT_RUNSTACK, JIT_R0);
#ifdef MZ_PRECISE_GC #ifdef JIT_PRECISE_GC
/* Save global-array index before we lose it: */ /* Save global-array index before we lose it: */
mz_set_local_p(JIT_R0, JIT_LOCAL3); mz_set_local_p(JIT_R0, JIT_LOCAL3);
#endif #endif
@ -3389,7 +3453,7 @@ static int do_generate_common(mz_jit_state *jitter, void *_data)
CHECK_LIMIT(); CHECK_LIMIT();
/* Syntax object is NULL, so we need to create it. */ /* Syntax object is NULL, so we need to create it. */
jit_ldxr_p(JIT_R0, JIT_V1, JIT_R2); /* put element at p in R0 */ jit_ldxr_p(JIT_R0, JIT_V1, JIT_R2); /* put element at p in R0 */
#ifndef MZ_PRECISE_GC #ifndef JIT_PRECISE_GC
/* Save global array: */ /* Save global array: */
mz_set_local_p(JIT_V1, JIT_LOCAL3); mz_set_local_p(JIT_V1, JIT_LOCAL3);
#endif #endif
@ -3413,9 +3477,9 @@ static int do_generate_common(mz_jit_state *jitter, void *_data)
CHECK_LIMIT(); CHECK_LIMIT();
jit_retval(JIT_R0); jit_retval(JIT_R0);
/* Restore global array into JIT_R1, and put computed element at i+p+1: */ /* Restore global array into JIT_R1, and put computed element at i+p+1: */
#ifdef MZ_PRECISE_GC #ifdef JIT_PRECISE_GC
mz_get_local_p(JIT_R1, JIT_LOCAL3); mz_get_local_p(JIT_R1, JIT_LOCAL3);
jit_ldxr_p(JIT_R1, JIT_RUNSTACK, JIT_R0); jit_ldxr_p(JIT_R1, JIT_RUNSTACK, JIT_R1);
#else #else
mz_get_local_p(JIT_R1, JIT_LOCAL3); mz_get_local_p(JIT_R1, JIT_LOCAL3);
#endif #endif
@ -3805,7 +3869,7 @@ static int do_generate_closure(mz_jit_state *jitter, void *_data)
__END_SHORT_JUMPS__(cnt < 100); __END_SHORT_JUMPS__(cnt < 100);
} }
#ifdef MZ_PRECISE_GC #ifdef JIT_PRECISE_GC
/* Keeping the native-closure pointer on the runstack /* Keeping the native-closure pointer on the runstack
ensures that the code won't be GCed while we're running ensures that the code won't be GCed while we're running
it. */ it. */
@ -3841,6 +3905,8 @@ static int do_generate_closure(mz_jit_state *jitter, void *_data)
} else } else
mz_runstack_pushed(jitter, 1); mz_runstack_pushed(jitter, 1);
} }
} else {
mz_runstack_pushed(jitter, cnt);
} }
LOG_IT(("PROC: %s\n", (data->name ? scheme_format_utf8("~s", 2, 1, &data->name, NULL) : "???"))); LOG_IT(("PROC: %s\n", (data->name ? scheme_format_utf8("~s", 2, 1, &data->name, NULL) : "???")));
@ -3884,7 +3950,7 @@ static void on_demand_generate_lambda(Scheme_Native_Closure_Data *ndata)
gdata.data = data; gdata.data = data;
generate_one(NULL, do_generate_closure, &gdata, 1, data->name); generate_one(NULL, do_generate_closure, &gdata, 1, data->name, ndata);
if (gdata.max_depth > data->max_let_depth) { if (gdata.max_depth > data->max_let_depth) {
scheme_console_printf("Bad max depth!\n"); scheme_console_printf("Bad max depth!\n");
@ -3956,16 +4022,22 @@ Scheme_Native_Closure_Data *scheme_generate_lambda(Scheme_Closure_Data *data, in
if (!jump_to_native_code) { if (!jump_to_native_code) {
/* Create shared code used for stack-overflow handling, etc.: */ /* Create shared code used for stack-overflow handling, etc.: */
generate_one(NULL, do_generate_common, NULL, 0, NULL); generate_one(NULL, do_generate_common, NULL, 0, NULL, NULL);
} }
if (!case_lam) { if (!case_lam) {
ndata = MALLOC_ONE_RT(Scheme_Native_Closure_Data); ndata = MALLOC_ONE_RT(Scheme_Native_Closure_Data);
#ifdef MZTAG_REQUIRED
ndata->type = scheme_rt_native_code;
#endif
} else { } else {
Scheme_Native_Closure_Data_Plus_Case *ndatap; Scheme_Native_Closure_Data_Plus_Case *ndatap;
ndatap = MALLOC_ONE_RT(Scheme_Native_Closure_Data_Plus_Case); ndatap = MALLOC_ONE_RT(Scheme_Native_Closure_Data_Plus_Case);
ndatap->case_lam = case_lam; ndatap->case_lam = case_lam;
ndata = (Scheme_Native_Closure_Data *)ndatap; ndata = (Scheme_Native_Closure_Data *)ndatap;
#ifdef MZTAG_REQUIRED
ndata->type = scheme_rt_native_code_plus_case;
#endif
} }
ndata->code = on_demand_jit_code; ndata->code = on_demand_jit_code;
ndata->u.tail_code = on_demand_jit_arity_code; ndata->u.tail_code = on_demand_jit_arity_code;
@ -4091,7 +4163,7 @@ static void *generate_lambda_simple_arity_check(int num_params, int has_rest, in
data.has_rest = has_rest; data.has_rest = has_rest;
data.is_method = is_method; data.is_method = is_method;
return generate_one(NULL, do_generate_lambda_simple_arity_check, &data, !permanent, NULL); return generate_one(NULL, do_generate_lambda_simple_arity_check, &data, !permanent, NULL, NULL);
} }
static int generate_case_lambda_dispatch(mz_jit_state *jitter, Scheme_Case_Lambda *c, Scheme_Native_Closure_Data *ndata, static int generate_case_lambda_dispatch(mz_jit_state *jitter, Scheme_Case_Lambda *c, Scheme_Native_Closure_Data *ndata,
@ -4204,7 +4276,7 @@ static void generate_case_lambda(Scheme_Case_Lambda *c, Scheme_Native_Closure_Da
gdata.ndata = ndata; gdata.ndata = ndata;
gdata.is_method = is_method; gdata.is_method = is_method;
generate_one(NULL, do_generate_case_lambda_dispatch, &gdata, 1, NULL); generate_one(NULL, do_generate_case_lambda_dispatch, &gdata, 1, NULL, ndata);
/* Generate arity table used by scheme_native_arity_check /* Generate arity table used by scheme_native_arity_check
and scheme_get_native_arity: */ and scheme_get_native_arity: */
@ -4495,6 +4567,10 @@ Scheme_Object *scheme_native_stack_trace(void)
return first; return first;
} }
#ifdef MZ_XFORM
START_XFORM_SKIP;
#endif
void scheme_flush_stack_cache() void scheme_flush_stack_cache()
{ {
void **p; void **p;
@ -4511,7 +4587,7 @@ void scheme_jit_longjmp(mz_jit_jmp_buf b, int v)
unsigned long limit; unsigned long limit;
void **p; void **p;
limit = (unsigned long)b->stack_frame; limit = b->stack_frame;
while (stack_cache_stack_pos while (stack_cache_stack_pos
&& STK_COMP((unsigned long)stack_cache_stack[stack_cache_stack_pos].stack_frame, && STK_COMP((unsigned long)stack_cache_stack[stack_cache_stack_pos].stack_frame,
@ -4528,12 +4604,55 @@ void scheme_jit_setjmp_prepare(mz_jit_jmp_buf b)
{ {
void *p; void *p;
p = &p; p = &p;
b->stack_frame = p; b->stack_frame = (unsigned long)p;
} }
#ifdef MZ_XFORM
END_XFORM_SKIP;
#endif
void scheme_clean_native_symtab(void) void scheme_clean_native_symtab(void)
{ {
#ifndef MZ_PRECISE_GC
clear_symbols_for_collected(); clear_symbols_for_collected();
#endif
} }
#ifdef MZ_PRECISE_GC
static void release_native_code(void *fnlized, void *p)
{
Scheme_Object *len;
len = SCHEME_BOX_VAL(fnlized);
/* Remove name mapping: */
add_symbol((unsigned long)p, (unsigned long)p + SCHEME_INT_VAL(len), NULL, 0);
/* Free memory: */
free(p);
}
#endif
/**********************************************************************/
/* Precise GC */
/**********************************************************************/
#ifdef MZ_PRECISE_GC
START_XFORM_SKIP;
#define MARKS_FOR_JIT_C
#include "mzmark.c"
static void register_traversers(void)
{
GC_REG_TRAV(scheme_native_closure_type, native_closure);
GC_REG_TRAV(scheme_rt_jitter_data, mark_jit_state);
GC_REG_TRAV(scheme_rt_native_code, native_unclosed_proc);
GC_REG_TRAV(scheme_rt_native_code_plus_case, native_unclosed_proc_plus_case);
}
END_XFORM_SKIP;
#endif /* MZ_PRECISE_GC */
#endif /* MZ_USE_JIT */ #endif /* MZ_USE_JIT */

View File

@ -38,13 +38,13 @@
(let ([prefix (read-lines re:mark)] (let ([prefix (read-lines re:mark)]
[mark (read-lines re:size)] [mark (read-lines re:size)]
[size (read-lines re:close)]) [size (read-lines re:close)])
(printf "int ~a_SIZE(void *p) {~n" name) (printf "static int ~a_SIZE(void *p) {~n" name)
(print-lines prefix) (print-lines prefix)
(printf " return~n") (printf " return~n")
(print-lines size) (print-lines size)
(printf "}~n~n") (printf "}~n~n")
(printf "int ~a_MARK(void *p) {~n" name) (printf "static int ~a_MARK(void *p) {~n" name)
(print-lines prefix) (print-lines prefix)
(print-lines (map (lambda (s) (print-lines (map (lambda (s)
(regexp-replace* (regexp-replace*
@ -59,7 +59,7 @@
(print-lines size) (print-lines size)
(printf "}~n~n") (printf "}~n~n")
(printf "int ~a_FIXUP(void *p) {~n" name) (printf "static int ~a_FIXUP(void *p) {~n" name)
(print-lines prefix) (print-lines prefix)
(print-lines (map (lambda (s) (print-lines (map (lambda (s)
(regexp-replace* (regexp-replace*

File diff suppressed because it is too large Load Diff

View File

@ -341,6 +341,9 @@ cont_proc {
gcMARK(c->orig_mark_segments); gcMARK(c->orig_mark_segments);
gcMARK(c->init_config); gcMARK(c->init_config);
gcMARK(c->init_break_cell); gcMARK(c->init_break_cell);
#ifdef MZ_USE_JIT
gcMARK(c->native_trace);
#endif
MARK_jmpup(&c->buf); MARK_jmpup(&c->buf);
MARK_cjs(&c->cjs); MARK_cjs(&c->cjs);
@ -380,6 +383,10 @@ escaping_cont_proc {
Scheme_Escaping_Cont *c = (Scheme_Escaping_Cont *)p; Scheme_Escaping_Cont *c = (Scheme_Escaping_Cont *)p;
gcMARK(c->mark_key); gcMARK(c->mark_key);
gcMARK(c->marks_prefix);
#ifdef MZ_USE_JIT
gcMARK(c->native_trace);
#endif
MARK_cjs(&c->cjs); MARK_cjs(&c->cjs);
MARK_stack_state(&c->envss); MARK_stack_state(&c->envss);
@ -561,6 +568,8 @@ thread_val {
MARK_cjs(&pr->cjs); MARK_cjs(&pr->cjs);
gcMARK(pr->current_escape_cont_key);
gcMARK(pr->cell_values); gcMARK(pr->cell_values);
gcMARK(pr->init_config); gcMARK(pr->init_config);
gcMARK(pr->init_break_cell); gcMARK(pr->init_break_cell);
@ -1765,4 +1774,68 @@ END stxobj;
/**********************************************************************/ /**********************************************************************/
START jit;
native_closure {
Scheme_Native_Closure *c = (Scheme_Native_Closure *)p;
int closure_size = ((Scheme_Native_Closure_Data *)GC_resolve(c->code))->closure_size;
if (closure_size < 0) {
closure_size = -(closure_size + 1);
}
mark:
{
int i = closure_size;
while (i--)
gcMARK(c->vals[i]);
}
gcMARK(c->code);
size:
gcBYTES_TO_WORDS((sizeof(Scheme_Native_Closure)
+ (closure_size - 1) * sizeof(Scheme_Object *)));
}
mark_jit_state {
mark:
mz_jit_state *j = (mz_jit_state *)p;
gcMARK(j->mappings);
size:
gcBYTES_TO_WORDS(sizeof(mz_jit_state));
}
native_unclosed_proc {
mark:
Scheme_Native_Closure_Data *d = (Scheme_Native_Closure_Data *)p;
int i;
gcMARK(d->u2.name);
for (i = d->retain_count; i--; ) {
gcMARK(d->retained[i]);
}
if (d->closure_size < 0) {
gcMARK(d->u.arities);
}
size:
gcBYTES_TO_WORDS(sizeof(Scheme_Native_Closure_Data));
}
native_unclosed_proc_plus_case {
mark:
Scheme_Native_Closure_Data_Plus_Case *d = (Scheme_Native_Closure_Data_Plus_Case *)p;
native_unclosed_proc_MARK(p);
gcMARK(d->case_lam);
size:
gcBYTES_TO_WORDS(sizeof(Scheme_Native_Closure_Data_Plus_Case));
}
END jit;
/**********************************************************************/
#define GC_REG_TRAV(type, base) GC_register_traversers(type, base ## _SIZE, base ## _MARK, base ## _FIXUP, base ## _IS_CONST_SIZE, base ## _IS_ATOMIC) #define GC_REG_TRAV(type, base) GC_register_traversers(type, base ## _SIZE, base ## _MARK, base ## _FIXUP, base ## _IS_CONST_SIZE, base ## _IS_ATOMIC)

View File

@ -13,7 +13,7 @@
#define USE_COMPILED_STARTUP 1 #define USE_COMPILED_STARTUP 1
#define EXPECTED_PRIM_COUNT 853 #define EXPECTED_PRIM_COUNT 855
#ifdef MZSCHEME_SOMETHING_OMITTED #ifdef MZSCHEME_SOMETHING_OMITTED
# undef USE_COMPILED_STARTUP # undef USE_COMPILED_STARTUP

View File

@ -59,7 +59,7 @@
#if PRIM_CHECK_MULTI #if PRIM_CHECK_MULTI
return _scheme_apply(rator, argc, argv); return _scheme_apply(rator, argc, argv);
#else #else
# ifdef PRIM_CHECK_VALUE # if PRIM_CHECK_VALUE
return _scheme_apply_multi(rator, argc, argv); return _scheme_apply_multi(rator, argc, argv);
# else # else
return _scheme_tail_apply(rator, argc, argv); return _scheme_tail_apply(rator, argc, argv);

View File

@ -881,6 +881,7 @@ typedef struct Scheme_Stack_State {
Scheme_Saved_Stack *runstack_saved; Scheme_Saved_Stack *runstack_saved;
MZ_MARK_POS_TYPE cont_mark_pos; MZ_MARK_POS_TYPE cont_mark_pos;
MZ_MARK_STACK_TYPE cont_mark_stack; MZ_MARK_STACK_TYPE cont_mark_stack;
Scheme_Object *current_escape_cont_key;
} Scheme_Stack_State; } Scheme_Stack_State;
typedef struct Scheme_Dynamic_Wind { typedef struct Scheme_Dynamic_Wind {
@ -914,6 +915,9 @@ typedef struct Scheme_Cont {
void *o_start; void *o_start;
Scheme_Config *init_config; Scheme_Config *init_config;
Scheme_Object *init_break_cell; Scheme_Object *init_break_cell;
#ifdef MZ_USE_JIT
Scheme_Object *native_trace;
#endif
struct Scheme_Overflow *save_overflow; struct Scheme_Overflow *save_overflow;
mz_jmp_buf *savebuf; /* save old error buffer here */ mz_jmp_buf *savebuf; /* save old error buffer here */
} Scheme_Cont; } Scheme_Cont;
@ -923,6 +927,10 @@ typedef struct Scheme_Escaping_Cont {
Scheme_Continuation_Jump_State cjs; Scheme_Continuation_Jump_State cjs;
Scheme_Object *mark_key; Scheme_Object *mark_key;
struct Scheme_Stack_State envss; struct Scheme_Stack_State envss;
#ifdef MZ_USE_JIT
Scheme_Object *native_trace;
#endif
Scheme_Object *marks_prefix;
mz_jmp_buf *saveerr; mz_jmp_buf *saveerr;
int suspend_break; int suspend_break;
} Scheme_Escaping_Cont; } Scheme_Escaping_Cont;
@ -934,11 +942,13 @@ int scheme_escape_continuation_ok(Scheme_Object *);
#define scheme_save_env_stack_w_thread(ss, p) \ #define scheme_save_env_stack_w_thread(ss, p) \
(ss.runstack = MZ_RUNSTACK, ss.runstack_start = MZ_RUNSTACK_START, \ (ss.runstack = MZ_RUNSTACK, ss.runstack_start = MZ_RUNSTACK_START, \
ss.cont_mark_stack = MZ_CONT_MARK_STACK, ss.cont_mark_pos = MZ_CONT_MARK_POS, \ ss.cont_mark_stack = MZ_CONT_MARK_STACK, ss.cont_mark_pos = MZ_CONT_MARK_POS, \
ss.runstack_size = p->runstack_size, ss.runstack_saved = p->runstack_saved) ss.runstack_size = p->runstack_size, ss.runstack_saved = p->runstack_saved, \
ss.current_escape_cont_key = p->current_escape_cont_key)
#define scheme_restore_env_stack_w_thread(ss, p) \ #define scheme_restore_env_stack_w_thread(ss, p) \
(MZ_RUNSTACK = ss.runstack, MZ_RUNSTACK_START = ss.runstack_start, \ (MZ_RUNSTACK = ss.runstack, MZ_RUNSTACK_START = ss.runstack_start, \
MZ_CONT_MARK_STACK = ss.cont_mark_stack, MZ_CONT_MARK_POS = ss.cont_mark_pos, \ MZ_CONT_MARK_STACK = ss.cont_mark_stack, MZ_CONT_MARK_POS = ss.cont_mark_pos, \
p->runstack_size = ss.runstack_size, p->runstack_saved = ss.runstack_saved) p->runstack_size = ss.runstack_size, p->runstack_saved = ss.runstack_saved, \
p->current_escape_cont_key = ss.current_escape_cont_key)
#define scheme_save_env_stack(ss) \ #define scheme_save_env_stack(ss) \
scheme_save_env_stack_w_thread(ss, scheme_current_thread) scheme_save_env_stack_w_thread(ss, scheme_current_thread)
#define scheme_restore_env_stack(ss) \ #define scheme_restore_env_stack(ss) \
@ -1566,7 +1576,8 @@ typedef struct Scheme_Native_Closure_Data {
Scheme_Object *name; Scheme_Object *name;
} u2; } u2;
#ifdef MZ_PRECISE_GC #ifdef MZ_PRECISE_GC
void *retain_start; /* up to arity_code */ void **retained; /* inside code */
mzshort retain_count;
#endif #endif
} Scheme_Native_Closure_Data; } Scheme_Native_Closure_Data;

View File

@ -9,6 +9,6 @@
#define MZSCHEME_VERSION_MAJOR 301 #define MZSCHEME_VERSION_MAJOR 301
#define MZSCHEME_VERSION_MINOR 5 #define MZSCHEME_VERSION_MINOR 6
#define MZSCHEME_VERSION "301.5" _MZ_SPECIAL_TAG #define MZSCHEME_VERSION "301.6" _MZ_SPECIAL_TAG

View File

@ -81,6 +81,8 @@ static Scheme_Object *struct_type_p(int argc, Scheme_Object *argv[]);
static Scheme_Object *struct_info(int argc, Scheme_Object *argv[]); static Scheme_Object *struct_info(int argc, Scheme_Object *argv[]);
static Scheme_Object *struct_type_info(int argc, Scheme_Object *argv[]); static Scheme_Object *struct_type_info(int argc, Scheme_Object *argv[]);
static Scheme_Object *struct_type_pred(int argc, Scheme_Object *argv[]);
static Scheme_Object *struct_type_constr(int argc, Scheme_Object *argv[]);
static Scheme_Object *struct_to_vector(int argc, Scheme_Object *argv[]); static Scheme_Object *struct_to_vector(int argc, Scheme_Object *argv[]);
static Scheme_Object *struct_setter_p(int argc, Scheme_Object *argv[]); static Scheme_Object *struct_setter_p(int argc, Scheme_Object *argv[]);
@ -367,6 +369,16 @@ scheme_init_struct (Scheme_Env *env)
1, 1, 1, 1,
mzNUM_ST_INFO, mzNUM_ST_INFO), mzNUM_ST_INFO, mzNUM_ST_INFO),
env); env);
scheme_add_global_constant("struct-type-make-predicate",
scheme_make_prim_w_arity(struct_type_pred,
"struct-type-make-predicate",
1, 1),
env);
scheme_add_global_constant("struct-type-make-constructor",
scheme_make_prim_w_arity(struct_type_constr,
"struct-type-make-constructor",
1, 1),
env);
scheme_add_global_constant("struct->vector", scheme_add_global_constant("struct->vector",
scheme_make_prim_w_arity(struct_to_vector, scheme_make_prim_w_arity(struct_to_vector,
"struct->vector", "struct->vector",
@ -1160,26 +1172,37 @@ static Scheme_Object *struct_info(int argc, Scheme_Object *argv[])
return scheme_values(2, a); return scheme_values(2, a);
} }
static void get_struct_type_info(int argc, Scheme_Object *argv[], Scheme_Object **a, int always) static Scheme_Object *check_type_and_inspector(const char *who, int always, int argc, Scheme_Object *argv[])
{ {
Scheme_Struct_Type *stype, *parent; Scheme_Object *insp;
Scheme_Object *insp, *ims; Scheme_Struct_Type *stype;
int p;
if (!SAME_TYPE(SCHEME_TYPE(argv[0]), scheme_struct_type_type)) if (!SAME_TYPE(SCHEME_TYPE(argv[0]), scheme_struct_type_type))
scheme_wrong_type("struct-type-info", "struct-type", 0, argc, argv); scheme_wrong_type(who, "struct-type", 0, argc, argv);
stype = (Scheme_Struct_Type *)argv[0]; stype = (Scheme_Struct_Type *)argv[0];
insp = scheme_get_param(scheme_current_config(), MZCONFIG_INSPECTOR); insp = scheme_get_param(scheme_current_config(), MZCONFIG_INSPECTOR);
if (!always && !scheme_is_subinspector(stype->inspector, insp)) { if (!always && !scheme_is_subinspector(stype->inspector, insp)) {
scheme_arg_mismatch("struct-type-info", scheme_arg_mismatch(who,
"current inspector cannot extract info for struct-type: ", "current inspector cannot extract info for struct-type: ",
argv[0]); argv[0]);
return; return NULL;
} }
return insp;
}
static void get_struct_type_info(int argc, Scheme_Object *argv[], Scheme_Object **a, int always)
{
Scheme_Struct_Type *stype, *parent;
Scheme_Object *insp, *ims;
int p;
insp = check_type_and_inspector("struct-type-info", always, argc, argv);
stype = (Scheme_Struct_Type *)argv[0];
/* Make sure generic accessor and mutator are created: */ /* Make sure generic accessor and mutator are created: */
if (!stype->accessor) { if (!stype->accessor) {
Scheme_Object *p; Scheme_Object *p;
@ -1234,6 +1257,34 @@ static Scheme_Object *struct_type_info(int argc, Scheme_Object *argv[])
return scheme_values(mzNUM_ST_INFO, a); return scheme_values(mzNUM_ST_INFO, a);
} }
static Scheme_Object *struct_type_pred(int argc, Scheme_Object *argv[])
{
Scheme_Struct_Type *stype;
check_type_and_inspector("struct-type-make-predicate", 0, argc, argv);
stype = (Scheme_Struct_Type *)argv[0];
return make_struct_proc(stype,
scheme_symbol_val(PRED_NAME(scheme_symbol_val(stype->name),
SCHEME_SYM_LEN(stype->name))),
SCHEME_PRED,
stype->num_slots);
}
static Scheme_Object *struct_type_constr(int argc, Scheme_Object *argv[])
{
Scheme_Struct_Type *stype;
check_type_and_inspector("struct-type-make-constructor", 0, argc, argv);
stype = (Scheme_Struct_Type *)argv[0];
return make_struct_proc(stype,
scheme_symbol_val(CSTR_NAME(scheme_symbol_val(stype->name),
SCHEME_SYM_LEN(stype->name))),
SCHEME_CONSTR,
stype->num_slots);
}
Scheme_Object *scheme_struct_to_vector(Scheme_Object *_s, Scheme_Object *unknown_val, Scheme_Object *insp) Scheme_Object *scheme_struct_to_vector(Scheme_Object *_s, Scheme_Object *unknown_val, Scheme_Object *insp)
{ {
Scheme_Structure *s; Scheme_Structure *s;

View File

@ -209,6 +209,9 @@ enum {
scheme_rt_parameterization, /* 188 */ scheme_rt_parameterization, /* 188 */
scheme_rt_print_params, /* 189 */ scheme_rt_print_params, /* 189 */
scheme_rt_read_params, /* 190 */ scheme_rt_read_params, /* 190 */
scheme_rt_native_code, /* 191 */
scheme_rt_native_code_plus_case, /* 192 */
scheme_rt_jitter_data, /* 193 */
#endif #endif
_scheme_last_type_ _scheme_last_type_

View File

@ -2292,6 +2292,8 @@ static void thread_is_dead(Scheme_Thread *r)
r->error_buf = NULL; r->error_buf = NULL;
r->overflow_buf = NULL; r->overflow_buf = NULL;
r->spare_runstack = NULL;
} }
static void remove_thread(Scheme_Thread *r) static void remove_thread(Scheme_Thread *r)
@ -3321,6 +3323,7 @@ static void raise_break(Scheme_Thread *p)
Scheme_Ready_Fun block_check; Scheme_Ready_Fun block_check;
Scheme_Needs_Wakeup_Fun block_needs_wakeup; Scheme_Needs_Wakeup_Fun block_needs_wakeup;
Scheme_Object *a[1]; Scheme_Object *a[1];
Scheme_Cont_Frame_Data cframe;
p->external_break = 0; p->external_break = 0;
@ -3337,8 +3340,15 @@ static void raise_break(Scheme_Thread *p)
a[0] = scheme_make_prim((Scheme_Prim *)raise_user_break); a[0] = scheme_make_prim((Scheme_Prim *)raise_user_break);
/* Continuation frame ensures that this doesn't
look like it's in tail position with respect to
an existing escape continuation */
scheme_push_continuation_frame(&cframe);
scheme_call_ec(1, a); scheme_call_ec(1, a);
scheme_pop_continuation_frame(&cframe);
/* Continue from break... */ /* Continue from break... */
p->block_descriptor = block_descriptor; p->block_descriptor = block_descriptor;
p->blocker = blocker; p->blocker = blocker;

View File

@ -356,6 +356,7 @@ static void MARK_stack_state(Scheme_Stack_State *ss)
gcMARK(ss->runstack_start); gcMARK(ss->runstack_start);
ss->runstack = ss->runstack_start + (ss->runstack - old); ss->runstack = ss->runstack_start + (ss->runstack - old);
gcMARK(ss->runstack_saved); gcMARK(ss->runstack_saved);
gcMARK(ss->current_escape_cont_key);
} }
static void FIXUP_stack_state(Scheme_Stack_State *ss) static void FIXUP_stack_state(Scheme_Stack_State *ss)
@ -366,6 +367,7 @@ static void FIXUP_stack_state(Scheme_Stack_State *ss)
gcFIXUP(ss->runstack_saved); gcFIXUP(ss->runstack_saved);
gcFIXUP_TYPED_NOW(Scheme_Object **, ss->runstack_start); gcFIXUP_TYPED_NOW(Scheme_Object **, ss->runstack_start);
ss->runstack = ss->runstack_start + (ss->runstack - old); ss->runstack = ss->runstack_start + (ss->runstack - old);
gcFIXUP(ss->current_escape_cont_key);
} }
static void MARK_jmpup(Scheme_Jumpup_Buf *buf) static void MARK_jmpup(Scheme_Jumpup_Buf *buf)

View File

@ -9,7 +9,7 @@
(system s)) (system s))
(define accounting-gc? #t) (define accounting-gc? #t)
(define opt-flags "/O2") (define opt-flags "/O2 /Oy-")
(define re:only #f) (define re:only #f)
(unless (directory-exists? "xsrc") (unless (directory-exists? "xsrc")
@ -30,6 +30,7 @@
"fun" "fun"
"hash" "hash"
"image" "image"
"jit"
"list" "list"
"module" "module"
"network" "network"