Skip to content
This repository was archived by the owner on Sep 13, 2019. It is now read-only.

Commit 5ade1ed

Browse files
committed
add support for an unsafe compilation mode
For now, unsafe mode is only accessible via `compile-linklet`, where it can be used to compile the expander in unsafe mode. Also add `vector*-length`, `vector*-ref`, `vector*-set!`, `unbox*`, and `set-box*!`, which can be converted in unsafe mode to the unsafe variants.
1 parent 3e8a8d4 commit 5ade1ed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+11951
-10135
lines changed

pkgs/base/info.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
(define collection 'multi)
1414

15-
(define version "6.90.0.14")
15+
(define version "6.90.0.15")
1616

1717
(define deps `("racket-lib"
1818
["racket" #:version ,version]))

pkgs/compiler-lib/compiler/decompile.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@
169169
(match expr
170170
[(struct toplevel (depth pos const? ready?))
171171
(decompile-tl expr globs stack closed #f)]
172-
[(struct varref (constant? tl dummy))
172+
[(struct varref (tl dummy constant? from-unsafe?))
173173
`(#%variable-reference . ,(cond
174174
[(not tl) '()]
175175
[(eq? tl #t) '(<constant-local>)]

pkgs/compiler-lib/compiler/demodularizer/gc.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
(for-each used! forms)]
6262
[(seq forms)
6363
(for-each used! forms)]
64-
[(varref constant? toplevel dummy)
64+
[(varref toplevel dummy constant? unsafe?)
6565
(used! toplevel)
6666
(used! dummy)]
6767
[(assign id rhs undef-ok?)

pkgs/compiler-lib/compiler/demodularizer/remap.rkt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@
5555
(beg0 (map remap forms))]
5656
[(seq forms)
5757
(seq (map remap forms))]
58-
[(varref constant? toplevel dummy)
59-
(varref constant? (remap toplevel) (remap dummy))]
58+
[(varref toplevel dummy constant? unsafe?)
59+
(varref (remap toplevel) (remap dummy) constant? unsafe?)]
6060
[(assign id rhs undef-ok?)
6161
(assign (remap id) (remap rhs) undef-ok?)]
6262
[(apply-values proc args-expr)

pkgs/racket-doc/scribblings/raco/zo-struct.scrbl

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -419,15 +419,21 @@ binding, constructor, etc.}
419419
@racket[seq] is never in tail position, even if it is the only
420420
expression in the list.}
421421

422-
@defstruct+[(varref expr) ([constant? boolean?]
423-
[toplevel (or/c toplevel? #t)]
424-
[dummy (or/c toplevel? #f)])]{
422+
@defstruct+[(varref expr) ([toplevel (or/c toplevel? #t)]
423+
[dummy (or/c toplevel? #f)]
424+
[constant? boolean?]
425+
[from-unsafe? boolean?])]{
425426
Represents a @racket[#%variable-reference] form. The @racket[toplevel]
426427
field is @racket[#t] if the original reference was to a constant local
427428
binding. The @racket[dummy] field
428429
accesses a variable bucket that strongly references its namespace (as
429430
opposed to a normal variable bucket, which only weakly references its
430-
namespace); it can be @racket[#f].}
431+
namespace); it can be @racket[#f].
432+
433+
The value of @racket[constant?] is true when the @racket[toplevel]
434+
field is not @racket[#t] but the referenced variable is known to be
435+
constant. The value of @racket[from-unsafe?] is true when the module
436+
that created the reference was compiled in unsafe mode.}
431437

432438
@defstruct+[(assign expr)
433439
([id toplevel?]

pkgs/racket-doc/scribblings/reference/data.scrbl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,18 @@ For any @racket[v], @racket[(unbox (box v))] returns @racket[v].
119119
Sets the content of @racket[box] to @racket[v].}
120120

121121

122+
@deftogether[(
123+
@defproc[(unbox* [box (and box? (not/c impersonator?))]) any/c]
124+
@defproc[(set-box*! [box (and/c box? (not/c immutable?) (not/c impersonator?))]
125+
[v any/c]) void?]
126+
)]{
127+
128+
Like @racket[unbox] and @racket[set-box!], but constrained to work on
129+
boxes that are not @tech{impersonators}.
130+
131+
@history[#:added "6.90.0.15"]}
132+
133+
122134
@defproc[(box-cas! [box (and/c box? (not/c immutable?) (not/c impersonator?))]
123135
[old any/c]
124136
[new any/c])

pkgs/racket-doc/scribblings/reference/linklet.scrbl

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#lang scribble/doc
22
@(require "mz.rkt"
3-
(for-label racket/linklet))
3+
(for-label racket/linklet
4+
racket/unsafe/ops))
45

56
@title[#:tag "linklets"]{Linklets and the Core Compiler}
67

@@ -119,15 +120,17 @@ otherwise.}
119120
[name any/c #f]
120121
[import-keys #f #f]
121122
[get-import #f #f]
122-
[serializable? any/c #t])
123+
[serializable? any/c #t]
124+
[unsafe-mode? any/c #f])
123125
linklet?]
124126
[(compile-linklet [form (or/c correlated? any/c)]
125127
[name any/c]
126128
[import-keys vector?]
127129
[get-import (or/c #f (any/c . -> . (values (or/c linklet? instance? #f)
128130
(or/c vector? #f))))
129131
#f]
130-
[serializable? any/c #t])
132+
[serializable? any/c #t]
133+
[unsafe-mode? any/c #f])
131134
(values linklet? vector?)])]{
132135

133136
Takes an S-expression or @tech{correlated object} for a
@@ -166,7 +169,21 @@ When @racket[import-keys] is not @racket[#f], then the compiler is
166169
allowed to grow or shrink the set of imported instances for the
167170
linklet. The result vector specifies the keys of the imports for the
168171
returned linklet. Any key that is @racket[#f] or a @tech{linklet instance}
169-
must be preserved intact, however.}
172+
must be preserved intact, however.
173+
174+
If @racket[unsafe-mode?] is true, then the linklet is compiled in
175+
@deftech{unsafe mode}: uses of safe operations within the linklet can
176+
be converted to unsafe operations on the assumption that the relevant
177+
contracts are satisfied. For example, @racket[car] is converted to
178+
@racket[unsafe-car]. Some substituted unsafe operations may not have
179+
directly accessible names, such as the unsafe variant of
180+
@racket[in-list] that can be substituted in @tech{unsafe mode}. An
181+
unsafe operation is substituted only if its (unchecked) contract is
182+
subsumed by the safe operation's contract. The fact that the linklet
183+
is compiled in @tech{unsafe mode} can be exposed through
184+
@racket[variable-reference-from-unsafe?] using a variable reference
185+
produced by a @racket[#%variable-reference] form within the module
186+
body.}
170187

171188

172189
@defproc*[([(recompile-linklet [linklet linklet?]

pkgs/racket-doc/scribblings/reference/namespaces.scrbl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,3 +503,27 @@ Returns the declaration @tech{inspector} (see @secref["modprotect"])
503503
for the module of @racket[varref], where @racket[varref] must refer to
504504
an anonymous module variable as produced by
505505
@racket[(#%variable-reference)].}
506+
507+
508+
@defproc[(variable-reference-from-unsafe? [varref variable-reference?]) boolean?]{
509+
510+
Returns @racket[#t] if the module of the variable reference itself
511+
(not necessarily a referenced variable) is compiled in unsafe mode,
512+
@racket[#f] otherwise.
513+
514+
The @racket[variable-reference-from-unsafe?] procedure is intended for
515+
use as
516+
517+
@racketblock[
518+
(variable-reference-from-unsafe? (#%variable-reference))
519+
]
520+
521+
which the compiler can optimize to a literal @racket[#t] or
522+
@racket[#f] (since the enclosing module is being compiled in
523+
@tech{unsafe mode} or not).
524+
525+
Currently @tech{unsafe mode} can be controlled only through the
526+
@tech{linklet} interface, but future changes may make @tech{unsafe
527+
mode} more accessible at the module level.
528+
529+
@history[#:added "6.12.0.4"]}

pkgs/racket-doc/scribblings/reference/unsafe.scrbl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,7 @@ fixnum).}
655655

656656
@history[#:added "6.9.0.2"]
657657
}
658+
658659
@; ------------------------------------------------------------------------
659660

660661
@include-section["unsafe-undefined.scrbl"]

pkgs/racket-doc/scribblings/reference/vectors.scrbl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,23 @@ slot is position @racket[0], and the last slot is one less than
7272

7373
Updates the slot @racket[pos] of @racket[vec] to contain @racket[v].}
7474

75+
76+
@deftogether[(
77+
@defproc[(vector*-length [vec (and/c vector? (not/c impersonator?))]) exact-nonnegative-integer?]
78+
@defproc[(vector*-ref [vec (and/c vector? (not/c impersonator?))] [pos exact-nonnegative-integer?]) any/c]
79+
@defproc[(vector*-set! [vec (and/c vector? (not/c immutable?) (not/c impersonator?))]
80+
[pos exact-nonnegative-integer?]
81+
[v any/c])
82+
void?]
83+
)]{
84+
85+
Like @racket[vector-length], @racket[vector-ref], and
86+
@racket[vector-set!], but constrained to work on vectors that are not
87+
@tech{impersonators}.
88+
89+
@history[#:added "6.90.0.15"]}
90+
91+
7592
@defproc[(vector-cas! [vec (and/c vector? (not/c immutable?) (not/c impersonator?))]
7693
[pos exact-nonnegative-integer?]
7794
[old-v any/c]

pkgs/racket-test-core/tests/racket/jitinline.rktl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,8 +702,14 @@
702702
(bin-exact 'b 'vector-ref #(a b c) 1)
703703
(bin-exact 'c 'vector-ref #(a b c) 2)
704704

705+
(bin-exact 'a 'vector*-ref #(a b c) 0 #t)
706+
(bin-exact 'b 'vector*-ref #(a b c) 1)
707+
(bin-exact 'c 'vector*-ref #(a b c) 2)
708+
705709
(un-exact 'a 'unbox (box 'a) #t)
710+
(un-exact 'a 'unbox* (box 'a) #t)
706711
(un-exact 3 'vector-length (vector 'a 'b 'c) #t)
712+
(un-exact 3 'vector*-length (vector 'a 'b 'c) #t)
707713

708714
(bin-exact 1.1 'flvector-ref (flvector 1.1 2.2 3.3) 0 #t)
709715
(bin-exact 3.3 'flvector-ref (flvector 1.1 2.2 3.3) 2)
@@ -857,6 +863,7 @@
857863
3rd-all-ok?))
858864
'(0 1 2))))])
859865
(test-setter make-vector #f 7 'vector-set! vector-set! vector-ref #t)
866+
(test-setter make-vector #f 7 'vector*-set! vector*-set! vector*-ref #t)
860867
(test-setter make-bytes 0 7 'bytes-set! bytes-set! bytes-ref #f)
861868
(test-setter make-string #\a #\7 'string-set! string-set! string-ref #f)
862869
(test-setter make-flvector 1.0 7.0 'flvector-set! flvector-set! flvector-ref #f)
@@ -869,14 +876,29 @@
869876
(test-setter (lambda (n v) (chap-vec (chap-vec (make-vector n v))))
870877
#f 7 'vector-set! vector-set! vector-ref #t)))
871878

879+
(err/rt-test (apply (list-ref (list (lambda (v) (vector*-length v))) (random 1))
880+
(list (chaperone-vector (vector 1 2 3) (lambda (vec i val) val) (lambda (vec i val) val)))))
881+
(err/rt-test (apply (list-ref (list (lambda (v) (vector*-ref v 0))) (random 1))
882+
(list (chaperone-vector (vector 1 2 3) (lambda (vec i val) val) (lambda (vec i val) val)))))
883+
(err/rt-test (apply (list-ref (list (lambda (v) (unbox* v))) (random 1))
884+
(list (chaperone-box (box 1) (lambda (b v) v) (lambda (b v) v)))))
885+
872886
(err/rt-test (apply (list-ref (list (lambda (v) (vector-set! v 0 #t))) (random 1))
873887
(list (vector-immutable 1 2 3))))
888+
(err/rt-test (apply (list-ref (list (lambda (v) (vector*-set! v 0 #t))) (random 1))
889+
(list (vector-immutable 1 2 3))))
890+
(err/rt-test (apply (list-ref (list (lambda (v) (vector*-set! v 0 #t))) (random 1))
891+
(list (chaperone-vector (vector 1 2 3) (lambda (vec i val) val) (lambda (vec i val) val)))))
874892
(err/rt-test (apply (list-ref (list (lambda (s) (string-set! s 0 #\a))) (random 1))
875893
(list "123")))
876894
(err/rt-test (apply (list-ref (list (lambda (s) (bytes-set! s 0 0))) (random 1))
877895
(list #"123")))
878896
(err/rt-test (apply (list-ref (list (lambda (b) (set-box! b #t))) (random 1))
879897
(list (box-immutable 1))))
898+
(err/rt-test (apply (list-ref (list (lambda (b) (set-box*! b #t))) (random 1))
899+
(list (box-immutable 1))))
900+
(err/rt-test (apply (list-ref (list (lambda (v) (set-box*! v 'no))) (random 1))
901+
(list (chaperone-box (box 1) (lambda (b v) v) (lambda (b v) v)))))
880902

881903
(let ([v (box 1)])
882904
(check-error-message 'set-box! (eval `(lambda (x) (set-box! x 10))))

pkgs/zo-lib/compiler/zo-marshal.rkt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -615,9 +615,11 @@
615615
(out-anything (protect-quote key) out)
616616
(out-anything (protect-quote val) out)
617617
(out-anything (protect-quote body) out)]
618-
[(struct varref (constant? expr dummy))
618+
[(struct varref (expr dummy constant? from-unsafe?))
619619
(out-byte CPT_VARREF out)
620-
(out-number (if constant? 1 0) out)
620+
(out-number (bitwise-ior (if constant? 1 0)
621+
(if from-unsafe? 2 0))
622+
out)
621623
(out-anything expr out)
622624
(out-anything dummy out)]
623625
[(struct inline-variant (direct inline))

pkgs/zo-lib/compiler/zo-parse.rkt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,10 @@
633633
(define undef-ok? (not (zero? (read-compact-number cp))))
634634
(make-assign (read-compact cp) (read-compact cp) undef-ok?)]
635635
[(varref)
636-
(make-varref (not (zero? (read-compact-number cp))) (read-compact cp) (read-compact cp))]
636+
(define flags (read-compact-number cp))
637+
(make-varref (read-compact cp) (read-compact cp)
638+
(bitwise-bit-set? flags 1)
639+
(bitwise-bit-set? flags 2))]
637640
[(apply-values)
638641
(make-apply-values (read-compact cp) (read-compact cp))]
639642
[(other-form)

pkgs/zo-lib/compiler/zo-structs.rkt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,10 @@
115115
[val (or/c expr? seq? any/c)]
116116
[body (or/c expr? seq? any/c)])) ; `with-continuation-mark'
117117
(define-form-struct (beg0 expr) ([seq (listof (or/c expr? seq? any/c))])) ; `begin0'
118-
(define-form-struct (varref expr) ([constant? boolean?] [toplevel (or/c toplevel? #f #t symbol?)] [dummy (or/c toplevel? #f)])) ; `#%variable-reference'
118+
(define-form-struct (varref expr) ([toplevel (or/c toplevel? #f #t symbol?)]
119+
[dummy (or/c toplevel? #f)]
120+
[constant? boolean?]
121+
[from-unsafe? boolean?]))
119122
(define-form-struct (assign expr) ([id toplevel?] [rhs (or/c expr? seq? any/c)] [undef-ok? boolean?])) ; top-level or module-level set!
120123
(define-form-struct (apply-values expr) ([proc (or/c expr? seq? any/c)] [args-expr (or/c expr? seq? any/c)])) ; `(call-with-values (lambda () ,args-expr) ,proc)
121124
(define-form-struct (with-immed-mark expr) ([key (or/c expr? seq? any/c)]

racket/collects/racket/private/for.rkt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,9 @@
388388
(raise-syntax-error #f
389389
"illegal outside of a loop or comprehension binding" stx))
390390

391+
(define-syntax-rule (unless-unsafe e)
392+
(unless (variable-reference-from-unsafe? (#%variable-reference)) e))
393+
391394
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
392395
;; streams & sequences
393396

@@ -807,7 +810,7 @@
807810
;;outer bindings
808811
([(ht) ht-expr])
809812
;; outer check
810-
(CHECK-SEQ ht)
813+
(unless-unsafe (CHECK-SEQ ht))
811814
;; loop bindings
812815
([i (-first ht)])
813816
;; pos check
@@ -1901,7 +1904,7 @@
19011904
([(start) a] [(end) b] [(inc) step])
19021905
;; outer check:
19031906
;; let `check-range' report the error:
1904-
(check-range start end inc)
1907+
(unless-unsafe (check-range start end inc))
19051908
;; loop bindings:
19061909
([pos start])
19071910
;; pos check
@@ -1942,7 +1945,7 @@
19421945
([(start) start-expr])
19431946
;; outer check:
19441947
;; let `check-naturals' report the error:
1945-
(check-naturals start)
1948+
(unless-unsafe (check-naturals start))
19461949
;; loop bindings:
19471950
([pos start])
19481951
;; pos check
@@ -1971,7 +1974,7 @@
19711974
;;outer bindings
19721975
([(lst) lst-expr])
19731976
;; outer check
1974-
(check-list lst)
1977+
(unless-unsafe (check-list lst))
19751978
;; loop bindings
19761979
([lst lst])
19771980
;; pos check
@@ -2025,7 +2028,7 @@
20252028
;;outer bindings
20262029
([(lst) lst-expr])
20272030
;; outer check
2028-
(unless (stream? lst) (in-stream lst))
2031+
(unless (unless-unsafe (stream? lst)) (in-stream lst))
20292032
;; loop bindings
20302033
([lst lst])
20312034
;; pos check

racket/src/cify/inline.rkt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@
1818
[(cons) (and (= n 2) can-gc? 'scheme_make_pair)]
1919
[(list*) (and (= n 2) can-gc? 'scheme_make_pair)]
2020
[(list) (and (or (= n 1) (= n 2)) can-gc? (if (= n 1) 'c_make_list1 'c_make_list2))]
21-
[(unbox unsafe-unbox unsafe-unbox*) (and (= n 1) 'c_box_ref)]
21+
[(unbox unsafe-unbox unbox* unsafe-unbox*) (and (= n 1) 'c_box_ref)]
2222
[(weak-box-value) (and (or (= n 1) (= n 2)) 'c_weak_box_value)]
23-
[(set-box! unsafe-set-box! unsafe-set-box*!) (and (= n 2) 'c_box_set)]
23+
[(set-box! set-box*! unsafe-set-box! unsafe-set-box*!) (and (= n 2) 'c_box_set)]
2424
[(vector-ref unsafe-vector-ref) (and (= n 2) 'c_vector_ref)]
25-
[(vector*-set! unsafe-vector*-set! unsafe-vector*-set!) (and (= n 3) 'c_vector_set)]
26-
[(unsafe-vector*-ref) (and (= n 2) 'c_authentic_vector_ref)]
27-
[(vector-length unsafe-vector-length unsafe-vector*-length) (and (= n 1) 'c_vector_length)]
25+
[(vector*-ref unsafe-vector*-ref) (and (= n 2) 'c_authentic_vector_ref)]
26+
[(vector-set! unsafe-vector-set! vector*-set! unsafe-vector*-set!) (and (= n 3) 'c_vector_set)]
27+
[(vector-length unsafe-vector-length vector*-length unsafe-vector*-length) (and (= n 1) 'c_vector_length)]
2828
[(string-ref unsafe-string-ref) (and (= n 2) can-gc? 'c_string_ref)]
2929
[(bytes-ref unsafe-bytes-ref) (and (= n 2) 'c_bytes_ref)]
3030
[(fx+ unsafe-fx+) (and (= n 2) 'c_int_add)]

racket/src/cs/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ PRIMITIVES_TABLES = primitive/kernel.ss primitive/unsafe.ss primitive/flfxnum.ss
2222

2323
CONVERT_DEPS = convert.rkt $(PRIMITIVES_TABLES)
2424

25-
CONVERT = $(RACKET) -l- raco make convert.rkt && $(RACKET) convert.rkt
25+
CONVERT = $(RACKET) -l- raco make convert.rkt && $(RACKET) convert.rkt $(UNSAFE_COMP)
2626

2727
THREAD_DEPS = chezpart.so rumble.so
2828
IO_DEPS = $(THREAD_DEPS) thread.so

racket/src/cs/convert.rkt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
(define skip-export? #f)
1414
(define for-cify? #f)
15+
(define unsafe-mode? #f)
1516

1617
(define-values (in-file out-file)
1718
(command-line
@@ -20,6 +21,8 @@
2021
(set! skip-export? #t)]
2122
[("--for-cify") "Keep `make-struct-type` as-is, etc."
2223
(set! for-cify? #t)]
24+
[("--unsafe") "Compile for unsafe mode"
25+
(set! unsafe-mode? #t)]
2326
#:args
2427
(in-file out-file)
2528
(values in-file out-file)))
@@ -121,7 +124,7 @@
121124
(printf "Schemify...\n")
122125
(define body
123126
(time
124-
(schemify-body bodys/constants-lifted (lambda (old-v new-v) new-v) prim-knowns #hasheq() #hasheq() for-cify?)))
127+
(schemify-body bodys/constants-lifted (lambda (old-v new-v) new-v) prim-knowns #hasheq() #hasheq() for-cify? unsafe-mode?)))
125128
(printf "Lift...\n")
126129
;; Lift functions to aviod closure creation:
127130
(define lifted-body

0 commit comments

Comments
 (0)