From 2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 9 May 2016 14:22:11 +0200 Subject: BASELINE: Update Chromium to 51.0.2704.41 Also adds in all smaller components by reversing logic for exclusion. Change-Id: Ibf90b506e7da088ea2f65dcf23f2b0992c504422 Reviewed-by: Joerg Bornemann --- chromium/base/metrics/statistics_recorder.cc | 202 +++++++++++++++++++++------ 1 file changed, 162 insertions(+), 40 deletions(-) (limited to 'chromium/base/metrics/statistics_recorder.cc') diff --git a/chromium/base/metrics/statistics_recorder.cc b/chromium/base/metrics/statistics_recorder.cc index b18efad280a..07e81b0f1b6 100644 --- a/chromium/base/metrics/statistics_recorder.cc +++ b/chromium/base/metrics/statistics_recorder.cc @@ -4,13 +4,15 @@ #include "base/metrics/statistics_recorder.h" +#include + #include "base/at_exit.h" #include "base/debug/leak_annotations.h" #include "base/json/string_escape.h" #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "base/metrics/histogram.h" #include "base/metrics/metrics_hashes.h" +#include "base/metrics/persistent_histogram_allocator.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/synchronization/lock.h" @@ -31,6 +33,55 @@ bool HistogramNameLesser(const base::HistogramBase* a, namespace base { +StatisticsRecorder::HistogramIterator::HistogramIterator( + const HistogramMap::iterator& iter, bool include_persistent) + : iter_(iter), + include_persistent_(include_persistent) { +} + +StatisticsRecorder::HistogramIterator::HistogramIterator( + const HistogramIterator& rhs) + : iter_(rhs.iter_), + include_persistent_(rhs.include_persistent_) { +} + +StatisticsRecorder::HistogramIterator::~HistogramIterator() {} + +StatisticsRecorder::HistogramIterator& +StatisticsRecorder::HistogramIterator::operator++() { + const HistogramMap::iterator histograms_end = histograms_->end(); + if (iter_ == histograms_end || lock_ == NULL) + return *this; + + base::AutoLock auto_lock(*lock_); + + for (;;) { + ++iter_; + if (iter_ == histograms_end) + break; + if (!include_persistent_ && (iter_->second->flags() & + HistogramBase::kIsPersistent)) { + continue; + } + break; + } + + return *this; +} + +StatisticsRecorder::~StatisticsRecorder() { + DCHECK(lock_); + DCHECK(histograms_); + DCHECK(ranges_); + + // Clean out what this object created and then restore what existed before. + Reset(); + base::AutoLock auto_lock(*lock_); + histograms_ = existing_histograms_.release(); + callbacks_ = existing_callbacks_.release(); + ranges_ = existing_ranges_.release(); +} + // static void StatisticsRecorder::Initialize() { // Ensure that an instance of the StatisticsRecorder object is created. @@ -66,10 +117,11 @@ HistogramBase* StatisticsRecorder::RegisterOrDeleteDuplicate( histogram_to_return = histogram; } else { const std::string& name = histogram->histogram_name(); - uint64_t name_hash = histogram->name_hash(); - HistogramMap::iterator it = histograms_->find(name_hash); + HistogramMap::iterator it = histograms_->find(name); if (histograms_->end() == it) { - (*histograms_)[name_hash] = histogram; + // The StringKey references the name within |histogram| rather than + // making a copy. + (*histograms_)[name] = histogram; ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 // If there are callbacks for this histogram, we set the kCallbackExists // flag. @@ -101,7 +153,7 @@ HistogramBase* StatisticsRecorder::RegisterOrDeleteDuplicate( const BucketRanges* StatisticsRecorder::RegisterOrDeleteDuplicateRanges( const BucketRanges* ranges) { DCHECK(ranges->HasValidChecksum()); - scoped_ptr ranges_deleter; + std::unique_ptr ranges_deleter; if (lock_ == NULL) { ANNOTATE_LEAKING_OBJECT_PTR(ranges); @@ -213,7 +265,6 @@ void StatisticsRecorder::GetHistograms(Histograms* output) { return; for (const auto& entry : *histograms_) { - DCHECK_EQ(entry.first, entry.second->name_hash()); output->push_back(entry.second); } } @@ -235,20 +286,69 @@ void StatisticsRecorder::GetBucketRanges( } // static -HistogramBase* StatisticsRecorder::FindHistogram(const std::string& name) { +HistogramBase* StatisticsRecorder::FindHistogram(base::StringPiece name) { if (lock_ == NULL) return NULL; + + // Import histograms from known persistent storage. Histograms could have + // been added by other processes and they must be fetched and recognized + // locally. If the persistent memory segment is not shared between processes, + // this call does nothing. + // This must be called *before* the lock is acquired below because it will + // call back into this object to register histograms. Those called methods + // will acquire the lock at that time. + GlobalHistogramAllocator* allocator = GlobalHistogramAllocator::Get(); + if (allocator) + allocator->ImportHistogramsToStatisticsRecorder(); + base::AutoLock auto_lock(*lock_); if (histograms_ == NULL) return NULL; - HistogramMap::iterator it = histograms_->find(HashMetricName(name)); + HistogramMap::iterator it = histograms_->find(name); if (histograms_->end() == it) return NULL; - DCHECK_EQ(name, it->second->histogram_name()) << "hash collision"; return it->second; } +// static +StatisticsRecorder::HistogramIterator StatisticsRecorder::begin( + bool include_persistent) { + DCHECK(histograms_); + + HistogramMap::iterator iter_begin; + { + base::AutoLock auto_lock(*lock_); + iter_begin = histograms_->begin(); + } + return HistogramIterator(iter_begin, include_persistent); +} + +// static +StatisticsRecorder::HistogramIterator StatisticsRecorder::end() { + HistogramMap::iterator iter_end; + { + base::AutoLock auto_lock(*lock_); + iter_end = histograms_->end(); + } + return HistogramIterator(iter_end, true); +} + +// static +void StatisticsRecorder::GetSnapshot(const std::string& query, + Histograms* snapshot) { + if (lock_ == NULL) + return; + base::AutoLock auto_lock(*lock_); + if (histograms_ == NULL) + return; + + for (const auto& entry : *histograms_) { + if (entry.second->histogram_name().find(query) != std::string::npos) + snapshot->push_back(entry.second); + } +} + // static bool StatisticsRecorder::SetCallback( const std::string& name, @@ -264,11 +364,9 @@ bool StatisticsRecorder::SetCallback( return false; callbacks_->insert(std::make_pair(name, cb)); - HistogramMap::iterator it = histograms_->find(HashMetricName(name)); - if (it != histograms_->end()) { - DCHECK_EQ(name, it->second->histogram_name()) << "hash collision"; + auto it = histograms_->find(name); + if (it != histograms_->end()) it->second->SetFlags(HistogramBase::kCallbackExists); - } return true; } @@ -284,11 +382,9 @@ void StatisticsRecorder::ClearCallback(const std::string& name) { callbacks_->erase(name); // We also clear the flag from the histogram (if it exists). - HistogramMap::iterator it = histograms_->find(HashMetricName(name)); - if (it != histograms_->end()) { - DCHECK_EQ(name, it->second->histogram_name()) << "hash collision"; + auto it = histograms_->find(name); + if (it != histograms_->end()) it->second->ClearFlags(HistogramBase::kCallbackExists); - } } // static @@ -305,26 +401,44 @@ StatisticsRecorder::OnSampleCallback StatisticsRecorder::FindCallback( : OnSampleCallback(); } -// private static -void StatisticsRecorder::GetSnapshot(const std::string& query, - Histograms* snapshot) { - if (lock_ == NULL) - return; +// static +size_t StatisticsRecorder::GetHistogramCount() { + if (!lock_) + return 0; + base::AutoLock auto_lock(*lock_); - if (histograms_ == NULL) + if (!histograms_) + return 0; + return histograms_->size(); +} + +// static +void StatisticsRecorder::ForgetHistogramForTesting(base::StringPiece name) { + if (histograms_) + histograms_->erase(name); +} + +// static +void StatisticsRecorder::UninitializeForTesting() { + // Stop now if it's never been initialized. + if (lock_ == NULL || histograms_ == NULL) return; - for (const auto& entry : *histograms_) { - if (entry.second->histogram_name().find(query) != std::string::npos) - snapshot->push_back(entry.second); - } + // Get the global instance and destruct it. It's held in static memory so + // can't "delete" it; call the destructor explicitly. + DCHECK(g_statistics_recorder_.private_instance_); + g_statistics_recorder_.Get().~StatisticsRecorder(); + + // Now the ugly part. There's no official way to release a LazyInstance once + // created so it's necessary to clear out an internal variable which + // shouldn't be publicly visible but is for initialization reasons. + g_statistics_recorder_.private_instance_ = 0; } // This singleton instance should be started during the single threaded portion // of main(), and hence it is not thread safe. It initializes globals to // provide support for all future calls. StatisticsRecorder::StatisticsRecorder() { - DCHECK(!histograms_); if (lock_ == NULL) { // This will leak on purpose. It's the only way to make sure we won't race // against the static uninitialization of the module while one of our @@ -334,7 +448,13 @@ StatisticsRecorder::StatisticsRecorder() { // during static initialization and released only on process termination. lock_ = new base::Lock; } + base::AutoLock auto_lock(*lock_); + + existing_histograms_.reset(histograms_); + existing_callbacks_.reset(callbacks_); + existing_ranges_.reset(ranges_); + histograms_ = new HistogramMap; callbacks_ = new CallbackMap; ranges_ = new RangesMap; @@ -344,19 +464,14 @@ StatisticsRecorder::StatisticsRecorder() { } // static -void StatisticsRecorder::DumpHistogramsToVlog(void* instance) { - std::string output; - StatisticsRecorder::WriteGraph(std::string(), &output); - VLOG(1) << output; -} - -StatisticsRecorder::~StatisticsRecorder() { - DCHECK(histograms_ && ranges_ && lock_); +void StatisticsRecorder::Reset() { + // If there's no lock then there is nothing to reset. + if (!lock_) + return; - // Clean up. - scoped_ptr histograms_deleter; - scoped_ptr callbacks_deleter; - scoped_ptr ranges_deleter; + std::unique_ptr histograms_deleter; + std::unique_ptr callbacks_deleter; + std::unique_ptr ranges_deleter; // We don't delete lock_ on purpose to avoid having to properly protect // against it going away after we checked for NULL in the static methods. { @@ -371,6 +486,13 @@ StatisticsRecorder::~StatisticsRecorder() { // We are going to leak the histograms and the ranges. } +// static +void StatisticsRecorder::DumpHistogramsToVlog(void* instance) { + std::string output; + StatisticsRecorder::WriteGraph(std::string(), &output); + VLOG(1) << output; +} + // static StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; -- cgit v1.2.1