Bug 375808 - GCX_PRIVATE is replaced by GCX_FUNCTION. r=brendan

This commit is contained in:
igor@mir2.org 2007-03-29 17:56:14 -07:00
Родитель 57995c4c65
Коммит f779f80083
4 изменённых файлов: 56 добавлений и 59 удалений

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

@ -969,6 +969,28 @@ static JSPropertySpec function_props[] = {
{0,0,0,0,0} {0,0,0,0,0}
}; };
void
js_MarkFunction(JSContext *cx, JSFunction *fun)
{
if (fun->object)
GC_MARK(cx, fun->object, "object");
if (fun->atom)
GC_MARK_ATOM(cx, fun->atom);
if (FUN_INTERPRETED(fun) && fun->u.i.script)
js_MarkScript(cx, fun->u.i.script);
}
void
js_FinalizeFunction(JSContext *cx, JSFunction *fun)
{
/*
* Null-check of i.script is required since the parser sets interpreted
* very early.
*/
if (FUN_INTERPRETED(fun) && fun->u.i.script)
js_DestroyScript(cx, fun->u.i.script);
}
static JSBool static JSBool
fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{ {
@ -1181,36 +1203,6 @@ fun_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
} }
} }
static void
fun_finalize(JSContext *cx, JSObject *obj)
{
JSFunction *fun;
JSScript *script;
/* No valid function object should lack private data, but check anyway. */
fun = (JSFunction *) JS_GetPrivate(cx, obj);
if (!fun)
return;
if (fun->object == obj)
fun->object = NULL;
/*
* Null-check of i.script is required since the parser sets interpreted
* very early.
*
* Here js_IsAboutToBeFinalized works because obj is finalized before
* JSFunction. See comments in js_GC before the finalization loop.
*/
if (FUN_INTERPRETED(fun) && fun->u.i.script &&
js_IsAboutToBeFinalized(cx, fun))
{
script = fun->u.i.script;
fun->u.i.script = NULL;
js_DestroyScript(cx, script);
}
}
#if JS_HAS_XDR #if JS_HAS_XDR
#include "jsxdrapi.h" #include "jsxdrapi.h"
@ -1444,13 +1436,8 @@ fun_mark(JSContext *cx, JSObject *obj, void *arg)
JSFunction *fun; JSFunction *fun;
fun = (JSFunction *) JS_GetPrivate(cx, obj); fun = (JSFunction *) JS_GetPrivate(cx, obj);
if (fun) { if (fun)
GC_MARK(cx, fun, "private"); GC_MARK(cx, fun, "private");
if (fun->atom)
GC_MARK_ATOM(cx, fun->atom);
if (FUN_INTERPRETED(fun) && fun->u.i.script)
js_MarkScript(cx, fun->u.i.script);
}
return 0; return 0;
} }
@ -1475,7 +1462,7 @@ JS_FRIEND_DATA(JSClass) js_FunctionClass = {
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
fun_getProperty, JS_PropertyStub, fun_getProperty, JS_PropertyStub,
fun_enumerate, (JSResolveOp)fun_resolve, fun_enumerate, (JSResolveOp)fun_resolve,
fun_convert, fun_finalize, fun_convert, JS_FinalizeStub,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
fun_xdrObject, fun_hasInstance, fun_xdrObject, fun_hasInstance,
@ -2125,10 +2112,10 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(funobj), &tvr); JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(funobj), &tvr);
/* /*
* Allocate fun after allocating funobj so slot allocation in js_NewObject * Allocate fun after allocating funobj so allocations in js_NewObject
* does not wipe out fun from newborn[GCX_PRIVATE]. * and hooks called from it do not wipe out fun from newborn[GCX_FUNCTION].
*/ */
fun = (JSFunction *) js_NewGCThing(cx, GCX_PRIVATE, sizeof(JSFunction)); fun = (JSFunction *) js_NewGCThing(cx, GCX_FUNCTION, sizeof(JSFunction));
if (!fun) if (!fun)
goto out; goto out;

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

@ -86,6 +86,12 @@ extern JS_FRIEND_DATA(JSClass) js_FunctionClass;
(!JSVAL_IS_PRIMITIVE(v) && \ (!JSVAL_IS_PRIMITIVE(v) && \
OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_FunctionClass) OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_FunctionClass)
extern void
js_MarkFunction(JSContext *cx, JSFunction *fun);
extern void
js_FinalizeFunction(JSContext *cx, JSFunction *fun);
extern JSBool extern JSBool
js_fun_toString(JSContext *cx, JSObject *obj, uint32 indent, js_fun_toString(JSContext *cx, JSObject *obj, uint32 indent,
uintN argc, jsval *argv, jsval *rval); uintN argc, jsval *argv, jsval *rval);

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

@ -242,14 +242,6 @@ JS_STATIC_ASSERT(sizeof(JSGCThing) >= sizeof(jsdouble));
/* We want to use all the available GC thing space for object's slots. */ /* We want to use all the available GC thing space for object's slots. */
JS_STATIC_ASSERT(sizeof(JSObject) % sizeof(JSGCThing) == 0); JS_STATIC_ASSERT(sizeof(JSObject) % sizeof(JSGCThing) == 0);
/*
* Ensure that GC-allocated JSFunction and JSObject would go to different
* lists so we can easily finalize JSObject before JSFunction. See comments
* in js_GC.
*/
JS_STATIC_ASSERT(GC_FREELIST_INDEX(sizeof(JSFunction)) !=
GC_FREELIST_INDEX(sizeof(JSObject)));
/* /*
* JSPtrTable capacity growth descriptor. The table grows by powers of two * JSPtrTable capacity growth descriptor. The table grows by powers of two
* starting from capacity JSPtrTableInfo.minCapacity, but switching to linear * starting from capacity JSPtrTableInfo.minCapacity, but switching to linear
@ -540,7 +532,7 @@ static GCFinalizeOp gc_finalizers[GCX_NTYPES] = {
(GCFinalizeOp) js_FinalizeString, /* GCX_STRING */ (GCFinalizeOp) js_FinalizeString, /* GCX_STRING */
(GCFinalizeOp) js_FinalizeDouble, /* GCX_DOUBLE */ (GCFinalizeOp) js_FinalizeDouble, /* GCX_DOUBLE */
(GCFinalizeOp) js_FinalizeString, /* GCX_MUTABLE_STRING */ (GCFinalizeOp) js_FinalizeString, /* GCX_MUTABLE_STRING */
NULL, /* GCX_PRIVATE */ (GCFinalizeOp) js_FinalizeFunction, /* GCX_FUNCTION */
(GCFinalizeOp) js_FinalizeXMLNamespace, /* GCX_NAMESPACE */ (GCFinalizeOp) js_FinalizeXMLNamespace, /* GCX_NAMESPACE */
(GCFinalizeOp) js_FinalizeXMLQName, /* GCX_QNAME */ (GCFinalizeOp) js_FinalizeXMLQName, /* GCX_QNAME */
(GCFinalizeOp) js_FinalizeXML, /* GCX_XML */ (GCFinalizeOp) js_FinalizeXML, /* GCX_XML */
@ -1922,6 +1914,17 @@ gc_dump_thing(JSContext *cx, JSGCThing *thing, FILE *fp)
fprintf(fp, "object %8p %s", privateThing, className); fprintf(fp, "object %8p %s", privateThing, className);
break; break;
} }
case GCX_FUNCTION:
{
JSFunction *fun = (JSFunction *)thing;
fprintf(fp, "function");
if (fun->atom && ATOM_IS_STRING(fun->atom)) {
fputc(' ', fp);
js_FileEscapedString(fp, ATOM_TO_STRING(fun->atom), 0);
}
break;
}
#if JS_HAS_XML_SUPPORT #if JS_HAS_XML_SUPPORT
case GCX_NAMESPACE: case GCX_NAMESPACE:
{ {
@ -1958,9 +1961,6 @@ gc_dump_thing(JSContext *cx, JSGCThing *thing, FILE *fp)
case GCX_DOUBLE: case GCX_DOUBLE:
fprintf(fp, "double %g", *(jsdouble *)thing); fprintf(fp, "double %g", *(jsdouble *)thing);
break; break;
case GCX_PRIVATE:
fprintf(fp, "private %8p", (void *)thing);
break;
default: default:
fputs("string ", fp); fputs("string ", fp);
js_FileEscapedString(fp, (JSString *)thing, 0); js_FileEscapedString(fp, (JSString *)thing, 0);
@ -2204,6 +2204,12 @@ MarkGCThingChildren(JSContext *cx, void *thing, uint8 *flagp,
goto start; goto start;
#endif #endif
case GCX_FUNCTION:
if (RECURSION_TOO_DEEP())
goto add_to_unscanned_bag;
js_MarkFunction(cx, (JSFunction *)thing);
break;
#if JS_HAS_XML_SUPPORT #if JS_HAS_XML_SUPPORT
case GCX_NAMESPACE: case GCX_NAMESPACE:
if (RECURSION_TOO_DEEP()) if (RECURSION_TOO_DEEP())
@ -2435,6 +2441,7 @@ ScanDelayedChildren(JSContext *cx)
*/ */
switch (*flagp & GCF_TYPEMASK) { switch (*flagp & GCF_TYPEMASK) {
case GCX_OBJECT: case GCX_OBJECT:
case GCX_FUNCTION:
# if JS_HAS_XML_SUPPORT # if JS_HAS_XML_SUPPORT
case GCX_NAMESPACE: case GCX_NAMESPACE:
case GCX_QNAME: case GCX_QNAME:
@ -3059,12 +3066,8 @@ restart:
* so that any attempt to allocate a GC-thing from a finalizer will fail, * so that any attempt to allocate a GC-thing from a finalizer will fail,
* rather than nest badly and leave the unmarked newborn to be swept. * rather than nest badly and leave the unmarked newborn to be swept.
* *
* Here we need to ensure that JSObject instances are finalized before GC- * Here we finalize the list containing JSObject first to ensure that
* allocated JSFunction instances so fun_finalize from jsfun.c can get the * JSObject finalizers can access JSString * and other GC things safely.
* proper result from the call to js_IsAboutToBeFinalized. For that we
* simply finalize the list containing JSObject first since the static
* assert at the beginning of the file guarantees that JSFunction instances
* are allocated from a different list.
*/ */
for (i = 0; i < GC_NUM_FREELISTS; i++) { for (i = 0; i < GC_NUM_FREELISTS; i++) {
arenaList = &rt->gcArenaList[i == 0 arenaList = &rt->gcArenaList[i == 0
@ -3072,6 +3075,7 @@ restart:
: i == GC_FREELIST_INDEX(sizeof(JSObject)) : i == GC_FREELIST_INDEX(sizeof(JSObject))
? 0 ? 0
: i]; : i];
arenaList = &rt->gcArenaList[i];
nbytes = arenaList->thingSize; nbytes = arenaList->thingSize;
limit = arenaList->lastLimit; limit = arenaList->lastLimit;
for (a = arenaList->last; a; a = a->prev) { for (a = arenaList->last; a; a = a->prev) {

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

@ -55,7 +55,7 @@ JS_BEGIN_EXTERN_C
#define GCX_DOUBLE 2 /* jsdouble */ #define GCX_DOUBLE 2 /* jsdouble */
#define GCX_MUTABLE_STRING 3 /* JSString that's mutable -- #define GCX_MUTABLE_STRING 3 /* JSString that's mutable --
single-threaded only! */ single-threaded only! */
#define GCX_PRIVATE 4 /* private (unscanned) data */ #define GCX_FUNCTION 4 /* JSFunction */
#define GCX_NAMESPACE 5 /* JSXMLNamespace */ #define GCX_NAMESPACE 5 /* JSXMLNamespace */
#define GCX_QNAME 6 /* JSXMLQName */ #define GCX_QNAME 6 /* JSXMLQName */
#define GCX_XML 7 /* JSXML */ #define GCX_XML 7 /* JSXML */