diff --git a/collects/compiler/decompile.ss b/collects/compiler/decompile.ss index 819e86569b..8729a983b1 100644 --- a/collects/compiler/decompile.ss +++ b/collects/compiler/decompile.ss @@ -13,6 +13,7 @@ (let ([ns (make-base-empty-namespace)]) (parameterize ([current-namespace ns]) (namespace-require ''#%kernel) + (namespace-require ''#%unsafe) (for/list ([l (namespace-mapped-symbols)]) (cons l (with-handlers ([exn:fail? (lambda (x) #f)]) (compile l))))))] @@ -320,7 +321,7 @@ list list* vector vector-immutable box))] [(3) (memq (car a) '(eq? = <= < >= > bitwise-bit-set? char=? - + - * / min max bitwise-and bitwise-ior + + - * / quotient remainder min max bitwise-and bitwise-ior arithmetic-shift vector-ref string-ref bytes-ref set-mcar! set-mcdr! cons mcons list list* vector vector-immutable))] diff --git a/collects/compiler/zo-parse.ss b/collects/compiler/zo-parse.ss index 8af27954f9..397f585e31 100644 --- a/collects/compiler/zo-parse.ss +++ b/collects/compiler/zo-parse.ss @@ -113,9 +113,12 @@ (make-compilation-top ld prefix code)])) (define (read-resolve-prefix v) - (match v - [`(,i ,tv . ,sv) - (make-prefix i (vector->list tv) (vector->list sv))])) + (let-values ([(v unsafe?) (if (integer? (car v)) + (values v #f) + (values (cdr v) #t))]) + (match v + [`(,i ,tv . ,sv) + (make-prefix i (vector->list tv) (vector->list sv))]))) (define (read-unclosed-procedure v) (define CLOS_HAS_REST 1) diff --git a/collects/scheme/private/for.ss b/collects/scheme/private/for.ss index b644940001..7052024de4 100644 --- a/collects/scheme/private/for.ss +++ b/collects/scheme/private/for.ss @@ -4,6 +4,7 @@ "misc.ss" "define.ss" "letstx-scheme.ss" + '#%unsafe (for-syntax '#%kernel "stx.ss" "qqstx.ss" @@ -410,7 +411,7 @@ (define (:vector-gen v start stop step) (values ;; pos->element - (lambda (i) (vector-ref v i)) + (lambda (i) (unsafe-vector-ref v i)) ;; next-pos ;; Minor optimisation. I assume add1 is faster than \x.x+1 (if (= step 1) add1 (lambda (i) (+ i step))) @@ -953,32 +954,44 @@ (lambda (stx) (let loop ([stx stx]) (syntax-case stx () - [[(id) (_ a b step)] #`[(id) - (:do-in - ;; outer bindings: - ([(start) a] [(end) b] [(inc) step]) - ;; outer check: - (unless (and (real? start) (real? end) (real? inc)) - ;; let `in-range' report the error: - (in-range start end inc)) - ;; loop bindings: - ([pos start]) - ;; pos check - #,(cond - [(not (number? (syntax-e #'step))) - #`(if (step . >= . 0) (< pos end) (> pos end))] - [((syntax-e #'step) . >= . 0) - #'(< pos end)] - [else - #'(> pos end)]) - ;; inner bindings - ([(id) pos]) - ;; pre guard - #t - ;; post guard - #t - ;; loop args - ((+ pos inc)))]] + [[(id) (_ a b step)] (let ([all-fx? + (and (fixnum? (syntax-e #'a)) + (fixnum? (syntax-e #'b)) + (memq (syntax-e #'step) '(1 -1)))]) + #`[(id) + (:do-in + ;; outer bindings: + ([(start) a] [(end) b] [(inc) step]) + ;; outer check: + (unless (and (real? start) (real? end) (real? inc)) + ;; let `in-range' report the error: + (in-range start end inc)) + ;; loop bindings: + ([pos start]) + ;; pos check + #,(if all-fx? + ;; Special case, can use unsafe ops: + (cond + [((syntax-e #'step) . >= . 0) + #'(unsafe-fx< pos end)] + [else + #'(unsafe-fx> pos end)]) + ;; General case: + (cond + [(not (number? (syntax-e #'step))) + #`(if (step . >= . 0) (< pos end) (> pos end))] + [((syntax-e #'step) . >= . 0) + #'(< pos end)] + [else + #'(> pos end)])) + ;; inner bindings + ([(id) pos]) + ;; pre guard + #t + ;; post guard + #t + ;; loop args + ((#,(if all-fx? #'unsafe-fx+ #'+) pos inc)))])] [[(id) (_ a b)] (loop #'[(id) (_ a b 1)])] [[(id) (_ b)] (loop #'[(id) (_ 0 b 1)])] [_ #f])))) @@ -1035,19 +1048,19 @@ #t ;; post guard #t - ;; loop args - ((cdr lst)))]] + ;; loop args -- ok to use unsafe-cdr, since car passed + ((unsafe-cdr lst)))]] [_ #f]))) (define-for-syntax (vector-like-gen vector?-id - vector-length-id + unsafe-vector-length-id in-vector-id - vector-ref-id) + unsafe-vector-ref-id) (define (in-vector-like stx) (with-syntax ([vector? vector?-id] [in-vector in-vector-id] - [vector-length vector-length-id] - [vector-ref vector-ref-id]) + [unsafe-vector-length unsafe-vector-length-id] + [unsafe-vector-ref unsafe-vector-ref-id]) (syntax-case stx () ;; Fast case [((id) (_ vec-expr)) @@ -1057,75 +1070,80 @@ ([(vec len) (let ([vec vec-expr]) (unless (vector? vec) (in-vector vec)) - (values vec (vector-length vec)))]) + (values vec (unsafe-vector-length vec)))]) ;; outer check #f ;; loop bindings ([pos 0]) ;; pos check - (pos . < . len) + (pos . unsafe-fx< . len) ;; inner bindings - ([(id) (vector-ref vec pos)]) + ([(id) (unsafe-vector-ref vec pos)]) ;; pre guard #t ;; post guard #t ;; loop args - ((add1 pos)))]] + ((unsafe-fx+ 1 pos)))]] ;; General case [((id) (_ vec-expr start)) (in-vector-like (syntax ((id) (_ vec-expr start #f 1))))] [((id) (_ vec-expr start stop)) (in-vector-like (syntax ((id) (_ vec-expr start stop 1))))] [((id) (_ vec-expr start stop step)) - #`[(id) - (:do-in - ;; Outer bindings - ;; Prevent multiple evaluation - ([(v* stop*) (let ([vec vec-expr] - [stop* stop]) - (if (and (not stop*) (vector? vec)) - (values vec (vector-length vec)) - (values vec stop*)))] - [(start*) start] - [(step*) step]) - ;; Outer check - (when (or (not (vector? v*)) - (not (exact-integer? start*)) - (not (exact-integer? stop*)) - (not (exact-integer? step*)) - (zero? step*) - (and (< start* stop*) (< step* 0)) - (and (> start* stop*) (> step* 0))) - ;; Let in-vector report the error - (in-vector v* start* stop* step*)) - ;; Loop bindings - ([idx start*]) - ;; Pos guard - #,(cond - [(not (number? (syntax-e #'step))) + (let ([all-fx? (memq (syntax-e #'step) '(1 -1))]) + #`[(id) + (:do-in + ;; Outer bindings + ;; Prevent multiple evaluation + ([(v* stop*) (let ([vec vec-expr] + [stop* stop]) + (if (and (not stop*) (vector? vec)) + (values vec (unsafe-vector-length vec)) + (values vec stop*)))] + [(start*) start] + [(step*) step]) + ;; Outer check + (when (or (not (vector? v*)) + (not (exact-integer? start*)) + (not (exact-integer? stop*)) + (not (exact-integer? step*)) + (zero? step*) + (and (< start* stop*) (< step* 0)) + (and (> start* stop*) (> step* 0))) + ;; Let in-vector report the error + (in-vector v* start* stop* step*)) + ;; Loop bindings + ([idx start*]) + ;; Pos guard + #,(cond + [(not (number? (syntax-e #'step))) #`(if (step* . >= . 0) (< idx stop*) (> idx stop*))] - [((syntax-e #'step) . >= . 0) - #'(< idx stop*)] - [else - #'(> idx stop*)]) - ;; Inner bindings - ([(id) (vector-ref v* idx)]) - ;; Pre guard - #t - ;; Post guard - #t - ;; Loop args - ((+ idx step)))]] + [((syntax-e #'step) . >= . 0) + (if all-fx? + #'(unsafe-fx< idx stop*) + #'(< idx stop*))] + [else + (if all-fx? + #'(unsafe-fx> idx stop*) + #'(> idx stop*))]) + ;; Inner bindings + ([(id) (unsafe-vector-ref v* idx)]) + ;; Pre guard + #t + ;; Post guard + #t + ;; Loop args + ((#,(if all-fx? #'unsafe-fx+ #'+) idx step)))])] [_ #f]))) in-vector-like) (define-sequence-syntax *in-vector (lambda () #'in-vector) (vector-like-gen #'vector? - #'vector-length + #'unsafe-vector-length #'in-vector - #'vector-ref)) + #'unsafe-vector-ref)) (define-sequence-syntax *in-string (lambda () #'in-string) diff --git a/collects/scheme/unsafe/ops.ss b/collects/scheme/unsafe/ops.ss new file mode 100644 index 0000000000..9338488826 --- /dev/null +++ b/collects/scheme/unsafe/ops.ss @@ -0,0 +1,5 @@ +#lang scheme/base +(require '#%unsafe) + +(provide (all-from-out '#%unsafe)) + diff --git a/collects/scribblings/mzc/decompile.scrbl b/collects/scribblings/mzc/decompile.scrbl index 787d5cf13e..10f3de91c4 100644 --- a/collects/scribblings/mzc/decompile.scrbl +++ b/collects/scribblings/mzc/decompile.scrbl @@ -76,7 +76,9 @@ Many forms in the decompiled code, such as @scheme[module], @schemeidfont{#%in}, which indicates that the JIT compiler will inline the operation. (Inlining information is not part of the bytecode, but is instead based on an enumeration of primitives that - the JIT is known to handle specially.)} + the JIT is known to handle specially.) Operations from + @schememodname[scheme/unsafe/ops] are always inlined, so + @schemeidfont{#%in} is not shown for them.} @item{A form @scheme[(#%apply-values _proc _expr)] is equivalent to @scheme[(call-with-values (lambda () _expr) _proc)], but the run-time diff --git a/collects/scribblings/reference/reference.scrbl b/collects/scribblings/reference/reference.scrbl index 6d665f7005..85c2385518 100644 --- a/collects/scribblings/reference/reference.scrbl +++ b/collects/scribblings/reference/reference.scrbl @@ -70,6 +70,7 @@ languages.} @include-section["security.scrbl"] @include-section["os.scrbl"] @include-section["memory.scrbl"] +@include-section["unsafe.scrbl"] @include-section["running.scrbl"] @;------------------------------------------------------------------------ diff --git a/collects/scribblings/reference/unsafe.scrbl b/collects/scribblings/reference/unsafe.scrbl new file mode 100644 index 0000000000..43342ba971 --- /dev/null +++ b/collects/scribblings/reference/unsafe.scrbl @@ -0,0 +1,144 @@ +#lang scribble/doc +@(require "mz.ss" + (for-label scheme/unsafe/ops)) + +@title[#:tag "unsafe"]{Unsafe Operations} + +@defmodule[scheme/unsafe/ops] + +All fuctions and forms provided by @schememodname[scheme/base] and +@schememodname[scheme] check their arguments to ensure that the +arguments conform to contracts and other constraints. For example, +@scheme[vector-ref] checks its arguments to ensure that the first +argument is a vector, that the second argument is an exact integer, +and that the second argument is between @scheme[0] and one less than +the vector's length, inclusive. + +Functions provided by @schememodname[scheme/unsafe/ops] are +@deftech{unsafe}. They have certain constraints, but the constraints +are not checked, which allows the system to generate and execute +faster code. If arguments violate an unsafe function's constraints, +the function's behavior and result is unpredictable, and the entire +system can crash or become corrupted. + +All of the exported bindings of @schememodname[scheme] are protected +in the sense of @scheme[protect-out], so access to unsafe operations +can be prevented by adjusting the code inspector (see +@secref["modprotect"]). + +@section{Unsafe Numeric Operations} + +@deftogether[( +@defproc[(unsafe-fx+ [a fixnum?][b fixnum?]) fixnum?] +@defproc[(unsafe-fx- [a fixnum?][b fixnum?]) fixnum?] +@defproc[(unsafe-fx* [a fixnum?][b fixnum?]) fixnum?] +@defproc[(unsafe-fxquotient [a fixnum?][b fixnum?]) fixnum?] +@defproc[(unsafe-fxremainder [a fixnum?][b fixnum?]) fixnum?] +)]{ + +For @tech{fixnums}: Like @scheme[+], @scheme[-], @scheme[*], +@scheme[quotient], and @scheme[remainder], but constrained to consume +@tech{fixnums} and produce a @tech{fixnum} result. The mathematical +operation on @scheme[a] and @scheme[b] must be representable as a +@tech{fixnum}. In the case of @scheme[unsafe-fxquotient] and +@scheme[unsafe-fxremainder], @scheme[b] must not be @scheme[0].} + + +@deftogether[( +@defproc[(unsafe-fxand [a fixnum?][b fixnum?]) fixnum?] +@defproc[(unsafe-fxior [a fixnum?][b fixnum?]) fixnum?] +@defproc[(unsafe-fxxor [a fixnum?][b fixnum?]) fixnum?] +@defproc[(unsafe-fxnot [a fixnum?]) fixnum?] +@defproc[(unsafe-fxlshift [a fixnum?][b fixnum?]) fixnum?] +@defproc[(unsafe-fxrshift [a fixnum?][b fixnum?]) fixnum?] +)]{ + +For @tech{fixnums}: Like @scheme[bitwise-and], @scheme[bitwise-ior], +@scheme[bitwise-xor], @scheme[bitwise-not], and +@scheme[arithmetic-shift], but constrained to consume @tech{fixnums}; +the result is always a @tech{fixnum}. The @scheme[unsafe-fxlshift] and +@scheme[unsafe-fxrshift] operations correspond to +@scheme[arithmetic-shift], but require non-negative arguments; +@scheme[unsafe-fxlshift] is a positive (i.e., left) shift, and +@scheme[unsafe-fxrshift] is a negative (i.e., right) shift, where the +number of bits to shift must be less than the number of bits used to +represent a @tech{fixnum}, and the result is effectively +@scheme[bitwise-and]ed with the most negative @tech{fixnum}.} + + +@deftogether[( +@defproc[(unsafe-fx= [a fixnum?][b fixnum?]) boolean?] +@defproc[(unsafe-fx< [a fixnum?][b fixnum?]) boolean?] +@defproc[(unsafe-fx> [a fixnum?][b fixnum?]) boolean?] +@defproc[(unsafe-fx<= [a fixnum?][b fixnum?]) boolean?] +@defproc[(unsafe-fx>= [a fixnum?][b fixnum?]) boolean?] +)]{ + +For @tech{fixnums}: Like @scheme[=], @scheme[<], @scheme[>], +@scheme[<=], and @scheme[>=], but constrained to consume +@tech{fixnums}.} + + +@deftogether[( +@defproc[(unsafe-fl+ [a inexact-real?][b inexact-real?]) inexact-real?] +@defproc[(unsafe-fl- [a inexact-real?][b inexact-real?]) inexact-real?] +@defproc[(unsafe-fl* [a inexact-real?][b inexact-real?]) inexact-real?] +@defproc[(unsafe-fl/ [a inexact-real?][b inexact-real?]) inexact-real?] +)]{ + +For real @tech{inexact numbers}: Like @scheme[+], @scheme[-], +@scheme[*], and @scheme[/], but constrained to consume real @tech{inexact +numbers}. The result is always a real @tech{inexact number}.} + + +@deftogether[( +@defproc[(unsafe-fl= [a inexact-real?][b inexact-real?]) boolean?] +@defproc[(unsafe-fl< [a inexact-real?][b inexact-real?]) boolean?] +@defproc[(unsafe-fl> [a inexact-real?][b inexact-real?]) boolean?] +@defproc[(unsafe-fl<= [a inexact-real?][b inexact-real?]) boolean?] +@defproc[(unsafe-fl>= [a inexact-real?][b inexact-real?]) boolean?] +)]{ + +For real @tech{inexact numbers}: Like @scheme[=], @scheme[<], +@scheme[>], @scheme[<=], and @scheme[>=], but constrained to consume +real @tech{inexact numbers}.} + + +@section{Unsafe Data Extraction} + +@deftogether[( +@defproc[(unsafe-car [p pair?]) any/c] +@defproc[(unsafe-cdr [p pair?]) any/c] +@defproc[(unsafe-mcar [p mpair?]) any/c] +@defproc[(unsafe-mcdr [p mpair?]) any/c] +@defproc[(unsafe-set-mcar! [p mpair?] [v any/c]) void?] +@defproc[(unsafe-set-mcdr! [p mpair?] [v any/c]) void?] +)]{ + +Unsafe variants of @scheme[car], @scheme[cdr], @scheme[mcar], +@scheme[mcdr], @scheme[set-mcar!], and @scheme[set-mcdr!].} + + +@deftogether[( +@defproc[(unsafe-vector-length [v vector?]) fixnum?] +@defproc[(unsafe-vector-ref [v vector?][k fixnum?]) any/c] +@defproc[(unsafe-vector-set! [v vector?][k fixnum?][val any/c]) any/c] +)]{ + +Unsafe versions of @scheme[vector-length], @scheme[vector-ref], and +@scheme[vector-set!]. A vector's size can never be larger than a +@tech{fixnum} (so even @scheme[vector-length] always returns a +fixnum).} + + + +@deftogether[( +@defproc[(unsafe-struct-ref [v any/c][k fixnum?]) any/c] +@defproc[(unsafe-struct-set! [v any/c][k fixnum?][val any/c]) any/c] +)]{ + +Unsafe field access and update for an instance of a structure +type. The index @scheme[k] must be between @scheme[0] (inclusive) and +the number of fields in the struture (exclusive). In the case of +@scheme[unsafe-struct-set!], the field must be mutable.} + diff --git a/collects/tests/mzscheme/mz-tests.ss b/collects/tests/mzscheme/mz-tests.ss index 07e8f7adc7..10f70a3066 100644 --- a/collects/tests/mzscheme/mz-tests.ss +++ b/collects/tests/mzscheme/mz-tests.ss @@ -11,6 +11,7 @@ (load-relative "stx.ss") (load-relative "module.ss") (load-relative "number.ss") +(load-relative "unsafe.ss") (load-relative "object.ss") (load-relative "struct.ss") (load-relative "unit.ss") diff --git a/collects/tests/mzscheme/optimize.ss b/collects/tests/mzscheme/optimize.ss index 24022e8808..0ca86f8881 100644 --- a/collects/tests/mzscheme/optimize.ss +++ b/collects/tests/mzscheme/optimize.ss @@ -63,17 +63,19 @@ (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-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-int v op arg1 arg2) (let ([iv (if (number? v) (if (eq? op '*) (/ v (* 33333 33333)) @@ -266,6 +268,18 @@ (bin -4 '/ 16 -4) (bin 4 '/ -16 -4) + (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-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 3 'min 3 300) (bin -300 'min 3 -300) (bin -400 'min -400 -300) diff --git a/collects/tests/mzscheme/unsafe.ss b/collects/tests/mzscheme/unsafe.ss new file mode 100644 index 0000000000..3a8562a474 --- /dev/null +++ b/collects/tests/mzscheme/unsafe.ss @@ -0,0 +1,156 @@ + +(load-relative "loadtest.ss") + +(Section 'unsafe) + +(require '#%unsafe) + +(let () + (define (test-tri result proc x y z + #:pre [pre void] + #:post [post (lambda (x) x)] + #:literal-ok? [lit-ok? #t]) + (pre) + (test result (compose post (eval proc)) x y z) + (pre) + (test result (compose post (eval `(lambda (x y z) (,proc x y z)))) x y z) + (when lit-ok? + (pre) + (test result (compose post (eval `(lambda (y z) (,proc ,x y z)))) y z)) + (pre) + (test result (compose post (eval `(lambda (x z) (,proc x ,y z)))) x z) + (pre) + (test result (compose post (eval `(lambda (x y) (,proc x y ,z)))) x y) + (pre) + (test result (compose post (eval `(lambda (x) (,proc x ,y ,z)))) x) + (when lit-ok? + (pre) + (test result (compose post (eval `(lambda (y) (,proc ,x y ,z)))) y) + (pre) + (test result (compose post (eval `(lambda (z) (,proc ,x ,y z)))) z))) + (define (test-bin result proc x y + #:pre [pre void] + #:post [post (lambda (x) x)] + #:literal-ok? [lit-ok? #t]) + (pre) + (test result (compose post (eval proc)) x y) + (pre) + (test result (compose post (eval `(lambda (x y) (,proc x y)))) x y) + (when lit-ok? + (pre) + (test result (compose post (eval `(lambda (y) (,proc ,x y)))) y)) + (pre) + (test result (compose post (eval `(lambda (x) (,proc x ,y)))) x)) + (define (test-un result proc x) + (test result (eval proc) x) + (test result (eval `(lambda (x) (,proc x))) x)) + + (test-bin 3 'unsafe-fx+ 1 2) + (test-bin -1 'unsafe-fx+ 1 -2) + + (test-bin 8 'unsafe-fx- 10 2) + (test-bin 3 'unsafe-fx- 1 -2) + + (test-bin 20 'unsafe-fx* 10 2) + (test-bin -20 'unsafe-fx* 10 -2) + + (test-bin 3 'unsafe-fxquotient 17 5) + (test-bin -3 'unsafe-fxquotient 17 -5) + + (test-bin 2 'unsafe-fxremainder 17 5) + (test-bin 2 'unsafe-fxremainder 17 -5) + + (test-bin 3.4 'unsafe-fl+ 1.4 2.0) + (test-bin -1.1 'unsafe-fl+ 1.0 -2.1) + (test-bin +inf.0 'unsafe-fl+ 1.0 +inf.0) + (test-bin -inf.0 'unsafe-fl+ 1.0 -inf.0) + (test-bin +nan.0 'unsafe-fl+ +nan.0 -inf.0) + + (test-bin #f unsafe-fx= 1 2) + (test-bin #t unsafe-fx= 2 2) + (test-bin #f unsafe-fx= 2 1) + + (test-bin #t unsafe-fx< 1 2) + (test-bin #f unsafe-fx< 2 2) + (test-bin #f unsafe-fx< 2 1) + + (test-bin #f unsafe-fx> 1 2) + (test-bin #f unsafe-fx> 2 2) + (test-bin #t unsafe-fx> 2 1) + + (test-bin #t unsafe-fx<= 1 2) + (test-bin #t unsafe-fx<= 2 2) + (test-bin #f unsafe-fx<= 2 1) + + (test-bin #f unsafe-fx>= 1 2) + (test-bin #t unsafe-fx>= 2 2) + (test-bin #t unsafe-fx>= 2 1) + + (test-bin 7.9 'unsafe-fl- 10.0 2.1) + (test-bin 3.7 'unsafe-fl- 1.0 -2.7) + + (test-bin 20.02 'unsafe-fl* 10.01 2.0) + (test-bin -20.02 'unsafe-fl* 10.01 -2.0) + + (test-bin (exact->inexact 17/5) 'unsafe-fl/ 17.0 5.0) + (test-bin +inf.0 'unsafe-fl/ 17.0 0.0) + (test-bin -inf.0 'unsafe-fl/ -17.0 0.0) + + (test-bin 3 'unsafe-fxand 7 3) + (test-bin 2 'unsafe-fxand 6 3) + (test-bin 3 'unsafe-fxand -1 3) + + (test-bin 7 'unsafe-fxior 7 3) + (test-bin 7 'unsafe-fxior 6 3) + (test-bin -1 'unsafe-fxior -1 3) + + (test-bin 4 'unsafe-fxxor 7 3) + (test-bin 5 'unsafe-fxxor 6 3) + (test-bin -4 'unsafe-fxxor -1 3) + + (test-un -1 'unsafe-fxnot 0) + (test-un -4 'unsafe-fxnot 3) + + (test-bin 32 'unsafe-fxlshift 2 4) + (test-bin 32 'unsafe-fxlshift 8 2) + (test-bin 8 'unsafe-fxlshift 8 0) + + (test-bin 2 'unsafe-fxrshift 32 4) + (test-bin 8 'unsafe-fxrshift 32 2) + (test-bin 8 'unsafe-fxrshift 8 0) + + (test-un 5 'unsafe-car (cons 5 9)) + (test-un 9 'unsafe-cdr (cons 5 9)) + (test-un 15 'unsafe-mcar (mcons 15 19)) + (test-un 19 'unsafe-mcdr (mcons 15 19)) + (let ([v (mcons 3 7)]) + (test-bin 8 'unsafe-set-mcar! v 8 + #:pre (lambda () (set-mcar! v 0)) + #:post (lambda (x) (mcar v)) + #:literal-ok? #f) + (test-bin 9 'unsafe-set-mcdr! v 9 + #:pre (lambda () (set-mcdr! v 0)) + #:post (lambda (x) (mcdr v)) + #:literal-ok? #f)) + + (test-bin 5 'unsafe-vector-ref #(1 5 7) 1) + (test-un 3 'unsafe-vector-length #(1 5 7)) + (let ([v (vector 0 3 7)]) + (test-tri 5 'unsafe-vector-set! v 2 5 + #:pre (lambda () (vector-set! v 2 0)) + #:post (lambda (x) (vector-ref v 2)) + #:literal-ok? #f)) + + (let () + (define-struct posn (x [y #:mutable] z)) + (test-bin 'a unsafe-struct-ref (make-posn 'a 'b 'c) 0 #:literal-ok? #f) + (test-bin 'b unsafe-struct-ref (make-posn 'a 'b 'c) 1 #:literal-ok? #f) + (let ([p (make-posn 100 200 300)]) + (test-tri 500 'unsafe-struct-set! p 1 500 + #:pre (lambda () (set-posn-y! p 0)) + #:post (lambda (x) (posn-y p)) + #:literal-ok? #f))) + + (void)) + +(report-errs) diff --git a/collects/typed-scheme/typed-scheme.ss b/collects/typed-scheme/typed-scheme.ss index 14cee3cee8..6ebafaf83c 100644 --- a/collects/typed-scheme/typed-scheme.ss +++ b/collects/typed-scheme/typed-scheme.ss @@ -69,7 +69,7 @@ [type-name-references null])] [begin (do-time "Initialized Envs")] ;; local-expand the module - ;; pmb = #%plain-module-begin + ;; pmb = #%plain-module-begin [with-syntax ([new-mod (local-expand (syntax/loc stx (#%plain-module-begin diff --git a/collects/typed-scheme/utils/syntax-traversal.ss b/collects/typed-scheme/utils/syntax-traversal.ss index ef0eeed44d..cfdaf4178f 100644 --- a/collects/typed-scheme/utils/syntax-traversal.ss +++ b/collects/typed-scheme/utils/syntax-traversal.ss @@ -14,7 +14,7 @@ stx (loop (list-ref (syntax->list stx) (car locs)) (cdr locs))))) -(define (syntax-loc stx) (list (syntax-position stx) (syntax-span stx))) +(define (syntax-loc stx) (list (syntax-source stx) (syntax-position stx) (syntax-span stx))) ;; -------------------- the real stuff @@ -35,16 +35,23 @@ (and (pair? stx) (or (loop (car stx)) (loop (cdr stx))))))))) - +(define (unwind p) + (if (syntax? p) + (vector (vector (syntax-source p) (syntax-line p)) (unwind (syntax-e p))) + (if (pair? p) + (cons (unwind (car p)) (unwind (cdr p))) + p))) ;; Look for (the outermost) syntax in `orig' that has the same ;; location as `lookfor' which is coming from the expanded `orig', ;; given in `expanded'. -(define (look-for-in-orig orig expanded lookfor) +(define (look-for-in-orig orig expanded lookfor) lookfor) + +#| (define src (syntax-source orig)) - ;(printf "orig : ~a~n" orig) + ;(printf "orig : ~a~n" (unwind orig)) ;(printf "expanded : ~a~n" expanded) - ;(printf "lookfor : ~a~n" lookfor) + ;(printf "lookfor : ~a~n" (unwind lookfor)) ;(printf "src : ~a~n" src) (let ([enclosing (enclosing-syntaxes-with-source expanded lookfor src)] [syntax-locs (make-hash)]) @@ -67,4 +74,6 @@ #;(printf "chose branch two ~a~n" enclosing)))))) ;(trace look-for-in-orig) +|# + diff --git a/doc/release-notes/mzscheme/HISTORY.txt b/doc/release-notes/mzscheme/HISTORY.txt index 4839195ec1..9b4d3136f7 100644 --- a/doc/release-notes/mzscheme/HISTORY.txt +++ b/doc/release-notes/mzscheme/HISTORY.txt @@ -1,3 +1,6 @@ +Version 4.2.1.8 +Added scheme/unsafe/ops + Version 4.2.1.7 Inside: embedding applications should call scheme_seal_parameters after initializing parameter values (currently used by Planet) diff --git a/src/mzscheme/src/cstartup.inc b/src/mzscheme/src/cstartup.inc index ac9f7a7098..5ffd9930e4 100644 --- a/src/mzscheme/src/cstartup.inc +++ b/src/mzscheme/src/cstartup.inc @@ -1,42 +1,42 @@ { - static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,52,46,50,46,49,46,55,50,0,0,0,1,0,0,3,0,12,0, -19,0,32,0,36,0,41,0,44,0,49,0,56,0,63,0,67,0,72,0,78, + static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,52,46,50,46,49,46,56,50,0,0,0,1,0,0,3,0,12,0, +19,0,23,0,28,0,31,0,36,0,49,0,56,0,63,0,67,0,72,0,78, 0,92,0,106,0,109,0,115,0,119,0,121,0,132,0,134,0,148,0,155,0, 177,0,179,0,193,0,1,1,27,1,35,1,43,1,53,1,89,1,122,1,155, 1,214,1,24,2,102,2,168,2,173,2,193,2,84,3,104,3,155,3,221,3, 106,4,248,4,44,5,67,5,146,5,0,0,93,7,0,0,29,11,11,68,104, -101,114,101,45,115,116,120,66,100,101,102,105,110,101,72,112,97,114,97,109,101, -116,101,114,105,122,101,63,97,110,100,64,108,101,116,42,62,111,114,64,99,111, -110,100,66,108,101,116,114,101,99,66,117,110,108,101,115,115,63,108,101,116,64, +101,114,101,45,115,116,120,66,100,101,102,105,110,101,63,97,110,100,64,108,101, +116,42,62,111,114,64,99,111,110,100,72,112,97,114,97,109,101,116,101,114,105, +122,101,66,108,101,116,114,101,99,66,117,110,108,101,115,115,63,108,101,116,64, 119,104,101,110,65,113,117,111,116,101,29,94,2,13,68,35,37,107,101,114,110, 101,108,11,29,94,2,13,68,35,37,112,97,114,97,109,122,11,62,105,102,65, 98,101,103,105,110,63,115,116,120,61,115,70,108,101,116,45,118,97,108,117,101, 115,61,120,73,108,101,116,114,101,99,45,118,97,108,117,101,115,66,108,97,109, 98,100,97,1,20,112,97,114,97,109,101,116,101,114,105,122,97,116,105,111,110, 45,107,101,121,61,118,73,100,101,102,105,110,101,45,118,97,108,117,101,115,97, -35,11,8,170,244,95,159,2,15,35,35,159,2,14,35,35,159,2,14,35,35, -16,20,2,3,2,1,2,4,2,1,2,7,2,1,2,5,2,1,2,6,2, -1,2,9,2,1,2,8,2,1,2,10,2,1,2,11,2,1,2,12,2,1, -97,36,11,8,170,244,93,159,2,14,35,36,16,2,2,2,161,2,1,36,2, -2,2,1,2,2,96,11,11,8,170,244,16,0,96,37,11,8,170,244,16,0, +35,11,8,162,246,95,159,2,15,35,35,159,2,14,35,35,159,2,14,35,35, +16,20,2,3,2,1,2,6,2,1,2,4,2,1,2,5,2,1,2,9,2, +1,2,7,2,1,2,8,2,1,2,10,2,1,2,11,2,1,2,12,2,1, +97,36,11,8,162,246,93,159,2,14,35,36,16,2,2,2,161,2,1,36,2, +2,2,1,2,2,96,11,11,8,162,246,16,0,96,37,11,8,162,246,16,0, 13,16,4,35,29,11,11,2,1,11,18,16,2,99,64,104,101,114,101,8,31, -8,30,8,29,8,28,8,27,93,8,224,49,61,0,0,95,9,8,224,49,61, +8,30,8,29,8,28,8,27,93,8,224,169,61,0,0,95,9,8,224,169,61, 0,0,2,1,27,248,22,137,4,195,249,22,130,4,80,158,38,35,251,22,77, 2,16,248,22,92,199,12,249,22,67,2,17,248,22,94,201,27,248,22,137,4, 195,249,22,130,4,80,158,38,35,251,22,77,2,16,248,22,92,199,249,22,67, 2,17,248,22,94,201,12,27,248,22,69,248,22,137,4,196,28,248,22,75,193, 20,15,159,36,35,36,28,248,22,75,248,22,69,194,248,22,68,193,249,22,130, -4,80,158,38,35,251,22,77,2,16,248,22,68,199,249,22,67,2,5,248,22, +4,80,158,38,35,251,22,77,2,16,248,22,68,199,249,22,67,2,4,248,22, 69,201,11,18,16,2,101,10,8,31,8,30,8,29,8,28,8,27,16,4,11, -11,2,18,3,1,8,101,110,118,49,48,51,50,48,16,4,11,11,2,19,3, -1,8,101,110,118,49,48,51,50,49,93,8,224,50,61,0,0,95,9,8,224, -50,61,0,0,2,1,27,248,22,69,248,22,137,4,196,28,248,22,75,193,20, +11,2,18,3,1,8,101,110,118,49,48,52,49,54,16,4,11,11,2,19,3, +1,8,101,110,118,49,48,52,49,55,93,8,224,170,61,0,0,95,9,8,224, +170,61,0,0,2,1,27,248,22,69,248,22,137,4,196,28,248,22,75,193,20, 15,159,36,35,36,28,248,22,75,248,22,69,194,248,22,68,193,249,22,130,4, 80,158,38,35,250,22,77,2,20,248,22,77,249,22,77,248,22,77,2,21,248, -22,68,201,251,22,77,2,16,2,21,2,21,249,22,67,2,7,248,22,69,204, +22,68,201,251,22,77,2,16,2,21,2,21,249,22,67,2,6,248,22,69,204, 18,16,2,101,11,8,31,8,30,8,29,8,28,8,27,16,4,11,11,2,18, -3,1,8,101,110,118,49,48,51,50,51,16,4,11,11,2,19,3,1,8,101, -110,118,49,48,51,50,52,93,8,224,51,61,0,0,95,9,8,224,51,61,0, +3,1,8,101,110,118,49,48,52,49,57,16,4,11,11,2,19,3,1,8,101, +110,118,49,48,52,50,48,93,8,224,171,61,0,0,95,9,8,224,171,61,0, 0,2,1,248,22,137,4,193,27,248,22,137,4,194,249,22,67,248,22,77,248, 22,68,196,248,22,69,195,27,248,22,69,248,22,137,4,23,197,1,249,22,130, 4,80,158,38,35,28,248,22,53,248,22,131,4,248,22,68,23,198,2,27,249, @@ -51,7 +51,7 @@ 222,33,42,248,22,137,4,248,22,68,201,248,22,69,198,27,248,22,69,248,22, 137,4,196,27,248,22,137,4,248,22,68,195,249,22,130,4,80,158,39,35,28, 248,22,75,195,250,22,78,2,20,9,248,22,69,199,250,22,77,2,11,248,22, -77,248,22,68,199,250,22,78,2,6,248,22,69,201,248,22,69,202,27,248,22, +77,248,22,68,199,250,22,78,2,5,248,22,69,201,248,22,69,202,27,248,22, 69,248,22,137,4,23,197,1,27,249,22,1,22,81,249,22,2,22,137,4,248, 22,137,4,248,22,68,199,249,22,130,4,80,158,39,35,251,22,77,1,22,119, 105,116,104,45,99,111,110,116,105,110,117,97,116,105,111,110,45,109,97,114,107, @@ -62,13 +62,13 @@ 28,248,22,75,193,20,15,159,36,35,36,249,22,130,4,80,158,38,35,27,248, 22,137,4,248,22,68,197,28,249,22,167,8,62,61,62,248,22,131,4,248,22, 92,196,250,22,77,2,20,248,22,77,249,22,77,21,93,2,25,248,22,68,199, -250,22,78,2,8,249,22,77,2,25,249,22,77,248,22,101,203,2,25,248,22, +250,22,78,2,7,249,22,77,2,25,249,22,77,248,22,101,203,2,25,248,22, 69,202,251,22,77,2,16,28,249,22,167,8,248,22,131,4,248,22,68,200,64, 101,108,115,101,10,248,22,68,197,250,22,78,2,20,9,248,22,69,200,249,22, -67,2,8,248,22,69,202,100,8,31,8,30,8,29,8,28,8,27,16,4,11, -11,2,18,3,1,8,101,110,118,49,48,51,52,54,16,4,11,11,2,19,3, -1,8,101,110,118,49,48,51,52,55,93,8,224,52,61,0,0,18,16,2,158, -94,10,64,118,111,105,100,8,47,95,9,8,224,52,61,0,0,2,1,27,248, +67,2,7,248,22,69,202,100,8,31,8,30,8,29,8,28,8,27,16,4,11, +11,2,18,3,1,8,101,110,118,49,48,52,52,50,16,4,11,11,2,19,3, +1,8,101,110,118,49,48,52,52,51,93,8,224,172,61,0,0,18,16,2,158, +94,10,64,118,111,105,100,8,47,95,9,8,224,172,61,0,0,2,1,27,248, 22,69,248,22,137,4,196,249,22,130,4,80,158,38,35,28,248,22,53,248,22, 131,4,248,22,68,197,250,22,77,2,26,248,22,77,248,22,68,199,248,22,92, 198,27,248,22,131,4,248,22,68,197,250,22,77,2,26,248,22,77,248,22,68, @@ -83,22 +83,22 @@ 159,35,35,35,35,20,103,159,35,16,0,16,1,33,32,10,16,5,2,10,89, 162,8,44,36,52,9,223,0,33,33,35,20,103,159,35,16,1,2,2,16,0, 11,16,5,2,12,89,162,8,44,36,52,9,223,0,33,34,35,20,103,159,35, -16,1,2,2,16,0,11,16,5,2,5,89,162,8,44,36,52,9,223,0,33, -35,35,20,103,159,35,16,1,2,2,16,1,33,36,11,16,5,2,7,89,162, +16,1,2,2,16,0,11,16,5,2,4,89,162,8,44,36,52,9,223,0,33, +35,35,20,103,159,35,16,1,2,2,16,1,33,36,11,16,5,2,6,89,162, 8,44,36,55,9,223,0,33,37,35,20,103,159,35,16,1,2,2,16,1,33, 38,11,16,5,2,11,89,162,8,44,36,57,9,223,0,33,41,35,20,103,159, 35,16,1,2,2,16,0,11,16,5,2,9,89,162,8,44,36,52,9,223,0, -33,43,35,20,103,159,35,16,1,2,2,16,0,11,16,5,2,6,89,162,8, +33,43,35,20,103,159,35,16,1,2,2,16,0,11,16,5,2,5,89,162,8, 44,36,53,9,223,0,33,44,35,20,103,159,35,16,1,2,2,16,0,11,16, -5,2,4,89,162,8,44,36,54,9,223,0,33,45,35,20,103,159,35,16,1, -2,2,16,0,11,16,5,2,8,89,162,8,44,36,57,9,223,0,33,46,35, +5,2,8,89,162,8,44,36,54,9,223,0,33,45,35,20,103,159,35,16,1, +2,2,16,0,11,16,5,2,7,89,162,8,44,36,57,9,223,0,33,46,35, 20,103,159,35,16,1,2,2,16,1,33,48,11,16,5,2,3,89,162,8,44, 36,53,9,223,0,33,49,35,20,103,159,35,16,1,2,2,16,0,11,16,0, 94,2,14,2,15,93,2,14,9,9,35,0}; EVAL_ONE_SIZED_STR((char *)expr, 2006); } { - static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,52,46,50,46,49,46,55,59,0,0,0,1,0,0,13,0,18,0, + static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,52,46,50,46,49,46,56,59,0,0,0,1,0,0,13,0,18,0, 35,0,50,0,68,0,84,0,94,0,112,0,132,0,148,0,166,0,197,0,226, 0,248,0,6,1,12,1,26,1,31,1,41,1,49,1,77,1,109,1,154,1, 199,1,223,1,6,2,8,2,65,2,155,3,196,3,31,5,135,5,239,5,100, @@ -340,25 +340,25 @@ EVAL_ONE_SIZED_STR((char *)expr, 5006); } { - static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,52,46,50,46,49,46,55,8,0,0,0,1,0,0,6,0,19,0, -34,0,48,0,62,0,76,0,115,0,0,0,6,1,0,0,65,113,117,111,116, + static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,52,46,50,46,49,46,56,8,0,0,0,1,0,0,6,0,19,0, +34,0,48,0,62,0,76,0,115,0,0,0,20,1,0,0,65,113,117,111,116, 101,29,94,2,1,67,35,37,117,116,105,108,115,11,29,94,2,1,69,35,37, 110,101,116,119,111,114,107,11,29,94,2,1,68,35,37,112,97,114,97,109,122, 11,29,94,2,1,68,35,37,101,120,112,111,98,115,11,29,94,2,1,68,35, -37,107,101,114,110,101,108,11,97,35,11,8,176,246,98,159,2,2,35,35,159, +37,107,101,114,110,101,108,11,97,35,11,8,168,248,98,159,2,2,35,35,159, 2,3,35,35,159,2,4,35,35,159,2,5,35,35,159,2,6,35,35,159,2, 6,35,35,16,0,159,35,20,103,159,35,16,1,11,16,0,83,158,41,20,100, 144,69,35,37,98,117,105,108,116,105,110,29,11,11,11,11,11,18,96,11,42, 42,42,35,80,158,35,35,20,103,159,35,16,0,16,0,16,0,35,16,0,35, 16,0,35,11,11,38,35,11,11,11,16,0,16,0,16,0,35,35,36,11,11, 11,16,0,16,0,16,0,35,35,11,11,11,11,16,0,16,0,16,0,35,35, -16,0,16,0,99,2,6,2,5,29,94,2,1,69,35,37,102,111,114,101,105, -103,110,11,2,4,2,3,2,2,29,94,2,1,67,35,37,112,108,97,99,101, -11,9,9,9,35,0}; - EVAL_ONE_SIZED_STR((char *)expr, 299); +16,0,16,0,100,2,6,2,5,29,94,2,1,69,35,37,102,111,114,101,105, +103,110,11,29,94,2,1,68,35,37,117,110,115,97,102,101,11,2,4,2,3, +2,2,29,94,2,1,67,35,37,112,108,97,99,101,11,9,9,9,35,0}; + EVAL_ONE_SIZED_STR((char *)expr, 313); } { - static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,52,46,50,46,49,46,55,56,0,0,0,1,0,0,11,0,38,0, + static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,52,46,50,46,49,46,56,56,0,0,0,1,0,0,11,0,38,0, 44,0,57,0,66,0,73,0,95,0,117,0,143,0,155,0,173,0,193,0,205, 0,221,0,244,0,0,1,31,1,38,1,43,1,48,1,53,1,58,1,67,1, 72,1,76,1,84,1,93,1,101,1,204,1,249,1,13,2,42,2,73,2,129, diff --git a/src/mzscheme/src/env.c b/src/mzscheme/src/env.c index a2a94cab6f..276f1ecc6a 100644 --- a/src/mzscheme/src/env.c +++ b/src/mzscheme/src/env.c @@ -52,6 +52,7 @@ static int env_uid_counter = 0; /* globals READ-ONLY SHARED */ static Scheme_Object *kernel_symbol; static Scheme_Env *kernel_env; +static Scheme_Env *unsafe_env; #define MAX_CONST_LOCAL_POS 64 #define MAX_CONST_LOCAL_TYPES 2 @@ -393,6 +394,39 @@ static void place_instance_init_pre_kernel(void *stack_base) { #endif } + +static void init_unsafe(Scheme_Env *env) +{ + scheme_defining_primitives = 1; + + REGISTER_SO(unsafe_env); + + unsafe_env = scheme_primitive_module(scheme_intern_symbol("#%unsafe"), env); + + scheme_init_unsafe_number(unsafe_env); + scheme_init_unsafe_numarith(unsafe_env); + scheme_init_unsafe_numcomp(unsafe_env); + scheme_init_unsafe_list(unsafe_env); + scheme_init_unsafe_vector(unsafe_env); + + scheme_finish_primitive_module(unsafe_env); + scheme_protect_primitive_provide(unsafe_env, NULL); + + scheme_defining_primitives = 0; + +#if USE_COMPILED_STARTUP + if (builtin_ref_counter != (EXPECTED_PRIM_COUNT + EXPECTED_UNSAFE_COUNT)) { + printf("Unsafe count %d doesn't match expected count %d\n", + builtin_ref_counter - EXPECTED_PRIM_COUNT, EXPECTED_UNSAFE_COUNT); + abort(); + } +#endif +} + +Scheme_Env *scheme_get_unsafe_env() { + return unsafe_env; +} + static Scheme_Env *place_instance_init_post_kernel() { Scheme_Env *env; /* error handling and buffers */ @@ -432,6 +466,8 @@ static Scheme_Env *place_instance_init_post_kernel() { init_dummy_foreign(env); #endif + init_unsafe(env); + scheme_add_embedded_builtins(env); boot_module_resolver(); @@ -608,7 +644,7 @@ static void make_kernel_env(void) printf("Primitive count %d doesn't match expected count %d\n" "Turn off USE_COMPILED_STARTUP in src/schminc.h\n", builtin_ref_counter, EXPECTED_PRIM_COUNT); - exit(1); + abort(); } #endif @@ -1248,22 +1284,28 @@ Scheme_Object **scheme_make_builtin_references_table(void) Scheme_Bucket **bs; Scheme_Env *kenv; long i; + int j; t = MALLOC_N(Scheme_Object *, (builtin_ref_counter + 1)); #ifdef MEMORY_COUNTING_ON scheme_misc_count += sizeof(Scheme_Object *) * (builtin_ref_counter + 1); #endif - kenv = scheme_get_kernel_env(); - - ht = kenv->toplevel; - - bs = ht->buckets; - - for (i = ht->size; i--; ) { - Scheme_Bucket *b = bs[i]; - if (b && (((Scheme_Bucket_With_Flags *)b)->flags & GLOB_HAS_REF_ID)) - t[((Scheme_Bucket_With_Ref_Id *)b)->id] = (Scheme_Object *)b->val; + for (j = 0; j < 2; j++) { + if (!j) + kenv = scheme_get_kernel_env(); + else + kenv = unsafe_env; + + ht = kenv->toplevel; + + bs = ht->buckets; + + for (i = ht->size; i--; ) { + Scheme_Bucket *b = bs[i]; + if (b && (((Scheme_Bucket_With_Flags *)b)->flags & GLOB_HAS_REF_ID)) + t[((Scheme_Bucket_With_Ref_Id *)b)->id] = (Scheme_Object *)b->val; + } } return t; @@ -1276,18 +1318,24 @@ Scheme_Hash_Table *scheme_map_constants_to_globals(void) Scheme_Bucket **bs; Scheme_Env *kenv; long i; - - kenv = scheme_get_kernel_env(); - - ht = kenv->toplevel; - bs = ht->buckets; + int j; result = scheme_make_hash_table(SCHEME_hash_ptr); - - for (i = ht->size; i--; ) { - Scheme_Bucket *b = bs[i]; - if (b && (((Scheme_Bucket_With_Flags *)b)->flags & GLOB_IS_CONST)) { - scheme_hash_set(result, b->val, (Scheme_Object *)b); + + for (j = 0; j < 2; j++) { + if (!j) + kenv = scheme_get_kernel_env(); + else + kenv = unsafe_env; + + ht = kenv->toplevel; + bs = ht->buckets; + + for (i = ht->size; i--; ) { + Scheme_Bucket *b = bs[i]; + if (b && (((Scheme_Bucket_With_Flags *)b)->flags & GLOB_IS_CONST)) { + scheme_hash_set(result, b->val, (Scheme_Object *)b); + } } } @@ -1713,6 +1761,38 @@ Scheme_Object *scheme_register_stx_in_prefix(Scheme_Object *var, Scheme_Comp_Env return o; } +void scheme_register_unsafe_in_prefix(Scheme_Comp_Env *env, + Scheme_Compile_Info *rec, int drec, + Scheme_Env *menv) +{ + Scheme_Object *v, *insp; + + if (rec && rec[drec].dont_mark_local_use) { + return; + } + + insp = menv->module->insp; + + v = env->prefix->uses_unsafe; + if (!v) + v = insp; + else if (!SAME_OBJ(v, insp)) { + Scheme_Hash_Tree *ht; + + if (SCHEME_HASHTRP(v)) { + ht = (Scheme_Hash_Tree *)v; + } else { + ht = scheme_make_hash_tree(0); + ht = scheme_hash_tree_set(ht, v, scheme_true); + } + + if (!scheme_hash_tree_get(ht, insp)) { + ht = scheme_hash_tree_set(ht, insp, scheme_true); + env->prefix->uses_unsafe = (Scheme_Object *)ht; + } + } +} + /*========================================================================*/ /* compile-time env, lookup bindings */ /*========================================================================*/ @@ -2864,7 +2944,8 @@ scheme_lookup_binding(Scheme_Object *find_id, Scheme_Comp_Env *env, int flags, /* Used to have `&& !SAME_OBJ(modidx, modname)' below, but that was a bad idea, because it causes module instances to be preserved. */ if (modname && !(flags & SCHEME_RESOLVE_MODIDS) - && (!scheme_is_kernel_modname(modname) || (flags & SCHEME_REFERENCING))) { + && (!(scheme_is_kernel_modname(modname) || scheme_is_unsafe_modname(modname)) + || (flags & SCHEME_REFERENCING))) { /* Create a module variable reference, so that idx is preserved: */ return scheme_hash_module_variable(env->genv, modidx, find_id, genv->module->insp, @@ -2882,7 +2963,8 @@ scheme_lookup_binding(Scheme_Object *find_id, Scheme_Comp_Env *env, int flags, if ((flags & SCHEME_ELIM_CONST) && b && b->val && (((Scheme_Bucket_With_Flags *)b)->flags & GLOB_IS_CONST) - && !(flags & SCHEME_GLOB_ALWAYS_REFERENCE)) + && !(flags & SCHEME_GLOB_ALWAYS_REFERENCE) + && (!modname || scheme_is_kernel_modname(modname))) return (Scheme_Object *)b->val; ASSERT_IS_VARIABLE_BUCKET(b); @@ -2892,6 +2974,15 @@ scheme_lookup_binding(Scheme_Object *find_id, Scheme_Comp_Env *env, int flags, return (Scheme_Object *)b; } +Scheme_Object *scheme_extract_unsafe(Scheme_Object *o) +{ + Scheme_Env *home = ((Scheme_Bucket_With_Home *)o)->home; + if (home && home->module && scheme_is_unsafe_modname(home->module->modname)) + return (Scheme_Object *)((Scheme_Bucket *)o)->val; + else + return NULL; +} + int *scheme_env_get_flags(Scheme_Comp_Env *frame, int start, int count) { int *v, i; @@ -3447,6 +3538,7 @@ Resolve_Prefix *scheme_resolve_prefix(int phase, Comp_Prefix *cp, int simplify) rp->so.type = scheme_resolve_prefix_type; rp->num_toplevels = cp->num_toplevels; rp->num_stxes = cp->num_stxes; + rp->uses_unsafe = cp->uses_unsafe; if (rp->num_toplevels) tls = MALLOC_N(Scheme_Object*, rp->num_toplevels); @@ -5407,14 +5499,27 @@ static Scheme_Object *write_resolve_prefix(Scheme_Object *obj) SCHEME_VEC_ELS(sv)[i] = ds; } - return scheme_make_pair(scheme_make_integer(rp->num_lifts), scheme_make_pair(tv, sv)); + tv = scheme_make_pair(scheme_make_integer(rp->num_lifts), + scheme_make_pair(tv, sv)); + + if (rp->uses_unsafe) + tv = scheme_make_pair(scheme_true, tv); + + return tv; } static Scheme_Object *read_resolve_prefix(Scheme_Object *obj) { Resolve_Prefix *rp; Scheme_Object *tv, *sv, **a, *stx; - int i; + int i, uses_unsafe = 0; + + if (!SCHEME_PAIRP(obj)) return NULL; + + if (!SCHEME_INTP(SCHEME_CAR(obj))) { + uses_unsafe = 1; + obj = SCHEME_CDR(obj); + } if (!SCHEME_PAIRP(obj)) return NULL; @@ -5435,6 +5540,8 @@ static Scheme_Object *read_resolve_prefix(Scheme_Object *obj) rp->num_toplevels = SCHEME_VEC_SIZE(tv); rp->num_stxes = SCHEME_VEC_SIZE(sv); rp->num_lifts = i; + if (uses_unsafe) + rp->uses_unsafe = scheme_true; /* reset in read_marshalled */ i = rp->num_toplevels; a = MALLOC_N(Scheme_Object *, i); diff --git a/src/mzscheme/src/eval.c b/src/mzscheme/src/eval.c index 6d987dd3e7..2b54ef1e19 100644 --- a/src/mzscheme/src/eval.c +++ b/src/mzscheme/src/eval.c @@ -5547,8 +5547,12 @@ scheme_compile_expand_expr(Scheme_Object *form, Scheme_Comp_Env *env, if (rec[drec].comp) { scheme_compile_rec_done_local(rec, drec); - if (SAME_TYPE(SCHEME_TYPE(var), scheme_variable_type) - || SAME_TYPE(SCHEME_TYPE(var), scheme_module_variable_type)) + if (SAME_TYPE(SCHEME_TYPE(var), scheme_variable_type) + && scheme_extract_unsafe(var)) { + scheme_register_unsafe_in_prefix(env, rec, drec, menv); + return scheme_extract_unsafe(var); + } else if (SAME_TYPE(SCHEME_TYPE(var), scheme_variable_type) + || SAME_TYPE(SCHEME_TYPE(var), scheme_module_variable_type)) return scheme_register_toplevel_in_prefix(var, env, rec, drec); else return var; @@ -10205,6 +10209,10 @@ Scheme_Object **scheme_push_prefix(Scheme_Env *genv, Resolve_Prefix *rp, rs_save = rs = MZ_RUNSTACK; + if (rp->uses_unsafe) { + scheme_check_unsafe_accessible(rp->uses_unsafe, genv); + } + if (rp->num_toplevels || rp->num_stxes || rp->num_lifts) { i = rp->num_toplevels; if (rp->num_stxes) { diff --git a/src/mzscheme/src/jit.c b/src/mzscheme/src/jit.c index 69e9efaff0..4b1eab186e 100644 --- a/src/mzscheme/src/jit.c +++ b/src/mzscheme/src/jit.c @@ -1339,6 +1339,24 @@ static int inline_alloc(mz_jit_state *jitter, int amt, Scheme_Type ty, int immut # endif #endif +int scheme_can_inline_fp_op() +{ +#ifdef INLINE_FP_OPS + return 1; +#else + return 0; +#endif +} + +int scheme_can_inline_fp_comp() +{ +#ifdef INLINE_FP_COMP + return 1; +#else + return 0; +#endif +} + #if defined(INLINE_FP_OPS) && !defined(CAN_INLINE_ALLOC) static double double_result; static void *malloc_double(void) @@ -2281,7 +2299,7 @@ static int generate_clear_slow_previous_args(mz_jit_state *jitter) mz_prepare(2); jit_pusharg_p(JIT_R0); jit_pusharg_l(JIT_V1); - mz_finish(clear_runstack); + (void)mz_finish(clear_runstack); jit_retval(JIT_R0); return 1; } @@ -3292,28 +3310,32 @@ static int can_fast_double(int arith, int cmp, int two_args) static int generate_double_arith(mz_jit_state *jitter, int arith, int cmp, int reversed, int two_args, int second_const, jit_insn **_refd, jit_insn **_refdt, - int branch_short) + int branch_short, int unsafe_fl) { #if defined(INLINE_FP_OPS) || defined(INLINE_FP_COMP) GC_CAN_IGNORE jit_insn *ref8, *ref9, *ref10, *refd, *refdt; int no_alloc = 0; - /* Maybe they're doubles */ - __START_TINY_JUMPS__(1); - if (two_args) { - jit_orr_ul(JIT_R2, JIT_R0, JIT_R1); - ref8 = jit_bmsi_ul(jit_forward(), JIT_R2, 0x1); - } else - ref8 = NULL; - jit_ldxi_s(JIT_R2, JIT_R0, &((Scheme_Object *)0x0)->type); - ref9 = jit_bnei_p(jit_forward(), JIT_R2, scheme_double_type); - if (two_args) { - jit_ldxi_s(JIT_R2, JIT_R1, &((Scheme_Object *)0x0)->type); - ref10 = jit_bnei_p(jit_forward(), JIT_R2, scheme_double_type); - } else - ref10 = NULL; - CHECK_LIMIT(); - __END_TINY_JUMPS__(1); + if (!unsafe_fl) { + /* Maybe they're doubles */ + __START_TINY_JUMPS__(1); + if (two_args) { + jit_orr_ul(JIT_R2, JIT_R0, JIT_R1); + ref8 = jit_bmsi_ul(jit_forward(), JIT_R2, 0x1); + } else + ref8 = NULL; + jit_ldxi_s(JIT_R2, JIT_R0, &((Scheme_Object *)0x0)->type); + ref9 = jit_bnei_p(jit_forward(), JIT_R2, scheme_double_type); + if (two_args) { + jit_ldxi_s(JIT_R2, JIT_R1, &((Scheme_Object *)0x0)->type); + ref10 = jit_bnei_p(jit_forward(), JIT_R2, scheme_double_type); + } else + ref10 = NULL; + CHECK_LIMIT(); + __END_TINY_JUMPS__(1); + } else { + ref8 = ref9 = ref10 = NULL; + } if (!two_args && !second_const && ((arith == 2) || ((arith == -2) && reversed))) { /* Special case: multiplication by exact 0 */ @@ -3434,36 +3456,45 @@ static int generate_double_arith(mz_jit_state *jitter, int arith, int cmp, int r } } - /* Jump to return result or true branch: */ - __START_SHORT_JUMPS__(branch_short); - refdt = jit_jmpi(jit_forward()); - *_refdt = refdt; - __END_SHORT_JUMPS__(branch_short); - - /* No, they're not both doubles. */ - __START_TINY_JUMPS__(1); - if (two_args) { - mz_patch_branch(ref8); - mz_patch_branch(ref10); + if (!unsafe_fl) { + /* Jump to return result or true branch: */ + __START_SHORT_JUMPS__(branch_short); + refdt = jit_jmpi(jit_forward()); + *_refdt = refdt; + __END_SHORT_JUMPS__(branch_short); + } + + if (!unsafe_fl) { + /* No, they're not both doubles. */ + __START_TINY_JUMPS__(1); + if (two_args) { + mz_patch_branch(ref8); + mz_patch_branch(ref10); + } + mz_patch_branch(ref9); + __END_TINY_JUMPS__(1); } - mz_patch_branch(ref9); - __END_TINY_JUMPS__(1); #endif return 1; } static int generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Object *rand, Scheme_Object *rand2, - int orig_args, int arith, int cmp, int v, jit_insn **for_branch, int branch_short) + int orig_args, int arith, int cmp, int v, jit_insn **for_branch, int branch_short, + int unsafe_fx, int unsafe_fl) /* needs de-sync */ /* Either arith is non-zero or it's a cmp; the value of each determines the operation: arith = 1 -> + or add1 (if !rand2) arith = -1 -> - or sub1 arith = 2 -> * + arith = -2 -> / + arith = -3 -> quotient + arith = -4 -> remainder arith = 3 -> bitwise-and arith = 4 -> bitwise-ior arith = 5 -> bitwise-xor - arith = 6 -> arithmetic-shift + arith = 6 -> arithmetic-shift, fxlshift + arith = -6 -> fxrshift arith = 7 -> bitwise-not arith = 9 -> min arith = 10 -> max @@ -3495,7 +3526,7 @@ static int generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj rand2 = NULL; } else if (SCHEME_INTP(rand) && SCHEME_INT_SMALL_ENOUGH(rand) - && (arith != 6) + && (arith != 6) && (arith != -6) && (cmp != 3)) { /* First is constant; swap argument order and use constant mode. */ v = SCHEME_INT_VAL(rand); @@ -3588,36 +3619,49 @@ static int generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj pos = mz_remap(SCHEME_LOCAL_POS(rand)); mz_rs_ldxi(JIT_R1, pos); } - /* check both fixnum bits at once by ANDing into R2: */ - jit_andr_ul(JIT_R2, JIT_R0, JIT_R1); - va = JIT_R2; + if (!unsafe_fx && !unsafe_fl) { + /* check both fixnum bits at once by ANDing into R2: */ + jit_andr_ul(JIT_R2, JIT_R0, JIT_R1); + va = JIT_R2; + } } - mz_rs_sync(); + if (!unsafe_fx && !unsafe_fl) { + mz_rs_sync(); - __START_TINY_JUMPS__(1); - ref2 = jit_bmsi_ul(jit_forward(), va, 0x1); - __END_TINY_JUMPS__(1); + __START_TINY_JUMPS__(1); + ref2 = jit_bmsi_ul(jit_forward(), va, 0x1); + __END_TINY_JUMPS__(1); + } else { + ref2 = NULL; + if (for_branch) mz_rs_sync(); + } - if (!SCHEME_INTP(rand) && can_fast_double(arith, cmp, 1)) { + if (unsafe_fl || (!SCHEME_INTP(rand) && can_fast_double(arith, cmp, 1))) { /* Maybe they're both doubles... */ - generate_double_arith(jitter, arith, cmp, reversed, 1, 0, &refd, &refdt, branch_short); + generate_double_arith(jitter, arith, cmp, reversed, 1, 0, &refd, &refdt, branch_short, unsafe_fl); CHECK_LIMIT(); } - if (!has_fixnum_fast) { - __START_TINY_JUMPS__(1); - mz_patch_branch(ref2); - __END_TINY_JUMPS__(1); - } + if (!unsafe_fx && !unsafe_fl) { + if (!has_fixnum_fast) { + __START_TINY_JUMPS__(1); + mz_patch_branch(ref2); + __END_TINY_JUMPS__(1); + } - /* Slow path */ - refslow = generate_arith_slow_path(jitter, rator, &ref, &ref4, for_branch, orig_args, reversed, arith, 0, 0); + /* Slow path */ + refslow = generate_arith_slow_path(jitter, rator, &ref, &ref4, for_branch, orig_args, reversed, arith, 0, 0); - if (has_fixnum_fast) { - __START_TINY_JUMPS__(1); - mz_patch_branch(ref2); - __END_TINY_JUMPS__(1); + if (has_fixnum_fast) { + __START_TINY_JUMPS__(1); + mz_patch_branch(ref2); + __END_TINY_JUMPS__(1); + } + } else { + refslow = NULL; + ref = NULL; + ref4 = NULL; } CHECK_LIMIT(); } else if (rand2) { @@ -3626,67 +3670,91 @@ static int generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj mz_rs_inc(1); mz_runstack_popped(jitter, 1); - mz_rs_sync(); + if (!unsafe_fx && !unsafe_fl) { + mz_rs_sync(); - /* check both fixnum bits at once by ANDing into R2: */ - jit_andr_ul(JIT_R2, JIT_R0, JIT_R1); - __START_TINY_JUMPS__(1); - ref2 = jit_bmsi_ul(jit_forward(), JIT_R2, 0x1); - __END_TINY_JUMPS__(1); - CHECK_LIMIT(); + /* check both fixnum bits at once by ANDing into R2: */ + jit_andr_ul(JIT_R2, JIT_R0, JIT_R1); + __START_TINY_JUMPS__(1); + ref2 = jit_bmsi_ul(jit_forward(), JIT_R2, 0x1); + __END_TINY_JUMPS__(1); + CHECK_LIMIT(); + } else { + if (for_branch) mz_rs_sync(); + ref2 = NULL; + CHECK_LIMIT(); + } - if (can_fast_double(arith, cmp, 1)) { + if (unsafe_fl || can_fast_double(arith, cmp, 1)) { /* Maybe they're both doubles... */ - generate_double_arith(jitter, arith, cmp, reversed, 1, 0, &refd, &refdt, branch_short); + generate_double_arith(jitter, arith, cmp, reversed, 1, 0, &refd, &refdt, branch_short, unsafe_fl); CHECK_LIMIT(); } - if (!has_fixnum_fast) { - __START_TINY_JUMPS__(1); - mz_patch_branch(ref2); - __END_TINY_JUMPS__(1); - } + if (!unsafe_fx && !unsafe_fl) { + if (!has_fixnum_fast) { + __START_TINY_JUMPS__(1); + mz_patch_branch(ref2); + __END_TINY_JUMPS__(1); + } - /* Slow path */ - refslow = generate_arith_slow_path(jitter, rator, &ref, &ref4, for_branch, orig_args, reversed, arith, 0, 0); - - if (has_fixnum_fast) { - /* Fixnum branch: */ - __START_TINY_JUMPS__(1); - mz_patch_branch(ref2); - __END_TINY_JUMPS__(1); + /* Slow path */ + refslow = generate_arith_slow_path(jitter, rator, &ref, &ref4, for_branch, orig_args, reversed, arith, 0, 0); + + if (has_fixnum_fast) { + /* Fixnum branch: */ + __START_TINY_JUMPS__(1); + mz_patch_branch(ref2); + __END_TINY_JUMPS__(1); + } + CHECK_LIMIT(); + } else { + refslow = NULL; + ref = NULL; + ref4 = NULL; } - CHECK_LIMIT(); } else { - mz_rs_sync(); /* Only one argument: */ - __START_TINY_JUMPS__(1); - ref2 = jit_bmsi_ul(jit_forward(), JIT_R0, 0x1); - __END_TINY_JUMPS__(1); + if (!unsafe_fx && !unsafe_fl) { + mz_rs_sync(); + __START_TINY_JUMPS__(1); + ref2 = jit_bmsi_ul(jit_forward(), JIT_R0, 0x1); + __END_TINY_JUMPS__(1); + } else { + if (for_branch) mz_rs_sync(); + ref2 = NULL; + } - if ((orig_args != 2) /* <- heuristic: we could generate code when an exact argument is - given, but the extra FP code is probably not worthwhile. */ - && can_fast_double(arith, cmp, 0) - /* watch out: divide by 0 is special: */ - && ((arith != -2) || v || reversed)) { + if (unsafe_fl + || ((orig_args != 2) /* <- heuristic: we could generate code when an exact argument is + given, but the extra FP code is probably not worthwhile. */ + && can_fast_double(arith, cmp, 0) + /* watch out: divide by 0 is special: */ + && ((arith != -2) || v || reversed))) { /* Maybe it's a double... */ - generate_double_arith(jitter, arith, cmp, reversed, 0, v, &refd, &refdt, branch_short); + generate_double_arith(jitter, arith, cmp, reversed, 0, v, &refd, &refdt, branch_short, unsafe_fl); CHECK_LIMIT(); } - if (!has_fixnum_fast) { - __START_TINY_JUMPS__(1); - mz_patch_branch(ref2); - __END_TINY_JUMPS__(1); - } + if (!unsafe_fx && !unsafe_fl) { + if (!has_fixnum_fast) { + __START_TINY_JUMPS__(1); + mz_patch_branch(ref2); + __END_TINY_JUMPS__(1); + } - /* Slow path */ - refslow = generate_arith_slow_path(jitter, rator, &ref, &ref4, for_branch, orig_args, reversed, arith, 1, v); + /* Slow path */ + refslow = generate_arith_slow_path(jitter, rator, &ref, &ref4, for_branch, orig_args, reversed, arith, 1, v); - if (has_fixnum_fast) { - __START_TINY_JUMPS__(1); - mz_patch_branch(ref2); - __END_TINY_JUMPS__(1); + if (has_fixnum_fast) { + __START_TINY_JUMPS__(1); + mz_patch_branch(ref2); + __END_TINY_JUMPS__(1); + } + } else { + refslow = NULL; + ref = NULL; + ref4 = NULL; } } @@ -3696,286 +3764,376 @@ static int generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj __START_SHORT_JUMPS__(branch_short); - if (arith) { - if (rand2) { - /* First arg is in JIT_R1, second is in JIT_R0 */ - if (arith == 1) { - jit_andi_ul(JIT_R2, JIT_R1, (~0x1)); - (void)jit_boaddr_l(refslow, JIT_R2, JIT_R0); - jit_movr_p(JIT_R0, JIT_R2); - } else if (arith == -1) { - if (reversed) { - jit_movr_p(JIT_R2, JIT_R0); - (void)jit_bosubr_l(refslow, JIT_R2, JIT_R1); - } else { - jit_movr_p(JIT_R2, JIT_R1); - (void)jit_bosubr_l(refslow, JIT_R2, JIT_R0); - } - jit_ori_ul(JIT_R0, JIT_R2, 0x1); - } else if (arith == 2) { - jit_andi_ul(JIT_R2, JIT_R1, (~0x1)); - jit_rshi_l(JIT_V1, JIT_R0, 0x1); - (void)jit_bomulr_l(refslow, JIT_V1, JIT_R2); - jit_ori_ul(JIT_R0, JIT_V1, 0x1); - } else if (arith == -2) { - if (has_fixnum_fast) { - /* No fast path for fixnum division, yet */ - (void)jit_jmpi(refslow); - } - } else if (arith == 3) { - /* and */ - jit_andr_ul(JIT_R0, JIT_R1, JIT_R0); - } else if (arith == 4) { - /* ior */ - jit_orr_ul(JIT_R0, JIT_R1, JIT_R0); - } else if (arith == 5) { - /* xor */ - jit_andi_ul(JIT_R0, JIT_R0, (~0x1)); - jit_xorr_ul(JIT_R0, JIT_R1, JIT_R0); - } else if (arith == 6) { - /* arithmetic-shift - This is a lot of code, but if you're using - arihtmetic-shift, then you probably want it. */ - int v1 = (reversed ? JIT_R0 : JIT_R1); - int v2 = (reversed ? JIT_R1 : JIT_R0); - jit_insn *refi, *refc; - - refi = jit_bgei_l(refslow, v2, (long)scheme_make_integer(0)); - - /* Right shift (always works for a small enough shift) */ - (void)jit_blti_l(refslow, v2, scheme_make_integer(-MAX_TRY_SHIFT)); - jit_notr_l(JIT_V1, v2); - jit_rshi_l(JIT_V1, JIT_V1, 0x1); - jit_addi_l(JIT_V1, JIT_V1, 0x1); - CHECK_LIMIT(); -#ifdef MZ_USE_JIT_I386 - /* Can't shift from _ECX */ - jit_movr_l(JIT_R2, v1); - jit_rshr_l(JIT_R2, JIT_R2, JIT_V1); -#else - jit_rshr_l(JIT_R2, v1, JIT_V1); -#endif - jit_ori_l(JIT_R0, JIT_R2, 0x1); - refc = jit_jmpi(jit_forward()); - CHECK_LIMIT(); - - /* Left shift */ - mz_patch_branch(refi); - (void)jit_bgti_l(refslow, v2, (long)scheme_make_integer(MAX_TRY_SHIFT)); - jit_rshi_l(JIT_V1, v2, 0x1); - jit_andi_l(v1, v1, (~0x1)); -#ifdef MZ_USE_JIT_I386 - /* Can't shift from _ECX */ - jit_movr_l(JIT_R2, v1); - jit_lshr_l(JIT_R2, JIT_R2, JIT_V1); -#else - jit_lshr_l(JIT_R2, v1, JIT_V1); -#endif - CHECK_LIMIT(); - /* If shifting back right produces a different result, that's overflow... */ - jit_rshr_l(JIT_V1, JIT_R2, JIT_V1); - /* !! In case we go refslow, it nseed to add back tag to v1 !! */ - (void)jit_bner_p(refslow, JIT_V1, v1); - /* No overflow. */ - jit_ori_l(JIT_R0, JIT_R2, 0x1); - - mz_patch_ucbranch(refc); - } else if (arith == 9) { - /* min */ - jit_insn *refc; - __START_INNER_TINY__(branch_short); - refc = jit_bltr_l(jit_forward(), JIT_R0, JIT_R1); - jit_movr_l(JIT_R0, JIT_R1); - mz_patch_branch(refc); - __END_INNER_TINY__(branch_short); - } else if (arith == 10) { - /* max */ - jit_insn *refc; - __START_INNER_TINY__(branch_short); - refc = jit_bgtr_l(jit_forward(), JIT_R0, JIT_R1); - jit_movr_l(JIT_R0, JIT_R1); - mz_patch_branch(refc); - __END_INNER_TINY__(branch_short); + if (!unsafe_fl) { + if (arith) { + if (((arith == -3) || (arith == -4)) && !rand2) { + (void)jit_movi_p(JIT_R1, scheme_make_integer(v)); + rand2 = scheme_true; + reversed = !reversed; } - } else { - /* Non-constant arg is in JIT_R0 */ - if (arith == 1) { - jit_movr_p(JIT_R2, JIT_R0); - (void)jit_boaddi_l(refslow, JIT_R2, v << 1); - jit_movr_p(JIT_R0, JIT_R2); - } else if (arith == -1) { - if (reversed) { - (void)jit_movi_p(JIT_R2, scheme_make_integer(v)); - (void)jit_bosubr_l(refslow, JIT_R2, JIT_R0); - jit_addi_ul(JIT_R0, JIT_R2, 0x1); - } else { - jit_movr_p(JIT_R2, JIT_R0); - (void)jit_bosubi_l(refslow, JIT_R2, v << 1); - jit_movr_p(JIT_R0, JIT_R2); - } - } else if (arith == 2) { - if (v == 1) { - /* R0 already is the answer */ - } else if (v == 0) { - (void)jit_movi_p(JIT_R0, scheme_make_integer(0)); - } else { - (void)jit_movi_p(JIT_R1, scheme_make_integer(v)); + + if (rand2) { + /* First arg is in JIT_R1, second is in JIT_R0 */ + if (arith == 1) { + jit_andi_ul(JIT_R2, JIT_R1, (~0x1)); + if (unsafe_fx) + jit_addr_l(JIT_R2, JIT_R2, JIT_R0); + else + (void)jit_boaddr_l(refslow, JIT_R2, JIT_R0); + jit_movr_p(JIT_R0, JIT_R2); + } else if (arith == -1) { + if (reversed) { + jit_movr_p(JIT_R2, JIT_R0); + if (unsafe_fx) + jit_subr_l(JIT_R2, JIT_R2, JIT_R1); + else + (void)jit_bosubr_l(refslow, JIT_R2, JIT_R1); + } else { + jit_movr_p(JIT_R2, JIT_R1); + if (unsafe_fx) + (void)jit_subr_l(JIT_R2, JIT_R2, JIT_R0); + else + (void)jit_bosubr_l(refslow, JIT_R2, JIT_R0); + } + jit_ori_ul(JIT_R0, JIT_R2, 0x1); + } else if (arith == 2) { jit_andi_ul(JIT_R2, JIT_R1, (~0x1)); jit_rshi_l(JIT_V1, JIT_R0, 0x1); - (void)jit_bomulr_l(refslow, JIT_V1, JIT_R2); + if (unsafe_fx) + jit_mulr_l(JIT_V1, JIT_V1, JIT_R2); + else + (void)jit_bomulr_l(refslow, JIT_V1, JIT_R2); jit_ori_ul(JIT_R0, JIT_V1, 0x1); - } - } else if (arith == -2) { - if ((v == 1) && !reversed) { - /* R0 already is the answer */ - } else { + } else if (arith == -2) { if (has_fixnum_fast) { - /* No general fast path for fixnum division, yet */ - (void)jit_movi_p(JIT_R1, scheme_make_integer(v)); + /* No fast path for fixnum division, yet */ (void)jit_jmpi(refslow); } - } - } else { - if (arith == 3) { - /* and */ - long l = (long)scheme_make_integer(v); - jit_andi_ul(JIT_R0, JIT_R0, l); - } else if (arith == 4) { - /* ior */ - long l = (long)scheme_make_integer(v); - jit_ori_ul(JIT_R0, JIT_R0, l); - } else if (arith == 5) { - /* xor */ - jit_xori_ul(JIT_R0, JIT_R0, v << 1); - } else if (arith == 6) { - /* arithmetic-shift */ - /* We only get here when v is between -MAX_TRY_SHIFT and MAX_TRY_SHIFT, inclusive */ - if (v <= 0) { - jit_rshi_l(JIT_R0, JIT_R0, -v); - jit_ori_l(JIT_R0, JIT_R0, 0x1); - } else { - jit_andi_l(JIT_R0, JIT_R0, (~0x1)); - jit_lshi_l(JIT_R2, JIT_R0, v); - /* If shifting back right produces a different result, that's overflow... */ - jit_rshi_l(JIT_V1, JIT_R2, v); - /* !! In case we go refslow, it nseed to add back tag to JIT_R0 !! */ - (void)jit_bner_p(refslow, JIT_V1, JIT_R0); - /* No overflow. */ - jit_ori_l(JIT_R0, JIT_R2, 0x1); - } - } else if (arith == 7) { - jit_notr_ul(JIT_R0, JIT_R0); - jit_ori_ul(JIT_R0, JIT_R0, 0x1); - } else if (arith == 9) { + } else if ((arith == -3) || (arith == -4)) { + /* -3 : quotient -4 : remainder */ + jit_rshi_l(JIT_V1, JIT_R0, 0x1); + jit_rshi_l(JIT_R2, JIT_R1, 0x1); + if (reversed) { + if (!unsafe_fx) + (void)jit_beqi_l(refslow, JIT_R2, 0); + if (arith == -3) + jit_divr_l(JIT_R0, JIT_V1, JIT_R2); + else + jit_modr_l(JIT_R0, JIT_V1, JIT_R2); + } else { + if (!unsafe_fx) + (void)jit_beqi_l(refslow, JIT_V1, 0); + if (arith == -3) + jit_divr_l(JIT_R0, JIT_R2, JIT_V1); + else + jit_modr_l(JIT_R0, JIT_R2, JIT_V1); + } + jit_lshi_l(JIT_R0, JIT_R0, 1); + jit_ori_l(JIT_R0, JIT_R0, 0x1); + } else if (arith == 3) { + /* and */ + jit_andr_ul(JIT_R0, JIT_R1, JIT_R0); + } else if (arith == 4) { + /* ior */ + jit_orr_ul(JIT_R0, JIT_R1, JIT_R0); + } else if (arith == 5) { + /* xor */ + jit_andi_ul(JIT_R0, JIT_R0, (~0x1)); + jit_xorr_ul(JIT_R0, JIT_R1, JIT_R0); + } else if ((arith == 6) || (arith == -6)) { + /* arithmetic-shift + This is a lot of code, but if you're using + arihtmetic-shift, then you probably want it. */ + int v1 = (reversed ? JIT_R0 : JIT_R1); + int v2 = (reversed ? JIT_R1 : JIT_R0); + jit_insn *refi, *refc; + + if (!unsafe_fx) + refi = jit_bgei_l(jit_forward(), v2, (long)scheme_make_integer(0)); + else + refi = NULL; + + if (!unsafe_fx || (arith == -6)) { + /* Right shift */ + if (!unsafe_fx) { + /* check for a small enough shift */ + (void)jit_blti_l(refslow, v2, scheme_make_integer(-MAX_TRY_SHIFT)); + jit_notr_l(JIT_V1, v2); + jit_rshi_l(JIT_V1, JIT_V1, 0x1); + } else { + jit_rshi_l(JIT_V1, v2, 0x1); + } + if (!unsafe_fx) + jit_addi_l(JIT_V1, JIT_V1, 0x1); + CHECK_LIMIT(); +#ifdef MZ_USE_JIT_I386 + /* Can't shift from _ECX */ + jit_movr_l(JIT_R2, v1); + jit_rshr_l(JIT_R2, JIT_R2, JIT_V1); +#else + jit_rshr_l(JIT_R2, v1, JIT_V1); +#endif + jit_ori_l(JIT_R0, JIT_R2, 0x1); + if (!unsafe_fx) + refc = jit_jmpi(jit_forward()); + else + refc = NULL; + CHECK_LIMIT(); + } else + refc = NULL; + + /* Left shift */ + if (!unsafe_fx || (arith == 6)) { + if (refi) + mz_patch_branch(refi); + if (!unsafe_fx) + (void)jit_bgti_l(refslow, v2, (long)scheme_make_integer(MAX_TRY_SHIFT)); + jit_rshi_l(JIT_V1, v2, 0x1); + jit_andi_l(v1, v1, (~0x1)); +#ifdef MZ_USE_JIT_I386 + /* Can't shift from _ECX */ + jit_movr_l(JIT_R2, v1); + jit_lshr_l(JIT_R2, JIT_R2, JIT_V1); +#else + jit_lshr_l(JIT_R2, v1, JIT_V1); +#endif + CHECK_LIMIT(); + /* If shifting back right produces a different result, that's overflow... */ + jit_rshr_l(JIT_V1, JIT_R2, JIT_V1); + /* !! In case we go refslow, it nseed to add back tag to v1 !! */ + if (!unsafe_fx) + (void)jit_bner_p(refslow, JIT_V1, v1); + /* No overflow. */ + jit_ori_l(JIT_R0, JIT_R2, 0x1); + } + + if (refc) + mz_patch_ucbranch(refc); + } else if (arith == 9) { /* min */ jit_insn *refc; __START_INNER_TINY__(branch_short); - refc = jit_blti_l(jit_forward(), JIT_R0, (long)scheme_make_integer(v)); - jit_movi_l(JIT_R0, (long)scheme_make_integer(v)); + refc = jit_bltr_l(jit_forward(), JIT_R0, JIT_R1); + jit_movr_l(JIT_R0, JIT_R1); mz_patch_branch(refc); __END_INNER_TINY__(branch_short); } else if (arith == 10) { /* max */ jit_insn *refc; __START_INNER_TINY__(branch_short); - refc = jit_bgti_l(jit_forward(), JIT_R0, (long)scheme_make_integer(v)); - jit_movi_l(JIT_R0, (long)scheme_make_integer(v)); + refc = jit_bgtr_l(jit_forward(), JIT_R0, JIT_R1); + jit_movr_l(JIT_R0, JIT_R1); mz_patch_branch(refc); __END_INNER_TINY__(branch_short); - } else if (arith == 11) { - /* abs */ - jit_insn *refc; - __START_INNER_TINY__(branch_short); - refc = jit_bgei_l(jit_forward(), JIT_R0, (long)scheme_make_integer(0)); - __END_INNER_TINY__(branch_short); - /* watch out for most negative fixnum! */ - (void)jit_beqi_p(refslow, JIT_R0, (void *)(((long)1 << ((8 * JIT_WORD_SIZE) - 1)) | 0x1)); - jit_rshi_l(JIT_R0, JIT_R0, 1); - jit_movi_l(JIT_R1, 0); - jit_subr_l(JIT_R0, JIT_R1, JIT_R0); - jit_lshi_l(JIT_R0, JIT_R0, 1); - jit_ori_l(JIT_R0, JIT_R0, 0x1); - __START_INNER_TINY__(branch_short); - mz_patch_branch(refc); - __END_INNER_TINY__(branch_short); - CHECK_LIMIT(); + } + } else { + /* Non-constant arg is in JIT_R0 */ + if (arith == 1) { + jit_movr_p(JIT_R2, JIT_R0); + if (unsafe_fx) + jit_addi_l(JIT_R2, JIT_R2, v << 1); + else + (void)jit_boaddi_l(refslow, JIT_R2, v << 1); + jit_movr_p(JIT_R0, JIT_R2); + } else if (arith == -1) { + if (reversed) { + (void)jit_movi_p(JIT_R2, scheme_make_integer(v)); + if (unsafe_fx) + jit_subr_l(JIT_R2, JIT_R2, JIT_R0); + else + (void)jit_bosubr_l(refslow, JIT_R2, JIT_R0); + jit_addi_ul(JIT_R0, JIT_R2, 0x1); + } else { + jit_movr_p(JIT_R2, JIT_R0); + if (unsafe_fx) + jit_subi_l(JIT_R2, JIT_R2, v << 1); + else + (void)jit_bosubi_l(refslow, JIT_R2, v << 1); + jit_movr_p(JIT_R0, JIT_R2); + } + } else if (arith == 2) { + if (v == 1) { + /* R0 already is the answer */ + } else if (v == 0) { + (void)jit_movi_p(JIT_R0, scheme_make_integer(0)); + } else { + (void)jit_movi_p(JIT_R1, scheme_make_integer(v)); + jit_andi_ul(JIT_R2, JIT_R1, (~0x1)); + jit_rshi_l(JIT_V1, JIT_R0, 0x1); + if (unsafe_fx) + jit_mulr_l(JIT_V1, JIT_V1, JIT_R2); + else + (void)jit_bomulr_l(refslow, JIT_V1, JIT_R2); + jit_ori_ul(JIT_R0, JIT_V1, 0x1); + } + } else if (arith == -2) { + if ((v == 1) && !reversed) { + /* R0 already is the answer */ + } else { + if (has_fixnum_fast) { + /* No general fast path for fixnum division, yet */ + (void)jit_movi_p(JIT_R1, scheme_make_integer(v)); + (void)jit_jmpi(refslow); + } + } + } else { + if (arith == 3) { + /* and */ + long l = (long)scheme_make_integer(v); + jit_andi_ul(JIT_R0, JIT_R0, l); + } else if (arith == 4) { + /* ior */ + long l = (long)scheme_make_integer(v); + jit_ori_ul(JIT_R0, JIT_R0, l); + } else if (arith == 5) { + /* xor */ + jit_xori_ul(JIT_R0, JIT_R0, v << 1); + } else if ((arith == 6) || (arith == -6)) { + /* arithmetic-shift */ + /* We only get here when v is between -MAX_TRY_SHIFT and MAX_TRY_SHIFT, inclusive */ + if ((v <= 0) || (arith == -6)) { + int amt = v; + if (arith != -6) + amt = -amt; + jit_rshi_l(JIT_R0, JIT_R0, amt); + jit_ori_l(JIT_R0, JIT_R0, 0x1); + } else { + jit_andi_l(JIT_R0, JIT_R0, (~0x1)); + jit_lshi_l(JIT_R2, JIT_R0, v); + if (!unsafe_fx) { + /* If shifting back right produces a different result, that's overflow... */ + jit_rshi_l(JIT_V1, JIT_R2, v); + /* !! In case we go refslow, it nseed to add back tag to JIT_R0 !! */ + (void)jit_bner_p(refslow, JIT_V1, JIT_R0); + } + /* No overflow. */ + jit_ori_l(JIT_R0, JIT_R2, 0x1); + } + } else if (arith == 7) { + jit_notr_ul(JIT_R0, JIT_R0); + jit_ori_ul(JIT_R0, JIT_R0, 0x1); + } else if (arith == 9) { + /* min */ + jit_insn *refc; + __START_INNER_TINY__(branch_short); + refc = jit_blti_l(jit_forward(), JIT_R0, (long)scheme_make_integer(v)); + jit_movi_l(JIT_R0, (long)scheme_make_integer(v)); + mz_patch_branch(refc); + __END_INNER_TINY__(branch_short); + } else if (arith == 10) { + /* max */ + jit_insn *refc; + __START_INNER_TINY__(branch_short); + refc = jit_bgti_l(jit_forward(), JIT_R0, (long)scheme_make_integer(v)); + jit_movi_l(JIT_R0, (long)scheme_make_integer(v)); + mz_patch_branch(refc); + __END_INNER_TINY__(branch_short); + } else if (arith == 11) { + /* abs */ + jit_insn *refc; + __START_INNER_TINY__(branch_short); + refc = jit_bgei_l(jit_forward(), JIT_R0, (long)scheme_make_integer(0)); + __END_INNER_TINY__(branch_short); + /* watch out for most negative fixnum! */ + if (!unsafe_fx) + (void)jit_beqi_p(refslow, JIT_R0, (void *)(((long)1 << ((8 * JIT_WORD_SIZE) - 1)) | 0x1)); + jit_rshi_l(JIT_R0, JIT_R0, 1); + jit_movi_l(JIT_R1, 0); + jit_subr_l(JIT_R0, JIT_R1, JIT_R0); + jit_lshi_l(JIT_R0, JIT_R0, 1); + jit_ori_l(JIT_R0, JIT_R0, 0x1); + __START_INNER_TINY__(branch_short); + mz_patch_branch(refc); + __END_INNER_TINY__(branch_short); + CHECK_LIMIT(); + } } } + if (refdt) + mz_patch_ucbranch(refdt); + if (!unsafe_fx && !unsafe_fl) + jit_patch_movi(ref, (_jit.x.pc)); + ref3 = NULL; + } else { + /* If second is constant, first arg is in JIT_R0. */ + /* Otherwise, first arg is in JIT_R1, second is in JIT_R0 */ + /* Jump to ref3 to produce false */ + switch (cmp) { + case -3: + if (rand2) { + if (!unsafe_fx) { + (void)jit_blti_l(refslow, JIT_R1, 0); + (void)jit_bgti_l(refslow, JIT_R1, (long)scheme_make_integer(MAX_TRY_SHIFT)); + } + jit_rshi_l(JIT_R1, JIT_R1, 1); + jit_addi_l(JIT_V1, JIT_R1, 1); + jit_movi_l(JIT_R2, 1); + jit_lshr_l(JIT_R2, JIT_R2, JIT_V1); + ref3 = jit_bmcr_l(jit_forward(), JIT_R0, JIT_R2); + } else { + /* shouldn't get here */ + scheme_signal_error("bitwise-bit-test? constant in wrong position"); + ref3 = NULL; + } + break; + case -2: + if (rand2) { + ref3 = jit_bger_l(jit_forward(), JIT_R1, JIT_R0); + } else { + ref3 = jit_bgei_l(jit_forward(), JIT_R0, (long)scheme_make_integer(v)); + } + break; + case -1: + if (rand2) { + ref3 = jit_bgtr_l(jit_forward(), JIT_R1, JIT_R0); + } else { + ref3 = jit_bgti_l(jit_forward(), JIT_R0, (long)scheme_make_integer(v)); + } + break; + case 0: + if (rand2) { + ref3 = jit_bner_l(jit_forward(), JIT_R1, JIT_R0); + } else { + ref3 = jit_bnei_l(jit_forward(), JIT_R0, (long)scheme_make_integer(v)); + } + break; + case 1: + if (rand2) { + ref3 = jit_bltr_l(jit_forward(), JIT_R1, JIT_R0); + } else { + ref3 = jit_blti_l(jit_forward(), JIT_R0, (long)scheme_make_integer(v)); + } + break; + case 2: + if (rand2) { + ref3 = jit_bler_l(jit_forward(), JIT_R1, JIT_R0); + } else { + ref3 = jit_blei_l(jit_forward(), JIT_R0, (long)scheme_make_integer(v)); + } + break; + default: + case 3: + if (rand2) { + if (!unsafe_fx) { + (void)jit_blti_l(refslow, JIT_R0, 0); + (void)jit_bgti_l(refslow, JIT_R0, (long)scheme_make_integer(MAX_TRY_SHIFT)); + } + jit_rshi_l(JIT_R0, JIT_R0, 1); + jit_addi_l(JIT_R0, JIT_R0, 1); + jit_movi_l(JIT_V1, 1); + jit_lshr_l(JIT_R0, JIT_V1, JIT_R0); + ref3 = jit_bmcr_l(jit_forward(), JIT_R1, JIT_R0); + } else { + ref3 = jit_bmci_l(jit_forward(), JIT_R0, 1 << (v+1)); + } + break; + } } - if (refdt) - mz_patch_ucbranch(refdt); - jit_patch_movi(ref, (_jit.x.pc)); } else { - /* If second is constant, first arg is in JIT_R0. */ - /* Otherwise, first arg is in JIT_R1, second is in JIT_R0 */ - /* Jump to ref3 to produce false */ - switch (cmp) { - case -3: - if (rand2) { - (void)jit_blti_l(refslow, JIT_R1, 0); - (void)jit_bgti_l(refslow, JIT_R1, (long)scheme_make_integer(MAX_TRY_SHIFT)); - jit_rshi_l(JIT_R1, JIT_R1, 1); - jit_addi_l(JIT_V1, JIT_R1, 1); - jit_movi_l(JIT_R2, 1); - jit_lshr_l(JIT_R2, JIT_R2, JIT_V1); - ref3 = jit_bmcr_l(jit_forward(), JIT_R0, JIT_R2); - } else { - /* shouldn't get here */ - scheme_signal_error("bitwise-bit-test? constant in wrong position"); - ref3 = NULL; - } - break; - case -2: - if (rand2) { - ref3 = jit_bger_l(jit_forward(), JIT_R1, JIT_R0); - } else { - ref3 = jit_bgei_l(jit_forward(), JIT_R0, (long)scheme_make_integer(v)); - } - break; - case -1: - if (rand2) { - ref3 = jit_bgtr_l(jit_forward(), JIT_R1, JIT_R0); - } else { - ref3 = jit_bgti_l(jit_forward(), JIT_R0, (long)scheme_make_integer(v)); - } - break; - case 0: - if (rand2) { - ref3 = jit_bner_l(jit_forward(), JIT_R1, JIT_R0); - } else { - ref3 = jit_bnei_l(jit_forward(), JIT_R0, (long)scheme_make_integer(v)); - } - break; - case 1: - if (rand2) { - ref3 = jit_bltr_l(jit_forward(), JIT_R1, JIT_R0); - } else { - ref3 = jit_blti_l(jit_forward(), JIT_R0, (long)scheme_make_integer(v)); - } - break; - case 2: - if (rand2) { - ref3 = jit_bler_l(jit_forward(), JIT_R1, JIT_R0); - } else { - ref3 = jit_blei_l(jit_forward(), JIT_R0, (long)scheme_make_integer(v)); - } - break; - default: - case 3: - if (rand2) { - (void)jit_blti_l(refslow, JIT_R0, 0); - (void)jit_bgti_l(refslow, JIT_R0, (long)scheme_make_integer(MAX_TRY_SHIFT)); - jit_rshi_l(JIT_R0, JIT_R0, 1); - jit_addi_l(JIT_R0, JIT_R0, 1); - jit_movi_l(JIT_V1, 1); - jit_lshr_l(JIT_R0, JIT_V1, JIT_R0); - ref3 = jit_bmcr_l(jit_forward(), JIT_R1, JIT_R0); - } else { - ref3 = jit_bmci_l(jit_forward(), JIT_R0, 1 << (v+1)); - } - break; - } + ref3 = NULL; + } + if (!arith) { if (refdt) mz_patch_ucbranch(refdt); @@ -3983,16 +4141,19 @@ static int generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj for_branch[0] = ref3; for_branch[1] = refd; for_branch[2] = ref; - jit_patch_movi(ref4, (_jit.x.pc)); + if (ref4) + jit_patch_movi(ref4, (_jit.x.pc)); } else { (void)jit_movi_p(JIT_R0, scheme_true); ref2 = jit_jmpi(jit_forward()); - mz_patch_branch(ref3); + if (ref3) + mz_patch_branch(ref3); if (refd) mz_patch_branch(refd); (void)jit_movi_p(JIT_R0, scheme_false); mz_patch_ucbranch(ref2); - jit_patch_movi(ref, (_jit.x.pc)); + if (!unsafe_fx && !unsafe_fl) + jit_patch_movi(ref, (_jit.x.pc)); } } @@ -4251,13 +4412,13 @@ static int generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, in generate_inlined_constant_test(jitter, app, scheme_eof, NULL, for_branch, branch_short, need_sync); return 1; } else if (IS_NAMED_PRIM(rator, "zero?")) { - generate_arith(jitter, rator, app->rand, NULL, 1, 0, 0, 0, for_branch, branch_short); + generate_arith(jitter, rator, app->rand, NULL, 1, 0, 0, 0, for_branch, branch_short, 0, 0); return 1; } else if (IS_NAMED_PRIM(rator, "negative?")) { - generate_arith(jitter, rator, app->rand, NULL, 1, 0, -2, 0, for_branch, branch_short); + generate_arith(jitter, rator, app->rand, NULL, 1, 0, -2, 0, for_branch, branch_short, 0, 0); return 1; } else if (IS_NAMED_PRIM(rator, "positive?")) { - generate_arith(jitter, rator, app->rand, NULL, 1, 0, 2, 0, for_branch, branch_short); + generate_arith(jitter, rator, app->rand, NULL, 1, 0, 2, 0, for_branch, branch_short, 0, 0); return 1; } else if (IS_NAMED_PRIM(rator, "exact-nonnegative-integer?") || IS_NAMED_PRIM(rator, "exact-positive-integer?")) { @@ -4440,7 +4601,31 @@ static int generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, in __END_TINY_JUMPS__(1); return 1; - } else if (IS_NAMED_PRIM(rator, "vector-length")) { + } else if (IS_NAMED_PRIM(rator, "unsafe-car") + || IS_NAMED_PRIM(rator, "unsafe-mcar") + || IS_NAMED_PRIM(rator, "unsafe-cdr") + || IS_NAMED_PRIM(rator, "unsafe-mcdr")) { + const char *name = ((Scheme_Primitive_Proc *)rator)->name; + + LOG_IT(("inlined %s\n", ((Scheme_Primitive_Proc *)rator)->name)); + + mz_runstack_skipped(jitter, 1); + + generate_non_tail(app->rand, jitter, 0, 1); + CHECK_LIMIT(); + + mz_runstack_unskipped(jitter, 1); + + if (!strcmp(name, "unsafe-car") || !strcmp(name, "unsafe-mcar")) { + (void)jit_ldxi_p(JIT_R0, JIT_R0, &((Scheme_Simple_Object *)0x0)->u.pair_val.car); + } else { + (void)jit_ldxi_p(JIT_R0, JIT_R0, &((Scheme_Simple_Object *)0x0)->u.pair_val.cdr); + } + CHECK_LIMIT(); + + return 1; + } else if (IS_NAMED_PRIM(rator, "vector-length") + || IS_NAMED_PRIM(rator, "unsafe-vector-length")) { GC_CAN_IGNORE jit_insn *reffail, *ref; LOG_IT(("inlined vector-length\n")); @@ -4452,20 +4637,22 @@ static int generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, in mz_runstack_unskipped(jitter, 1); - mz_rs_sync_fail_branch(); + if (!IS_NAMED_PRIM(rator, "unsafe-vector-length")) { + mz_rs_sync_fail_branch(); - __START_TINY_JUMPS__(1); - ref = jit_bmci_ul(jit_forward(), JIT_R0, 0x1); - __END_TINY_JUMPS__(1); + __START_TINY_JUMPS__(1); + ref = jit_bmci_ul(jit_forward(), JIT_R0, 0x1); + __END_TINY_JUMPS__(1); + + reffail = _jit.x.pc; + (void)jit_calli(bad_vector_length_code); - reffail = _jit.x.pc; - (void)jit_calli(bad_vector_length_code); - - __START_TINY_JUMPS__(1); - mz_patch_branch(ref); - jit_ldxi_s(JIT_R1, JIT_R0, &((Scheme_Object *)0x0)->type); - (void)jit_bnei_i(reffail, JIT_R1, scheme_vector_type); - __END_TINY_JUMPS__(1); + __START_TINY_JUMPS__(1); + mz_patch_branch(ref); + jit_ldxi_s(JIT_R1, JIT_R0, &((Scheme_Object *)0x0)->type); + (void)jit_bnei_i(reffail, JIT_R1, scheme_vector_type); + __END_TINY_JUMPS__(1); + } (void)jit_ldxi_i(JIT_R0, JIT_R0, &SCHEME_VEC_SIZE(0x0)); jit_lshi_l(JIT_R0, JIT_R0, 1); @@ -4501,6 +4688,19 @@ static int generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, in (void)jit_ldxi_p(JIT_R0, JIT_R0, &SCHEME_BOX_VAL(0x0)); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-unbox")) { + LOG_IT(("inlined unbox\n")); + + mz_runstack_skipped(jitter, 1); + + generate_non_tail(app->rand, jitter, 0, 1); + CHECK_LIMIT(); + + mz_runstack_unskipped(jitter, 1); + + (void)jit_ldxi_p(JIT_R0, JIT_R0, &SCHEME_BOX_VAL(0x0)); + return 1; } else if (IS_NAMED_PRIM(rator, "syntax-e")) { LOG_IT(("inlined syntax-e\n")); @@ -4518,19 +4718,22 @@ static int generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, in return 1; } else if (IS_NAMED_PRIM(rator, "add1")) { - generate_arith(jitter, rator, app->rand, NULL, 1, 1, 0, 1, NULL, 1); + generate_arith(jitter, rator, app->rand, NULL, 1, 1, 0, 1, NULL, 1, 0, 0); return 1; } else if (IS_NAMED_PRIM(rator, "sub1")) { - generate_arith(jitter, rator, app->rand, NULL, 1, -1, 0, 1, NULL, 1); + generate_arith(jitter, rator, app->rand, NULL, 1, -1, 0, 1, NULL, 1, 0, 0); return 1; } else if (IS_NAMED_PRIM(rator, "-")) { - generate_arith(jitter, rator, app->rand, NULL, 1, -1, 0, 0, NULL, 1); + generate_arith(jitter, rator, app->rand, NULL, 1, -1, 0, 0, NULL, 1, 0, 0); return 1; } else if (IS_NAMED_PRIM(rator, "abs")) { - generate_arith(jitter, rator, app->rand, NULL, 1, 11, 0, 0, NULL, 1); + generate_arith(jitter, rator, app->rand, NULL, 1, 11, 0, 0, NULL, 1, 0, 0); return 1; } else if (IS_NAMED_PRIM(rator, "bitwise-not")) { - generate_arith(jitter, rator, app->rand, NULL, 1, 7, 0, 9, NULL, 1); + generate_arith(jitter, rator, app->rand, NULL, 1, 7, 0, 9, NULL, 1, 0, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fxnot")) { + generate_arith(jitter, rator, app->rand, NULL, 1, 7, 0, 9, NULL, 1, 1, 0); return 1; } else if (IS_NAMED_PRIM(rator, "vector-immutable") || IS_NAMED_PRIM(rator, "vector")) { @@ -4751,13 +4954,13 @@ static int generate_binary_char(mz_jit_state *jitter, Scheme_App3_Rec *app, return 1; } -static int generate_vector_op(mz_jit_state *jitter, int set, int int_ready) -/* if int_ready, JIT_R1 has num index and JIT_V1 has pre-computed offset, +static int generate_vector_op(mz_jit_state *jitter, int set, int int_ready, int base_offset, int unsafe) +/* if int_ready, JIT_R1 has num index (for safe mode) and JIT_V1 has pre-computed offset, otherwise JIT_R1 has fixnum index */ { GC_CAN_IGNORE jit_insn *ref, *reffail; - if (!skip_checks) { + if (!skip_checks && !unsafe) { __START_TINY_JUMPS__(1); ref = jit_bmci_ul(jit_forward(), JIT_R0, 0x1); __END_TINY_JUMPS__(1); @@ -4797,7 +5000,7 @@ static int generate_vector_op(mz_jit_state *jitter, int set, int int_ready) if (!int_ready) { jit_lshi_ul(JIT_V1, JIT_V1, JIT_LOG_WORD_SIZE); - jit_addi_p(JIT_V1, JIT_V1, (int)&SCHEME_VEC_ELS(0x0)); + jit_addi_p(JIT_V1, JIT_V1, base_offset); } if (set) { jit_ldr_p(JIT_R2, JIT_RUNSTACK); @@ -4912,66 +5115,153 @@ static int generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i return 1; } else if (IS_NAMED_PRIM(rator, "=")) { - generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, 0, 0, for_branch, branch_short); + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, 0, 0, for_branch, branch_short, 0, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fx=")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, 0, 0, for_branch, branch_short, 1, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fl=")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, 0, 0, for_branch, branch_short, 0, 1); return 1; } else if (IS_NAMED_PRIM(rator, "<=")) { - generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, -1, 0, for_branch, branch_short); + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, -1, 0, for_branch, branch_short, 0, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fx<=")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, -1, 0, for_branch, branch_short, 1, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fl<=")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, -1, 0, for_branch, branch_short, 0, 1); return 1; } else if (IS_NAMED_PRIM(rator, "<")) { - generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, -2, 0, for_branch, branch_short); + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, -2, 0, for_branch, branch_short, 0, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fx<")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, -2, 0, for_branch, branch_short, 1, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fl<")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, -2, 0, for_branch, branch_short, 0, 1); return 1; } else if (IS_NAMED_PRIM(rator, ">=")) { - generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, 1, 0, for_branch, branch_short); + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, 1, 0, for_branch, branch_short, 0, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fx>=")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, 1, 0, for_branch, branch_short, 1, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fl>=")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, 1, 0, for_branch, branch_short, 0, 1); return 1; } else if (IS_NAMED_PRIM(rator, ">")) { - generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, 2, 0, for_branch, branch_short); + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, 2, 0, for_branch, branch_short, 0, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fx>")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, 2, 0, for_branch, branch_short, 1, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fl>")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, 2, 0, for_branch, branch_short, 0, 1); return 1; } else if (IS_NAMED_PRIM(rator, "bitwise-bit-set?")) { - generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, 3, 0, for_branch, branch_short); + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, 3, 0, for_branch, branch_short, 0, 0); return 1; } else if (IS_NAMED_PRIM(rator, "char=?")) { generate_binary_char(jitter, app, for_branch, branch_short); return 1; } else if (!for_branch) { if (IS_NAMED_PRIM(rator, "+")) { - generate_arith(jitter, rator, app->rand1, app->rand2, 2, 1, 0, 0, NULL, 1); + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 1, 0, 0, NULL, 1, 0, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fx+")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 1, 0, 0, NULL, 1, 1, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fl+")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 1, 0, 0, NULL, 1, 0, 1); return 1; } else if (IS_NAMED_PRIM(rator, "-")) { - generate_arith(jitter, rator, app->rand1, app->rand2, 2, -1, 0, 0, NULL, 1); + generate_arith(jitter, rator, app->rand1, app->rand2, 2, -1, 0, 0, NULL, 1, 0, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fx-")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, -1, 0, 0, NULL, 1, 1, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fl-")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, -1, 0, 0, NULL, 1, 0, 1); return 1; } else if (IS_NAMED_PRIM(rator, "*")) { - generate_arith(jitter, rator, app->rand1, app->rand2, 2, 2, 0, 0, NULL, 1); + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 2, 0, 0, NULL, 1, 0, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fx*")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 2, 0, 0, NULL, 1, 1, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fl*")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 2, 0, 0, NULL, 1, 0, 1); return 1; } else if (IS_NAMED_PRIM(rator, "/")) { - generate_arith(jitter, rator, app->rand1, app->rand2, 2, -2, 0, 0, NULL, 1); + generate_arith(jitter, rator, app->rand1, app->rand2, 2, -2, 0, 0, NULL, 1, 0, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fl/")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, -2, 0, 0, NULL, 1, 0, 1); + return 1; + } else if (IS_NAMED_PRIM(rator, "quotient")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, -3, 0, 0, NULL, 1, 0, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fxquotient")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, -3, 0, 0, NULL, 1, 1, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "remainder")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, -4, 0, 0, NULL, 1, 0, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fxremainder")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, -4, 0, 0, NULL, 1, 1, 0); return 1; } else if (IS_NAMED_PRIM(rator, "min")) { - generate_arith(jitter, rator, app->rand1, app->rand2, 2, 9, 0, 0, NULL, 1); + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 9, 0, 0, NULL, 1, 0, 0); return 1; } else if (IS_NAMED_PRIM(rator, "max")) { - generate_arith(jitter, rator, app->rand1, app->rand2, 2, 10, 0, 0, NULL, 1); + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 10, 0, 0, NULL, 1, 0, 0); return 1; } else if (IS_NAMED_PRIM(rator, "bitwise-and")) { - generate_arith(jitter, rator, app->rand1, app->rand2, 2, 3, 0, 0, NULL, 1); + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 3, 0, 0, NULL, 1, 0, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fxand")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 3, 0, 0, NULL, 1, 1, 0); return 1; } else if (IS_NAMED_PRIM(rator, "bitwise-ior")) { - generate_arith(jitter, rator, app->rand1, app->rand2, 2, 4, 0, 0, NULL, 1); + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 4, 0, 0, NULL, 1, 0, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fxior")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 4, 0, 0, NULL, 1, 1, 0); return 1; } else if (IS_NAMED_PRIM(rator, "bitwise-xor")) { - generate_arith(jitter, rator, app->rand1, app->rand2, 2, 5, 0, 0, NULL, 1); + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 5, 0, 0, NULL, 1, 0, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fxxor")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 5, 0, 0, NULL, 1, 1, 0); return 1; } else if (IS_NAMED_PRIM(rator, "arithmetic-shift")) { - generate_arith(jitter, rator, app->rand1, app->rand2, 2, 6, 0, 0, NULL, 1); + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 6, 0, 0, NULL, 1, 0, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fxlshift")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, 6, 0, 0, NULL, 1, 1, 0); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-fxrshift")) { + generate_arith(jitter, rator, app->rand1, app->rand2, 2, -6, 0, 0, NULL, 1, 1, 0); return 1; } else if (IS_NAMED_PRIM(rator, "vector-ref") + || IS_NAMED_PRIM(rator, "unsafe-vector-ref") + || IS_NAMED_PRIM(rator, "unsafe-struct-ref") || IS_NAMED_PRIM(rator, "string-ref") || IS_NAMED_PRIM(rator, "bytes-ref")) { int simple; - int which; + int which, unsafe = 0, base_offset = ((int)&SCHEME_VEC_ELS(0x0)); if (IS_NAMED_PRIM(rator, "vector-ref")) which = 0; - else if (IS_NAMED_PRIM(rator, "string-ref")) + else if (IS_NAMED_PRIM(rator, "unsafe-vector-ref")) { + which = 0; + unsafe = 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-struct-ref")) { + which = 0; + unsafe = 1; + base_offset = ((int)&((Scheme_Structure *)0x0)->slots); + } else if (IS_NAMED_PRIM(rator, "string-ref")) which = 1; else which = 2; @@ -4989,7 +5279,7 @@ static int generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i if (!which) { /* vector-ref is relatively simple and worth inlining */ - generate_vector_op(jitter, 0, 0); + generate_vector_op(jitter, 0, 0, base_offset, unsafe); CHECK_LIMIT(); } else if (which == 1) { (void)jit_calli(string_ref_check_index_code); @@ -5007,15 +5297,16 @@ static int generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i mz_rs_sync(); offset = SCHEME_INT_VAL(app->rand2); - (void)jit_movi_p(JIT_R1, offset); + if (!unsafe) + (void)jit_movi_p(JIT_R1, offset); if (!which) - offset = ((int)&SCHEME_VEC_ELS(0x0)) + WORDS_TO_BYTES(offset); + offset = base_offset + WORDS_TO_BYTES(offset); else if (which == 1) offset = offset << LOG_MZCHAR_SIZE; jit_movi_l(JIT_V1, offset); if (!which) { /* vector-ref is relatively simple and worth inlining */ - generate_vector_op(jitter, 0, 1); + generate_vector_op(jitter, 0, 1, base_offset, unsafe); CHECK_LIMIT(); } else if (which == 1) { (void)jit_calli(string_ref_code); @@ -5062,6 +5353,34 @@ static int generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i (void)jit_movi_p(JIT_R0, scheme_void); + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-set-mcar!") + || IS_NAMED_PRIM(rator, "unsafe-set-mcdr!")) { + int set_mcar; + + set_mcar = IS_NAMED_PRIM(rator, "unsafe-set-mcar!"); + + LOG_IT(("inlined unsafe-set-mcar!\n")); + + generate_two_args(app->rand1, app->rand2, jitter, 1, 2); + CHECK_LIMIT(); + if (set_mcar) + (void)jit_stxi_p(&((Scheme_Simple_Object *)0x0)->u.pair_val.car, JIT_R0, JIT_R1); + else + (void)jit_stxi_p(&((Scheme_Simple_Object *)0x0)->u.pair_val.cdr, JIT_R0, JIT_R1); + + (void)jit_movi_p(JIT_R0, scheme_void); + + return 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-set-box!")) { + LOG_IT(("inlined unsafe-set-box!\n")); + + generate_two_args(app->rand1, app->rand2, jitter, 1, 2); + CHECK_LIMIT(); + (void)jit_stxi_p(&SCHEME_BOX_VAL(0x0), JIT_R0, JIT_R1); + + (void)jit_movi_p(JIT_R0, scheme_void); + return 1; } else if (IS_NAMED_PRIM(rator, "cons") || IS_NAMED_PRIM(rator, "list*")) { @@ -5158,15 +5477,24 @@ static int generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int if (!for_branch) { if (IS_NAMED_PRIM(rator, "vector-set!") + || IS_NAMED_PRIM(rator, "unsafe-vector-set!") + || IS_NAMED_PRIM(rator, "unsafe-struct-set!") || IS_NAMED_PRIM(rator, "string-set!") || IS_NAMED_PRIM(rator, "bytes-set!")) { int simple, constval; - int which; + int which, unsafe = 0, base_offset = ((int)&SCHEME_VEC_ELS(0x0)); int pushed; if (IS_NAMED_PRIM(rator, "vector-set!")) which = 0; - else if (IS_NAMED_PRIM(rator, "string-set!")) + else if (IS_NAMED_PRIM(rator, "unsafe-vector-set!")) { + which = 0; + unsafe = 1; + } else if (IS_NAMED_PRIM(rator, "unsafe-struct-set!")) { + which = 0; + unsafe = 1; + base_offset = ((int)&((Scheme_Structure *)0x0)->slots); + } else if (IS_NAMED_PRIM(rator, "string-set!")) which = 1; else which = 2; @@ -5230,7 +5558,7 @@ static int generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int if (!simple) { if (!which) { /* vector-set! is relatively simple and worth inlining */ - generate_vector_op(jitter, 1, 0); + generate_vector_op(jitter, 1, 0, base_offset, unsafe); CHECK_LIMIT(); } else if (which == 1) { (void)jit_calli(string_set_check_index_code); @@ -5242,13 +5570,13 @@ static int generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int offset = SCHEME_INT_VAL(app->args[2]); (void)jit_movi_p(JIT_R1, offset); if (!which) - offset = ((int)&SCHEME_VEC_ELS(0x0)) + WORDS_TO_BYTES(offset); + offset = base_offset + WORDS_TO_BYTES(offset); else if (which == 1) offset = offset << LOG_MZCHAR_SIZE; jit_movi_l(JIT_V1, offset); if (!which) { /* vector-set! is relatively simple and worth inlining */ - generate_vector_op(jitter, 1, 1); + generate_vector_op(jitter, 1, 1, base_offset, unsafe); CHECK_LIMIT(); } else if (which == 1) { (void)jit_calli(string_set_code); diff --git a/src/mzscheme/src/lightning/i386/asm.h b/src/mzscheme/src/lightning/i386/asm.h index ec33c330fa..7a61015387 100644 --- a/src/mzscheme/src/lightning/i386/asm.h +++ b/src/mzscheme/src/lightning/i386/asm.h @@ -471,6 +471,7 @@ typedef _uc jit_insn; #define DIVLr(RS) _O_Mrm (0xf7 ,_b11,_b110 ,_r4(RS) ) #define DIVLm(MD,MB,MI,MS) _O_r_X (0xf7 ,_b110 ,MD,MB,MI,MS ) +#define DIVQr(RS) _qO_Mrm (0xf7 ,_b11,_b110 ,_r8(RS) ) #define ENTERii(W, B) _O_W_B (0xc8 ,_su16(W),_su8(B)) #define HLT_() _O (0xf4 ) @@ -485,6 +486,8 @@ typedef _uc jit_insn; #define IDIVLr(RS) _O_Mrm (0xf7 ,_b11,_b111 ,_r4(RS) ) #define IDIVLm(MD,MB,MI,MS) _O_r_X (0xf7 ,_b111 ,MD,MB,MI,MS ) +#define IDIVQr(RS) _qO_Mrm (0xf7 ,_b11,_b111 ,_r8(RS) ) + #define IMULBr(RS) _O_Mrm (0xf6 ,_b11,_b101 ,_r1(RS) ) #define IMULBm(MD,MB,MI,MS) _O_r_X (0xf6 ,_b101 ,MD,MB,MI,MS ) diff --git a/src/mzscheme/src/lightning/i386/core.h b/src/mzscheme/src/lightning/i386/core.h index 2cc980cbd5..b5ffab1737 100644 --- a/src/mzscheme/src/lightning/i386/core.h +++ b/src/mzscheme/src/lightning/i386/core.h @@ -171,64 +171,83 @@ struct jit_local_state { (MOVLir(is, rs == _EAX ? _EDX : _EAX), \ IMULLr(rs == _EAX ? _EDX : rs)) -#define jit_divi_i_(result, d, rs, is) \ +#define jit_divi_i_X(result, d, rs, is, MOVr, MOVi, SARi, nbits, IDIVr) \ (jit_might (d, _EAX, PUSHLr(_EAX)), \ jit_might (d, _ECX, PUSHLr(_ECX)), \ jit_might (d, _EDX, PUSHLr(_EDX)), \ - jit_might (rs, _EAX, MOVLrr(rs, _EAX)), \ - jit_might (rs, _EDX, MOVLrr(rs, _EDX)), \ - MOVLir(is, _ECX), \ - SARLir(31, _EDX), \ - IDIVLr(_ECX), \ - jit_might(d, result, MOVLrr(result, d)), \ + jit_might (rs, _EAX, MOVr(rs, _EAX)), \ + jit_might (rs, _EDX, MOVr(rs, _EDX)), \ + MOVr(is, _ECX), \ + SARi(nbits, _EDX), \ + IDIVr(_ECX), \ + jit_might(d, result, MOVr(result, d)), \ jit_might(d, _EDX, POPLr(_EDX)), \ jit_might(d, _ECX, POPLr(_ECX)), \ jit_might(d, _EAX, POPLr(_EAX))) -#define jit_divr_i_(result, d, s1, s2) \ +#define jit_divi_i_(result, d, rs, is) \ + jit_divi_i_X(result, d, rs, is, MOVLrr, MOVLir, SARLir, 31, IDIVLr) +#define jit_divi_l_(result, d, rs, is) \ + jit_divi_i_X(result, d, rs, is, MOVQrr, MOVQir, SARQir, 31, IDIVQr) + +#define jit_divr_i_X(result, d, s1, s2, MOVr, MOVi, SARi, nbits, IDIVr) \ (jit_might (d, _EAX, PUSHLr(_EAX)), \ jit_might (d, _ECX, PUSHLr(_ECX)), \ jit_might (d, _EDX, PUSHLr(_EDX)), \ ((s1 == _ECX) ? PUSHLr(_ECX) : 0), \ - jit_might (s2, _ECX, MOVLrr(s2, _ECX)), \ + jit_might (s2, _ECX, MOVr(s2, _ECX)), \ ((s1 == _ECX) ? POPLr(_EDX) : \ - jit_might (s1, _EDX, MOVLrr(s1, _EDX))), \ - MOVLrr(_EDX, _EAX), \ - SARLir(31, _EDX), \ - IDIVLr(_ECX), \ - jit_might(d, result, MOVLrr(result, d)), \ + jit_might (s1, _EDX, MOVr(s1, _EDX))), \ + MOVr(_EDX, _EAX), \ + SARi(nbits, _EDX), \ + IDIVr(_ECX), \ + jit_might(d, result, MOVr(result, d)), \ + jit_might(d, _EDX, POPLr(_EDX)), \ + jit_might(d, _ECX, POPLr(_ECX)), \ + jit_might(d, _EAX, POPLr(_EAX))) + +#define jit_divr_i_(result, d, s1, s2) \ + jit_divr_i_X(result, d, s1, s2, MOVLrr, MOVLir, SARLir, 31, IDIVLr) +#define jit_divr_l_(result, d, s1, s2) \ + jit_divr_i_X(result, d, s1, s2, MOVQrr, MOVQir, SARQir, 63, IDIVQr) + +#define jit_divi_ui_X(result, d, rs, is, MOVr, MOVi, XORr, DIVr) \ + (jit_might (d, _EAX, PUSHLr(_EAX)), \ + jit_might (d, _ECX, PUSHLr(_ECX)), \ + jit_might (d, _EDX, PUSHLr(_EDX)), \ + jit_might (rs, _EAX, MOVr(rs, _EAX)), \ + MOVi(is, _ECX), \ + XORr(_EDX, _EDX), \ + DIVr(_ECX), \ + jit_might(d, result, MOVr(result, d)), \ jit_might(d, _EDX, POPLr(_EDX)), \ jit_might(d, _ECX, POPLr(_ECX)), \ jit_might(d, _EAX, POPLr(_EAX))) #define jit_divi_ui_(result, d, rs, is) \ + jit_divi_ui_X(result, d, rs, is, MOVLrr, MOVLir, XORLrr, DIVLr) +#define jit_divi_ul_(result, d, rs, is) \ + jit_divi_ui_X(result, d, rs, is, MOVQrr, MOVQir, XORQrr, DIVQr) + +#define jit_divr_ui_X(result, d, s1, s2, MOVr, XORr, DIVr) \ (jit_might (d, _EAX, PUSHLr(_EAX)), \ jit_might (d, _ECX, PUSHLr(_ECX)), \ jit_might (d, _EDX, PUSHLr(_EDX)), \ - jit_might (rs, _EAX, MOVLrr(rs, _EAX)), \ - MOVLir(is, _ECX), \ - XORLrr(_EDX, _EDX), \ - DIVLr(_ECX), \ - jit_might(d, result, MOVLrr(result, d)), \ + ((s1 == _ECX) ? PUSHLr(_ECX) : 0), \ + jit_might (s2, _ECX, MOVr(s2, _ECX)), \ + ((s1 == _ECX) ? POPLr(_EAX) : \ + jit_might (s1, _EAX, MOVr(s1, _EAX))), \ + XORr(_EDX, _EDX), \ + DIVr(_ECX), \ + jit_might(d, result, MOVr(result, d)), \ jit_might(d, _EDX, POPLr(_EDX)), \ jit_might(d, _ECX, POPLr(_ECX)), \ jit_might(d, _EAX, POPLr(_EAX))) #define jit_divr_ui_(result, d, s1, s2) \ - (jit_might (d, _EAX, PUSHLr(_EAX)), \ - jit_might (d, _ECX, PUSHLr(_ECX)), \ - jit_might (d, _EDX, PUSHLr(_EDX)), \ - ((s1 == _ECX) ? PUSHLr(_ECX) : 0), \ - jit_might (s2, _ECX, MOVLrr(s2, _ECX)), \ - ((s1 == _ECX) ? POPLr(_EAX) : \ - jit_might (s1, _EAX, MOVLrr(s1, _EAX))), \ - XORLrr(_EDX, _EDX), \ - DIVLr(_ECX), \ - jit_might(d, result, MOVLrr(result, d)), \ - jit_might(d, _EDX, POPLr(_EDX)), \ - jit_might(d, _ECX, POPLr(_ECX)), \ - jit_might(d, _EAX, POPLr(_EAX))) - + jit_divr_ui_X(result, d, s1, s2, MOVLrr, XORLrr, DIVLr) +#define jit_divr_ul_(result, d, s1, s2) \ + jit_divr_ui_X(result, d, s1, s2, MOVQrr, XORQrr, DIVQr) /* ALU */ #define jit_addi_i(d, rs, is) jit_opi_((d), (rs), ADDLir((is), (d)), LEALmr((is), (rs), 0, 0, (d)) ) @@ -254,6 +273,8 @@ struct jit_local_state { #define jit_subr_l(d, s1, s2) jit_qopr_((d), (s1), (s2), (SUBQrr((s1), (d)), NEGQr(d)), SUBQrr((s2), (d)) ) #define jit_xorr_l(d, s1, s2) jit_qopr_((d), (s1), (s2), XORQrr((s1), (d)), XORQrr((s2), (d)) ) +#define jit_mulr_l(d, s1, s2) jit_opo_((d), (s1), (s2), IMULQrr((s2), (d)), IMULQrr((s1), (d)), LEAQmr(0, (s1), (s2), 1, (d)) ) + /* These can sometimes use byte or word versions! */ #define jit_ori_i(d, rs, is) jit_op_ ((d), (rs), jit_reduce(OR, (is), (d)) ) #define jit_xori_i(d, rs, is) jit_op_ ((d), (rs), jit_reduce(XOR, (is), (d)) ) @@ -294,8 +315,12 @@ struct jit_local_state { #define jit_modi_ui(d, rs, is) jit_divi_ui_(_EDX, (d), (rs), (is)) #define jit_divr_i(d, s1, s2) jit_divr_i_(_EAX, (d), (s1), (s2)) #define jit_divr_ui(d, s1, s2) jit_divr_ui_(_EAX, (d), (s1), (s2)) +#define jit_divr_l(d, s1, s2) jit_divr_l_(_EAX, (d), (s1), (s2)) +#define jit_divr_ul(d, s1, s2) jit_divr_ul_(_EAX, (d), (s1), (s2)) #define jit_modr_i(d, s1, s2) jit_divr_i_(_EDX, (d), (s1), (s2)) #define jit_modr_ui(d, s1, s2) jit_divr_ui_(_EDX, (d), (s1), (s2)) +#define jit_modr_l(d, s1, s2) jit_divr_l_(_EDX, (d), (s1), (s2)) +#define jit_modr_ul(d, s1, s2) jit_divr_ul_(_EDX, (d), (s1), (s2)) /* Shifts */ diff --git a/src/mzscheme/src/list.c b/src/mzscheme/src/list.c index 634c1cf545..04532047e8 100644 --- a/src/mzscheme/src/list.c +++ b/src/mzscheme/src/list.c @@ -135,6 +135,15 @@ static Scheme_Object *make_hasheq_placeholder(int argc, Scheme_Object *argv[]); static Scheme_Object *make_hasheqv_placeholder(int argc, Scheme_Object *argv[]); static Scheme_Object *table_placeholder_p(int argc, Scheme_Object *argv[]); +static Scheme_Object *unsafe_car (int argc, Scheme_Object *argv[]); +static Scheme_Object *unsafe_cdr (int argc, Scheme_Object *argv[]); +static Scheme_Object *unsafe_mcar (int argc, Scheme_Object *argv[]); +static Scheme_Object *unsafe_mcdr (int argc, Scheme_Object *argv[]); +static Scheme_Object *unsafe_set_mcar (int argc, Scheme_Object *argv[]); +static Scheme_Object *unsafe_set_mcdr (int argc, Scheme_Object *argv[]); +static Scheme_Object *unsafe_unbox (int argc, Scheme_Object *argv[]); +static Scheme_Object *unsafe_set_box (int argc, Scheme_Object *argv[]); + #define BOX "box" #define BOXP "box?" #define UNBOX "unbox" @@ -684,6 +693,46 @@ scheme_init_list (Scheme_Env *env) equal_symbol = scheme_intern_symbol("equal"); } +void +scheme_init_unsafe_list (Scheme_Env *env) +{ + Scheme_Object *p; + + scheme_null->type = scheme_null_type; + + p = scheme_make_folding_prim(unsafe_car, "unsafe-car", 1, 1, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_UNARY_INLINED; + scheme_add_global_constant ("unsafe-car", p, env); + + p = scheme_make_folding_prim(unsafe_cdr, "unsafe-cdr", 1, 1, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_UNARY_INLINED; + scheme_add_global_constant ("unsafe-cdr", p, env); + + p = scheme_make_immed_prim(unsafe_mcar, "unsafe-mcar", 1, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_UNARY_INLINED; + scheme_add_global_constant ("unsafe-mcar", p, env); + + p = scheme_make_immed_prim(unsafe_mcdr, "unsafe-mcdr", 1, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_UNARY_INLINED; + scheme_add_global_constant ("unsafe-mcdr", p, env); + + p = scheme_make_immed_prim(unsafe_set_mcar, "unsafe-set-mcar!", 2, 2); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant ("unsafe-set-mcar!", p, env); + + p = scheme_make_immed_prim(unsafe_set_mcdr, "unsafe-set-mcdr!", 2, 2); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant ("unsafe-set-mcdr!", p, env); + + p = scheme_make_immed_prim(unsafe_unbox, "unsafe-unbox", 1, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_UNARY_INLINED; + scheme_add_global_constant("unsafe-unbox", p, env); + + p = scheme_make_immed_prim(unsafe_set_box, "unsafe-set-box!", 2, 2); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-set-box!", p, env); +} + Scheme_Object *scheme_make_pair(Scheme_Object *car, Scheme_Object *cdr) { #ifdef MZ_PRECISE_GC @@ -2534,3 +2583,50 @@ void scheme_init_ephemerons(void) } #endif + +/************************************************************/ +/* unsafe */ +/************************************************************/ + +static Scheme_Object *unsafe_car (int argc, Scheme_Object *argv[]) +{ + return SCHEME_CAR(argv[0]); +} + +static Scheme_Object *unsafe_cdr (int argc, Scheme_Object *argv[]) +{ + return SCHEME_CDR(argv[0]); +} + +static Scheme_Object *unsafe_mcar (int argc, Scheme_Object *argv[]) +{ + return SCHEME_CAR(argv[0]); +} + +static Scheme_Object *unsafe_mcdr (int argc, Scheme_Object *argv[]) +{ + return SCHEME_CDR(argv[0]); +} + +static Scheme_Object *unsafe_set_mcar (int argc, Scheme_Object *argv[]) +{ + SCHEME_CAR(argv[0]) = argv[1]; + return scheme_void; +} + +static Scheme_Object *unsafe_set_mcdr (int argc, Scheme_Object *argv[]) +{ + SCHEME_CDR(argv[0]) = argv[1]; + return scheme_void; +} + +static Scheme_Object *unsafe_unbox (int argc, Scheme_Object *argv[]) +{ + return SCHEME_BOX_VAL(argv[0]); +} + +static Scheme_Object *unsafe_set_box (int argc, Scheme_Object *argv[]) +{ + SCHEME_BOX_VAL(argv[0]) = argv[1]; + return scheme_void; +} diff --git a/src/mzscheme/src/module.c b/src/mzscheme/src/module.c index 4b92b72665..f1c1d8e5f4 100644 --- a/src/mzscheme/src/module.c +++ b/src/mzscheme/src/module.c @@ -132,6 +132,7 @@ static Scheme_Object *kernel_modname; static Scheme_Object *kernel_symbol; static Scheme_Object *kernel_modidx; static Scheme_Module *kernel; +static Scheme_Object *unsafe_modname; /* global read-only symbols */ static Scheme_Object *module_symbol; @@ -328,12 +329,14 @@ void scheme_init_module(Scheme_Env *env) REGISTER_SO(kernel_symbol); REGISTER_SO(kernel_modname); REGISTER_SO(kernel_modidx); + REGISTER_SO(unsafe_modname); kernel_symbol = scheme_intern_symbol("#%kernel"); kernel_modname = scheme_intern_resolved_module_path(kernel_symbol); kernel_modidx = scheme_make_modidx(scheme_make_pair(quote_symbol, scheme_make_pair(kernel_symbol, scheme_null)), scheme_false, kernel_modname); + unsafe_modname = scheme_intern_resolved_module_path(scheme_intern_symbol("#%unsafe")); REGISTER_SO(module_symbol); REGISTER_SO(module_begin_symbol); @@ -580,6 +583,11 @@ int scheme_is_kernel_modname(Scheme_Object *modname) return SAME_OBJ(modname, kernel_modname); } +int scheme_is_unsafe_modname(Scheme_Object *modname) +{ + return SAME_OBJ(modname, unsafe_modname); +} + Scheme_Object *scheme_sys_wraps(Scheme_Comp_Env *env) { long phase; @@ -3480,6 +3488,36 @@ Scheme_Object *scheme_check_accessible_in_module(Scheme_Env *env, Scheme_Object return NULL; } +void scheme_check_unsafe_accessible(Scheme_Object *insp, Scheme_Env *from_env) +{ + Scheme_Env *unsafe_env; + + unsafe_env = scheme_get_unsafe_env(); + + if (SCHEME_HASHTRP(insp)) { + Scheme_Hash_Tree *t = (Scheme_Hash_Tree *)insp; + int i; + Scheme_Object *k, *v; + + for (i = t->count; i--; ) { + scheme_hash_tree_index(t, i, &k, &v); + insp = k; + if (scheme_module_protected_wrt(unsafe_env->insp, insp)) { + break; + } + } + + if (i < 0) + return; + } + + if (scheme_module_protected_wrt(unsafe_env->insp, insp)) { + scheme_wrong_syntax("link", + NULL, NULL, + "attempt to access unsafe bindings from an untrusted context"); + } +} + int scheme_module_export_position(Scheme_Object *modname, Scheme_Env *env, Scheme_Object *varname) { Scheme_Module *m; diff --git a/src/mzscheme/src/mzmark.c b/src/mzscheme/src/mzmark.c index 0b2cf62ae3..9df6163088 100644 --- a/src/mzscheme/src/mzmark.c +++ b/src/mzscheme/src/mzmark.c @@ -2218,6 +2218,7 @@ static int resolve_prefix_val_MARK(void *p) { gcMARK(rp->toplevels); gcMARK(rp->stxes); gcMARK(rp->delay_info_rpair); + gcMARK(rp->uses_unsafe); return gcBYTES_TO_WORDS(sizeof(Resolve_Prefix)); @@ -2228,6 +2229,7 @@ static int resolve_prefix_val_FIXUP(void *p) { gcFIXUP(rp->toplevels); gcFIXUP(rp->stxes); gcFIXUP(rp->delay_info_rpair); + gcFIXUP(rp->uses_unsafe); return gcBYTES_TO_WORDS(sizeof(Resolve_Prefix)); @@ -2246,6 +2248,7 @@ static int comp_prefix_val_MARK(void *p) { Comp_Prefix *cp = (Comp_Prefix *)p; gcMARK(cp->toplevels); gcMARK(cp->stxes); + gcMARK(cp->uses_unsafe); return gcBYTES_TO_WORDS(sizeof(Comp_Prefix)); @@ -2255,6 +2258,7 @@ static int comp_prefix_val_FIXUP(void *p) { Comp_Prefix *cp = (Comp_Prefix *)p; gcFIXUP(cp->toplevels); gcFIXUP(cp->stxes); + gcFIXUP(cp->uses_unsafe); return gcBYTES_TO_WORDS(sizeof(Comp_Prefix)); diff --git a/src/mzscheme/src/mzmarksrc.c b/src/mzscheme/src/mzmarksrc.c index d14952ecc8..c0da46ce60 100644 --- a/src/mzscheme/src/mzmarksrc.c +++ b/src/mzscheme/src/mzmarksrc.c @@ -884,6 +884,7 @@ resolve_prefix_val { gcMARK(rp->toplevels); gcMARK(rp->stxes); gcMARK(rp->delay_info_rpair); + gcMARK(rp->uses_unsafe); size: gcBYTES_TO_WORDS(sizeof(Resolve_Prefix)); @@ -894,6 +895,7 @@ comp_prefix_val { Comp_Prefix *cp = (Comp_Prefix *)p; gcMARK(cp->toplevels); gcMARK(cp->stxes); + gcMARK(cp->uses_unsafe); size: gcBYTES_TO_WORDS(sizeof(Comp_Prefix)); diff --git a/src/mzscheme/src/numarith.c b/src/mzscheme/src/numarith.c index 151bbe858c..d5e91969ae 100644 --- a/src/mzscheme/src/numarith.c +++ b/src/mzscheme/src/numarith.c @@ -35,6 +35,17 @@ static Scheme_Object *quotient (int argc, Scheme_Object *argv[]); static Scheme_Object *rem_prim (int argc, Scheme_Object *argv[]); static Scheme_Object *quotient_remainder (int argc, Scheme_Object *argv[]); +static Scheme_Object *fx_plus (int argc, Scheme_Object *argv[]); +static Scheme_Object *fx_minus (int argc, Scheme_Object *argv[]); +static Scheme_Object *fx_mult (int argc, Scheme_Object *argv[]); +static Scheme_Object *fx_div (int argc, Scheme_Object *argv[]); +static Scheme_Object *fx_rem (int argc, Scheme_Object *argv[]); + +static Scheme_Object *fl_plus (int argc, Scheme_Object *argv[]); +static Scheme_Object *fl_minus (int argc, Scheme_Object *argv[]); +static Scheme_Object *fl_mult (int argc, Scheme_Object *argv[]); +static Scheme_Object *fl_div (int argc, Scheme_Object *argv[]); + #define zeroi scheme_exact_zero void scheme_init_numarith(Scheme_Env *env) @@ -69,17 +80,15 @@ void scheme_init_numarith(Scheme_Env *env) p = scheme_make_folding_prim(scheme_abs, "abs", 1, 1, 1); SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_UNARY_INLINED; scheme_add_global_constant("abs", p, env); + + p = scheme_make_folding_prim(quotient, "quotient", 2, 2, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("quotient", p, env); + + p = scheme_make_folding_prim(rem_prim, "remainder", 2, 2, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("remainder", p, env); - scheme_add_global_constant("quotient", - scheme_make_folding_prim(quotient, - "quotient", - 2, 2, 1), - env); - scheme_add_global_constant("remainder", - scheme_make_folding_prim(rem_prim, - "remainder", - 2, 2, 1), - env); scheme_add_global_constant("quotient/remainder", scheme_make_prim_w_arity2(quotient_remainder, "quotient/remainder", @@ -93,6 +102,53 @@ void scheme_init_numarith(Scheme_Env *env) env); } +void scheme_init_unsafe_numarith(Scheme_Env *env) +{ + Scheme_Object *p; + + p = scheme_make_folding_prim(fx_plus, "unsafe-fx+", 2, 2, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fx+", p, env); + + p = scheme_make_folding_prim(fx_minus, "unsafe-fx-", 2, 2, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= (SCHEME_PRIM_IS_BINARY_INLINED + | SCHEME_PRIM_IS_UNARY_INLINED); + scheme_add_global_constant("unsafe-fx-", p, env); + + p = scheme_make_folding_prim(fx_mult, "unsafe-fx*", 2, 2, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fx*", p, env); + + p = scheme_make_folding_prim(fx_div, "unsafe-fxquotient", 2, 2, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fxquotient", p, env); + + p = scheme_make_folding_prim(fx_rem, "unsafe-fxremainder", 2, 2, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fxremainder", p, env); + + + p = scheme_make_folding_prim(fl_plus, "unsafe-fl+", 2, 2, 1); + if (scheme_can_inline_fp_op()) + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fl+", p, env); + + p = scheme_make_folding_prim(fl_minus, "unsafe-fl-", 2, 2, 1); + if (scheme_can_inline_fp_op()) + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fl-", p, env); + + p = scheme_make_folding_prim(fl_mult, "unsafe-fl*", 2, 2, 1); + if (scheme_can_inline_fp_op()) + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fl*", p, env); + + p = scheme_make_folding_prim(fl_div, "unsafe-fl/", 2, 2, 1); + if (scheme_can_inline_fp_op()) + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fl/", p, env); +} + Scheme_Object * scheme_add1 (int argc, Scheme_Object *argv[]) { @@ -707,3 +763,36 @@ quotient_remainder(int argc, Scheme_Object *argv[]) a[1] = rem; return scheme_values(2, a); } + +/************************************************************************/ +/* Unsafe */ +/************************************************************************/ + +#define UNSAFE_FX(name, op, fold) \ + static Scheme_Object *name(int argc, Scheme_Object *argv[]) \ + { \ + long v; \ + if (scheme_current_thread->constant_folding) return fold(argc, argv); \ + v = SCHEME_INT_VAL(argv[0]) op SCHEME_INT_VAL(argv[1]); \ + return scheme_make_integer(v); \ + } + +UNSAFE_FX(fx_plus, +, plus) +UNSAFE_FX(fx_minus, -, minus) +UNSAFE_FX(fx_mult, *, mult) +UNSAFE_FX(fx_div, /, quotient) +UNSAFE_FX(fx_rem, %, rem_prim) + +#define UNSAFE_FL(name, op, fold) \ + static Scheme_Object *name(int argc, Scheme_Object *argv[]) \ + { \ + double v; \ + if (scheme_current_thread->constant_folding) return fold(argc, argv); \ + v = SCHEME_DBL_VAL(argv[0]) op SCHEME_DBL_VAL(argv[1]); \ + return scheme_make_double(v); \ + } + +UNSAFE_FL(fl_plus, +, plus) +UNSAFE_FL(fl_minus, -, minus) +UNSAFE_FL(fl_mult, *, mult) +UNSAFE_FL(fl_div, /, div_prim) diff --git a/src/mzscheme/src/number.c b/src/mzscheme/src/number.c index cd955c933b..5584477529 100644 --- a/src/mzscheme/src/number.c +++ b/src/mzscheme/src/number.c @@ -98,6 +98,13 @@ static Scheme_Object *angle (int argc, Scheme_Object *argv[]); static Scheme_Object *int_sqrt (int argc, Scheme_Object *argv[]); static Scheme_Object *int_sqrt_rem (int argc, Scheme_Object *argv[]); +static Scheme_Object *fx_and (int argc, Scheme_Object *argv[]); +static Scheme_Object *fx_or (int argc, Scheme_Object *argv[]); +static Scheme_Object *fx_xor (int argc, Scheme_Object *argv[]); +static Scheme_Object *fx_not (int argc, Scheme_Object *argv[]); +static Scheme_Object *fx_lshift (int argc, Scheme_Object *argv[]); +static Scheme_Object *fx_rshift (int argc, Scheme_Object *argv[]); + static double not_a_number_val; Scheme_Object *scheme_inf_object, *scheme_minus_inf_object, *scheme_nan_object; @@ -482,6 +489,36 @@ scheme_init_number (Scheme_Env *env) env); } +void scheme_init_unsafe_number(Scheme_Env *env) +{ + Scheme_Object *p; + + p = scheme_make_folding_prim(fx_and, "unsafe-fxand", 0, -1, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fxand", p, env); + + p = scheme_make_folding_prim(fx_or, "unsafe-fxior", 0, -1, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fxior", p, env); + + p = scheme_make_folding_prim(fx_xor, "unsafe-fxxor", 0, -1, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fxxor", p, env); + + p = scheme_make_folding_prim(fx_not, "unsafe-fxnot", 1, 1, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_UNARY_INLINED; + scheme_add_global_constant("unsafe-fxnot", p, env); + + p = scheme_make_folding_prim(fx_lshift, "unsafe-fxlshift", 2, 2, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fxlshift", p, env); + + p = scheme_make_folding_prim(fx_rshift, "unsafe-fxrshift", 2, 2, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fxrshift", p, env); +} + + Scheme_Object * scheme_make_integer_value(long i) @@ -2723,3 +2760,41 @@ long scheme_integer_length(Scheme_Object *n) r = integer_length(1, a); return SCHEME_INT_VAL(r); } + +/************************************************************************/ +/* Unsafe */ +/************************************************************************/ + +#define UNSAFE_FX(name, op, fold) \ + static Scheme_Object *name(int argc, Scheme_Object *argv[]) \ + { \ + long v; \ + if (scheme_current_thread->constant_folding) return fold(argc, argv); \ + v = SCHEME_INT_VAL(argv[0]) op SCHEME_INT_VAL(argv[1]); \ + return scheme_make_integer(v); \ + } + +UNSAFE_FX(fx_and, &, scheme_bitwise_and) +UNSAFE_FX(fx_or, |, bitwise_or) +UNSAFE_FX(fx_xor, ^, bitwise_xor) +UNSAFE_FX(fx_lshift, <<, scheme_bitwise_shift) + +static Scheme_Object *neg_bitwise_shift(int argc, Scheme_Object *argv[]) +{ + Scheme_Object *a[2]; + a[0] = argv[0]; + a[1] = scheme_bin_minus(scheme_make_integer(0), argv[1]); + return scheme_bitwise_shift(argc, a); +} + +UNSAFE_FX(fx_rshift, >>, neg_bitwise_shift) + +static Scheme_Object *fx_not (int argc, Scheme_Object *argv[]) +{ + long v; + if (scheme_current_thread->constant_folding) return bitwise_not(argc, argv); + v = SCHEME_INT_VAL(argv[0]); + v = ~v; + return scheme_make_integer(v); +} + diff --git a/src/mzscheme/src/numcomp.c b/src/mzscheme/src/numcomp.c index 324edab988..48744b9129 100644 --- a/src/mzscheme/src/numcomp.c +++ b/src/mzscheme/src/numcomp.c @@ -38,6 +38,18 @@ static Scheme_Object *negative_p (int argc, Scheme_Object *argv[]); static Scheme_Object *sch_max (int argc, Scheme_Object *argv[]); static Scheme_Object *sch_min (int argc, Scheme_Object *argv[]); +static Scheme_Object *fx_eq (int argc, Scheme_Object *argv[]); +static Scheme_Object *fx_lt (int argc, Scheme_Object *argv[]); +static Scheme_Object *fx_gt (int argc, Scheme_Object *argv[]); +static Scheme_Object *fx_lt_eq (int argc, Scheme_Object *argv[]); +static Scheme_Object *fx_gt_eq (int argc, Scheme_Object *argv[]); + +static Scheme_Object *fl_eq (int argc, Scheme_Object *argv[]); +static Scheme_Object *fl_lt (int argc, Scheme_Object *argv[]); +static Scheme_Object *fl_gt (int argc, Scheme_Object *argv[]); +static Scheme_Object *fl_lt_eq (int argc, Scheme_Object *argv[]); +static Scheme_Object *fl_gt_eq (int argc, Scheme_Object *argv[]); + #define zeroi scheme_exact_zero void scheme_init_numcomp(Scheme_Env *env) @@ -85,6 +97,56 @@ void scheme_init_numcomp(Scheme_Env *env) scheme_add_global_constant("min", p, env); } +void scheme_init_unsafe_numcomp(Scheme_Env *env) +{ + Scheme_Object *p; + + p = scheme_make_folding_prim(fx_eq, "unsafe-fx=", 2, 2, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fx=", p, env); + + p = scheme_make_folding_prim(fx_lt, "unsafe-fx<", 2, 2, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fx<", p, env); + + p = scheme_make_folding_prim(fx_gt, "unsafe-fx>", 2, 2, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fx>", p, env); + + p = scheme_make_folding_prim(fx_lt_eq, "unsafe-fx<=", 2, 2, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fx<=", p, env); + + p = scheme_make_folding_prim(fx_gt_eq, "unsafe-fx>=", 2, 2, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fx>=", p, env); + + p = scheme_make_folding_prim(fl_eq, "unsafe-fl=", 2, 2, 1); + if (scheme_can_inline_fp_comp()) + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fl=", p, env); + + p = scheme_make_folding_prim(fl_lt, "unsafe-fl<", 2, 2, 1); + if (scheme_can_inline_fp_comp()) + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fl<", p, env); + + p = scheme_make_folding_prim(fl_gt, "unsafe-fl>", 2, 2, 1); + if (scheme_can_inline_fp_comp()) + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fl>", p, env); + + p = scheme_make_folding_prim(fl_lt_eq, "unsafe-fl<=", 2, 2, 1); + if (scheme_can_inline_fp_comp()) + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fl<=", p, env); + + p = scheme_make_folding_prim(fl_gt_eq, "unsafe-fl>=", 2, 2, 1); + if (scheme_can_inline_fp_comp()) + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-fl>=", p, env); +} + /* Prototype needed for 3m conversion: */ static MZ_INLINE Scheme_Object *force_rat(Scheme_Object *n, Small_Rational *sr); @@ -294,3 +356,39 @@ static GEN_BIN_OP(bin_min, "min", MIN, F_MIN, FS_MIN, scheme_bignum_min, scheme_ GEN_TWOARY_OP(static, sch_max, "max", bin_max, SCHEME_REALP, REAL_NUMBER_STR) GEN_TWOARY_OP(static, sch_min, "min", bin_min, SCHEME_REALP, REAL_NUMBER_STR) + +/************************************************************************/ +/* Unsafe */ +/************************************************************************/ + +#define UNSAFE_FX(name, op, fold) \ + static Scheme_Object *name(int argc, Scheme_Object *argv[]) \ + { \ + if (scheme_current_thread->constant_folding) return (fold(argv[0], argv[1]) ? scheme_true : scheme_false); \ + if (SCHEME_INT_VAL(argv[0]) op SCHEME_INT_VAL(argv[1])) \ + return scheme_true; \ + else \ + return scheme_false; \ + } + +UNSAFE_FX(fx_eq, ==, scheme_bin_eq) +UNSAFE_FX(fx_lt, <, scheme_bin_lt) +UNSAFE_FX(fx_gt, >, scheme_bin_gt) +UNSAFE_FX(fx_lt_eq, <=, scheme_bin_lt_eq) +UNSAFE_FX(fx_gt_eq, >=, scheme_bin_gt_eq) + +#define UNSAFE_FL(name, op, fold) \ + static Scheme_Object *name(int argc, Scheme_Object *argv[]) \ + { \ + if (scheme_current_thread->constant_folding) return (fold(argv[0], argv[1]) ? scheme_true : scheme_false); \ + if (SCHEME_DBL_VAL(argv[0]) op SCHEME_DBL_VAL(argv[1])) \ + return scheme_true; \ + else \ + return scheme_false; \ + } + +UNSAFE_FL(fl_eq, ==, scheme_bin_eq) +UNSAFE_FL(fl_lt, <, scheme_bin_lt) +UNSAFE_FL(fl_gt, >, scheme_bin_gt) +UNSAFE_FL(fl_lt_eq, <=, scheme_bin_lt_eq) +UNSAFE_FL(fl_gt_eq, >=, scheme_bin_gt_eq) diff --git a/src/mzscheme/src/print.c b/src/mzscheme/src/print.c index 7eeb514b5b..778bb691d8 100644 --- a/src/mzscheme/src/print.c +++ b/src/mzscheme/src/print.c @@ -808,6 +808,7 @@ print_to_string(Scheme_Object *obj, params.case_sens = 1; params.honu_mode = 0; params.inspector = scheme_false; + params.print_syntax = -1; } else { config = scheme_current_config(); diff --git a/src/mzscheme/src/read.c b/src/mzscheme/src/read.c index 15f8eccfe6..f2a6dcb7a4 100644 --- a/src/mzscheme/src/read.c +++ b/src/mzscheme/src/read.c @@ -4681,7 +4681,7 @@ static Scheme_Object *read_compact(CPort *port, int use_stack) break; case CPT_REFERENCE: l = read_compact_number(port); - RANGE_CHECK(l, < EXPECTED_PRIM_COUNT); + RANGE_CHECK(l, < (EXPECTED_PRIM_COUNT + EXPECTED_UNSAFE_COUNT)); return variable_references[l]; break; case CPT_LOCAL: @@ -5081,6 +5081,12 @@ static Scheme_Object *read_marshalled(int type, CPort *port) if (!l) scheme_ill_formed_code(port); + if (type == scheme_resolve_prefix_type) { + /* If unsafe_insp is set, need to use the one in port: */ + if (((Resolve_Prefix *)l)->uses_unsafe) + ((Resolve_Prefix *)l)->uses_unsafe = port->insp; + } + return l; } diff --git a/src/mzscheme/src/schminc.h b/src/mzscheme/src/schminc.h index b9355e70d7..54bfee4a49 100644 --- a/src/mzscheme/src/schminc.h +++ b/src/mzscheme/src/schminc.h @@ -14,6 +14,7 @@ #define USE_COMPILED_STARTUP 1 #define EXPECTED_PRIM_COUNT 959 +#define EXPECTED_UNSAFE_COUNT 38 #ifdef MZSCHEME_SOMETHING_OMITTED # undef USE_COMPILED_STARTUP diff --git a/src/mzscheme/src/schpriv.h b/src/mzscheme/src/schpriv.h index f6dcd063ff..b0f37a2134 100644 --- a/src/mzscheme/src/schpriv.h +++ b/src/mzscheme/src/schpriv.h @@ -171,6 +171,7 @@ void scheme_init_symbol_table(void); void scheme_init_symbol_type(Scheme_Env *env); void scheme_init_type(); void scheme_init_list(Scheme_Env *env); +void scheme_init_unsafe_list(Scheme_Env *env); void scheme_init_stx(Scheme_Env *env); void scheme_init_module(Scheme_Env *env); void scheme_init_module_path_table(void); @@ -180,10 +181,14 @@ void scheme_init_network(Scheme_Env *env); void scheme_init_file(Scheme_Env *env); void scheme_init_proc(Scheme_Env *env); void scheme_init_vector(Scheme_Env *env); +void scheme_init_unsafe_vector(Scheme_Env *env); void scheme_init_string(Scheme_Env *env); void scheme_init_number(Scheme_Env *env); void scheme_init_numarith(Scheme_Env *env); +void scheme_init_unsafe_numarith(Scheme_Env *env); +void scheme_init_unsafe_number(Scheme_Env *env); void scheme_init_numcomp(Scheme_Env *env); +void scheme_init_unsafe_numcomp(Scheme_Env *env); void scheme_init_numstr(Scheme_Env *env); void scheme_init_eval(Scheme_Env *env); void scheme_init_promise(Scheme_Env *env); @@ -1828,6 +1833,7 @@ typedef struct Comp_Prefix int num_toplevels, num_stxes; Scheme_Hash_Table *toplevels; /* buckets for toplevel/module variables */ Scheme_Hash_Table *stxes; /* syntax objects */ + Scheme_Object *uses_unsafe; /* NULL, inspector, or hashtree of inspectors */ } Comp_Prefix; typedef struct Scheme_Comp_Env @@ -1900,6 +1906,7 @@ typedef struct Resolve_Prefix Scheme_Object **toplevels; Scheme_Object **stxes; /* simplified */ Scheme_Object *delay_info_rpair; /* (rcons refcount Scheme_Load_Delay*) */ + Scheme_Object *uses_unsafe; /* non-NULL => inspector or hashtree of inspectors for accessing #%unsafe bindings */ } Resolve_Prefix; typedef struct Resolve_Info @@ -2086,6 +2093,8 @@ Scheme_Object *scheme_lookup_binding(Scheme_Object *symbol, Scheme_Comp_Env *env Scheme_Env **_menv, int *_protected, Scheme_Object **_lexical_binding_id); +Scheme_Object *scheme_extract_unsafe(Scheme_Object *o); + Scheme_Object *scheme_add_env_renames(Scheme_Object *stx, Scheme_Comp_Env *env, Scheme_Comp_Env *upto); @@ -2137,6 +2146,9 @@ Scheme_Object *scheme_register_toplevel_in_prefix(Scheme_Object *var, Scheme_Com Scheme_Compile_Info *rec, int drec); Scheme_Object *scheme_register_stx_in_prefix(Scheme_Object *var, Scheme_Comp_Env *env, Scheme_Compile_Info *rec, int drec); +void scheme_register_unsafe_in_prefix(Scheme_Comp_Env *env, + Scheme_Compile_Info *rec, int drec, + Scheme_Env *menv); void scheme_bind_syntaxes(const char *where, Scheme_Object *names, Scheme_Object *a, Scheme_Env *exp_env, Scheme_Object *insp, @@ -2753,6 +2765,7 @@ Scheme_Object *scheme_check_accessible_in_module(Scheme_Env *env, Scheme_Object int position, int want_pos, int *_protected, int *_unexported, Scheme_Env *from_env, int *_would_complain); +void scheme_check_unsafe_accessible(Scheme_Object *insp, Scheme_Env *from_env); Scheme_Object *scheme_module_syntax(Scheme_Object *modname, Scheme_Env *env, Scheme_Object *name); Scheme_Object *scheme_modidx_shift(Scheme_Object *modidx, @@ -2769,7 +2782,7 @@ Scheme_Object *scheme_hash_module_variable(Scheme_Env *env, Scheme_Object *modid Scheme_Env *scheme_get_kernel_env(); int scheme_is_kernel_env(); - +Scheme_Env *scheme_get_unsafe_env(); void scheme_install_initial_module_set(Scheme_Env *env); Scheme_Bucket_Table *scheme_clone_toplevel(Scheme_Bucket_Table *ht, Scheme_Env *home); @@ -2781,6 +2794,7 @@ void scheme_clean_dead_env(Scheme_Env *env); Scheme_Module *scheme_extract_compiled_module(Scheme_Object *o); int scheme_is_kernel_modname(Scheme_Object *modname); +int scheme_is_unsafe_modname(Scheme_Object *modname); void scheme_clear_modidx_cache(void); void scheme_clear_shift_cache(void); @@ -3185,6 +3199,9 @@ unsigned short * scheme_ucs4_to_utf16(const mzchar *text, int start, int end, Scheme_Object *scheme_current_library_collection_paths(int argc, Scheme_Object *argv[]); +int scheme_can_inline_fp_op(); +int scheme_can_inline_fp_comp(); + /*========================================================================*/ /* places */ /*========================================================================*/ diff --git a/src/mzscheme/src/schvers.h b/src/mzscheme/src/schvers.h index 8491f6ec4c..25e71eaded 100644 --- a/src/mzscheme/src/schvers.h +++ b/src/mzscheme/src/schvers.h @@ -13,12 +13,12 @@ consistently.) */ -#define MZSCHEME_VERSION "4.2.1.7" +#define MZSCHEME_VERSION "4.2.1.8" #define MZSCHEME_VERSION_X 4 #define MZSCHEME_VERSION_Y 2 #define MZSCHEME_VERSION_Z 1 -#define MZSCHEME_VERSION_W 7 +#define MZSCHEME_VERSION_W 8 #define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y) #define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W) diff --git a/src/mzscheme/src/startup.inc b/src/mzscheme/src/startup.inc index b1dad98cba..7c8c60286f 100644 --- a/src/mzscheme/src/startup.inc +++ b/src/mzscheme/src/startup.inc @@ -391,6 +391,7 @@ "(module #%builtin '#%kernel" "(#%require '#%expobs" "(only '#%foreign) " +"(only '#%unsafe) " " '#%paramz" " '#%network" " '#%utils" diff --git a/src/mzscheme/src/startup.ss b/src/mzscheme/src/startup.ss index 88ac3b59a5..15e1185570 100644 --- a/src/mzscheme/src/startup.ss +++ b/src/mzscheme/src/startup.ss @@ -465,6 +465,7 @@ (module #%builtin '#%kernel (#%require '#%expobs (only '#%foreign) ; so it's attached, but doesn't depend on any exports + (only '#%unsafe) ; ditto '#%paramz '#%network '#%utils diff --git a/src/mzscheme/src/vector.c b/src/mzscheme/src/vector.c index faf8982094..5b2d436d4a 100644 --- a/src/mzscheme/src/vector.c +++ b/src/mzscheme/src/vector.c @@ -42,6 +42,12 @@ static Scheme_Object *vector_copy_bang(int argc, Scheme_Object *argv[]); static Scheme_Object *vector_to_immutable (int argc, Scheme_Object *argv[]); static Scheme_Object *vector_to_values (int argc, Scheme_Object *argv[]); +static Scheme_Object *unsafe_vector_len (int argc, Scheme_Object *argv[]); +static Scheme_Object *unsafe_vector_ref (int argc, Scheme_Object *argv[]); +static Scheme_Object *unsafe_vector_set (int argc, Scheme_Object *argv[]); +static Scheme_Object *unsafe_struct_ref (int argc, Scheme_Object *argv[]); +static Scheme_Object *unsafe_struct_set (int argc, Scheme_Object *argv[]); + void scheme_init_vector (Scheme_Env *env) { @@ -122,6 +128,45 @@ scheme_init_vector (Scheme_Env *env) env); } +void +scheme_init_unsafe_vector (Scheme_Env *env) +{ + Scheme_Object *p; + + p = scheme_make_immed_prim(unsafe_vector_len, + "unsafe-vector-length", + 1, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_UNARY_INLINED; + scheme_add_global_constant("unsafe-vector-length", p, env); + + p = scheme_make_immed_prim(unsafe_vector_ref, + "unsafe-vector-ref", + 2, 2); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-vector-ref", p, env); + + p = scheme_make_immed_prim(unsafe_vector_set, + "unsafe-vector-set!", + 3, 3); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_NARY_INLINED; + scheme_add_global_constant("unsafe-vector-set!", p, env); + p = scheme_make_immed_prim(unsafe_vector_ref, + "unsafe-vector-ref", + 2, 2); + + p = scheme_make_immed_prim(unsafe_struct_ref, + "unsafe-struct-ref", + 2, 2); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED; + scheme_add_global_constant("unsafe-struct-ref", p, env); + + p = scheme_make_immed_prim(unsafe_struct_set, + "unsafe-struct-set!", + 3, 3); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_NARY_INLINED; + scheme_add_global_constant("unsafe-struct-set!", p, env); +} + Scheme_Object * scheme_make_vector (long size, Scheme_Object *fill) { @@ -475,3 +520,35 @@ static Scheme_Object *vector_to_values (int argc, Scheme_Object *argv[]) return SCHEME_MULTIPLE_VALUES; } + +/************************************************************/ +/* unsafe */ +/************************************************************/ + +static Scheme_Object *unsafe_vector_len (int argc, Scheme_Object *argv[]) +{ + long n = SCHEME_VEC_SIZE(argv[0]); + return scheme_make_integer(n); +} + +static Scheme_Object *unsafe_vector_ref (int argc, Scheme_Object *argv[]) +{ + return SCHEME_VEC_ELS(argv[0])[SCHEME_INT_VAL(argv[1])]; +} + +static Scheme_Object *unsafe_vector_set (int argc, Scheme_Object *argv[]) +{ + SCHEME_VEC_ELS(argv[0])[SCHEME_INT_VAL(argv[1])] = argv[2]; + return scheme_void; +} + +static Scheme_Object *unsafe_struct_ref (int argc, Scheme_Object *argv[]) +{ + return ((Scheme_Structure *)argv[0])->slots[SCHEME_INT_VAL(argv[1])]; +} + +static Scheme_Object *unsafe_struct_set (int argc, Scheme_Object *argv[]) +{ + ((Scheme_Structure *)argv[0])->slots[SCHEME_INT_VAL(argv[1])] = argv[2]; + return scheme_void; +}