cs: add missing prompt-tag checks in mark lookup
This commit is contained in:
parent
aed8d4f3e5
commit
c47cbbf6c5
|
@ -464,6 +464,7 @@
|
||||||
exn:fail:contract:continuation?)
|
exn:fail:contract:continuation?)
|
||||||
(err/rt-test (continuation-mark-set-first #f 'key #f (make-continuation-prompt-tag 'px))
|
(err/rt-test (continuation-mark-set-first #f 'key #f (make-continuation-prompt-tag 'px))
|
||||||
exn:fail:contract:continuation?)
|
exn:fail:contract:continuation?)
|
||||||
|
(test 'nope continuation-mark-set-first (current-continuation-marks) 'key 'nope (make-continuation-prompt-tag 'px))
|
||||||
|
|
||||||
;; Create a deep stack with a deep mark stack
|
;; Create a deep stack with a deep mark stack
|
||||||
|
|
||||||
|
|
|
@ -390,10 +390,10 @@
|
||||||
;; Capturing and applying continuations
|
;; Capturing and applying continuations
|
||||||
|
|
||||||
(define-record continuation ())
|
(define-record continuation ())
|
||||||
(define-record full-continuation continuation (k winders mark-stack mark-splice mc))
|
(define-record full-continuation continuation (k winders mark-stack mark-splice mc tag))
|
||||||
(define-record composable-continuation full-continuation ())
|
(define-record composable-continuation full-continuation ())
|
||||||
(define-record composable-continuation/no-wind composable-continuation ())
|
(define-record composable-continuation/no-wind composable-continuation ())
|
||||||
(define-record non-composable-continuation full-continuation (tag))
|
(define-record non-composable-continuation full-continuation ())
|
||||||
(define-record escape-continuation continuation (tag))
|
(define-record escape-continuation continuation (tag))
|
||||||
|
|
||||||
(define/who call-with-current-continuation
|
(define/who call-with-current-continuation
|
||||||
|
@ -437,7 +437,8 @@
|
||||||
(current-winders)
|
(current-winders)
|
||||||
(current-mark-stack)
|
(current-mark-stack)
|
||||||
(current-mark-splice)
|
(current-mark-splice)
|
||||||
(extract-metacontinuation 'call-with-composable-continuation (strip-impersonator tag) #f))))))
|
(extract-metacontinuation 'call-with-composable-continuation (strip-impersonator tag) #f)
|
||||||
|
tag)))))
|
||||||
|
|
||||||
(define (unsafe-call-with-composable-continuation/no-wind p tag)
|
(define (unsafe-call-with-composable-continuation/no-wind p tag)
|
||||||
(call-with-composable-continuation* p tag #f))
|
(call-with-composable-continuation* p tag #f))
|
||||||
|
@ -481,7 +482,7 @@
|
||||||
|
|
||||||
(define (apply-non-composable-continuation c args)
|
(define (apply-non-composable-continuation c args)
|
||||||
(assert-in-uninterrupted)
|
(assert-in-uninterrupted)
|
||||||
(let* ([tag (non-composable-continuation-tag c)])
|
(let* ([tag (full-continuation-tag c)])
|
||||||
(let-values ([(common-mc ; shared part of the current metacontinuation
|
(let-values ([(common-mc ; shared part of the current metacontinuation
|
||||||
rmc-append) ; non-shared part of the destination metacontinuation
|
rmc-append) ; non-shared part of the destination metacontinuation
|
||||||
;; We check every time, just in case control operations
|
;; We check every time, just in case control operations
|
||||||
|
@ -531,7 +532,7 @@
|
||||||
;; callbacks here are run with a continuation barrier, so
|
;; callbacks here are run with a continuation barrier, so
|
||||||
;; the metacontinuation won't change (except by escaping):
|
;; the metacontinuation won't change (except by escaping):
|
||||||
(activate-and-wrap-cc-guard-for-impersonator!
|
(activate-and-wrap-cc-guard-for-impersonator!
|
||||||
(non-composable-continuation-tag c)))
|
(full-continuation-tag c)))
|
||||||
((full-continuation-k c) (lambda () (end-uninterrupted-with-values args))))
|
((full-continuation-k c) (lambda () (end-uninterrupted-with-values args))))
|
||||||
;; If a winder changed the meta-continuation, try again for a
|
;; If a winder changed the meta-continuation, try again for a
|
||||||
;; non-composable continuation:
|
;; non-composable continuation:
|
||||||
|
@ -662,9 +663,12 @@
|
||||||
|
|
||||||
(define (check-prompt-tag-available who tag)
|
(define (check-prompt-tag-available who tag)
|
||||||
(unless (continuation-prompt-available? tag)
|
(unless (continuation-prompt-available? tag)
|
||||||
(do-raise-arguments-error who "continuation includes no prompt with the given tag"
|
(raise-no-prompt-tag who tag)))
|
||||||
exn:fail:contract:continuation
|
|
||||||
(list "tag" tag))))
|
(define (raise-no-prompt-tag who tag)
|
||||||
|
(do-raise-arguments-error who "continuation includes no prompt with the given tag"
|
||||||
|
exn:fail:contract:continuation
|
||||||
|
(list "tag" tag)))
|
||||||
|
|
||||||
(define (call-with-appended-metacontinuation rmc dest-c dest-args proc)
|
(define (call-with-appended-metacontinuation rmc dest-c dest-args proc)
|
||||||
;; Assumes that the current metacontinuation frame is ready to be
|
;; Assumes that the current metacontinuation frame is ready to be
|
||||||
|
@ -944,13 +948,18 @@
|
||||||
[else
|
[else
|
||||||
(prune-mark-chain-prefix tag (cdr mark-chain))]))
|
(prune-mark-chain-prefix tag (cdr mark-chain))]))
|
||||||
|
|
||||||
(define (prune-mark-chain-suffix tag mark-chain)
|
(define (prune-mark-chain-suffix who tag must-find-tag mark-chain)
|
||||||
(cond
|
(cond
|
||||||
[(null? mark-chain) null]
|
[(null? mark-chain)
|
||||||
|
(when must-find-tag
|
||||||
|
(unless (or (eq? tag the-default-continuation-prompt-tag)
|
||||||
|
(eq? tag the-root-continuation-prompt-tag))
|
||||||
|
(raise-no-prompt-tag who must-find-tag)))
|
||||||
|
null]
|
||||||
[(eq? tag (mark-chain-frame-tag (elem+cache-strip (car mark-chain))))
|
[(eq? tag (mark-chain-frame-tag (elem+cache-strip (car mark-chain))))
|
||||||
null]
|
null]
|
||||||
[else
|
[else
|
||||||
(let ([rest-mark-chain (prune-mark-chain-suffix tag (cdr mark-chain))])
|
(let ([rest-mark-chain (prune-mark-chain-suffix who tag must-find-tag (cdr mark-chain))])
|
||||||
(if (eq? rest-mark-chain (cdr mark-chain))
|
(if (eq? rest-mark-chain (cdr mark-chain))
|
||||||
mark-chain
|
mark-chain
|
||||||
(cons (car mark-chain)
|
(cons (car mark-chain)
|
||||||
|
@ -1027,11 +1036,11 @@
|
||||||
(eq? key parameterization-key))
|
(eq? key parameterization-key))
|
||||||
the-root-continuation-prompt-tag
|
the-root-continuation-prompt-tag
|
||||||
the-default-continuation-prompt-tag))]
|
the-default-continuation-prompt-tag))]
|
||||||
[(marks key none-v prompt-tag)
|
[(marks key none-v orig-prompt-tag)
|
||||||
(check who continuation-mark-set? :or-false marks)
|
(check who continuation-mark-set? :or-false marks)
|
||||||
(check who continuation-prompt-tag? prompt-tag)
|
(check who continuation-prompt-tag? orig-prompt-tag)
|
||||||
(maybe-future-barricade prompt-tag)
|
(maybe-future-barricade orig-prompt-tag)
|
||||||
(let ([prompt-tag (strip-impersonator prompt-tag)])
|
(let ([prompt-tag (strip-impersonator orig-prompt-tag)])
|
||||||
(let-values ([(key wrapper) (extract-continuation-mark-key-and-wrapper 'continuation-mark-set-first key)])
|
(let-values ([(key wrapper) (extract-continuation-mark-key-and-wrapper 'continuation-mark-set-first key)])
|
||||||
(let* ([v0 (if marks
|
(let* ([v0 (if marks
|
||||||
none
|
none
|
||||||
|
@ -1039,7 +1048,8 @@
|
||||||
(marks-search (mark-stack-to-marks (current-mark-stack))
|
(marks-search (mark-stack-to-marks (current-mark-stack))
|
||||||
key
|
key
|
||||||
#f ; at-outer?
|
#f ; at-outer?
|
||||||
prompt-tag))]
|
prompt-tag
|
||||||
|
#f))]
|
||||||
[v (if (eq? v0 none)
|
[v (if (eq? v0 none)
|
||||||
(marks-search (or (and marks
|
(marks-search (or (and marks
|
||||||
(continuation-mark-set-mark-chain marks))
|
(continuation-mark-set-mark-chain marks))
|
||||||
|
@ -1047,7 +1057,10 @@
|
||||||
(get-rest-mark-chain (current-mark-splice) (current-metacontinuation)))
|
(get-rest-mark-chain (current-mark-splice) (current-metacontinuation)))
|
||||||
key
|
key
|
||||||
#t ; at-outer?
|
#t ; at-outer?
|
||||||
prompt-tag)
|
prompt-tag
|
||||||
|
(not (or marks
|
||||||
|
(or (eq? prompt-tag the-default-continuation-prompt-tag)
|
||||||
|
(eq? prompt-tag the-root-continuation-prompt-tag)))))
|
||||||
v0)])
|
v0)])
|
||||||
(cond
|
(cond
|
||||||
[(eq? v none)
|
[(eq? v none)
|
||||||
|
@ -1059,19 +1072,27 @@
|
||||||
(current-engine-init-break-enabled-cell none-v)]
|
(current-engine-init-break-enabled-cell none-v)]
|
||||||
[else
|
[else
|
||||||
none-v])]
|
none-v])]
|
||||||
|
[(eq? v none2)
|
||||||
|
;; Didn't find prompt tag when searching the current continuation
|
||||||
|
(raise-no-prompt-tag who orig-prompt-tag)]
|
||||||
[else (wrapper v)]))))]))
|
[else (wrapper v)]))))]))
|
||||||
|
|
||||||
;; To make `continuation-mark-set-first` constant-time, if we traverse
|
;; To make `continuation-mark-set-first` constant-time, if we traverse
|
||||||
;; N elements to get an answer, then cache the answer at N/2 elements.
|
;; N elements to get an answer, then cache the answer at N/2 elements.
|
||||||
(define (marks-search elems key at-outer? prompt-tag)
|
;; The result is `none` is not found.
|
||||||
|
;; The result is `none2` if `need-tag?` and the prompt tag is never found.
|
||||||
|
(define (marks-search elems key at-outer? prompt-tag need-tag?)
|
||||||
(let loop ([elems elems] [elems/cache-pos elems] [cache-step? #f] [depth 0])
|
(let loop ([elems elems] [elems/cache-pos elems] [cache-step? #f] [depth 0])
|
||||||
(cond
|
(cond
|
||||||
[(or (null? elems)
|
[(or (null? elems)
|
||||||
(and at-outer?
|
(and at-outer?
|
||||||
(eq? (mark-chain-frame-tag (elem+cache-strip (car elems))) prompt-tag)))
|
(eq? (mark-chain-frame-tag (elem+cache-strip (car elems))) prompt-tag)))
|
||||||
;; Not found
|
;; Not found
|
||||||
(cache-result! elems elems/cache-pos depth key none at-outer? prompt-tag)
|
(cond
|
||||||
none]
|
[(and need-tag? (null? elems)) none2]
|
||||||
|
[else
|
||||||
|
(cache-result! elems elems/cache-pos depth key none at-outer? prompt-tag)
|
||||||
|
none])]
|
||||||
[else
|
[else
|
||||||
(let t-loop ([t (car elems)])
|
(let t-loop ([t (car elems)])
|
||||||
(cond
|
(cond
|
||||||
|
@ -1107,7 +1128,7 @@
|
||||||
(let ([marks (mark-chain-frame-marks t)])
|
(let ([marks (mark-chain-frame-marks t)])
|
||||||
(if (null? marks)
|
(if (null? marks)
|
||||||
none
|
none
|
||||||
(marks-search marks key #f #f)))
|
(marks-search marks key #f #f #f)))
|
||||||
;; We're looking at just one frame:
|
;; We're looking at just one frame:
|
||||||
(intmap-ref t key none))])
|
(intmap-ref t key none))])
|
||||||
(cond
|
(cond
|
||||||
|
@ -1233,10 +1254,9 @@
|
||||||
[(tag)
|
[(tag)
|
||||||
(check who continuation-prompt-tag? tag)
|
(check who continuation-prompt-tag? tag)
|
||||||
(maybe-future-barricade tag)
|
(maybe-future-barricade tag)
|
||||||
(check-prompt-tag-available who tag)
|
|
||||||
(call/cc
|
(call/cc
|
||||||
(lambda (k)
|
(lambda (k)
|
||||||
(make-continuation-mark-set (prune-mark-chain-suffix (strip-impersonator tag) (current-mark-chain))
|
(make-continuation-mark-set (prune-mark-chain-suffix who (strip-impersonator tag) tag (current-mark-chain))
|
||||||
(cons (continuation->trace k)
|
(cons (continuation->trace k)
|
||||||
(get-metacontinuation-traces (current-metacontinuation))))))]))
|
(get-metacontinuation-traces (current-metacontinuation))))))]))
|
||||||
|
|
||||||
|
@ -1247,28 +1267,33 @@
|
||||||
(define/who continuation-marks
|
(define/who continuation-marks
|
||||||
(case-lambda
|
(case-lambda
|
||||||
[(k) (continuation-marks k (default-continuation-prompt-tag))]
|
[(k) (continuation-marks k (default-continuation-prompt-tag))]
|
||||||
[(k tag)
|
[(k orig-tag)
|
||||||
;; If `k` is a procedure, we assume that it's an engine
|
;; If `k` is a procedure, we assume that it's an engine
|
||||||
(check who (lambda (p) (or (not p)
|
(check who (lambda (p) (or (not p)
|
||||||
(continuation? p)
|
(continuation? p)
|
||||||
(and (#%procedure? p) (procedure-arity-includes? p 0))))
|
(and (#%procedure? p) (procedure-arity-includes? p 0))))
|
||||||
:contract "(or/c continuation? engine-procedure? #f)"
|
:contract "(or/c continuation? engine-procedure? #f)"
|
||||||
k)
|
k)
|
||||||
(check who continuation-prompt-tag? tag)
|
(check who continuation-prompt-tag? orig-tag)
|
||||||
(maybe-future-barricade tag)
|
(maybe-future-barricade orig-tag)
|
||||||
(let ([tag (strip-impersonator tag)])
|
(let ([tag (strip-impersonator orig-tag)])
|
||||||
(cond
|
(cond
|
||||||
[(#%procedure? k)
|
[(#%procedure? k)
|
||||||
(let ([mc (saved-metacontinuation-mc (k))])
|
(let ([mc (saved-metacontinuation-mc (k))])
|
||||||
(make-continuation-mark-set
|
(make-continuation-mark-set
|
||||||
(prune-mark-chain-suffix
|
(prune-mark-chain-suffix
|
||||||
|
who
|
||||||
tag
|
tag
|
||||||
|
orig-tag
|
||||||
(get-mark-chain '() #f mc))
|
(get-mark-chain '() #f mc))
|
||||||
(get-metacontinuation-traces mc)))]
|
(get-metacontinuation-traces mc)))]
|
||||||
[(full-continuation? k)
|
[(full-continuation? k)
|
||||||
(make-continuation-mark-set
|
(make-continuation-mark-set
|
||||||
(prune-mark-chain-suffix
|
(prune-mark-chain-suffix
|
||||||
|
who
|
||||||
tag
|
tag
|
||||||
|
(and (not (eq? tag (strip-impersonator (full-continuation-tag k))))
|
||||||
|
orig-tag)
|
||||||
(get-mark-chain (full-continuation-mark-stack k)
|
(get-mark-chain (full-continuation-mark-stack k)
|
||||||
(full-continuation-mark-splice k)
|
(full-continuation-mark-splice k)
|
||||||
(full-continuation-mc k)))
|
(full-continuation-mc k)))
|
||||||
|
@ -1280,7 +1305,9 @@
|
||||||
"escape continuation not in the current continuation"))
|
"escape continuation not in the current continuation"))
|
||||||
(make-continuation-mark-set
|
(make-continuation-mark-set
|
||||||
(prune-mark-chain-suffix
|
(prune-mark-chain-suffix
|
||||||
|
who
|
||||||
tag
|
tag
|
||||||
|
orig-tag
|
||||||
(prune-mark-chain-prefix (escape-continuation-tag k) (current-mark-chain)))
|
(prune-mark-chain-prefix (escape-continuation-tag k) (current-mark-chain)))
|
||||||
null)]
|
null)]
|
||||||
[else
|
[else
|
||||||
|
|
Loading…
Reference in New Issue
Block a user