зеркало из https://github.com/mozilla/gecko-dev.git
bug 517199 - typed GC free lsists - newborn refactoring. r=brendan
This commit is contained in:
Родитель
f065057d5d
Коммит
2c25587f18
|
@ -2603,12 +2603,10 @@ JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer)
|
|||
JS_PUBLIC_API(JSString *)
|
||||
JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type)
|
||||
{
|
||||
JSString *str;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
JS_ASSERT((uintN) type < (uintN) (GCX_NTYPES - GCX_EXTERNAL_STRING));
|
||||
JS_ASSERT(uintN(type) < JS_EXTERNAL_STRING_LIMIT);
|
||||
|
||||
str = js_NewGCString(cx, (uintN) type + GCX_EXTERNAL_STRING);
|
||||
JSString *str = js_NewGCExternalString(cx, uintN(type));
|
||||
if (!str)
|
||||
return NULL;
|
||||
str->initFlat(chars, length);
|
||||
|
@ -4869,7 +4867,7 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
|
|||
#endif
|
||||
|
||||
out:
|
||||
cx->weakRoots.newborn[JSTRACE_OBJECT] = FUN_OBJECT(fun);
|
||||
cx->weakRoots.newbornObject = FUN_OBJECT(fun);
|
||||
JS_POP_TEMP_ROOT(cx, &tvr);
|
||||
|
||||
out2:
|
||||
|
|
|
@ -3391,7 +3391,7 @@ js_NewEmptyArray(JSContext* cx, JSObject* proto)
|
|||
{
|
||||
JS_ASSERT(OBJ_IS_ARRAY(cx, proto));
|
||||
|
||||
JSObject* obj = js_NewGCObject(cx, GCX_OBJECT);
|
||||
JSObject* obj = js_NewGCObject(cx);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
|
@ -3463,7 +3463,7 @@ js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector, JSBool holey)
|
|||
JS_POP_TEMP_ROOT(cx, &tvr);
|
||||
|
||||
/* Set/clear newborn root, in case we lost it. */
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = obj;
|
||||
cx->weakRoots.newbornObject = obj;
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
|
@ -407,7 +407,7 @@ js_NewNullClosure(JSContext* cx, JSObject* funobj, JSObject* proto, JSObject* pa
|
|||
JSFunction *fun = (JSFunction*) funobj;
|
||||
JS_ASSERT(GET_FUNCTION_PRIVATE(cx, funobj) == fun);
|
||||
|
||||
JSObject* closure = js_NewGCObject(cx, GCX_OBJECT);
|
||||
JSObject* closure = js_NewGCObject(cx);
|
||||
if (!closure)
|
||||
return NULL;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
@ -107,7 +107,7 @@ typedef union JSLocalNames {
|
|||
#define JSFUN_KINDMASK 0xc000 /* encode interp vs. native and closure
|
||||
optimization level -- see above */
|
||||
|
||||
#define FUN_OBJECT(fun) (&(fun)->object)
|
||||
#define FUN_OBJECT(fun) (static_cast<JSObject *>(fun))
|
||||
#define FUN_KIND(fun) ((fun)->flags & JSFUN_KINDMASK)
|
||||
#define FUN_SET_KIND(fun,k) ((fun)->flags = ((fun)->flags & ~JSFUN_KINDMASK) | (k))
|
||||
#define FUN_INTERPRETED(fun) (FUN_KIND(fun) >= JSFUN_INTERPRETED)
|
||||
|
@ -128,8 +128,7 @@ typedef union JSLocalNames {
|
|||
JS_ASSERT((fun)->flags & JSFUN_TRCINFO), \
|
||||
fun->u.n.trcinfo)
|
||||
|
||||
struct JSFunction {
|
||||
JSObject object; /* GC'ed object header */
|
||||
struct JSFunction : public JSObject {
|
||||
uint16 nargs; /* maximum number of specified arguments,
|
||||
reflected as f.length/f.arity */
|
||||
uint16 flags; /* flags, see JSFUN_* below and in jsapi.h */
|
||||
|
|
|
@ -1765,8 +1765,9 @@ IsGCThresholdReached(JSRuntime *rt)
|
|||
rt->gcBytes >= rt->gcTriggerBytes;
|
||||
}
|
||||
|
||||
template <class T> static JS_INLINE T*
|
||||
NewGCThing(JSContext *cx, uintN flags)
|
||||
template <typename T, typename NewbornType>
|
||||
static JS_INLINE T*
|
||||
NewGCThing(JSContext *cx, uintN flags, NewbornType** newbornRoot)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
bool doGC;
|
||||
|
@ -1995,7 +1996,7 @@ testReservedObjects:
|
|||
* No local root scope, so we're stuck with the old, fragile model of
|
||||
* depending on a pigeon-hole newborn per type per context.
|
||||
*/
|
||||
cx->weakRoots.newborn[flags & GCF_TYPEMASK] = thing;
|
||||
*newbornRoot = (T *) thing;
|
||||
}
|
||||
|
||||
/* We can't fail now, so update flags. */
|
||||
|
@ -2027,26 +2028,40 @@ fail:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
extern JSObject* js_NewGCObject(JSContext *cx, uintN flags)
|
||||
JSObject *
|
||||
js_NewGCObject(JSContext *cx)
|
||||
{
|
||||
return NewGCThing<JSObject>(cx, flags);
|
||||
return NewGCThing<JSObject>(cx, GCX_OBJECT, &cx->weakRoots.newbornObject);
|
||||
}
|
||||
|
||||
extern JSString* js_NewGCString(JSContext *cx, uintN flags)
|
||||
JSString *
|
||||
js_NewGCString(JSContext *cx)
|
||||
{
|
||||
return NewGCThing<JSString>(cx, flags);
|
||||
return NewGCThing<JSString>(cx, GCX_STRING, &cx->weakRoots.newbornString);
|
||||
}
|
||||
|
||||
extern JSFunction* js_NewGCFunction(JSContext *cx, uintN flags)
|
||||
JSString *
|
||||
js_NewGCExternalString(JSContext *cx, uintN type)
|
||||
{
|
||||
return NewGCThing<JSFunction>(cx, flags);
|
||||
JS_ASSERT(type < JS_EXTERNAL_STRING_LIMIT);
|
||||
return NewGCThing<JSString>(cx, GCX_EXTERNAL_STRING + type,
|
||||
&cx->weakRoots.newbornExternalString[type]);
|
||||
}
|
||||
|
||||
extern JSXML* js_NewGCXML(JSContext *cx, uintN flags)
|
||||
JSFunction *
|
||||
js_NewGCFunction(JSContext *cx)
|
||||
{
|
||||
return NewGCThing<JSXML>(cx, flags);
|
||||
return NewGCThing<JSFunction>(cx, GCX_OBJECT, &cx->weakRoots.newbornObject);
|
||||
}
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
JSXML *
|
||||
js_NewGCXML(JSContext *cx)
|
||||
{
|
||||
return NewGCThing<JSXML>(cx, GCX_XML, &cx->weakRoots.newbornXML);
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSGCDoubleCell *
|
||||
RefillDoubleFreeList(JSContext *cx)
|
||||
{
|
||||
|
@ -2224,7 +2239,7 @@ js_NewWeaklyRootedDouble(JSContext *cx, jsdouble d)
|
|||
if (js_PushLocalRoot(cx, cx->localRootStack, v) < 0)
|
||||
return NULL;
|
||||
} else {
|
||||
cx->weakRoots.newborn[GCX_DOUBLE] = dp;
|
||||
cx->weakRoots.newbornDouble = dp;
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
@ -2240,7 +2255,7 @@ js_ReserveObjects(JSContext *cx, size_t nobjects)
|
|||
JSObject *&head = JS_TRACE_MONITOR(cx).reservedObjects;
|
||||
size_t i = head ? JSVAL_TO_INT(head->fslots[1]) : 0;
|
||||
while (i < nobjects) {
|
||||
JSObject *obj = js_NewGCObject(cx, GCX_OBJECT);
|
||||
JSObject *obj = js_NewGCObject(cx);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
memset(obj, 0, sizeof(JSObject));
|
||||
|
@ -2889,33 +2904,21 @@ js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp)
|
|||
static void
|
||||
TraceWeakRoots(JSTracer *trc, JSWeakRoots *wr)
|
||||
{
|
||||
uint32 i;
|
||||
void *thing;
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char *weakRootNames[JSTRACE_LIMIT] = {
|
||||
"newborn object",
|
||||
"newborn double",
|
||||
"newborn string",
|
||||
"newborn xml"
|
||||
};
|
||||
if (wr->newbornObject)
|
||||
JS_CALL_OBJECT_TRACER(trc, wr->newbornObject, "newborn_object");
|
||||
if (wr->newbornString)
|
||||
JS_CALL_STRING_TRACER(trc, wr->newbornString, "newborn_string");
|
||||
if (wr->newbornDouble)
|
||||
JS_CALL_DOUBLE_TRACER(trc, wr->newbornDouble, "newborn_double");
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
if (wr->newbornXML)
|
||||
JS_CALL_TRACER(trc, wr->newbornXML, JSTRACE_XML, "newborn_xml");
|
||||
#endif
|
||||
|
||||
for (i = 0; i != JSTRACE_LIMIT; i++) {
|
||||
thing = wr->newborn[i];
|
||||
if (thing)
|
||||
JS_CALL_TRACER(trc, thing, i, weakRootNames[i]);
|
||||
for (uint32 i = 0; i != JS_EXTERNAL_STRING_LIMIT; i++) {
|
||||
JSString *str = wr->newbornExternalString[i];
|
||||
if (str)
|
||||
JS_CALL_STRING_TRACER(trc, str, "newborn_external_string");
|
||||
}
|
||||
JS_ASSERT(i == GCX_EXTERNAL_STRING);
|
||||
for (; i != GCX_NTYPES; ++i) {
|
||||
thing = wr->newborn[i];
|
||||
if (thing) {
|
||||
JS_SET_TRACING_INDEX(trc, "newborn external string",
|
||||
i - GCX_EXTERNAL_STRING);
|
||||
JS_CallTracer(trc, thing, JSTRACE_STRING);
|
||||
}
|
||||
}
|
||||
|
||||
JS_CALL_VALUE_TRACER(trc, wr->lastAtom, "lastAtom");
|
||||
JS_SET_TRACING_NAME(trc, "lastInternalResult");
|
||||
js_CallValueTracerIfGCThing(trc, wr->lastInternalResult);
|
||||
|
@ -3213,7 +3216,8 @@ FinalizeObject(JSContext *cx, JSObject *obj)
|
|||
js_FreeSlots(cx, obj);
|
||||
}
|
||||
|
||||
static JSStringFinalizeOp str_finalizers[GCX_NTYPES - GCX_EXTERNAL_STRING] = {
|
||||
JS_STATIC_ASSERT(JS_EXTERNAL_STRING_LIMIT == 8);
|
||||
static JSStringFinalizeOp str_finalizers[JS_EXTERNAL_STRING_LIMIT] = {
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
|
@ -3221,12 +3225,10 @@ intN
|
|||
js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
|
||||
JSStringFinalizeOp newop)
|
||||
{
|
||||
uintN i;
|
||||
|
||||
for (i = 0; i != JS_ARRAY_LENGTH(str_finalizers); i++) {
|
||||
for (uintN i = 0; i != JS_ARRAY_LENGTH(str_finalizers); i++) {
|
||||
if (str_finalizers[i] == oldop) {
|
||||
str_finalizers[i] = newop;
|
||||
return (intN) i;
|
||||
return intN(i);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
|
|
@ -68,11 +68,13 @@ JS_BEGIN_EXTERN_C
|
|||
#define GCX_XML JSTRACE_XML /* JSXML */
|
||||
#define GCX_EXTERNAL_STRING JSTRACE_LIMIT /* JSString with external
|
||||
chars */
|
||||
const uintN JS_EXTERNAL_STRING_LIMIT = 8;
|
||||
|
||||
/*
|
||||
* The number of defined GC types and the maximum limit for the number of
|
||||
* possible GC types.
|
||||
*/
|
||||
#define GCX_NTYPES (GCX_EXTERNAL_STRING + 8)
|
||||
#define GCX_NTYPES (GCX_EXTERNAL_STRING + JS_EXTERNAL_STRING_LIMIT)
|
||||
#define GCX_LIMIT_LOG2 4 /* type index bits */
|
||||
#define GCX_LIMIT JS_BIT(GCX_LIMIT_LOG2)
|
||||
|
||||
|
@ -169,16 +171,19 @@ struct JSGCThing {
|
|||
* values stored in the partially initialized thing.
|
||||
*/
|
||||
extern JSObject*
|
||||
js_NewGCObject(JSContext *cx, uintN flags);
|
||||
js_NewGCObject(JSContext *cx);
|
||||
|
||||
extern JSString*
|
||||
js_NewGCString(JSContext *cx, uintN flags);
|
||||
js_NewGCString(JSContext *cx);
|
||||
|
||||
extern JSString*
|
||||
js_NewGCExternalString(JSContext *cx, uintN type);
|
||||
|
||||
extern JSFunction*
|
||||
js_NewGCFunction(JSContext *cx, uintN flags);
|
||||
js_NewGCFunction(JSContext *cx);
|
||||
|
||||
extern JSXML*
|
||||
js_NewGCXML(JSContext *cx, uintN flags);
|
||||
js_NewGCXML(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Allocate a new double jsval and store the result in *vp. vp must be a root.
|
||||
|
@ -315,7 +320,13 @@ js_DestroyScriptsToGC(JSContext *cx, JSThreadData *data);
|
|||
|
||||
struct JSWeakRoots {
|
||||
/* Most recently created things by type, members of the GC's root set. */
|
||||
void *newborn[GCX_NTYPES];
|
||||
JSObject *newbornObject;
|
||||
jsdouble *newbornDouble;
|
||||
JSString *newbornString;
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
JSXML *newbornXML;
|
||||
#endif
|
||||
JSString *newbornExternalString[JS_EXTERNAL_STRING_LIMIT];
|
||||
|
||||
/* Atom root for the last-looked-up atom on this context. */
|
||||
jsval lastAtom;
|
||||
|
|
|
@ -2211,14 +2211,14 @@ js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
|
|||
*/
|
||||
JSObject* obj;
|
||||
if (clasp == &js_FunctionClass && !objectSize) {
|
||||
obj = (JSObject*) js_NewGCFunction(cx, GCX_OBJECT);
|
||||
obj = (JSObject*) js_NewGCFunction(cx);
|
||||
#ifdef DEBUG
|
||||
memset((uint8 *) obj + sizeof(JSObject), JS_FREE_PATTERN,
|
||||
sizeof(JSFunction) - sizeof(JSObject));
|
||||
#endif
|
||||
} else {
|
||||
JS_ASSERT(!objectSize || objectSize == sizeof(JSObject));
|
||||
obj = js_NewGCObject(cx, GCX_OBJECT);
|
||||
obj = js_NewGCObject(cx);
|
||||
}
|
||||
if (!obj)
|
||||
goto out;
|
||||
|
@ -2243,7 +2243,7 @@ js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
|
|||
}
|
||||
|
||||
/* Check that the newborn root still holds the object. */
|
||||
JS_ASSERT_IF(!cx->localRootStack, cx->weakRoots.newborn[GCX_OBJECT] == obj);
|
||||
JS_ASSERT_IF(!cx->localRootStack, cx->weakRoots.newbornObject == obj);
|
||||
|
||||
/*
|
||||
* Do not call debug hooks on trace, because we might be in a non-_FAIL
|
||||
|
@ -2255,7 +2255,7 @@ js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
|
|||
cx->debugHooks->objectHook(cx, obj, JS_TRUE,
|
||||
cx->debugHooks->objectHookData);
|
||||
JS_UNKEEP_ATOMS(cx->runtime);
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = obj;
|
||||
cx->weakRoots.newbornObject = obj;
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -2320,7 +2320,7 @@ NewNativeObject(JSContext* cx, JSClass* clasp, JSObject* proto,
|
|||
JSObject *parent, jsval privateSlotValue)
|
||||
{
|
||||
JS_ASSERT(JS_ON_TRACE(cx));
|
||||
JSObject* obj = js_NewGCObject(cx, GCX_OBJECT);
|
||||
JSObject* obj = js_NewGCObject(cx);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
|
@ -2659,7 +2659,7 @@ js_CloneBlockObject(JSContext *cx, JSObject *proto, JSStackFrame *fp)
|
|||
JS_ASSERT(!OBJ_IS_CLONED_BLOCK(proto));
|
||||
JS_ASSERT(STOBJ_GET_CLASS(proto) == &js_BlockClass);
|
||||
|
||||
JSObject *clone = js_NewGCObject(cx, GCX_OBJECT);
|
||||
JSObject *clone = js_NewGCObject(cx);
|
||||
if (!clone)
|
||||
return NULL;
|
||||
|
||||
|
@ -3259,7 +3259,7 @@ js_NewNativeObject(JSContext *cx, JSClass *clasp, JSObject *proto,
|
|||
JS_ASSERT(proto->map->ops == &js_ObjectOps);
|
||||
JS_ASSERT(OBJ_GET_CLASS(cx, proto) == clasp);
|
||||
|
||||
JSObject* obj = js_NewGCObject(cx, GCX_OBJECT);
|
||||
JSObject* obj = js_NewGCObject(cx);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
|
@ -5508,7 +5508,7 @@ js_GetClassPrototype(JSContext *cx, JSObject *scope, jsid id,
|
|||
* instance that delegates to this object, or just query the
|
||||
* prototype for its class.
|
||||
*/
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(v);
|
||||
cx->weakRoots.newbornObject = JSVAL_TO_OBJECT(v);
|
||||
}
|
||||
}
|
||||
*protop = JSVAL_IS_OBJECT(v) ? JSVAL_TO_OBJECT(v) : NULL;
|
||||
|
|
|
@ -3483,7 +3483,7 @@
|
|||
JS_ASSERT(regs.sp - StackBase(fp) >= 1);
|
||||
lval = FETCH_OPND(-1);
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(lval));
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(lval);
|
||||
cx->weakRoots.newbornObject = JSVAL_TO_OBJECT(lval);
|
||||
END_CASE(JSOP_ENDINIT)
|
||||
|
||||
BEGIN_CASE(JSOP_INITPROP)
|
||||
|
|
|
@ -3025,7 +3025,7 @@ js_NewString(JSContext *cx, jschar *chars, size_t length)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
str = js_NewGCString(cx, GCX_STRING);
|
||||
str = js_NewGCString(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
str->initFlat(chars, length);
|
||||
|
@ -3095,7 +3095,7 @@ js_NewDependentString(JSContext *cx, JSString *base, size_t start,
|
|||
return js_NewStringCopyN(cx, base->chars() + start, length);
|
||||
}
|
||||
|
||||
ds = js_NewGCString(cx, GCX_STRING);
|
||||
ds = js_NewGCString(cx);
|
||||
if (!ds)
|
||||
return NULL;
|
||||
if (start == 0)
|
||||
|
|
|
@ -3385,9 +3385,9 @@ Descendants(JSContext *cx, JSXML *xml, jsval id)
|
|||
|
||||
/*
|
||||
* Protect nameqn's object and strings from GC by linking list to it
|
||||
* temporarily. The cx->newborn[GCX_OBJECT] GC root protects listobj,
|
||||
* which protects list. Any other object allocations occuring beneath
|
||||
* DescendantsHelper use local roots.
|
||||
* temporarily. The newborn GC root for the last allocated object
|
||||
* protects listobj, which protects list. Any other object allocations
|
||||
* occurring beneath DescendantsHelper use local roots.
|
||||
*/
|
||||
list->name = nameqn;
|
||||
if (!js_EnterLocalRootScope(cx))
|
||||
|
@ -7182,9 +7182,7 @@ uint32 xml_serial;
|
|||
JSXML *
|
||||
js_NewXML(JSContext *cx, JSXMLClass xml_class)
|
||||
{
|
||||
JSXML *xml;
|
||||
|
||||
xml = (JSXML *) js_NewGCXML(cx, GCX_XML);
|
||||
JSXML *xml = js_NewGCXML(cx);
|
||||
if (!xml)
|
||||
return NULL;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче