Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/js/GCAPI.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
 * vim: set ts=8 sts=4 et sw=4 tw=99:
3
 * This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
/*
8
 * High-level interface to the JS garbage collector.
9
 */
10
11
#ifndef js_GCAPI_h
12
#define js_GCAPI_h
13
14
#include "mozilla/TimeStamp.h"
15
#include "mozilla/Vector.h"
16
17
#include "js/GCAnnotations.h"
18
#include "js/TypeDecls.h"
19
#include "js/UniquePtr.h"
20
#include "js/Utility.h"
21
22
struct JSFreeOp;
23
24
#ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
25
#pragma GCC diagnostic push
26
#pragma GCC diagnostic ignored "-Wattributes"
27
#endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
28
29
class JS_PUBLIC_API(JSTracer);
30
31
#ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
32
#pragma GCC diagnostic pop
33
#endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
34
35
namespace js {
36
namespace gc {
37
class GCRuntime;
38
} // namespace gc
39
namespace gcstats {
40
struct Statistics;
41
} // namespace gcstats
42
} // namespace js
43
44
typedef enum JSGCMode {
45
    /** Perform only global GCs. */
46
    JSGC_MODE_GLOBAL = 0,
47
48
    /** Perform per-zone GCs until too much garbage has accumulated. */
49
    JSGC_MODE_ZONE = 1,
50
51
    /**
52
     * Collect in short time slices rather than all at once. Implies
53
     * JSGC_MODE_ZONE.
54
     */
55
    JSGC_MODE_INCREMENTAL = 2
56
} JSGCMode;
57
58
/**
59
 * Kinds of js_GC invocation.
60
 */
61
typedef enum JSGCInvocationKind {
62
    /* Normal invocation. */
63
    GC_NORMAL = 0,
64
65
    /* Minimize GC triggers and release empty GC chunks right away. */
66
    GC_SHRINK = 1
67
} JSGCInvocationKind;
68
69
typedef enum JSGCParamKey {
70
    /**
71
     * Maximum nominal heap before last ditch GC.
72
     *
73
     * Soft limit on the number of bytes we are allowed to allocate in the GC
74
     * heap. Attempts to allocate gcthings over this limit will return null and
75
     * subsequently invoke the standard OOM machinery, independent of available
76
     * physical memory.
77
     *
78
     * Pref: javascript.options.mem.max
79
     * Default: 0xffffffff
80
     */
81
    JSGC_MAX_BYTES          = 0,
82
83
    /**
84
     * Initial value for the malloc bytes threshold.
85
     *
86
     * Pref: javascript.options.mem.high_water_mark
87
     * Default: TuningDefaults::MaxMallocBytes
88
     */
89
    JSGC_MAX_MALLOC_BYTES   = 1,
90
91
    /**
92
     * Maximum size of the generational GC nurseries.
93
     *
94
     * Pref: javascript.options.mem.nursery.max_kb
95
     * Default: JS::DefaultNurseryBytes
96
     */
97
    JSGC_MAX_NURSERY_BYTES  = 2,
98
99
    /** Amount of bytes allocated by the GC. */
100
    JSGC_BYTES = 3,
101
102
    /** Number of times GC has been invoked. Includes both major and minor GC. */
103
    JSGC_NUMBER = 4,
104
105
    /**
106
     * Select GC mode.
107
     *
108
     * See: JSGCMode in GCAPI.h
109
     * prefs: javascript.options.mem.gc_per_zone and
110
     *   javascript.options.mem.gc_incremental.
111
     * Default: JSGC_MODE_INCREMENTAL
112
     */
113
    JSGC_MODE = 6,
114
115
    /** Number of cached empty GC chunks. */
116
    JSGC_UNUSED_CHUNKS = 7,
117
118
    /** Total number of allocated GC chunks. */
119
    JSGC_TOTAL_CHUNKS = 8,
120
121
    /**
122
     * Max milliseconds to spend in an incremental GC slice.
123
     *
124
     * Pref: javascript.options.mem.gc_incremental_slice_ms
125
     * Default: DefaultTimeBudget.
126
     */
127
    JSGC_SLICE_TIME_BUDGET = 9,
128
129
    /**
130
     * Maximum size the GC mark stack can grow to.
131
     *
132
     * Pref: none
133
     * Default: MarkStack::DefaultCapacity
134
     */
135
    JSGC_MARK_STACK_LIMIT = 10,
136
137
    /**
138
     * GCs less than this far apart in time will be considered 'high-frequency
139
     * GCs'.
140
     *
141
     * See setGCLastBytes in jsgc.cpp.
142
     *
143
     * Pref: javascript.options.mem.gc_high_frequency_time_limit_ms
144
     * Default: HighFrequencyThreshold
145
     */
146
    JSGC_HIGH_FREQUENCY_TIME_LIMIT = 11,
147
148
    /**
149
     * Start of dynamic heap growth.
150
     *
151
     * Pref: javascript.options.mem.gc_high_frequency_low_limit_mb
152
     * Default: HighFrequencyLowLimitBytes
153
     */
154
    JSGC_HIGH_FREQUENCY_LOW_LIMIT = 12,
155
156
    /**
157
     * End of dynamic heap growth.
158
     *
159
     * Pref: javascript.options.mem.gc_high_frequency_high_limit_mb
160
     * Default: HighFrequencyHighLimitBytes
161
     */
162
    JSGC_HIGH_FREQUENCY_HIGH_LIMIT = 13,
163
164
    /**
165
     * Upper bound of heap growth.
166
     *
167
     * Pref: javascript.options.mem.gc_high_frequency_heap_growth_max
168
     * Default: HighFrequencyHeapGrowthMax
169
     */
170
    JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX = 14,
171
172
    /**
173
     * Lower bound of heap growth.
174
     *
175
     * Pref: javascript.options.mem.gc_high_frequency_heap_growth_min
176
     * Default: HighFrequencyHeapGrowthMin
177
     */
178
    JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN = 15,
179
180
    /**
181
     * Heap growth for low frequency GCs.
182
     *
183
     * Pref: javascript.options.mem.gc_low_frequency_heap_growth
184
     * Default: LowFrequencyHeapGrowth
185
     */
186
    JSGC_LOW_FREQUENCY_HEAP_GROWTH = 16,
187
188
    /**
189
     * If false, the heap growth factor is fixed at 3. If true, it is determined
190
     * based on whether GCs are high- or low- frequency.
191
     *
192
     * Pref: javascript.options.mem.gc_dynamic_heap_growth
193
     * Default: DynamicHeapGrowthEnabled
194
     */
195
    JSGC_DYNAMIC_HEAP_GROWTH = 17,
196
197
    /**
198
     * If true, high-frequency GCs will use a longer mark slice.
199
     *
200
     * Pref: javascript.options.mem.gc_dynamic_mark_slice
201
     * Default: DynamicMarkSliceEnabled
202
     */
203
    JSGC_DYNAMIC_MARK_SLICE = 18,
204
205
    /**
206
     * Lower limit after which we limit the heap growth.
207
     *
208
     * The base value used to compute zone->threshold.gcTriggerBytes(). When
209
     * usage.gcBytes() surpasses threshold.gcTriggerBytes() for a zone, the
210
     * zone may be scheduled for a GC, depending on the exact circumstances.
211
     *
212
     * Pref: javascript.options.mem.gc_allocation_threshold_mb
213
     * Default GCZoneAllocThresholdBase
214
     */
215
    JSGC_ALLOCATION_THRESHOLD = 19,
216
217
    /**
218
     * We try to keep at least this many unused chunks in the free chunk pool at
219
     * all times, even after a shrinking GC.
220
     *
221
     * Pref: javascript.options.mem.gc_min_empty_chunk_count
222
     * Default: MinEmptyChunkCount
223
     */
224
    JSGC_MIN_EMPTY_CHUNK_COUNT = 21,
225
226
    /**
227
     * We never keep more than this many unused chunks in the free chunk
228
     * pool.
229
     *
230
     * Pref: javascript.options.mem.gc_min_empty_chunk_count
231
     * Default: MinEmptyChunkCount
232
     */
233
    JSGC_MAX_EMPTY_CHUNK_COUNT = 22,
234
235
    /**
236
     * Whether compacting GC is enabled.
237
     *
238
     * Pref: javascript.options.mem.gc_compacting
239
     * Default: CompactingEnabled
240
     */
241
    JSGC_COMPACTING_ENABLED = 23,
242
243
    /**
244
     * Factor for triggering a GC based on JSGC_ALLOCATION_THRESHOLD
245
     *
246
     * Default: ZoneAllocThresholdFactorDefault
247
     * Pref: None
248
     */
249
    JSGC_ALLOCATION_THRESHOLD_FACTOR = 25,
250
251
    /**
252
     * Factor for triggering a GC based on JSGC_ALLOCATION_THRESHOLD.
253
     * Used if another GC (in different zones) is already running.
254
     *
255
     * Default: ZoneAllocThresholdFactorAvoidInterruptDefault
256
     * Pref: None
257
     */
258
    JSGC_ALLOCATION_THRESHOLD_FACTOR_AVOID_INTERRUPT = 26,
259
260
    /**
261
     * Attempt to run a minor GC in the idle time if the free space falls
262
     * below this threshold.
263
     *
264
     * Default: NurseryChunkUsableSize / 4
265
     * Pref: None
266
     */
267
    JSGC_NURSERY_FREE_THRESHOLD_FOR_IDLE_COLLECTION = 27,
268
} JSGCParamKey;
269
270
/*
271
 * Generic trace operation that calls JS::TraceEdge on each traceable thing's
272
 * location reachable from data.
273
 */
274
typedef void
275
(* JSTraceDataOp)(JSTracer* trc, void* data);
276
277
typedef enum JSGCStatus {
278
    JSGC_BEGIN,
279
    JSGC_END
280
} JSGCStatus;
281
282
typedef void
283
(* JSGCCallback)(JSContext* cx, JSGCStatus status, void* data);
284
285
typedef void
286
(* JSObjectsTenuredCallback)(JSContext* cx, void* data);
287
288
typedef enum JSFinalizeStatus {
289
    /**
290
     * Called when preparing to sweep a group of zones, before anything has been
291
     * swept.  The collector will not yield to the mutator before calling the
292
     * callback with JSFINALIZE_GROUP_START status.
293
     */
294
    JSFINALIZE_GROUP_PREPARE,
295
296
    /**
297
     * Called after preparing to sweep a group of zones. Weak references to
298
     * unmarked things have been removed at this point, but no GC things have
299
     * been swept. The collector may yield to the mutator after this point.
300
     */
301
    JSFINALIZE_GROUP_START,
302
303
    /**
304
     * Called after sweeping a group of zones. All dead GC things have been
305
     * swept at this point.
306
     */
307
    JSFINALIZE_GROUP_END,
308
309
    /**
310
     * Called at the end of collection when everything has been swept.
311
     */
312
    JSFINALIZE_COLLECTION_END
313
} JSFinalizeStatus;
314
315
typedef void
316
(* JSFinalizeCallback)(JSFreeOp* fop, JSFinalizeStatus status, void* data);
317
318
typedef void
319
(* JSWeakPointerZonesCallback)(JSContext* cx, void* data);
320
321
typedef void
322
(* JSWeakPointerCompartmentCallback)(JSContext* cx, JS::Compartment* comp, void* data);
323
324
/**
325
 * Finalizes external strings created by JS_NewExternalString. The finalizer
326
 * can be called off the main thread.
327
 */
328
struct JSStringFinalizer {
329
    void (*finalize)(const JSStringFinalizer* fin, char16_t* chars);
330
};
331
332
namespace JS {
333
334
#define GCREASONS(D)                            \
335
    /* Reasons internal to the JS engine */     \
336
0
    D(API)                                      \
337
0
    D(EAGER_ALLOC_TRIGGER)                      \
338
0
    D(DESTROY_RUNTIME)                          \
339
0
    D(ROOTS_REMOVED)                            \
340
0
    D(LAST_DITCH)                               \
341
0
    D(TOO_MUCH_MALLOC)                          \
342
118
    D(ALLOC_TRIGGER)                            \
343
118
    D(DEBUG_GC)                                 \
344
0
    D(COMPARTMENT_REVIVED)                      \
345
0
    D(RESET)                                    \
346
0
    D(OUT_OF_NURSERY)                           \
347
0
    D(EVICT_NURSERY)                            \
348
0
    D(DELAYED_ATOMS_GC)                         \
349
0
    D(SHARED_MEMORY_LIMIT)                      \
350
0
    D(IDLE_TIME_COLLECTION)                     \
351
0
    D(INCREMENTAL_TOO_SLOW)                     \
352
0
    D(ABORT_GC)                                 \
353
0
    D(FULL_WHOLE_CELL_BUFFER)                   \
354
0
    D(FULL_GENERIC_BUFFER)                      \
355
0
    D(FULL_VALUE_BUFFER)                        \
356
0
    D(FULL_CELL_PTR_BUFFER)                     \
357
0
    D(FULL_SLOT_BUFFER)                         \
358
0
    D(FULL_SHAPE_BUFFER)                        \
359
0
    D(TOO_MUCH_WASM_MEMORY)                     \
360
0
                                                \
361
0
    /* These are reserved for future use. */    \
362
0
    D(RESERVED0)                                \
363
0
    D(RESERVED1)                                \
364
0
    D(RESERVED2)                                \
365
0
    D(RESERVED3)                                \
366
0
    D(RESERVED4)                                \
367
0
    D(RESERVED5)                                \
368
0
    D(RESERVED6)                                \
369
0
    D(RESERVED7)                                \
370
0
    D(RESERVED8)                                \
371
0
                                                \
372
0
    /* Reasons from Firefox */                  \
373
0
    D(DOM_WINDOW_UTILS)                         \
374
0
    D(COMPONENT_UTILS)                          \
375
0
    D(MEM_PRESSURE)                             \
376
0
    D(CC_WAITING)                               \
377
0
    D(CC_FORCED)                                \
378
0
    D(LOAD_END)                                 \
379
0
    D(POST_COMPARTMENT)                         \
380
0
    D(PAGE_HIDE)                                \
381
0
    D(NSJSCONTEXT_DESTROY)                      \
382
0
    D(SET_NEW_DOCUMENT)                         \
383
0
    D(SET_DOC_SHELL)                            \
384
0
    D(DOM_UTILS)                                \
385
0
    D(DOM_IPC)                                  \
386
0
    D(DOM_WORKER)                               \
387
0
    D(INTER_SLICE_GC)                           \
388
0
    D(UNUSED1)                                  \
389
0
    D(FULL_GC_TIMER)                            \
390
0
    D(SHUTDOWN_CC)                              \
391
0
    D(UNUSED2)                                  \
392
0
    D(USER_INACTIVE)                            \
393
0
    D(XPCONNECT_SHUTDOWN)                       \
394
0
    D(DOCSHELL)                                 \
395
0
    D(HTML_PARSER)
396
397
namespace gcreason {
398
399
/* GCReasons will end up looking like JSGC_MAYBEGC */
400
enum Reason {
401
#define MAKE_REASON(name) name,
402
    GCREASONS(MAKE_REASON)
403
#undef MAKE_REASON
404
    NO_REASON,
405
    NUM_REASONS,
406
407
    /*
408
     * For telemetry, we want to keep a fixed max bucket size over time so we
409
     * don't have to switch histograms. 100 is conservative; as of this writing
410
     * there are 52. But the cost of extra buckets seems to be low while the
411
     * cost of switching histograms is high.
412
     */
413
    NUM_TELEMETRY_REASONS = 100
414
};
415
416
/**
417
 * Get a statically allocated C string explaining the given GC reason.
418
 */
419
extern JS_PUBLIC_API(const char*)
420
ExplainReason(JS::gcreason::Reason reason);
421
422
} /* namespace gcreason */
423
424
/*
425
 * Zone GC:
426
 *
427
 * SpiderMonkey's GC is capable of performing a collection on an arbitrary
428
 * subset of the zones in the system. This allows an embedding to minimize
429
 * collection time by only collecting zones that have run code recently,
430
 * ignoring the parts of the heap that are unlikely to have changed.
431
 *
432
 * When triggering a GC using one of the functions below, it is first necessary
433
 * to select the zones to be collected. To do this, you can call
434
 * PrepareZoneForGC on each zone, or you can call PrepareForFullGC to select
435
 * all zones. Failing to select any zone is an error.
436
 */
437
438
/**
439
 * Schedule the given zone to be collected as part of the next GC.
440
 */
441
extern JS_PUBLIC_API(void)
442
PrepareZoneForGC(Zone* zone);
443
444
/**
445
 * Schedule all zones to be collected in the next GC.
446
 */
447
extern JS_PUBLIC_API(void)
448
PrepareForFullGC(JSContext* cx);
449
450
/**
451
 * When performing an incremental GC, the zones that were selected for the
452
 * previous incremental slice must be selected in subsequent slices as well.
453
 * This function selects those slices automatically.
454
 */
455
extern JS_PUBLIC_API(void)
456
PrepareForIncrementalGC(JSContext* cx);
457
458
/**
459
 * Returns true if any zone in the system has been scheduled for GC with one of
460
 * the functions above or by the JS engine.
461
 */
462
extern JS_PUBLIC_API(bool)
463
IsGCScheduled(JSContext* cx);
464
465
/**
466
 * Undoes the effect of the Prepare methods above. The given zone will not be
467
 * collected in the next GC.
468
 */
469
extern JS_PUBLIC_API(void)
470
SkipZoneForGC(Zone* zone);
471
472
/*
473
 * Non-Incremental GC:
474
 *
475
 * The following functions perform a non-incremental GC.
476
 */
477
478
/**
479
 * Performs a non-incremental collection of all selected zones.
480
 *
481
 * If the gckind argument is GC_NORMAL, then some objects that are unreachable
482
 * from the program may still be alive afterwards because of internal
483
 * references; if GC_SHRINK is passed then caches and other temporary references
484
 * to objects will be cleared and all unreferenced objects will be removed from
485
 * the system.
486
 */
487
extern JS_PUBLIC_API(void)
488
NonIncrementalGC(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason);
489
490
/*
491
 * Incremental GC:
492
 *
493
 * Incremental GC divides the full mark-and-sweep collection into multiple
494
 * slices, allowing client JavaScript code to run between each slice. This
495
 * allows interactive apps to avoid long collection pauses. Incremental GC does
496
 * not make collection take less time, it merely spreads that time out so that
497
 * the pauses are less noticable.
498
 *
499
 * For a collection to be carried out incrementally the following conditions
500
 * must be met:
501
 *  - The collection must be run by calling JS::IncrementalGC() rather than
502
 *    JS_GC().
503
 *  - The GC mode must have been set to JSGC_MODE_INCREMENTAL with
504
 *    JS_SetGCParameter().
505
 *
506
 * Note: Even if incremental GC is enabled and working correctly,
507
 *       non-incremental collections can still happen when low on memory.
508
 */
509
510
/**
511
 * Begin an incremental collection and perform one slice worth of work. When
512
 * this function returns, the collection may not be complete.
513
 * IncrementalGCSlice() must be called repeatedly until
514
 * !IsIncrementalGCInProgress(cx).
515
 *
516
 * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
517
 *       shorter than the requested interval.
518
 */
519
extern JS_PUBLIC_API(void)
520
StartIncrementalGC(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason,
521
                   int64_t millis = 0);
522
523
/**
524
 * Perform a slice of an ongoing incremental collection. When this function
525
 * returns, the collection may not be complete. It must be called repeatedly
526
 * until !IsIncrementalGCInProgress(cx).
527
 *
528
 * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
529
 *       shorter than the requested interval.
530
 */
531
extern JS_PUBLIC_API(void)
532
IncrementalGCSlice(JSContext* cx, gcreason::Reason reason, int64_t millis = 0);
533
534
/**
535
 * If IsIncrementalGCInProgress(cx), this call finishes the ongoing collection
536
 * by performing an arbitrarily long slice. If !IsIncrementalGCInProgress(cx),
537
 * this is equivalent to NonIncrementalGC. When this function returns,
538
 * IsIncrementalGCInProgress(cx) will always be false.
539
 */
540
extern JS_PUBLIC_API(void)
541
FinishIncrementalGC(JSContext* cx, gcreason::Reason reason);
542
543
/**
544
 * If IsIncrementalGCInProgress(cx), this call aborts the ongoing collection and
545
 * performs whatever work needs to be done to return the collector to its idle
546
 * state. This may take an arbitrarily long time. When this function returns,
547
 * IsIncrementalGCInProgress(cx) will always be false.
548
 */
549
extern JS_PUBLIC_API(void)
550
AbortIncrementalGC(JSContext* cx);
551
552
namespace dbg {
553
554
// The `JS::dbg::GarbageCollectionEvent` class is essentially a view of the
555
// `js::gcstats::Statistics` data without the uber implementation-specific bits.
556
// It should generally be palatable for web developers.
557
class GarbageCollectionEvent
558
{
559
    // The major GC number of the GC cycle this data pertains to.
560
    uint64_t majorGCNumber_;
561
562
    // Reference to a non-owned, statically allocated C string. This is a very
563
    // short reason explaining why a GC was triggered.
564
    const char* reason;
565
566
    // Reference to a nullable, non-owned, statically allocated C string. If the
567
    // collection was forced to be non-incremental, this is a short reason of
568
    // why the GC could not perform an incremental collection.
569
    const char* nonincrementalReason;
570
571
    // Represents a single slice of a possibly multi-slice incremental garbage
572
    // collection.
573
    struct Collection {
574
        mozilla::TimeStamp startTimestamp;
575
        mozilla::TimeStamp endTimestamp;
576
    };
577
578
    // The set of garbage collection slices that made up this GC cycle.
579
    mozilla::Vector<Collection> collections;
580
581
    GarbageCollectionEvent(const GarbageCollectionEvent& rhs) = delete;
582
    GarbageCollectionEvent& operator=(const GarbageCollectionEvent& rhs) = delete;
583
584
  public:
585
    explicit GarbageCollectionEvent(uint64_t majorGCNum)
586
        : majorGCNumber_(majorGCNum)
587
        , reason(nullptr)
588
        , nonincrementalReason(nullptr)
589
        , collections()
590
0
    { }
591
592
    using Ptr = js::UniquePtr<GarbageCollectionEvent>;
593
    static Ptr Create(JSRuntime* rt, ::js::gcstats::Statistics& stats, uint64_t majorGCNumber);
594
595
    JSObject* toJSObject(JSContext* cx) const;
596
597
0
    uint64_t majorGCNumber() const { return majorGCNumber_; }
598
};
599
600
} // namespace dbg
601
602
enum GCProgress {
603
    /*
604
     * During GC, the GC is bracketed by GC_CYCLE_BEGIN/END callbacks. Each
605
     * slice between those (whether an incremental or the sole non-incremental
606
     * slice) is bracketed by GC_SLICE_BEGIN/GC_SLICE_END.
607
     */
608
609
    GC_CYCLE_BEGIN,
610
    GC_SLICE_BEGIN,
611
    GC_SLICE_END,
612
    GC_CYCLE_END
613
};
614
615
struct JS_PUBLIC_API(GCDescription) {
616
    bool isZone_;
617
    bool isComplete_;
618
    JSGCInvocationKind invocationKind_;
619
    gcreason::Reason reason_;
620
621
    GCDescription(bool isZone, bool isComplete, JSGCInvocationKind kind, gcreason::Reason reason)
622
0
      : isZone_(isZone), isComplete_(isComplete), invocationKind_(kind), reason_(reason) {}
623
624
    char16_t* formatSliceMessage(JSContext* cx) const;
625
    char16_t* formatSummaryMessage(JSContext* cx) const;
626
    char16_t* formatJSON(JSContext* cx, uint64_t timestamp) const;
627
628
    mozilla::TimeStamp startTime(JSContext* cx) const;
629
    mozilla::TimeStamp endTime(JSContext* cx) const;
630
    mozilla::TimeStamp lastSliceStart(JSContext* cx) const;
631
    mozilla::TimeStamp lastSliceEnd(JSContext* cx) const;
632
633
    JS::UniqueChars sliceToJSON(JSContext* cx) const;
634
    JS::UniqueChars summaryToJSON(JSContext* cx) const;
635
636
    JS::dbg::GarbageCollectionEvent::Ptr toGCEvent(JSContext* cx) const;
637
};
638
639
extern JS_PUBLIC_API(UniqueChars)
640
MinorGcToJSON(JSContext* cx);
641
642
typedef void
643
(* GCSliceCallback)(JSContext* cx, GCProgress progress, const GCDescription& desc);
644
645
/**
646
 * The GC slice callback is called at the beginning and end of each slice. This
647
 * callback may be used for GC notifications as well as to perform additional
648
 * marking.
649
 */
650
extern JS_PUBLIC_API(GCSliceCallback)
651
SetGCSliceCallback(JSContext* cx, GCSliceCallback callback);
652
653
/**
654
 * Describes the progress of an observed nursery collection.
655
 */
656
enum class GCNurseryProgress {
657
    /**
658
     * The nursery collection is starting.
659
     */
660
    GC_NURSERY_COLLECTION_START,
661
    /**
662
     * The nursery collection is ending.
663
     */
664
    GC_NURSERY_COLLECTION_END
665
};
666
667
/**
668
 * A nursery collection callback receives the progress of the nursery collection
669
 * and the reason for the collection.
670
 */
671
using GCNurseryCollectionCallback = void(*)(JSContext* cx, GCNurseryProgress progress,
672
                                            gcreason::Reason reason);
673
674
/**
675
 * Set the nursery collection callback for the given runtime. When set, it will
676
 * be called at the start and end of every nursery collection.
677
 */
678
extern JS_PUBLIC_API(GCNurseryCollectionCallback)
679
SetGCNurseryCollectionCallback(JSContext* cx, GCNurseryCollectionCallback callback);
680
681
typedef void
682
(* DoCycleCollectionCallback)(JSContext* cx);
683
684
/**
685
 * The purge gray callback is called after any COMPARTMENT_REVIVED GC in which
686
 * the majority of compartments have been marked gray.
687
 */
688
extern JS_PUBLIC_API(DoCycleCollectionCallback)
689
SetDoCycleCollectionCallback(JSContext* cx, DoCycleCollectionCallback callback);
690
691
/**
692
 * Incremental GC defaults to enabled, but may be disabled for testing or in
693
 * embeddings that have not yet implemented barriers on their native classes.
694
 * There is not currently a way to re-enable incremental GC once it has been
695
 * disabled on the runtime.
696
 */
697
extern JS_PUBLIC_API(void)
698
DisableIncrementalGC(JSContext* cx);
699
700
/**
701
 * Returns true if incremental GC is enabled. Simply having incremental GC
702
 * enabled is not sufficient to ensure incremental collections are happening.
703
 * See the comment "Incremental GC" above for reasons why incremental GC may be
704
 * suppressed. Inspection of the "nonincremental reason" field of the
705
 * GCDescription returned by GCSliceCallback may help narrow down the cause if
706
 * collections are not happening incrementally when expected.
707
 */
708
extern JS_PUBLIC_API(bool)
709
IsIncrementalGCEnabled(JSContext* cx);
710
711
/**
712
 * Returns true while an incremental GC is ongoing, both when actively
713
 * collecting and between slices.
714
 */
715
extern JS_PUBLIC_API(bool)
716
IsIncrementalGCInProgress(JSContext* cx);
717
718
/**
719
 * Returns true while an incremental GC is ongoing, both when actively
720
 * collecting and between slices.
721
 */
722
extern JS_PUBLIC_API(bool)
723
IsIncrementalGCInProgress(JSRuntime* rt);
724
725
/**
726
 * Returns true if the most recent GC ran incrementally.
727
 */
728
extern JS_PUBLIC_API(bool)
729
WasIncrementalGC(JSRuntime* rt);
730
731
/*
732
 * Generational GC:
733
 *
734
 * Note: Generational GC is not yet enabled by default. The following class
735
 *       is non-functional unless SpiderMonkey was configured with
736
 *       --enable-gcgenerational.
737
 */
738
739
/** Ensure that generational GC is disabled within some scope. */
740
class JS_PUBLIC_API(AutoDisableGenerationalGC)
741
{
742
    JSContext* cx;
743
744
  public:
745
    explicit AutoDisableGenerationalGC(JSContext* cx);
746
    ~AutoDisableGenerationalGC();
747
};
748
749
/**
750
 * Returns true if generational allocation and collection is currently enabled
751
 * on the given runtime.
752
 */
753
extern JS_PUBLIC_API(bool)
754
IsGenerationalGCEnabled(JSRuntime* rt);
755
756
/**
757
 * Returns the GC's "number". This does not correspond directly to the number
758
 * of GCs that have been run, but is guaranteed to be monotonically increasing
759
 * with GC activity.
760
 */
761
extern JS_PUBLIC_API(size_t)
762
GetGCNumber();
763
764
/**
765
 * Pass a subclass of this "abstract" class to callees to require that they
766
 * never GC. Subclasses can use assertions or the hazard analysis to ensure no
767
 * GC happens.
768
 */
769
class JS_PUBLIC_API(AutoRequireNoGC)
770
{
771
  protected:
772
0
    AutoRequireNoGC() {}
773
0
    ~AutoRequireNoGC() {}
774
};
775
776
/**
777
 * Diagnostic assert (see MOZ_DIAGNOSTIC_ASSERT) that GC cannot occur while this
778
 * class is live. This class does not disable the static rooting hazard
779
 * analysis.
780
 *
781
 * This works by entering a GC unsafe region, which is checked on allocation and
782
 * on GC.
783
 */
784
class JS_PUBLIC_API(AutoAssertNoGC) : public AutoRequireNoGC
785
{
786
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
787
    JSContext* cx_;
788
789
  public:
790
    // This gets the context from TLS if it is not passed in.
791
    explicit AutoAssertNoGC(JSContext* cx = nullptr);
792
    ~AutoAssertNoGC();
793
#else
794
  public:
795
    explicit AutoAssertNoGC(JSContext* cx = nullptr) {}
796
    ~AutoAssertNoGC() {}
797
#endif
798
};
799
800
/**
801
 * Disable the static rooting hazard analysis in the live region and assert in
802
 * debug builds if any allocation that could potentially trigger a GC occurs
803
 * while this guard object is live. This is most useful to help the exact
804
 * rooting hazard analysis in complex regions, since it cannot understand
805
 * dataflow.
806
 *
807
 * Note: GC behavior is unpredictable even when deterministic and is generally
808
 *       non-deterministic in practice. The fact that this guard has not
809
 *       asserted is not a guarantee that a GC cannot happen in the guarded
810
 *       region. As a rule, anyone performing a GC unsafe action should
811
 *       understand the GC properties of all code in that region and ensure
812
 *       that the hazard analysis is correct for that code, rather than relying
813
 *       on this class.
814
 */
815
#ifdef DEBUG
816
class JS_PUBLIC_API(AutoSuppressGCAnalysis) : public AutoAssertNoGC
817
{
818
  public:
819
    explicit AutoSuppressGCAnalysis(JSContext* cx = nullptr) : AutoAssertNoGC(cx) {}
820
} JS_HAZ_GC_SUPPRESSED;
821
#else
822
class JS_PUBLIC_API(AutoSuppressGCAnalysis) : public AutoRequireNoGC
823
{
824
  public:
825
0
    explicit AutoSuppressGCAnalysis(JSContext* cx = nullptr) {}
826
} JS_HAZ_GC_SUPPRESSED;
827
#endif
828
829
/**
830
 * Assert that code is only ever called from a GC callback, disable the static
831
 * rooting hazard analysis and assert if any allocation that could potentially
832
 * trigger a GC occurs while this guard object is live.
833
 *
834
 * This is useful to make the static analysis ignore code that runs in GC
835
 * callbacks.
836
 */
837
class JS_PUBLIC_API(AutoAssertGCCallback) : public AutoSuppressGCAnalysis
838
{
839
  public:
840
#ifdef DEBUG
841
    AutoAssertGCCallback();
842
#else
843
0
    AutoAssertGCCallback() {}
844
#endif
845
};
846
847
/**
848
 * Place AutoCheckCannotGC in scopes that you believe can never GC. These
849
 * annotations will be verified both dynamically via AutoAssertNoGC, and
850
 * statically with the rooting hazard analysis (implemented by making the
851
 * analysis consider AutoCheckCannotGC to be a GC pointer, and therefore
852
 * complain if it is live across a GC call.) It is useful when dealing with
853
 * internal pointers to GC things where the GC thing itself may not be present
854
 * for the static analysis: e.g. acquiring inline chars from a JSString* on the
855
 * heap.
856
 *
857
 * We only do the assertion checking in DEBUG builds.
858
 */
859
#ifdef DEBUG
860
class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoAssertNoGC
861
{
862
  public:
863
    explicit AutoCheckCannotGC(JSContext* cx = nullptr) : AutoAssertNoGC(cx) {}
864
} JS_HAZ_GC_INVALIDATED;
865
#else
866
class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoRequireNoGC
867
{
868
  public:
869
0
    explicit AutoCheckCannotGC(JSContext* cx = nullptr) {}
870
} JS_HAZ_GC_INVALIDATED;
871
#endif
872
873
/*
874
 * Internal to Firefox.
875
 */
876
extern JS_FRIEND_API(void)
877
NotifyGCRootsRemoved(JSContext* cx);
878
879
} /* namespace JS */
880
881
/**
882
 * Register externally maintained GC roots.
883
 *
884
 * traceOp: the trace operation. For each root the implementation should call
885
 *          JS::TraceEdge whenever the root contains a traceable thing.
886
 * data:    the data argument to pass to each invocation of traceOp.
887
 */
888
extern JS_PUBLIC_API(bool)
889
JS_AddExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data);
890
891
/** Undo a call to JS_AddExtraGCRootsTracer. */
892
extern JS_PUBLIC_API(void)
893
JS_RemoveExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data);
894
895
extern JS_PUBLIC_API(void)
896
JS_GC(JSContext* cx);
897
898
extern JS_PUBLIC_API(void)
899
JS_MaybeGC(JSContext* cx);
900
901
extern JS_PUBLIC_API(void)
902
JS_SetGCCallback(JSContext* cx, JSGCCallback cb, void* data);
903
904
extern JS_PUBLIC_API(void)
905
JS_SetObjectsTenuredCallback(JSContext* cx, JSObjectsTenuredCallback cb,
906
                             void* data);
907
908
extern JS_PUBLIC_API(bool)
909
JS_AddFinalizeCallback(JSContext* cx, JSFinalizeCallback cb, void* data);
910
911
extern JS_PUBLIC_API(void)
912
JS_RemoveFinalizeCallback(JSContext* cx, JSFinalizeCallback cb);
913
914
/*
915
 * Weak pointers and garbage collection
916
 *
917
 * Weak pointers are by their nature not marked as part of garbage collection,
918
 * but they may need to be updated in two cases after a GC:
919
 *
920
 *  1) Their referent was found not to be live and is about to be finalized
921
 *  2) Their referent has been moved by a compacting GC
922
 *
923
 * To handle this, any part of the system that maintain weak pointers to
924
 * JavaScript GC things must register a callback with
925
 * JS_(Add,Remove)WeakPointer{ZoneGroup,Compartment}Callback(). This callback
926
 * must then call JS_UpdateWeakPointerAfterGC() on all weak pointers it knows
927
 * about.
928
 *
929
 * Since sweeping is incremental, we have several callbacks to avoid repeatedly
930
 * having to visit all embedder structures. The WeakPointerZonesCallback is
931
 * called once for each strongly connected group of zones, whereas the
932
 * WeakPointerCompartmentCallback is called once for each compartment that is
933
 * visited while sweeping. Structures that cannot contain references in more
934
 * than one compartment should sweep the relevant per-compartment structures
935
 * using the latter callback to minimizer per-slice overhead.
936
 *
937
 * The argument to JS_UpdateWeakPointerAfterGC() is an in-out param. If the
938
 * referent is about to be finalized the pointer will be set to null. If the
939
 * referent has been moved then the pointer will be updated to point to the new
940
 * location.
941
 *
942
 * Callers of this method are responsible for updating any state that is
943
 * dependent on the object's address. For example, if the object's address is
944
 * used as a key in a hashtable, then the object must be removed and
945
 * re-inserted with the correct hash.
946
 */
947
948
extern JS_PUBLIC_API(bool)
949
JS_AddWeakPointerZonesCallback(JSContext* cx, JSWeakPointerZonesCallback cb, void* data);
950
951
extern JS_PUBLIC_API(void)
952
JS_RemoveWeakPointerZonesCallback(JSContext* cx, JSWeakPointerZonesCallback cb);
953
954
extern JS_PUBLIC_API(bool)
955
JS_AddWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb,
956
                                     void* data);
957
958
extern JS_PUBLIC_API(void)
959
JS_RemoveWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb);
960
961
namespace JS {
962
template <typename T> class Heap;
963
}
964
965
extern JS_PUBLIC_API(void)
966
JS_UpdateWeakPointerAfterGC(JS::Heap<JSObject*>* objp);
967
968
extern JS_PUBLIC_API(void)
969
JS_UpdateWeakPointerAfterGCUnbarriered(JSObject** objp);
970
971
extern JS_PUBLIC_API(void)
972
JS_SetGCParameter(JSContext* cx, JSGCParamKey key, uint32_t value);
973
974
extern JS_PUBLIC_API(void)
975
JS_ResetGCParameter(JSContext* cx, JSGCParamKey key);
976
977
extern JS_PUBLIC_API(uint32_t)
978
JS_GetGCParameter(JSContext* cx, JSGCParamKey key);
979
980
extern JS_PUBLIC_API(void)
981
JS_SetGCParametersBasedOnAvailableMemory(JSContext* cx, uint32_t availMem);
982
983
/**
984
 * Create a new JSString whose chars member refers to external memory, i.e.,
985
 * memory requiring application-specific finalization.
986
 */
987
extern JS_PUBLIC_API(JSString*)
988
JS_NewExternalString(JSContext* cx, const char16_t* chars, size_t length,
989
                     const JSStringFinalizer* fin);
990
991
/**
992
 * Create a new JSString whose chars member may refer to external memory.
993
 * If a new external string is allocated, |*allocatedExternal| is set to true.
994
 * Otherwise the returned string is either not an external string or an
995
 * external string allocated by a previous call and |*allocatedExternal| is set
996
 * to false. If |*allocatedExternal| is false, |fin| won't be called.
997
 */
998
extern JS_PUBLIC_API(JSString*)
999
JS_NewMaybeExternalString(JSContext* cx, const char16_t* chars, size_t length,
1000
                          const JSStringFinalizer* fin, bool* allocatedExternal);
1001
1002
/**
1003
 * Return whether 'str' was created with JS_NewExternalString or
1004
 * JS_NewExternalStringWithClosure.
1005
 */
1006
extern JS_PUBLIC_API(bool)
1007
JS_IsExternalString(JSString* str);
1008
1009
/**
1010
 * Return the 'fin' arg passed to JS_NewExternalString.
1011
 */
1012
extern JS_PUBLIC_API(const JSStringFinalizer*)
1013
JS_GetExternalStringFinalizer(JSString* str);
1014
1015
namespace JS {
1016
1017
extern JS_PUBLIC_API(bool)
1018
IsIdleGCTaskNeeded(JSRuntime* rt);
1019
1020
extern JS_PUBLIC_API(void)
1021
RunIdleTimeGCTask(JSRuntime* rt);
1022
1023
} // namespace JS
1024
1025
namespace js {
1026
namespace gc {
1027
1028
/**
1029
 * Create an object providing access to the garbage collector's internal notion
1030
 * of the current state of memory (both GC heap memory and GCthing-controlled
1031
 * malloc memory.
1032
 */
1033
extern JS_PUBLIC_API(JSObject*)
1034
NewMemoryInfoObject(JSContext* cx);
1035
1036
} /* namespace gc */
1037
} /* namespace js */
1038
1039
#endif /* js_GCAPI_h */