Bug 341877: Infrastructure to properly mark native iterator state during GC without changing public API. r=brendan

This commit is contained in:
igor.bukanov%gmail.com 2006-06-19 22:53:51 +00:00
Родитель e03eb62472
Коммит 2d2124eb15
7 изменённых файлов: 54 добавлений и 51 удалений

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

@ -649,6 +649,9 @@ struct JSContext {
/* Top of the GC mark stack. */ /* Top of the GC mark stack. */
void *gcCurrentMarkNode; void *gcCurrentMarkNode;
#endif #endif
/* List of native iterator states, needed for marking id arrays. */
JSNativeIteratorState *nativeIteratorStates;
}; };
#define JS_THREAD_ID(cx) ((cx)->thread ? (cx)->thread->id : 0) #define JS_THREAD_ID(cx) ((cx)->thread ? (cx)->thread->id : 0)

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

@ -2449,6 +2449,9 @@ restart:
if (acx->sharpObjectMap.depth > 0) if (acx->sharpObjectMap.depth > 0)
js_GCMarkSharpMap(cx, &acx->sharpObjectMap); js_GCMarkSharpMap(cx, &acx->sharpObjectMap);
if (acx->nativeIteratorStates)
js_MarkNativeIteratorStates(cx, acx->nativeIteratorStates);
acx->cachedIterObj = NULL; acx->cachedIterObj = NULL;
} }

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

@ -76,33 +76,6 @@ extern const char js_throw_str[]; /* from jsscan.h */
#error JS_INITIAL_NSLOTS must be greater than JSSLOT_ITER_FLAGS. #error JS_INITIAL_NSLOTS must be greater than JSSLOT_ITER_FLAGS.
#endif #endif
static uint32
iterator_mark(JSContext *cx, JSObject *obj, void *arg)
{
jsval state, parent;
JSObject *iterable;
/* Avoid double work if js_CloseNativeIterator was called on obj. */
state = obj->slots[JSSLOT_ITER_STATE];
if (JSVAL_IS_VOID(state))
return 0;
parent = obj->slots[JSSLOT_PARENT];
if (!JSVAL_IS_NULL(state) && !JSVAL_IS_PRIMITIVE(parent)) {
iterable = JSVAL_TO_OBJECT(parent);
#if JS_HAS_XML_SUPPORT
if ((JSVAL_TO_INT(obj->slots[JSSLOT_ITER_FLAGS]) & JSITER_FOREACH) &&
OBJECT_IS_XML(cx, iterable)) {
((JSXMLObjectOps *) iterable->map->ops)->
enumerateValues(cx, iterable, JSENUMERATE_MARK, &state,
NULL, NULL);
} else
#endif
OBJ_ENUMERATE(cx, iterable, JSENUMERATE_MARK, &state, NULL);
}
return 0;
}
static void static void
iterator_close(JSContext *cx, JSObject *obj) iterator_close(JSContext *cx, JSObject *obj)
{ {
@ -137,8 +110,7 @@ JSExtendedClass js_IteratorClass = {
JSCLASS_HAS_CACHED_PROTO(JSProto_Iterator), JSCLASS_HAS_CACHED_PROTO(JSProto_Iterator),
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
NULL, NULL, NULL, NULL, JSCLASS_NO_OPTIONAL_MEMBERS },
NULL, NULL, iterator_mark, NULL },
NULL, NULL, NULL, iterator_close, NULL, NULL, NULL, iterator_close,
JSCLASS_NO_RESERVED_MEMBERS JSCLASS_NO_RESERVED_MEMBERS
}; };

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

@ -3673,10 +3673,12 @@ js_SetIdArrayLength(JSContext *cx, JSIdArray *ida, jsint length)
} }
/* Private type used to iterate over all properties of a native JS object */ /* Private type used to iterate over all properties of a native JS object */
typedef struct JSNativeIteratorState { struct JSNativeIteratorState {
jsint next_index; /* index into jsid array */ jsint next_index; /* index into jsid array */
JSIdArray *ida; /* all property ids in enumeration */ JSIdArray *ida; /* all property ids in enumeration */
} JSNativeIteratorState; JSNativeIteratorState *next; /* double-linked list support */
JSNativeIteratorState **prevp;
};
/* /*
* This function is used to enumerate the properties of native JSObjects * This function is used to enumerate the properties of native JSObjects
@ -3772,6 +3774,13 @@ js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
} }
state->ida = ida; state->ida = ida;
state->next_index = 0; state->next_index = 0;
state->next = cx->nativeIteratorStates;
if (state->next)
state->next->prevp = &state->next;
state->prevp = &cx->nativeIteratorStates;
*state->prevp = state;
*statep = PRIVATE_TO_JSVAL(state); *statep = PRIVATE_TO_JSVAL(state);
if (idp) if (idp)
*idp = INT_TO_JSVAL(length); *idp = INT_TO_JSVAL(length);
@ -3789,28 +3798,43 @@ js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
case JSENUMERATE_DESTROY: case JSENUMERATE_DESTROY:
state = (JSNativeIteratorState *) JSVAL_TO_PRIVATE(*statep); state = (JSNativeIteratorState *) JSVAL_TO_PRIVATE(*statep);
JS_ASSERT(cx->nativeIteratorStates);
JS_ASSERT(*state->prevp == state);
if (state->next) {
JS_ASSERT(state->next->prevp == &state->next);
state->next->prevp = state->prevp;
}
*state->prevp = state->next;
JS_DestroyIdArray(cx, state->ida); JS_DestroyIdArray(cx, state->ida);
JS_free(cx, state); JS_free(cx, state);
*statep = JSVAL_NULL; *statep = JSVAL_NULL;
break; break;
}
return JS_TRUE;
}
case JSENUMERATE_MARK: void
state = (JSNativeIteratorState *) JSVAL_TO_PRIVATE(*statep); js_MarkNativeIteratorStates(JSContext *cx, JSNativeIteratorState *state)
ida = state->ida; {
length = ida->length; jsid *cursor, *end, id;
for (i = 0; i < length; i++) {
jsid id;
id = ida->vector[i]; JS_ASSERT(state);
do {
JS_ASSERT(*state->prevp == state);
cursor = state->ida->vector;
end = cursor + state->ida->length;
for (; cursor != end; ++cursor) {
id = *cursor;
if (JSID_IS_ATOM(id)) { if (JSID_IS_ATOM(id)) {
GC_MARK_ATOM(cx, JSID_TO_ATOM(id)); GC_MARK_ATOM(cx, JSID_TO_ATOM(id));
} else if (JSID_IS_OBJECT(id)) { } else if (JSID_IS_OBJECT(id)) {
GC_MARK(cx, JSID_TO_OBJECT(id), "ida->vector[i]"); GC_MARK(cx, JSID_TO_OBJECT(id), "ida->vector[i]");
} }
} }
break; } while ((state = state->next) != NULL);
}
return JS_TRUE;
} }
JSBool JSBool

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

@ -498,6 +498,14 @@ extern JSBool
js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
jsval *statep, jsid *idp); jsval *statep, jsid *idp);
/*
* js_Enumerate uses this opaque structure to hold its state.
*/
typedef struct JSNativeIteratorState JSNativeIteratorState;
extern void
js_MarkNativeIteratorStates(JSContext *cx, JSNativeIteratorState *state);
extern JSBool extern JSBool
js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
jsval *vp, uintN *attrsp); jsval *vp, uintN *attrsp);

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

@ -119,8 +119,7 @@ typedef enum JSAccessMode {
typedef enum JSIterateOp { typedef enum JSIterateOp {
JSENUMERATE_INIT, /* Create new iterator state */ JSENUMERATE_INIT, /* Create new iterator state */
JSENUMERATE_NEXT, /* Iterate once */ JSENUMERATE_NEXT, /* Iterate once */
JSENUMERATE_DESTROY, /* Destroy iterator state */ JSENUMERATE_DESTROY /* Destroy iterator state */
JSENUMERATE_MARK /* mark opaque iterator state */
} JSIterateOp; } JSIterateOp;
/* Struct typedefs. */ /* Struct typedefs. */

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

@ -5151,9 +5151,6 @@ xml_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
} }
*statep = JSVAL_NULL; *statep = JSVAL_NULL;
break; break;
case JSENUMERATE_MARK:
break;
} }
return JS_TRUE; return JS_TRUE;
} }
@ -5313,9 +5310,6 @@ xml_enumerateValues(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
} }
*statep = JSVAL_NULL; *statep = JSVAL_NULL;
break; break;
case JSENUMERATE_MARK:
break;
} }
return JS_TRUE; return JS_TRUE;
} }