3.9 vs. 3.10 : Closures, fixTemps

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

Re: 3.9 vs. 3.10 : Closures, fixTemps

Mathieu SUEN
Well so propose us your solution.
At least the new compiler exist .

On Dec 19, 2007, at 6:12 PM, Andreas Raab wrote:

> Philippe Marschall wrote:
>>> there is really no reason whatsoever why a working closure solution
>>> couldn't be adopted to the current compiler (which would mitigate  
>>> the
>>> risk factors of adoption dramatically).
>> They why was the closure solution of the new compiler rejected?
>
> "The closure solution rejected"? Not that I know of. I haven't even  
> seen a thorough discussion about its merits (which should include  
> benchmarks etc) - what I did see was some talk that led me to  
> believe that there is still a ways to go here. To the best of my  
> knowledge this solution isn't "final" by any means.
>
> Or do you mean the compiler itself? In which case all I can say it's  
> hard to recommend a compiler which can't even recompile Object ;-)
>
> Cheers,
>  - Andreas
>
>

        Mth




Reply | Threaded
Open this post in threaded view
|

Re: 3.9 vs. 3.10 : Closures, fixTemps

Andreas.Raab
In reply to this post by stephane ducasse
stephane ducasse wrote:
> The newcompiler can recompile the complete image. I do not which version
> you are using.

* Start with 3.9.7067-final
* From Squeakmap load the latest published version of AST
* From Squeakmap load the latest published version of NewCompiler
* Preferences enable: #compileUseNewCompiler
* Object compileAll
* Boom.

Besides, when I tried to load NewCompiler yesterday evening via
Universes in 3.10 it failed to load entirely. Not sure why (and I wasn't
in a mood of trying to find out).

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: 3.9 vs. 3.10 : Closures, fixTemps

Andreas.Raab
In reply to this post by Mathieu SUEN
Mathieu Suen wrote:
> Well so propose us your solution.
> At least the new compiler exist .

You are missing my point entirely. I wasn't talking about inventing a
solution - I was talking about adopting one, such as from NewCompiler if
it's a viable, robust solution. But I don't know if it is, and I  find
little of a discussion about it and I couldn't try for myself. So it's
kinda hard to tell.

Cheers,
   - Andreas

>
> On Dec 19, 2007, at 6:12 PM, Andreas Raab wrote:
>
>> Philippe Marschall wrote:
>>>> there is really no reason whatsoever why a working closure solution
>>>> couldn't be adopted to the current compiler (which would mitigate the
>>>> risk factors of adoption dramatically).
>>> They why was the closure solution of the new compiler rejected?
>>
>> "The closure solution rejected"? Not that I know of. I haven't even
>> seen a thorough discussion about its merits (which should include
>> benchmarks etc) - what I did see was some talk that led me to believe
>> that there is still a ways to go here. To the best of my knowledge
>> this solution isn't "final" by any means.
>>
>> Or do you mean the compiler itself? In which case all I can say it's
>> hard to recommend a compiler which can't even recompile Object ;-)
>>
>> Cheers,
>>  - Andreas
>>
>>
>
>     Mth
>
>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: 3.9 vs. 3.10 : Closures, fixTemps

Mathieu SUEN
In reply to this post by Andreas.Raab

On Dec 19, 2007, at 9:48 PM, Andreas Raab wrote:

> stephane ducasse wrote:
>> The newcompiler can recompile the complete image. I do not which  
>> version you are using.
>
> * Start with 3.9.7067-final
> * From Squeakmap load the latest published version of AST
> * From Squeakmap load the latest published version of NewCompiler
> * Preferences enable: #compileUseNewCompiler
> * Object compileAll
> * Boom.
>
> Besides, when I tried to load NewCompiler yesterday evening via  
> Universes in 3.10 it failed to load entirely. Not sure why (and I  
> wasn't in a mood of trying to find out).
>
> Cheers,
>  - Andreas
>

Sorry I made a mistake in the universe browser. It is now fix

        Mth




Reply | Threaded
Open this post in threaded view
|

Re: 3.9 vs. 3.10 : Closures, fixTemps

Edgar J. De Cleene
In reply to this post by Andreas.Raab



El 12/19/07 5:48 PM, "Andreas Raab" <[hidden email]> escribió:

> * Start with 3.9.7067-final
> * From Squeakmap load the latest published version of AST
> * From Squeakmap load the latest published version of NewCompiler
> * Preferences enable: #compileUseNewCompiler
> * Object compileAll
> * Boom.
>
> Besides, when I tried to load NewCompiler yesterday evening via
> Universes in 3.10 it failed to load entirely. Not sure why (and I wasn't
> in a mood of trying to find out).
>
> Cheers,
>    - Andreas

Not so. I attach pict.
If this is a good to have, then all experts in this field should request for
3.11.

Edgar




Picture 2.png (50K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: 3.9 vs. 3.10 : Closures, fixTemps

Andreas.Raab
In reply to this post by Mathieu SUEN
Mathieu Suen wrote:
> Sorry I made a mistake in the universe browser. It is now fix

Indeed much better now. I'm getting halfways through now with
recompiling everything but now it dies in the middle of recompiling
Preferences (you can try this by executing "Preferences compileAll").
Any ideas?

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Implementing closures (was: Re: 3.9 vs. 3.10 : Closures, fixTemps)

Andreas.Raab
In reply to this post by Mathieu SUEN
Mathieu Suen wrote:
> Well so propose us your solution.

Okay, I promised not to invent a solution but it's one of "those"
problems that I've thought about for a while in the past so let's see.
Here is how I would address the problem of implementing full closures in
Squeak:

1) First, I would fix the "attempt to evaluate a block that is already
evaluated" problem. That's about ten lines of code in the VM - if you
look at primitiveValue[withArgs] you'll find that we fail if the
CallerIndex is non-nil. Instead of failing, I'd clone the original
context and continue as usual.

At this point you'd be able to execute code like:

   | v |
   fac := [v > 0 ifTrue:[1] ifFalse:[v := v-1. fac value * (v+1)]].
   fac value: 10.

which allows recursive evaluation but without block args (since they get
hacked in some terrible ways).

2) Next, I'd deal with block variables (temps and args). Instead of
sharing the method contexts, blocks would store their own temps and
access them via tempAt:. So that for example code like here:

   self do:[:v| | v2 | v2 := v squared. v2].

would be compiled into to:

   self do:[:v|
     thisContext push: nil. "allocate v2"
     thisContext tempAt: 2 "v2" put: (thisContext tempAt: 1 "v") squared.
     thisContext tempAt: 2.
   ].

This would be slower than what we have today but obviously, the pattern
"thisContext tempAt:" is a prime candidate for optimization. At this
point we'd be able to run the following correctly:

fac [:v| v = 0 ifTrue:[1] ifFalse:[ v * (fac value: v-1)].

The implementation would be pretty straightforward too, since all you'd
have to do is to add BlockVariableNode that generates tempAt: messages
(plus some initialization). Very, very straightforward.

3) Next, I would deal with "outer" state like here:

   self do:[:x|
     x do:[:y| x * y]
   ].

This is probably the hardest part since dealing with "non-method
closed-over state" can be tricky due to life-time issues. Anyway, for
starters I would just add a hidden temporary "outerContext" for all
blocks that is just a temp like any other such that the compiler can
generate code like:

   self do:[:x|
     x do:[:y|
       ((thisContext tempAt: 1) "outerContext" tempAt: 1 "x") *
         (thisContext tempAt: 2) "y"
     ].
   ].

At this point (I think - please correct me if I'm missing something) we
have *complete* closure semantics in a straightforward way. What remains
is optimization.

4) Lastly, optimization. I would start with the obvious
push/popBlockTemp bytecodes which would bring all of the above up to par
with current Squeak (except (3) which could still be slower). Finally,
one might look at the life-time of closed-over state - it is certainly
not necessary to preserve the entire outer context so there may be other
things that could be done to fix it.

In any case, the above looks pretty simple and straightforward. Wouldn't
you agree?

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: Implementing closures (was: Re: 3.9 vs. 3.10 : Closures, fixTemps)

timrowledge

On 19-Dec-07, at 8:19 PM, Andreas Raab wrote:

> Mathieu Suen wrote:
>> Well so propose us your solution.
>
> Okay, I promised not to invent a solution but it's one of "those"  
> problems that I've thought about for a while in the past so let's  
> see. Here is how I would address the problem of implementing full  
> closures in Squeak:

Well at a quick look it appears plausible - but I have a much simpler  
idea. Eliot solved this problems in 1987 - in fact I *think* he was  
the first so to do but wouldn't bet any large amount of money - and  
the basics are described in his seminal paper from the 87 OOPSLa  
proceedings.

Since he is currently employed to do work in Squeak it seems entirely  
reasonable to me to see if he would (re)solve the problem for us.

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Decafalon (n.): The grueling event of getting through the day  
consuming only things that are good for you.



Reply | Threaded
Open this post in threaded view
|

Re: Implementing closures

Paolo Bonzini-2
tim Rowledge wrote:

>
> On 19-Dec-07, at 8:19 PM, Andreas Raab wrote:
>
>> Mathieu Suen wrote:
>>> Well so propose us your solution.
>>
>> Okay, I promised not to invent a solution but it's one of "those"
>> problems that I've thought about for a while in the past so let's see.
>> Here is how I would address the problem of implementing full closures
>> in Squeak:
>
> Well at a quick look it appears plausible - but I have a much simpler
> idea. Eliot solved this problems in 1987 - in fact I *think* he was the
> first so to do but wouldn't bet any large amount of money - and the
> basics are described in his seminal paper from the 87 OOPSLa proceedings.

Note that Scheme interpreters have done this earlier than 1987 probably;
Eliot was the first to bring the full power of lambdas to Smalltalk.

GNU Smalltalk's closures more or less follow the same style that Andreas
outlined, except that as far as I understood he doesn't need
BlockClosure objects because he keeps the bytecodes in the
CompiledMethod rather than extracting them into a CompiledBlock.  This
makes sense given Squeak's Smalltalk-80 legacy, and it looks like
BrouHaHa did the same.

A very useful optimization is to implement copying blocks.  I've never
found the time to implement it in GNU Smalltalk, but it should give
interesting speedups.

Paolo


Reply | Threaded
Open this post in threaded view
|

Re: 3.9 vs. 3.10 : Closures, fixTemps

Mathieu SUEN
In reply to this post by Andreas.Raab

On Dec 20, 2007, at 1:55 AM, Andreas Raab wrote:

> Mathieu Suen wrote:
>> Sorry I made a mistake in the universe browser. It is now fix
>
> Indeed much better now. I'm getting halfways through now with  
> recompiling everything but now it dies in the middle of recompiling  
> Preferences (you can try this by executing "Preferences  
> compileAll"). Any ideas?
>
> Cheers,
>  - Andreas
>

It work for me which version do you use?

        Mth




Reply | Threaded
Open this post in threaded view
|

Re: Implementing closures (was: Re: 3.9 vs. 3.10 : Closures, fixTemps)

Klaus D. Witzel
In reply to this post by Andreas.Raab
On Thu, 20 Dec 2007 05:19:33 +0100, Andreas Raab wrote:

> Mathieu Suen wrote:
>> Well so propose us your solution.
>
> Okay, I promised not to invent a solution but it's one of "those"  
> problems that I've thought about for a while in the past so let's see.  
> Here is how I would address the problem of implementing full closures in  
> Squeak:
>
> 1) First, I would fix the "attempt to evaluate a block that is already  
> evaluated" problem. That's about ten lines of code in the VM - if you  
> look at primitiveValue[withArgs] you'll find that we fail if the  
> CallerIndex is non-nil. Instead of failing, I'd clone the original  
> context and continue as usual.
>
> At this point you'd be able to execute code like:
>
>    | v |
>    fac := [v > 0 ifTrue:[1] ifFalse:[v := v-1. fac value * (v+1)]].
>    fac value: 10.
>
> which allows recursive evaluation but without block args

Did you mean

     | v |
     v := 10.
     fac := [v > 0 ifFalse:[1] ifTrue:[v := v-1. fac fixTemps clone value *  
(v+1)]].
     fac clone value

I confess that I copied the idea from Self's view on method activation (a  
clone of a template :)

But then, how'd that be on Smalltalks other than Squeak, i.e. if a  
Seasider creates+tests such code with Squeak and later runs it on another  
Seaside-capable VM? Looks like opening the cross-Smalltalk Hunting Season  
:(

> (since they get hacked in some terrible ways).
>
> 2) Next, I'd deal with block variables (temps and args). Instead of  
> sharing the method contexts, blocks would store their own temps and  
> access them via tempAt:. So that for example code like here:
>
>    self do:[:v| | v2 | v2 := v squared. v2].
>
> would be compiled into to:
>
>    self do:[:v|
>      thisContext push: nil. "allocate v2"
>      thisContext tempAt: 2 "v2" put: (thisContext tempAt: 1 "v") squared.
>      thisContext tempAt: 2.
>    ].

Sure, that'd be an easy one for the compiler+decompiler guild.

> This would be slower than what we have today but obviously, the pattern  
> "thisContext tempAt:" is a prime candidate for optimization.

AFAIK there's no bytecode which pushes/pops temps in *activeContext*, only  
in *homeContext* (and so the main reason behind this discussion). That  
looks like a major change to VM.

> At this point we'd be able to run the following correctly:
>
> fac [:v| v = 0 ifTrue:[1] ifFalse:[ v * (fac value: v-1)].

This statement does not parse. Can you reformulate without syntax error.

> The implementation would be pretty straightforward too, since all you'd  
> have to do is to add BlockVariableNode that generates tempAt: messages  
> (plus some initialization). Very, very straightforward.
>
> 3) Next, I would deal with "outer" state like here:
>
>    self do:[:x|
>      x do:[:y| x * y]
>    ].
>
> This is probably the hardest part since dealing with "non-method  
> closed-over state" can be tricky due to life-time issues. Anyway, for  
> starters I would just add a hidden temporary "outerContext" for all  
> blocks that is just a temp like any other such that the compiler can  
> generate code like:
>
>    self do:[:x|
>      x do:[:y|
>        ((thisContext tempAt: 1) "outerContext" tempAt: 1 "x") *
>          (thisContext tempAt: 2) "y"
>      ].
>    ].

Sort of "outerContext" is already part of the BlockClosure handling with  
NewCompiler, there it's an instance of ClosureEnvironment.

> At this point (I think - please correct me if I'm missing something) we  
> have *complete* closure semantics in a straightforward way.

I would like to see comment(s) on the above from Marcus, but he's  
currently not subscribed to squeak-dev (cc'ed him anyways).

> What remains is optimization.

Bryce & Marcus & Math & my discussed optimizing BlockClosure+bytecodes  
some time ago, if that's of interest

- http://www.google.com/search?&q=Newcompiler+bytecode+recycling+closure

> 4) Lastly, optimization.

During the discussion we came to the point that context recycling, which  
is interrupted by explicit and implicit #pushActiveContext, would no  
longer be hindered because BlockClosure seems to be a complete replacement  
for BlockContext. By that time it looked like a very promising speed-up.

/Klaus

> I would start with the obvious push/popBlockTemp bytecodes which would  
> bring all of the above up to par with current Squeak (except (3) which  
> could still be slower). Finally, one might look at the life-time of  
> closed-over state - it is certainly not necessary to preserve the entire  
> outer context so there may be other things that could be done to fix it.
>
> In any case, the above looks pretty simple and straightforward. Wouldn't  
> you agree?
>
> Cheers,
>    - Andreas
>
>



Reply | Threaded
Open this post in threaded view
|

Re: Implementing closures (was: Re: 3.9 vs. 3.10 : Closures, fixTemps)

Mathieu SUEN
In reply to this post by Andreas.Raab
Your idea is quite the same than the one from the NewCompiler.
In your idea #tempsAt: will fetch temps inside an array of an instance  
variable of the BlockContext.
In the NewCompiler we have the same and we call this array a  
ClosureEnvironment.

As you said storing or pushing from temp is prim candidate. I have  
implement 2 bytecodes pushing and storing in ClosureEnvironment.
I also have implement some primitive for createBlock: and stuff like  
that.
The benchmark I have made show that it run 2 time slower but some  
other optimization could be done.

We also don't share the bytecode with the home context. instead we  
create a compiled method that we put in the literal array.

Note that we only create this method when it is needed. For example if  
the block do not reference a outer temp we use the old block context.

Cheers,

On Dec 20, 2007, at 5:19 AM, Andreas Raab wrote:

> Mathieu Suen wrote:
>> Well so propose us your solution.
>
> Okay, I promised not to invent a solution but it's one of "those"  
> problems that I've thought about for a while in the past so let's  
> see. Here is how I would address the problem of implementing full  
> closures in Squeak:
>
> 1) First, I would fix the "attempt to evaluate a block that is  
> already evaluated" problem. That's about ten lines of code in the VM  
> - if you look at primitiveValue[withArgs] you'll find that we fail  
> if the CallerIndex is non-nil. Instead of failing, I'd clone the  
> original context and continue as usual.
>
> At this point you'd be able to execute code like:
>
>  | v |
>  fac := [v > 0 ifTrue:[1] ifFalse:[v := v-1. fac value * (v+1)]].
>  fac value: 10.
>
> which allows recursive evaluation but without block args (since they  
> get hacked in some terrible ways).
>
> 2) Next, I'd deal with block variables (temps and args). Instead of  
> sharing the method contexts, blocks would store their own temps and  
> access them via tempAt:. So that for example code like here:
>
>  self do:[:v| | v2 | v2 := v squared. v2].
>
> would be compiled into to:
>
>  self do:[:v|
>    thisContext push: nil. "allocate v2"
>    thisContext tempAt: 2 "v2" put: (thisContext tempAt: 1 "v")  
> squared.
>    thisContext tempAt: 2.
>  ].
>
> This would be slower than what we have today but obviously, the  
> pattern "thisContext tempAt:" is a prime candidate for optimization.  
> At this point we'd be able to run the following correctly:
>
> fac [:v| v = 0 ifTrue:[1] ifFalse:[ v * (fac value: v-1)].
>
> The implementation would be pretty straightforward too, since all  
> you'd have to do is to add BlockVariableNode that generates tempAt:  
> messages (plus some initialization). Very, very straightforward.
>
> 3) Next, I would deal with "outer" state like here:
>
>  self do:[:x|
>    x do:[:y| x * y]
>  ].
>
> This is probably the hardest part since dealing with "non-method  
> closed-over state" can be tricky due to life-time issues. Anyway,  
> for starters I would just add a hidden temporary "outerContext" for  
> all blocks that is just a temp like any other such that the compiler  
> can generate code like:
>
>  self do:[:x|
>    x do:[:y|
>      ((thisContext tempAt: 1) "outerContext" tempAt: 1 "x") *
>        (thisContext tempAt: 2) "y"
>    ].
>  ].
>
> At this point (I think - please correct me if I'm missing something)  
> we have *complete* closure semantics in a straightforward way. What  
> remains is optimization.
>
> 4) Lastly, optimization. I would start with the obvious push/
> popBlockTemp bytecodes which would bring all of the above up to par  
> with current Squeak (except (3) which could still be slower).  
> Finally, one might look at the life-time of closed-over state - it  
> is certainly not necessary to preserve the entire outer context so  
> there may be other things that could be done to fix it.
>
> In any case, the above looks pretty simple and straightforward.  
> Wouldn't you agree?
>
> Cheers,
>  - Andreas
>

        Mth




Reply | Threaded
Open this post in threaded view
|

Re: Implementing closures

Jecel Assumpcao Jr
In reply to this post by timrowledge
Tim Rowledge wrote:
> Well at a quick look it appears plausible - but I have a much simpler  
> idea. Eliot solved this problems in 1987 - in fact I *think* he was  
> the first so to do but wouldn't bet any large amount of money - and  
> the basics are described in his seminal paper from the 87 OOPSLa  
> proceedings.

Well, I solved this problem by accident in 1984:

http://www.lsi.usp.br/~jecel/st84.txt

I didn't pay enough attention to the blue book and never considered the
possibility that Smalltalk-80 didn't have full closures. Of course,
since nobody was able to use my design Eliot's should be considered as
the first. Though the text in the above link says this was just a "paper
design", the main ideas were actually tested in a program writetn in
TI99/4A Extended BASIC.

-- Jecel

Reply | Threaded
Open this post in threaded view
|

Re: Implementing closures (was: Re: 3.9 vs. 3.10 : Closures, fixTemps)

Marcus Denker
In reply to this post by Klaus D. Witzel
Hi,

I am busy with writing my thesis right now... so it might take a while  
till I can answer.

I will try to write something over christmas to explain why I actually  
like Anthony Hannan's
design of the NewCompiler (that it is split in SmaCC-arser, RB-
AST,..., IRBuilder) even
though it is slower in compiling code then the old compiler.

Sadly do not think that I can take part in any lengthy email-list-
discussion right now, this has
to wait untill March 08.

        Marcus

On 20.12.2007, at 11:53, Klaus D. Witzel wrote:

> On Thu, 20 Dec 2007 05:19:33 +0100, Andreas Raab wrote:
>
>> Mathieu Suen wrote:
>>> Well so propose us your solution.
>>
>> Okay, I promised not to invent a solution but it's one of "those"  
>> problems that I've thought about for a while in the past so let's  
>> see. Here is how I would address the problem of implementing full  
>> closures in Squeak:
>>
>> 1) First, I would fix the "attempt to evaluate a block that is  
>> already evaluated" problem. That's about ten lines of code in the  
>> VM - if you look at primitiveValue[withArgs] you'll find that we  
>> fail if the CallerIndex is non-nil. Instead of failing, I'd clone  
>> the original context and continue as usual.
>>
>> At this point you'd be able to execute code like:
>>
>>   | v |
>>   fac := [v > 0 ifTrue:[1] ifFalse:[v := v-1. fac value * (v+1)]].
>>   fac value: 10.
>>
>> which allows recursive evaluation but without block args
>
> Did you mean
>
>    | v |
>    v := 10.
>    fac := [v > 0 ifFalse:[1] ifTrue:[v := v-1. fac fixTemps clone  
> value * (v+1)]].
>    fac clone value
>
> I confess that I copied the idea from Self's view on method  
> activation (a clone of a template :)
>
> But then, how'd that be on Smalltalks other than Squeak, i.e. if a  
> Seasider creates+tests such code with Squeak and later runs it on  
> another Seaside-capable VM? Looks like opening the cross-Smalltalk  
> Hunting Season :(
>
>> (since they get hacked in some terrible ways).
>>
>> 2) Next, I'd deal with block variables (temps and args). Instead of  
>> sharing the method contexts, blocks would store their own temps and  
>> access them via tempAt:. So that for example code like here:
>>
>>   self do:[:v| | v2 | v2 := v squared. v2].
>>
>> would be compiled into to:
>>
>>   self do:[:v|
>>     thisContext push: nil. "allocate v2"
>>     thisContext tempAt: 2 "v2" put: (thisContext tempAt: 1 "v")  
>> squared.
>>     thisContext tempAt: 2.
>>   ].
>
> Sure, that'd be an easy one for the compiler+decompiler guild.
>
>> This would be slower than what we have today but obviously, the  
>> pattern "thisContext tempAt:" is a prime candidate for optimization.
>
> AFAIK there's no bytecode which pushes/pops temps in  
> *activeContext*, only in *homeContext* (and so the main reason  
> behind this discussion). That looks like a major change to VM.
>
>> At this point we'd be able to run the following correctly:
>>
>> fac [:v| v = 0 ifTrue:[1] ifFalse:[ v * (fac value: v-1)].
>
> This statement does not parse. Can you reformulate without syntax  
> error.
>
>> The implementation would be pretty straightforward too, since all  
>> you'd have to do is to add BlockVariableNode that generates tempAt:  
>> messages (plus some initialization). Very, very straightforward.
>>
>> 3) Next, I would deal with "outer" state like here:
>>
>>   self do:[:x|
>>     x do:[:y| x * y]
>>   ].
>>
>> This is probably the hardest part since dealing with "non-method  
>> closed-over state" can be tricky due to life-time issues. Anyway,  
>> for starters I would just add a hidden temporary "outerContext" for  
>> all blocks that is just a temp like any other such that the  
>> compiler can generate code like:
>>
>>   self do:[:x|
>>     x do:[:y|
>>       ((thisContext tempAt: 1) "outerContext" tempAt: 1 "x") *
>>         (thisContext tempAt: 2) "y"
>>     ].
>>   ].
>
> Sort of "outerContext" is already part of the BlockClosure handling  
> with NewCompiler, there it's an instance of ClosureEnvironment.
>
>> At this point (I think - please correct me if I'm missing  
>> something) we have *complete* closure semantics in a  
>> straightforward way.
>
> I would like to see comment(s) on the above from Marcus, but he's  
> currently not subscribed to squeak-dev (cc'ed him anyways).
>
>> What remains is optimization.
>
> Bryce & Marcus & Math & my discussed optimizing BlockClosure
> +bytecodes some time ago, if that's of interest
>
> - http://www.google.com/search?&q=Newcompiler+bytecode+recycling+closure
>
>> 4) Lastly, optimization.
>
> During the discussion we came to the point that context recycling,  
> which is interrupted by explicit and implicit #pushActiveContext,  
> would no longer be hindered because BlockClosure seems to be a  
> complete replacement for BlockContext. By that time it looked like a  
> very promising speed-up.
>
> /Klaus
>
>> I would start with the obvious push/popBlockTemp bytecodes which  
>> would bring all of the above up to par with current Squeak (except  
>> (3) which could still be slower). Finally, one might look at the  
>> life-time of closed-over state - it is certainly not necessary to  
>> preserve the entire outer context so there may be other things that  
>> could be done to fix it.
>>
>> In any case, the above looks pretty simple and straightforward.  
>> Wouldn't you agree?
>>
>> Cheers,
>>   - Andreas
>>
>>
>
>

        Marcus
--
Marcus Denker  --  [hidden email]
http://www.iam.unibe.ch/~denker




Reply | Threaded
Open this post in threaded view
|

Re: Implementing closures

timrowledge
In reply to this post by Paolo Bonzini-2

On 20-Dec-07, at 12:13 AM, Paolo Bonzini wrote:
>
> Note that Scheme interpreters have done this earlier than 1987  
> probably; Eliot was the first to bring the full power of lambdas to  
> Smalltalk.

Well yes, we *are* talking about Smalltalk here, after all.

I think BHH kept the bytecodes all in the CM but used a Closure object  
in place of using the copyBlock bytecode and then a blockcontext was  
created each time the closure was evaluated. But it is a very long  
time since I last did any active development of that VM, most likely  
1991. Too long to remember details!

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Strange OpCodes: EIV: Erase IPL Volume



12