• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "ecmascript/serializer/base_deserializer.h"
17 
18 #include "ecmascript/free_object.h"
19 #include "ecmascript/global_env.h"
20 #include "ecmascript/js_arraybuffer.h"
21 #include "ecmascript/js_function.h"
22 #include "ecmascript/js_regexp.h"
23 #include "ecmascript/checkpoint/thread_state_transition.h"
24 
25 namespace panda::ecmascript {
26 
27 #define NEW_OBJECT_ALL_SPACES()                                           \
28     (uint8_t)SerializedObjectSpace::OLD_SPACE:                            \
29     case (uint8_t)SerializedObjectSpace::NON_MOVABLE_SPACE:               \
30     case (uint8_t)SerializedObjectSpace::MACHINE_CODE_SPACE:              \
31     case (uint8_t)SerializedObjectSpace::HUGE_SPACE:                      \
32     case (uint8_t)SerializedObjectSpace::SHARED_OLD_SPACE:                \
33     case (uint8_t)SerializedObjectSpace::SHARED_NON_MOVABLE_SPACE:        \
34     case (uint8_t)SerializedObjectSpace::SHARED_HUGE_SPACE
35 
BaseDeserializer(JSThread * thread,SerializeData * data,void * hint)36 BaseDeserializer::BaseDeserializer(JSThread *thread, SerializeData *data, void *hint)
37     : thread_(thread), heap_(const_cast<Heap *>(thread->GetEcmaVM()->GetHeap())), data_(data), engine_(hint)
38 {
39     sheap_ = SharedHeap::GetInstance();
40     uint32_t index = data_->GetDataIndex();
41     if (index != 0) {
42         sharedObjChunk_ = Runtime::GetInstance()->GetSerializeRootMapValue(thread_, index);
43         if (sharedObjChunk_ == nullptr) {
44             LOG_ECMA(FATAL) << "Unknown serializer root index: " << index;
45             UNREACHABLE();
46         }
47     }
48 }
49 
ReadValue()50 JSHandle<JSTaggedValue> BaseDeserializer::ReadValue()
51 {
52     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "Deserialize dataSize: " + std::to_string(data_->Size()));
53     AllocateToDifferentSpaces();
54     JSHandle<JSTaggedValue> res = DeserializeJSTaggedValue();
55     return res;
56 }
57 
DeserializeJSTaggedValue()58 JSHandle<JSTaggedValue> BaseDeserializer::DeserializeJSTaggedValue()
59 {
60     if (data_->IsIncompleteData()) {
61         LOG_ECMA(ERROR) << "The serialization data is incomplete";
62         return JSHandle<JSTaggedValue>();
63     }
64 
65     // stop gc during deserialize
66     heap_->SetOnSerializeEvent(true);
67 
68     uint8_t encodeFlag = data_->ReadUint8(position_);
69     JSHandle<JSTaggedValue> resHandle(thread_, JSTaggedValue::Undefined());
70     while (ReadSingleEncodeData(encodeFlag, resHandle.GetAddress(), 0, true) == 0) { // 0: root object offset
71         encodeFlag = data_->ReadUint8(position_);
72     }
73 
74     // initialize concurrent func here
75     for (auto func : concurrentFunctions_) {
76         JSFunction::InitializeForConcurrentFunction(thread_, func);
77     }
78     concurrentFunctions_.clear();
79 
80     // new native binding object here
81     for (auto nativeBindingInfo : nativeBindingInfos_) {
82         DeserializeNativeBindingObject(nativeBindingInfo);
83         delete nativeBindingInfo;
84     }
85     nativeBindingInfos_.clear();
86 
87     // new js error here
88     for (auto jsErrorInfo : jsErrorInfos_) {
89         DeserializeJSError(jsErrorInfo);
90         delete jsErrorInfo;
91     }
92     jsErrorInfos_.clear();
93 
94     // recovery gc after serialize
95     heap_->SetOnSerializeEvent(false);
96 
97     return resHandle;
98 }
99 
DeserializeTaggedObject(SerializedObjectSpace space)100 uintptr_t BaseDeserializer::DeserializeTaggedObject(SerializedObjectSpace space)
101 {
102     size_t objSize = data_->ReadUint32(position_);
103     uintptr_t res = RelocateObjectAddr(space, objSize);
104     objectVector_.push_back(static_cast<JSTaggedType>(res));
105     DeserializeObjectField(res, res + objSize);
106     return res;
107 }
108 
DeserializeObjectField(uintptr_t start,uintptr_t end)109 void BaseDeserializer::DeserializeObjectField(uintptr_t start, uintptr_t end)
110 {
111     size_t offset = 0; // 0: initial offset
112     while (start + offset < end) {
113         uint8_t encodeFlag = data_->ReadUint8(position_);
114         offset += ReadSingleEncodeData(encodeFlag, start, offset);
115     }
116 }
117 
DeserializeNativeBindingObject(NativeBindingInfo * info)118 void BaseDeserializer::DeserializeNativeBindingObject(NativeBindingInfo *info)
119 {
120     [[maybe_unused]] EcmaHandleScope scope(thread_);
121     AttachFunc af = info->af_;
122     void *bufferPointer = info->bufferPointer_;
123     void *hint = info->hint_;
124     void *attachData = info->attachData_;
125     bool root = info->root_;
126     Local<JSValueRef> attachVal;
127     {
128         ThreadNativeScope nativeScope(thread_);
129         attachVal = af(engine_, bufferPointer, hint, attachData);
130     }
131     if (attachVal.IsEmpty()) {
132         LOG_ECMA(ERROR) << "NativeBindingObject is empty";
133         attachVal = JSValueRef::Undefined(thread_->GetEcmaVM());
134     }
135     JSTaggedType res = JSNApiHelper::ToJSHandle(attachVal).GetTaggedType();
136     ObjectSlot slot = info->GetSlot();
137     slot.Update(res);
138     if (!root && !JSTaggedValue(res).IsInvalidValue()) {
139         WriteBarrier(thread_, reinterpret_cast<void *>(info->GetObjAddr()), info->GetFieldOffset(), res);
140     }
141 }
142 
DeserializeJSError(JSErrorInfo * info)143 void BaseDeserializer::DeserializeJSError(JSErrorInfo *info)
144 {
145     [[maybe_unused]] EcmaHandleScope scope(thread_);
146     uint8_t type = info->errorType_;
147     base::ErrorType errorType = base::ErrorType(type - static_cast<uint8_t>(JSType::JS_ERROR_FIRST));
148     JSTaggedValue errorMsg = info->errorMsg_;
149     bool root = info->root_;
150     ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
151     JSHandle<JSObject> errorTag = factory->NewJSError(errorType, JSHandle<EcmaString>(thread_, errorMsg),
152                                                       StackCheck::NO);
153     ObjectSlot slot = info->GetSlot();
154     slot.Update(errorTag.GetTaggedType());
155     if (!root && !errorTag.GetTaggedValue().IsInvalidValue()) {
156         WriteBarrier(thread_, reinterpret_cast<void *>(info->GetObjAddr()), info->GetFieldOffset(),
157                      errorTag.GetTaggedType());
158     }
159 }
160 
HandleNewObjectEncodeFlag(SerializedObjectSpace space,uintptr_t objAddr,size_t fieldOffset,bool isRoot)161 void BaseDeserializer::HandleNewObjectEncodeFlag(SerializedObjectSpace space,  uintptr_t objAddr, size_t fieldOffset,
162                                                  bool isRoot)
163 {
164     // deserialize object prologue
165     bool isWeak = GetAndResetWeak();
166     bool isTransferBuffer = GetAndResetTransferBuffer();
167     bool isSharedArrayBuffer = GetAndResetSharedArrayBuffer();
168     void *bufferPointer = GetAndResetBufferPointer();
169     // deserialize object here
170     uintptr_t addr = DeserializeTaggedObject(space);
171 
172     // deserialize object epilogue
173     if (isTransferBuffer) {
174         TransferArrayBufferAttach(addr);
175     } else if (isSharedArrayBuffer) {
176         IncreaseSharedArrayBufferReference(addr);
177     } else if (bufferPointer != nullptr) {
178         ResetNativePointerBuffer(addr, bufferPointer);
179     }
180     TaggedObject *object = reinterpret_cast<TaggedObject *>(addr);
181     if (object->GetClass()->IsJSNativePointer()) {
182         JSNativePointer *nativePointer = reinterpret_cast<JSNativePointer *>(object);
183         if (nativePointer->GetDeleter() != nullptr) {
184             if (!JSTaggedValue::Cast(object).IsInSharedHeap()) {
185                 thread_->GetEcmaVM()->PushToNativePointerList(nativePointer);
186             }
187         }
188     } else if (object->GetClass()->IsJSFunction()) {
189         JSFunction* func = reinterpret_cast<JSFunction *>(object);
190         FunctionKind funcKind = func->GetFunctionKind();
191         if (funcKind == FunctionKind::CONCURRENT_FUNCTION || object->GetClass()->IsJSSharedFunction()) {
192             // defer initialize concurrent function
193             JSHandle<JSFunction> funcHandle(thread_, func);
194             concurrentFunctions_.push_back(funcHandle);
195         }
196         func->SetRawProfileTypeInfo(thread_, thread_->GlobalConstants()->GetEmptyProfileTypeInfoCell(), SKIP_BARRIER);
197         func->SetWorkNodePointer(reinterpret_cast<uintptr_t>(nullptr));
198     }
199     UpdateMaybeWeak(ObjectSlot(objAddr + fieldOffset), addr, isWeak);
200     if (!isRoot) {
201         WriteBarrier<WriteBarrierType::DESERIALIZE>(thread_, reinterpret_cast<void *>(objAddr), fieldOffset,
202                                                     static_cast<JSTaggedType>(addr));
203     }
204 }
205 
TransferArrayBufferAttach(uintptr_t objAddr)206 void BaseDeserializer::TransferArrayBufferAttach(uintptr_t objAddr)
207 {
208     ASSERT(JSTaggedValue(static_cast<JSTaggedType>(objAddr)).IsArrayBuffer());
209     JSArrayBuffer *arrayBuffer = reinterpret_cast<JSArrayBuffer *>(objAddr);
210     size_t arrayLength = arrayBuffer->GetArrayBufferByteLength();
211     bool withNativeAreaAllocator = arrayBuffer->GetWithNativeAreaAllocator();
212     JSNativePointer *np = reinterpret_cast<JSNativePointer *>(arrayBuffer->GetArrayBufferData().GetTaggedObject());
213     arrayBuffer->Attach(thread_, arrayLength, JSTaggedValue(np), withNativeAreaAllocator);
214 }
215 
IncreaseSharedArrayBufferReference(uintptr_t objAddr)216 void BaseDeserializer::IncreaseSharedArrayBufferReference(uintptr_t objAddr)
217 {
218     ASSERT(JSTaggedValue(static_cast<JSTaggedType>(objAddr)).IsSharedArrayBuffer());
219     JSArrayBuffer *arrayBuffer = reinterpret_cast<JSArrayBuffer *>(objAddr);
220     size_t arrayLength = arrayBuffer->GetArrayBufferByteLength();
221     JSNativePointer *np = reinterpret_cast<JSNativePointer *>(arrayBuffer->GetArrayBufferData().GetTaggedObject());
222     void *buffer = np->GetExternalPointer();
223     if (JSSharedMemoryManager::GetInstance()->CreateOrLoad(&buffer, arrayLength)) {
224         LOG_ECMA(FATAL) << "BaseDeserializer::IncreaseSharedArrayBufferReference failed";
225     }
226 }
227 
ResetNativePointerBuffer(uintptr_t objAddr,void * bufferPointer)228 void BaseDeserializer::ResetNativePointerBuffer(uintptr_t objAddr, void *bufferPointer)
229 {
230     JSTaggedValue obj = JSTaggedValue(static_cast<JSTaggedType>(objAddr));
231     ASSERT(obj.IsArrayBuffer() || obj.IsJSRegExp());
232     auto nativeAreaAllocator = thread_->GetEcmaVM()->GetNativeAreaAllocator();
233     JSNativePointer *np = nullptr;
234     if (obj.IsArrayBuffer()) {
235         JSArrayBuffer *arrayBuffer = reinterpret_cast<JSArrayBuffer *>(objAddr);
236         arrayBuffer->SetWithNativeAreaAllocator(true);
237         np = reinterpret_cast<JSNativePointer *>(arrayBuffer->GetArrayBufferData().GetTaggedObject());
238         nativeAreaAllocator->IncreaseNativeSizeStats(arrayBuffer->GetArrayBufferByteLength(), NativeFlag::ARRAY_BUFFER);
239     } else {
240         JSRegExp *jsRegExp = reinterpret_cast<JSRegExp *>(objAddr);
241         np = reinterpret_cast<JSNativePointer *>(jsRegExp->GetByteCodeBuffer().GetTaggedObject());
242         nativeAreaAllocator->IncreaseNativeSizeStats(jsRegExp->GetLength(), NativeFlag::REGEXP_BTYECODE);
243     }
244 
245     np->SetExternalPointer(bufferPointer);
246     np->SetDeleter(NativeAreaAllocator::FreeBufferFunc);
247     np->SetData(thread_->GetEcmaVM()->GetNativeAreaAllocator());
248 }
249 
ReadSingleEncodeData(uint8_t encodeFlag,uintptr_t objAddr,size_t fieldOffset,bool isRoot)250 size_t BaseDeserializer::ReadSingleEncodeData(uint8_t encodeFlag, uintptr_t objAddr, size_t fieldOffset, bool isRoot)
251 {
252     size_t handledFieldSize = sizeof(JSTaggedType);
253     ObjectSlot slot(objAddr + fieldOffset);
254     switch (encodeFlag) {
255         case NEW_OBJECT_ALL_SPACES(): {
256             SerializedObjectSpace space = SerializeData::DecodeSpace(encodeFlag);
257             HandleNewObjectEncodeFlag(space, objAddr, fieldOffset, isRoot);
258             break;
259         }
260         case (uint8_t)EncodeFlag::REFERENCE: {
261             uint32_t valueIndex = data_->ReadUint32(position_);
262             JSTaggedType valueAddr = objectVector_[valueIndex];
263             UpdateMaybeWeak(slot, valueAddr, GetAndResetWeak());
264             WriteBarrier<WriteBarrierType::DESERIALIZE>(thread_, reinterpret_cast<void *>(objAddr), fieldOffset,
265                                                         valueAddr);
266             break;
267         }
268         case (uint8_t)EncodeFlag::WEAK: {
269             ASSERT(!isWeak_);
270             isWeak_ = true;
271             handledFieldSize = 0;
272             break;
273         }
274         case (uint8_t)EncodeFlag::PRIMITIVE: {
275             JSTaggedType value = data_->ReadJSTaggedType(position_);
276             slot.Update(value);
277             break;
278         }
279         case (uint8_t)EncodeFlag::MULTI_RAW_DATA: {
280             uint32_t size = data_->ReadUint32(position_);
281             data_->ReadRawData(objAddr + fieldOffset, size, position_);
282             handledFieldSize = size;
283             break;
284         }
285         case (uint8_t)EncodeFlag::ROOT_OBJECT: {
286             uint32_t index = data_->ReadUint32(position_);
287             uintptr_t valueAddr = thread_->GetEcmaVM()->GetSnapshotEnv()->RelocateRootObjectAddr(index);
288             if (!isRoot && valueAddr > JSTaggedValue::INVALID_VALUE_LIMIT) {
289                 WriteBarrier<WriteBarrierType::DESERIALIZE>(thread_, reinterpret_cast<void *>(objAddr), fieldOffset,
290                                                             static_cast<JSTaggedType>(valueAddr));
291             }
292             UpdateMaybeWeak(slot, valueAddr, GetAndResetWeak());
293             break;
294         }
295         case (uint8_t)EncodeFlag::OBJECT_PROTO: {
296             uint8_t type = data_->ReadUint8(position_);
297             uintptr_t protoAddr = RelocateObjectProtoAddr(type);
298             if (!isRoot && protoAddr > JSTaggedValue::INVALID_VALUE_LIMIT) {
299                 WriteBarrier<WriteBarrierType::DESERIALIZE>(thread_, reinterpret_cast<void *>(objAddr), fieldOffset,
300                                                             static_cast<JSTaggedType>(protoAddr));
301             }
302             UpdateMaybeWeak(slot, protoAddr, GetAndResetWeak());
303             break;
304         }
305         case (uint8_t)EncodeFlag::TRANSFER_ARRAY_BUFFER: {
306             isTransferArrayBuffer_ = true;
307             handledFieldSize = 0;
308             break;
309         }
310         case (uint8_t)EncodeFlag::SHARED_ARRAY_BUFFER: {
311             isSharedArrayBuffer_ = true;
312             handledFieldSize = 0;
313             break;
314         }
315         case (uint8_t)EncodeFlag::ARRAY_BUFFER:
316         case (uint8_t)EncodeFlag::SENDABLE_ARRAY_BUFFER:
317         case (uint8_t)EncodeFlag::JS_REG_EXP: {
318             size_t bufferLength = data_->ReadUint32(position_);
319             auto nativeAreaAllocator = thread_->GetEcmaVM()->GetNativeAreaAllocator();
320             bufferPointer_ = nativeAreaAllocator->AllocateBuffer(bufferLength);
321             heap_->IncNativeSizeAfterLastGC(bufferLength);
322             data_->ReadRawData(ToUintPtr(bufferPointer_), bufferLength, position_);
323             heap_->IncreaseNativeBindingSize(bufferLength);
324             handledFieldSize = 0;
325             break;
326         }
327         case (uint8_t)EncodeFlag::NATIVE_BINDING_OBJECT: {
328             slot.Update(JSTaggedValue::Undefined().GetRawData());
329             AttachFunc af = reinterpret_cast<AttachFunc>(data_->ReadJSTaggedType(position_));
330             void *bufferPointer = reinterpret_cast<void *>(data_->ReadJSTaggedType(position_));
331             void *hint = reinterpret_cast<void *>(data_->ReadJSTaggedType(position_));
332             void *attachData = reinterpret_cast<void *>(data_->ReadJSTaggedType(position_));
333             // defer new native binding object until deserialize finish
334             nativeBindingInfos_.push_back(new NativeBindingInfo(af, bufferPointer, hint, attachData,
335                                                                 objAddr, fieldOffset, isRoot));
336             break;
337         }
338         case (uint8_t)EncodeFlag::JS_ERROR: {
339             slot.Update(JSTaggedValue::Undefined().GetRawData());
340             uint8_t type = data_->ReadUint8(position_);
341             ASSERT(type >= static_cast<uint8_t>(JSType::JS_ERROR_FIRST)
342                 && type <= static_cast<uint8_t>(JSType::JS_ERROR_LAST));
343             jsErrorInfos_.push_back(new JSErrorInfo(type, JSTaggedValue::Undefined(), objAddr, fieldOffset, isRoot));
344             uint8_t flag = data_->ReadUint8(position_);
345             if (flag == 1) { // error msg is string
346                 isErrorMsg_ = true;
347                 handledFieldSize = 0;
348             }
349             break;
350         }
351         case (uint8_t)EncodeFlag::SHARED_OBJECT: {
352             uint32_t index = data_->ReadUint32(position_);
353             if (UNLIKELY(index >= sharedObjChunk_->Size())) {
354                 LOG_ECMA(FATAL) << "Shared object index invalid, index: " << index << " chunkSize: "
355                     << sharedObjChunk_->Size();
356                 UNREACHABLE();
357             }
358             JSTaggedType value = sharedObjChunk_->Get(index);
359             objectVector_.push_back(value);
360             bool isErrorMsg = GetAndResetIsErrorMsg();
361             if (isErrorMsg) {
362                 // defer new js error
363                 jsErrorInfos_.back()->errorMsg_ = JSTaggedValue(value);
364                 break;
365             }
366             if (!isRoot) {
367                 WriteBarrier(thread_, reinterpret_cast<void *>(objAddr), fieldOffset, value);
368             }
369             UpdateMaybeWeak(slot, value, GetAndResetWeak());
370             break;
371         }
372         default:
373             LOG_ECMA(FATAL) << "this branch is unreachable";
374             UNREACHABLE();
375             break;
376     }
377     return handledFieldSize;
378 }
379 
RelocateObjectAddr(SerializedObjectSpace space,size_t objSize)380 uintptr_t BaseDeserializer::RelocateObjectAddr(SerializedObjectSpace space, size_t objSize)
381 {
382     uintptr_t res = 0U;
383     switch (space) {
384         case SerializedObjectSpace::OLD_SPACE: {
385             if (oldSpaceBeginAddr_ + objSize > AlignUp(oldSpaceBeginAddr_, DEFAULT_REGION_SIZE)) {
386                 ASSERT(oldRegionIndex_ < regionVector_.size());
387                 oldSpaceBeginAddr_ = regionVector_[oldRegionIndex_++]->GetBegin();
388             }
389             res = oldSpaceBeginAddr_;
390             oldSpaceBeginAddr_ += objSize;
391             break;
392         }
393         case SerializedObjectSpace::NON_MOVABLE_SPACE: {
394             if (nonMovableSpaceBeginAddr_ + objSize > AlignUp(nonMovableSpaceBeginAddr_, DEFAULT_REGION_SIZE)) {
395                 ASSERT(nonMovableRegionIndex_ < regionVector_.size());
396                 nonMovableSpaceBeginAddr_ = regionVector_[nonMovableRegionIndex_++]->GetBegin();
397             }
398             res = nonMovableSpaceBeginAddr_;
399             nonMovableSpaceBeginAddr_ += objSize;
400             break;
401         }
402         case SerializedObjectSpace::MACHINE_CODE_SPACE: {
403             if (machineCodeSpaceBeginAddr_ + objSize > AlignUp(machineCodeSpaceBeginAddr_, DEFAULT_REGION_SIZE)) {
404                 ASSERT(machineCodeRegionIndex_ < regionVector_.size());
405                 machineCodeSpaceBeginAddr_ = regionVector_[machineCodeRegionIndex_++]->GetBegin();
406             }
407             res = machineCodeSpaceBeginAddr_;
408             machineCodeSpaceBeginAddr_ += objSize;
409             break;
410         }
411         case SerializedObjectSpace::HUGE_SPACE: {
412             // no gc for this allocate
413             res = heap_->GetHugeObjectSpace()->Allocate(objSize, thread_, AllocateEventType::DESERIALIZE);
414             if (res == 0) {
415                 DeserializeFatalOutOfMemory(objSize, false, false);
416             }
417             break;
418         }
419         case SerializedObjectSpace::SHARED_OLD_SPACE: {
420             if (sOldSpaceBeginAddr_ + objSize > AlignUp(sOldSpaceBeginAddr_, DEFAULT_REGION_SIZE)) {
421                 ASSERT(sOldRegionIndex_ < regionVector_.size());
422                 sOldSpaceBeginAddr_ = regionVector_[sOldRegionIndex_++]->GetBegin();
423             }
424             res = sOldSpaceBeginAddr_;
425             sOldSpaceBeginAddr_ += objSize;
426             break;
427         }
428         case SerializedObjectSpace::SHARED_NON_MOVABLE_SPACE: {
429             if (sNonMovableSpaceBeginAddr_ + objSize > AlignUp(sNonMovableSpaceBeginAddr_, DEFAULT_REGION_SIZE)) {
430                 ASSERT(sNonMovableRegionIndex_ < regionVector_.size());
431                 sNonMovableSpaceBeginAddr_ = regionVector_[sNonMovableRegionIndex_++]->GetBegin();
432             }
433             res = sNonMovableSpaceBeginAddr_;
434             sNonMovableSpaceBeginAddr_ += objSize;
435             break;
436         }
437         case SerializedObjectSpace::SHARED_HUGE_SPACE: {
438             // no gc for this allocate
439             res = sheap_->GetHugeObjectSpace()->Allocate(thread_, objSize, AllocateEventType::DESERIALIZE);
440             if (res == 0) {
441                 DeserializeFatalOutOfMemory(objSize, false, true);
442             }
443             break;
444         }
445         default:
446             LOG_ECMA(FATAL) << "this branch is unreachable";
447             UNREACHABLE();
448     }
449     return res;
450 }
451 
RelocateObjectProtoAddr(uint8_t objectType)452 JSTaggedType BaseDeserializer::RelocateObjectProtoAddr(uint8_t objectType)
453 {
454     auto env = thread_->GetEcmaVM()->GetGlobalEnv();
455     switch (objectType) {
456         case (uint8_t)JSType::JS_OBJECT:
457             return env->GetObjectFunctionPrototype().GetTaggedType();
458         case (uint8_t)JSType::JS_ERROR:
459             return JSHandle<JSFunction>(env->GetErrorFunction())->GetFunctionPrototype().GetRawData();
460         case (uint8_t)JSType::JS_EVAL_ERROR:
461             return JSHandle<JSFunction>(env->GetEvalErrorFunction())->GetFunctionPrototype().GetRawData();
462         case (uint8_t)JSType::JS_RANGE_ERROR:
463             return JSHandle<JSFunction>(env->GetRangeErrorFunction())->GetFunctionPrototype().GetRawData();
464         case (uint8_t)JSType::JS_REFERENCE_ERROR:
465             return JSHandle<JSFunction>(env->GetReferenceErrorFunction())->GetFunctionPrototype().GetRawData();
466         case (uint8_t)JSType::JS_TYPE_ERROR:
467             return JSHandle<JSFunction>(env->GetTypeErrorFunction())->GetFunctionPrototype().GetRawData();
468         case (uint8_t)JSType::JS_AGGREGATE_ERROR:
469             return JSHandle<JSFunction>(env->GetAggregateErrorFunction())->GetFunctionPrototype().GetRawData();
470         case (uint8_t)JSType::JS_URI_ERROR:
471             return JSHandle<JSFunction>(env->GetURIErrorFunction())->GetFunctionPrototype().GetRawData();
472         case (uint8_t)JSType::JS_SYNTAX_ERROR:
473             return JSHandle<JSFunction>(env->GetSyntaxErrorFunction())->GetFunctionPrototype().GetRawData();
474         case (uint8_t)JSType::JS_OOM_ERROR:
475             return JSHandle<JSFunction>(env->GetOOMErrorFunction())->GetFunctionPrototype().GetRawData();
476         case (uint8_t)JSType::JS_TERMINATION_ERROR:
477             return JSHandle<JSFunction>(env->GetTerminationErrorFunction())->GetFunctionPrototype().GetRawData();
478         case (uint8_t)JSType::JS_DATE:
479             return env->GetDatePrototype().GetTaggedType();
480         case (uint8_t)JSType::JS_ARRAY:
481             return env->GetArrayPrototype().GetTaggedType();
482         case (uint8_t)JSType::JS_SHARED_ARRAY:
483             return env->GetSharedArrayPrototype().GetTaggedType();
484         case (uint8_t)JSType::JS_API_BITVECTOR:
485             return env->GetBitVectorPrototype().GetTaggedType();
486         case (uint8_t)JSType::JS_MAP:
487             return env->GetMapPrototype().GetTaggedType();
488         case (uint8_t)JSType::JS_SHARED_MAP:
489             return env->GetSharedMapPrototype().GetTaggedType();
490         case (uint8_t)JSType::JS_SET:
491             return env->GetSetPrototype().GetTaggedType();
492         case (uint8_t)JSType::JS_SHARED_SET:
493             return env->GetSharedSetPrototype().GetTaggedType();
494         case (uint8_t)JSType::JS_SENDABLE_ARRAY_BUFFER:
495             return env->GetSendableArrayBufferPrototype().GetTaggedType();
496         case (uint8_t)JSType::JS_REG_EXP:
497             return env->GetRegExpPrototype().GetTaggedType();
498         case (uint8_t)JSType::JS_INT8_ARRAY:
499             return env->GetInt8ArrayFunctionPrototype().GetTaggedType();
500         case (uint8_t)JSType::JS_UINT8_ARRAY:
501             return env->GetUint8ArrayFunctionPrototype().GetTaggedType();
502         case (uint8_t)JSType::JS_UINT8_CLAMPED_ARRAY:
503             return env->GetUint8ClampedArrayFunctionPrototype().GetTaggedType();
504         case (uint8_t)JSType::JS_INT16_ARRAY:
505             return env->GetInt16ArrayFunctionPrototype().GetTaggedType();
506         case (uint8_t)JSType::JS_UINT16_ARRAY:
507             return env->GetUint16ArrayFunctionPrototype().GetTaggedType();
508         case (uint8_t)JSType::JS_INT32_ARRAY:
509             return env->GetInt32ArrayFunctionPrototype().GetTaggedType();
510         case (uint8_t)JSType::JS_UINT32_ARRAY:
511             return env->GetUint32ArrayFunctionPrototype().GetTaggedType();
512         case (uint8_t)JSType::JS_FLOAT32_ARRAY:
513             return env->GetFloat32ArrayFunctionPrototype().GetTaggedType();
514         case (uint8_t)JSType::JS_FLOAT64_ARRAY:
515             return env->GetFloat64ArrayFunctionPrototype().GetTaggedType();
516         case (uint8_t)JSType::JS_BIGINT64_ARRAY:
517             return env->GetBigInt64ArrayFunctionPrototype().GetTaggedType();
518         case (uint8_t)JSType::JS_BIGUINT64_ARRAY:
519             return env->GetBigUint64ArrayFunctionPrototype().GetTaggedType();
520         case (uint8_t)JSType::JS_SHARED_INT8_ARRAY:
521             return env->GetSharedInt8ArrayFunctionPrototype().GetTaggedType();
522         case (uint8_t)JSType::JS_SHARED_UINT8_ARRAY:
523             return env->GetSharedUint8ArrayFunctionPrototype().GetTaggedType();
524         case (uint8_t)JSType::JS_SHARED_UINT8_CLAMPED_ARRAY:
525             return env->GetSharedUint8ClampedArrayFunctionPrototype().GetTaggedType();
526         case (uint8_t)JSType::JS_SHARED_INT16_ARRAY:
527             return env->GetSharedInt16ArrayFunctionPrototype().GetTaggedType();
528         case (uint8_t)JSType::JS_SHARED_UINT16_ARRAY:
529             return env->GetSharedUint16ArrayFunctionPrototype().GetTaggedType();
530         case (uint8_t)JSType::JS_SHARED_INT32_ARRAY:
531             return env->GetSharedInt32ArrayFunctionPrototype().GetTaggedType();
532         case (uint8_t)JSType::JS_SHARED_UINT32_ARRAY:
533             return env->GetSharedUint32ArrayFunctionPrototype().GetTaggedType();
534         case (uint8_t)JSType::JS_SHARED_FLOAT32_ARRAY:
535             return env->GetSharedFloat32ArrayFunctionPrototype().GetTaggedType();
536         case (uint8_t)JSType::JS_SHARED_FLOAT64_ARRAY:
537             return env->GetSharedFloat64ArrayFunctionPrototype().GetTaggedType();
538         case (uint8_t)JSType::JS_SHARED_BIGINT64_ARRAY:
539             return env->GetSharedBigInt64ArrayFunctionPrototype().GetTaggedType();
540         case (uint8_t)JSType::JS_SHARED_BIGUINT64_ARRAY:
541             return env->GetSharedBigUint64ArrayFunctionPrototype().GetTaggedType();
542         case (uint8_t)JSType::JS_ARRAY_BUFFER:
543             return JSHandle<JSFunction>(env->GetArrayBufferFunction())->GetFunctionPrototype().GetRawData();
544         case (uint8_t)JSType::JS_SHARED_ARRAY_BUFFER:
545             return JSHandle<JSFunction>(env->GetSharedArrayBufferFunction())->GetFunctionPrototype().GetRawData();
546         case (uint8_t)JSType::JS_ASYNC_FUNCTION:
547             return env->GetAsyncFunctionPrototype().GetTaggedType();
548         case (uint8_t)JSType::JS_SHARED_ASYNC_FUNCTION:
549             return env->GetSAsyncFunctionPrototype().GetTaggedType();
550         case (uint8_t)JSType::BIGINT:
551             return JSHandle<JSFunction>(env->GetBigIntFunction())->GetFunctionPrototype().GetRawData();
552         default:
553             LOG_ECMA(ERROR) << "Relocate unsupported JSType: " << JSHClass::DumpJSType(static_cast<JSType>(objectType));
554             LOG_ECMA(FATAL) << "this branch is unreachable";
555             UNREACHABLE();
556             break;
557     }
558 }
559 
AllocateToDifferentSpaces()560 void BaseDeserializer::AllocateToDifferentSpaces()
561 {
562     size_t oldSpaceSize = data_->GetOldSpaceSize();
563     if (oldSpaceSize > 0) {
564         heap_->GetOldSpace()->IncreaseLiveObjectSize(oldSpaceSize);
565         AllocateToOldSpace(oldSpaceSize);
566     }
567     size_t nonMovableSpaceSize = data_->GetNonMovableSpaceSize();
568     if (nonMovableSpaceSize > 0) {
569         heap_->GetNonMovableSpace()->IncreaseLiveObjectSize(nonMovableSpaceSize);
570         AllocateToNonMovableSpace(nonMovableSpaceSize);
571     }
572     size_t machineCodeSpaceSize = data_->GetMachineCodeSpaceSize();
573     if (machineCodeSpaceSize > 0) {
574         heap_->GetMachineCodeSpace()->IncreaseLiveObjectSize(machineCodeSpaceSize);
575         AllocateToMachineCodeSpace(machineCodeSpaceSize);
576     }
577     size_t sOldSpaceSize = data_->GetSharedOldSpaceSize();
578     if (sOldSpaceSize > 0) {
579         sheap_->GetOldSpace()->IncreaseLiveObjectSize(sOldSpaceSize);
580         AllocateToSharedOldSpace(sOldSpaceSize);
581     }
582     size_t sNonMovableSpaceSize = data_->GetSharedNonMovableSpaceSize();
583     if (sNonMovableSpaceSize > 0) {
584         sheap_->GetNonMovableSpace()->IncreaseLiveObjectSize(sNonMovableSpaceSize);
585         AllocateToSharedNonMovableSpace(sNonMovableSpaceSize);
586     }
587 }
588 
AllocateMultiRegion(SparseSpace * space,size_t spaceObjSize,size_t & regionIndex)589 void BaseDeserializer::AllocateMultiRegion(SparseSpace *space, size_t spaceObjSize, size_t &regionIndex)
590 {
591     regionIndex = regionVector_.size();
592     size_t regionAlignedSize = SerializeData::AlignUpRegionAvailableSize(spaceObjSize);
593     size_t regionNum = regionAlignedSize / Region::GetRegionAvailableSize();
594     while (regionNum > 1) { // 1: one region have allocated before
595         std::vector<size_t> regionRemainSizeVector = data_->GetRegionRemainSizeVector();
596         space->ResetTopPointer(space->GetCurrentRegion()->GetEnd() - regionRemainSizeVector[regionRemainSizeIndex_++]);
597         if (!space->Expand()) {
598             DeserializeFatalOutOfMemory(spaceObjSize);
599         }
600         Region *currentRegion = space->GetCurrentRegion();
601         FreeObject::FillFreeObject(heap_, currentRegion->GetBegin(), currentRegion->GetSize());
602         regionVector_.push_back(currentRegion);
603         regionNum--;
604     }
605     size_t lastRegionRemainSize = regionAlignedSize - spaceObjSize;
606     space->ResetTopPointer(space->GetCurrentRegion()->GetEnd() - lastRegionRemainSize);
607 }
608 
AllocateMultiSharedRegion(SharedSparseSpace * space,size_t spaceObjSize,size_t & regionIndex)609 void BaseDeserializer::AllocateMultiSharedRegion(SharedSparseSpace *space, size_t spaceObjSize, size_t &regionIndex)
610 {
611     regionIndex = regionVector_.size();
612     size_t regionAlignedSize = SerializeData::AlignUpRegionAvailableSize(spaceObjSize);
613     size_t regionNum = regionAlignedSize / Region::GetRegionAvailableSize();
614     std::vector<size_t> regionRemainSizeVector = data_->GetRegionRemainSizeVector();
615     std::vector<Region *> allocateRegions;
616     while (regionNum > 0) {
617         if (space->CommittedSizeExceed()) {
618             DeserializeFatalOutOfMemory(spaceObjSize, true, true);
619         }
620         Region *region = space->AllocateDeserializeRegion(thread_);
621         FreeObject::FillFreeObject(sheap_, region->GetBegin(), region->GetSize());
622         if (regionNum == 1) { // 1: Last allocate region
623             size_t lastRegionRemainSize = regionAlignedSize - spaceObjSize;
624             region->SetHighWaterMark(region->GetEnd() - lastRegionRemainSize);
625         } else {
626             region->SetHighWaterMark(region->GetEnd() - regionRemainSizeVector[regionRemainSizeIndex_++]);
627         }
628         region->IncreaseAliveObject(region->GetAllocatedBytes());
629         regionVector_.push_back(region);
630         allocateRegions.push_back(region);
631         regionNum--;
632     }
633     space->MergeDeserializeAllocateRegions(allocateRegions);
634 }
635 
AllocateToOldSpace(size_t oldSpaceSize)636 void BaseDeserializer::AllocateToOldSpace(size_t oldSpaceSize)
637 {
638     SparseSpace *space = heap_->GetOldSpace();
639     uintptr_t object = space->Allocate(oldSpaceSize, false);
640     if (UNLIKELY(object == 0U)) {
641         if (space->CommittedSizeExceed()) {
642             DeserializeFatalOutOfMemory(oldSpaceSize);
643         }
644         oldSpaceBeginAddr_ = space->GetCurrentRegion()->GetBegin();
645         FreeObject::FillFreeObject(heap_, oldSpaceBeginAddr_, space->GetCurrentRegion()->GetSize());
646         AllocateMultiRegion(space, oldSpaceSize, oldRegionIndex_);
647     } else {
648         FreeObject::FillFreeObject(heap_, object, oldSpaceSize);
649         oldSpaceBeginAddr_ = object;
650     }
651 }
652 
AllocateToNonMovableSpace(size_t nonMovableSpaceSize)653 void BaseDeserializer::AllocateToNonMovableSpace(size_t nonMovableSpaceSize)
654 {
655     SparseSpace *space = heap_->GetNonMovableSpace();
656     uintptr_t object = space->Allocate(nonMovableSpaceSize, false);
657     if (UNLIKELY(object == 0U)) {
658         if (space->CommittedSizeExceed()) {
659             DeserializeFatalOutOfMemory(nonMovableSpaceSize);
660         }
661         nonMovableSpaceBeginAddr_ = space->GetCurrentRegion()->GetBegin();
662         FreeObject::FillFreeObject(heap_, nonMovableSpaceBeginAddr_, space->GetCurrentRegion()->GetSize());
663         AllocateMultiRegion(space, nonMovableSpaceSize, nonMovableRegionIndex_);
664     } else {
665         FreeObject::FillFreeObject(heap_, object, nonMovableSpaceSize);
666         nonMovableSpaceBeginAddr_ = object;
667     }
668 }
669 
AllocateToMachineCodeSpace(size_t machineCodeSpaceSize)670 void BaseDeserializer::AllocateToMachineCodeSpace(size_t machineCodeSpaceSize)
671 {
672     SparseSpace *space = heap_->GetMachineCodeSpace();
673     uintptr_t object = space->Allocate(machineCodeSpaceSize, false);
674     if (UNLIKELY(object == 0U)) {
675         if (space->CommittedSizeExceed()) {
676             DeserializeFatalOutOfMemory(machineCodeSpaceSize);
677         }
678         machineCodeSpaceBeginAddr_ = space->GetCurrentRegion()->GetBegin();
679         FreeObject::FillFreeObject(heap_, machineCodeSpaceBeginAddr_, space->GetCurrentRegion()->GetSize());
680         AllocateMultiRegion(space, machineCodeSpaceSize, machineCodeRegionIndex_);
681     } else {
682         FreeObject::FillFreeObject(heap_, object, machineCodeSpaceSize);
683         machineCodeSpaceBeginAddr_ = object;
684     }
685 }
686 
AllocateToSharedOldSpace(size_t sOldSpaceSize)687 void BaseDeserializer::AllocateToSharedOldSpace(size_t sOldSpaceSize)
688 {
689     SharedSparseSpace *space = sheap_->GetOldSpace();
690     uintptr_t object = space->AllocateNoGCAndExpand(thread_, sOldSpaceSize);
691     if (UNLIKELY(object == 0U)) {
692         AllocateMultiSharedRegion(space, sOldSpaceSize, sOldRegionIndex_);
693         sOldSpaceBeginAddr_ = regionVector_[sOldRegionIndex_++]->GetBegin();
694     } else {
695         if (thread_->IsSharedConcurrentMarkingOrFinished()) {
696             Region *region = Region::ObjectAddressToRange(object);
697             region->IncreaseAliveObject(sOldSpaceSize);
698         }
699         FreeObject::FillFreeObject(sheap_, object, sOldSpaceSize);
700         sOldSpaceBeginAddr_ = object;
701     }
702 }
703 
AllocateToSharedNonMovableSpace(size_t sNonMovableSpaceSize)704 void BaseDeserializer::AllocateToSharedNonMovableSpace(size_t sNonMovableSpaceSize)
705 {
706     SharedNonMovableSpace *space = sheap_->GetNonMovableSpace();
707     uintptr_t object = space->AllocateNoGCAndExpand(thread_, sNonMovableSpaceSize);
708     if (UNLIKELY(object == 0U)) {
709         AllocateMultiSharedRegion(space, sNonMovableSpaceSize, sNonMovableRegionIndex_);
710         sNonMovableSpaceBeginAddr_ = regionVector_[sNonMovableRegionIndex_++]->GetBegin();
711     } else {
712         if (thread_->IsSharedConcurrentMarkingOrFinished()) {
713             Region *region = Region::ObjectAddressToRange(object);
714             region->IncreaseAliveObject(sNonMovableSpaceSize);
715         }
716         FreeObject::FillFreeObject(sheap_, object, sNonMovableSpaceSize);
717         sNonMovableSpaceBeginAddr_ = object;
718     }
719 }
720 
721 }  // namespace panda::ecmascript
722 
723