Skip to content

Commit 2d149e4

Browse files
committed
Fix broken stats gathering code if no. of GCs > MAX_PHASES
1 parent 5e7d9da commit 2d149e4

File tree

3 files changed

+24
-33
lines changed

3 files changed

+24
-33
lines changed

src/util/statistics/counter/event_counter.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::*;
2-
use crate::util::statistics::stats::{SharedStats, MAX_PHASES};
2+
use crate::util::statistics::stats::{SharedStats, DEFAULT_NUM_PHASES};
33
use std::sync::Arc;
44

55
/**
@@ -10,7 +10,7 @@ pub struct EventCounter {
1010
name: String,
1111
pub implicitly_start: bool,
1212
merge_phases: bool,
13-
count: Box<[u64; MAX_PHASES]>,
13+
count: Vec<u64>,
1414
current_count: u64,
1515
running: bool,
1616
stats: Arc<SharedStats>,
@@ -27,7 +27,7 @@ impl EventCounter {
2727
name,
2828
implicitly_start,
2929
merge_phases,
30-
count: Box::new([0; MAX_PHASES]),
30+
count: Vec::with_capacity(DEFAULT_NUM_PHASES),
3131
current_count: 0,
3232
running: false,
3333
stats,
@@ -76,13 +76,15 @@ impl Counter for EventCounter {
7676
return;
7777
}
7878
debug_assert!(self.running);
79-
self.count[self.stats.get_phase()] = self.current_count;
79+
self.count.push(self.current_count);
80+
debug_assert_eq!(self.count[self.stats.get_phase()], self.current_count);
8081
self.running = false;
8182
}
8283

8384
fn phase_change(&mut self, old_phase: usize) {
8485
if self.running {
85-
self.count[old_phase] = self.current_count;
86+
self.count.push(self.current_count);
87+
debug_assert_eq!(self.count[old_phase], self.current_count);
8688
self.current_count = 0;
8789
}
8890
}

src/util/statistics/counter/long_counter.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use super::*;
2-
use crate::util::statistics::stats::{SharedStats, MAX_PHASES};
2+
use crate::util::statistics::stats::{SharedStats, DEFAULT_NUM_PHASES};
33
use std::fmt;
44
use std::sync::Arc;
55

66
pub struct LongCounter<T: Diffable> {
77
name: String,
88
pub implicitly_start: bool,
99
merge_phases: bool,
10-
count: Box<[u64; MAX_PHASES]>, // FIXME make this resizable
10+
count: Vec<u64>,
1111
diffable: T,
1212
start_value: Option<T::Val>,
1313
total_count: u64,
@@ -41,15 +41,17 @@ impl<T: Diffable> Counter for LongCounter<T> {
4141
self.diffable.stop();
4242
let current_value = self.diffable.current_value();
4343
let delta = T::diff(&current_value, self.start_value.as_ref().unwrap());
44-
self.count[self.stats.get_phase()] += delta;
44+
self.count.push(delta);
45+
debug_assert_eq!(self.count[self.stats.get_phase()], delta);
4546
self.total_count += delta;
4647
}
4748

4849
fn phase_change(&mut self, old_phase: usize) {
4950
if self.running {
5051
let now = self.diffable.current_value();
5152
let delta = T::diff(&now, self.start_value.as_ref().unwrap());
52-
self.count[old_phase] += delta;
53+
self.count.push(delta);
54+
debug_assert_eq!(self.count[old_phase], delta);
5355
self.total_count += delta;
5456
self.start_value = Some(now);
5557
}
@@ -139,7 +141,7 @@ impl<T: Diffable> LongCounter<T> {
139141
name,
140142
implicitly_start,
141143
merge_phases,
142-
count: Box::new([0; MAX_PHASES]),
144+
count: Vec::with_capacity(DEFAULT_NUM_PHASES),
143145
diffable,
144146
start_value: None,
145147
total_count: 0,

src/util/statistics/stats.rs

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
1111
use std::sync::Arc;
1212
use std::sync::Mutex;
1313

14-
// TODO: Increasing this number would cause JikesRVM die at boot time. I don't really know why.
15-
// E.g. using 1 << 14 will cause JikesRVM segfault at boot time.
16-
pub const MAX_PHASES: usize = 1 << 12;
14+
/// The default number of phases for the statistics.
15+
pub const DEFAULT_NUM_PHASES: usize = 1 << 12;
1716
pub const MAX_COUNTERS: usize = 100;
1817

1918
/// GC stats shared among counters
@@ -51,7 +50,6 @@ pub struct Stats {
5150
// Initialization of libpfm4 is required before we can use `PerfEvent` types
5251
#[cfg(feature = "perf_counter")]
5352
perfmon: Perfmon,
54-
5553
pub shared: Arc<SharedStats>,
5654
counters: Mutex<Vec<Arc<Mutex<dyn Counter + Send>>>>,
5755
exceeded_phase_limit: AtomicBool,
@@ -99,7 +97,6 @@ impl Stats {
9997
total_time: t,
10098
#[cfg(feature = "perf_counter")]
10199
perfmon,
102-
103100
shared,
104101
counters: Mutex::new(counters),
105102
exceeded_phase_limit: AtomicBool::new(false),
@@ -157,32 +154,22 @@ impl Stats {
157154
if !self.get_gathering_stats() {
158155
return;
159156
}
160-
if self.get_phase() < MAX_PHASES - 1 {
161-
let counters = self.counters.lock().unwrap();
162-
for counter in &(*counters) {
163-
counter.lock().unwrap().phase_change(self.get_phase());
164-
}
165-
self.shared.increment_phase();
166-
} else if !self.exceeded_phase_limit.load(Ordering::SeqCst) {
167-
eprintln!("Warning: number of GC phases exceeds MAX_PHASES");
168-
self.exceeded_phase_limit.store(true, Ordering::SeqCst);
157+
let counters = self.counters.lock().unwrap();
158+
for counter in &(*counters) {
159+
counter.lock().unwrap().phase_change(self.get_phase());
169160
}
161+
self.shared.increment_phase();
170162
}
171163

172164
pub fn end_gc(&self) {
173165
if !self.get_gathering_stats() {
174166
return;
175167
}
176-
if self.get_phase() < MAX_PHASES - 1 {
177-
let counters = self.counters.lock().unwrap();
178-
for counter in &(*counters) {
179-
counter.lock().unwrap().phase_change(self.get_phase());
180-
}
181-
self.shared.increment_phase();
182-
} else if !self.exceeded_phase_limit.load(Ordering::SeqCst) {
183-
eprintln!("Warning: number of GC phases exceeds MAX_PHASES");
184-
self.exceeded_phase_limit.store(true, Ordering::SeqCst);
168+
let counters = self.counters.lock().unwrap();
169+
for counter in &(*counters) {
170+
counter.lock().unwrap().phase_change(self.get_phase());
185171
}
172+
self.shared.increment_phase();
186173
}
187174

188175
pub fn print_stats<VM: VMBinding>(&self, mmtk: &'static MMTK<VM>) {

0 commit comments

Comments
 (0)