1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
16 * The Original Code is Mozilla Communicator client code, released
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.
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.
38 * ***** END LICENSE BLOCK ***** */
43 * JS Garbage Collector.
52 #include "jsversion.h"
59 * One past the maximum trace kind.
61 #define JSTRACE_LIMIT 4
63 const uintN JS_EXTERNAL_STRING_LIMIT
= 8;
66 * Get the type of the external string or -1 if the string was not created
67 * with JS_NewExternalString.
70 js_GetExternalStringGCType(JSString
*str
);
72 extern JS_FRIEND_API(uint32
)
73 js_GetGCThingTraceKind(void *thing
);
76 * The sole purpose of the function is to preserve public API compatibility
77 * in JS_GetStringBytes which takes only single JSString* argument.
80 js_GetGCThingRuntime(void *thing
);
84 * Since we're forcing a GC from JS_GC anyway, don't bother wasting cycles
85 * loading oldval. XXX remove implied force, fix jsinterp.c's "second arg
88 #define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JS_TRUE)
90 #define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JSVAL_IS_GCTHING(oldval))
94 js_InitGC(JSRuntime
*rt
, uint32 maxbytes
);
97 js_FinishGC(JSRuntime
*rt
);
100 js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop
,
101 JSStringFinalizeOp newop
);
104 js_AddRoot(JSContext
*cx
, void *rp
, const char *name
);
107 js_AddRootRT(JSRuntime
*rt
, void *rp
, const char *name
);
110 js_RemoveRoot(JSRuntime
*rt
, void *rp
);
114 js_DumpNamedRoots(JSRuntime
*rt
,
115 void (*dump
)(const char *name
, void *rp
, void *data
),
120 js_MapGCRoots(JSRuntime
*rt
, JSGCRootMapFun map
, void *data
);
122 /* Table of pointers with count valid members. */
123 typedef struct JSPtrTable
{
129 js_RegisterCloseableIterator(JSContext
*cx
, JSObject
*obj
);
132 * Allocate a new double jsval and store the result in *vp. vp must be a root.
133 * The function does not copy the result into any weak root.
136 js_NewDoubleInRootedValue(JSContext
*cx
, jsdouble d
, jsval
*vp
);
139 * Return a pointer to a new GC-allocated and weakly-rooted jsdouble number,
140 * or null when the allocation fails.
143 js_NewWeaklyRootedDouble(JSContext
*cx
, jsdouble d
);
147 js_ReserveObjects(JSContext
*cx
, size_t nobjects
);
151 js_LockGCThingRT(JSRuntime
*rt
, void *thing
);
154 js_UnlockGCThingRT(JSRuntime
*rt
, void *thing
);
157 js_IsAboutToBeFinalized(void *thing
);
160 * Macro to test if a traversal is the marking phase of GC to avoid exposing
161 * ScriptFilenameEntry to traversal implementations.
163 #define IS_GC_MARKING_TRACER(trc) ((trc)->callback == NULL)
165 #if JS_HAS_XML_SUPPORT
166 # define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) < JSTRACE_LIMIT)
168 # define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_STRING)
172 * Trace jsval when JSVAL_IS_OBJECT(v) can be a GC thing pointer tagged as a
173 * jsval. NB: punning an arbitrary JSString * as an untagged (object-tagged)
174 * jsval no longer works due to static int and unit strings!
177 js_CallValueTracerIfGCThing(JSTracer
*trc
, jsval v
);
180 js_TraceStackFrame(JSTracer
*trc
, JSStackFrame
*fp
);
182 extern JS_REQUIRES_STACK
void
183 js_TraceRuntime(JSTracer
*trc
);
185 extern JS_REQUIRES_STACK
JS_FRIEND_API(void)
186 js_TraceContext(JSTracer
*trc
, JSContext
*acx
);
189 * Schedule the GC call at a later safe point.
191 #ifndef JS_THREADSAFE
192 # define js_TriggerGC(cx, gcLocked) js_TriggerGC (cx)
196 js_TriggerGC(JSContext
*cx
, JSBool gcLocked
);
199 * Kinds of js_GC invocation.
201 typedef enum JSGCInvocationKind
{
202 /* Normal invocation. */
206 * Called from js_DestroyContext for last JSContext in a JSRuntime, when
207 * it is imperative that rt->gcPoke gets cleared early in js_GC.
212 * Flag bit telling js_GC that the caller has already acquired rt->gcLock.
217 * Called from js_SetProtoOrParent with a request to set an object's proto
218 * or parent slot inserted on rt->setSlotRequests.
220 GC_SET_SLOT_REQUEST
= GC_LOCK_HELD
| 1
221 } JSGCInvocationKind
;
224 js_GC(JSContext
*cx
, JSGCInvocationKind gckind
);
227 js_CallGCMarker(JSTracer
*trc
, void *thing
, uint32 kind
);
230 * The kind of GC thing with a finalizer. The external strings follow the
231 * ordinary string to simplify js_GetExternalStringGCType.
233 enum JSFinalizeGCThingKind
{
237 #if JS_HAS_XML_SUPPORT
241 FINALIZE_EXTERNAL_STRING0
,
242 FINALIZE_EXTERNAL_STRING1
,
243 FINALIZE_EXTERNAL_STRING2
,
244 FINALIZE_EXTERNAL_STRING3
,
245 FINALIZE_EXTERNAL_STRING4
,
246 FINALIZE_EXTERNAL_STRING5
,
247 FINALIZE_EXTERNAL_STRING6
,
248 FINALIZE_EXTERNAL_STRING7
,
249 FINALIZE_EXTERNAL_STRING_LAST
= FINALIZE_EXTERNAL_STRING7
,
254 IsFinalizableStringKind(unsigned thingKind
)
256 return unsigned(FINALIZE_STRING
) <= thingKind
&&
257 thingKind
<= unsigned(FINALIZE_EXTERNAL_STRING_LAST
);
261 * Allocates a new GC thing. After a successful allocation the caller must
262 * fully initialize the thing before calling any function that can potentially
263 * trigger GC. This will ensure that GC tracing never sees junk values stored
264 * in the partially initialized thing.
267 js_NewFinalizableGCThing(JSContext
*cx
, unsigned thingKind
);
269 static inline JSObject
*
270 js_NewGCObject(JSContext
*cx
)
272 return (JSObject
*) js_NewFinalizableGCThing(cx
, FINALIZE_OBJECT
);
275 static inline JSObject
*
276 js_NewGCIter(JSContext
*cx
)
278 return (JSObject
*) js_NewFinalizableGCThing(cx
, FINALIZE_ITER
);
281 static inline JSString
*
282 js_NewGCString(JSContext
*cx
)
284 return (JSString
*) js_NewFinalizableGCThing(cx
, FINALIZE_STRING
);
287 static inline JSString
*
288 js_NewGCExternalString(JSContext
*cx
, uintN type
)
290 JS_ASSERT(type
< JS_EXTERNAL_STRING_LIMIT
);
291 type
+= FINALIZE_EXTERNAL_STRING0
;
292 return (JSString
*) js_NewFinalizableGCThing(cx
, type
);
295 static inline JSFunction
*
296 js_NewGCFunction(JSContext
*cx
)
298 return (JSFunction
*) js_NewFinalizableGCThing(cx
, FINALIZE_FUNCTION
);
301 #if JS_HAS_XML_SUPPORT
302 static inline JSXML
*
303 js_NewGCXML(JSContext
*cx
)
305 return (JSXML
*) js_NewFinalizableGCThing(cx
, FINALIZE_XML
);
310 struct JSGCChunkInfo
;
312 struct JSGCArenaList
{
313 JSGCArena
*head
; /* list start */
314 JSGCArena
*cursor
; /* arena with free things */
315 uint32 thingKind
; /* one of JSFinalizeGCThingKind */
316 uint32 thingSize
; /* size of things to allocate on this list
320 struct JSGCDoubleArenaList
{
321 JSGCArena
*head
; /* list start */
322 JSGCArena
*cursor
; /* next arena with free cells */
325 struct JSGCFreeLists
{
327 JSGCThing
*finalizables
[FINALIZE_LIMIT
];
330 void moveTo(JSGCFreeLists
* another
);
333 bool isEmpty() const {
336 for (size_t i
= 0; i
!= JS_ARRAY_LENGTH(finalizables
); ++i
) {
346 js_DestroyScriptsToGC(JSContext
*cx
, JSThreadData
*data
);
349 /* Most recently created things by type, members of the GC's root set. */
350 void *finalizableNewborns
[FINALIZE_LIMIT
];
351 jsdouble
*newbornDouble
;
353 /* Atom root for the last-looked-up atom on this context. */
356 /* Root for the result of the most recent js_InternalInvoke call. */
357 jsval lastInternalResult
;
359 void mark(JSTracer
*trc
);
362 #define JS_CLEAR_WEAK_ROOTS(wr) (memset((wr), 0, sizeof(JSWeakRoots)))
369 * During the finalization we do not free immediately. Rather we add the
370 * corresponding pointers to a buffer which we later release on the
373 * The buffer is implemented as a vector of 64K arrays of pointers, not as a
374 * simple vector, to avoid realloc calls during the vector growth and to not
375 * bloat the binary size of the inlined freeLater method. Any OOM during
376 * buffer growth results in the pointer being freed immediately.
378 class BackgroundSweepTask
: public JSBackgroundTask
{
379 static const size_t FREE_ARRAY_SIZE
= size_t(1) << 16;
380 static const size_t FREE_ARRAY_LENGTH
= FREE_ARRAY_SIZE
/ sizeof(void *);
382 Vector
<void **, 16, js::SystemAllocPolicy
> freeVector
;
384 void **freeCursorEnd
;
387 replenishAndFreeLater(void *ptr
);
389 static void freeElementsAndArray(void **array
, void **end
) {
390 JS_ASSERT(array
<= end
);
391 for (void **p
= array
; p
!= end
; ++p
)
397 BackgroundSweepTask()
398 : freeCursor(NULL
), freeCursorEnd(NULL
) { }
400 void freeLater(void* ptr
) {
401 if (freeCursor
!= freeCursorEnd
)
404 replenishAndFreeLater(ptr
);
414 js_FinalizeStringRT(JSRuntime
*rt
, JSString
*str
);
416 #if defined JS_GCMETER
417 const bool JS_WANT_GC_METER_PRINT
= true;
419 # define JS_GCMETER 1
420 const bool JS_WANT_GC_METER_PRINT
= false;
425 struct JSGCArenaStats
{
426 uint32 alloc
; /* allocation attempts */
427 uint32 localalloc
; /* allocations from local lists */
428 uint32 retry
; /* allocation retries after running the GC */
429 uint32 fail
; /* allocation failures */
430 uint32 nthings
; /* live GC things */
431 uint32 maxthings
; /* maximum of live GC cells */
432 double totalthings
; /* live GC things the GC scanned so far */
433 uint32 narenas
; /* number of arena in list before the GC */
434 uint32 newarenas
; /* new arenas allocated before the last GC */
435 uint32 livearenas
; /* number of live arenas after the last GC */
436 uint32 maxarenas
; /* maximum of allocated arenas */
437 uint32 totalarenas
; /* total number of arenas with live things that
442 uint32 finalfail
; /* finalizer calls allocator failures */
443 uint32 lockborn
; /* things born locked */
444 uint32 lock
; /* valid lock calls */
445 uint32 unlock
; /* valid unlock calls */
446 uint32 depth
; /* mark tail recursion depth */
447 uint32 maxdepth
; /* maximum mark tail recursion depth */
448 uint32 cdepth
; /* mark recursion depth of C functions */
449 uint32 maxcdepth
; /* maximum mark recursion depth of C functions */
450 uint32 unmarked
; /* number of times marking of GC thing's children were
451 delayed due to a low C stack */
453 uint32 maxunmarked
;/* maximum number of things with children to mark
456 uint32 maxlevel
; /* maximum GC nesting (indirect recursion) level */
457 uint32 poke
; /* number of potentially useful GC calls */
458 uint32 afree
; /* thing arenas freed so far */
459 uint32 stackseg
; /* total extraordinary stack segments scanned */
460 uint32 segslots
; /* total stack segment jsval slots scanned */
461 uint32 nclose
; /* number of objects with close hooks */
462 uint32 maxnclose
; /* max number of objects with close hooks */
463 uint32 closelater
; /* number of close hooks scheduled to run */
464 uint32 maxcloselater
; /* max number of close hooks scheduled to run */
465 uint32 nallarenas
; /* number of all allocated arenas */
466 uint32 maxnallarenas
; /* maximum number of all allocated arenas */
467 uint32 nchunks
; /* number of allocated chunks */
468 uint32 maxnchunks
; /* maximum number of allocated chunks */
470 JSGCArenaStats arenaStats
[FINALIZE_LIMIT
];
471 JSGCArenaStats doubleArenaStats
;
474 extern JS_FRIEND_API(void)
475 js_DumpGCStats(JSRuntime
*rt
, FILE *fp
);
477 #endif /* JS_GCMETER */
480 * This function is defined in jsdbgapi.cpp but is declared here to avoid
481 * polluting jsdbgapi.h, a public API header, with internal functions.
484 js_MarkTraps(JSTracer
*trc
);
491 TraceObjectVector(JSTracer
*trc
, JSObject
**vec
, uint32 len
);
495 TraceValues(JSTracer
*trc
, size_t len
, jsval
*vec
, const char *name
)
497 TraceValues(JSTracer
*trc
, size_t len
, jsval
*vec
, const char *) /* last arg unused in release. kill unreferenced formal param warnings */
500 for (jsval
*vp
= vec
, *end
= vp
+ len
; vp
< end
; vp
++) {
502 if (JSVAL_IS_TRACEABLE(v
)) {
503 JS_SET_TRACING_INDEX(trc
, name
, vp
- vec
);
504 js_CallGCMarker(trc
, JSVAL_TO_TRACEABLE(v
), JSVAL_TRACE_KIND(v
));
511 #endif /* jsgc_h___ */