public
Description: Mozilla's C implementation of JavaScript
Homepage: http://www.mozilla.org/js/spidermonkey
Clone URL: git://github.com/jbarnette/spidermonkey.git
Search Repo:
spidermonkey / jsgc.h
100644 404 lines (338 sloc) 14.039 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
/* -*- 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
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Mozilla Communicator client code, released
 * March 31, 1998.
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */
 
#ifndef jsgc_h___
#define jsgc_h___
/*
 * JS Garbage Collector.
 */
#include "jsprvtd.h"
#include "jspubtd.h"
#include "jsdhash.h"
#include "jsbit.h"
#include "jsutil.h"
 
JS_BEGIN_EXTERN_C
 
JS_STATIC_ASSERT(JSTRACE_STRING == 2);
 
#define JSTRACE_NAMESPACE 3
#define JSTRACE_QNAME 4
#define JSTRACE_XML 5
 
/*
 * One past the maximum trace kind.
 */
#define JSTRACE_LIMIT 6
 
/*
 * We use the trace kinds as the types for all GC things except external
 * strings.
 */
#define GCX_OBJECT JSTRACE_OBJECT /* JSObject */
#define GCX_DOUBLE JSTRACE_DOUBLE /* jsdouble */
#define GCX_STRING JSTRACE_STRING /* JSString */
#define GCX_NAMESPACE JSTRACE_NAMESPACE /* JSXMLNamespace */
#define GCX_QNAME JSTRACE_QNAME /* JSXMLQName */
#define GCX_XML JSTRACE_XML /* JSXML */
#define GCX_EXTERNAL_STRING JSTRACE_LIMIT /* JSString with external
                                                       chars */
/*
 * The number of defined GC types.
 */
#define GCX_NTYPES (GCX_EXTERNAL_STRING + 8)
 
/*
 * The maximum limit for the number of GC types.
 */
#define GCX_LIMIT_LOG2 4 /* type index bits */
#define GCX_LIMIT JS_BIT(GCX_LIMIT_LOG2)
 
JS_STATIC_ASSERT(GCX_NTYPES <= GCX_LIMIT);
 
/* GC flag definitions, must fit in 8 bits (type index goes in the low bits). */
#define GCF_TYPEMASK JS_BITMASK(GCX_LIMIT_LOG2)
#define GCF_MARK JS_BIT(GCX_LIMIT_LOG2)
#define GCF_FINAL JS_BIT(GCX_LIMIT_LOG2 + 1)
#define GCF_LOCKSHIFT (GCX_LIMIT_LOG2 + 2) /* lock bit shift */
#define GCF_LOCK JS_BIT(GCF_LOCKSHIFT) /* lock request bit in API */
 
/*
 * Get the type of the external string or -1 if the string was not created
 * with JS_NewExternalString.
 */
extern intN
js_GetExternalStringGCType(JSString *str);
 
extern JS_FRIEND_API(uint32)
js_GetGCThingTraceKind(void *thing);
 
/*
 * The sole purpose of the function is to preserve public API compatibility
 * in JS_GetStringBytes which takes only single JSString* argument.
 */
JSRuntime*
js_GetGCStringRuntime(JSString *str);
 
#if 1
/*
 * Since we're forcing a GC from JS_GC anyway, don't bother wasting cycles
 * loading oldval. XXX remove implied force, fix jsinterp.c's "second arg
 * ignored", etc.
 */
#define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JS_TRUE)
#else
#define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JSVAL_IS_GCTHING(oldval))
#endif
 
/*
 * Write barrier macro monitoring property update from oldval to newval in
 * scope->object.
 *
 * Since oldval is used only for the branded scope case, and the oldval actual
 * argument expression is typically not used otherwise by callers, performance
 * benefits if oldval is *not* evaluated into a callsite temporary variable,
 * and instead passed to GC_WRITE_BARRIER for conditional evaluation (we rely
 * on modern compilers to do a good CSE job). Yay, C macros.
 */
#define GC_WRITE_BARRIER(cx,scope,oldval,newval) \
    JS_BEGIN_MACRO \
        if (SCOPE_IS_BRANDED(scope) && \
            (oldval) != (newval) && \
            (VALUE_IS_FUNCTION(cx,oldval) || VALUE_IS_FUNCTION(cx,newval))) { \
            SCOPE_MAKE_UNIQUE_SHAPE(cx, scope); \
        } \
        GC_POKE(cx, oldval); \
    JS_END_MACRO
 
extern JSBool
js_InitGC(JSRuntime *rt, uint32 maxbytes);
 
extern void
js_FinishGC(JSRuntime *rt);
 
extern intN
js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
                                 JSStringFinalizeOp newop);
 
extern JSBool
js_AddRoot(JSContext *cx, void *rp, const char *name);
 
extern JSBool
js_AddRootRT(JSRuntime *rt, void *rp, const char *name);
 
extern JSBool
js_RemoveRoot(JSRuntime *rt, void *rp);
 
#ifdef DEBUG
extern void
js_DumpNamedRoots(JSRuntime *rt,
                  void (*dump)(const char *name, void *rp, void *data),
                  void *data);
#endif
 
extern uint32
js_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data);
 
/* Table of pointers with count valid members. */
typedef struct JSPtrTable {
    size_t count;
    void **array;
} JSPtrTable;
 
extern JSBool
js_RegisterCloseableIterator(JSContext *cx, JSObject *obj);
 
/*
 * The private JSGCThing struct, which describes a gcFreeList element.
 */
struct JSGCThing {
    JSGCThing *next;
    uint8 *flagp;
};
 
#define GC_NBYTES_MAX (10 * sizeof(JSGCThing))
#define GC_NUM_FREELISTS (GC_NBYTES_MAX / sizeof(JSGCThing))
#define GC_FREELIST_NBYTES(i) (((i) + 1) * sizeof(JSGCThing))
#define GC_FREELIST_INDEX(n) (((n) / sizeof(JSGCThing)) - 1)
 
/*
 * Allocates a new GC thing of the given size. After a successful allocation
 * the caller must fully initialize the thing before calling any function that
 * can potentially trigger GC. This will ensure that GC tracing never sees junk
 * values stored in the partially initialized thing.
 */
extern void *
js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes);
 
/*
 * Allocate a new double jsval and store the result in *vp. vp must be a root.
 * The function does not copy the result into any weak root.
 */
extern JSBool
js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp);
 
/*
 * Return a pointer to a new GC-allocated and weakly-rooted jsdouble number,
 * or null when the allocation fails.
 */
extern jsdouble *
js_NewWeaklyRootedDouble(JSContext *cx, jsdouble d);
 
extern JSBool
js_LockGCThingRT(JSRuntime *rt, void *thing);
 
extern JSBool
js_UnlockGCThingRT(JSRuntime *rt, void *thing);
 
extern JSBool
js_IsAboutToBeFinalized(JSContext *cx, void *thing);
 
/*
 * Macro to test if a traversal is the marking phase of GC to avoid exposing
 * ScriptFilenameEntry to traversal implementations.
 */
#define IS_GC_MARKING_TRACER(trc) ((trc)->callback == NULL)
 
#if JS_HAS_XML_SUPPORT
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_XML)
#else
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_STRING)
#endif
 
/*
 * JS_IS_VALID_TRACE_KIND assumes that JSTRACE_STRING is the last non-xml
 * trace kind when JS_HAS_XML_SUPPORT is false.
 */
JS_STATIC_ASSERT(JSTRACE_STRING + 1 == JSTRACE_NAMESPACE);
 
/*
 * Trace jsval when JSVAL_IS_OBJECT(v) can be an arbitrary GC thing casted as
 * JSVAL_OBJECT and js_GetGCThingTraceKind has to be used to find the real
 * type behind v.
 */
extern void
js_CallValueTracerIfGCThing(JSTracer *trc, jsval v);
 
extern void
js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp);
 
extern void
js_TraceRuntime(JSTracer *trc, JSBool allAtoms);
 
extern JS_FRIEND_API(void)
js_TraceContext(JSTracer *trc, JSContext *acx);
 
/*
 * Kinds of js_GC invocation.
 */
typedef enum JSGCInvocationKind {
    /* Normal invocation. */
    GC_NORMAL = 0,
 
    /*
     * Called from js_DestroyContext for last JSContext in a JSRuntime, when
     * it is imperative that rt->gcPoke gets cleared early in js_GC.
     */
    GC_LAST_CONTEXT = 1,
 
    /*
     * Flag bit telling js_GC that the caller has already acquired rt->gcLock.
     * Currently, this flag is set for the invocation kinds that also preserve
     * atoms and weak roots, so we don't need another bit for GC_KEEP_ATOMS.
     */
    GC_LOCK_HELD = 0x10,
    GC_KEEP_ATOMS = GC_LOCK_HELD,
 
    /*
     * Called from js_SetProtoOrParent with a request to set an object's proto
     * or parent slot inserted on rt->setSlotRequests.
     */
    GC_SET_SLOT_REQUEST = GC_LOCK_HELD | 1,
 
    /*
     * Called from js_NewGCThing as a last-ditch GC attempt. See comments
     * in jsgc.c just before js_GC's definition for details.
     */
    GC_LAST_DITCH = GC_LOCK_HELD | 2
} JSGCInvocationKind;
 
extern void
js_GC(JSContext *cx, JSGCInvocationKind gckind);
 
/* Call this after succesful malloc of memory for GC-related things. */
extern void
js_UpdateMallocCounter(JSContext *cx, size_t nbytes);
 
typedef struct JSGCArenaInfo JSGCArenaInfo;
typedef struct JSGCArenaList JSGCArenaList;
typedef struct JSGCChunkInfo JSGCChunkInfo;
 
struct JSGCArenaList {
    JSGCArenaInfo *last; /* last allocated GC arena */
    uint16 lastCount; /* number of allocated things in the last
                                       arena */
    uint16 thingSize; /* size of things to allocate on this list
                                     */
    JSGCThing *freeList; /* list of free GC things */
};
 
typedef union JSGCDoubleCell JSGCDoubleCell;
 
union JSGCDoubleCell {
    double number;
    JSGCDoubleCell *link;
};
 
JS_STATIC_ASSERT(sizeof(JSGCDoubleCell) == sizeof(double));
 
typedef struct JSGCDoubleArenaList {
    JSGCArenaInfo *first; /* first allocated GC arena */
    jsbitmap *nextDoubleFlags; /* bitmask with flags to check for free
                                           things */
} JSGCDoubleArenaList;
 
struct JSWeakRoots {
    /* Most recently created things by type, members of the GC's root set. */
    void *newborn[GCX_NTYPES];
 
    /* Atom root for the last-looked-up atom on this context. */
    jsval lastAtom;
 
    /* Root for the result of the most recent js_InternalInvoke call. */
    jsval lastInternalResult;
};
 
JS_STATIC_ASSERT(JSVAL_NULL == 0);
#define JS_CLEAR_WEAK_ROOTS(wr) (memset((wr), 0, sizeof(JSWeakRoots)))
 
#ifdef DEBUG_notme
#define JS_GCMETER 1
#endif
 
#ifdef JS_GCMETER
 
typedef struct JSGCArenaStats {
    uint32 alloc; /* allocation attempts */
    uint32 localalloc; /* allocations from local lists */
    uint32 retry; /* allocation retries after running the GC */
    uint32 fail; /* allocation failures */
    uint32 nthings; /* live GC things */
    uint32 maxthings; /* maximum of live GC cells */
    double totalthings; /* live GC things the GC scanned so far */
    uint32 narenas; /* number of arena in list before the GC */
    uint32 newarenas; /* new arenas allocated before the last GC */
    uint32 livearenas; /* number of live arenas after the last GC */
    uint32 maxarenas; /* maximum of allocated arenas */
    uint32 totalarenas; /* total number of arenas with live things that
                               GC scanned so far */
} JSGCArenaStats;
 
typedef struct JSGCStats {
    uint32 finalfail; /* finalizer calls allocator failures */
    uint32 lockborn; /* things born locked */
    uint32 lock; /* valid lock calls */
    uint32 unlock; /* valid unlock calls */
    uint32 depth; /* mark tail recursion depth */
    uint32 maxdepth; /* maximum mark tail recursion depth */
    uint32 cdepth; /* mark recursion depth of C functions */
    uint32 maxcdepth; /* maximum mark recursion depth of C functions */
    uint32 untraced; /* number of times tracing of GC thing's children were
                           delayed due to a low C stack */
#ifdef DEBUG
    uint32 maxuntraced;/* maximum number of things with children to trace
                           later */
#endif
    uint32 maxlevel; /* maximum GC nesting (indirect recursion) level */
    uint32 poke; /* number of potentially useful GC calls */
    uint32 afree; /* thing arenas freed so far */
    uint32 stackseg; /* total extraordinary stack segments scanned */
    uint32 segslots; /* total stack segment jsval slots scanned */
    uint32 nclose; /* number of objects with close hooks */
    uint32 maxnclose; /* max number of objects with close hooks */
    uint32 closelater; /* number of close hooks scheduled to run */
    uint32 maxcloselater; /* max number of close hooks scheduled to run */
 
    JSGCArenaStats arenaStats[GC_NUM_FREELISTS];
    JSGCArenaStats doubleArenaStats;
} JSGCStats;
 
extern JS_FRIEND_API(void)
js_DumpGCStats(JSRuntime *rt, FILE *fp);
 
#endif /* JS_GCMETER */
 
JS_END_EXTERN_C
 
#endif /* jsgc_h___ */