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 ®ionIndex)
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