xref: /aosp_15_r20/external/zucchini/target_pool.cc (revision a03ca8b91e029cd15055c20c78c2e087c84792e4)
1*a03ca8b9SKrzysztof Kosiński // Copyright 2017 The Chromium Authors. All rights reserved.
2*a03ca8b9SKrzysztof Kosiński // Use of this source code is governed by a BSD-style license that can be
3*a03ca8b9SKrzysztof Kosiński // found in the LICENSE file.
4*a03ca8b9SKrzysztof Kosiński 
5*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/target_pool.h"
6*a03ca8b9SKrzysztof Kosiński 
7*a03ca8b9SKrzysztof Kosiński #include <algorithm>
8*a03ca8b9SKrzysztof Kosiński #include <iterator>
9*a03ca8b9SKrzysztof Kosiński #include <utility>
10*a03ca8b9SKrzysztof Kosiński 
11*a03ca8b9SKrzysztof Kosiński #include "base/check.h"
12*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/algorithm.h"
13*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/equivalence_map.h"
14*a03ca8b9SKrzysztof Kosiński 
15*a03ca8b9SKrzysztof Kosiński namespace zucchini {
16*a03ca8b9SKrzysztof Kosiński 
17*a03ca8b9SKrzysztof Kosiński TargetPool::TargetPool() = default;
18*a03ca8b9SKrzysztof Kosiński 
TargetPool(std::deque<offset_t> && targets)19*a03ca8b9SKrzysztof Kosiński TargetPool::TargetPool(std::deque<offset_t>&& targets) {
20*a03ca8b9SKrzysztof Kosiński   DCHECK(targets_.empty());
21*a03ca8b9SKrzysztof Kosiński   DCHECK(std::is_sorted(targets.begin(), targets.end()));
22*a03ca8b9SKrzysztof Kosiński   targets_ = std::move(targets);
23*a03ca8b9SKrzysztof Kosiński }
24*a03ca8b9SKrzysztof Kosiński 
25*a03ca8b9SKrzysztof Kosiński TargetPool::TargetPool(TargetPool&&) = default;
26*a03ca8b9SKrzysztof Kosiński TargetPool::TargetPool(const TargetPool&) = default;
27*a03ca8b9SKrzysztof Kosiński TargetPool::~TargetPool() = default;
28*a03ca8b9SKrzysztof Kosiński 
InsertTargets(const std::vector<offset_t> & targets)29*a03ca8b9SKrzysztof Kosiński void TargetPool::InsertTargets(const std::vector<offset_t>& targets) {
30*a03ca8b9SKrzysztof Kosiński   std::copy(targets.begin(), targets.end(), std::back_inserter(targets_));
31*a03ca8b9SKrzysztof Kosiński   SortAndUniquify(&targets_);
32*a03ca8b9SKrzysztof Kosiński }
33*a03ca8b9SKrzysztof Kosiński 
InsertTargets(TargetSource * targets)34*a03ca8b9SKrzysztof Kosiński void TargetPool::InsertTargets(TargetSource* targets) {
35*a03ca8b9SKrzysztof Kosiński   for (auto target = targets->GetNext(); target.has_value();
36*a03ca8b9SKrzysztof Kosiński        target = targets->GetNext()) {
37*a03ca8b9SKrzysztof Kosiński     targets_.push_back(*target);
38*a03ca8b9SKrzysztof Kosiński   }
39*a03ca8b9SKrzysztof Kosiński   // InsertTargets() can be called many times (number of reference types for the
40*a03ca8b9SKrzysztof Kosiński   // pool) in succession. Calling SortAndUniquify() every time enables deduping
41*a03ca8b9SKrzysztof Kosiński   // to occur more often. This prioritizes peak memory reduction over running
42*a03ca8b9SKrzysztof Kosiński   // time.
43*a03ca8b9SKrzysztof Kosiński   SortAndUniquify(&targets_);
44*a03ca8b9SKrzysztof Kosiński }
45*a03ca8b9SKrzysztof Kosiński 
InsertTargets(const std::vector<Reference> & references)46*a03ca8b9SKrzysztof Kosiński void TargetPool::InsertTargets(const std::vector<Reference>& references) {
47*a03ca8b9SKrzysztof Kosiński   // This can be called many times, so it's better to let std::back_inserter()
48*a03ca8b9SKrzysztof Kosiński   // manage |targets_| resize, instead of manually reserving space.
49*a03ca8b9SKrzysztof Kosiński   std::transform(references.begin(), references.end(),
50*a03ca8b9SKrzysztof Kosiński                  std::back_inserter(targets_),
51*a03ca8b9SKrzysztof Kosiński                  [](const Reference& ref) { return ref.target; });
52*a03ca8b9SKrzysztof Kosiński   SortAndUniquify(&targets_);
53*a03ca8b9SKrzysztof Kosiński }
54*a03ca8b9SKrzysztof Kosiński 
InsertTargets(ReferenceReader && references)55*a03ca8b9SKrzysztof Kosiński void TargetPool::InsertTargets(ReferenceReader&& references) {
56*a03ca8b9SKrzysztof Kosiński   for (auto ref = references.GetNext(); ref.has_value();
57*a03ca8b9SKrzysztof Kosiński        ref = references.GetNext()) {
58*a03ca8b9SKrzysztof Kosiński     targets_.push_back(ref->target);
59*a03ca8b9SKrzysztof Kosiński   }
60*a03ca8b9SKrzysztof Kosiński   SortAndUniquify(&targets_);
61*a03ca8b9SKrzysztof Kosiński }
62*a03ca8b9SKrzysztof Kosiński 
KeyForOffset(offset_t offset) const63*a03ca8b9SKrzysztof Kosiński key_t TargetPool::KeyForOffset(offset_t offset) const {
64*a03ca8b9SKrzysztof Kosiński   auto pos = std::lower_bound(targets_.begin(), targets_.end(), offset);
65*a03ca8b9SKrzysztof Kosiński   DCHECK(pos != targets_.end() && *pos == offset);
66*a03ca8b9SKrzysztof Kosiński   return static_cast<offset_t>(pos - targets_.begin());
67*a03ca8b9SKrzysztof Kosiński }
68*a03ca8b9SKrzysztof Kosiński 
KeyForNearestOffset(offset_t offset) const69*a03ca8b9SKrzysztof Kosiński key_t TargetPool::KeyForNearestOffset(offset_t offset) const {
70*a03ca8b9SKrzysztof Kosiński   auto pos = std::lower_bound(targets_.begin(), targets_.end(), offset);
71*a03ca8b9SKrzysztof Kosiński   if (pos != targets_.begin()) {
72*a03ca8b9SKrzysztof Kosiński     // If distances are equal, prefer lower key.
73*a03ca8b9SKrzysztof Kosiński     if (pos == targets_.end() || *pos - offset >= offset - pos[-1])
74*a03ca8b9SKrzysztof Kosiński       --pos;
75*a03ca8b9SKrzysztof Kosiński   }
76*a03ca8b9SKrzysztof Kosiński   return static_cast<offset_t>(pos - targets_.begin());
77*a03ca8b9SKrzysztof Kosiński }
78*a03ca8b9SKrzysztof Kosiński 
FilterAndProject(const OffsetMapper & offset_mapper)79*a03ca8b9SKrzysztof Kosiński void TargetPool::FilterAndProject(const OffsetMapper& offset_mapper) {
80*a03ca8b9SKrzysztof Kosiński   offset_mapper.ForwardProjectAll(&targets_);
81*a03ca8b9SKrzysztof Kosiński   std::sort(targets_.begin(), targets_.end());
82*a03ca8b9SKrzysztof Kosiński }
83*a03ca8b9SKrzysztof Kosiński 
84*a03ca8b9SKrzysztof Kosiński }  // namespace zucchini
85