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.
This commit is contained in:
Matthew Flatt 2019-07-18 11:56:19 -06:00
parent 68bbd79b3a
commit 43ba15ca38
5 changed files with 213 additions and 90 deletions

View File

@ -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)))

View File

@ -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!)

View File

@ -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)
(cond
[(and known-pairs
tail?
(hash-ref known-pairs s #f))
s]
[else
(f tail? (cons (loop #f (car s) seen)
(loop #t (cdr s) seen)))]
(loop (if tail? (fx+ 1 tail?) 1) (cdr s) seen)))])]
[(or (symbol? s) (boolean? s) (number? s))
(f #f s)]
[(vector? s)

View File

@ -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

View File

@ -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!)"