Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  concurrent_copying.h

  Sprache: C
 

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#ifndef ART_RUNTIME_GC_COLLECTOR_CONCURRENT_COPYING_H_
#define ART_RUNTIME_GC_COLLECTOR_CONCURRENT_COPYING_H_

#include "base/macros.h"
#include "base/offsets.h"
#include "garbage_collector.h"
#include "gc/accounting/space_bitmap.h"
#include "immune_spaces.h"

#include <map>
#include <memory>
#include <unordered_map>
#include <vector>

namespace art HIDDEN {
class Barrier;
class Closure;
class RootInfo;

namespace mirror {
template<class MirrorType> class CompressedReference;
template<class MirrorType> class HeapReference;
class Object;
}  // namespace mirror

namespace gc {

namespace accounting {
template <size_t kAlignment> class SpaceBitmap;
using ContinuousSpaceBitmap = SpaceBitmap<kObjectAlignment>;
class HeapBitmap;
class ReadBarrierTable;
}  // namespace accounting

namespace space {
class RegionSpace;
}  // namespace space

namespace collector {

class ConcurrentCopying : public GarbageCollector {
 public:
  // Enable the no-from-space-refs verification at the pause.
  static constexpr bool kEnableNoFromSpaceRefsVerification = kIsDebugBuild;
  // Enable the from-space bytes/objects check.
  static constexpr bool kEnableFromSpaceAccountingCheck = kIsDebugBuild;
  // Enable verbose mode.
  static constexpr bool kVerboseMode = false;
  // If kGrayDirtyImmuneObjects is true then we gray dirty objects in the GC pause to prevent dirty
  // pages.
  static constexpr bool kGrayDirtyImmuneObjects = true;

  ConcurrentCopying(Heap* heap,
                    bool young_gen,
                    bool use_generational_cc,
                    const std::string& name_prefix = "",
                    bool measure_read_barrier_slow_path = false);
  ~ConcurrentCopying();

  void RunPhases() override
      REQUIRES(!immune_gray_stack_lock_,
               !mark_stack_lock_,
               !rb_slow_path_histogram_lock_,
               !skipped_blocks_lock_);
  void InitializePhase() REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_, !immune_gray_stack_lock_);
  void MarkingPhase() REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_);
  void CopyingPhase() REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_);
  void ReclaimPhase() REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!mark_stack_lock_);
  void FinishPhase() REQUIRES(!mark_stack_lock_,
                              !rb_slow_path_histogram_lock_,
                              !skipped_blocks_lock_);

  void CaptureRssAtPeak() REQUIRES(!mark_stack_lock_);
  void BindBitmaps() REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::heap_bitmap_lock_);
  GcType GetGcType() const override {
    return (use_generational_cc_ && young_gen_)
        ? kGcTypeSticky
        : kGcTypePartial;
  }
  CollectorType GetCollectorType() const override {
    return kCollectorTypeCC;
  }
  void RevokeAllThreadLocalBuffers() override;
  // Creates inter-region ref bitmaps for region-space and non-moving-space.
  // Gets called in Heap construction after the two spaces are created.
  void CreateInterRegionRefBitmaps();
  void SetRegionSpace(space::RegionSpace* region_space) {
    DCHECK(region_space != nullptr);
    region_space_ = region_space;
  }
  space::RegionSpace* RegionSpace() {
    return region_space_;
  }
  // Assert the to-space invariant for a heap reference `ref` held in `obj` at offset `offset`.
  void AssertToSpaceInvariant(mirror::Object* obj, MemberOffset offset, mirror::Object* ref)
      REQUIRES_SHARED(Locks::mutator_lock_);
  // Assert the to-space invariant for a GC root reference `ref`.
  void AssertToSpaceInvariant(GcRootSource* gc_root_source, mirror::Object* ref)
      REQUIRES_SHARED(Locks::mutator_lock_);
  bool IsInToSpace(mirror::Object* ref) REQUIRES_SHARED(Locks::mutator_lock_) {
    DCHECK(ref != nullptr);
    return IsMarked(ref) == ref;
  }
  // Mark object `from_ref`, copying it to the to-space if needed.
  template<bool kGrayImmuneObject = truebool kNoUnEvac = falsebool kFromGCThread = false>
  ALWAYS_INLINE mirror::Object* Mark(Thread* const self,
                                     mirror::Object* from_ref,
                                     mirror::Object* holder = nullptr,
                                     MemberOffset offset = MemberOffset(0))
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_);
  ALWAYS_INLINE mirror::Object* MarkFromReadBarrier(mirror::Object* from_ref)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_);
  bool IsMarking() const {
    return is_marking_;
  }
  // We may want to use read barrier entrypoints before is_marking_ is true since concurrent graying
  // creates a small window where we might dispatch on these entrypoints.
  bool IsUsingReadBarrierEntrypoints() const {
    return is_using_read_barrier_entrypoints_;
  }
  bool IsActive() const {
    return is_active_;
  }
  Barrier& GetBarrier() {
    return *gc_barrier_;
  }
  bool IsWeakRefAccessEnabled() REQUIRES(Locks::thread_list_lock_) {
    return weak_ref_access_enabled_;
  }
  void RevokeThreadLocalMarkStack(Thread* thread) REQUIRES(!mark_stack_lock_);

  // Blindly return the forwarding pointer from the lockword, or null if there is none.
  static mirror::Object* GetFwdPtrUnchecked(mirror::Object* from_ref)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // If marked, return the to-space object, otherwise null.
  mirror::Object* IsMarked(mirror::Object* from_ref) override
      REQUIRES_SHARED(Locks::mutator_lock_);

  void AssertNoThreadMarkStackMapping(Thread* thread) REQUIRES(!mark_stack_lock_);
  // Dump information about reference `ref` and return it as a string.
  // Use `ref_name` to name the reference in messages. Each message is prefixed with `indent`.
  std::string DumpReferenceInfo(mirror::Object* ref, const char* ref_name, const char* indent = "")
      REQUIRES_SHARED(Locks::mutator_lock_);

 private:
  EXPORT void PushOntoMarkStack(Thread* const self, mirror::Object* obj)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!mark_stack_lock_);
  // Returns a to-space copy of the from-space object from_ref, and atomically installs a
  // forwarding pointer. Ensures that the forwarding reference is visible to other threads before
  // the returned to-space pointer becomes visible to them.
  EXPORT mirror::Object* Copy(Thread* const self,
                              mirror::Object* from_ref,
                              mirror::Object* holder,
                              MemberOffset offset) REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_);
  // Scan the reference fields of object `to_ref`.
  template <bool kNoUnEvac>
  void Scan(mirror::Object* to_ref, size_t obj_size = 0) REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_);
  // Scan the reference fields of object 'obj' in the dirty cards during
  // card-table scan. In addition to visiting the references, it also sets the
  // read-barrier state to gray for Reference-type objects to ensure that
  // GetReferent() called on these objects calls the read-barrier on the referent.
  template <bool kNoUnEvac>
  void ScanDirtyObject(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_);
  // Process a field.
  template <bool kNoUnEvac>
  void Process(mirror::Object* obj, MemberOffset offset)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_ , !skipped_blocks_lock_, !immune_gray_stack_lock_);
  void VisitRoots(mirror::Object*** roots, size_t count, const RootInfo& info) override
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_);
  template<bool kGrayImmuneObject>
  void MarkRoot(Thread* const self, mirror::CompressedReference<mirror::Object>* root)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_);
  void VisitRoots(mirror::CompressedReference<mirror::Object>** roots,
                  size_t count,
                  const RootInfo& info) override
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_);
  void VerifyNoFromSpaceReferences() REQUIRES(Locks::mutator_lock_);
  accounting::ObjectStack* GetAllocationStack();
  accounting::ObjectStack* GetLiveStack();
  void ProcessMarkStack() override REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_);
  bool ProcessMarkStackOnce() REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!mark_stack_lock_);
  void ProcessMarkStackRef(mirror::Object* to_ref) REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_);
  void GrayAllDirtyImmuneObjects()
      REQUIRES(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_);
  void GrayAllNewlyDirtyImmuneObjects()
      REQUIRES(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_);
  void VerifyGrayImmuneObjects()
      REQUIRES(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_);
  void VerifyNoMissingCardMarks()
      REQUIRES(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_);
  template <typename Processor>
  size_t ProcessThreadLocalMarkStacks(bool disable_weak_ref_access,
                                      Closure* checkpoint_callback,
                                      const Processor& processor)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!mark_stack_lock_);
  void RevokeThreadLocalMarkStacks(bool disable_weak_ref_access, Closure* checkpoint_callback)
      REQUIRES_SHARED(Locks::mutator_lock_);
  void SwitchToSharedMarkStackMode() REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_);
  void SwitchToGcExclusiveMarkStackMode() REQUIRES_SHARED(Locks::mutator_lock_);
  void DelayReferenceReferent(ObjPtr<mirror::Class> klass,
                              ObjPtr<mirror::Reference> reference) override
      REQUIRES_SHARED(Locks::mutator_lock_);
  void ProcessReferences(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
  mirror::Object* MarkObject(mirror::Object* from_ref) override
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_);
  void MarkHeapReference(mirror::HeapReference<mirror::Object>* from_ref,
                         bool do_atomic_update) override
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_);
  bool IsMarkedInUnevacFromSpace(mirror::Object* from_ref)
      REQUIRES_SHARED(Locks::mutator_lock_);
  bool IsMarkedInNonMovingSpace(mirror::Object* from_ref)
      REQUIRES_SHARED(Locks::mutator_lock_);
  bool IsNullOrMarkedHeapReference(mirror::HeapReference<mirror::Object>* field) override
      REQUIRES_SHARED(Locks::mutator_lock_);
  void SweepSystemWeaks(Thread* self)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::heap_bitmap_lock_);
  // Sweep unmarked objects to complete the garbage collection. Full GCs sweep
  // all allocation spaces (except the region space). Sticky-bit GCs just sweep
  // a subset of the heap.
  void Sweep(bool swap_bitmaps)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_, !mark_stack_lock_);
  void SweepArray(accounting::ObjectStack* obj_arr, bool swap_bitmaps)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_, !mark_stack_lock_);
  void SweepLargeObjects(bool swap_bitmaps)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_);
  void MarkZygoteLargeObjects()
      REQUIRES_SHARED(Locks::mutator_lock_);
  void FillWithFakeObject(Thread* const self, mirror::Object* fake_obj, size_t byte_size)
      REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);
  mirror::Object* AllocateInSkippedBlock(Thread* const self, size_t alloc_size)
      REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);
  void CheckEmptyMarkStack() REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!mark_stack_lock_);
  void IssueEmptyCheckpoint() REQUIRES_SHARED(Locks::mutator_lock_);
  bool IsOnAllocStack(mirror::Object* ref) REQUIRES_SHARED(Locks::mutator_lock_);
  // Return the forwarding pointer from the lockword. The argument must be in from space.
  mirror::Object* GetFwdPtr(mirror::Object* from_ref) REQUIRES_SHARED(Locks::mutator_lock_);
  void FlipThreadRoots() REQUIRES(!Locks::mutator_lock_);
  void SwapStacks() REQUIRES_SHARED(Locks::mutator_lock_);
  void RecordLiveStackFreezeSize(Thread* self);
  void ComputeUnevacFromSpaceLiveRatio();
  void LogFromSpaceRefHolder(mirror::Object* obj, MemberOffset offset)
      REQUIRES_SHARED(Locks::mutator_lock_);
  // Dump information about heap reference `ref`, referenced from object `obj` at offset `offset`,
  // and return it as a string.
  EXPORT std::string DumpHeapReference(mirror::Object* obj,
                                       MemberOffset offset,
                                       mirror::Object* ref) REQUIRES_SHARED(Locks::mutator_lock_);
  // Dump information about GC root `ref` and return it as a string.
  std::string DumpGcRoot(mirror::Object* ref) REQUIRES_SHARED(Locks::mutator_lock_);
  void AssertToSpaceInvariantInNonMovingSpace(mirror::Object* obj, mirror::Object* ref)
      REQUIRES_SHARED(Locks::mutator_lock_);
  void ReenableWeakRefAccess(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
  void DisableMarking() REQUIRES_SHARED(Locks::mutator_lock_);
  void IssueDisableMarkingCheckpoint() REQUIRES_SHARED(Locks::mutator_lock_);
  void ExpandGcMarkStack() REQUIRES_SHARED(Locks::mutator_lock_);
  EXPORT mirror::Object* MarkNonMoving(Thread* const self,
                                       mirror::Object* from_ref,
                                       mirror::Object* holder = nullptr,
                                       MemberOffset offset = MemberOffset(0))
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_);
  ALWAYS_INLINE mirror::Object* MarkUnevacFromSpaceRegion(Thread* const self,
      mirror::Object* from_ref,
      accounting::SpaceBitmap<kObjectAlignment>* bitmap)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_);
  template<bool kGrayImmuneObject>
  ALWAYS_INLINE mirror::Object* MarkImmuneSpace(Thread* const self,
                                                mirror::Object* from_ref)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!immune_gray_stack_lock_);
  void ScanImmuneObject(mirror::Object* obj)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!mark_stack_lock_);
  EXPORT mirror::Object* MarkFromReadBarrierWithMeasurements(Thread* const self,
                                                             mirror::Object* from_ref)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_);
  void DumpPerformanceInfo(std::ostream& os) override REQUIRES(!rb_slow_path_histogram_lock_);
  // Set the read barrier mark entrypoints to non-null.
  void ActivateReadBarrierEntrypoints();

  void CaptureThreadRootsForMarking() REQUIRES_SHARED(Locks::mutator_lock_);
  void AddLiveBytesAndScanRef(mirror::Object* ref) REQUIRES_SHARED(Locks::mutator_lock_);
  bool TestMarkBitmapForRef(mirror::Object* ref) REQUIRES_SHARED(Locks::mutator_lock_);
  template <bool kAtomic = false>
  bool TestAndSetMarkBitForRef(mirror::Object* ref) REQUIRES_SHARED(Locks::mutator_lock_);
  void PushOntoLocalMarkStack(mirror::Object* ref) REQUIRES_SHARED(Locks::mutator_lock_);
  void ProcessMarkStackForMarkingAndComputeLiveBytes() REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!mark_stack_lock_);

  void RemoveThreadMarkStackMapping(Thread* thread, accounting::ObjectStack* tl_mark_stack)
      REQUIRES(mark_stack_lock_);
  void AddThreadMarkStackMapping(Thread* thread, accounting::ObjectStack* tl_mark_stack)
      REQUIRES(mark_stack_lock_);
  void AssertEmptyThreadMarkStackMap() REQUIRES(mark_stack_lock_);
  void VerifyLargeObject(mirror::Object* ref, mirror::Object* holder, MemberOffset offset)
      REQUIRES_SHARED(Locks::mutator_lock_);

  space::RegionSpace* region_space_;      // The underlying region space.
  std::unique_ptr<Barrier> gc_barrier_;
  std::unique_ptr<accounting::ObjectStack> gc_mark_stack_;

  // If true, enable generational collection when using the Concurrent Copying
  // (CC) collector, i.e. use sticky-bit CC for minor collections and (full) CC
  // for major collections. Generational CC collection is currently only
  // compatible with Baker read barriers. Set in Heap constructor.
  const bool use_generational_cc_;

  // Generational "sticky", only trace through dirty objects in region space.
  const bool young_gen_;

  // If true, the GC thread is done scanning marked objects on dirty and aged
  // card (see ConcurrentCopying::CopyingPhase).
  Atomic<bool> done_scanning_;

  // The read-barrier mark-bit stack. Stores object references whose
  // mark bit has been set by ConcurrentCopying::MarkFromReadBarrier,
  // so that this bit can be reset at the end of the collection in
  // ConcurrentCopying::FinishPhase. The mark bit of an object can be
  // used by mutator read barrier code to quickly test whether that
  // object has been already marked.
  std::unique_ptr<accounting::ObjectStack> rb_mark_bit_stack_;
  // Thread-unsafe Boolean value hinting that `rb_mark_bit_stack_` is
  // full. A thread-safe test of whether the read-barrier mark-bit
  // stack is full is implemented by `rb_mark_bit_stack_->AtomicPushBack(ref)`
  // (see use case in ConcurrentCopying::MarkFromReadBarrier).
  bool rb_mark_bit_stack_full_;

  // Guards access to pooled_mark_stacks_ and revoked_mark_stacks_ vectors.
  // Also guards destruction and revocations of thread-local mark-stacks.
  // Clearing thread-local mark-stack (by other threads or during destruction)
  // should be guarded by it.
  Mutex mark_stack_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
  std::vector<accounting::ObjectStack*> revoked_mark_stacks_
      GUARDED_BY(mark_stack_lock_);
  // Size of thread local mark stack.
  static size_t GetMarkStackSize() {
    return gPageSize;
  }
  static constexpr size_t kMarkStackPoolSize = 256;
  std::vector<accounting::ObjectStack*> pooled_mark_stacks_
      GUARDED_BY(mark_stack_lock_);
  Thread* thread_running_gc_;
  bool is_marking_;                       // True while marking is ongoing.
  // True while we might dispatch on the read barrier entrypoints.
  bool is_using_read_barrier_entrypoints_;
  bool is_active_;                        // True while the collection is ongoing.
  bool is_asserting_to_space_invariant_;  // True while asserting the to-space invariant.
  ImmuneSpaces immune_spaces_;
  accounting::ContinuousSpaceBitmap* region_space_bitmap_;
  // A cache of Heap::GetMarkBitmap().
  accounting::HeapBitmap* heap_mark_bitmap_;
  size_t live_stack_freeze_size_;
  size_t from_space_num_bytes_at_first_pause_;  // Computed if kEnableFromSpaceAccountingCheck
  Atomic<int> is_mark_stack_push_disallowed_;   // Debug only.
  enum MarkStackMode {
    kMarkStackModeOff = 0,      // Mark stack is off.
    kMarkStackModeThreadLocal,  // All threads except for the GC-running thread push refs onto
                                // thread-local mark stacks. The GC-running thread pushes onto and
                                // pops off the GC mark stack without a lock.
    kMarkStackModeShared,       // All threads share the GC mark stack with a lock.
    kMarkStackModeGcExclusive   // The GC-running thread pushes onto and pops from the GC mark stack
                                // without a lock. Other threads won't access the mark stack.
  };
  // mark_stack_mode_ is updated asynchronoulsy by the GC. We cannot assume that another thread
  // has seen it until it has run some kind of checkpoint.  We generally access this using
  // acquire/release ordering, to ensure that any relevant prior changes are visible to readers of
  // the flag, and to ensure that CHECKs prior to a state change cannot be delayed past the state
  // change.
  Atomic<MarkStackMode> mark_stack_mode_;
  bool weak_ref_access_enabled_ GUARDED_BY(Locks::thread_list_lock_);

  // How many objects and bytes we moved. The GC thread moves many more objects
  // than mutators.  Therefore, we separate the two to avoid CAS.  Bytes_moved_ and
  // bytes_moved_gc_thread_ are critical for GC triggering; the others are just informative.
  Atomic<size_t> bytes_moved_;  // Used by mutators
  Atomic<size_t> objects_moved_;  // Used by mutators

  // copied_live_bytes_ratio_sum_ is read and written by CC per GC, in
  // ReclaimPhase, and is read by DumpPerformanceInfo (potentially from another
  // thread). However, at present, DumpPerformanceInfo is only called when the
  // runtime shuts down, so no concurrent access. The same reasoning goes for
  // gc_count_ and reclaimed_bytes_ratio_sum_

  // The sum of of all copied live bytes ratio (to_bytes/from_bytes)
  float copied_live_bytes_ratio_sum_;
  // The number of GC counts, used to calculate the average above. (It doesn't
  // include GC where from_bytes is zero, IOW, from-space is empty, which is
  // possible for minor GC if all allocated objects are in non-moving
  // space.)
  size_t gc_count_;
  // Bit is set if the corresponding object has inter-region references that
  // were found during the marking phase of two-phase full-heap GC cycle.
  accounting::ContinuousSpaceBitmap region_space_inter_region_bitmap_;
  accounting::ContinuousSpaceBitmap non_moving_space_inter_region_bitmap_;

  // reclaimed_bytes_ratio = reclaimed_bytes/num_allocated_bytes per GC cycle
  float reclaimed_bytes_ratio_sum_;

  // Used only by GC thread, so need not be atomic. Also, should be kept
  // in a different cacheline than bytes/objects_moved_ (above) to avoid false
  // cacheline sharing.
  size_t bytes_moved_gc_thread_;
  size_t objects_moved_gc_thread_;
  uint64_t bytes_scanned_;
  uint64_t cumulative_bytes_moved_;

  // The skipped blocks are memory blocks/chucks that were copies of
  // objects that were unused due to lost races (cas failures) at
  // object copy/forward pointer install. They may be reused.
  // Skipped blocks are always in region space. Their size is included directly
  // in num_bytes_allocated_, i.e. they are treated as allocated, but may be directly
  // used without going through a GC cycle like other objects. They are reused only
  // if we run out of region space. TODO: Revisit this design.
  Mutex skipped_blocks_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
  std::multimap<size_t, uint8_t*> skipped_blocks_map_ GUARDED_BY(skipped_blocks_lock_);
  Atomic<size_t> to_space_bytes_skipped_;
  Atomic<size_t> to_space_objects_skipped_;

  // If measure_read_barrier_slow_path_ is true, we count how long is spent in MarkFromReadBarrier
  // and also log.
  bool measure_read_barrier_slow_path_;
  // mark_from_read_barrier_measurements_ is true if systrace is enabled or
  // measure_read_barrier_time_ is true.
  bool mark_from_read_barrier_measurements_;
  Atomic<uint64_t> rb_slow_path_ns_;
  Atomic<uint64_t> rb_slow_path_count_;
  Atomic<uint64_t> rb_slow_path_count_gc_;
  uint64_t app_slow_path_start_time_;
  mutable Mutex rb_slow_path_histogram_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
  Histogram<uint64_t> rb_slow_path_time_histogram_ GUARDED_BY(rb_slow_path_histogram_lock_);
  uint64_t rb_slow_path_count_total_ GUARDED_BY(rb_slow_path_histogram_lock_);
  uint64_t rb_slow_path_count_gc_total_ GUARDED_BY(rb_slow_path_histogram_lock_);

  accounting::ReadBarrierTable* rb_table_;
  bool force_evacuate_all_;  // True if all regions are evacuated.
  Atomic<bool> updated_all_immune_objects_;
  bool gc_grays_immune_objects_;
  Mutex immune_gray_stack_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
  std::vector<mirror::Object*> immune_gray_stack_ GUARDED_BY(immune_gray_stack_lock_);

  // Class of java.lang.Object. Filled in from WellKnownClasses in FlipCallback. Must
  // be filled in before flipping thread roots so that FillWithFakeObject can run. Not
  // ObjPtr since the GC may transition to suspended and runnable between phases.
  mirror::Class* java_lang_Object_;

  // Use signed because after_gc may be larger than before_gc.
  int64_t num_bytes_allocated_before_gc_;

  class ActivateReadBarrierEntrypointsCallback;
  class ActivateReadBarrierEntrypointsCheckpoint;
  class AssertToSpaceInvariantFieldVisitor;
  class AssertToSpaceInvariantRefsVisitor;
  class ClearBlackPtrsVisitor;
  class ComputeUnevacFromSpaceLiveRatioVisitor;
  class DisableMarkingCallback;
  class DisableMarkingCheckpoint;
  class DisableWeakRefAccessCallback;
  class FlipCallback;
  template <bool kConcurrent> class GrayImmuneObjectVisitor;
  class ImmuneSpaceScanObjVisitor;
  class LostCopyVisitor;
  template <bool kNoUnEvac> class RefFieldsVisitor;
  class RevokeThreadLocalMarkStackCheckpoint;
  class ScopedGcGraysImmuneObjects;
  class ThreadFlipVisitor;
  class VerifyGrayImmuneObjectsVisitor;
  class VerifyNoFromSpaceRefsFieldVisitor;
  class VerifyNoFromSpaceRefsVisitor;
  class VerifyNoMissingCardMarkVisitor;
  class ImmuneSpaceCaptureRefsVisitor;
  template <bool kAtomicTestAndSet = falseclass CaptureRootsForMarkingVisitor;
  class CaptureThreadRootsForMarkingAndCheckpoint;
  template <bool kHandleInterRegionRefs> class ComputeLiveBytesAndMarkRefFieldsVisitor;

  DISALLOW_IMPLICIT_CONSTRUCTORS(ConcurrentCopying);
};

}  // namespace collector
}  // namespace gc
}  // namespace art

#endif  // ART_RUNTIME_GC_COLLECTOR_CONCURRENT_COPYING_H_

Messung V0.5 in Prozent
C=89 H=97 G=93

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik