| Index: courgette/label_manager.cc
|
| diff --git a/courgette/label_manager.cc b/courgette/label_manager.cc
|
| index bd568b0f26d41ce42da56f57c8c86ce8beec62ed..a109d8bda9fe9d43877301b2910150650e0ece03 100644
|
| --- a/courgette/label_manager.cc
|
| +++ b/courgette/label_manager.cc
|
| @@ -16,38 +16,11 @@
|
|
|
| namespace courgette {
|
|
|
| -LabelManager::LabelManager() {}
|
| -
|
| -LabelManager::~LabelManager() {}
|
| -
|
| -// static
|
| -int LabelManager::GetIndexBound(const LabelVector& labels) {
|
| - int max_index = -1;
|
| - for (const Label& label : labels) {
|
| - if (label.index_ != Label::kNoIndex)
|
| - max_index = std::max(max_index, label.index_);
|
| - }
|
| - return max_index + 1;
|
| -}
|
| -
|
| -// static
|
| -int LabelManager::GetIndexBound(const RVAToLabel& labels_map) {
|
| - int max_index = -1;
|
| - for (const auto& rva_and_label : labels_map) {
|
| - const Label& label = *rva_and_label.second;
|
| - if (label.index_ != Label::kNoIndex)
|
| - max_index = std::max(max_index, label.index_);
|
| - }
|
| - return max_index + 1;
|
| -}
|
| -
|
| -LabelManagerImpl::RvaVisitor::~RvaVisitor() {}
|
| -
|
| -LabelManagerImpl::SimpleIndexAssigner::SimpleIndexAssigner(LabelVector* labels)
|
| +LabelManager::SimpleIndexAssigner::SimpleIndexAssigner(LabelVector* labels)
|
| : labels_(labels) {
|
| // Initialize |num_index_| and |available_|.
|
| num_index_ = std::max(base::checked_cast<int>(labels_->size()),
|
| - LabelManager::GetIndexBound(*labels_));
|
| + GetLabelIndexBound(*labels_));
|
| available_.resize(num_index_, true);
|
| size_t used = 0;
|
| for (const Label& label : *labels_) {
|
| @@ -59,9 +32,9 @@ LabelManagerImpl::SimpleIndexAssigner::SimpleIndexAssigner(LabelVector* labels)
|
| VLOG(1) << used << " of " << labels_->size() << " labels pre-assigned.";
|
| }
|
|
|
| -LabelManagerImpl::SimpleIndexAssigner::~SimpleIndexAssigner() {}
|
| +LabelManager::SimpleIndexAssigner::~SimpleIndexAssigner() {}
|
|
|
| -void LabelManagerImpl::SimpleIndexAssigner::DoForwardFill() {
|
| +void LabelManager::SimpleIndexAssigner::DoForwardFill() {
|
| size_t count = 0;
|
| // Inside the loop, if |prev_index| == |kNoIndex| then we try to assign 0.
|
| // This allows 0 (if unused) to be assigned in middle of |labels_|.
|
| @@ -80,7 +53,7 @@ void LabelManagerImpl::SimpleIndexAssigner::DoForwardFill() {
|
| VLOG(1) << " fill forward " << count;
|
| }
|
|
|
| -void LabelManagerImpl::SimpleIndexAssigner::DoBackwardFill() {
|
| +void LabelManager::SimpleIndexAssigner::DoBackwardFill() {
|
| size_t count = 0;
|
| // This is asymmetric from DoForwardFill(), to preserve old behavior.
|
| // Inside the loop, if |prev_index| == |kNoIndex| then we skip assignment.
|
| @@ -102,7 +75,7 @@ void LabelManagerImpl::SimpleIndexAssigner::DoBackwardFill() {
|
| VLOG(1) << " fill backward " << count;
|
| }
|
|
|
| -void LabelManagerImpl::SimpleIndexAssigner::DoInFill() {
|
| +void LabelManager::SimpleIndexAssigner::DoInFill() {
|
| size_t count = 0;
|
| int index = 0;
|
| for (Label& label : *labels_) {
|
| @@ -118,59 +91,40 @@ void LabelManagerImpl::SimpleIndexAssigner::DoInFill() {
|
| VLOG(1) << " infill " << count;
|
| }
|
|
|
| -LabelManagerImpl::LabelManagerImpl() {}
|
| -
|
| -LabelManagerImpl::~LabelManagerImpl() {}
|
| -
|
| -// We wish to minimize peak memory usage here. Analysis: Let
|
| -// m = number of (RVA) elements in |rva_visitor|,
|
| -// n = number of distinct (RVA) elements in |rva_visitor|.
|
| -// The final storage is n * sizeof(Label) bytes. During computation we uniquify
|
| -// m RVAs, and count repeats. Taking sizeof(RVA) = 4, an implementation using
|
| -// std::map or std::unordered_map would consume additionally 32 * n bytes.
|
| -// Meanwhile, our std::vector implementation consumes additionally 4 * m bytes
|
| -// For our typical usage (i.e. Chrome) we see m = ~4n, so we use 16 * n bytes of
|
| -// extra contiguous memory during computation. Assuming memory fragmentation
|
| -// would not be an issue, this is much better than using std::map.
|
| -void LabelManagerImpl::Read(RvaVisitor* rva_visitor) {
|
| - // Write all values in |rva_visitor| to |rvas|.
|
| - size_t num_rva = rva_visitor->Remaining();
|
| - std::vector<RVA> rvas(num_rva);
|
| - for (size_t i = 0; i < num_rva; ++i, rva_visitor->Next())
|
| - rvas[i] = rva_visitor->Get();
|
| -
|
| - // Sort |rvas|, then count the number of distinct values.
|
| - using CRV = ConsecutiveRangeVisitor<std::vector<RVA>::iterator>;
|
| - std::sort(rvas.begin(), rvas.end());
|
| - DCHECK(rvas.empty() || rvas.back() != kUnassignedRVA);
|
| +LabelManager::LabelManager() {}
|
|
|
| - size_t num_distinct_rva = 0;
|
| - for (CRV it(rvas.begin(), rvas.end()); it.has_more(); it.advance())
|
| - ++num_distinct_rva;
|
| +LabelManager::~LabelManager() {}
|
|
|
| - // Reserve space for |labels_|, populate with sorted RVA and repeats.
|
| - DCHECK(labels_.empty());
|
| - labels_.reserve(num_distinct_rva);
|
| - for (CRV it(rvas.begin(), rvas.end()); it.has_more(); it.advance()) {
|
| - labels_.push_back(Label(*it.cur()));
|
| - base::CheckedNumeric<uint32_t> count = it.repeat();
|
| - labels_.back().count_ = count.ValueOrDie();
|
| +// static
|
| +int LabelManager::GetIndexBound(const RVAToLabel& labels_map) {
|
| + int max_index = -1;
|
| + for (const auto& rva_and_label : labels_map) {
|
| + const Label& label = *rva_and_label.second;
|
| + if (label.index_ != Label::kNoIndex)
|
| + max_index = std::max(max_index, label.index_);
|
| }
|
| + return max_index + 1;
|
| }
|
|
|
| -size_t LabelManagerImpl::Size() const {
|
| - return labels_.size();
|
| +// static
|
| +int LabelManager::GetLabelIndexBound(const LabelVector& labels) {
|
| + int max_index = -1;
|
| + for (const Label& label : labels) {
|
| + if (label.index_ != Label::kNoIndex)
|
| + max_index = std::max(max_index, label.index_);
|
| + }
|
| + return max_index + 1;
|
| }
|
|
|
| // Uses binary search to find |rva|.
|
| -Label* LabelManagerImpl::Find(RVA rva) {
|
| +Label* LabelManager::Find(RVA rva) {
|
| auto it = std::lower_bound(
|
| labels_.begin(), labels_.end(), Label(rva),
|
| [](const Label& l1, const Label& l2) { return l1.rva_ < l2.rva_; });
|
| return it == labels_.end() || it->rva_ != rva ? nullptr : &(*it);
|
| }
|
|
|
| -void LabelManagerImpl::RemoveUnderusedLabels(int32_t count_threshold) {
|
| +void LabelManager::RemoveUnderusedLabels(int32_t count_threshold) {
|
| if (count_threshold <= 0)
|
| return;
|
| labels_.erase(std::remove_if(labels_.begin(), labels_.end(),
|
| @@ -181,12 +135,12 @@ void LabelManagerImpl::RemoveUnderusedLabels(int32_t count_threshold) {
|
| // Not shrinking |labels_|, since this may cause reallocation.
|
| }
|
|
|
| -void LabelManagerImpl::UnassignIndexes() {
|
| +void LabelManager::UnassignIndexes() {
|
| for (Label& label : labels_)
|
| label.index_ = Label::kNoIndex;
|
| }
|
|
|
| -void LabelManagerImpl::DefaultAssignIndexes() {
|
| +void LabelManager::DefaultAssignIndexes() {
|
| int cur_index = 0;
|
| for (Label& label : labels_) {
|
| CHECK_EQ(Label::kNoIndex, label.index_);
|
| @@ -194,7 +148,7 @@ void LabelManagerImpl::DefaultAssignIndexes() {
|
| }
|
| }
|
|
|
| -void LabelManagerImpl::AssignRemainingIndexes() {
|
| +void LabelManager::AssignRemainingIndexes() {
|
| // This adds some memory overhead, about 1 bit per Label (more if indexes >=
|
| // |labels_.size()| get used).
|
| SimpleIndexAssigner assigner(&labels_);
|
| @@ -203,8 +157,40 @@ void LabelManagerImpl::AssignRemainingIndexes() {
|
| assigner.DoInFill();
|
| }
|
|
|
| -void LabelManagerImpl::SetLabels(const LabelVector& labels) {
|
| - labels_ = labels;
|
| +// We wish to minimize peak memory usage here. Analysis: Let
|
| +// m = number of (RVA) elements in |rva_visitor|,
|
| +// n = number of distinct (RVA) elements in |rva_visitor|.
|
| +// The final storage is n * sizeof(Label) bytes. During computation we uniquify
|
| +// m RVAs, and count repeats. Taking sizeof(RVA) = 4, an implementation using
|
| +// std::map or std::unordered_map would consume additionally 32 * n bytes.
|
| +// Meanwhile, our std::vector implementation consumes additionally 4 * m bytes
|
| +// For our typical usage (i.e. Chrome) we see m = ~4n, so we use 16 * n bytes of
|
| +// extra contiguous memory during computation. Assuming memory fragmentation
|
| +// would not be an issue, this is much better than using std::map.
|
| +void LabelManager::Read(RvaVisitor* rva_visitor) {
|
| + // Write all values in |rva_visitor| to |rvas|.
|
| + size_t num_rva = rva_visitor->Remaining();
|
| + std::vector<RVA> rvas(num_rva);
|
| + for (size_t i = 0; i < num_rva; ++i, rva_visitor->Next())
|
| + rvas[i] = rva_visitor->Get();
|
| +
|
| + // Sort |rvas|, then count the number of distinct values.
|
| + using CRV = ConsecutiveRangeVisitor<std::vector<RVA>::iterator>;
|
| + std::sort(rvas.begin(), rvas.end());
|
| + DCHECK(rvas.empty() || rvas.back() != kUnassignedRVA);
|
| +
|
| + size_t num_distinct_rva = 0;
|
| + for (CRV it(rvas.begin(), rvas.end()); it.has_more(); it.advance())
|
| + ++num_distinct_rva;
|
| +
|
| + // Reserve space for |labels_|, populate with sorted RVA and repeats.
|
| + DCHECK(labels_.empty());
|
| + labels_.reserve(num_distinct_rva);
|
| + for (CRV it(rvas.begin(), rvas.end()); it.has_more(); it.advance()) {
|
| + labels_.push_back(Label(*it.cur()));
|
| + base::CheckedNumeric<uint32_t> count = it.repeat();
|
| + labels_.back().count_ = count.ValueOrDie();
|
| + }
|
| }
|
|
|
| } // namespace courgette
|
|
|