1 /* 2 * Copyright (c) 2023 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_SERIALIZER_BASE_DESERIALIZER_H 17 #define ECMASCRIPT_SERIALIZER_BASE_DESERIALIZER_H 18 19 #include "ecmascript/serializer/serialize_data.h" 20 21 namespace panda::ecmascript { 22 class Heap; 23 class JSThread; 24 struct NativeBindingAttachInfo { 25 AttachFunc af_ {nullptr}; 26 void *bufferPointer_ {nullptr}; 27 void *hint_ = {nullptr}; 28 void *attachData_ = {nullptr}; 29 JSHandle<JSTaggedValue> obj_; 30 size_t offset_ {0U}; 31 NativeBindingAttachInfoNativeBindingAttachInfo32 NativeBindingAttachInfo(AttachFunc af, void *bufferPointer, void *hint, void *attachData, 33 JSHandle<JSTaggedValue> obj, size_t offset) : af_(af), bufferPointer_(bufferPointer), 34 hint_(hint), attachData_(attachData), obj_(obj), offset_(offset) {} 35 GetObjAddrNativeBindingAttachInfo36 uintptr_t GetObjAddr() const 37 { 38 return static_cast<uintptr_t>(obj_.GetTaggedType()); 39 } 40 GetFieldOffsetNativeBindingAttachInfo41 size_t GetFieldOffset() const 42 { 43 return offset_; 44 } 45 GetSlotNativeBindingAttachInfo46 ObjectSlot GetSlot() const 47 { 48 return ObjectSlot(GetObjAddr() + offset_); 49 } 50 }; 51 52 struct JSErrorInfo { 53 uint8_t errorType_ {0}; 54 JSHandle<JSTaggedValue> errorMsg_; 55 JSHandle<JSTaggedValue> obj_; 56 size_t offset_ {0U}; 57 JSErrorInfoJSErrorInfo58 JSErrorInfo(uint8_t errorType, JSHandle<JSTaggedValue> errorMsg, JSHandle<JSTaggedValue> obj, size_t offset) 59 : errorType_(errorType), errorMsg_(errorMsg), obj_(obj), offset_(offset) {} 60 GetObjAddrJSErrorInfo61 uintptr_t GetObjAddr() const 62 { 63 return static_cast<uintptr_t>(obj_.GetTaggedType()); 64 } 65 GetFieldOffsetJSErrorInfo66 size_t GetFieldOffset() const 67 { 68 return offset_; 69 } 70 GetSlotJSErrorInfo71 ObjectSlot GetSlot() const 72 { 73 return ObjectSlot(GetObjAddr() + offset_); 74 } 75 }; 76 77 class BaseDeserializer { 78 public: 79 explicit BaseDeserializer(JSThread *thread, SerializeData *data, void *hint = nullptr); 80 ~BaseDeserializer()81 virtual ~BaseDeserializer() 82 { 83 objectVector_.clear(); 84 regionVector_.clear(); 85 } 86 87 NO_COPY_SEMANTIC(BaseDeserializer); 88 NO_MOVE_SEMANTIC(BaseDeserializer); 89 90 JSHandle<JSTaggedValue> ReadValue(); 91 92 protected: 93 virtual uintptr_t DeserializeTaggedObject(SerializedObjectSpace space); 94 95 private: 96 JSHandle<JSTaggedValue> DeserializeJSTaggedValue(); 97 void DeserializeNativeBindingObject(NativeBindingAttachInfo *info); 98 void DeserializeJSError(JSErrorInfo *info); 99 uintptr_t RelocateObjectAddr(SerializedObjectSpace space, size_t objSize); 100 JSTaggedType RelocateObjectProtoAddr(uint8_t objectType); 101 void DeserializeObjectField(uintptr_t start, uintptr_t end); 102 size_t ReadSingleEncodeData(uint8_t encodeFlag, uintptr_t objAddr, size_t fieldOffset); 103 virtual size_t DerivedExtraReadSingleEncodeData(uint8_t encodeFlag, uintptr_t objAddr, size_t fieldOffset); 104 void HandleNewObjectEncodeFlag(SerializedObjectSpace space, uintptr_t objAddr, size_t fieldOffset); 105 106 void TransferArrayBufferAttach(uintptr_t objAddr); 107 void IncreaseSharedArrayBufferReference(uintptr_t objAddr); 108 void ResetNativePointerBuffer(uintptr_t objAddr, void *bufferPointer); 109 110 void AllocateToDifferentSpaces(); 111 enum class RegionType : uint8_t { 112 RegularRegion, 113 PinRegion, 114 }; 115 void AllocateToRegularSpace(size_t regularSpaceSize); 116 void AllocateToPinSpace(size_t pinSpaceSize); 117 uintptr_t AllocateMultiCMCRegion(size_t spaceObjSize, size_t ®ionIndex, RegionType regionType); 118 void AllocateMultiRegion(SparseSpace *space, size_t spaceObjSize, size_t ®ionIndex, 119 SerializedObjectSpace spaceType); 120 void AllocateMultiNonmovableRegion(SparseSpace *space, size_t spaceObjSize, size_t ®ionIndex, 121 SerializedObjectSpace spaceType); 122 void AllocateMultiSharedRegion(SharedSparseSpace *space, size_t spaceObjSize, size_t ®ionIndex, 123 SerializedObjectSpace spaceType); 124 void AllocateToOldSpace(size_t oldSpaceSize); 125 void AllocateToNonMovableSpace(size_t nonMovableSpaceSize); 126 void AllocateToMachineCodeSpace(size_t machineCodeSpaceSize); 127 void AllocateToSharedOldSpace(size_t sOldSpaceSize); 128 void AllocateToSharedNonMovableSpace(size_t sNonMovableSpaceSize); GetAndResetWeak()129 bool GetAndResetWeak() 130 { 131 bool isWeak = isWeak_; 132 if (isWeak_) { 133 isWeak_ = false; 134 } 135 return isWeak; 136 } 137 GetAndResetTransferBuffer()138 bool GetAndResetTransferBuffer() 139 { 140 bool isTransferArrayBuffer = isTransferArrayBuffer_; 141 if (isTransferArrayBuffer_) { 142 isTransferArrayBuffer_ = false; 143 } 144 return isTransferArrayBuffer; 145 } 146 GetAndResetSharedArrayBuffer()147 bool GetAndResetSharedArrayBuffer() 148 { 149 bool isSharedArrayBuffer = isSharedArrayBuffer_; 150 if (isSharedArrayBuffer_) { 151 isSharedArrayBuffer_ = false; 152 } 153 return isSharedArrayBuffer; 154 } 155 GetAndResetIsErrorMsg()156 bool GetAndResetIsErrorMsg() 157 { 158 bool isErrorMsg = isErrorMsg_; 159 if (isErrorMsg_) { 160 isErrorMsg_ = false; 161 } 162 return isErrorMsg; 163 } 164 GetAndResetFunctionInShared()165 bool GetAndResetFunctionInShared() 166 { 167 bool functionInShared = functionInShared_; 168 if (functionInShared_) { 169 functionInShared_ = false; 170 } 171 return functionInShared; 172 } 173 GetAndResetBufferPointer()174 void *GetAndResetBufferPointer() 175 { 176 if (bufferPointer_) { 177 void *buffer = bufferPointer_; 178 bufferPointer_ = nullptr; 179 return buffer; 180 } 181 return nullptr; 182 } 183 184 void DeserializeFatalOutOfMemory(size_t size, bool dump = true, bool isShared = false) 185 { 186 if (isShared) { 187 if (dump) { 188 sheap_->DumpHeapSnapshotBeforeOOM(thread_, SharedHeapOOMSource::DESERIALIZE); 189 } 190 LOG_ECMA(FATAL) << "BaseDeserializer::OutOfMemory when deserialize shared obj size: " << size 191 << ", old space heap object size: " 192 << sheap_->GetOldSpace()->GetHeapObjectSize() 193 << ", old space committed size: " 194 << sheap_->GetOldSpace()->GetCommittedSize() 195 << ", non movable space heap object size: " 196 << sheap_->GetNonMovableSpace()->GetHeapObjectSize() 197 << ", non movable space committed size: " 198 << sheap_->GetNonMovableSpace()->GetCommittedSize() 199 << ", huge space committed size: " 200 << sheap_->GetHugeObjectSpace()->GetCommittedSize(); 201 } else { 202 if (dump) { 203 heap_->StatisticHeapDetail(); 204 heap_->DumpHeapSnapshotBeforeOOM(); 205 } 206 LOG_ECMA(FATAL) << "BaseDeserializer::OutOfMemory when deserialize obj size: " << size 207 << ", old space heap object size: " 208 << heap_->GetOldSpace()->GetHeapObjectSize() 209 << ", old space committed size: " 210 << heap_->GetOldSpace()->GetCommittedSize() 211 << ", non movable space heap object size: " 212 << heap_->GetNonMovableSpace()->GetHeapObjectSize() 213 << ", non movable space committed size: " 214 << heap_->GetNonMovableSpace()->GetCommittedSize() 215 << ", huge space committed size: " 216 << heap_->GetHugeObjectSpace()->GetCommittedSize(); 217 } 218 } 219 UpdateMaybeWeak(ObjectSlot slot,uintptr_t addr,bool isWeak)220 void UpdateMaybeWeak(ObjectSlot slot, uintptr_t addr, bool isWeak) 221 { 222 isWeak ? slot.UpdateWeak(addr) : slot.Update(addr); 223 } 224 GetLazyArray()225 bool *GetLazyArray() 226 { 227 if (moduleLazyArray_) { 228 bool *buffer = moduleLazyArray_; 229 moduleLazyArray_ = nullptr; 230 return buffer; 231 } 232 return nullptr; 233 } 234 235 protected: 236 JSThread *thread_; 237 SerializeData *data_; 238 void *engine_; 239 size_t position_ {0}; 240 CVector<JSTaggedType> objectVector_ {}; 241 DeserializeSpecialRecordedObjects()242 virtual void DeserializeSpecialRecordedObjects() {} 243 244 private: 245 Heap *heap_; 246 SharedHeap *sheap_; 247 uintptr_t currentRegularObjectAddr_ {0}; 248 uintptr_t currentRegularRegionBeginAddr_ {0}; 249 uintptr_t currentPinObjectAddr_ {0}; 250 uintptr_t currentPinRegionBeginAddr_ {0}; 251 size_t regularRegionIndex_ {0}; 252 size_t pinRegionIndex_ {0}; 253 CVector<uintptr_t> regionVector_; 254 uintptr_t oldSpaceBeginAddr_ {0}; 255 uintptr_t nonMovableSpaceBeginAddr_ {0}; 256 uintptr_t machineCodeSpaceBeginAddr_ {0}; 257 uintptr_t sOldSpaceBeginAddr_ {0}; 258 uintptr_t sNonMovableSpaceBeginAddr_ {0}; 259 size_t oldRegionIndex_ {0}; 260 size_t nonMovableRegionIndex_ {0}; 261 size_t machineCodeRegionIndex_ {0}; 262 size_t sOldRegionIndex_ {0}; 263 size_t sNonMovableRegionIndex_ {0}; 264 // SerializationChunk store shared objects which have been serialized 265 SerializationChunk *sharedObjChunk_ {nullptr}; 266 bool isWeak_ {false}; 267 bool isTransferArrayBuffer_ {false}; 268 bool isSharedArrayBuffer_ {false}; 269 bool isErrorMsg_ {false}; 270 void *bufferPointer_ {nullptr}; 271 bool functionInShared_ {false}; 272 CVector<NativeBindingAttachInfo> nativeBindingAttachInfos_; 273 CVector<JSErrorInfo> jsErrorInfos_; 274 CVector<JSHandle<JSFunction>> concurrentFunctions_; 275 // module deserialize 276 CString moduleFileName_ {}; 277 CString moduleRecordName_ {}; 278 bool* moduleLazyArray_ {nullptr}; 279 }; 280 } 281 282 #endif // ECMASCRIPT_SERIALIZER_BASE_DESERIALIZER_H 283