;;; -*- Mode:LISP; Package:REGION-BITS; Base:10; Readtable:CL -*- (export '( $$scavenge-enabled $$scavenge-disabled $$region-copy-space $$region-external-bus $$region-fixed $$region-flippable $$region-internal-memory $$region-new-space $$region-read-only $$region-read-write $$region-space-code $$region-space-cons $$region-space-free $$region-space-invalid $$region-space-structure $$region-space-unboxed cluster-region-bits encode-region-bits free-region initialize-fresh-cluster make-region read-region-bits region-copy-space region-external-bus region-external-bus? region-flippable region-read-only region-read-only? region-scavenge-enable region-scavenge-enable? region-space-type region-swapin-quantum )) ;;; Each entry in the region bits table is a Q with the bits encoded ;;; as follows. NOTE: The datatype is reserved in this table even ;;; though it is not used. This table should be considered unboxed ;;; storage. This is because it shares a region with the quantum map ;;; which is unboxed. ;;; Regions are numbered according to the cluster they begin in. ;;; Regions occupy a contiguous chunk of address space. They occupy ;;; an integral number of quanta. No quantum contains more than one ;;; region. Because there are sufficient entries in the region tables ;;; to describe all the quanta, some of the information kept there ;;; is not valid (for instance, region 2 is 7 quanta long, so there ;;; will not be a region 3, 4, 5, etc.) ;;; The region bits keep track of the following information. ;;; SWAPIN-QUANTUM is how many clusters to page in whenever a page ;;; fault is taken in this region. ;;; SCAVENGE-BIT allows the scavenger to look at this region. ;;; It should only be on for boxed storage, and then, only ;;; for copyspace regions. It could be deduced from these ;;; constraints, but this is an optimization. ;;; READ-ONLY makes all clusters in this region read-only. ;;; Writing and consing are not permitted. ;;; SPACE-TYPE describes the format of the storage in this ;;; region. ;;; FREE this entry does not belong to any region (denotes free space) ;;; INVALID this entry corresponds to a region number that is ;;; covered by another region. The code should never use ;;; this kind of entry. ;;; These entries denote valid storage, each is scavenged differently. ;;; UNBOXED This region contains unboxed storage. It cannot be scavenged ;;; or flipped, so those bits will not be set. ;;; CONS This region contains only boxed storage. The scavenge bit ;;; should be on. In addition, the transporter will treat this ;;; region as cons cells and keep pairs together. If the flip bit ;;; is on, you should only put cons cells here. Structure handles ;;; are not kept for clusters in this region. ;;; STRUCTURE This region contains boxed and unboxed storage. Every chunk ;;; of storage here will have a header. Structure handles are kept ;;; for clusters in this region. ;;; CODE This region contains executable code. The clusters in this region ;;; must be marked as read-only. If the scavenge bit is on, the scavenger ;;; will examine all CALL instructions and "move immediate 32bits boxed" ;;; instructions. ;;; ;;; NEW-SPACE prevents the transporter from consing in this region. Typically, ;;; the user will cons in NEW-SPACE and the transporter in COPYSPACE. ;;; FLIPPABLE allows the garbage collector to reclaim this region. Don't turn ;;; it on for UNBOXED regions. (defconstant %%region-bits (byte 12. 0.)) (defconstant %%region-bits-swapin-quantum (byte 4. 0.)) (defconstant %%region-bits-scavenge-bit (byte 1. 4.)) (defconstant %%region-bits-read-only (byte 1. 5.)) (defconstant %%region-bits-space-type (byte 3. 6.)) (defconstant %%region-bits-new-space (byte 1. 9.)) (defconstant %%region-bits-flippable (byte 1. 10.)) (defconstant %%region-bits-external-bus (byte 1. 11.)) ;; reserved (byte 3. 12.) (see area region bits) ;; unused (byte 10. 15.) ;; reserved %%k-data-type (defconstant $$region-internal-memory 0) (defconstant $$region-external-bus 1) (vinc::defextractor region-external-bus %%region-bits-external-bus) (vinc::defflag-extractor region-external-bus? %%region-bits-external-bus $$region-external-bus) (vinc::defextractor region-swapin-quantum %%region-bits-swapin-quantum) (defconstant $$scavenge-disabled 0.) (defconstant $$scavenge-enabled 1.) (vinc::defextractor region-scavenge-enable %%region-bits-scavenge-bit) (vinc::defflag-extractor region-scavenge-enable? %%region-bits-scavenge-bit $$scavenge-enabled) (defconstant $$region-read-write 0.) (defconstant $$region-read-only 1.) (vinc::defextractor region-read-only %%region-bits-read-only) (vinc::defflag-extractor region-read-only? %%region-bits-read-only $$region-read-only) (vinc::defextractor region-space-type %%region-bits-space-type) (defconstant $$region-space-free #b000) (defconstant $$region-space-invalid #b001) (defconstant $$region-space-unboxed #b010) (defconstant $$region-space-cons #b011) (defconstant $$region-space-structure #b100) (defconstant $$region-space-code #b101) ;; unused 6, 7 (defconstant $$region-copy-space 0) (defconstant $$region-new-space 1) (vinc::defextractor region-copy-space %%region-bits-new-space) (vinc::defflag-extractor region-copy-space? %%region-bits-new-space $$region-copy-space) (defconstant $$region-fixed 0) (defconstant $$region-flippable 1) (vinc::defextractor region-flippable %%region-bits-flippable) (vinc::defflag-extractor region-flippable? %%region-bits-flippable $$region-flippable) (defun verify-region (region) (when (not (and (quantum-map:valid-quantum? region) (= (quantum-map:quantum-region-origin region) region))) (trap::illop "Found an invalid region."))) (defsubst read-region-bits (region) (system-table-ref gr::*region-bits* region)) (defsubst write-region-bits (region value) (system-table-store gr::*region-bits* region value)) (defsubst region-valid? (region) (not (= (region-space-type (read-region-bits region)) $$region-space-invalid))) (defsubst region-free? (region) (= (region-space-type (read-region-bits region)) $$region-space-free)) (defsubst encode-region-bits (flippable new-space space-type read-only scavenge-enable external-bus swapin-quantum) (vinc::dpb-multiple-boxed flippable %%region-bits-flippable new-space %%region-bits-new-space space-type %%region-bits-space-type read-only %%region-bits-read-only scavenge-enable %%region-bits-scavenge-bit external-bus %%region-bits-external-bus swapin-quantum %%region-bits-swapin-quantum 0.)) (defun make-region (size-in-quanta region-bits volatility) ;this does not hack the physical map, altho it does verify that map show "fresh" for clusters in the region. ;the region bits are stored in the gr::*region-bits* array. (let ((quantum-origin (quantum-map:allocate-quanta size-in-quanta (= $$region-space-code (region-space-type region-bits)) volatility))) ; (trap::illop "Making region.") (labels ((verify-fresh-quantum (quantum cluster) (cond ((= cluster vinc::*clusters-in-quantum*) '()) ((not (map::fresh-cluster? (hw:dpb quantum %%quantum-number-in-cluster cluster))) (trap::illop "Make region found some unfresh clusters.")) (t (verify-fresh-quantum quantum (1+ cluster))))) (verify-fresh-quanta (count quantum) (if (zerop count) '() (progn (verify-fresh-quantum quantum 0) (verify-fresh-quanta (1- count) (1+ quantum)))))) ;; Verify that the clusters are fresh in the physical map. (verify-fresh-quanta size-in-quanta quantum-origin)) ; (trap::illop "Verified freshness.") ;; Setup the region bits in gr:*region-bits* (labels ((invalidate-region-bits (start how-many) (if (zerop how-many) '() (progn (write-region-bits start (hw:dpb $$region-space-invalid %%region-bits-space-type region-bits)) (invalidate-region-bits (1+ start) (1- how-many)))))) (invalidate-region-bits quantum-origin size-in-quanta)) ; (trap::illop "Invalidated region bits.") (write-region-bits quantum-origin (hw:ldb region-bits %%region-bits 0.)) quantum-origin)) (defun free-clusters-in-region (region cluster) (if (= cluster vinc:*clusters-in-quantum*) '() (progn (free-cluster (hw:dpb region %%quantum-number-in-cluster cluster)) (free-clusters-in-region region (1+ cluster))))) (defun zap-region-bits (region) (write-region-bits region (encode-region-bits $$region-fixed $$region-copy-space $$region-space-free $$region-read-only $$scavenge-disabled $$region-internal-memory 0.))) (defun free-region (n) ;; N is the region number to free. We scan over the quanta in this ;; region using the fact that the region number and the initial quantum ;; is the same. (verify-region n) (labels ((zap-region (n) (if (= n *number-of-regions*) '() (let ((bits (read-region-bits n))) (when (= (region-space-type bits) $$region-space-invalid) (zap-region-bits n) (free-clusters-in-region n 0) (zap-region (1+ n))))))) (zap-region-bits n) (free-clusters-in-region n 0) (zap-region (1+ n))) ;; Now toss out the quanta associated with this region. (quantum-map:deallocate-quanta n)) (defun cluster-region-bits (cluster) (read-region-bits (quantum-map:cluster-region cluster))) (defun initialize-free-cluster (va) va (trap::illop "Initialize-fresh-cluster called on cluster in free-space.")) (defun initialize-invalid-cluster (va) va (trap::illop "Initialize-fresh-cluster called on invalid region.")) (defun initialize-unboxed-cluster (va) (hw:write-md-unboxed (hw:unboxed-constant 0)) (do ((ptr (cluster->address *temporary-map-entry*) (hw:24+ 4 ptr)) (i (hw:ldb vinc:*qs-in-cluster* (byte 22. 2.) 0) (1- i))) ((zerop i) nil) (hw:vma-start-write-no-gc-trap-unboxed (hw:24+ 0 ptr)) (hw:nop) (hw:vma-start-write-no-gc-trap-unboxed (hw:24+ 1 ptr)) (hw:nop) (hw:vma-start-write-no-gc-trap-unboxed (hw:24+ 2 ptr)) (hw:nop) (hw:vma-start-write-no-gc-trap-unboxed (hw:24+ 3 ptr)))) (defun initialize-cons-cluster (va) ()) (defun initialize-structure-cluster (va) (hw:write-md-boxed nil) (do ((ptr (cluster->address *temporary-map-entry*) (hw:24+ 4 ptr)) (i (hw:ldb vinc:*qs-in-cluster* (byte 22. 2.) 0) (1- i))) ((zerop i) nil) (hw:vma-start-write-unboxed (hw:24+ 0 ptr)) (hw:nop) (hw:vma-start-write-unboxed (hw:24+ 1 ptr)) (hw:nop) (hw:vma-start-write-unboxed (hw:24+ 2 ptr)) (hw:nop) (hw:vma-start-write-unboxed (hw:24+ 3 ptr)))) (defun initialize-code-cluster (va) (hw:write-md-unboxed (hw:unboxed-constant 0)) (do ((ptr (cluster->address *temporary-map-entry*) (hw:24+ 4 ptr)) (i (hw:ldb vinc:*qs-in-cluster* (byte 22. 2.) 0) (1- i))) ((zerop i) nil) (hw:vma-start-write-no-gc-trap-unboxed (hw:24+ 0 ptr)) (hw:nop) (hw:vma-start-write-no-gc-trap-unboxed (hw:24+ 1 ptr)) (hw:nop) (hw:vma-start-write-no-gc-trap-unboxed (hw:24+ 2 ptr)) (hw:nop) (hw:vma-start-write-no-gc-trap-unboxed (hw:24+ 3 ptr)))) (defun initialize-unknown-cluster (va) (trap::illop "Initialize-fresh-cluster called on unknown data.")) (defun initialize-fresh-cluster (physical-cluster virtual-cluster region-bits) (associate-temporary virtual-cluster physical-cluster 0) (dispatch %%region-bits-space-type region-bits ($$region-space-free (initialize-free-cluster virtual-cluster)) ($$region-space-invalid (initialize-invalid-cluster virtual-cluster)) ($$region-space-unboxed (initialize-unboxed-cluster virtual-cluster)) ($$region-space-cons (initialize-cons-cluster virtual-cluster)) ($$region-space-structure (initialize-structure-cluster virtual-cluster)) ($$region-space-code (initialize-code-cluster virtual-cluster)) (t (initialize-unknown-cluster virtual-cluster))) (deassociate-temporary) )