|
|
1.1 root 1: /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2: *
3: * ***** BEGIN LICENSE BLOCK *****
4: * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5: *
6: * The contents of this file are subject to the Mozilla Public License Version
7: * 1.1 (the "License"); you may not use this file except in compliance with
8: * the License. You may obtain a copy of the License at
9: * http://www.mozilla.org/MPL/
10: *
11: * Software distributed under the License is distributed on an "AS IS" basis,
12: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13: * for the specific language governing rights and limitations under the
14: * License.
15: *
16: * The Original Code is Mozilla Communicator client code, released
17: * March 31, 1998.
18: *
19: * The Initial Developer of the Original Code is
20: * Netscape Communications Corporation.
21: * Portions created by the Initial Developer are Copyright (C) 1998
22: * the Initial Developer. All Rights Reserved.
23: *
24: * Contributor(s):
25: *
26: * Alternatively, the contents of this file may be used under the terms of
27: * either of the GNU General Public License Version 2 or later (the "GPL"),
28: * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29: * in which case the provisions of the GPL or the LGPL are applicable instead
30: * of those above. If you wish to allow use of your version of this file only
31: * under the terms of either the GPL or the LGPL, and not to allow others to
32: * use your version of this file under the terms of the MPL, indicate your
33: * decision by deleting the provisions above and replace them with the notice
34: * and other provisions required by the GPL or the LGPL. If you do not delete
35: * the provisions above, a recipient may use your version of this file under
36: * the terms of any one of the MPL, the GPL or the LGPL.
37: *
38: * ***** END LICENSE BLOCK ***** */
39:
40: #ifndef jsgc_h___
41: #define jsgc_h___
42: /*
43: * JS Garbage Collector.
44: */
45: #include "jsprvtd.h"
46: #include "jspubtd.h"
47: #include "jsdhash.h"
1.1.1.2 ! root 48: #include "jsutil.h"
1.1 root 49:
50: JS_BEGIN_EXTERN_C
51:
52: /* GC thing type indexes. */
53: #define GCX_OBJECT 0 /* JSObject */
54: #define GCX_STRING 1 /* JSString */
55: #define GCX_DOUBLE 2 /* jsdouble */
56: #define GCX_MUTABLE_STRING 3 /* JSString that's mutable --
57: single-threaded only! */
1.1.1.2 ! root 58: #define GCX_PRIVATE 4 /* private (unscanned) data */
! 59: #define GCX_NAMESPACE 5 /* JSXMLNamespace */
! 60: #define GCX_QNAME 6 /* JSXMLQName */
! 61: #define GCX_XML 7 /* JSXML */
! 62: #define GCX_EXTERNAL_STRING 8 /* JSString w/ external chars */
! 63:
! 64: #define GCX_NTYPES_LOG2 4 /* type index bits */
1.1 root 65: #define GCX_NTYPES JS_BIT(GCX_NTYPES_LOG2)
66:
67: /* GC flag definitions, must fit in 8 bits (type index goes in the low bits). */
68: #define GCF_TYPEMASK JS_BITMASK(GCX_NTYPES_LOG2)
69: #define GCF_MARK JS_BIT(GCX_NTYPES_LOG2)
70: #define GCF_FINAL JS_BIT(GCX_NTYPES_LOG2 + 1)
1.1.1.2 ! root 71: #define GCF_SYSTEM JS_BIT(GCX_NTYPES_LOG2 + 2)
! 72: #define GCF_LOCKSHIFT (GCX_NTYPES_LOG2 + 3) /* lock bit shift */
1.1 root 73: #define GCF_LOCK JS_BIT(GCF_LOCKSHIFT) /* lock request bit in API */
74:
75: /* Pseudo-flag that modifies GCX_STRING to make GCX_MUTABLE_STRING. */
76: #define GCF_MUTABLE 2
77:
78: #if (GCX_STRING | GCF_MUTABLE) != GCX_MUTABLE_STRING
79: # error "mutable string type index botch!"
80: #endif
81:
82: extern uint8 *
83: js_GetGCThingFlags(void *thing);
84:
1.1.1.2 ! root 85: /*
! 86: * The sole purpose of the function is to preserve public API compatibility
! 87: * in JS_GetStringBytes which takes only single JSString* argument.
! 88: */
! 89: JSRuntime*
! 90: js_GetGCStringRuntime(JSString *str);
1.1 root 91:
92: #if 1
93: /*
94: * Since we're forcing a GC from JS_GC anyway, don't bother wasting cycles
95: * loading oldval. XXX remove implied force, fix jsinterp.c's "second arg
96: * ignored", etc.
97: */
98: #define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JS_TRUE)
99: #else
100: #define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JSVAL_IS_GCTHING(oldval))
101: #endif
102:
103: extern intN
104: js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
105: JSStringFinalizeOp newop);
106:
107: extern JSBool
108: js_InitGC(JSRuntime *rt, uint32 maxbytes);
109:
110: extern void
111: js_FinishGC(JSRuntime *rt);
112:
113: extern JSBool
114: js_AddRoot(JSContext *cx, void *rp, const char *name);
115:
116: extern JSBool
117: js_AddRootRT(JSRuntime *rt, void *rp, const char *name);
118:
119: extern JSBool
120: js_RemoveRoot(JSRuntime *rt, void *rp);
121:
1.1.1.2 ! root 122: #ifdef DEBUG
! 123: extern void
! 124: js_DumpNamedRoots(JSRuntime *rt,
! 125: void (*dump)(const char *name, void *rp, void *data),
! 126: void *data);
! 127: #endif
! 128:
! 129: extern uint32
! 130: js_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data);
! 131:
! 132: /* Table of pointers with count valid members. */
! 133: typedef struct JSPtrTable {
! 134: size_t count;
! 135: void **array;
! 136: } JSPtrTable;
! 137:
! 138: extern JSBool
! 139: js_RegisterCloseableIterator(JSContext *cx, JSObject *obj);
! 140:
! 141: #if JS_HAS_GENERATORS
! 142:
! 143: /*
! 144: * Runtime state to support generators' close hooks.
! 145: */
! 146: typedef struct JSGCCloseState {
! 147: /*
! 148: * Singly linked list of generators that are reachable from GC roots or
! 149: * were created after the last GC.
! 150: */
! 151: JSGenerator *reachableList;
! 152:
! 153: /*
! 154: * Head of the queue of generators that have already become unreachable but
! 155: * whose close hooks are not yet run.
! 156: */
! 157: JSGenerator *todoQueue;
! 158:
! 159: #ifndef JS_THREADSAFE
! 160: /*
! 161: * Flag indicating that the current thread is excuting a close hook for
! 162: * single thread case.
! 163: */
! 164: JSBool runningCloseHook;
! 165: #endif
! 166: } JSGCCloseState;
! 167:
! 168: extern void
! 169: js_RegisterGenerator(JSContext *cx, JSGenerator *gen);
! 170:
! 171: extern JSBool
! 172: js_RunCloseHooks(JSContext *cx);
! 173:
! 174: #endif
! 175:
! 176: /*
! 177: * The private JSGCThing struct, which describes a gcFreeList element.
! 178: */
! 179: struct JSGCThing {
! 180: JSGCThing *next;
! 181: uint8 *flagp;
! 182: };
! 183:
! 184: #define GC_NBYTES_MAX (10 * sizeof(JSGCThing))
! 185: #define GC_NUM_FREELISTS (GC_NBYTES_MAX / sizeof(JSGCThing))
! 186: #define GC_FREELIST_NBYTES(i) (((i) + 1) * sizeof(JSGCThing))
! 187: #define GC_FREELIST_INDEX(n) (((n) / sizeof(JSGCThing)) - 1)
! 188:
1.1 root 189: extern void *
1.1.1.2 ! root 190: js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes);
1.1 root 191:
192: extern JSBool
193: js_LockGCThing(JSContext *cx, void *thing);
194:
195: extern JSBool
196: js_LockGCThingRT(JSRuntime *rt, void *thing);
197:
198: extern JSBool
199: js_UnlockGCThingRT(JSRuntime *rt, void *thing);
200:
1.1.1.2 ! root 201: extern JSBool
1.1 root 202: js_IsAboutToBeFinalized(JSContext *cx, void *thing);
203:
204: extern void
1.1.1.2 ! root 205: js_MarkAtom(JSContext *cx, JSAtom *atom);
1.1 root 206:
207: /* We avoid a large number of unnecessary calls by doing the flag check first */
1.1.1.2 ! root 208: #define GC_MARK_ATOM(cx, atom) \
1.1 root 209: JS_BEGIN_MACRO \
210: if (!((atom)->flags & ATOM_MARK)) \
1.1.1.2 ! root 211: js_MarkAtom(cx, atom); \
1.1 root 212: JS_END_MACRO
213:
1.1.1.2 ! root 214: /*
! 215: * Always use GC_MARK macro and never call js_MarkGCThing directly so
! 216: * when GC_MARK_DEBUG is defined the dump of live GC things does not miss
! 217: * a thing.
! 218: */
1.1 root 219: extern void
1.1.1.2 ! root 220: js_MarkGCThing(JSContext *cx, void *thing);
1.1 root 221:
222: #ifdef GC_MARK_DEBUG
223:
1.1.1.2 ! root 224: # define GC_MARK(cx, thing, name) js_MarkNamedGCThing(cx, thing, name)
1.1 root 225:
1.1.1.2 ! root 226: extern void
! 227: js_MarkNamedGCThing(JSContext *cx, void *thing, const char *name);
1.1 root 228:
1.1.1.2 ! root 229: extern JS_FRIEND_DATA(FILE *) js_DumpGCHeap;
! 230: JS_EXTERN_DATA(void *) js_LiveThingToFind;
1.1 root 231:
1.1.1.2 ! root 232: #else
1.1 root 233:
1.1.1.2 ! root 234: # define GC_MARK(cx, thing, name) js_MarkGCThing(cx, thing)
1.1 root 235:
1.1.1.2 ! root 236: #endif
! 237:
! 238: extern void
! 239: js_MarkStackFrame(JSContext *cx, JSStackFrame *fp);
1.1 root 240:
241: /*
1.1.1.2 ! root 242: * Kinds of js_GC invocation.
1.1 root 243: */
1.1.1.2 ! root 244: typedef enum JSGCInvocationKind {
! 245: /* Normal invocation. */
! 246: GC_NORMAL,
! 247:
! 248: /*
! 249: * Called from js_DestroyContext for last JSContext in a JSRuntime, when
! 250: * it is imperative that rt->gcPoke gets cleared early in js_GC.
! 251: */
! 252: GC_LAST_CONTEXT,
! 253:
! 254: /*
! 255: * Called from js_NewGCThing as a last-ditch GC attempt. See comments
! 256: * before js_GC definition for details.
! 257: */
! 258: GC_LAST_DITCH
! 259: } JSGCInvocationKind;
1.1 root 260:
261: extern void
1.1.1.2 ! root 262: js_GC(JSContext *cx, JSGCInvocationKind gckind);
1.1 root 263:
1.1.1.2 ! root 264: /* Call this after succesful malloc of memory for GC-related things. */
1.1 root 265: extern void
1.1.1.2 ! root 266: js_UpdateMallocCounter(JSContext *cx, size_t nbytes);
! 267:
! 268: #ifdef DEBUG_notme
! 269: #define JS_GCMETER 1
! 270: #endif
1.1 root 271:
272: #ifdef JS_GCMETER
273:
274: typedef struct JSGCStats {
1.1.1.2 ! root 275: #ifdef JS_THREADSAFE
! 276: uint32 localalloc; /* number of succeeded allocations from local lists */
! 277: #endif
1.1 root 278: uint32 alloc; /* number of allocation attempts */
279: uint32 retry; /* allocation attempt retries after running the GC */
1.1.1.2 ! root 280: uint32 retryhalt; /* allocation retries halted by the branch callback */
1.1 root 281: uint32 fail; /* allocation failures */
282: uint32 finalfail; /* finalizer calls allocator failures */
1.1.1.2 ! root 283: uint32 lockborn; /* things born locked */
1.1 root 284: uint32 lock; /* valid lock calls */
285: uint32 unlock; /* valid unlock calls */
1.1.1.2 ! root 286: uint32 depth; /* mark tail recursion depth */
! 287: uint32 maxdepth; /* maximum mark tail recursion depth */
! 288: uint32 cdepth; /* mark recursion depth of C functions */
! 289: uint32 maxcdepth; /* maximum mark recursion depth of C functions */
! 290: uint32 unscanned; /* mark C stack overflows or number of times
! 291: GC things were put in unscanned bag */
! 292: #ifdef DEBUG
! 293: uint32 maxunscanned; /* maximum size of unscanned bag */
! 294: #endif
1.1 root 295: uint32 maxlevel; /* maximum GC nesting (indirect recursion) level */
296: uint32 poke; /* number of potentially useful GC calls */
297: uint32 nopoke; /* useless GC calls where js_PokeGC was not set */
298: uint32 afree; /* thing arenas freed so far */
299: uint32 stackseg; /* total extraordinary stack segments scanned */
300: uint32 segslots; /* total stack segment jsval slots scanned */
1.1.1.2 ! root 301: uint32 nclose; /* number of objects with close hooks */
! 302: uint32 maxnclose; /* max number of objects with close hooks */
! 303: uint32 closelater; /* number of close hooks scheduled to run */
! 304: uint32 maxcloselater; /* max number of close hooks scheduled to run */
1.1 root 305: } JSGCStats;
306:
1.1.1.2 ! root 307: extern JS_FRIEND_API(void)
1.1 root 308: js_DumpGCStats(JSRuntime *rt, FILE *fp);
309:
310: #endif /* JS_GCMETER */
311:
1.1.1.2 ! root 312: typedef struct JSGCArena JSGCArena;
! 313: typedef struct JSGCArenaList JSGCArenaList;
! 314:
! 315: #ifdef JS_GCMETER
! 316: typedef struct JSGCArenaStats JSGCArenaStats;
! 317:
! 318: struct JSGCArenaStats {
! 319: uint32 narenas; /* number of arena in list */
! 320: uint32 maxarenas; /* maximun number of allocated arenas */
! 321: uint32 nthings; /* number of allocates JSGCThing */
! 322: uint32 maxthings; /* maximum number number of allocates JSGCThing */
! 323: uint32 totalnew; /* number of succeeded calls to js_NewGCThing */
! 324: uint32 freelen; /* freeList lengths */
! 325: uint32 recycle; /* number of things recycled through freeList */
! 326: uint32 totalarenas; /* total number of arenas with live things that
! 327: GC scanned so far */
! 328: uint32 totalfreelen; /* total number of things that GC put to free
! 329: list so far */
! 330: };
! 331: #endif
! 332:
! 333: struct JSGCArenaList {
! 334: JSGCArena *last; /* last allocated GC arena */
! 335: uint16 lastLimit; /* end offset of allocated so far things in
! 336: the last arena */
! 337: uint16 thingSize; /* size of things to allocate on this list */
! 338: JSGCThing *freeList; /* list of free GC things */
! 339: #ifdef JS_GCMETER
! 340: JSGCArenaStats stats;
! 341: #endif
! 342: };
! 343:
! 344: typedef struct JSWeakRoots {
! 345: /* Most recently created things by type, members of the GC's root set. */
! 346: JSGCThing *newborn[GCX_NTYPES];
! 347:
! 348: /* Atom root for the last-looked-up atom on this context. */
! 349: JSAtom *lastAtom;
! 350:
! 351: /* Root for the result of the most recent js_InternalInvoke call. */
! 352: jsval lastInternalResult;
! 353: } JSWeakRoots;
! 354:
! 355: JS_STATIC_ASSERT(JSVAL_NULL == 0);
! 356: #define JS_CLEAR_WEAK_ROOTS(wr) (memset((wr), 0, sizeof(JSWeakRoots)))
! 357:
! 358: #ifdef DEBUG_notme
! 359: #define TOO_MUCH_GC 1
! 360: #endif
! 361:
! 362: #ifdef WAY_TOO_MUCH_GC
! 363: #define TOO_MUCH_GC 1
! 364: #endif
! 365:
1.1 root 366: JS_END_EXTERN_C
367:
368: #endif /* jsgc_h___ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.