Immediate closing of iterators

Brendan Eich brendan at mozilla.org
Wed Dec 20 17:33:31 PST 2006


On Dec 20, 2006, at 3:49 PM, Chris Hansen wrote:

> In this case the generator shouldn't be closed.  If gen2 had been  
> defined as
>
> function gen2() {
>  return gen1();
> }
>
> I would expect that it should.

This is, as you say, asking for a full reference graph analysis.  We  
don't propose that.

Consider two cases:

1. The Mozilla bug Jeff Thompson mentioned, https:// 
bugzilla.mozilla.org/show_bug.cgi?id=349326, wants only a generator- 
iterator created "under the hood" to be closed promptly:

   for (i in o)
     break;

where o denotes some object that's not an iterator -- an object that  
does not have an iterator::get method at all, or whose iterator::get  
returns a different object (o is the iterable, the returned object is  
its iterator).

In this case, the for-in loop can tell whether it is calling a well- 
known iterator::get native method, or the default used when there is  
no o.iterator::get, whose result is newborn and where the result  
can't escape.  The returned iterator could be a generator-iterator:

   o.iterator::get = function () { yield 1; yield 2 }

The internal Generator class's iterator::get method (called  
__iterator__ in JS1.7 in Firefox, for want of full namespace support)  
is immutable (in ECMA-262 terms a generator-iterator's iterator::get  
property has the ReadOnly and DontDelete attributes set).  This  
method returns its |this| parameter, since a generator is an iterator.

The for-in loop can tell whether o's iterator::get (mutable, but it  
doesn't matter for this analysis) references a generator-function.   
It knows that the generator-function will return a new generator- 
iterator that can't escape, because the Generator class prototype's  
iterator::get method can't be replaced or shadowed, so its return  
value can't be spied on.  Therefore in this case, the implementation  
can guarantee prompt close without a full heap scan.

2. To handle the

   for (i in gen())
     break;

case, the implementation would need to recognize gen, whether via  
static analysis in strict mode or in any sufficiently optimizing  
implementation, or dynamically in standard mode or in cases where  
static analysis can't decide, as a generator function.  At this point  
the analysis for case 1 applies.

Anything else (function returning generator-iterator that might have  
escaped to a global, etc.) defeats the prompt close promise.

Does this work for the cases users care about?  I believe it does,  
but welcome counterexamples.

/be



More information about the Es4-discuss mailing list