summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lisp/libobjcl.lisp6
-rw-r--r--Lisp/memory-management.lisp149
-rw-r--r--Lisp/method-invocation.lisp7
3 files changed, 80 insertions, 82 deletions
diff --git a/Lisp/libobjcl.lisp b/Lisp/libobjcl.lisp
index 7c5fd8c..1a7e21a 100644
--- a/Lisp/libobjcl.lisp
+++ b/Lisp/libobjcl.lisp
@@ -412,7 +412,7 @@ conventional case for namespace identifiers in Objective-C."
(let ((selector-ptr (%objcl-find-selector selector-name)))
(if (cffi:null-pointer-p selector-ptr)
nil
- (make-pointer-wrapper 'selector :pointer selector-ptr))))
+ (intern-pointer-wrapper 'selector :pointer selector-ptr))))
(defun intern-selector-by-name (selector-name)
@@ -420,7 +420,7 @@ conventional case for namespace identifiers in Objective-C."
(assert (not (cffi:null-pointer-p selector-ptr))
(selector-ptr)
"%OBJCL-INTERN-SELECTOR must always return a selector.")
- (make-pointer-wrapper 'selector :pointer selector-ptr)))
+ (intern-pointer-wrapper 'selector :pointer selector-ptr)))
(declaim (ftype (function ((or objective-c-class id exception)) string)
@@ -718,7 +718,7 @@ separating parts by hyphens works nicely in all of the `:INVERT`,
(let ((superclass-ptr (%objcl-class-superclass class-ptr)))
(if (and (not (null-pointer-p superclass-ptr))
(%objcl-object-is-class superclass-ptr))
- (make-pointer-wrapper t :pointer superclass-ptr)
+ (intern-pointer-wrapper t :pointer superclass-ptr)
nil)))
(defun objcl-class-superclass (class)
diff --git a/Lisp/memory-management.lisp b/Lisp/memory-management.lisp
index 6e4731a..3d4685d 100644
--- a/Lisp/memory-management.lisp
+++ b/Lisp/memory-management.lisp
@@ -23,97 +23,94 @@
(defvar *selector-objects* (make-weak-value-hash-table))
-(defun make-pointer-wrapper (class &rest initargs &key pointer &allow-other-keys)
+(defun intern-pointer-wrapper (class &rest initargs &key pointer &allow-other-keys)
(when (or (null-pointer-p pointer)
(pointer-eq (objcl-get-nil) pointer))
- (return-from make-pointer-wrapper
+ (return-from intern-pointer-wrapper
;; We can't simply return +NIL+ here, because this function might
;; be called at load-time (see the MAKE-LOAD-FORM methods in
;; data-types.lisp).
(make-instance 'id :pointer (objcl-get-nil))))
(when (not (eq 'selector class))
(cond ((%objcl-object-is-meta-class pointer)
- (return-from make-pointer-wrapper
+ (return-from intern-pointer-wrapper
(find-objc-meta-class-by-name (%objcl-class-name pointer))))
((%objcl-object-is-class pointer)
- (return-from make-pointer-wrapper
+ (return-from intern-pointer-wrapper
(find-objc-class-by-name (%objcl-class-name pointer))))))
(let* ((hash-table (ecase class
((id) *id-objects*)
((exception) *exception-objects*)
((selector) *selector-objects*)))
(address (cffi:pointer-address pointer))
- (object (weak-gethash address hash-table nil))
- (constructor (case class
- ((exception) #'make-condition)
- (otherwise #'make-instance))))
+ (object (weak-gethash address hash-table nil)))
(if object
object
- (progn
- ;; Note that we do not care whether another thread does the
- ;; same here, so we don't need to lock the hash table before
- ;; peeking into it. If our new object isn't put into the hash
- ;; table because another thread was faster than us, that's
- ;; fine. The important thing here is that (a) all objects
- ;; that do get into the hash table are properly set up for
- ;; garbage collection, and (b) most objects don't need to be
- ;; boxed and set up for garbage collection (and later
- ;; garbage-collected) anew all the time but can be retrieved
- ;; from the hash table.
- ;;
- ;; (a) is ensured by MAKE-INSTANCE (see below), while (b) is
- ;; what this function is all about.
- ;;
- ;; Note, too, that we would indeed have to lock the hash table
- ;; before peeking into it if we wanted all wrapper objects to
- ;; the same object to be EQL. I think that that would
- ;; probably not only be necessary, but even sufficient.
- ;;
- ;; By the way, is using the return value of SETF considered
- ;; bad style?
- (let* ((*in-make-pointer-wrapper-p* t)
- (new-wrapper (apply constructor
- ;; We do not create direct
- ;; instances of ID anymore.
- ;; Instead, we look for the correct
- ;; Objective-C wrapper class and
- ;; use that.
- ;;
- ;; Note that we do not have to
- ;; handle the case of POINTER
- ;; pointing to a class, because it
- ;; is handled right at the
- ;; beginning of the function.
- (if (eq class 'id)
- (primitive-invoke pointer
- "class"
- 'id)
- class)
- initargs)))
- (setf (weak-gethash address hash-table) new-wrapper)
- ;; As classes always have a retain count of -1, we don't
- ;; have to do memory management for them. Meanwhile,
- ;; selectors and meta-classes cannot receive messages, so
- ;; trying to do memory management for them would not be
- ;; healthy. Considering these facts, doing memory
- ;; management only for id instances seems the right thing to
- ;; do.
- (when (eq class 'id)
- ;; We call the `retain' method on every object that we
- ;; receive from a method call or otherwise except
- ;; non-convenience constructor methods (i.e. those whose
- ;; name starts with `alloc' or `new'). Upon Lisp-side
- ;; finalization of an object, wie `release' it.
- (unless *skip-retaining*
- (primitive-invoke new-wrapper "retain" 'id))
- (flet ((finalizer ()
- ;; Nowadays, PRIMITIVE-INVOKE happily accepts a
- ;; pointer as its first argument, which is
- ;; important here because the previously created
- ;; object wrapper cannot be used anymore. We're
- ;; right within its finalisation phase, after
- ;; all.
- (weak-remhash address hash-table)
- (primitive-invoke pointer "release" :void)))
- (trivial-garbage:finalize new-wrapper #'finalizer)))
- new-wrapper)))))
+ (apply #'make-pointer-wrapper hash-table address class initargs))))
+
+
+(defun make-pointer-wrapper (hash-table address class
+ &rest initargs
+ &key pointer &allow-other-keys)
+ ;; Note that we do not care whether another thread does the same here,
+ ;; so we don't need to lock the hash table before peeking into it. If
+ ;; our new object isn't put into the hash table because another thread
+ ;; was faster than us, that's fine. The important thing here is that
+ ;; (a) all objects that do get into the hash table are properly set up
+ ;; for garbage collection, and (b) most objects don't need to be boxed
+ ;; and set up for garbage collection (and later garbage-collected)
+ ;; anew all the time but can be retrieved from the hash table.
+ ;;
+ ;; (a) is ensured by MAKE-INSTANCE (see below), while (b) is what this
+ ;; function is all about.
+ ;;
+ ;; Note, too, that we would indeed have to lock the hash table before
+ ;; peeking into it if we wanted all wrapper objects to the same object
+ ;; to be EQL. I think that that would probably not only be necessary,
+ ;; but even sufficient.
+ ;;
+ ;; By the way, is using the return value of SETF considered bad style?
+ (let* ((constructor (case class
+ ((exception) #'make-condition)
+ (otherwise #'make-instance)))(*in-make-pointer-wrapper-p* t)
+ (new-wrapper (apply constructor
+ ;; We do not create direct instances of ID
+ ;; anymore. Instead, we look for the
+ ;; correct Objective-C wrapper class and
+ ;; use that.
+ ;;
+ ;; Note that we do not have to handle the
+ ;; case of POINTER pointing to a class,
+ ;; because it is handled right at the
+ ;; beginning of the function.
+ (if (eq class 'id)
+ (primitive-invoke pointer
+ "class"
+ 'id)
+ class)
+ initargs)))
+ (setf (weak-gethash address hash-table) new-wrapper)
+ ;; As classes always have a retain count of -1, we don't have to do
+ ;; memory management for them. Meanwhile, selectors and
+ ;; meta-classes cannot receive messages, so trying to do memory
+ ;; management for them would not be healthy. Considering these
+ ;; facts, doing memory management only for id instances seems the
+ ;; right thing to do.
+ (when (eq class 'id)
+ ;; We call the `retain' method on every object that we receive
+ ;; from a method call or otherwise except non-convenience
+ ;; constructor methods (i.e. those whose name starts with `alloc'
+ ;; or `new'). Upon Lisp-side finalization of an object, wie
+ ;; `release' it.
+ (unless *skip-retaining*
+ (primitive-invoke new-wrapper "retain" 'id))
+ (flet ((finalizer ()
+ ;; Nowadays, PRIMITIVE-INVOKE happily accepts a pointer
+ ;; as its first argument, which is important here because
+ ;; the previously created object wrapper cannot be used
+ ;; anymore. We're right within its finalisation phase,
+ ;; after all.
+ (weak-remhash address hash-table)
+ (primitive-invoke pointer "release" :void)))
+ (trivial-garbage:finalize new-wrapper #'finalizer)))
+ new-wrapper))
diff --git a/Lisp/method-invocation.lisp b/Lisp/method-invocation.lisp
index 750647f..660b9ae 100644
--- a/Lisp/method-invocation.lisp
+++ b/Lisp/method-invocation.lisp
@@ -451,9 +451,10 @@ easier to use with __apply__.
(let ((*skip-retaining*
(or *skip-retaining*
(constructor-name-p (selector-name selector)))))
- (make-pointer-wrapper (car return-type)
- :pointer (cffi:mem-ref objc-return-value-cell
- return-c-type))))
+ (intern-pointer-wrapper (car return-type)
+ :pointer (cffi:mem-ref
+ objc-return-value-cell
+ return-c-type))))
((:char :unsigned-char)
;; FIXME? This is non-trivial. See policy.lisp for
;; details.