[squeak-dev] detecting if method has an prim error code

Eliot Miranda eliot.miranda at gmail.com
Fri Feb 10 18:21:00 UTC 2012


On Fri, Feb 10, 2012 at 9:56 AM, Igor Stasenko <siguctua at gmail.com> wrote:

> Is there a simple way to detect that given method using:
>
>
> myMethod
>  <primitive: #primFoo module: #moduleBar error: errorCode>
>
> but not:
>
> myMethod
>  <primitive: #primFoo module: #moduleBar>
>
> ?
>

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>>#decompile:in:method:using: find

"skip primitive error code store if necessary"
(method primitive ~= 0 and: [self willStore]) ifTrue:
[pc := pc + 2.
 tempVars := tempVars asOrderedCollection].

...

method primitive > 0 ifTrue:
[node removeAndRenameLastTempIfErrorCode].

So (InstructionStream on: aMethod) willStore is nearly it.  However, quick
methods confuse InstructionStream, so one needs aMethod isQuick not and:
[(InstructionStream on: aMethod) willStore]

and so

(SystemNavigation new allSelect: [:m| m primitiveErrorVariableName notNil])
= (SystemNavigation new allSelect: [:m| m isQuick not and:
[(InstructionStream on: m) willStore]]) true

and

| m |
m := Alien >> #sizeFieldPut:.
{ Time millisecondsToRun: [1 to: 1000000 do: [:i| m
primitiveErrorVariableName notNil]].
Time millisecondsToRun: [1 to: 1000000 do: [:i| m isQuick not and:
[(InstructionStream on: m) willStore]]]. } #(3516 161)

If you're searching, e.g. via browseAllSelect: then you'll save time by
adding a primitive > 0 guard, so

{ [:m| m primitiveErrorVariableName notNil].
  [:m| m primitive > 0 and: [m primitiveErrorVariableName notNil]].
  [:m| m isQuick not and: [(InstructionStream on: m) willStore]].
  [:m| m primitive > 0 and: [m isQuick not and: [(InstructionStream on: m)
willStore]]] } collect:
[:b|
Time millisecondsToRun: [10 timesRepeat: [SystemNavigation new allSelect:
b]]]
 #(478 468 513 382)


> should i use a method's pragmas to see if it has
> #primitive:module:error: pragma?
>
> And if this check is ok, do i remember correctly, that temp which is
> used for storing an error is first temp in context, i.e.:
>
> err := context tempAt: 1
>
> ?
>

No, its always the last.  The first temp is reserved for the first
argument, if any.


>
> (ok i checked, it is actually always last temp), no matter if i
> declare temps before pragma or not.
>
> i.e. the order is same for:
>
> myMethod
> | a b c |
>  <primitive: #primFoo module: #moduleBar error: errorCode>
>
> and
>
> myMethod
>  <primitive: #primFoo module: #moduleBar error: errorCode>
> | a b c |
>

Right.

(*) the scheme is to have a no-op store to "store" 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.

--
> Best regards,
> Igor Stasenko.

-- 
best,
Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20120210/8f89bc71/attachment.htm


More information about the Squeak-dev mailing list