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 thread_->GetEcmaVM()->PushToNativePointerList(nativePointer);
185 }
186 } else if (object->GetClass()->IsJSFunction()) {
187 JSFunction* func = reinterpret_cast<JSFunction *>(object);
188 FunctionKind funcKind = func->GetFunctionKind();
189 if (funcKind == FunctionKind::CONCURRENT_FUNCTION || object->GetClass()->IsJSSharedFunction()) {
190 // defer initialize concurrent function
191 JSHandle<JSFunction> funcHandle(thread_, func);
192 concurrentFunctions_.push_back(funcHandle);
193 }
194 func->SetRawProfileTypeInfo(thread_, thread_->GlobalConstants()->GetEmptyProfileTypeInfoCell(), SKIP_BARRIER);
195 func->SetWorkNodePointer(reinterpret_cast<uintptr_t>(nullptr));
196 }
197 UpdateMaybeWeak(ObjectSlot(objAddr + fieldOffset), addr, isWeak);
198 if (!isRoot) {
199 WriteBarrier<WriteBarrierType::DESERIALIZE>(thread_, reinterpret_cast<void *>(objAddr), fieldOffset,
200 static_cast<JSTaggedType>(addr));
201 }
202 }
203
TransferArrayBufferAttach(uintptr_t objAddr)204 void BaseDeserializer::TransferArrayBufferAttach(uintptr_t objAddr)
205 {
206 ASSERT(JSTaggedValue(static_cast<JSTaggedType>(objAddr)).IsArrayBuffer());
207 JSArrayBuffer *arrayBuffer = reinterpret_cast<JSArrayBuffer *>(objAddr);
208 size_t arrayLength = arrayBuffer->GetArrayBufferByteLength();
209 bool withNativeAreaAllocator = arrayBuffer->GetWithNativeAreaAllocator();
210 JSNativePointer *np = reinterpret_cast<JSNativePointer *>(arrayBuffer->GetArrayBufferData().GetTaggedObject());
211 arrayBuffer->Attach(thread_, arrayLength, JSTaggedValue(np), withNativeAreaAllocator);
212 }
213
IncreaseSharedArrayBufferReference(uintptr_t objAddr)214 void BaseDeserializer::IncreaseSharedArrayBufferReference(uintptr_t objAddr)
215 {
216 ASSERT(JSTaggedValue(static_cast<JSTaggedType>(objAddr)).IsSharedArrayBuffer());
217 JSArrayBuffer *arrayBuffer = reinterpret_cast<JSArrayBuffer *>(objAddr);
218 size_t arrayLength = arrayBuffer->GetArrayBufferByteLength();
219 JSNativePointer *np = reinterpret_cast<JSNativePointer *>(arrayBuffer->GetArrayBufferData().GetTaggedObject());
220 void *buffer = np->GetExternalPointer();
221 if (JSSharedMemoryManager::GetInstance()->CreateOrLoad(&buffer, arrayLength)) {
222 LOG_ECMA(FATAL) << "BaseDeserializer::IncreaseSharedArrayBufferReference failed";
223 }
224 }
225
ResetNativePointerBuffer(uintptr_t objAddr,void * bufferPointer)226 void BaseDeserializer::ResetNativePointerBuffer(uintptr_t objAddr, void *bufferPointer)
227 {
228 JSTaggedValue obj = JSTaggedValue(static_cast<JSTaggedType>(objAddr));
229 ASSERT(obj.IsArrayBuffer() || obj.IsJSRegExp());
230 auto nativeAreaAllocator = thread_->GetEcmaVM()->GetNativeAreaAllocator();
231 JSNativePointer *np = nullptr;
232 if (obj.IsArrayBuffer()) {
233 JSArrayBuffer *arrayBuffer = reinterpret_cast<JSArrayBuffer *>(objAddr);
234 arrayBuffer->SetWithNativeAreaAllocator(true);
235 np = reinterpret_cast<JSNativePointer *>(arrayBuffer->GetArrayBufferData().GetTaggedObject());
236 nativeAreaAllocator->IncreaseNativeSizeStats(arrayBuffer->GetArrayBufferByteLength(), NativeFlag::ARRAY_BUFFER);
237 } else {
238 JSRegExp *jsRegExp = reinterpret_cast<JSRegExp *>(objAddr);
239 np = reinterpret_cast<JSNativePointer *>(jsRegExp->GetByteCodeBuffer().GetTaggedObject());
240 nativeAreaAllocator->IncreaseNativeSizeStats(jsRegExp->GetLength(), NativeFlag::REGEXP_BTYECODE);
241 }
242
243 np->SetExternalPointer(bufferPointer);
244 np->SetDeleter(NativeAreaAllocator::FreeBufferFunc);
245 np->SetData(thread_->GetEcmaVM()->GetNativeAreaAllocator());
246 }
247
ReadSingleEncodeData(uint8_t encodeFlag,uintptr_t objAddr,size_t fieldOffset,bool isRoot)248 size_t BaseDeserializer::ReadSingleEncodeData(uint8_t encodeFlag, uintptr_t objAddr, size_t fieldOffset, bool isRoot)
249 {
250 size_t handledFieldSize = sizeof(JSTaggedType);
251 ObjectSlot slot(objAddr + fieldOffset);
252 switch (encodeFlag) {
253 case NEW_OBJECT_ALL_SPACES(): {
254 SerializedObjectSpace space = SerializeData::DecodeSpace(encodeFlag);
255 HandleNewObjectEncodeFlag(space, objAddr, fieldOffset, isRoot);
256 break;
257 }
258 case (uint8_t)EncodeFlag::REFERENCE: {
259 uint32_t valueIndex = data_->ReadUint32(position_);
260 JSTaggedType valueAddr = objectVector_[valueIndex];
261 UpdateMaybeWeak(slot, valueAddr, GetAndResetWeak());
262 WriteBarrier<WriteBarrierType::DESERIALIZE>(thread_, reinterpret_cast<void *>(objAddr), fieldOffset,
263 valueAddr);
264 break;
265 }
266 case (uint8_t)EncodeFlag::WEAK: {
267 ASSERT(!isWeak_);
268 isWeak_ = true;
269 handledFieldSize = 0;
270 break;
271 }
272 case (uint8_t)EncodeFlag::PRIMITIVE: {
273 JSTaggedType value = data_->ReadJSTaggedType(position_);
274 slot.Update(value);
275 break;
276 }
277 case (uint8_t)EncodeFlag::MULTI_RAW_DATA: {
278 uint32_t size = data_->ReadUint32(position_);
279 data_->ReadRawData(objAddr + fieldOffset, size, position_);
280 handledFieldSize = size;
281 break;
282 }
283 case (uint8_t)EncodeFlag::ROOT_OBJECT: {
284 uint32_t index = data_->ReadUint32(position_);
285 uintptr_t valueAddr = thread_->GetEcmaVM()->GetSnapshotEnv()->RelocateRootObjectAddr(index);
286 if (!isRoot && valueAddr > JSTaggedValue::INVALID_VALUE_LIMIT) {
287 WriteBarrier<WriteBarrierType::DESERIALIZE>(thread_, reinterpret_cast<void *>(objAddr), fieldOffset,
288 static_cast<JSTaggedType>(valueAddr));
289 }
290 UpdateMaybeWeak(slot, valueAddr, GetAndResetWeak());
291 break;
292 }
293 case (uint8_t)EncodeFlag::OBJECT_PROTO: {
294 uint8_t type = data_->ReadUint8(position_);
295 uintptr_t protoAddr = RelocateObjectProtoAddr(type);
296 if (!isRoot && protoAddr > JSTaggedValue::INVALID_VALUE_LIMIT) {
297 WriteBarrier<WriteBarrierType::DESERIALIZE>(thread_, reinterpret_cast<void *>(objAddr), fieldOffset,
298 static_cast<JSTaggedType>(protoAddr));
299 }
300 UpdateMaybeWeak(slot, protoAddr, GetAndResetWeak());
301 break;
302 }
303 case (uint8_t)EncodeFlag::TRANSFER_ARRAY_BUFFER: {
304 isTransferArrayBuffer_ = true;
305 handledFieldSize = 0;
306 break;
307 }
308 case (uint8_t)EncodeFlag::SHARED_ARRAY_BUFFER: {
309 isSharedArrayBuffer_ = true;
310 handledFieldSize = 0;
311 break;
312 }
313 case (uint8_t)EncodeFlag::ARRAY_BUFFER:
314 case (uint8_t)EncodeFlag::SENDABLE_ARRAY_BUFFER:
315 case (uint8_t)EncodeFlag::JS_REG_EXP: {
316 size_t bufferLength = data_->ReadUint32(position_);
317 auto nativeAreaAllocator = thread_->GetEcmaVM()->GetNativeAreaAllocator();
318 bufferPointer_ = nativeAreaAllocator->AllocateBuffer(bufferLength);
319 heap_->IncNativeSizeAfterLastGC(bufferLength);
320 data_->ReadRawData(ToUintPtr(bufferPointer_), bufferLength, position_);
321 heap_->IncreaseNativeBindingSize(bufferLength);
322 handledFieldSize = 0;
323 break;
324 }
325 case (uint8_t)EncodeFlag::NATIVE_BINDING_OBJECT: {
326 slot.Update(JSTaggedValue::Undefined().GetRawData());
327 AttachFunc af = reinterpret_cast<AttachFunc>(data_->ReadJSTaggedType(position_));
328 void *bufferPointer = reinterpret_cast<void *>(data_->ReadJSTaggedType(position_));
329 void *hint = reinterpret_cast<void *>(data_->ReadJSTaggedType(position_));
330 void *attachData = reinterpret_cast<void *>(data_->ReadJSTaggedType(position_));
331 // defer new native binding object until deserialize finish
332 nativeBindingInfos_.push_back(new NativeBindingInfo(af, bufferPointer, hint, attachData,
333 objAddr, fieldOffset, isRoot));
334 break;
335 }
336 case (uint8_t)EncodeFlag::JS_ERROR: {
337 slot.Update(JSTaggedValue::Undefined().GetRawData());
338 uint8_t type = data_->ReadUint8(position_);
339 ASSERT(type >= static_cast<uint8_t>(JSType::JS_ERROR_FIRST)
340 && type <= static_cast<uint8_t>(JSType::JS_ERROR_LAST));
341 jsErrorInfos_.push_back(new JSErrorInfo(type, JSTaggedValue::Undefined(), objAddr, fieldOffset, isRoot));
342 uint8_t flag = data_->ReadUint8(position_);
343 if (flag == 1) { // error msg is string
344 isErrorMsg_ = true;
345 handledFieldSize = 0;
346 }
347 break;
348 }
349 case (uint8_t)EncodeFlag::SHARED_OBJECT: {
350 uint32_t index = data_->ReadUint32(position_);
351 if (UNLIKELY(index >= sharedObjChunk_->Size())) {
352 LOG_ECMA(FATAL) << "Shared object index invalid, index: " << index << " chunkSize: "
353 << sharedObjChunk_->Size();
354 UNREACHABLE();
355 }
356 JSTaggedType value = sharedObjChunk_->Get(index);
357 objectVector_.push_back(value);
358 bool isErrorMsg = GetAndResetIsErrorMsg();
359 if (isErrorMsg) {
360 // defer new js error
361 jsErrorInfos_.back()->errorMsg_ = JSTaggedValue(value);
362 break;
363 }
364 if (!isRoot) {
365 WriteBarrier(thread_, reinterpret_cast<void *>(objAddr), fieldOffset, value);
366 }
367 UpdateMaybeWeak(slot, value, GetAndResetWeak());
368 break;
369 }
370 default:
371 LOG_ECMA(FATAL) << "this branch is unreachable";
372 UNREACHABLE();
373 break;
374 }
375 return handledFieldSize;
376 }
377
RelocateObjectAddr(SerializedObjectSpace space,size_t objSize)378 uintptr_t BaseDeserializer::RelocateObjectAddr(SerializedObjectSpace space, size_t objSize)
379 {
380 uintptr_t res = 0U;
381 switch (space) {
382 case SerializedObjectSpace::OLD_SPACE: {
383 if (oldSpaceBeginAddr_ + objSize > AlignUp(oldSpaceBeginAddr_, DEFAULT_REGION_SIZE)) {
384 ASSERT(oldRegionIndex_ < regionVector_.size());
385 oldSpaceBeginAddr_ = regionVector_[oldRegionIndex_++]->GetBegin();
386 }
387 res = oldSpaceBeginAddr_;
388 oldSpaceBeginAddr_ += objSize;
389 break;
390 }
391 case SerializedObjectSpace::NON_MOVABLE_SPACE: {
392 if (nonMovableSpaceBeginAddr_ + objSize > AlignUp(nonMovableSpaceBeginAddr_, DEFAULT_REGION_SIZE)) {
393 ASSERT(nonMovableRegionIndex_ < regionVector_.size());
394 nonMovableSpaceBeginAddr_ = regionVector_[nonMovableRegionIndex_++]->GetBegin();
395 }
396 res = nonMovableSpaceBeginAddr_;
397 nonMovableSpaceBeginAddr_ += objSize;
398 break;
399 }
400 case SerializedObjectSpace::MACHINE_CODE_SPACE: {
401 if (machineCodeSpaceBeginAddr_ + objSize > AlignUp(machineCodeSpaceBeginAddr_, DEFAULT_REGION_SIZE)) {
402 ASSERT(machineCodeRegionIndex_ < regionVector_.size());
403 machineCodeSpaceBeginAddr_ = regionVector_[machineCodeRegionIndex_++]->GetBegin();
404 }
405 res = machineCodeSpaceBeginAddr_;
406 machineCodeSpaceBeginAddr_ += objSize;
407 break;
408 }
409 case SerializedObjectSpace::HUGE_SPACE: {
410 // no gc for this allocate
411 res = heap_->GetHugeObjectSpace()->Allocate(objSize, thread_, AllocateEventType::DESERIALIZE);
412 if (res == 0) {
413 DeserializeFatalOutOfMemory(objSize, false, false);
414 }
415 break;
416 }
417 case SerializedObjectSpace::SHARED_OLD_SPACE: {
418 if (sOldSpaceBeginAddr_ + objSize > AlignUp(sOldSpaceBeginAddr_, DEFAULT_REGION_SIZE)) {
419 ASSERT(sOldRegionIndex_ < regionVector_.size());
420 sOldSpaceBeginAddr_ = regionVector_[sOldRegionIndex_++]->GetBegin();
421 }
422 res = sOldSpaceBeginAddr_;
423 sOldSpaceBeginAddr_ += objSize;
424 break;
425 }
426 case SerializedObjectSpace::SHARED_NON_MOVABLE_SPACE: {
427 if (sNonMovableSpaceBeginAddr_ + objSize > AlignUp(sNonMovableSpaceBeginAddr_, DEFAULT_REGION_SIZE)) {
428 ASSERT(sNonMovableRegionIndex_ < regionVector_.size());
429 sNonMovableSpaceBeginAddr_ = regionVector_[sNonMovableRegionIndex_++]->GetBegin();
430 }
431 res = sNonMovableSpaceBeginAddr_;
432 sNonMovableSpaceBeginAddr_ += objSize;
433 break;
434 }
435 case SerializedObjectSpace::SHARED_HUGE_SPACE: {
436 // no gc for this allocate
437 res = sheap_->GetHugeObjectSpace()->Allocate(thread_, objSize, AllocateEventType::DESERIALIZE);
438 if (res == 0) {
439 DeserializeFatalOutOfMemory(objSize, false, true);
440 }
441 break;
442 }
443 default:
444 LOG_ECMA(FATAL) << "this branch is unreachable";
445 UNREACHABLE();
446 }
447 return res;
448 }
449
RelocateObjectProtoAddr(uint8_t objectType)450 JSTaggedType BaseDeserializer::RelocateObjectProtoAddr(uint8_t objectType)
451 {
452 auto env = thread_->GetEcmaVM()->GetGlobalEnv();
453 switch (objectType) {
454 case (uint8_t)JSType::JS_OBJECT:
455 return env->GetObjectFunctionPrototype().GetTaggedType();
456 case (uint8_t)JSType::JS_ERROR:
457 return JSHandle<JSFunction>(env->GetErrorFunction())->GetFunctionPrototype().GetRawData();
458 case (uint8_t)JSType::JS_EVAL_ERROR:
459 return JSHandle<JSFunction>(env->GetEvalErrorFunction())->GetFunctionPrototype().GetRawData();
460 case (uint8_t)JSType::JS_RANGE_ERROR:
461 return JSHandle<JSFunction>(env->GetRangeErrorFunction())->GetFunctionPrototype().GetRawData();
462 case (uint8_t)JSType::JS_REFERENCE_ERROR:
463 return JSHandle<JSFunction>(env->GetReferenceErrorFunction())->GetFunctionPrototype().GetRawData();
464 case (uint8_t)JSType::JS_TYPE_ERROR:
465 return JSHandle<JSFunction>(env->GetTypeErrorFunction())->GetFunctionPrototype().GetRawData();
466 case (uint8_t)JSType::JS_AGGREGATE_ERROR:
467 return JSHandle<JSFunction>(env->GetAggregateErrorFunction())->GetFunctionPrototype().GetRawData();
468 case (uint8_t)JSType::JS_URI_ERROR:
469 return JSHandle<JSFunction>(env->GetURIErrorFunction())->GetFunctionPrototype().GetRawData();
470 case (uint8_t)JSType::JS_SYNTAX_ERROR:
471 return JSHandle<JSFunction>(env->GetSyntaxErrorFunction())->GetFunctionPrototype().GetRawData();
472 case (uint8_t)JSType::JS_OOM_ERROR:
473 return JSHandle<JSFunction>(env->GetOOMErrorFunction())->GetFunctionPrototype().GetRawData();
474 case (uint8_t)JSType::JS_TERMINATION_ERROR:
475 return JSHandle<JSFunction>(env->GetTerminationErrorFunction())->GetFunctionPrototype().GetRawData();
476 case (uint8_t)JSType::JS_DATE:
477 return env->GetDatePrototype().GetTaggedType();
478 case (uint8_t)JSType::JS_ARRAY:
479 return env->GetArrayPrototype().GetTaggedType();
480 case (uint8_t)JSType::JS_SHARED_ARRAY:
481 return env->GetSharedArrayPrototype().GetTaggedType();
482 case (uint8_t)JSType::JS_API_BITVECTOR:
483 return env->GetBitVectorPrototype().GetTaggedType();
484 case (uint8_t)JSType::JS_MAP:
485 return env->GetMapPrototype().GetTaggedType();
486 case (uint8_t)JSType::JS_SHARED_MAP:
487 return env->GetSharedMapPrototype().GetTaggedType();
488 case (uint8_t)JSType::JS_SET:
489 return env->GetSetPrototype().GetTaggedType();
490 case (uint8_t)JSType::JS_SHARED_SET:
491 return env->GetSharedSetPrototype().GetTaggedType();
492 case (uint8_t)JSType::JS_SENDABLE_ARRAY_BUFFER:
493 return env->GetSendableArrayBufferPrototype().GetTaggedType();
494 case (uint8_t)JSType::JS_REG_EXP:
495 return env->GetRegExpPrototype().GetTaggedType();
496 case (uint8_t)JSType::JS_INT8_ARRAY:
497 return env->GetInt8ArrayFunctionPrototype().GetTaggedType();
498 case (uint8_t)JSType::JS_UINT8_ARRAY:
499 return env->GetUint8ArrayFunctionPrototype().GetTaggedType();
500 case (uint8_t)JSType::JS_UINT8_CLAMPED_ARRAY:
501 return env->GetUint8ClampedArrayFunctionPrototype().GetTaggedType();
502 case (uint8_t)JSType::JS_INT16_ARRAY:
503 return env->GetInt16ArrayFunctionPrototype().GetTaggedType();
504 case (uint8_t)JSType::JS_UINT16_ARRAY:
505 return env->GetUint16ArrayFunctionPrototype().GetTaggedType();
506 case (uint8_t)JSType::JS_INT32_ARRAY:
507 return env->GetInt32ArrayFunctionPrototype().GetTaggedType();
508 case (uint8_t)JSType::JS_UINT32_ARRAY:
509 return env->GetUint32ArrayFunctionPrototype().GetTaggedType();
510 case (uint8_t)JSType::JS_FLOAT32_ARRAY:
511 return env->GetFloat32ArrayFunctionPrototype().GetTaggedType();
512 case (uint8_t)JSType::JS_FLOAT64_ARRAY:
513 return env->GetFloat64ArrayFunctionPrototype().GetTaggedType();
514 case (uint8_t)JSType::JS_BIGINT64_ARRAY:
515 return env->GetBigInt64ArrayFunctionPrototype().GetTaggedType();
516 case (uint8_t)JSType::JS_BIGUINT64_ARRAY:
517 return env->GetBigUint64ArrayFunctionPrototype().GetTaggedType();
518 case (uint8_t)JSType::JS_SHARED_INT8_ARRAY:
519 return env->GetSharedInt8ArrayFunctionPrototype().GetTaggedType();
520 case (uint8_t)JSType::JS_SHARED_UINT8_ARRAY:
521 return env->GetSharedUint8ArrayFunctionPrototype().GetTaggedType();
522 case (uint8_t)JSType::JS_SHARED_UINT8_CLAMPED_ARRAY:
523 return env->GetSharedUint8ClampedArrayFunctionPrototype().GetTaggedType();
524 case (uint8_t)JSType::JS_SHARED_INT16_ARRAY:
525 return env->GetSharedInt16ArrayFunctionPrototype().GetTaggedType();
526 case (uint8_t)JSType::JS_SHARED_UINT16_ARRAY:
527 return env->GetSharedUint16ArrayFunctionPrototype().GetTaggedType();
528 case (uint8_t)JSType::JS_SHARED_INT32_ARRAY:
529 return env->GetSharedInt32ArrayFunctionPrototype().GetTaggedType();
530 case (uint8_t)JSType::JS_SHARED_UINT32_ARRAY:
531 return env->GetSharedUint32ArrayFunctionPrototype().GetTaggedType();
532 case (uint8_t)JSType::JS_SHARED_FLOAT32_ARRAY:
533 return env->GetSharedFloat32ArrayFunctionPrototype().GetTaggedType();
534 case (uint8_t)JSType::JS_SHARED_FLOAT64_ARRAY:
535 return env->GetSharedFloat64ArrayFunctionPrototype().GetTaggedType();
536 case (uint8_t)JSType::JS_SHARED_BIGINT64_ARRAY:
537 return env->GetSharedBigInt64ArrayFunctionPrototype().GetTaggedType();
538 case (uint8_t)JSType::JS_SHARED_BIGUINT64_ARRAY:
539 return env->GetSharedBigUint64ArrayFunctionPrototype().GetTaggedType();
540 case (uint8_t)JSType::JS_ARRAY_BUFFER:
541 return JSHandle<JSFunction>(env->GetArrayBufferFunction())->GetFunctionPrototype().GetRawData();
542 case (uint8_t)JSType::JS_SHARED_ARRAY_BUFFER:
543 return JSHandle<JSFunction>(env->GetSharedArrayBufferFunction())->GetFunctionPrototype().GetRawData();
544 case (uint8_t)JSType::JS_ASYNC_FUNCTION:
545 return env->GetAsyncFunctionPrototype().GetTaggedType();
546 case (uint8_t)JSType::JS_SHARED_ASYNC_FUNCTION:
547 return env->GetSAsyncFunctionPrototype().GetTaggedType();
548 case (uint8_t)JSType::BIGINT:
549 return JSHandle<JSFunction>(env->GetBigIntFunction())->GetFunctionPrototype().GetRawData();
550 default:
551 LOG_ECMA(ERROR) << "Relocate unsupported JSType: " << JSHClass::DumpJSType(static_cast<JSType>(objectType));
552 LOG_ECMA(FATAL) << "this branch is unreachable";
553 UNREACHABLE();
554 break;
555 }
556 }
557
AllocateToDifferentSpaces()558 void BaseDeserializer::AllocateToDifferentSpaces()
559 {
560 size_t oldSpaceSize = data_->GetOldSpaceSize();
561 if (oldSpaceSize > 0) {
562 heap_->GetOldSpace()->IncreaseLiveObjectSize(oldSpaceSize);
563 AllocateToOldSpace(oldSpaceSize);
564 }
565 size_t nonMovableSpaceSize = data_->GetNonMovableSpaceSize();
566 if (nonMovableSpaceSize > 0) {
567 heap_->GetNonMovableSpace()->IncreaseLiveObjectSize(nonMovableSpaceSize);
568 AllocateToNonMovableSpace(nonMovableSpaceSize);
569 }
570 size_t machineCodeSpaceSize = data_->GetMachineCodeSpaceSize();
571 if (machineCodeSpaceSize > 0) {
572 heap_->GetMachineCodeSpace()->IncreaseLiveObjectSize(machineCodeSpaceSize);
573 AllocateToMachineCodeSpace(machineCodeSpaceSize);
574 }
575 size_t sOldSpaceSize = data_->GetSharedOldSpaceSize();
576 if (sOldSpaceSize > 0) {
577 sheap_->GetOldSpace()->IncreaseLiveObjectSize(sOldSpaceSize);
578 AllocateToSharedOldSpace(sOldSpaceSize);
579 }
580 size_t sNonMovableSpaceSize = data_->GetSharedNonMovableSpaceSize();
581 if (sNonMovableSpaceSize > 0) {
582 sheap_->GetNonMovableSpace()->IncreaseLiveObjectSize(sNonMovableSpaceSize);
583 AllocateToSharedNonMovableSpace(sNonMovableSpaceSize);
584 }
585 }
586
AllocateMultiRegion(SparseSpace * space,size_t spaceObjSize,size_t & regionIndex)587 void BaseDeserializer::AllocateMultiRegion(SparseSpace *space, size_t spaceObjSize, size_t ®ionIndex)
588 {
589 regionIndex = regionVector_.size();
590 size_t regionAlignedSize = SerializeData::AlignUpRegionAvailableSize(spaceObjSize);
591 size_t regionNum = regionAlignedSize / Region::GetRegionAvailableSize();
592 while (regionNum > 1) { // 1: one region have allocated before
593 std::vector<size_t> regionRemainSizeVector = data_->GetRegionRemainSizeVector();
594 space->ResetTopPointer(space->GetCurrentRegion()->GetEnd() - regionRemainSizeVector[regionRemainSizeIndex_++]);
595 if (!space->Expand()) {
596 DeserializeFatalOutOfMemory(spaceObjSize);
597 }
598 Region *currentRegion = space->GetCurrentRegion();
599 FreeObject::FillFreeObject(heap_, currentRegion->GetBegin(), currentRegion->GetSize());
600 regionVector_.push_back(currentRegion);
601 regionNum--;
602 }
603 size_t lastRegionRemainSize = regionAlignedSize - spaceObjSize;
604 space->ResetTopPointer(space->GetCurrentRegion()->GetEnd() - lastRegionRemainSize);
605 }
606
AllocateMultiSharedRegion(SharedSparseSpace * space,size_t spaceObjSize,size_t & regionIndex)607 void BaseDeserializer::AllocateMultiSharedRegion(SharedSparseSpace *space, size_t spaceObjSize, size_t ®ionIndex)
608 {
609 regionIndex = regionVector_.size();
610 size_t regionAlignedSize = SerializeData::AlignUpRegionAvailableSize(spaceObjSize);
611 size_t regionNum = regionAlignedSize / Region::GetRegionAvailableSize();
612 std::vector<size_t> regionRemainSizeVector = data_->GetRegionRemainSizeVector();
613 std::vector<Region *> allocateRegions;
614 while (regionNum > 0) {
615 if (space->CommittedSizeExceed()) {
616 DeserializeFatalOutOfMemory(spaceObjSize, true, true);
617 }
618 Region *region = space->AllocateDeserializeRegion(thread_);
619 FreeObject::FillFreeObject(sheap_, region->GetBegin(), region->GetSize());
620 if (regionNum == 1) { // 1: Last allocate region
621 size_t lastRegionRemainSize = regionAlignedSize - spaceObjSize;
622 region->SetHighWaterMark(region->GetEnd() - lastRegionRemainSize);
623 } else {
624 region->SetHighWaterMark(region->GetEnd() - regionRemainSizeVector[regionRemainSizeIndex_++]);
625 }
626 region->IncreaseAliveObject(region->GetAllocatedBytes());
627 regionVector_.push_back(region);
628 allocateRegions.push_back(region);
629 regionNum--;
630 }
631 space->MergeDeserializeAllocateRegions(allocateRegions);
632 }
633
AllocateToOldSpace(size_t oldSpaceSize)634 void BaseDeserializer::AllocateToOldSpace(size_t oldSpaceSize)
635 {
636 SparseSpace *space = heap_->GetOldSpace();
637 uintptr_t object = space->Allocate(oldSpaceSize, false);
638 if (UNLIKELY(object == 0U)) {
639 if (space->CommittedSizeExceed()) {
640 DeserializeFatalOutOfMemory(oldSpaceSize);
641 }
642 oldSpaceBeginAddr_ = space->GetCurrentRegion()->GetBegin();
643 FreeObject::FillFreeObject(heap_, oldSpaceBeginAddr_, space->GetCurrentRegion()->GetSize());
644 AllocateMultiRegion(space, oldSpaceSize, oldRegionIndex_);
645 } else {
646 FreeObject::FillFreeObject(heap_, object, oldSpaceSize);
647 oldSpaceBeginAddr_ = object;
648 }
649 }
650
AllocateToNonMovableSpace(size_t nonMovableSpaceSize)651 void BaseDeserializer::AllocateToNonMovableSpace(size_t nonMovableSpaceSize)
652 {
653 SparseSpace *space = heap_->GetNonMovableSpace();
654 uintptr_t object = space->Allocate(nonMovableSpaceSize, false);
655 if (UNLIKELY(object == 0U)) {
656 if (space->CommittedSizeExceed()) {
657 DeserializeFatalOutOfMemory(nonMovableSpaceSize);
658 }
659 nonMovableSpaceBeginAddr_ = space->GetCurrentRegion()->GetBegin();
660 FreeObject::FillFreeObject(heap_, nonMovableSpaceBeginAddr_, space->GetCurrentRegion()->GetSize());
661 AllocateMultiRegion(space, nonMovableSpaceSize, nonMovableRegionIndex_);
662 } else {
663 FreeObject::FillFreeObject(heap_, object, nonMovableSpaceSize);
664 nonMovableSpaceBeginAddr_ = object;
665 }
666 }
667
AllocateToMachineCodeSpace(size_t machineCodeSpaceSize)668 void BaseDeserializer::AllocateToMachineCodeSpace(size_t machineCodeSpaceSize)
669 {
670 SparseSpace *space = heap_->GetMachineCodeSpace();
671 uintptr_t object = space->Allocate(machineCodeSpaceSize, false);
672 if (UNLIKELY(object == 0U)) {
673 if (space->CommittedSizeExceed()) {
674 DeserializeFatalOutOfMemory(machineCodeSpaceSize);
675 }
676 machineCodeSpaceBeginAddr_ = space->GetCurrentRegion()->GetBegin();
677 FreeObject::FillFreeObject(heap_, machineCodeSpaceBeginAddr_, space->GetCurrentRegion()->GetSize());
678 AllocateMultiRegion(space, machineCodeSpaceSize, machineCodeRegionIndex_);
679 } else {
680 FreeObject::FillFreeObject(heap_, object, machineCodeSpaceSize);
681 machineCodeSpaceBeginAddr_ = object;
682 }
683 }
684
AllocateToSharedOldSpace(size_t sOldSpaceSize)685 void BaseDeserializer::AllocateToSharedOldSpace(size_t sOldSpaceSize)
686 {
687 SharedSparseSpace *space = sheap_->GetOldSpace();
688 uintptr_t object = space->AllocateNoGCAndExpand(thread_, sOldSpaceSize);
689 if (UNLIKELY(object == 0U)) {
690 AllocateMultiSharedRegion(space, sOldSpaceSize, sOldRegionIndex_);
691 sOldSpaceBeginAddr_ = regionVector_[sOldRegionIndex_++]->GetBegin();
692 } else {
693 if (thread_->IsSharedConcurrentMarkingOrFinished()) {
694 Region *region = Region::ObjectAddressToRange(object);
695 region->IncreaseAliveObject(sOldSpaceSize);
696 }
697 FreeObject::FillFreeObject(sheap_, object, sOldSpaceSize);
698 sOldSpaceBeginAddr_ = object;
699 }
700 }
701
AllocateToSharedNonMovableSpace(size_t sNonMovableSpaceSize)702 void BaseDeserializer::AllocateToSharedNonMovableSpace(size_t sNonMovableSpaceSize)
703 {
704 SharedNonMovableSpace *space = sheap_->GetNonMovableSpace();
705 uintptr_t object = space->AllocateNoGCAndExpand(thread_, sNonMovableSpaceSize);
706 if (UNLIKELY(object == 0U)) {
707 AllocateMultiSharedRegion(space, sNonMovableSpaceSize, sNonMovableRegionIndex_);
708 sNonMovableSpaceBeginAddr_ = regionVector_[sNonMovableRegionIndex_++]->GetBegin();
709 } else {
710 if (thread_->IsSharedConcurrentMarkingOrFinished()) {
711 Region *region = Region::ObjectAddressToRange(object);
712 region->IncreaseAliveObject(sNonMovableSpaceSize);
713 }
714 FreeObject::FillFreeObject(sheap_, object, sNonMovableSpaceSize);
715 sNonMovableSpaceBeginAddr_ = object;
716 }
717 }
718
719 } // namespace panda::ecmascript
720
721