[squeak-dev] modifying copied context vars

Eliot Miranda eliot.miranda at gmail.com
Fri Mar 25 05:26:45 UTC 2016


Hi Nicolai,

> On Mar 24, 2016, at 1:53 AM, Nicolai Hess <nicolaihess at gmail.com> wrote:
> 
> Hello,
> 
> we have a failing test (OCClosureCompilerTest>>#testDebuggerTempAccess)
> (fails since spur, but not related - I think).
> 
> A simple example to reproduce the behavior:
> | local1 remote1|
> remote1:=4.
> local1 :=3.
> [:i | |c|
>     c := local1.
>     remote1 := i.
>     i halt.
>     "local1:=25.  <-- evaluate during debugging"
>      ] value:1.
> Transcript show:local1;cr.
> Transcript show:remote1;cr.
> (Executing this code and evaluating "local:=25" after the debugger halts for 
> "i halt" will modify the var "remote1" instead of "local1", as this is a vector tempvar , proceeding
> the execution will crash at accessing the remote1 value).
> 
> 
> The purpose of the testDebuggerTempAccess test case is, evaluating code
> that changes the value of a copied temp var *does not* change the value of
> this var in the outer context. (see comment in the test case:
> "this is not 25 as the var is a local, non escaping variable that was copied into the block,
>     If the compiler would have known about the write, it would have made the var escaping".
> )
> 
> But the implementation (OCCopyingTempVariable>>#writeFromContext: aContext scope: contextScope value: aValue)
> explicitly iterates through all outer context(s) and changes the vars as well.
> 
> 1. Question: Who is right?

What do you mean?  Because the closure model is as it is (for very good reason) the computer copies temporaries whose values cannot change during the execution of a block into that block if the block references the variable.  If the debugger is to support updating such copied variables then it must create the illusion of "the variable being updated" because there isn't just one variable.


> But the reason why the test actually fails is different. It is because evaluating
> the code that modifies the var "local1:=25" ends up to a call
> aContext tempAt: self indexFromIR put: aValue
> but the index (indexFromIR) can be different for every context (method context / inner block
> context(s)).

Right.

> 
> 2. Question: should the index be always the same?

How can it be?  If, for example, a nullary block makes use of a copied variable and has no local temps then that variable will end up with index 0, no matter its indices in outer scopes.  Surely you're not proposing padding the block with unused variables just so copied variables can have the same index?

> 
> thanks inadvance
> 
> Nicolai
> 
> 
> ps: since spur (resp. compiler changes that were done for new spur images), the index of tempvars can be different.
> In pre-spur, this testcase modifies an outer context var, but one that isn't checked (the argument "two"), therefore
> the test succeed. In spur, this testcase modifes a different outer context var "remote1", and the test
> fails.


Since Sour hasn't changed the compiler there looks to be a bug.  Sour has changed the identityHash size a lot from IIRC 11 bits to 22.  So hashed collections can end up with different enumerations.  But that shouldn't affect the ordering assigned to temps in the compiler.  I suggest tracking down why the code is different in Spur is a very important thing to do.

HTH

Eliot
_,,,^..^,,,_ (phone)

PS if you want to understand why copied variables are so important in the closure model you need to understand context-to-stack mapping and the overhead that not copying temps adds to returns in a context-to-stack mapping VM.  It's not obvious but I hope my blog does an ok job of explaining something alas complex but extremely important for performance.


More information about the Squeak-dev mailing list