Chez Scheme GC: simplify make parallel sweeper object exchange

Make the exchange of objects by parallel sweepers --- which is needed
when an object being swept by one thread refers to an object owner by
another thread --- much simpler and slightly faster.

The original design of exchanging memory regions didn't really work
out, and it had degrenerated to essentially exchanging objects.
Explicitly exchanging objects instead of regions makes the GC simpler,
because received objects can be just added to the regular sweep stack,
and less additional space<->type correspondence is needed.
This commit is contained in:
Matthew Flatt 2020-10-12 16:13:03 -06:00
parent 1a1bad4e90
commit 449f01b55d
7 changed files with 283 additions and 431 deletions

View File

@ -84,6 +84,10 @@ LZ4Sources=../lz4/lib/lz4.h ../lz4/lib/lz4frame.h \
../lz4/lib/lz4.c ../lz4/lib/lz4frame.c \
../lz4/lib/lz4hc.c ../lz4/lib/xxhash.c
.PHONY: run
run:
env SCHEMEHEAPDIRS=../boot/$m/ ../bin/$m/scheme $(ARGS)
clean:
rm -f *.$o ${mdclean}
rm -f Make.out

File diff suppressed because it is too large Load Diff

View File

@ -666,13 +666,6 @@ void S_check_heap(aftergc, mcg) IBOOL aftergc; IGEN mcg; {
printf("!!! inconsistent thread NEXT %p and BASE %p\n",
TO_VOIDP(tgc->next_loc[g][s]), TO_VOIDP(tgc->base_loc[g][s]));
}
if ((tgc->remote_range_end != (ptr)0)
|| (tgc->remote_range_start != (ptr)(uptr)-1)) {
S_checkheap_errors += 1;
printf("!!! nonempty thread REMOTERANGE %p-%p\n",
TO_VOIDP(tgc->remote_range_start),
TO_VOIDP(tgc->remote_range_end));
}
}
}
}
@ -1022,7 +1015,7 @@ void S_check_heap(aftergc, mcg) IBOOL aftergc; IGEN mcg; {
if (S_checkheap_errors) {
printf("heap check failed%s\n", (aftergc ? " after gc" : ""));
exit(1);
abort();
}
}

View File

@ -163,11 +163,7 @@ ptr S_create_thread_object(who, p_tc) const char *who; ptr p_tc; {
tgc->during_alloc = 0;
tgc->sweeper = main_sweeper_index;
tgc->remote_range_start = (ptr)(uptr)-1;
tgc->remote_range_end = (ptr)0;
tgc->pending_ephemerons = (ptr)0;
tgc->ranges_to_send = NULL;
tgc->ranges_received = NULL;
for (i = 0; i < (int)DIRTY_SEGMENT_LISTS; i++)
tgc->dirty_segments[i] = NULL;
tgc->thread = (ptr)0;

View File

@ -464,14 +464,6 @@ typedef struct {
#define AS_IMPLICIT_ATOMIC(T, X) X
#endif
typedef struct remote_range {
ISPC s;
IGEN g;
ptr start, end;
struct thread_gc *tgc;
struct remote_range *next;
} remote_range;
typedef struct thread_gc {
ptr tc;
ptr thread; /* set only when collecting */
@ -497,12 +489,16 @@ typedef struct thread_gc {
int sweep_change;
int sweeper; /* parallel GC: sweeper thread identity */
struct thread_gc *remote_range_tgc;
ptr remote_range_start;
ptr remote_range_end;
remote_range *ranges_to_send; /* modified only by owning sweeper */
remote_range *ranges_received; /* modified with sweeper mutex held */
/* modified only by owning sweeper; contains ptr and thread_gc* */
ptr send_remote_sweep_stack;
ptr send_remote_sweep_stack_start;
ptr send_remote_sweep_stack_limit;
/* modified with sweeper mutex held; contains just ptr */
ptr receive_remote_sweep_stack;
ptr receive_remote_sweep_stack_start;
ptr receive_remote_sweep_stack_limit;
seginfo *dirty_segments[DIRTY_SEGMENT_LISTS];

View File

@ -444,6 +444,9 @@ prettyclean:
clean: prettyclean
rm -f Make.out
.PHONY: run
run:
env SCHEMEHEAPDIRS=../boot/$m/ ../bin/$m/scheme $(ARGS)
### rules for generating various experr files

View File

@ -243,7 +243,7 @@
;; A stack segment has a single owner, so it's ok for us
;; to sweep the stack content, even though it's on a
;; remote segment relative to the current sweeper.
(RECORD_REMOTE_RANGE _tgc_ _ _size_ s_si)]
(RECORD_REMOTE s_si)]
[else
(set! (continuation-stack _)
(copy_stack _tgc_
@ -794,7 +794,7 @@
(SEGMENT_IS_LOCAL v_si val))
(trace-symcode symbol-pvalue val)]
[else
(RECORD_REMOTE_RANGE _tgc_ _ _size_ v_si)])]
(RECORD_REMOTE v_si)])]
[off (trace-symcode symbol-pvalue val)])]
[else
(trace-symcode symbol-pvalue val)]))
@ -869,7 +869,7 @@
(trace-record-type-pm num rtd)]
[else
;; Try again in the bignum's sweeper
(RECORD_REMOTE_RANGE _tgc_ _ _size_ pm_si)
(RECORD_REMOTE pm_si)
(set! num S_G.zero_length_bignum)])]
[off
(trace-record-type-pm num rtd)])]
@ -1110,7 +1110,7 @@
(trace-pure (* (ENTRYNONCOMPACTLIVEMASKADDR oldret)))
(set! num (ENTRYLIVEMASK oldret))]
[else
(RECORD_REMOTE_RANGE _tgc_ _ _size_ n_si)
(RECORD_REMOTE n_si)
(set! num S_G.zero_length_bignum)])])
(let* ([index : iptr (BIGLEN num)])
(while
@ -1140,7 +1140,7 @@
[(sweep sweep-in-old)
(define x_si : seginfo* (SegInfo (ptr_get_segment c_p)))
(when (-> x_si old_space)
(relocate_code c_p x_si _ _size_)
(relocate_code c_p x_si)
(case-mode
[sweep-in-old]
[else
@ -1222,7 +1222,7 @@
(find_gc_room _tgc_ space_data from_g typemod n t)
(memcpy_aligned (TO_VOIDP t) (TO_VOIDP oldt) n))])]
[else
(RECORD_REMOTE_RANGE _tgc_ _ _size_ t_si)])))
(RECORD_REMOTE t_si)])))
(set! (reloc-table-code t) _)
(set! (code-reloc _) t)])
(S_record_code_mod (-> _tgc_ tc) (cast uptr (TO_PTR (& (code-data _ 0)))) (cast uptr (code-length _)))]
@ -1526,15 +1526,20 @@
"return si->generation;")]
[(sweep)
(code-block
"FLUSH_REMOTE_BLOCK"
(and (lookup 'maybe-backreferences? config #f)
"PUSH_BACKREFERENCE(p)")
(body)
(and (lookup 'maybe-backreferences? config #f)
"POP_BACKREFERENCE()")
"FLUSH_REMOTE(tgc, p);"
(and (lookup 'as-dirty? config #f)
"return youngest;"))]
[(sweep-in-old)
(body)]
(code-block
"FLUSH_REMOTE_BLOCK"
(body)
"ASSERT_EMPTY_FLUSH_REMOTE();")]
[(measure)
(body)]
[(self-test)
@ -2215,27 +2220,19 @@
(define (relocate-statement purity e config)
(define mode (lookup 'mode config))
(define (get-start) (expression '_ config))
(define (get-size) (cond
[(lookup 'early-rtd? config #f)
(expression '(size_record_inst (UNFIX (record-type-size (record-type _)))) config)]
[(lookup 'early-code? config #f)
(expression '(size_closure (CODEFREE (CLOSCODE _))) config)]
[else
(expression '_size_ config)]))
(case mode
[(vfasl-sweep)
(format "vfasl_relocate(vfi, &~a);" e)]
[(sweep-in-old)
(if (eq? purity 'pure)
(format "relocate_pure(&~a, ~a, ~a);" e (get-start) (get-size))
(format "relocate_indirect(~a, ~a, ~a);" e (get-start) (get-size)))]
(format "relocate_pure(&~a);" e)
(format "relocate_indirect(~a);" e))]
[else
(if (lookup 'as-dirty? config #f)
(begin
(when (eq? purity 'pure) (error 'relocate-statement "pure as dirty?"))
(format "relocate_dirty(&~a, youngest, ~a, ~a);" e (get-start) (get-size)))
(format "relocate_~a(&~a~a, ~a, ~a);" purity e (if (eq? purity 'impure) ", from_g" "") (get-start) (get-size)))]))
(format "relocate_dirty(&~a, youngest);" e))
(format "relocate_~a(&~a~a);" purity e (if (eq? purity 'impure) ", from_g" "")))]))
(define (measure-statement e)
(code