How to partially turn off optimization

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

How to partially turn off optimization

Louis LaBrunda
Hi,

I was playing around and decided to try to extend Character with the following code:

to: endCharacter do: aBlock
"Evaluate aBlock for each element of the character progression from the receiver to endCharacter in increments of 1."
"If the value of endCharacter is less than the value of self than increment down by -1."
| start end |

start := self value.
end := endCharacter value.
(end > start)
ifTrue: [start to: end do: [:v | aBlock value: v asCharacter]]
ifFalse: [start to: end by: -1 do: [:v | aBlock value: v asCharacter]].

The trouble is #to:do: gets optimized to the version from Integer and/or Number.  I don't want to turn the optimization off all the time by I would like to learn a little about how it works.

Lou

--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/va-smalltalk.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: How to partially turn off optimization

Seth Berman
Hi Lou,

See EsMessageExpression class>>initializeAfterLoad  for the list of selectors which are inlined.  So this is a code generation optimization, not a vm execution optimization (i.e. special selectors).
When a parse tree is built for a receiver that sends the message #to:do:, a special EsToDo parse node is inserted in place of an EsMessageExpression.
When code is generated from this parse tree, the EsToDo will transform that 'reciever to: arg do: aBlock' into a series of inc/test/jump bytecodes instead of an actual message send and block activation.
Similar types of bytecode gen optimizations are going on for the other ones.
These are applied anytime the parser is seeing the selector name.  It can't (not easily) know that this should only apply to Number >> selector because that would imply it can successfully resolve the receiver type at "compile time"...that's why it applies everywhere.

- Seth

On Thursday, November 2, 2017 at 3:25:22 PM UTC-4, Louis LaBrunda wrote:
Hi,

I was playing around and decided to try to extend Character with the following code:

to: endCharacter do: aBlock
"Evaluate aBlock for each element of the character progression from the receiver to endCharacter in increments of 1."
"If the value of endCharacter is less than the value of self than increment down by -1."
| start end |

start := self value.
end := endCharacter value.
(end > start)
ifTrue: [start to: end do: [:v | aBlock value: v asCharacter]]
ifFalse: [start to: end by: -1 do: [:v | aBlock value: v asCharacter]].

The trouble is #to:do: gets optimized to the version from Integer and/or Number.  I don't want to turn the optimization off all the time by I would like to learn a little about how it works.

Lou

--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/va-smalltalk.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: How to partially turn off optimization

Louis LaBrunda
Hi Seth,

On Thursday, November 2, 2017 at 3:54:59 PM UTC-4, Seth Berman wrote:
Hi Lou,

See EsMessageExpression class>>initializeAfterLoad  for the list of selectors which are inlined.  So this is a code generation optimization, not a vm execution optimization (i.e. special selectors).
When a parse tree is built for a receiver that sends the message #to:do:, a special EsToDo parse node is inserted in place of an EsMessageExpression.
When code is generated from this parse tree, the EsToDo will transform that 'reciever to: arg do: aBlock' into a series of inc/test/jump bytecodes instead of an actual message send and block activation.
Similar types of bytecode gen optimizations are going on for the other ones.
These are applied anytime the parser is seeing the selector name.  It can't (not easily) know that this should only apply to Number >> selector because that would imply it can successfully resolve the receiver type at "compile time"...that's why it applies everywhere.

That's what I thought.  Since I am just playing around I think I will just change the name to #toChar:do:. 

Lou

 
- Seth

On Thursday, November 2, 2017 at 3:25:22 PM UTC-4, Louis LaBrunda wrote:
Hi,

I was playing around and decided to try to extend Character with the following code:

to: endCharacter do: aBlock
"Evaluate aBlock for each element of the character progression from the receiver to endCharacter in increments of 1."
"If the value of endCharacter is less than the value of self than increment down by -1."
| start end |

start := self value.
end := endCharacter value.
(end > start)
ifTrue: [start to: end do: [:v | aBlock value: v asCharacter]]
ifFalse: [start to: end by: -1 do: [:v | aBlock value: v asCharacter]].

The trouble is #to:do: gets optimized to the version from Integer and/or Number.  I don't want to turn the optimization off all the time by I would like to learn a little about how it works.

Lou

--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/va-smalltalk.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: How to partially turn off optimization

Louis LaBrunda
In reply to this post by Seth Berman
Hi Seth, Everybody,

As I said, I don't really need this but I was thinking.  Is there a way that the in-lined code could, at run time test the target object to see if it is an integer and if so, proceed with the in-lined code and if not, do the message send?  I don't think this would slow things down much as it wouldn't be in the loop and it shouldn't grow the code much.

Lou


On Thursday, November 2, 2017 at 3:54:59 PM UTC-4, Seth Berman wrote:
Hi Lou,

See EsMessageExpression class>>initializeAfterLoad  for the list of selectors which are inlined.  So this is a code generation optimization, not a vm execution optimization (i.e. special selectors).
When a parse tree is built for a receiver that sends the message #to:do:, a special EsToDo parse node is inserted in place of an EsMessageExpression.
When code is generated from this parse tree, the EsToDo will transform that 'reciever to: arg do: aBlock' into a series of inc/test/jump bytecodes instead of an actual message send and block activation.
Similar types of bytecode gen optimizations are going on for the other ones.
These are applied anytime the parser is seeing the selector name.  It can't (not easily) know that this should only apply to Number >> selector because that would imply it can successfully resolve the receiver type at "compile time"...that's why it applies everywhere.

- Seth

On Thursday, November 2, 2017 at 3:25:22 PM UTC-4, Louis LaBrunda wrote:
Hi,

I was playing around and decided to try to extend Character with the following code:

to: endCharacter do: aBlock
"Evaluate aBlock for each element of the character progression from the receiver to endCharacter in increments of 1."
"If the value of endCharacter is less than the value of self than increment down by -1."
| start end |

start := self value.
end := endCharacter value.
(end > start)
ifTrue: [start to: end do: [:v | aBlock value: v asCharacter]]
ifFalse: [start to: end by: -1 do: [:v | aBlock value: v asCharacter]].

The trouble is #to:do: gets optimized to the version from Integer and/or Number.  I don't want to turn the optimization off all the time by I would like to learn a little about how it works.

Lou

--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/va-smalltalk.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: How to partially turn off optimization

Seth Berman
Hi Lou,

It's certainly possible, and in fact, something to this effect is a common just-in-time compiler optimization...although it would be more like generating optimized code for the current situation with a quick test to see if the situation changes.  If it does, then jumping back to the interpreter (deoptimizing) to generically handle it.  Or some other method to "deoptimize" and create more generic code.
VA's special selectors operate almost exactly like you describe within the interpreter implementation...except that it happens in native instructions, not bytecodes.
I guess the real question would be if the additional complexity to the smalltalk compiler, safely handling all the corner cases, and performance benefit, would actually be worth the effort to do it.
Intriguing question.

-- Seth

On Friday, November 3, 2017 at 11:06:10 AM UTC-4, Louis LaBrunda wrote:
Hi Seth, Everybody,

As I said, I don't really need this but I was thinking.  Is there a way that the in-lined code could, at run time test the target object to see if it is an integer and if so, proceed with the in-lined code and if not, do the message send?  I don't think this would slow things down much as it wouldn't be in the loop and it shouldn't grow the code much.

Lou


On Thursday, November 2, 2017 at 3:54:59 PM UTC-4, Seth Berman wrote:
Hi Lou,

See EsMessageExpression class>>initializeAfterLoad  for the list of selectors which are inlined.  So this is a code generation optimization, not a vm execution optimization (i.e. special selectors).
When a parse tree is built for a receiver that sends the message #to:do:, a special EsToDo parse node is inserted in place of an EsMessageExpression.
When code is generated from this parse tree, the EsToDo will transform that 'reciever to: arg do: aBlock' into a series of inc/test/jump bytecodes instead of an actual message send and block activation.
Similar types of bytecode gen optimizations are going on for the other ones.
These are applied anytime the parser is seeing the selector name.  It can't (not easily) know that this should only apply to Number >> selector because that would imply it can successfully resolve the receiver type at "compile time"...that's why it applies everywhere.

- Seth

On Thursday, November 2, 2017 at 3:25:22 PM UTC-4, Louis LaBrunda wrote:
Hi,

I was playing around and decided to try to extend Character with the following code:

to: endCharacter do: aBlock
"Evaluate aBlock for each element of the character progression from the receiver to endCharacter in increments of 1."
"If the value of endCharacter is less than the value of self than increment down by -1."
| start end |

start := self value.
end := endCharacter value.
(end > start)
ifTrue: [start to: end do: [:v | aBlock value: v asCharacter]]
ifFalse: [start to: end by: -1 do: [:v | aBlock value: v asCharacter]].

The trouble is #to:do: gets optimized to the version from Integer and/or Number.  I don't want to turn the optimization off all the time by I would like to learn a little about how it works.

Lou

--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/va-smalltalk.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: How to partially turn off optimization

Hans-Martin Mosner-3
In reply to this post by Louis LaBrunda
You could also implement #+ and #- in Character to make the inlined code work with Character, too, but then you might get bitten by locale-specific character comparison semantics...

Cheers,
Hans-Martin

--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/va-smalltalk.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: How to partially turn off optimization

Louis LaBrunda
Hi Hans-Martin,

An interesting idea.  I haven't tried it but I'm wondering if the in-lined code would actually send a + 1 to the character?  Seems like it should.  I will have to make some time to play with it.

Lou


On Wednesday, December 6, 2017 at 4:36:46 AM UTC-5, Hans-Martin Mosner wrote:
You could also implement #+ and #- in Character to make the inlined code work with Character, too, but then you might get bitten by locale-specific character comparison semantics...

Cheers,
Hans-Martin

--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/va-smalltalk.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: How to partially turn off optimization

Hans-Martin Mosner-3
In reply to this post by Louis LaBrunda
I tested it before I posted, so I know it works in principle, except for the problematic comparison. Didn't expect that I need a #- method as well, but that's probably generated by the loop inlining code to make checking for the limit simpler.
For clarity and reliability, you should implement a special method to loop over character ranges, though. If this turns out to be a performance bottleneck, you probably have issues somewhere else that won't be resolved by forcing inlined loops.

Cheers,
Hans-Martin

--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/va-smalltalk.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: How to partially turn off optimization

Louis LaBrunda
Hi Hans-Martin,

As you say it does work.  I also implemented #to:by:do: for the sake of completeness and because #to:do: doesn't handle going from a high value to a low one.  Thanks for the suggestion.  This was fun and the kind of thing you can't do in a lot of other languages.

Lou

On Wednesday, December 6, 2017 at 11:00:35 AM UTC-5, Hans-Martin Mosner wrote:
I tested it before I posted, so I know it works in principle, except for the problematic comparison. Didn't expect that I need a #- method as well, but that's probably generated by the loop inlining code to make checking for the limit simpler.
For clarity and reliability, you should implement a special method to loop over character ranges, though. If this turns out to be a performance bottleneck, you probably have issues somewhere else that won't be resolved by forcing inlined loops.

Cheers,
Hans-Martin

--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/va-smalltalk.
For more options, visit https://groups.google.com/d/optout.