Non-local returns with promises (was: Re: Thoughts on a concurrent Squeak VM)

Rob Withers reefedjib at yahoo.com
Sun Nov 4 14:27:10 UTC 2007


----- Original Message ----- 
From: "Igor Stasenko" <siguctua at gmail.com>

> I'm personally much more worrying about non-local returns.

As an example of the problem of non-local return, let's look at this simple 
method:

foo: bar

    bar ifTrue: [^ 1].
    self snafu.
    ^ 0

If bar is eventual, we don't know at the time of invocation whether the 
method will exit through the non-local
return or through the return at the end of the method.

How to best deal with this?

My thought is that the context needs to become eventual, be sent as a lambda
to the bar promise, and the context return a promise.  The return will check
to see if there is a resolver on the context and #resolve: it with the
appropriate return value.  The lambda needs to be all sequential code from
the point where a message is sent to the promise that includes a block as an
argument to the end of the context.  So the lambda would be:

f := [:barVow |
    barVow ifTrue: [^1].
    self snafu.
    ^ 0]

and we would send:
    ^ bar whenResolved: f.

So the challenge here would be in capturing the lambda and in effect 
rewriting the code for this method, on the fly.  The lambda is just a one 
arg blockContext, where the ip points to the pushTemp: 0.

17 <10> pushTemp: 0
18 <99> jumpFalse: 21
19 <76> pushConstant: 1
20 <7C> returnTop
21 <70> self
22 <D0> send: snafu
23 <87> pop
24 <75> pushConstant: 0
25 <7C> returnTop

and the two return bytecodes, would each need to resolve the promise 
returned.  This needs to become something like the following, where lines 
28-36 is the original block with three rewrites:
    first, pushTemp: 1 instead of pushTemp: 0, since the block arg is a 
separate temp.
    second, the two returnTops needs to become a jumpTo: and a blockReturn, 
so we can resolve the promise.

21 <10> pushTemp: 0
22 <89> pushThisContext:
23 <76> pushConstant: 1
24 <C8> send: blockCopy:
25 <A4 0A> jumpTo: 37
27 <69> popIntoTemp: 1
28 <11> pushTemp: 1
29 <99> jumpFalse: 32
30 <76> pushConstant: 1
31 <93> jumpTo: 36
32 <70> self
33 <D1> send: snafu
34 <87> pop
35 <75> pushConstant: 0
36 <7D> blockReturn
37 <E0> send: whenResolved:
38 <7C> returnTop

Of course, we don't want to modify the original method, since another call 
to it may not involve a promise.  So we are looking at creating a new 
MethodContext, which we rewrite to create a new BlockContext defined from 
lines 22-25 through 36 above.  For every non-local return method when called 
with a promise.

What do you think?

Rob 




More information about the Squeak-dev mailing list