js/public/GCAPI.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef js_GCAPI_h
michael@0 8 #define js_GCAPI_h
michael@0 9
michael@0 10 #include "mozilla/NullPtr.h"
michael@0 11
michael@0 12 #include "js/HeapAPI.h"
michael@0 13 #include "js/RootingAPI.h"
michael@0 14 #include "js/Value.h"
michael@0 15
michael@0 16 typedef enum JSGCMode {
michael@0 17 /* Perform only global GCs. */
michael@0 18 JSGC_MODE_GLOBAL = 0,
michael@0 19
michael@0 20 /* Perform per-compartment GCs until too much garbage has accumulated. */
michael@0 21 JSGC_MODE_COMPARTMENT = 1,
michael@0 22
michael@0 23 /*
michael@0 24 * Collect in short time slices rather than all at once. Implies
michael@0 25 * JSGC_MODE_COMPARTMENT.
michael@0 26 */
michael@0 27 JSGC_MODE_INCREMENTAL = 2
michael@0 28 } JSGCMode;
michael@0 29
michael@0 30 namespace JS {
michael@0 31
michael@0 32 #define GCREASONS(D) \
michael@0 33 /* Reasons internal to the JS engine */ \
michael@0 34 D(API) \
michael@0 35 D(MAYBEGC) \
michael@0 36 D(DESTROY_RUNTIME) \
michael@0 37 D(DESTROY_CONTEXT) \
michael@0 38 D(LAST_DITCH) \
michael@0 39 D(TOO_MUCH_MALLOC) \
michael@0 40 D(ALLOC_TRIGGER) \
michael@0 41 D(DEBUG_GC) \
michael@0 42 D(TRANSPLANT) \
michael@0 43 D(RESET) \
michael@0 44 D(OUT_OF_NURSERY) \
michael@0 45 D(EVICT_NURSERY) \
michael@0 46 D(FULL_STORE_BUFFER) \
michael@0 47 \
michael@0 48 /* These are reserved for future use. */ \
michael@0 49 D(RESERVED0) \
michael@0 50 D(RESERVED1) \
michael@0 51 D(RESERVED2) \
michael@0 52 D(RESERVED3) \
michael@0 53 D(RESERVED4) \
michael@0 54 D(RESERVED5) \
michael@0 55 D(RESERVED6) \
michael@0 56 D(RESERVED7) \
michael@0 57 D(RESERVED8) \
michael@0 58 D(RESERVED9) \
michael@0 59 D(RESERVED10) \
michael@0 60 D(RESERVED11) \
michael@0 61 D(RESERVED12) \
michael@0 62 D(RESERVED13) \
michael@0 63 D(RESERVED14) \
michael@0 64 D(RESERVED15) \
michael@0 65 D(RESERVED16) \
michael@0 66 D(RESERVED17) \
michael@0 67 D(RESERVED18) \
michael@0 68 D(RESERVED19) \
michael@0 69 \
michael@0 70 /* Reasons from Firefox */ \
michael@0 71 D(DOM_WINDOW_UTILS) \
michael@0 72 D(COMPONENT_UTILS) \
michael@0 73 D(MEM_PRESSURE) \
michael@0 74 D(CC_WAITING) \
michael@0 75 D(CC_FORCED) \
michael@0 76 D(LOAD_END) \
michael@0 77 D(POST_COMPARTMENT) \
michael@0 78 D(PAGE_HIDE) \
michael@0 79 D(NSJSCONTEXT_DESTROY) \
michael@0 80 D(SET_NEW_DOCUMENT) \
michael@0 81 D(SET_DOC_SHELL) \
michael@0 82 D(DOM_UTILS) \
michael@0 83 D(DOM_IPC) \
michael@0 84 D(DOM_WORKER) \
michael@0 85 D(INTER_SLICE_GC) \
michael@0 86 D(REFRESH_FRAME) \
michael@0 87 D(FULL_GC_TIMER) \
michael@0 88 D(SHUTDOWN_CC) \
michael@0 89 D(FINISH_LARGE_EVALUTE)
michael@0 90
michael@0 91 namespace gcreason {
michael@0 92
michael@0 93 /* GCReasons will end up looking like JSGC_MAYBEGC */
michael@0 94 enum Reason {
michael@0 95 #define MAKE_REASON(name) name,
michael@0 96 GCREASONS(MAKE_REASON)
michael@0 97 #undef MAKE_REASON
michael@0 98 NO_REASON,
michael@0 99 NUM_REASONS,
michael@0 100
michael@0 101 /*
michael@0 102 * For telemetry, we want to keep a fixed max bucket size over time so we
michael@0 103 * don't have to switch histograms. 100 is conservative; as of this writing
michael@0 104 * there are 26. But the cost of extra buckets seems to be low while the
michael@0 105 * cost of switching histograms is high.
michael@0 106 */
michael@0 107 NUM_TELEMETRY_REASONS = 100
michael@0 108 };
michael@0 109
michael@0 110 } /* namespace gcreason */
michael@0 111
michael@0 112 /*
michael@0 113 * Zone GC:
michael@0 114 *
michael@0 115 * SpiderMonkey's GC is capable of performing a collection on an arbitrary
michael@0 116 * subset of the zones in the system. This allows an embedding to minimize
michael@0 117 * collection time by only collecting zones that have run code recently,
michael@0 118 * ignoring the parts of the heap that are unlikely to have changed.
michael@0 119 *
michael@0 120 * When triggering a GC using one of the functions below, it is first necessary
michael@0 121 * to select the zones to be collected. To do this, you can call
michael@0 122 * PrepareZoneForGC on each zone, or you can call PrepareForFullGC to select
michael@0 123 * all zones. Failing to select any zone is an error.
michael@0 124 */
michael@0 125
michael@0 126 /*
michael@0 127 * Schedule the given zone to be collected as part of the next GC.
michael@0 128 */
michael@0 129 extern JS_FRIEND_API(void)
michael@0 130 PrepareZoneForGC(Zone *zone);
michael@0 131
michael@0 132 /*
michael@0 133 * Schedule all zones to be collected in the next GC.
michael@0 134 */
michael@0 135 extern JS_FRIEND_API(void)
michael@0 136 PrepareForFullGC(JSRuntime *rt);
michael@0 137
michael@0 138 /*
michael@0 139 * When performing an incremental GC, the zones that were selected for the
michael@0 140 * previous incremental slice must be selected in subsequent slices as well.
michael@0 141 * This function selects those slices automatically.
michael@0 142 */
michael@0 143 extern JS_FRIEND_API(void)
michael@0 144 PrepareForIncrementalGC(JSRuntime *rt);
michael@0 145
michael@0 146 /*
michael@0 147 * Returns true if any zone in the system has been scheduled for GC with one of
michael@0 148 * the functions above or by the JS engine.
michael@0 149 */
michael@0 150 extern JS_FRIEND_API(bool)
michael@0 151 IsGCScheduled(JSRuntime *rt);
michael@0 152
michael@0 153 /*
michael@0 154 * Undoes the effect of the Prepare methods above. The given zone will not be
michael@0 155 * collected in the next GC.
michael@0 156 */
michael@0 157 extern JS_FRIEND_API(void)
michael@0 158 SkipZoneForGC(Zone *zone);
michael@0 159
michael@0 160 /*
michael@0 161 * Non-Incremental GC:
michael@0 162 *
michael@0 163 * The following functions perform a non-incremental GC.
michael@0 164 */
michael@0 165
michael@0 166 /*
michael@0 167 * Performs a non-incremental collection of all selected zones. Some objects
michael@0 168 * that are unreachable from the program may still be alive afterwards because
michael@0 169 * of internal references.
michael@0 170 */
michael@0 171 extern JS_FRIEND_API(void)
michael@0 172 GCForReason(JSRuntime *rt, gcreason::Reason reason);
michael@0 173
michael@0 174 /*
michael@0 175 * Perform a non-incremental collection after clearing caches and other
michael@0 176 * temporary references to objects. This will remove all unreferenced objects
michael@0 177 * in the system.
michael@0 178 */
michael@0 179 extern JS_FRIEND_API(void)
michael@0 180 ShrinkingGC(JSRuntime *rt, gcreason::Reason reason);
michael@0 181
michael@0 182 /*
michael@0 183 * Incremental GC:
michael@0 184 *
michael@0 185 * Incremental GC divides the full mark-and-sweep collection into multiple
michael@0 186 * slices, allowing client JavaScript code to run between each slice. This
michael@0 187 * allows interactive apps to avoid long collection pauses. Incremental GC does
michael@0 188 * not make collection take less time, it merely spreads that time out so that
michael@0 189 * the pauses are less noticable.
michael@0 190 *
michael@0 191 * For a collection to be carried out incrementally the following conditions
michael@0 192 * must be met:
michael@0 193 * - The collection must be run by calling JS::IncrementalGC() rather than
michael@0 194 * JS_GC().
michael@0 195 * - The GC mode must have been set to JSGC_MODE_INCREMENTAL with
michael@0 196 * JS_SetGCParameter().
michael@0 197 * - All native objects that have their own trace hook must indicate that they
michael@0 198 * implement read and write barriers with the JSCLASS_IMPLEMENTS_BARRIERS
michael@0 199 * flag.
michael@0 200 *
michael@0 201 * Note: Even if incremental GC is enabled and working correctly,
michael@0 202 * non-incremental collections can still happen when low on memory.
michael@0 203 */
michael@0 204
michael@0 205 /*
michael@0 206 * Begin an incremental collection and perform one slice worth of work or
michael@0 207 * perform a slice of an ongoing incremental collection. When this function
michael@0 208 * returns, the collection is not complete. This function must be called
michael@0 209 * repeatedly until !IsIncrementalGCInProgress(rt).
michael@0 210 *
michael@0 211 * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
michael@0 212 * shorter than the requested interval.
michael@0 213 */
michael@0 214 extern JS_FRIEND_API(void)
michael@0 215 IncrementalGC(JSRuntime *rt, gcreason::Reason reason, int64_t millis = 0);
michael@0 216
michael@0 217 /*
michael@0 218 * If IsIncrementalGCInProgress(rt), this call finishes the ongoing collection
michael@0 219 * by performing an arbitrarily long slice. If !IsIncrementalGCInProgress(rt),
michael@0 220 * this is equivalent to GCForReason. When this function returns,
michael@0 221 * IsIncrementalGCInProgress(rt) will always be false.
michael@0 222 */
michael@0 223 extern JS_FRIEND_API(void)
michael@0 224 FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason);
michael@0 225
michael@0 226 enum GCProgress {
michael@0 227 /*
michael@0 228 * During non-incremental GC, the GC is bracketed by JSGC_CYCLE_BEGIN/END
michael@0 229 * callbacks. During an incremental GC, the sequence of callbacks is as
michael@0 230 * follows:
michael@0 231 * JSGC_CYCLE_BEGIN, JSGC_SLICE_END (first slice)
michael@0 232 * JSGC_SLICE_BEGIN, JSGC_SLICE_END (second slice)
michael@0 233 * ...
michael@0 234 * JSGC_SLICE_BEGIN, JSGC_CYCLE_END (last slice)
michael@0 235 */
michael@0 236
michael@0 237 GC_CYCLE_BEGIN,
michael@0 238 GC_SLICE_BEGIN,
michael@0 239 GC_SLICE_END,
michael@0 240 GC_CYCLE_END
michael@0 241 };
michael@0 242
michael@0 243 struct JS_FRIEND_API(GCDescription) {
michael@0 244 bool isCompartment_;
michael@0 245
michael@0 246 GCDescription(bool isCompartment)
michael@0 247 : isCompartment_(isCompartment) {}
michael@0 248
michael@0 249 jschar *formatMessage(JSRuntime *rt) const;
michael@0 250 jschar *formatJSON(JSRuntime *rt, uint64_t timestamp) const;
michael@0 251 };
michael@0 252
michael@0 253 typedef void
michael@0 254 (* GCSliceCallback)(JSRuntime *rt, GCProgress progress, const GCDescription &desc);
michael@0 255
michael@0 256 /*
michael@0 257 * The GC slice callback is called at the beginning and end of each slice. This
michael@0 258 * callback may be used for GC notifications as well as to perform additional
michael@0 259 * marking.
michael@0 260 */
michael@0 261 extern JS_FRIEND_API(GCSliceCallback)
michael@0 262 SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback);
michael@0 263
michael@0 264 /*
michael@0 265 * Incremental GC defaults to enabled, but may be disabled for testing or in
michael@0 266 * embeddings that have not yet implemented barriers on their native classes.
michael@0 267 * There is not currently a way to re-enable incremental GC once it has been
michael@0 268 * disabled on the runtime.
michael@0 269 */
michael@0 270 extern JS_FRIEND_API(void)
michael@0 271 DisableIncrementalGC(JSRuntime *rt);
michael@0 272
michael@0 273 /*
michael@0 274 * Returns true if incremental GC is enabled. Simply having incremental GC
michael@0 275 * enabled is not sufficient to ensure incremental collections are happening.
michael@0 276 * See the comment "Incremental GC" above for reasons why incremental GC may be
michael@0 277 * suppressed. Inspection of the "nonincremental reason" field of the
michael@0 278 * GCDescription returned by GCSliceCallback may help narrow down the cause if
michael@0 279 * collections are not happening incrementally when expected.
michael@0 280 */
michael@0 281 extern JS_FRIEND_API(bool)
michael@0 282 IsIncrementalGCEnabled(JSRuntime *rt);
michael@0 283
michael@0 284 /*
michael@0 285 * Returns true while an incremental GC is ongoing, both when actively
michael@0 286 * collecting and between slices.
michael@0 287 */
michael@0 288 JS_FRIEND_API(bool)
michael@0 289 IsIncrementalGCInProgress(JSRuntime *rt);
michael@0 290
michael@0 291 /*
michael@0 292 * Returns true when writes to GC things must call an incremental (pre) barrier.
michael@0 293 * This is generally only true when running mutator code in-between GC slices.
michael@0 294 * At other times, the barrier may be elided for performance.
michael@0 295 */
michael@0 296 extern JS_FRIEND_API(bool)
michael@0 297 IsIncrementalBarrierNeeded(JSRuntime *rt);
michael@0 298
michael@0 299 extern JS_FRIEND_API(bool)
michael@0 300 IsIncrementalBarrierNeeded(JSContext *cx);
michael@0 301
michael@0 302 /*
michael@0 303 * Notify the GC that a reference to a GC thing is about to be overwritten.
michael@0 304 * These methods must be called if IsIncrementalBarrierNeeded.
michael@0 305 */
michael@0 306 extern JS_FRIEND_API(void)
michael@0 307 IncrementalReferenceBarrier(void *ptr, JSGCTraceKind kind);
michael@0 308
michael@0 309 extern JS_FRIEND_API(void)
michael@0 310 IncrementalValueBarrier(const Value &v);
michael@0 311
michael@0 312 extern JS_FRIEND_API(void)
michael@0 313 IncrementalObjectBarrier(JSObject *obj);
michael@0 314
michael@0 315 /*
michael@0 316 * Returns true if the most recent GC ran incrementally.
michael@0 317 */
michael@0 318 extern JS_FRIEND_API(bool)
michael@0 319 WasIncrementalGC(JSRuntime *rt);
michael@0 320
michael@0 321 /*
michael@0 322 * Generational GC:
michael@0 323 *
michael@0 324 * Note: Generational GC is not yet enabled by default. The following class
michael@0 325 * is non-functional unless SpiderMonkey was configured with
michael@0 326 * --enable-gcgenerational.
michael@0 327 */
michael@0 328
michael@0 329 /* Ensure that generational GC is disabled within some scope. */
michael@0 330 class JS_FRIEND_API(AutoDisableGenerationalGC)
michael@0 331 {
michael@0 332 JSRuntime *runtime;
michael@0 333 #if defined(JSGC_GENERATIONAL) && defined(JS_GC_ZEAL)
michael@0 334 bool restartVerifier;
michael@0 335 #endif
michael@0 336
michael@0 337 public:
michael@0 338 AutoDisableGenerationalGC(JSRuntime *rt);
michael@0 339 ~AutoDisableGenerationalGC();
michael@0 340 };
michael@0 341
michael@0 342 /*
michael@0 343 * Returns true if generational allocation and collection is currently enabled
michael@0 344 * on the given runtime.
michael@0 345 */
michael@0 346 extern JS_FRIEND_API(bool)
michael@0 347 IsGenerationalGCEnabled(JSRuntime *rt);
michael@0 348
michael@0 349 /*
michael@0 350 * Returns the GC's "number". This does not correspond directly to the number
michael@0 351 * of GCs that have been run, but is guaranteed to be monotonically increasing
michael@0 352 * with GC activity.
michael@0 353 */
michael@0 354 extern JS_FRIEND_API(size_t)
michael@0 355 GetGCNumber();
michael@0 356
michael@0 357 /*
michael@0 358 * The GC does not immediately return the unused memory freed by a collection
michael@0 359 * back to the system incase it is needed soon afterwards. This call forces the
michael@0 360 * GC to return this memory immediately.
michael@0 361 */
michael@0 362 extern JS_FRIEND_API(void)
michael@0 363 ShrinkGCBuffers(JSRuntime *rt);
michael@0 364
michael@0 365 /*
michael@0 366 * Assert if any GC occured while this guard object was live. This is most
michael@0 367 * useful to help the exact rooting hazard analysis in complex regions, since
michael@0 368 * it cannot understand dataflow.
michael@0 369 *
michael@0 370 * Note: GC behavior is unpredictable even when deterministice and is generally
michael@0 371 * non-deterministic in practice. The fact that this guard has not
michael@0 372 * asserted is not a guarantee that a GC cannot happen in the guarded
michael@0 373 * region. As a rule, anyone performing a GC unsafe action should
michael@0 374 * understand the GC properties of all code in that region and ensure
michael@0 375 * that the hazard analysis is correct for that code, rather than relying
michael@0 376 * on this class.
michael@0 377 */
michael@0 378 class JS_PUBLIC_API(AutoAssertNoGC)
michael@0 379 {
michael@0 380 #ifdef JS_DEBUG
michael@0 381 JSRuntime *runtime;
michael@0 382 size_t gcNumber;
michael@0 383
michael@0 384 public:
michael@0 385 AutoAssertNoGC();
michael@0 386 AutoAssertNoGC(JSRuntime *rt);
michael@0 387 ~AutoAssertNoGC();
michael@0 388 #else
michael@0 389 public:
michael@0 390 /* Prevent unreferenced local warnings in opt builds. */
michael@0 391 AutoAssertNoGC() {}
michael@0 392 AutoAssertNoGC(JSRuntime *) {}
michael@0 393 #endif
michael@0 394 };
michael@0 395
michael@0 396 class JS_PUBLIC_API(ObjectPtr)
michael@0 397 {
michael@0 398 Heap<JSObject *> value;
michael@0 399
michael@0 400 public:
michael@0 401 ObjectPtr() : value(nullptr) {}
michael@0 402
michael@0 403 ObjectPtr(JSObject *obj) : value(obj) {}
michael@0 404
michael@0 405 /* Always call finalize before the destructor. */
michael@0 406 ~ObjectPtr() { MOZ_ASSERT(!value); }
michael@0 407
michael@0 408 void finalize(JSRuntime *rt) {
michael@0 409 if (IsIncrementalBarrierNeeded(rt))
michael@0 410 IncrementalObjectBarrier(value);
michael@0 411 value = nullptr;
michael@0 412 }
michael@0 413
michael@0 414 void init(JSObject *obj) { value = obj; }
michael@0 415
michael@0 416 JSObject *get() const { return value; }
michael@0 417
michael@0 418 void writeBarrierPre(JSRuntime *rt) {
michael@0 419 IncrementalObjectBarrier(value);
michael@0 420 }
michael@0 421
michael@0 422 bool isAboutToBeFinalized();
michael@0 423
michael@0 424 ObjectPtr &operator=(JSObject *obj) {
michael@0 425 IncrementalObjectBarrier(value);
michael@0 426 value = obj;
michael@0 427 return *this;
michael@0 428 }
michael@0 429
michael@0 430 void trace(JSTracer *trc, const char *name);
michael@0 431
michael@0 432 JSObject &operator*() const { return *value; }
michael@0 433 JSObject *operator->() const { return value; }
michael@0 434 operator JSObject *() const { return value; }
michael@0 435 };
michael@0 436
michael@0 437 /*
michael@0 438 * Unsets the gray bit for anything reachable from |thing|. |kind| should not be
michael@0 439 * JSTRACE_SHAPE. |thing| should be non-null.
michael@0 440 */
michael@0 441 extern JS_FRIEND_API(bool)
michael@0 442 UnmarkGrayGCThingRecursively(void *thing, JSGCTraceKind kind);
michael@0 443
michael@0 444 /*
michael@0 445 * This should be called when an object that is marked gray is exposed to the JS
michael@0 446 * engine (by handing it to running JS code or writing it into live JS
michael@0 447 * data). During incremental GC, since the gray bits haven't been computed yet,
michael@0 448 * we conservatively mark the object black.
michael@0 449 */
michael@0 450 static MOZ_ALWAYS_INLINE void
michael@0 451 ExposeGCThingToActiveJS(void *thing, JSGCTraceKind kind)
michael@0 452 {
michael@0 453 MOZ_ASSERT(kind != JSTRACE_SHAPE);
michael@0 454
michael@0 455 shadow::Runtime *rt = js::gc::GetGCThingRuntime(thing);
michael@0 456 #ifdef JSGC_GENERATIONAL
michael@0 457 /*
michael@0 458 * GC things residing in the nursery cannot be gray: they have no mark bits.
michael@0 459 * All live objects in the nursery are moved to tenured at the beginning of
michael@0 460 * each GC slice, so the gray marker never sees nursery things.
michael@0 461 */
michael@0 462 if (js::gc::IsInsideNursery(rt, thing))
michael@0 463 return;
michael@0 464 #endif
michael@0 465 if (IsIncrementalBarrierNeededOnGCThing(rt, thing, kind))
michael@0 466 IncrementalReferenceBarrier(thing, kind);
michael@0 467 else if (GCThingIsMarkedGray(thing))
michael@0 468 UnmarkGrayGCThingRecursively(thing, kind);
michael@0 469 }
michael@0 470
michael@0 471 static MOZ_ALWAYS_INLINE void
michael@0 472 ExposeValueToActiveJS(const Value &v)
michael@0 473 {
michael@0 474 if (v.isMarkable())
michael@0 475 ExposeGCThingToActiveJS(v.toGCThing(), v.gcKind());
michael@0 476 }
michael@0 477
michael@0 478 static MOZ_ALWAYS_INLINE void
michael@0 479 ExposeObjectToActiveJS(JSObject *obj)
michael@0 480 {
michael@0 481 ExposeGCThingToActiveJS(obj, JSTRACE_OBJECT);
michael@0 482 }
michael@0 483
michael@0 484 /*
michael@0 485 * If a GC is currently marking, mark the object black.
michael@0 486 */
michael@0 487 static MOZ_ALWAYS_INLINE void
michael@0 488 MarkGCThingAsLive(JSRuntime *rt_, void *thing, JSGCTraceKind kind)
michael@0 489 {
michael@0 490 shadow::Runtime *rt = shadow::Runtime::asShadowRuntime(rt_);
michael@0 491 #ifdef JSGC_GENERATIONAL
michael@0 492 /*
michael@0 493 * Any object in the nursery will not be freed during any GC running at that time.
michael@0 494 */
michael@0 495 if (js::gc::IsInsideNursery(rt, thing))
michael@0 496 return;
michael@0 497 #endif
michael@0 498 if (IsIncrementalBarrierNeededOnGCThing(rt, thing, kind))
michael@0 499 IncrementalReferenceBarrier(thing, kind);
michael@0 500 }
michael@0 501
michael@0 502 static MOZ_ALWAYS_INLINE void
michael@0 503 MarkStringAsLive(Zone *zone, JSString *string)
michael@0 504 {
michael@0 505 JSRuntime *rt = JS::shadow::Zone::asShadowZone(zone)->runtimeFromMainThread();
michael@0 506 MarkGCThingAsLive(rt, string, JSTRACE_STRING);
michael@0 507 }
michael@0 508
michael@0 509 /*
michael@0 510 * Internal to Firefox.
michael@0 511 *
michael@0 512 * Note: this is not related to the PokeGC in nsJSEnvironment.
michael@0 513 */
michael@0 514 extern JS_FRIEND_API(void)
michael@0 515 PokeGC(JSRuntime *rt);
michael@0 516
michael@0 517 /*
michael@0 518 * Internal to Firefox.
michael@0 519 */
michael@0 520 extern JS_FRIEND_API(void)
michael@0 521 NotifyDidPaint(JSRuntime *rt);
michael@0 522
michael@0 523 } /* namespace JS */
michael@0 524
michael@0 525 #endif /* js_GCAPI_h */

mercurial