No need to lookup parent/proto for iterator objects, and cache the last free one (bug 558058, r=brendan).

This commit is contained in:
Andreas Gal 2010-04-08 07:53:09 -07:00
Родитель b3d36a925a
Коммит 5c4f856ea3
3 изменённых файлов: 21 добавлений и 9 удалений

Просмотреть файл

@ -155,6 +155,8 @@ JSThreadData::mark(JSTracer *trc)
void
JSThreadData::purge(JSContext *cx)
{
cachedIteratorObject = NULL;
purgeGCFreeLists();
js_PurgeGSNCache(&gsnCache);

Просмотреть файл

@ -567,6 +567,12 @@ struct JSThreadData {
jsuword nativeEnumCache[NATIVE_ENUM_CACHE_SIZE];
/*
* One-entry deep cache of iterator objects. We deposit here the last
* iterator that was freed in JSOP_ENDITER.
*/
JSObject *cachedIteratorObject;
bool init();
void finish();
void mark(JSTracer *trc);

Просмотреть файл

@ -391,16 +391,19 @@ js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp)
if (JSVAL_IS_VOID(*vp)) {
default_iter:
/*
* Fail over to the default enumerating native iterator.
*
* Create iterobj with a NULL parent to ensure that we use the
* correct scope chain to lookup the iterator's constructor. Since
* we use the parent slot to keep track of the iterable, we must
* fix it up after.
* Fail over to the default enumerating native iterator. These objects
* never escape, so we don't care for the proper parent or proto to
* be set. Furthermore we re-use the last cached iterator object, if
* possible.
*/
iterobj = js_NewObject(cx, &js_IteratorClass, NULL, NULL);
if (!iterobj)
return false;
iterobj = JS_THREAD_DATA(cx)->cachedIteratorObject;
if (iterobj) {
JS_THREAD_DATA(cx)->cachedIteratorObject = NULL;
} else {
iterobj = js_NewObjectWithGivenProto(cx, &js_IteratorClass, NULL, NULL);
if (!iterobj)
return false;
}
/* Store in *vp to protect it from GC (callers must root vp). */
*vp = OBJECT_TO_JSVAL(iterobj);
@ -434,6 +437,7 @@ js_CloseIterator(JSContext *cx, jsval v)
if (clasp == &js_IteratorClass) {
js_CloseNativeIterator(cx, obj);
JS_THREAD_DATA(cx)->cachedIteratorObject = obj;
}
#if JS_HAS_GENERATORS
else if (clasp == &js_GeneratorClass) {