xref: /aosp_15_r20/art/dex2oat/linker/code_info_table_deduper.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_DEX2OAT_LINKER_CODE_INFO_TABLE_DEDUPER_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_DEX2OAT_LINKER_CODE_INFO_TABLE_DEDUPER_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <vector>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include "base/bit_memory_region.h"
23*795d594fSAndroid Build Coastguard Worker #include "base/hash_set.h"
24*795d594fSAndroid Build Coastguard Worker 
25*795d594fSAndroid Build Coastguard Worker namespace art {
26*795d594fSAndroid Build Coastguard Worker namespace linker {
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker class CodeInfoTableDeduper {
29*795d594fSAndroid Build Coastguard Worker  public:
CodeInfoTableDeduper(std::vector<uint8_t> * output)30*795d594fSAndroid Build Coastguard Worker   explicit CodeInfoTableDeduper(std::vector<uint8_t>* output)
31*795d594fSAndroid Build Coastguard Worker       : writer_(output),
32*795d594fSAndroid Build Coastguard Worker         dedupe_set_(kMinLoadFactor,
33*795d594fSAndroid Build Coastguard Worker                     kMaxLoadFactor,
34*795d594fSAndroid Build Coastguard Worker                     DedupeSetEntryHash(output),
35*795d594fSAndroid Build Coastguard Worker                     DedupeSetEntryEquals(output)) {
36*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(output->size(), 0u);
37*795d594fSAndroid Build Coastguard Worker   }
38*795d594fSAndroid Build Coastguard Worker 
39*795d594fSAndroid Build Coastguard Worker   void ReserveDedupeBuffer(size_t num_code_infos);
40*795d594fSAndroid Build Coastguard Worker 
41*795d594fSAndroid Build Coastguard Worker   // Copy CodeInfo into output while de-duplicating the internal bit tables.
42*795d594fSAndroid Build Coastguard Worker   // It returns the byte offset of the copied CodeInfo within the output.
43*795d594fSAndroid Build Coastguard Worker   size_t Dedupe(const uint8_t* code_info);
44*795d594fSAndroid Build Coastguard Worker 
45*795d594fSAndroid Build Coastguard Worker  private:
46*795d594fSAndroid Build Coastguard Worker   struct DedupeSetEntry {
47*795d594fSAndroid Build Coastguard Worker     uint32_t bit_start;
48*795d594fSAndroid Build Coastguard Worker     uint32_t bit_size;
49*795d594fSAndroid Build Coastguard Worker   };
50*795d594fSAndroid Build Coastguard Worker 
51*795d594fSAndroid Build Coastguard Worker   class DedupeSetEntryEmpty {
52*795d594fSAndroid Build Coastguard Worker    public:
MakeEmpty(DedupeSetEntry & item)53*795d594fSAndroid Build Coastguard Worker     void MakeEmpty(DedupeSetEntry& item) const {
54*795d594fSAndroid Build Coastguard Worker       item = {0u, 0u};
55*795d594fSAndroid Build Coastguard Worker     }
IsEmpty(const DedupeSetEntry & item)56*795d594fSAndroid Build Coastguard Worker     bool IsEmpty(const DedupeSetEntry& item) const {
57*795d594fSAndroid Build Coastguard Worker       return item.bit_size == 0u;
58*795d594fSAndroid Build Coastguard Worker     }
59*795d594fSAndroid Build Coastguard Worker   };
60*795d594fSAndroid Build Coastguard Worker 
61*795d594fSAndroid Build Coastguard Worker   class DedupeSetEntryHash {
62*795d594fSAndroid Build Coastguard Worker    public:
DedupeSetEntryHash(std::vector<uint8_t> * output)63*795d594fSAndroid Build Coastguard Worker     explicit DedupeSetEntryHash(std::vector<uint8_t>* output) : output_(output) {}
64*795d594fSAndroid Build Coastguard Worker 
operator()65*795d594fSAndroid Build Coastguard Worker     uint32_t operator()(const DedupeSetEntry& item) const {
66*795d594fSAndroid Build Coastguard Worker       return DataHash()(BitMemoryRegion(output_->data(), item.bit_start, item.bit_size));
67*795d594fSAndroid Build Coastguard Worker     }
68*795d594fSAndroid Build Coastguard Worker 
69*795d594fSAndroid Build Coastguard Worker    private:
70*795d594fSAndroid Build Coastguard Worker     std::vector<uint8_t>* const output_;
71*795d594fSAndroid Build Coastguard Worker   };
72*795d594fSAndroid Build Coastguard Worker 
73*795d594fSAndroid Build Coastguard Worker   class DedupeSetEntryEquals {
74*795d594fSAndroid Build Coastguard Worker    public:
DedupeSetEntryEquals(std::vector<uint8_t> * output)75*795d594fSAndroid Build Coastguard Worker     explicit DedupeSetEntryEquals(std::vector<uint8_t>* output) : output_(output) {}
76*795d594fSAndroid Build Coastguard Worker 
operator()77*795d594fSAndroid Build Coastguard Worker     bool operator()(const DedupeSetEntry& lhs, const DedupeSetEntry& rhs) const {
78*795d594fSAndroid Build Coastguard Worker       DCHECK_NE(lhs.bit_size, 0u);
79*795d594fSAndroid Build Coastguard Worker       DCHECK_NE(rhs.bit_size, 0u);
80*795d594fSAndroid Build Coastguard Worker       return lhs.bit_size == rhs.bit_size &&
81*795d594fSAndroid Build Coastguard Worker              BitMemoryRegion::Equals(
82*795d594fSAndroid Build Coastguard Worker                  BitMemoryRegion(output_->data(), lhs.bit_start, lhs.bit_size),
83*795d594fSAndroid Build Coastguard Worker                  BitMemoryRegion(output_->data(), rhs.bit_start, rhs.bit_size));
84*795d594fSAndroid Build Coastguard Worker     }
85*795d594fSAndroid Build Coastguard Worker 
86*795d594fSAndroid Build Coastguard Worker    private:
87*795d594fSAndroid Build Coastguard Worker     std::vector<uint8_t>* const output_;
88*795d594fSAndroid Build Coastguard Worker   };
89*795d594fSAndroid Build Coastguard Worker 
90*795d594fSAndroid Build Coastguard Worker   using DedupeSet =
91*795d594fSAndroid Build Coastguard Worker       HashSet<DedupeSetEntry, DedupeSetEntryEmpty, DedupeSetEntryHash, DedupeSetEntryEquals>;
92*795d594fSAndroid Build Coastguard Worker 
93*795d594fSAndroid Build Coastguard Worker   static constexpr double kMinLoadFactor = 0.5;
94*795d594fSAndroid Build Coastguard Worker   static constexpr double kMaxLoadFactor = 0.75;
95*795d594fSAndroid Build Coastguard Worker 
96*795d594fSAndroid Build Coastguard Worker   BitMemoryWriter<std::vector<uint8_t>> writer_;
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker   // Deduplicate at BitTable level. Entries describe ranges in `output`, see constructor.
99*795d594fSAndroid Build Coastguard Worker   DedupeSet dedupe_set_;
100*795d594fSAndroid Build Coastguard Worker };
101*795d594fSAndroid Build Coastguard Worker 
102*795d594fSAndroid Build Coastguard Worker }  //  namespace linker
103*795d594fSAndroid Build Coastguard Worker }  //  namespace art
104*795d594fSAndroid Build Coastguard Worker 
105*795d594fSAndroid Build Coastguard Worker #endif  // ART_DEX2OAT_LINKER_CODE_INFO_TABLE_DEDUPER_H_
106