add unsafe-set-immutable-{car,cdr}!
Reluctantly, with intentionally oxymoronic names, and with the key caveat: using these requires making correct assumptions about Racket's implementation. With BC, a related assumption was that `unsafe-set-mcar!` and `unsafe-set-mcdr!` mutate pairs, but that's not the case with CS. So, adding these functions supports a kind of portability between BC and CS.
This commit is contained in:
parent
becf34a79b
commit
ea96e2d304
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
;; In the Racket source repo, this version should change only when
|
;; In the Racket source repo, this version should change only when
|
||||||
;; "racket_version.h" changes:
|
;; "racket_version.h" changes:
|
||||||
(define version "7.9.0.17")
|
(define version "7.9.0.18")
|
||||||
|
|
||||||
(define deps `("racket-lib"
|
(define deps `("racket-lib"
|
||||||
["racket" #:version ,version]))
|
["racket" #:version ,version]))
|
||||||
|
|
|
@ -235,7 +235,7 @@ Unchecked versions of @racket[char=?], @racket[char<?], @racket[char>?],
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@section{Unsafe Data Extraction}
|
@section[#:tag "Unsafe Data Extraction"]{Unsafe Compound-Data Operations}
|
||||||
|
|
||||||
@deftogether[(
|
@deftogether[(
|
||||||
@defproc[(unsafe-car [p pair?]) any/c]
|
@defproc[(unsafe-car [p pair?]) any/c]
|
||||||
|
@ -267,6 +267,44 @@ at least @racket[(add1 pos)] (for @racket[unsafe-list-ref]) or
|
||||||
@racket[pos] (for @racket[unsafe-list-tail]) pairs.}
|
@racket[pos] (for @racket[unsafe-list-tail]) pairs.}
|
||||||
|
|
||||||
|
|
||||||
|
@deftogether[(
|
||||||
|
@defproc[(unsafe-set-immutable-car! [p pair?] [v any/c]) void?]
|
||||||
|
@defproc[(unsafe-set-immutable-cdr! [p pair?] [v any/c]) void?]
|
||||||
|
)]{
|
||||||
|
|
||||||
|
As their oxymoronic names should suggest, there is @emph{no generally
|
||||||
|
correct way} to use these functions. They may be useful nevertheless,
|
||||||
|
as a last resort, in settings where pairs are used in a constrained
|
||||||
|
way and when making correct assumptions about Racket's implementation
|
||||||
|
(including limits on the compiler's optimizations).
|
||||||
|
|
||||||
|
Some pitfalls of using @racket[unsafe-set-immutable-car!] and
|
||||||
|
@racket[unsafe-set-immutable-cdr!]:
|
||||||
|
|
||||||
|
@itemlist[
|
||||||
|
|
||||||
|
@item{Functions that consume a pair may take advantage of
|
||||||
|
immutability, such as computing a list's length once and
|
||||||
|
expecting the list to retain that length, or checking a list
|
||||||
|
against a contract and expecting the contract to hold
|
||||||
|
thereafter.}
|
||||||
|
|
||||||
|
@item{The result of @racket[list?] for a pair may be cached
|
||||||
|
internally, so that changing the @racket[cdr] of a pair from a
|
||||||
|
list to a non-list or vice versa may cause @racket[list?] to
|
||||||
|
produce the wrong value---for the mutated pair or for another
|
||||||
|
pair that reaches the mutated pair.}
|
||||||
|
|
||||||
|
@item{The compiler may reorder or even optimize away a call to
|
||||||
|
@racket[car] or @racket[cdr] on the grounds that pairs are
|
||||||
|
immutable, in which case a @racket[unsafe-set-immutable-car!]
|
||||||
|
or @racket[unsafe-set-immutable-cdr!] may not have an effect on
|
||||||
|
the use of @racket[car] or @racket[cdr].}
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
@history[#:added "7.9.0.18"]}
|
||||||
|
|
||||||
@deftogether[(
|
@deftogether[(
|
||||||
@defproc[(unsafe-unbox [b box?]) fixnum?]
|
@defproc[(unsafe-unbox [b box?]) fixnum?]
|
||||||
@defproc[(unsafe-set-box! [b box?] [k fixnum?]) void?]
|
@defproc[(unsafe-set-box! [b box?] [k fixnum?]) void?]
|
||||||
|
|
|
@ -526,6 +526,15 @@
|
||||||
|
|
||||||
(test-un 5 'unsafe-car (cons 5 9))
|
(test-un 5 'unsafe-car (cons 5 9))
|
||||||
(test-un 9 'unsafe-cdr (cons 5 9))
|
(test-un 9 'unsafe-cdr (cons 5 9))
|
||||||
|
(let ([v (cons 3 7)])
|
||||||
|
(test-bin 8 'unsafe-set-immutable-car! v 8
|
||||||
|
#:pre (lambda () (unsafe-set-immutable-car! v 0))
|
||||||
|
#:post (lambda (x) (car v))
|
||||||
|
#:literal-ok? #f)
|
||||||
|
(test-bin 9 'unsafe-set-immutable-cdr! v 9
|
||||||
|
#:pre (lambda () (unsafe-set-immutable-cdr! v 0))
|
||||||
|
#:post (lambda (x) (cdr v))
|
||||||
|
#:literal-ok? #f))
|
||||||
(test-un 15 'unsafe-mcar (mcons 15 19))
|
(test-un 15 'unsafe-mcar (mcons 15 19))
|
||||||
(test-un 19 'unsafe-mcdr (mcons 15 19))
|
(test-un 19 'unsafe-mcdr (mcons 15 19))
|
||||||
(let ([v (mcons 3 7)])
|
(let ([v (mcons 3 7)])
|
||||||
|
|
|
@ -4242,10 +4242,13 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
} else if (IS_NAMED_PRIM(rator, "unsafe-set-mcar!")
|
} else if (IS_NAMED_PRIM(rator, "unsafe-set-mcar!")
|
||||||
|| IS_NAMED_PRIM(rator, "unsafe-set-mcdr!")) {
|
|| IS_NAMED_PRIM(rator, "unsafe-set-mcdr!")
|
||||||
|
|| IS_NAMED_PRIM(rator, "unsafe-set-immutable-car!")
|
||||||
|
|| IS_NAMED_PRIM(rator, "unsafe-set-immutable-cdr!")) {
|
||||||
int set_mcar;
|
int set_mcar;
|
||||||
|
|
||||||
set_mcar = IS_NAMED_PRIM(rator, "unsafe-set-mcar!");
|
set_mcar = (IS_NAMED_PRIM(rator, "unsafe-set-mcar!")
|
||||||
|
|| IS_NAMED_PRIM(rator, "unsafe-set-immutable-car!"));
|
||||||
|
|
||||||
LOG_IT(("inlined unsafe-set-mcar!\n"));
|
LOG_IT(("inlined unsafe-set-mcar!\n"));
|
||||||
|
|
||||||
|
|
|
@ -875,6 +875,14 @@ scheme_init_unsafe_list (Scheme_Startup_Env *env)
|
||||||
scheme_addto_prim_instance ("unsafe-cdr", p, env);
|
scheme_addto_prim_instance ("unsafe-cdr", p, env);
|
||||||
scheme_unsafe_cdr_proc = p;
|
scheme_unsafe_cdr_proc = p;
|
||||||
|
|
||||||
|
p = scheme_make_immed_prim(unsafe_set_mcar, "unsafe-set-immutable-car!", 2, 2);
|
||||||
|
SCHEME_PRIM_PROC_FLAGS(p) |= scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_BINARY_INLINED);
|
||||||
|
scheme_addto_prim_instance ("unsafe-set-immutable-car!", p, env);
|
||||||
|
|
||||||
|
p = scheme_make_immed_prim(unsafe_set_mcdr, "unsafe-set-immutable-cdr!", 2, 2);
|
||||||
|
SCHEME_PRIM_PROC_FLAGS(p) |= scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_BINARY_INLINED);
|
||||||
|
scheme_addto_prim_instance ("unsafe-set-immutable-cdr!", p, env);
|
||||||
|
|
||||||
p = scheme_make_folding_prim(unsafe_list_ref, "unsafe-list-ref", 2, 2, 1);
|
p = scheme_make_folding_prim(unsafe_list_ref, "unsafe-list-ref", 2, 2, 1);
|
||||||
SCHEME_PRIM_PROC_FLAGS(p) |= scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_UNARY_INLINED
|
SCHEME_PRIM_PROC_FLAGS(p) |= scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_UNARY_INLINED
|
||||||
| SCHEME_PRIM_IS_UNSAFE_FUNCTIONAL
|
| SCHEME_PRIM_IS_UNSAFE_FUNCTIONAL
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
#define USE_COMPILED_STARTUP 1
|
#define USE_COMPILED_STARTUP 1
|
||||||
|
|
||||||
#define EXPECTED_PRIM_COUNT 1482
|
#define EXPECTED_PRIM_COUNT 1484
|
||||||
|
|
||||||
#ifdef MZSCHEME_SOMETHING_OMITTED
|
#ifdef MZSCHEME_SOMETHING_OMITTED
|
||||||
# undef USE_COMPILED_STARTUP
|
# undef USE_COMPILED_STARTUP
|
||||||
|
|
|
@ -122,8 +122,8 @@
|
||||||
[unsafe-make-os-semaphore (known-procedure 1)]
|
[unsafe-make-os-semaphore (known-procedure 1)]
|
||||||
[unsafe-make-security-guard-at-root (known-procedure 15)]
|
[unsafe-make-security-guard-at-root (known-procedure 15)]
|
||||||
[unsafe-make-srcloc (known-procedure/pure 32)]
|
[unsafe-make-srcloc (known-procedure/pure 32)]
|
||||||
[unsafe-mcar (known-procedure 2)]
|
[unsafe-mcar (known-procedure/succeeds 2)]
|
||||||
[unsafe-mcdr (known-procedure 2)]
|
[unsafe-mcdr (known-procedure/succeeds 2)]
|
||||||
[unsafe-mutable-hash-iterate-first (known-procedure 2)]
|
[unsafe-mutable-hash-iterate-first (known-procedure 2)]
|
||||||
[unsafe-mutable-hash-iterate-key (known-procedure 12)]
|
[unsafe-mutable-hash-iterate-key (known-procedure 12)]
|
||||||
[unsafe-mutable-hash-iterate-key+value (known-procedure 12)]
|
[unsafe-mutable-hash-iterate-key+value (known-procedure 12)]
|
||||||
|
@ -145,12 +145,14 @@
|
||||||
[unsafe-register-process-global (known-procedure 4)]
|
[unsafe-register-process-global (known-procedure 4)]
|
||||||
[unsafe-remove-collect-callbacks (known-procedure 2)]
|
[unsafe-remove-collect-callbacks (known-procedure 2)]
|
||||||
[unsafe-root-continuation-prompt-tag (known-procedure/pure 1)]
|
[unsafe-root-continuation-prompt-tag (known-procedure/pure 1)]
|
||||||
[unsafe-s16vector-ref (known-procedure 4)]
|
[unsafe-s16vector-ref (known-procedure/succeeds 4)]
|
||||||
[unsafe-s16vector-set! (known-procedure 8)]
|
[unsafe-s16vector-set! (known-procedure/succeeds 8)]
|
||||||
[unsafe-set-box! (known-procedure 4)]
|
[unsafe-set-box! (known-procedure 4)]
|
||||||
[unsafe-set-box*! (known-procedure 4)]
|
[unsafe-set-box*! (known-procedure/succeeds 4)]
|
||||||
[unsafe-set-mcar! (known-procedure 4)]
|
[unsafe-set-immutable-car! (known-procedure/succeeds 4)]
|
||||||
[unsafe-set-mcdr! (known-procedure 4)]
|
[unsafe-set-immutable-cdr! (known-procedure/succeeds 4)]
|
||||||
|
[unsafe-set-mcar! (known-procedure/succeeds 4)]
|
||||||
|
[unsafe-set-mcdr! (known-procedure/succeeds 4)]
|
||||||
[unsafe-set-on-atomic-timeout! (known-procedure 2)]
|
[unsafe-set-on-atomic-timeout! (known-procedure 2)]
|
||||||
[unsafe-set-sleep-in-thread! (known-procedure 4)]
|
[unsafe-set-sleep-in-thread! (known-procedure 4)]
|
||||||
[unsafe-signal-received (known-procedure 1)]
|
[unsafe-signal-received (known-procedure 1)]
|
||||||
|
|
|
@ -511,6 +511,8 @@
|
||||||
unsafe-list-tail
|
unsafe-list-tail
|
||||||
unsafe-list-ref
|
unsafe-list-ref
|
||||||
unsafe-cons-list
|
unsafe-cons-list
|
||||||
|
unsafe-set-immutable-car!
|
||||||
|
unsafe-set-immutable-cdr!
|
||||||
|
|
||||||
unsafe-char=?
|
unsafe-char=?
|
||||||
unsafe-char<?
|
unsafe-char<?
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
(define unsafe-cdr (unsafe-primitive cdr))
|
(define unsafe-cdr (unsafe-primitive cdr))
|
||||||
(define unsafe-list-tail (unsafe-primitive list-tail))
|
(define unsafe-list-tail (unsafe-primitive list-tail))
|
||||||
(define unsafe-list-ref (unsafe-primitive list-ref))
|
(define unsafe-list-ref (unsafe-primitive list-ref))
|
||||||
|
(define (unsafe-set-immutable-car! p a) ((unsafe-primitive set-car!) p a))
|
||||||
|
(define (unsafe-set-immutable-cdr! p d) ((unsafe-primitive set-cdr!) p d))
|
||||||
|
|
||||||
(define unsafe-char=? (unsafe-primitive char=?))
|
(define unsafe-char=? (unsafe-primitive char=?))
|
||||||
(define unsafe-char<? (unsafe-primitive char<?))
|
(define unsafe-char<? (unsafe-primitive char<?))
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#define MZSCHEME_VERSION_X 7
|
#define MZSCHEME_VERSION_X 7
|
||||||
#define MZSCHEME_VERSION_Y 9
|
#define MZSCHEME_VERSION_Y 9
|
||||||
#define MZSCHEME_VERSION_Z 0
|
#define MZSCHEME_VERSION_Z 0
|
||||||
#define MZSCHEME_VERSION_W 17
|
#define MZSCHEME_VERSION_W 18
|
||||||
|
|
||||||
/* A level of indirection makes `#` work as needed: */
|
/* A level of indirection makes `#` work as needed: */
|
||||||
#define AS_a_STR_HELPER(x) #x
|
#define AS_a_STR_HELPER(x) #x
|
||||||
|
|
Loading…
Reference in New Issue
Block a user