From 43ba15ca389e99dc9825284daa6cb8562ac1d50c Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Thu, 18 Jul 2019 11:56:19 -0600 Subject: [PATCH] expander: fix performance problem with `datum->syntax` In a pattern like (let loop ([l l]) (define v (syntax-e l)) (cond [(null? v) 'done] [else (loop (datum->syntax #f (cdr v)))])) the running time was O(N^2) for a list of syntax objects of length N. That pattern is relevant for traversals that use `syntax-case` like (let loop ([l l]) (syntax-case l () [(a . b) (loop #'b)] [() 'done])) Avoid bad behavior by recording in an weak hash table certain pairs that were previously been produced by `datum->syntax` internally so that they can be used as-is. --- .../tests/racket/stress/datum-to-syntax.rkt | 19 ++ racket/src/expander/main.rkt | 2 + racket/src/expander/syntax/datum-map.rkt | 28 ++- racket/src/expander/syntax/syntax.rkt | 29 ++- racket/src/racket/src/startup.inc | 225 ++++++++++++------ 5 files changed, 213 insertions(+), 90 deletions(-) create mode 100644 pkgs/racket-test/tests/racket/stress/datum-to-syntax.rkt diff --git a/pkgs/racket-test/tests/racket/stress/datum-to-syntax.rkt b/pkgs/racket-test/tests/racket/stress/datum-to-syntax.rkt new file mode 100644 index 0000000000..4e6ddd9f0d --- /dev/null +++ b/pkgs/racket-test/tests/racket/stress/datum-to-syntax.rkt @@ -0,0 +1,19 @@ +#lang racket/base + +(define l (datum->syntax + #f + (for/list ([i 10000]) + 'x))) + + +(let ([now (current-inexact-milliseconds)]) + (let loop ([l l]) + (define v (syntax-e l)) + (cond + [(null? v) 'done] + [else + (loop (datum->syntax #f (cdr v)))])) + (define t (- (current-inexact-milliseconds) now)) + (unless (t . < . 1000.0) + (error 'datum->syntax-stress "took too long: ~a" t))) + diff --git a/racket/src/expander/main.rkt b/racket/src/expander/main.rkt index eb7d420485..5e81da2782 100644 --- a/racket/src/expander/main.rkt +++ b/racket/src/expander/main.rkt @@ -34,6 +34,7 @@ compiled-expression-recompile) (only-in racket/private/config find-main-config) (only-in "syntax/cache.rkt" cache-place-init!) + (only-in "syntax/syntax.rkt" syntax-place-init!) (only-in "syntax/scope.rkt" scope-place-init!) (only-in "eval/module-cache.rkt" module-cache-place-init!) (only-in "common/performance.rkt" performance-place-init!) @@ -207,6 +208,7 @@ (datum->syntax core-stx s)) (define (expander-place-init!) + (syntax-place-init!) (scope-place-init!) (cache-place-init!) (core-place-init!) diff --git a/racket/src/expander/syntax/datum-map.rkt b/racket/src/expander/syntax/datum-map.rkt index 845b3cb0a1..f71fc17b49 100644 --- a/racket/src/expander/syntax/datum-map.rkt +++ b/racket/src/expander/syntax/datum-map.rkt @@ -11,7 +11,9 @@ ;; ;; `(f tail? d)` is called on each datum `d`, where `tail?` ;; indicates that the value is a pair/null in a `cdr` --- so that it -;; doesn't need to be wrapped for `datum->syntax`, for example +;; doesn't need to be wrapped for `datum->syntax`, for example; +;; the `tail?` argument is actually #f or a fixnum for a lower bound +;; on `cdr`s that have been taken ;; ;; `gf` is like `f`, but `gf` is used when the argument might be ;; syntax; if `gf` is provided, `f` can assume that its argument @@ -21,28 +23,32 @@ ;; hash table, and cycle checking is enabled; when a cycle is ;; discovered, the procedure attached to 'cycle-fail in the initial ;; table is called +;; +;; If a `known-pairs` argument is provided, then it should be an +;; `eq?`-based hash table to map pairs that can be returned as-is +;; in a `tail?` position ;; The inline version uses `f` only in an application position to ;; help avoid allocating a closure. It also covers only the most common ;; cases, defering to the general (not inlined) function for other cases. -(define-inline (datum-map s f [gf f] [seen #f]) +(define-inline (datum-map s f [gf f] [seen #f] [known-pairs #f]) (let loop ([tail? #f] [s s] [prev-depth 0]) (define depth (fx+ 1 prev-depth)) ; avoid cycle-checking overhead for shallow cases (cond [(and seen (depth . fx> . 32)) - (datum-map-slow tail? s (lambda (tail? s) (gf tail? s)) seen)] + (datum-map-slow tail? s (lambda (tail? s) (gf tail? s)) seen known-pairs)] [(null? s) (f tail? s)] [(pair? s) (f tail? (cons (loop #f (car s) depth) - (loop #t (cdr s) depth)))] + (loop 1 (cdr s) depth)))] [(symbol? s) (f #f s)] [(boolean? s) (f #f s)] [(number? s) (f #f s)] [(or (vector? s) (box? s) (prefab-struct-key s) (hash? s)) - (datum-map-slow tail? s (lambda (tail? s) (gf tail? s)) seen)] + (datum-map-slow tail? s (lambda (tail? s) (gf tail? s)) seen known-pairs)] [else (gf #f s)]))) -(define (datum-map-slow tail? s f seen) +(define (datum-map-slow tail? s f seen known-pairs) (let loop ([tail? tail?] [s s] [prev-seen seen]) (define seen (cond @@ -55,8 +61,14 @@ (cond [(null? s) (f tail? s)] [(pair? s) - (f tail? (cons (loop #f (car s) seen) - (loop #t (cdr s) seen)))] + (cond + [(and known-pairs + tail? + (hash-ref known-pairs s #f)) + s] + [else + (f tail? (cons (loop #f (car s) seen) + (loop (if tail? (fx+ 1 tail?) 1) (cdr s) seen)))])] [(or (symbol? s) (boolean? s) (number? s)) (f #f s)] [(vector? s) diff --git a/racket/src/expander/syntax/syntax.rkt b/racket/src/expander/syntax/syntax.rkt index 8610435ff3..b63a6e789f 100644 --- a/racket/src/expander/syntax/syntax.rkt +++ b/racket/src/expander/syntax/syntax.rkt @@ -1,5 +1,7 @@ #lang racket/base -(require "../compile/serialize-property.rkt" +(require racket/private/place-local + racket/fixnum + "../compile/serialize-property.rkt" "../compile/serialize-state.rkt" "../common/set.rkt" "../common/inline.rkt" @@ -30,7 +32,9 @@ deserialize-syntax deserialize-datum->syntax - current-arm-inspectors) + current-arm-inspectors + + syntax-place-init!) (struct syntax ([content #:mutable] ; datum and nested syntax objects; mutated for lazy propagation scopes ; scopes that apply at all phases @@ -186,6 +190,8 @@ (define (syntax->datum s) (syntax-map s (lambda (tail? x) x) (lambda (s d) d) syntax-content)) +(define-place-local known-syntax-pairs (make-weak-hasheq)) + (define (datum->syntax stx-c s [stx-l #f] [stx-p #f]) (cond [(syntax? s) s] @@ -212,9 +218,16 @@ (weaker-inspector insp (syntax-inspector stx-c))))) (define result-s (non-syntax-map s - (lambda (tail? x) (if tail? x (wrap x))) + (lambda (tail? x) (cond + [tail? + (when (and (fx> tail? 32) + (fx= 0 (fxand tail? (fx- tail? 1)))) + (hash-set! known-syntax-pairs x #t)) + x] + [else (wrap x)])) (lambda (s) s) - disallow-cycles)) + disallow-cycles + known-syntax-pairs)) (if (and stx-p (not (eq? (syntax-props stx-p) empty-props))) (struct-copy syntax result-s [props (syntax-props stx-p)]) @@ -248,14 +261,15 @@ ;; when a syntax object is found, it is just passed to `s->` --- so there's ;; no `d->s` or `s-e`, since they would not be called -(define-inline (non-syntax-map s f [s-> (lambda (x) x)] [seen #f]) +(define-inline (non-syntax-map s f [s-> (lambda (x) x)] [seen #f] [known-pairs #f]) (datum-map s f (lambda (tail? v) (cond [(syntax? v) (s-> v)] [else (f tail? v)])) - seen)) + seen + known-pairs)) (define disallow-cycles (hasheq 'cycle-fail @@ -264,6 +278,9 @@ "cannot create syntax from cyclic datum" "datum" s)))) +(define (syntax-place-init!) + (set! known-syntax-pairs (make-weak-hasheq))) + ;; ---------------------------------------- ;; When serializing syntax objects, let nested objects know the diff --git a/racket/src/racket/src/startup.inc b/racket/src/racket/src/startup.inc index b99e967733..d6c081253c 100644 --- a/racket/src/racket/src/startup.inc +++ b/racket/src/racket/src/startup.inc @@ -2755,7 +2755,7 @@ static const char *startup_source = "(define-values(end-atomic)(lambda()(begin(unsafe-end-atomic))))" "(define-values(start-breakable-atomic)(lambda()(begin(unsafe-start-breakable-atomic))))" "(define-values(end-breakable-atomic)(lambda()(begin(unsafe-end-breakable-atomic))))" -"(define-values(cell.1$9)(unsafe-make-place-local #f))" +"(define-values(cell.1$10)(unsafe-make-place-local #f))" "(define-values" "(entered-err-string-handler)" "(lambda(s_0 n_0)(begin(call-as-nonatomic(lambda()((error-value->string-handler) s_0 n_0))))))" @@ -2772,7 +2772,7 @@ static const char *startup_source = "(if(if(procedure? f_0)(procedure-arity-includes? f_0 0) #f)" "(void)" " (let-values () (raise-type-error 'call-as-atomic \"procedure (arity 0)\" f_0)))" -"(if(eq?(unsafe-place-local-ref cell.1$9)(current-thread))" +"(if(eq?(unsafe-place-local-ref cell.1$10)(current-thread))" "(let-values()" "(dynamic-wind" "(lambda()" @@ -2791,7 +2791,7 @@ static const char *startup_source = "(call-with-continuation-prompt" "(lambda()" "(dynamic-wind" -"(lambda()(begin(start-breakable-atomic)(unsafe-place-local-set! cell.1$9(current-thread))))" +"(lambda()(begin(start-breakable-atomic)(unsafe-place-local-set! cell.1$10(current-thread))))" "(lambda()" "(begin" "(unsafe-place-local-set! cell.2$5(current-parameterization))" @@ -2817,7 +2817,7 @@ static const char *startup_source = " f_0))))))))" "(lambda()" "(begin" -"(unsafe-place-local-set! cell.1$9 #f)" +"(unsafe-place-local-set! cell.1$10 #f)" "(unsafe-place-local-set! cell.2$5 #f)" "(unsafe-place-local-set! cell.3$2 #f)" "(end-breakable-atomic)))))" @@ -2831,7 +2831,7 @@ static const char *startup_source = "(if(if(procedure? f_0)(procedure-arity-includes? f_0 0) #f)" "(void)" " (let-values () (raise-type-error 'call-as-nonatomic \"procedure (arity 0)\" f_0)))" -"(if(eq?(unsafe-place-local-ref cell.1$9)(current-thread))" +"(if(eq?(unsafe-place-local-ref cell.1$10)(current-thread))" "(void)" " (let-values () (error 'call-as-nonatomic \"not in atomic area for ~e\" f_0)))" "(let-values(((paramz_0)(unsafe-place-local-ref cell.2$5))" @@ -2849,7 +2849,7 @@ static const char *startup_source = "(dynamic-wind" "(lambda()" "(begin" -"(unsafe-place-local-set! cell.1$9 #f)" +"(unsafe-place-local-set! cell.1$10 #f)" "(unsafe-place-local-set! cell.4$2 0)" "(end-breakable-atomic)" "((letrec-values(((loop_0)" @@ -2877,7 +2877,7 @@ static const char *startup_source = " loop_0)" " extra-depth_0)" "(unsafe-place-local-set! cell.4$2 extra-depth_0)" -"(unsafe-place-local-set! cell.1$9(current-thread)))))))))))))))" +"(unsafe-place-local-set! cell.1$10(current-thread)))))))))))))))" "(define-values(prop:serialize serialize? serialize-ref)(make-struct-type-property 'serialize))" "(define-values" "(prop:serialize-fill! serialize-fill!? serialize-fill!-ref)" @@ -2892,7 +2892,7 @@ static const char *startup_source = "(define-values" "(log-performance?)" " (if (environment-variables-ref (current-environment-variables) #\"PLT_EXPANDER_TIMES\") #t #f))" -"(define-values(cell.1$8)(unsafe-make-place-local #f))" +"(define-values(cell.1$9)(unsafe-make-place-local #f))" "(define-values(cell.2$4)(unsafe-make-place-local(make-hasheq)))" "(define-values(performance-place-init!)(lambda()(begin(unsafe-place-local-set! cell.2$4(make-hasheq)))))" "(define-values" @@ -2945,10 +2945,10 @@ static const char *startup_source = "(lambda path_0" "(begin" "(unsafe-place-local-set!" -" cell.1$8" +" cell.1$9" "(cons" "(region1.1" -"(if(unsafe-place-local-ref cell.1$8)" +"(if(unsafe-place-local-ref cell.1$9)" "((letrec-values(((loop_0)" "(lambda(path_1 enclosing-path_0)" "(begin" @@ -2964,22 +2964,22 @@ static const char *startup_source = "(if(pair? enclosing-path_0)(cdr enclosing-path_0) null))))))))" " loop_0)" " path_0" -"(region-path(car(unsafe-place-local-ref cell.1$8))))" +"(region-path(car(unsafe-place-local-ref cell.1$9))))" " path_0)" "(current-inexact-milliseconds)" "(current-memory-use 'cumulative)" " 0.0" " 0)" -"(unsafe-place-local-ref cell.1$8))))))" +"(unsafe-place-local-ref cell.1$9))))))" "(define-values" "(end-performance-region)" "(lambda()" "(begin" "(let-values(((now_0)(current-inexact-milliseconds)))" "(let-values(((now-memory_0)(current-memory-use 'cumulative)))" -"(let-values(((r_0)(car(unsafe-place-local-ref cell.1$8))))" +"(let-values(((r_0)(car(unsafe-place-local-ref cell.1$9))))" "(let-values((()" -"(begin(unsafe-place-local-set! cell.1$8(cdr(unsafe-place-local-ref cell.1$8)))(values))))" +"(begin(unsafe-place-local-set! cell.1$9(cdr(unsafe-place-local-ref cell.1$9)))(values))))" "(let-values(((full-delta_0)(- now_0(region-start r_0))))" "(let-values(((delta_0)(- full-delta_0(region-as-nested r_0))))" "(let-values(((full-delta-memory_0)(- now-memory_0(region-start-memory r_0))))" @@ -3017,16 +3017,16 @@ static const char *startup_source = " loop_0)" "(unsafe-place-local-ref cell.2$4)" "(region-path r_0))" -"(if(unsafe-place-local-ref cell.1$8)" +"(if(unsafe-place-local-ref cell.1$9)" "(let-values()" "(begin" "(set-region-as-nested!" -"(car(unsafe-place-local-ref cell.1$8))" -"(+(region-as-nested(car(unsafe-place-local-ref cell.1$8))) full-delta_0))" +"(car(unsafe-place-local-ref cell.1$9))" +"(+(region-as-nested(car(unsafe-place-local-ref cell.1$9))) full-delta_0))" "(set-region-as-nested-memory!" -"(car(unsafe-place-local-ref cell.1$8))" +"(car(unsafe-place-local-ref cell.1$9))" "(+" -"(region-as-nested-memory(car(unsafe-place-local-ref cell.1$8)))" +"(region-as-nested-memory(car(unsafe-place-local-ref cell.1$9)))" " full-delta-memory_0))))" "(void))))))))))))))" "(call-with-values" @@ -4784,9 +4784,9 @@ static const char *startup_source = "(make-self-module-path-index" "(let-values(((name25_0) name_0)((temp26_0)(if enclosing_0(1/module-path-index-resolve enclosing_0) #f)))" "(build-module-name16.1 unsafe-undefined name25_0 temp26_0))))))" -"(define-values(cell.1$7)(unsafe-make-place-local(make-weak-hash)))" +"(define-values(cell.1$8)(unsafe-make-place-local(make-weak-hash)))" "(define-values(generic-module-name) '|expanded module|)" -"(define-values(module-path-place-init!)(lambda()(begin(unsafe-place-local-set! cell.1$7(make-weak-hash)))))" +"(define-values(module-path-place-init!)(lambda()(begin(unsafe-place-local-set! cell.1$8(make-weak-hash)))))" "(define-values" "(make-generic-self-module-path-index)" "(lambda(self_0)" @@ -4796,12 +4796,12 @@ static const char *startup_source = "(start-atomic)" "(begin0" "(let-values(((or-part_0)" -"(let-values(((e_0)(hash-ref(unsafe-place-local-ref cell.1$7) r_0 #f)))" +"(let-values(((e_0)(hash-ref(unsafe-place-local-ref cell.1$8) r_0 #f)))" "(if e_0(ephemeron-value e_0) #f))))" "(if or-part_0" " or-part_0" "(let-values(((mpi_0)(module-path-index2.1 #f #f r_0 #f)))" -"(begin(hash-set!(unsafe-place-local-ref cell.1$7) r_0(make-ephemeron r_0 mpi_0)) mpi_0))))" +"(begin(hash-set!(unsafe-place-local-ref cell.1$8) r_0(make-ephemeron r_0 mpi_0)) mpi_0))))" "(end-atomic)))))))" "(define-values" "(resolved-module-path-to-generic-resolved-module-path)" @@ -5278,6 +5278,7 @@ static const char *startup_source = "(pop-syntax-context!)" "(lambda(state_0)" "(begin(let-values(((b_0)(serialize-state-syntax-context state_0)))(set-box! b_0(cdr(unbox b_0)))))))" +" (define-values (not-an-fX.1) (lambda (who_0 v_0) (begin 'not-an-fX (raise-argument-error who_0 \"fixnum?\" v_0))))" "(define-values(root-tag)(unsafe-root-continuation-prompt-tag))" "(define-values(default-val.1$2) #f)" "(define-values" @@ -5317,10 +5318,9 @@ static const char *startup_source = "(if(zero?(vector-length(car rk_2)))(all-fields-immutable?$1(cdr rk_2)) #f)" "(all-fields-immutable?$1 rk_2))))))))))))" "(define-values(all-fields-immutable?)(lambda(k_0)(begin(prefab-key-all-fields-immutable? k_0))))" -" (define-values (not-an-fX.1) (lambda (who_0 v_0) (begin 'not-an-fX (raise-argument-error who_0 \"fixnum?\" v_0))))" "(define-values" "(datum-map-slow)" -"(lambda(tail?_0 s_0 f_0 seen_0)" +"(lambda(tail?_0 s_0 f_0 seen_0 known-pairs_0)" "(begin" "((letrec-values(((loop_0)" "(lambda(tail?_1 s_1 prev-seen_0)" @@ -5337,7 +5337,14 @@ static const char *startup_source = "(let-values()(f_0 tail?_1 s_1))" "(if(pair? s_1)" "(let-values()" -"(f_0 tail?_1(cons(loop_0 #f(car s_1) seen_1)(loop_0 #t(cdr s_1) seen_1))))" +"(if(if known-pairs_0(if tail?_1(hash-ref known-pairs_0 s_1 #f) #f) #f)" +"(let-values() s_1)" +"(let-values()" +"(f_0" +" tail?_1" +"(cons" +"(loop_0 #f(car s_1) seen_1)" +"(loop_0(if tail?_1(fx+ 1 tail?_1) 1)(cdr s_1) seen_1))))))" "(if(let-values(((or-part_0)(symbol? s_1)))" "(if or-part_0" " or-part_0" @@ -5716,7 +5723,11 @@ static const char *startup_source = " \"value\"" " v_1)))" " v_1)))))" -"(let-values(((s_0) v_0)((f_0) check-preserve_0)((gf_0) check-preserve_0)((seen_0) disallow-cycles$1))" +"(let-values(((s_0) v_0)" +"((f_0) check-preserve_0)" +"((gf_0) check-preserve_0)" +"((seen_0) disallow-cycles$1)" +"((known-pairs_0) #f))" "((letrec-values(((loop_0)" "(lambda(tail?_0 s_1 prev-depth_0)" "(begin" @@ -5724,14 +5735,19 @@ static const char *startup_source = "(let-values(((depth_0)(fx+ 1 prev-depth_0)))" "(if(if seen_0(fx> depth_0 32) #f)" "(let-values()" -"(datum-map-slow tail?_0 s_1(lambda(tail?_1 s_2)(gf_0 tail?_1 s_2)) seen_0))" +"(datum-map-slow" +" tail?_0" +" s_1" +"(lambda(tail?_1 s_2)(gf_0 tail?_1 s_2))" +" seen_0" +" known-pairs_0))" "(if(null? s_1)" "(let-values()(f_0 tail?_0 s_1))" "(if(pair? s_1)" "(let-values()" "(f_0" " tail?_0" -"(cons(loop_0 #f(car s_1) depth_0)(loop_0 #t(cdr s_1) depth_0))))" +"(cons(loop_0 #f(car s_1) depth_0)(loop_0 1(cdr s_1) depth_0))))" "(if(symbol? s_1)" "(let-values()(f_0 #f s_1))" "(if(boolean? s_1)" @@ -5751,7 +5767,8 @@ static const char *startup_source = " tail?_0" " s_1" "(lambda(tail?_1 s_2)(gf_0 tail?_1 s_2))" -" seen_0))" +" seen_0" +" known-pairs_0))" "(let-values()(gf_0 #f s_1))))))))))))))" " loop_0)" " #f" @@ -5948,7 +5965,7 @@ static const char *startup_source = "(let-values((()(begin(ser-push!_0 'tag '#:syntax)(values))))" "(let-values(((this-state_0)" "(if(no-pair-syntax-in-cdr? content_0)" -"(syntax-state17.1" +"(syntax-state18.1" " #t" " context-triple_0" "(syntax-srcloc s_0))" @@ -6075,7 +6092,8 @@ static const char *startup_source = "(if(syntax?$1 v_0)" "(let-values()(d->s_0 v_0(loop_0(s-e_0 v_0))))" "(let-values()(f_0 tail?_0 v_0))))))" -"((seen_1) seen_0))" +"((seen_1) seen_0)" +"((known-pairs_0) #f))" "((letrec-values(((loop_1)" "(lambda(tail?_0 s_4 prev-depth_0)" "(begin" @@ -6087,7 +6105,8 @@ static const char *startup_source = " tail?_0" " s_4" "(lambda(tail?_1 s_5)(gf_0 tail?_1 s_5))" -" seen_1))" +" seen_1" +" known-pairs_0))" "(if(null? s_4)" "(let-values()(f_1 tail?_0 s_4))" "(if(pair? s_4)" @@ -6096,7 +6115,7 @@ static const char *startup_source = " tail?_0" "(cons" "(loop_1 #f(car s_4) depth_0)" -"(loop_1 #t(cdr s_4) depth_0))))" +"(loop_1 1(cdr s_4) depth_0))))" "(if(symbol? s_4)" "(let-values()(f_1 #f s_4))" "(if(boolean? s_4)" @@ -6119,7 +6138,8 @@ static const char *startup_source = " tail?_0" " s_4" "(lambda(tail?_1 s_5)(gf_0 tail?_1 s_5))" -" seen_1))" +" seen_1" +" known-pairs_0))" "(let-values()(gf_0 #f s_4))))))))))))))" " loop_1)" " #f" @@ -6127,6 +6147,7 @@ static const char *startup_source = " 0))))))" " loop_0)" " s_1)))))" +"(define-values(cell.1$7)(unsafe-make-place-local(make-weak-hasheq)))" "(define-values" "(datum->syntax$1)" "(let-values(((datum->syntax6_0)" @@ -6182,9 +6203,27 @@ static const char *startup_source = "(let-values(((s_1) s_0)" "((f_0)" "(lambda(tail?_0 x_0)" -"(begin 'f(if tail?_0 x_0(wrap_0 x_0)))))" +"(begin" +" 'f" +"(if tail?_0" +"(let-values()" +"(begin" +"(if(if(fx> tail?_0 32)" +"(fx=" +" 0" +"(fxand tail?_0(fx- tail?_0 1)))" +" #f)" +"(let-values()" +"(hash-set!" +"(unsafe-place-local-ref cell.1$7)" +" x_0" +" #t))" +"(void))" +" x_0))" +"(let-values()(wrap_0 x_0))))))" "((s->_0)(lambda(s_1)(begin 's-> s_1)))" -"((seen_0) disallow-cycles))" +"((seen_0) disallow-cycles)" +"((known-pairs_0)(unsafe-place-local-ref cell.1$7)))" "(let-values(((s_2) s_1)" "((f_1) f_0)" "((gf_0)" @@ -6194,7 +6233,8 @@ static const char *startup_source = "(if(syntax?$1 v_0)" "(let-values()(s->_0 v_0))" "(let-values()(f_0 tail?_0 v_0))))))" -"((seen_1) seen_0))" +"((seen_1) seen_0)" +"((known-pairs_1) known-pairs_0))" "((letrec-values(((loop_0)" "(lambda(tail?_0 s_3 prev-depth_0)" "(begin" @@ -6208,7 +6248,8 @@ static const char *startup_source = " s_3" "(lambda(tail?_1 s_4)" "(gf_0 tail?_1 s_4))" -" seen_1))" +" seen_1" +" known-pairs_1))" "(if(null? s_3)" "(let-values()(f_1 tail?_0 s_3))" "(if(pair? s_3)" @@ -6218,7 +6259,7 @@ static const char *startup_source = "(cons" "(loop_0 #f(car s_3) depth_0)" "(loop_0" -" #t" +" 1" "(cdr s_3)" " depth_0))))" "(if(symbol? s_3)" @@ -6250,7 +6291,8 @@ static const char *startup_source = " s_3" "(lambda(tail?_1 s_4)" "(gf_0 tail?_1 s_4))" -" seen_1))" +" seen_1" +" known-pairs_1))" "(let-values()" "(gf_0" " #f" @@ -6262,7 +6304,7 @@ static const char *startup_source = "(if(if stx-p_0(not(eq?(syntax-props stx-p_0) empty-props)) #f)" "(let-values(((the-struct_0) result-s_0))" "(if(syntax?$1 the-struct_0)" -"(let-values(((props19_0)(syntax-props stx-p_0)))" +"(let-values(((props20_0)(syntax-props stx-p_0)))" "(syntax1.1" "(syntax-content the-struct_0)" "(syntax-scopes the-struct_0)" @@ -6270,7 +6312,7 @@ static const char *startup_source = "(syntax-scope-propagations+tamper the-struct_0)" "(syntax-mpi-shifts the-struct_0)" "(syntax-srcloc the-struct_0)" -" props19_0" +" props20_0" "(syntax-inspector the-struct_0)))" " (raise-argument-error 'struct-copy \"syntax?\" the-struct_0)))" " result-s_0)))))))))))))))" @@ -6283,9 +6325,10 @@ static const char *startup_source = "(hasheq" " 'cycle-fail" " (lambda (s_0) (raise-arguments-error 'datum->syntax \"cannot create syntax from cyclic datum\" \"datum\" s_0))))" +"(define-values(syntax-place-init!)(lambda()(begin(unsafe-place-local-set! cell.1$7(make-weak-hasheq)))))" "(define-values" "(struct:syntax-state" -" syntax-state17.1" +" syntax-state18.1" " syntax-state?" " syntax-state-all-sharing?" " syntax-state-context-triple" @@ -7807,13 +7850,15 @@ static const char *startup_source = "(syntax-props the-struct_0)" "(syntax-inspector the-struct_0)))" " (raise-argument-error 'struct-copy \"syntax?\" the-struct_0)))))))))" -"((seen_0) #f))" +"((seen_0) #f)" +"((known-pairs_0) #f))" "(let-values(((s_1) s_0)" "((f_1) f_0)" "((gf_0)" "(lambda(tail?_0 v_0)" "(begin 'gf(if(syntax?$1 v_0)(let-values()(s->_0 v_0))(let-values()(f_0 tail?_0 v_0))))))" -"((seen_1) seen_0))" +"((seen_1) seen_0)" +"((known-pairs_1) known-pairs_0))" "((letrec-values(((loop_0)" "(lambda(tail?_0 s_2 prev-depth_0)" "(begin" @@ -7821,14 +7866,19 @@ static const char *startup_source = "(let-values(((depth_0)(fx+ 1 prev-depth_0)))" "(if(if seen_1(fx> depth_0 32) #f)" "(let-values()" -"(datum-map-slow tail?_0 s_2(lambda(tail?_1 s_3)(gf_0 tail?_1 s_3)) seen_1))" +"(datum-map-slow" +" tail?_0" +" s_2" +"(lambda(tail?_1 s_3)(gf_0 tail?_1 s_3))" +" seen_1" +" known-pairs_1))" "(if(null? s_2)" "(let-values()(f_1 tail?_0 s_2))" "(if(pair? s_2)" "(let-values()" "(f_1" " tail?_0" -"(cons(loop_0 #f(car s_2) depth_0)(loop_0 #t(cdr s_2) depth_0))))" +"(cons(loop_0 #f(car s_2) depth_0)(loop_0 1(cdr s_2) depth_0))))" "(if(symbol? s_2)" "(let-values()(f_1 #f s_2))" "(if(boolean? s_2)" @@ -7848,7 +7898,8 @@ static const char *startup_source = " tail?_0" " s_2" "(lambda(tail?_1 s_3)(gf_0 tail?_1 s_3))" -" seen_1))" +" seen_1" +" known-pairs_1))" "(let-values()(gf_0 #f s_2))))))))))))))" " loop_0)" " #f" @@ -9055,7 +9106,8 @@ static const char *startup_source = "(syntax-props the-struct_0)" "(syntax-inspector the-struct_0)))" " (raise-argument-error 'struct-copy \"syntax?\" the-struct_0))))))))" -"((seen_0) #f))" +"((seen_0) #f)" +"((known-pairs_0) #f))" "(let-values(((s_2) s_1)" "((f_1) f_0)" "((gf_0)" @@ -9065,7 +9117,8 @@ static const char *startup_source = "(if(syntax?$1 v_0)" "(let-values()(s->_0 v_0))" "(let-values()(f_0 tail?_0 v_0))))))" -"((seen_1) seen_0))" +"((seen_1) seen_0)" +"((known-pairs_1) known-pairs_0))" "((letrec-values(((loop_0)" "(lambda(tail?_0 s_3 prev-depth_0)" "(begin" @@ -9077,7 +9130,8 @@ static const char *startup_source = " tail?_0" " s_3" "(lambda(tail?_1 s_4)(gf_0 tail?_1 s_4))" -" seen_1))" +" seen_1" +" known-pairs_1))" "(if(null? s_3)" "(let-values()(f_1 tail?_0 s_3))" "(if(pair? s_3)" @@ -9086,7 +9140,7 @@ static const char *startup_source = " tail?_0" "(cons" "(loop_0 #f(car s_3) depth_0)" -"(loop_0 #t(cdr s_3) depth_0))))" +"(loop_0 1(cdr s_3) depth_0))))" "(if(symbol? s_3)" "(let-values()(f_1 #f s_3))" "(if(boolean? s_3)" @@ -9107,7 +9161,8 @@ static const char *startup_source = " tail?_0" " s_3" "(lambda(tail?_1 s_4)(gf_0 tail?_1 s_4))" -" seen_1))" +" seen_1" +" known-pairs_1))" "(let-values()(gf_0 #f s_3))))))))))))))" " loop_0)" " #f" @@ -9431,7 +9486,8 @@ static const char *startup_source = "(if(syntax?$1 v_0)" "(let-values()(d->s_0 v_0(loop_0(s-e_0 v_0))))" "(let-values()(f_0 tail?_0 v_0))))))" -"((seen_1) seen_0))" +"((seen_1) seen_0)" +"((known-pairs_0) #f))" "((letrec-values(((loop_1)" "(lambda(tail?_0 s_4 prev-depth_0)" "(begin" @@ -9443,7 +9499,8 @@ static const char *startup_source = " tail?_0" " s_4" "(lambda(tail?_1 s_5)(gf_0 tail?_1 s_5))" -" seen_1))" +" seen_1" +" known-pairs_0))" "(if(null? s_4)" "(let-values()(f_1 tail?_0 s_4))" "(if(pair? s_4)" @@ -9452,7 +9509,7 @@ static const char *startup_source = " tail?_0" "(cons" "(loop_1 #f(car s_4) depth_0)" -"(loop_1 #t(cdr s_4) depth_0))))" +"(loop_1 1(cdr s_4) depth_0))))" "(if(symbol? s_4)" "(let-values()(f_1 #f s_4))" "(if(boolean? s_4)" @@ -9476,7 +9533,8 @@ static const char *startup_source = " tail?_0" " s_4" "(lambda(tail?_1 s_5)(gf_0 tail?_1 s_5))" -" seen_1))" +" seen_1" +" known-pairs_0))" "(let-values()(gf_0 #f s_4))))))))))))))" " loop_1)" " #f" @@ -10042,7 +10100,8 @@ static const char *startup_source = "(if(syntax?$1 v_0)" "(let-values()(d->s_0 v_0(loop_0(s-e_0 v_0))))" "(let-values()(f_0 tail?_0 v_0))))))" -"((seen_1) seen_0))" +"((seen_1) seen_0)" +"((known-pairs_0) #f))" "((letrec-values(((loop_1)" "(lambda(tail?_0 s_4 prev-depth_0)" "(begin" @@ -10054,7 +10113,8 @@ static const char *startup_source = " tail?_0" " s_4" "(lambda(tail?_1 s_5)(gf_0 tail?_1 s_5))" -" seen_1))" +" seen_1" +" known-pairs_0))" "(if(null? s_4)" "(let-values()(f_1 tail?_0 s_4))" "(if(pair? s_4)" @@ -10063,7 +10123,7 @@ static const char *startup_source = " tail?_0" "(cons" "(loop_1 #f(car s_4) depth_0)" -"(loop_1 #t(cdr s_4) depth_0))))" +"(loop_1 1(cdr s_4) depth_0))))" "(if(symbol? s_4)" "(let-values()(f_1 #f s_4))" "(if(boolean? s_4)" @@ -10090,7 +10150,8 @@ static const char *startup_source = " s_4" "(lambda(tail?_1 s_5)" "(gf_0 tail?_1 s_5))" -" seen_1))" +" seen_1" +" known-pairs_0))" "(let-values()" "(gf_0 #f s_4))))))))))))))" " loop_1)" @@ -10257,7 +10318,8 @@ static const char *startup_source = "(if(syntax?$1 v_0)" "(let-values()(d->s_0 v_0(loop_0(s-e_0 v_0))))" "(let-values()(f_0 tail?_0 v_0))))))" -"((seen_1) seen_0))" +"((seen_1) seen_0)" +"((known-pairs_0) #f))" "((letrec-values(((loop_1)" "(lambda(tail?_0 s_4 prev-depth_0)" "(begin" @@ -10269,7 +10331,8 @@ static const char *startup_source = " tail?_0" " s_4" "(lambda(tail?_1 s_5)(gf_0 tail?_1 s_5))" -" seen_1))" +" seen_1" +" known-pairs_0))" "(if(null? s_4)" "(let-values()(f_1 tail?_0 s_4))" "(if(pair? s_4)" @@ -10278,7 +10341,7 @@ static const char *startup_source = " tail?_0" "(cons" "(loop_1 #f(car s_4) depth_0)" -"(loop_1 #t(cdr s_4) depth_0))))" +"(loop_1 1(cdr s_4) depth_0))))" "(if(symbol? s_4)" "(let-values()(f_1 #f s_4))" "(if(boolean? s_4)" @@ -10305,7 +10368,8 @@ static const char *startup_source = " s_4" "(lambda(tail?_1 s_5)" "(gf_0 tail?_1 s_5))" -" seen_1))" +" seen_1" +" known-pairs_0))" "(let-values()" "(gf_0 #f s_4))))))))))))))" " loop_1)" @@ -16353,7 +16417,8 @@ static const char *startup_source = "(begin" " 's->" "(loop_0 s_2(syntax-taint-mode-property s_2)))))" -"((seen_0) #f))" +"((seen_0) #f)" +"((known-pairs_0) #f))" "(let-values(((s_3) s_2)" "((f_1) f_0)" "((gf_0)" @@ -16363,7 +16428,8 @@ static const char *startup_source = "(if(syntax?$1 v_0)" "(let-values()(s->_0 v_0))" "(let-values()(f_0 tail?_0 v_0))))))" -"((seen_1) seen_0))" +"((seen_1) seen_0)" +"((known-pairs_1) known-pairs_0))" "((letrec-values(((loop_1)" "(lambda(tail?_0 s_4 prev-depth_0)" "(begin" @@ -16377,7 +16443,8 @@ static const char *startup_source = " s_4" "(lambda(tail?_1 s_5)" "(gf_0 tail?_1 s_5))" -" seen_1))" +" seen_1" +" known-pairs_1))" "(if(null? s_4)" "(let-values()(f_1 tail?_0 s_4))" "(if(pair? s_4)" @@ -16387,7 +16454,7 @@ static const char *startup_source = "(cons" "(loop_1 #f(car s_4) depth_0)" "(loop_1" -" #t" +" 1" "(cdr s_4)" " depth_0))))" "(if(symbol? s_4)" @@ -16419,7 +16486,8 @@ static const char *startup_source = " s_4" "(lambda(tail?_1 s_5)" "(gf_0 tail?_1 s_5))" -" seen_1))" +" seen_1" +" known-pairs_1))" "(let-values()" "(gf_0" " #f" @@ -16465,7 +16533,8 @@ static const char *startup_source = "(loop_0" " s_2" "(syntax-taint-mode-property s_2)))))" -"((seen_0) #f))" +"((seen_0) #f)" +"((known-pairs_0) #f))" "(let-values(((s_3) s_2)" "((f_1) f_0)" "((gf_0)" @@ -16475,7 +16544,8 @@ static const char *startup_source = "(if(syntax?$1 v_0)" "(let-values()(s->_0 v_0))" "(let-values()(f_0 tail?_0 v_0))))))" -"((seen_1) seen_0))" +"((seen_1) seen_0)" +"((known-pairs_1) known-pairs_0))" "((letrec-values(((loop_1)" "(lambda(tail?_0 s_4 prev-depth_0)" "(begin" @@ -16489,7 +16559,8 @@ static const char *startup_source = " s_4" "(lambda(tail?_1 s_5)" "(gf_0 tail?_1 s_5))" -" seen_1))" +" seen_1" +" known-pairs_1))" "(if(null? s_4)" "(let-values()" "(f_1 tail?_0 s_4))" @@ -16503,7 +16574,7 @@ static const char *startup_source = "(car s_4)" " depth_0)" "(loop_1" -" #t" +" 1" "(cdr s_4)" " depth_0))))" "(if(symbol? s_4)" @@ -16541,7 +16612,8 @@ static const char *startup_source = "(gf_0" " tail?_1" " s_5))" -" seen_1))" +" seen_1" +" known-pairs_1))" "(let-values()" "(gf_0" " #f" @@ -83784,6 +83856,7 @@ static const char *startup_source = "(lambda()" "(begin" "(begin" +"(syntax-place-init!)" "(scope-place-init!)" "(cache-place-init!)" "(core-place-init!)"