runtime compiled method optimizations

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

runtime compiled method optimizations

Rob Withers
Hi all,

I have a simple method containing an ifTrue: message.  I have  
compiled it normally, which uses macro transformations:

17 <10> pushTemp: 0
18 <9B> jumpFalse: 23
19 <10> pushTemp: 0
20 <20> pushConstant: 4
21 <B0> send: +
22 <7C> returnTop
23 <78> returnSelf

and I have compiled it using Klaus Witzel's nifty compiler changes to  
remove macro transformations and the result is an explicit message  
send of #ifTrue:

21 <10> pushTemp: 0
22 <89> pushThisContext:
23 <75> pushConstant: 0
24 <C8> send: blockCopy:
25 <A4 04> jumpTo: 31
27 <10> pushTemp: 0
28 <21> pushConstant: 4
29 <B0> send: +
30 <7C> returnTop
31 <E0> send: ifTrue:
32 <87> pop
33 <78> returnSelf

I would like to check the receiver of the ifTrue:, the 1st method arg  
in this case (Temp: 0), to see if a certain situation exists (is it a  
local reference to an object?).  If it is true, I would like to run  
the optimal code from the first example, instead of the longer second  
example.   How could we do that?  Something like this?  Could it be  
done entirely by the compiler, given the existence of the bytecode  
routine for #testLocalReference?

21 <10> pushTemp: 0
22 <??> testLocalReference
23 <??> jumpFalse: 30
24 <10> pushTemp: 0
25 <??> jumpFalse: 40
26 <10> pushTemp: 0
27 <20> pushConstant: 4
28 <B0> send: +
29 <7C> returnTop
30 <89> pushThisContext:
31 <75> pushConstant: 0
32 <C8> send: blockCopy:
33 <?? ??> jumpTo: 38
34 <10> pushTemp: 0
35 <21> pushConstant: 4
36 <B0> send: +
37 <7C> returnTop
38 <E0> send: ifTrue:
39 <87> pop
40 <78> returnSelf


Thanks!
Rob


Reply | Threaded
Open this post in threaded view
|

Re: runtime compiled method optimizations

Igor Stasenko
No, i think you'd better change the implementation of #jumpFalse bytecode.
If you see that receiver is non-local , then simply do message send.
And, i think you can safely use info from jump bytecode to extract
block contents
(bytes 19 - 22 is the block body).

On 19/10/2007, Robert Withers <[hidden email]> wrote:

> Hi all,
>
> I have a simple method containing an ifTrue: message.  I have
> compiled it normally, which uses macro transformations:
>
> 17 <10> pushTemp: 0
> 18 <9B> jumpFalse: 23
> 19 <10> pushTemp: 0
> 20 <20> pushConstant: 4
> 21 <B0> send: +
> 22 <7C> returnTop
> 23 <78> returnSelf
>
> and I have compiled it using Klaus Witzel's nifty compiler changes to
> remove macro transformations and the result is an explicit message
> send of #ifTrue:
>
> 21 <10> pushTemp: 0
> 22 <89> pushThisContext:
> 23 <75> pushConstant: 0
> 24 <C8> send: blockCopy:
> 25 <A4 04> jumpTo: 31
> 27 <10> pushTemp: 0
> 28 <21> pushConstant: 4
> 29 <B0> send: +
> 30 <7C> returnTop
> 31 <E0> send: ifTrue:
> 32 <87> pop
> 33 <78> returnSelf
>
> I would like to check the receiver of the ifTrue:, the 1st method arg
> in this case (Temp: 0), to see if a certain situation exists (is it a
> local reference to an object?).  If it is true, I would like to run
> the optimal code from the first example, instead of the longer second
> example.   How could we do that?  Something like this?  Could it be
> done entirely by the compiler, given the existence of the bytecode
> routine for #testLocalReference?
>
> 21 <10> pushTemp: 0
> 22 <??> testLocalReference
> 23 <??> jumpFalse: 30
> 24 <10> pushTemp: 0
> 25 <??> jumpFalse: 40
> 26 <10> pushTemp: 0
> 27 <20> pushConstant: 4
> 28 <B0> send: +
> 29 <7C> returnTop
> 30 <89> pushThisContext:
> 31 <75> pushConstant: 0
> 32 <C8> send: blockCopy:
> 33 <?? ??> jumpTo: 38
> 34 <10> pushTemp: 0
> 35 <21> pushConstant: 4
> 36 <B0> send: +
> 37 <7C> returnTop
> 38 <E0> send: ifTrue:
> 39 <87> pop
> 40 <78> returnSelf
>
>
> Thanks!
> Rob
>
>
>


--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: runtime compiled method optimizations

Rob Withers
In reply to this post by Rob Withers
Igor, I'm afraid you've lost me.  What would the bytecodes look like in your
proposal?  From what you've said, wouldn't the #jumpFalse need to know what
the literal to send is?  I also don't understand how it would extract the
block contents.

thanks,
Rob


----- Original Message -----
From: "Igor Stasenko" <[hidden email]>
To: "The general-purpose Squeak developers list"
<[hidden email]>
Sent: Thursday, October 18, 2007 3:06 PM
Subject: Re: runtime compiled method optimizations


> No, i think you'd better change the implementation of #jumpFalse
> bytecode.
> If you see that receiver is non-local , then simply do message send.
> And, i think you can safely use info from jump bytecode to extract
> block contents
> (bytes 19 - 22 is the block body).
>
> On 19/10/2007, Robert Withers <[hidden email]> wrote:
>> Hi all,
>>
>> I have a simple method containing an ifTrue: message.  I have
>> compiled it normally, which uses macro transformations:
>>
>> 17 <10> pushTemp: 0
>> 18 <9B> jumpFalse: 23
>> 19 <10> pushTemp: 0
>> 20 <20> pushConstant: 4
>> 21 <B0> send: +
>> 22 <7C> returnTop
>> 23 <78> returnSelf
>>
>> and I have compiled it using Klaus Witzel's nifty compiler changes to
>> remove macro transformations and the result is an explicit message
>> send of #ifTrue:
>>
>> 21 <10> pushTemp: 0
>> 22 <89> pushThisContext:
>> 23 <75> pushConstant: 0
>> 24 <C8> send: blockCopy:
>> 25 <A4 04> jumpTo: 31
>> 27 <10> pushTemp: 0
>> 28 <21> pushConstant: 4
>> 29 <B0> send: +
>> 30 <7C> returnTop
>> 31 <E0> send: ifTrue:
>> 32 <87> pop
>> 33 <78> returnSelf
>>
>> I would like to check the receiver of the ifTrue:, the 1st method arg
>> in this case (Temp: 0), to see if a certain situation exists (is it a
>> local reference to an object?).  If it is true, I would like to run
>> the optimal code from the first example, instead of the longer second
>> example.   How could we do that?  Something like this?  Could it be
>> done entirely by the compiler, given the existence of the bytecode
>> routine for #testLocalReference?
>>
>> 21 <10> pushTemp: 0
>> 22 <??> testLocalReference
>> 23 <??> jumpFalse: 30
>> 24 <10> pushTemp: 0
>> 25 <??> jumpFalse: 40
>> 26 <10> pushTemp: 0
>> 27 <20> pushConstant: 4
>> 28 <B0> send: +
>> 29 <7C> returnTop
>> 30 <89> pushThisContext:
>> 31 <75> pushConstant: 0
>> 32 <C8> send: blockCopy:
>> 33 <?? ??> jumpTo: 38
>> 34 <10> pushTemp: 0
>> 35 <21> pushConstant: 4
>> 36 <B0> send: +
>> 37 <7C> returnTop
>> 38 <E0> send: ifTrue:
>> 39 <87> pop
>> 40 <78> returnSelf
>>
>>
>> Thanks!
>> Rob
>>
>>
>>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>
>


Reply | Threaded
Open this post in threaded view
|

Re: runtime compiled method optimizations

Igor Stasenko
On 19/10/2007, Rob Withers <[hidden email]> wrote:
> Igor, I'm afraid you've lost me.  What would the bytecodes look like in your
> proposal?  From what you've said, wouldn't the #jumpFalse need to know what
> the literal to send is?  I also don't understand how it would extract the
> block contents.

You don't need to change bytecode. Just by analysing that jump
bytecode jumps over a block. Then you can assume that bytes between
jump bytecode and byte where it points to is the block body.
So, you can do the trick by changing implementation of #jumpFalse.
By sending #IfTrue: message to receiver and checking the result.

>
> thanks,
> Rob
>
>
> ----- Original Message -----
> From: "Igor Stasenko" <[hidden email]>
> To: "The general-purpose Squeak developers list"
> <[hidden email]>
> Sent: Thursday, October 18, 2007 3:06 PM
> Subject: Re: runtime compiled method optimizations
>
>
> > No, i think you'd better change the implementation of #jumpFalse
> > bytecode.
> > If you see that receiver is non-local , then simply do message send.
> > And, i think you can safely use info from jump bytecode to extract
> > block contents
> > (bytes 19 - 22 is the block body).
> >
> > On 19/10/2007, Robert Withers <[hidden email]> wrote:
> >> Hi all,
> >>
> >> I have a simple method containing an ifTrue: message.  I have
> >> compiled it normally, which uses macro transformations:
> >>
> >> 17 <10> pushTemp: 0
> >> 18 <9B> jumpFalse: 23
> >> 19 <10> pushTemp: 0
> >> 20 <20> pushConstant: 4
> >> 21 <B0> send: +
> >> 22 <7C> returnTop
> >> 23 <78> returnSelf
> >>
> >> and I have compiled it using Klaus Witzel's nifty compiler changes to
> >> remove macro transformations and the result is an explicit message
> >> send of #ifTrue:
> >>
> >> 21 <10> pushTemp: 0
> >> 22 <89> pushThisContext:
> >> 23 <75> pushConstant: 0
> >> 24 <C8> send: blockCopy:
> >> 25 <A4 04> jumpTo: 31
> >> 27 <10> pushTemp: 0
> >> 28 <21> pushConstant: 4
> >> 29 <B0> send: +
> >> 30 <7C> returnTop
> >> 31 <E0> send: ifTrue:
> >> 32 <87> pop
> >> 33 <78> returnSelf
> >>
> >> I would like to check the receiver of the ifTrue:, the 1st method arg
> >> in this case (Temp: 0), to see if a certain situation exists (is it a
> >> local reference to an object?).  If it is true, I would like to run
> >> the optimal code from the first example, instead of the longer second
> >> example.   How could we do that?  Something like this?  Could it be
> >> done entirely by the compiler, given the existence of the bytecode
> >> routine for #testLocalReference?
> >>
> >> 21 <10> pushTemp: 0
> >> 22 <??> testLocalReference
> >> 23 <??> jumpFalse: 30
> >> 24 <10> pushTemp: 0
> >> 25 <??> jumpFalse: 40
> >> 26 <10> pushTemp: 0
> >> 27 <20> pushConstant: 4
> >> 28 <B0> send: +
> >> 29 <7C> returnTop
> >> 30 <89> pushThisContext:
> >> 31 <75> pushConstant: 0
> >> 32 <C8> send: blockCopy:
> >> 33 <?? ??> jumpTo: 38
> >> 34 <10> pushTemp: 0
> >> 35 <21> pushConstant: 4
> >> 36 <B0> send: +
> >> 37 <7C> returnTop
> >> 38 <E0> send: ifTrue:
> >> 39 <87> pop
> >> 40 <78> returnSelf
> >>
> >>
> >> Thanks!
> >> Rob
> >>
> >>
> >>
> >
> >
> > --
> > Best regards,
> > Igor Stasenko AKA sig.
> >
> >
>
>
>


--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: runtime compiled method optimizations

Rob Withers

----- Original Message -----
From: "Igor Stasenko" <[hidden email]>
To: "The general-purpose Squeak developers list"
<[hidden email]>
Sent: Thursday, October 18, 2007 11:58 PM
Subject: Re: runtime compiled method optimizations


> On 19/10/2007, Rob Withers <[hidden email]> wrote:
>> Igor, I'm afraid you've lost me.  What would the bytecodes look like in
>> your
>> proposal?  From what you've said, wouldn't the #jumpFalse need to know
>> what
>> the literal to send is?  I also don't understand how it would extract the
>> block contents.
>
> You don't need to change bytecode. Just by analysing that jump
> bytecode jumps over a block. Then you can assume that bytes between
> jump bytecode and byte where it points to is the block body.
> So, you can do the trick by changing implementation of #jumpFalse.
> By sending #IfTrue: message to receiver and checking the result.

I'm still not getting it.  I am all about getting this functionality in the
most compact form.  Are you saying that I should stick to the following
bytecodes?

17 <10> pushTemp: 0
18 <9B> jumpFalse: 23
19 <10> pushTemp: 0
20 <20> pushConstant: 4
21 <B0> send: +
22 <7C> returnTop
23 <78> returnSelf

Then if I am reading you right, the block is defined as
    PC start of block := the PC of the jumpFalse: + 1
    PC end of block := the PC of the arg to the jumpBlock - 1
but I don't see where you setup and send the #blockCopy:

I believe, but I am not sure, the #jumpFalse: is not only used for #ifTrue:,
ifFalse:. ifTrue:ifFalse: and #ifFalse:ifTrue:, plus I want to be able to
distinguish between these 4 methods.  Unless they all get transformed to
#ifTrue:ifFalse: with appropriate nil blocks...

Still, I am having a hard time understanding how #jumpFalse: suddenly knows
to test for boolean (better than the testLocalReference), then if it is not
boolean, instead of sending mustBeBoolean, do a couple of block copies and
send #ifTrue:ifFalse:.  Can it do all that?  Can we have it scan the
bytecodes of the current method to make decisions about the boundaries of
the block copies?  Are we sure it should always send #ifTrue:ifFalse:?  You
raise some interesting questions.

Rob

>
>>
>> thanks,
>> Rob
>>
>>
>> ----- Original Message -----
>> From: "Igor Stasenko" <[hidden email]>
>> To: "The general-purpose Squeak developers list"
>> <[hidden email]>
>> Sent: Thursday, October 18, 2007 3:06 PM
>> Subject: Re: runtime compiled method optimizations
>>
>>
>> > No, i think you'd better change the implementation of #jumpFalse
>> > bytecode.
>> > If you see that receiver is non-local , then simply do message send.
>> > And, i think you can safely use info from jump bytecode to extract
>> > block contents
>> > (bytes 19 - 22 is the block body).
>> >
>> > On 19/10/2007, Robert Withers <[hidden email]> wrote:
>> >> Hi all,
>> >>
>> >> I have a simple method containing an ifTrue: message.  I have
>> >> compiled it normally, which uses macro transformations:
>> >>
>> >> 17 <10> pushTemp: 0
>> >> 18 <9B> jumpFalse: 23
>> >> 19 <10> pushTemp: 0
>> >> 20 <20> pushConstant: 4
>> >> 21 <B0> send: +
>> >> 22 <7C> returnTop
>> >> 23 <78> returnSelf
>> >>
>> >> and I have compiled it using Klaus Witzel's nifty compiler changes to
>> >> remove macro transformations and the result is an explicit message
>> >> send of #ifTrue:
>> >>
>> >> 21 <10> pushTemp: 0
>> >> 22 <89> pushThisContext:
>> >> 23 <75> pushConstant: 0
>> >> 24 <C8> send: blockCopy:
>> >> 25 <A4 04> jumpTo: 31
>> >> 27 <10> pushTemp: 0
>> >> 28 <21> pushConstant: 4
>> >> 29 <B0> send: +
>> >> 30 <7C> returnTop
>> >> 31 <E0> send: ifTrue:
>> >> 32 <87> pop
>> >> 33 <78> returnSelf
>> >>
>> >> I would like to check the receiver of the ifTrue:, the 1st method arg
>> >> in this case (Temp: 0), to see if a certain situation exists (is it a
>> >> local reference to an object?).  If it is true, I would like to run
>> >> the optimal code from the first example, instead of the longer second
>> >> example.   How could we do that?  Something like this?  Could it be
>> >> done entirely by the compiler, given the existence of the bytecode
>> >> routine for #testLocalReference?
>> >>
>> >> 21 <10> pushTemp: 0
>> >> 22 <??> testLocalReference
>> >> 23 <??> jumpFalse: 30
>> >> 24 <10> pushTemp: 0
>> >> 25 <??> jumpFalse: 40
>> >> 26 <10> pushTemp: 0
>> >> 27 <20> pushConstant: 4
>> >> 28 <B0> send: +
>> >> 29 <7C> returnTop
>> >> 30 <89> pushThisContext:
>> >> 31 <75> pushConstant: 0
>> >> 32 <C8> send: blockCopy:
>> >> 33 <?? ??> jumpTo: 38
>> >> 34 <10> pushTemp: 0
>> >> 35 <21> pushConstant: 4
>> >> 36 <B0> send: +
>> >> 37 <7C> returnTop
>> >> 38 <E0> send: ifTrue:
>> >> 39 <87> pop
>> >> 40 <78> returnSelf
>> >>
>> >>
>> >> Thanks!
>> >> Rob
>> >>
>> >>
>> >>
>> >
>> >
>> > --
>> > Best regards,
>> > Igor Stasenko AKA sig.
>> >
>> >
>>
>>
>>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>
>


Reply | Threaded
Open this post in threaded view
|

Re: runtime compiled method optimizations

Nicolas Cellier-3
You will also have backward jumps generated by loops (to:do: whileTrue:
whileFalse:)...

Though you might be able to transform all these jumps in equivalent
message send (See Decompiler), that's might be impracticle to do that at
interpreter level.


Rob Withers a écrit :

>
> ----- Original Message ----- From: "Igor Stasenko" <[hidden email]>
> To: "The general-purpose Squeak developers list"
> <[hidden email]>
> Sent: Thursday, October 18, 2007 11:58 PM
> Subject: Re: runtime compiled method optimizations
>
>
>> On 19/10/2007, Rob Withers <[hidden email]> wrote:
>>> Igor, I'm afraid you've lost me.  What would the bytecodes look like
>>> in your
>>> proposal?  From what you've said, wouldn't the #jumpFalse need to
>>> know what
>>> the literal to send is?  I also don't understand how it would extract
>>> the
>>> block contents.
>>
>> You don't need to change bytecode. Just by analysing that jump
>> bytecode jumps over a block. Then you can assume that bytes between
>> jump bytecode and byte where it points to is the block body.
>> So, you can do the trick by changing implementation of #jumpFalse.
>> By sending #IfTrue: message to receiver and checking the result.
>
> I'm still not getting it.  I am all about getting this functionality in
> the most compact form.  Are you saying that I should stick to the
> following bytecodes?
>
> 17 <10> pushTemp: 0
> 18 <9B> jumpFalse: 23
> 19 <10> pushTemp: 0
> 20 <20> pushConstant: 4
> 21 <B0> send: +
> 22 <7C> returnTop
> 23 <78> returnSelf
>
> Then if I am reading you right, the block is defined as
>    PC start of block := the PC of the jumpFalse: + 1
>    PC end of block := the PC of the arg to the jumpBlock - 1
> but I don't see where you setup and send the #blockCopy:
>
> I believe, but I am not sure, the #jumpFalse: is not only used for
> #ifTrue:, ifFalse:. ifTrue:ifFalse: and #ifFalse:ifTrue:, plus I want to
> be able to distinguish between these 4 methods.  Unless they all get
> transformed to #ifTrue:ifFalse: with appropriate nil blocks...
>
> Still, I am having a hard time understanding how #jumpFalse: suddenly
> knows to test for boolean (better than the testLocalReference), then if
> it is not boolean, instead of sending mustBeBoolean, do a couple of
> block copies and send #ifTrue:ifFalse:.  Can it do all that?  Can we
> have it scan the bytecodes of the current method to make decisions about
> the boundaries of the block copies?  Are we sure it should always send
> #ifTrue:ifFalse:?  You raise some interesting questions.
>
> Rob
>
>>
>>>
>>> thanks,
>>> Rob
>>>
>>>
>>> ----- Original Message -----
>>> From: "Igor Stasenko" <[hidden email]>
>>> To: "The general-purpose Squeak developers list"
>>> <[hidden email]>
>>> Sent: Thursday, October 18, 2007 3:06 PM
>>> Subject: Re: runtime compiled method optimizations
>>>
>>>
>>> > No, i think you'd better change the implementation of #jumpFalse
>>> > bytecode.
>>> > If you see that receiver is non-local , then simply do message send.
>>> > And, i think you can safely use info from jump bytecode to extract
>>> > block contents
>>> > (bytes 19 - 22 is the block body).
>>> >
>>> > On 19/10/2007, Robert Withers <[hidden email]> wrote:
>>> >> Hi all,
>>> >>
>>> >> I have a simple method containing an ifTrue: message.  I have
>>> >> compiled it normally, which uses macro transformations:
>>> >>
>>> >> 17 <10> pushTemp: 0
>>> >> 18 <9B> jumpFalse: 23
>>> >> 19 <10> pushTemp: 0
>>> >> 20 <20> pushConstant: 4
>>> >> 21 <B0> send: +
>>> >> 22 <7C> returnTop
>>> >> 23 <78> returnSelf
>>> >>
>>> >> and I have compiled it using Klaus Witzel's nifty compiler changes to
>>> >> remove macro transformations and the result is an explicit message
>>> >> send of #ifTrue:
>>> >>
>>> >> 21 <10> pushTemp: 0
>>> >> 22 <89> pushThisContext:
>>> >> 23 <75> pushConstant: 0
>>> >> 24 <C8> send: blockCopy:
>>> >> 25 <A4 04> jumpTo: 31
>>> >> 27 <10> pushTemp: 0
>>> >> 28 <21> pushConstant: 4
>>> >> 29 <B0> send: +
>>> >> 30 <7C> returnTop
>>> >> 31 <E0> send: ifTrue:
>>> >> 32 <87> pop
>>> >> 33 <78> returnSelf
>>> >>
>>> >> I would like to check the receiver of the ifTrue:, the 1st method arg
>>> >> in this case (Temp: 0), to see if a certain situation exists (is it a
>>> >> local reference to an object?).  If it is true, I would like to run
>>> >> the optimal code from the first example, instead of the longer second
>>> >> example.   How could we do that?  Something like this?  Could it be
>>> >> done entirely by the compiler, given the existence of the bytecode
>>> >> routine for #testLocalReference?
>>> >>
>>> >> 21 <10> pushTemp: 0
>>> >> 22 <??> testLocalReference
>>> >> 23 <??> jumpFalse: 30
>>> >> 24 <10> pushTemp: 0
>>> >> 25 <??> jumpFalse: 40
>>> >> 26 <10> pushTemp: 0
>>> >> 27 <20> pushConstant: 4
>>> >> 28 <B0> send: +
>>> >> 29 <7C> returnTop
>>> >> 30 <89> pushThisContext:
>>> >> 31 <75> pushConstant: 0
>>> >> 32 <C8> send: blockCopy:
>>> >> 33 <?? ??> jumpTo: 38
>>> >> 34 <10> pushTemp: 0
>>> >> 35 <21> pushConstant: 4
>>> >> 36 <B0> send: +
>>> >> 37 <7C> returnTop
>>> >> 38 <E0> send: ifTrue:
>>> >> 39 <87> pop
>>> >> 40 <78> returnSelf
>>> >>
>>> >>
>>> >> Thanks!
>>> >> Rob
>>> >>
>>> >>
>>> >>
>>> >
>>> >
>>> > --
>>> > Best regards,
>>> > Igor Stasenko AKA sig.
>>> >
>>> >
>>>
>>>
>>>
>>
>>
>> --
>> Best regards,
>> Igor Stasenko AKA sig.
>>
>>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: runtime compiled method optimizations

Rob Withers
That's it, the backward jumps use jumpFalse: and jumpTrue:.  It rings a
bell.

I am trying to transform these jumps to equivalent msg sends, only when the
receiver is not the expected type.  This way, the normal fast transform
works most of the time and when it is the wrong receiver we get a msg send
in the image that I can intercept.  The best of both worlds.  Unfortunately
it more than doubles the bytecodes for these composite constructs, so I'd
love to figure out the most compact forms.

Perhaps the way to go is to define bytecodes for all combinations like
    jumpFalseForIfTrue:
    jumpFalseForIfFalse:
    jumpFalseForIfTrueIfFalse:
    jumpFalseForWhileFalse:
    jumpTrueForWhileTrue:
    jumpFalseForToDo:
and so on.  Then I would need to figure out how to capture the blocks.

Rob

----- Original Message -----
From: "nicolas cellier" <[hidden email]>
To: <[hidden email]>
Sent: Friday, October 19, 2007 12:17 PM
Subject: Re: runtime compiled method optimizations


> You will also have backward jumps generated by loops (to:do: whileTrue:
> whileFalse:)...
>
> Though you might be able to transform all these jumps in equivalent
> message send (See Decompiler), that's might be impracticle to do that at
> interpreter level.
>
>
> Rob Withers a écrit :
>>
>> ----- Original Message ----- From: "Igor Stasenko" <[hidden email]>
>> To: "The general-purpose Squeak developers list"
>> <[hidden email]>
>> Sent: Thursday, October 18, 2007 11:58 PM
>> Subject: Re: runtime compiled method optimizations
>>
>>
>>> On 19/10/2007, Rob Withers <[hidden email]> wrote:
>>>> Igor, I'm afraid you've lost me.  What would the bytecodes look like in
>>>> your
>>>> proposal?  From what you've said, wouldn't the #jumpFalse need to know
>>>> what
>>>> the literal to send is?  I also don't understand how it would extract
>>>> the
>>>> block contents.
>>>
>>> You don't need to change bytecode. Just by analysing that jump
>>> bytecode jumps over a block. Then you can assume that bytes between
>>> jump bytecode and byte where it points to is the block body.
>>> So, you can do the trick by changing implementation of #jumpFalse.
>>> By sending #IfTrue: message to receiver and checking the result.
>>
>> I'm still not getting it.  I am all about getting this functionality in
>> the most compact form.  Are you saying that I should stick to the
>> following bytecodes?
>>
>> 17 <10> pushTemp: 0
>> 18 <9B> jumpFalse: 23
>> 19 <10> pushTemp: 0
>> 20 <20> pushConstant: 4
>> 21 <B0> send: +
>> 22 <7C> returnTop
>> 23 <78> returnSelf
>>
>> Then if I am reading you right, the block is defined as
>>    PC start of block := the PC of the jumpFalse: + 1
>>    PC end of block := the PC of the arg to the jumpBlock - 1
>> but I don't see where you setup and send the #blockCopy:
>>
>> I believe, but I am not sure, the #jumpFalse: is not only used for
>> #ifTrue:, ifFalse:. ifTrue:ifFalse: and #ifFalse:ifTrue:, plus I want to
>> be able to distinguish between these 4 methods.  Unless they all get
>> transformed to #ifTrue:ifFalse: with appropriate nil blocks...
>>
>> Still, I am having a hard time understanding how #jumpFalse: suddenly
>> knows to test for boolean (better than the testLocalReference), then if
>> it is not boolean, instead of sending mustBeBoolean, do a couple of block
>> copies and send #ifTrue:ifFalse:.  Can it do all that?  Can we have it
>> scan the bytecodes of the current method to make decisions about the
>> boundaries of the block copies?  Are we sure it should always send
>> #ifTrue:ifFalse:?  You raise some interesting questions.
>>
>> Rob
>>
>>>
>>>>
>>>> thanks,
>>>> Rob
>>>>
>>>>
>>>> ----- Original Message -----
>>>> From: "Igor Stasenko" <[hidden email]>
>>>> To: "The general-purpose Squeak developers list"
>>>> <[hidden email]>
>>>> Sent: Thursday, October 18, 2007 3:06 PM
>>>> Subject: Re: runtime compiled method optimizations
>>>>
>>>>
>>>> > No, i think you'd better change the implementation of #jumpFalse
>>>> > bytecode.
>>>> > If you see that receiver is non-local , then simply do message send.
>>>> > And, i think you can safely use info from jump bytecode to extract
>>>> > block contents
>>>> > (bytes 19 - 22 is the block body).
>>>> >
>>>> > On 19/10/2007, Robert Withers <[hidden email]> wrote:
>>>> >> Hi all,
>>>> >>
>>>> >> I have a simple method containing an ifTrue: message.  I have
>>>> >> compiled it normally, which uses macro transformations:
>>>> >>
>>>> >> 17 <10> pushTemp: 0
>>>> >> 18 <9B> jumpFalse: 23
>>>> >> 19 <10> pushTemp: 0
>>>> >> 20 <20> pushConstant: 4
>>>> >> 21 <B0> send: +
>>>> >> 22 <7C> returnTop
>>>> >> 23 <78> returnSelf
>>>> >>
>>>> >> and I have compiled it using Klaus Witzel's nifty compiler changes
>>>> >> to
>>>> >> remove macro transformations and the result is an explicit message
>>>> >> send of #ifTrue:
>>>> >>
>>>> >> 21 <10> pushTemp: 0
>>>> >> 22 <89> pushThisContext:
>>>> >> 23 <75> pushConstant: 0
>>>> >> 24 <C8> send: blockCopy:
>>>> >> 25 <A4 04> jumpTo: 31
>>>> >> 27 <10> pushTemp: 0
>>>> >> 28 <21> pushConstant: 4
>>>> >> 29 <B0> send: +
>>>> >> 30 <7C> returnTop
>>>> >> 31 <E0> send: ifTrue:
>>>> >> 32 <87> pop
>>>> >> 33 <78> returnSelf
>>>> >>
>>>> >> I would like to check the receiver of the ifTrue:, the 1st method
>>>> >> arg
>>>> >> in this case (Temp: 0), to see if a certain situation exists (is it
>>>> >> a
>>>> >> local reference to an object?).  If it is true, I would like to run
>>>> >> the optimal code from the first example, instead of the longer
>>>> >> second
>>>> >> example.   How could we do that?  Something like this?  Could it be
>>>> >> done entirely by the compiler, given the existence of the bytecode
>>>> >> routine for #testLocalReference?
>>>> >>
>>>> >> 21 <10> pushTemp: 0
>>>> >> 22 <??> testLocalReference
>>>> >> 23 <??> jumpFalse: 30
>>>> >> 24 <10> pushTemp: 0
>>>> >> 25 <??> jumpFalse: 40
>>>> >> 26 <10> pushTemp: 0
>>>> >> 27 <20> pushConstant: 4
>>>> >> 28 <B0> send: +
>>>> >> 29 <7C> returnTop
>>>> >> 30 <89> pushThisContext:
>>>> >> 31 <75> pushConstant: 0
>>>> >> 32 <C8> send: blockCopy:
>>>> >> 33 <?? ??> jumpTo: 38
>>>> >> 34 <10> pushTemp: 0
>>>> >> 35 <21> pushConstant: 4
>>>> >> 36 <B0> send: +
>>>> >> 37 <7C> returnTop
>>>> >> 38 <E0> send: ifTrue:
>>>> >> 39 <87> pop
>>>> >> 40 <78> returnSelf
>>>> >>
>>>> >>
>>>> >> Thanks!
>>>> >> Rob
>>>> >>
>>>> >>
>>>> >>
>>>> >
>>>> >
>>>> > --
>>>> > Best regards,
>>>> > Igor Stasenko AKA sig.
>>>> >
>>>> >
>>>>
>>>>
>>>>
>>>
>>>
>>> --
>>> Best regards,
>>> Igor Stasenko AKA sig.
>>>
>>>
>>
>>
>>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: runtime compiled method optimizations

Mathieu SUEN
But you can do somethings like:


exp isLocalReference ifTrue:[exp perform: #ifTrue:ifFalse: with: ...  
with: ....] ifFalse: [...]


        Mth



On Oct 19, 2007, at 9:32 PM, Rob Withers wrote:

> That's it, the backward jumps use jumpFalse: and jumpTrue:.  It  
> rings a bell.
>
> I am trying to transform these jumps to equivalent msg sends, only  
> when the receiver is not the expected type.  This way, the normal  
> fast transform works most of the time and when it is the wrong  
> receiver we get a msg send in the image that I can intercept.  The  
> best of both worlds.  Unfortunately it more than doubles the  
> bytecodes for these composite constructs, so I'd love to figure out  
> the most compact forms.
>
> Perhaps the way to go is to define bytecodes for all combinations like
>    jumpFalseForIfTrue:
>    jumpFalseForIfFalse:
>    jumpFalseForIfTrueIfFalse:
>    jumpFalseForWhileFalse:
>    jumpTrueForWhileTrue:
>    jumpFalseForToDo:
> and so on.  Then I would need to figure out how to capture the blocks.
>
> Rob
>
> ----- Original Message ----- From: "nicolas cellier"  
> <[hidden email]>
> To: <[hidden email]>
> Sent: Friday, October 19, 2007 12:17 PM
> Subject: Re: runtime compiled method optimizations
>
>
>> You will also have backward jumps generated by loops (to:do:  
>> whileTrue: whileFalse:)...
>>
>> Though you might be able to transform all these jumps in  
>> equivalent message send (See Decompiler), that's might be  
>> impracticle to do that at interpreter level.
>>
>>
>> Rob Withers a écrit :
>>>
>>> ----- Original Message ----- From: "Igor Stasenko"  
>>> <[hidden email]>
>>> To: "The general-purpose Squeak developers list" <squeak-
>>> [hidden email]>
>>> Sent: Thursday, October 18, 2007 11:58 PM
>>> Subject: Re: runtime compiled method optimizations
>>>
>>>
>>>> On 19/10/2007, Rob Withers <[hidden email]> wrote:
>>>>> Igor, I'm afraid you've lost me.  What would the bytecodes look  
>>>>> like in your
>>>>> proposal?  From what you've said, wouldn't the #jumpFalse need  
>>>>> to know what
>>>>> the literal to send is?  I also don't understand how it would  
>>>>> extract the
>>>>> block contents.
>>>>
>>>> You don't need to change bytecode. Just by analysing that jump
>>>> bytecode jumps over a block. Then you can assume that bytes between
>>>> jump bytecode and byte where it points to is the block body.
>>>> So, you can do the trick by changing implementation of #jumpFalse.
>>>> By sending #IfTrue: message to receiver and checking the result.
>>>
>>> I'm still not getting it.  I am all about getting this  
>>> functionality in the most compact form.  Are you saying that I  
>>> should stick to the following bytecodes?
>>>
>>> 17 <10> pushTemp: 0
>>> 18 <9B> jumpFalse: 23
>>> 19 <10> pushTemp: 0
>>> 20 <20> pushConstant: 4
>>> 21 <B0> send: +
>>> 22 <7C> returnTop
>>> 23 <78> returnSelf
>>>
>>> Then if I am reading you right, the block is defined as
>>>    PC start of block := the PC of the jumpFalse: + 1
>>>    PC end of block := the PC of the arg to the jumpBlock - 1
>>> but I don't see where you setup and send the #blockCopy:
>>>
>>> I believe, but I am not sure, the #jumpFalse: is not only used  
>>> for #ifTrue:, ifFalse:. ifTrue:ifFalse: and #ifFalse:ifTrue:,  
>>> plus I want to be able to distinguish between these 4 methods.  
>>> Unless they all get transformed to #ifTrue:ifFalse: with  
>>> appropriate nil blocks...
>>>
>>> Still, I am having a hard time understanding how #jumpFalse:  
>>> suddenly knows to test for boolean (better than the  
>>> testLocalReference), then if it is not boolean, instead of  
>>> sending mustBeBoolean, do a couple of block copies and send  
>>> #ifTrue:ifFalse:.  Can it do all that?  Can we have it scan the  
>>> bytecodes of the current method to make decisions about the  
>>> boundaries of the block copies?  Are we sure it should always  
>>> send #ifTrue:ifFalse:?  You raise some interesting questions.
>>>
>>> Rob
>>>
>>>>
>>>>>
>>>>> thanks,
>>>>> Rob
>>>>>
>>>>>
>>>>> ----- Original Message -----
>>>>> From: "Igor Stasenko" <[hidden email]>
>>>>> To: "The general-purpose Squeak developers list"
>>>>> <[hidden email]>
>>>>> Sent: Thursday, October 18, 2007 3:06 PM
>>>>> Subject: Re: runtime compiled method optimizations
>>>>>
>>>>>
>>>>> > No, i think you'd better change the implementation of #jumpFalse
>>>>> > bytecode.
>>>>> > If you see that receiver is non-local , then simply do  
>>>>> message send.
>>>>> > And, i think you can safely use info from jump bytecode to  
>>>>> extract
>>>>> > block contents
>>>>> > (bytes 19 - 22 is the block body).
>>>>> >
>>>>> > On 19/10/2007, Robert Withers <[hidden email]> wrote:
>>>>> >> Hi all,
>>>>> >>
>>>>> >> I have a simple method containing an ifTrue: message.  I have
>>>>> >> compiled it normally, which uses macro transformations:
>>>>> >>
>>>>> >> 17 <10> pushTemp: 0
>>>>> >> 18 <9B> jumpFalse: 23
>>>>> >> 19 <10> pushTemp: 0
>>>>> >> 20 <20> pushConstant: 4
>>>>> >> 21 <B0> send: +
>>>>> >> 22 <7C> returnTop
>>>>> >> 23 <78> returnSelf
>>>>> >>
>>>>> >> and I have compiled it using Klaus Witzel's nifty compiler  
>>>>> changes >> to
>>>>> >> remove macro transformations and the result is an explicit  
>>>>> message
>>>>> >> send of #ifTrue:
>>>>> >>
>>>>> >> 21 <10> pushTemp: 0
>>>>> >> 22 <89> pushThisContext:
>>>>> >> 23 <75> pushConstant: 0
>>>>> >> 24 <C8> send: blockCopy:
>>>>> >> 25 <A4 04> jumpTo: 31
>>>>> >> 27 <10> pushTemp: 0
>>>>> >> 28 <21> pushConstant: 4
>>>>> >> 29 <B0> send: +
>>>>> >> 30 <7C> returnTop
>>>>> >> 31 <E0> send: ifTrue:
>>>>> >> 32 <87> pop
>>>>> >> 33 <78> returnSelf
>>>>> >>
>>>>> >> I would like to check the receiver of the ifTrue:, the 1st  
>>>>> method >> arg
>>>>> >> in this case (Temp: 0), to see if a certain situation exists  
>>>>> (is it >> a
>>>>> >> local reference to an object?).  If it is true, I would like  
>>>>> to run
>>>>> >> the optimal code from the first example, instead of the  
>>>>> longer >> second
>>>>> >> example.   How could we do that?  Something like this?  
>>>>> Could it be
>>>>> >> done entirely by the compiler, given the existence of the  
>>>>> bytecode
>>>>> >> routine for #testLocalReference?
>>>>> >>
>>>>> >> 21 <10> pushTemp: 0
>>>>> >> 22 <??> testLocalReference
>>>>> >> 23 <??> jumpFalse: 30
>>>>> >> 24 <10> pushTemp: 0
>>>>> >> 25 <??> jumpFalse: 40
>>>>> >> 26 <10> pushTemp: 0
>>>>> >> 27 <20> pushConstant: 4
>>>>> >> 28 <B0> send: +
>>>>> >> 29 <7C> returnTop
>>>>> >> 30 <89> pushThisContext:
>>>>> >> 31 <75> pushConstant: 0
>>>>> >> 32 <C8> send: blockCopy:
>>>>> >> 33 <?? ??> jumpTo: 38
>>>>> >> 34 <10> pushTemp: 0
>>>>> >> 35 <21> pushConstant: 4
>>>>> >> 36 <B0> send: +
>>>>> >> 37 <7C> returnTop
>>>>> >> 38 <E0> send: ifTrue:
>>>>> >> 39 <87> pop
>>>>> >> 40 <78> returnSelf
>>>>> >>
>>>>> >>
>>>>> >> Thanks!
>>>>> >> Rob
>>>>> >>
>>>>> >>
>>>>> >>
>>>>> >
>>>>> >
>>>>> > --
>>>>> > Best regards,
>>>>> > Igor Stasenko AKA sig.
>>>>> >
>>>>> >
>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>> Best regards,
>>>> Igor Stasenko AKA sig.
>>>>
>>>>
>>>
>>>
>>>
>>
>>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: runtime compiled method optimizations

Yoshiki Ohshima-2
In reply to this post by Rob Withers
  Rob,

  As I gather, it is more experimental and performance concern comes
later, right?

  If so, I'd forget about bytecodes and stuff, and write your own
Smalltalk parser first.  The parser creates a parse tree (not
ParseNode kind but almost just nested arrays).  You do analysis and
transformation of the tree and convert the result to bunch of methods
in whatever way you would like.  For a selector like #+, you just
translate it to some other selector and don't have to worry about
bytecode.

  OMeta package on SqueakMap and an Smalltalk implementation example
in MMeta package on SqueakMap might help you.  It is a few hundreds of
lines code so not hard to learn and change.

  Stay at higher level whenever possible.

  Just a thought,

-- Yoshiki

At Fri, 19 Oct 2007 12:32:30 -0700,
Rob Withers wrote:

>
> That's it, the backward jumps use jumpFalse: and jumpTrue:.  It rings a
> bell.
>
> I am trying to transform these jumps to equivalent msg sends, only when the
> receiver is not the expected type.  This way, the normal fast transform
> works most of the time and when it is the wrong receiver we get a msg send
> in the image that I can intercept.  The best of both worlds.  Unfortunately
> it more than doubles the bytecodes for these composite constructs, so I'd
> love to figure out the most compact forms.
>
> Perhaps the way to go is to define bytecodes for all combinations like
>     jumpFalseForIfTrue:
>     jumpFalseForIfFalse:
>     jumpFalseForIfTrueIfFalse:
>     jumpFalseForWhileFalse:
>     jumpTrueForWhileTrue:
>     jumpFalseForToDo:
> and so on.  Then I would need to figure out how to capture the blocks.
>
> Rob
>
> ----- Original Message -----
> From: "nicolas cellier" <[hidden email]>
> To: <[hidden email]>
> Sent: Friday, October 19, 2007 12:17 PM
> Subject: Re: runtime compiled method optimizations
>
>
> > You will also have backward jumps generated by loops (to:do: whileTrue:
> > whileFalse:)...
> >
> > Though you might be able to transform all these jumps in equivalent
> > message send (See Decompiler), that's might be impracticle to do that at
> > interpreter level.
> >
> >
> > Rob Withers a écrit :
> >>
> >> ----- Original Message ----- From: "Igor Stasenko" <[hidden email]>
> >> To: "The general-purpose Squeak developers list"
> >> <[hidden email]>
> >> Sent: Thursday, October 18, 2007 11:58 PM
> >> Subject: Re: runtime compiled method optimizations
> >>
> >>
> >>> On 19/10/2007, Rob Withers <[hidden email]> wrote:
> >>>> Igor, I'm afraid you've lost me.  What would the bytecodes look like in
> >>>> your
> >>>> proposal?  From what you've said, wouldn't the #jumpFalse need to know
> >>>> what
> >>>> the literal to send is?  I also don't understand how it would extract
> >>>> the
> >>>> block contents.
> >>>
> >>> You don't need to change bytecode. Just by analysing that jump
> >>> bytecode jumps over a block. Then you can assume that bytes between
> >>> jump bytecode and byte where it points to is the block body.
> >>> So, you can do the trick by changing implementation of #jumpFalse.
> >>> By sending #IfTrue: message to receiver and checking the result.
> >>
> >> I'm still not getting it.  I am all about getting this functionality in
> >> the most compact form.  Are you saying that I should stick to the
> >> following bytecodes?
> >>
> >> 17 <10> pushTemp: 0
> >> 18 <9B> jumpFalse: 23
> >> 19 <10> pushTemp: 0
> >> 20 <20> pushConstant: 4
> >> 21 <B0> send: +
> >> 22 <7C> returnTop
> >> 23 <78> returnSelf
> >>
> >> Then if I am reading you right, the block is defined as
> >>    PC start of block := the PC of the jumpFalse: + 1
> >>    PC end of block := the PC of the arg to the jumpBlock - 1
> >> but I don't see where you setup and send the #blockCopy:
> >>
> >> I believe, but I am not sure, the #jumpFalse: is not only used for
> >> #ifTrue:, ifFalse:. ifTrue:ifFalse: and #ifFalse:ifTrue:, plus I want to
> >> be able to distinguish between these 4 methods.  Unless they all get
> >> transformed to #ifTrue:ifFalse: with appropriate nil blocks...
> >>
> >> Still, I am having a hard time understanding how #jumpFalse: suddenly
> >> knows to test for boolean (better than the testLocalReference), then if
> >> it is not boolean, instead of sending mustBeBoolean, do a couple of block
> >> copies and send #ifTrue:ifFalse:.  Can it do all that?  Can we have it
> >> scan the bytecodes of the current method to make decisions about the
> >> boundaries of the block copies?  Are we sure it should always send
> >> #ifTrue:ifFalse:?  You raise some interesting questions.
> >>
> >> Rob
> >>
> >>>
> >>>>
> >>>> thanks,
> >>>> Rob
> >>>>
> >>>>
> >>>> ----- Original Message -----
> >>>> From: "Igor Stasenko" <[hidden email]>
> >>>> To: "The general-purpose Squeak developers list"
> >>>> <[hidden email]>
> >>>> Sent: Thursday, October 18, 2007 3:06 PM
> >>>> Subject: Re: runtime compiled method optimizations
> >>>>
> >>>>
> >>>> > No, i think you'd better change the implementation of #jumpFalse
> >>>> > bytecode.
> >>>> > If you see that receiver is non-local , then simply do message send.
> >>>> > And, i think you can safely use info from jump bytecode to extract
> >>>> > block contents
> >>>> > (bytes 19 - 22 is the block body).
> >>>> >
> >>>> > On 19/10/2007, Robert Withers <[hidden email]> wrote:
> >>>> >> Hi all,
> >>>> >>
> >>>> >> I have a simple method containing an ifTrue: message.  I have
> >>>> >> compiled it normally, which uses macro transformations:
> >>>> >>
> >>>> >> 17 <10> pushTemp: 0
> >>>> >> 18 <9B> jumpFalse: 23
> >>>> >> 19 <10> pushTemp: 0
> >>>> >> 20 <20> pushConstant: 4
> >>>> >> 21 <B0> send: +
> >>>> >> 22 <7C> returnTop
> >>>> >> 23 <78> returnSelf
> >>>> >>
> >>>> >> and I have compiled it using Klaus Witzel's nifty compiler changes
> >>>> >> to
> >>>> >> remove macro transformations and the result is an explicit message
> >>>> >> send of #ifTrue:
> >>>> >>
> >>>> >> 21 <10> pushTemp: 0
> >>>> >> 22 <89> pushThisContext:
> >>>> >> 23 <75> pushConstant: 0
> >>>> >> 24 <C8> send: blockCopy:
> >>>> >> 25 <A4 04> jumpTo: 31
> >>>> >> 27 <10> pushTemp: 0
> >>>> >> 28 <21> pushConstant: 4
> >>>> >> 29 <B0> send: +
> >>>> >> 30 <7C> returnTop
> >>>> >> 31 <E0> send: ifTrue:
> >>>> >> 32 <87> pop
> >>>> >> 33 <78> returnSelf
> >>>> >>
> >>>> >> I would like to check the receiver of the ifTrue:, the 1st method
> >>>> >> arg
> >>>> >> in this case (Temp: 0), to see if a certain situation exists (is it
> >>>> >> a
> >>>> >> local reference to an object?).  If it is true, I would like to run
> >>>> >> the optimal code from the first example, instead of the longer
> >>>> >> second
> >>>> >> example.   How could we do that?  Something like this?  Could it be
> >>>> >> done entirely by the compiler, given the existence of the bytecode
> >>>> >> routine for #testLocalReference?
> >>>> >>
> >>>> >> 21 <10> pushTemp: 0
> >>>> >> 22 <??> testLocalReference
> >>>> >> 23 <??> jumpFalse: 30
> >>>> >> 24 <10> pushTemp: 0
> >>>> >> 25 <??> jumpFalse: 40
> >>>> >> 26 <10> pushTemp: 0
> >>>> >> 27 <20> pushConstant: 4
> >>>> >> 28 <B0> send: +
> >>>> >> 29 <7C> returnTop
> >>>> >> 30 <89> pushThisContext:
> >>>> >> 31 <75> pushConstant: 0
> >>>> >> 32 <C8> send: blockCopy:
> >>>> >> 33 <?? ??> jumpTo: 38
> >>>> >> 34 <10> pushTemp: 0
> >>>> >> 35 <21> pushConstant: 4
> >>>> >> 36 <B0> send: +
> >>>> >> 37 <7C> returnTop
> >>>> >> 38 <E0> send: ifTrue:
> >>>> >> 39 <87> pop
> >>>> >> 40 <78> returnSelf
> >>>> >>
> >>>> >>
> >>>> >> Thanks!
> >>>> >> Rob
> >>>> >>
> >>>> >>
> >>>> >>
> >>>> >
> >>>> >
> >>>> > --
> >>>> > Best regards,
> >>>> > Igor Stasenko AKA sig.
> >>>> >
> >>>> >
> >>>>
> >>>>
> >>>>
> >>>
> >>>
> >>> --
> >>> Best regards,
> >>> Igor Stasenko AKA sig.
> >>>
> >>>
> >>
> >>
> >>
> >
> >
> >
>
>

Reply | Threaded
Open this post in threaded view
|

Re: runtime compiled method optimizations

Rob Withers
Thank you, Yoshiki, for your advice.  I'll take a look at those packages.
One thing, I am trying to change the bytecodes that the Compiler generates
for #ifTrue:, for example.  I want to recompile the entire system to use
these.  This way I can get msg sends from anywhere when I need them
(receiver is not a boolean).  To do this, I need to add 4 bytecode routines
to the interpreter, so don't use these bytecodes at home!  But you can
generate them to see what they look like.  In addition to adding 4 routines
to the interpreter, I also need to make the new MessageNodes bulletproof
with respect to decompiling, before I make them part of the Compiler.

Here are the samples that are macro transformed.  After loading the attached
changeset, run them to see the CompiledMethods generated.

(ConditionalTransformCompiler compile: 'true ifTrue: [4+2]') method.
(ConditionalTransformCompiler compile: 'false ifFalse: [4+2]') method.
(ConditionalTransformCompiler compile: 'true ifTrue: [4+2] ifFalse: [3+1]')
method.
(ConditionalTransformCompiler compile: 'true ifFalse: [3+1] ifTrue: [4+2]')
method.
(ConditionalTransformCompiler compile: 'true and: [4+2]') method.
(ConditionalTransformCompiler compile: 'false or: [4+2]') method.
(ConditionalTransformCompiler compile: '[true] whileTrue: [4+2]') method.
(ConditionalTransformCompiler compile: '[false] whileFalse: [4+2]') method.
(ConditionalTransformCompiler compile: '[true] whileTrue') method.
(ConditionalTransformCompiler compile: '[false] whileFalse') method.
(ConditionalTransformCompiler compile: '1 to: 5 do: [:idx | 4+2]') method.
(ConditionalTransformCompiler compile: '1 to: 5 by: 2 do: [:idx | 4+2]')
method.
(ConditionalTransformCompiler compile: '1 caseOf: {[2+2]->[1]}') method.
(ConditionalTransformCompiler compile: '1 caseOf: {[2]->[1]} otherwise:
[0]') method.
(ConditionalTransformCompiler compile: 'nil ifNil: [4+2]') method.
(ConditionalTransformCompiler compile: '1 ifNotNil: [4+2]') method.
(ConditionalTransformCompiler compile: 'nil ifNil: [4+2] ifNotNil: [3+1]')
method.
(ConditionalTransformCompiler compile: '1 ifNotNil: [4+2] ifNil: [3+1]')
method.


Cheers,
Rob



----- Original Message -----
From: "Yoshiki Ohshima" <[hidden email]>
To: "The general-purpose Squeak developerslist"
<[hidden email]>
Sent: Saturday, October 20, 2007 11:44 AM
Subject: Re: runtime compiled method optimizations


  Rob,

  As I gather, it is more experimental and performance concern comes
later, right?

  If so, I'd forget about bytecodes and stuff, and write your own
Smalltalk parser first.  The parser creates a parse tree (not
ParseNode kind but almost just nested arrays).  You do analysis and
transformation of the tree and convert the result to bunch of methods
in whatever way you would like.  For a selector like #+, you just
translate it to some other selector and don't have to worry about
bytecode.

  OMeta package on SqueakMap and an Smalltalk implementation example
in MMeta package on SqueakMap might help you.  It is a few hundreds of
lines code so not hard to learn and change.

  Stay at higher level whenever possible.

  Just a thought,

-- Yoshiki

At Fri, 19 Oct 2007 12:32:30 -0700,
Rob Withers wrote:

>
> That's it, the backward jumps use jumpFalse: and jumpTrue:.  It rings a
> bell.
>
> I am trying to transform these jumps to equivalent msg sends, only when
> the
> receiver is not the expected type.  This way, the normal fast transform
> works most of the time and when it is the wrong receiver we get a msg send
> in the image that I can intercept.  The best of both worlds.
> Unfortunately
> it more than doubles the bytecodes for these composite constructs, so I'd
> love to figure out the most compact forms.
>
> Perhaps the way to go is to define bytecodes for all combinations like
>     jumpFalseForIfTrue:
>     jumpFalseForIfFalse:
>     jumpFalseForIfTrueIfFalse:
>     jumpFalseForWhileFalse:
>     jumpTrueForWhileTrue:
>     jumpFalseForToDo:
> and so on.  Then I would need to figure out how to capture the blocks.
>
> Rob
>
> ----- Original Message -----
> From: "nicolas cellier" <[hidden email]>
> To: <[hidden email]>
> Sent: Friday, October 19, 2007 12:17 PM
> Subject: Re: runtime compiled method optimizations
>
>
> > You will also have backward jumps generated by loops (to:do: whileTrue:
> > whileFalse:)...
> >
> > Though you might be able to transform all these jumps in equivalent
> > message send (See Decompiler), that's might be impracticle to do that at
> > interpreter level.
> >
> >
> > Rob Withers a écrit :
> >>
> >> ----- Original Message ----- From: "Igor Stasenko" <[hidden email]>
> >> To: "The general-purpose Squeak developers list"
> >> <[hidden email]>
> >> Sent: Thursday, October 18, 2007 11:58 PM
> >> Subject: Re: runtime compiled method optimizations
> >>
> >>
> >>> On 19/10/2007, Rob Withers <[hidden email]> wrote:
> >>>> Igor, I'm afraid you've lost me.  What would the bytecodes look like
> >>>> in
> >>>> your
> >>>> proposal?  From what you've said, wouldn't the #jumpFalse need to
> >>>> know
> >>>> what
> >>>> the literal to send is?  I also don't understand how it would extract
> >>>> the
> >>>> block contents.
> >>>
> >>> You don't need to change bytecode. Just by analysing that jump
> >>> bytecode jumps over a block. Then you can assume that bytes between
> >>> jump bytecode and byte where it points to is the block body.
> >>> So, you can do the trick by changing implementation of #jumpFalse.
> >>> By sending #IfTrue: message to receiver and checking the result.
> >>
> >> I'm still not getting it.  I am all about getting this functionality in
> >> the most compact form.  Are you saying that I should stick to the
> >> following bytecodes?
> >>
> >> 17 <10> pushTemp: 0
> >> 18 <9B> jumpFalse: 23
> >> 19 <10> pushTemp: 0
> >> 20 <20> pushConstant: 4
> >> 21 <B0> send: +
> >> 22 <7C> returnTop
> >> 23 <78> returnSelf
> >>
> >> Then if I am reading you right, the block is defined as
> >>    PC start of block := the PC of the jumpFalse: + 1
> >>    PC end of block := the PC of the arg to the jumpBlock - 1
> >> but I don't see where you setup and send the #blockCopy:
> >>
> >> I believe, but I am not sure, the #jumpFalse: is not only used for
> >> #ifTrue:, ifFalse:. ifTrue:ifFalse: and #ifFalse:ifTrue:, plus I want
> >> to
> >> be able to distinguish between these 4 methods.  Unless they all get
> >> transformed to #ifTrue:ifFalse: with appropriate nil blocks...
> >>
> >> Still, I am having a hard time understanding how #jumpFalse: suddenly
> >> knows to test for boolean (better than the testLocalReference), then if
> >> it is not boolean, instead of sending mustBeBoolean, do a couple of
> >> block
> >> copies and send #ifTrue:ifFalse:.  Can it do all that?  Can we have it
> >> scan the bytecodes of the current method to make decisions about the
> >> boundaries of the block copies?  Are we sure it should always send
> >> #ifTrue:ifFalse:?  You raise some interesting questions.
> >>
> >> Rob
> >>
> >>>
> >>>>
> >>>> thanks,
> >>>> Rob
> >>>>
> >>>>
> >>>> ----- Original Message -----
> >>>> From: "Igor Stasenko" <[hidden email]>
> >>>> To: "The general-purpose Squeak developers list"
> >>>> <[hidden email]>
> >>>> Sent: Thursday, October 18, 2007 3:06 PM
> >>>> Subject: Re: runtime compiled method optimizations
> >>>>
> >>>>
> >>>> > No, i think you'd better change the implementation of #jumpFalse
> >>>> > bytecode.
> >>>> > If you see that receiver is non-local , then simply do message
> >>>> > send.
> >>>> > And, i think you can safely use info from jump bytecode to extract
> >>>> > block contents
> >>>> > (bytes 19 - 22 is the block body).
> >>>> >
> >>>> > On 19/10/2007, Robert Withers <[hidden email]> wrote:
> >>>> >> Hi all,
> >>>> >>
> >>>> >> I have a simple method containing an ifTrue: message.  I have
> >>>> >> compiled it normally, which uses macro transformations:
> >>>> >>
> >>>> >> 17 <10> pushTemp: 0
> >>>> >> 18 <9B> jumpFalse: 23
> >>>> >> 19 <10> pushTemp: 0
> >>>> >> 20 <20> pushConstant: 4
> >>>> >> 21 <B0> send: +
> >>>> >> 22 <7C> returnTop
> >>>> >> 23 <78> returnSelf
> >>>> >>
> >>>> >> and I have compiled it using Klaus Witzel's nifty compiler changes
> >>>> >> to
> >>>> >> remove macro transformations and the result is an explicit message
> >>>> >> send of #ifTrue:
> >>>> >>
> >>>> >> 21 <10> pushTemp: 0
> >>>> >> 22 <89> pushThisContext:
> >>>> >> 23 <75> pushConstant: 0
> >>>> >> 24 <C8> send: blockCopy:
> >>>> >> 25 <A4 04> jumpTo: 31
> >>>> >> 27 <10> pushTemp: 0
> >>>> >> 28 <21> pushConstant: 4
> >>>> >> 29 <B0> send: +
> >>>> >> 30 <7C> returnTop
> >>>> >> 31 <E0> send: ifTrue:
> >>>> >> 32 <87> pop
> >>>> >> 33 <78> returnSelf
> >>>> >>
> >>>> >> I would like to check the receiver of the ifTrue:, the 1st method
> >>>> >> arg
> >>>> >> in this case (Temp: 0), to see if a certain situation exists (is
> >>>> >> it
> >>>> >> a
> >>>> >> local reference to an object?).  If it is true, I would like to
> >>>> >> run
> >>>> >> the optimal code from the first example, instead of the longer
> >>>> >> second
> >>>> >> example.   How could we do that?  Something like this?  Could it
> >>>> >> be
> >>>> >> done entirely by the compiler, given the existence of the bytecode
> >>>> >> routine for #testLocalReference?
> >>>> >>
> >>>> >> 21 <10> pushTemp: 0
> >>>> >> 22 <??> testLocalReference
> >>>> >> 23 <??> jumpFalse: 30
> >>>> >> 24 <10> pushTemp: 0
> >>>> >> 25 <??> jumpFalse: 40
> >>>> >> 26 <10> pushTemp: 0
> >>>> >> 27 <20> pushConstant: 4
> >>>> >> 28 <B0> send: +
> >>>> >> 29 <7C> returnTop
> >>>> >> 30 <89> pushThisContext:
> >>>> >> 31 <75> pushConstant: 0
> >>>> >> 32 <C8> send: blockCopy:
> >>>> >> 33 <?? ??> jumpTo: 38
> >>>> >> 34 <10> pushTemp: 0
> >>>> >> 35 <21> pushConstant: 4
> >>>> >> 36 <B0> send: +
> >>>> >> 37 <7C> returnTop
> >>>> >> 38 <E0> send: ifTrue:
> >>>> >> 39 <87> pop
> >>>> >> 40 <78> returnSelf
> >>>> >>
> >>>> >>
> >>>> >> Thanks!
> >>>> >> Rob
> >>>> >>
> >>>> >>
> >>>> >>
> >>>> >
> >>>> >
> >>>> > --
> >>>> > Best regards,
> >>>> > Igor Stasenko AKA sig.
> >>>> >
> >>>> >
> >>>>
> >>>>
> >>>>
> >>>
> >>>
> >>> --
> >>> Best regards,
> >>> Igor Stasenko AKA sig.
> >>>
> >>>
> >>
> >>
> >>
> >
> >
> >
>
>



ConditionalTransformCompiler.1.cs (42K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: runtime compiled method optimizations

Rob Withers
In reply to this post by Yoshiki Ohshima-2
Oops.  I can't find either MMeta or OMeta on SqueakMap.

----- Original Message -----
From: "Yoshiki Ohshima" <[hidden email]>
To: "The general-purpose Squeak developerslist"
<[hidden email]>
Sent: Saturday, October 20, 2007 11:44 AM
Subject: Re: runtime compiled method optimizations


  Rob,

  As I gather, it is more experimental and performance concern comes
later, right?

  If so, I'd forget about bytecodes and stuff, and write your own
Smalltalk parser first.  The parser creates a parse tree (not
ParseNode kind but almost just nested arrays).  You do analysis and
transformation of the tree and convert the result to bunch of methods
in whatever way you would like.  For a selector like #+, you just
translate it to some other selector and don't have to worry about
bytecode.

  OMeta package on SqueakMap and an Smalltalk implementation example
in MMeta package on SqueakMap might help you.  It is a few hundreds of
lines code so not hard to learn and change.

  Stay at higher level whenever possible.

  Just a thought,

-- Yoshiki

At Fri, 19 Oct 2007 12:32:30 -0700,
Rob Withers wrote:

>
> That's it, the backward jumps use jumpFalse: and jumpTrue:.  It rings a
> bell.
>
> I am trying to transform these jumps to equivalent msg sends, only when
> the
> receiver is not the expected type.  This way, the normal fast transform
> works most of the time and when it is the wrong receiver we get a msg send
> in the image that I can intercept.  The best of both worlds.
> Unfortunately
> it more than doubles the bytecodes for these composite constructs, so I'd
> love to figure out the most compact forms.
>
> Perhaps the way to go is to define bytecodes for all combinations like
>     jumpFalseForIfTrue:
>     jumpFalseForIfFalse:
>     jumpFalseForIfTrueIfFalse:
>     jumpFalseForWhileFalse:
>     jumpTrueForWhileTrue:
>     jumpFalseForToDo:
> and so on.  Then I would need to figure out how to capture the blocks.
>
> Rob
>
> ----- Original Message -----
> From: "nicolas cellier" <[hidden email]>
> To: <[hidden email]>
> Sent: Friday, October 19, 2007 12:17 PM
> Subject: Re: runtime compiled method optimizations
>
>
> > You will also have backward jumps generated by loops (to:do: whileTrue:
> > whileFalse:)...
> >
> > Though you might be able to transform all these jumps in equivalent
> > message send (See Decompiler), that's might be impracticle to do that at
> > interpreter level.
> >
> >
> > Rob Withers a écrit :
> >>
> >> ----- Original Message ----- From: "Igor Stasenko" <[hidden email]>
> >> To: "The general-purpose Squeak developers list"
> >> <[hidden email]>
> >> Sent: Thursday, October 18, 2007 11:58 PM
> >> Subject: Re: runtime compiled method optimizations
> >>
> >>
> >>> On 19/10/2007, Rob Withers <[hidden email]> wrote:
> >>>> Igor, I'm afraid you've lost me.  What would the bytecodes look like
> >>>> in
> >>>> your
> >>>> proposal?  From what you've said, wouldn't the #jumpFalse need to
> >>>> know
> >>>> what
> >>>> the literal to send is?  I also don't understand how it would extract
> >>>> the
> >>>> block contents.
> >>>
> >>> You don't need to change bytecode. Just by analysing that jump
> >>> bytecode jumps over a block. Then you can assume that bytes between
> >>> jump bytecode and byte where it points to is the block body.
> >>> So, you can do the trick by changing implementation of #jumpFalse.
> >>> By sending #IfTrue: message to receiver and checking the result.
> >>
> >> I'm still not getting it.  I am all about getting this functionality in
> >> the most compact form.  Are you saying that I should stick to the
> >> following bytecodes?
> >>
> >> 17 <10> pushTemp: 0
> >> 18 <9B> jumpFalse: 23
> >> 19 <10> pushTemp: 0
> >> 20 <20> pushConstant: 4
> >> 21 <B0> send: +
> >> 22 <7C> returnTop
> >> 23 <78> returnSelf
> >>
> >> Then if I am reading you right, the block is defined as
> >>    PC start of block := the PC of the jumpFalse: + 1
> >>    PC end of block := the PC of the arg to the jumpBlock - 1
> >> but I don't see where you setup and send the #blockCopy:
> >>
> >> I believe, but I am not sure, the #jumpFalse: is not only used for
> >> #ifTrue:, ifFalse:. ifTrue:ifFalse: and #ifFalse:ifTrue:, plus I want
> >> to
> >> be able to distinguish between these 4 methods.  Unless they all get
> >> transformed to #ifTrue:ifFalse: with appropriate nil blocks...
> >>
> >> Still, I am having a hard time understanding how #jumpFalse: suddenly
> >> knows to test for boolean (better than the testLocalReference), then if
> >> it is not boolean, instead of sending mustBeBoolean, do a couple of
> >> block
> >> copies and send #ifTrue:ifFalse:.  Can it do all that?  Can we have it
> >> scan the bytecodes of the current method to make decisions about the
> >> boundaries of the block copies?  Are we sure it should always send
> >> #ifTrue:ifFalse:?  You raise some interesting questions.
> >>
> >> Rob
> >>
> >>>
> >>>>
> >>>> thanks,
> >>>> Rob
> >>>>
> >>>>
> >>>> ----- Original Message -----
> >>>> From: "Igor Stasenko" <[hidden email]>
> >>>> To: "The general-purpose Squeak developers list"
> >>>> <[hidden email]>
> >>>> Sent: Thursday, October 18, 2007 3:06 PM
> >>>> Subject: Re: runtime compiled method optimizations
> >>>>
> >>>>
> >>>> > No, i think you'd better change the implementation of #jumpFalse
> >>>> > bytecode.
> >>>> > If you see that receiver is non-local , then simply do message
> >>>> > send.
> >>>> > And, i think you can safely use info from jump bytecode to extract
> >>>> > block contents
> >>>> > (bytes 19 - 22 is the block body).
> >>>> >
> >>>> > On 19/10/2007, Robert Withers <[hidden email]> wrote:
> >>>> >> Hi all,
> >>>> >>
> >>>> >> I have a simple method containing an ifTrue: message.  I have
> >>>> >> compiled it normally, which uses macro transformations:
> >>>> >>
> >>>> >> 17 <10> pushTemp: 0
> >>>> >> 18 <9B> jumpFalse: 23
> >>>> >> 19 <10> pushTemp: 0
> >>>> >> 20 <20> pushConstant: 4
> >>>> >> 21 <B0> send: +
> >>>> >> 22 <7C> returnTop
> >>>> >> 23 <78> returnSelf
> >>>> >>
> >>>> >> and I have compiled it using Klaus Witzel's nifty compiler changes
> >>>> >> to
> >>>> >> remove macro transformations and the result is an explicit message
> >>>> >> send of #ifTrue:
> >>>> >>
> >>>> >> 21 <10> pushTemp: 0
> >>>> >> 22 <89> pushThisContext:
> >>>> >> 23 <75> pushConstant: 0
> >>>> >> 24 <C8> send: blockCopy:
> >>>> >> 25 <A4 04> jumpTo: 31
> >>>> >> 27 <10> pushTemp: 0
> >>>> >> 28 <21> pushConstant: 4
> >>>> >> 29 <B0> send: +
> >>>> >> 30 <7C> returnTop
> >>>> >> 31 <E0> send: ifTrue:
> >>>> >> 32 <87> pop
> >>>> >> 33 <78> returnSelf
> >>>> >>
> >>>> >> I would like to check the receiver of the ifTrue:, the 1st method
> >>>> >> arg
> >>>> >> in this case (Temp: 0), to see if a certain situation exists (is
> >>>> >> it
> >>>> >> a
> >>>> >> local reference to an object?).  If it is true, I would like to
> >>>> >> run
> >>>> >> the optimal code from the first example, instead of the longer
> >>>> >> second
> >>>> >> example.   How could we do that?  Something like this?  Could it
> >>>> >> be
> >>>> >> done entirely by the compiler, given the existence of the bytecode
> >>>> >> routine for #testLocalReference?
> >>>> >>
> >>>> >> 21 <10> pushTemp: 0
> >>>> >> 22 <??> testLocalReference
> >>>> >> 23 <??> jumpFalse: 30
> >>>> >> 24 <10> pushTemp: 0
> >>>> >> 25 <??> jumpFalse: 40
> >>>> >> 26 <10> pushTemp: 0
> >>>> >> 27 <20> pushConstant: 4
> >>>> >> 28 <B0> send: +
> >>>> >> 29 <7C> returnTop
> >>>> >> 30 <89> pushThisContext:
> >>>> >> 31 <75> pushConstant: 0
> >>>> >> 32 <C8> send: blockCopy:
> >>>> >> 33 <?? ??> jumpTo: 38
> >>>> >> 34 <10> pushTemp: 0
> >>>> >> 35 <21> pushConstant: 4
> >>>> >> 36 <B0> send: +
> >>>> >> 37 <7C> returnTop
> >>>> >> 38 <E0> send: ifTrue:
> >>>> >> 39 <87> pop
> >>>> >> 40 <78> returnSelf
> >>>> >>
> >>>> >>
> >>>> >> Thanks!
> >>>> >> Rob
> >>>> >>
> >>>> >>
> >>>> >>
> >>>> >
> >>>> >
> >>>> > --
> >>>> > Best regards,
> >>>> > Igor Stasenko AKA sig.
> >>>> >
> >>>> >
> >>>>
> >>>>
> >>>>
> >>>
> >>>
> >>> --
> >>> Best regards,
> >>> Igor Stasenko AKA sig.
> >>>
> >>>
> >>
> >>
> >>
> >
> >
> >
>
>



Reply | Threaded
Open this post in threaded view
|

Re: runtime compiled method optimizations

Yoshiki Ohshima-2
> Oops.  I can't find either MMeta or OMeta on SqueakMap.

  Sorry.  From this page:

http://map1.squeakfoundation.org/packagesbyname

look for "Meta" for MMeta
(http://map1.squeakfoundation.org/package/e3cdcb13-a408-49c8-9a97-5e9b8befa4ac)
and OMeta
(http://map1.squeakfoundation.org/package/dea7935d-2497-45df-936c-69f0daedd136).

-- Yoshiki