diff --git a/racket/src/cs/primitive/kernel.ss b/racket/src/cs/primitive/kernel.ss index e3e514e058..44ca2ed867 100644 --- a/racket/src/cs/primitive/kernel.ss +++ b/racket/src/cs/primitive/kernel.ss @@ -19,7 +19,7 @@ [acos (known-procedure/folding 2)] [add1 (known-procedure/folding 2)] [alarm-evt (known-procedure/no-prompt 2)] - [always-evt (known-constant)] + [always-evt (known-authentic)] [andmap (known-procedure -4)] [angle (known-procedure/folding 2)] [append (known-procedure/no-prompt -1)] @@ -552,7 +552,7 @@ [mpair? (known-procedure/pure/folding 2)] [nack-guard-evt (known-procedure/no-prompt 2)] [negative? (known-procedure/folding 2)] - [never-evt (known-constant)] + [never-evt (known-authentic)] [newline (known-procedure 3)] [not (known-procedure/pure/folding 2)] [null (known-literal '())] diff --git a/racket/src/cs/primitive/paramz.ss b/racket/src/cs/primitive/paramz.ss index 012f632745..14c971676a 100644 --- a/racket/src/cs/primitive/paramz.ss +++ b/racket/src/cs/primitive/paramz.ss @@ -1,11 +1,11 @@ (define-primitive-table paramz-table - [break-enabled-key (known-constant)] + [break-enabled-key (known-authentic)] [cache-configuration (known-procedure 4)] [check-for-break (known-procedure 1)] - [exception-handler-key (known-constant)] + [exception-handler-key (known-authentic)] [extend-parameterization (known-procedure -2)] - [parameterization-key (known-constant)] + [parameterization-key (known-authentic)] [reparameterize (known-procedure 2)] [security-guard-check-file (known-procedure 8)] [security-guard-check-file-link (known-procedure 8)] diff --git a/racket/src/cs/rumble.sls b/racket/src/cs/rumble.sls index 5570b560b2..f3ecb28840 100644 --- a/racket/src/cs/rumble.sls +++ b/racket/src/cs/rumble.sls @@ -29,6 +29,7 @@ unsafe-call-with-composable-continuation/no-wind with-continuation-mark + with-continuation-mark* ; not exported to Racket (rename [call-with-immediate-continuation-mark/inline call-with-immediate-continuation-mark] [call-with-immediate-continuation-mark diff --git a/racket/src/cs/rumble/control.ss b/racket/src/cs/rumble/control.ss index 608dbe5575..8868fab8ff 100644 --- a/racket/src/cs/rumble/control.ss +++ b/racket/src/cs/rumble/control.ss @@ -940,6 +940,48 @@ (lambda () body)))))])) +;; Specializations of `with-continuation-mark*` as determined by a mode: +(define-syntax with-continuation-mark* + (lambda (stx) + (syntax-case stx () + [(_ mode key val body) + (case (syntax->datum #'mode) + [(general) + #'(with-continuation-mark key val body)] + [(push) + ;; Assume no mark in place for this frame + #'(let* ([k key] + [v val]) + (call-setting-continuation-attachment + (if (impersonator? k) + (mark-frame-update empty-mark-frame k v) + (cons k v)) + (lambda () + body)))] + [(authentic) + ;; Assume `key` produces an authentic value + #'(let* ([k key] + [v val]) + (call-consuming-continuation-attachment + empty-mark-frame + (lambda (a) + (call-setting-continuation-attachment + (if a + (mark-frame-update a k v) + (cons k v)) + (lambda () + body)))))] + [(push-authentic) + ;; Assume no mark in place, and `key` produces an authentic value + #'(let* ([k key] + [v val]) + (call-setting-continuation-attachment + (cons k v) + (lambda () + body)))] + [else + (#%error 'with-continuation-mark* "unrecognized mode: ~s" #'mode)])]))) + ;; Return a continuation that expects a thunk to resume. That way, we ;; can can an `(end-uninterrupted)` and check for breaks in the ;; destination continuation diff --git a/racket/src/expander/compile/built-in-symbol.rkt b/racket/src/expander/compile/built-in-symbol.rkt index 1c3a1dd33b..237dc7360b 100644 --- a/racket/src/expander/compile/built-in-symbol.rkt +++ b/racket/src/expander/compile/built-in-symbol.rkt @@ -57,6 +57,7 @@ letrec* define $value + with-continuation-mark* pariah variable-set! variable-ref diff --git a/racket/src/schemify/authentic.rkt b/racket/src/schemify/authentic.rkt new file mode 100644 index 0000000000..065d298ca7 --- /dev/null +++ b/racket/src/schemify/authentic.rkt @@ -0,0 +1,36 @@ +#lang racket/base +(require "wrap.rkt" + "match.rkt" + "known.rkt" + "import.rkt" + "mutated-state.rkt") + +(provide authentic-valued?) + +;; Check whether pre-schemifed `v` is known to produce a non-impersonator + +(define (authentic-valued? v knowns prim-knowns imports mutated) + (let authentic-valued? ([v v]) + (match v + [`(quote ,v) + (not (impersonator? v))] + [`,_ + (define u-v (unwrap v)) + (cond + [(symbol? u-v) + (cond + [(not (simple-mutated-state? (hash-ref mutated u-v #f))) + #f] + [(or (hash-ref prim-knowns u-v #f) + (hash-ref-either knowns imports u-v)) + => (lambda (k) + (or (known-authentic? k) + (known-procedure? k) + (and (known-literal? k) + (not (impersonator? (known-literal-value k)))) + (and (known-copy? k) + (authentic-valued? (known-copy-id k)))))] + [else #f])] + [else + ;; Any literal allows as unquoted is authentic + (not (pair? u-v))])]))) diff --git a/racket/src/schemify/interpret.rkt b/racket/src/schemify/interpret.rkt index d8881694bc..bc43d446fd 100644 --- a/racket/src/schemify/interpret.rkt +++ b/racket/src/schemify/interpret.rkt @@ -243,7 +243,7 @@ (compile-expr tst env stack-depth stk-i #f) (add-clears new-then then-stk-i all-clear) (add-clears new-else else-stk-i all-clear))] - [`(with-continuation-mark ,key ,val ,body) + [`(with-continuation-mark* ,mode ,key ,val ,body) (define new-body (compile-expr body env stack-depth stk-i tail?)) (define new-val (compile-expr val env stack-depth stk-i #f)) (vector 'wcm @@ -841,7 +841,8 @@ (letrec ([ok 'ok]) (set! other (call-with-values (lambda () (values 71 (begin0 88 ok))) (lambda (v q) (list q v)))) - (with-continuation-mark + (with-continuation-mark* + general 'x 'cm/x (list (if s s #f) x ok other (f 'vec) (g 'also-vec 'more) diff --git a/racket/src/schemify/jitify.rkt b/racket/src/schemify/jitify.rkt index 31dfcdd3a9..42c1d44172 100644 --- a/racket/src/schemify/jitify.rkt +++ b/racket/src/schemify/jitify.rkt @@ -286,7 +286,7 @@ (values (reannotate v `(if ,new-tst ,new-thn ,new-els)) new-free/els new-lifts/els)] - [`(with-continuation-mark ,key ,val ,body) + [`(with-continuation-mark* ,mode ,key ,val ,body) (define sub-convert-mode (convert-mode-non-tail convert-mode)) (define-values (new-key new-free/key new-lifts/key) (jitify-expr key env mutables free lifts sub-convert-mode #f in-name)) @@ -294,7 +294,7 @@ (jitify-expr val env mutables new-free/key new-lifts/key sub-convert-mode #f in-name)) (define-values (new-body new-free/body new-lifts/body) (jitify-expr body env mutables new-free/val new-lifts/val convert-mode name in-name)) - (values (reannotate v `(with-continuation-mark ,new-key ,new-val ,new-body)) + (values (reannotate v `(with-continuation-mark* ,mode ,new-key ,new-val ,new-body)) new-free/body new-lifts/body)] [`(quote ,_) (values v free lifts)] @@ -651,7 +651,7 @@ (find-mutable env tst (find-mutable env thn (find-mutable env els accum)))] - [`(with-continuation-mark ,key ,val ,body) + [`(with-continuation-mark* ,mode ,key ,val ,body) (find-mutable env key (find-mutable env val (find-mutable env body accum)))] @@ -797,7 +797,7 @@ (record-sizes! tst sizes) (record-sizes! thn sizes) (record-sizes! els sizes))] - [`(with-continuation-mark ,key ,val ,body) + [`(with-continuation-mark* ,mode ,key ,val ,body) (+ 1 (record-sizes! key sizes) (record-sizes! val sizes) diff --git a/racket/src/schemify/known.rkt b/racket/src/schemify/known.rkt index 9bf31eb70a..1862765b7e 100644 --- a/racket/src/schemify/known.rkt +++ b/racket/src/schemify/known.rkt @@ -5,6 +5,7 @@ (provide known-constant known-constant? known-consistent known-consistent? + known-authentic known-authentic? known-copy? known-copy known-copy-id known-literal known-literal? known-literal-value known-procedure known-procedure? known-procedure-arity-mask @@ -46,6 +47,9 @@ ;; being a predicate for a structure type (struct known-consistent () #:prefab #:omit-define-syntaxes #:super struct:known-constant) +;; the value at run time is never an impersonator +(struct known-authentic () #:prefab #:omit-define-syntaxes #:super struct:known-constant) + ;; copy propagation --- use for local bindings or copies of primitives, only (struct known-copy (id) #:prefab #:omit-define-syntaxes #:super struct:known-constant) @@ -77,7 +81,7 @@ ;; procedure that never raises an exception or otherwise captures/escapes the calling context (struct known-procedure/succeeds () #:prefab #:omit-define-syntaxes #:super struct:known-procedure/no-prompt) -;; procedure that accepts any arguments and is functional so that it can be reordered +;; procedure that accepts any arguments, returns a single value, and is functional so that it can be reordered (struct known-procedure/pure () #:prefab #:omit-define-syntaxes #:super struct:known-procedure/succeeds) ;; pure and folding: diff --git a/racket/src/schemify/lift.rkt b/racket/src/schemify/lift.rkt index 5d26efa49f..acfcdd3f86 100644 --- a/racket/src/schemify/lift.rkt +++ b/racket/src/schemify/lift.rkt @@ -102,7 +102,7 @@ (lift-in-expr? v))] [`(if ,tst ,thn ,els) (or (lift-in-expr? tst) (lift-in-expr? thn) (lift-in-expr? els))] - [`(with-continuation-mark ,key ,val ,body) + [`(with-continuation-mark* ,_ ,key ,val ,body) (or (lift-in-expr? key) (lift-in-expr? val) (lift-in-expr? body))] [`(quote ,_) #f] [`(#%variable-reference . ,_) (error 'internal-error "unexpected variable reference")] @@ -143,7 +143,7 @@ [`(quote . ,_) #f] [`(if ,tst ,thn ,els) (or (lift? tst) (lift? thn) (lift? els))] - [`(with-continuation-mark ,key ,val ,body) + [`(with-continuation-mark* ,_ ,key ,val ,body) (or (lift? key) (lift? val) (lift? body))] [`(set! ,_ ,rhs) (lift? rhs)] [`(#%variable-reference) #f] @@ -229,10 +229,12 @@ (reannotate v `(if ,(lift-in-expr tst) ,(lift-in-expr thn) ,(lift-in-expr els)))] - [`(with-continuation-mark ,key ,val ,body) - (reannotate v `(with-continuation-mark ,(lift-in-expr key) - ,(lift-in-expr val) - ,(lift-in-expr body)))] + [`(with-continuation-mark* ,mode ,key ,val ,body) + (reannotate v `(with-continuation-mark* + ,mode + ,(lift-in-expr key) + ,(lift-in-expr val) + ,(lift-in-expr body)))] [`(quote ,_) v] [`(#%variable-reference . ,_) (error 'internal-error "unexpected variable reference")] [`(set! ,id ,rhs) @@ -310,7 +312,7 @@ [frees+binds (compute-lifts! thn frees+binds lifts locals)] [frees+binds (compute-lifts! els frees+binds lifts locals)]) frees+binds)] - [`(with-continuation-mark ,key ,val ,body) + [`(with-continuation-mark* ,_ ,key ,val ,body) (let* ([frees+binds (compute-lifts! key frees+binds lifts locals)] [frees+binds (compute-lifts! val frees+binds lifts locals)] [frees+binds (compute-lifts! body frees+binds lifts locals)]) @@ -519,8 +521,8 @@ [`(quote . ,_) v] [`(if ,tst ,thn ,els) (reannotate v `(if ,(convert tst) ,(convert thn) ,(convert els)))] - [`(with-continuation-mark ,key ,val ,body) - (reannotate v `(with-continuation-mark ,(convert key) ,(convert val) ,(convert body)))] + [`(with-continuation-mark* ,mode ,key ,val ,body) + (reannotate v `(with-continuation-mark* ,mode ,(convert key) ,(convert val) ,(convert body)))] [`(set! ,id ,rhs) (define info (and (hash-ref lifts (unwrap id) #f))) (cond diff --git a/racket/src/schemify/optimize.rkt b/racket/src/schemify/optimize.rkt index 037c6948b0..85b4719b83 100644 --- a/racket/src/schemify/optimize.rkt +++ b/racket/src/schemify/optimize.rkt @@ -21,6 +21,8 @@ (if (literal? t) (if (unwrap t) e1 e2) v)] + [`(begin (quote ,_) ,e . ,es) ; avoid `begin` that looks like it provides a name + (optimize (reannotate v `(begin ,e . ,es)) prim-knowns primitives knowns imports mutated)] [`(not ,t) (if (literal? t) `,(not (unwrap t)) @@ -76,8 +78,8 @@ ;; ---------------------------------------- -;; Recursive optimization --- useful when not fused with schemify, -;; such as for an initial optimization pass on a definition of a +;; Recursive optimization on pre-schemified --- useful when not fused with +;; schemify, such as for an initial optimization pass on a definition of a ;; function that can be inlined (where converting away ;; `variable-reference-from-unsafe?` is particularly important) diff --git a/racket/src/schemify/schemify.rkt b/racket/src/schemify/schemify.rkt index 291d8aeef5..28b8c05428 100644 --- a/racket/src/schemify/schemify.rkt +++ b/racket/src/schemify/schemify.rkt @@ -21,7 +21,9 @@ "letrec.rkt" "infer-name.rkt" "ptr-ref-set.rkt" - "literal.rkt") + "literal.rkt" + "authentic.rkt" + "single-valued.rkt") (provide schemify-linklet schemify-body) @@ -428,8 +430,9 @@ ;; effectively canceled with a mapping in `knowns`. (define (schemify v prim-knowns primitives knowns mutated imports exports simples allow-set!-undefined? add-import! for-cify? for-jitify? unsafe-mode? allow-inline? no-prompt?) - (let schemify/knowns ([knowns knowns] [inline-fuel init-inline-fuel] [v v]) - (define (schemify v) + ;; `wcm-state` is one of: 'tail (= unknown), 'fresh (= no marks), or 'marked (= some marks) + (let schemify/knowns ([knowns knowns] [inline-fuel init-inline-fuel] [wcm-state 'tail] [v v]) + (define (schemify v wcm-state) (define s-v (reannotate v @@ -437,13 +440,13 @@ [`(lambda ,formals ,body ...) (infer-procedure-name v - `(lambda ,formals ,@(schemify-body body)))] + `(lambda ,formals ,@(schemify-body body 'tail)))] [`(case-lambda [,formalss ,bodys ...] ...) (infer-procedure-name v `(case-lambda ,@(for/list ([formals (in-list formalss)] [body (in-list bodys)]) - `[,formals ,@(schemify-body body)])))] + `[,formals ,@(schemify-body body 'tail)])))] [`(define-values (,struct:s ,make-s ,s? ,acc/muts ...) (let-values (((,struct: ,make ,?1 ,-ref ,-set!) ,mk)) (values ,struct:2 @@ -453,20 +456,20 @@ #:guard (not (or for-jitify? for-cify?)) (define new-seq (struct-convert v prim-knowns knowns imports mutated - (lambda (v knowns) (schemify/knowns knowns inline-fuel v)) no-prompt?)) + (lambda (v knowns) (schemify/knowns knowns inline-fuel 'fresh v)) no-prompt?)) (or new-seq (match v [`(,_ ,ids ,rhs) - `(define-values ,ids ,(schemify rhs))]))] + `(define-values ,ids ,(schemify rhs 'fresh))]))] [`(define-values (,id) ,rhs) - `(define ,id ,(schemify rhs))] + `(define ,id ,(schemify rhs 'fresh))] [`(define-values ,ids ,rhs) - `(define-values ,ids ,(schemify rhs))] + `(define-values ,ids ,(schemify rhs 'fresh))] [`(quote ,_) v] [`(let-values () ,body) - (schemify body)] + (schemify body wcm-state)] [`(let-values () ,bodys ...) - (schemify `(begin . ,bodys))] + (schemify `(begin . ,bodys) wcm-state)] [`(let-values ([(,ids) ,rhss] ...) ,bodys ...) (define new-knowns (for/fold ([knowns knowns]) ([id (in-list ids)] @@ -487,29 +490,29 @@ (for/list ([id (in-list ids)] [rhs (in-list rhss)] #:unless (merely-a-copy? id)) - (schemify rhs)) + (schemify rhs 'fresh)) (for/list ([body (in-list bodys)]) - (schemify/knowns new-knowns inline-fuel body)) + (schemify/knowns new-knowns inline-fuel wcm-state body)) prim-knowns knowns imports mutated simples)] [`(let-values ([() (begin ,rhss ... (values))]) ,bodys ...) - `(begin ,@(schemify-body rhss) ,@(schemify-body bodys))] + `(begin ,@(schemify-body rhss 'fresh) ,@(schemify-body bodys wcm-state))] [`(let-values ([,idss ,rhss] ...) ,bodys ...) (or (struct-convert-local v prim-knowns knowns imports mutated simples - (lambda (v knowns) (schemify/knowns knowns inline-fuel v)) + (lambda (v knowns) (schemify/knowns knowns inline-fuel 'fresh v)) #:unsafe-mode? unsafe-mode?) (left-to-right/let-values idss (for/list ([rhs (in-list rhss)]) - (schemify rhs)) - (schemify-body bodys) + (schemify rhs 'fresh)) + (schemify-body bodys wcm-state) mutated for-cify?))] [`(letrec-values () ,bodys ...) - (schemify `(begin . ,bodys))] + (schemify `(begin . ,bodys) wcm-state)] [`(letrec-values ([() (values)]) ,bodys ...) - (schemify `(begin . ,bodys))] + (schemify `(begin . ,bodys) wcm-state)] [`(letrec-values ([(,id) (values ,rhs)]) ,bodys ...) ;; special case of splitable values: - (schemify `(letrec-values ([(,id) ,rhs]) . ,bodys))] + (schemify `(letrec-values ([(,id) ,rhs]) . ,bodys) wcm-state)] [`(letrec-values ([(,ids) ,rhss] ...) ,bodys ...) (define-values (rhs-knowns body-knowns) (for/fold ([rhs-knowns knowns] [body-knowns knowns]) ([id (in-list ids)] @@ -525,18 +528,19 @@ ids mutated for-cify? `(letrec* ,(for/list ([id (in-list ids)] [rhs (in-list rhss)]) - `[,id ,(schemify/knowns rhs-knowns inline-fuel rhs)]) + `[,id ,(schemify/knowns rhs-knowns inline-fuel 'fresh rhs)]) ,@(for/list ([body (in-list bodys)]) - (schemify/knowns body-knowns inline-fuel body))))] + (schemify/knowns body-knowns inline-fuel wcm-state body))))] [`(letrec-values ([,idss ,rhss] ...) ,bodys ...) (cond [(struct-convert-local v #:letrec? #t prim-knowns knowns imports mutated simples - (lambda (v knowns) (schemify/knowns knowns inline-fuel v)) + (lambda (v knowns) (schemify/knowns knowns inline-fuel 'fresh v)) #:unsafe-mode? unsafe-mode?) => (lambda (form) form)] [(letrec-splitable-values-binding? idss rhss) (schemify - (letrec-split-values-binding idss rhss bodys))] + (letrec-split-values-binding idss rhss bodys) + wcm-state)] [else ;; Convert ;; (letrec*-values ([(id ...) rhs] ...) ....) @@ -551,7 +555,7 @@ append (for/list ([ids (in-wrap-list idss)] [rhs (in-list rhss)]) - (let ([rhs (schemify rhs)]) + (let ([rhs (schemify rhs 'fresh)]) (cond [(null? ids) `([,(gensym "lr") @@ -564,21 +568,41 @@ ,@(for/list ([id (in-list ids)] [pos (in-naturals)]) `[,id (unsafe-vector*-ref ,lr ,pos)]))])))) - ,@(schemify-body bodys)))])] + ,@(schemify-body bodys wcm-state)))])] [`(if ,tst ,thn ,els) - `(if ,(schemify tst) ,(schemify thn) ,(schemify els))] + `(if ,(schemify tst 'fresh) ,(schemify thn wcm-state) ,(schemify els wcm-state))] [`(with-continuation-mark ,key ,val ,body) - `(with-continuation-mark ,(schemify key) ,(schemify val) ,(schemify body))] + (define s-key (schemify key 'fresh)) + (define s-val (schemify val 'fresh)) + (define s-body (schemify body 'marked)) + (define authentic-key? + (authentic-valued? key knowns prim-knowns imports mutated)) + (cond + [(and authentic-key? + (simple? s-body prim-knowns knowns imports mutated simples)) + `(begin ,(ensure-single-valued s-key knowns prim-knowns imports mutated) + ,(ensure-single-valued s-val knowns prim-knowns imports mutated) + ,s-body)] + [for-cify? + `(with-continuation-mark ,s-key ,s-val ,s-body)] + [else + (define mode + (case wcm-state + [(fresh) (if authentic-key? 'push-authentic 'push)] + [else (if authentic-key? 'authentic 'general)])) + `(with-continuation-mark* ,mode ,s-key ,s-val ,s-body)])] [`(begin ,exp) - (schemify exp)] + (schemify exp wcm-state)] [`(begin ,exps ...) - `(begin . ,(schemify-body exps))] - [`(begin0 ,exps ...) - `(begin0 . ,(schemify-body exps))] + `(begin . ,(schemify-body exps wcm-state))] + [`(begin0 ,exp) + (schemify exp wcm-state)] + [`(begin0 ,exp ,exps ...) + `(begin0 ,(schemify exp 'fresh) . ,(schemify-body exps 'fresh))] [`(set! ,id ,rhs) (define int-id (unwrap id)) (define ex (hash-ref exports int-id #f)) - (define new-rhs (schemify rhs)) + (define new-rhs (schemify rhs 'fresh)) (define state (hash-ref mutated int-id #f)) (cond [ex @@ -612,7 +636,7 @@ [(known-constant? (import-lookup im)) #t] [else ;; Not statically known - `(variable-reference-constant? ,(schemify `(#%variable-reference ,id)))])])] + `(variable-reference-constant? ,(schemify `(#%variable-reference ,id) 'fresh))])])] [`(variable-reference-from-unsafe? (#%variable-reference)) unsafe-mode?] [`(#%variable-reference) @@ -634,8 +658,8 @@ [(hash-ref prim-knowns u #f) u] ; assuming that `mutable` and `constant` are not primitives [else 'constant])))] [`(equal? ,exp1 ,exp2) - (let ([exp1 (schemify exp1)] - [exp2 (schemify exp2)]) + (let ([exp1 (schemify exp1 'fresh)] + [exp2 (schemify exp2 'fresh)]) (cond [(or (equal-implies-eq? exp1) (equal-implies-eq? exp2)) `(eq? ,exp1 ,exp2)] @@ -650,17 +674,17 @@ (cond [(and (lambda? generator) (lambda? receiver)) - `(call-with-values ,(schemify generator) ,(schemify receiver))] + `(call-with-values ,(schemify generator 'fresh) ,(schemify receiver 'fresh))] [else (left-to-right/app (if for-cify? 'call-with-values '#%call-with-values) - (list (schemify generator) (schemify receiver)) + (list (schemify generator 'fresh) (schemify receiver 'fresh)) #t for-cify? prim-knowns knowns imports mutated simples)])] [`(single-flonum-available?) ;; Fold to a boolean to allow earlier simplification for-cify?] [`((letrec-values ,binds ,rator) ,rands ...) - (schemify `(letrec-values ,binds (,rator . ,rands)))] + (schemify `(letrec-values ,binds (,rator . ,rands)) wcm-state)] [`(,rator ,exps ...) (define (left-left-lambda-convert rator inline-fuel) (match rator @@ -672,6 +696,7 @@ (and (wrap-null? args) (schemify/knowns knowns inline-fuel + wcm-state `(let-values ,(reverse binds) . ,bodys)))] [(null? args) #f] [(not (wrap-pair? formal-args)) @@ -719,7 +744,7 @@ (cond [type-id (define tmp (maybe-tmp (car args) 'v)) - (define sel `(if (unsafe-struct? ,tmp ,(schemify type-id)) + (define sel `(if (unsafe-struct? ,tmp ,(schemify type-id 'fresh)) (unsafe-struct*-ref ,tmp ,(known-field-accessor-pos k)) (,s-rator ,tmp))) (wrap-tmp tmp (car args) @@ -735,7 +760,7 @@ [type-id (define tmp (maybe-tmp (car args) 'v)) (define tmp-rhs (maybe-tmp (cadr args) 'rhs)) - (define mut `(if (unsafe-struct? ,tmp ,(schemify type-id)) + (define mut `(if (unsafe-struct? ,tmp ,(schemify type-id 'fresh)) (unsafe-struct*-set! ,tmp ,(known-field-mutator-pos k) ,tmp-rhs) (,s-rator ,tmp ,tmp-rhs))) (wrap-tmp tmp (car args) @@ -745,8 +770,8 @@ (or (left-left-lambda-convert rator inline-fuel) (and (positive? inline-fuel) (inline-rator)) - (let ([s-rator (schemify rator)] - [args (schemify-body exps)] + (let ([s-rator (schemify rator 'fresh)] + [args (schemify-body exps 'fresh)] [u-rator (unwrap rator)]) (define-values (k im) (find-known+import u-rator prim-knowns knowns imports mutated)) (cond @@ -820,7 +845,7 @@ (cond [(and (known-copy? k) (simple-mutated-state? (hash-ref mutated u-v #f))) - (schemify (known-copy-id k))] + (schemify (known-copy-id k) wcm-state)] [else v]))] [(and (too-early-mutated-state? state) (not for-cify?)) @@ -830,8 +855,13 @@ [else v])]))]))) (optimize s-v prim-knowns primitives knowns imports mutated)) - (define (schemify-body l) - (for/list ([e (in-list l)]) - (schemify e))) + (define (schemify-body l wcm-state) + (cond + [(null? l) null] + [(null? (cdr l)) + (list (schemify (car l) wcm-state))] + [else + (cons (schemify (car l) 'fresh) + (schemify-body (cdr l) wcm-state))])) - (schemify v))) + (schemify v 'fresh))) diff --git a/racket/src/schemify/serialize.rkt b/racket/src/schemify/serialize.rkt index 0779aa9e40..9fccdf4fd2 100644 --- a/racket/src/schemify/serialize.rkt +++ b/racket/src/schemify/serialize.rkt @@ -64,8 +64,8 @@ ,@(convert-body bodys))] [`(if ,tst ,thn ,els) `(if ,(convert tst) ,(convert thn) ,(convert els))] - [`(with-continuation-mark ,key ,val ,body) - `(with-continuation-mark ,(convert key) ,(convert val) ,(convert body))] + [`(with-continuation-mark* ,mode ,key ,val ,body) + `(with-continuation-mark* ,mode ,(convert key) ,(convert val) ,(convert body))] [`(begin ,exps ...) `(begin . ,(convert-body exps))] [`(begin0 ,exps ...) @@ -120,7 +120,7 @@ (or (convert-any? tst) (convert-any? thn) (convert-any? els))] - [`(with-continuation-mark ,key ,val ,body) + [`(with-continuation-mark* ,_ ,key ,val ,body) (or (convert-any? key) (convert-any? val) (convert-any? body))] diff --git a/racket/src/schemify/single-valued.rkt b/racket/src/schemify/single-valued.rkt new file mode 100644 index 0000000000..b179872290 --- /dev/null +++ b/racket/src/schemify/single-valued.rkt @@ -0,0 +1,25 @@ +#lang racket/base +(require "match.rkt" + "wrap.rkt" + "known.rkt" + "import.rkt" + "mutated-state.rkt") + +(provide ensure-single-valued) + +(define (ensure-single-valued v knowns prim-knowns imports mutated) + (match v + [`(quote ,_) v] + [`(lambda . ,_) v] + [`(case-lambda . ,_) v] + [`(,proc-or-form . ,_) + (define u (unwrap proc-or-form)) + (cond + [(and (symbol? u) + (simple-mutated-state? (hash-ref mutated u #f)) + (let ([k (or (hash-ref prim-knowns u #f) + (hash-ref-either knowns imports u))]) + (known-procedure/pure? k))) + v] + [else `($value ,v)])] + [`,_ v])) diff --git a/racket/src/schemify/size.rkt b/racket/src/schemify/size.rkt index 458e10e8ba..6cdbe71a80 100644 --- a/racket/src/schemify/size.rkt +++ b/racket/src/schemify/size.rkt @@ -32,7 +32,7 @@ (body-leftover-size (cons rhss body) (sub1 size))] [`(if ,tst ,thn ,els) (leftover-size els (leftover-size thn (leftover-size tst (sub1 size))))] - [`(with-continuation-mark ,key ,val ,body) + [`(with-continuation-mark* ,_ ,key ,val ,body) (leftover-size body (leftover-size val (leftover-size key (sub1 size))))] [`(begin0 . ,body) (body-leftover-size body (sub1 size))] diff --git a/racket/src/schemify/xify.rkt b/racket/src/schemify/xify.rkt index d0a0e98a36..0955fc4e4d 100644 --- a/racket/src/schemify/xify.rkt +++ b/racket/src/schemify/xify.rkt @@ -32,8 +32,8 @@ `(begin . ,(xify-body body env))] [`(if ,tst ,thn ,els) `(if ,(xify tst env) ,(xify thn env) ,(xify els env))] - [`(with-continuation-mark ,key ,val ,body) - `(with-continuation-mark ,(xify key env) ,(xify val env) ,(xify body env))] + [`(with-continuation-mark* ,mode ,key ,val ,body) + `(with-continuation-mark* ,mode ,(xify key env) ,(xify val env) ,(xify body env))] [`(set! ,id ,rhs) `(set! ,(xify id env) ,(xify rhs env))] ;; Catch-all for other forms, which we can treat like applications