3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; While most of SBCL is derived from the CMU CL system, the test
7 ;;;; files (like this one) were written from scratch after the fork
10 ;;;; This software is in the public domain and is provided with
11 ;;;; absoluely no warranty. See the COPYING and CREDITS files for
12 ;;;; more information.
16 (defvar *weak-vect
* (make-weak-vector 8))
17 (defmacro wvref
(v i
) `(sb-int:weak-vector-ref
,v
,i
))
18 (with-test (:name
:weak-vector
21 (random-symbol (make-symbol "FRED")))
23 (setf (wvref a
0) (cons 'foo
'bar
)
24 (wvref a
1) (format nil
"Time is: ~D~%" (get-internal-real-time))
25 (wvref a
2) 'interned-symbol
26 (wvref a
3) random-symbol
28 (wvref a
5) (+ most-positive-fixnum
1 (random 100) (random 100))
29 (wvref a
6) (make-hash-table))))
30 (declare (notinline x
)) ;; Leave all the values below the stack pointer for
31 (x)) ;; scrub-control-stack to work
32 (assert (weak-vector-p a
))
33 (sb-sys:scrub-control-stack
)
35 (assert (eq (wvref a
2) 'interned-symbol
))
36 (assert (eq (wvref a
3) random-symbol
))
37 (assert (= (wvref a
4) 18))
38 ;; broken cells are the cons, string, bignum, hash-table, plus one NIL
39 ;; cell that was never assigned into
40 (assert (null (wvref a
0)))
41 (assert (null (wvref a
1)))
42 (assert (null (wvref a
5)))
43 (assert (null (wvref a
6)))
46 ;; Assert something about *CURRENT-THREAD* seeing objects that it just consed.
47 (with-test (:name
:m-a-o-threadlocally-precise
48 :skipped-on
(:or
(:not
:sb-thread
) :interpreter
:gc-stress
)
49 :fails-on
:mark-region-gc
)
50 (let ((before (make-array 4))
51 (after (make-array 4 :initial-element
0)))
52 (flet ((countit (obj type size
)
53 (declare (ignore type size
))
54 (symbol-macrolet ((n-conses (aref after
1))
55 (n-bitvectors (aref after
2))
56 (n-symbols (aref after
3))
57 (n-other (aref after
0)))
59 (list (incf n-conses
))
60 (bit-vector (incf n-bitvectors
))
61 (symbol (incf n-symbols
))
62 (t (incf n-other
))))))
63 (sb-vm:map-allocated-objects
#'countit
:all
)
64 (replace before after
)
66 ;; expect to see 1 cons, 1 bit-vector, 1 symbol, and nothing else
67 (let ((* (cons (make-array 5 :element-type
'bit
)
68 (make-symbol "WAT"))))
69 (sb-vm:map-allocated-objects
#'countit
:all
)
70 (assert (equal (map 'list
#'- after before
) '(0 1 1 1)))))))
72 (defun count-dynamic-space-objects ()
74 (sb-vm:map-allocated-objects
75 (lambda (obj widetag size
)
76 (declare (ignore obj widetag size
))
80 (defun make-one-cons () (cons 'x
'y
))
82 ;;; While this does not directly test LIST-ALLOCATED-OBJECTS,
83 ;;; it checks that L-A-O would potentially (probably) include in its
84 ;;; output each new object allocated, barring any intervening GC.
85 ;;; It is all but impossible to actually test L-A-O in an A/B scenario
86 ;;; because it conses as many new cells as there were objects to begin
87 ;;; with, plus a vector. i.e. you can't easily perform "list the objects,
88 ;;; create one cons, list the objects, assert that there is that one
89 ;;; cons plus exactly the previous list of objects"
90 ;;; Counting and getting the right answer should be somewhat reassuring.
91 ;;; This test needs dynamic-extent to work properly.
92 ;;; (I don't know what platforms it passes on, but at least these two it does)
93 (with-test (:name
:repeatably-count-allocated-objects
94 :fails-on
:mark-region-gc
95 :skipped-on
(or (not (or :x86
:x86-64
))
98 (let ((a (make-array 5)))
99 (dotimes (i (length a
))
100 (setf (aref a i
) (count-dynamic-space-objects))
102 (dotimes (i (1- (length a
)))
103 (assert (= (aref a
(1+ i
)) (1+ (aref a i
)))))))
105 (with-test (:name
:list-allocated-objects
106 :skipped-on
:weak-vector-readbarrier
) ; uses more weak-pointers
107 ;; Assert that if :COUNT is supplied as a higher number
108 ;; than number of objects that exists, the output is
109 ;; not COUNT many items long.
110 (let ((l (sb-vm:list-allocated-objects
:dynamic
112 :type sb-vm
:weak-pointer-widetag
)))
113 ;; This is a change-detector unfortunately,
114 ;; but seems like it'll be OK for a while.
115 ;; I see only 4 weak pointers in the baseline image.
116 ;; Really we could just assert /= 1000.
117 (assert (< (length l
) 80))))
119 ;; check that WITHOUT-INTERRUPTS doesn't block SIG_STOP_FOR_GC
120 (with-test (:name
:gc-without-interrupts
121 :skipped-on
(not :sb-thread
))
122 (sb-sys:without-interrupts
123 (let ((thread (sb-thread:make-thread
(lambda () (sb-ext:gc
)))))
124 (loop while
(sb-thread:thread-alive-p thread
)))))
126 (defglobal *some-object-handles
* nil
)
127 (defun make-some-objects ()
128 (declare (notinline format
))
129 (let* ((string-one (format nil
"~a~a~a" "pot" "ayt" "o"))
130 (string-two (concatenate 'string
"two " string-one
))
132 (let (#+immobile-space
(sb-c::*compile-to-memory-space
* :dynamic
))
133 (compile nil
`(sb-int:named-lambda
,string-two
(x) (coerce x
'float
))))))
134 (setq *some-object-handles
*
135 (list (sb-kernel:get-lisp-obj-address afunction
)
136 (sb-kernel:get-lisp-obj-address string-one
)
137 (sb-kernel:get-lisp-obj-address string-two
)))))
138 (with-test (:name
:pin-all-code-with-gc-enabled
139 :fails-on
:mark-region-gc
140 :skipped-on
(or :interpreter
:gc-stress
))
142 #+sb-thread
(sb-thread:join-thread
(sb-thread:make-thread
#'make-some-objects
))
143 #-sb-thread
(progn (make-some-objects) (sb-sys:scrub-control-stack
))
144 (sb-sys:with-code-pages-pinned
(:dynamic
) (gc))
145 ;; this should not fail to find FUN at its old address
146 (let ((fun (sb-kernel:make-lisp-obj
(first *some-object-handles
*))))
147 ;; To prove that _some_ things moved in memory,
148 ;; assert that we don't see the arbitrary string at its old address.
149 (multiple-value-bind (thing existsp
)
150 (sb-kernel:make-lisp-obj
(second *some-object-handles
*) nil
)
151 (assert (or (not existsp
) (not (typep thing
'(string 7))))))
152 ;; this should similarly fail- STRING-TWO was transitively reachable but movable
153 (multiple-value-bind (obj validp
) (sb-kernel:make-lisp-obj
(third *some-object-handles
*) nil
)
155 (warn "Weird: obj=~s" obj
)))
156 ;; (assert (not (nth-value 1 (sb-kernel:make-lisp-obj (third *some-object-handles*) nil))))
157 (assert (string= (sb-kernel:%simple-fun-name fun
) "two potayto"))))
159 (with-test (:name
:generation-of-fdefn
)
160 ;; GENERATION-OF broke when fdefns stopped storing a generation in word 0.
161 ;; Normally we expect to see SB-VM:+PSEUDO-STATIC-GENERATION+
162 ;; but allow for varied definition of CORE_PAGE_GENERATION.
164 ;; Note that if (SB-EDITCORE:MOVE-DYNAMIC-CODE-TO-TEXT-SPACE) has been performed
165 ;; on this core, then #'CAR has no generation because it is essentially static.
166 ;; So we can't really assert anything in that case.
167 (when (numberp (sb-kernel:generation-of
#'car
))
168 (assert (= (sb-kernel:generation-of
(sb-int:find-fdefn
'(setf car
)))
169 (sb-kernel:generation-of
#'car
)))))
171 (with-test (:name
:static-fdefn-space
)
172 (sb-int:dovector
(name sb-vm
:+static-fdefns
+)
173 (assert (eq (sb-ext:heap-allocated-p
(sb-int:find-fdefn name
))
174 (or #+(and immobile-code x86-64
) :immobile
:static
)))))
176 ;;; SB-EXT:GENERATION-* accessors returned bogus values for generation > 0
177 (with-test (:name
:bug-529014
)
178 (loop for i from
0 to sb-vm
:+pseudo-static-generation
+
179 do
(assert (= (sb-ext:generation-bytes-consed-between-gcs i
)
180 (truncate (sb-ext:bytes-consed-between-gcs
)
181 sb-vm
:+highest-normal-generation
+)))
182 ;; FIXME: These parameters are a) tunable in the source and b)
183 ;; duplicated multiple times there and now here. It would be good to
184 ;; OAOO-ify them (probably to src/compiler/generic/params.lisp).
185 (assert (= (sb-ext:generation-minimum-age-before-gc i
) 0.75))
186 (assert (= (sb-ext:generation-number-of-gcs-before-promotion i
) 1))))
188 (with-test (:name
:gc-logfile
)
189 (assert (not (gc-logfile)))
190 (let ((p (scratch-file-name "log")))
191 (assert (not (probe-file p
)))
192 (assert (equal p
(setf (gc-logfile) p
)))
194 (let ((p2 (gc-logfile)))
195 (assert (equal (truename p2
) (truename p
))))
196 (assert (not (setf (gc-logfile) nil
)))
197 (assert (not (gc-logfile)))
200 #+nil
; immobile-code
201 (with-test (:name
(sb-kernel::order-by-in-degree
:uninterned-function-names
))
202 ;; This creates two functions whose names are uninterned symbols and
203 ;; that are both referenced once, resulting in a tie
204 ;; w.r.t. ORDER-BY-IN-DEGREE. Uninterned symbols used to cause an
205 ;; error in the tie-breaker.
206 (let* ((sb-c::*compile-to-memory-space
* :immobile
)
207 (f (eval `(defun ,(gensym) ())))
208 (g (eval `(defun ,(gensym) ()))))
209 (eval `(defun h () (,f
) (,g
))))
210 (sb-kernel::order-by-in-degree
))
212 (defparameter *pin-test-object
* nil
)
213 (defparameter *pin-test-object-address
* nil
)
215 (with-test (:name
(sb-sys:with-pinned-objects
:actually-pins-objects
)
216 :skipped-on
:cheneygc
)
217 ;; The interpreters (both sb-eval and sb-fasteval) special-case
218 ;; WITH-PINNED-OBJECTS as a "special form", because the x86oid
219 ;; version of WITH-PINNED-OBJECTS uses special functionality that
220 ;; isn't supportable outside of the compiler. The non-x86oid
221 ;; versions of WITH-PINNED-OBJECTS don't use this special
222 ;; functionality, but are overridden anyway. But the special-case
223 ;; logic was, historically broken, and this affects all gencgc
224 ;; targets (cheneygc isn't affected because cheneygc
225 ;; WITH-PINNED-OBJECTS devolves to WITHOUT-GCING).
227 ;; Our basic approach is to allocate some kind of object and stuff
228 ;; it where it doesn't need to be on the control stack. We then pin
229 ;; the object, take its address and store that somewhere as well,
230 ;; force a full GC, re-take the address, and see if it moved.
231 (locally (declare (notinline make-string
)) ;; force full call
232 (setf *pin-test-object
* (make-string 100)))
233 (sb-sys:with-pinned-objects
(*pin-test-object
*)
234 (setf *pin-test-object-address
*
235 (sb-kernel:get-lisp-obj-address
*pin-test-object
*))
237 (assert (= (sb-kernel:get-lisp-obj-address
*pin-test-object
*)
238 *pin-test-object-address
*))))
240 (import 'sb-kernel
:%make-lisp-obj
)
241 (defun ensure-code/data-separation
()
242 (let* ((n-bits (+ sb-vm
:next-free-page
10))
243 (code-bits (make-array n-bits
:element-type
'bit
:initial-element
0))
244 (data-bits (make-array n-bits
:element-type
'bit
:initial-element
0))
246 (sb-vm:map-allocated-objects
247 (lambda (obj type size
)
248 (declare ((and fixnum
(integer 1)) size
))
249 ;; M-A-O disables GC, therefore GET-LISP-OBJ-ADDRESS is safe
250 (let ((obj-addr (sb-kernel:get-lisp-obj-address obj
))
251 (array (cond ((member type
`(,sb-vm
:code-header-widetag
252 #+executable-funinstances
253 ,sb-vm
:funcallable-instance-widetag
))
254 (incf total-code-size size
)
258 ;; This is not the most efficient way to update the bit arrays,
259 ;; but the simplest and clearest for sure. (The loop could avoided
260 ;; if the current page is the same as the previously seen page)
261 (loop for index from
(sb-vm::find-page-index obj-addr
)
262 to
(sb-vm::find-page-index
(truly-the word
263 (+ (logandc2 obj-addr sb-vm
:lowtag-mask
)
265 do
(setf (sbit array index
) 1))))
267 (let ((p (position 1 (bit-and code-bits data-bits
))))
269 (format t
"~&code+data: page index ~d, generation ~D~%"
270 p
(slot (deref sb-vm
::page-table p
) 'sb-vm
::gen
))
271 (assert (zerop (slot (deref sb-vm
::page-table p
) 'sb-vm
::start
)))
272 (let ((base (+ (* p sb-vm
:gencgc-page-bytes
)
273 sb-vm
:dynamic-space-start
)))
274 ;; This mapping operation may fail if the page's first object is not at the base
275 ;; or it ends with a page-spanning object. But this diagnostic logic should
276 ;; never be invoked. If it is, you should find the cause of that rather than
277 ;; worry about this slightly dubious use of map-objects-in-range.
278 (sb-vm::map-objects-in-range
279 (lambda (obj widetag size
)
280 (declare (ignore widetag size
))
281 (format t
"~x ~s~%" (sb-kernel:get-lisp-obj-address obj
) (type-of obj
)))
282 (%make-lisp-obj base
)
283 (%make-lisp-obj
(+ base
284 (ash (slot (deref sb-vm
::page-table p
) 'sb-vm
::words-used
*)
285 sb-vm
:word-shift
)))))))
286 (assert (not (find 1 (bit-and code-bits data-bits
))))
287 (let* ((code-bytes-consumed
288 (* (count 1 code-bits
) sb-vm
:gencgc-page-bytes
))
290 (- total-code-size code-bytes-consumed
)))
291 ;; This should be true for all platforms.
292 ;; Some have as little as .5% space wasted.
293 (assert (<= waste
(* 3/100 code-bytes-consumed
))))))
295 (with-test (:name
:code
/data-separation
)
296 (compile 'ensure-code
/data-separation
)
297 (ensure-code/data-separation
))
300 (with-test (:name
:immobile-space-addr-p
)
301 ;; Upper bound should be exclusive
302 (assert (not (sb-kernel:immobile-space-addr-p
303 (+ sb-vm
:fixedobj-space-start
304 sb-vm
:fixedobj-space-size
305 sb-vm
:alien-linkage-space-size
306 sb-vm
:text-space-size
)))))
308 (with-test (:name
:unique-code-serialno
:skipped-on
:interpreter
)
309 (let ((a (make-array 100000 :element-type
'bit
:initial-element
0)))
310 (sb-vm:map-allocated-objects
311 (lambda (obj type size
)
312 (declare (ignore size
))
313 (when (and (= type sb-vm
:code-header-widetag
)
314 (plusp (sb-kernel:code-n-entries obj
)))
315 (let ((serial (sb-kernel:%code-serialno obj
)))
316 (assert (zerop (aref a serial
)))
317 (setf (aref a serial
) 1))))
320 (defun parse-address-range (line)
321 ;; I hope nothing preceding the match of "-" could be a false positive.
322 ;; If there is, I suspect we should parse the legend that contains
323 ;; "REGION TYPE START - END" to determine the column
324 ;; with a #\- which appears consistently in the same place on each following line.
325 (let ((separator (position #\- line
)))
327 (let* ((start separator
))
328 (loop (if (digit-char-p (char line
(1- start
)) 16) (decf start
) (return)))
329 (values (parse-integer line
:start start
:end separator
:radix
16)
330 (multiple-value-bind (value end
)
331 (parse-integer line
:start
(1+ separator
) :radix
16 :junk-allowed t
)
332 (assert (and (> end
(+ separator
3))
333 (or (= end
(length line
))
334 (char= (char line end
) #\space
))))
337 (defun get-shared-library-maps ()
340 (with-open-file (f "/proc/self/maps")
341 (loop (let ((line (read-line f nil
)))
342 (unless line
(return))
343 (when (and (search "r-xp" line
) (search ".so" line
))
344 (let ((p (position #\- line
)))
345 (let ((start (parse-integer line
:end p
:radix
16))
346 (end (parse-integer line
:start
(1+ p
) :radix
16
348 (push `(,start .
,end
) result
)))))))
350 (let ((p (run-program "/usr/bin/vmmap" (list (write-to-string (sb-unix:unix-getpid
)))
353 (with-open-stream (s (process-output p
))
354 (loop (let ((line (read-line s
)))
355 (when (search "regions for" line
) (return))))
356 (assert (search "REGION TYPE" (read-line s
)))
357 (loop (let ((line (read-line s
)))
358 (when (zerop (length line
)) (return))
359 ;; Look for lines that look like
360 ;; "{mumble} 7fff646c8000-7fff646ca000 {mumble}.dylib"
361 (when (search ".dylib" line
)
362 (multiple-value-bind (start end
) (parse-address-range line
)
363 (push `(,start .
,end
) result
))))))
367 ;;; Change 7143001bbe7d50c6 contained little to no rationale for why Darwin could
368 ;;; deadlock, and how adding a WITHOUT-GCING to SAP-FOREIGN-SYMBOL fixed anything.
369 ;;; Verify that it works fine while invoking GC in another thread
370 ;;; despite removal of the mysterious WITHOUT-GCING.
372 (with-test (:name
:sap-foreign-symbol-no-deadlock
373 :skipped-on
:interpreter
) ;; needlessly slow when interpreted
374 (let* ((worker-thread
375 (sb-thread:make-thread
377 (dolist (range ranges
)
378 (let ((start (car range
))
382 (loop for addr from start to end by
8
384 do
(let ((sym (sb-sys:sap-foreign-symbol
(sb-sys:int-sap addr
))))
385 (when (and sym
(string/= sym prevsym
))
387 (setq prevsym sym
))))
388 #+nil
(format t
"~x ~x: ~d~%" start end nsyms
))))
389 :arguments
(list (get-shared-library-maps))))
392 (sb-thread:make-thread
394 (loop while working do
(gc) (sleep .01))))))
395 (sb-thread:join-thread worker-thread
)
397 (sb-thread:join-thread gc-thread
)))
399 (defun use-up-thread-region ()
400 ;; cons until the thread-local allocation buffer uses up a page
402 (let* ((c (make-array 0))
403 (end (+ (sb-kernel:get-lisp-obj-address c
)
404 (- sb-vm
:other-pointer-lowtag
)
405 (* 2 sb-vm
:n-word-bytes
))))
406 (when (zerop (logand end
(1- sb-vm
:gencgc-page-bytes
)))
411 (with-test (:name
:c-call-save-p
:skipped-on
:interpreter
)
412 ;; Surely there's a better way to assert that registers get onto the stack
413 ;; (so they can be seen by GC) than by random hammering on (LIST (LIST ...)).
414 ;; This should probably be in gc-testlib.c. Or better yet: get rid of #+sb-safepoint
415 ;; for #+win32, and store the machine context the same as for #-sb-safepoint.
416 (let* ((fun (compile nil
'(lambda (a b c d e f g h i j k l m
)
417 (declare (optimize (sb-c::alien-funcall-saves-fp-and-pc
0)))
420 (alien-funcall (extern-alien "Sleep" (function void int
)) 300)
422 (alien-funcall (extern-alien "sb_nanosleep" (function void int int
)) 0 300000000)
423 (values a b c d e f g h i j k l m
))))
424 (thr (sb-thread:make-thread
(lambda ()
425 (let ((args #1=(list (LIST 'A
) (LIST 'B
) (LIST 'C
)
426 (LIST 'D
) (LIST 'E
) (LIST 'F
) (LIST 'G
)
427 (LIST 'H
) (LIST 'I
) (LIST 'J
) (LIST 'K
)
428 (LIST 'L
) (LIST 'M
))))
429 (use-up-thread-region)
432 (loop (sb-thread:barrier
(:read
))
436 (assert (equal (multiple-value-list (sb-thread:join-thread thr
)) #1#))))
439 (defun code-iterator (how)
440 (let ((n 0) (tot-bytes 0))
441 (sb-int:dx-flet
((visit (obj type size
)
442 (declare (ignore obj
))
443 (when (= type sb-vm
:code-header-widetag
)
445 (incf tot-bytes size
))))
447 (:slow
(sb-vm:map-allocated-objects
#'visit
:dynamic
))
448 (:fast
(sb-vm::walk-dynamic-space
#'visit
#x7f
3 3)))
449 (values n tot-bytes
))))
450 (compile 'code-iterator
)
452 (with-test (:name
:code-iteration-fast
453 :broken-on
:mark-region-gc
454 :skipped-on
:gc-stress
)
455 (sb-int:binding
* (((slow-n slow-bytes
) (code-iterator :slow
))
456 ((fast-n fast-bytes
) (code-iterator :fast
)))
457 ;; Fast should be 20x to 50x faster than slow, but that's kinda sensitive
458 ;; to the machine and can't be reliably asserted.
459 (assert (= slow-n fast-n
))
460 (assert (= slow-bytes fast-bytes
)))))
462 (defglobal *wp-for-signal-handler-gc-test
* nil
)
464 (with-test (:name
:signal-handler-gc-test
465 :skipped-on
(not (and :generational
:unix
:sb-thread
))
466 :broken-on
(and :arm64
:gc-stress
))
467 (sb-thread:join-thread
468 (sb-thread:make-thread
470 (let ((foo (make-symbol "hey")))
471 (setf *wp-for-signal-handler-gc-test
* (make-weak-pointer foo
))
472 (sb-sys:enable-interrupt
474 (lambda (&rest x
) (declare (ignore x
)) (constantly foo
)))))))
476 ;; If fullcgc fails to see the closure that is installed as a signal handler
477 ;; (actually a closure around a closure) then the weak pointer won't survive.
478 ;; Was broken in https://sourceforge.net/p/sbcl/sbcl/ci/04296434
479 (assert (weak-pointer-value *wp-for-signal-handler-gc-test
*)))
481 ;;; We can be certain that the marked status pertains to exactly one
482 ;;; object by ensuring that it can not share pages with other objects.
483 (defvar *vvv
* (make-array
484 (/ sb-vm
:large-object-size sb-vm
:n-word-bytes
)))
486 (with-test (:name
:page-protected-p
487 :fails-on
(or (and :big-endian
:ppc64
)
488 (and :mark-region-gc
:darwin
))
489 :broken-on
(or :x86
(and :mark-region-gc
(not :darwin
)))
490 :skipped-on
:gc-stress
)
491 (if (= (sb-kernel:generation-of
*vvv
*) 0) (gc))
492 (assert (= (sb-kernel:generation-of
*vvv
*) 1))
493 (assert (sb-kernel:page-protected-p
*vvv
*))
494 (let ((marks (sb-kernel:object-card-marks
*vvv
*)))
495 (assert (not (find 1 marks
))))
496 (setf (svref *vvv
* (/ sb-vm
:gencgc-card-bytes sb-vm
:n-word-bytes
))
498 (let ((marks (sb-kernel:object-card-marks
*vvv
*)))
499 (assert (eql (bit marks
1) 1))) ; should be marked
501 ;; Depending whether the gensym was promoted (it's now in gen1)
502 ;; the vector is or isn't marked on one of its cards.
503 (let ((marks (sb-kernel:object-card-marks
*vvv
*)))
504 (ecase (sb-kernel:generation-of
505 (svref *vvv
* (/ sb-vm
:gencgc-card-bytes sb-vm
:n-word-bytes
)))
507 (assert (eql (bit marks
1) 1))) ; should be marked
509 (assert (eql (bit marks
1) 0))))) ; should not be marked
510 (setf (svref *vvv
* (/ sb-vm
:gencgc-card-bytes sb-vm
:n-word-bytes
)) 0)
512 (let ((marks (sb-kernel:object-card-marks
*vvv
*)))
513 (assert (not (find 1 marks
)))))
515 (with-test (:name
:%shrink-vector
)
516 (let ((v (make-array 25 :initial-element
'yikes
)))
517 (sb-sys:with-pinned-objects
(v)
518 ;; Can't call VECTOR-SAP on simple-vector.
519 ;; (Honestly I don't see what purpose that limitation serves)
520 (let ((sap (sb-sys:sap
+ (sb-sys:int-sap
(sb-kernel:get-lisp-obj-address v
))
521 (- (ash sb-vm
:vector-data-offset sb-vm
:word-shift
)
522 sb-vm
:other-pointer-lowtag
))))
523 (sb-impl::%shrink-vector v
9)
524 (loop for i from
10 to
24
526 (assert (= (sb-sys:sap-ref-word sap
(ash i sb-vm
:word-shift
)))))))))
528 (with-test (:name
:rospace-strings
529 :fails-on
:darwin-jit
)
530 (let ((err (handler-case (setf (char (opaque-identity (symbol-name '*readtable
*)) 0) #\
*)
531 (sb-sys:memory-fault-error
(c)
532 (write-to-string c
:escape nil
)))))
533 (assert (search "modify a read-only object" err
))))
535 (with-test (:name
:time-measures
536 :skipped-on
(:not
(:and
(:or
:linux
:darwin
) :sb-thread
)))
537 (assert (plusp (sb-thread::thread-sum-stw-pause sb-thread
:*current-thread
*)))
538 (assert (plusp (sb-thread::thread-gc-virtual-time sb-thread
:*current-thread
*))))