| /* |
| * Copyright (C) 2013 Google Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following disclaimer |
| * in the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_THREAD_STATE_H_ |
| #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_THREAD_STATE_H_ |
| |
| #include <atomic> |
| #include <memory> |
| |
| #include "base/macros.h" |
| #include "base/synchronization/lock.h" |
| #include "base/task/post_job.h" |
| #include "third_party/blink/renderer/platform/heap/blink_gc.h" |
| #include "third_party/blink/renderer/platform/heap/impl/atomic_entry_flag.h" |
| #include "third_party/blink/renderer/platform/heap/impl/threading_traits.h" |
| #include "third_party/blink/renderer/platform/platform_export.h" |
| #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" |
| #include "third_party/blink/renderer/platform/wtf/forward.h" |
| #include "third_party/blink/renderer/platform/wtf/hash_map.h" |
| #include "third_party/blink/renderer/platform/wtf/hash_set.h" |
| #include "third_party/blink/renderer/platform/wtf/linked_hash_set.h" |
| #include "third_party/blink/renderer/platform/wtf/sanitizers.h" |
| #include "third_party/blink/renderer/platform/wtf/thread_specific.h" |
| #include "third_party/blink/renderer/platform/wtf/threading.h" |
| #include "third_party/blink/renderer/platform/wtf/threading_primitives.h" |
| #include "third_party/blink/renderer/platform/wtf/vector.h" |
| #include "v8/include/v8.h" |
| |
| namespace v8 { |
| class EmbedderGraph; |
| class Isolate; |
| } // namespace v8 |
| |
| namespace blink { |
| |
| namespace incremental_marking_test { |
| class IncrementalMarkingScope; |
| } // namespace incremental_marking_test |
| |
| class MarkingVisitor; |
| class MarkingSchedulingOracle; |
| class PersistentRegion; |
| class ThreadHeap; |
| class ThreadState; |
| template <ThreadAffinity affinity> |
| class ThreadStateFor; |
| class UnifiedHeapController; |
| class Visitor; |
| |
| // Declare that a class has a pre-finalizer which gets invoked before objects |
| // get swept. It is thus safe to touch on-heap objects that may be collected in |
| // the same GC cycle. This is useful when it's not possible to avoid touching |
| // on-heap objects in a destructor which is forbidden. |
| // |
| // Note that: |
| // (a) Pre-finalizers *must* not resurrect dead objects. |
| // (b) Run on the same thread they are registered. |
| // (c) Decrease GC performance which means that they should only be used if |
| // absolute necessary. |
| // |
| // Usage: |
| // class Foo : GarbageCollected<Foo> { |
| // USING_PRE_FINALIZER(Foo, Dispose); |
| // private: |
| // void Dispose() { |
| // bar_->...; // It is safe to touch other on-heap objects. |
| // } |
| // Member<Bar> bar_; |
| // }; |
| #define USING_PRE_FINALIZER(Class, PreFinalizer) \ |
| public: \ |
| static bool InvokePreFinalizer(const LivenessBroker& info, void* object) { \ |
| Class* self = reinterpret_cast<Class*>(object); \ |
| if (info.IsHeapObjectAlive(self)) \ |
| return false; \ |
| self->Class::PreFinalizer(); \ |
| return true; \ |
| } \ |
| \ |
| private: \ |
| ThreadState::PrefinalizerRegistration<Class> prefinalizer_dummy_{this}; \ |
| using UsingPreFinalizerMacroNeedsTrailingSemiColon = char |
| |
| class PLATFORM_EXPORT ThreadState final { |
| USING_FAST_MALLOC(ThreadState); |
| |
| public: |
| // Register the pre-finalizer for the |self| object. The class T be using |
| // USING_PRE_FINALIZER() macro. |
| template <typename T> |
| class PrefinalizerRegistration final { |
| DISALLOW_NEW(); |
| |
| public: |
| PrefinalizerRegistration(T* self) { // NOLINT |
| static_assert(sizeof(&T::InvokePreFinalizer) > 0, |
| "USING_PRE_FINALIZER(T) must be defined."); |
| ThreadState* state = |
| ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState(); |
| #if DCHECK_IS_ON() |
| DCHECK(state->CheckThread()); |
| #endif |
| DCHECK(!state->SweepForbidden()); |
| DCHECK(std::find(state->ordered_pre_finalizers_.begin(), |
| state->ordered_pre_finalizers_.end(), |
| PreFinalizer(self, T::InvokePreFinalizer)) == |
| state->ordered_pre_finalizers_.end()); |
| state->ordered_pre_finalizers_.emplace_back(self, T::InvokePreFinalizer); |
| } |
| }; |
| |
| // See setGCState() for possible state transitions. |
| enum GCState { |
| kNoGCScheduled, |
| kIncrementalMarkingStepPaused, |
| kIncrementalMarkingStepScheduled, |
| kIncrementalMarkingFinalizeScheduled, |
| kForcedGCForTestingScheduled, |
| kIncrementalGCScheduled, |
| }; |
| |
| // The phase that the GC is in. The GCPhase will not return kNone for mutators |
| // running during incremental marking and lazy sweeping. See SetGCPhase() for |
| // possible state transitions. |
| enum class GCPhase { |
| // GC is doing nothing. |
| kNone, |
| // GC is in marking phase. |
| kMarking, |
| // GC is in sweeping phase. |
| kSweeping, |
| }; |
| |
| enum class EphemeronProcessing { |
| kPartialProcessing, // Perofrm one ephemeron processing iteration every |
| // few step |
| kFullProcessing // Perofrm full fixed-point ephemeron processing on each |
| // step |
| }; |
| |
| class AtomicPauseScope; |
| class GCForbiddenScope; |
| class LsanDisabledScope; |
| class NoAllocationScope; |
| class StatisticsCollector; |
| struct Statistics; |
| class SweepForbiddenScope; |
| |
| using V8BuildEmbedderGraphCallback = void (*)(v8::Isolate*, |
| v8::EmbedderGraph*, |
| void*); |
| |
| // Returns true if some thread (possibly the current thread) may be doing |
| // incremental marking. If false is returned, the *current* thread is |
| // definitely not doing incremental marking. See atomic_entry_flag.h for |
| // details. |
| // |
| // For an exact check, use ThreadState::IsIncrementalMarking. |
| ALWAYS_INLINE static bool IsAnyIncrementalMarking() { |
| return incremental_marking_flag_.MightBeEntered(); |
| } |
| |
| static ThreadState* AttachMainThread(); |
| |
| // Associate ThreadState object with the current thread. After this |
| // call thread can start using the garbage collected heap infrastructure. |
| // It also has to periodically check for safepoints. |
| static ThreadState* AttachCurrentThread(); |
| |
| // Disassociate attached ThreadState from the current thread. The thread |
| // can no longer use the garbage collected heap after this call. |
| // |
| // When ThreadState is detaching from non-main thread its heap is expected to |
| // be empty (because it is going away). Perform registered cleanup tasks and |
| // garbage collection to sweep away any objects that are left on this heap. |
| // |
| // This method asserts that no objects remain after this cleanup. If assertion |
| // does not hold we crash as we are potentially in the dangling pointer |
| // situation. |
| static void DetachCurrentThread(); |
| |
| static ThreadState* Current() { return **thread_specific_; } |
| |
| static ThreadState* MainThreadState() { |
| return reinterpret_cast<ThreadState*>(main_thread_state_storage_); |
| } |
| |
| static ThreadState* FromObject(const void*); |
| |
| bool IsMainThread() const { return this == MainThreadState(); } |
| bool CheckThread() const { return thread_ == CurrentThread(); } |
| |
| ThreadHeap& Heap() const { return *heap_; } |
| base::PlatformThreadId ThreadId() const { return thread_; } |
| |
| // Associates |ThreadState| with a given |v8::Isolate|, essentially tying |
| // there garbage collectors together. |
| void AttachToIsolate(v8::Isolate*, V8BuildEmbedderGraphCallback); |
| |
| // Removes the association from a potentially attached |v8::Isolate|. |
| void DetachFromIsolate(); |
| |
| // Returns an |UnifiedHeapController| if ThreadState is attached to a V8 |
| // isolate (see |AttachToIsolate|) and nullptr otherwise. |
| UnifiedHeapController* unified_heap_controller() const { |
| DCHECK(isolate_); |
| return unified_heap_controller_.get(); |
| } |
| |
| void PerformIdleLazySweep(base::TimeTicks deadline); |
| void PerformConcurrentSweep(base::JobDelegate*); |
| |
| void ScheduleForcedGCForTesting(); |
| void ScheduleGCIfNeeded(); |
| void SetGCState(GCState); |
| GCState GetGCState() const { return gc_state_; } |
| void SetGCPhase(GCPhase); |
| |
| // Immediately starts incremental marking and schedules further steps if |
| // necessary. |
| void StartIncrementalMarking(BlinkGC::GCReason); |
| |
| // Returns true if marking is in progress. |
| bool IsMarkingInProgress() const { return gc_phase_ == GCPhase::kMarking; } |
| |
| // Returns true if unified heap marking is in progress. |
| bool IsUnifiedGCMarkingInProgress() const { |
| return IsMarkingInProgress() && IsUnifiedHeapGC(); |
| } |
| |
| // Returns true if sweeping is in progress. |
| bool IsSweepingInProgress() const { return gc_phase_ == GCPhase::kSweeping; } |
| |
| // Returns true if the current GC is a memory reducing GC. |
| bool IsMemoryReducingGC() const { |
| return current_gc_data_.reason == |
| BlinkGC::GCReason::kUnifiedHeapForMemoryReductionGC || |
| current_gc_data_.reason == |
| BlinkGC::GCReason::kUnifiedHeapForcedForTestingGC; |
| } |
| |
| bool IsUnifiedHeapGC() const { |
| return current_gc_data_.reason == BlinkGC::GCReason::kUnifiedHeapGC || |
| current_gc_data_.reason == |
| BlinkGC::GCReason::kUnifiedHeapForMemoryReductionGC || |
| current_gc_data_.reason == |
| BlinkGC::GCReason::kUnifiedHeapForcedForTestingGC; |
| } |
| |
| bool FinishIncrementalMarkingIfRunning(BlinkGC::CollectionType, |
| BlinkGC::StackState, |
| BlinkGC::MarkingType, |
| BlinkGC::SweepingType, |
| BlinkGC::GCReason); |
| |
| void EnableIncrementalMarkingBarrier(); |
| void DisableIncrementalMarkingBarrier(); |
| |
| void RestartIncrementalMarkingIfPaused(); |
| |
| void CompleteSweep(); |
| |
| // Returns whether it is currently allowed to allocate an object. Mainly used |
| // for sanity checks asserts. |
| bool IsAllocationAllowed() const { |
| // Allocation is not allowed during atomic marking pause, but it is allowed |
| // during atomic sweeping pause. |
| return !InAtomicMarkingPause() && !no_allocation_count_; |
| } |
| |
| // Returns whether it is currently forbidden to trigger a GC. |
| bool IsGCForbidden() const { return gc_forbidden_count_; } |
| |
| // Returns whether it is currently forbidden to sweep objects. |
| bool SweepForbidden() const { return sweep_forbidden_; } |
| |
| bool in_atomic_pause() const { return in_atomic_pause_; } |
| |
| bool InAtomicMarkingPause() const { |
| return in_atomic_pause() && IsMarkingInProgress(); |
| } |
| bool InAtomicSweepingPause() const { |
| return in_atomic_pause() && IsSweepingInProgress(); |
| } |
| |
| bool IsIncrementalMarking() const { return incremental_marking_; } |
| void SetIncrementalMarking(bool value) { incremental_marking_ = value; } |
| |
| void SafePoint(BlinkGC::StackState); |
| |
| // A region of non-weak PersistentNodes allocated on the given thread. |
| PersistentRegion* GetPersistentRegion() const { |
| return persistent_region_.get(); |
| } |
| |
| // A region of PersistentNodes for WeakPersistents allocated on the given |
| // thread. |
| PersistentRegion* GetWeakPersistentRegion() const { |
| return weak_persistent_region_.get(); |
| } |
| |
| v8::Isolate* GetIsolate() const { return isolate_; } |
| |
| // Returns |true| if |object| resides on this thread's heap. |
| // It is well-defined to call this method on any heap allocated |
| // reference, provided its associated heap hasn't been detached |
| // and shut down. Its behavior is undefined for any other pointer |
| // value. |
| bool IsOnThreadHeap(const void* object) const { |
| return &FromObject(object)->Heap() == &Heap(); |
| } |
| |
| ALWAYS_INLINE bool IsOnStack(Address address) const { |
| return reinterpret_cast<Address>(start_of_stack_) >= address && |
| address >= (reinterpret_cast<Address>(reinterpret_cast<uintptr_t>( |
| WTF::GetCurrentStackPosition()))); |
| } |
| |
| MarkingVisitor* CurrentVisitor() const { |
| return current_gc_data_.visitor.get(); |
| } |
| |
| // Returns true if the marking verifier is enabled, false otherwise. |
| bool IsVerifyMarkingEnabled() const; |
| |
| void SkipIncrementalMarkingForTesting() { |
| skip_incremental_marking_for_testing_ = true; |
| } |
| |
| // Performs stand-alone garbage collections considering only C++ objects for |
| // testing. |
| // |
| // Since it only considers C++ objects this type of GC is mostly useful for |
| // unit tests. |
| void CollectGarbageForTesting(BlinkGC::CollectionType, |
| BlinkGC::StackState, |
| BlinkGC::MarkingType, |
| BlinkGC::SweepingType, |
| BlinkGC::GCReason); |
| |
| // Forced garbage collection for testing: |
| // - Performs unified heap garbage collections if ThreadState is attached to a |
| // v8::Isolate using ThreadState::AttachToIsolate. |
| // - Otherwise, performs stand-alone garbage collections. |
| // - Collects garbage as long as live memory decreases (capped at 5). |
| void CollectAllGarbageForTesting( |
| BlinkGC::StackState stack_state = |
| BlinkGC::StackState::kNoHeapPointersOnStack); |
| |
| // Enables compaction for next garbage collection. |
| void EnableCompactionForNextGCForTesting(); |
| |
| bool RequiresForcedGCForTesting() const { |
| return current_gc_data_.stack_state == |
| BlinkGC::StackState::kHeapPointersOnStack && |
| !forced_scheduled_gc_for_testing_; |
| } |
| |
| void EnterNoHeapVerificationScopeForTesting() { |
| ++disable_heap_verification_scope_; |
| } |
| void LeaveNoHeapVerificationScopeForTesting() { |
| --disable_heap_verification_scope_; |
| } |
| |
| void NotifyGarbageCollection(v8::GCType, v8::GCCallbackFlags); |
| |
| // Waits until sweeping is done and invokes the given callback with |
| // the total sizes of live objects in Node and CSS arenas. |
| void CollectNodeAndCssStatistics( |
| base::OnceCallback<void(size_t allocated_node_bytes, |
| size_t allocated_css_bytes)>); |
| |
| private: |
| class IncrementalMarkingScheduler; |
| |
| // Stores whether some ThreadState is currently in incremental marking. |
| static AtomicEntryFlag incremental_marking_flag_; |
| |
| static WTF::ThreadSpecific<ThreadState*>* thread_specific_; |
| |
| // We can't create a static member of type ThreadState here because it will |
| // introduce global constructor and destructor. We would like to manage |
| // lifetime of the ThreadState attached to the main thread explicitly instead |
| // and still use normal constructor and destructor for the ThreadState class. |
| // For this we reserve static storage for the main ThreadState and lazily |
| // construct ThreadState in it using placement new. |
| static uint8_t main_thread_state_storage_[]; |
| |
| // Callback executed directly after pushing all callee-saved registers. |
| // |end_of_stack| denotes the end of the stack that can hold references to |
| // managed objects. |
| static void VisitStackAfterPushingRegisters(ThreadState*, |
| intptr_t* end_of_stack); |
| |
| static bool IsForcedGC(BlinkGC::GCReason reason) { |
| return reason == BlinkGC::GCReason::kThreadTerminationGC || |
| reason == BlinkGC::GCReason::kForcedGCForTesting || |
| reason == BlinkGC::GCReason::kUnifiedHeapForcedForTestingGC; |
| } |
| |
| ThreadState(); |
| ~ThreadState(); |
| |
| void EnterNoAllocationScope() { no_allocation_count_++; } |
| void LeaveNoAllocationScope() { no_allocation_count_--; } |
| |
| void EnterAtomicPause() { |
| DCHECK(!in_atomic_pause_); |
| in_atomic_pause_ = true; |
| } |
| void LeaveAtomicPause() { |
| DCHECK(in_atomic_pause_); |
| in_atomic_pause_ = false; |
| } |
| |
| void EnterGCForbiddenScope() { gc_forbidden_count_++; } |
| void LeaveGCForbiddenScope() { |
| DCHECK_GT(gc_forbidden_count_, 0u); |
| gc_forbidden_count_--; |
| } |
| |
| // Performs stand-alone garbage collections considering only C++ objects. |
| // |
| // Use the public *ForTesting calls for calling GC in tests. |
| void CollectGarbage(BlinkGC::CollectionType, |
| BlinkGC::StackState, |
| BlinkGC::MarkingType, |
| BlinkGC::SweepingType, |
| BlinkGC::GCReason); |
| |
| // The following methods are used to compose RunAtomicPause. Public users |
| // should use the CollectGarbage entrypoint. Internal users should use these |
| // methods to compose a full garbage collection. |
| void AtomicPauseMarkPrologue(BlinkGC::CollectionType, |
| BlinkGC::StackState, |
| BlinkGC::MarkingType, |
| BlinkGC::GCReason); |
| void AtomicPauseMarkRoots(BlinkGC::StackState, |
| BlinkGC::MarkingType, |
| BlinkGC::GCReason); |
| void AtomicPauseMarkTransitiveClosure(); |
| void AtomicPauseMarkEpilogue(BlinkGC::MarkingType); |
| void AtomicPauseSweepAndCompact(BlinkGC::CollectionType, |
| BlinkGC::MarkingType marking_type, |
| BlinkGC::SweepingType sweeping_type); |
| void AtomicPauseEpilogue(); |
| |
| // RunAtomicPause composes the final atomic pause that finishes a mark-compact |
| // phase of a garbage collection. Depending on SweepingType it may also finish |
| // sweeping or schedule lazy/concurrent sweeping. |
| void RunAtomicPause(BlinkGC::CollectionType, |
| BlinkGC::StackState, |
| BlinkGC::MarkingType, |
| BlinkGC::SweepingType, |
| BlinkGC::GCReason); |
| |
| // The version is needed to be able to start incremental marking. |
| void MarkPhasePrologue(BlinkGC::CollectionType, |
| BlinkGC::StackState, |
| BlinkGC::MarkingType, |
| BlinkGC::GCReason); |
| void MarkPhaseEpilogue(BlinkGC::MarkingType); |
| void MarkPhaseVisitRoots(); |
| void MarkPhaseVisitNotFullyConstructedObjects(); |
| bool MarkPhaseAdvanceMarkingBasedOnSchedule(base::TimeDelta, |
| EphemeronProcessing); |
| bool MarkPhaseAdvanceMarking(base::TimeDelta, EphemeronProcessing); |
| void VerifyMarking(BlinkGC::MarkingType); |
| |
| // Visit the stack after pushing registers onto the stack. |
| void PushRegistersAndVisitStack(); |
| |
| // Visit local thread stack and trace all pointers conservatively. Never call |
| // directly but always call through |PushRegistersAndVisitStack|. |
| void VisitStackImpl(MarkingVisitor*, Address*, Address*); |
| void VisitStack(MarkingVisitor*, Address*); |
| void VisitUnsafeStack(MarkingVisitor*); |
| |
| // Visit the asan fake stack frame corresponding to a slot on the real machine |
| // stack if there is one. Never call directly but always call through |
| // |PushRegistersAndVisitStack|. |
| void VisitAsanFakeStackForPointer(MarkingVisitor*, |
| Address, |
| Address*, |
| Address*); |
| |
| // Visit all non-weak persistents allocated on this thread. |
| void VisitPersistents(Visitor*); |
| |
| // Visit all weak persistents allocated on this thread. |
| void VisitWeakPersistents(Visitor*); |
| |
| // Visit card tables (remembered sets) containing inter-generational pointers. |
| void VisitRememberedSets(MarkingVisitor*); |
| |
| // Incremental marking implementation functions. |
| void IncrementalMarkingStartForTesting(); |
| void IncrementalMarkingStart(BlinkGC::GCReason); |
| // Incremental marking step advance marking on the mutator thread. This method |
| // also reschedules concurrent marking tasks if needed. The duration parameter |
| // applies only to incremental marking steps on the mutator thread. |
| void IncrementalMarkingStep(BlinkGC::StackState); |
| void IncrementalMarkingFinalize(); |
| |
| // Returns true if concurrent marking is finished (i.e. all current threads |
| // terminated and the worklist is empty) |
| bool ConcurrentMarkingStep(); |
| void ScheduleConcurrentMarking(); |
| void PerformConcurrentMark(base::JobDelegate* job); |
| |
| // Schedule helpers. |
| void ScheduleIdleLazySweep(); |
| void ScheduleConcurrentAndLazySweep(); |
| // Advances sweeping and returns true if sweeping is complete. |
| bool AdvanceLazySweep(base::TimeTicks deadline); |
| |
| void NotifySweepDone(); |
| void PostSweep(); |
| |
| // See |DetachCurrentThread|. |
| void RunTerminationGC(); |
| |
| void RunScheduledGC(BlinkGC::StackState); |
| |
| void SynchronizeAndFinishConcurrentSweeping(); |
| |
| void InvokePreFinalizers(); |
| |
| bool IsForcedGC() const { return IsForcedGC(current_gc_data_.reason); } |
| |
| // Returns whether stack scanning is forced. This is currently only used in |
| // platform tests where non nested tasks can be run with heap pointers on |
| // stack. |
| bool HeapPointersOnStackForced() const { |
| return heap_pointers_on_stack_forced_; |
| } |
| |
| #if defined(ADDRESS_SANITIZER) |
| // Poisons payload of unmarked objects. |
| // |
| // Also unpoisons memory areas for handles that may require resetting which |
| // can race with destructors. Note that cross-thread access still requires |
| // synchronization using a lock. |
| void PoisonUnmarkedObjects(); |
| #endif // ADDRESS_SANITIZER |
| |
| std::unique_ptr<ThreadHeap> heap_; |
| base::PlatformThreadId thread_; |
| std::unique_ptr<PersistentRegion> persistent_region_; |
| std::unique_ptr<PersistentRegion> weak_persistent_region_; |
| |
| // Start of the stack which is the boundary until conservative stack scanning |
| // needs to search for managed pointers. |
| Address* start_of_stack_; |
| |
| bool in_atomic_pause_ = false; |
| bool sweep_forbidden_ = false; |
| bool heap_pointers_on_stack_forced_ = false; |
| bool incremental_marking_ = false; |
| bool should_optimize_for_load_time_ = false; |
| bool forced_scheduled_gc_for_testing_ = false; |
| size_t no_allocation_count_ = 0; |
| size_t gc_forbidden_count_ = 0; |
| |
| GCState gc_state_ = GCState::kNoGCScheduled; |
| GCPhase gc_phase_ = GCPhase::kNone; |
| BlinkGC::GCReason reason_for_scheduled_gc_ = |
| BlinkGC::GCReason::kForcedGCForTesting; |
| |
| using PreFinalizerCallback = bool (*)(const LivenessBroker&, void*); |
| using PreFinalizer = std::pair<void*, PreFinalizerCallback>; |
| |
| // Pre-finalizers are called in the reverse order in which they are |
| // registered by the constructors (including constructors of Mixin objects) |
| // for an object, by processing the ordered_pre_finalizers_ back-to-front. |
| Deque<PreFinalizer> ordered_pre_finalizers_; |
| |
| v8::Isolate* isolate_ = nullptr; |
| V8BuildEmbedderGraphCallback v8_build_embedder_graph_ = nullptr; |
| std::unique_ptr<UnifiedHeapController> unified_heap_controller_; |
| |
| #if defined(ADDRESS_SANITIZER) |
| void* asan_fake_stack_; |
| #endif |
| |
| struct GCData { |
| BlinkGC::CollectionType collection_type; |
| BlinkGC::StackState stack_state; |
| BlinkGC::MarkingType marking_type; |
| BlinkGC::GCReason reason; |
| std::unique_ptr<MarkingVisitor> visitor; |
| }; |
| GCData current_gc_data_; |
| |
| std::unique_ptr<IncrementalMarkingScheduler> incremental_marking_scheduler_; |
| std::unique_ptr<MarkingSchedulingOracle> marking_scheduling_; |
| |
| base::JobHandle marker_handle_; |
| |
| base::JobHandle sweeper_handle_; |
| std::atomic_bool has_unswept_pages_{false}; |
| |
| size_t disable_heap_verification_scope_ = 0; |
| |
| bool skip_incremental_marking_for_testing_ = false; |
| |
| size_t last_concurrently_marked_bytes_ = 0; |
| base::TimeTicks last_concurrently_marked_bytes_update_; |
| bool concurrent_marking_priority_increased_ = false; |
| |
| friend class incremental_marking_test::IncrementalMarkingScope; |
| friend class HeapPointersOnStackScope; |
| friend class IncrementalMarkingTestDriver; |
| friend class HeapAllocator; |
| template <typename T> |
| friend class PrefinalizerRegistration; |
| friend class TestGCScope; |
| friend class TestSupportingGC; |
| friend class ThreadStateSchedulingTest; |
| friend class UnifiedHeapController; |
| |
| DISALLOW_COPY_AND_ASSIGN(ThreadState); |
| }; |
| |
| template <> |
| class ThreadStateFor<kMainThreadOnly> { |
| STATIC_ONLY(ThreadStateFor); |
| |
| public: |
| static ThreadState* GetState() { |
| // This specialization must only be used from the main thread. |
| DCHECK(ThreadState::Current()->IsMainThread()); |
| return ThreadState::MainThreadState(); |
| } |
| }; |
| |
| template <> |
| class ThreadStateFor<kAnyThread> { |
| STATIC_ONLY(ThreadStateFor); |
| |
| public: |
| static ThreadState* GetState() { return ThreadState::Current(); } |
| }; |
| |
| } // namespace blink |
| |
| #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_THREAD_STATE_H_ |