* Reported by Lars Rune Nøstdal.
* SB-PCL::DEFAULT-INITARGS doesn't have to be a generic function.
* Test-case.
with a specialised code sequence.
* optimization: MAKE-INSTANCE with non-constant class-argument but constant
keywords is an order of magnitude faster.
- * optimization: MAKE-INSTANCE with constant keyword arguments is somewhat
- faster for non-standard metaclass classes as long as there are no methods
- additional on MAKE-INSTANCE and initialization arguments can be validated
- at compile-time.
+ * optimization: MAKE-INSTANCE with constant keyword arguments is x2-4 faster
+ in the presence of :AROUND or non-standard primary INITIALIZE-INSTANCE
+ methods, and similarly for non-standard metaclass classes as long as there
+ are no methods additional on MAKE-INSTANCE.
* optimization: more efficient type-checks for FIXNUMs when the value
is known to be a signed word on x86 and x86-64.
* optimization: compiler now optimizes (EXPT -1 INTEGER), (EXPT -1.0 INTEGER),
;; *COMPILING-OPTIMIZED-CONSTRUCTOR* which is bound around compilation of
;; the constructor, hence avoiding the possibility of endless recursion.
(make-instance ,class ,@initargs))
- `(lambda ,lambda-list
- (declare #.*optimize-speed*)
- (fast-make-instance ,class ,@initargs)))))
+ (let ((defaults (class-default-initargs class)))
+ (when defaults
+ (setf initargs (default-initargs initargs defaults)))
+ `(lambda ,lambda-list
+ (declare #.*optimize-speed*)
+ (fast-make-instance ,class ,@initargs))))))
;;; Not as good as the real optimizing generator, but faster than going
;;; via MAKE-INSTANCE: 1 GF call less, and no need to check initargs.
(defgeneric compute-slot-accessor-info (slotd type gf))
-(defgeneric default-initargs (class initargs defaults))
-
(defgeneric find-method-combination (generic-function type options))
(defgeneric invalid-qualifiers (generic-function combin method))
(unless (class-finalized-p class) (finalize-inheritance class))
(let ((class-default-initargs (class-default-initargs class)))
(when class-default-initargs
- (setf initargs (default-initargs class initargs class-default-initargs)))
+ (setf initargs (default-initargs initargs class-default-initargs)))
(when initargs
(when (and (eq *boot-state* 'complete)
(not (getf initargs :allow-other-keys)))
(apply #'initialize-instance instance initargs)
instance)))
-(defmethod default-initargs ((class slot-class)
- supplied-initargs
- class-default-initargs)
+(defun default-initargs (supplied-initargs class-default-initargs)
(loop for (key nil fun) in class-default-initargs
when (eq (getf supplied-initargs key '.not-there.) '.not-there.)
append (list key (funcall fun)) into default-initargs
(push (cons "Time default-initargs."
'(time-default-initargs (find-class 'plist-mixin) 1000))
*tests*)
-(defun time-default-initargs (class n)
- (time (dotimes-fixnum (i n) (default-initargs class nil))))
+(defun time-default-initargs (n)
+ (time (dotimes-fixnum (i n) (default-initargs nil nil))))
(push (cons "Time make-instance."
'(time-make-instance (find-class 'plist-mixin) 1000))
(when (and (consp c) (eq 'sb-pcl::ctor-cache (car c)))
(return c)))))))
+;;; FIXME: Move this to test-utils -- compiler tests have / need stuff like this
+;;; as well.
+(defun find-callee (f &key (type t) (name nil namep))
+ (let ((code (sb-kernel:fun-code-header (sb-kernel:%fun-fun f))))
+ (loop for i from sb-vm::code-constants-offset below (sb-kernel:get-header-data code)
+ for c = (sb-kernel:code-header-ref code i)
+ do (when (typep c 'sb-impl::fdefn)
+ (let ((fun (sb-impl::fdefn-fun c)))
+ (when (and (typep fun type)
+ (or (not namep)
+ (equal name (sb-impl::fdefn-name c))))
+ (return fun)))))))
+
(let* ((cmacro (compiler-macro-function 'make-instance))
(opt 0)
(wrapper (lambda (form env)
(dolist (class classes)
(assert (typep (funcall f (if (oddp count) class (find-class class))) class))
(incf count))))
+
+;;; Make sure we get default initargs right with on the FAST-MAKE-INSTANCE path CTORs
+(defclass some-class ()
+ ((aroundp :initform nil :reader aroundp))
+ (:default-initargs :x :success?))
+(defmethod initialize-instance :around ((some-class some-class) &key (x :fail?))
+ (unless (eq x :success?)
+ (error "Default initarg lossage"))
+ (setf (slot-value some-class 'aroundp) t)
+ (when (next-method-p)
+ (call-next-method)))
+(with-test (:name (make-instance :ctor-default-initargs))
+ (assert (aroundp (eval `(make-instance 'some-class))))
+ (let ((fun (compile nil `(lambda () (make-instance 'some-class)))))
+ (assert (aroundp (funcall fun)))
+ ;; make sure we tested what we think we tested...
+ (let ((ctor (find-callee fun :type 'sb-pcl::ctor)))
+ (assert (find-callee ctor :name 'sb-pcl::fast-make-instance)))))
\f
;;;; success
;;; checkins which aren't released. (And occasionally for internal
;;; versions, especially for internal versions off the main CVS
;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.29.47"
+"1.0.29.48"