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 uintptr_t objAddr_ {0U}; 30 size_t offset_ {0U}; 31 bool root_ {false}; 32 NativeBindingAttachInfoNativeBindingAttachInfo33 NativeBindingAttachInfo(AttachFunc af, void *bufferPointer, void *hint, void *attachData, 34 uintptr_t objAddr, size_t offset, bool root) : af_(af), bufferPointer_(bufferPointer), 35 hint_(hint), attachData_(attachData), objAddr_(objAddr), offset_(offset), root_(root) {} 36 GetObjAddrNativeBindingAttachInfo37 uintptr_t GetObjAddr() const 38 { 39 return objAddr_; 40 } 41 GetFieldOffsetNativeBindingAttachInfo42 size_t GetFieldOffset() const 43 { 44 return offset_; 45 } 46 GetSlotNativeBindingAttachInfo47 ObjectSlot GetSlot() const 48 { 49 return ObjectSlot(objAddr_ + offset_); 50 } 51 }; 52 53 struct JSErrorInfo { 54 uint8_t errorType_ {0}; 55 JSTaggedValue errorMsg_; 56 uintptr_t objAddr_ {0U}; 57 size_t offset_ {0U}; 58 bool root_ {false}; 59 JSErrorInfoJSErrorInfo60 JSErrorInfo(uint8_t errorType, JSTaggedValue errorMsg, uintptr_t objAddr, size_t offset, bool root) 61 : errorType_(errorType), errorMsg_(errorMsg), objAddr_(objAddr), offset_(offset), root_(root) {} 62 GetObjAddrJSErrorInfo63 uintptr_t GetObjAddr() const 64 { 65 return objAddr_; 66 } 67 GetFieldOffsetJSErrorInfo68 size_t GetFieldOffset() const 69 { 70 return offset_; 71 } 72 GetSlotJSErrorInfo73 ObjectSlot GetSlot() const 74 { 75 return ObjectSlot(objAddr_ + offset_); 76 } 77 }; 78 79 class BaseDeserializer { 80 public: 81 explicit BaseDeserializer(JSThread *thread, SerializeData *data, void *hint = nullptr); 82 ~BaseDeserializer()83 ~BaseDeserializer() 84 { 85 objectVector_.clear(); 86 regionVector_.clear(); 87 } 88 89 NO_COPY_SEMANTIC(BaseDeserializer); 90 NO_MOVE_SEMANTIC(BaseDeserializer); 91 92 JSHandle<JSTaggedValue> ReadValue(); 93 94 private: 95 JSHandle<JSTaggedValue> DeserializeJSTaggedValue(); 96 uintptr_t DeserializeTaggedObject(SerializedObjectSpace space); 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, bool isRoot = false); 103 void HandleNewObjectEncodeFlag(SerializedObjectSpace space, uintptr_t objAddr, size_t fieldOffset, bool isRoot); 104 105 void TransferArrayBufferAttach(uintptr_t objAddr); 106 void IncreaseSharedArrayBufferReference(uintptr_t objAddr); 107 void ResetNativePointerBuffer(uintptr_t objAddr, void *bufferPointer); 108 109 void AllocateToDifferentSpaces(); 110 void AllocateMultiRegion(SparseSpace *space, size_t spaceObjSize, size_t ®ionIndex); 111 void AllocateMultiSharedRegion(SharedSparseSpace *space, size_t spaceObjSize, size_t ®ionIndex); 112 void AllocateToOldSpace(size_t oldSpaceSize); 113 void AllocateToNonMovableSpace(size_t nonMovableSpaceSize); 114 void AllocateToMachineCodeSpace(size_t machineCodeSpaceSize); 115 void AllocateToSharedOldSpace(size_t sOldSpaceSize); 116 void AllocateToSharedNonMovableSpace(size_t sNonMovableSpaceSize); 117 GetAndResetWeak()118 bool GetAndResetWeak() 119 { 120 bool isWeak = isWeak_; 121 if (isWeak_) { 122 isWeak_ = false; 123 } 124 return isWeak; 125 } 126 GetAndResetTransferBuffer()127 bool GetAndResetTransferBuffer() 128 { 129 bool isTransferArrayBuffer = isTransferArrayBuffer_; 130 if (isTransferArrayBuffer_) { 131 isTransferArrayBuffer_ = false; 132 } 133 return isTransferArrayBuffer; 134 } 135 GetAndResetSharedArrayBuffer()136 bool GetAndResetSharedArrayBuffer() 137 { 138 bool isSharedArrayBuffer = isSharedArrayBuffer_; 139 if (isSharedArrayBuffer_) { 140 isSharedArrayBuffer_ = false; 141 } 142 return isSharedArrayBuffer; 143 } 144 GetAndResetIsErrorMsg()145 bool GetAndResetIsErrorMsg() 146 { 147 bool isErrorMsg = isErrorMsg_; 148 if (isErrorMsg_) { 149 isErrorMsg_ = false; 150 } 151 return isErrorMsg; 152 } 153 GetAndResetFunctionInShared()154 bool GetAndResetFunctionInShared() 155 { 156 bool functionInShared = functionInShared_; 157 if (functionInShared_) { 158 functionInShared_ = false; 159 } 160 return functionInShared; 161 } 162 GetAndResetBufferPointer()163 void *GetAndResetBufferPointer() 164 { 165 if (bufferPointer_) { 166 void *buffer = bufferPointer_; 167 bufferPointer_ = nullptr; 168 return buffer; 169 } 170 return nullptr; 171 } 172 173 void DeserializeFatalOutOfMemory(size_t size, bool dump = true, bool isShared = false) 174 { 175 if (isShared) { 176 if (dump) { 177 sheap_->DumpHeapSnapshotBeforeOOM(false, thread_, SharedHeapOOMSource::DESERIALIZE); 178 } 179 LOG_ECMA(FATAL) << "BaseDeserializer::OutOfMemory when deserialize shared obj size: " << size 180 << ", old space heap object size: " 181 << sheap_->GetOldSpace()->GetHeapObjectSize() 182 << ", old space committed size: " 183 << sheap_->GetOldSpace()->GetCommittedSize() 184 << ", non movable space heap object size: " 185 << sheap_->GetNonMovableSpace()->GetHeapObjectSize() 186 << ", non movable space committed size: " 187 << sheap_->GetNonMovableSpace()->GetCommittedSize() 188 << ", huge space committed size: " 189 << sheap_->GetHugeObjectSpace()->GetCommittedSize(); 190 } else { 191 if (dump) { 192 heap_->StatisticHeapDetail(); 193 heap_->DumpHeapSnapshotBeforeOOM(false); 194 } 195 LOG_ECMA(FATAL) << "BaseDeserializer::OutOfMemory when deserialize obj size: " << size 196 << ", old space heap object size: " 197 << heap_->GetOldSpace()->GetHeapObjectSize() 198 << ", old space committed size: " 199 << heap_->GetOldSpace()->GetCommittedSize() 200 << ", non movable space heap object size: " 201 << heap_->GetNonMovableSpace()->GetHeapObjectSize() 202 << ", non movable space committed size: " 203 << heap_->GetNonMovableSpace()->GetCommittedSize() 204 << ", huge space committed size: " 205 << heap_->GetHugeObjectSpace()->GetCommittedSize(); 206 } 207 } 208 UpdateMaybeWeak(ObjectSlot slot,uintptr_t addr,bool isWeak)209 void UpdateMaybeWeak(ObjectSlot slot, uintptr_t addr, bool isWeak) 210 { 211 isWeak ? slot.UpdateWeak(addr) : slot.Update(addr); 212 } 213 214 private: 215 JSThread *thread_; 216 Heap *heap_; 217 SharedHeap *sheap_; 218 SerializeData* data_; 219 void *engine_; 220 uintptr_t oldSpaceBeginAddr_ {0}; 221 uintptr_t nonMovableSpaceBeginAddr_ {0}; 222 uintptr_t machineCodeSpaceBeginAddr_ {0}; 223 uintptr_t sOldSpaceBeginAddr_ {0}; 224 uintptr_t sNonMovableSpaceBeginAddr_ {0}; 225 // SerializationChunk store shared objects which have been serialized 226 SerializationChunk *sharedObjChunk_ {nullptr}; 227 CVector<JSTaggedType> objectVector_; 228 CVector<Region *> regionVector_; 229 size_t oldRegionIndex_ {0}; 230 size_t nonMovableRegionIndex_ {0}; 231 size_t machineCodeRegionIndex_ {0}; 232 size_t sOldRegionIndex_ {0}; 233 size_t sNonMovableRegionIndex_ {0}; 234 size_t regionRemainSizeIndex_ {0}; 235 bool isWeak_ {false}; 236 bool isTransferArrayBuffer_ {false}; 237 bool isSharedArrayBuffer_ {false}; 238 bool isErrorMsg_ {false}; 239 void *bufferPointer_ {nullptr}; 240 bool functionInShared_ {false}; 241 CVector<NativeBindingAttachInfo *> nativeBindingAttachInfos_; 242 CVector<JSErrorInfo *> jsErrorInfos_; 243 CVector<JSHandle<JSFunction>> concurrentFunctions_; 244 size_t position_ {0}; 245 }; 246 } 247 248 #endif // ECMASCRIPT_SERIALIZER_BASE_DESERIALIZER_H