detecting if method has an prim error code

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

detecting if method has an prim error code

Igor Stasenko
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>

?

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

?

(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 |




--
Best regards,
Igor Stasenko.

Reply | Threaded
Open this post in threaded view
|

Re: detecting if method has an prim error code

Eliot Miranda-2


On Fri, Feb 10, 2012 at 9:56 AM, Igor Stasenko <[hidden email]> 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



Reply | Threaded
Open this post in threaded view
|

Re: detecting if method has an prim error code

Igor Stasenko
On 10 February 2012 19:21, Eliot Miranda <[hidden email]> wrote:

>
>
> On Fri, Feb 10, 2012 at 9:56 AM, Igor Stasenko <[hidden email]> 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)
>

No, i just writing a common handler for errors.
In my case, in NativeBoost many  methods using same primitive, in a
form that you can do it like:

myMethod
<primitive: #primitiveNativeCall module: #.. error: errorcode>

CommonErrorHandler handleError


like that i need to extract error code from a context state (a context
which is sender of #handleError), not from parameter which user should
always pass directly..
because forcing users to also pass the error code producing a lot of
extra code, which not necessary since i can access this stuff via
reflection.
Apparently, for making it work, first i need to know if primitive uses
that form of pragma or not, and then read the error code at right
place,
and of course i don't really care if it fast or quick or not :)

Thanks for clearing the fog :) Just wanted to know if i do it right.

>>
>> 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
>
>
>
>



--
Best regards,
Igor Stasenko.