summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/base/histogram-inl.h238
-rw-r--r--src/base/histogram.h120
-rw-r--r--src/base/histogram_test.cc252
-rw-r--r--src/base/timing_logger.cc152
-rw-r--r--src/base/timing_logger.h81
-rw-r--r--src/class_linker.cc9
-rw-r--r--src/compiler.cc8
-rw-r--r--src/dex2oat.cc2
-rw-r--r--src/gc/mark_sweep.cc17
-rw-r--r--src/gc/mark_sweep.h19
-rw-r--r--src/heap.cc17
-rw-r--r--src/heap.h2
-rw-r--r--src/interpreter/interpreter.cc2
-rw-r--r--src/mirror/object-inl.h88
-rw-r--r--src/mirror/object.cc86
-rw-r--r--src/mirror/object.h14
-rw-r--r--src/monitor.cc2
-rw-r--r--src/native/dalvik_system_DexFile.cc1
-rw-r--r--src/native/dalvik_system_Zygote.cc8
-rw-r--r--src/native/java_lang_Object.cc10
-rw-r--r--src/oat/runtime/support_locks.cc2
-rw-r--r--src/object_utils.h8
-rw-r--r--src/thread.cc5
-rw-r--r--src/thread_list.cc6
-rw-r--r--src/timing_logger.cc98
-rw-r--r--src/timing_logger.h160
26 files changed, 994 insertions, 413 deletions
diff --git a/src/base/histogram-inl.h b/src/base/histogram-inl.h
new file mode 100644
index 0000000000..e9e52b69e1
--- /dev/null
+++ b/src/base/histogram-inl.h
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2013 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 SRC_BASE_HISTOGRAM_INL_H_
+#define SRC_BASE_HISTOGRAM_INL_H_
+
+#include "histogram.h"
+
+#include "utils.h"
+
+#include <algorithm>
+#include <cmath>
+#include <limits>
+#include <ostream>
+
+namespace art {
+
+template <class Value> inline void Histogram<Value>::AddValue(Value value) {
+ CHECK_GE(value, 0.0);
+ if (value >= max_) {
+ Value new_max = ((value + 1) / bucket_width_ + 1) * bucket_width_;
+ DCHECK_GT(new_max, max_);
+ GrowBuckets(new_max);
+ }
+
+ BucketiseValue(value);
+ new_values_added_ = true;
+}
+
+template <class Value>
+inline Histogram<Value>::Histogram(const std::string name)
+ : kAdjust(1000),
+ kBucketWidth(5),
+ kInitialBucketCount(10),
+ bucket_width_(kBucketWidth),
+ bucket_count_(kInitialBucketCount) {
+ name_ = name;
+ Reset();
+}
+
+template <class Value>
+inline void Histogram<Value>::GrowBuckets(Value new_max) {
+ while (max_ < new_max) {
+ max_ += bucket_width_;
+ ranges_.push_back(max_);
+ frequency_.push_back(0);
+ bucket_count_++;
+ }
+}
+
+template <class Value> inline size_t Histogram<Value>::FindBucket(Value val) {
+ // Since this is only a linear histogram, bucket index can be found simply with
+ // dividing the value by the bucket width.
+ DCHECK_GE(val, min_);
+ DCHECK_LE(val, max_);
+ size_t bucket_idx = static_cast<size_t>((double)(val - min_) / bucket_width_);
+ DCHECK_GE(bucket_idx, 0ul);
+ DCHECK_LE(bucket_idx, bucket_count_);
+ return bucket_idx;
+}
+
+template <class Value>
+inline void Histogram<Value>::BucketiseValue(Value value) {
+ CHECK_LT(value, max_);
+ sum_ += value;
+ sum_of_squares_ += value * value;
+ size_t bucket_idx = FindBucket(value);
+ sample_size_++;
+ if (value > max_value_added_) {
+ max_value_added_ = value;
+ }
+ if (value < min_value_added_) {
+ min_value_added_ = value;
+ }
+ frequency_[bucket_idx]++;
+}
+
+template <class Value> inline void Histogram<Value>::Initialize() {
+ DCHECK_GT(bucket_count_, 0ul);
+ size_t idx = 0;
+ for (; idx < bucket_count_; idx++) {
+ ranges_.push_back(min_ + static_cast<Value>(idx) * (bucket_width_));
+ frequency_.push_back(0);
+ }
+ // Cumulative frequency and ranges has a length of 1 over frequency.
+ ranges_.push_back(min_ + idx * bucket_width_);
+ max_ = bucket_width_ * bucket_count_;
+}
+
+template <class Value> inline void Histogram<Value>::Reset() {
+ bucket_width_ = kBucketWidth;
+ bucket_count_ = kInitialBucketCount;
+ max_ = bucket_width_ * bucket_count_;
+ sum_of_squares_ = 0;
+ sample_size_ = 0;
+ min_ = 0;
+ sum_ = 0;
+ min_value_added_ = std::numeric_limits<Value>::max();
+ max_value_added_ = std::numeric_limits<Value>::min();
+ new_values_added_ = false;
+ ranges_.clear();
+ frequency_.clear();
+ cumulative_freq_.clear();
+ cumulative_perc_.clear();
+ Initialize();
+}
+
+template <class Value> inline void Histogram<Value>::BuildRanges() {
+ for (size_t idx = 0; idx < bucket_count_; ++idx) {
+ ranges_.push_back(min_ + idx * bucket_width_);
+ }
+}
+
+template <class Value> inline double Histogram<Value>::Mean() const {
+ DCHECK_GT(sample_size_, 0ull);
+ return static_cast<double>(sum_) / static_cast<double>(sample_size_);
+}
+
+template <class Value> inline double Histogram<Value>::Variance() const {
+ DCHECK_GT(sample_size_, 0ull);
+ // Using algorithms for calculating variance over a population:
+ // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
+ Value sum_squared = sum_ * sum_;
+ double sum_squared_by_n_squared =
+ static_cast<double>(sum_squared) /
+ static_cast<double>(sample_size_ * sample_size_);
+ double sum_of_squares_by_n =
+ static_cast<double>(sum_of_squares_) / static_cast<double>(sample_size_);
+ return sum_of_squares_by_n - sum_squared_by_n_squared;
+}
+
+template <class Value>
+inline void Histogram<Value>::PrintBins(std::ostream &os) {
+ DCHECK_GT(sample_size_, 0ull);
+ DCHECK(new_values_added_);
+ size_t bin_idx = 0;
+ while (bin_idx < cumulative_freq_.size()) {
+ if (bin_idx > 0 &&
+ cumulative_perc_[bin_idx] == cumulative_perc_[bin_idx - 1]) {
+ bin_idx++;
+ continue;
+ }
+ os << ranges_[bin_idx] << ": " << cumulative_freq_[bin_idx] << "\t"
+ << cumulative_perc_[bin_idx] * 100.0 << "%\n";
+ bin_idx++;
+ }
+}
+
+template <class Value>
+inline void Histogram<Value>::PrintConfidenceIntervals(std::ostream &os,
+ double interval) const {
+ DCHECK_GT(interval, 0);
+ DCHECK_LT(interval, 1.0);
+
+ double per_0 = (1.0 - interval) / 2.0;
+ double per_1 = per_0 + interval;
+ os << Name() << ":\t";
+ TimeUnit unit = GetAppropriateTimeUnit(Mean() * kAdjust);
+ os << interval << "% C.I. "
+ << FormatDuration(Percentile(per_0) * kAdjust, unit);
+ os << "-" << FormatDuration(Percentile(per_1) * kAdjust, unit) << " ";
+ os << "Avg: " << FormatDuration(Mean() * kAdjust, unit) << " Max: ";
+ os << FormatDuration(Max() * kAdjust, unit) << "\n";
+}
+
+template <class Value> inline void Histogram<Value>::BuildCDF() {
+ DCHECK_EQ(cumulative_freq_.size(), 0ull);
+ DCHECK_EQ(cumulative_perc_.size(), 0ull);
+ uint64_t accumulated = 0;
+
+ cumulative_freq_.push_back(accumulated);
+ cumulative_perc_.push_back(0.0);
+ for (size_t idx = 0; idx < frequency_.size(); idx++) {
+ accumulated += frequency_[idx];
+ cumulative_freq_.push_back(accumulated);
+ cumulative_perc_.push_back(static_cast<double>(accumulated) /
+ static_cast<double>(sample_size_));
+ }
+ DCHECK_EQ(*(cumulative_freq_.end() - 1), sample_size_);
+ DCHECK_EQ(*(cumulative_perc_.end() - 1), 1.0);
+}
+
+template <class Value> inline void Histogram<Value>::CreateHistogram() {
+ DCHECK_GT(sample_size_, 0ull);
+
+ // Create a histogram only if new values are added.
+ if (!new_values_added_)
+ return;
+
+ // Reset cumulative values in case this is not the first time creating histogram.
+ cumulative_freq_.clear();
+ cumulative_perc_.clear();
+ BuildCDF();
+ new_values_added_ = false;
+}
+;
+
+template <class Value>
+inline double Histogram<Value>::Percentile(double per) const {
+ DCHECK_GT(cumulative_perc_.size(), 0ull);
+ size_t idx;
+ for (idx = 0; idx < cumulative_perc_.size(); idx++) {
+ if (per <= cumulative_perc_[idx + 1])
+ break;
+ }
+ double lower_value = static_cast<double>(ranges_[idx]);
+ double upper_value = static_cast<double>(ranges_[idx + 1]);
+ double lower_perc = cumulative_perc_[idx];
+ double upper_perc = cumulative_perc_[idx + 1];
+ if (per == lower_perc) {
+ return lower_value;
+ }
+ if (per == upper_perc) {
+ return upper_value;
+ }
+ DCHECK_GT(upper_perc, lower_perc);
+ double value = lower_value + (upper_value - lower_value) *
+ (per - lower_perc) / (upper_perc - lower_perc);
+
+ return value;
+}
+
+} // namespace art
+#endif // SRC_BASE_HISTOGRAM_INL_H_
+
diff --git a/src/base/histogram.h b/src/base/histogram.h
new file mode 100644
index 0000000000..6878e71ccc
--- /dev/null
+++ b/src/base/histogram.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2013 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_SRC_BASE_HISTOGRAM_H_
+#define ART_SRC_BASE_HISTOGRAM_H_
+
+#include <vector>
+#include <string>
+
+#include "base/logging.h"
+#include "utils.h"
+
+namespace art {
+
+// Creates a data histogram for a better understanding of statistical data.
+// Histogram analysis goes beyond simple mean and standard deviation to provide
+// percentiles values, describing where the $% of the input data lies.
+// Designed to be simple and used with timing logger in art.
+
+template <class Value> class Histogram {
+
+ const double kAdjust;
+ const Value kBucketWidth;
+ const size_t kInitialBucketCount;
+
+ public:
+ Histogram(std::string);
+ void AddValue(Value);
+ void CreateHistogram();
+ void Reset();
+ double Mean() const;
+ double Variance() const;
+ double Percentile(double) const;
+ void PrintConfidenceIntervals(std::ostream &, double) const;
+ void PrintBins(std::ostream &);
+
+ uint64_t SampleSize() const {
+ return sample_size_;
+ }
+
+ Value Sum() const {
+ return sum_;
+ }
+
+ Value Min() const {
+ return min_value_added_;
+ }
+
+ Value Max() const {
+ return max_value_added_;
+ }
+
+ const std::string &Name() const {
+ return name_;
+ }
+
+
+ private:
+ void BuildRanges();
+ void Initialize();
+ size_t FindBucket(Value);
+ void BucketiseValue(Value);
+ // Builds the cumulative distribution function from the frequency data.
+ // Must be called before using the percentile function.
+ void BuildCDF();
+ // Add more buckets to the histogram to fill in a new value that exceeded
+ // the max_read_value_.
+ void GrowBuckets(Value);
+ bool new_values_added_;
+ std::string name_;
+ // Number of samples placed in histogram.
+ uint64_t sample_size_;
+ // Width of the bucket range. The lower the value is the more accurate
+ // histogram percentiles are.
+ Value bucket_width_;
+ // Number of bucket to have in the histogram. this value will increase
+ // to accommodate for big values that don't fit in initial bucket ranges.
+ size_t bucket_count_;
+ // Represents the ranges of the histograms. Has SampleSize() + 1 elements
+ // e.g. 0,5,10,15 represents ranges 0-5, 5-10, 10-15
+ std::vector<Value> ranges_;
+ // How many occurrences of values fall within a corresponding range that is
+ // saved in the ranges_ vector.
+ std::vector<uint64_t> frequency_;
+ // Accumulative summation of frequencies.
+ // cumulative_freq_[i] = sum(cumulative_freq_[j] : 0 < j < i )
+ std::vector<uint64_t> cumulative_freq_;
+ // Accumulative summation of percentiles; which is the frequency / SampleSize
+ // cumulative_freq_[i] = sum(cumulative_freq_[j] : 0 < j < i )
+ std::vector<double> cumulative_perc_;
+ // Summation of all the elements inputed by the user.
+ Value sum_;
+ // Maximum value that can fit in the histogram, grows adaptively.
+ Value min_;
+ // Minimum value that can fit in the histogram. Fixed to zero for now.
+ Value max_;
+ // Summation of the values entered. Used to calculate variance.
+ Value sum_of_squares_;
+ // Maximum value entered in the histogram.
+ Value min_value_added_;
+ // Minimum value entered in the histogram.
+ Value max_value_added_;
+
+ DISALLOW_COPY_AND_ASSIGN(Histogram);
+};
+}
+
+#endif // ART_SRC_BASE_HISTOGRAM_H_
diff --git a/src/base/histogram_test.cc b/src/base/histogram_test.cc
new file mode 100644
index 0000000000..2adb41b55a
--- /dev/null
+++ b/src/base/histogram_test.cc
@@ -0,0 +1,252 @@
+#include "gtest/gtest.h"
+#include "histogram-inl.h"
+#include <sstream>
+using namespace art;
+
+//Simple usage:
+// Histogram *hist = new Histogram("SimplePercentiles");
+// Percentile PerValue
+// hist->AddValue(121);
+// hist->AddValue(132);
+// hist->AddValue(140);
+// hist->AddValue(145);
+// hist->AddValue(155);
+// hist->CreateHistogram();
+// PerValue = hist->PercentileVal(0.50); finds the 50th percentile(median).
+
+TEST(Histtest, MeanTest) {
+
+ Histogram<uint64_t> *hist = new Histogram<uint64_t>("MeanTest");
+ double mean;
+ for (size_t Idx = 0; Idx < 90; Idx++) {
+ hist->AddValue(static_cast<uint64_t>(50));
+ }
+ mean = hist->Mean();
+ EXPECT_EQ(mean, 50);
+ hist->Reset();
+ hist->AddValue(9);
+ hist->AddValue(17);
+ hist->AddValue(28);
+ hist->AddValue(28);
+ mean = hist->Mean();
+ EXPECT_EQ(mean, 20.5);
+}
+;
+
+TEST(Histtest, VarianceTest) {
+
+ Histogram<uint64_t> *hist = new Histogram<uint64_t>("VarianceTest");
+ double variance;
+ hist->AddValue(9);
+ hist->AddValue(17);
+ hist->AddValue(28);
+ hist->AddValue(28);
+ hist->CreateHistogram();
+ variance = hist->Variance();
+ EXPECT_EQ(variance, 64.25);
+ delete hist;
+}
+;
+
+TEST(Histtest, Percentile) {
+
+ Histogram<uint64_t> *hist = new Histogram<uint64_t>("Percentile");
+ double PerValue;
+
+ hist->AddValue(20);
+ hist->AddValue(31);
+ hist->AddValue(42);
+ hist->AddValue(50);
+ hist->AddValue(60);
+ hist->AddValue(70);
+ hist->AddValue(98);
+ hist->AddValue(110);
+ hist->AddValue(121);
+ hist->AddValue(132);
+ hist->AddValue(140);
+ hist->AddValue(145);
+ hist->AddValue(155);
+
+ hist->CreateHistogram();
+ PerValue = hist->Percentile(0.50);
+ EXPECT_GE(PerValue, 70);
+ EXPECT_LE(PerValue, 110);
+
+ delete hist;
+}
+;
+
+TEST(Histtest, UpdateRange) {
+
+ Histogram<uint64_t> *hist = new Histogram<uint64_t>("UpdateRange");
+ double PerValue;
+
+ hist->AddValue(15);
+ hist->AddValue(17);
+ hist->AddValue(35);
+ hist->AddValue(50);
+ hist->AddValue(68);
+ hist->AddValue(75);
+ hist->AddValue(93);
+ hist->AddValue(110);
+ hist->AddValue(121);
+ hist->AddValue(132);
+ hist->AddValue(140); //Median value
+ hist->AddValue(145);
+ hist->AddValue(155);
+ hist->AddValue(163);
+ hist->AddValue(168);
+ hist->AddValue(175);
+ hist->AddValue(182);
+ hist->AddValue(193);
+ hist->AddValue(200);
+ hist->AddValue(205);
+ hist->AddValue(212);
+ hist->CreateHistogram();
+ PerValue = hist->Percentile(0.50);
+
+ std::string text;
+ std::stringstream stream;
+ std::string expected =
+ "UpdateRange:\t0.99% C.I. 15.262us-214.475us Avg: 126.380us Max: 212us\n";
+ hist->PrintConfidenceIntervals(stream, 0.99);
+
+ EXPECT_EQ(expected, stream.str());
+ EXPECT_GE(PerValue, 132);
+ EXPECT_LE(PerValue, 145);
+
+ delete hist;
+}
+;
+
+TEST(Histtest, Reset) {
+
+ Histogram<uint64_t> *hist = new Histogram<uint64_t>("Reset");
+ double PerValue;
+ hist->AddValue(0);
+ hist->AddValue(189);
+ hist->AddValue(389);
+ hist->Reset();
+ hist->AddValue(15);
+ hist->AddValue(17);
+ hist->AddValue(35);
+ hist->AddValue(50);
+ hist->AddValue(68);
+ hist->AddValue(75);
+ hist->AddValue(93);
+ hist->AddValue(110);
+ hist->AddValue(121);
+ hist->AddValue(132);
+ hist->AddValue(140); //Median value
+ hist->AddValue(145);
+ hist->AddValue(155);
+ hist->AddValue(163);
+ hist->AddValue(168);
+ hist->AddValue(175);
+ hist->AddValue(182);
+ hist->AddValue(193);
+ hist->AddValue(200);
+ hist->AddValue(205);
+ hist->AddValue(212);
+ hist->CreateHistogram();
+ PerValue = hist->Percentile(0.50);
+
+ std::string text;
+ std::stringstream stream;
+ std::string expected =
+ "Reset:\t0.99% C.I. 15.262us-214.475us Avg: 126.380us Max: 212us\n";
+ hist->PrintConfidenceIntervals(stream, 0.99);
+
+ EXPECT_EQ(expected, stream.str());
+ EXPECT_GE(PerValue, 132);
+ EXPECT_LE(PerValue, 145);
+
+ delete hist;
+}
+;
+
+TEST(Histtest, MultipleCreateHist) {
+
+ Histogram<uint64_t> *hist = new Histogram<uint64_t>("MultipleCreateHist");
+ double PerValue;
+ hist->AddValue(15);
+ hist->AddValue(17);
+ hist->AddValue(35);
+ hist->AddValue(50);
+ hist->AddValue(68);
+ hist->AddValue(75);
+ hist->AddValue(93);
+ hist->CreateHistogram();
+ hist->AddValue(110);
+ hist->AddValue(121);
+ hist->AddValue(132);
+ hist->AddValue(140); //Median value
+ hist->AddValue(145);
+ hist->AddValue(155);
+ hist->AddValue(163);
+ hist->AddValue(168);
+ hist->CreateHistogram();
+ hist->AddValue(175);
+ hist->AddValue(182);
+ hist->AddValue(193);
+ hist->AddValue(200);
+ hist->AddValue(205);
+ hist->AddValue(212);
+ hist->CreateHistogram();
+ PerValue = hist->Percentile(0.50);
+
+ std::string text;
+ std::stringstream stream;
+ std::string expected =
+ "MultipleCreateHist:\t0.99% C.I. 15.262us-214.475us Avg: 126.380us Max: 212us\n";
+ hist->PrintConfidenceIntervals(stream, 0.99);
+
+ EXPECT_EQ(expected, stream.str());
+ EXPECT_GE(PerValue, 132);
+ EXPECT_LE(PerValue, 145);
+
+ delete hist;
+}
+;
+
+TEST(Histtest, SingleValue) {
+
+ Histogram<uint64_t> *hist = new Histogram<uint64_t>("SingleValue");
+ double PerValue_10;
+ double PerValue_90;
+
+ hist->AddValue(1);
+ hist->CreateHistogram();
+ PerValue_10 = hist->Percentile(0.1);
+ PerValue_90 = hist->Percentile(0.9);
+
+ EXPECT_GT(PerValue_10, 0);
+ EXPECT_LT(PerValue_90, 5);
+
+ delete hist;
+}
+;
+
+TEST(Histtest, SpikyValues) {
+
+ Histogram<uint64_t> *hist = new Histogram<uint64_t>("SpikyValues");
+ double PerValue_005;
+ double PerValue_995;
+
+ for (size_t Idx = 0; Idx < 300; Idx++) {
+ hist->AddValue(rand() % 200);
+ }
+
+ hist->AddValue(10000);
+ hist->CreateHistogram();
+ PerValue_005 = hist->Percentile(0.005);
+ PerValue_995 = hist->Percentile(0.995);
+
+ EXPECT_EQ(1.075, PerValue_005);
+ EXPECT_EQ(199747, static_cast<int>(PerValue_995 * 1000));
+ delete hist;
+}
+;
+
+
+
diff --git a/src/base/timing_logger.cc b/src/base/timing_logger.cc
new file mode 100644
index 0000000000..d2c7eef6d4
--- /dev/null
+++ b/src/base/timing_logger.cc
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "timing_logger.h"
+
+#include "base/logging.h"
+#include "thread.h"
+#include "base/stl_util.h"
+#include "base/histogram-inl.h"
+
+#include <cmath>
+#include <iomanip>
+
+namespace art {
+
+void TimingLogger::Reset() {
+ times_.clear();
+ labels_.clear();
+ AddSplit("");
+}
+
+TimingLogger::TimingLogger(const std::string &name, bool precise)
+ : name_(name),
+ precise_(precise) {
+ AddSplit("");
+}
+
+void TimingLogger::AddSplit(const std::string &label) {
+ times_.push_back(NanoTime());
+ labels_.push_back(label);
+}
+
+uint64_t TimingLogger::GetTotalNs() const {
+ return times_.back() - times_.front();
+}
+;
+
+void TimingLogger::Dump(std::ostream &os) const {
+ uint64_t largest_time = 0;
+ os << name_ << ": begin\n";
+ for (size_t i = 1; i < times_.size(); ++i) {
+ uint64_t delta_time = times_[i] - times_[i - 1];
+ largest_time = std::max(largest_time, delta_time);
+ }
+ // Compute which type of unit we will use for printing the timings.
+ TimeUnit tu = GetAppropriateTimeUnit(largest_time);
+ uint64_t divisor = GetNsToTimeUnitDivisor(tu);
+ for (size_t i = 1; i < times_.size(); ++i) {
+ uint64_t delta_time = times_[i] - times_[i - 1];
+ if (!precise_ && divisor >= 1000) {
+ // Make the fraction 0.
+ delta_time -= delta_time % (divisor / 1000);
+ }
+ os << name_ << ": " << std::setw(8) << FormatDuration(delta_time, tu) << " "
+ << labels_[i] << "\n";
+ }
+ os << name_ << ": end, " << NsToMs(GetTotalNs()) << " ms\n";
+}
+
+CumulativeLogger::CumulativeLogger(const std::string &name)
+ : name_(name),
+ lock_(("CumulativeLoggerLock" + name).c_str(), kDefaultMutexLevel, true) {
+ Reset();
+}
+
+CumulativeLogger::~CumulativeLogger() { STLDeleteElements(&histograms_); }
+
+void CumulativeLogger::SetName(const std::string &name) { name_ = name; }
+
+void CumulativeLogger::Start() {
+ MutexLock mu(Thread::Current(), lock_);
+ index_ = 0;
+}
+
+void CumulativeLogger::End() {
+ MutexLock mu(Thread::Current(), lock_);
+ iterations_++;
+}
+void CumulativeLogger::Reset() {
+ MutexLock mu(Thread::Current(), lock_);
+ iterations_ = 0;
+ STLDeleteElements(&histograms_);
+}
+
+uint64_t CumulativeLogger::GetTotalNs() const {
+ return GetTotalTime() * kAdjust;
+}
+
+uint64_t CumulativeLogger::GetTotalTime() const {
+ MutexLock mu(Thread::Current(), lock_);
+ uint64_t total = 0;
+ for (size_t i = 0; i < histograms_.size(); ++i) {
+ total += histograms_[i]->Sum();
+ }
+ return total;
+}
+
+void CumulativeLogger::AddLogger(const TimingLogger &logger) {
+ MutexLock mu(Thread::Current(), lock_);
+ DCHECK_EQ(logger.times_.size(), logger.labels_.size());
+ for (size_t i = 1; i < logger.times_.size(); ++i) {
+ const uint64_t delta_time = logger.times_[i] - logger.times_[i - 1];
+ const std::string &label = logger.labels_[i];
+ AddPair(label, delta_time);
+ }
+}
+
+void CumulativeLogger::Dump(std::ostream &os) {
+ MutexLock mu(Thread::Current(), lock_);
+ DumpHistogram(os);
+}
+
+void CumulativeLogger::AddPair(const std::string &label, uint64_t delta_time) {
+
+ // Convert delta time to microseconds so that we don't overflow our counters.
+ delta_time /= kAdjust;
+ if (index_ >= histograms_.size()) {
+ Histogram<uint64_t> *tmp_hist = new Histogram<uint64_t>(label);
+ tmp_hist->AddValue(delta_time);
+ histograms_.push_back(tmp_hist);
+ } else {
+ histograms_[index_]->AddValue(delta_time);
+ DCHECK_EQ(label, histograms_[index_]->Name());
+ }
+ index_++;
+}
+
+void CumulativeLogger::DumpHistogram(std::ostream &os) {
+ os << "Start Dumping histograms for " << iterations_ << " iterations"
+ << " for " << name_ << "\n";
+ for (size_t Idx = 0; Idx < histograms_.size(); Idx++) {
+ Histogram<uint64_t> &hist = *(histograms_[Idx]);
+ hist.CreateHistogram();
+ hist.PrintConfidenceIntervals(os, 0.99);
+ }
+ os << "Done Dumping histograms \n";
+}
+
+} // namespace art
diff --git a/src/base/timing_logger.h b/src/base/timing_logger.h
new file mode 100644
index 0000000000..d3f7ef410c
--- /dev/null
+++ b/src/base/timing_logger.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2011 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_SRC_TIMING_LOGGER_H_
+#define ART_SRC_TIMING_LOGGER_H_
+
+#include "base/histogram.h"
+#include "base/macros.h"
+#include "base/mutex.h"
+
+#include <string>
+#include <vector>
+
+namespace art {
+
+class CumulativeLogger;
+
+class TimingLogger {
+ public:
+ explicit TimingLogger(const std::string &name, bool precise);
+ void AddSplit(const std::string &label);
+ void Dump(std::ostream &os) const;
+ void Reset();
+ uint64_t GetTotalNs() const;
+
+ protected:
+ std::string name_;
+ bool precise_;
+ std::vector<uint64_t> times_;
+ std::vector<std::string> labels_;
+
+ friend class CumulativeLogger;
+};
+
+class CumulativeLogger {
+
+ public:
+
+ explicit CumulativeLogger(const std::string &name);
+ void prepare_stats();
+ ~CumulativeLogger();
+ void Start();
+ void End();
+ void Reset();
+ void Dump(std::ostream &os) LOCKS_EXCLUDED(lock_);
+ uint64_t GetTotalNs() const;
+ void SetName(const std::string &name);
+ void AddLogger(const TimingLogger &logger) LOCKS_EXCLUDED(lock_);
+
+ private:
+
+ void AddPair(const std::string &label, uint64_t delta_time)
+ EXCLUSIVE_LOCKS_REQUIRED(lock_);
+ void DumpHistogram(std::ostream &os) EXCLUSIVE_LOCKS_REQUIRED(lock_);
+ uint64_t GetTotalTime() const;
+ static const uint64_t kAdjust = 1000;
+ std::vector<Histogram<uint64_t> *> histograms_ GUARDED_BY(lock_);
+ std::string name_;
+ mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+ size_t index_ GUARDED_BY(lock_);
+ size_t iterations_ GUARDED_BY(lock_);
+
+ DISALLOW_COPY_AND_ASSIGN(CumulativeLogger);
+};
+
+} // namespace art
+
+#endif // ART_SRC_TIMING_LOGGER_H_
diff --git a/src/class_linker.cc b/src/class_linker.cc
index ad51b5e377..0e267913e2 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1250,7 +1250,7 @@ static mirror::Class* EnsureResolved(Thread* self, mirror::Class* klass)
}
// Wait for the pending initialization to complete.
while (!klass->IsResolved() && !klass->IsErroneous()) {
- lock.Wait();
+ lock.WaitIgnoringInterrupts();
}
}
if (klass->IsErroneous()) {
@@ -2740,7 +2740,7 @@ bool ClassLinker::WaitForInitializeClass(mirror::Class* klass, Thread* self, Obj
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
while (true) {
self->AssertNoPendingException();
- lock.Wait();
+ lock.WaitIgnoringInterrupts();
// When we wake up, repeat the test for init-in-progress. If
// there's an exception pending (only possible if
@@ -2873,7 +2873,8 @@ bool ClassLinker::InitializeSuperClass(mirror::Class* klass, bool can_run_clinit
if (!super_class->IsInitialized()) {
CHECK(!super_class->IsInterface());
// Must hold lock on object when initializing and setting status.
- ObjectLock lock(Thread::Current(), klass);
+ Thread* self = Thread::Current();
+ ObjectLock lock(self, klass);
bool super_initialized = InitializeClass(super_class, can_run_clinit, can_init_fields);
// TODO: check for a pending exception
if (!super_initialized) {
@@ -2884,7 +2885,7 @@ bool ClassLinker::InitializeSuperClass(mirror::Class* klass, bool can_run_clinit
return false;
}
klass->SetStatus(mirror::Class::kStatusError);
- klass->NotifyAll();
+ klass->NotifyAll(self);
return false;
}
}
diff --git a/src/compiler.cc b/src/compiler.cc
index 48aa335758..580da60a40 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -22,6 +22,7 @@
#include <unistd.h>
#include "base/stl_util.h"
+#include "base/timing_logger.h"
#include "class_linker.h"
#include "jni_internal.h"
#include "oat_compilation_unit.h"
@@ -43,7 +44,6 @@
#include "ScopedLocalRef.h"
#include "thread.h"
#include "thread_pool.h"
-#include "timing_logger.h"
#include "verifier/method_verifier.h"
#if defined(__APPLE__)
@@ -489,14 +489,14 @@ void Compiler::CompileAll(jobject class_loader,
DCHECK(!Runtime::Current()->IsStarted());
UniquePtr<ThreadPool> thread_pool(new ThreadPool(thread_count_));
- TimingLogger timings("compiler");
+ TimingLogger timings("compiler", false);
PreCompile(class_loader, dex_files, *thread_pool.get(), timings);
Compile(class_loader, dex_files, *thread_pool.get(), timings);
if (dump_timings_ && timings.GetTotalNs() > MsToNs(1000)) {
- timings.Dump();
+ LOG(INFO) << Dumpable<TimingLogger>(timings);
}
if (dump_stats_) {
@@ -527,7 +527,7 @@ void Compiler::CompileOne(const mirror::AbstractMethod* method) {
dex_files.push_back(dex_file);
UniquePtr<ThreadPool> thread_pool(new ThreadPool(1U));
- TimingLogger timings("CompileOne");
+ TimingLogger timings("CompileOne", false);
PreCompile(class_loader, dex_files, *thread_pool.get(), timings);
uint32_t method_idx = method->GetDexMethodIndex();
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index bc38bdcfc9..d0bd2fcae4 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -25,6 +25,7 @@
#include "base/stl_util.h"
#include "base/stringpiece.h"
+#include "base/timing_logger.h"
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
#include "compiler.h"
@@ -42,7 +43,6 @@
#include "ScopedLocalRef.h"
#include "scoped_thread_state_change.h"
#include "sirt_ref.h"
-#include "timing_logger.h"
#include "vector_output_stream.h"
#include "well_known_classes.h"
#include "zip_archive.h"
diff --git a/src/gc/mark_sweep.cc b/src/gc/mark_sweep.cc
index 81d5e170a2..6fcaf83ce4 100644
--- a/src/gc/mark_sweep.cc
+++ b/src/gc/mark_sweep.cc
@@ -21,10 +21,10 @@
#include <climits>
#include <vector>
-#include "barrier.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/mutex-inl.h"
+#include "base/timing_logger.h"
#include "card_table.h"
#include "card_table-inl.h"
#include "heap.h"
@@ -45,7 +45,6 @@
#include "runtime.h"
#include "space.h"
#include "space_bitmap-inl.h"
-#include "timing_logger.h"
#include "thread.h"
#include "thread_list.h"
#include "verifier/method_verifier.h"
@@ -139,7 +138,7 @@ MarkSweep::MarkSweep(Heap* heap, bool is_concurrent)
large_object_lock_("large object lock"),
mark_stack_expand_lock_("mark stack expand lock"),
timings_(GetName(), true),
- cumulative_timings_(GetName(), true),
+ cumulative_timings_(GetName()),
is_concurrent_(is_concurrent) {
cumulative_timings_.SetName(GetName());
ResetCumulativeStatistics();
@@ -829,18 +828,6 @@ class CheckpointMarkThreadRoots : public Closure {
MarkSweep* mark_sweep_;
};
-Barrier& MarkSweep::GetBarrier() {
- return *gc_barrier_;
-}
-
-const TimingLogger& MarkSweep::GetTimings() const {
- return timings_;
-}
-
-const CumulativeLogger& MarkSweep::GetCumulativeTimings() const {
- return cumulative_timings_;
-}
-
void MarkSweep::ResetCumulativeStatistics() {
cumulative_timings_.Reset();
total_time_ = 0;
diff --git a/src/gc/mark_sweep.h b/src/gc/mark_sweep.h
index 0d43bee795..dc722a0fe9 100644
--- a/src/gc/mark_sweep.h
+++ b/src/gc/mark_sweep.h
@@ -18,13 +18,14 @@
#define ART_SRC_GC_MARK_SWEEP_H_
#include "atomic_integer.h"
+#include "barrier.h"
#include "base/macros.h"
#include "base/mutex.h"
+#include "base/timing_logger.h"
#include "garbage_collector.h"
#include "gc_type.h"
#include "offsets.h"
#include "root_visitor.h"
-#include "timing_logger.h"
#include "UniquePtr.h"
namespace art {
@@ -34,7 +35,6 @@ class Object;
template<class T> class ObjectArray;
}
template <typename T> class AtomicStack;
-class Barrier;
class CheckObjectVisitor;
class ContinuousSpace;
class Heap;
@@ -233,9 +233,18 @@ class MarkSweep : public GarbageCollector {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
- Barrier& GetBarrier();
- const TimingLogger& GetTimings() const;
- const CumulativeLogger& GetCumulativeTimings() const;
+ Barrier& GetBarrier() {
+ return *gc_barrier_;
+ }
+
+ TimingLogger& GetTimings() {
+ return timings_;
+ }
+
+ CumulativeLogger& GetCumulativeTimings() {
+ return cumulative_timings_;
+ }
+
void ResetCumulativeStatistics();
protected:
diff --git a/src/heap.cc b/src/heap.cc
index e531dc8010..f7abe0a210 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -51,7 +51,6 @@
#include "scoped_thread_state_change.h"
#include "sirt_ref.h"
#include "thread_list.h"
-#include "timing_logger.h"
#include "UniquePtr.h"
#include "well_known_classes.h"
@@ -377,11 +376,11 @@ void Heap::DumpGcPerformanceInfo() {
// TODO: C++0x
uint64_t total_paused_time = 0;
for (Collectors::const_iterator it = mark_sweep_collectors_.begin();
- it != mark_sweep_collectors_.end(); ++it) {
+ it != mark_sweep_collectors_.end(); ++it) {
MarkSweep* collector = *it;
- const CumulativeLogger& logger = collector->GetCumulativeTimings();
+ CumulativeLogger& logger = collector->GetCumulativeTimings();
if (logger.GetTotalNs() != 0) {
- logger.Dump();
+ LOG(INFO) << Dumpable<CumulativeLogger>(logger);
const uint64_t total_ns = logger.GetTotalNs();
const uint64_t total_pause_ns = (*it)->GetTotalPausedTime();
double seconds = NsToMs(logger.GetTotalNs()) / 1000.0;
@@ -1155,12 +1154,12 @@ GcType Heap::CollectGarbageInternal(GcType gc_type, GcCause gc_cause, bool clear
<< ((i != pauses.size() - 1) ? ", " : "");
}
LOG(INFO) << gc_cause << " " << collector->GetName()
- << "GC freed " << PrettySize(collector->GetFreedBytes()) << ", "
- << percent_free << "% free, " << PrettySize(current_heap_size) << "/"
- << PrettySize(total_memory) << ", " << "paused " << pause_string.str()
- << " total " << PrettyDuration((duration / 1000) * 1000);
+ << "GC freed " << PrettySize(collector->GetFreedBytes()) << ", "
+ << percent_free << "% free, " << PrettySize(current_heap_size) << "/"
+ << PrettySize(total_memory) << ", " << "paused " << pause_string.str()
+ << " total " << PrettyDuration((duration / 1000) * 1000);
if (VLOG_IS_ON(heap)) {
- collector->GetTimings().Dump();
+ LOG(INFO) << Dumpable<TimingLogger>(collector->GetTimings());
}
}
diff --git a/src/heap.h b/src/heap.h
index 9981f835c8..7af15cdd1b 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -22,6 +22,7 @@
#include <vector>
#include "atomic_integer.h"
+#include "base/timing_logger.h"
#include "gc/atomic_stack.h"
#include "gc/card_table.h"
#include "gc/gc_type.h"
@@ -31,7 +32,6 @@
#include "locks.h"
#include "offsets.h"
#include "safe_map.h"
-#include "timing_logger.h"
#include "thread_pool.h"
#define VERIFY_OBJECT_ENABLED 0
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index bd63c30fb4..195549a3a0 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -163,7 +163,7 @@ static void UnstartedRuntimeJni(Thread* self, AbstractMethod* method,
} else if (name == "java.lang.Object java.lang.Object.internalClone()") {
result->SetL(receiver->Clone(self));
} else if (name == "void java.lang.Object.notifyAll()") {
- receiver->NotifyAll();
+ receiver->NotifyAll(self);
} else if (name == "int java.lang.String.compareTo(java.lang.String)") {
String* rhs = args[0].GetL()->AsString();
CHECK(rhs != NULL);
diff --git a/src/mirror/object-inl.h b/src/mirror/object-inl.h
index 723192dc8a..b6c8008b1f 100644
--- a/src/mirror/object-inl.h
+++ b/src/mirror/object-inl.h
@@ -24,7 +24,9 @@
#include "array.h"
#include "field.h"
#include "class.h"
+#include "monitor.h"
#include "runtime.h"
+#include "throwable.h"
namespace art {
namespace mirror {
@@ -41,6 +43,34 @@ inline void Object::SetClass(Class* new_klass) {
SetFieldPtr(OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass, false, false);
}
+inline uint32_t Object::GetThinLockId() {
+ return Monitor::GetThinLockId(monitor_);
+}
+
+inline void Object::MonitorEnter(Thread* self) {
+ Monitor::MonitorEnter(self, this);
+}
+
+inline bool Object::MonitorExit(Thread* self) {
+ return Monitor::MonitorExit(self, this);
+}
+
+inline void Object::Notify(Thread* self) {
+ Monitor::Notify(self, this);
+}
+
+inline void Object::NotifyAll(Thread* self) {
+ Monitor::NotifyAll(self, this);
+}
+
+inline void Object::Wait(Thread* self) {
+ Monitor::Wait(self, this, 0, 0, true, kWaiting);
+}
+
+inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) {
+ Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
+}
+
inline bool Object::InstanceOf(const Class* klass) const {
DCHECK(klass != NULL);
DCHECK(GetClass() != NULL);
@@ -114,6 +144,64 @@ inline bool Object::IsReferenceInstance() const {
return GetClass()->IsReferenceClass();
}
+inline Array* Object::AsArray() {
+ DCHECK(IsArrayInstance());
+ return down_cast<Array*>(this);
+}
+
+inline const Array* Object::AsArray() const {
+ DCHECK(IsArrayInstance());
+ return down_cast<const Array*>(this);
+}
+
+inline BooleanArray* Object::AsBooleanArray() {
+ DCHECK(GetClass()->IsArrayClass());
+ DCHECK(GetClass()->GetComponentType()->IsPrimitiveBoolean());
+ return down_cast<BooleanArray*>(this);
+}
+
+inline ByteArray* Object::AsByteArray() {
+ DCHECK(GetClass()->IsArrayClass());
+ DCHECK(GetClass()->GetComponentType()->IsPrimitiveByte());
+ return down_cast<ByteArray*>(this);
+}
+
+inline CharArray* Object::AsCharArray() {
+ DCHECK(GetClass()->IsArrayClass());
+ DCHECK(GetClass()->GetComponentType()->IsPrimitiveChar());
+ return down_cast<CharArray*>(this);
+}
+
+inline ShortArray* Object::AsShortArray() {
+ DCHECK(GetClass()->IsArrayClass());
+ DCHECK(GetClass()->GetComponentType()->IsPrimitiveShort());
+ return down_cast<ShortArray*>(this);
+}
+
+inline IntArray* Object::AsIntArray() {
+ DCHECK(GetClass()->IsArrayClass());
+ DCHECK(GetClass()->GetComponentType()->IsPrimitiveInt() ||
+ GetClass()->GetComponentType()->IsPrimitiveFloat());
+ return down_cast<IntArray*>(this);
+}
+
+inline LongArray* Object::AsLongArray() {
+ DCHECK(GetClass()->IsArrayClass());
+ DCHECK(GetClass()->GetComponentType()->IsPrimitiveLong() ||
+ GetClass()->GetComponentType()->IsPrimitiveDouble());
+ return down_cast<LongArray*>(this);
+}
+
+inline String* Object::AsString() {
+ DCHECK(GetClass()->IsStringClass());
+ return down_cast<String*>(this);
+}
+
+inline Throwable* Object::AsThrowable() {
+ DCHECK(GetClass()->IsThrowableClass());
+ return down_cast<Throwable*>(this);
+}
+
inline bool Object::IsWeakReferenceInstance() const {
return GetClass()->IsWeakReferenceClass();
}
diff --git a/src/mirror/object.cc b/src/mirror/object.cc
index 27a42d3334..5c65b83593 100644
--- a/src/mirror/object.cc
+++ b/src/mirror/object.cc
@@ -35,64 +35,6 @@
namespace art {
namespace mirror {
-Array* Object::AsArray() {
- DCHECK(IsArrayInstance());
- return down_cast<Array*>(this);
-}
-
-const Array* Object::AsArray() const {
- DCHECK(IsArrayInstance());
- return down_cast<const Array*>(this);
-}
-
-BooleanArray* Object::AsBooleanArray() {
- DCHECK(GetClass()->IsArrayClass());
- DCHECK(GetClass()->GetComponentType()->IsPrimitiveBoolean());
- return down_cast<BooleanArray*>(this);
-}
-
-ByteArray* Object::AsByteArray() {
- DCHECK(GetClass()->IsArrayClass());
- DCHECK(GetClass()->GetComponentType()->IsPrimitiveByte());
- return down_cast<ByteArray*>(this);
-}
-
-CharArray* Object::AsCharArray() {
- DCHECK(GetClass()->IsArrayClass());
- DCHECK(GetClass()->GetComponentType()->IsPrimitiveChar());
- return down_cast<CharArray*>(this);
-}
-
-ShortArray* Object::AsShortArray() {
- DCHECK(GetClass()->IsArrayClass());
- DCHECK(GetClass()->GetComponentType()->IsPrimitiveShort());
- return down_cast<ShortArray*>(this);
-}
-
-IntArray* Object::AsIntArray() {
- DCHECK(GetClass()->IsArrayClass());
- DCHECK(GetClass()->GetComponentType()->IsPrimitiveInt() ||
- GetClass()->GetComponentType()->IsPrimitiveFloat());
- return down_cast<IntArray*>(this);
-}
-
-LongArray* Object::AsLongArray() {
- DCHECK(GetClass()->IsArrayClass());
- DCHECK(GetClass()->GetComponentType()->IsPrimitiveLong() ||
- GetClass()->GetComponentType()->IsPrimitiveDouble());
- return down_cast<LongArray*>(this);
-}
-
-String* Object::AsString() {
- DCHECK(GetClass()->IsStringClass());
- return down_cast<String*>(this);
-}
-
-Throwable* Object::AsThrowable() {
- DCHECK(GetClass()->IsThrowableClass());
- return down_cast<Throwable*>(this);
-}
-
Object* Object::Clone(Thread* self) {
Class* c = GetClass();
DCHECK(!c->IsClassClass());
@@ -138,34 +80,6 @@ Object* Object::Clone(Thread* self) {
return copy.get();
}
-uint32_t Object::GetThinLockId() {
- return Monitor::GetThinLockId(monitor_);
-}
-
-void Object::MonitorEnter(Thread* thread) {
- Monitor::MonitorEnter(thread, this);
-}
-
-bool Object::MonitorExit(Thread* thread) {
- return Monitor::MonitorExit(thread, this);
-}
-
-void Object::Notify() {
- Monitor::Notify(Thread::Current(), this);
-}
-
-void Object::NotifyAll() {
- Monitor::NotifyAll(Thread::Current(), this);
-}
-
-void Object::Wait() {
- Monitor::Wait(Thread::Current(), this, 0, 0, true, kWaiting);
-}
-
-void Object::Wait(int64_t ms, int32_t ns) {
- Monitor::Wait(Thread::Current(), this, ms, ns, true, kTimedWaiting);
-}
-
#if VERIFY_OBJECT_ENABLED
void Object::CheckFieldAssignment(MemberOffset field_offset, const Object* new_value) {
const Class* c = GetClass();
diff --git a/src/mirror/object.h b/src/mirror/object.h
index e2cedd860b..c404b61393 100644
--- a/src/mirror/object.h
+++ b/src/mirror/object.h
@@ -97,21 +97,19 @@ class MANAGED Object {
uint32_t GetThinLockId();
- void MonitorEnter(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ void MonitorEnter(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCK_FUNCTION(monitor_lock_);
- bool MonitorExit(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ bool MonitorExit(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
UNLOCK_FUNCTION(monitor_lock_);
- void Notify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void Notify(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void NotifyAll() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void NotifyAll(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void Wait() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void Wait(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void Wait(int64_t timeout) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- void Wait(int64_t timeout, int32_t nanos) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void Wait(Thread* self, int64_t timeout, int32_t nanos) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsClass() const;
diff --git a/src/monitor.cc b/src/monitor.cc
index aa4e5acefe..b4c3964bb4 100644
--- a/src/monitor.cc
+++ b/src/monitor.cc
@@ -23,7 +23,7 @@
#include "class_linker.h"
#include "dex_instruction.h"
#include "mirror/abstract_method-inl.h"
-#include "mirror/object.h"
+#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "object_utils.h"
#include "scoped_thread_state_change.h"
diff --git a/src/native/dalvik_system_DexFile.cc b/src/native/dalvik_system_DexFile.cc
index e549a8bf74..0390703914 100644
--- a/src/native/dalvik_system_DexFile.cc
+++ b/src/native/dalvik_system_DexFile.cc
@@ -23,6 +23,7 @@
#include "image.h"
#include "jni_internal.h"
#include "mirror/class_loader.h"
+#include "mirror/object-inl.h"
#include "mirror/string.h"
#include "oat.h"
#include "os.h"
diff --git a/src/native/dalvik_system_Zygote.cc b/src/native/dalvik_system_Zygote.cc
index 1c4c98637c..dcfe9d2015 100644
--- a/src/native/dalvik_system_Zygote.cc
+++ b/src/native/dalvik_system_Zygote.cc
@@ -403,14 +403,14 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
SetRLimits(env, javaRlimits);
- int rc = setgid(gid);
+ int rc = setresgid(gid, gid, gid);
if (rc == -1) {
- PLOG(FATAL) << "setgid(" << gid << ") failed";
+ PLOG(FATAL) << "setresgid(" << gid << ") failed";
}
- rc = setuid(uid);
+ rc = setresuid(uid, uid, uid);
if (rc == -1) {
- PLOG(FATAL) << "setuid(" << uid << ") failed";
+ PLOG(FATAL) << "setresuid(" << uid << ") failed";
}
#if defined(__linux__)
diff --git a/src/native/java_lang_Object.cc b/src/native/java_lang_Object.cc
index 75d5f70bef..5db7a330a8 100644
--- a/src/native/java_lang_Object.cc
+++ b/src/native/java_lang_Object.cc
@@ -15,7 +15,7 @@
*/
#include "jni_internal.h"
-#include "mirror/object.h"
+#include "mirror/object-inl.h"
#include "scoped_thread_state_change.h"
// TODO: better support for overloading.
@@ -34,25 +34,25 @@ static jobject Object_internalClone(JNIEnv* env, jobject java_this) {
static void Object_notify(JNIEnv* env, jobject java_this) {
ScopedObjectAccess soa(env);
mirror::Object* o = soa.Decode<mirror::Object*>(java_this);
- o->Notify();
+ o->Notify(soa.Self());
}
static void Object_notifyAll(JNIEnv* env, jobject java_this) {
ScopedObjectAccess soa(env);
mirror::Object* o = soa.Decode<mirror::Object*>(java_this);
- o->NotifyAll();
+ o->NotifyAll(soa.Self());
}
static void Object_wait(JNIEnv* env, jobject java_this) {
ScopedObjectAccess soa(env);
mirror::Object* o = soa.Decode<mirror::Object*>(java_this);
- o->Wait();
+ o->Wait(soa.Self());
}
static void Object_waitJI(JNIEnv* env, jobject java_this, jlong ms, jint ns) {
ScopedObjectAccess soa(env);
mirror::Object* o = soa.Decode<mirror::Object*>(java_this);
- o->Wait(ms, ns);
+ o->Wait(soa.Self(), ms, ns);
}
static JNINativeMethod gMethods[] = {
diff --git a/src/oat/runtime/support_locks.cc b/src/oat/runtime/support_locks.cc
index 38fc48cba0..79bb7a69f1 100644
--- a/src/oat/runtime/support_locks.cc
+++ b/src/oat/runtime/support_locks.cc
@@ -15,7 +15,7 @@
*/
#include "callee_save_frame.h"
-#include "mirror/object.h"
+#include "mirror/object-inl.h"
namespace art {
diff --git a/src/object_utils.h b/src/object_utils.h
index ea4de903b1..18ad312de2 100644
--- a/src/object_utils.h
+++ b/src/object_utils.h
@@ -46,16 +46,16 @@ class ObjectLock {
obj_->MonitorExit(self_);
}
- void Wait() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return Monitor::Wait(self_, obj_, 0, 0, false, kWaiting);
+ void WaitIgnoringInterrupts() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ Monitor::Wait(self_, obj_, 0, 0, false, kWaiting);
}
void Notify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- obj_->Notify();
+ obj_->Notify(self_);
}
void NotifyAll() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- obj_->NotifyAll();
+ obj_->NotifyAll(self_);
}
private:
diff --git a/src/thread.cc b/src/thread.cc
index 37c678370f..d0401b6390 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -987,9 +987,8 @@ void Thread::Destroy() {
soa.DecodeField(WellKnownClasses::java_lang_Thread_lock)->GetObject(opeer_);
// (This conditional is only needed for tests, where Thread.lock won't have been set.)
if (lock != NULL) {
- lock->MonitorEnter(self);
- lock->Notify();
- lock->MonitorExit(self);
+ ObjectLock locker(self, lock);
+ locker.Notify();
}
}
diff --git a/src/thread_list.cc b/src/thread_list.cc
index ea8baacd30..45ddd23382 100644
--- a/src/thread_list.cc
+++ b/src/thread_list.cc
@@ -21,9 +21,9 @@
#include <unistd.h>
#include "base/mutex.h"
+#include "base/timing_logger.h"
#include "debugger.h"
#include "thread.h"
-#include "timing_logger.h"
#include "utils.h"
namespace art {
@@ -210,8 +210,8 @@ size_t ThreadList::RunCheckpoint(Closure* checkpoint_function) {
// Shouldn't need to wait for longer than 1 millisecond.
const uint64_t threshold = 1;
if (NsToMs(end - start) > threshold) {
- LOG(INFO) << "Warning: waited longer than " << threshold << " ms for thread suspend"
- << std::endl;
+ LOG(INFO) << "Warning: waited longer than " << threshold
+ << " ms for thread suspend\n";
}
}
// We know for sure that the thread is suspended at this point.
diff --git a/src/timing_logger.cc b/src/timing_logger.cc
deleted file mode 100644
index fee7a30579..0000000000
--- a/src/timing_logger.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#include "timing_logger.h"
-
-#include "base/logging.h"
-#include "utils.h"
-
-#include <cmath>
-#include <iomanip>
-
-namespace art {
-
-void TimingLogger::Dump() const {
- Dump(LOG(INFO));
-}
-
-void TimingLogger::Dump(std::ostream& os) const {
- uint64_t largest_time = 0;
- os << name_ << ": begin\n";
- for (size_t i = 1; i < times_.size(); ++i) {
- uint64_t delta_time = times_[i] - times_[i - 1];
- largest_time = std::max(largest_time, delta_time);
- }
- // Compute which type of unit we will use for printing the timings.
- TimeUnit tu = GetAppropriateTimeUnit(largest_time);
- uint64_t divisor = GetNsToTimeUnitDivisor(tu);
- for (size_t i = 1; i < times_.size(); ++i) {
- uint64_t delta_time = times_[i] - times_[i - 1];
- if (!precise_ && divisor >= 1000) {
- // Make the fraction 0.
- delta_time -= delta_time % (divisor / 1000);
- }
- os << name_ << ": " << std::setw(8) << FormatDuration(delta_time, tu) << " " << labels_[i]
- << "\n";
- }
- os << name_ << ": end, " << NsToMs(GetTotalNs()) << " ms\n";
-}
-
-void CumulativeLogger::Dump() const {
- Dump(LOG(INFO));
-}
-
-void CumulativeLogger::Dump(std::ostream& os) const {
- os << name_ << ": iterations " << iterations_ << " begin\n";
- //Find which unit we will use for the timing logger.
- uint64_t largest_mean = 0;
- for (size_t i = 0; i < times_.size(); ++i) {
- // Convert back to nanoseconds from microseconds.
- uint64_t mean = times_[i] / iterations_;
- largest_mean = std::max(largest_mean, mean);
- }
- // Convert largest mean back to ns
- TimeUnit tu = GetAppropriateTimeUnit(largest_mean * kAdjust);
- uint64_t divisor = GetNsToTimeUnitDivisor(tu);
- for (size_t i = 0; i < times_.size(); ++i) {
- uint64_t mean_x2 = times_squared_[i] / iterations_;
- uint64_t mean = times_[i] / iterations_;
- uint64_t variance = mean_x2 - (mean * mean);
- uint64_t std_dev = static_cast<uint64_t>(std::sqrt(static_cast<double>(variance)));
- if (!precise_ && divisor >= 1000) {
- // Make the fraction 0.
- mean -= mean % (divisor / 1000);
- std_dev -= std_dev % (divisor / 1000);
- }
- os << StringPrintf("%s: %10s (std_dev %8s) %s\n",
- name_.c_str(),
- FormatDuration(mean * kAdjust, tu).c_str(),
- FormatDuration(std_dev * kAdjust, tu).c_str(),
- labels_[i].c_str());
- }
- uint64_t total_mean_x2 = total_time_squared_;
- uint64_t mean_total_ns = GetTotalTime();
- if (iterations_ != 0) {
- total_mean_x2 /= iterations_;
- mean_total_ns /= iterations_;
- }
- uint64_t total_variance = total_mean_x2 - (mean_total_ns * mean_total_ns);
- uint64_t total_std_dev = static_cast<uint64_t>(
- std::sqrt(static_cast<double>(total_variance)));
- os << name_ << ": end, mean " << PrettyDuration(mean_total_ns * kAdjust)
- << " std_dev " << PrettyDuration(total_std_dev * kAdjust) << "\n";
-}
-
-} // namespace art
diff --git a/src/timing_logger.h b/src/timing_logger.h
deleted file mode 100644
index fc47028afe..0000000000
--- a/src/timing_logger.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2011 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_SRC_TIMING_LOGGER_H_
-#define ART_SRC_TIMING_LOGGER_H_
-
-#include "utils.h" // For NanoTime.
-
-#include <stdint.h>
-#include <string>
-#include <vector>
-
-namespace art {
-
-class CumulativeLogger;
-
-class TimingLogger {
- public:
- explicit TimingLogger(const std::string& name, bool precise = false)
- : name_(name), precise_(precise) {
- AddSplit("");
- }
-
- void Reset() {
- times_.clear();
- labels_.clear();
- AddSplit("");
- }
-
- void AddSplit(const std::string& label) {
- times_.push_back(NanoTime());
- labels_.push_back(label);
- }
-
- void Dump() const;
-
- void Dump(std::ostream& os) const;
-
- uint64_t GetTotalNs() const {
- return times_.back() - times_.front();
- }
-
- protected:
- std::string name_;
- bool precise_;
- std::vector<uint64_t> times_;
- std::vector<std::string> labels_;
-
- friend class CumulativeLogger;
-};
-
-class CumulativeLogger {
- public:
- explicit CumulativeLogger(const std::string& name = "", bool precise = false)
- : name_(name),
- precise_(precise) {
- Reset();
- }
-
- void SetName(const std::string& name) {
- name_ = name;
- }
-
- void Start() {
- index_ = 0;
- last_split_ = NanoTime();
- }
-
- void End() {
- iterations_++;
- }
-
- void AddSplit(const std::string& label) {
- uint64_t cur_time = NanoTime();
- AddPair(label, cur_time - last_split_);
- last_split_ = cur_time;
- }
-
- void Reset() {
- times_.clear();
- labels_.clear();
- times_squared_.clear();
- iterations_ = 0;
- total_time_squared_ = 0;
- }
-
- void AddPair(const std::string& label, uint64_t delta_time) {
- // Convert delta time to microseconds so that we don't overflow our counters.
- delta_time /= kAdjust;
- if (index_ >= times_.size()) {
- times_.push_back(delta_time);
- times_squared_.push_back(delta_time * delta_time);
- labels_.push_back(label);
- } else {
- times_[index_] += delta_time;
- times_squared_[index_] += delta_time * delta_time;
- DCHECK_EQ(labels_[index_], label);
- }
- index_++;
- }
-
- void AddLogger(const TimingLogger& logger) {
- DCHECK_EQ(logger.times_.size(), logger.labels_.size());
- uint64_t total_time = 0;
- for (size_t i = 1; i < logger.times_.size(); ++i) {
- const uint64_t delta_time = logger.times_[i] - logger.times_[i - 1];
- const std::string& label = logger.labels_[i];
- AddPair(label, delta_time);
- total_time += delta_time;
- }
- total_time /= kAdjust;
- total_time_squared_ += total_time * total_time;
- }
-
- void Dump() const;
-
- void Dump(std::ostream& os) const;
-
- uint64_t GetTotalNs() const {
- return GetTotalTime() * kAdjust;
- }
-
- private:
-
- uint64_t GetTotalTime() const {
- uint64_t total = 0;
- for (size_t i = 0; i < times_.size(); ++i) {
- total += times_[i];
- }
- return total;
- }
-
- static const uint64_t kAdjust = 1000;
- std::string name_;
- bool precise_;
- uint64_t total_time_squared_;
- std::vector<uint64_t> times_;
- std::vector<uint64_t> times_squared_;
- std::vector<std::string> labels_;
- size_t index_;
- size_t iterations_;
- uint64_t last_split_;
-};
-
-} // namespace art
-
-#endif // ART_SRC_TIMING_LOGGER_H_