<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2017-03-15 14:23 GMT+01:00 Ben Coman <span dir="ltr"><<a target="_blank" href="mailto:btc@openinworld.com">btc@openinworld.com</a>></span>:<br><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote"> <br><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Mar 14, 2017 at 11:46 PM, Eliot Miranda <span dir="ltr"><<a target="_blank" href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>></span> wrote:<br><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote"> <br><div dir="ltr">Hi Esteban, Hi Igor, Hi All,<div class="gmail_extra"><br><div class="gmail_quote">On Fri, Mar 10, 2017 at 7:35 AM, Esteban Lorenzano <span dir="ltr"><<a target="_blank" href="mailto:estebanlm@gmail.com">estebanlm@gmail.com</a>></span> wrote:<br><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote"><br>
Hi,<br>
<br>
I’m tumbling into an error in Pharo, because we use callbacks intensively, in Athens(cairo)-to-World conversion in particular, and people is sending always their crash reports… we made the whole conversion a lot more robust since problems started to arise, but now I hit a wall I cannot solve: I think problem is in something in callbacks.<br>
<br>
And problem is showing very easy on 64bits (while in 32bits it takes time and is more random).<br></blockquote><div><br></div><div> I responded in the "image not opening" thread, but it's the same problem.  I really want to hear what y'all think because I'll happily implement a fix, but I want to know which one y'all think is a good idea.  Here's my reply (edits between [ & ] to add information):</div><div><br></div><div><br></div><div>On Mon, Mar 13, 2017 at 9:11 PM, Eliot Miranda <span dir="ltr"><<a target="_blank" href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.c<wbr>om</a>></span> wrote:<br></div><div><br></div><div><div style="color:rgb(0,0,0);font-size:14px">I'm pretty confident [I know] this is to do with bugs in the Athens surface code which assumes that callbacks can be made in the existing copyBits and warpBits primitive.  They can't do this safely because a GC (scavenge) can happen during a callback, which then causes chaos when the copyBits primitive tries to access objects that have been moved under its feet.</div><div style="color:rgb(0,0,0);font-size:14px"><br></div><div style="color:rgb(0,0,0);font-size:14px">I've done work to fix callbacks so that when there is a failure it is the copyBits primitive that fails, instead of apparently the callback return primitive.  One of the apparent effects of this fix is to stop the screen opening up too small; another is getting the background colour right, and yet another is eliminating bogus pixels in the VGTigerDemo demo.  But more work is required to fix the copyBits and warpBits primitives.  There are a few approaches one might take:</div><div style="color:rgb(0,0,0);font-size:14px"><br></div><div style="color:rgb(0,0,0);font-size:14px">a)  fixing the primitive so that it saves and restores oops around the callbacks using the external oop table [InterpreterProxy>>addGCRoot: & removeGCRoot:].  That's a pain but possible. [It's a pain because all the derived pointers (the start of the destForm, sourceForm, halftoneForm and colorMapTable) must be recomputed also, and of course most of the time the objects don't move; we only scavenge about once every 2 seconds in normal running]</div><div style="color:rgb(0,0,0);font-size:14px"><br></div><div style="color:rgb(0,0,0);font-size:14px">b) fixing the primitive so that it pins the objects it needs before ever invoking a callback [this is a pain because pinning an object causes it to be tenured to old space if it is in new space; objects can't be pinned in new space, so instead the pin operation forwards the new space object to an old space copy if required and answers its location in old space, so a putative withPinnedObjectsDo: operation for the copyBits primitive looks like</div><div style="color:rgb(0,0,0);font-size:14px"><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">          </span>withPinnedFormsDo: aBlock</div><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                 </span><inline: #always></div><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                   </span>self cppIf: SPURVM & false</div><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                            </span>ifTrue:</div><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                                   </span>[| bitBltOopWasPinned destWasPinned sourceWasPinned halftoneWasPinned |</div><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                                   </span> (bitBltOopWasPinned := interpreterProxy isPinned: bitBltOop) ifFalse:</div><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                                          </span>[bitBltOop := interpreterProxy pinObject: bitBltOop].</div><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                                   </span> (destWasPinned := interpreterProxy isPinned: destForm) ifFalse:</div><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                                          </span>[destForm := interpreterProxy pinObject: destForm].</div><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                                       </span> (sourceWasPinned := interpreterProxy isPinned: sourceForm) ifFalse:</div><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                                              </span>[sourceForm := interpreterProxy pinObject: sourceForm].</div><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                                   </span> (halftoneWasPinned := interpreterProxy isPinned: halftoneForm) ifFalse:</div><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                                          </span>[halftoneForm := interpreterProxy pinObject: halftoneForm].</div><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                                       </span> aBlock value.</div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                                       </span> bitBltOopWasPinned ifFalse: [interpreterProxy unpinObject: bitBltOop].<div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                                    </span> destWasPinned ifFalse: [interpreterProxy unpinObject: destForm].</div><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                                 </span> sourceWasPinned ifFalse: [interpreterProxy unpinObject: sourceForm].</div><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                                     </span> halftoneWasPinned ifFalse: [interpreterProxy unpinObject: halftoneForm]]</div><div><span style="white-space:pre-wrap" class="gmail-m_6637499196065563500m_4214313850272847920gmail-Apple-tab-span">                         </span>ifFalse: [aBlock value]</div><div>   and tenuring objects to old space is not ideal because they are only collected by a full GC, so doing this would at least tenure the bitBltOop which is very likely to be in new space]</div></div><div style="color:rgb(0,0,0);font-size:14px"><br></div><div style="color:rgb(0,0,0);font-size:14px">c) fixing the primitive so that it uses the scavenge and fullGC counters in the VM to detect if a GC occurred during one of the callbacks and would fail the primitive [if it detected that a GC had occurred in any of the surface functions].   The primitive would then simply be retried. </div><div style="color:rgb(0,0,0);font-size:14px"><br></div><div style="color:rgb(0,0,0);font-size:14px">d) ?</div></div></div></div></div></blockquote><div><br></div><div>d) A question and idea in ignorance of Cario infrastructure...</div><div>Do these surfaces persist in the Image after it is saved&quitted?</div></div></div></div></blockquote><div><br></div><div>No<br></div><div> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>Why not allocate surface memory on the C heap so that GC won't move it?</div></div></div></div></blockquote><div><br></div><div>It is not the surface that moves. And the surface memory is on the heap, that is why we need a surface plugin  to actually work with that data.<br>It is the Form-Object that moves. If the Forms instance variable "bits" does not hold a (byte)array with pixeldata, but non-smalltalk integer value, the BitBlt will access the image data<br></div><div>by calling the  surface plugin (cairo). The problem is, or the callgraph is:<br><br></div><div>primitive copy bits<br></div><div>-> get source form (ObjectPointer)<br></div><div>-> get dest form (ObjectPointer)<br></div><div>-> get form (image) format<br></div><div>   -> get bits-field (if integer -> call surfaceplugin for surface format [1] / if object pointer -> get format from the Form-Object)<br></div><div>-> get image data<br> -> get bits-field [2] (if integer -> call surfaceplugin for surface data  / if object pointer -> get data from Form-Object)<br><br></div><div>The problem is, if [1] calls a callback that can trigger the GC, and the object pointer and hence the bits-field for [2] is not valid anymore.<br><br><br></div><div><br><br></div><div> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><br></div><div>cheers -ben</div><br></div></div></div>
<br></blockquote></div><br></div></div>