continuation-attachment performance

Add a shortcut check when refiying the continuation frame in tail
position, which is significantly cheaper when the frame is already
there. We pay down the check by skipping an attachment-lists check
that is not needed if the frame is newly reified.

Aslo, add a one-shot continuation-frame cache, which makes a shallow
temporary attachment cheaper, as in

 (let loop ([i N])
   (if (zero? i)
       0
       (loop (call-setting-continuation-attachment
              i
              (lambda ()
                (f (sub1 i)))))))

The cache is just one frame. Keeping a chain of allocated-by-not-GCed
frames doesn't pay off.

Meanwhile, remove the leftover `$shift-attachment` library entry.

original commit: 1f454f536b1d7efe20fe9e793cda31e54e31e5f4
This commit is contained in:
Matthew Flatt 2019-09-10 16:01:43 -06:00
parent 502b0b5f50
commit b842a134fd
5 changed files with 35 additions and 40 deletions

1
c/gc.c
View File

@ -1842,6 +1842,7 @@ static void sweep_thread(p) ptr p; {
/* iptr SCHEMESTACKSIZE */
relocate(&WINDERS(tc))
relocate(&ATTACHMENTS(tc))
CACHEDFRAME(tc) = Sfalse;
relocate_return_addr(&FRAME(tc,0))
sweep_stack((uptr)SCHEMESTACK(tc), (uptr)SFP(tc), (uptr)FRAME(tc,0));
relocate(&U(tc))

View File

@ -81,6 +81,7 @@ ptr S_create_thread_object(who, p_tc) const char *who; ptr p_tc; {
WINDERS(tc) = Snil;
ATTACHMENTS(tc) = Snil;
CACHEDFRAME(tc) = Sfalse;
STACKLINK(tc) = SYMVAL(S_G.null_continuation_id);
STACKCACHE(tc) = Snil;

View File

@ -1379,6 +1379,7 @@
[iptr scheme-stack-size]
[ptr winders]
[ptr attachments]
[ptr cached-frame]
[ptr U]
[ptr V]
[ptr W]
@ -2696,7 +2697,6 @@
($wrapper-apply #f 0 #f #f)
(wrapper-apply #f 0 #f #f)
(arity-wrapper-apply #f 0 #f #f)
($shift-attachment #f 0 #f #f)
))
(let ()

View File

@ -5575,8 +5575,7 @@
(define hand-coded-closure?
(lambda (name)
(not (memq name '(nuate nonprocedure-code error-invoke invoke
$wrapper-apply wrapper-apply arity-wrapper-apply
$shift-attachment)))))
$wrapper-apply wrapper-apply arity-wrapper-apply)))))
(define-inline 2 $hand-coded
[(name)
(nanopass-case (L7 Expr) name
@ -11574,6 +11573,7 @@
(set! ,(%tc-ref scheme-stack) ,(%mref ,xp/cp ,(constant continuation-stack-disp)))
(set! ,(%tc-ref stack-link) ,(%mref ,xp/cp ,(constant continuation-link-disp)))
(set! ,%ts ,(%mref ,xp/cp ,(constant continuation-attachments-disp)))
(set! ,(%tc-ref cached-frame) ,xp/cp) ; save for fast immediate realloc
(set! ,(%tc-ref attachments) ,%ts)
(goto ,Lreturn))
; can't merge
@ -11666,9 +11666,18 @@
,(%inline eq? ,%ref-ret ,%ac0))
,(finish %td)
,(%seq
(set! ,%xp ,(%constant-alloc type-closure (constant size-continuation)))
(set! ,(%mref ,%xp ,(constant continuation-code-disp))
(literal ,(make-info-literal #f 'library (lookup-libspec nuate) (constant code-data-disp))))
,(let ([alloc
(%seq
(set! ,%xp ,(%constant-alloc type-closure (constant size-continuation)))
(set! ,(%mref ,%xp ,(constant continuation-code-disp))
(literal ,(make-info-literal #f 'library (lookup-libspec nuate) (constant code-data-disp)))))])
(if 1-shot?
(%seq
(set! ,%xp ,(%tc-ref cached-frame))
(if ,(%inline eq? ,%xp ,(%constant sfalse))
,alloc
(set! ,(%tc-ref cached-frame) ,(%constant sfalse))))
alloc))
(set! ,(%mref ,%xp ,(constant continuation-return-address-disp)) ,%ref-ret)
(set! ,(%mref ,%xp ,(constant continuation-winders-disp)) ,(%tc-ref winders))
(set! ,(%mref ,%xp ,(constant continuation-attachments-disp)) ,(%tc-ref attachments))
@ -12004,13 +12013,24 @@
(set! ,ats ,(%mref ,ats ,(constant pair-cdr-disp)))
,(make-push))]
[(reify-and-set)
(%seq
(set! ,%td (inline ,(intrinsic-info-asmlib reify-cc #f) ,%asmlibcall))
(set! ,ats ,(%tc-ref attachments))
(if ,(%inline eq? ,(%mref ,%td ,(constant continuation-attachments-disp)) ,ats)
(nop)
(set! ,ats ,(%mref ,ats ,(constant pair-cdr-disp))))
,(make-push))]
(let ([tmp (make-tmp 'uf)])
(%seq
;; Fast check for existing reified, first
(set! ,%td ,(%tc-ref stack-link))
(set! ,tmp (literal ,(make-info-literal #f 'library-code
(lookup-libspec dounderflow)
(fx+ (constant code-data-disp) (constant size-rp-header)))))
(set! ,ats ,(%tc-ref attachments))
(if (if ,(%inline eq?
,(%mref ,%td ,(constant continuation-attachments-disp))
,(%constant sfalse))
(false)
,(%inline eq? ,%ref-ret ,tmp))
(if ,(%inline eq? ,(%mref ,%td ,(constant continuation-attachments-disp)) ,ats)
(nop)
(set! ,ats ,(%mref ,ats ,(constant pair-cdr-disp))))
(set! ,%td (inline ,(intrinsic-info-asmlib reify-cc #f) ,%asmlibcall)))
,(make-push)))]
[else
($oops who "unexpected attachment-set mode ~s" aop)]))])
(Tail : Tail (ir) -> Tail ()
@ -12941,32 +12961,6 @@
(set! ,(ref-reg %cp) ,%td)
(jump ,(%mref ,%td ,(constant closure-code-disp))
(,%ac0 ,(reg-cons* %ret arg-registers) ...)))))])))]
[($shift-attachment)
;; Reify the continuation, but dropping the first `attachments` element,
;; which must be present, so that the attachment will be popped
;; on return from the continuation
(let ([info (make-info "$shift-attachment" '())])
(info-lambda-fv*-set! info '(proc))
`(lambda ,info 0 ()
,(%seq
(set! ,(ref-reg %ac1) ,%ac0) ; save argument count
(set! ,%td (inline ,(intrinsic-info-asmlib reify-cc #f) ,%asmlibcall))
(set! ,%ts ,(%mref ,%td ,(constant continuation-attachments-disp)))
(set! ,(%mref ,%td ,(constant continuation-attachments-disp)) ,(%mref ,%ts ,(constant pair-cdr-disp)))
(set! ,%ac0 ,(ref-reg %ac1)) ; restore argument count
,(meta-cond
[(real-register? '%cp)
(%seq
(set! ,%cp ,(%mref ,%cp ,(constant closure-data-disp)))
(jump ,(%mref ,%cp ,(constant closure-code-disp))
(,%ac0 ,%cp ,(reg-cons* %ret arg-registers) ...)))]
[else
(%seq
(set! ,%td ,(ref-reg %cp))
(set! ,%td ,(%mref ,%td ,(constant closure-data-disp)))
(set! ,(ref-reg %cp) ,%td)
(jump ,(%mref ,%td ,(constant closure-code-disp))
(,%ac0 ,(reg-cons* %ret arg-registers) ...)))]))))]
[(bytevector=?)
(let ([bv1 (make-tmp 'bv1)] [bv2 (make-tmp 'bv2)] [idx (make-tmp 'idx)] [len2 (make-tmp 'len2)])
(define (argcnt->max-fv n) (max (- n (length arg-registers)) 0))

View File

@ -126,7 +126,6 @@
(define-hand-coded-library-entry dofretu32*)
(define-hand-coded-library-entry domvleterr)
(define-hand-coded-library-entry values-error)
(define-hand-coded-library-entry $shift-attachment)
(define-hand-coded-library-entry bytevector=?)
(define-hand-coded-library-entry $wrapper-apply)
(define-hand-coded-library-entry wrapper-apply)