Hi Levente,
2011/4/26 Levente Uzonyi
<[hidden email]>
Hi Eliot,
On Tue, 26 Apr 2011, Eliot Miranda wrote:
Hi Levente,
try out the latest VMs. They don't fix the bugs, but do change the symptoms. e.g. in
c := [ 3 + PartialContinuationNotification signal ]
on: PartialContinuationNotification
do: [ :not | not continuation ].
c value: 4. "==> 7"
there is now an MNU of #+ since 3 has been replaced by a MethodContext.
So if I could ask you could dig in again, that would help.
the symptoms are much better now. The cause of the MNU seems to be that the copied contexts have some "junk" at their indexable slots. Implementing ContextPart >> #copyTo: as below solves (hides) the problem.
ContextPart >> copyTo: aContext
"Copy self and my sender chain down to, but not including, aContext. End of copied chain will have nil sender."
| copy |
self == aContext ifTrue: [ ^nil ].
copy := self copy.
"Cog doesn't copy the temps properly, so copy them here."
1 to: self size do: [ :i | copy at: i put: (self at: i) ].
sender ifNotNil: [ copy privSender: (sender copyTo: aContext) ].
^copy
To reproduce the "junk" copying bug, evaluate the following:
| context |
context := thisContext copy.
{ context. context copy } explore
The first context's first slot will be nil, while the second context's first slot will point to the sender context. Actually the indexable slots are filled with the values of the fixed slots, that's why the sender context is at the first indexable slot of the second context. Here's an example with more indexable slots:
| context a b c d e |
context := thisContext copy.
a := b := c := d := e := context.
{ context. context copy } explore.
{ a. b. c. d. e } "This is here to avoid compiler complaints."
Hmm... the above behavior is intentional and correct in that to speed up context-to-stack mapping Cog makes no guarantee to preserve the values of temporary values after a context has returned. You'll notice that the entire closure scheme is centered around this, in that temporaries that must outlive their dynamic extent for the correct working of blocks are either copied into blocks (as copied values) or stored into remote temp vectors, hence breaking any dependence on the temporaries in enclosing contexts.
If you can live with this restriction then instead of stating
"Cog doesn't copy the temps properly, so copy them here."
in your reimplementation of copyTo: it would be more accurate to state
"Cog doesn't preserve non-closed-over temps beyond their dynamic extent, so copy them here."
or some such.
Note that Cog /does/ preserve arguments. However, I've clearly still got some bug because look at the following. In the copy the arguments ba1 & ba2 (1 & 2) are in the wrong place on the stack. Sigh...
[:ba1 :ba2| | context a b c d e |
context := thisContext copy.
a := b := c := d := e := context.
{ context. context copy } explore.
{ a. b. c. d. e } "This is here to avoid compiler complaints."] value: 1 value: 2
Levente
thanks!
best,
Eliot