cs: use new immobile-object support
Implement 'atomic-interior allocation and immobile cells using `make-immobile-bytevector` and `make-immobile-vector`, which avoids having to unlock through a finalizer. Also, the Chez Scheme GC can now mostly mark a major generation, instead of copying it, which can significantly reduce memory use during a GC for an old, large heap (such as DrRacket's).
This commit is contained in:
parent
dccd841adf
commit
16ad9ed522
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
(define collection 'multi)
|
(define collection 'multi)
|
||||||
|
|
||||||
(define version "7.7.0.2")
|
(define version "7.7.0.3")
|
||||||
|
|
||||||
(define deps `("racket-lib"
|
(define deps `("racket-lib"
|
||||||
["racket" #:version ,version]))
|
["racket" #:version ,version]))
|
||||||
|
|
|
@ -280,23 +280,12 @@ specification is required at minimum:
|
||||||
@item{@indexed-racket['atomic-interior] --- Like
|
@item{@indexed-racket['atomic-interior] --- Like
|
||||||
@racket['atomic], but the allocated object will not be moved by
|
@racket['atomic], but the allocated object will not be moved by
|
||||||
the garbage collector as long as the allocated object is
|
the garbage collector as long as the allocated object is
|
||||||
sufficiently retained as described below.
|
retained.
|
||||||
|
|
||||||
For the @3m[] and @CGC[] Racket variants, ``sufficiently retained''
|
For the @3m[] and @CGC[] Racket variants, a reference can point
|
||||||
means that the garbage collector does not collect the allocated
|
to the interior of the object, instead of its starting address.
|
||||||
object because some pointer (that is visible to the collector)
|
|
||||||
refers to the object. Furthermore, that reference can point to
|
|
||||||
the interior of the object, insteda of its starting address.
|
|
||||||
This allocation mode corresponds to
|
This allocation mode corresponds to
|
||||||
@cpp{scheme_malloc_atomic_allow_interior} in the C API.
|
@cpp{scheme_malloc_atomic_allow_interior} in the C API.}
|
||||||
|
|
||||||
For the @CS[] Racket variant, ``sufficiently retained'' means that the
|
|
||||||
specific C pointer object returned by @racket[malloc] remains
|
|
||||||
accessible. Note that casting the pointer via @racket[cast], for example,
|
|
||||||
generates a new pointer object which would not by itself
|
|
||||||
prevent the result of @racket[malloc] from moving, even though
|
|
||||||
a reference to the same memory could prevent the object from
|
|
||||||
being reclaimed.}
|
|
||||||
|
|
||||||
@item{@indexed-racket['nonatomic-interior] --- Like
|
@item{@indexed-racket['nonatomic-interior] --- Like
|
||||||
@racket['nonatomic], but the allocated object will not be moved
|
@racket['nonatomic], but the allocated object will not be moved
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
;; Check to make we're using a build of Chez Scheme
|
;; Check to make we're using a build of Chez Scheme
|
||||||
;; that has all the features we need.
|
;; that has all the features we need.
|
||||||
(define-values (need-maj need-min need-sub need-dev)
|
(define-values (need-maj need-min need-sub need-dev)
|
||||||
(values 9 5 3 26))
|
(values 9 5 3 27))
|
||||||
|
|
||||||
(unless (guard (x [else #f]) (eval 'scheme-fork-version-number))
|
(unless (guard (x [else #f]) (eval 'scheme-fork-version-number))
|
||||||
(error 'compile-file
|
(error 'compile-file
|
||||||
|
|
|
@ -475,7 +475,6 @@
|
||||||
[else
|
[else
|
||||||
(post-as-asynchronous-callback go)]))))])
|
(post-as-asynchronous-callback go)]))))])
|
||||||
(let ([callable (foreign-callable __collect_safe glib-log-message (string int string) void)])
|
(let ([callable (foreign-callable __collect_safe glib-log-message (string int string) void)])
|
||||||
(lock-object callable)
|
|
||||||
(foreign-callable-entry-point callable))))
|
(foreign-callable-entry-point callable))))
|
||||||
|
|
||||||
;; ----------------------------------------
|
;; ----------------------------------------
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
(if (eq? v #!bwp)
|
(if (eq? v #!bwp)
|
||||||
gced-v
|
gced-v
|
||||||
v))]
|
v))]
|
||||||
[(e gced-v keep-live)
|
[(e gced-v keep-live-v)
|
||||||
(let ([v (ephemeron-value e gced-v)])
|
(let ([v (ephemeron-value e gced-v)])
|
||||||
(#%$keep-live keep-live)
|
(keep-live keep-live-v)
|
||||||
v)]))
|
v)]))
|
||||||
|
|
|
@ -1409,11 +1409,8 @@
|
||||||
;; a finalizer is associated with the cpointer (as opposed to
|
;; a finalizer is associated with the cpointer (as opposed to
|
||||||
;; the address that is wrapped by the cpointer). Also, interior
|
;; the address that is wrapped by the cpointer). Also, interior
|
||||||
;; pointers are not allowed as GCable pointers.
|
;; pointers are not allowed as GCable pointers.
|
||||||
(let* ([bstr (make-bytevector size 0)]
|
(let* ([bstr (make-immobile-bytevector size)])
|
||||||
[p (make-cpointer bstr #f)])
|
(make-cpointer bstr #f))]
|
||||||
(lock-object bstr)
|
|
||||||
(unsafe-add-global-finalizer p (lambda () (unlock-object bstr)))
|
|
||||||
p)]
|
|
||||||
[else
|
[else
|
||||||
(raise-unsupported-error 'malloc
|
(raise-unsupported-error 'malloc
|
||||||
(format "'~a mode is not supported" mode))]))
|
(format "'~a mode is not supported" mode))]))
|
||||||
|
@ -1427,13 +1424,18 @@
|
||||||
(parent cpointer)
|
(parent cpointer)
|
||||||
(fields))
|
(fields))
|
||||||
|
|
||||||
|
(define immobile-cells (make-eq-hashtable))
|
||||||
|
|
||||||
(define (malloc-immobile-cell v)
|
(define (malloc-immobile-cell v)
|
||||||
(let ([vec (vector v)])
|
(let ([vec (make-immobile-vector 1)])
|
||||||
(lock-object vec)
|
(#%vector-set! vec 0 v)
|
||||||
|
(with-global-lock
|
||||||
|
(eq-hashtable-set! immobile-cells vec #t))
|
||||||
(make-cpointer/cell vec #f)))
|
(make-cpointer/cell vec #f)))
|
||||||
|
|
||||||
(define (free-immobile-cell b)
|
(define (free-immobile-cell b)
|
||||||
(unlock-object (cpointer-memory b)))
|
(with-global-lock
|
||||||
|
(eq-hashtable-delete! immobile-cells (cpointer-memory b))))
|
||||||
|
|
||||||
(define (immobile-cell-ref b)
|
(define (immobile-cell-ref b)
|
||||||
(#%vector-ref (cpointer-memory b) 0))
|
(#%vector-ref (cpointer-memory b) 0))
|
||||||
|
@ -1542,7 +1544,7 @@
|
||||||
;; so uses of the FFI can rely on passing an argument to a foreign
|
;; so uses of the FFI can rely on passing an argument to a foreign
|
||||||
;; function as retaining the argument until the function returns.
|
;; function as retaining the argument until the function returns.
|
||||||
(let ([result e])
|
(let ([result e])
|
||||||
(#%$keep-live v) ...
|
(keep-live v) ...
|
||||||
result))
|
result))
|
||||||
|
|
||||||
(define call-locks (make-eq-hashtable))
|
(define call-locks (make-eq-hashtable))
|
||||||
|
@ -1945,11 +1947,7 @@
|
||||||
(let ([make-code (ffi-call/callable #f in-types out-type abi #f #f #f #f (and atomic? #t) async-apply)])
|
(let ([make-code (ffi-call/callable #f in-types out-type abi #f #f #f #f (and atomic? #t) async-apply)])
|
||||||
(lambda (proc)
|
(lambda (proc)
|
||||||
(check 'make-ffi-callback procedure? proc)
|
(check 'make-ffi-callback procedure? proc)
|
||||||
(let* ([code (make-code proc)]
|
(create-callback (make-code proc))))]))
|
||||||
[cb (create-callback code)])
|
|
||||||
(lock-object code)
|
|
||||||
(unsafe-add-global-finalizer cb (lambda () (unlock-object code)))
|
|
||||||
cb)))]))
|
|
||||||
|
|
||||||
;; ----------------------------------------
|
;; ----------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#define MZSCHEME_VERSION_X 7
|
#define MZSCHEME_VERSION_X 7
|
||||||
#define MZSCHEME_VERSION_Y 7
|
#define MZSCHEME_VERSION_Y 7
|
||||||
#define MZSCHEME_VERSION_Z 0
|
#define MZSCHEME_VERSION_Z 0
|
||||||
#define MZSCHEME_VERSION_W 2
|
#define MZSCHEME_VERSION_W 3
|
||||||
|
|
||||||
/* 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