123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #ifndef js_GCAPI_h
- #define js_GCAPI_h
- #include "mozilla/Vector.h"
- #include "js/GCAnnotations.h"
- #include "js/HeapAPI.h"
- #include "js/UniquePtr.h"
- namespace js {
- namespace gc {
- class GCRuntime;
- } // namespace gc
- namespace gcstats {
- struct Statistics;
- } // namespace gcstats
- } // namespace js
- typedef enum JSGCMode {
- /** Perform only global GCs. */
- JSGC_MODE_GLOBAL = 0,
- /** Perform per-zone GCs until too much garbage has accumulated. */
- JSGC_MODE_ZONE = 1,
- /**
- * Collect in short time slices rather than all at once. Implies
- * JSGC_MODE_ZONE.
- */
- JSGC_MODE_INCREMENTAL = 2
- } JSGCMode;
- /**
- * Kinds of js_GC invocation.
- */
- typedef enum JSGCInvocationKind {
- /* Normal invocation. */
- GC_NORMAL = 0,
- /* Minimize GC triggers and release empty GC chunks right away. */
- GC_SHRINK = 1
- } JSGCInvocationKind;
- namespace JS {
- #define GCREASONS(D) \
- /* Reasons internal to the JS engine */ \
- D(API) \
- D(EAGER_ALLOC_TRIGGER) \
- D(DESTROY_RUNTIME) \
- D(UNUSED0) \
- D(LAST_DITCH) \
- D(TOO_MUCH_MALLOC) \
- D(ALLOC_TRIGGER) \
- D(DEBUG_GC) \
- D(COMPARTMENT_REVIVED) \
- D(RESET) \
- D(OUT_OF_NURSERY) \
- D(EVICT_NURSERY) \
- D(FULL_STORE_BUFFER) \
- D(SHARED_MEMORY_LIMIT) \
- D(UNUSED1) \
- D(INCREMENTAL_TOO_SLOW) \
- D(ABORT_GC) \
- \
- /* These are reserved for future use. */ \
- D(RESERVED0) \
- D(RESERVED1) \
- D(RESERVED2) \
- D(RESERVED3) \
- D(RESERVED4) \
- D(RESERVED5) \
- D(RESERVED6) \
- D(RESERVED7) \
- D(RESERVED8) \
- D(RESERVED9) \
- D(RESERVED10) \
- D(RESERVED11) \
- D(RESERVED12) \
- D(RESERVED13) \
- D(RESERVED14) \
- D(RESERVED15) \
- \
- /* Reasons from Firefox */ \
- D(DOM_WINDOW_UTILS) \
- D(COMPONENT_UTILS) \
- D(MEM_PRESSURE) \
- D(CC_WAITING) \
- D(CC_FORCED) \
- D(LOAD_END) \
- D(POST_COMPARTMENT) \
- D(PAGE_HIDE) \
- D(NSJSCONTEXT_DESTROY) \
- D(SET_NEW_DOCUMENT) \
- D(SET_DOC_SHELL) \
- D(DOM_UTILS) \
- D(DOM_IPC) \
- D(DOM_WORKER) \
- D(INTER_SLICE_GC) \
- D(REFRESH_FRAME) \
- D(FULL_GC_TIMER) \
- D(SHUTDOWN_CC) \
- D(FINISH_LARGE_EVALUATE) \
- D(USER_INACTIVE) \
- D(XPCONNECT_SHUTDOWN)
- namespace gcreason {
- /* GCReasons will end up looking like JSGC_MAYBEGC */
- enum Reason {
- #define MAKE_REASON(name) name,
- GCREASONS(MAKE_REASON)
- #undef MAKE_REASON
- NO_REASON,
- NUM_REASONS,
- };
- /**
- * Get a statically allocated C string explaining the given GC reason.
- */
- extern JS_PUBLIC_API(const char*)
- ExplainReason(JS::gcreason::Reason reason);
- } /* namespace gcreason */
- /*
- * Zone GC:
- *
- * SpiderMonkey's GC is capable of performing a collection on an arbitrary
- * subset of the zones in the system. This allows an embedding to minimize
- * collection time by only collecting zones that have run code recently,
- * ignoring the parts of the heap that are unlikely to have changed.
- *
- * When triggering a GC using one of the functions below, it is first necessary
- * to select the zones to be collected. To do this, you can call
- * PrepareZoneForGC on each zone, or you can call PrepareForFullGC to select
- * all zones. Failing to select any zone is an error.
- */
- /**
- * Schedule the given zone to be collected as part of the next GC.
- */
- extern JS_PUBLIC_API(void)
- PrepareZoneForGC(Zone* zone);
- /**
- * Schedule all zones to be collected in the next GC.
- */
- extern JS_PUBLIC_API(void)
- PrepareForFullGC(JSContext* cx);
- /**
- * When performing an incremental GC, the zones that were selected for the
- * previous incremental slice must be selected in subsequent slices as well.
- * This function selects those slices automatically.
- */
- extern JS_PUBLIC_API(void)
- PrepareForIncrementalGC(JSContext* cx);
- /**
- * Returns true if any zone in the system has been scheduled for GC with one of
- * the functions above or by the JS engine.
- */
- extern JS_PUBLIC_API(bool)
- IsGCScheduled(JSContext* cx);
- /**
- * Undoes the effect of the Prepare methods above. The given zone will not be
- * collected in the next GC.
- */
- extern JS_PUBLIC_API(void)
- SkipZoneForGC(Zone* zone);
- /*
- * Non-Incremental GC:
- *
- * The following functions perform a non-incremental GC.
- */
- /**
- * Performs a non-incremental collection of all selected zones.
- *
- * If the gckind argument is GC_NORMAL, then some objects that are unreachable
- * from the program may still be alive afterwards because of internal
- * references; if GC_SHRINK is passed then caches and other temporary references
- * to objects will be cleared and all unreferenced objects will be removed from
- * the system.
- */
- extern JS_PUBLIC_API(void)
- GCForReason(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason);
- /*
- * Incremental GC:
- *
- * Incremental GC divides the full mark-and-sweep collection into multiple
- * slices, allowing client JavaScript code to run between each slice. This
- * allows interactive apps to avoid long collection pauses. Incremental GC does
- * not make collection take less time, it merely spreads that time out so that
- * the pauses are less noticable.
- *
- * For a collection to be carried out incrementally the following conditions
- * must be met:
- * - The collection must be run by calling JS::IncrementalGC() rather than
- * JS_GC().
- * - The GC mode must have been set to JSGC_MODE_INCREMENTAL with
- * JS_SetGCParameter().
- *
- * Note: Even if incremental GC is enabled and working correctly,
- * non-incremental collections can still happen when low on memory.
- */
- /**
- * Begin an incremental collection and perform one slice worth of work. When
- * this function returns, the collection may not be complete.
- * IncrementalGCSlice() must be called repeatedly until
- * !IsIncrementalGCInProgress(cx).
- *
- * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
- * shorter than the requested interval.
- */
- extern JS_PUBLIC_API(void)
- StartIncrementalGC(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason,
- int64_t millis = 0);
- /**
- * Perform a slice of an ongoing incremental collection. When this function
- * returns, the collection may not be complete. It must be called repeatedly
- * until !IsIncrementalGCInProgress(cx).
- *
- * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
- * shorter than the requested interval.
- */
- extern JS_PUBLIC_API(void)
- IncrementalGCSlice(JSContext* cx, gcreason::Reason reason, int64_t millis = 0);
- /**
- * If IsIncrementalGCInProgress(cx), this call finishes the ongoing collection
- * by performing an arbitrarily long slice. If !IsIncrementalGCInProgress(cx),
- * this is equivalent to GCForReason. When this function returns,
- * IsIncrementalGCInProgress(cx) will always be false.
- */
- extern JS_PUBLIC_API(void)
- FinishIncrementalGC(JSContext* cx, gcreason::Reason reason);
- /**
- * If IsIncrementalGCInProgress(cx), this call aborts the ongoing collection and
- * performs whatever work needs to be done to return the collector to its idle
- * state. This may take an arbitrarily long time. When this function returns,
- * IsIncrementalGCInProgress(cx) will always be false.
- */
- extern JS_PUBLIC_API(void)
- AbortIncrementalGC(JSContext* cx);
- namespace dbg {
- // The `JS::dbg::GarbageCollectionEvent` class is essentially a view of the
- // `js::gcstats::Statistics` data without the uber implementation-specific bits.
- // It should generally be palatable for web developers.
- class GarbageCollectionEvent
- {
- // The major GC number of the GC cycle this data pertains to.
- uint64_t majorGCNumber_;
- // Reference to a non-owned, statically allocated C string. This is a very
- // short reason explaining why a GC was triggered.
- const char* reason;
- // Reference to a nullable, non-owned, statically allocated C string. If the
- // collection was forced to be non-incremental, this is a short reason of
- // why the GC could not perform an incremental collection.
- const char* nonincrementalReason;
- // Represents a single slice of a possibly multi-slice incremental garbage
- // collection.
- struct Collection {
- double startTimestamp;
- double endTimestamp;
- };
- // The set of garbage collection slices that made up this GC cycle.
- mozilla::Vector<Collection> collections;
- GarbageCollectionEvent(const GarbageCollectionEvent& rhs) = delete;
- GarbageCollectionEvent& operator=(const GarbageCollectionEvent& rhs) = delete;
- public:
- explicit GarbageCollectionEvent(uint64_t majorGCNum)
- : majorGCNumber_(majorGCNum)
- , reason(nullptr)
- , nonincrementalReason(nullptr)
- , collections()
- { }
- using Ptr = js::UniquePtr<GarbageCollectionEvent>;
- static Ptr Create(JSRuntime* rt, ::js::gcstats::Statistics& stats, uint64_t majorGCNumber);
- JSObject* toJSObject(JSContext* cx) const;
- uint64_t majorGCNumber() const { return majorGCNumber_; }
- };
- } // namespace dbg
- enum GCProgress {
- /*
- * During non-incremental GC, the GC is bracketed by JSGC_CYCLE_BEGIN/END
- * callbacks. During an incremental GC, the sequence of callbacks is as
- * follows:
- * JSGC_CYCLE_BEGIN, JSGC_SLICE_END (first slice)
- * JSGC_SLICE_BEGIN, JSGC_SLICE_END (second slice)
- * ...
- * JSGC_SLICE_BEGIN, JSGC_CYCLE_END (last slice)
- */
- GC_CYCLE_BEGIN,
- GC_SLICE_BEGIN,
- GC_SLICE_END,
- GC_CYCLE_END
- };
- struct JS_PUBLIC_API(GCDescription) {
- bool isZone_;
- JSGCInvocationKind invocationKind_;
- gcreason::Reason reason_;
- GCDescription(bool isZone, JSGCInvocationKind kind, gcreason::Reason reason)
- : isZone_(isZone), invocationKind_(kind), reason_(reason) {}
- char16_t* formatSliceMessage(JSContext* cx) const;
- char16_t* formatSummaryMessage(JSContext* cx) const;
- char16_t* formatJSON(JSContext* cx, uint64_t timestamp) const;
- JS::dbg::GarbageCollectionEvent::Ptr toGCEvent(JSContext* cx) const;
- };
- typedef void
- (* GCSliceCallback)(JSContext* cx, GCProgress progress, const GCDescription& desc);
- /**
- * The GC slice callback is called at the beginning and end of each slice. This
- * callback may be used for GC notifications as well as to perform additional
- * marking.
- */
- extern JS_PUBLIC_API(GCSliceCallback)
- SetGCSliceCallback(JSContext* cx, GCSliceCallback callback);
- /**
- * Describes the progress of an observed nursery collection.
- */
- enum class GCNurseryProgress {
- /**
- * The nursery collection is starting.
- */
- GC_NURSERY_COLLECTION_START,
- /**
- * The nursery collection is ending.
- */
- GC_NURSERY_COLLECTION_END
- };
- /**
- * A nursery collection callback receives the progress of the nursery collection
- * and the reason for the collection.
- */
- using GCNurseryCollectionCallback = void(*)(JSContext* cx, GCNurseryProgress progress,
- gcreason::Reason reason);
- /**
- * Set the nursery collection callback for the given runtime. When set, it will
- * be called at the start and end of every nursery collection.
- */
- extern JS_PUBLIC_API(GCNurseryCollectionCallback)
- SetGCNurseryCollectionCallback(JSContext* cx, GCNurseryCollectionCallback callback);
- typedef void
- (* DoCycleCollectionCallback)(JSContext* cx);
- /**
- * The purge gray callback is called after any COMPARTMENT_REVIVED GC in which
- * the majority of compartments have been marked gray.
- */
- extern JS_PUBLIC_API(DoCycleCollectionCallback)
- SetDoCycleCollectionCallback(JSContext* cx, DoCycleCollectionCallback callback);
- /**
- * Incremental GC defaults to enabled, but may be disabled for testing or in
- * embeddings that have not yet implemented barriers on their native classes.
- * There is not currently a way to re-enable incremental GC once it has been
- * disabled on the runtime.
- */
- extern JS_PUBLIC_API(void)
- DisableIncrementalGC(JSContext* cx);
- /**
- * Returns true if incremental GC is enabled. Simply having incremental GC
- * enabled is not sufficient to ensure incremental collections are happening.
- * See the comment "Incremental GC" above for reasons why incremental GC may be
- * suppressed. Inspection of the "nonincremental reason" field of the
- * GCDescription returned by GCSliceCallback may help narrow down the cause if
- * collections are not happening incrementally when expected.
- */
- extern JS_PUBLIC_API(bool)
- IsIncrementalGCEnabled(JSContext* cx);
- /**
- * Returns true while an incremental GC is ongoing, both when actively
- * collecting and between slices.
- */
- extern JS_PUBLIC_API(bool)
- IsIncrementalGCInProgress(JSContext* cx);
- /*
- * Returns true when writes to GC things must call an incremental (pre) barrier.
- * This is generally only true when running mutator code in-between GC slices.
- * At other times, the barrier may be elided for performance.
- */
- extern JS_PUBLIC_API(bool)
- IsIncrementalBarrierNeeded(JSContext* cx);
- /*
- * Notify the GC that a reference to a GC thing is about to be overwritten.
- * These methods must be called if IsIncrementalBarrierNeeded.
- */
- extern JS_PUBLIC_API(void)
- IncrementalReferenceBarrier(GCCellPtr thing);
- extern JS_PUBLIC_API(void)
- IncrementalValueBarrier(const Value& v);
- extern JS_PUBLIC_API(void)
- IncrementalObjectBarrier(JSObject* obj);
- /**
- * Returns true if the most recent GC ran incrementally.
- */
- extern JS_PUBLIC_API(bool)
- WasIncrementalGC(JSContext* cx);
- /*
- * Generational GC:
- *
- * Note: Generational GC is not yet enabled by default. The following class
- * is non-functional unless SpiderMonkey was configured with
- * --enable-gcgenerational.
- */
- /** Ensure that generational GC is disabled within some scope. */
- class JS_PUBLIC_API(AutoDisableGenerationalGC)
- {
- js::gc::GCRuntime* gc;
- public:
- explicit AutoDisableGenerationalGC(JSRuntime* rt);
- ~AutoDisableGenerationalGC();
- };
- /**
- * Returns true if generational allocation and collection is currently enabled
- * on the given runtime.
- */
- extern JS_PUBLIC_API(bool)
- IsGenerationalGCEnabled(JSRuntime* rt);
- /**
- * Returns the GC's "number". This does not correspond directly to the number
- * of GCs that have been run, but is guaranteed to be monotonically increasing
- * with GC activity.
- */
- extern JS_PUBLIC_API(size_t)
- GetGCNumber();
- /**
- * Pass a subclass of this "abstract" class to callees to require that they
- * never GC. Subclasses can use assertions or the hazard analysis to ensure no
- * GC happens.
- */
- class JS_PUBLIC_API(AutoRequireNoGC)
- {
- protected:
- AutoRequireNoGC() {}
- ~AutoRequireNoGC() {}
- };
- /**
- * Diagnostic assert (see MOZ_DIAGNOSTIC_ASSERT) that GC cannot occur while this
- * class is live. This class does not disable the static rooting hazard
- * analysis.
- *
- * This works by entering a GC unsafe region, which is checked on allocation and
- * on GC.
- */
- class JS_PUBLIC_API(AutoAssertNoGC) : public AutoRequireNoGC
- {
- js::gc::GCRuntime* gc;
- size_t gcNumber;
- public:
- AutoAssertNoGC();
- explicit AutoAssertNoGC(JSRuntime* rt);
- explicit AutoAssertNoGC(JSContext* cx);
- ~AutoAssertNoGC();
- };
- /**
- * Assert if an allocation of a GC thing occurs while this class is live. This
- * class does not disable the static rooting hazard analysis.
- */
- class JS_PUBLIC_API(AutoAssertNoAlloc)
- {
- #ifdef JS_DEBUG
- js::gc::GCRuntime* gc;
- public:
- AutoAssertNoAlloc() : gc(nullptr) {}
- explicit AutoAssertNoAlloc(JSContext* cx);
- void disallowAlloc(JSRuntime* rt);
- ~AutoAssertNoAlloc();
- #else
- public:
- AutoAssertNoAlloc() {}
- explicit AutoAssertNoAlloc(JSContext* cx) {}
- void disallowAlloc(JSRuntime* rt) {}
- #endif
- };
- /**
- * Assert if a GC barrier is invoked while this class is live. This class does
- * not disable the static rooting hazard analysis.
- */
- class JS_PUBLIC_API(AutoAssertOnBarrier)
- {
- JSContext* context;
- bool prev;
- public:
- explicit AutoAssertOnBarrier(JSContext* cx);
- ~AutoAssertOnBarrier();
- };
- /**
- * Disable the static rooting hazard analysis in the live region and assert if
- * any allocation that could potentially trigger a GC occurs while this guard
- * object is live. This is most useful to help the exact rooting hazard analysis
- * in complex regions, since it cannot understand dataflow.
- *
- * Note: GC behavior is unpredictable even when deterministic and is generally
- * non-deterministic in practice. The fact that this guard has not
- * asserted is not a guarantee that a GC cannot happen in the guarded
- * region. As a rule, anyone performing a GC unsafe action should
- * understand the GC properties of all code in that region and ensure
- * that the hazard analysis is correct for that code, rather than relying
- * on this class.
- */
- class JS_PUBLIC_API(AutoSuppressGCAnalysis) : public AutoAssertNoAlloc
- {
- public:
- AutoSuppressGCAnalysis() : AutoAssertNoAlloc() {}
- explicit AutoSuppressGCAnalysis(JSContext* cx) : AutoAssertNoAlloc(cx) {}
- } JS_HAZ_GC_SUPPRESSED;
- /**
- * Assert that code is only ever called from a GC callback, disable the static
- * rooting hazard analysis and assert if any allocation that could potentially
- * trigger a GC occurs while this guard object is live.
- *
- * This is useful to make the static analysis ignore code that runs in GC
- * callbacks.
- */
- class JS_PUBLIC_API(AutoAssertGCCallback) : public AutoSuppressGCAnalysis
- {
- public:
- explicit AutoAssertGCCallback(JSObject* obj);
- };
- /**
- * Place AutoCheckCannotGC in scopes that you believe can never GC. These
- * annotations will be verified both dynamically via AutoAssertNoGC, and
- * statically with the rooting hazard analysis (implemented by making the
- * analysis consider AutoCheckCannotGC to be a GC pointer, and therefore
- * complain if it is live across a GC call.) It is useful when dealing with
- * internal pointers to GC things where the GC thing itself may not be present
- * for the static analysis: e.g. acquiring inline chars from a JSString* on the
- * heap.
- *
- * We only do the assertion checking in DEBUG builds.
- */
- #ifdef DEBUG
- class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoAssertNoGC
- {
- public:
- AutoCheckCannotGC() : AutoAssertNoGC() {}
- explicit AutoCheckCannotGC(JSContext* cx) : AutoAssertNoGC(cx) {}
- } JS_HAZ_GC_INVALIDATED;
- #else
- class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoRequireNoGC
- {
- public:
- AutoCheckCannotGC() {}
- explicit AutoCheckCannotGC(JSContext* cx) {}
- } JS_HAZ_GC_INVALIDATED;
- #endif
- /**
- * Unsets the gray bit for anything reachable from |thing|. |kind| should not be
- * JS::TraceKind::Shape. |thing| should be non-null. The return value indicates
- * if anything was unmarked.
- */
- extern JS_FRIEND_API(bool)
- UnmarkGrayGCThingRecursively(GCCellPtr thing);
- } /* namespace JS */
- namespace js {
- namespace gc {
- static MOZ_ALWAYS_INLINE void
- ExposeGCThingToActiveJS(JS::GCCellPtr thing)
- {
- // GC things residing in the nursery cannot be gray: they have no mark bits.
- // All live objects in the nursery are moved to tenured at the beginning of
- // each GC slice, so the gray marker never sees nursery things.
- if (IsInsideNursery(thing.asCell()))
- return;
- // There's nothing to do for permanent GC things that might be owned by
- // another runtime.
- if (thing.mayBeOwnedByOtherRuntime())
- return;
- JS::shadow::Runtime* rt = detail::GetCellRuntime(thing.asCell());
- MOZ_DIAGNOSTIC_ASSERT(rt->allowGCBarriers());
- if (IsIncrementalBarrierNeededOnTenuredGCThing(rt, thing))
- JS::IncrementalReferenceBarrier(thing);
- else if (!thing.mayBeOwnedByOtherRuntime() && js::gc::detail::CellIsMarkedGray(thing.asCell()))
- JS::UnmarkGrayGCThingRecursively(thing);
- }
- static MOZ_ALWAYS_INLINE void
- MarkGCThingAsLive(JSRuntime* aRt, JS::GCCellPtr thing)
- {
- // Any object in the nursery will not be freed during any GC running at that
- // time.
- if (IsInsideNursery(thing.asCell()))
- return;
- // There's nothing to do for permanent GC things that might be owned by
- // another runtime.
- if (thing.mayBeOwnedByOtherRuntime())
- return;
- JS::shadow::Runtime* rt = JS::shadow::Runtime::asShadowRuntime(aRt);
- MOZ_DIAGNOSTIC_ASSERT(rt->allowGCBarriers());
- if (IsIncrementalBarrierNeededOnTenuredGCThing(rt, thing))
- JS::IncrementalReferenceBarrier(thing);
- }
- } /* namespace gc */
- } /* namespace js */
- namespace JS {
- /*
- * This should be called when an object that is marked gray is exposed to the JS
- * engine (by handing it to running JS code or writing it into live JS
- * data). During incremental GC, since the gray bits haven't been computed yet,
- * we conservatively mark the object black.
- */
- static MOZ_ALWAYS_INLINE void
- ExposeObjectToActiveJS(JSObject* obj)
- {
- MOZ_ASSERT(obj);
- js::gc::ExposeGCThingToActiveJS(GCCellPtr(obj));
- }
- static MOZ_ALWAYS_INLINE void
- ExposeScriptToActiveJS(JSScript* script)
- {
- js::gc::ExposeGCThingToActiveJS(GCCellPtr(script));
- }
- /*
- * If a GC is currently marking, mark the string black.
- */
- static MOZ_ALWAYS_INLINE void
- MarkStringAsLive(Zone* zone, JSString* string)
- {
- JSRuntime* rt = JS::shadow::Zone::asShadowZone(zone)->runtimeFromMainThread();
- js::gc::MarkGCThingAsLive(rt, GCCellPtr(string));
- }
- /*
- * Internal to Firefox.
- *
- * Note: this is not related to the PokeGC in nsJSEnvironment.
- */
- extern JS_FRIEND_API(void)
- PokeGC(JSContext* cx);
- /*
- * Internal to Firefox.
- */
- extern JS_FRIEND_API(void)
- NotifyDidPaint(JSContext* cx);
- } /* namespace JS */
- #endif /* js_GCAPI_h */
|