add phantom byte strings
A phantom byte string is a small object that the memory manager treats as an arbitrary-sized object, where the size is specified when the phantom byte string is created or or when size is changed via `set-phantom-bytes!'.
This commit is contained in:
parent
67af968a73
commit
aa08a68424
|
@ -252,3 +252,50 @@ information in a dump. The information that is available depends on
|
||||||
your Racket build; check the end of a dump from a particular build to
|
your Racket build; check the end of a dump from a particular build to
|
||||||
see if it offers additional information; otherwise, all @racket[v]s are
|
see if it offers additional information; otherwise, all @racket[v]s are
|
||||||
ignored.}
|
ignored.}
|
||||||
|
|
||||||
|
@;------------------------------------------------------------------------
|
||||||
|
@section[#:tag "phantom-bytes"]{Phantom Byte Strings}
|
||||||
|
|
||||||
|
A @deftech{phantom byte string} is a small Racket value that is
|
||||||
|
treated by the Racket memory manager as having an arbitrary size,
|
||||||
|
which is specified when the @tech{phantom byte string} is created or
|
||||||
|
when it is changed via @racket[set-phantom-bytes!].
|
||||||
|
|
||||||
|
A @tech{phantom byte string} acts as a hint to Racket's memory
|
||||||
|
manager that memory is allocated within the process but through a
|
||||||
|
separate allocator, such as through a foreign library that is accessed
|
||||||
|
via @racketmodname[ffi/unsafe]. This hint is used to trigger
|
||||||
|
@tech{garbage collections} or to compute the result of
|
||||||
|
@racket[current-memory-use]. Currently, the hint is used only in
|
||||||
|
Racket 3m (the main variant of Racket).
|
||||||
|
|
||||||
|
@defproc[(phantom-bytes? [v any/c]) boolean?]{
|
||||||
|
|
||||||
|
Returns @racket[#t] if @racket[v] is a @tech{phantom byte string},
|
||||||
|
@racket[#f] otherwise.}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(make-phantom-bytes [k exact-nonnegative-integer?])
|
||||||
|
phantom-bytes?]{
|
||||||
|
|
||||||
|
Creates a @tech{phantom byte string} that is treated by the Racket
|
||||||
|
memory manager as being @racket[k] bytes in size. For a large enough
|
||||||
|
@racket[k], the @exnraise[exn:fail:out-of-memory]---either because the
|
||||||
|
size is implausibly large, or because a memory limit has been
|
||||||
|
installed with @racket[custodian-limit-memory].}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(set-phantom-bytes! [phantom-bstr phantom-bytes?]
|
||||||
|
[k exact-nonnegative-integer?])
|
||||||
|
phantom-bytes?]{
|
||||||
|
|
||||||
|
Adjusts the size of a @tech{phantom byte string} as it is treated by
|
||||||
|
the Racket memory manager.
|
||||||
|
|
||||||
|
For example, if the memory that @racket[phantom-bstr] represents is
|
||||||
|
released through a foreign library, then @racket[(set-phantom-bytes!
|
||||||
|
phantom-bstr 0)] can reflect the change in memory use.
|
||||||
|
|
||||||
|
When @racket[k] is larger than the current size of
|
||||||
|
@racket[phantom-bstr], then this function can raise
|
||||||
|
@racket[exn:fail:out-of-memory], like @racket[make-phantom-bytes].}
|
||||||
|
|
|
@ -185,6 +185,39 @@
|
||||||
(num-or (ephemeron-value (cdr p) 0) 1))))
|
(num-or (ephemeron-value (cdr p) 0) 1))))
|
||||||
(test #t < n 50))
|
(test #t < n 50))
|
||||||
|
|
||||||
|
;; ----------------------------------------
|
||||||
|
;; Phantom bytes:
|
||||||
|
|
||||||
|
(when (eq? '3m (system-type 'gc))
|
||||||
|
(define s (make-semaphore))
|
||||||
|
(define c (make-custodian))
|
||||||
|
(define t (parameterize ([current-custodian c])
|
||||||
|
(thread (lambda ()
|
||||||
|
(semaphore-wait s)
|
||||||
|
(define b (make-phantom-bytes (expt 2 29)))
|
||||||
|
(test #t phantom-bytes? b)
|
||||||
|
(test #f phantom-bytes? 0)
|
||||||
|
(semaphore-wait s)
|
||||||
|
(set-phantom-bytes! b 0)
|
||||||
|
(semaphore-wait s)))))
|
||||||
|
(sync (system-idle-evt))
|
||||||
|
(collect-garbage)
|
||||||
|
(define m (current-memory-use))
|
||||||
|
(define mc (current-memory-use c))
|
||||||
|
(semaphore-post s)
|
||||||
|
(sync (system-idle-evt))
|
||||||
|
(test #t > (current-memory-use) (+ m (expt 2 28)))
|
||||||
|
(collect-garbage)
|
||||||
|
(test #t > (current-memory-use) (+ m (expt 2 28)))
|
||||||
|
(test #t > (current-memory-use c) (+ mc (expt 2 28)))
|
||||||
|
(semaphore-post s)
|
||||||
|
(sync (system-idle-evt))
|
||||||
|
(test #t < (current-memory-use) (+ m (expt 2 28)))
|
||||||
|
(collect-garbage)
|
||||||
|
(test #t < (current-memory-use) (+ m (expt 2 28)))
|
||||||
|
(test #t < (current-memory-use c) (+ mc (expt 2 28)))
|
||||||
|
(semaphore-post s))
|
||||||
|
|
||||||
;; ----------------------------------------
|
;; ----------------------------------------
|
||||||
|
|
||||||
(report-errs)
|
(report-errs)
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
Version 5.3.1.10
|
||||||
|
Added phantom byte strings
|
||||||
|
|
||||||
Version 5.3.1.9
|
Version 5.3.1.9
|
||||||
Changed case to use equal? instead of eqv?
|
Changed case to use equal? instead of eqv?
|
||||||
r5rs, r6rs: fixed case and cond to disallow internal definitions
|
r5rs, r6rs: fixed case and cond to disallow internal definitions
|
||||||
|
|
|
@ -91,7 +91,8 @@ GC2_EXTERN void GC_add_roots(void *start, void *end);
|
||||||
`start' (inclusive) and `end' (exclusive) contains pointers. */
|
`start' (inclusive) and `end' (exclusive) contains pointers. */
|
||||||
|
|
||||||
GC2_EXTERN void GC_init_type_tags(int count, int pair, int mutable_pair, int weakbox,
|
GC2_EXTERN void GC_init_type_tags(int count, int pair, int mutable_pair, int weakbox,
|
||||||
int ephemeron, int weakarray, int custbox);
|
int ephemeron, int weakarray, int custbox,
|
||||||
|
int phantom);
|
||||||
/*
|
/*
|
||||||
Called by Racket to indicate the number of different type tags it
|
Called by Racket to indicate the number of different type tags it
|
||||||
uses, starting from 0. `count' is always less than 256. The weakbox
|
uses, starting from 0. `count' is always less than 256. The weakbox
|
||||||
|
@ -276,6 +277,11 @@ GC2_EXTERN int GC_is_on_allocated_page(void *p);
|
||||||
the GC allocates objects (although p may or may not
|
the GC allocates objects (although p may or may not
|
||||||
be a valid pointer to the start of an alloctaed object). */
|
be a valid pointer to the start of an alloctaed object). */
|
||||||
|
|
||||||
|
GC2_EXTERN int GC_allocate_phantom_bytes(intptr_t);
|
||||||
|
/*
|
||||||
|
Returns 0 if allocation should fail due to a memory limit,
|
||||||
|
1 otherwise. */
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/* Memory tracing */
|
/* Memory tracing */
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
|
@ -447,6 +447,9 @@ static void BTC_do_accounting(NewGC *gc)
|
||||||
last = cur;
|
last = cur;
|
||||||
while(cur) {
|
while(cur) {
|
||||||
int owner = custodian_to_owner_set(gc, cur);
|
int owner = custodian_to_owner_set(gc, cur);
|
||||||
|
uintptr_t save_count = gc->phantom_count;
|
||||||
|
|
||||||
|
gc->phantom_count = 0;
|
||||||
|
|
||||||
gc->current_mark_owner = owner;
|
gc->current_mark_owner = owner;
|
||||||
GCDEBUG((DEBUGOUTF,"MARKING THREADS OF OWNER %i (CUST %p)\n", owner, cur));
|
GCDEBUG((DEBUGOUTF,"MARKING THREADS OF OWNER %i (CUST %p)\n", owner, cur));
|
||||||
|
@ -458,6 +461,10 @@ static void BTC_do_accounting(NewGC *gc)
|
||||||
|
|
||||||
last = cur;
|
last = cur;
|
||||||
box = cur->global_next; cur = box ? SCHEME_PTR1_VAL(box) : NULL;
|
box = cur->global_next; cur = box ? SCHEME_PTR1_VAL(box) : NULL;
|
||||||
|
|
||||||
|
owner_table[owner]->memory_use = add_no_overflow(owner_table[owner]->memory_use,
|
||||||
|
gcBYTES_TO_WORDS(gc->phantom_count));
|
||||||
|
gc->phantom_count = save_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* walk backward folding totals int parent */
|
/* walk backward folding totals int parent */
|
||||||
|
@ -470,7 +477,8 @@ static void BTC_do_accounting(NewGC *gc)
|
||||||
int powner = custodian_to_owner_set(gc, parent);
|
int powner = custodian_to_owner_set(gc, parent);
|
||||||
|
|
||||||
owner_table = gc->owner_table;
|
owner_table = gc->owner_table;
|
||||||
owner_table[powner]->memory_use += owner_table[owner]->memory_use;
|
owner_table[powner]->memory_use = add_no_overflow(owner_table[powner]->memory_use,
|
||||||
|
owner_table[owner]->memory_use);
|
||||||
owner_table[powner]->master_memory_use += owner_table[owner]->master_memory_use;
|
owner_table[powner]->master_memory_use += owner_table[owner]->master_memory_use;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1492,6 +1492,44 @@ intptr_t GC_alloc_alignment()
|
||||||
|
|
||||||
intptr_t GC_malloc_stays_put_threshold() { return MAX_OBJECT_SIZE; }
|
intptr_t GC_malloc_stays_put_threshold() { return MAX_OBJECT_SIZE; }
|
||||||
|
|
||||||
|
uintptr_t add_no_overflow(uintptr_t a, uintptr_t b)
|
||||||
|
{
|
||||||
|
uintptr_t c = a + b;
|
||||||
|
|
||||||
|
if (c < a)
|
||||||
|
c = (uintptr_t)-1;
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GC_allocate_phantom_bytes(intptr_t request_size_bytes)
|
||||||
|
{
|
||||||
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
|
NewGC *gc = GC_get_GC();
|
||||||
|
|
||||||
|
if (premaster_or_place_gc(gc)) {
|
||||||
|
if (BTC_single_allocation_limit(gc, request_size_bytes))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((request_size_bytes > 0)
|
||||||
|
&& ((gc->phantom_count + request_size_bytes) < gc->phantom_count))
|
||||||
|
/* overflow */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
gc->phantom_count += request_size_bytes;
|
||||||
|
/* adjust `gc->memory_in_use', but protect against {over,under}flow: */
|
||||||
|
if (request_size_bytes < 0) {
|
||||||
|
request_size_bytes = -request_size_bytes;
|
||||||
|
if (gc->memory_in_use > request_size_bytes)
|
||||||
|
gc->memory_in_use -= request_size_bytes;
|
||||||
|
} else
|
||||||
|
gc->memory_in_use = add_no_overflow(gc->memory_in_use, request_size_bytes);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void GC_create_message_allocator() {
|
void GC_create_message_allocator() {
|
||||||
NewGC *gc = GC_get_GC();
|
NewGC *gc = GC_get_GC();
|
||||||
Allocator *a;
|
Allocator *a;
|
||||||
|
@ -1769,8 +1807,10 @@ inline static void master_set_max_size(NewGC *gc)
|
||||||
inline static void reset_nursery(NewGC *gc)
|
inline static void reset_nursery(NewGC *gc)
|
||||||
{
|
{
|
||||||
uintptr_t new_gen0_size;
|
uintptr_t new_gen0_size;
|
||||||
|
|
||||||
new_gen0_size = NUM((GEN0_SIZE_FACTOR * (float)gc->memory_in_use) + GEN0_SIZE_ADDITION);
|
new_gen0_size = NUM((GEN0_SIZE_FACTOR * (float)gc->memory_in_use) + GEN0_SIZE_ADDITION);
|
||||||
if(new_gen0_size > GEN0_MAX_SIZE)
|
if ((new_gen0_size > GEN0_MAX_SIZE)
|
||||||
|
|| (gc->memory_in_use > GEN0_MAX_SIZE)) /* => overflow */
|
||||||
new_gen0_size = GEN0_MAX_SIZE;
|
new_gen0_size = GEN0_MAX_SIZE;
|
||||||
|
|
||||||
resize_gen0(gc, new_gen0_size);
|
resize_gen0(gc, new_gen0_size);
|
||||||
|
@ -2206,6 +2246,34 @@ inline static void check_finalizers(NewGC *gc, int level)
|
||||||
#undef is_marked
|
#undef is_marked
|
||||||
#undef weak_box_resolve
|
#undef weak_box_resolve
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* phantom bytes and accounting */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
short tag;
|
||||||
|
intptr_t count;
|
||||||
|
} Phantom_Bytes;
|
||||||
|
|
||||||
|
static int size_phantom(void *p, struct NewGC *gc)
|
||||||
|
{
|
||||||
|
return gcBYTES_TO_WORDS(sizeof(Phantom_Bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mark_phantom(void *p, struct NewGC *gc)
|
||||||
|
{
|
||||||
|
Phantom_Bytes *pb = (Phantom_Bytes *)p;
|
||||||
|
|
||||||
|
gc->phantom_count = add_no_overflow(gc->phantom_count, pb->count);
|
||||||
|
|
||||||
|
return gcBYTES_TO_WORDS(sizeof(Phantom_Bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fixup_phantom(void *p, struct NewGC *gc)
|
||||||
|
{
|
||||||
|
return gcBYTES_TO_WORDS(sizeof(Phantom_Bytes));
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Internal Stack Routines */
|
/* Internal Stack Routines */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -2729,7 +2797,9 @@ static void NewGC_initialize(NewGC *newgc, NewGC *inheritgc, NewGC *parentgc) {
|
||||||
|
|
||||||
/* NOTE This method sets the constructed GC as the new Thread Specific GC. */
|
/* NOTE This method sets the constructed GC as the new Thread Specific GC. */
|
||||||
static NewGC *init_type_tags_worker(NewGC *inheritgc, NewGC *parentgc,
|
static NewGC *init_type_tags_worker(NewGC *inheritgc, NewGC *parentgc,
|
||||||
int count, int pair, int mutable_pair, int weakbox, int ephemeron, int weakarray, int custbox)
|
int count, int pair, int mutable_pair, int weakbox,
|
||||||
|
int ephemeron, int weakarray,
|
||||||
|
int custbox, int phantom)
|
||||||
{
|
{
|
||||||
NewGC *gc;
|
NewGC *gc;
|
||||||
|
|
||||||
|
@ -2744,6 +2814,7 @@ static NewGC *init_type_tags_worker(NewGC *inheritgc, NewGC *parentgc,
|
||||||
# ifdef NEWGC_BTC_ACCOUNT
|
# ifdef NEWGC_BTC_ACCOUNT
|
||||||
gc->cust_box_tag = custbox;
|
gc->cust_box_tag = custbox;
|
||||||
# endif
|
# endif
|
||||||
|
gc->phantom_tag = phantom;
|
||||||
|
|
||||||
NewGC_initialize(gc, inheritgc, parentgc);
|
NewGC_initialize(gc, inheritgc, parentgc);
|
||||||
|
|
||||||
|
@ -2763,6 +2834,7 @@ static NewGC *init_type_tags_worker(NewGC *inheritgc, NewGC *parentgc,
|
||||||
GC_register_traversers2(gc->weak_box_tag, size_weak_box, mark_weak_box, fixup_weak_box, 0, 0);
|
GC_register_traversers2(gc->weak_box_tag, size_weak_box, mark_weak_box, fixup_weak_box, 0, 0);
|
||||||
GC_register_traversers2(gc->ephemeron_tag, size_ephemeron, mark_ephemeron, fixup_ephemeron, 0, 0);
|
GC_register_traversers2(gc->ephemeron_tag, size_ephemeron, mark_ephemeron, fixup_ephemeron, 0, 0);
|
||||||
GC_register_traversers2(gc->weak_array_tag, size_weak_array, mark_weak_array, fixup_weak_array, 0, 0);
|
GC_register_traversers2(gc->weak_array_tag, size_weak_array, mark_weak_array, fixup_weak_array, 0, 0);
|
||||||
|
GC_register_traversers2(gc->phantom_tag, size_phantom, mark_phantom, fixup_phantom, 0, 0);
|
||||||
}
|
}
|
||||||
initialize_signal_handler(gc);
|
initialize_signal_handler(gc);
|
||||||
GC_add_roots(&gc->park, (char *)&gc->park + sizeof(gc->park) + 1);
|
GC_add_roots(&gc->park, (char *)&gc->park + sizeof(gc->park) + 1);
|
||||||
|
@ -2771,13 +2843,15 @@ static NewGC *init_type_tags_worker(NewGC *inheritgc, NewGC *parentgc,
|
||||||
return gc;
|
return gc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GC_init_type_tags(int count, int pair, int mutable_pair, int weakbox, int ephemeron, int weakarray, int custbox)
|
void GC_init_type_tags(int count, int pair, int mutable_pair, int weakbox, int ephemeron, int weakarray,
|
||||||
|
int custbox, int phantom)
|
||||||
{
|
{
|
||||||
static int initialized = 0;
|
static int initialized = 0;
|
||||||
|
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
init_type_tags_worker(NULL, NULL, count, pair, mutable_pair, weakbox, ephemeron, weakarray, custbox);
|
init_type_tags_worker(NULL, NULL, count, pair, mutable_pair, weakbox, ephemeron, weakarray,
|
||||||
|
custbox, phantom);
|
||||||
} else {
|
} else {
|
||||||
GCPRINT(GCOUTF, "GC_init_type_tags should only be called once!\n");
|
GCPRINT(GCOUTF, "GC_init_type_tags should only be called once!\n");
|
||||||
abort();
|
abort();
|
||||||
|
@ -2791,7 +2865,8 @@ struct NewGC *GC_get_current_instance() {
|
||||||
#ifdef MZ_USE_PLACES
|
#ifdef MZ_USE_PLACES
|
||||||
void GC_construct_child_gc(struct NewGC *parent_gc, intptr_t limit) {
|
void GC_construct_child_gc(struct NewGC *parent_gc, intptr_t limit) {
|
||||||
NewGC *gc = MASTERGC;
|
NewGC *gc = MASTERGC;
|
||||||
NewGC *newgc = init_type_tags_worker(gc, parent_gc, 0, 0, 0, gc->weak_box_tag, gc->ephemeron_tag, gc->weak_array_tag, gc->cust_box_tag);
|
NewGC *newgc = init_type_tags_worker(gc, parent_gc, 0, 0, 0, gc->weak_box_tag, gc->ephemeron_tag,
|
||||||
|
gc->weak_array_tag, gc->cust_box_tag, gc->phantom_tag);
|
||||||
newgc->primoridal_gc = MASTERGC;
|
newgc->primoridal_gc = MASTERGC;
|
||||||
newgc->dont_master_gc_until_child_registers = 1;
|
newgc->dont_master_gc_until_child_registers = 1;
|
||||||
if (limit)
|
if (limit)
|
||||||
|
@ -2972,19 +3047,20 @@ void GC_register_traversers(short tag, Size_Proc size, Mark_Proc mark,
|
||||||
intptr_t GC_get_memory_use(void *o)
|
intptr_t GC_get_memory_use(void *o)
|
||||||
{
|
{
|
||||||
NewGC *gc = GC_get_GC();
|
NewGC *gc = GC_get_GC();
|
||||||
intptr_t amt;
|
uintptr_t amt;
|
||||||
#ifdef NEWGC_BTC_ACCOUNT
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
if(o) {
|
if (o) {
|
||||||
return BTC_get_memory_use(gc, o);
|
return BTC_get_memory_use(gc, o);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
amt = gen0_size_in_use(gc) + gc->memory_in_use;
|
amt = add_no_overflow(gen0_size_in_use(gc), gc->memory_in_use);
|
||||||
#ifdef MZ_USE_PLACES
|
#ifdef MZ_USE_PLACES
|
||||||
mzrt_mutex_lock(gc->child_total_lock);
|
mzrt_mutex_lock(gc->child_total_lock);
|
||||||
amt += gc->child_gc_total;
|
amt = add_no_overflow(amt, gc->child_gc_total);
|
||||||
mzrt_mutex_unlock(gc->child_total_lock);
|
mzrt_mutex_unlock(gc->child_total_lock);
|
||||||
#endif
|
#endif
|
||||||
return amt;
|
|
||||||
|
return (intptr_t)amt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -4255,7 +4331,7 @@ inline static void gen0_free_big_pages(NewGC *gc) {
|
||||||
static void clean_up_heap(NewGC *gc)
|
static void clean_up_heap(NewGC *gc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
size_t memory_in_use = 0;
|
uintptr_t memory_in_use = 0;
|
||||||
PageMap pagemap = gc->page_maps;
|
PageMap pagemap = gc->page_maps;
|
||||||
|
|
||||||
gen0_free_big_pages(gc);
|
gen0_free_big_pages(gc);
|
||||||
|
@ -4346,6 +4422,8 @@ static void clean_up_heap(NewGC *gc)
|
||||||
gc->med_freelist_pages[i] = prev;
|
gc->med_freelist_pages[i] = prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memory_in_use = add_no_overflow(memory_in_use, gc->phantom_count);
|
||||||
|
|
||||||
gc->memory_in_use = memory_in_use;
|
gc->memory_in_use = memory_in_use;
|
||||||
cleanup_vacated_pages(gc);
|
cleanup_vacated_pages(gc);
|
||||||
}
|
}
|
||||||
|
@ -4533,6 +4611,9 @@ static void garbage_collect(NewGC *gc, int force_full, int switching_master, Log
|
||||||
gc->in_unsafe_allocation_mode = 1;
|
gc->in_unsafe_allocation_mode = 1;
|
||||||
gc->unsafe_allocation_abort = out_of_memory_gc;
|
gc->unsafe_allocation_abort = out_of_memory_gc;
|
||||||
|
|
||||||
|
if (gc->gc_full)
|
||||||
|
gc->phantom_count = 0;
|
||||||
|
|
||||||
TIME_INIT();
|
TIME_INIT();
|
||||||
|
|
||||||
/* inform the system (if it wants us to) that we're starting collection */
|
/* inform the system (if it wants us to) that we're starting collection */
|
||||||
|
@ -4811,7 +4892,7 @@ intptr_t GC_propagate_hierarchy_memory_use()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return gc->memory_in_use + gc->child_gc_total;
|
return add_no_overflow(gc->memory_in_use, gc->child_gc_total);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MZ_GC_BACKTRACE
|
#if MZ_GC_BACKTRACE
|
||||||
|
|
|
@ -231,6 +231,9 @@ typedef struct NewGC {
|
||||||
unsigned short weak_box_tag;
|
unsigned short weak_box_tag;
|
||||||
unsigned short ephemeron_tag;
|
unsigned short ephemeron_tag;
|
||||||
unsigned short cust_box_tag;
|
unsigned short cust_box_tag;
|
||||||
|
unsigned short phantom_tag;
|
||||||
|
|
||||||
|
uintptr_t phantom_count;
|
||||||
|
|
||||||
Roots roots;
|
Roots roots;
|
||||||
GC_Weak_Array *weak_arrays;
|
GC_Weak_Array *weak_arrays;
|
||||||
|
@ -246,7 +249,7 @@ typedef struct NewGC {
|
||||||
intptr_t previously_reported_total; /* how much we previously reported to the parent */
|
intptr_t previously_reported_total; /* how much we previously reported to the parent */
|
||||||
mzrt_mutex *child_total_lock; /* lock on `child_gc_total' */
|
mzrt_mutex *child_total_lock; /* lock on `child_gc_total' */
|
||||||
#endif
|
#endif
|
||||||
intptr_t child_gc_total;
|
uintptr_t child_gc_total;
|
||||||
|
|
||||||
uintptr_t place_memory_limit; /* set to propagate a custodian limit from a parent place */
|
uintptr_t place_memory_limit; /* set to propagate a custodian limit from a parent place */
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -113,7 +113,7 @@ void scheme_set_stack_base(void *base, int no_auto_statics) XFORM_SKIP_PROC
|
||||||
GC_init_type_tags(_scheme_last_type_,
|
GC_init_type_tags(_scheme_last_type_,
|
||||||
scheme_pair_type, scheme_mutable_pair_type, scheme_weak_box_type,
|
scheme_pair_type, scheme_mutable_pair_type, scheme_weak_box_type,
|
||||||
scheme_ephemeron_type, scheme_rt_weak_array,
|
scheme_ephemeron_type, scheme_rt_weak_array,
|
||||||
scheme_cust_box_type);
|
scheme_cust_box_type, scheme_phantom_bytes_type);
|
||||||
/* We want to be able to allocate symbols early. */
|
/* We want to be able to allocate symbols early. */
|
||||||
scheme_register_traversers();
|
scheme_register_traversers();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#define USE_COMPILED_STARTUP 1
|
#define USE_COMPILED_STARTUP 1
|
||||||
|
|
||||||
#define EXPECTED_PRIM_COUNT 1073
|
#define EXPECTED_PRIM_COUNT 1076
|
||||||
#define EXPECTED_UNSAFE_COUNT 80
|
#define EXPECTED_UNSAFE_COUNT 80
|
||||||
#define EXPECTED_FLFXNUM_COUNT 69
|
#define EXPECTED_FLFXNUM_COUNT 69
|
||||||
#define EXPECTED_FUTURES_COUNT 15
|
#define EXPECTED_FUTURES_COUNT 15
|
||||||
|
|
|
@ -13,12 +13,12 @@
|
||||||
consistently.)
|
consistently.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MZSCHEME_VERSION "5.3.1.9"
|
#define MZSCHEME_VERSION "5.3.1.10"
|
||||||
|
|
||||||
#define MZSCHEME_VERSION_X 5
|
#define MZSCHEME_VERSION_X 5
|
||||||
#define MZSCHEME_VERSION_Y 3
|
#define MZSCHEME_VERSION_Y 3
|
||||||
#define MZSCHEME_VERSION_Z 1
|
#define MZSCHEME_VERSION_Z 1
|
||||||
#define MZSCHEME_VERSION_W 9
|
#define MZSCHEME_VERSION_W 10
|
||||||
|
|
||||||
#define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y)
|
#define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y)
|
||||||
#define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W)
|
#define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W)
|
||||||
|
|
|
@ -200,83 +200,84 @@ enum {
|
||||||
scheme_port_closed_evt_type, /* 180 */
|
scheme_port_closed_evt_type, /* 180 */
|
||||||
scheme_proc_shape_type, /* 181 */
|
scheme_proc_shape_type, /* 181 */
|
||||||
scheme_struct_proc_shape_type, /* 182 */
|
scheme_struct_proc_shape_type, /* 182 */
|
||||||
|
scheme_phantom_bytes_type, /* 183 */
|
||||||
|
|
||||||
#ifdef MZTAG_REQUIRED
|
#ifdef MZTAG_REQUIRED
|
||||||
_scheme_last_normal_type_, /* 183 */
|
_scheme_last_normal_type_, /* 184 */
|
||||||
|
|
||||||
scheme_rt_weak_array, /* 184 */
|
scheme_rt_weak_array, /* 185 */
|
||||||
|
|
||||||
scheme_rt_comp_env, /* 185 */
|
scheme_rt_comp_env, /* 186 */
|
||||||
scheme_rt_constant_binding, /* 186 */
|
scheme_rt_constant_binding, /* 187 */
|
||||||
scheme_rt_resolve_info, /* 187 */
|
scheme_rt_resolve_info, /* 188 */
|
||||||
scheme_rt_unresolve_info, /* 188 */
|
scheme_rt_unresolve_info, /* 189 */
|
||||||
scheme_rt_optimize_info, /* 189 */
|
scheme_rt_optimize_info, /* 190 */
|
||||||
scheme_rt_compile_info, /* 190 */
|
scheme_rt_compile_info, /* 191 */
|
||||||
scheme_rt_cont_mark, /* 191 */
|
scheme_rt_cont_mark, /* 192 */
|
||||||
scheme_rt_saved_stack, /* 192 */
|
scheme_rt_saved_stack, /* 193 */
|
||||||
scheme_rt_reply_item, /* 193 */
|
scheme_rt_reply_item, /* 194 */
|
||||||
scheme_rt_closure_info, /* 194 */
|
scheme_rt_closure_info, /* 195 */
|
||||||
scheme_rt_overflow, /* 195 */
|
scheme_rt_overflow, /* 196 */
|
||||||
scheme_rt_overflow_jmp, /* 196 */
|
scheme_rt_overflow_jmp, /* 197 */
|
||||||
scheme_rt_meta_cont, /* 197 */
|
scheme_rt_meta_cont, /* 198 */
|
||||||
scheme_rt_dyn_wind_cell, /* 198 */
|
scheme_rt_dyn_wind_cell, /* 199 */
|
||||||
scheme_rt_dyn_wind_info, /* 199 */
|
scheme_rt_dyn_wind_info, /* 200 */
|
||||||
scheme_rt_dyn_wind, /* 200 */
|
scheme_rt_dyn_wind, /* 201 */
|
||||||
scheme_rt_dup_check, /* 201 */
|
scheme_rt_dup_check, /* 202 */
|
||||||
scheme_rt_thread_memory, /* 202 */
|
scheme_rt_thread_memory, /* 203 */
|
||||||
scheme_rt_input_file, /* 203 */
|
scheme_rt_input_file, /* 204 */
|
||||||
scheme_rt_input_fd, /* 204 */
|
scheme_rt_input_fd, /* 205 */
|
||||||
scheme_rt_oskit_console_input, /* 205 */
|
scheme_rt_oskit_console_input, /* 206 */
|
||||||
scheme_rt_tested_input_file, /* 206 */
|
scheme_rt_tested_input_file, /* 207 */
|
||||||
scheme_rt_tested_output_file, /* 207 */
|
scheme_rt_tested_output_file, /* 208 */
|
||||||
scheme_rt_indexed_string, /* 208 */
|
scheme_rt_indexed_string, /* 209 */
|
||||||
scheme_rt_output_file, /* 209 */
|
scheme_rt_output_file, /* 210 */
|
||||||
scheme_rt_load_handler_data, /* 210 */
|
scheme_rt_load_handler_data, /* 211 */
|
||||||
scheme_rt_pipe, /* 211 */
|
scheme_rt_pipe, /* 212 */
|
||||||
scheme_rt_beos_process, /* 212 */
|
scheme_rt_beos_process, /* 213 */
|
||||||
scheme_rt_system_child, /* 213 */
|
scheme_rt_system_child, /* 214 */
|
||||||
scheme_rt_tcp, /* 214 */
|
scheme_rt_tcp, /* 215 */
|
||||||
scheme_rt_write_data, /* 215 */
|
scheme_rt_write_data, /* 216 */
|
||||||
scheme_rt_tcp_select_info, /* 216 */
|
scheme_rt_tcp_select_info, /* 217 */
|
||||||
scheme_rt_param_data, /* 217 */
|
scheme_rt_param_data, /* 218 */
|
||||||
scheme_rt_will, /* 218 */
|
scheme_rt_will, /* 219 */
|
||||||
scheme_rt_linker_name, /* 219 */
|
scheme_rt_linker_name, /* 220 */
|
||||||
scheme_rt_param_map, /* 220 */
|
scheme_rt_param_map, /* 221 */
|
||||||
scheme_rt_finalization, /* 221 */
|
scheme_rt_finalization, /* 222 */
|
||||||
scheme_rt_finalizations, /* 222 */
|
scheme_rt_finalizations, /* 223 */
|
||||||
scheme_rt_cpp_object, /* 223 */
|
scheme_rt_cpp_object, /* 224 */
|
||||||
scheme_rt_cpp_array_object, /* 224 */
|
scheme_rt_cpp_array_object, /* 225 */
|
||||||
scheme_rt_stack_object, /* 225 */
|
scheme_rt_stack_object, /* 226 */
|
||||||
scheme_rt_preallocated_object, /* 226 */
|
scheme_rt_preallocated_object, /* 227 */
|
||||||
scheme_thread_hop_type, /* 227 */
|
scheme_thread_hop_type, /* 228 */
|
||||||
scheme_rt_srcloc, /* 228 */
|
scheme_rt_srcloc, /* 229 */
|
||||||
scheme_rt_evt, /* 229 */
|
scheme_rt_evt, /* 230 */
|
||||||
scheme_rt_syncing, /* 230 */
|
scheme_rt_syncing, /* 231 */
|
||||||
scheme_rt_comp_prefix, /* 231 */
|
scheme_rt_comp_prefix, /* 232 */
|
||||||
scheme_rt_user_input, /* 232 */
|
scheme_rt_user_input, /* 233 */
|
||||||
scheme_rt_user_output, /* 233 */
|
scheme_rt_user_output, /* 234 */
|
||||||
scheme_rt_compact_port, /* 234 */
|
scheme_rt_compact_port, /* 235 */
|
||||||
scheme_rt_read_special_dw, /* 235 */
|
scheme_rt_read_special_dw, /* 236 */
|
||||||
scheme_rt_regwork, /* 236 */
|
scheme_rt_regwork, /* 237 */
|
||||||
scheme_rt_rx_lazy_string, /* 237 */
|
scheme_rt_rx_lazy_string, /* 238 */
|
||||||
scheme_rt_buf_holder, /* 238 */
|
scheme_rt_buf_holder, /* 239 */
|
||||||
scheme_rt_parameterization, /* 239 */
|
scheme_rt_parameterization, /* 240 */
|
||||||
scheme_rt_print_params, /* 240 */
|
scheme_rt_print_params, /* 241 */
|
||||||
scheme_rt_read_params, /* 241 */
|
scheme_rt_read_params, /* 242 */
|
||||||
scheme_rt_native_code, /* 242 */
|
scheme_rt_native_code, /* 243 */
|
||||||
scheme_rt_native_code_plus_case, /* 243 */
|
scheme_rt_native_code_plus_case, /* 244 */
|
||||||
scheme_rt_jitter_data, /* 244 */
|
scheme_rt_jitter_data, /* 245 */
|
||||||
scheme_rt_module_exports, /* 245 */
|
scheme_rt_module_exports, /* 246 */
|
||||||
scheme_rt_delay_load_info, /* 246 */
|
scheme_rt_delay_load_info, /* 247 */
|
||||||
scheme_rt_marshal_info, /* 247 */
|
scheme_rt_marshal_info, /* 248 */
|
||||||
scheme_rt_unmarshal_info, /* 248 */
|
scheme_rt_unmarshal_info, /* 249 */
|
||||||
scheme_rt_runstack, /* 249 */
|
scheme_rt_runstack, /* 250 */
|
||||||
scheme_rt_sfs_info, /* 250 */
|
scheme_rt_sfs_info, /* 251 */
|
||||||
scheme_rt_validate_clearing, /* 251 */
|
scheme_rt_validate_clearing, /* 252 */
|
||||||
scheme_rt_avl_node, /* 252 */
|
scheme_rt_avl_node, /* 253 */
|
||||||
scheme_rt_lightweight_cont, /* 253 */
|
scheme_rt_lightweight_cont, /* 254 */
|
||||||
scheme_rt_export_info, /* 254 */
|
scheme_rt_export_info, /* 255 */
|
||||||
scheme_rt_cont_jmp, /* 255 */
|
scheme_rt_cont_jmp, /* 256 */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_scheme_last_type_
|
_scheme_last_type_
|
||||||
|
|
|
@ -271,7 +271,7 @@ extern intptr_t GC_is_place();
|
||||||
#ifdef MZ_PRECISE_GC
|
#ifdef MZ_PRECISE_GC
|
||||||
extern intptr_t GC_get_memory_use(void *c);
|
extern intptr_t GC_get_memory_use(void *c);
|
||||||
#else
|
#else
|
||||||
extern MZ_DLLIMPORT long GC_get_memory_use();
|
extern MZ_DLLIMPORT intptr_t GC_get_memory_use();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct Thread_Cell {
|
typedef struct Thread_Cell {
|
||||||
|
@ -316,6 +316,11 @@ SHARED_OK static Proc_Global_Rec *process_globals;
|
||||||
static mzrt_mutex *process_global_lock;
|
static mzrt_mutex *process_global_lock;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Scheme_Object so;
|
||||||
|
intptr_t size;
|
||||||
|
} Scheme_Phantom_Bytes;
|
||||||
|
|
||||||
#ifdef MZ_PRECISE_GC
|
#ifdef MZ_PRECISE_GC
|
||||||
static void register_traversers(void);
|
static void register_traversers(void);
|
||||||
#endif
|
#endif
|
||||||
|
@ -392,6 +397,10 @@ static Scheme_Object *current_thread_set(int argc, Scheme_Object *argv[]);
|
||||||
|
|
||||||
static Scheme_Object *current_thread_initial_stack_size(int argc, Scheme_Object *argv[]);
|
static Scheme_Object *current_thread_initial_stack_size(int argc, Scheme_Object *argv[]);
|
||||||
|
|
||||||
|
static Scheme_Object *phantom_bytes_p(int argc, Scheme_Object *argv[]);
|
||||||
|
static Scheme_Object *make_phantom_bytes(int argc, Scheme_Object *argv[]);
|
||||||
|
static Scheme_Object *set_phantom_bytes(int argc, Scheme_Object *argv[]);
|
||||||
|
|
||||||
static void adjust_custodian_family(void *pr, void *ignored);
|
static void adjust_custodian_family(void *pr, void *ignored);
|
||||||
|
|
||||||
static Scheme_Object *make_will_executor(int argc, Scheme_Object *args[]);
|
static Scheme_Object *make_will_executor(int argc, Scheme_Object *args[]);
|
||||||
|
@ -579,6 +588,10 @@ void scheme_init_thread(Scheme_Env *env)
|
||||||
GLOBAL_PRIM_W_ARITY("choice-evt" , evts_to_evt , 0, -1, env);
|
GLOBAL_PRIM_W_ARITY("choice-evt" , evts_to_evt , 0, -1, env);
|
||||||
|
|
||||||
GLOBAL_PARAMETER("current-thread-initial-stack-size", current_thread_initial_stack_size, MZCONFIG_THREAD_INIT_STACK_SIZE, env);
|
GLOBAL_PARAMETER("current-thread-initial-stack-size", current_thread_initial_stack_size, MZCONFIG_THREAD_INIT_STACK_SIZE, env);
|
||||||
|
|
||||||
|
GLOBAL_PRIM_W_ARITY("phantom-bytes?", phantom_bytes_p, 1, 1, env);
|
||||||
|
GLOBAL_PRIM_W_ARITY("make-phantom-bytes", make_phantom_bytes, 1, 1, env);
|
||||||
|
GLOBAL_PRIM_W_ARITY("set-phantom-bytes!", set_phantom_bytes, 2, 2, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheme_init_thread_places(void) {
|
void scheme_init_thread_places(void) {
|
||||||
|
@ -679,7 +692,7 @@ static Scheme_Object *collect_garbage(int c, Scheme_Object *p[])
|
||||||
static Scheme_Object *current_memory_use(int argc, Scheme_Object *args[])
|
static Scheme_Object *current_memory_use(int argc, Scheme_Object *args[])
|
||||||
{
|
{
|
||||||
Scheme_Object *arg = NULL;
|
Scheme_Object *arg = NULL;
|
||||||
intptr_t retval = 0;
|
uintptr_t retval = 0;
|
||||||
|
|
||||||
if (argc) {
|
if (argc) {
|
||||||
if (SCHEME_FALSEP(args[0])) {
|
if (SCHEME_FALSEP(args[0])) {
|
||||||
|
@ -700,7 +713,7 @@ static Scheme_Object *current_memory_use(int argc, Scheme_Object *args[])
|
||||||
retval = GC_get_memory_use();
|
retval = GC_get_memory_use();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return scheme_make_integer_value(retval);
|
return scheme_make_integer_value_from_unsigned(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -7586,7 +7599,7 @@ Scheme_Object *scheme_param_config(char *name, Scheme_Object *pos,
|
||||||
static Scheme_Object *
|
static Scheme_Object *
|
||||||
exact_positive_integer_p (int argc, Scheme_Object *argv[])
|
exact_positive_integer_p (int argc, Scheme_Object *argv[])
|
||||||
{
|
{
|
||||||
Scheme_Object *n = argv[0];
|
Scheme_Object *n = argv[argc-1];
|
||||||
if (SCHEME_INTP(n) && (SCHEME_INT_VAL(n) > 0))
|
if (SCHEME_INTP(n) && (SCHEME_INT_VAL(n) > 0))
|
||||||
return scheme_true;
|
return scheme_true;
|
||||||
if (SCHEME_BIGNUMP(n) && SCHEME_BIGPOS(n))
|
if (SCHEME_BIGNUMP(n) && SCHEME_BIGPOS(n))
|
||||||
|
@ -7603,6 +7616,58 @@ static Scheme_Object *current_thread_initial_stack_size(int argc, Scheme_Object
|
||||||
-1, exact_positive_integer_p, "exact positive integer", 0);
|
-1, exact_positive_integer_p, "exact positive integer", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Scheme_Object *phantom_bytes_p(int argc, Scheme_Object *argv[])
|
||||||
|
{
|
||||||
|
return (SAME_TYPE(SCHEME_TYPE(argv[0]), scheme_phantom_bytes_type)
|
||||||
|
? scheme_true
|
||||||
|
: scheme_false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Scheme_Object *make_phantom_bytes(int argc, Scheme_Object *argv[])
|
||||||
|
{
|
||||||
|
Scheme_Phantom_Bytes *pb;
|
||||||
|
|
||||||
|
if (!scheme_nonneg_exact_p(argv[0]))
|
||||||
|
scheme_wrong_contract("make-phantom-bytes", "exact-nonnegative-integer?", 0, argc, argv);
|
||||||
|
|
||||||
|
if (!SCHEME_INTP(argv[0]))
|
||||||
|
scheme_raise_out_of_memory("make-phantom-bytes", NULL);
|
||||||
|
|
||||||
|
pb = MALLOC_ONE_TAGGED(Scheme_Phantom_Bytes);
|
||||||
|
pb->so.type = scheme_phantom_bytes_type;
|
||||||
|
pb->size = SCHEME_INT_VAL(argv[0]);
|
||||||
|
|
||||||
|
# ifdef MZ_PRECISE_GC
|
||||||
|
if (!GC_allocate_phantom_bytes(pb->size))
|
||||||
|
scheme_raise_out_of_memory("make-phantom-bytes", NULL);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return (Scheme_Object *)pb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Scheme_Object *set_phantom_bytes(int argc, Scheme_Object *argv[])
|
||||||
|
{
|
||||||
|
Scheme_Phantom_Bytes *pb;
|
||||||
|
intptr_t amt;
|
||||||
|
|
||||||
|
if (!SAME_TYPE(SCHEME_TYPE(argv[0]), scheme_phantom_bytes_type))
|
||||||
|
scheme_wrong_contract("set-phantom-bytes!", "phantom-bytes?", 0, argc, argv);
|
||||||
|
if (!scheme_nonneg_exact_p(argv[1]))
|
||||||
|
scheme_wrong_contract("set-phantom-bytes!", "exact-nonnegative-integer?", 1, argc, argv);
|
||||||
|
|
||||||
|
pb = (Scheme_Phantom_Bytes *)argv[0];
|
||||||
|
amt = SCHEME_INT_VAL(argv[1]);
|
||||||
|
|
||||||
|
# ifdef MZ_PRECISE_GC
|
||||||
|
if (!GC_allocate_phantom_bytes(amt - pb->size))
|
||||||
|
scheme_raise_out_of_memory("make-phantom-bytes", NULL);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
pb->size = amt;
|
||||||
|
|
||||||
|
return scheme_void;
|
||||||
|
}
|
||||||
|
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
/* namespaces */
|
/* namespaces */
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
|
|
|
@ -307,6 +307,8 @@ scheme_init_type ()
|
||||||
|
|
||||||
set_name(scheme_resolved_module_path_type, "<resolve-module-path>");
|
set_name(scheme_resolved_module_path_type, "<resolve-module-path>");
|
||||||
|
|
||||||
|
set_name(scheme_phantom_bytes_type, "<phantom-bytes>");
|
||||||
|
|
||||||
#ifdef MZ_GC_BACKTRACE
|
#ifdef MZ_GC_BACKTRACE
|
||||||
set_name(scheme_rt_meta_cont, "<meta-continuation>");
|
set_name(scheme_rt_meta_cont, "<meta-continuation>");
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user