当前仓库属于关闭状态,部分功能使用受限,详情请查阅 仓库状态说明
57 Star 30 Fork 160

OpenHarmony-SIG/arkcompiler_runtime_core
关闭

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
file_item_container.cpp 28.49 KB
一键复制 编辑 原始数据 按行查看 历史
K Prokopenko 提交于 2023-05-11 16:30 +08:00 . add bytecode static linker [squash]
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
/**
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* 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.
*/
#include "file_item_container.h"
#include <cstdint>
#include <type_traits>
#include "macros.h"
#include "file_format_version.h"
#include "pgo.h"
namespace panda::panda_file {
class ItemDeduper {
public:
template <class T>
T *Deduplicate(T *item)
{
static_assert(std::is_base_of_v<BaseItem, T>);
if (auto iter = already_deduped_items_.find(item); iter != already_deduped_items_.end()) {
ASSERT(item->GetItemType() == iter->second->GetItemType());
return static_cast<T *>(iter->second);
}
ItemData item_data(item);
auto it = items_.find(item_data);
if (it == items_.cend()) {
items_.insert(item_data);
return item;
}
auto result_item = it->GetItem();
ASSERT(item->GetItemType() == result_item->GetItemType());
auto result = static_cast<T *>(result_item);
if (item != result) {
already_deduped_items_.emplace(item, result);
if constexpr (!std::is_same_v<T, LineNumberProgramItem>) {
item->SetNeedsEmit(false);
}
}
return result;
}
size_t GetUniqueCount() const
{
return items_.size();
}
private:
class ItemWriter : public Writer {
public:
ItemWriter(std::vector<uint8_t> *buf, size_t offset) : buf_(buf), offset_(offset) {}
~ItemWriter() override = default;
NO_COPY_SEMANTIC(ItemWriter);
NO_MOVE_SEMANTIC(ItemWriter);
bool WriteByte(uint8_t byte) override
{
buf_->push_back(byte);
++offset_;
return true;
}
bool WriteBytes(const std::vector<uint8_t> &bytes) override
{
buf_->insert(buf_->end(), bytes.cbegin(), bytes.cend());
offset_ += bytes.size();
return true;
}
size_t GetOffset() const override
{
return offset_;
}
private:
std::vector<uint8_t> *buf_;
size_t offset_;
};
class ItemData {
public:
explicit ItemData(BaseItem *item) : item_(item)
{
Initialize();
}
~ItemData() = default;
DEFAULT_COPY_SEMANTIC(ItemData);
NO_MOVE_SEMANTIC(ItemData);
BaseItem *GetItem() const
{
return item_;
}
uint32_t GetHash() const
{
ASSERT(IsInitialized());
return hash_;
}
bool operator==(const ItemData &item_data) const noexcept
{
ASSERT(IsInitialized());
return data_ == item_data.data_;
}
private:
bool IsInitialized() const
{
return !data_.empty();
}
void Initialize()
{
ASSERT(item_->NeedsEmit());
ItemWriter writer(&data_, item_->GetOffset());
[[maybe_unused]] auto res = item_->Write(&writer);
ASSERT(res);
ASSERT(data_.size() == item_->GetSize());
hash_ = GetHash32(data_.data(), data_.size());
}
BaseItem *item_;
uint32_t hash_ {0};
std::vector<uint8_t> data_;
};
struct ItemHash {
size_t operator()(const ItemData &item_data) const noexcept
{
return item_data.GetHash();
}
};
std::unordered_set<ItemData, ItemHash> items_;
std::unordered_map<BaseItem *, BaseItem *> already_deduped_items_;
};
// TODO(nsizov): make method for items deletion
template <class T, class C, class I, class P, class E, class... Args>
static T *GetOrInsert(C &map, I &items, const P &pos, const E &key, bool is_foreign, Args &&...args)
{
auto it = map.find(key);
if (it != map.cend()) {
auto *item = it->second;
if (item->IsForeign() == is_foreign) {
return static_cast<T *>(item);
}
UNREACHABLE();
return nullptr;
}
auto ii = items.insert(pos, std::make_unique<T>(std::forward<Args>(args)...));
auto *item = static_cast<T *>(ii->get());
[[maybe_unused]] auto res = map.insert({key, item});
ASSERT(res.second);
return item;
}
ItemContainer::ItemContainer()
{
items_end_ = items_.insert(items_.end(), std::make_unique<EndItem>());
annotation_items_end_ = items_.insert(items_.end(), std::make_unique<EndItem>());
code_items_end_ = items_.insert(items_.end(), std::make_unique<EndItem>());
debug_items_end_ = items_.insert(items_.end(), std::make_unique<EndItem>());
end_ = debug_items_end_->get();
}
ClassItem *ItemContainer::GetOrCreateClassItem(const std::string &str)
{
return GetOrInsert<ClassItem>(class_map_, items_, items_end_, str, false, str);
}
ForeignClassItem *ItemContainer::GetOrCreateForeignClassItem(const std::string &str)
{
return GetOrInsert<ForeignClassItem>(class_map_, foreign_items_, foreign_items_.end(), str, true, str);
}
StringItem *ItemContainer::GetOrCreateStringItem(const std::string &str)
{
auto it = class_map_.find(str);
if (it != class_map_.cend()) {
return it->second->GetNameItem();
}
return GetOrInsert<StringItem>(string_map_, items_, items_end_, str, false, str);
}
LiteralArrayItem *ItemContainer::GetOrCreateLiteralArrayItem(const std::string &id)
{
return GetOrInsert<LiteralArrayItem>(literalarray_map_, items_, items_end_, id, false);
}
ScalarValueItem *ItemContainer::GetOrCreateIntegerValueItem(uint32_t v)
{
return GetOrInsert<ScalarValueItem>(int_value_map_, items_, items_end_, v, false, v);
}
ScalarValueItem *ItemContainer::GetOrCreateLongValueItem(uint64_t v)
{
return GetOrInsert<ScalarValueItem>(long_value_map_, items_, items_end_, v, false, v);
}
ScalarValueItem *ItemContainer::GetOrCreateFloatValueItem(float v)
{
return GetOrInsert<ScalarValueItem>(float_value_map_, items_, items_end_, bit_cast<uint32_t>(v), false, v);
}
ScalarValueItem *ItemContainer::GetOrCreateDoubleValueItem(double v)
{
return GetOrInsert<ScalarValueItem>(double_value_map_, items_, items_end_, bit_cast<uint64_t>(v), false, v);
}
ScalarValueItem *ItemContainer::GetOrCreateIdValueItem(BaseItem *v)
{
return GetOrInsert<ScalarValueItem>(id_value_map_, items_, items_end_, v, false, v);
}
ProtoItem *ItemContainer::GetOrCreateProtoItem(TypeItem *ret_type, const std::vector<MethodParamItem> &params)
{
ProtoKey key(ret_type, params);
return GetOrInsert<ProtoItem>(proto_map_, items_, items_end_, key, false, ret_type, params);
}
PrimitiveTypeItem *ItemContainer::GetOrCreatePrimitiveTypeItem(Type type)
{
return GetOrCreatePrimitiveTypeItem(type.GetId());
}
PrimitiveTypeItem *ItemContainer::GetOrCreatePrimitiveTypeItem(Type::TypeId type)
{
return GetOrInsert<PrimitiveTypeItem>(primitive_type_map_, items_, items_end_, type, false, type);
}
LineNumberProgramItem *ItemContainer::CreateLineNumberProgramItem()
{
auto it = items_.insert(debug_items_end_, std::make_unique<LineNumberProgramItem>());
auto *item = static_cast<LineNumberProgramItem *>(it->get());
[[maybe_unused]] auto res = line_number_program_index_item_.Add(item);
ASSERT(res);
return item;
}
void ItemContainer::IncRefLineNumberProgramItem(LineNumberProgramItem *it)
{
line_number_program_index_item_.IncRefCount(it);
}
void ItemContainer::DeduplicateLineNumberProgram(DebugInfoItem *item, ItemDeduper *deduper)
{
auto *line_number_program = item->GetLineNumberProgram();
auto *deduplicated = deduper->Deduplicate(line_number_program);
if (deduplicated != line_number_program) {
item->SetLineNumberProgram(deduplicated);
line_number_program_index_item_.IncRefCount(deduplicated);
line_number_program_index_item_.DecRefCount(line_number_program);
}
}
void ItemContainer::DeduplicateDebugInfo(MethodItem *method, ItemDeduper *debug_info_deduper,
ItemDeduper *line_number_program_deduper)
{
auto *debug_item = method->GetDebugInfo();
if (debug_item == nullptr) {
return;
}
DeduplicateLineNumberProgram(debug_item, line_number_program_deduper);
auto *deduplicated = debug_info_deduper->Deduplicate(debug_item);
if (deduplicated != debug_item) {
method->SetDebugInfo(deduplicated);
line_number_program_index_item_.DecRefCount(debug_item->GetLineNumberProgram());
}
}
static void DeduplicateCode(MethodItem *method, ItemDeduper *code_deduper)
{
auto *code_item = method->GetCode();
if (code_item == nullptr) {
return;
}
auto *deduplicated = code_deduper->Deduplicate(code_item);
if (deduplicated != code_item) {
method->SetCode(deduplicated);
deduplicated->AddMethod(method); // we need it for Profile-Guided optimization
}
}
void ItemContainer::DeduplicateCodeAndDebugInfo()
{
ItemDeduper line_number_program_deduper;
ItemDeduper debug_deduper;
ItemDeduper code_deduper;
for (auto &p : class_map_) {
auto *item = p.second;
if (item->IsForeign()) {
continue;
}
auto *class_item = static_cast<ClassItem *>(item);
class_item->VisitMethods(
[this, &debug_deduper, &line_number_program_deduper, &code_deduper](BaseItem *param_item) {
auto *method_item = static_cast<MethodItem *>(param_item);
DeduplicateDebugInfo(method_item, &debug_deduper, &line_number_program_deduper);
DeduplicateCode(method_item, &code_deduper);
return true;
});
}
}
static void DeduplicateAnnotationValue(AnnotationItem *annotation_item, ItemDeduper *deduper)
{
auto *elems = annotation_item->GetElements();
const auto &tags = annotation_item->GetTags();
for (size_t i = 0; i < elems->size(); i++) {
auto tag = tags[i];
// try to dedupe only ArrayValueItems
switch (tag.GetItem()) {
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
case '@':
break;
default:
continue;
}
auto &elem = (*elems)[i];
auto *value = elem.GetValue();
auto *deduplicated = deduper->Deduplicate(value);
if (deduplicated != value) {
elem.SetValue(deduplicated);
}
}
}
static void DeduplicateAnnotations(std::vector<AnnotationItem *> *items, ItemDeduper *annotation_deduper,
ItemDeduper *value_deduper)
{
for (auto &item : *items) {
DeduplicateAnnotationValue(item, value_deduper);
auto *deduplicated = annotation_deduper->Deduplicate(item);
if (deduplicated != item) {
item = deduplicated;
}
}
}
void ItemContainer::DeduplicateAnnotations()
{
ItemDeduper value_deduper;
ItemDeduper annotation_deduper;
for (auto &p : class_map_) {
auto *item = p.second;
if (item->IsForeign()) {
continue;
}
auto *class_item = static_cast<ClassItem *>(item);
panda_file::DeduplicateAnnotations(class_item->GetRuntimeAnnotations(), &annotation_deduper, &value_deduper);
panda_file::DeduplicateAnnotations(class_item->GetAnnotations(), &annotation_deduper, &value_deduper);
panda_file::DeduplicateAnnotations(class_item->GetRuntimeTypeAnnotations(), &annotation_deduper,
&value_deduper);
panda_file::DeduplicateAnnotations(class_item->GetTypeAnnotations(), &annotation_deduper, &value_deduper);
class_item->VisitMethods([&annotation_deduper, &value_deduper](BaseItem *param_item) {
auto *method_item = static_cast<MethodItem *>(param_item);
panda_file::DeduplicateAnnotations(method_item->GetRuntimeAnnotations(), &annotation_deduper,
&value_deduper);
panda_file::DeduplicateAnnotations(method_item->GetAnnotations(), &annotation_deduper, &value_deduper);
panda_file::DeduplicateAnnotations(method_item->GetRuntimeTypeAnnotations(), &annotation_deduper,
&value_deduper);
panda_file::DeduplicateAnnotations(method_item->GetTypeAnnotations(), &annotation_deduper, &value_deduper);
return true;
});
class_item->VisitFields([&annotation_deduper, &value_deduper](BaseItem *param_item) {
auto *field_item = static_cast<FieldItem *>(param_item);
panda_file::DeduplicateAnnotations(field_item->GetRuntimeAnnotations(), &annotation_deduper,
&value_deduper);
panda_file::DeduplicateAnnotations(field_item->GetAnnotations(), &annotation_deduper, &value_deduper);
panda_file::DeduplicateAnnotations(field_item->GetRuntimeTypeAnnotations(), &annotation_deduper,
&value_deduper);
panda_file::DeduplicateAnnotations(field_item->GetTypeAnnotations(), &annotation_deduper, &value_deduper);
return true;
});
}
}
void ItemContainer::DeduplicateItems(bool compute_layout)
{
if (compute_layout) {
ComputeLayout();
}
DeduplicateCodeAndDebugInfo();
DeduplicateAnnotations();
}
uint32_t ItemContainer::ComputeLayout()
{
uint32_t num_classes = class_map_.size();
uint32_t num_literalarrays = literalarray_map_.size();
uint32_t class_idx_offset = sizeof(File::Header);
uint32_t cur_offset = class_idx_offset + (num_classes + num_literalarrays) * ID_SIZE;
UpdateOrderIndexes();
UpdateLiteralIndexes();
RebuildRegionSection();
RebuildLineNumberProgramIndex();
region_section_item_.SetOffset(cur_offset);
region_section_item_.ComputeLayout();
cur_offset += region_section_item_.GetSize();
for (auto &item : foreign_items_) {
cur_offset = RoundUp(cur_offset, item->Alignment());
item->SetOffset(cur_offset);
item->ComputeLayout();
cur_offset += item->GetSize();
}
for (auto &item : items_) {
if (!item->NeedsEmit()) {
continue;
}
cur_offset = RoundUp(cur_offset, item->Alignment());
item->SetOffset(cur_offset);
item->ComputeLayout();
cur_offset += item->GetSize();
}
// Line number program should be last because it's size is known only after deduplication
cur_offset = RoundUp(cur_offset, line_number_program_index_item_.Alignment());
line_number_program_index_item_.SetOffset(cur_offset);
line_number_program_index_item_.ComputeLayout();
cur_offset += line_number_program_index_item_.GetSize();
end_->SetOffset(cur_offset);
return cur_offset;
}
void ItemContainer::RebuildLineNumberProgramIndex()
{
line_number_program_index_item_.Reset();
line_number_program_index_item_.UpdateItems(nullptr, nullptr);
}
void ItemContainer::RebuildRegionSection()
{
region_section_item_.Reset();
for (auto &item : foreign_items_) {
ProcessIndexDependecies(item.get());
}
for (auto &item : items_) {
if (!item->NeedsEmit()) {
continue;
}
ProcessIndexDependecies(item.get());
}
if (!region_section_item_.IsEmpty()) {
region_section_item_.GetCurrentHeader()->SetEnd(end_);
}
region_section_item_.UpdateItems();
}
void ItemContainer::UpdateOrderIndexes()
{
size_t idx = 0;
for (auto &item : foreign_items_) {
item->SetOrderIndex(idx++);
item->Visit([&idx](BaseItem *param_item) {
param_item->SetOrderIndex(idx++);
return true;
});
}
for (auto &item : items_) {
if (!item->NeedsEmit()) {
continue;
}
item->SetOrderIndex(idx++);
item->Visit([&idx](BaseItem *param_item) {
param_item->SetOrderIndex(idx++);
return true;
});
}
end_->SetOrderIndex(idx++);
}
void ItemContainer::UpdateLiteralIndexes()
{
size_t idx = 0;
for (auto &it : literalarray_map_) {
it.second->SetIndex(idx++);
}
}
void ItemContainer::ReorderItems(panda::panda_file::pgo::ProfileOptimizer *profile_opt)
{
profile_opt->ProfileGuidedRelayout(items_);
}
void ItemContainer::ProcessIndexDependecies(BaseItem *item)
{
auto deps = item->GetIndexDependencies();
item->Visit([&deps](BaseItem *param_item) {
const auto &item_deps = param_item->GetIndexDependencies();
deps.insert(deps.end(), item_deps.cbegin(), item_deps.cend());
return true;
});
if (region_section_item_.IsEmpty()) {
region_section_item_.AddHeader();
region_section_item_.GetCurrentHeader()->SetStart(item);
}
if (region_section_item_.GetCurrentHeader()->Add(deps)) {
return;
}
region_section_item_.GetCurrentHeader()->SetEnd(item);
region_section_item_.AddHeader();
region_section_item_.GetCurrentHeader()->SetStart(item);
if (!region_section_item_.GetCurrentHeader()->Add(deps)) {
LOG(FATAL, PANDAFILE) << "Cannot add " << deps.size() << " items to index";
}
}
bool ItemContainer::WriteHeaderIndexInfo(Writer *writer)
{
if (!writer->Write<uint32_t>(class_map_.size())) {
return false;
}
if (!writer->Write<uint32_t>(sizeof(File::Header))) {
return false;
}
if (!writer->Write<uint32_t>(line_number_program_index_item_.GetNumItems())) {
return false;
}
if (!writer->Write<uint32_t>(line_number_program_index_item_.GetOffset())) {
return false;
}
if (!writer->Write<uint32_t>(literalarray_map_.size())) {
return false;
}
uint32_t literalarray_idx_offset = sizeof(File::Header) + class_map_.size() * ID_SIZE;
if (!writer->Write<uint32_t>(literalarray_idx_offset)) {
return false;
}
if (!writer->Write<uint32_t>(region_section_item_.GetNumHeaders())) {
return false;
}
size_t index_section_off = literalarray_idx_offset + literalarray_map_.size() * ID_SIZE;
return writer->Write<uint32_t>(index_section_off);
}
bool ItemContainer::WriteHeader(Writer *writer, ssize_t *checksum_offset)
{
uint32_t file_size = ComputeLayout();
std::vector<uint8_t> magic;
magic.assign(File::MAGIC.cbegin(), File::MAGIC.cend());
if (!writer->WriteBytes(magic)) {
return false;
}
*checksum_offset = static_cast<ssize_t>(writer->GetOffset());
uint32_t checksum = 0;
if (!writer->Write(checksum)) {
return false;
}
writer->CountChecksum(true);
std::vector<uint8_t> version_vec(std::begin(VERSION), std::end(VERSION));
if (!writer->WriteBytes(version_vec)) {
return false;
}
if (!writer->Write(file_size)) {
return false;
}
uint32_t foreign_offset = GetForeignOffset();
if (!writer->Write(foreign_offset)) {
return false;
}
uint32_t foreign_size = GetForeignSize();
if (!writer->Write(foreign_size)) {
return false;
}
if (!writer->Write<uint32_t>(static_cast<uint32_t>(is_quickened_))) {
return false;
}
return WriteHeaderIndexInfo(writer);
}
bool ItemContainer::Write(Writer *writer, bool deduplicate_items, bool compute_layout)
{
if (deduplicate_items) {
DeduplicateItems(compute_layout);
}
ssize_t checksum_offset = -1;
if (!WriteHeader(writer, &checksum_offset)) {
return false;
}
ASSERT(checksum_offset != -1);
// Write class idx
for (auto &entry : class_map_) {
if (!writer->Write(entry.second->GetOffset())) {
return false;
}
}
// Write literalArray idx
for (auto &entry : literalarray_map_) {
if (!writer->Write(entry.second->GetOffset())) {
return false;
}
}
// Write index section
if (!region_section_item_.Write(writer)) {
return false;
}
for (auto &item : foreign_items_) {
if (!writer->Align(item->Alignment())) {
return false;
}
if (!item->Write(writer)) {
return false;
}
}
for (auto &item : items_) {
if (!item->NeedsEmit()) {
continue;
}
if (!writer->Align(item->Alignment())) {
return false;
}
if (!item->Write(writer)) {
return false;
}
}
if (!writer->Align(line_number_program_index_item_.Alignment())) {
return false;
}
// Write line number program idx
if (!line_number_program_index_item_.Write(writer)) {
return false;
}
writer->CountChecksum(false);
writer->WriteChecksum(checksum_offset);
return true;
}
std::map<std::string, size_t> ItemContainer::GetStat()
{
std::map<std::string, size_t> stat;
DeduplicateItems();
ComputeLayout();
stat["header_item"] = sizeof(File::Header);
stat["class_idx_item"] = class_map_.size() * ID_SIZE;
stat["line_number_program_idx_item"] = line_number_program_index_item_.GetNumItems() * ID_SIZE;
stat["literalarray_idx"] = literalarray_map_.size() * ID_SIZE;
stat["region_section_item"] = region_section_item_.GetSize();
stat["foreign_item"] = GetForeignSize();
size_t num_ins = 0;
size_t codesize = 0;
for (auto &item : items_) {
if (!item->NeedsEmit()) {
continue;
}
const auto &name = item->GetName();
size_t size = item->GetSize();
auto it = stat.find(name);
if (it != stat.cend()) {
stat[name] += size;
} else if (size != 0) {
stat[name] = size;
}
if (name == "code_item") {
num_ins += static_cast<CodeItem *>(item.get())->GetNumInstructions();
codesize += static_cast<CodeItem *>(item.get())->GetCodeSize();
}
}
stat["instructions_number"] = num_ins;
stat["codesize"] = codesize;
return stat;
}
void ItemContainer::DumpItemsStat(std::ostream &os) const
{
struct Stat {
size_t n;
size_t total_size;
};
std::map<std::string, Stat> stat;
auto collect_stat = [&stat](auto &items) {
for (auto &item : items) {
if (!item->NeedsEmit()) {
continue;
}
const auto &name = item->GetName();
size_t size = item->GetSize();
auto it = stat.find(name);
if (it != stat.cend()) {
stat[name].n += 1;
stat[name].total_size += size;
} else if (size != 0) {
stat[name] = {1, size};
}
}
};
collect_stat(foreign_items_);
collect_stat(items_);
for (auto &[name, elem] : stat) {
os << name << ":" << std::endl;
os << " n = " << elem.n << std::endl;
os << " total size = " << elem.total_size << std::endl;
}
}
size_t ItemContainer::GetForeignOffset() const
{
if (foreign_items_.empty()) {
return 0;
}
return foreign_items_.front()->GetOffset();
}
size_t ItemContainer::GetForeignSize() const
{
if (foreign_items_.empty()) {
return 0;
}
size_t begin = foreign_items_.front()->GetOffset();
size_t end = foreign_items_.back()->GetOffset() + foreign_items_.back()->GetSize();
return end - begin;
}
bool ItemContainer::RegionHeaderItem::Write(Writer *writer)
{
ASSERT(GetOffset() == writer->GetOffset());
ASSERT(start_ != nullptr);
ASSERT(start_->GetOffset() != 0);
ASSERT(end_ != nullptr);
ASSERT(end_->GetOffset() != 0);
if (!writer->Write<uint32_t>(start_->GetOffset())) {
return false;
}
if (!writer->Write<uint32_t>(end_->GetOffset())) {
return false;
}
for (auto *index_item : indexes_) {
if (!writer->Write<uint32_t>(index_item->GetNumItems())) {
return false;
}
ASSERT(index_item->GetOffset() != 0);
if (!writer->Write<uint32_t>(index_item->GetOffset())) {
return false;
}
}
return true;
}
bool ItemContainer::RegionHeaderItem::Add(const std::list<IndexedItem *> &items)
{
std::list<IndexedItem *> added_items;
for (auto *item : items) {
auto type = item->GetIndexType();
ASSERT(type != IndexType::NONE);
auto *index_item = GetIndexByType(type);
if (index_item->Has(item)) {
continue;
}
if (!index_item->Add(item)) {
Remove(added_items);
return false;
}
added_items.push_back(item);
}
return true;
}
void ItemContainer::RegionHeaderItem::Remove(const std::list<IndexedItem *> &items)
{
for (auto *item : items) {
auto type = item->GetIndexType();
ASSERT(type != IndexType::NONE);
auto *index_item = GetIndexByType(type);
index_item->Remove(item);
}
}
bool ItemContainer::IndexItem::Write(Writer *writer)
{
ASSERT(GetOffset() == writer->GetOffset());
for (auto *item : index_) {
if (!writer->Write<uint32_t>(item->GetOffset())) {
return false;
}
}
return true;
}
ItemTypes ItemContainer::IndexItem::GetItemType() const
{
switch (type_) {
case IndexType::CLASS:
return ItemTypes::CLASS_INDEX_ITEM;
case IndexType::METHOD:
return ItemTypes::METHOD_INDEX_ITEM;
case IndexType::FIELD:
return ItemTypes::FIELD_INDEX_ITEM;
case IndexType::PROTO:
return ItemTypes::PROTO_INDEX_ITEM;
case IndexType::LINE_NUMBER_PROG:
return ItemTypes::LINE_NUMBER_PROGRAM_INDEX_ITEM;
default:
break;
}
UNREACHABLE();
}
bool ItemContainer::IndexItem::Add(IndexedItem *item)
{
auto size = index_.size();
ASSERT(size <= max_index_);
if (size == max_index_) {
return false;
}
auto res = index_.insert(item);
ASSERT(res.second);
return res.second;
}
void ItemContainer::RegionSectionItem::AddHeader()
{
std::vector<IndexItem *> index_items;
for (size_t i = 0; i < INDEX_COUNT_16; i++) {
auto type = static_cast<IndexType>(i);
indexes_.emplace_back(type, MAX_INDEX_16);
index_items.push_back(&indexes_.back());
}
headers_.emplace_back(index_items);
}
size_t ItemContainer::RegionSectionItem::CalculateSize() const
{
size_t size = headers_.size() * sizeof(File::RegionHeader);
for (auto &index_item : indexes_) {
size += index_item.GetSize();
}
return size;
}
void ItemContainer::RegionSectionItem::ComputeLayout()
{
size_t offset = GetOffset();
for (auto &header : headers_) {
header.SetOffset(offset);
header.ComputeLayout();
offset += header.GetSize();
}
for (auto &index : indexes_) {
index.SetOffset(offset);
index.ComputeLayout();
offset += index.GetSize();
}
}
bool ItemContainer::RegionSectionItem::Write(Writer *writer)
{
ASSERT(GetOffset() == writer->GetOffset());
for (auto &header : headers_) {
if (!header.Write(writer)) {
return false;
}
}
for (auto &index : indexes_) {
if (!index.Write(writer)) {
return false;
}
}
return true;
}
ItemContainer::ProtoKey::ProtoKey(TypeItem *ret_type, const std::vector<MethodParamItem> &params)
{
Add(ret_type);
for (const auto &param : params) {
Add(param.GetType());
}
size_t shorty_hash = std::hash<std::string>()(shorty_);
size_t ret_type_hash = std::hash<TypeItem *>()(ret_type);
// combine hashes of shorty and ref_types
hash_ = panda::MergeHashes(shorty_hash, ret_type_hash);
// combine hashes of all param types
for (const auto &item : params) {
size_t param_type_hash = std::hash<TypeItem *>()(item.GetType());
hash_ = panda::MergeHashes(hash_, param_type_hash);
}
}
void ItemContainer::ProtoKey::Add(TypeItem *item)
{
auto type = item->GetType();
shorty_.append(Type::GetSignatureByTypeId(type));
if (type.IsReference()) {
ref_types_.push_back(item);
}
}
} // namespace panda::panda_file
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/openharmony-sig/arkcompiler_runtime_core.git
git@gitee.com:openharmony-sig/arkcompiler_runtime_core.git
openharmony-sig
arkcompiler_runtime_core
arkcompiler_runtime_core
master

搜索帮助