/* * Copyright (C) 2022 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_DEX2OAT_LINKER_CODE_INFO_TABLE_DEDUPER_H_ #define ART_DEX2OAT_LINKER_CODE_INFO_TABLE_DEDUPER_H_ #include #include "base/bit_memory_region.h" #include "base/hash_set.h" namespace art { namespace linker { class CodeInfoTableDeduper { public: explicit CodeInfoTableDeduper(std::vector* output) : writer_(output), dedupe_set_(kMinLoadFactor, kMaxLoadFactor, DedupeSetEntryHash(output), DedupeSetEntryEquals(output)) { DCHECK_EQ(output->size(), 0u); } void ReserveDedupeBuffer(size_t num_code_infos); // Copy CodeInfo into output while de-duplicating the internal bit tables. // It returns the byte offset of the copied CodeInfo within the output. size_t Dedupe(const uint8_t* code_info); private: struct DedupeSetEntry { uint32_t bit_start; uint32_t bit_size; }; class DedupeSetEntryEmpty { public: void MakeEmpty(DedupeSetEntry& item) const { item = {0u, 0u}; } bool IsEmpty(const DedupeSetEntry& item) const { return item.bit_size == 0u; } }; class DedupeSetEntryHash { public: explicit DedupeSetEntryHash(std::vector* output) : output_(output) {} uint32_t operator()(const DedupeSetEntry& item) const { return DataHash()(BitMemoryRegion(output_->data(), item.bit_start, item.bit_size)); } private: std::vector* const output_; }; class DedupeSetEntryEquals { public: explicit DedupeSetEntryEquals(std::vector* output) : output_(output) {} bool operator()(const DedupeSetEntry& lhs, const DedupeSetEntry& rhs) const { DCHECK_NE(lhs.bit_size, 0u); DCHECK_NE(rhs.bit_size, 0u); return lhs.bit_size == rhs.bit_size && BitMemoryRegion::Equals( BitMemoryRegion(output_->data(), lhs.bit_start, lhs.bit_size), BitMemoryRegion(output_->data(), rhs.bit_start, rhs.bit_size)); } private: std::vector* const output_; }; using DedupeSet = HashSet; static constexpr double kMinLoadFactor = 0.5; static constexpr double kMaxLoadFactor = 0.75; BitMemoryWriter> writer_; // Deduplicate at BitTable level. Entries describe ranges in `output`, see constructor. DedupeSet dedupe_set_; }; } // namespace linker } // namespace art #endif // ART_DEX2OAT_LINKER_CODE_INFO_TABLE_DEDUPER_H_