[squeak-dev] Re: Problem with variable capture in blocks or ? #7532

Ken Causey ken at kencausey.com
Mon May 17 18:39:08 UTC 2010


Thanks Eliot.  I should clarify that I am not in fact the source of this
example, killerboy/unoduetre deserves the credit there.

Ken

On Sun, 2010-05-16 at 17:47 -0700, Eliot Miranda wrote:
> 
> 
> On Sun, May 16, 2010 at 3:32 PM, Andreas Raab <andreas.raab at gmx.de>
> wrote:
>         Hi Ken -
>         
>         Very interesting. Looks like an issue with
>         OutOfScopeNotification. The problem appears to be that this
>         code:
>         
>                "..." [ :a | a ].
>                "..." a.
>         
>         generates an OutOfScopeNotification that is being suppressed
>         in workspaces (I'm not exactly sure why that is). This is of
>         course is interesting because of the highly unusual situation
>         of a temp shadowing a global instead of another temp / ivar.
>         For example, this wouldn't compile:
>         
>          | a |
>          [ :a | a ].
>         
>         But stranglely, this does:
>         
>          [ :Object | Object ].
>         
>         so your example code is roughly equivalent to running:
>         
>                b := [ :Object | Object ].
>                c := b value: Object.
>         
>         When you run this line by line it works 'as expected' and when
>         you run it as a single doIt you get the result of c being a
>         "[closure] in UndefinedObject>>DoIt" due to the
>         OutOfScopeNotification.
>         
>         Hope this explains the issue - as for how to fix it, I have no
>         clue :-)
> 
> 
> Yes, the bug is that Encoder>>encodeVariable:sourceRange:ifUnknown:
> doesn't continue from a caught OutOfScopeNotification by answering the
> ifUnknown: action.  Instead it returns the out-of-scope block temp.
>  This is a rather serious compiler bug that I'd left unfixed because
> it only bites in workspaces (apologies) and I didn't have a small
> example to analyse before (thanks Ken!).  The code generated is
> actually equivalent to
> 
> 
>        b := [ :a | a ].
>        c := b value: <temp 0>.
> 
> 
> Since there aren't any temps, temp 0 is top of stack, which just
> happens to be the closure just created by the preceding bytecode.
>  e.g. look at bytecode 49 in the following:
> 
> 
> a := 4. b := [ :a | a ]. c := b value: a. { a. b. c } thisContext
> method symbolic
> 
> 
> The fix is simple.  When an OutOfScopeNotification is caught the
> Encoder should still answer what ever it should for an out of scope
> variable.   In Encoder>>encodeVariable:sourceRange:ifUnknown: the
> statements
> 
> 
> (varNode isTemp and: [varNode scope < 0]) ifTrue: [
> OutOfScopeNotification signal ifFalse: [ ^self notify: 'out of
> scope'].
> ].
> ^ varNode
> 
> 
> should read
> 
> 
> (varNode isTemp and: [varNode scope < 0]) ifTrue:
> [^OutOfScopeNotification signal
> ifTrue: [action value]
> ifFalse: [self notify: 'out of scope']].
> ^varNode
> 
> 
> Find attached:
> 
> 
> !Encoder methodsFor: 'encoding' stamp: 'eem 5/16/2010 17:33'!
> encodeVariable: name sourceRange: range ifUnknown: action
> | varNode |
> varNode := scopeTable
> at: name
> ifAbsent: 
> [(self lookupInPools: name 
> ifFound: [:assoc | varNode := self global: assoc name: name])
> ifTrue: [varNode]
> ifFalse: [^action value]].
> range ifNotNil:
> [name first canBeGlobalVarInitial ifTrue:
> [globalSourceRanges addLast: { name. range. false }]].
> 
> 
> (varNode isTemp and: [varNode scope < 0]) ifTrue:
> [^OutOfScopeNotification signal
> ifTrue: [action value]
> ifFalse: [self notify: 'out of scope']].
> ^varNode! !
> 
> 
> P.S. this is probably applicable to any Squeak bytecode compiler
> (including eToys).  The only change in my closure compiler from
> Andreas' 2003 version was changing "name first isUppercase" to "name
> first canBeGlobalVarInitial".
> 
> 
> 
> 
> P.P.S.  Again Ken, thanks for a comprehensible example.  It always bit
> me in huge doits I was using to analyse the entire system's compiled
> methods, and invariably crashed the VM.  I never took the time to
> isolate the bug, I just fixed the doit and continued.  Turns out to be
> very simple.
> 
> 
> best
> Eliot
> 
> 
>         
>         Cheers,
>          - Andreas
>         
>         
>         
>         
>         On 5/16/2010 12:35 PM, Ken Causey wrote:
>                 Well, it's nothing new but this one has stumped me:
>                 
>                 http://bugs.squeak.org/view.php?id=7532
>                 
>                 Initially I (and Frank) thought the reporter was
>                 mistaken until we
>                 understood that the problem shows up when you execute
>                 the main code all
>                 in one do-it.  I've since modified the original report
>                 to make this
>                 clearer.
>                 
>                 So here it is:
>                 
>                 a := 4.
>                 b := [ :a | a ].
>                 c := b value: a.
>                 
>                 If you SELECT ALL OF THIS AND EXECUTE IT ALL AT ONE
>                 TIME (crucial
>                 detail). The result is that a is 4, b is a
>                 BlockClosure, and c is a
>                 BlockClosure not 4 as expected. Execute each statement
>                 separately and c
>                 is 4.
>                 
>                 Alternately, from a suggestion from jmckeon, if you
>                 specify a different
>                 symbol for the block argument:
>                 
>                 a := 4.
>                 b := [ :d | d ].
>                 c := b value: a.
>                 
>                 when executed all at one time works as you would
>                 expect: a is 4, b is a
>                 BlockClosure, and c is 4. (and d is nil)
>                 
>                 So what's up?
>                 
>                 Ken
>                 
>                 
>                 
>         
>         
>         
> 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 190 bytes
Desc: This is a digitally signed message part
Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20100517/3f58e9fb/attachment.pgp


More information about the Squeak-dev mailing list