<br><br><div class="gmail_quote">On Fri, Feb 10, 2012 at 9:56 AM, Igor Stasenko <span dir="ltr">&lt;<a href="mailto:siguctua@gmail.com">siguctua@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">
Is there a simple way to detect that given method using:<br>
<br>
<br>
myMethod<br>
 &lt;primitive: #primFoo module: #moduleBar error: errorCode&gt;<br>
<br>
but not:<br>
<br>
myMethod<br>
 &lt;primitive: #primFoo module: #moduleBar&gt;<br>
<br>
?<br></blockquote><div><br></div><div>Yes.  The first bytecode of a method that contains a primitive error code will be a temp store bytecode, storing the stack top to the error code (*).  e.g. in Decompiler&gt;&gt;#decompile:in:method:using: find</div>
<div> </div><div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>&quot;skip primitive error code store if necessary&quot;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>(method primitive ~= 0 and: [self willStore]) ifTrue:</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>[pc := pc + 2.</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span> tempVars := tempVars asOrderedCollection].</div></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>method primitive &gt; 0 ifTrue:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>[node removeAndRenameLastTempIfErrorCode].</div>
<div><br></div><div><span class="Apple-style-span">So (InstructionStream on: aMethod) willStore is nearly it.  However, quick methods confuse InstructionStream, so one needs </span>aMethod<span class="Apple-style-span"> isQuick not and: [(InstructionStream on: </span>aMethod<span class="Apple-style-span">) willStore]</span></div>
<div><span class="Apple-style-span"><br></span></div><div><span class="Apple-style-span">and so</span></div><div><span class="Apple-style-span"><br></span></div><div><span class="Apple-style-span">(SystemNavigation new allSelect: [:m| m primitiveErrorVariableName notNil]) = (SystemNavigation new allSelect: [:m| m isQuick not and: [(InstructionStream on: m) willStore]]) true</span></div>
<div><br></div><div>and</div><div><div><br></div><div>| m |</div><div>m := Alien &gt;&gt; #sizeFieldPut:.</div><div>{ Time millisecondsToRun: [1 to: 1000000 do: [:i| m primitiveErrorVariableName notNil]].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>Time millisecondsToRun: [1 to: 1000000 do: [:i| m isQuick not and: [(InstructionStream on: m) willStore]]]. } #(3516 161)</div>
</div><div><br></div><div>If you&#39;re searching, e.g. via browseAllSelect: then you&#39;ll save time by adding a primitive &gt; 0 guard, so</div><div><br></div><div><div><div>{ [:m| m primitiveErrorVariableName notNil].</div>
<div>  [:m| m primitive &gt; 0 and: [m primitiveErrorVariableName notNil]].</div><div>  [:m| m isQuick not and: [(InstructionStream on: m) willStore]].</div><div>  [:m| m primitive &gt; 0 and: [m isQuick not and: [(InstructionStream on: m) willStore]]] } collect:</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>[:b|</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>Time millisecondsToRun: [10 timesRepeat: [SystemNavigation new allSelect: b]]]</div>
<div> #(478 468 513 382)</div></div></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
should i use a method&#39;s pragmas to see if it has<br>
#primitive:module:error: pragma?<br>
<br>
And if this check is ok, do i remember correctly, that temp which is<br>
used for storing an error is first temp in context, i.e.:<br>
<br>
err := context tempAt: 1<br>
<br>
?<br></blockquote><div><br></div><div>No, its always the last.  The first temp is reserved for the first argument, if any.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<br>
(ok i checked, it is actually always last temp), no matter if i<br>
declare temps before pragma or not.<br>
<br>
i.e. the order is same for:<br>
<br>
myMethod<br>
| a b c |<br>
 &lt;primitive: #primFoo module: #moduleBar error: errorCode&gt;<br>
<br>
and<br>
<br>
myMethod<br>
 &lt;primitive: #primFoo module: #moduleBar error: errorCode&gt;<br>
| a b c |<br></blockquote><div><br></div><div>Right.</div><div><br></div><div>(*) the scheme is to have a no-op store to &quot;store&quot; the error code.  The store is always a store of the stack top to the last temp, but on entry to a method the stack top *is* the last temp.  So on old VMs this store has no effect, and on new VMs the store is taken as an indication that the last temp holds the primitive error code and that on failing a primitive the error code should be stored into the last temp.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><font color="#888888">--<br>
Best regards,<br>
Igor Stasenko.</font></blockquote></div>-- <br>best,<div>Eliot</div><br>