Skip to main content

SpanMeta

Struct SpanMeta 

Source
pub struct SpanMeta {
    pub class: u8,
    pub live: u16,
    pub high_water: u16,
    pub discarded: u16,
    pub retired: bool,
    /* private fields */
}
Expand description

Per-span bookkeeping. Deliberately not small: the bitmap is the price of page-granular reclaim, and it lives in the header span, which exists to be spent on exactly this.

Fields§

§class: u8

Size class this span serves, or NO_CLASS.

§live: u16

Slots handed out and not yet freed.

§high_water: u16

Slots at or above this index have never been handed out; their pages were never touched and are not resident.

§discarded: u16

Pages returned to the OS (MADV_DONTNEED). Cleared per page when an allocation lands back in one; set wholesale by Heap::retire_empty_span when the span is emptied and its pages go back together.

§retired: bool

Set when this span was emptied and handed back to the free pool, as opposed to never having been assigned at all.

Both are class == NO_CLASS, and they are opposite kinds of unassigned: one was never touched, the other was touched and then either discarded or deliberately kept. Without this bit all three collapse into one bucket, which is what they did — the identity balances the same whichever way they fall, so nothing caught it.

§Examples

The three states a span with no class can be in, and the two fields that tell them apart:

use kevy_alloc::pagemap::{ALL_PAGES_DISCARDED, NO_CLASS};

// (class, retired, discarded) -> what it is
let never_claimed = (NO_CLASS, false, 0u16);
let given_back = (NO_CLASS, true, ALL_PAGES_DISCARDED);
let held = (NO_CLASS, true, 0u16);

// All three read as "unassigned", and only `retired` plus the
// discard bitmap separate the one that was never touched from the
// one whose pages went back and the one still resident.
for (class, _, _) in [never_claimed, given_back, held] {
    assert_eq!(class, NO_CLASS);
}
assert!(!never_claimed.1);
assert_ne!(given_back.2, held.2);

Implementations§

Source§

impl SpanMeta

Source

pub fn reset(&mut self, class: u8)

Assign this span to a class, forgetting everything it held. Only legal when nothing in it is live.

Source

pub fn capacity(&self) -> u32

Slots this span can hold, given its class.

Source

pub fn alloc_slot(&mut self) -> Option<u32>

Take the lowest free slot, or None when the span is full.

Source

pub fn claim_word(&mut self) -> Option<(u8, u64)>

Claim every free bit of the lowest holed word for local handout: the bits are marked live in the bitmap (a claimed bit pins its pages exactly as a live slot does, which is what makes the claim invisible to reclaim), and the caller hands them out from its own copy without touching this header again. Returns (word_index, claimed_mask), or None when the span is full.

The far-line arithmetic this exists for: one header round-trip claims up to 64 slots, so the per-allocation touch that profiled at 17.3% of collection-write self time amortizes 64:1. Position-awareness coarsens from bit to word — the claim still takes the LOWEST holed word, so densification’s lowest-first semantics survive at word granularity.

Source

pub fn retire_word(&mut self, w: u8, unused: u64)

Return the bits of a claimed word that were never handed out (or were handed out and locally freed). The exact inverse of the claim’s marking; the hint walks back so lowest-first allocation sees the holes again.

Source

pub fn free_slot(&mut self, i: u32)

Mark slot i free.

Source

pub fn is_live(&self, i: u32) -> bool

Whether slot i is live (or parked foreign, which pins pages identically).

Source

pub fn range_has_live(&self, first: u32, last: u32) -> bool

Whether any slot in first..=last is live.

Trait Implementations§

Source§

impl Clone for SpanMeta

Source§

fn clone(&self) -> SpanMeta

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for SpanMeta

Source§

impl Debug for SpanMeta

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.