1b1994897Sopenharmony_ci/**
2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License.
5b1994897Sopenharmony_ci * You may obtain a copy of the License at
6b1994897Sopenharmony_ci *
7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8b1994897Sopenharmony_ci *
9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and
13b1994897Sopenharmony_ci * limitations under the License.
14b1994897Sopenharmony_ci */
15b1994897Sopenharmony_ci
16b1994897Sopenharmony_ci#ifndef LIBPANDAFILE_FILE_ITEM_CONTAINER_H
17b1994897Sopenharmony_ci#define LIBPANDAFILE_FILE_ITEM_CONTAINER_H
18b1994897Sopenharmony_ci
19b1994897Sopenharmony_ci#include "file_items.h"
20b1994897Sopenharmony_ci#include "file_writer.h"
21b1994897Sopenharmony_ci#include "pgo.h"
22b1994897Sopenharmony_ci
23b1994897Sopenharmony_ci#include <list>
24b1994897Sopenharmony_ci#include <map>
25b1994897Sopenharmony_ci#include <memory>
26b1994897Sopenharmony_ci#include <set>
27b1994897Sopenharmony_ci#include <string>
28b1994897Sopenharmony_ci#include <unordered_map>
29b1994897Sopenharmony_ci#include <unordered_set>
30b1994897Sopenharmony_ci
31b1994897Sopenharmony_cinamespace panda::panda_file {
32b1994897Sopenharmony_ci
33b1994897Sopenharmony_ciclass ItemDeduper;
34b1994897Sopenharmony_ci
35b1994897Sopenharmony_ciclass ItemContainer {
36b1994897Sopenharmony_cipublic:
37b1994897Sopenharmony_ci    explicit ItemContainer();
38b1994897Sopenharmony_ci    ~ItemContainer() = default;
39b1994897Sopenharmony_ci    NO_COPY_SEMANTIC(ItemContainer);
40b1994897Sopenharmony_ci    NO_MOVE_SEMANTIC(ItemContainer);
41b1994897Sopenharmony_ci
42b1994897Sopenharmony_ci    StringItem *GetOrCreateStringItem(const std::string &str);
43b1994897Sopenharmony_ci
44b1994897Sopenharmony_ci    LiteralArrayItem *GetOrCreateLiteralArrayItem(const std::string &id);
45b1994897Sopenharmony_ci
46b1994897Sopenharmony_ci    ClassItem *GetOrCreateClassItem(const std::string &str);
47b1994897Sopenharmony_ci
48b1994897Sopenharmony_ci    ForeignClassItem *GetOrCreateForeignClassItem(const std::string &str);
49b1994897Sopenharmony_ci
50b1994897Sopenharmony_ci    ScalarValueItem *GetOrCreateIntegerValueItem(uint32_t v);
51b1994897Sopenharmony_ci
52b1994897Sopenharmony_ci    ScalarValueItem *GetOrCreateLongValueItem(uint64_t v);
53b1994897Sopenharmony_ci
54b1994897Sopenharmony_ci    ScalarValueItem *GetOrCreateFloatValueItem(float v);
55b1994897Sopenharmony_ci
56b1994897Sopenharmony_ci    ScalarValueItem *GetOrCreateDoubleValueItem(double v);
57b1994897Sopenharmony_ci
58b1994897Sopenharmony_ci    ScalarValueItem *GetOrCreateIdValueItem(BaseItem *v);
59b1994897Sopenharmony_ci
60b1994897Sopenharmony_ci    ClassItem *GetOrCreateGlobalClassItem()
61b1994897Sopenharmony_ci    {
62b1994897Sopenharmony_ci        return GetOrCreateClassItem("L_GLOBAL;");
63b1994897Sopenharmony_ci    }
64b1994897Sopenharmony_ci
65b1994897Sopenharmony_ci    ProtoItem *GetOrCreateProtoItem(TypeItem *ret_type, const std::vector<MethodParamItem> &params);
66b1994897Sopenharmony_ci
67b1994897Sopenharmony_ci    PrimitiveTypeItem *GetOrCreatePrimitiveTypeItem(Type type);
68b1994897Sopenharmony_ci
69b1994897Sopenharmony_ci    PrimitiveTypeItem *GetOrCreatePrimitiveTypeItem(Type::TypeId type);
70b1994897Sopenharmony_ci
71b1994897Sopenharmony_ci    LineNumberProgramItem *CreateLineNumberProgramItem();
72b1994897Sopenharmony_ci
73b1994897Sopenharmony_ci    template <class T, class... Args>
74b1994897Sopenharmony_ci    T *CreateItem(Args &&... args)
75b1994897Sopenharmony_ci    {
76b1994897Sopenharmony_ci        static_assert(!std::is_same_v<T, StringItem>, "Use GetOrCreateStringItem to create StringItem");
77b1994897Sopenharmony_ci        static_assert(!std::is_same_v<T, ClassItem>, "Use GetOrCreateClassItem to create ClassItem");
78b1994897Sopenharmony_ci        static_assert(!std::is_same_v<T, ForeignClassItem>,
79b1994897Sopenharmony_ci                      "Use GetOrCreateForeignClassItem to create ForeignClassItem");
80b1994897Sopenharmony_ci        static_assert(!std::is_same_v<T, ValueItem>, "Use GetOrCreateValueItem functions to create ValueItem");
81b1994897Sopenharmony_ci        static_assert(!std::is_same_v<T, ProtoItem>, "Use GetOrCreateProtoItem to create ValueItem");
82b1994897Sopenharmony_ci        static_assert(!std::is_same_v<T, LineNumberProgramItem>,
83b1994897Sopenharmony_ci                      "Use CreateLineNumberProgramItem to create LineNumberProgramItem");
84b1994897Sopenharmony_ci        static_assert(!std::is_same_v<T, PrimitiveTypeItem>,
85b1994897Sopenharmony_ci                      "Use GetOrCreatePrimitiveTypeItem to create PrimitiveTypeItem");
86b1994897Sopenharmony_ci        static_assert(!std::is_same_v<T, MethodItem>, "Use ClassItem instance to create MethodItem");
87b1994897Sopenharmony_ci        static_assert(!std::is_same_v<T, FieldItem>, "Use ClassItem instance to create FieldItem");
88b1994897Sopenharmony_ci
89b1994897Sopenharmony_ci        std::unique_ptr<T> ptr = nullptr;
90b1994897Sopenharmony_ci        if constexpr (std::is_same_v<T, ForeignFieldItem> || std::is_same_v<T, ForeignMethodItem> ||
91b1994897Sopenharmony_ci            std::is_same_v<T, ScalarValueItem> || std::is_same_v<T, ArrayValueItem> ||
92b1994897Sopenharmony_ci            std::is_same_v<T, LiteralArrayItem>) {
93b1994897Sopenharmony_ci            ptr = std::make_unique<T>(std::forward<Args>(args)..., this);
94b1994897Sopenharmony_ci        } else {
95b1994897Sopenharmony_ci            ptr = std::make_unique<T>(std::forward<Args>(args)...);
96b1994897Sopenharmony_ci        }
97b1994897Sopenharmony_ci
98b1994897Sopenharmony_ci        auto ret = ptr.get();
99b1994897Sopenharmony_ci        if (ptr->IsForeign()) {
100b1994897Sopenharmony_ci            foreign_items_.emplace_back(std::move(ptr));
101b1994897Sopenharmony_ci        } else {
102b1994897Sopenharmony_ci            items_.insert(GetInsertPosition<T>(), std::move(ptr));
103b1994897Sopenharmony_ci        }
104b1994897Sopenharmony_ci        return ret;
105b1994897Sopenharmony_ci    }
106b1994897Sopenharmony_ci
107b1994897Sopenharmony_ci    void ReLayout();
108b1994897Sopenharmony_ci    uint32_t ComputeLayout();
109b1994897Sopenharmony_ci    bool Write(Writer *writer, bool deduplicateItems = true);
110b1994897Sopenharmony_ci
111b1994897Sopenharmony_ci    std::map<std::string, size_t> GetStat();
112b1994897Sopenharmony_ci
113b1994897Sopenharmony_ci    void DumpItemsStat(std::ostream &os) const;
114b1994897Sopenharmony_ci
115b1994897Sopenharmony_ci    uint32_t CalculateRoundUpSize(uint32_t before, uint32_t after)
116b1994897Sopenharmony_ci    {
117b1994897Sopenharmony_ci        return after - before;
118b1994897Sopenharmony_ci    }
119b1994897Sopenharmony_ci
120b1994897Sopenharmony_ci    std::unordered_map<std::string, StringItem *> *GetStringMap()
121b1994897Sopenharmony_ci    {
122b1994897Sopenharmony_ci        return &string_map_;
123b1994897Sopenharmony_ci    }
124b1994897Sopenharmony_ci
125b1994897Sopenharmony_ci    LiteralArrayItem *GetLiteralArrayItem(const std::string &key)
126b1994897Sopenharmony_ci    {
127b1994897Sopenharmony_ci        return literalarray_map_.at(key);
128b1994897Sopenharmony_ci    }
129b1994897Sopenharmony_ci
130b1994897Sopenharmony_ci    std::map<std::string, BaseClassItem *> *GetClassMap()
131b1994897Sopenharmony_ci    {
132b1994897Sopenharmony_ci        return &class_map_;
133b1994897Sopenharmony_ci    }
134b1994897Sopenharmony_ci
135b1994897Sopenharmony_ci    std::unordered_map<uint32_t, ValueItem *> *GetIntValueMap()
136b1994897Sopenharmony_ci    {
137b1994897Sopenharmony_ci        return &int_value_map_;
138b1994897Sopenharmony_ci    }
139b1994897Sopenharmony_ci
140b1994897Sopenharmony_ci    std::unordered_map<uint64_t, ValueItem *> *GetLongValueMap()
141b1994897Sopenharmony_ci    {
142b1994897Sopenharmony_ci        return &long_value_map_;
143b1994897Sopenharmony_ci    }
144b1994897Sopenharmony_ci
145b1994897Sopenharmony_ci    std::unordered_map<uint32_t, ValueItem *> *GetFloatValueMap()
146b1994897Sopenharmony_ci    {
147b1994897Sopenharmony_ci        return &float_value_map_;
148b1994897Sopenharmony_ci    }
149b1994897Sopenharmony_ci
150b1994897Sopenharmony_ci    std::unordered_map<uint64_t, ValueItem *> *GetDoubleValueMap()
151b1994897Sopenharmony_ci    {
152b1994897Sopenharmony_ci        return &double_value_map_;
153b1994897Sopenharmony_ci    }
154b1994897Sopenharmony_ci
155b1994897Sopenharmony_ci    std::unordered_map<BaseItem *, ValueItem *> *GetScalarValueMap()
156b1994897Sopenharmony_ci    {
157b1994897Sopenharmony_ci        return &id_value_map_;
158b1994897Sopenharmony_ci    }
159b1994897Sopenharmony_ci
160b1994897Sopenharmony_ci    ProtoItem *GetProtoItem(TypeItem *retType, const std::vector<MethodParamItem> &params)
161b1994897Sopenharmony_ci    {
162b1994897Sopenharmony_ci        return proto_map_.at(ProtoKey {retType, params});
163b1994897Sopenharmony_ci    }
164b1994897Sopenharmony_ci
165b1994897Sopenharmony_ci    std::unordered_map<Type::TypeId, PrimitiveTypeItem *> *GetPrimitiveTypeMap()
166b1994897Sopenharmony_ci    {
167b1994897Sopenharmony_ci        return &primitive_type_map_;
168b1994897Sopenharmony_ci    }
169b1994897Sopenharmony_ci
170b1994897Sopenharmony_ci    std::list<std::unique_ptr<BaseItem>> &GetItems()
171b1994897Sopenharmony_ci    {
172b1994897Sopenharmony_ci        return items_;
173b1994897Sopenharmony_ci    }
174b1994897Sopenharmony_ci
175b1994897Sopenharmony_ci    const std::list<std::unique_ptr<BaseItem>> &GetItems() const
176b1994897Sopenharmony_ci    {
177b1994897Sopenharmony_ci        return items_;
178b1994897Sopenharmony_ci    }
179b1994897Sopenharmony_ci
180b1994897Sopenharmony_ci    const std::vector<std::unique_ptr<BaseItem>> &GetForeigtems()
181b1994897Sopenharmony_ci    {
182b1994897Sopenharmony_ci        return foreign_items_;
183b1994897Sopenharmony_ci    }
184b1994897Sopenharmony_ci
185b1994897Sopenharmony_ci    BaseItem *GetEndItem()
186b1994897Sopenharmony_ci    {
187b1994897Sopenharmony_ci        return end_;
188b1994897Sopenharmony_ci    }
189b1994897Sopenharmony_ci
190b1994897Sopenharmony_ci    void ReorderItems(panda::panda_file::pgo::ProfileOptimizer *profile_opt);
191b1994897Sopenharmony_ci
192b1994897Sopenharmony_ci    void DeduplicateItems(bool computeLayout = true);
193b1994897Sopenharmony_ci
194b1994897Sopenharmony_ci    void DeduplicateCodeAndDebugInfo();
195b1994897Sopenharmony_ci
196b1994897Sopenharmony_ci    void DeduplicateAnnotations();
197b1994897Sopenharmony_ci
198b1994897Sopenharmony_ci    void DeduplicateLineNumberProgram(DebugInfoItem *item, ItemDeduper *deduper);
199b1994897Sopenharmony_ci
200b1994897Sopenharmony_ci    void DeduplicateDebugInfo(MethodItem *method, ItemDeduper *debug_info_deduper,
201b1994897Sopenharmony_ci                              ItemDeduper *line_number_program_deduper);
202b1994897Sopenharmony_ci
203b1994897Sopenharmony_ci    size_t GetIndexedItemCount() const
204b1994897Sopenharmony_ci    {
205b1994897Sopenharmony_ci        return indexed_item_count_;
206b1994897Sopenharmony_ci    }
207b1994897Sopenharmony_ci
208b1994897Sopenharmony_ci    void IncIndexedItemCount()
209b1994897Sopenharmony_ci    {
210b1994897Sopenharmony_ci        indexed_item_count_++;
211b1994897Sopenharmony_ci    }
212b1994897Sopenharmony_ci
213b1994897Sopenharmony_ci    static void SetApi(uint8_t api)
214b1994897Sopenharmony_ci    {
215b1994897Sopenharmony_ci        ItemContainer::apiVersion = api;
216b1994897Sopenharmony_ci    }
217b1994897Sopenharmony_ci
218b1994897Sopenharmony_ci    static void SetSubApi(std::string subApi)
219b1994897Sopenharmony_ci    {
220b1994897Sopenharmony_ci        ItemContainer::subApiVersion = subApi;
221b1994897Sopenharmony_ci    }
222b1994897Sopenharmony_ci
223b1994897Sopenharmony_ci    static std::string GetSubApi()
224b1994897Sopenharmony_ci    {
225b1994897Sopenharmony_ci        return ItemContainer::subApiVersion;
226b1994897Sopenharmony_ci    }
227b1994897Sopenharmony_ci
228b1994897Sopenharmony_ci    static uint8_t GetApi()
229b1994897Sopenharmony_ci    {
230b1994897Sopenharmony_ci        return ItemContainer::apiVersion;
231b1994897Sopenharmony_ci    }
232b1994897Sopenharmony_ci
233b1994897Sopenharmony_ci    static uint8_t apiVersion;
234b1994897Sopenharmony_ci    static std::string subApiVersion;
235b1994897Sopenharmony_ci
236b1994897Sopenharmony_ciprivate:
237b1994897Sopenharmony_ci    template <class T>
238b1994897Sopenharmony_ci    auto GetInsertPosition()
239b1994897Sopenharmony_ci    {
240b1994897Sopenharmony_ci        if (std::is_same_v<T, CodeItem>) {
241b1994897Sopenharmony_ci            return code_items_end_;
242b1994897Sopenharmony_ci        }
243b1994897Sopenharmony_ci
244b1994897Sopenharmony_ci        if (std::is_same_v<T, DebugInfoItem>) {
245b1994897Sopenharmony_ci            return debug_items_end_;
246b1994897Sopenharmony_ci        }
247b1994897Sopenharmony_ci
248b1994897Sopenharmony_ci        return items_end_;
249b1994897Sopenharmony_ci    }
250b1994897Sopenharmony_ci
251b1994897Sopenharmony_ci    class IndexItem : public BaseItem {
252b1994897Sopenharmony_ci    public:
253b1994897Sopenharmony_ci        IndexItem(IndexType type, size_t max_index) : type_(type), max_index_(max_index)
254b1994897Sopenharmony_ci        {
255b1994897Sopenharmony_ci            ASSERT(type_ != IndexType::NONE);
256b1994897Sopenharmony_ci
257b1994897Sopenharmony_ci            const auto bc_version = GetVersionByApi(ItemContainer::GetApi(), ItemContainer::GetSubApi());
258b1994897Sopenharmony_ci            if (bc_version.value().front() >= API_12 && (type == IndexType::FIELD || type == IndexType::PROTO)) {
259b1994897Sopenharmony_ci                SetNeedsEmit(false);
260b1994897Sopenharmony_ci            }
261b1994897Sopenharmony_ci        }
262b1994897Sopenharmony_ci
263b1994897Sopenharmony_ci        ~IndexItem() override = default;
264b1994897Sopenharmony_ci
265b1994897Sopenharmony_ci        DEFAULT_COPY_SEMANTIC(IndexItem);
266b1994897Sopenharmony_ci        NO_MOVE_SEMANTIC(IndexItem);
267b1994897Sopenharmony_ci
268b1994897Sopenharmony_ci        size_t Alignment() override
269b1994897Sopenharmony_ci        {
270b1994897Sopenharmony_ci            return sizeof(uint32_t);
271b1994897Sopenharmony_ci        }
272b1994897Sopenharmony_ci
273b1994897Sopenharmony_ci        bool Write(Writer *writer) override;
274b1994897Sopenharmony_ci
275b1994897Sopenharmony_ci        ItemTypes GetItemType() const override;
276b1994897Sopenharmony_ci
277b1994897Sopenharmony_ci        bool Add(IndexedItem *item);
278b1994897Sopenharmony_ci
279b1994897Sopenharmony_ci        bool Has(IndexedItem *item) const
280b1994897Sopenharmony_ci        {
281b1994897Sopenharmony_ci            auto res = index_.find(item);
282b1994897Sopenharmony_ci            return res != index_.cend();
283b1994897Sopenharmony_ci        }
284b1994897Sopenharmony_ci
285b1994897Sopenharmony_ci        void Remove(IndexedItem *item)
286b1994897Sopenharmony_ci        {
287b1994897Sopenharmony_ci            index_.erase(item);
288b1994897Sopenharmony_ci        }
289b1994897Sopenharmony_ci
290b1994897Sopenharmony_ci        size_t GetNumItems() const
291b1994897Sopenharmony_ci        {
292b1994897Sopenharmony_ci            return index_.size();
293b1994897Sopenharmony_ci        }
294b1994897Sopenharmony_ci
295b1994897Sopenharmony_ci        void UpdateItems(BaseItem *start, BaseItem *end)
296b1994897Sopenharmony_ci        {
297b1994897Sopenharmony_ci            size_t i = 0;
298b1994897Sopenharmony_ci            for (auto *item : index_) {
299b1994897Sopenharmony_ci                item->SetIndex(start, end, i++);
300b1994897Sopenharmony_ci            }
301b1994897Sopenharmony_ci        }
302b1994897Sopenharmony_ci
303b1994897Sopenharmony_ci        void Reset()
304b1994897Sopenharmony_ci        {
305b1994897Sopenharmony_ci            for (auto *item : index_) {
306b1994897Sopenharmony_ci                item->ClearIndexes();
307b1994897Sopenharmony_ci            }
308b1994897Sopenharmony_ci        }
309b1994897Sopenharmony_ci
310b1994897Sopenharmony_ci    protected:
311b1994897Sopenharmony_ci        size_t CalculateSize() const override
312b1994897Sopenharmony_ci        {
313b1994897Sopenharmony_ci            if (NeedsEmit()) {
314b1994897Sopenharmony_ci                return index_.size() * ID_SIZE;
315b1994897Sopenharmony_ci            }
316b1994897Sopenharmony_ci            return 0;
317b1994897Sopenharmony_ci        }
318b1994897Sopenharmony_ci
319b1994897Sopenharmony_ci    private:
320b1994897Sopenharmony_ci        struct Comparator {
321b1994897Sopenharmony_ci            bool operator()(IndexedItem *item1, IndexedItem *item2) const noexcept
322b1994897Sopenharmony_ci            {
323b1994897Sopenharmony_ci                auto index_type = item1->GetIndexType();
324b1994897Sopenharmony_ci                if (index_type == IndexType::CLASS) {
325b1994897Sopenharmony_ci                    auto type_item1 = static_cast<TypeItem *>(item1);
326b1994897Sopenharmony_ci                    auto type_item2 = static_cast<TypeItem *>(item2);
327b1994897Sopenharmony_ci                    auto type_id1 = static_cast<size_t>(type_item1->GetType().GetId());
328b1994897Sopenharmony_ci                    auto type_id2 = static_cast<size_t>(type_item2->GetType().GetId());
329b1994897Sopenharmony_ci                    if (type_id1 != type_id2) {
330b1994897Sopenharmony_ci                        return type_id1 < type_id2;
331b1994897Sopenharmony_ci                    }
332b1994897Sopenharmony_ci                }
333b1994897Sopenharmony_ci
334b1994897Sopenharmony_ci                if (index_type == IndexType::LINE_NUMBER_PROG) {
335b1994897Sopenharmony_ci                    auto ref_count1 = item1->GetRefCount();
336b1994897Sopenharmony_ci                    auto ref_count2 = item2->GetRefCount();
337b1994897Sopenharmony_ci                    if (ref_count1 != ref_count2) {
338b1994897Sopenharmony_ci                        return ref_count1 > ref_count2;
339b1994897Sopenharmony_ci                    }
340b1994897Sopenharmony_ci                }
341b1994897Sopenharmony_ci
342b1994897Sopenharmony_ci                return item1->GetIndexedItemCount() < item2->GetIndexedItemCount();
343b1994897Sopenharmony_ci            }
344b1994897Sopenharmony_ci        };
345b1994897Sopenharmony_ci
346b1994897Sopenharmony_ci        IndexType type_;
347b1994897Sopenharmony_ci        size_t max_index_;
348b1994897Sopenharmony_ci        std::set<IndexedItem *, Comparator> index_;
349b1994897Sopenharmony_ci    };
350b1994897Sopenharmony_ci
351b1994897Sopenharmony_ci    class LineNumberProgramIndexItem : public IndexItem {
352b1994897Sopenharmony_ci    public:
353b1994897Sopenharmony_ci        LineNumberProgramIndexItem() : IndexItem(IndexType::LINE_NUMBER_PROG, MAX_INDEX_32) {}
354b1994897Sopenharmony_ci        ~LineNumberProgramIndexItem() override = default;
355b1994897Sopenharmony_ci        DEFAULT_COPY_SEMANTIC(LineNumberProgramIndexItem);
356b1994897Sopenharmony_ci        NO_MOVE_SEMANTIC(LineNumberProgramIndexItem);
357b1994897Sopenharmony_ci
358b1994897Sopenharmony_ci        void IncRefCount(LineNumberProgramItem *item)
359b1994897Sopenharmony_ci        {
360b1994897Sopenharmony_ci            ASSERT(Has(item));
361b1994897Sopenharmony_ci            Remove(item);
362b1994897Sopenharmony_ci            item->IncRefCount();
363b1994897Sopenharmony_ci            Add(item);
364b1994897Sopenharmony_ci        }
365b1994897Sopenharmony_ci
366b1994897Sopenharmony_ci        void DecRefCount(LineNumberProgramItem *item)
367b1994897Sopenharmony_ci        {
368b1994897Sopenharmony_ci            ASSERT(Has(item));
369b1994897Sopenharmony_ci            Remove(item);
370b1994897Sopenharmony_ci            item->DecRefCount();
371b1994897Sopenharmony_ci            Add(item);
372b1994897Sopenharmony_ci        }
373b1994897Sopenharmony_ci    };
374b1994897Sopenharmony_ci
375b1994897Sopenharmony_ci    class IndexHeaderItem : public BaseItem {
376b1994897Sopenharmony_ci    public:
377b1994897Sopenharmony_ci        explicit IndexHeaderItem(std::vector<IndexItem *> indexes) : indexes_(std::move(indexes))
378b1994897Sopenharmony_ci        {
379b1994897Sopenharmony_ci            ASSERT(indexes_.size() == INDEX_COUNT_16);
380b1994897Sopenharmony_ci        }
381b1994897Sopenharmony_ci
382b1994897Sopenharmony_ci        ~IndexHeaderItem() override = default;
383b1994897Sopenharmony_ci
384b1994897Sopenharmony_ci        DEFAULT_COPY_SEMANTIC(IndexHeaderItem);
385b1994897Sopenharmony_ci        NO_MOVE_SEMANTIC(IndexHeaderItem);
386b1994897Sopenharmony_ci
387b1994897Sopenharmony_ci        size_t Alignment() override
388b1994897Sopenharmony_ci        {
389b1994897Sopenharmony_ci            return ID_SIZE;
390b1994897Sopenharmony_ci        }
391b1994897Sopenharmony_ci
392b1994897Sopenharmony_ci        bool Write(Writer *writer) override;
393b1994897Sopenharmony_ci
394b1994897Sopenharmony_ci        ItemTypes GetItemType() const override
395b1994897Sopenharmony_ci        {
396b1994897Sopenharmony_ci            return ItemTypes::INDEX_HEADER;
397b1994897Sopenharmony_ci        }
398b1994897Sopenharmony_ci
399b1994897Sopenharmony_ci        bool Add(const std::list<IndexedItem *> &items);
400b1994897Sopenharmony_ci
401b1994897Sopenharmony_ci        void Remove(const std::list<IndexedItem *> &items);
402b1994897Sopenharmony_ci
403b1994897Sopenharmony_ci        void SetStart(BaseItem *item)
404b1994897Sopenharmony_ci        {
405b1994897Sopenharmony_ci            start_ = item;
406b1994897Sopenharmony_ci        }
407b1994897Sopenharmony_ci
408b1994897Sopenharmony_ci        void SetEnd(BaseItem *item)
409b1994897Sopenharmony_ci        {
410b1994897Sopenharmony_ci            end_ = item;
411b1994897Sopenharmony_ci        }
412b1994897Sopenharmony_ci
413b1994897Sopenharmony_ci        void UpdateItems()
414b1994897Sopenharmony_ci        {
415b1994897Sopenharmony_ci            for (auto *index : indexes_) {
416b1994897Sopenharmony_ci                index->UpdateItems(start_, end_);
417b1994897Sopenharmony_ci            }
418b1994897Sopenharmony_ci        }
419b1994897Sopenharmony_ci
420b1994897Sopenharmony_ci    protected:
421b1994897Sopenharmony_ci        size_t CalculateSize() const override
422b1994897Sopenharmony_ci        {
423b1994897Sopenharmony_ci            return sizeof(File::IndexHeader);
424b1994897Sopenharmony_ci        }
425b1994897Sopenharmony_ci
426b1994897Sopenharmony_ci    private:
427b1994897Sopenharmony_ci        IndexItem *IndexGetIndexByType(IndexType type) const
428b1994897Sopenharmony_ci        {
429b1994897Sopenharmony_ci            auto i = static_cast<size_t>(type);
430b1994897Sopenharmony_ci            return indexes_[i];
431b1994897Sopenharmony_ci        }
432b1994897Sopenharmony_ci
433b1994897Sopenharmony_ci        BaseItem *start_ {nullptr};
434b1994897Sopenharmony_ci        BaseItem *end_ {nullptr};
435b1994897Sopenharmony_ci        std::vector<IndexItem *> indexes_;
436b1994897Sopenharmony_ci    };
437b1994897Sopenharmony_ci
438b1994897Sopenharmony_ci    class IndexSectionItem : public BaseItem {
439b1994897Sopenharmony_ci    public:
440b1994897Sopenharmony_ci        size_t Alignment() override
441b1994897Sopenharmony_ci        {
442b1994897Sopenharmony_ci            return ID_SIZE;
443b1994897Sopenharmony_ci        }
444b1994897Sopenharmony_ci
445b1994897Sopenharmony_ci        bool Write(Writer *writer) override;
446b1994897Sopenharmony_ci
447b1994897Sopenharmony_ci        ItemTypes GetItemType() const override
448b1994897Sopenharmony_ci        {
449b1994897Sopenharmony_ci            return ItemTypes::INDEX_SECTION;
450b1994897Sopenharmony_ci        }
451b1994897Sopenharmony_ci
452b1994897Sopenharmony_ci        void Reset()
453b1994897Sopenharmony_ci        {
454b1994897Sopenharmony_ci            headers_.clear();
455b1994897Sopenharmony_ci
456b1994897Sopenharmony_ci            for (auto &index : indexes_) {
457b1994897Sopenharmony_ci                index.Reset();
458b1994897Sopenharmony_ci            }
459b1994897Sopenharmony_ci
460b1994897Sopenharmony_ci            indexes_.clear();
461b1994897Sopenharmony_ci        }
462b1994897Sopenharmony_ci
463b1994897Sopenharmony_ci        void AddHeader();
464b1994897Sopenharmony_ci
465b1994897Sopenharmony_ci        IndexHeaderItem *GetCurrentHeader()
466b1994897Sopenharmony_ci        {
467b1994897Sopenharmony_ci            return &headers_.back();
468b1994897Sopenharmony_ci        }
469b1994897Sopenharmony_ci
470b1994897Sopenharmony_ci        bool IsEmpty() const
471b1994897Sopenharmony_ci        {
472b1994897Sopenharmony_ci            return headers_.empty();
473b1994897Sopenharmony_ci        }
474b1994897Sopenharmony_ci
475b1994897Sopenharmony_ci        size_t GetNumHeaders() const
476b1994897Sopenharmony_ci        {
477b1994897Sopenharmony_ci            return headers_.size();
478b1994897Sopenharmony_ci        }
479b1994897Sopenharmony_ci
480b1994897Sopenharmony_ci        void ComputeLayout() override;
481b1994897Sopenharmony_ci
482b1994897Sopenharmony_ci        void UpdateItems()
483b1994897Sopenharmony_ci        {
484b1994897Sopenharmony_ci            for (auto &header : headers_) {
485b1994897Sopenharmony_ci                header.UpdateItems();
486b1994897Sopenharmony_ci            }
487b1994897Sopenharmony_ci        }
488b1994897Sopenharmony_ci
489b1994897Sopenharmony_ci    protected:
490b1994897Sopenharmony_ci        size_t CalculateSize() const override;
491b1994897Sopenharmony_ci
492b1994897Sopenharmony_ci    private:
493b1994897Sopenharmony_ci        std::list<IndexHeaderItem> headers_;
494b1994897Sopenharmony_ci        std::list<IndexItem> indexes_;
495b1994897Sopenharmony_ci    };
496b1994897Sopenharmony_ci
497b1994897Sopenharmony_ci    class ProtoKey {
498b1994897Sopenharmony_ci    public:
499b1994897Sopenharmony_ci        ProtoKey(TypeItem *ret_type, const std::vector<MethodParamItem> &params);
500b1994897Sopenharmony_ci
501b1994897Sopenharmony_ci        ~ProtoKey() = default;
502b1994897Sopenharmony_ci
503b1994897Sopenharmony_ci        DEFAULT_COPY_SEMANTIC(ProtoKey);
504b1994897Sopenharmony_ci        NO_MOVE_SEMANTIC(ProtoKey);
505b1994897Sopenharmony_ci
506b1994897Sopenharmony_ci        size_t GetHash() const
507b1994897Sopenharmony_ci        {
508b1994897Sopenharmony_ci            return hash_;
509b1994897Sopenharmony_ci        }
510b1994897Sopenharmony_ci
511b1994897Sopenharmony_ci        bool operator==(const ProtoKey &key) const
512b1994897Sopenharmony_ci        {
513b1994897Sopenharmony_ci            return shorty_ == key.shorty_ && ref_types_ == key.ref_types_;
514b1994897Sopenharmony_ci        }
515b1994897Sopenharmony_ci
516b1994897Sopenharmony_ci    private:
517b1994897Sopenharmony_ci        void Add(TypeItem *item);
518b1994897Sopenharmony_ci
519b1994897Sopenharmony_ci        size_t hash_;
520b1994897Sopenharmony_ci        std::string shorty_;
521b1994897Sopenharmony_ci        std::vector<TypeItem *> ref_types_;
522b1994897Sopenharmony_ci    };
523b1994897Sopenharmony_ci
524b1994897Sopenharmony_ci    struct ProtoKeyHash {
525b1994897Sopenharmony_ci        size_t operator()(const ProtoKey &key) const noexcept
526b1994897Sopenharmony_ci        {
527b1994897Sopenharmony_ci            return key.GetHash();
528b1994897Sopenharmony_ci        };
529b1994897Sopenharmony_ci    };
530b1994897Sopenharmony_ci
531b1994897Sopenharmony_ci    class EndItem : public BaseItem {
532b1994897Sopenharmony_ci    public:
533b1994897Sopenharmony_ci        EndItem()
534b1994897Sopenharmony_ci        {
535b1994897Sopenharmony_ci            SetNeedsEmit(false);
536b1994897Sopenharmony_ci        }
537b1994897Sopenharmony_ci
538b1994897Sopenharmony_ci        ~EndItem() override = default;
539b1994897Sopenharmony_ci
540b1994897Sopenharmony_ci        DEFAULT_COPY_SEMANTIC(EndItem);
541b1994897Sopenharmony_ci        NO_MOVE_SEMANTIC(EndItem);
542b1994897Sopenharmony_ci
543b1994897Sopenharmony_ci        size_t CalculateSize() const override
544b1994897Sopenharmony_ci        {
545b1994897Sopenharmony_ci            return 0;
546b1994897Sopenharmony_ci        }
547b1994897Sopenharmony_ci
548b1994897Sopenharmony_ci        bool Write([[maybe_unused]] Writer *writer) override
549b1994897Sopenharmony_ci        {
550b1994897Sopenharmony_ci            return true;
551b1994897Sopenharmony_ci        }
552b1994897Sopenharmony_ci
553b1994897Sopenharmony_ci        ItemTypes GetItemType() const override
554b1994897Sopenharmony_ci        {
555b1994897Sopenharmony_ci            return ItemTypes::END_ITEM;
556b1994897Sopenharmony_ci        }
557b1994897Sopenharmony_ci    };
558b1994897Sopenharmony_ci
559b1994897Sopenharmony_ci    bool WriteHeader(Writer *writer, ssize_t *checksum_offset);
560b1994897Sopenharmony_ci
561b1994897Sopenharmony_ci    bool WriteItems(Writer *writer);
562b1994897Sopenharmony_ci
563b1994897Sopenharmony_ci    bool WriteHeaderIndexInfo(Writer *writer);
564b1994897Sopenharmony_ci
565b1994897Sopenharmony_ci    void RebuildIndexSection();
566b1994897Sopenharmony_ci
567b1994897Sopenharmony_ci    void RebuildLineNumberProgramIndex();
568b1994897Sopenharmony_ci
569b1994897Sopenharmony_ci    void UpdateOrderIndexes();
570b1994897Sopenharmony_ci
571b1994897Sopenharmony_ci    void AddIndexDependecies(BaseItem *item);
572b1994897Sopenharmony_ci
573b1994897Sopenharmony_ci    void ProcessIndexDependecies(BaseItem *item);
574b1994897Sopenharmony_ci
575b1994897Sopenharmony_ci    size_t GetForeignOffset() const;
576b1994897Sopenharmony_ci
577b1994897Sopenharmony_ci    size_t GetForeignSize() const;
578b1994897Sopenharmony_ci
579b1994897Sopenharmony_ci    std::unordered_map<std::string, StringItem *> string_map_;
580b1994897Sopenharmony_ci    std::unordered_map<std::string, LiteralArrayItem *> literalarray_map_;
581b1994897Sopenharmony_ci
582b1994897Sopenharmony_ci    std::map<std::string, BaseClassItem *> class_map_;
583b1994897Sopenharmony_ci
584b1994897Sopenharmony_ci    std::unordered_map<uint32_t, ValueItem *> int_value_map_;
585b1994897Sopenharmony_ci    std::unordered_map<uint64_t, ValueItem *> long_value_map_;
586b1994897Sopenharmony_ci    // NB! For f32 and f64 value maps we use integral keys
587b1994897Sopenharmony_ci    // (in fact, bit patterns of corresponding values) to
588b1994897Sopenharmony_ci    // workaround 0.0 == -0.0 semantics.
589b1994897Sopenharmony_ci    std::unordered_map<uint32_t, ValueItem *> float_value_map_;
590b1994897Sopenharmony_ci    std::unordered_map<uint64_t, ValueItem *> double_value_map_;
591b1994897Sopenharmony_ci    std::unordered_map<BaseItem *, ValueItem *> id_value_map_;
592b1994897Sopenharmony_ci    std::unordered_map<ProtoKey, ProtoItem *, ProtoKeyHash> proto_map_;
593b1994897Sopenharmony_ci    std::unordered_map<Type::TypeId, PrimitiveTypeItem *> primitive_type_map_;
594b1994897Sopenharmony_ci
595b1994897Sopenharmony_ci    std::list<std::unique_ptr<BaseItem>> items_;
596b1994897Sopenharmony_ci
597b1994897Sopenharmony_ci    std::vector<std::unique_ptr<BaseItem>> foreign_items_;
598b1994897Sopenharmony_ci
599b1994897Sopenharmony_ci    IndexSectionItem index_section_item_;
600b1994897Sopenharmony_ci
601b1994897Sopenharmony_ci    LineNumberProgramIndexItem line_number_program_index_item_;
602b1994897Sopenharmony_ci
603b1994897Sopenharmony_ci    std::list<std::unique_ptr<BaseItem>>::iterator items_end_;
604b1994897Sopenharmony_ci    std::list<std::unique_ptr<BaseItem>>::iterator code_items_end_;
605b1994897Sopenharmony_ci    std::list<std::unique_ptr<BaseItem>>::iterator debug_items_end_;
606b1994897Sopenharmony_ci
607b1994897Sopenharmony_ci    // Get Roundup Alignment Size
608b1994897Sopenharmony_ci    std::unordered_map<std::string, size_t> items_round_up_size_;
609b1994897Sopenharmony_ci    uint32_t foreign_item_roundup_size_ {0};
610b1994897Sopenharmony_ci    uint32_t line_number_item_roundup_size_ {0};
611b1994897Sopenharmony_ci
612b1994897Sopenharmony_ci    BaseItem *end_;
613b1994897Sopenharmony_ci    size_t indexed_item_count_ {0};
614b1994897Sopenharmony_ci};
615b1994897Sopenharmony_ci
616b1994897Sopenharmony_ci}  // namespace panda::panda_file
617b1994897Sopenharmony_ci
618b1994897Sopenharmony_ci#endif  // LIBPANDAFILE_FILE_ITEM_CONTAINER_H
619