GCAPI.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. * This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef js_GCAPI_h
  6. #define js_GCAPI_h
  7. #include "mozilla/Vector.h"
  8. #include "js/GCAnnotations.h"
  9. #include "js/HeapAPI.h"
  10. #include "js/UniquePtr.h"
  11. namespace js {
  12. namespace gc {
  13. class GCRuntime;
  14. } // namespace gc
  15. namespace gcstats {
  16. struct Statistics;
  17. } // namespace gcstats
  18. } // namespace js
  19. typedef enum JSGCMode {
  20. /** Perform only global GCs. */
  21. JSGC_MODE_GLOBAL = 0,
  22. /** Perform per-zone GCs until too much garbage has accumulated. */
  23. JSGC_MODE_ZONE = 1,
  24. /**
  25. * Collect in short time slices rather than all at once. Implies
  26. * JSGC_MODE_ZONE.
  27. */
  28. JSGC_MODE_INCREMENTAL = 2
  29. } JSGCMode;
  30. /**
  31. * Kinds of js_GC invocation.
  32. */
  33. typedef enum JSGCInvocationKind {
  34. /* Normal invocation. */
  35. GC_NORMAL = 0,
  36. /* Minimize GC triggers and release empty GC chunks right away. */
  37. GC_SHRINK = 1
  38. } JSGCInvocationKind;
  39. namespace JS {
  40. #define GCREASONS(D) \
  41. /* Reasons internal to the JS engine */ \
  42. D(API) \
  43. D(EAGER_ALLOC_TRIGGER) \
  44. D(DESTROY_RUNTIME) \
  45. D(UNUSED0) \
  46. D(LAST_DITCH) \
  47. D(TOO_MUCH_MALLOC) \
  48. D(ALLOC_TRIGGER) \
  49. D(DEBUG_GC) \
  50. D(COMPARTMENT_REVIVED) \
  51. D(RESET) \
  52. D(OUT_OF_NURSERY) \
  53. D(EVICT_NURSERY) \
  54. D(FULL_STORE_BUFFER) \
  55. D(SHARED_MEMORY_LIMIT) \
  56. D(UNUSED1) \
  57. D(INCREMENTAL_TOO_SLOW) \
  58. D(ABORT_GC) \
  59. \
  60. /* These are reserved for future use. */ \
  61. D(RESERVED0) \
  62. D(RESERVED1) \
  63. D(RESERVED2) \
  64. D(RESERVED3) \
  65. D(RESERVED4) \
  66. D(RESERVED5) \
  67. D(RESERVED6) \
  68. D(RESERVED7) \
  69. D(RESERVED8) \
  70. D(RESERVED9) \
  71. D(RESERVED10) \
  72. D(RESERVED11) \
  73. D(RESERVED12) \
  74. D(RESERVED13) \
  75. D(RESERVED14) \
  76. D(RESERVED15) \
  77. \
  78. /* Reasons from Firefox */ \
  79. D(DOM_WINDOW_UTILS) \
  80. D(COMPONENT_UTILS) \
  81. D(MEM_PRESSURE) \
  82. D(CC_WAITING) \
  83. D(CC_FORCED) \
  84. D(LOAD_END) \
  85. D(POST_COMPARTMENT) \
  86. D(PAGE_HIDE) \
  87. D(NSJSCONTEXT_DESTROY) \
  88. D(SET_NEW_DOCUMENT) \
  89. D(SET_DOC_SHELL) \
  90. D(DOM_UTILS) \
  91. D(DOM_IPC) \
  92. D(DOM_WORKER) \
  93. D(INTER_SLICE_GC) \
  94. D(REFRESH_FRAME) \
  95. D(FULL_GC_TIMER) \
  96. D(SHUTDOWN_CC) \
  97. D(FINISH_LARGE_EVALUATE) \
  98. D(USER_INACTIVE) \
  99. D(XPCONNECT_SHUTDOWN)
  100. namespace gcreason {
  101. /* GCReasons will end up looking like JSGC_MAYBEGC */
  102. enum Reason {
  103. #define MAKE_REASON(name) name,
  104. GCREASONS(MAKE_REASON)
  105. #undef MAKE_REASON
  106. NO_REASON,
  107. NUM_REASONS,
  108. };
  109. /**
  110. * Get a statically allocated C string explaining the given GC reason.
  111. */
  112. extern JS_PUBLIC_API(const char*)
  113. ExplainReason(JS::gcreason::Reason reason);
  114. } /* namespace gcreason */
  115. /*
  116. * Zone GC:
  117. *
  118. * SpiderMonkey's GC is capable of performing a collection on an arbitrary
  119. * subset of the zones in the system. This allows an embedding to minimize
  120. * collection time by only collecting zones that have run code recently,
  121. * ignoring the parts of the heap that are unlikely to have changed.
  122. *
  123. * When triggering a GC using one of the functions below, it is first necessary
  124. * to select the zones to be collected. To do this, you can call
  125. * PrepareZoneForGC on each zone, or you can call PrepareForFullGC to select
  126. * all zones. Failing to select any zone is an error.
  127. */
  128. /**
  129. * Schedule the given zone to be collected as part of the next GC.
  130. */
  131. extern JS_PUBLIC_API(void)
  132. PrepareZoneForGC(Zone* zone);
  133. /**
  134. * Schedule all zones to be collected in the next GC.
  135. */
  136. extern JS_PUBLIC_API(void)
  137. PrepareForFullGC(JSContext* cx);
  138. /**
  139. * When performing an incremental GC, the zones that were selected for the
  140. * previous incremental slice must be selected in subsequent slices as well.
  141. * This function selects those slices automatically.
  142. */
  143. extern JS_PUBLIC_API(void)
  144. PrepareForIncrementalGC(JSContext* cx);
  145. /**
  146. * Returns true if any zone in the system has been scheduled for GC with one of
  147. * the functions above or by the JS engine.
  148. */
  149. extern JS_PUBLIC_API(bool)
  150. IsGCScheduled(JSContext* cx);
  151. /**
  152. * Undoes the effect of the Prepare methods above. The given zone will not be
  153. * collected in the next GC.
  154. */
  155. extern JS_PUBLIC_API(void)
  156. SkipZoneForGC(Zone* zone);
  157. /*
  158. * Non-Incremental GC:
  159. *
  160. * The following functions perform a non-incremental GC.
  161. */
  162. /**
  163. * Performs a non-incremental collection of all selected zones.
  164. *
  165. * If the gckind argument is GC_NORMAL, then some objects that are unreachable
  166. * from the program may still be alive afterwards because of internal
  167. * references; if GC_SHRINK is passed then caches and other temporary references
  168. * to objects will be cleared and all unreferenced objects will be removed from
  169. * the system.
  170. */
  171. extern JS_PUBLIC_API(void)
  172. GCForReason(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason);
  173. /*
  174. * Incremental GC:
  175. *
  176. * Incremental GC divides the full mark-and-sweep collection into multiple
  177. * slices, allowing client JavaScript code to run between each slice. This
  178. * allows interactive apps to avoid long collection pauses. Incremental GC does
  179. * not make collection take less time, it merely spreads that time out so that
  180. * the pauses are less noticable.
  181. *
  182. * For a collection to be carried out incrementally the following conditions
  183. * must be met:
  184. * - The collection must be run by calling JS::IncrementalGC() rather than
  185. * JS_GC().
  186. * - The GC mode must have been set to JSGC_MODE_INCREMENTAL with
  187. * JS_SetGCParameter().
  188. *
  189. * Note: Even if incremental GC is enabled and working correctly,
  190. * non-incremental collections can still happen when low on memory.
  191. */
  192. /**
  193. * Begin an incremental collection and perform one slice worth of work. When
  194. * this function returns, the collection may not be complete.
  195. * IncrementalGCSlice() must be called repeatedly until
  196. * !IsIncrementalGCInProgress(cx).
  197. *
  198. * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
  199. * shorter than the requested interval.
  200. */
  201. extern JS_PUBLIC_API(void)
  202. StartIncrementalGC(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason,
  203. int64_t millis = 0);
  204. /**
  205. * Perform a slice of an ongoing incremental collection. When this function
  206. * returns, the collection may not be complete. It must be called repeatedly
  207. * until !IsIncrementalGCInProgress(cx).
  208. *
  209. * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
  210. * shorter than the requested interval.
  211. */
  212. extern JS_PUBLIC_API(void)
  213. IncrementalGCSlice(JSContext* cx, gcreason::Reason reason, int64_t millis = 0);
  214. /**
  215. * If IsIncrementalGCInProgress(cx), this call finishes the ongoing collection
  216. * by performing an arbitrarily long slice. If !IsIncrementalGCInProgress(cx),
  217. * this is equivalent to GCForReason. When this function returns,
  218. * IsIncrementalGCInProgress(cx) will always be false.
  219. */
  220. extern JS_PUBLIC_API(void)
  221. FinishIncrementalGC(JSContext* cx, gcreason::Reason reason);
  222. /**
  223. * If IsIncrementalGCInProgress(cx), this call aborts the ongoing collection and
  224. * performs whatever work needs to be done to return the collector to its idle
  225. * state. This may take an arbitrarily long time. When this function returns,
  226. * IsIncrementalGCInProgress(cx) will always be false.
  227. */
  228. extern JS_PUBLIC_API(void)
  229. AbortIncrementalGC(JSContext* cx);
  230. namespace dbg {
  231. // The `JS::dbg::GarbageCollectionEvent` class is essentially a view of the
  232. // `js::gcstats::Statistics` data without the uber implementation-specific bits.
  233. // It should generally be palatable for web developers.
  234. class GarbageCollectionEvent
  235. {
  236. // The major GC number of the GC cycle this data pertains to.
  237. uint64_t majorGCNumber_;
  238. // Reference to a non-owned, statically allocated C string. This is a very
  239. // short reason explaining why a GC was triggered.
  240. const char* reason;
  241. // Reference to a nullable, non-owned, statically allocated C string. If the
  242. // collection was forced to be non-incremental, this is a short reason of
  243. // why the GC could not perform an incremental collection.
  244. const char* nonincrementalReason;
  245. // Represents a single slice of a possibly multi-slice incremental garbage
  246. // collection.
  247. struct Collection {
  248. double startTimestamp;
  249. double endTimestamp;
  250. };
  251. // The set of garbage collection slices that made up this GC cycle.
  252. mozilla::Vector<Collection> collections;
  253. GarbageCollectionEvent(const GarbageCollectionEvent& rhs) = delete;
  254. GarbageCollectionEvent& operator=(const GarbageCollectionEvent& rhs) = delete;
  255. public:
  256. explicit GarbageCollectionEvent(uint64_t majorGCNum)
  257. : majorGCNumber_(majorGCNum)
  258. , reason(nullptr)
  259. , nonincrementalReason(nullptr)
  260. , collections()
  261. { }
  262. using Ptr = js::UniquePtr<GarbageCollectionEvent>;
  263. static Ptr Create(JSRuntime* rt, ::js::gcstats::Statistics& stats, uint64_t majorGCNumber);
  264. JSObject* toJSObject(JSContext* cx) const;
  265. uint64_t majorGCNumber() const { return majorGCNumber_; }
  266. };
  267. } // namespace dbg
  268. enum GCProgress {
  269. /*
  270. * During non-incremental GC, the GC is bracketed by JSGC_CYCLE_BEGIN/END
  271. * callbacks. During an incremental GC, the sequence of callbacks is as
  272. * follows:
  273. * JSGC_CYCLE_BEGIN, JSGC_SLICE_END (first slice)
  274. * JSGC_SLICE_BEGIN, JSGC_SLICE_END (second slice)
  275. * ...
  276. * JSGC_SLICE_BEGIN, JSGC_CYCLE_END (last slice)
  277. */
  278. GC_CYCLE_BEGIN,
  279. GC_SLICE_BEGIN,
  280. GC_SLICE_END,
  281. GC_CYCLE_END
  282. };
  283. struct JS_PUBLIC_API(GCDescription) {
  284. bool isZone_;
  285. JSGCInvocationKind invocationKind_;
  286. gcreason::Reason reason_;
  287. GCDescription(bool isZone, JSGCInvocationKind kind, gcreason::Reason reason)
  288. : isZone_(isZone), invocationKind_(kind), reason_(reason) {}
  289. char16_t* formatSliceMessage(JSContext* cx) const;
  290. char16_t* formatSummaryMessage(JSContext* cx) const;
  291. char16_t* formatJSON(JSContext* cx, uint64_t timestamp) const;
  292. JS::dbg::GarbageCollectionEvent::Ptr toGCEvent(JSContext* cx) const;
  293. };
  294. typedef void
  295. (* GCSliceCallback)(JSContext* cx, GCProgress progress, const GCDescription& desc);
  296. /**
  297. * The GC slice callback is called at the beginning and end of each slice. This
  298. * callback may be used for GC notifications as well as to perform additional
  299. * marking.
  300. */
  301. extern JS_PUBLIC_API(GCSliceCallback)
  302. SetGCSliceCallback(JSContext* cx, GCSliceCallback callback);
  303. /**
  304. * Describes the progress of an observed nursery collection.
  305. */
  306. enum class GCNurseryProgress {
  307. /**
  308. * The nursery collection is starting.
  309. */
  310. GC_NURSERY_COLLECTION_START,
  311. /**
  312. * The nursery collection is ending.
  313. */
  314. GC_NURSERY_COLLECTION_END
  315. };
  316. /**
  317. * A nursery collection callback receives the progress of the nursery collection
  318. * and the reason for the collection.
  319. */
  320. using GCNurseryCollectionCallback = void(*)(JSContext* cx, GCNurseryProgress progress,
  321. gcreason::Reason reason);
  322. /**
  323. * Set the nursery collection callback for the given runtime. When set, it will
  324. * be called at the start and end of every nursery collection.
  325. */
  326. extern JS_PUBLIC_API(GCNurseryCollectionCallback)
  327. SetGCNurseryCollectionCallback(JSContext* cx, GCNurseryCollectionCallback callback);
  328. typedef void
  329. (* DoCycleCollectionCallback)(JSContext* cx);
  330. /**
  331. * The purge gray callback is called after any COMPARTMENT_REVIVED GC in which
  332. * the majority of compartments have been marked gray.
  333. */
  334. extern JS_PUBLIC_API(DoCycleCollectionCallback)
  335. SetDoCycleCollectionCallback(JSContext* cx, DoCycleCollectionCallback callback);
  336. /**
  337. * Incremental GC defaults to enabled, but may be disabled for testing or in
  338. * embeddings that have not yet implemented barriers on their native classes.
  339. * There is not currently a way to re-enable incremental GC once it has been
  340. * disabled on the runtime.
  341. */
  342. extern JS_PUBLIC_API(void)
  343. DisableIncrementalGC(JSContext* cx);
  344. /**
  345. * Returns true if incremental GC is enabled. Simply having incremental GC
  346. * enabled is not sufficient to ensure incremental collections are happening.
  347. * See the comment "Incremental GC" above for reasons why incremental GC may be
  348. * suppressed. Inspection of the "nonincremental reason" field of the
  349. * GCDescription returned by GCSliceCallback may help narrow down the cause if
  350. * collections are not happening incrementally when expected.
  351. */
  352. extern JS_PUBLIC_API(bool)
  353. IsIncrementalGCEnabled(JSContext* cx);
  354. /**
  355. * Returns true while an incremental GC is ongoing, both when actively
  356. * collecting and between slices.
  357. */
  358. extern JS_PUBLIC_API(bool)
  359. IsIncrementalGCInProgress(JSContext* cx);
  360. /*
  361. * Returns true when writes to GC things must call an incremental (pre) barrier.
  362. * This is generally only true when running mutator code in-between GC slices.
  363. * At other times, the barrier may be elided for performance.
  364. */
  365. extern JS_PUBLIC_API(bool)
  366. IsIncrementalBarrierNeeded(JSContext* cx);
  367. /*
  368. * Notify the GC that a reference to a GC thing is about to be overwritten.
  369. * These methods must be called if IsIncrementalBarrierNeeded.
  370. */
  371. extern JS_PUBLIC_API(void)
  372. IncrementalReferenceBarrier(GCCellPtr thing);
  373. extern JS_PUBLIC_API(void)
  374. IncrementalValueBarrier(const Value& v);
  375. extern JS_PUBLIC_API(void)
  376. IncrementalObjectBarrier(JSObject* obj);
  377. /**
  378. * Returns true if the most recent GC ran incrementally.
  379. */
  380. extern JS_PUBLIC_API(bool)
  381. WasIncrementalGC(JSContext* cx);
  382. /*
  383. * Generational GC:
  384. *
  385. * Note: Generational GC is not yet enabled by default. The following class
  386. * is non-functional unless SpiderMonkey was configured with
  387. * --enable-gcgenerational.
  388. */
  389. /** Ensure that generational GC is disabled within some scope. */
  390. class JS_PUBLIC_API(AutoDisableGenerationalGC)
  391. {
  392. js::gc::GCRuntime* gc;
  393. public:
  394. explicit AutoDisableGenerationalGC(JSRuntime* rt);
  395. ~AutoDisableGenerationalGC();
  396. };
  397. /**
  398. * Returns true if generational allocation and collection is currently enabled
  399. * on the given runtime.
  400. */
  401. extern JS_PUBLIC_API(bool)
  402. IsGenerationalGCEnabled(JSRuntime* rt);
  403. /**
  404. * Returns the GC's "number". This does not correspond directly to the number
  405. * of GCs that have been run, but is guaranteed to be monotonically increasing
  406. * with GC activity.
  407. */
  408. extern JS_PUBLIC_API(size_t)
  409. GetGCNumber();
  410. /**
  411. * Pass a subclass of this "abstract" class to callees to require that they
  412. * never GC. Subclasses can use assertions or the hazard analysis to ensure no
  413. * GC happens.
  414. */
  415. class JS_PUBLIC_API(AutoRequireNoGC)
  416. {
  417. protected:
  418. AutoRequireNoGC() {}
  419. ~AutoRequireNoGC() {}
  420. };
  421. /**
  422. * Diagnostic assert (see MOZ_DIAGNOSTIC_ASSERT) that GC cannot occur while this
  423. * class is live. This class does not disable the static rooting hazard
  424. * analysis.
  425. *
  426. * This works by entering a GC unsafe region, which is checked on allocation and
  427. * on GC.
  428. */
  429. class JS_PUBLIC_API(AutoAssertNoGC) : public AutoRequireNoGC
  430. {
  431. js::gc::GCRuntime* gc;
  432. size_t gcNumber;
  433. public:
  434. AutoAssertNoGC();
  435. explicit AutoAssertNoGC(JSRuntime* rt);
  436. explicit AutoAssertNoGC(JSContext* cx);
  437. ~AutoAssertNoGC();
  438. };
  439. /**
  440. * Assert if an allocation of a GC thing occurs while this class is live. This
  441. * class does not disable the static rooting hazard analysis.
  442. */
  443. class JS_PUBLIC_API(AutoAssertNoAlloc)
  444. {
  445. #ifdef JS_DEBUG
  446. js::gc::GCRuntime* gc;
  447. public:
  448. AutoAssertNoAlloc() : gc(nullptr) {}
  449. explicit AutoAssertNoAlloc(JSContext* cx);
  450. void disallowAlloc(JSRuntime* rt);
  451. ~AutoAssertNoAlloc();
  452. #else
  453. public:
  454. AutoAssertNoAlloc() {}
  455. explicit AutoAssertNoAlloc(JSContext* cx) {}
  456. void disallowAlloc(JSRuntime* rt) {}
  457. #endif
  458. };
  459. /**
  460. * Assert if a GC barrier is invoked while this class is live. This class does
  461. * not disable the static rooting hazard analysis.
  462. */
  463. class JS_PUBLIC_API(AutoAssertOnBarrier)
  464. {
  465. JSContext* context;
  466. bool prev;
  467. public:
  468. explicit AutoAssertOnBarrier(JSContext* cx);
  469. ~AutoAssertOnBarrier();
  470. };
  471. /**
  472. * Disable the static rooting hazard analysis in the live region and assert if
  473. * any allocation that could potentially trigger a GC occurs while this guard
  474. * object is live. This is most useful to help the exact rooting hazard analysis
  475. * in complex regions, since it cannot understand dataflow.
  476. *
  477. * Note: GC behavior is unpredictable even when deterministic and is generally
  478. * non-deterministic in practice. The fact that this guard has not
  479. * asserted is not a guarantee that a GC cannot happen in the guarded
  480. * region. As a rule, anyone performing a GC unsafe action should
  481. * understand the GC properties of all code in that region and ensure
  482. * that the hazard analysis is correct for that code, rather than relying
  483. * on this class.
  484. */
  485. class JS_PUBLIC_API(AutoSuppressGCAnalysis) : public AutoAssertNoAlloc
  486. {
  487. public:
  488. AutoSuppressGCAnalysis() : AutoAssertNoAlloc() {}
  489. explicit AutoSuppressGCAnalysis(JSContext* cx) : AutoAssertNoAlloc(cx) {}
  490. } JS_HAZ_GC_SUPPRESSED;
  491. /**
  492. * Assert that code is only ever called from a GC callback, disable the static
  493. * rooting hazard analysis and assert if any allocation that could potentially
  494. * trigger a GC occurs while this guard object is live.
  495. *
  496. * This is useful to make the static analysis ignore code that runs in GC
  497. * callbacks.
  498. */
  499. class JS_PUBLIC_API(AutoAssertGCCallback) : public AutoSuppressGCAnalysis
  500. {
  501. public:
  502. explicit AutoAssertGCCallback(JSObject* obj);
  503. };
  504. /**
  505. * Place AutoCheckCannotGC in scopes that you believe can never GC. These
  506. * annotations will be verified both dynamically via AutoAssertNoGC, and
  507. * statically with the rooting hazard analysis (implemented by making the
  508. * analysis consider AutoCheckCannotGC to be a GC pointer, and therefore
  509. * complain if it is live across a GC call.) It is useful when dealing with
  510. * internal pointers to GC things where the GC thing itself may not be present
  511. * for the static analysis: e.g. acquiring inline chars from a JSString* on the
  512. * heap.
  513. *
  514. * We only do the assertion checking in DEBUG builds.
  515. */
  516. #ifdef DEBUG
  517. class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoAssertNoGC
  518. {
  519. public:
  520. AutoCheckCannotGC() : AutoAssertNoGC() {}
  521. explicit AutoCheckCannotGC(JSContext* cx) : AutoAssertNoGC(cx) {}
  522. } JS_HAZ_GC_INVALIDATED;
  523. #else
  524. class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoRequireNoGC
  525. {
  526. public:
  527. AutoCheckCannotGC() {}
  528. explicit AutoCheckCannotGC(JSContext* cx) {}
  529. } JS_HAZ_GC_INVALIDATED;
  530. #endif
  531. /**
  532. * Unsets the gray bit for anything reachable from |thing|. |kind| should not be
  533. * JS::TraceKind::Shape. |thing| should be non-null. The return value indicates
  534. * if anything was unmarked.
  535. */
  536. extern JS_FRIEND_API(bool)
  537. UnmarkGrayGCThingRecursively(GCCellPtr thing);
  538. } /* namespace JS */
  539. namespace js {
  540. namespace gc {
  541. static MOZ_ALWAYS_INLINE void
  542. ExposeGCThingToActiveJS(JS::GCCellPtr thing)
  543. {
  544. // GC things residing in the nursery cannot be gray: they have no mark bits.
  545. // All live objects in the nursery are moved to tenured at the beginning of
  546. // each GC slice, so the gray marker never sees nursery things.
  547. if (IsInsideNursery(thing.asCell()))
  548. return;
  549. // There's nothing to do for permanent GC things that might be owned by
  550. // another runtime.
  551. if (thing.mayBeOwnedByOtherRuntime())
  552. return;
  553. JS::shadow::Runtime* rt = detail::GetCellRuntime(thing.asCell());
  554. MOZ_DIAGNOSTIC_ASSERT(rt->allowGCBarriers());
  555. if (IsIncrementalBarrierNeededOnTenuredGCThing(rt, thing))
  556. JS::IncrementalReferenceBarrier(thing);
  557. else if (!thing.mayBeOwnedByOtherRuntime() && js::gc::detail::CellIsMarkedGray(thing.asCell()))
  558. JS::UnmarkGrayGCThingRecursively(thing);
  559. }
  560. static MOZ_ALWAYS_INLINE void
  561. MarkGCThingAsLive(JSRuntime* aRt, JS::GCCellPtr thing)
  562. {
  563. // Any object in the nursery will not be freed during any GC running at that
  564. // time.
  565. if (IsInsideNursery(thing.asCell()))
  566. return;
  567. // There's nothing to do for permanent GC things that might be owned by
  568. // another runtime.
  569. if (thing.mayBeOwnedByOtherRuntime())
  570. return;
  571. JS::shadow::Runtime* rt = JS::shadow::Runtime::asShadowRuntime(aRt);
  572. MOZ_DIAGNOSTIC_ASSERT(rt->allowGCBarriers());
  573. if (IsIncrementalBarrierNeededOnTenuredGCThing(rt, thing))
  574. JS::IncrementalReferenceBarrier(thing);
  575. }
  576. } /* namespace gc */
  577. } /* namespace js */
  578. namespace JS {
  579. /*
  580. * This should be called when an object that is marked gray is exposed to the JS
  581. * engine (by handing it to running JS code or writing it into live JS
  582. * data). During incremental GC, since the gray bits haven't been computed yet,
  583. * we conservatively mark the object black.
  584. */
  585. static MOZ_ALWAYS_INLINE void
  586. ExposeObjectToActiveJS(JSObject* obj)
  587. {
  588. MOZ_ASSERT(obj);
  589. js::gc::ExposeGCThingToActiveJS(GCCellPtr(obj));
  590. }
  591. static MOZ_ALWAYS_INLINE void
  592. ExposeScriptToActiveJS(JSScript* script)
  593. {
  594. js::gc::ExposeGCThingToActiveJS(GCCellPtr(script));
  595. }
  596. /*
  597. * If a GC is currently marking, mark the string black.
  598. */
  599. static MOZ_ALWAYS_INLINE void
  600. MarkStringAsLive(Zone* zone, JSString* string)
  601. {
  602. JSRuntime* rt = JS::shadow::Zone::asShadowZone(zone)->runtimeFromMainThread();
  603. js::gc::MarkGCThingAsLive(rt, GCCellPtr(string));
  604. }
  605. /*
  606. * Internal to Firefox.
  607. *
  608. * Note: this is not related to the PokeGC in nsJSEnvironment.
  609. */
  610. extern JS_FRIEND_API(void)
  611. PokeGC(JSContext* cx);
  612. /*
  613. * Internal to Firefox.
  614. */
  615. extern JS_FRIEND_API(void)
  616. NotifyDidPaint(JSContext* cx);
  617. } /* namespace JS */
  618. #endif /* js_GCAPI_h */