Zone.h (3971B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 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 /* Shadow definition of |JS::Zone| innards. Do not use this directly! */ 8 9 #ifndef js_shadow_Zone_h 10 #define js_shadow_Zone_h 11 12 #include "mozilla/Assertions.h" // MOZ_ASSERT 13 #include "mozilla/Atomics.h" 14 15 #include <stdint.h> // uint8_t, uint32_t 16 17 #include "jspubtd.h" // js::CurrentThreadCanAccessRuntime 18 #include "jstypes.h" // js::Bit 19 20 struct JS_PUBLIC_API JSRuntime; 21 class JS_PUBLIC_API JSTracer; 22 23 namespace JS { 24 25 namespace shadow { 26 27 struct Zone { 28 enum GCState : uint32_t { 29 NoGC = 0, 30 Prepare, 31 MarkBlackOnly, 32 MarkBlackAndGray, 33 Sweep, 34 Finished, 35 Compact, 36 VerifyPreBarriers, 37 38 Limit 39 }; 40 41 using BarrierState = mozilla::Atomic<uint32_t, mozilla::Relaxed>; 42 43 enum Kind : uint8_t { NormalZone, AtomsZone, SystemZone }; 44 45 protected: 46 JSRuntime* const runtime_; 47 JSTracer* const barrierTracer_; // A pointer to the JSRuntime's |gcMarker|. 48 BarrierState needsIncrementalBarrier_; 49 GCState gcState_ = NoGC; 50 const Kind kind_; 51 52 Zone(JSRuntime* runtime, JSTracer* barrierTracerArg, Kind kind) 53 : runtime_(runtime), barrierTracer_(barrierTracerArg), kind_(kind) { 54 MOZ_ASSERT(!needsIncrementalBarrier()); 55 } 56 57 public: 58 bool needsIncrementalBarrier() const { return needsIncrementalBarrier_; } 59 60 JSTracer* barrierTracer() { 61 MOZ_ASSERT(needsIncrementalBarrier_); 62 MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(runtime_)); 63 return barrierTracer_; 64 } 65 66 JSRuntime* runtimeFromMainThread() const { 67 MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(runtime_)); 68 return runtime_; 69 } 70 71 // Note: Unrestricted access to the zone's runtime from an arbitrary 72 // thread can easily lead to races. Use this method very carefully. 73 JSRuntime* runtimeFromAnyThread() const { return runtime_; } 74 75 GCState gcState() const { return GCState(uint32_t(gcState_)); } 76 77 static constexpr uint32_t gcStateMask(GCState state) { 78 static_assert(uint32_t(Limit) < 32); 79 return js::Bit(state); 80 } 81 82 bool hasAnyGCState(uint32_t stateMask) const { 83 return js::Bit(gcState_) & stateMask; 84 } 85 86 bool wasGCStarted() const { return gcState() != NoGC; } 87 bool isGCPreparing() const { return gcState() == Prepare; } 88 bool isGCMarkingBlackOnly() const { return gcState() == MarkBlackOnly; } 89 bool isGCMarkingBlackAndGray() const { return gcState() == MarkBlackAndGray; } 90 bool isGCSweeping() const { return gcState() == Sweep; } 91 bool isGCFinished() const { return gcState() == Finished; } 92 bool isGCCompacting() const { return gcState() == Compact; } 93 bool isGCMarking() const { 94 return hasAnyGCState(gcStateMask(MarkBlackOnly) | 95 gcStateMask(MarkBlackAndGray)); 96 } 97 bool isGCMarkingOrSweeping() const { 98 return hasAnyGCState(gcStateMask(MarkBlackOnly) | 99 gcStateMask(MarkBlackAndGray) | gcStateMask(Sweep)); 100 } 101 bool isGCMarkingOrVerifyingPreBarriers() const { 102 return hasAnyGCState(gcStateMask(MarkBlackOnly) | 103 gcStateMask(MarkBlackAndGray) | 104 gcStateMask(VerifyPreBarriers)); 105 } 106 bool isGCSweepingOrCompacting() const { 107 return hasAnyGCState(gcStateMask(Sweep) | gcStateMask(Compact)); 108 } 109 bool isVerifyingPreBarriers() const { return gcState() == VerifyPreBarriers; } 110 111 bool isAtomsZone() const { return kind_ == AtomsZone; } 112 bool isSystemZone() const { return kind_ == SystemZone; } 113 114 static shadow::Zone* from(JS::Zone* zone) { 115 return reinterpret_cast<shadow::Zone*>(zone); 116 } 117 static const shadow::Zone* from(const JS::Zone* zone) { 118 return reinterpret_cast<const shadow::Zone*>(zone); 119 } 120 }; 121 122 } // namespace shadow 123 124 } // namespace JS 125 126 #endif // js_shadow_Zone_h