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