• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_SNAPSHOT_MEM_SNAPSHOT_PROCESSOR_H
17 #define ECMASCRIPT_SNAPSHOT_MEM_SNAPSHOT_PROCESSOR_H
18 
19 #include <iostream>
20 #include <fstream>
21 #include <sstream>
22 
23 #include "ecmascript/snapshot/mem/encode_bit.h"
24 #include "ecmascript/jspandafile/method_literal.h"
25 #include "ecmascript/js_tagged_value.h"
26 #include "ecmascript/mem/object_xray.h"
27 
28 #include "libpandabase/macros.h"
29 
30 namespace panda::ecmascript {
31 class EcmaVM;
32 class JSPandaFile;
33 class AOTFileManager;
34 
35 enum class SnapshotType {
36     VM_ROOT,
37     BUILTINS,
38     AI
39 };
40 
41 struct SnapshotRegionHeadInfo {
42     uint32_t regionIndex_ {0};
43     uint32_t aliveObjectSize_ {0};
44 
RegionHeadInfoSizeSnapshotRegionHeadInfo45     static constexpr size_t RegionHeadInfoSize()
46     {
47         return sizeof(SnapshotRegionHeadInfo);
48     }
49 };
50 
51 using ObjectEncode = std::pair<uint64_t, ecmascript::EncodeBit>;
52 
53 class SnapshotProcessor final {
54 public:
SnapshotProcessor(EcmaVM * vm)55     explicit SnapshotProcessor(EcmaVM *vm)
56         : vm_(vm), sHeap_(SharedHeap::GetInstance()) {}
57     ~SnapshotProcessor();
58 
59     void Initialize();
60     void StopAllocate();
61     void WriteObjectToFile(std::fstream &write);
62     std::vector<uint32_t> StatisticsObjectSize();
63     void ProcessObjectQueue(CQueue<TaggedObject *> *queue, std::unordered_map<uint64_t, ObjectEncode> *data);
64     void SerializeObject(TaggedObject *objectHeader, CQueue<TaggedObject *> *queue,
65                          std::unordered_map<uint64_t, ObjectEncode> *data);
66     void Relocate(SnapshotType type, const JSPandaFile *jsPandaFile,
67                   uint64_t rootObjSize);
68     void RelocateSpaceObject(const JSPandaFile *jsPandaFile, Space* space, SnapshotType type, MethodLiteral* methods,
69                              size_t methodNums, size_t rootObjSize);
70     void SerializePandaFileMethod();
71     uintptr_t GetNewObj(size_t objectSize, TaggedObject *objectHeader);
72     EncodeBit EncodeTaggedObject(TaggedObject *objectHeader, CQueue<TaggedObject *> *queue,
73                                  std::unordered_map<uint64_t, ObjectEncode> *data);
74     EncodeBit GetObjectEncode(JSTaggedValue object, CQueue<TaggedObject *> *queue,
75                               std::unordered_map<uint64_t, ObjectEncode> *data);
76     void EncodeTaggedObjectRange(ObjectSlot start, ObjectSlot end, CQueue<TaggedObject *> *queue,
77                                  std::unordered_map<uint64_t, ObjectEncode> *data);
78     void DeserializeObjectExcludeString(uintptr_t oldSpaceBegin, size_t oldSpaceObjSize, size_t nonMovableObjSize,
79                                         size_t machineCodeObjSize, size_t snapshotObjSize, size_t hugeSpaceObjSize);
80     void DeserializeString(uintptr_t stringBegin, uintptr_t stringEnd);
81 
82     void AddRootObjectToAOTFileManager(SnapshotType type, const CString &fileName);
83 
SetProgramSerializeStart()84     void SetProgramSerializeStart()
85     {
86         programSerialize_ = true;
87     }
88 
SetBuiltinsSerializeStart()89     void SetBuiltinsSerializeStart()
90     {
91         builtinsSerialize_ = true;
92     }
93 
SetBuiltinsDeserializeStart()94     void SetBuiltinsDeserializeStart()
95     {
96         builtinsDeserialize_ = true;
97     }
98 
GetStringVector()99     const CVector<uintptr_t> GetStringVector() const
100     {
101         return stringVector_;
102     }
103 
GetOldLocalSpace()104     LocalSpace* GetOldLocalSpace() const
105     {
106         return oldLocalSpace_;
107     }
108 
109     size_t GetNativeTableSize() const;
110 
111 private:
112     class SerializeObjectVisitor final : public EcmaObjectRangeVisitor<SerializeObjectVisitor> {
113     public:
114         explicit SerializeObjectVisitor(SnapshotProcessor *processor, uintptr_t snapshotObj,
115             CQueue<TaggedObject *> *queue, std::unordered_map<uint64_t, ObjectEncode> *data);
116         ~SerializeObjectVisitor() override = default;
117 
118         void VisitObjectRangeImpl(TaggedObject *root, ObjectSlot start, ObjectSlot end, VisitObjectArea area) override;
119     private:
120         SnapshotProcessor *processor_ {nullptr};
121         uintptr_t snapshotObj_ {-1};
122         CQueue<TaggedObject *> *queue_ {nullptr};
123         std::unordered_map<uint64_t, ObjectEncode> *data_{nullptr};
124     };
125 
126     class DeserializeFieldVisitor final : public EcmaObjectRangeVisitor<DeserializeFieldVisitor> {
127     public:
128         explicit DeserializeFieldVisitor(SnapshotProcessor *processor);
129         ~DeserializeFieldVisitor() override = default;
130 
131         void VisitObjectRangeImpl(TaggedObject *root, ObjectSlot start, ObjectSlot end, VisitObjectArea area) override;
132     private:
133         SnapshotProcessor *processor_ {nullptr};
134     };
GetMarkGCBitSetSize()135     size_t GetMarkGCBitSetSize() const
136     {
137         return GCBitset::SizeOfGCBitset(DEFAULT_REGION_SIZE -
138             AlignUp(sizeof(Region), static_cast<size_t>(MemAlignment::MEM_ALIGN_REGION)));
139     }
140 
141     bool VisitObjectBodyWithRep(TaggedObject *root, ObjectSlot slot, uintptr_t obj, int index, VisitObjectArea area);
142     void SetObjectEncodeField(uintptr_t obj, size_t offset, uint64_t value);
143 
144     EncodeBit SerializeObjectHeader(TaggedObject *objectHeader, size_t objectType, CQueue<TaggedObject *> *queue,
145                                     std::unordered_map<uint64_t, ObjectEncode> *data);
146     uint64_t SerializeTaggedField(JSTaggedType *tagged, CQueue<TaggedObject *> *queue,
147                                   std::unordered_map<uint64_t, ObjectEncode> *data);
148     void DeserializeField(TaggedObject *objectHeader);
149     void DeserializeTaggedField(uint64_t *value, TaggedObject *root);
150     void DeserializeNativePointer(uint64_t *value);
151     void DeserializeClassWord(TaggedObject *object);
152     void DeserializePandaMethod(uintptr_t begin, uintptr_t end, MethodLiteral *methods,
153                                 size_t &methodNums, size_t &others);
154     void DeserializeSpaceObject(uintptr_t beginAddr, Space* space, size_t spaceObjSize);
155     void DeserializeHugeSpaceObject(uintptr_t beginAddr, HugeObjectSpace* space, size_t hugeSpaceObjSize);
156     void HandleRootObject(SnapshotType type, uintptr_t rootObjectAddr, size_t objType, size_t &constSpecialIndex);
157 
158     EncodeBit NativePointerToEncodeBit(void *nativePointer);
159     size_t SearchNativeMethodIndex(void *nativePointer);
160     uintptr_t TaggedObjectEncodeBitToAddr(EncodeBit taggedBit);
161     void WriteSpaceObjectToFile(Space* space, std::fstream &write);
162     void WriteHugeObjectToFile(HugeObjectSpace* space, std::fstream &writer);
163     uint32_t StatisticsSpaceObjectSize(Space* space);
164     uint32_t StatisticsHugeObjectSize(HugeObjectSpace* space);
165     uintptr_t AllocateObjectToLocalSpace(Space *space, size_t objectSize);
166     SnapshotRegionHeadInfo GenerateRegionHeadInfo(Region *region);
167     void ResetRegionUnusedRange(Region *region);
168 
169     EcmaVM *vm_ {nullptr};
170     SharedHeap* sHeap_ {nullptr};
171     LocalSpace *oldLocalSpace_ {nullptr};
172     LocalSpace *nonMovableLocalSpace_ {nullptr};
173     LocalSpace *machineCodeLocalSpace_ {nullptr};
174     SnapshotSpace *snapshotLocalSpace_ {nullptr};
175     HugeObjectSpace *hugeObjectLocalSpace_ {nullptr};
176     bool programSerialize_ {false};
177     bool builtinsSerialize_ {false};
178     bool builtinsDeserialize_ {false};
179     CVector<uintptr_t> pandaMethod_;
180     CVector<uintptr_t> stringVector_;
181     /**
182      * In deserialize, RuntimeLock for string table may cause a SharedGC, making strings just created invalid,
183      * so use handle to protect.
184     */
185     CVector<JSHandle<EcmaString>> deserializeStringVector_;
186     std::unordered_map<size_t, Region *> regionIndexMap_;
187     size_t regionIndex_ {0};
188     bool isRootObjRelocate_ {false};
189     JSTaggedValue root_ {JSTaggedValue::Hole()};
190 
191     NO_COPY_SEMANTIC(SnapshotProcessor);
192     NO_MOVE_SEMANTIC(SnapshotProcessor);
193 };
194 
195 class SnapshotHelper {
196 public:
197     // when snapshot serialize, huge obj size is writed to region snapshotData_ high 32 bits
EncodeHugeObjectSize(uint64_t objSize)198     static inline uint64_t EncodeHugeObjectSize(uint64_t objSize)
199     {
200         return objSize << Constants::UINT_32_BITS_COUNT;
201     }
202 
203     // get huge object size which is saved in region snapshotData_ high 32 bits
GetHugeObjectSize(uint64_t snapshotData)204     static inline size_t GetHugeObjectSize(uint64_t snapshotData)
205     {
206         return snapshotData >> Constants::UINT_32_BITS_COUNT;
207     }
208 
209     // get huge object region index which is saved in region snapshotMark_ low 32 bits
GetHugeObjectRegionIndex(uint64_t snapshotData)210     static inline size_t GetHugeObjectRegionIndex(uint64_t snapshotData)
211     {
212         return snapshotData & Constants::MAX_UINT_32;
213     }
214 };
215 }  // namespace panda::ecmascript
216 
217 #endif  // ECMASCRIPT_SNAPSHOT_MEM_SNAPSHOT_PROCESSOR_H
218