• 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/ecma_string_table.h"
19 #include "ecmascript/ecma_vm.h"
20 #include "ecmascript/global_env.h"
21 #include "ecmascript/js_arraybuffer.h"
22 #include "ecmascript/js_regexp.h"
23 #include "ecmascript/js_thread.h"
24 #include "ecmascript/mem/mem.h"
25 #include "ecmascript/mem/sparse_space.h"
26 
27 namespace panda::ecmascript {
28 
29 #define NEW_OBJECT_ALL_SPACES()                                           \
30     (uint8_t)SerializedObjectSpace::OLD_SPACE:                            \
31     case (uint8_t)SerializedObjectSpace::NON_MOVABLE_SPACE:               \
32     case (uint8_t)SerializedObjectSpace::MACHINE_CODE_SPACE:              \
33     case (uint8_t)SerializedObjectSpace::HUGE_SPACE
34 
ReadValue()35 JSHandle<JSTaggedValue> BaseDeserializer::ReadValue()
36 {
37     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "Deserialize dataSize: " + std::to_string(data_->Size()));
38     AllocateToDifferentSpaces();
39     JSHandle<JSTaggedValue> res = DeserializeJSTaggedValue();
40     return res;
41 }
42 
DeserializeJSTaggedValue()43 JSHandle<JSTaggedValue> BaseDeserializer::DeserializeJSTaggedValue()
44 {
45     if (data_->IsIncompleteData()) {
46         LOG_ECMA(ERROR) << "The serialization data is incomplete";
47         return JSHandle<JSTaggedValue>();
48     }
49 
50     // stop gc during deserialize
51     heap_->SetOnSerializeEvent(true);
52 
53     uint8_t encodeFlag = data_->ReadUint8();
54     JSTaggedType result = 0U;
55     while (ReadSingleEncodeData(encodeFlag, ToUintPtr(&result), 0, true) == 0) { // 0: root object offset
56         encodeFlag = data_->ReadUint8();
57     }
58     // now new constpool here if newConstPoolInfos_ is not empty
59     for (auto newConstpoolInfo : newConstPoolInfos_) {
60         DeserializeConstPool(newConstpoolInfo);
61         delete newConstpoolInfo;
62     }
63     newConstPoolInfos_.clear();
64 
65     // initialize concurrent func here after constpool is set
66     for (auto func : concurrentFunctions_) {
67         func->InitializeForConcurrentFunction(thread_);
68     }
69     concurrentFunctions_.clear();
70 
71     // new native binding object here
72     for (auto nativeBindingInfo : nativeBindingInfos_) {
73         DeserializeNativeBindingObject(nativeBindingInfo);
74         delete nativeBindingInfo;
75     }
76     nativeBindingInfos_.clear();
77 
78     // new js error here
79     for (auto jsErrorInfo : jsErrorInfos_) {
80         DeserializeJSError(jsErrorInfo);
81         delete jsErrorInfo;
82     }
83     jsErrorInfos_.clear();
84 
85     // recovery gc after serialize
86     heap_->SetOnSerializeEvent(false);
87 
88     // If is on concurrent mark, mark push root object to stack for mark
89     if (JSTaggedValue(result).IsHeapObject() && thread_->IsConcurrentMarkingOrFinished()) {
90         Barriers::MarkAndPushForDeserialize(thread_, JSTaggedValue(result).GetHeapObject());
91     }
92 
93     return JSHandle<JSTaggedValue>(thread_, JSTaggedValue(result));
94 }
95 
DeserializeTaggedObject(SerializedObjectSpace space)96 uintptr_t BaseDeserializer::DeserializeTaggedObject(SerializedObjectSpace space)
97 {
98     size_t objSize = data_->ReadUint32();
99     uintptr_t res = RelocateObjectAddr(space, objSize);
100     objectVector_.push_back(res);
101     size_t resIndex = objectVector_.size() - 1;
102     DeserializeObjectField(res, res + objSize);
103     JSType type = reinterpret_cast<TaggedObject *>(res)->GetClass()->GetObjectType();
104     // String need remove duplicates if string table can find
105     if (type == JSType::LINE_STRING || type == JSType::CONSTANT_STRING) {
106         EcmaStringTable *stringTable = thread_->GetEcmaVM()->GetEcmaStringTable();
107         EcmaString *str = stringTable->GetString(reinterpret_cast<EcmaString *>(res));
108         if (str) {
109             res = ToUintPtr(str);
110             objectVector_[resIndex] = res;
111         } else {
112             EcmaStringAccessor(reinterpret_cast<EcmaString *>(res)).ClearInternString();
113             stringTable->InternString(reinterpret_cast<EcmaString *>(res));
114         }
115     }
116     return res;
117 }
118 
DeserializeObjectField(uintptr_t start,uintptr_t end)119 void BaseDeserializer::DeserializeObjectField(uintptr_t start, uintptr_t end)
120 {
121     size_t offset = 0; // 0: initial offset
122     while (start + offset < end) {
123         uint8_t encodeFlag = data_->ReadUint8();
124         offset += ReadSingleEncodeData(encodeFlag, start, offset);
125     }
126 }
127 
DeserializeConstPool(NewConstPoolInfo * info)128 void BaseDeserializer::DeserializeConstPool(NewConstPoolInfo *info)
129 {
130     [[maybe_unused]] EcmaHandleScope scope(thread_);
131     JSPandaFile *jsPandaFile = info->jsPandaFile_;
132     panda_file::File::EntityId methodId = info->methodId_;
133     ObjectSlot slot = info->GetSlot();
134     JSHandle<ConstantPool> constpool = ConstantPool::CreateConstPool(thread_->GetEcmaVM(), jsPandaFile, methodId);
135     panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(), methodId);
136     int32_t index = static_cast<int32_t>(indexAccessor.GetHeaderIndex());
137     thread_->GetCurrentEcmaContext()->AddConstpool(jsPandaFile, constpool.GetTaggedValue(), index);
138 
139     slot.Update(constpool.GetTaggedType());
140     WriteBarrier(thread_, reinterpret_cast<void *>(info->GetObjAddr()), info->GetFieldOffset(),
141                  constpool.GetTaggedType());
142 }
143 
DeserializeNativeBindingObject(NativeBindingInfo * info)144 void BaseDeserializer::DeserializeNativeBindingObject(NativeBindingInfo *info)
145 {
146     [[maybe_unused]] EcmaHandleScope scope(thread_);
147     AttachFunc af = info->af_;
148     void *bufferPointer = info->bufferPointer_;
149     void *hint = info->hint_;
150     void *attachData = info->attachData_;
151     bool root = info->root_;
152     Local<JSValueRef> attachVal = af(engine_, bufferPointer, hint, attachData);
153     if (attachVal.IsEmpty()) {
154         LOG_ECMA(ERROR) << "NativeBindingObject is empty";
155         attachVal = JSValueRef::Undefined(thread_->GetEcmaVM());
156     }
157     JSTaggedType res = JSNApiHelper::ToJSHandle(attachVal).GetTaggedType();
158     ObjectSlot slot = info->GetSlot();
159     slot.Update(res);
160     if (!root && !JSTaggedValue(res).IsInvalidValue()) {
161         WriteBarrier(thread_, reinterpret_cast<void *>(info->GetObjAddr()), info->GetFieldOffset(), res);
162     }
163 }
164 
DeserializeJSError(JSErrorInfo * info)165 void BaseDeserializer::DeserializeJSError(JSErrorInfo *info)
166 {
167     [[maybe_unused]] EcmaHandleScope scope(thread_);
168     uint8_t type = info->errorType_;
169     base::ErrorType errorType = base::ErrorType(type - static_cast<uint8_t>(JSType::JS_ERROR_FIRST));
170     JSTaggedValue errorMsg = info->errorMsg_;
171     bool root = info->root_;
172     ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
173     JSHandle<JSObject> errorTag = factory->NewJSError(errorType, JSHandle<EcmaString>(thread_, errorMsg));
174     ObjectSlot slot = info->GetSlot();
175     slot.Update(errorTag.GetTaggedType());
176     if (!root && !errorTag.GetTaggedValue().IsInvalidValue()) {
177         WriteBarrier(thread_, reinterpret_cast<void *>(info->GetObjAddr()), info->GetFieldOffset(),
178                      errorTag.GetTaggedType());
179     }
180 }
181 
HandleNewObjectEncodeFlag(SerializedObjectSpace space,uintptr_t objAddr,size_t fieldOffset,bool isRoot)182 void BaseDeserializer::HandleNewObjectEncodeFlag(SerializedObjectSpace space,  uintptr_t objAddr, size_t fieldOffset,
183                                                  bool isRoot)
184 {
185     // deserialize object prologue
186     bool isWeak = GetAndResetWeak();
187     bool isTransferBuffer = GetAndResetTransferBuffer();
188     void *bufferPointer = GetAndResetBufferPointer();
189     ConstantPool *constpool = GetAndResetConstantPool();
190     bool needNewConstPool = GetAndResetNeedNewConstPool();
191     bool isErrorMsg = GetAndResetIsErrorMsg();
192     bool functionInShared = GetAndResetFunctionInShared();
193 
194     // deserialize object here
195     uintptr_t addr = DeserializeTaggedObject(space);
196 
197     // deserialize object epilogue
198     if (isErrorMsg) {
199         // defer new js error
200         jsErrorInfos_.back()->errorMsg_ = JSTaggedValue(static_cast<JSTaggedType>(addr));
201         return;
202     }
203 
204     if (isTransferBuffer) {
205         TransferArrayBufferAttach(addr);
206     } else if (bufferPointer != nullptr) {
207         ResetNativePointerBuffer(addr, bufferPointer);
208     } else if (constpool != nullptr) {
209         ResetMethodConstantPool(addr, constpool);
210     } else if (needNewConstPool) {
211         // defer new constpool
212         newConstPoolInfos_.back()->objAddr_ = addr;
213         newConstPoolInfos_.back()->offset_ = Method::CONSTANT_POOL_OFFSET;
214     }
215     if (functionInShared) {
216         concurrentFunctions_.push_back(reinterpret_cast<JSFunction *>(addr));
217     }
218     TaggedObject *object = reinterpret_cast<TaggedObject *>(addr);
219     if (object->GetClass()->IsJSNativePointer()) {
220         JSNativePointer *nativePointer = reinterpret_cast<JSNativePointer *>(object);
221         if (nativePointer->GetDeleter() != nullptr) {
222             thread_->GetEcmaVM()->PushToNativePointerList(nativePointer);
223         }
224     } else if (object->GetClass()->IsJSFunction()) {
225         JSFunction* func = reinterpret_cast<JSFunction *>(object);
226         FunctionKind funcKind = func->GetFunctionKind();
227         if (funcKind == FunctionKind::CONCURRENT_FUNCTION) {
228             // defer initialize concurrent function until constpool is set
229             concurrentFunctions_.push_back(reinterpret_cast<JSFunction *>(object));
230         }
231     }
232     UpdateMaybeWeak(ObjectSlot(objAddr + fieldOffset), addr, isWeak);
233     if (!isRoot) {
234         WriteBarrier<WriteBarrierType::DESERIALIZE>(thread_, reinterpret_cast<void *>(objAddr), fieldOffset,
235                                                     static_cast<JSTaggedType>(addr));
236     }
237 }
238 
HandleMethodEncodeFlag()239 void BaseDeserializer::HandleMethodEncodeFlag()
240 {
241     panda_file::File::EntityId methodId = MethodLiteral::GetMethodId(data_->ReadJSTaggedType());
242     JSPandaFile *jsPandaFile = reinterpret_cast<JSPandaFile *>(data_->ReadJSTaggedType());
243     panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(), methodId);
244     int32_t index = static_cast<int32_t>(indexAccessor.GetHeaderIndex());
245     JSTaggedValue constpool = thread_->GetCurrentEcmaContext()->FindConstpoolWithAOT(jsPandaFile, index);
246     if (constpool.IsHole()) {
247         LOG_ECMA(INFO) << "ValueDeserialize: function deserialize can't find constpool from panda file: "
248             << jsPandaFile;
249         // defer new constpool until deserialize finish
250         needNewConstPool_ = true;
251         newConstPoolInfos_.push_back(new NewConstPoolInfo(jsPandaFile, methodId));
252     } else {
253         constpool_ = reinterpret_cast<ConstantPool *>(constpool.GetTaggedObject());
254     }
255 }
256 
TransferArrayBufferAttach(uintptr_t objAddr)257 void BaseDeserializer::TransferArrayBufferAttach(uintptr_t objAddr)
258 {
259     ASSERT(JSTaggedValue(static_cast<JSTaggedType>(objAddr)).IsArrayBuffer());
260     JSArrayBuffer *arrayBuffer = reinterpret_cast<JSArrayBuffer *>(objAddr);
261     size_t arrayLength = arrayBuffer->GetArrayBufferByteLength();
262     bool withNativeAreaAllocator = arrayBuffer->GetWithNativeAreaAllocator();
263     JSNativePointer *np = reinterpret_cast<JSNativePointer *>(arrayBuffer->GetArrayBufferData().GetTaggedObject());
264     arrayBuffer->Attach(thread_, arrayLength, JSTaggedValue(np), withNativeAreaAllocator);
265 }
266 
ResetNativePointerBuffer(uintptr_t objAddr,void * bufferPointer)267 void BaseDeserializer::ResetNativePointerBuffer(uintptr_t objAddr, void *bufferPointer)
268 {
269     JSTaggedValue obj = JSTaggedValue(static_cast<JSTaggedType>(objAddr));
270     ASSERT(obj.IsArrayBuffer() || obj.IsJSRegExp());
271     auto nativeAreaAllocator = thread_->GetEcmaVM()->GetNativeAreaAllocator();
272     JSNativePointer *np = nullptr;
273     if (obj.IsArrayBuffer()) {
274         JSArrayBuffer *arrayBuffer = reinterpret_cast<JSArrayBuffer *>(objAddr);
275         arrayBuffer->SetWithNativeAreaAllocator(true);
276         np = reinterpret_cast<JSNativePointer *>(arrayBuffer->GetArrayBufferData().GetTaggedObject());
277         nativeAreaAllocator->IncreaseNativeSizeStats(arrayBuffer->GetArrayBufferByteLength(), NativeFlag::ARRAY_BUFFER);
278     } else {
279         JSRegExp *jsRegExp = reinterpret_cast<JSRegExp *>(objAddr);
280         np = reinterpret_cast<JSNativePointer *>(jsRegExp->GetByteCodeBuffer().GetTaggedObject());
281         nativeAreaAllocator->IncreaseNativeSizeStats(jsRegExp->GetLength(), NativeFlag::REGEXP_BTYECODE);
282     }
283 
284     np->SetExternalPointer(bufferPointer);
285     np->SetDeleter(NativeAreaAllocator::FreeBufferFunc);
286     np->SetData(thread_->GetEcmaVM()->GetNativeAreaAllocator());
287 }
288 
ResetMethodConstantPool(uintptr_t objAddr,ConstantPool * constpool)289 void BaseDeserializer::ResetMethodConstantPool(uintptr_t objAddr, ConstantPool *constpool)
290 {
291     ASSERT(JSTaggedValue(static_cast<JSTaggedType>(objAddr)).IsMethod());
292     Method *method = reinterpret_cast<Method *>(objAddr);
293     method->SetConstantPool(thread_, JSTaggedValue(constpool), BarrierMode::SKIP_BARRIER);
294 }
295 
ReadSingleEncodeData(uint8_t encodeFlag,uintptr_t objAddr,size_t fieldOffset,bool isRoot)296 size_t BaseDeserializer::ReadSingleEncodeData(uint8_t encodeFlag, uintptr_t objAddr, size_t fieldOffset, bool isRoot)
297 {
298     size_t handledFieldSize = sizeof(JSTaggedType);
299     ObjectSlot slot(objAddr + fieldOffset);
300     switch (encodeFlag) {
301         case NEW_OBJECT_ALL_SPACES(): {
302             SerializedObjectSpace space = SerializeData::DecodeSpace(encodeFlag);
303             HandleNewObjectEncodeFlag(space, objAddr, fieldOffset, isRoot);
304             break;
305         }
306         case (uint8_t)EncodeFlag::REFERENCE: {
307             uint32_t valueIndex = data_->ReadUint32();
308             uintptr_t valueAddr = objectVector_[valueIndex];
309             UpdateMaybeWeak(slot, valueAddr, GetAndResetWeak());
310             WriteBarrier<WriteBarrierType::DESERIALIZE>(thread_, reinterpret_cast<void *>(objAddr), fieldOffset,
311                                                         static_cast<JSTaggedType>(valueAddr));
312             break;
313         }
314         case (uint8_t)EncodeFlag::WEAK: {
315             ASSERT(!isWeak_);
316             isWeak_ = true;
317             handledFieldSize = 0;
318             break;
319         }
320         case (uint8_t)EncodeFlag::PRIMITIVE: {
321             JSTaggedType value = data_->ReadJSTaggedType();
322             slot.Update(value);
323             break;
324         }
325         case (uint8_t)EncodeFlag::MULTI_RAW_DATA: {
326             uint32_t size = data_->ReadUint32();
327             data_->ReadRawData(objAddr + fieldOffset, size);
328             handledFieldSize = size;
329             break;
330         }
331         case (uint8_t)EncodeFlag::ROOT_OBJECT: {
332             uint32_t index = data_->ReadUint32();
333             uintptr_t valueAddr = thread_->GetEcmaVM()->GetSnapshotEnv()->RelocateRootObjectAddr(index);
334             if (!isRoot && valueAddr > JSTaggedValue::INVALID_VALUE_LIMIT) {
335                 WriteBarrier<WriteBarrierType::DESERIALIZE>(thread_, reinterpret_cast<void *>(objAddr), fieldOffset,
336                                                             static_cast<JSTaggedType>(valueAddr));
337             }
338             UpdateMaybeWeak(slot, valueAddr, GetAndResetWeak());
339             break;
340         }
341         case (uint8_t)EncodeFlag::OBJECT_PROTO: {
342             uint8_t type = data_->ReadUint8();
343             uintptr_t protoAddr = RelocateObjectProtoAddr(type);
344             if (!isRoot && protoAddr > JSTaggedValue::INVALID_VALUE_LIMIT) {
345                 WriteBarrier<WriteBarrierType::DESERIALIZE>(thread_, reinterpret_cast<void *>(objAddr), fieldOffset,
346                                                             static_cast<JSTaggedType>(protoAddr));
347             }
348             UpdateMaybeWeak(slot, protoAddr, GetAndResetWeak());
349             break;
350         }
351         case (uint8_t)EncodeFlag::TRANSFER_ARRAY_BUFFER: {
352             isTransferArrayBuffer_ = true;
353             handledFieldSize = 0;
354             break;
355         }
356         case (uint8_t)EncodeFlag::ARRAY_BUFFER:
357         case (uint8_t)EncodeFlag::JS_REG_EXP: {
358             size_t bufferLength = data_->ReadUint32();
359             auto nativeAreaAllocator = thread_->GetEcmaVM()->GetNativeAreaAllocator();
360             bufferPointer_ = nativeAreaAllocator->AllocateBuffer(bufferLength);
361             data_->ReadRawData(ToUintPtr(bufferPointer_), bufferLength);
362             heap_->IncreaseNativeBindingSize(bufferLength);
363             handledFieldSize = 0;
364             break;
365         }
366         case (uint8_t)EncodeFlag::METHOD: {
367             HandleMethodEncodeFlag();
368             handledFieldSize = 0;
369             break;
370         }
371         case (uint8_t)EncodeFlag::NATIVE_BINDING_OBJECT: {
372             slot.Update(JSTaggedValue::Undefined().GetRawData());
373             AttachFunc af = reinterpret_cast<AttachFunc>(data_->ReadJSTaggedType());
374             void *bufferPointer = reinterpret_cast<void *>(data_->ReadJSTaggedType());
375             void *hint = reinterpret_cast<void *>(data_->ReadJSTaggedType());
376             void *attachData = reinterpret_cast<void *>(data_->ReadJSTaggedType());
377             // defer new native binding object until deserialize finish
378             nativeBindingInfos_.push_back(new NativeBindingInfo(af, bufferPointer, hint, attachData,
379                                                                 objAddr, fieldOffset, isRoot));
380             break;
381         }
382         case (uint8_t)EncodeFlag::JS_ERROR: {
383             uint8_t type = data_->ReadUint8();
384             ASSERT(type >= static_cast<uint8_t>(JSType::JS_ERROR_FIRST)
385                 && type <= static_cast<uint8_t>(JSType::JS_ERROR_LAST));
386             jsErrorInfos_.push_back(new JSErrorInfo(type, JSTaggedValue::Undefined(), objAddr, fieldOffset, isRoot));
387             uint8_t flag = data_->ReadUint8();
388             if (flag == 1) { // error msg is string
389                 isErrorMsg_ = true;
390                 handledFieldSize = 0;
391             }
392             break;
393         }
394         case (uint8_t)EncodeFlag::JS_FUNCTION_IN_SHARED: {
395             functionInShared_ = true;
396             handledFieldSize = 0;
397             break;
398         }
399         default:
400             LOG_ECMA(FATAL) << "this branch is unreachable";
401             UNREACHABLE();
402             break;
403     }
404     return handledFieldSize;
405 }
406 
RelocateObjectAddr(SerializedObjectSpace space,size_t objSize)407 uintptr_t BaseDeserializer::RelocateObjectAddr(SerializedObjectSpace space, size_t objSize)
408 {
409     uintptr_t res = 0U;
410     switch (space) {
411         case SerializedObjectSpace::OLD_SPACE: {
412             if (oldSpaceBeginAddr_ + objSize > AlignUp(oldSpaceBeginAddr_, DEFAULT_REGION_SIZE)) {
413                 ASSERT(oldRegionIndex_ < regionVector_.size());
414                 oldSpaceBeginAddr_ = regionVector_[oldRegionIndex_++]->GetBegin();
415             }
416             res = oldSpaceBeginAddr_;
417             oldSpaceBeginAddr_ += objSize;
418             break;
419         }
420         case SerializedObjectSpace::NON_MOVABLE_SPACE: {
421             if (nonMovableSpaceBeginAddr_ + objSize > AlignUp(nonMovableSpaceBeginAddr_, DEFAULT_REGION_SIZE)) {
422                 ASSERT(nonMovableRegionIndex_ < regionVector_.size());
423                 nonMovableSpaceBeginAddr_ = regionVector_[nonMovableRegionIndex_++]->GetBegin();
424             }
425             res = nonMovableSpaceBeginAddr_;
426             nonMovableSpaceBeginAddr_ += objSize;
427             break;
428         }
429         case SerializedObjectSpace::MACHINE_CODE_SPACE: {
430             if (machineCodeSpaceBeginAddr_ + objSize > AlignUp(machineCodeSpaceBeginAddr_, DEFAULT_REGION_SIZE)) {
431                 ASSERT(machineCodeRegionIndex_ < regionVector_.size());
432                 machineCodeSpaceBeginAddr_ = regionVector_[machineCodeRegionIndex_++]->GetBegin();
433             }
434             res = nonMovableSpaceBeginAddr_;
435             nonMovableSpaceBeginAddr_ += objSize;
436             break;
437         }
438         default:
439             // no gc for this allocate
440             res = heap_->GetHugeObjectSpace()->Allocate(objSize, thread_);
441             break;
442     }
443     return res;
444 }
445 
RelocateObjectProtoAddr(uint8_t objectType)446 JSTaggedType BaseDeserializer::RelocateObjectProtoAddr(uint8_t objectType)
447 {
448     auto env = thread_->GetEcmaVM()->GetGlobalEnv();
449     switch (objectType) {
450         case (uint8_t)JSType::JS_OBJECT:
451             return env->GetObjectFunctionPrototype().GetTaggedType();
452         case (uint8_t)JSType::JS_ERROR:
453             return JSHandle<JSFunction>(env->GetErrorFunction())->GetFunctionPrototype().GetRawData();
454         case (uint8_t)JSType::JS_EVAL_ERROR:
455             return JSHandle<JSFunction>(env->GetEvalErrorFunction())->GetFunctionPrototype().GetRawData();
456         case (uint8_t)JSType::JS_RANGE_ERROR:
457             return JSHandle<JSFunction>(env->GetRangeErrorFunction())->GetFunctionPrototype().GetRawData();
458         case (uint8_t)JSType::JS_REFERENCE_ERROR:
459             return JSHandle<JSFunction>(env->GetReferenceErrorFunction())->GetFunctionPrototype().GetRawData();
460         case (uint8_t)JSType::JS_TYPE_ERROR:
461             return JSHandle<JSFunction>(env->GetTypeErrorFunction())->GetFunctionPrototype().GetRawData();
462         case (uint8_t)JSType::JS_AGGREGATE_ERROR:
463             return JSHandle<JSFunction>(env->GetAggregateErrorFunction())->GetFunctionPrototype().GetRawData();
464         case (uint8_t)JSType::JS_URI_ERROR:
465             return JSHandle<JSFunction>(env->GetURIErrorFunction())->GetFunctionPrototype().GetRawData();
466         case (uint8_t)JSType::JS_SYNTAX_ERROR:
467             return JSHandle<JSFunction>(env->GetSyntaxErrorFunction())->GetFunctionPrototype().GetRawData();
468         case (uint8_t)JSType::JS_OOM_ERROR:
469             return JSHandle<JSFunction>(env->GetOOMErrorFunction())->GetFunctionPrototype().GetRawData();
470         case (uint8_t)JSType::JS_TERMINATION_ERROR:
471             return JSHandle<JSFunction>(env->GetTerminationErrorFunction())->GetFunctionPrototype().GetRawData();
472         case (uint8_t)JSType::JS_DATE:
473             return env->GetDatePrototype().GetTaggedType();
474         case (uint8_t)JSType::JS_ARRAY:
475             return env->GetArrayPrototype().GetTaggedType();
476         case (uint8_t)JSType::JS_MAP:
477             return env->GetMapPrototype().GetTaggedType();
478         case (uint8_t)JSType::JS_SET:
479             return env->GetSetPrototype().GetTaggedType();
480         case (uint8_t)JSType::JS_REG_EXP:
481             return env->GetRegExpPrototype().GetTaggedType();
482         case (uint8_t)JSType::JS_INT8_ARRAY:
483             return env->GetInt8ArrayFunctionPrototype().GetTaggedType();
484         case (uint8_t)JSType::JS_UINT8_ARRAY:
485             return env->GetUint8ArrayFunctionPrototype().GetTaggedType();
486         case (uint8_t)JSType::JS_UINT8_CLAMPED_ARRAY:
487             return env->GetUint8ClampedArrayFunctionPrototype().GetTaggedType();
488         case (uint8_t)JSType::JS_INT16_ARRAY:
489             return env->GetInt16ArrayFunctionPrototype().GetTaggedType();
490         case (uint8_t)JSType::JS_UINT16_ARRAY:
491             return env->GetUint16ArrayFunctionPrototype().GetTaggedType();
492         case (uint8_t)JSType::JS_INT32_ARRAY:
493             return env->GetInt32ArrayFunctionPrototype().GetTaggedType();
494         case (uint8_t)JSType::JS_UINT32_ARRAY:
495             return env->GetUint32ArrayFunctionPrototype().GetTaggedType();
496         case (uint8_t)JSType::JS_FLOAT32_ARRAY:
497             return env->GetFloat32ArrayFunctionPrototype().GetTaggedType();
498         case (uint8_t)JSType::JS_FLOAT64_ARRAY:
499             return env->GetFloat64ArrayFunctionPrototype().GetTaggedType();
500         case (uint8_t)JSType::JS_BIGINT64_ARRAY:
501             return env->GetBigInt64ArrayFunctionPrototype().GetTaggedType();
502         case (uint8_t)JSType::JS_BIGUINT64_ARRAY:
503             return env->GetBigUint64ArrayFunctionPrototype().GetTaggedType();
504         case (uint8_t)JSType::JS_ARRAY_BUFFER:
505             return JSHandle<JSFunction>(env->GetArrayBufferFunction())->GetFunctionPrototype().GetRawData();
506         case (uint8_t)JSType::JS_SHARED_ARRAY_BUFFER:
507             return JSHandle<JSFunction>(env->GetSharedArrayBufferFunction())->GetFunctionPrototype().GetRawData();
508         case (uint8_t)JSType::JS_ASYNC_FUNCTION:
509             return env->GetAsyncFunctionPrototype().GetTaggedType();
510         case (uint8_t)JSType::BIGINT:
511             return JSHandle<JSFunction>(env->GetBigIntFunction())->GetFunctionPrototype().GetRawData();
512         default:
513             LOG_ECMA(ERROR) << "Relocate unsupported JSType: " << JSHClass::DumpJSType(static_cast<JSType>(objectType));
514             LOG_ECMA(FATAL) << "this branch is unreachable";
515             UNREACHABLE();
516             break;
517     }
518 }
519 
AllocateToDifferentSpaces()520 void BaseDeserializer::AllocateToDifferentSpaces()
521 {
522     size_t oldSpaceSize = data_->GetOldSpaceSize();
523     if (oldSpaceSize > 0) {
524         heap_->GetOldSpace()->IncreaseLiveObjectSize(oldSpaceSize);
525         AllocateToOldSpace(oldSpaceSize);
526     }
527     size_t nonMovableSpaceSize = data_->GetNonMovableSpaceSize();
528     if (nonMovableSpaceSize > 0) {
529         heap_->GetNonMovableSpace()->IncreaseLiveObjectSize(nonMovableSpaceSize);
530         AllocateToNonMovableSpace(nonMovableSpaceSize);
531     }
532     size_t machineCodeSpaceSize = data_->GetMachineCodeSpaceSize();
533     if (machineCodeSpaceSize > 0) {
534         heap_->GetMachineCodeSpace()->IncreaseLiveObjectSize(machineCodeSpaceSize);
535         AllocateToMachineCodeSpace(machineCodeSpaceSize);
536     }
537 }
538 
AllocateMultiRegion(SparseSpace * space,size_t spaceObjSize,size_t & regionIndex)539 void BaseDeserializer::AllocateMultiRegion(SparseSpace *space, size_t spaceObjSize, size_t &regionIndex)
540 {
541     regionIndex = regionVector_.size();
542     size_t regionAlignedSize = SerializeData::AlignUpRegionAvailableSize(spaceObjSize);
543     size_t regionNum = regionAlignedSize / Region::GetRegionAvailableSize();
544     while (regionNum > 1) { // 1: one region have allocated before
545         std::vector<size_t> regionRemainSizeVector = data_->GetRegionRemainSizeVector();
546         space->ResetTopPointer(space->GetCurrentRegion()->GetEnd() - regionRemainSizeVector[regionRemainSizeIndex_++]);
547         if (!space->Expand()) {
548             LOG_ECMA(FATAL) << "BaseDeserializer::OutOfMemory when deserialize";
549         }
550         regionVector_.push_back(space->GetCurrentRegion());
551         regionNum--;
552     }
553     size_t lastRegionRemainSize = regionAlignedSize - spaceObjSize;
554     space->ResetTopPointer(space->GetCurrentRegion()->GetEnd() - lastRegionRemainSize);
555 }
556 
AllocateToOldSpace(size_t oldSpaceSize)557 void BaseDeserializer::AllocateToOldSpace(size_t oldSpaceSize)
558 {
559     SparseSpace *space = heap_->GetOldSpace();
560     uintptr_t object = space->Allocate(oldSpaceSize, false);
561     if (UNLIKELY(object == 0U)) {
562         if (space->CommittedSizeExceed()) {
563             LOG_ECMA(FATAL) << "BaseDeserializer::OutOfMemory when deserialize";
564         }
565         oldSpaceBeginAddr_ = space->GetCurrentRegion()->GetBegin();
566         AllocateMultiRegion(space, oldSpaceSize, oldRegionIndex_);
567     } else {
568         oldSpaceBeginAddr_ = object;
569     }
570 }
571 
AllocateToNonMovableSpace(size_t nonMovableSpaceSize)572 void BaseDeserializer::AllocateToNonMovableSpace(size_t nonMovableSpaceSize)
573 {
574     SparseSpace *space = heap_->GetNonMovableSpace();
575     uintptr_t object = space->Allocate(nonMovableSpaceSize, false);
576     if (UNLIKELY(object == 0U)) {
577         if (space->CommittedSizeExceed()) {
578             LOG_ECMA(FATAL) << "BaseDeserializer::OutOfMemory when deserialize";
579         }
580         nonMovableSpaceBeginAddr_ = space->GetCurrentRegion()->GetBegin();
581         AllocateMultiRegion(space, nonMovableSpaceSize, nonMovableRegionIndex_);
582     } else {
583         nonMovableSpaceBeginAddr_ = object;
584     }
585 }
586 
AllocateToMachineCodeSpace(size_t machineCodeSpaceSize)587 void BaseDeserializer::AllocateToMachineCodeSpace(size_t machineCodeSpaceSize)
588 {
589     SparseSpace *space = heap_->GetMachineCodeSpace();
590     uintptr_t object = space->Allocate(machineCodeSpaceSize, false);
591     if (UNLIKELY(object == 0U)) {
592         if (space->CommittedSizeExceed()) {
593             LOG_ECMA(FATAL) << "BaseDeserializer::OutOfMemory when deserialize";
594         }
595         machineCodeSpaceBeginAddr_ = space->GetCurrentRegion()->GetBegin();
596         AllocateMultiRegion(space, machineCodeSpaceSize, machineCodeRegionIndex_);
597     } else {
598         machineCodeSpaceBeginAddr_ = object;
599     }
600 }
601 
602 }  // namespace panda::ecmascript
603 
604