summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStas Boukarev <stassats@gmail.com>2022-08-17 19:37:26 +0300
committerStas Boukarev <stassats@gmail.com>2022-08-17 20:01:45 +0300
commit953d4b7757d83da2320458f7f60e35a8eb5ea56d (patch)
tree73236113c28652e4a433ac1cc6bbe665bda5dc1d
parent78322bd085dc956e5b495d010b80ffc517aea889 (diff)
Test for sealed classes using structure-typep too.
-rw-r--r--src/compiler/arm64/type-vops.lisp42
-rw-r--r--src/compiler/typetran.lisp30
-rw-r--r--src/compiler/x86-64/type-vops.lisp94
3 files changed, 112 insertions, 54 deletions
diff --git a/src/compiler/arm64/type-vops.lisp b/src/compiler/arm64/type-vops.lisp
index 2a266901c..74ea9d994 100644
--- a/src/compiler/arm64/type-vops.lisp
+++ b/src/compiler/arm64/type-vops.lisp
@@ -595,7 +595,7 @@
(inst b :ne not-instance))
(loadw r object instance-slots-offset instance-pointer-lowtag)))
-(defun structure-is-a (layout temp this-id test-layout &optional target not-p done)
+(defun structure-is-a (layout temp this-id test-layout &optional desc-temp target not-p done)
(cond ((integerp test-layout)
(inst ldrsw temp
(@ layout
@@ -604,6 +604,11 @@
word-shift)
instance-pointer-lowtag)))
(inst tst temp test-layout))
+ ((and desc-temp
+ (neq (tn-kind desc-temp) :unused))
+ (inst load-constant desc-temp
+ (tn-byte-offset (emit-constant test-layout)))
+ (inst cmp layout desc-temp))
(t
(let* ((test-id (layout-id test-layout))
(depthoid (wrapper-depthoid test-layout))
@@ -658,14 +663,28 @@
(:conditional)
(:info target not-p test-layout)
(:temporary (:sc descriptor-reg) layout)
- (:temporary (:sc unsigned-reg) this-id temp)
+ (:temporary (:sc unsigned-reg
+ :unused-if
+ (and (instance-tn-ref-p args)
+ #1=(and (not (integerp test-layout))
+ (let ((classoid (wrapper-classoid test-layout)))
+ (and (eq (classoid-state classoid) :sealed)
+ (not (classoid-subclasses classoid)))))))
+ temp)
+ (:temporary (:sc unsigned-reg
+ :unused-if (or (integerp test-layout)
+ #1#))
+ this-id)
+ (:temporary (:sc descriptor-reg
+ :unused-if (not #1#))
+ desc-temp)
(:generator 4
(unless (instance-tn-ref-p args)
(inst and temp object lowtag-mask)
(inst cmp temp instance-pointer-lowtag)
(inst b :ne (if not-p target done)))
(loadw layout object instance-slots-offset instance-pointer-lowtag)
- (structure-is-a layout temp this-id test-layout target not-p done)
+ (structure-is-a layout temp this-id test-layout desc-temp target not-p done)
(inst b (if (if (integerp test-layout)
(not not-p)
not-p)
@@ -678,9 +697,22 @@
(:policy :fast-safe)
(:conditional)
(:info target not-p test-layout)
- (:temporary (:sc unsigned-reg) this-id temp)
+ (:temporary (:sc unsigned-reg
+ :unused-if
+ #1=(and (not (integerp test-layout))
+ (let ((classoid (wrapper-classoid test-layout)))
+ (and (eq (classoid-state classoid) :sealed)
+ (not (classoid-subclasses classoid))))))
+ temp)
+ (:temporary (:sc unsigned-reg
+ :unused-if (or (integerp test-layout)
+ #1#))
+ this-id)
+ (:temporary (:sc descriptor-reg
+ :unused-if (not #1#))
+ desc-temp)
(:generator 4
- (structure-is-a layout temp this-id test-layout target not-p done)
+ (structure-is-a layout temp this-id test-layout desc-temp target not-p done)
(inst b (if (if (integerp test-layout)
(not not-p)
not-p)
diff --git a/src/compiler/typetran.lisp b/src/compiler/typetran.lisp
index 7e3964e9a..273df6921 100644
--- a/src/compiler/typetran.lisp
+++ b/src/compiler/typetran.lisp
@@ -922,19 +922,23 @@
((and wrapper
(eq (classoid-state classoid) :sealed)
(not (classoid-subclasses classoid)))
- (if lowtag-test
- `(and ,lowtag-test
- ,(if (vop-existsp :translate layout-eq)
- `(layout-eq object ,wrapper ,lowtag)
- `(eq ,slot-reader ,layout)))
- ;; `(eq ,layout
- ;; (if-vop-existsp (:translate %instanceoid-layout)
- ;; (%instanceoid-layout object)
- ;; ;; Slightly quicker than LAYOUT-OF. See also %PCL-INSTANCE-P
- ;; (cond ((%instancep object) (%instance-layout object))
- ;; ((funcallable-instance-p object) (%fun-layout object))
- ;; (t ,(find-layout 't)))))
- (bug "Unexpected metatype for ~S" wrapper)))
+ (cond ((and (eq lowtag sb-vm:instance-pointer-lowtag)
+ (vop-existsp :translate structure-typep))
+ `(structure-typep object ,wrapper))
+ (lowtag-test
+ `(and ,lowtag-test
+ ,(if (vop-existsp :translate layout-eq)
+ `(layout-eq object ,wrapper ,lowtag)
+ `(eq ,slot-reader ,layout))))
+ (t
+ ;; `(eq ,layout
+ ;; (if-vop-existsp (:translate %instanceoid-layout)
+ ;; (%instanceoid-layout object)
+ ;; ;; Slightly quicker than LAYOUT-OF. See also %PCL-INSTANCE-P
+ ;; (cond ((%instancep object) (%instance-layout object))
+ ;; ((funcallable-instance-p object) (%fun-layout object))
+ ;; (t ,(find-layout 't)))))
+ (bug "Unexpected metatype for ~S" wrapper))))
;; All other structure types
((and (typep classoid 'structure-classoid) wrapper)
diff --git a/src/compiler/x86-64/type-vops.lisp b/src/compiler/x86-64/type-vops.lisp
index 5c75fb7aa..8cba092c1 100644
--- a/src/compiler/x86-64/type-vops.lisp
+++ b/src/compiler/x86-64/type-vops.lisp
@@ -942,37 +942,46 @@
(inst cmp :dword (read-depthoid) (fixnumize k))))
(defun structure-is-a (layout test-layout &optional target not-p done)
- (if (integerp test-layout)
- (inst test
- (if (typep test-layout '(unsigned-byte 8))
- :byte
- :dword)
- (ea (- (ash (+ instance-slots-offset
- (get-dsd-index layout sb-kernel::flags))
- word-shift)
- instance-pointer-lowtag)
- layout)
- test-layout)
- (let* ((depthoid (wrapper-depthoid test-layout))
- (offset (+ (id-bits-offset)
- (ash (- depthoid 2) 2)
- (- instance-pointer-lowtag))))
- (when (and target
- (> depthoid sb-kernel::layout-id-vector-fixed-capacity))
- (inst cmp :dword (read-depthoid) (fixnumize depthoid))
- (inst jmp :l (if not-p target done)))
- (inst cmp :dword
- (ea offset layout)
- ;; Small layout-ids can only occur for layouts made in genesis.
- ;; Therefore if the compile-time value of the ID is small,
- ;; it is permanently assigned to that type.
- ;; Otherwise, we allow for the possibility that the compile-time ID
- ;; is not the same as the load-time ID.
- ;; I don't think layout-id 0 can get here, but be sure to exclude it.
- (if (or (typep (layout-id test-layout) '(and (signed-byte 8) (not (eql 0))))
- (not (sb-c::producing-fasl-file)))
- (layout-id test-layout)
- (make-fixup test-layout :layout-id)))))))
+ (cond ((integerp test-layout)
+ (inst test
+ (if (typep test-layout '(unsigned-byte 8))
+ :byte
+ :dword)
+ (ea (- (ash (+ instance-slots-offset
+ (get-dsd-index layout sb-kernel::flags))
+ word-shift)
+ instance-pointer-lowtag)
+ layout)
+ test-layout))
+ ((let ((classoid (wrapper-classoid test-layout)))
+ (and (eq (classoid-state classoid) :sealed)
+ (not (classoid-subclasses classoid))))
+ (emit-constant test-layout)
+ (inst cmp #+compact-instance-header :dword
+ layout (make-fixup test-layout :layout)))
+
+ (t
+ (let* ((depthoid (wrapper-depthoid test-layout))
+ (offset (+ (id-bits-offset)
+ (ash (- depthoid 2) 2)
+ (- instance-pointer-lowtag))))
+ (when (and target
+ (> depthoid sb-kernel::layout-id-vector-fixed-capacity))
+ (inst cmp :dword (read-depthoid) (fixnumize depthoid))
+ (inst jmp :l (if not-p target done)))
+ (inst cmp #+compact-instance-header :dword
+ (ea offset layout)
+ ;; Small layout-ids can only occur for layouts made in genesis.
+ ;; Therefore if the compile-time value of the ID is small,
+ ;; it is permanently assigned to that type.
+ ;; Otherwise, we allow for the possibility that the compile-time ID
+ ;; is not the same as the load-time ID.
+ ;; I don't think layout-id 0 can get here, but be sure to exclude it.
+ (cond ((or (typep (layout-id test-layout) '(and (signed-byte 8) (not (eql 0))))
+ (not (sb-c::producing-fasl-file)))
+ (layout-id test-layout))
+ (t
+ (make-fixup test-layout :layout-id)))))))))
(define-vop ()
(:translate sb-c::%structure-is-a)
@@ -996,11 +1005,24 @@
(:generator 4
(unless (instance-tn-ref-p args)
(%test-lowtag object layout (if not-p target done) t instance-pointer-lowtag))
- #+compact-instance-header
- (inst mov :dword layout (ea (- 4 instance-pointer-lowtag) object))
- #-compact-instance-header
- (loadw layout object instance-slots-offset instance-pointer-lowtag)
- (structure-is-a layout test-layout target not-p done)
+
+ (cond ((and (not (integerp test-layout))
+ (let ((classoid (wrapper-classoid test-layout)))
+ (and (eq (classoid-state classoid) :sealed)
+ (not (classoid-subclasses classoid)))))
+ (emit-constant test-layout)
+ #+compact-instance-header
+ (inst cmp :dword (ea (- 4 instance-pointer-lowtag) object)
+ (make-fixup test-layout :layout))
+ #-compact-instance-header
+ (inst cmp (object-slot-ea layout instance-slots-offset instance-pointer-lowtag)
+ (make-fixup test-layout :layout)))
+ (t
+ #+compact-instance-header
+ (inst mov :dword layout (ea (- 4 instance-pointer-lowtag) object))
+ #-compact-instance-header
+ (loadw layout object instance-slots-offset instance-pointer-lowtag)
+ (structure-is-a layout test-layout target not-p done)))
(inst jmp (if (if (integerp test-layout)
(not not-p)
not-p)