static constexpr bool kProtectFromSpace = true;
static constexpr bool kClearFromSpace = true;
static constexpr bool kStoreStackTraces = false;
+static constexpr bool kUseBytesPromoted = true;
+static constexpr size_t kBytesPromotedThreshold = 4 * MB;
void SemiSpace::BindBitmaps() {
timings_.StartSplit("BindBitmaps");
generational_(generational),
last_gc_to_space_end_(nullptr),
bytes_promoted_(0),
+ bytes_promoted_since_last_whole_heap_collection_(0),
whole_heap_collection_(true),
- whole_heap_collection_interval_counter_(0) {
+ whole_heap_collection_interval_counter_(0),
+ collector_name_(name_) {
}
void SemiSpace::InitializePhase() {
// collection, collect the whole heap (and reset the interval
// counter to be consistent.)
whole_heap_collection_ = true;
- whole_heap_collection_interval_counter_ = 0;
+ if (!kUseBytesPromoted) {
+ whole_heap_collection_interval_counter_ = 0;
+ }
}
if (whole_heap_collection_) {
VLOG(heap) << "Whole heap collection";
+ name_ = collector_name_ + " whole";
} else {
VLOG(heap) << "Bump pointer space only collection";
+ name_ = collector_name_ + " bps";
+ }
+ }
+
+ if (!clear_soft_references_) {
+ if (!generational_) {
+ // If non-generational, always clear soft references.
+ clear_soft_references_ = true;
+ } else {
+ // If generational, clear soft references if a whole heap collection.
+ if (whole_heap_collection_) {
+ clear_soft_references_ = true;
+ }
}
}
+
Locks::mutator_lock_->AssertExclusiveHeld(self_);
TimingLogger::ScopedSplit split("MarkingPhase", &timings_);
if (generational_) {
// Decide whether to do a whole heap collection or a bump pointer
// only space collection at the next collection by updating
- // whole_heap_collection. Enable whole_heap_collection once every
- // kDefaultWholeHeapCollectionInterval collections.
+ // whole_heap_collection.
if (!whole_heap_collection_) {
- --whole_heap_collection_interval_counter_;
- DCHECK_GE(whole_heap_collection_interval_counter_, 0);
- if (whole_heap_collection_interval_counter_ == 0) {
- whole_heap_collection_ = true;
+ if (!kUseBytesPromoted) {
+ // Enable whole_heap_collection once every
+ // kDefaultWholeHeapCollectionInterval collections.
+ --whole_heap_collection_interval_counter_;
+ DCHECK_GE(whole_heap_collection_interval_counter_, 0);
+ if (whole_heap_collection_interval_counter_ == 0) {
+ whole_heap_collection_ = true;
+ }
+ } else {
+ // Enable whole_heap_collection if the bytes promoted since
+ // the last whole heap collection exceeds a threshold.
+ bytes_promoted_since_last_whole_heap_collection_ += bytes_promoted_;
+ if (bytes_promoted_since_last_whole_heap_collection_ >= kBytesPromotedThreshold) {
+ whole_heap_collection_ = true;
+ }
}
} else {
- DCHECK_EQ(whole_heap_collection_interval_counter_, 0);
- whole_heap_collection_interval_counter_ = kDefaultWholeHeapCollectionInterval;
- whole_heap_collection_ = false;
+ if (!kUseBytesPromoted) {
+ DCHECK_EQ(whole_heap_collection_interval_counter_, 0);
+ whole_heap_collection_interval_counter_ = kDefaultWholeHeapCollectionInterval;
+ whole_heap_collection_ = false;
+ } else {
+ // Reset it.
+ bytes_promoted_since_last_whole_heap_collection_ = bytes_promoted_;
+ whole_heap_collection_ = false;
+ }
}
}
// Clear all of the spaces' mark bitmaps.
// bump pointer space to the non-moving space.
uint64_t bytes_promoted_;
+ // Used for the generational mode. Keeps track of how many bytes of
+ // objects have been copied so far from the bump pointer space to
+ // the non-moving space, since the last whole heap collection.
+ uint64_t bytes_promoted_since_last_whole_heap_collection_;
+
// Used for the generational mode. When true, collect the whole
// heap. When false, collect only the bump pointer spaces.
bool whole_heap_collection_;
// How many bytes we avoided dirtying.
size_t saved_bytes_;
+ // The name of the collector.
+ std::string collector_name_;
+
// Used for the generational mode. The default interval of the whole
// heap collection. If N, the whole heap collection occurs every N
// collections.
if (kMovingCollector) {
// TODO: Clean this up.
bool generational = post_zygote_collector_type_ == kCollectorTypeGSS;
- semi_space_collector_ = new collector::SemiSpace(this, generational);
+ semi_space_collector_ = new collector::SemiSpace(this, generational,
+ generational ? "generational" : "");
garbage_collectors_.push_back(semi_space_collector_);
concurrent_copying_collector_ = new collector::ConcurrentCopying(this);
<< "Could not find garbage collector with collector_type="
<< static_cast<size_t>(collector_type_) << " and gc_type=" << gc_type;
ATRACE_BEGIN(StringPrintf("%s %s GC", PrettyCause(gc_cause), collector->GetName()).c_str());
- if (!clear_soft_references) {
- clear_soft_references = gc_type != collector::kGcTypeSticky; // TODO: GSS?
- }
collector->Run(gc_cause, clear_soft_references || runtime->IsZygote());
total_objects_freed_ever_ += collector->GetFreedObjects();
total_bytes_freed_ever_ += collector->GetFreedBytes();