[test] Introduce flag for fuzzer analysis phase.

--stress-marking and --stress-scavenge flags with the value
greater than 0 enable additional tracking, allocation observers etc.

--fuzzer-analysis switches --stress-* flags into analysis mode,
which means that all allocation observers and additional checks
are still executed, but GC is not influenced by them. It also
provides analysis information needed by the fuzzer on the stdout.

Bug: v8:6972
Change-Id: I5ac45adb311441d57d5b951aeec036e689930e9f
Reviewed-on: https://chromium-review.googlesource.com/814536
Reviewed-by: Hannes Payer <hpayer@chromium.org>
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
Commit-Queue: Michał Majewski <majeski@google.com>
Cr-Commit-Position: refs/heads/master@{#50453}
This commit is contained in:
Michal Majewski 2018-01-09 10:50:04 +01:00 committed by Commit Bot
parent bf4cc9ee15
commit 5c56e27d49
5 changed files with 75 additions and 22 deletions

View File

@ -656,6 +656,8 @@ DEFINE_BOOL(parallel_pointer_update, true,
"use parallel pointer update during compaction")
DEFINE_BOOL(trace_incremental_marking, false,
"trace progress of the incremental marking")
DEFINE_BOOL(trace_stress_marking, false, "trace stress marking progress")
DEFINE_BOOL(trace_stress_scavenge, false, "trace stress scavenge progress")
DEFINE_BOOL(track_gc_object_stats, false,
"track object counts and memory usage")
DEFINE_BOOL(trace_gc_object_stats, false,
@ -705,13 +707,18 @@ DEFINE_BOOL(stress_compaction_random, false,
"evacuation candidates. It overrides stress_compaction.")
DEFINE_BOOL(stress_incremental_marking, false,
"force incremental marking for small heaps and run it more often")
DEFINE_BOOL(fuzzer_gc_analysis, false,
"enables analysis mode for gc fuzz testing, e.g. --stress-marking, "
"--stress-scavenge")
DEFINE_INT(stress_marking, 0,
"force marking at random points between 0 and X (inclusive) percent "
"of the regular marking start limit")
DEFINE_INT(stress_scavenge, 0,
"force scavenge at random points between 0 and X (inclusive) "
"percent of the new space capacity")
DEFINE_BOOL(stress_scavenge_analysis, false, "enables stress-scavenge logging.")
DEFINE_IMPLICATION(fuzzer_gc_analysis, stress_marking)
DEFINE_IMPLICATION(fuzzer_gc_analysis, stress_scavenge)
DEFINE_BOOL(manual_evacuation_candidates_selection, false,
"Test mode only flag. It allows an unit test to select evacuation "

View File

@ -177,6 +177,7 @@ Heap::Heap()
raw_allocations_hash_(0),
stress_marking_observer_(nullptr),
stress_scavenge_observer_(nullptr),
max_marking_limit_reached_(0.0),
ms_count_(0),
gc_count_(0),
mmap_region_base_(0),
@ -5448,13 +5449,20 @@ Heap::IncrementalMarkingLimit Heap::IncrementalMarkingLimitReached() {
if (bytes_to_limit > 0) {
double current_percent = (gained_since_last_gc / bytes_to_limit) * 100.0;
if (FLAG_trace_incremental_marking) {
if (FLAG_trace_stress_marking) {
isolate()->PrintWithTimestamp(
"[IncrementalMarking] %.2lf%% of the memory limit reached\n",
current_percent);
}
if (static_cast<int>(current_percent) >= stress_marking_percentage_) {
if (FLAG_fuzzer_gc_analysis) {
// Skips values >=100% since they already trigger marking.
if (current_percent < 100.0) {
max_marking_limit_reached_ =
std::max(max_marking_limit_reached_, current_percent);
}
} else if (static_cast<int>(current_percent) >=
stress_marking_percentage_) {
stress_marking_percentage_ = NextStressMarkingLimit();
return IncrementalMarkingLimit::kHardLimit;
}
@ -5610,12 +5618,11 @@ bool Heap::SetUp() {
if (FLAG_stress_marking > 0) {
stress_marking_percentage_ = NextStressMarkingLimit();
stress_marking_observer_ = new StressMarkingObserver(*this);
AddAllocationObserversToAllSpaces(stress_marking_observer_,
stress_marking_observer_);
}
if (FLAG_stress_scavenge_analysis || FLAG_stress_scavenge > 0) {
if (FLAG_stress_scavenge > 0) {
stress_scavenge_observer_ = new StressScavengeObserver(*this);
new_space()->AddAllocationObserver(stress_scavenge_observer_);
}
@ -5658,6 +5665,16 @@ void Heap::PrintAllocationsHash() {
PrintF("\n### Allocations = %u, hash = 0x%08x\n", allocations_count(), hash);
}
void Heap::PrintMaxMarkingLimitReached() {
PrintF("\n### Maximum marking limit reached = %.02lf\n",
max_marking_limit_reached_);
}
void Heap::PrintMaxNewSpaceSizeReached() {
PrintF("\n### Maximum new space size reached = %.02lf\n",
stress_scavenge_observer_->MaxNewSpaceSizeReached());
}
int Heap::NextStressMarkingLimit() {
return isolate()->fuzzer_rng()->NextInt(FLAG_stress_marking + 1);
}
@ -5724,6 +5741,15 @@ void Heap::TearDown() {
PrintAllocationsHash();
}
if (FLAG_fuzzer_gc_analysis) {
if (FLAG_stress_marking > 0) {
PrintMaxMarkingLimitReached();
}
if (FLAG_stress_scavenge > 0) {
PrintMaxNewSpaceSizeReached();
}
}
new_space()->RemoveAllocationObserver(idle_scavenge_observer_);
delete idle_scavenge_observer_;
idle_scavenge_observer_ = nullptr;
@ -5734,7 +5760,7 @@ void Heap::TearDown() {
delete stress_marking_observer_;
stress_marking_observer_ = nullptr;
}
if (FLAG_stress_scavenge_analysis || FLAG_stress_scavenge > 0) {
if (FLAG_stress_scavenge > 0) {
new_space()->RemoveAllocationObserver(stress_scavenge_observer_);
delete stress_scavenge_observer_;
stress_scavenge_observer_ = nullptr;

View File

@ -1869,6 +1869,9 @@ class Heap {
inline void UpdateAllocationsHash(uint32_t value);
void PrintAllocationsHash();
void PrintMaxMarkingLimitReached();
void PrintMaxNewSpaceSizeReached();
int NextStressMarkingLimit();
void AddToRingBuffer(const char* string);
@ -2394,6 +2397,10 @@ class Heap {
// Observer that can cause early scavenge start.
StressScavengeObserver* stress_scavenge_observer_;
// The maximum percent of the marking limit reached wihout causing marking.
// This is tracked when specyfing --fuzzer-gc-analysis.
double max_marking_limit_reached_;
// How many mark-sweep collections happened.
unsigned int ms_count_;

View File

@ -14,14 +14,15 @@ namespace internal {
// TODO(majeski): meaningful step_size
StressScavengeObserver::StressScavengeObserver(Heap& heap)
: AllocationObserver(64), heap_(heap), has_requested_gc_(false) {
if (FLAG_stress_scavenge > 0) {
limit_percentage_ = NextLimit();
: AllocationObserver(64),
heap_(heap),
has_requested_gc_(false),
max_new_space_size_reached_(0.0) {
limit_percentage_ = NextLimit();
if (FLAG_stress_scavenge_analysis) {
heap_.isolate()->PrintWithTimestamp(
"[StressScavenge] %d%% is the new limit\n", limit_percentage_);
}
if (FLAG_trace_stress_scavenge && !FLAG_fuzzer_gc_analysis) {
heap_.isolate()->PrintWithTimestamp(
"[StressScavenge] %d%% is the new limit\n", limit_percentage_);
}
}
@ -34,19 +35,21 @@ void StressScavengeObserver::Step(int bytes_allocated, Address soon_object,
double current_percent =
heap_.new_space()->Size() * 100.0 / heap_.new_space()->Capacity();
if (FLAG_stress_scavenge_analysis) {
if (FLAG_trace_stress_scavenge) {
heap_.isolate()->PrintWithTimestamp(
"[StressScavenge] %.2lf%% of the new space capacity reached\n",
"[Scavenge] %.2lf%% of the new space capacity reached\n",
current_percent);
}
if (!FLAG_stress_scavenge) {
if (FLAG_fuzzer_gc_analysis) {
max_new_space_size_reached_ =
std::max(max_new_space_size_reached_, current_percent);
return;
}
if (static_cast<int>(current_percent) >= limit_percentage_) {
if (FLAG_stress_scavenge_analysis) {
heap_.isolate()->PrintWithTimestamp("[StressScavenge] GC requested\n");
if (FLAG_trace_stress_scavenge) {
heap_.isolate()->PrintWithTimestamp("[Scavenge] GC requested\n");
}
has_requested_gc_ = true;
@ -63,17 +66,21 @@ void StressScavengeObserver::RequestedGCDone() {
heap_.new_space()->Size() * 100.0 / heap_.new_space()->Capacity();
limit_percentage_ = NextLimit(static_cast<int>(current_percent));
if (FLAG_stress_scavenge_analysis) {
if (FLAG_trace_stress_scavenge) {
heap_.isolate()->PrintWithTimestamp(
"[StressScavenge] %.2lf%% of the new space capacity reached\n",
"[Scavenge] %.2lf%% of the new space capacity reached\n",
current_percent);
heap_.isolate()->PrintWithTimestamp(
"[StressScavenge] %d%% is the new limit\n", limit_percentage_);
heap_.isolate()->PrintWithTimestamp("[Scavenge] %d%% is the new limit\n",
limit_percentage_);
}
has_requested_gc_ = false;
}
double StressScavengeObserver::MaxNewSpaceSizeReached() const {
return max_new_space_size_reached_;
}
int StressScavengeObserver::NextLimit(int min) {
int max = FLAG_stress_scavenge;
if (min >= max) {

View File

@ -19,11 +19,17 @@ class StressScavengeObserver : public AllocationObserver {
bool HasRequestedGC() const;
void RequestedGCDone();
// The maximum percent of the newspace capacity reached. This is tracked when
// specyfing --fuzzer-gc-analysis.
double MaxNewSpaceSizeReached() const;
private:
Heap& heap_;
int limit_percentage_;
bool has_requested_gc_;
double max_new_space_size_reached_;
int NextLimit(int min = 0);
};