Rewrite the reducing-constants.2 test
[sbcl.git] / tests / gc.impure.lisp
blobc32f06575ea83c9fbec47b701038c89bf6664f4f
1 ;;;; gc tests
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
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
8 ;;;; from CMU CL.
9 ;;;
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.
14 (in-package :cl-user)
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
19 :fails-on :win32)
20 (let ((a *weak-vect*)
21 (random-symbol (make-symbol "FRED")))
22 (flet ((x ()
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
27 (wvref a 4) 18
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)
34 (gc)
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)))
44 *weak-vect*))
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)))
58 (typecase obj
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)
65 (fill after 0)
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 ()
73 (let ((n 0))
74 (sb-vm:map-allocated-objects
75 (lambda (obj widetag size)
76 (declare (ignore obj widetag size))
77 (incf n))
78 :dynamic)
79 n))
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))
96 :gc-stress
97 :interpreter))
98 (let ((a (make-array 5)))
99 (dotimes (i (length a))
100 (setf (aref a i) (count-dynamic-space-objects))
101 (make-one-cons))
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
111 :count 1000
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))
131 (afunction
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))
141 (gc)
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)
154 (if validp
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)))
193 (gc)
194 (let ((p2 (gc-logfile)))
195 (assert (equal (truename p2) (truename p))))
196 (assert (not (setf (gc-logfile) nil)))
197 (assert (not (gc-logfile)))
198 (delete-file p)))
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*))
236 (gc :full t)
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))
245 (total-code-size 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)
255 code-bits)
257 data-bits))))
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)
264 (1- size))))
265 do (setf (sbit array index) 1))))
266 :dynamic)
267 (let ((p (position 1 (bit-and code-bits data-bits))))
268 (when p
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))
289 (waste
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))
299 #+immobile-space
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))))
318 :all)))
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)))
326 (assert separator)
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))))
335 value)))))
337 (defun get-shared-library-maps ()
338 (let (result)
339 #+linux
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
347 :junk-allowed t)))
348 (push `(,start . ,end) result)))))))
349 #+darwin
350 (let ((p (run-program "/usr/bin/vmmap" (list (write-to-string (sb-unix:unix-getpid)))
351 :output :stream
352 :wait nil)))
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))))))
364 (process-wait p))
365 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.
371 #+sb-thread
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
376 (lambda (ranges)
377 (dolist (range ranges)
378 (let ((start (car range))
379 (end (cdr range))
380 (prevsym "")
381 (nsyms 0))
382 (loop for addr from start to end by 8
383 repeat 100
384 do (let ((sym (sb-sys:sap-foreign-symbol (sb-sys:int-sap addr))))
385 (when (and sym (string/= sym prevsym))
386 (incf nsyms)
387 (setq prevsym sym))))
388 #+nil (format t "~x ~x: ~d~%" start end nsyms))))
389 :arguments (list (get-shared-library-maps))))
390 (working t)
391 (gc-thread
392 (sb-thread:make-thread
393 (lambda ()
394 (loop while working do (gc) (sleep .01))))))
395 (sb-thread:join-thread worker-thread)
396 (setq working nil)
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
401 (loop
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)))
407 (return)))))
408 (defglobal *go* nil)
410 #+sb-thread
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)))
418 (setq *go* t)
419 #+win32
420 (alien-funcall (extern-alien "Sleep" (function void int)) 300)
421 #-win32
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)
430 (apply fun
431 args))))))
432 (loop (sb-thread:barrier (:read))
433 (if *go* (return))
434 (sleep .1))
435 (gc)
436 (assert (equal (multiple-value-list (sb-thread:join-thread thr)) #1#))))
438 (progn
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)
444 (incf n)
445 (incf tot-bytes size))))
446 (ecase how
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)
463 #-win32
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
469 (lambda ()
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)))))))
475 (sb-ext:gc :gen 7)
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)))
485 (gc)
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))
497 (gensym))
498 (let ((marks (sb-kernel:object-card-marks *vvv*)))
499 (assert (eql (bit marks 1) 1))) ; should be marked
500 (gc)
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)
511 (gc)
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*))))