Skip to content

Spur (Image) Memory Layout

j4yk edited this page May 17, 2015 · 7 revisions

Since Spur is not only the new object header and image format, but also the new memory manager in Cog, some additional memory constraints come with it.

The first objects in the heap (at "oldSpaceStart" and thus the first ones in the image) are nil, false and true. After those, there comes the "freeListObj" and after that the "hiddenRootsObj".

The hiddenRootsObj is interesting because its first pointer points to the first page of the class table, which maps class hashes/indexes to class oops. Each class table page has 1024 slots (the class table minor index is 10 bits wide) and there are 2^12 table pages (the remaining 12 of the total 22 class index bits). The first 2^12 slots of the hiddenRootsObj point to those pages, although nil is a valid and common value for each but the first of these references when there are significantly less than 4 mil. classes.

SpurBootstrap allocates the first class index page immediately following the hiddenRootsObj. (SpurBootstrap>>allocateClassTable) The first classes in the first page are SmallInteger and Character. (SpurBootstrap>>fillInClassTable). The first page is reserved for known classes. (SpurMemoryManager>>enterIntoClassTable:, SpurMemoryManager class>>initializeCompactClassIndices, SpurBootstrap>>defineKnownClassIndices)

For the implementation of Spur image synthesis (via tracing or otherwise), SpurMemoryManager>>initializeObjectMemory:, its callees and assertions are highly relevant.

(source: SpurMemoryManager class comments and code)

Memory Segments and Bridges

In Spur, at runtime there can be multiple segments of memory, which need not be contiguous. To make the gaps between these segments transparent to the memory manager, pinned (non-GC-moveable) bridge objects are "put into the gaps". The size of these bridge objects is exactly the size of the gap in the address space between two segments. Only the header of a bridge is actually stored in a segment. Therefore, the last two header words (16 bytes, in case the gap "has more than 255 slots") of each segment are reserved for the bridge. When the object memory is saved into an image, the gaps between segments are removed and the bridge header is reused to store the information necessary to restore the correct pointers. The first 8 bytes of the bridge header store the bridge span, i.e. the size of the former memory gap. The second 8 bytes store the size of the following segment (so the image reader can easily navigate to the next segment end), or zero if no further segment follows. When the image is read, all segments are combined into a single segment and the pointers must be rectified ("swizzling"). In each segment, the sum of the preceding bridge header sizes (16 bytes each) and bridge spans must be subtracted in addition to the usual offset computed from the old base address in the image header.

Clone this wiki locally