197 lines
7.1 KiB
Racket
197 lines
7.1 KiB
Racket
#lang scheme
|
|
(require redex/reduction-semantics
|
|
scheme/system
|
|
scheme/flonum
|
|
scheme/future)
|
|
|
|
#|
|
|
The JIT-inlined primitives are listed in `compiler/decompile' in
|
|
`annotate-inline'. Plus the unboxed ones in `annoted-unboxed'. Those
|
|
are probably interesting.
|
|
|
|
Other interesting primitives would be ones that consume procedures to
|
|
tail-call, such as `apply' or `hash-ref'.
|
|
|
|
Multiple return values are also interesting.
|
|
|
|
Errors/exceptions and other kinds of control?
|
|
|
|
(define (annotate-inline a)
|
|
(if (and (symbol? (car a))
|
|
(case (length a)
|
|
[(2) (memq (car a) '(not null? pair? mpair? symbol?
|
|
syntax? char? boolean?
|
|
number? real? exact-integer?
|
|
fixnum? inexact-real?
|
|
procedure? vector? box? string? bytes? eof-object?
|
|
zero? negative? exact-nonnegative-integer?
|
|
exact-positive-integer?
|
|
car cdr caar cadr cdar cddr
|
|
mcar mcdr unbox vector-length syntax-e
|
|
add1 sub1 - abs bitwise-not
|
|
list list* vector vector-immutable box))]
|
|
[(3) (memq (car a) '(eq? = <= < >= >
|
|
bitwise-bit-set? char=?
|
|
+ - * / quotient remainder min max bitwise-and bitwise-ior bitwise-xor
|
|
arithmetic-shift vector-ref string-ref bytes-ref
|
|
set-mcar! set-mcdr! cons mcons
|
|
list list* vector vector-immutable))]
|
|
[(4) (memq (car a) '(vector-set! string-set! bytes-set!
|
|
list list* vector vector-immutable
|
|
+ - * / min max bitwise-and bitwise-ior bitwise-xor))]
|
|
[else (memq (car a) '(list list* vector vector-immutable
|
|
+ - * / min max bitwise-and bitwise-ior bitwise-xor))]))
|
|
(cons '#%in a)
|
|
a))
|
|
|
|
(define (annotate-unboxed args a)
|
|
(define (unboxable? e s)
|
|
(cond
|
|
[(localref? e) #t]
|
|
[(toplevel? e) #t]
|
|
[(eq? '#%flonum (car s)) #t]
|
|
[(not (expr? e)) #t]
|
|
[else #f]))
|
|
(if (and (symbol? (car a))
|
|
(case (length a)
|
|
[(2) (memq (car a) '(flabs flsqrt ->fl
|
|
unsafe-flabs
|
|
unsafe-flsqrt
|
|
unsafe-fx->fl
|
|
flsin flcos fltan
|
|
flasin flacos flatan
|
|
flexp fllog
|
|
flfloor flceiling flround fltruncate
|
|
flmin flmax
|
|
unsafe-flmin unsafe-flmax))]
|
|
[(3) (memq (car a) '(fl+ fl- fl* fl/
|
|
fl< fl> fl<= fl>= fl=
|
|
flvector-ref
|
|
unsafe-fl+ unsafe-fl- unsafe-fl* unsafe-fl/
|
|
unsafe-fl< unsafe-fl>
|
|
unsafe-fl=
|
|
unsafe-fl<= unsafe-fl>=
|
|
unsafe-flvector-ref
|
|
unsafe-f64vector-ref))]
|
|
|
|
[(4) (memq (car a) '(flvector-set!
|
|
unsafe-flvector-set!
|
|
unsafe-f64vector-set!))]
|
|
[else #f])
|
|
(andmap unboxable? args (cdr a)))
|
|
(cons '#%flonum a)
|
|
a))
|
|
|
|
|#
|
|
|
|
(define-language fut
|
|
;; single value, non-error expressions
|
|
(exp (any->any/prim exp)
|
|
fl-exp
|
|
(begin exp exp ...)
|
|
(if (fl-fl->bool/prim fl-exp fl-exp)
|
|
exp
|
|
exp)
|
|
(let-values ([(a b) 2v-exp])
|
|
a)
|
|
(hash-ref (make-hash) 'not-there (λ () exp))
|
|
(with-handlers ((exn:fail? (λ (x) 'failed))) (begin bad-exp 'passed)))
|
|
|
|
;; expressions that probably signal a runtime error
|
|
(bad-exp exp
|
|
2v-exp
|
|
(prim bad-exp ...)
|
|
(if bad-exp bad-exp bad-exp)
|
|
(begin bad-exp bad-exp ...)
|
|
(values bad-exp ...))
|
|
|
|
;; expressions that produce two multiple values
|
|
(2v-exp (hash-ref (make-hash) 'not-there (λ () 2v-exp))
|
|
(values exp exp)
|
|
(if exp 2v-exp 2v-exp))
|
|
|
|
(fl-exp fl-val
|
|
(fl-fl->fl/prim fl-exp fl-exp)
|
|
(fl->fl/prim fl-exp)
|
|
(apply fl-fl->fl/prim (list fl-exp fl-exp)))
|
|
|
|
(base-val stx sym num fl-val)
|
|
(stx #'exp)
|
|
(sym 'x 'y 'z)
|
|
(num 0 -1 1 1/2 5/3 (sqrt 2))
|
|
(fl-val 1.0 2.0 -1.0 (sqrt 2))
|
|
|
|
(prim exact-int->fl
|
|
fl->fl/prim
|
|
fl-fl->fl/prim
|
|
fl-fl->bool/prim)
|
|
|
|
(exact-int->fl ->fl) ;; unused
|
|
(fl->fl/prim flabs flsqrt
|
|
flsin flcos fltan
|
|
flasin flacos flatan
|
|
flexp fllog
|
|
flfloor flceiling flround fltruncate)
|
|
|
|
(fl-fl->fl/prim fl+ fl- fl* fl/ flmin flmax)
|
|
(fl-fl->bool/prim fl< fl> fl<= fl>= fl=)
|
|
|
|
(any->any/prim not pair? mpair? symbol? syntax?
|
|
syntax? char? boolean?
|
|
number? real? exact-integer?
|
|
fixnum? inexact-real?
|
|
procedure? vector? box? string? bytes? eof-object?))
|
|
|
|
(define iterations-to-try 10000)
|
|
|
|
(define gen-exp (let ([f (generate-term fut exp)])
|
|
(λ () (f 10))))
|
|
|
|
(define (write-and-try-prog prog)
|
|
(call-with-output-file "tmp.rkt"
|
|
(λ (port)
|
|
(display "#lang scheme\n" port)
|
|
(pretty-print '(require scheme/future scheme/flonum) port)
|
|
(pretty-print prog port))
|
|
#:exists 'truncate)
|
|
(unless (system "./mzscheme3m tmp.rkt")
|
|
(error 'system-failed)))
|
|
|
|
(define (gen-prog)
|
|
(let* ([expressions (gen-expressions)]
|
|
[vars (build-list (length expressions)
|
|
(λ (x) (string->symbol (format "f~a" x))))])
|
|
`(let (,@(map (λ (x y) `[,x (future (λ () (let loop ([i ,iterations-to-try])
|
|
(unless (zero? i)
|
|
,y
|
|
(loop (- i 1))))))])
|
|
vars
|
|
expressions))
|
|
,@(map (λ (x) `(touch ,x)) vars))))
|
|
|
|
;; gen-expressions : -> (non-empty-listof expressions)
|
|
;; currently tailored to the two processor case.
|
|
(define (gen-expressions)
|
|
(case (random 5)
|
|
[(0 1 2) (let ([e (gen-exp)])
|
|
(list e e))]
|
|
[(3) (list (gen-exp)
|
|
(gen-exp))]
|
|
[(4) (list (gen-exp)
|
|
(gen-exp)
|
|
(gen-exp))]))
|
|
|
|
(define-namespace-anchor ns-here)
|
|
(let ([seed (+ 1 (random (expt 2 30)))])
|
|
(printf "DrDr Ignore! random-seed ~s\n" seed)
|
|
(random-seed seed))
|
|
|
|
(let loop ([n 32])
|
|
(unless (zero? n)
|
|
(printf ".") (flush-output)
|
|
(let ([p (gen-prog)])
|
|
;(pretty-print p)
|
|
(eval p (namespace-anchor->namespace ns-here)))
|
|
(loop (- n 1))))
|
|
(newline)
|