mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 13:25:37 +00:00
Clean up JSObjectOps layering violations by adding mark and clear ops; JSClass gets a corresponding mark op so classes with unregistered roots in private data can mark them. The JS API gets a new JS_MarkGCThing entry point for JSObjectOps.mark implementors. Prerequisite check-in for bug 49816 and others (r=shaver).
This commit is contained in:
parent
1196739ccc
commit
c77f05ae2e
16
js/src/js.c
16
js/src/js.c
@ -18,7 +18,7 @@
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
@ -140,7 +140,7 @@ int fputs(const char *s, FILE *file)
|
||||
char buffer[4096];
|
||||
int n = strlen(s);
|
||||
int extra = 0;
|
||||
|
||||
|
||||
while (n > sizeof buffer) {
|
||||
memcpy(buffer, s, sizeof buffer);
|
||||
translateLFtoCR(buffer, sizeof buffer);
|
||||
@ -629,7 +629,7 @@ Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
static JSBool
|
||||
Quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
int r = 0;
|
||||
int r = 0;
|
||||
|
||||
#ifdef LIVECONNECT
|
||||
JSJ_SimpleShutdown();
|
||||
@ -1336,6 +1336,15 @@ BuildDate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Clear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
if (argc != 0 && !JS_ValueToObject(cx, argv[0], &obj))
|
||||
return JS_FALSE;
|
||||
JS_ClearScope(cx, obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSFunctionSpec shell_functions[] = {
|
||||
{"version", Version, 0},
|
||||
{"options", Options, 0},
|
||||
@ -1362,6 +1371,7 @@ static JSFunctionSpec shell_functions[] = {
|
||||
{"cvtargs", ConvertArgs, 0, 0, 12},
|
||||
#endif
|
||||
{"build", BuildDate, 0},
|
||||
{"clear", Clear, 0},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
@ -958,7 +958,7 @@ InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
|
||||
if (!cx->globalObject)
|
||||
cx->globalObject = obj;
|
||||
|
||||
/* Record both Function and Object in resolving, if we are resolving. */
|
||||
/* Record both Function and Object in cx->resolving, if we are resolving. */
|
||||
table = cx->resolving;
|
||||
if (table) {
|
||||
rt = cx->runtime;
|
||||
@ -1047,7 +1047,7 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj)
|
||||
#define OFFSET_TO_ATOM(rt,off) (*(JSAtom **)((char*)&(rt)->atomState + (off)))
|
||||
#define TAG_ATOM_OFFSET(name) ((const char *) ATOM_OFFSET(name))
|
||||
#define TAG_CHAR_STRING(name) name
|
||||
#define UNTAG_ATOM_OFFSET(ptr) ((size_t) (ptr))
|
||||
#define UNTAG_ATOM_OFFSET(ptr) ((size_t)(ptr))
|
||||
#define UNTAG_CHAR_STRING(ptr) ptr
|
||||
#define IS_ATOM_OFFSET(ptr) ((size_t)(ptr) < sizeof(JSAtomState))
|
||||
|
||||
@ -1490,6 +1490,17 @@ JS_UnlockGCThing(JSContext *cx, void *thing)
|
||||
return ok;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg)
|
||||
{
|
||||
JS_ASSERT(cx->runtime->gcLevel > 0);
|
||||
#ifdef JS_THREADSAFE
|
||||
JS_ASSERT(cx->runtime->gcThread == js_CurrentThreadId());
|
||||
#endif
|
||||
|
||||
GC_MARK(cx, thing, name, arg);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_GC(JSContext *cx)
|
||||
{
|
||||
@ -2433,25 +2444,10 @@ JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval)
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ClearScope(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSObjectMap *map;
|
||||
JSScope *scope;
|
||||
uint32 i;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
/* XXXbe push this into jsobj.c or jsscope.c */
|
||||
/* XXXbe2 worse, assumes obj is native here, before MAP_IS_NATIVE! */
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
map = obj->map;
|
||||
if (MAP_IS_NATIVE(map)) {
|
||||
scope = (JSScope *)map;
|
||||
scope->ops->clear(cx, scope);
|
||||
}
|
||||
|
||||
/* Clear slot values and reset freeslot so we're consistent. */
|
||||
map->freeslot = JSSLOT_FREE(OBJ_GET_CLASS(cx, obj));
|
||||
for (i = map->nslots-1; i >= map->freeslot; --i)
|
||||
obj->slots[i] = JSVAL_VOID;
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
if (obj->map->ops->clear)
|
||||
obj->map->ops->clear(cx, obj);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSIdArray *)
|
||||
|
@ -523,6 +523,22 @@ JS_LockGCThing(JSContext *cx, void *thing);
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_UnlockGCThing(JSContext *cx, void *thing);
|
||||
|
||||
/*
|
||||
* For implementors of JSObjectOps.mark, to mark a GC-thing reachable via a
|
||||
* property or other strong ref identified for debugging purposes by name.
|
||||
* The name argument's storage needs to live only as long as the call to
|
||||
* this routine.
|
||||
*
|
||||
* The final arg is used by GC_MARK_DEBUG code to build a ref path through
|
||||
* the GC's live thing graph. Implementors of JSObjectOps.mark should pass
|
||||
* its final arg through to this function when marking all GC-things that are
|
||||
* directly reachable from the object being marked.
|
||||
*
|
||||
* See the JSMarkOp typedef in jspubtd.h, and the JSObjectOps struct below.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_GC(JSContext *cx);
|
||||
|
||||
@ -561,16 +577,17 @@ struct JSClass {
|
||||
JSNative construct;
|
||||
JSXDRObjectOp xdrObject;
|
||||
JSHasInstanceOp hasInstance;
|
||||
jsword spare[2];
|
||||
JSMarkOp mark;
|
||||
jsword spare;
|
||||
};
|
||||
|
||||
#define JSCLASS_HAS_PRIVATE 0x01 /* class instances have private slot */
|
||||
#define JSCLASS_NEW_ENUMERATE 0x02 /* class has JSNewEnumerateOp method */
|
||||
#define JSCLASS_NEW_RESOLVE 0x04 /* class has JSNewResolveOp method */
|
||||
#define JSCLASS_PRIVATE_IS_NSISUPPORTS 0x08 /* private slot is nsISupports* */
|
||||
/* Fill in null values for unused members. */
|
||||
#define JSCLASS_NO_OPTIONAL_MEMBERS \
|
||||
0,0,0,0,0,0,{0,0}
|
||||
#define JSCLASS_PRIVATE_IS_NSISUPPORTS 0x08 /* private is (nsISupports *) */
|
||||
|
||||
/* Initializer for unused members of statically initialized JSClass structs. */
|
||||
#define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,0,0,0
|
||||
|
||||
struct JSObjectOps {
|
||||
/* Mandatory non-null function pointer members. */
|
||||
@ -596,10 +613,10 @@ struct JSObjectOps {
|
||||
JSHasInstanceOp hasInstance;
|
||||
JSSetObjectSlotOp setProto;
|
||||
JSSetObjectSlotOp setParent;
|
||||
JSMarkOp mark;
|
||||
JSFinalizeOp clear;
|
||||
jsword spare1;
|
||||
jsword spare2;
|
||||
jsword spare3;
|
||||
jsword spare4;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -306,8 +306,8 @@ js_FreeAtomState(JSContext *cx, JSAtomState *state)
|
||||
}
|
||||
|
||||
typedef struct MarkArgs {
|
||||
JSRuntime *runtime;
|
||||
JSGCThingMarker mark;
|
||||
void *data;
|
||||
} MarkArgs;
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(intN)
|
||||
@ -323,19 +323,19 @@ js_atom_marker(JSHashEntry *he, intN i, void *arg)
|
||||
key = ATOM_KEY(atom);
|
||||
if (JSVAL_IS_GCTHING(key)) {
|
||||
args = (MarkArgs *) arg;
|
||||
args->mark(args->runtime, JSVAL_TO_GCTHING(key));
|
||||
args->mark(JSVAL_TO_GCTHING(key), args->data);
|
||||
}
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
js_MarkAtomState(JSAtomState *state, JSGCThingMarker mark)
|
||||
js_MarkAtomState(JSAtomState *state, JSGCThingMarker mark, void *data)
|
||||
{
|
||||
MarkArgs args;
|
||||
|
||||
args.runtime = state->runtime;
|
||||
args.mark = mark;
|
||||
args.data = data;
|
||||
JS_HashTableEnumerateEntries(state->table, js_atom_marker, &args);
|
||||
}
|
||||
|
||||
|
@ -241,10 +241,10 @@ js_FreeAtomState(JSContext *cx, JSAtomState *state);
|
||||
* Atom garbage collection hooks.
|
||||
*/
|
||||
typedef void
|
||||
(*JSGCThingMarker)(JSRuntime *rt, void *thing);
|
||||
(*JSGCThingMarker)(void *thing, void *data);
|
||||
|
||||
extern void
|
||||
js_MarkAtomState(JSAtomState *state, JSGCThingMarker mark);
|
||||
js_MarkAtomState(JSAtomState *state, JSGCThingMarker mark, void *data);
|
||||
|
||||
extern void
|
||||
js_SweepAtomState(JSAtomState *state, uintN gcflags);
|
||||
|
@ -68,7 +68,7 @@ static JSClass ExceptionClass = {
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize,
|
||||
NULL, NULL, NULL, Exception,
|
||||
0,0,{0,0}
|
||||
NULL, NULL, NULL, 0
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1043,6 +1043,21 @@ fun_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
|
||||
|
||||
#endif /* !JS_HAS_INSTANCEOF */
|
||||
|
||||
static uint32
|
||||
fun_mark(JSContext *cx, JSObject *obj, void *arg)
|
||||
{
|
||||
JSFunction *fun;
|
||||
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
||||
if (fun) {
|
||||
if (fun->atom)
|
||||
js_MarkAtom(cx, fun->atom, arg);
|
||||
if (fun->script)
|
||||
js_MarkScript(cx, fun->script, arg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
JSClass js_FunctionClass = {
|
||||
js_Function_str,
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE,
|
||||
@ -1053,7 +1068,7 @@ JSClass js_FunctionClass = {
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
fun_xdrObject, fun_hasInstance,
|
||||
{0,0}
|
||||
fun_mark, 0
|
||||
};
|
||||
|
||||
static JSBool
|
||||
|
308
js/src/jsgc.c
308
js/src/jsgc.c
@ -53,7 +53,6 @@
|
||||
#include "jsatom.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsconfig.h"
|
||||
#include "jsfun.h"
|
||||
#include "jsgc.h"
|
||||
#include "jsinterp.h"
|
||||
#include "jslock.h"
|
||||
@ -204,6 +203,7 @@ js_AllocGCThing(JSContext *cx, uintN flags)
|
||||
|
||||
rt = cx->runtime;
|
||||
JS_LOCK_GC(rt);
|
||||
JS_ASSERT(rt->gcLevel == 0);
|
||||
METER(rt->gcStats.alloc++);
|
||||
retry:
|
||||
thing = rt->gcFreeList;
|
||||
@ -413,15 +413,6 @@ js_UnlockGCThing(JSContext *cx, void *thing)
|
||||
JS_FRIEND_DATA(FILE *) js_DumpGCHeap;
|
||||
JS_EXPORT_DATA(void *) js_LiveThingToFind;
|
||||
|
||||
typedef struct GCMarkNode GCMarkNode;
|
||||
|
||||
struct GCMarkNode {
|
||||
void *thing;
|
||||
char *name;
|
||||
GCMarkNode *next;
|
||||
GCMarkNode *prev;
|
||||
};
|
||||
|
||||
#ifdef HAVE_XPCONNECT
|
||||
#include "dump_xpc.h"
|
||||
#endif
|
||||
@ -500,50 +491,21 @@ gc_dump_thing(JSRuntime* rt, JSGCThing *thing, uint8 flags, GCMarkNode *prev,
|
||||
free(path);
|
||||
}
|
||||
|
||||
static void
|
||||
gc_mark_node(JSRuntime *rt, void *thing, GCMarkNode *prev);
|
||||
|
||||
#define GC_MARK(_rt, _thing, _name, _prev) \
|
||||
JS_BEGIN_MACRO \
|
||||
GCMarkNode _node; \
|
||||
_node.thing = _thing; \
|
||||
_node.name = _name; \
|
||||
_node.next = NULL; \
|
||||
_node.prev = _prev; \
|
||||
if (_prev) ((GCMarkNode *)(_prev))->next = &_node; \
|
||||
gc_mark_node(_rt, _thing, &_node); \
|
||||
JS_END_MACRO
|
||||
|
||||
static void
|
||||
gc_mark(JSRuntime *rt, void *thing)
|
||||
{
|
||||
GC_MARK(rt, thing, "atom", NULL);
|
||||
}
|
||||
|
||||
#define GC_MARK_ATOM(rt, atom, prev) gc_mark_atom(rt, atom, prev)
|
||||
#define GC_MARK_SCRIPT(rt, script, prev) gc_mark_script(rt, script, prev)
|
||||
|
||||
#else /* !GC_MARK_DEBUG */
|
||||
|
||||
#define GC_MARK(rt, thing, name, prev) gc_mark(rt, thing)
|
||||
#define GC_MARK_ATOM(rt, atom, prev) gc_mark_atom(rt, atom)
|
||||
#define GC_MARK_SCRIPT(rt, script, prev) gc_mark_script(rt, script)
|
||||
|
||||
static void
|
||||
gc_mark(JSRuntime *rt, void *thing);
|
||||
|
||||
#endif /* !GC_MARK_DEBUG */
|
||||
|
||||
static void
|
||||
gc_mark_atom(JSRuntime *rt, JSAtom *atom
|
||||
#ifdef GC_MARK_DEBUG
|
||||
, GCMarkNode *prev
|
||||
#endif
|
||||
)
|
||||
gc_mark_atom_key_thing(void *thing, void *arg)
|
||||
{
|
||||
JSContext *cx = (JSContext *) arg;
|
||||
GC_MARK(cx, thing, "atom", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
js_MarkAtom(JSContext *cx, JSAtom *atom, void *arg)
|
||||
{
|
||||
jsval key;
|
||||
|
||||
if (!atom || atom->flags & ATOM_MARK)
|
||||
if (atom->flags & ATOM_MARK)
|
||||
return;
|
||||
atom->flags |= ATOM_MARK;
|
||||
key = ATOM_KEY(atom);
|
||||
@ -558,47 +520,26 @@ gc_mark_atom(JSRuntime *rt, JSAtom *atom
|
||||
JS_snprintf(name, sizeof name, "<%x>", key);
|
||||
}
|
||||
#endif
|
||||
GC_MARK(rt, JSVAL_TO_GCTHING(key), name, prev);
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(key), name, arg);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gc_mark_script(JSRuntime *rt, JSScript *script
|
||||
#ifdef GC_MARK_DEBUG
|
||||
, GCMarkNode *prev
|
||||
#endif
|
||||
)
|
||||
{
|
||||
JSAtomMap *map;
|
||||
uintN i, length;
|
||||
JSAtom **vector;
|
||||
|
||||
map = &script->atomMap;
|
||||
length = map->length;
|
||||
vector = map->vector;
|
||||
for (i = 0; i < length; i++)
|
||||
GC_MARK_ATOM(rt, vector[i], prev);
|
||||
}
|
||||
|
||||
static void
|
||||
#ifdef GC_MARK_DEBUG
|
||||
gc_mark_node(JSRuntime *rt, void *thing, GCMarkNode *prev)
|
||||
#else
|
||||
gc_mark(JSRuntime *rt, void *thing)
|
||||
#endif
|
||||
void
|
||||
js_MarkGCThing(JSContext *cx, void *thing, void *arg)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
uint8 flags, *flagp;
|
||||
JSObject *obj;
|
||||
uint32 nslots;
|
||||
jsval v, *vp, *end;
|
||||
#ifdef GC_MARK_DEBUG
|
||||
JSScope *scope;
|
||||
JSClass *clasp;
|
||||
JSScript *script;
|
||||
JSFunction *fun;
|
||||
JSScopeProperty *sprop;
|
||||
JSSymbol *sym;
|
||||
#endif
|
||||
|
||||
if (!thing)
|
||||
return;
|
||||
rt = cx->runtime;
|
||||
flagp = gc_find_flags(rt, thing);
|
||||
if (!flagp)
|
||||
return;
|
||||
@ -627,134 +568,65 @@ gc_mark(JSRuntime *rt, void *thing)
|
||||
if ((flags & GCF_TYPEMASK) == GCX_OBJECT) {
|
||||
obj = (JSObject *) thing;
|
||||
vp = obj->slots;
|
||||
if (vp) {
|
||||
scope = OBJ_IS_NATIVE(obj) ? OBJ_SCOPE(obj) : NULL;
|
||||
if (scope) {
|
||||
clasp = (JSClass *) JSVAL_TO_PRIVATE(obj->slots[JSSLOT_CLASS]);
|
||||
|
||||
if (clasp == &js_ScriptClass) {
|
||||
v = vp[JSSLOT_PRIVATE];
|
||||
if (!JSVAL_IS_VOID(v)) {
|
||||
script = (JSScript *) JSVAL_TO_PRIVATE(v);
|
||||
if (script)
|
||||
GC_MARK_SCRIPT(rt, script, prev);
|
||||
}
|
||||
}
|
||||
|
||||
if (clasp == &js_FunctionClass) {
|
||||
v = vp[JSSLOT_PRIVATE];
|
||||
if (!JSVAL_IS_VOID(v)) {
|
||||
fun = (JSFunction *) JSVAL_TO_PRIVATE(v);
|
||||
if (fun) {
|
||||
if (fun->atom)
|
||||
GC_MARK_ATOM(rt, fun->atom, prev);
|
||||
if (fun->script)
|
||||
GC_MARK_SCRIPT(rt, fun->script, prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (sprop = scope->props; sprop; sprop = sprop->next) {
|
||||
for (sym = sprop->symbols; sym; sym = sym->next) {
|
||||
if (JSVAL_IS_INT(sym_id(sym)))
|
||||
continue;
|
||||
GC_MARK_ATOM(rt, sym_atom(sym), prev);
|
||||
}
|
||||
#if JS_HAS_GETTER_SETTER
|
||||
if (sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
|
||||
nslots = (obj->map->ops->mark)
|
||||
? obj->map->ops->mark(cx, obj, arg)
|
||||
: obj->map->freeslot;
|
||||
#ifdef GC_MARK_DEBUG
|
||||
char buf[64];
|
||||
JSAtom *atom = sym_atom(sprop->symbols);
|
||||
const char *id = (atom && ATOM_IS_STRING(atom))
|
||||
? JS_GetStringBytes(ATOM_TO_STRING(atom))
|
||||
: "unknown";
|
||||
scope = OBJ_IS_NATIVE(obj) ? OBJ_SCOPE(obj) : NULL;
|
||||
#endif
|
||||
|
||||
if (sprop->attrs & JSPROP_GETTER) {
|
||||
for (end = vp + nslots; vp < end; vp++) {
|
||||
v = *vp;
|
||||
if (JSVAL_IS_GCTHING(v)) {
|
||||
#ifdef GC_MARK_DEBUG
|
||||
JS_snprintf(buf, sizeof buf, "%s %s",
|
||||
id, js_getter_str);
|
||||
#endif
|
||||
GC_MARK(rt,
|
||||
JSVAL_TO_GCTHING((jsval)
|
||||
SPROP_GETTER_SCOPE(sprop, scope)),
|
||||
buf,
|
||||
prev);
|
||||
char name[32];
|
||||
|
||||
if (scope) {
|
||||
uint32 slot;
|
||||
jsval nval;
|
||||
|
||||
slot = vp - obj->slots;
|
||||
for (sprop = scope->props; ; sprop = sprop->next) {
|
||||
if (!sprop) {
|
||||
switch (slot) {
|
||||
case JSSLOT_PROTO:
|
||||
strcpy(name, "__proto__");
|
||||
break;
|
||||
case JSSLOT_PARENT:
|
||||
strcpy(name, "__parent__");
|
||||
break;
|
||||
case JSSLOT_PRIVATE:
|
||||
strcpy(name, "__private__");
|
||||
break;
|
||||
default:
|
||||
JS_snprintf(name, sizeof name,
|
||||
"**UNKNOWN SLOT %ld**",
|
||||
(long)slot);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (sprop->attrs & JSPROP_SETTER) {
|
||||
#ifdef GC_MARK_DEBUG
|
||||
JS_snprintf(buf, sizeof buf, "%s %s",
|
||||
id, js_setter_str);
|
||||
#endif
|
||||
GC_MARK(rt,
|
||||
JSVAL_TO_GCTHING((jsval)
|
||||
SPROP_SETTER_SCOPE(sprop, scope)),
|
||||
buf,
|
||||
prev);
|
||||
if (sprop->slot == slot) {
|
||||
nval = sprop->symbols
|
||||
? js_IdToValue(sym_id(sprop->symbols))
|
||||
: sprop->id;
|
||||
if (JSVAL_IS_INT(nval)) {
|
||||
JS_snprintf(name, sizeof name, "%ld",
|
||||
(long)JSVAL_TO_INT(nval));
|
||||
} else if (JSVAL_IS_STRING(nval)) {
|
||||
JS_snprintf(name, sizeof name, "%s",
|
||||
JS_GetStringBytes(JSVAL_TO_STRING(nval)));
|
||||
} else {
|
||||
strcpy(name, "**FINALIZED ATOM KEY**");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* JS_HAS_GETTER_SETTER */
|
||||
}
|
||||
}
|
||||
if (!scope || scope->object == obj)
|
||||
end = vp + obj->map->freeslot;
|
||||
else
|
||||
end = vp + JS_INITIAL_NSLOTS;
|
||||
for (; vp < end; vp++) {
|
||||
v = *vp;
|
||||
if (JSVAL_IS_GCTHING(v)) {
|
||||
#ifdef GC_MARK_DEBUG
|
||||
char name[32];
|
||||
|
||||
if (scope) {
|
||||
uint32 slot;
|
||||
jsval nval;
|
||||
|
||||
slot = vp - obj->slots;
|
||||
for (sprop = scope->props; ; sprop = sprop->next) {
|
||||
if (!sprop) {
|
||||
switch (slot) {
|
||||
case JSSLOT_PROTO:
|
||||
strcpy(name, "__proto__");
|
||||
break;
|
||||
case JSSLOT_PARENT:
|
||||
strcpy(name, "__parent__");
|
||||
break;
|
||||
case JSSLOT_PRIVATE:
|
||||
strcpy(name, "__private__");
|
||||
break;
|
||||
default:
|
||||
JS_snprintf(name, sizeof name,
|
||||
"**UNKNOWN SLOT %ld**",
|
||||
(long)slot);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (sprop->slot == slot) {
|
||||
nval = sprop->symbols
|
||||
? js_IdToValue(sym_id(sprop->symbols))
|
||||
: sprop->id;
|
||||
if (JSVAL_IS_INT(nval)) {
|
||||
JS_snprintf(name, sizeof name, "%ld",
|
||||
(long)JSVAL_TO_INT(nval));
|
||||
} else if (JSVAL_IS_STRING(nval)) {
|
||||
JS_snprintf(name, sizeof name, "%s",
|
||||
JS_GetStringBytes(JSVAL_TO_STRING(nval)));
|
||||
} else {
|
||||
strcpy(name, "**FINALIZED ATOM KEY**");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
GC_MARK(rt, JSVAL_TO_GCTHING(v), name, prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(v), name, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
METER(rt->gcStats.depth--);
|
||||
}
|
||||
|
||||
@ -774,13 +646,13 @@ gc_root_marker(JSHashEntry *he, intN i, void *arg)
|
||||
|
||||
/* Ignore null object and scalar values. */
|
||||
if (!JSVAL_IS_NULL(v) && JSVAL_IS_GCTHING(v)) {
|
||||
JSRuntime *rt = (JSRuntime *)arg;
|
||||
JSContext *cx = (JSContext *)arg;
|
||||
#ifdef DEBUG
|
||||
JSArena *a;
|
||||
JSBool root_points_to_gcArenaPool = JS_FALSE;
|
||||
void *thing = JSVAL_TO_GCTHING(v);
|
||||
|
||||
for (a = rt->gcArenaPool.first.next; a; a = a->next) {
|
||||
for (a = cx->runtime->gcArenaPool.first.next; a; a = a->next) {
|
||||
if (JS_UPTRDIFF(thing, a->base) < a->avail - a->base) {
|
||||
root_points_to_gcArenaPool = JS_TRUE;
|
||||
break;
|
||||
@ -796,7 +668,7 @@ gc_root_marker(JSHashEntry *he, intN i, void *arg)
|
||||
JS_ASSERT(root_points_to_gcArenaPool);
|
||||
#endif
|
||||
|
||||
GC_MARK(rt, JSVAL_TO_GCTHING(v), he->value ? he->value : "root", NULL);
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(v), he->value ? he->value : "root", NULL);
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
@ -805,9 +677,9 @@ JS_STATIC_DLL_CALLBACK(intN)
|
||||
gc_lock_marker(JSHashEntry *he, intN i, void *arg)
|
||||
{
|
||||
void *thing = (void *)he->key;
|
||||
JSRuntime *rt = (JSRuntime *)arg;
|
||||
JSContext *cx = (JSContext *)arg;
|
||||
|
||||
GC_MARK(rt, thing, "locked object", NULL);
|
||||
GC_MARK(cx, thing, "locked object", NULL);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
@ -961,10 +833,10 @@ restart:
|
||||
/*
|
||||
* Mark phase.
|
||||
*/
|
||||
JS_HashTableEnumerateEntries(rt->gcRootsHash, gc_root_marker, rt);
|
||||
JS_HashTableEnumerateEntries(rt->gcRootsHash, gc_root_marker, cx);
|
||||
if (rt->gcLocksHash)
|
||||
JS_HashTableEnumerateEntries(rt->gcLocksHash, gc_lock_marker, rt);
|
||||
js_MarkAtomState(&rt->atomState, gc_mark);
|
||||
JS_HashTableEnumerateEntries(rt->gcLocksHash, gc_lock_marker, cx);
|
||||
js_MarkAtomState(&rt->atomState, gc_mark_atom_key_thing, cx);
|
||||
iter = NULL;
|
||||
while ((acx = js_ContextIterator(rt, &iter)) != NULL) {
|
||||
/*
|
||||
@ -1010,25 +882,25 @@ restart:
|
||||
for (vp = (jsval *)begin; vp < (jsval *)end; vp++) {
|
||||
v = *vp;
|
||||
if (JSVAL_IS_GCTHING(v))
|
||||
GC_MARK(rt, JSVAL_TO_GCTHING(v), "stack", NULL);
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(v), "stack", NULL);
|
||||
}
|
||||
if (end == (jsuword)sp)
|
||||
break;
|
||||
}
|
||||
}
|
||||
do {
|
||||
GC_MARK(rt, fp->scopeChain, "scope chain", NULL);
|
||||
GC_MARK(rt, fp->thisp, "this", NULL);
|
||||
GC_MARK(cx, fp->scopeChain, "scope chain", NULL);
|
||||
GC_MARK(cx, fp->thisp, "this", NULL);
|
||||
if (JSVAL_IS_GCTHING(fp->rval))
|
||||
GC_MARK(rt, JSVAL_TO_GCTHING(fp->rval), "rval", NULL);
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(fp->rval), "rval", NULL);
|
||||
if (fp->callobj)
|
||||
GC_MARK(rt, fp->callobj, "call object", NULL);
|
||||
GC_MARK(cx, fp->callobj, "call object", NULL);
|
||||
if (fp->argsobj)
|
||||
GC_MARK(rt, fp->argsobj, "arguments object", NULL);
|
||||
GC_MARK(cx, fp->argsobj, "arguments object", NULL);
|
||||
if (fp->script)
|
||||
GC_MARK_SCRIPT(rt, fp->script, NULL);
|
||||
js_MarkScript(cx, fp->script, NULL);
|
||||
if (fp->sharpArray)
|
||||
GC_MARK(rt, fp->sharpArray, "sharp array", NULL);
|
||||
GC_MARK(cx, fp->sharpArray, "sharp array", NULL);
|
||||
} while ((fp = fp->down) != NULL);
|
||||
}
|
||||
|
||||
@ -1037,13 +909,13 @@ restart:
|
||||
acx->fp->dormantNext = NULL;
|
||||
|
||||
/* Mark other roots-by-definition in acx. */
|
||||
GC_MARK(rt, acx->globalObject, "global object", NULL);
|
||||
GC_MARK(rt, acx->newborn[GCX_OBJECT], "newborn object", NULL);
|
||||
GC_MARK(rt, acx->newborn[GCX_STRING], "newborn string", NULL);
|
||||
GC_MARK(rt, acx->newborn[GCX_DOUBLE], "newborn double", NULL);
|
||||
GC_MARK(cx, acx->globalObject, "global object", NULL);
|
||||
GC_MARK(cx, acx->newborn[GCX_OBJECT], "newborn object", NULL);
|
||||
GC_MARK(cx, acx->newborn[GCX_STRING], "newborn string", NULL);
|
||||
GC_MARK(cx, acx->newborn[GCX_DOUBLE], "newborn double", NULL);
|
||||
#if JS_HAS_EXCEPTIONS
|
||||
if (acx->throwing && JSVAL_IS_GCTHING(acx->exception))
|
||||
GC_MARK(rt, JSVAL_TO_GCTHING(acx->exception), "exception", NULL);
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(acx->exception), "exception", NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
@ -37,24 +37,25 @@
|
||||
/*
|
||||
* JS Garbage Collector.
|
||||
*/
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/* GC thing type indexes. */
|
||||
#define GCX_OBJECT 0 /* JSObject */
|
||||
#define GCX_STRING 1 /* JSString */
|
||||
#define GCX_DOUBLE 2 /* jsdouble */
|
||||
#define GCX_OBJECT 0 /* JSObject */
|
||||
#define GCX_STRING 1 /* JSString */
|
||||
#define GCX_DOUBLE 2 /* jsdouble */
|
||||
#define GCX_DECIMAL 3 /* JSDecimal */
|
||||
#define GCX_NTYPES 4
|
||||
|
||||
/* GC flag definitions (type index goes in low bits). */
|
||||
#define GCF_TYPEMASK JS_BITMASK(2) /* use low bits for type */
|
||||
#define GCF_MARK JS_BIT(2) /* mark bit */
|
||||
#define GCF_FINAL JS_BIT(3) /* in finalization bit */
|
||||
#define GCF_LOCKBIT 4 /* lock bit shift and mask */
|
||||
#define GCF_LOCKMASK (JS_BITMASK(4) << GCF_LOCKBIT)
|
||||
#define GCF_LOCK JS_BIT(GCF_LOCKBIT) /* lock request bit in API */
|
||||
#define GCF_TYPEMASK JS_BITMASK(2) /* use low bits for type */
|
||||
#define GCF_MARK JS_BIT(2) /* mark bit */
|
||||
#define GCF_FINAL JS_BIT(3) /* in finalization bit */
|
||||
#define GCF_LOCKBIT 4 /* lock bit shift and mask */
|
||||
#define GCF_LOCKMASK (JS_BITMASK(4) << GCF_LOCKBIT)
|
||||
#define GCF_LOCK JS_BIT(GCF_LOCKBIT) /* lock request bit in API */
|
||||
|
||||
#if 1
|
||||
/*
|
||||
@ -87,6 +88,40 @@ js_LockGCThing(JSContext *cx, void *thing);
|
||||
extern JSBool
|
||||
js_UnlockGCThing(JSContext *cx, void *thing);
|
||||
|
||||
extern void
|
||||
js_MarkAtom(JSContext *cx, JSAtom *atom, void *arg);
|
||||
|
||||
extern void
|
||||
js_MarkGCThing(JSContext *cx, void *thing, void *arg);
|
||||
|
||||
#ifdef GC_MARK_DEBUG
|
||||
|
||||
typedef struct GCMarkNode GCMarkNode;
|
||||
|
||||
struct GCMarkNode {
|
||||
void *thing;
|
||||
const char *name;
|
||||
GCMarkNode *next;
|
||||
GCMarkNode *prev;
|
||||
};
|
||||
|
||||
#define GC_MARK(_cx, _thing, _name, _prev) \
|
||||
JS_BEGIN_MACRO \
|
||||
GCMarkNode _node; \
|
||||
_node.thing = _thing; \
|
||||
_node.name = _name; \
|
||||
_node.next = NULL; \
|
||||
_node.prev = _prev; \
|
||||
if (_prev) ((GCMarkNode *)(_prev))->next = &_node; \
|
||||
js_MarkGCThing(_cx, _thing, &_node); \
|
||||
JS_END_MACRO
|
||||
|
||||
#else /* !GC_MARK_DEBUG */
|
||||
|
||||
#define GC_MARK(cx, thing, name, prev) js_MarkGCThing(cx, thing, NULL)
|
||||
|
||||
#endif /* !GC_MARK_DEBUG */
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_ForceGC(JSContext *cx);
|
||||
|
||||
|
@ -91,7 +91,8 @@ JS_FRIEND_DATA(JSObjectOps) js_ObjectOps = {
|
||||
js_Call, js_Construct,
|
||||
NULL, js_HasInstance,
|
||||
js_SetProtoOrParent, js_SetProtoOrParent,
|
||||
0,0,0,0
|
||||
js_Mark, js_Clear,
|
||||
0, 0
|
||||
};
|
||||
|
||||
#ifdef XP_MAC
|
||||
@ -1268,7 +1269,8 @@ JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps = {
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
js_SetProtoOrParent, js_SetProtoOrParent,
|
||||
0,0,0,0
|
||||
js_Mark, js_Clear,
|
||||
0, 0
|
||||
};
|
||||
|
||||
static JSObjectOps *
|
||||
@ -1283,7 +1285,7 @@ JSClass js_WithClass = {
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
|
||||
with_getObjectOps,
|
||||
0,0,0,0,0,{0,0}
|
||||
0,0,0,0,0,0,0
|
||||
};
|
||||
|
||||
#if JS_HAS_OBJ_PROTO_PROP
|
||||
@ -3010,6 +3012,85 @@ out:
|
||||
|
||||
#endif /* JS_HAS_XDR */
|
||||
|
||||
uint32
|
||||
js_Mark(JSContext *cx, JSObject *obj, void *arg)
|
||||
{
|
||||
JSScope *scope;
|
||||
JSScopeProperty *sprop;
|
||||
JSSymbol *sym;
|
||||
JSClass *clasp;
|
||||
|
||||
JS_ASSERT(OBJ_IS_NATIVE(obj));
|
||||
scope = OBJ_SCOPE(obj);
|
||||
|
||||
for (sprop = scope->props; sprop; sprop = sprop->next) {
|
||||
for (sym = sprop->symbols; sym; sym = sym->next) {
|
||||
if (JSVAL_IS_INT(sym_id(sym)))
|
||||
continue;
|
||||
js_MarkAtom(cx, sym_atom(sym), arg);
|
||||
}
|
||||
#if JS_HAS_GETTER_SETTER
|
||||
if (sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
|
||||
#ifdef GC_MARK_DEBUG
|
||||
char buf[64];
|
||||
JSAtom *atom = sym_atom(sprop->symbols);
|
||||
const char *id = (atom && ATOM_IS_STRING(atom))
|
||||
? JS_GetStringBytes(ATOM_TO_STRING(atom))
|
||||
: "unknown";
|
||||
#endif
|
||||
|
||||
if (sprop->attrs & JSPROP_GETTER) {
|
||||
#ifdef GC_MARK_DEBUG
|
||||
JS_snprintf(buf, sizeof buf, "%s %s",
|
||||
id, js_getter_str);
|
||||
#endif
|
||||
GC_MARK(cx,
|
||||
JSVAL_TO_GCTHING((jsval)
|
||||
SPROP_GETTER_SCOPE(sprop, scope)),
|
||||
buf,
|
||||
arg);
|
||||
}
|
||||
if (sprop->attrs & JSPROP_SETTER) {
|
||||
#ifdef GC_MARK_DEBUG
|
||||
JS_snprintf(buf, sizeof buf, "%s %s",
|
||||
id, js_setter_str);
|
||||
#endif
|
||||
GC_MARK(cx,
|
||||
JSVAL_TO_GCTHING((jsval)
|
||||
SPROP_SETTER_SCOPE(sprop, scope)),
|
||||
buf,
|
||||
arg);
|
||||
}
|
||||
}
|
||||
#endif /* JS_HAS_GETTER_SETTER */
|
||||
}
|
||||
|
||||
/* No one runs while the GC is running, so we can use LOCKED_... here. */
|
||||
clasp = LOCKED_OBJ_GET_CLASS(obj);
|
||||
if (clasp->mark)
|
||||
(void) clasp->mark(cx, obj, arg);
|
||||
return (scope->object == obj) ? obj->map->freeslot : JS_INITIAL_NSLOTS;
|
||||
}
|
||||
|
||||
void
|
||||
js_Clear(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSScope *scope;
|
||||
uint32 i, n;
|
||||
|
||||
/* Clear our scope of all symbols and properties. */
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope->ops->clear(cx, scope);
|
||||
|
||||
/* Clear slot values and reset freeslot so we're consistent. */
|
||||
i = scope->map.nslots;
|
||||
n = JSSLOT_FREE(LOCKED_OBJ_GET_CLASS(obj));
|
||||
while (--i >= n)
|
||||
obj->slots[i] = JSVAL_VOID;
|
||||
scope->map.freeslot = n;
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
|
@ -354,6 +354,12 @@ js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom,
|
||||
extern JSBool
|
||||
js_XDRObject(JSXDRState *xdr, JSObject **objp);
|
||||
|
||||
extern uint32
|
||||
js_Mark(JSContext *cx, JSObject *obj, void *arg);
|
||||
|
||||
extern void
|
||||
js_Clear(JSContext *cx, JSObject *obj);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsobj_h___ */
|
||||
|
@ -188,6 +188,9 @@ typedef JSBool
|
||||
(* CRT_CALL JSSetObjectSlotOp)(JSContext *cx, JSObject *obj, uint32 slot,
|
||||
JSObject *pobj);
|
||||
|
||||
typedef uint32
|
||||
(* CRT_CALL JSMarkOp)(JSContext *cx, JSObject *obj, void *arg);
|
||||
|
||||
/* JSObjectOps function pointer typedefs. */
|
||||
|
||||
typedef JSObjectMap *
|
||||
|
@ -2488,8 +2488,7 @@ JSClass js_RegExpClass = {
|
||||
JS_PropertyStub, JS_PropertyStub, regexp_getProperty, regexp_setProperty,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, regexp_finalize,
|
||||
NULL, NULL, regexp_call, NULL,
|
||||
regexp_xdrObject,
|
||||
0,{0,0}
|
||||
regexp_xdrObject, NULL, NULL, 0
|
||||
};
|
||||
|
||||
static JSBool
|
||||
|
@ -622,13 +622,24 @@ script_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32
|
||||
script_mark(JSContext *cx, JSObject *obj, void *arg)
|
||||
{
|
||||
JSScript *script;
|
||||
|
||||
script = (JSScript *) JS_GetPrivate(cx, obj);
|
||||
if (script)
|
||||
js_MarkScript(cx, script, arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
JS_FRIEND_DATA(JSClass) js_ScriptClass = {
|
||||
js_Script_str,
|
||||
JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, script_finalize,
|
||||
NULL, NULL, script_call, NULL,/*XXXbe xdr*/
|
||||
0,0,{0,0}
|
||||
NULL, NULL, script_mark, 0
|
||||
};
|
||||
|
||||
#if JS_HAS_SCRIPT_OBJECT
|
||||
@ -783,6 +794,20 @@ js_DestroyScript(JSContext *cx, JSScript *script)
|
||||
JS_free(cx, script);
|
||||
}
|
||||
|
||||
void
|
||||
js_MarkScript(JSContext *cx, JSScript *script, void *arg)
|
||||
{
|
||||
JSAtomMap *map;
|
||||
uintN i, length;
|
||||
JSAtom **vector;
|
||||
|
||||
map = &script->atomMap;
|
||||
length = map->length;
|
||||
vector = map->vector;
|
||||
for (i = 0; i < length; i++)
|
||||
js_MarkAtom(cx, vector[i], arg);
|
||||
}
|
||||
|
||||
jssrcnote *
|
||||
js_GetSrcNote(JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
|
@ -70,6 +70,20 @@ struct JSScript {
|
||||
JSObject *object; /* optional Script-class object wrapper */
|
||||
};
|
||||
|
||||
#define JSSCRIPT_FIND_CATCH_START(script, pc, catchpc) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSTryNote *_tn = (script)->trynotes; \
|
||||
jsbytecode *_catchpc = NULL; \
|
||||
if (_tn) { \
|
||||
ptrdiff_t _offset = PTRDIFF(pc, (script)->main, jsbytecode); \
|
||||
while (JS_UPTRDIFF(_offset, _tn->start) >= (jsuword)_tn->length) \
|
||||
_tn++; \
|
||||
if (_tn->catchStart) \
|
||||
_catchpc = (script)->main + _tn->catchStart; \
|
||||
} \
|
||||
catchpc = _catchpc; \
|
||||
JS_END_MACRO
|
||||
|
||||
extern JS_FRIEND_DATA(JSClass) js_ScriptClass;
|
||||
|
||||
extern JSObject *
|
||||
@ -91,6 +105,9 @@ js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg, JSFunction *fun);
|
||||
extern void
|
||||
js_DestroyScript(JSContext *cx, JSScript *script);
|
||||
|
||||
extern void
|
||||
js_MarkScript(JSContext *cx, JSScript *script, void *arg);
|
||||
|
||||
extern jssrcnote *
|
||||
js_GetSrcNote(JSScript *script, jsbytecode *pc);
|
||||
|
||||
|
@ -424,7 +424,9 @@ JSObjectOps JavaArray_ops = {
|
||||
NULL, /* hasInstance */
|
||||
NULL, /* setProto */
|
||||
NULL, /* setParent */
|
||||
0,0,0,0 /* spare */
|
||||
NULL, /* mark */
|
||||
NULL, /* clear */
|
||||
0,0 /* spare */
|
||||
};
|
||||
|
||||
static JSObjectOps *
|
||||
@ -445,7 +447,8 @@ JSClass JavaArray_class = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
{0, 0},
|
||||
NULL,
|
||||
0,
|
||||
};
|
||||
|
||||
extern JS_IMPORT_DATA(JSObjectOps) js_ObjectOps;
|
||||
|
@ -561,7 +561,9 @@ JSObjectOps JavaClass_ops = {
|
||||
JavaClass_hasInstance, /* hasInstance */
|
||||
NULL, /* setProto */
|
||||
NULL, /* setParent */
|
||||
0,0,0,0 /* spare */
|
||||
NULL, /* mark */
|
||||
NULL, /* clear */
|
||||
0,0 /* spare */
|
||||
};
|
||||
|
||||
static JSObjectOps *
|
||||
@ -582,7 +584,8 @@ JSClass JavaClass_class = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
{0, 0},
|
||||
NULL,
|
||||
0,
|
||||
};
|
||||
|
||||
static JSObject *
|
||||
|
@ -165,7 +165,8 @@ JSClass JavaMember_class = {
|
||||
NULL, /* construct */
|
||||
NULL, /* xdrObject */
|
||||
NULL, /* hasInstance */
|
||||
{0, 0}, /* spare */
|
||||
NULL, /* mark */
|
||||
0, /* spare */
|
||||
};
|
||||
|
||||
JSBool
|
||||
|
@ -908,7 +908,9 @@ JSObjectOps JavaObject_ops = {
|
||||
NULL, /* hasInstance */
|
||||
NULL, /* setProto */
|
||||
NULL, /* setParent */
|
||||
0,0,0,0 /* spare */
|
||||
NULL, /* mark */
|
||||
NULL, /* clear */
|
||||
0,0 /* spare */
|
||||
};
|
||||
|
||||
static JSObjectOps *
|
||||
@ -929,7 +931,8 @@ JSClass JavaObject_class = {
|
||||
NULL, /* construct */
|
||||
NULL, /* xdrObject */
|
||||
NULL, /* hasInstance */
|
||||
{0, 0}, /* spare */
|
||||
NULL, /* mark */
|
||||
0, /* spare */
|
||||
};
|
||||
|
||||
extern JS_IMPORT_DATA(JSObjectOps) js_ObjectOps;
|
||||
|
@ -336,7 +336,8 @@ JSClass JavaPackage_class = {
|
||||
NULL, /* construct */
|
||||
NULL, /* xdrObject */
|
||||
NULL, /* hasInstance */
|
||||
{0, 0}, /* spare */
|
||||
NULL, /* mark */
|
||||
0, /* spare */
|
||||
};
|
||||
|
||||
JavaPackageDef
|
||||
|
@ -824,13 +824,15 @@ static JSObjectOps WrappedNative_ops = {
|
||||
WrappedNative_HasInstance, /* hasInstance */
|
||||
nsnull, /* setProto */
|
||||
nsnull, /* setParent */
|
||||
0,0,0,0 /* spare */
|
||||
nsnull, /* filled in at runtime! - mark */
|
||||
nsnull, /* filled in at runtime! - clear */
|
||||
0,0 /* spare */
|
||||
};
|
||||
|
||||
static JSObjectOps WrappedNativeWithCall_ops = {
|
||||
/* Mandatory non-null function pointer members. */
|
||||
nsnull, /* filled in at runtime! - newObjectMap */
|
||||
nsnull, /* filled in at runtime! - destroyObjectMap */
|
||||
nsnull, /* filled in at runtime! - newObjectMap */
|
||||
nsnull, /* filled in at runtime! - destroyObjectMap */
|
||||
WrappedNative_LookupProperty,
|
||||
WrappedNative_DefineProperty,
|
||||
WrappedNative_GetProperty,
|
||||
@ -849,9 +851,11 @@ static JSObjectOps WrappedNativeWithCall_ops = {
|
||||
WrappedNative_Construct, /* construct */
|
||||
nsnull, /* xdrObject */
|
||||
WrappedNative_HasInstance, /* hasInstance */
|
||||
NULL, /* setProto */
|
||||
NULL, /* setParent */
|
||||
0,0,0,0 /* spare */
|
||||
nsnull, /* setProto */
|
||||
nsnull, /* setParent */
|
||||
nsnull, /* filled in at runtime! - mark */
|
||||
nsnull, /* filled in at runtime! - clear */
|
||||
0,0 /* spare */
|
||||
};
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSObjectOps *)
|
||||
@ -905,9 +909,13 @@ JSBool xpc_InitWrappedNativeJSOps()
|
||||
{
|
||||
WrappedNative_ops.newObjectMap = js_ObjectOps.newObjectMap;
|
||||
WrappedNative_ops.destroyObjectMap = js_ObjectOps.destroyObjectMap;
|
||||
WrappedNative_ops.mark = js_ObjectOps.mark;
|
||||
WrappedNative_ops.clear = js_ObjectOps.clear;
|
||||
|
||||
WrappedNativeWithCall_ops.newObjectMap = js_ObjectOps.newObjectMap;
|
||||
WrappedNativeWithCall_ops.destroyObjectMap = js_ObjectOps.destroyObjectMap;
|
||||
WrappedNativeWithCall_ops.mark = js_ObjectOps.mark;
|
||||
WrappedNativeWithCall_ops.clear = js_ObjectOps.clear;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user