Hacker News new | ask | show | jobs
by ChuckMcM 4733 days ago
An excellent catch. The parse tree for the closure should be able to ascertain the reachability of the variables in scope so that fences around particular sets of variables can be established. To do that would require something a bit more sophisticated than a single taint id though. You would really want a taint 'flavor' such that for any closure and in variable in scope of that closure you could defined f(closure, var) which would return turn if that variable cannot be collected. I can't think off the top of my head how you would recycle identifiers without risking temporal tainting (where a new closure in scope with the same id came at a later time and double tainted the variable leaving it essentially uncollectable or collected early. Hmm, or maybe not since their address on the heap will be different you're probably ok with that.

FWIW that is certainly the twisty bits of garbage collected languages.

1 comments

> The parse tree for the closure should be able to ascertain the reachability of the variables in scope so that fences around particular sets of variables can be established.

Sadly it's not quite that simple because of the behavior of `eval` (strictly speaking, direct `eval`): it can leak bindings into the surrounding scope.

The eval case is already being handled, where the entire local scope automatically captured if there is an eval.

It seems like ChuckMcM is describing is reference counting which variables are needed in the closure. His suggestion would fix this memory issue, but probably have a big performance penalty.

Right, but according to sections 10.4.2 and 15.1.2.1.1 of the ECMAScript standard, you only get lexical bindings inside your `eval` if it's literally a call to a thing called `eval`. (Which I believe is what you meant by "direct `eval`".)

So you should be able to statically determine if this is the case, and it's not here.

Nice! You've explained why this 'memory leak' could be by design - blame eval.

In fact, Chrome GC-ing unreferenced variables could break eval if they didn't cover that case.

Only direct `eval` though. As long as you don't see any calls to symbols named `eval`, you can implement this optimization.

See http://stackoverflow.com/questions/8694300/how-eval-in-javas...

Yeah, you could test this in the first example by replacing the string 'interval' with something like "alert(str.length)", and then redefining console.log=eval.

e: nm, I missed pcwalton's point -- when you call eval indirectly it isn't accessing the same scope. So redefining console.log couldn't access local variables like str. (I don't think?)

Correct. Not only is eval not a good idea in general, but it's a very weird beast in javascript. See http://perfectionkills.com/global-eval-what-are-the-options/ for a very complete exposition of its weirdness.
ewww, yuck! Absolutely right about that. So you need to plug the tainting into the code generation perhaps? Suggests that both a reachability test (can the code ever be reached) combined with a taint test (code that can be reached and has this variable in scope). Then there is code that could exist if instantiated but doesn't yet.