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