<br><br><div class="gmail_quote">On Thu, Mar 31, 2011 at 6:11 AM, Javier Pimás <span dir="ltr">&lt;<a href="mailto:elpochodelagente@gmail.com">elpochodelagente@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Hi, we are having a problem with callbacks in alien and we would like to see if we are doing something wrong or if it is a bug in the implementation (for the standard old vm).<div><br></div><div>We are receiving the callback just in the middle of a primitiveExternalCall (actually to a function that will fail because the plugin is not present, but i don&#39;t think that&#39;s important). We pinned it to occur always in the same line, which is </div>


<div><br></div><div><div><span style="white-space:pre-wrap">        </span>longAtput((lit + (BASE_HEADER_SIZE)) + (2 &lt;&lt; (SHIFT_FOR_WORD)), ConstZero);</div></div><div><br></div><div>of primitiveExternalCall. When the callback occurs, the thunkEntry is called, which if we understand correctly, saves the active context and runs the interpreter by calling sendInvokeCallbackStackRegistersJmpbuf. The problem is that things like messageSelector and lkupClass, which are global variables are not saved while saving the context, and when the callback returns, the last line of primitiveExternalCall,</div>


<div><br></div><div><div><span style="white-space:pre-wrap">                </span>rewriteMethodCacheSelclassprimIndex(messageSelector, lkupClass, 0);</div>

</div><div><br></div><div>puts a 0 in the wrong place. Also, probably as las message sent was primReturnFromContext:through: (because we just returned from the context), we get a primitiveFailed, but not for the original called function but for primReturnFromContext:through:.</div>


<div><br></div><div>What do you think? are we missing something?</div></blockquote><div><br></div><div>Hmmm, looking at it I think you must be taking a callback before the external call occurs.  Here&#39;s how the code reads in Cog:</div>
<div><br></div><div><br></div><div><span class="Apple-tab-span" style="white-space: pre; ">        </span>...</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>addr := self ioLoadExternalFunction: functionName + BaseHeaderSize</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>OfLength: functionLength</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>FromModule: moduleName + BaseHeaderSize</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>OfLength: moduleLength.</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>addr = 0</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [index := -1]</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifFalse: [&quot;add the function to the external primitive table&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>index := self addToExternalPrimitiveTable: addr].</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>&quot;Store the index (or -1 if failure) back in the literal&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>objectMemory storePointerUnchecked: 3 ofObject: lit withValue: (objectMemory integerObjectOf: index).</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>&quot;If the function has been successfully loaded cache and call it&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>index &gt;= 0</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue:</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>[self rewriteMethodCacheEntryForExternalPrimitiveToFunction: (self cCode: [addr] inSmalltalk: [1000 + index]).</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>self callExternalPrimitive: addr]</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifFalse: [&quot;Otherwise void the primitive function and fail&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>self rewriteMethodCacheEntryForExternalPrimitiveToFunction: 0.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>^self primitiveFailFor: PrimErrNotFound]</div>
<div><br></div><div>So the rewrite to zero (self rewriteMethodCacheEntryForExternalPrimitiveToFunction: 0) isn&#39;t done if no callout is made.  Where is your callback comming from?  Looks like its comming from the internals of things like ioLoadExternalFunction...</div>
<div><br></div><div>It is hard to save and restore all the VM state around a callback.  There&#39;s too much of it in the current VM design.  Take a look at rewriteMethodCacheEntryForExternalPrimitiveToFunction:.  It is written to be fast, using lastMethodCacheProbeWrite to avoid work in rewriting the cache entry if the module and/or function load fails.  That&#39;s state one doesn&#39;t want to have to save and restore around callbacks along with lkupClass, messageSelector.  primitiveFunctionPointer, newMethod, framePointer, instructionPointer and stackPointer are already a lot.  Tthis needs more thought.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div><br></div><div>Regards,</div><div>            Javier.</div><div><br></div><font color="#888888"><div>
<br></div><div><div>-- <br>Javier Pimás<br>Ciudad de Buenos Aires<br>


</div></div>
</font></blockquote></div><br>