cs & ffi/unsafe: change base type of (_bytes o <n>) to _pointer

A base type of `_gcpointer` works ok for traditional Racket as a kind
of "maybe it's GCable, so treat it that way just in case". That
approach doesn't work for Racket CS, where `_gpointer` has to mean
"definitely GCable memory". Although the difference is unfortunate,
making Racket CS base `(_bytes o <n>)` on `_pointer` is consistent
with the way plain `_bytes` is like `_pointer` in Racket CS and like
`_gcpointer` in traditional Racket.
This commit is contained in:
Matthew Flatt 2019-10-16 11:27:38 -06:00
parent e0b51e2709
commit 01ed8e4662
4 changed files with 46 additions and 23 deletions

View File

@ -57,8 +57,18 @@ offset is always in bytes.}
@defproc[(cpointer-gcable? [cptr cpointer?]) boolean?]{ @defproc[(cpointer-gcable? [cptr cpointer?]) boolean?]{
Returns @racket[#t] if @racket[cptr] is treated as a reference to Returns @racket[#t] if @racket[cptr] is treated as a reference to
memory that is managed by the garbage collector, @racket[#f] memory that is (assumed to be) managed by the garbage collector,
otherwise.} @racket[#f] otherwise.
For a pointer based on @racket[_gcpointer] as a result type,
@racket[cpointer-gcable?] will return @racket[#t]. In the @3m[] and
@CGC[] variants of Racket, @racket[cpointer-gcable?] will return
@racket[#f] for a pointer based on @racket[_pointer] as a result type.
The @CS[] variant is mostly the sane, except that if a pointer is
extracted using the @racket[_pointer] type from memory allocated as
@racket['nonatomic], @racket[cpointer-gcable?] will report @racket[#t]
for the extracted pointer.}
@; ---------------------------------------------------------------------- @; ----------------------------------------------------------------------
@ -466,12 +476,12 @@ use by such finalizers.}
@defproc[(make-sized-byte-string [cptr cpointer?] [length exact-nonnegative-integer?]) @defproc[(make-sized-byte-string [cptr cpointer?] [length exact-nonnegative-integer?])
bytes?]{ bytes?]{
Returns a byte string made of the given pointer and the given length. Returns a byte string made of the given pointer and the given length
No copying is performed. Beware that future implementations of Racket in the @3m[] and @CGC[] variants of Racket; no copying is performed.
may not support this function (in case of a byte string representation In the @CS[] variant, the @racket[exn:fail:unsupported] exception is
that combines a size and byte-string content without an indirection). raised.
Beware also that the representation of a Racket byte string normally Beware that the representation of a Racket byte string normally
requires a nul terminator at the end of the byte string (after requires a nul terminator at the end of the byte string (after
@racket[length] bytes), but some functions work with a byte-string @racket[length] bytes), but some functions work with a byte-string
representation that has no such terminator---notably representation that has no such terminator---notably

View File

@ -418,11 +418,13 @@ See @secref["foreign:tagged-pointers"] for creating pointer types that
use these tags for safety. A @racket[#f] value is converted to use these tags for safety. A @racket[#f] value is converted to
@cpp{NULL} and vice versa. @cpp{NULL} and vice versa.
The address referenced by a @racket[_pointer] value must not refer to As a result type, the address referenced by a @racket[_pointer] value must not refer to
memory managed by the garbage collector (unless the address memory managed by the garbage collector (unless the address
corresponds to a value that supports interior pointers and that is corresponds to a value that supports interior pointers and that is
otherwise referenced to preserve the value from garbage collection). otherwise referenced to preserve the value from garbage collection).
The reference is not traced or updated by the garbage collector. The reference is not traced or updated by the garbage collector.
As an argument type, @racket[_pointer] works for a reference to either
GC-managed memory or not.
The @racket[equal?] predicate equates C pointers (including pointers The @racket[equal?] predicate equates C pointers (including pointers
for @racket[_gcpointer] and possibly containing an offset) when they for @racket[_gcpointer] and possibly containing an offset) when they
@ -433,11 +435,13 @@ case the equality rules of the relevant structure types apply.}
@defthing[_gcpointer ctype?]{ @defthing[_gcpointer ctype?]{
Like @racket[_pointer], but for a C pointer value that can refer to memory The same as @racket[_pointer] as an argument type, but as a result
managed by the garbage collector. type, @racket[_gcpointer] corresponds to a C pointer value that refers
to memory managed by the garbage collector.
Although a @racket[_gcpointer] can reference to memory that is not In the @3m[] and @CGC[] variants of Racket, a @racket[_gcpointer] result
managed by the garbage collector, beware of using an address that pointer can reference to memory that is not
managed by the garbage collector, but beware of using an address that
might eventually become managed by the garbage collector. For example, might eventually become managed by the garbage collector. For example,
if a reference is created by @racket[malloc] with @racket['raw] and if a reference is created by @racket[malloc] with @racket['raw] and
released by @racket[free], then the @racket[free] may allow the memory released by @racket[free], then the @racket[free] may allow the memory
@ -445,9 +449,8 @@ formerly occupied by the reference to be used later by the garbage
collector. collector.
The @racket[cpointer-gcable?] function returns @racket[#t] for a The @racket[cpointer-gcable?] function returns @racket[#t] for a
cpointer generated via the @racket[_gcpointer] type, while it cpointer generated via the @racket[_gcpointer] result type. See
generates @racket[#f] for a cpointer generated via the @racket[cpointer-gcable?] for more information.}
@racket[_cpointer] type.}
@deftogether[( @deftogether[(
@ -1141,10 +1144,13 @@ type; a byte string is passed as @racket[_bytes] without any copying.
Beware that a Racket byte string is not necessarily nul terminated; Beware that a Racket byte string is not necessarily nul terminated;
see also @racket[_bytes/nul-terminated]. see also @racket[_bytes/nul-terminated].
In the @3m[] and @CGC[] variants of Racket, a C non-NULL @cpp{char*} In the @3m[] and @CGC[] variants of Racket, a C non-NULL result value
is converted to a Racket byte string without copying. In the @CS[] is converted to a Racket byte string without copying; the pointer is
variant, conversion requires copying to represent a C @cpp{char*} treated as potentially managed by the garbage collector (see
result as a Racket byte string. In both cases, the C result must have @racket[_gcpointer] for caveats). In the @CS[] variant of Racket,
conversion requires copying to represent a C @cpp{char*}
result as a Racket byte string, and the original pointer is @emph{not}
treated as managed by the garbage collector. In both cases, the C result must have
a nul terminator to determine the Racket byte string's length. a nul terminator to determine the Racket byte string's length.
A @racket[(_bytes o len-expr)] form is a @tech{custom function type}. A @racket[(_bytes o len-expr)] form is a @tech{custom function type}.
@ -1182,6 +1188,7 @@ results.
@history[#:added "6.12.0.2"]} @history[#:added "6.12.0.2"]}
@; ------------------------------------------------------------ @; ------------------------------------------------------------
@section{C Struct Types} @section{C Struct Types}

View File

@ -1114,6 +1114,13 @@
pre: (x => (vector->cblock x t)) pre: (x => (vector->cblock x t))
post: (x => (cblock->vector x t n)))])) post: (x => (cblock->vector x t n)))]))
;; Reflect the difference between 'racket and 'chez-scheme
;; VMs for `_bytes` in `_bytes*`:
(define _pointer/maybe-gcable
(if (eq? 'racket (system-type 'vm))
_gcpointer
_pointer))
;; _bytes or (_bytes o n) is for a memory block represented as a Scheme byte ;; _bytes or (_bytes o n) is for a memory block represented as a Scheme byte
;; string. _bytes is just like a byte-string, and (_bytes o n) is for ;; string. _bytes is just like a byte-string, and (_bytes o n) is for
;; pre-malloc of the string. There is no need for other modes: i or io would ;; pre-malloc of the string. There is no need for other modes: i or io would
@ -1123,7 +1130,7 @@
(provide (rename-out [_bytes* _bytes])) (provide (rename-out [_bytes* _bytes]))
(define-fun-syntax _bytes* (define-fun-syntax _bytes*
(syntax-id-rules (o) (syntax-id-rules (o)
[(_ o n) (type: _gcpointer [(_ o n) (type: _pointer/maybe-gcable
pre: (make-bytes-argument n) pre: (make-bytes-argument n)
;; post is needed when this is used as a function output type ;; post is needed when this is used as a function output type
post: (x => (receive-bytes-result x n)))] post: (x => (receive-bytes-result x n)))]

View File

@ -268,9 +268,8 @@
(define (to-utf-16 s) (define (to-utf-16 s)
(let ([v (malloc _gcpointer)]) (let ([v (malloc _gcpointer)])
(ptr-set! v _string/utf-16 s) (ptr-set! v _string/utf-16 s)
(let ([p (ptr-ref v _gcpointer)]) (let ([len (* 2 (+ 1 (utf-16-length s)))])
(let ([len (* 2 (+ 1 (utf-16-length s)))]) (ptr-ref v (_bytes o len)))))
(ptr-ref v (_bytes o len))))))
(define (utf-16-length s) (define (utf-16-length s)
(for/fold ([len 0]) ([c (in-string s)]) (for/fold ([len 0]) ([c (in-string s)])