зеркало из https://github.com/mozilla/gecko-dev.git
Bug 341877: Infrastructure to properly mark native iterator state during GC without changing public API. r=brendan
This commit is contained in:
Родитель
e03eb62472
Коммит
2d2124eb15
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче