(load-relative "loadtest.ss") (Section 'optimization) (require scheme/flonum scheme/fixnum) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Check JIT inlining of primitives: (parameterize ([current-namespace (make-base-namespace)] [eval-jit-enabled #t]) (namespace-require 'scheme/flonum) (namespace-require 'scheme/fixnum) (let* ([check-error-message (lambda (name proc) (unless (memq name '(eq? not null? pair? real? number? boolean? procedure? symbol? string? bytes? vector? box? eof-object? exact-integer? exact-nonnegative-integer? exact-positive-integer?)) (let ([s (with-handlers ([exn? exn-message]) (proc 'bad))] [name (symbol->string name)]) (test name (lambda (v) (and (string? v) (let ([v (regexp-match (format "^~a" (regexp-replace* #rx"[*?+]" name "\\\\\\0")) v)]) (and v (car v))))) s))))] [un0 (lambda (v op arg) ;; (printf "Trying ~a ~a\n" op arg) (let ([name `(,op ,arg)]) (test v name ((eval `(lambda (x) (,op x))) arg)) (when (boolean? v) (test (if v 'yes 'no) name ((eval `(lambda (x) (if (,op x) 'yes 'no))) arg)))))] [un-exact (lambda (v op arg) (check-error-message op (eval `(lambda (x) (,op x)))) (un0 v op arg))] [un (lambda (v op arg) (un-exact v op arg) (when (number? arg) (let ([iv (if (number? v) (exact->inexact v) v)]) (un0 iv op (exact->inexact arg)))))] [bin0 (lambda (v op arg1 arg2) ;; (printf "Trying ~a ~a ~a\n" op arg1 arg2); (let ([name `(,op ,arg1 ,arg2)]) (test v name ((eval `(lambda (x) (,op x ,arg2))) arg1)) (test v name ((eval `(lambda (x) (,op ,arg1 x))) arg2)) (test v name ((eval `(lambda (x y) (,op x y))) arg1 arg2)) (when (boolean? v) ;; (printf " for branch...\n") (test (if v 'yes 'no) name ((eval `(lambda (x) (if (,op x ,arg2) 'yes 'no))) arg1)) (test (if v 'yes 'no) name ((eval `(lambda (x) (if (,op ,arg1 x) 'yes 'no))) arg2)))))] [bin-exact (lambda (v op arg1 arg2) (check-error-message op (eval `(lambda (x) (,op x ,arg2)))) (check-error-message op (eval `(lambda (x) (,op ,arg1 x)))) (bin0 v op arg1 arg2))] [bin-int (lambda (v op arg1 arg2) (bin-exact v op arg1 arg2) (let* ([iv (if (number? v) (exact->inexact v) v)] [iv0 (if (and (memq op '(* /)) (zero? iv)) 0 iv)]) (bin0 iv op (exact->inexact arg1) arg2) (bin0 iv0 op arg1 (exact->inexact arg2)) (bin0 iv op (exact->inexact arg1) (exact->inexact arg2))))] [bin (lambda (v op arg1 arg2) (bin-int v op arg1 arg2) (let ([iv (if (number? v) (if (eq? op '*) (/ v (* 33333 33333)) (if (eq? op '/) v (/ v 33333))) v)]) (bin0 iv op (/ arg1 33333) (/ arg2 33333))) (let ([iv (if (number? v) +nan.0 #f)]) (bin0 iv op (exact->inexact arg1) +nan.0) (bin0 iv op +nan.0 (exact->inexact arg2)) (unless (eq? op 'eq?) (bin0 iv op +nan.0 +nan.0))))] [tri0 (lambda (v op get-arg1 arg2 arg3 check-effect #:wrap [wrap values]) ;; (printf "Trying ~a ~a ~a\n" op (get-arg1) arg2 arg3); (let ([name `(,op ,get-arg1 ,arg2, arg3)] [get-arg2 (lambda () arg2)] [get-arg3 (lambda () arg3)]) (test v name ((eval `(lambda (x) ,(wrap `(,op x ,arg2 ,arg3)))) (get-arg1))) (check-effect) (test v name ((eval `(lambda (x) ,(wrap `(,op (,get-arg1) x ,arg3)))) arg2)) (check-effect) (test v name ((eval `(lambda (x) ,(wrap `(,op x (,get-arg2) ,arg3)))) (get-arg1))) (check-effect) (test v name ((eval `(lambda (x) ,(wrap `(,op (,get-arg1) (,get-arg2) x)))) arg3)) (check-effect) (test v name ((eval `(lambda () ,(wrap `(,op (,get-arg1) (,get-arg2) (,get-arg3))))))) (check-effect) (test v name ((eval `(lambda (x) ,(wrap `(,op (,get-arg1) ,arg2 x)))) arg3)) (check-effect) (test v name ((eval `(lambda (x y) ,(wrap `(,op (,get-arg1) x y)))) arg2 arg3)) (check-effect) (eval `(define _arg2 ,arg2)) (test v name ((eval `(lambda (y) ,(wrap `(,op (,get-arg1) _arg2 y)))) arg3)) (check-effect) (test v name ((eval `(lambda (x y z) ,(wrap `(,op x y z)))) (get-arg1) arg2 arg3)) (check-effect)))] [tri (lambda (v op get-arg1 arg2 arg3 check-effect #:wrap [wrap values]) (define (e->i n) (if (number? n) (exact->inexact n) n)) (tri0 v op get-arg1 arg2 arg3 check-effect #:wrap wrap) (tri0 (e->i v) op (lambda () (exact->inexact (get-arg1))) (exact->inexact arg2) (exact->inexact arg3) check-effect #:wrap wrap) (tri0 (e->i v) op get-arg1 (exact->inexact arg2) arg3 check-effect #:wrap wrap))] [tri-if (lambda (v op get-arg1 arg2 arg3 check-effect) (tri v op get-arg1 arg2 arg3 check-effect) (tri (if v 'true 'false) op get-arg1 arg2 arg3 check-effect #:wrap (lambda (e) `(if ,e 'true 'false))))] [tri-exact (lambda (v op get-arg1 arg2 arg3 check-effect 3rd-all-ok?) (check-error-message op (eval `(lambda (x) (,op x ,arg2 ,arg3)))) (check-error-message op (eval `(lambda (x) (,op (,get-arg1) x ,arg3)))) (unless 3rd-all-ok? (check-error-message op (eval `(lambda (x) (,op (,get-arg1) ,arg2 x))))) (tri0 v op get-arg1 arg2 arg3 check-effect))]) (un #f 'null? 0) (un #f 'pair? 0) (un #f 'boolean? 0) (un #t 'boolean? #t) (un #t 'boolean? #f) (un #f 'eof-object? #f) (un #t 'eof-object? eof) (un #f 'procedure? #f) (un #t 'procedure? procedure?) (un #t 'procedure? (lambda (x) 10)) (un #t 'symbol? 'ok) (un #f 'symbol? #f) (un #t 'vector? (vector 1 2 3)) (un #f 'vector? #f) (un #t 'box? (box 10)) (un #f 'box? #f) (un #t 'string? "apple") (un #f 'string? #"apple") (un #f 'bytes? "apple") (un #t 'bytes? #"apple") (bin #f 'eq? 0 10) (un #t 'zero? 0) (un #f 'zero? 1) (un #f 'zero? -1) (un #f 'positive? 0) (un #t 'positive? 1) (un #f 'positive? -1) (un #f 'negative? 0) (un #f 'negative? 1) (un #t 'negative? -1) (un #t 'real? 1) (un #t 'real? (expt 2 100)) (un #t 'real? 1.0) (un #f 'real? 1+2i) (un #f 'real? 'apple) (un #t 'number? 1) (un #t 'number? (expt 2 100)) (un #t 'number? 1.0) (un #t 'number? 1+2i) (un #f 'number? 'apple) (un-exact #t 'exact-integer? 0) (un-exact #t 'exact-integer? 10) (un-exact #t 'exact-integer? -10) (un-exact #t 'exact-integer? (expt 2 100)) (un-exact #t 'exact-integer? (- (expt 2 100))) (un-exact #f 'exact-integer? 10.0) (un-exact #f 'exact-integer? 1/2) (un-exact #t 'exact-nonnegative-integer? 0) (un-exact #t 'exact-nonnegative-integer? 10) (un-exact #f 'exact-nonnegative-integer? -10) (un-exact #t 'exact-nonnegative-integer? (expt 2 100)) (un-exact #f 'exact-nonnegative-integer? (- (expt 2 100))) (un-exact #f 'exact-nonnegative-integer? 10.0) (un-exact #f 'exact-nonnegative-integer? 1/2) (un-exact #f 'exact-positive-integer? 0) (un-exact #t 'exact-positive-integer? 10) (un-exact #f 'exact-positive-integer? -10) (un-exact #t 'exact-positive-integer? (expt 2 100)) (un-exact #f 'exact-positive-integer? (- (expt 2 100))) (un-exact #f 'exact-positive-integer? 10.0) (un-exact #f 'exact-positive-integer? 1/2) (un #t 'not #f) (un #f 'not #t) (un #f 'not 10) (bin #t '< 100 200) (bin #f '< 200 100) (bin #f '< 100 100) (bin #t '< -200 100) (bin #f '< 100 -200) (bin #t '< 1 (expt 2 30)) (tri-if #t '< (lambda () 1) 2 3 void) (tri-if #f '< (lambda () 1) 3 3 void) (tri-if #f '< (lambda () 1) -1 3 void) (bin-exact #t 'fx< 100 200) (bin-exact #f 'fx< 200 100) (bin-exact #f 'fx< 200 200) (bin-exact #t 'fl< 100.0 200.0) (bin-exact #f 'fl< 200.0 100.0) (bin-exact #f 'fl< 200.0 200.0) (bin #t '<= 100 200) (bin #f '<= 200 100) (bin #t '<= 100 100) (bin #t '<= -200 100) (bin #f '<= 100 -200) (tri-if #t '<= (lambda () 1) 2 3 void) (tri-if #t '<= (lambda () 1) 3 3 void) (tri-if #f '<= (lambda () 1) -1 3 void) (bin-exact #t 'fx<= 100 200) (bin-exact #f 'fx<= 200 100) (bin-exact #t 'fx<= 200 200) (bin-exact #t 'fl<= 100.0 200.0) (bin-exact #f 'fl<= 200.0 100.0) (bin-exact #t 'fl<= 200.0 200.0) (bin #f '> 100 200) (bin #t '> 200 100) (bin #f '> 100 100) (bin #f '> -200 100) (bin #t '> 100 -200) (bin #f '> 1 (expt 2 30)) (tri-if #t '> (lambda () 3) 2 1 void) (tri-if #f '> (lambda () 3) 3 1 void) (tri-if #f '> (lambda () 3) -1 1 void) (bin-exact #f 'fx> 100 200) (bin-exact #t 'fx> 200 100) (bin-exact #f 'fx> 200 200) (bin-exact #f 'fl> 100.0 200.0) (bin-exact #t 'fl> 200.0 100.0) (bin-exact #f 'fl> 200.0 200.0) (bin #f '>= 100 200) (bin #t '>= 200 100) (bin #t '>= 100 100) (bin #f '>= -200 100) (bin #t '>= 100 -200) (tri-if #t '>= (lambda () 3) 2 1 void) (tri-if #t '>= (lambda () 3) 3 1 void) (tri-if #f '>= (lambda () 3) -1 1 void) (bin-exact #f 'fx>= 100 200) (bin-exact #t 'fx>= 200 100) (bin-exact #t 'fx>= 200 200) (bin-exact #f 'fl>= 100.0 200.0) (bin-exact #t 'fl>= 200.0 100.0) (bin-exact #t 'fl>= 200.0 200.0) (bin #f '= 100 200) (bin #f '= 200 100) (bin #t '= 100 100) (bin #f '= -200 100) (bin #f '= +nan.0 +nan.0) (tri-if #t '= (lambda () 3) 3 3 void) (tri-if #f '= (lambda () 3) 3 1 void) (tri-if #f '= (lambda () 3) 1 3 void) (tri-if #f '= (lambda () 1) 3 3 void) (bin-exact #f 'fx= 100 200) (bin-exact #t 'fx= 200 200) (bin-exact #f 'fl= 100.0 200.0) (bin-exact #t 'fl= 200.0 200.0) (un 3 'add1 2) (un -3 'add1 -4) (un (expt 2 30) 'add1 (sub1 (expt 2 30))) (un 1 'sub1 2) (un -5 'sub1 -4) (un (- (expt 2 30)) 'sub1 (- 1 (expt 2 30))) (un -1 '- 1) (un 1 '- -1) (un (- (expt 2 30)) '- (expt 2 30)) (un (expt 2 30) '- (- (expt 2 30))) (un -0.0 '- 0.0) (un 0.0 '- -0.0) (un 0 'abs 0) (un 1 'abs 1) (un 1 'abs -1) (un (sub1 (expt 2 30)) 'abs (sub1 (expt 2 30))) (un (expt 2 30) 'abs (- (expt 2 30))) (un (sub1 (expt 2 62)) 'abs (sub1 (expt 2 62))) (un (expt 2 62) 'abs (- (expt 2 62))) (un-exact 3.0 'flabs -3.0) (un-exact 3.0 'flsqrt 9.0) (un-exact +nan.0 'flsqrt -9.0) (let ([test-trig (lambda (trig fltrig) (un (trig 1.0) fltrig 1.0) (un +nan.0 fltrig +nan.0))]) (test-trig sin 'flsin) (test-trig cos 'flcos) (test-trig tan 'fltan) (test-trig asin 'flasin) (test-trig acos 'flacos) (test-trig atan 'flatan) (test-trig log 'fllog) (test-trig exp 'flexp)) (un 1.0 'exact->inexact 1) (un 1073741823.0 'exact->inexact (sub1 (expt 2 30))) (un -1073741824.0 'exact->inexact (- (expt 2 30))) (un 4611686018427387903.0 'exact->inexact (sub1 (expt 2 62))) (un -4611686018427387904.0 'exact->inexact (- (expt 2 62))) (un-exact 10.0 '->fl 10) (un-exact 10.0 'fx->fl 10) (bin 11 '+ 4 7) (bin -3 '+ 4 -7) (bin (expt 2 30) '+ (expt 2 29) (expt 2 29)) (bin (- (expt 2 31) 2) '+ (sub1 (expt 2 30)) (sub1 (expt 2 30))) (tri 6 '+ (lambda () 1) 2 3 void) (tri 13/2 '+ (lambda () 1) 5/2 3 void) (bin-exact 25 'fx+ 10 15) (bin-exact 3.4 'fl+ 1.1 2.3) (bin 3 '- 7 4) (bin 11 '- 7 -4) (bin 0 '- (expt 2 29) (expt 2 29)) (bin (expt 2 30) '- (expt 2 29) (- (expt 2 29))) (bin (- (expt 2 30)) '- (- (expt 2 29)) (expt 2 29)) (bin (- 2 (expt 2 31)) '- (- 1 (expt 2 30)) (sub1 (expt 2 30))) (tri 6 '- (lambda () 10) 3 1 void) (tri 13/2 '- (lambda () 10) 3 1/2 void) (bin-exact 13 'fx- 5 -8) (bin-exact -0.75 'fl- 1.5 2.25) (bin 4 '* 1 4) (bin 0 '* 0 4) (bin 12 '* 3 4) (bin -12 '* -3 4) (bin -12 '* 3 -4) (bin 12 '* -3 -4) (bin (expt 2 70) '* 2 (expt 2 69)) (bin (expt 2 30) '* 2 (expt 2 29)) (bin (expt 2 31) '* 2 (expt 2 30)) (bin (- (expt 2 30)) '* 2 (- (expt 2 29))) (tri 30 '* (lambda () 2) 3 5 void) (tri 5 '* (lambda () 2) 3 5/6 void) (bin-exact 253 'fx* 11 23) (bin-exact 2.53 'fl* 1.1 2.3) (bin 0 '/ 0 4) (bin 1/4 '/ 1 4) (bin 4 '/ 4 1) (bin 4 '/ 16 4) (bin -4 '/ -16 4) (bin -4 '/ 16 -4) (bin 4 '/ -16 -4) (tri 3 '/ (lambda () 30) 5 2 void) (tri 12 '/ (lambda () 30) 5 1/2 void) (bin-exact (/ 1.1 2.3) 'fl/ 1.1 2.3) (bin-int 3 'quotient 10 3) (bin-int -3 'quotient 10 -3) (bin-int 3 'quotient -10 -3) (bin-int -3 'quotient -10 3) (bin-exact 7 'quotient (* 7 (expt 2 100)) (expt 2 100)) (bin-exact 3 'fxquotient 10 3) (bin-exact -3 'fxquotient 10 -3) (bin-exact (expt 2 30) 'quotient (- (expt 2 30)) -1) (bin-int 1 'remainder 10 3) (bin-int 1 'remainder 10 -3) (bin-int -1 'remainder -10 -3) (bin-int -1 'remainder -10 3) (bin-exact 7 'remainder (+ 7 (expt 2 100)) (expt 2 100)) (bin-exact 1 'fxremainder 10 3) (bin-exact 1 'fxremainder 10 -3) (bin-exact -1 'fxremainder -10 3) (bin-exact -1 'fxremainder -10 -3) (bin-int 1 'modulo 10 3) (bin-int -2 'modulo 10 -3) (bin-int -1 'modulo -10 -3) (bin-int 2 'modulo -10 3) (bin-exact 7 'modulo (+ 7 (expt 2 100)) (expt 2 100)) (bin-exact 1 'fxmodulo 10 3) (bin-exact -2 'fxmodulo 10 -3) (bin-exact -1 'fxmodulo -10 -3) (bin-exact 2 'fxmodulo -10 3) (bin 3 'min 3 300) (bin -300 'min 3 -300) (bin -400 'min -400 -300) (tri 5 'min (lambda () 10) 5 20 void) (tri 5 'min (lambda () 5) 10 20 void) (tri 5 'min (lambda () 20) 10 5 void) (bin-exact 3.0 'flmin 3.0 4.5) (bin-exact 2.5 'flmin 3.0 2.5) (bin-exact 30 'fxmin 30 45) (bin-exact 25 'fxmin 30 25) (bin 300 'max 3 300) (bin 3 'max 3 -300) (bin -3 'max -3 -300) (tri 50 'max (lambda () 10) 50 20 void) (tri 50 'max (lambda () 50) 10 20 void) (tri 50 'max (lambda () 20) 10 50 void) (bin-exact 4.5 'flmax 3.0 4.5) (bin-exact 3.0 'flmax 3.0 2.5) (bin-exact 45 'fxmax 30 45) (bin-exact 30 'fxmax 30 25) (bin-exact 11 'bitwise-and 11 43) (bin-exact 0 'bitwise-and 11 32) (bin-exact 0 'bitwise-and 11 (expt 2 50)) (bin-exact 0 'bitwise-and 0 -32) (bin-exact 11 'bitwise-and 11 -1) (bin-exact -11 'bitwise-and -11 -1) (bin-exact (expt 2 50) 'bitwise-and (expt 2 50) (expt 2 50)) (tri-exact #x10101 'bitwise-and (lambda () #x11111) #x10111 #x110101 void #f) (bin-exact 11 'fxand 11 43) (bin-exact 11 'bitwise-ior 8 3) (bin-exact 11 'bitwise-ior 11 3) (bin-exact -1 'bitwise-ior 11 -1) (bin-exact (sub1 (expt 2 51)) 'bitwise-ior (sub1 (expt 2 50)) (expt 2 50)) (bin-exact (add1 (expt 2 50)) 'bitwise-ior 1 (expt 2 50)) (tri-exact #x10101 'bitwise-ior (lambda () #x1) #x100 #x10000 void #f) (bin-exact 11 'fxior 8 3) (bin-exact 11 'bitwise-xor 8 3) (bin-exact 8 'bitwise-xor 11 3) (bin-exact -2 'bitwise-xor 1 -1) (bin-exact (sub1 (expt 2 51)) 'bitwise-xor (sub1 (expt 2 50)) (expt 2 50)) (bin-exact (add1 (expt 2 50)) 'bitwise-xor 1 (expt 2 50)) (tri-exact #x10101 'bitwise-xor (lambda () #x1) #x110 #x10010 void #f) (bin-exact 11 'fxxor 8 3) (bin-exact 4 'arithmetic-shift 2 1) (bin-exact 1 'arithmetic-shift 2 -1) (bin-exact (expt 2 30) 'arithmetic-shift 2 29) (bin-exact (expt 2 31) 'arithmetic-shift 2 30) (bin-exact (expt 2 32) 'arithmetic-shift 2 31) (bin-exact (expt 2 33) 'arithmetic-shift 2 32) (bin-exact -2 'arithmetic-shift -1 1) (bin-exact -1 'arithmetic-shift -1 -1) (bin-exact 2 'arithmetic-shift (expt 2 33) -32) (bin-exact 8 'arithmetic-shift (expt 2 33) -30) (bin-exact 4 'fxlshift 2 1) (bin-exact 1 'fxrshift 2 1) (un-exact -1 'bitwise-not 0) (un-exact 0 'bitwise-not -1) (un-exact (- -1 (expt 2 30)) 'bitwise-not (expt 2 30)) (un-exact (- (expt 2 30)) 'bitwise-not (sub1 (expt 2 30))) (un-exact (- -1 (expt 2 32)) 'bitwise-not (expt 2 32)) (un-exact -1 'fxnot 0) (un-exact 0 'fxnot -1) (bin-exact #t 'bitwise-bit-set? 1 0) (bin-exact #f 'bitwise-bit-set? 1 1) (bin-exact #t 'bitwise-bit-set? 2 1) (bin-exact #t 'bitwise-bit-set? 200 7) (bin-exact #f 'bitwise-bit-set? 127 7) (bin-exact #f 'bitwise-bit-set? 383 7) (bin-exact #f 'bitwise-bit-set? 10 128) (bin-exact #t 'bitwise-bit-set? -10 128) (bin-exact #t 'bitwise-bit-set? (expt 2 30) 30) (bin-exact #t 'bitwise-bit-set? (expt 2 40) 40) (bin-exact #f 'bitwise-bit-set? (expt 2 40) 41) (bin-exact #t 'bitwise-bit-set? (- (expt 2 40)) 41) (bin-exact #t 'char=? #\a #\a) (bin-exact #t 'char=? #\u1034 #\u1034) (bin-exact #f 'char=? #\a #\b) (bin-exact #f 'char=? #\u1034 #\a) (bin-exact 'a 'vector-ref #(a b c) 0) (bin-exact 'b 'vector-ref #(a b c) 1) (bin-exact 'c 'vector-ref #(a b c) 2) (un-exact 'a 'unbox (box 'a)) (un-exact 3 'vector-length (vector 'a 'b 'c)) (bin-exact 1.1 'flvector-ref (flvector 1.1 2.2 3.3) 0) (bin-exact 3.3 'flvector-ref (flvector 1.1 2.2 3.3) 2) (un-exact 3 'flvector-length (flvector 1.1 2.2 3.3)) (bin-exact #\a 'string-ref "abc\u2001" 0) (bin-exact #\b 'string-ref "abc\u2001" 1) (bin-exact #\c 'string-ref "abc\u2001" 2) (bin-exact #\u2001 'string-ref "abc\u2001" 3) (bin-exact 65 'bytes-ref #"Abc\xF7" 0) (bin-exact 99 'bytes-ref #"Abc\xF7" 2) (bin-exact #xF7 'bytes-ref #"Abc\xF7" 3) (un0 #(1) 'vector 1) (un0 #(1) 'vector-immutable 1) (bin0 #(1 2) 'vector 1 2) (bin0 #(1 2) 'vector-immutable 1 2) (tri0 #(1 2 3) 'vector (lambda () 1) 2 3 void) (tri0 #(1 2 3) 'vector-immutable (lambda () 1) 2 3 void) (un0 '(1) 'list 1) (bin0 '(1 2) 'list 1 2) (tri0 '(1 2 3) 'list (lambda () 1) 2 3 void) (un0 '1 'list* 1) (bin0 '(1 . 2) 'list* 1 2) (tri0 '(1 2 . 3) 'list* (lambda () 1) 2 3 void) (un0 '#&1 'box 1) (let ([test-setter (lambda (make-X def-val set-val set-name set ref) (let ([v (make-X 3 def-val)]) (check-error-message set-name (eval `(lambda (x) (,set-name ,v -1 ,set-val)))) (check-error-message set-name (eval `(lambda (x) (,set-name ,v 3 ,set-val)))) (unless (integer? set-val) (check-error-message set-name (eval `(lambda (x) (,set-name ,v 0 12))))) (for-each (lambda (i) (tri-exact (void) set-name (lambda () v) i set-val (lambda () (test set-val ref v i) (test def-val ref v (modulo (+ i 1) 3)) (test def-val ref v (modulo (+ i 2) 3)) (set v i def-val)) #t)) '(0 1 2))))]) (test-setter make-vector #f 7 'vector-set! vector-set! vector-ref) (test-setter make-bytes 0 7 'bytes-set! bytes-set! bytes-ref) (test-setter make-string #\a #\7 'string-set! string-set! string-ref) (test-setter make-flvector 1.0 7.0 'flvector-set! flvector-set! flvector-ref)) )) (define (comp=? c1 c2) (let ([s1 (open-output-bytes)] [s2 (open-output-bytes)]) (write c1 s1) (write c2 s2) (let ([t1 (get-output-bytes s1)] [t2 (get-output-bytes s2)]) (or (bytes=? t1 t2) (begin (printf "~s\n~s\n" t1 t2) #f ))))) (define test-comp (case-lambda [(expr1 expr2) (test-comp expr1 expr2 #t)] [(expr1 expr2 same?) (test same? `(compile ,same? ,expr2) (comp=? (compile expr1) (compile expr2)))])) (let ([x (compile '(lambda (x) x))]) (test #t 'fixpt (eq? x (compile x)))) (test-comp 5 '(if #t 5 (cons 1 2))) (test-comp 5 '(if #f (cons 1 2) 5)) (test-comp 5 '(begin0 5 'hi "apple" 1.5)) (test-comp 5 '(begin0 5 (begin0 'hi "apple" 1.5))) (test-comp 5 '(begin0 5 (begin0 'hi "apple") 1.5)) (test-comp 5 '(begin0 5 (begin 'hi "apple" 1.5))) (test-comp 5 '(begin0 5 (begin 'hi "apple") 1.5)) (test-comp 5 '(begin0 (begin0 5 'hi "apple" 1.5))) (test-comp 5 '(begin0 (begin0 5 'hi "apple") 1.5)) ; Can't drop `begin0' if the first expresson is not valueable: (test-comp '(begin0 (begin0 (+ 1 2) 0) 0) '(begin0 (begin0 (+ 1 2) 'hi "apple") 1.5)) (test-comp 5 '(begin 'hi "apple" 1.5 5)) (test-comp 5 '(begin (begin 'hi "apple" 1.5) 5)) (test-comp 5 '(begin (begin 'hi "apple") 1.5 5)) (test-comp 5 '(begin (begin0 'hi "apple" 1.5) 5)) (test-comp 5 '(begin (begin0 'hi "apple") 1.5 5)) (test-comp 5 '(begin (begin 'hi "apple" 1.5 5))) (test-comp 5 '(begin 'hi (begin "apple" 1.5 5))) (test-comp '(let ([x 8][y 9]) (lambda () x)) '(let ([x 8][y 9]) (lambda () (if #f y x)))) (test-comp '(let ([x 8][y 9]) (lambda () (+ x y))) '(let ([x 8][y 9]) (lambda () (if #f y (+ x y))))) (test-comp '(let ([x 5]) (set! x 2)) '(let ([x 5]) (set! x x) (set! x 2))) (test-comp '(let* () (f 5)) '(f 5)) (test-comp '(letrec () (f 5)) '(f 5)) (test-comp '(with-handlers () (f 5)) '(f 5)) (test-comp '(parameterize () (f 5)) '(f 5)) (test-comp '(let ([i (cons 0 1)]) (let ([j i]) j)) '(let ([i (cons 0 1)]) i)) (define (normalize-depth s) `(let ([a ,s] [b (let-values ([(a b c d e f) (values 1 2 3 4 5 6)]) (list a b c d e f))]) 10)) ;; We use nonsense `display' and `write' where we used to use `cons' and ;; `list', because the old ones now get optimized away: (test-comp (normalize-depth '(let* ([i (display 0 1)][j i]) j)) (normalize-depth '(let* ([i (display 0 1)]) i))) (test-comp (normalize-depth '(let* ([i (display 0 1)][j (write 2)][k (write 3)][g i]) g)) (normalize-depth '(let* ([i (display 0 1)][j (write 2)][k (write 3)]) i))) (test-comp (normalize-depth '(let* ([i (display 0 1)][j (write 2)][k (write 3)][g i][h g]) h)) (normalize-depth '(let* ([i (display 0 1)][j (write 2)][k (write 3)]) i))) (test-comp (normalize-depth '(let* ([i (display 0 1)][g i][h (car g)][m h]) m)) (normalize-depth '(let* ([i (display 0 1)][h (car i)]) h))) ; (require #%kernel) ; (test-comp (void) '(void)) (test-comp 3 '(+ 1 2)) (test-comp 65 '(char->integer #\A)) (test-comp (expt 5 30) '(expt 5 (* 5 6))) (test-comp 88 '(if (pair? null) 89 88)) (test-comp '(if _x_ 2 1) '(if (not _x_) 1 2)) (test-comp '(if _x_ 2 1) '(if (not (not (not _x_))) 1 2)) (test-comp '(let ([x 3]) x) '((lambda (x) x) 3)) (test-comp '(let ([x 3][y 4]) (+ x y)) '((lambda (x y) (+ x y)) 3 4)) (test-comp '(let ([x 1][y 2]) x) '1) (test-comp '(let ([x 1][y 2]) (+ y x)) '3) (test-comp '(let ([x 1][y 2]) (cons x y)) '(cons 1 2)) (test-comp '(let* ([x (cons 1 1)][y x]) (cons x y)) '(let* ([x (cons 1 1)]) (cons x x))) (test-comp '(let* ([x 1][y (add1 x)]) (+ y x)) '3) (test-comp '(letrec ([x (cons 1 1)][y x]) (cons x y)) '(letrec ([x (cons 1 1)][y x]) (cons x x))) (test-comp '(let ([f (lambda (x) x)]) f) (syntax-property (datum->syntax #f '(lambda (x) x)) 'inferred-name 'f)) (test-comp '(letrec ([f (lambda (x) x)]) (f 10) f) '(letrec ([f (lambda (x) x)]) f)) (test-comp '(let ([f (lambda (x) x)]) (f 10)) 10) (test-comp '(let ([f (lambda (x) (add1 x))] [y 10]) (f y)) '11) (test-comp '(module m mzscheme (define (f x) (+ x 1)) (f 8)) '(module m mzscheme (define (f x) (+ x 1)) 9)) (test-comp '(let ([f (lambda (x) 10)]) 3) '3) (test-comp '(let ([x (#%expression (begin (quote-syntax foo) 3))]) x) '3) (test-comp '(if (lambda () 10) 'ok (quote-syntax no!)) ''ok) (test-comp '(lambda (x) (if x x #f)) '(lambda (x) x)) (test-comp '(lambda (x) (if (cons 1 x) 78 78)) '(lambda (x) 78)) (test-comp '(lambda (x) (if (let ([r (something)]) (if r r (something-else))) (a1) (a2))) '(lambda (x) (if (if (something) #t (something-else)) (a1) (a2)))) (test-comp '(values 10) 10) (test-comp '(let ([x (values 10)]) (values x)) 10) (test-comp '(let ([x (random)]) (values x)) '(let ([x (random)]) x)) (test-comp '(let ([x (+ (cons 1 2) 0)]) (values x)) '(let ([x (+ (cons 1 2) 0)]) x)) (test-comp '(let ([x (+ (cons 1 2) 0)]) (- x 8)) '(- (+ (cons 1 2) 0) 8)) (test-comp '(let-values ([(x y) (values 1 2)]) (+ x y)) 3) (test-comp '(let-values ([() (values)]) 5) 5) (test-comp '(let-values ([() (values)]) (lambda () x)) '(lambda () x)) (test-comp '(letrec-values ([() (values)]) 5) 5) (test-comp '(let-values ([() (values)] [(x) 10]) x) 10) (test-comp '(letrec-values ([() (values)] [(x) 10]) x) 10) (test-comp '(letrec-values ([(x) 10] [() (values)]) x) 10) (test-comp '(let-values ([(x) 10] [() (values)]) x) 10) (test-comp '(letrec ([x 3] [f (lambda (y) x)]) f) '(letrec ([f (lambda (y) 3)]) f)) (test-comp '(letrec ([x 3] [f (lambda (y) x)]) (f 10)) 3) (test-comp '(letrec ([f (lambda (y) (f y))]) 3) 3) (test-comp '(letrec ([len (lambda (l) (if (null? l) 0 (len (cdr l))))]) (len null)) 0) (test-comp '(letrec ([foo (lambda () (set! foo 10))]) 0) 0) (test-comp '(letrec ([foo (lambda () 12)] [goo (lambda () foo)]) goo) '(let* ([foo (lambda () 12)] [goo (lambda () foo)]) goo)) (test-comp '(let* ([foo (lambda () 12)] [goo (lambda () foo)]) 11) 11) (test-comp '(letrec ([foo (lambda () 12)] [goo (lambda () foo)]) 11) 11) (test-comp '(letrec ([goo (lambda () foo)] [foo (lambda () goo)]) 15) 15) (parameterize ([compile-context-preservation-enabled ;; Avoid different amounts of unrolling #t]) (test-comp '(letrec ((even (let ([unused 6]) (let ([even (lambda (x) (if (zero? x) #t (even (sub1 x))))]) (values even))))) (even 10000)) '(letrec ((even (lambda (x) (if (zero? x) #t (even (sub1 x)))))) (even 10000)))) (test-comp '(procedure? add1) #t) (test-comp '(procedure? (lambda (x) x)) #t) (test-comp '(let ([f (lambda (x) x)]) (if (procedure? f) (list f) 88)) '(let ([f (lambda (x) x)]) (list f))) (test-comp '(procedure-arity-includes? integer? 1) #t) (test-comp '(module m mzscheme (define foo integer?) (display (procedure-arity-includes? foo 1))) '(module m mzscheme (define foo integer?) (display #t))) (test-comp '(module m mzscheme (void 10)) '(module m mzscheme)) (test-comp '(module m mzscheme (void (quote-syntax unused!))) '(module m mzscheme)) (test-comp '(module m mzscheme (values 1 2)) '(module m mzscheme)) (test-comp '(module m mzscheme (printf "pre\n") (void 10)) '(module m mzscheme (printf "pre\n"))) (test-comp '(module m mzscheme (define (q x) ;; Single-use bindings should be inlined always: (let* ([a (lambda (x) (+ x 10))] [b (lambda (x) (+ 1 (a x)))] [c (lambda (x) (+ 1 (b x)))] [d (lambda (x) (+ 1 (c x)))] [e (lambda (x) (+ 1 (d x)))] [f (lambda (x) (+ 1 (e x)))] [g (lambda (x) (+ 1 (f x)))] [h (lambda (x) (+ 1 (g x)))] [i (lambda (x) (+ 1 (h x)))] [j (lambda (x) (+ 1 (i x)))] [k (lambda (x) (+ 1 (j x)))]) (k x)))) '(module m mzscheme (define (q x) (+ 1 (+ 1 (+ 1 (+ 1 (+ 1 (+ 1 (+ 1 (+ 1 (+ 1 (+ 1 (+ x 10)))))))))))))) (let ([check (lambda (proc arities non-arities) (test-comp `(module m scheme/base (define f ,proc) (print (procedure? f))) `(module m scheme/base (define f ,proc) (print #t))) (for-each (lambda (a) (test-comp `(module m scheme/base (define f ,proc) (print (procedure-arity-includes? f ,a))) `(module m scheme/base (define f ,proc) (print #t)))) arities) (for-each (lambda (a) (test-comp `(module m scheme/base (define f ,proc) (print (procedure-arity-includes? f ,a))) `(module m scheme/base (define f ,proc) (print #f)))) non-arities))]) (check '(lambda (x) x) '(1) '(0 2)) (check '(lambda (x . y) x) '(1 2 3) '(0)) (check '(case-lambda [() 1] [(x y) x]) '(0 2) '(1 3)) (check '(lambda (x [y #f]) y) '(1 2) '(0 3))) (let ([test-dropped (lambda (cons-name . args) (test-comp `(let ([x 5]) (let ([y (,cons-name ,@args)]) x)) 5))]) (test-dropped 'cons 1 2) (test-dropped 'mcons 1 2) (test-dropped 'box 1) (let ([test-multi (lambda (cons-name) (test-dropped cons-name 1 2) (test-dropped cons-name 1 2 3) (test-dropped cons-name 1) (test-dropped cons-name))]) (test-multi 'list) (test-multi 'list*) (test-multi 'vector) (test-multi 'vector-immutable))) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Check bytecode verification of lifted functions (let ([check (lambda (expr) (let-values ([(r w) (make-pipe)]) (write (compile expr) w) (parameterize ([read-accept-compiled #t]) (read r))))]) (check '(module m mzscheme (provide f) (define (f x) (let loop ([n 0]) (set! x (+ n 1)) ; close over mutated variable (loop n #f) (loop n))))) (check '(module m mzscheme (provide f) (define s (make-string 10)) (define (f x) (let loop ([n 0]) (set! x (+ n 1)) ; close over mutated variable (loop n s) ; and refer to global (loop n)))))) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Make sure "mutated?" flag isn't confused with "ready" flag: (module bad-order mzscheme (define (f) (printf "~a\n" i)) (f) (define i 9) (set! i 10)) (err/rt-test (dynamic-require ''bad-order #f)) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Check lifting of a function with only an unused rest arg: (test 1 'continue (let/ec foo (let ([continue (lambda extras (foo 1))]) (+ 1 (continue))))) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; call-with-values optimization ;; should get converted to let: (module cwv-1 mzscheme (define (cwv-1-f x) (call-with-values (lambda () (+ x 3)) (lambda (y) (+ y 2)))) (provide cwv-1-f)) (require 'cwv-1) (test 15 cwv-1-f 10) ;; known function doesn't expect 1 argument (module cwv-2 mzscheme (define (cwv-2-f x) (call-with-values (lambda () (+ x 3)) (lambda (y z) (+ y 2)))) (provide cwv-2-f)) (require 'cwv-2) (err/rt-test (cwv-2-f 10) exn:fail:contract:arity?) ;; known function, unknown number of results: (module cwv-3 mzscheme (define (cwv-3-f g) (call-with-values (lambda () (g)) (lambda (y) (+ y 2)))) (provide cwv-3-f)) (require 'cwv-3) (test 12 cwv-3-f (lambda () 10)) (err/rt-test (cwv-3-f (lambda () (values 1 2))) exn:fail:contract:arity?) ;; ditto, need 2 results: (module cwv-4 mzscheme (define (cwv-4-f g) (call-with-values (lambda () (g)) (lambda (y z) (+ y z 2)))) (provide cwv-4-f)) (require 'cwv-4) (test 12 cwv-4-f (lambda () (values 4 6))) (err/rt-test (cwv-4-f (lambda () 10)) exn:fail:contract:arity?) (err/rt-test (cwv-4-f (lambda () (values 1 2 10))) exn:fail:contract:arity?) ;; unknown first function: (module cwv-5 mzscheme (define (cwv-5-f g) (call-with-values g (lambda (y) (+ y 2)))) (provide cwv-5-f)) (require 'cwv-5) (test 12 cwv-5-f (lambda () 10)) (err/rt-test (cwv-5-f (lambda () (values 1 2))) exn:fail:contract:arity?) ;; ditto, need 2 results: (module cwv-6 mzscheme (define (cwv-6-f g) (call-with-values g (lambda (y z) (+ y z 2)))) (provide cwv-6-f)) (require 'cwv-6) (test 12 cwv-6-f (lambda () (values 4 6))) (err/rt-test (cwv-6-f (lambda () 10)) exn:fail:contract:arity?) (err/rt-test (cwv-6-f (lambda () (values 1 2 10))) exn:fail:contract:arity?) ;; unknown second function: (module cwv-2-1 mzscheme (define (cwv-2-1-f x h) (call-with-values (lambda () (+ x 3)) h)) (provide cwv-2-1-f)) (require 'cwv-2-1) (test 15 cwv-2-1-f 10 (lambda (y) (+ y 2))) ;; unknown function doesn't expect 1 argument (module cwv-2-2 mzscheme (define (cwv-2-2-f x h) (call-with-values (lambda () (+ x 3)) h)) (provide cwv-2-2-f)) (require 'cwv-2-2) (err/rt-test (cwv-2-2-f 10 (lambda (y z) (+ y 2))) exn:fail:contract:arity?) ;; known function, unknown number of results: (module cwv-2-3 mzscheme (define (cwv-2-3-f g h) (call-with-values (lambda () (g)) h)) (provide cwv-2-3-f)) (require 'cwv-2-3) (test 12 cwv-2-3-f (lambda () 10) (lambda (y) (+ y 2))) (test 23 cwv-2-3-f (lambda () (values 10 11)) (lambda (y z) (+ y z 2))) (err/rt-test (cwv-2-3-f (lambda () (values 1 2)) (lambda (y) (+ y 2))) exn:fail:contract:arity?) (err/rt-test (cwv-2-3-f (lambda () 10) (lambda (y z) (+ y 2))) exn:fail:contract:arity?) (err/rt-test (cwv-2-3-f (lambda () (values 1 2 3)) (lambda (y z) (+ y 2))) exn:fail:contract:arity?) ;; unknown first function: (module cwv-2-5 mzscheme (define (cwv-2-5-f g h) (call-with-values g h)) (provide cwv-2-5-f)) (require 'cwv-2-5) (test 12 cwv-2-5-f (lambda () 10) (lambda (y) (+ y 2))) (err/rt-test (cwv-2-5-f (lambda () (values 1 2)) (lambda (y) (+ y 2))) exn:fail:contract:arity?) (err/rt-test (cwv-2-5-f (lambda () 1) (lambda (y z) (+ y 2))) exn:fail:contract:arity?) (err/rt-test (cwv-2-5-f (lambda () (values 1 2 3)) (lambda (y z) (+ y 2))) exn:fail:contract:arity?) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (report-errs)