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