
Ömer Sinan Ağacan
I'm not sure what you mean by "garbage". The bitmap merely determines whether a field is a pointer,
I think the bitmap is for liveness, not for whether a field is pointer or not. Relevant code for building an info table for a function:
mk_pieces (Fun arity (ArgGen arg_bits)) srt_label = do { (liveness_lit, liveness_data) <- mkLivenessBits dflags arg_bits ; let fun_type | null liveness_data = aRG_GEN | otherwise = aRG_GEN_BIG extra_bits = [ packIntsCLit dflags fun_type arity ] ++ (if inlineSRT dflags then [] else [ srt_lit ]) ++ [ liveness_lit, slow_entry ] ; return (Nothing, Nothing, extra_bits, liveness_data) }
This uses the word "liveness" rather than "pointers".
However I just realized that the word "garbage" is still not the best way to describe what I'm trying to say. In the example
[pap_info, x, y, z]
If the function's bitmap is [1, 0, 1], then `y` may be a dead (an unused argument, or "garbage" as I describe in my previous email) OR it may be a non-pointer, but used (i.e. not a garbage).
So maybe "liveness" is also not the best way to describe this bitmap, as 0 does not mean dead but rather "don't follow in GC".
This is indeed my understanding; "not live" in this context really just means "not a pointer traced by the GC". I agree that "liveness" is a poor word for it. This is briefly described in a comment in includes/rts/storage/InfoTables.h.
On my quest to understand and document this code better I have one more question. When generating info tables for functions with known argument patterns (ArgSpec) we initialize the bitmap as 0. Relevant code:
mk_pieces (Fun arity (ArgSpec fun_type)) srt_label = do { let extra_bits = packIntsCLit dflags fun_type arity : srt_label ; return (Nothing, Nothing, extra_bits, []) }
Here the last return value is for the liveness data. I don't understand how can this be correct, because when we use this function in a PAP this will cause NOT scavenging the PAP payload. Relevant code (simplified):
STATIC_INLINE GNUC_ATTR_HOT StgPtr scavenge_PAP_payload (StgClosure *fun, StgClosure **payload, StgWord size) { const StgFunInfoTable *fun_info = get_fun_itbl(UNTAG_CONST_CLOSURE(fun));
StgPtr p = (StgPtr)payload;
StgWord bitmap; switch (fun_info->f.fun_type) { ... default: bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]); small_bitmap: p = scavenge_small_bitmap(p, size, bitmap); break; } return p; }
Here if I have a function with three pointer args (ARG_PPP) the shown branch that will be taken, but because the bitmap is 0 (as shown in the mk_pieces code above) nothing in the PAPs payload will be scavenged.
Here's an example from a debugging session:
>>> print pap $10 = (StgPAP *) 0x42001fe030
>>> print *pap $11 = { header = { info = 0x7fbdd1f06640
}, arity = 2, n_args = 1, fun = 0x7fbdd2d23ffb, payload = 0x42001fe048 } So this PAP is applied one argument, which is a boxed object (a FUN_2_0):
>>> print *get_itbl(UNTAG_CLOSURE(pap->payload[0])) $20 = { layout = { payload = { ptrs = 2, nptrs = 0 }, bitmap = 2, large_bitmap_offset = 2, __pad_large_bitmap_offset = 2, selector_offset = 2 }, type = 11, srt = 1914488, code = 0x7fbdd2b509c0 "H\215E\370L9\370r[I\203\304 M;\245X\003" }
However if I look at the function of this PAP:
>>> print *get_fun_itbl(UNTAG_CLOSURE(pap->fun)) $21 = { f = { slow_apply_offset = 16, __pad_slow_apply_offset = 3135120895, b = { bitmap = 74900193017889, bitmap_offset = 258342945, __pad_bitmap_offset = 258342945 }, fun_type = 23, arity = 3 }, i = { layout = { payload = { ptrs = 0, nptrs = 0 }, bitmap = 0, large_bitmap_offset = 0, __pad_large_bitmap_offset = 0, selector_offset = 0 }, type = 14, srt = 1916288, code = 0x7fbdd2b50260
"I\203\304(M;\245X\003" } } It has arity 3. Since the first argument is a boxed object and this function has arity 3, if the argument is actually live in the function (i.e. not an unused argument), then the bitmap should have a 1 for this. But because the argument pattern is known (ARG_PPP) we initialized the bitmap as 0! Not sure how this can work.
What am I missing?
Note that the meaning of the bit values in the bitmap are slightly surprising: 0 is pointer, 1 is non-pointer. Consequently, a bitmap of 0 means all fields are pointers. Does this explain the confusion? Cheers, - Ben