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