1 //! Definitions for bits in the in-memory / in-table representation of references. 2 3 /// An "initialized bit" in a funcref table. 4 /// 5 /// We lazily initialize tables of funcrefs, and this mechanism 6 /// requires us to interpret zero as "uninitialized", triggering a 7 /// slowpath on table read to possibly initialize the element. (This 8 /// has to be *zero* because that is the only value we can cheaply 9 /// initialize, e.g. with newly mmap'd memory.) 10 /// 11 /// However, the user can also store a null reference into a table. We 12 /// have to interpret this as "actually null", and not "lazily 13 /// initialize to the original funcref that this slot had". 14 /// 15 /// To do so, we rewrite nulls into the "initialized null" value. Note 16 /// that this should *only exist inside the table*: whenever we load a 17 /// value out of a table, we immediately mask off the low bit that 18 /// contains the initialized-null flag. Conversely, when we store into 19 /// a table, we have to translate a true null into an "initialized 20 /// null". 21 /// 22 /// We can generalize a bit in order to simply the table-set logic: we 23 /// can set the LSB of *all* explicitly stored values to 1 in order to 24 /// note that they are indeed explicitly stored. We then mask off this 25 /// bit every time we load. 26 /// 27 /// Note that we take care to set this bit and mask it off when 28 /// accessing tables directly in fastpaths in generated code as well. 29 pub const FUNCREF_INIT_BIT: usize = 1; 30 31 /// The mask we apply to all refs loaded from funcref tables. 32 /// 33 /// This allows us to use the LSB as an "initialized flag" (see below) 34 /// to distinguish from an uninitialized element in a 35 /// lazily-initialized funcref table. 36 pub const FUNCREF_MASK: usize = !FUNCREF_INIT_BIT; 37