<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
span.EmailStyle19
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri",sans-serif;
        mso-fareast-language:EN-US;}
.MsoPapDefault
        {mso-style-type:export-only;
        margin-top:6.0pt;
        margin-right:0cm;
        margin-bottom:6.0pt;
        margin-left:0cm;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-GB" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal">I’m not following this in detail, but do please make sure that the results of this discussion end up in a suitable Note.  Obviously it’s not transparently clear as-is, and I can see clarity emerging<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Thanks!<o:p></o:p></p>
<p class="MsoNormal"><br>
Simon<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div style="border:none;border-left:solid blue 1.5pt;padding:0cm 0cm 0cm 4.0pt">
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal"><b><span lang="EN-US">From:</span></b><span lang="EN-US"> ghc-devs <ghc-devs-bounces@haskell.org>
<b>On Behalf Of </b>Simon Marlow<br>
<b>Sent:</b> 24 February 2020 08:22<br>
<b>To:</b> Ömer Sinan Ağacan <omeragacan@gmail.com><br>
<b>Cc:</b> ghc-devs <ghc-devs@haskell.org><br>
<b>Subject:</b> Re: Confused about PAP object layout<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
On Thu, 20 Feb 2020 at 09:21, Ömer Sinan Ağacan <<a href="mailto:omeragacan@gmail.com">omeragacan@gmail.com</a>> wrote:<o:p></o:p></p>
</div>
<div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-right:0cm">
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
> I'm not sure what you mean by "garbage". The bitmap merely determines whether<br>
> a field is a pointer,<br>
<br>
I think the bitmap is for liveness, not for whether a field is pointer or not.<br>
Relevant code for building an info table for a function:<br>
<br>
    mk_pieces (Fun arity (ArgGen arg_bits)) srt_label<br>
      = do { (liveness_lit, liveness_data) <- mkLivenessBits dflags arg_bits<br>
           ; let fun_type | null liveness_data = aRG_GEN<br>
                          | otherwise          = aRG_GEN_BIG<br>
                 extra_bits = [ packIntsCLit dflags fun_type arity ]<br>
                           ++ (if inlineSRT dflags then [] else [ srt_lit ])<br>
                           ++ [ liveness_lit, slow_entry ]<br>
           ; return (Nothing, Nothing, extra_bits, liveness_data) }<br>
<br>
This uses the word "liveness" rather than "pointers".<br>
<br>
However I just realized that the word "garbage" is still not the best way to<br>
describe what I'm trying to say. In the example<br>
<br>
    [pap_info, x, y, z]<br>
<br>
If the function's bitmap is [1, 0, 1], then `y` may be a dead (an unused<br>
argument, or "garbage" as I describe in my previous email) OR it may be a<br>
non-pointer, but used (i.e. not a garbage).<o:p></o:p></p>
</blockquote>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
I don't think we ever put a zero in the bitmap for a pointer-but-not-used argument. We don't do liveness analysis for function arguments, as far as I'm aware. So a 0 in the bitmap always means "non-pointer".<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
The only reaosn the code uses the terminology "liveness" here is that it's sharing code with the code that handles bitmaps for stack frames, which do deal with liveness.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
 <o:p></o:p></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-right:0cm">
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
So maybe "liveness" is also not the best way to describe this bitmap, as 0 does<br>
not mean dead but rather "don't follow in GC".<o:p></o:p></p>
</blockquote>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-right:0cm">
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<br>
On my quest to understand and document this code better I have one more<br>
question. When generating info tables for functions with know argument patterns<br>
(ArgSpec) we initialize the bitmap as 0. Relevant code:<br>
<br>
    mk_pieces (Fun arity (ArgSpec fun_type)) srt_label<br>
      = do { let extra_bits = packIntsCLit dflags fun_type arity : srt_label<br>
           ; return (Nothing, Nothing,  extra_bits, []) }<br>
<br>
Here the last return value is for the liveness data. I don't understand how can<br>
this be correct, because when we use this function in a PAP this will cause NOT<br>
scavenging the PAP payload. Relevant code (simplified):<br>
<br>
    STATIC_INLINE GNUC_ATTR_HOT StgPtr<br>
    scavenge_PAP_payload (StgClosure *fun, StgClosure **payload, StgWord size)<br>
    {<br>
        const StgFunInfoTable *fun_info =<br>
            get_fun_itbl(UNTAG_CONST_CLOSURE(fun));<br>
<br>
        StgPtr p = (StgPtr)payload;<br>
<br>
        StgWord bitmap;<br>
        switch (fun_info->f.fun_type) {<br>
        ...<o:p></o:p></p>
</blockquote>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-right:0cm">
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
        default:<br>
            bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);<br>
        small_bitmap:<br>
            p = scavenge_small_bitmap(p, size, bitmap);<br>
            break;<br>
        }<br>
        return p;<br>
    }<o:p></o:p></p>
</blockquote>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-right:0cm">
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<br>
Here if I have a function with three pointer args (ARG_PPP) the shown branch<br>
that will be taken, but because the bitmap is 0 (as shown in the mk_pieces code<br>
above) nothing in the PAPs payload will be scavenged.<o:p></o:p></p>
</blockquote>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
It gets the bitmap from stg_arg_bitmaps[fun_info->f.fun_type], not from the info table.  Hope this helps.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
Cheers<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
Simon<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
 <o:p></o:p></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-right:0cm">
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<br>
Here's an example from a debugging session:<br>
<br>
    >>> print pap<br>
    $10 = (StgPAP *) 0x42001fe030<br>
<br>
    >>> print *pap<br>
    $11 = {<br>
      header = {<br>
        info = 0x7fbdd1f06640 <stg_PAP_info><br>
      },<br>
      arity = 2,<br>
      n_args = 1,<br>
      fun = 0x7fbdd2d23ffb,<br>
      payload = 0x42001fe048<br>
    }<br>
<br>
So this PAP is applied one argument, which is a boxed object (a FUN_2_0):<br>
<br>
    >>> print *get_itbl(UNTAG_CLOSURE(pap->payload[0]))<br>
    $20 = {<br>
      layout = {<br>
        payload = {<br>
          ptrs = 2,<br>
          nptrs = 0<br>
        },<br>
        bitmap = 2,<br>
        large_bitmap_offset = 2,<br>
        __pad_large_bitmap_offset = 2,<br>
        selector_offset = 2<br>
      },<br>
      type = 11,<br>
      srt = 1914488,<br>
      code = 0x7fbdd2b509c0 "H\215E\370L9\370r[I\203\304 M;\245X\003"<br>
    }<br>
<br>
However if I look at the function of this PAP:<br>
<br>
    >>> print *get_fun_itbl(UNTAG_CLOSURE(pap->fun))<br>
    $21 = {<br>
      f = {<br>
        slow_apply_offset = 16,<br>
        __pad_slow_apply_offset = 3135120895,<br>
        b = {<br>
          bitmap = 74900193017889,<br>
          bitmap_offset = 258342945,<br>
          __pad_bitmap_offset = 258342945<br>
        },<br>
        fun_type = 23,<br>
        arity = 3<br>
      },<br>
      i = {<br>
        layout = {<br>
          payload = {<br>
            ptrs = 0,<br>
            nptrs = 0<br>
          },<br>
          bitmap = 0,<br>
          large_bitmap_offset = 0,<br>
          __pad_large_bitmap_offset = 0,<br>
          selector_offset = 0<br>
        },<br>
        type = 14,<br>
        srt = 1916288,<br>
        code = 0x7fbdd2b50260 <base_GHCziRead_list3_info><br>
"I\203\304(M;\245X\003"<br>
      }<br>
    }<br>
<br>
It has arity 3. Since the first argument is a boxed object and this function has<br>
arity 3, if the argument is actually live in the function (i.e. not an unused<br>
argument), then the bitmap should have a 1 for this. But because the argument<br>
pattern is known (ARG_PPP) we initialized the bitmap as 0! Not sure how this<br>
can work.<br>
<br>
What am I missing?<br>
<br>
Thanks,<br>
<br>
Ömer<br>
<br>
Ben Gamari <<a href="mailto:ben@smart-cactus.org" target="_blank">ben@smart-cactus.org</a>>, 14 Şub 2020 Cum, 20:25 tarihinde şunu yazdı:<br>
><br>
> Ömer Sinan Ağacan <<a href="mailto:omeragacan@gmail.com" target="_blank">omeragacan@gmail.com</a>> writes:<br>
><br>
> > I think that makes sense, with the invariant that n_args <= bitmap_size. We<br>
> > evacuate the arguments used by the function but not others. Thanks.<br>
> ><br>
> > It's somewhat weird to see an object with useful stuff, then garbage, then<br>
> > useful stuff again in the heap, but that's not an issue by itself. For example<br>
> > if I have something like<br>
> ><br>
> >     [pap_info, x, y, z]<br>
> ><br>
> > and according to the function `y` is dead, then after evacuating I get<br>
> ><br>
> >     [pap_info, x, <garbage>, z]<br>
> ><br>
> > This "garbage" is evacuated again and again every time we evacuate this PAP.<br>
> ><br>
> I'm not sure what you mean by "garbage". The bitmap merely determines<br>
> whether a field is a pointer, not whether it is copied during<br>
> evacuation. A field's bitmap bit not being set merely means that we won't<br>
> evacuate the value of that field during scavenging.<br>
><br>
> Nevertheless, this all deserves a comment in scavenge_PAP.<br>
><br>
> Cheers,<br>
><br>
> - Ben<br>
><o:p></o:p></p>
</blockquote>
</div>
</div>
</div>
</div>
</body>
</html>