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