Am 28.06.2013 um 23:09 schrieb Sven Van Caekenberghe <sven@stfx.eu>:
On 28 Jun 2013, at 22:42, Marcus Denker <marcus.denker@inria.fr> wrote:
On Jun 28, 2013, at 9:26 PM, Sven Van Caekenberghe <sven@stfx.eu> wrote:
Hi,
Does the closure returned from
| foo | foo := #( data 1 2 3 ). [ :x | x + 1 ]
close over foo ? No.
Since foo is not used, it should not, right ? right. if we get the AST of your method
ast := (TT>>#tt) ast. (ast scope lookupVar: 'foo') isEscaping
--> false.
OK, that seems OK.
The reason I was asking was because I wanted to know if this JavaScript bug would hit us as well:
http://point.davidglasser.net/2013/06/27/surprising-javascript-memory-leak.h...
It is slightly more complicated than the basic question of closing over an unreferenced variable though.
I just can't figure out a way to quickly test it in Pharo. I think it is worth looking into.
I don't think it is easy to do in pharo. The problem in the article only works because a string primitive is directly referenced. Primitives are copied as a whole when assigned. An object holding that huge string wouldn't be a problem because the enclosed activation record would just hold a reference to that object. As we don't have primitive types in smalltalk the problem doesn't apply IMHO. So his example is the combination that on every function invocation an activation record is created and the primitive string is copied into. The chain of the calling activation records _is_ the lexical scope IIRC. So tweaking the enclosed environment would need to copy and alter the activation records. And to be honest I fail to see why having foo in the scope is wrong. I mean why is it an error if it is there? In my opinion it is normal that foo is there but it can be an optimization to get rid of it, no? And I'm not sure it is easy in most cases to determine the liveliness of a variable. Norbert
Now the question is what the inspector of the context should show?
e.g.
tt | foo | foo := #( data 1 2 3 ). ^[ :x | x + 1. thisContext inspect ]
if we now execute:
TT new tt value: 2
the inspector pops up and shows both x and foo.
The reason is that we need to decide what to show
1) the variable that is stored in the context 2) all *possible* variables that I can write in the block and recompile and it works.
1) is this: ast statements last value scope localTempNames
2) is this:
ast statements last value scope allTemps
Opal implements is like this because the old Compiler (DebuggerMethodMap) did it like this. At first I thought this is wrong and I wanted to change it. But then I thought that it is not that wrong: in the debugger the inspector of the context shows not just the vars that are in the context, but all that *could* be there. All where I can lookup and get a result, e.g.
ast statements last value scope lookupVar: 'foo'
Thus all those that I *could* write in the code inside the block.
I am not sure, though⦠maybe we should change it.
Marcus
But it seems that the outer context of the block closure knows about foo, although the value seems nil.
And if it closes over foo, foo's value/binding won't be GC-ed so long as there is a reference to the block closure, even though foo is not practically accessible.
Sven