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?]{
Returns @racket[#t] if @racket[cptr] is treated as a reference to
memory that is managed by the garbage collector, @racket[#f]
otherwise.}
memory that is (assumed to be) managed by the garbage collector,
@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?])
bytes?]{
Returns a byte string made of the given pointer and the given length.
No copying is performed. Beware that future implementations of Racket
may not support this function (in case of a byte string representation
that combines a size and byte-string content without an indirection).
Returns a byte string made of the given pointer and the given length
in the @3m[] and @CGC[] variants of Racket; no copying is performed.
In the @CS[] variant, the @racket[exn:fail:unsupported] exception is
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
@racket[length] bytes), but some functions work with a byte-string
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
@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
corresponds to a value that supports interior pointers and that is
otherwise referenced to preserve the value from garbage collection).
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
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?]{
Like @racket[_pointer], but for a C pointer value that can refer to memory
managed by the garbage collector.
The same as @racket[_pointer] as an argument type, but as a result
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
managed by the garbage collector, beware of using an address that
In the @3m[] and @CGC[] variants of Racket, a @racket[_gcpointer] result
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,
if a reference is created by @racket[malloc] with @racket['raw] and
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.
The @racket[cpointer-gcable?] function returns @racket[#t] for a
cpointer generated via the @racket[_gcpointer] type, while it
generates @racket[#f] for a cpointer generated via the
@racket[_cpointer] type.}
cpointer generated via the @racket[_gcpointer] result type. See
@racket[cpointer-gcable?] for more information.}
@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;
see also @racket[_bytes/nul-terminated].
In the @3m[] and @CGC[] variants of Racket, a C non-NULL @cpp{char*}
is converted to a Racket byte string without copying. In the @CS[]
variant, conversion requires copying to represent a C @cpp{char*}
result as a Racket byte string. In both cases, the C result must have
In the @3m[] and @CGC[] variants of Racket, a C non-NULL result value
is converted to a Racket byte string without copying; the pointer is
treated as potentially managed by the garbage collector (see
@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 @racket[(_bytes o len-expr)] form is a @tech{custom function type}.
@ -1182,6 +1188,7 @@ results.
@history[#:added "6.12.0.2"]}
@; ------------------------------------------------------------
@section{C Struct Types}

View File

@ -1114,6 +1114,13 @@
pre: (x => (vector->cblock x t))
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
;; 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
@ -1123,7 +1130,7 @@
(provide (rename-out [_bytes* _bytes]))
(define-fun-syntax _bytes*
(syntax-id-rules (o)
[(_ o n) (type: _gcpointer
[(_ o n) (type: _pointer/maybe-gcable
pre: (make-bytes-argument n)
;; post is needed when this is used as a function output type
post: (x => (receive-bytes-result x n)))]

View File

@ -268,9 +268,8 @@
(define (to-utf-16 s)
(let ([v (malloc _gcpointer)])
(ptr-set! v _string/utf-16 s)
(let ([p (ptr-ref v _gcpointer)])
(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)
(for/fold ([len 0]) ([c (in-string s)])