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