代码拉取完成,页面将自动刷新
/**
* 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.
*/
#ifndef LIBPANDAFILE_FILE_ITEM_CONTAINER_H_
#define LIBPANDAFILE_FILE_ITEM_CONTAINER_H_
#include "file_items.h"
#include "file_writer.h"
#include "pgo.h"
#include <list>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <string_view>
#include <unordered_map>
#include <unordered_set>
namespace panda::panda_file {
class ItemDeduper;
class ItemContainer {
public:
ItemContainer();
~ItemContainer() = default;
NO_COPY_SEMANTIC(ItemContainer);
NO_MOVE_SEMANTIC(ItemContainer);
constexpr static std::string_view GetGlobalClassName()
{
return "L_GLOBAL;";
}
StringItem *GetOrCreateStringItem(const std::string &str);
LiteralArrayItem *GetOrCreateLiteralArrayItem(const std::string &id);
ClassItem *GetOrCreateClassItem(const std::string &str);
ForeignClassItem *GetOrCreateForeignClassItem(const std::string &str);
ScalarValueItem *GetOrCreateIntegerValueItem(uint32_t v);
ScalarValueItem *GetOrCreateLongValueItem(uint64_t v);
ScalarValueItem *GetOrCreateFloatValueItem(float v);
ScalarValueItem *GetOrCreateDoubleValueItem(double v);
ScalarValueItem *GetOrCreateIdValueItem(BaseItem *v);
ClassItem *GetOrCreateGlobalClassItem()
{
return GetOrCreateClassItem(std::string(GetGlobalClassName()));
}
ProtoItem *GetOrCreateProtoItem(TypeItem *ret_type, const std::vector<MethodParamItem> ¶ms);
PrimitiveTypeItem *GetOrCreatePrimitiveTypeItem(Type type);
PrimitiveTypeItem *GetOrCreatePrimitiveTypeItem(Type::TypeId type);
LineNumberProgramItem *CreateLineNumberProgramItem();
void IncRefLineNumberProgramItem(LineNumberProgramItem *it);
void SetQuickened()
{
is_quickened_ = true;
}
bool IsQuickened() const
{
return is_quickened_;
}
template <class T, class... Args>
T *CreateItem(Args &&...args)
{
static_assert(!std::is_same_v<T, StringItem>, "Use GetOrCreateStringItem to create StringItem");
static_assert(!std::is_same_v<T, ClassItem>, "Use GetOrCreateClassItem to create ClassItem");
static_assert(!std::is_same_v<T, ForeignClassItem>,
"Use GetOrCreateForeignClassItem to create ForeignClassItem");
static_assert(!std::is_same_v<T, ValueItem>, "Use GetOrCreateValueItem functions to create ValueItem");
static_assert(!std::is_same_v<T, ProtoItem>, "Use GetOrCreateProtoItem to create ValueItem");
static_assert(!std::is_same_v<T, LineNumberProgramItem>,
"Use CreateLineNumberProgramItem to create LineNumberProgramItem");
static_assert(!std::is_same_v<T, PrimitiveTypeItem>,
"Use GetOrCreatePrimitiveTypeItem to create PrimitiveTypeItem");
static_assert(!std::is_same_v<T, MethodItem>, "Use ClassItem instance to create MethodItem");
static_assert(!std::is_same_v<T, FieldItem>, "Use ClassItem instance to create FieldItem");
auto ptr = std::make_unique<T>(std::forward<Args>(args)...);
auto ret = ptr.get();
if (ptr->IsForeign()) {
foreign_items_.emplace_back(std::move(ptr));
} else {
items_.insert(GetInsertPosition<T>(), std::move(ptr));
}
return ret;
}
uint32_t ComputeLayout();
bool Write(Writer *writer, bool deduplicate_items = true, bool compute_layout = true);
std::map<std::string, size_t> GetStat();
void DumpItemsStat(std::ostream &os) const;
std::unordered_map<std::string, StringItem *> *GetStringMap()
{
return &string_map_;
}
LiteralArrayItem *GetLiteralArrayItem(const std::string &key)
{
return literalarray_map_.at(key);
}
std::map<std::string, BaseClassItem *> *GetClassMap()
{
return &class_map_;
}
std::unordered_map<uint32_t, ValueItem *> *GetIntValueMap()
{
return &int_value_map_;
}
std::unordered_map<uint64_t, ValueItem *> *GetLongValueMap()
{
return &long_value_map_;
}
std::unordered_map<uint32_t, ValueItem *> *GetFloatValueMap()
{
return &float_value_map_;
}
std::unordered_map<uint64_t, ValueItem *> *GetDoubleValueMap()
{
return &double_value_map_;
}
std::unordered_map<BaseItem *, ValueItem *> *GetScalarValueMap()
{
return &id_value_map_;
}
ProtoItem *GetProtoItem(TypeItem *ret_type, const std::vector<MethodParamItem> ¶ms)
{
return proto_map_.at(ProtoKey {ret_type, params});
}
std::unordered_map<Type::TypeId, PrimitiveTypeItem *> *GetPrimitiveTypeMap()
{
return &primitive_type_map_;
}
const std::list<std::unique_ptr<BaseItem>> &GetItems() const
{
return items_;
}
const std::vector<std::unique_ptr<BaseItem>> &GetForeignItems()
{
return foreign_items_;
}
BaseItem *GetEndItem()
{
return end_;
}
void ReorderItems(panda::panda_file::pgo::ProfileOptimizer *profile_opt);
void DeduplicateItems(bool compute_layout = true);
void DeduplicateCodeAndDebugInfo();
void DeduplicateAnnotations();
void DeduplicateLineNumberProgram(DebugInfoItem *item, ItemDeduper *deduper);
void DeduplicateDebugInfo(MethodItem *method, ItemDeduper *debug_info_deduper,
ItemDeduper *line_number_program_deduper);
private:
template <class T>
auto GetInsertPosition()
{
if (std::is_same_v<T, CodeItem>) {
return code_items_end_;
}
if (std::is_same_v<T, DebugInfoItem>) {
return debug_items_end_;
}
if (std::is_same_v<T, AnnotationItem> || std::is_base_of_v<ValueItem, T>) {
return annotation_items_end_;
}
return items_end_;
}
class IndexItem : public BaseItem {
public:
IndexItem(IndexType type, size_t max_index) : type_(type), max_index_(max_index)
{
ASSERT(type_ != IndexType::NONE);
}
~IndexItem() override = default;
DEFAULT_COPY_SEMANTIC(IndexItem);
NO_MOVE_SEMANTIC(IndexItem);
size_t Alignment() override
{
return sizeof(uint32_t);
}
bool Write(Writer *writer) override;
ItemTypes GetItemType() const override;
bool Add(IndexedItem *item);
bool Has(IndexedItem *item) const
{
auto res = index_.find(item);
return res != index_.cend();
}
void Remove(IndexedItem *item)
{
index_.erase(item);
}
size_t GetNumItems() const
{
return index_.size();
}
void UpdateItems(BaseItem *start, BaseItem *end)
{
size_t i = 0;
for (auto *item : index_) {
item->SetIndex(start, end, i++);
}
}
void Reset()
{
for (auto *item : index_) {
item->ClearIndexes();
}
}
protected:
size_t CalculateSize() const override
{
return index_.size() * ID_SIZE;
}
private:
struct Comparator {
bool operator()(IndexedItem *item1, IndexedItem *item2) const noexcept
{
auto index_type = item1->GetIndexType();
if (index_type == IndexType::CLASS) {
auto type_item1 = static_cast<TypeItem *>(item1);
auto type_item2 = static_cast<TypeItem *>(item2);
auto type_id1 = static_cast<size_t>(type_item1->GetType().GetId());
auto type_id2 = static_cast<size_t>(type_item2->GetType().GetId());
if (type_id1 != type_id2) {
return type_id1 < type_id2;
}
}
if (index_type == IndexType::LINE_NUMBER_PROG) {
auto ref_count1 = item1->GetRefCount();
auto ref_count2 = item2->GetRefCount();
if (ref_count1 != ref_count2) {
return ref_count1 > ref_count2;
}
}
return item1->GetItemAllocId() < item2->GetItemAllocId();
}
};
IndexType type_;
size_t max_index_;
std::set<IndexedItem *, Comparator> index_;
};
class LineNumberProgramIndexItem : public IndexItem {
public:
LineNumberProgramIndexItem() : IndexItem(IndexType::LINE_NUMBER_PROG, MAX_INDEX_32) {}
~LineNumberProgramIndexItem() override = default;
DEFAULT_COPY_SEMANTIC(LineNumberProgramIndexItem);
NO_MOVE_SEMANTIC(LineNumberProgramIndexItem);
void IncRefCount(LineNumberProgramItem *item)
{
ASSERT(item->GetRefCount() > 0);
ASSERT(Has(item));
Remove(item);
item->IncRefCount();
Add(item);
}
void DecRefCount(LineNumberProgramItem *item)
{
ASSERT(Has(item));
Remove(item);
item->DecRefCount();
if (item->GetRefCount() == 0) {
item->SetNeedsEmit(false);
} else {
Add(item);
}
}
};
class RegionHeaderItem : public BaseItem {
public:
explicit RegionHeaderItem(std::vector<IndexItem *> indexes) : indexes_(std::move(indexes))
{
ASSERT(indexes_.size() == INDEX_COUNT_16);
}
~RegionHeaderItem() override = default;
DEFAULT_COPY_SEMANTIC(RegionHeaderItem);
NO_MOVE_SEMANTIC(RegionHeaderItem);
size_t Alignment() override
{
return ID_SIZE;
}
bool Write(Writer *writer) override;
ItemTypes GetItemType() const override
{
return ItemTypes::REGION_HEADER;
}
bool Add(const std::list<IndexedItem *> &items);
void Remove(const std::list<IndexedItem *> &items);
void SetStart(BaseItem *item)
{
start_ = item;
}
void SetEnd(BaseItem *item)
{
end_ = item;
}
void UpdateItems()
{
for (auto *index : indexes_) {
index->UpdateItems(start_, end_);
}
}
protected:
size_t CalculateSize() const override
{
return sizeof(File::RegionHeader);
}
private:
IndexItem *GetIndexByType(IndexType type) const
{
auto i = static_cast<size_t>(type);
return indexes_[i];
}
BaseItem *start_ {nullptr};
BaseItem *end_ {nullptr};
std::vector<IndexItem *> indexes_;
};
class RegionSectionItem : public BaseItem {
public:
size_t Alignment() override
{
return ID_SIZE;
}
bool Write(Writer *writer) override;
ItemTypes GetItemType() const override
{
return ItemTypes::REGION_SECTION;
}
void Reset()
{
headers_.clear();
for (auto &index : indexes_) {
index.Reset();
}
indexes_.clear();
}
void AddHeader();
RegionHeaderItem *GetCurrentHeader()
{
return &headers_.back();
}
bool IsEmpty() const
{
return headers_.empty();
}
size_t GetNumHeaders() const
{
return headers_.size();
}
void ComputeLayout() override;
void UpdateItems()
{
for (auto &header : headers_) {
header.UpdateItems();
}
}
protected:
size_t CalculateSize() const override;
private:
std::list<RegionHeaderItem> headers_;
std::list<IndexItem> indexes_;
};
class ProtoKey {
public:
ProtoKey(TypeItem *ret_type, const std::vector<MethodParamItem> ¶ms);
~ProtoKey() = default;
DEFAULT_COPY_SEMANTIC(ProtoKey);
NO_MOVE_SEMANTIC(ProtoKey);
size_t GetHash() const
{
return hash_;
}
bool operator==(const ProtoKey &key) const
{
return shorty_ == key.shorty_ && ref_types_ == key.ref_types_;
}
private:
void Add(TypeItem *item);
size_t hash_;
std::string shorty_;
std::vector<TypeItem *> ref_types_;
};
struct ProtoKeyHash {
size_t operator()(const ProtoKey &key) const noexcept
{
return key.GetHash();
};
};
struct LiteralArrayCompare {
bool operator()(const std::string &lhs, const std::string &rhs) const
{
return lhs.length() < rhs.length() || (lhs.length() == rhs.length() && lhs < rhs);
}
};
class EndItem : public BaseItem {
public:
EndItem()
{
SetNeedsEmit(false);
}
~EndItem() override = default;
DEFAULT_COPY_SEMANTIC(EndItem);
NO_MOVE_SEMANTIC(EndItem);
size_t CalculateSize() const override
{
return 0;
}
bool Write([[maybe_unused]] Writer *writer) override
{
return true;
}
ItemTypes GetItemType() const override
{
return ItemTypes::END_ITEM;
}
};
bool WriteHeader(Writer *writer, ssize_t *checksum_offset);
bool WriteHeaderIndexInfo(Writer *writer);
void RebuildRegionSection();
void RebuildLineNumberProgramIndex();
void UpdateOrderIndexes();
void UpdateLiteralIndexes();
void ProcessIndexDependecies(BaseItem *item);
size_t GetForeignOffset() const;
size_t GetForeignSize() const;
std::unordered_map<std::string, StringItem *> string_map_;
std::map<std::string, LiteralArrayItem *, LiteralArrayCompare> literalarray_map_;
std::map<std::string, BaseClassItem *> class_map_;
std::unordered_map<uint32_t, ValueItem *> int_value_map_;
std::unordered_map<uint64_t, ValueItem *> long_value_map_;
// NB! For f32 and f64 value maps we use integral keys
// (in fact, bit patterns of corresponding values) to
// workaround 0.0 == -0.0 semantics.
std::unordered_map<uint32_t, ValueItem *> float_value_map_;
std::unordered_map<uint64_t, ValueItem *> double_value_map_;
std::unordered_map<BaseItem *, ValueItem *> id_value_map_;
std::unordered_map<ProtoKey, ProtoItem *, ProtoKeyHash> proto_map_;
std::unordered_map<Type::TypeId, PrimitiveTypeItem *> primitive_type_map_;
std::list<std::unique_ptr<BaseItem>> items_;
std::vector<std::unique_ptr<BaseItem>> foreign_items_;
RegionSectionItem region_section_item_;
LineNumberProgramIndexItem line_number_program_index_item_;
std::list<std::unique_ptr<BaseItem>>::iterator items_end_;
std::list<std::unique_ptr<BaseItem>>::iterator annotation_items_end_;
std::list<std::unique_ptr<BaseItem>>::iterator code_items_end_;
std::list<std::unique_ptr<BaseItem>>::iterator debug_items_end_;
BaseItem *end_;
bool is_quickened_ = false;
};
} // namespace panda::panda_file
#endif // LIBPANDAFILE_FILE_ITEM_CONTAINER_H_
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。