106 lines
3.1 KiB
C++
106 lines
3.1 KiB
C++
/*
|
|
* 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 <vector>
|
|
|
|
#include "base/bit_memory_region.h"
|
|
#include "base/hash_set.h"
|
|
|
|
namespace art {
|
|
namespace linker {
|
|
|
|
class CodeInfoTableDeduper {
|
|
public:
|
|
explicit CodeInfoTableDeduper(std::vector<uint8_t>* 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<uint8_t>* output) : output_(output) {}
|
|
|
|
uint32_t operator()(const DedupeSetEntry& item) const {
|
|
return DataHash()(BitMemoryRegion(output_->data(), item.bit_start, item.bit_size));
|
|
}
|
|
|
|
private:
|
|
std::vector<uint8_t>* const output_;
|
|
};
|
|
|
|
class DedupeSetEntryEquals {
|
|
public:
|
|
explicit DedupeSetEntryEquals(std::vector<uint8_t>* 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<uint8_t>* const output_;
|
|
};
|
|
|
|
using DedupeSet =
|
|
HashSet<DedupeSetEntry, DedupeSetEntryEmpty, DedupeSetEntryHash, DedupeSetEntryEquals>;
|
|
|
|
static constexpr double kMinLoadFactor = 0.5;
|
|
static constexpr double kMaxLoadFactor = 0.75;
|
|
|
|
BitMemoryWriter<std::vector<uint8_t>> 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_
|