|
jam 0.0.1
A compacting generational garbage collector for C++26
|
native::simd<ptr<T>, N, A> stores actual pointer subobjects. Put the vector in a manifest and its lanes are traced and forwarded in place. native::wide<V, K> visits each register. Numeric vectors remain ordinary data. Both can be complete heap records or embedded members.
Pointer vectors offer lane access, typed load/store, raw encoded offsets via to_native(), and lane-wise ==/!= against vectors or null. Assignments and stores obey the old-to-young barrier.
gather is a free function found through ADL. Pass a mask when several reads should share a null check; omit it to use nodes != nullptr.
Here a and b are live pointers in the current heap. Selected lanes must be nonnull and valid. Inactive lanes are not accessed and return zero or null. Gathering a pointer field says nothing about whether that child is nonnull.
The wide overload forms all register masks before gathering. An explicit native::wide<mask_type, K> can be supplied as the third argument. Lane and register order are preserved.
Single, nonvirtual inheritance is supported, including classes with virtual functions. For lanes of ptr<Derived>, an inherited &Base::field is converted to the corresponding Derived member pointer before its displacement is used. This is a fixed offset, not a virtual call or a per-lane layout lookup. SIMD and wide overloads accept the same inherited member syntax.
Fields can be 32/64-bit integers, float, double or ptr<U>, provided native supports the result shape. Wider fields may require fewer lanes; wide lets you retain a larger batch. The ISA tag selects the implementation at compile time. Call it from a kernel compiled for that ISA and admitted on the current CPU.
AVX2 and AVX512 use masked gathers; baseline and NEON read active lanes individually. On x86, the generation bit divides the mask between two bases. The remaining 31-bit index is scaled by eight. Clang's flat member-pointer ABI supplies the field displacement: Itanium on Unix, flat MS on Windows. Extended MS representations are rejected. Finding the displacement neither fabricates an object nor extracts the active mask.
External vectors and gathered pointers become stale across collection, just like scalar ptrs. Root a heap-resident vector and obtain a fresh copy afterward.