
Correct the second-biggest design flaw in the bytecode optimizer: instead of using a de Bruijn-like representation of variable references in the optimizer pass, use variable objects. This change is intended to address limitations on programs like the one in http://bugs.racket-lang.org/query/?cmd=view&pr=15244 where the optimizer could not perform a straightforward-seeming transformation due to the constraints of its representation. Besides handling the bug-report example better, there are other minor optimization improvements as a side effect of refactoring the code. To simplify the optimizer's implementation (e.g., eliminate code that I didn't want to convert) and also preserve success for optimizer tests, the optimizer ended up getting a little better at flattening and eliminating `let` forms and `begin`--`let` combinations. Overall, the optimizer tests in "optimize.rktl" pass, which helps ensure that no optimizations were lost. I had to modify just a few tests: * The test at line 2139 didn't actually check against reordering as intended, but was instead checking that the bug-report limitation was intact (and now it's not). * The tests around 3095 got extra `p` references, because the optimizer is now able to eliminate an unused `let` around the second case, but it still doesn't discover the unusedness of `p` in the first case soon enough to eliminate the `let`. The extra references prevent eliminating the `let` in both case, since that's not the point of the tests. Thanks to Gustavo for taking a close look at the changes. LocalWords: pkgs rkt
32 lines
930 B
Racket
32 lines
930 B
Racket
#lang racket/base
|
|
|
|
;; Test the existence of forged generic functions for
|
|
;; gen:custom-write and gen:equal+hash
|
|
|
|
(require racket/generic)
|
|
|
|
(struct tuple (ref)
|
|
#:methods gen:custom-write
|
|
[(define/generic super write-proc)
|
|
(define (write-proc v p w)
|
|
(super v p w))]
|
|
#:methods gen:equal+hash
|
|
[(define/generic super-eq equal-proc)
|
|
(define/generic hash1 hash-proc)
|
|
(define/generic hash2 hash2-proc)
|
|
(define (equal-proc a b e)
|
|
(super-eq (tuple-ref a) (tuple-ref b) e))
|
|
(define (hash-proc a h)
|
|
(hash1 (tuple-ref a) h))
|
|
(define (hash2-proc a h)
|
|
(hash2 (tuple-ref a) h))])
|
|
|
|
(module+ test
|
|
(require rackunit racket/port)
|
|
|
|
;; ok if these don't raise unbound id errors
|
|
(check-equal? (with-output-to-string (lambda () (write (tuple 5)))) "#0=#0#")
|
|
(check-equal? (tuple 5) (tuple 5))
|
|
(check-equal? (equal-hash-code (tuple 5)) 55)
|
|
(check-equal? (equal-secondary-hash-code (tuple 5)) 46))
|