1 /* 2 * Copyright (c) 2021-2024 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 #ifndef ECMASCRIPT_JSPANDAFILE_PROGRAM_OBJECT_H 17 #define ECMASCRIPT_JSPANDAFILE_PROGRAM_OBJECT_H 18 19 #include <atomic> 20 #include "ecmascript/compiler/aot_file/aot_file_manager.h" 21 #include "ecmascript/ecma_context.h" 22 #include "ecmascript/ecma_macros.h" 23 #include "ecmascript/global_env.h" 24 #include "ecmascript/js_array.h" 25 #include "ecmascript/js_tagged_value-inl.h" 26 #include "ecmascript/jspandafile/class_info_extractor.h" 27 #include "ecmascript/jspandafile/class_literal.h" 28 #include "ecmascript/jspandafile/constpool_value.h" 29 #include "ecmascript/jspandafile/js_pandafile_manager.h" 30 #include "ecmascript/jspandafile/literal_data_extractor.h" 31 #include "ecmascript/module/js_module_manager.h" 32 #include "ecmascript/module/js_shared_module.h" 33 #include "ecmascript/patch/quick_fix_manager.h" 34 #include "ecmascript/pgo_profiler/pgo_profiler.h" 35 #include "ecmascript/tagged_array-inl.h" 36 37 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h" 38 #include "ecmascript/pgo_profiler/pgo_utils.h" 39 #include "libpandafile/class_data_accessor-inl.h" 40 #include "libpandafile/index_accessor.h" 41 42 namespace panda { 43 namespace ecmascript { 44 class JSThread; 45 46 class Program : public ECMAObject { 47 public: 48 DECL_CAST(Program) 49 50 static constexpr size_t MAIN_FUNCTION_OFFSET = ECMAObject::SIZE; 51 ACCESSORS(MainFunction, MAIN_FUNCTION_OFFSET, SIZE) 52 53 DECL_VISIT_OBJECT(MAIN_FUNCTION_OFFSET, SIZE) 54 DECL_DUMP() 55 }; 56 57 /* ConstantPool(TaggedArray) 58 * +--------------------------------+---------------------------------- 59 * | ... | ^ ^ ^ index 0 60 * | Method / AOTLiteralInfo / Int | | | | 61 * | String | | | | 62 * | Array Literal | ConstpoolLength | | 63 * | Class Literal | | | | 64 * | Object Literal | | | | 65 * | ... | v | | 66 * +--------------------------------+--------------- | | 67 * | ProtoTransTableInfo |PointerToIndexDic | | 68 * +--------------------------------+--------------- | | 69 * | AOTSymbolInfo |TaggedArray | | 70 * +--------------------------------+--------------- | | 71 * | unshared constpool index |int32_t CacheLength | 72 * +--------------------------------+--------------- | Length 73 * | shared constpool id |int32_t | | 74 * +--------------------------------+--------------- | | 75 * | AOTHClassInfo |TaggedArray | | 76 * +--------------------------------+--------------- | | 77 * | AOTArrayInfo |TaggedArray | | 78 * +--------------------------------+--------------- | | 79 * | constIndexInfo |TaggedArray v | 80 * +--------------------------------+-------------------------- | 81 * | IndexHeader | | 82 * +--------------------------------+ | 83 * | JSPandaFile | v index: Length-1 84 * +--------------------------------+----------------------------------- 85 */ 86 class ConstantPool : public TaggedArray { 87 public: 88 static constexpr size_t JS_PANDA_FILE_INDEX = 1; // not need gc 89 static constexpr size_t INDEX_HEADER_INDEX = 2; // not need gc 90 static constexpr size_t CONSTANT_INDEX_INFO_INDEX = 3; 91 static constexpr size_t AOT_ARRAY_INFO_INDEX = 4; 92 static constexpr size_t AOT_HCLASS_INFO_INDEX = 5; 93 static constexpr size_t UNSHARED_CONSTPOOL_INDEX = 6; 94 static constexpr size_t SHARED_CONSTPOOL_ID = 7; 95 static constexpr size_t AOT_SYMBOL_INFO_INDEX = 8; 96 static constexpr size_t PROTO_TRANS_TABLE_INFO_INDEX = 9; 97 static constexpr size_t RESERVED_POOL_LENGTH = INDEX_HEADER_INDEX; // divide the gc area 98 99 // AOTHClassInfo, AOTArrayInfo, ConstIndexInfo, unsharedConstpoolIndex, constpoolId, AOTSymbolInfo, 100 // ProtoTransTableInfo 101 static constexpr size_t EXTEND_DATA_NUM = 7; 102 103 static constexpr int32_t CONSTPOOL_TYPE_FLAG = INT32_MAX; // INT32_MAX : unshared constpool. 104 static constexpr int32_t CONSTPOOL_INVALID_ID = 0; 105 Cast(TaggedObject * object)106 static ConstantPool *Cast(TaggedObject *object) 107 { 108 ASSERT(JSTaggedValue(object).IsConstantPool()); 109 return static_cast<ConstantPool *>(object); 110 } 111 CreateUnSharedConstPool(EcmaVM * vm,const JSPandaFile * jsPandaFile,panda_file::File::EntityId id)112 static JSHandle<ConstantPool> CreateUnSharedConstPool(EcmaVM *vm, const JSPandaFile *jsPandaFile, 113 panda_file::File::EntityId id) 114 { 115 const panda_file::File::IndexHeader *mainIndex = jsPandaFile->GetPandaFile()->GetIndexHeader(id); 116 LOG_ECMA_IF(mainIndex == nullptr, FATAL) << "Unknown methodId: " << id.GetOffset(); 117 auto constpoolSize = mainIndex->method_idx_size; 118 119 JSHandle<JSTaggedValue> constpool(vm->GetJSThread(), JSTaggedValue::Hole()); 120 bool isLoadedAOT = jsPandaFile->IsLoadedAOT(); 121 if (isLoadedAOT) { 122 #if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS) 123 panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(), id); 124 int32_t index = static_cast<int32_t>(indexAccessor.GetHeaderIndex()); 125 constpool = GetDeserializedConstantPool(vm, jsPandaFile, index); 126 #else 127 LOG_FULL(FATAL) << "Aot don't support Windows and MacOS platform"; 128 UNREACHABLE(); 129 #endif 130 } 131 JSHandle<ConstantPool> constpoolObj; 132 if (constpool.GetTaggedValue().IsHole()) { 133 ObjectFactory *factory = vm->GetFactory(); 134 constpoolObj = factory->NewConstantPool(constpoolSize); 135 } else { 136 constpoolObj = JSHandle<ConstantPool>(constpool); 137 } 138 139 constpoolObj->SetJSPandaFile(jsPandaFile); 140 constpoolObj->SetIndexHeader(mainIndex); 141 142 return constpoolObj; 143 } 144 CreateUnSharedConstPoolBySharedConstpool(EcmaVM * vm,const JSPandaFile * jsPandaFile,ConstantPool * shareCp)145 static JSHandle<ConstantPool> CreateUnSharedConstPoolBySharedConstpool( 146 EcmaVM *vm, const JSPandaFile *jsPandaFile, ConstantPool *shareCp) 147 { 148 const panda_file::File::IndexHeader *mainIndex = shareCp->GetIndexHeader(); 149 auto constpoolSize = mainIndex->method_idx_size; 150 151 JSHandle<JSTaggedValue> constpool(vm->GetJSThread(), JSTaggedValue::Hole()); 152 bool isLoadedAOT = jsPandaFile->IsLoadedAOT(); 153 if (isLoadedAOT) { 154 #if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS) 155 int32_t cpId = shareCp->GetSharedConstpoolId().GetInt(); 156 constpool = GetDeserializedConstantPool(vm, jsPandaFile, cpId); 157 #else 158 LOG_FULL(FATAL) << "Aot don't support Windows and MacOS platform"; 159 UNREACHABLE(); 160 #endif 161 } 162 JSHandle<ConstantPool> constpoolObj; 163 if (constpool.GetTaggedValue().IsHole()) { 164 ObjectFactory *factory = vm->GetFactory(); 165 constpoolObj = factory->NewConstantPool(constpoolSize); 166 } else { 167 constpoolObj = JSHandle<ConstantPool>(constpool); 168 } 169 170 constpoolObj->SetJSPandaFile(jsPandaFile); 171 constpoolObj->SetIndexHeader(mainIndex); 172 173 return constpoolObj; 174 } 175 176 static JSHandle<ConstantPool> CreateSharedConstPool(EcmaVM *vm, const JSPandaFile *jsPandaFile, 177 panda_file::File::EntityId id, 178 int32_t cpId = 0) 179 { 180 const panda_file::File::IndexHeader *mainIndex = jsPandaFile->GetPandaFile()->GetIndexHeader(id); 181 LOG_ECMA_IF(mainIndex == nullptr, FATAL) << "Unknown methodId: " << id.GetOffset(); 182 auto constpoolSize = mainIndex->method_idx_size; 183 184 JSHandle<ConstantPool> constpool(vm->GetJSThread(), JSTaggedValue::Hole()); 185 if (constpool.GetTaggedValue().IsHole()) { 186 ObjectFactory *factory = vm->GetFactory(); 187 constpool = factory->NewSConstantPool(constpoolSize); 188 } 189 190 constpool->SetJSPandaFile(jsPandaFile); 191 constpool->SetIndexHeader(mainIndex); 192 constpool->SetUnsharedConstpoolIndex(JSTaggedValue(0)); 193 constpool->SetSharedConstpoolId(JSTaggedValue(cpId)); 194 195 return constpool; 196 } 197 IsAotSymbolInfoExist(JSHandle<TaggedArray> symbolInfo,JSTaggedValue symbol)198 static bool IsAotSymbolInfoExist(JSHandle<TaggedArray> symbolInfo, JSTaggedValue symbol) 199 { 200 return symbolInfo->GetLength() > 0 && !symbol.IsHole(); 201 } 202 203 static JSHandle<ConstantPool> CreateSharedConstPoolForAOT( 204 EcmaVM *vm, JSHandle<ConstantPool> constpool, int32_t cpId = 0) 205 { 206 JSHandle<ConstantPool> sconstpool(vm->GetJSThread(), JSTaggedValue::Hole()); 207 uint32_t capacity = constpool->GetConstpoolLength(); 208 if (sconstpool.GetTaggedValue().IsHole()) { 209 ObjectFactory *factory = vm->GetFactory(); 210 sconstpool = factory->NewSConstantPool(capacity); 211 } 212 JSThread *thread = vm->GetJSThread(); 213 for (uint32_t i = 0; i < capacity; i++) { 214 JSTaggedValue val = constpool->GetObjectFromCache(i); 215 if (val.IsString()) { 216 sconstpool->SetObjectToCache(thread, i, val); 217 } else if (IsAotMethodLiteralInfo(val)) { 218 JSHandle<AOTLiteralInfo> valHandle(thread, val); 219 JSHandle<AOTLiteralInfo> methodLiteral = CopySharedMethodAOTLiteralInfo(vm, valHandle); 220 sconstpool->SetObjectToCache(thread, i, methodLiteral.GetTaggedValue()); 221 } else if (val.IsInt()) { 222 // Here is to copy methodCodeEntry which does not have ihc infos from aot. 223 sconstpool->SetObjectToCache(thread, i, val); 224 } 225 } 226 227 JSHandle<TaggedArray> array(thread->GlobalConstants()->GetHandledEmptyArray()); 228 sconstpool->SetAotSymbolInfo(thread, array.GetTaggedValue()); 229 sconstpool->SetProtoTransTableInfo(thread, JSTaggedValue::Undefined()); 230 sconstpool->SetAotHClassInfo(thread, array.GetTaggedValue()); 231 sconstpool->SetAotArrayInfo(thread, array.GetTaggedValue()); 232 sconstpool->SetConstantIndexInfo(thread, array.GetTaggedValue()); 233 sconstpool->SetJSPandaFile(constpool->GetJSPandaFile()); 234 sconstpool->SetIndexHeader(constpool->GetIndexHeader()); 235 sconstpool->SetUnsharedConstpoolIndex(JSTaggedValue(0)); 236 sconstpool->SetSharedConstpoolId(JSTaggedValue(cpId)); 237 return sconstpool; 238 } 239 CopySharedMethodAOTLiteralInfo(EcmaVM * vm,JSHandle<AOTLiteralInfo> src)240 static JSHandle<AOTLiteralInfo> CopySharedMethodAOTLiteralInfo(EcmaVM *vm, 241 JSHandle<AOTLiteralInfo> src) 242 { 243 ObjectFactory *factory = vm->GetFactory(); 244 JSHandle<AOTLiteralInfo> dst = factory->NewSAOTLiteralInfo(1); 245 for (uint32_t i = 0; i < src->GetCacheLength(); i++) { 246 JSTaggedValue val = src->GetObjectFromCache(i); 247 ASSERT(!val.IsHeapObject() || val.IsJSShared()); 248 dst->SetObjectToCache(vm->GetJSThread(), i, val); 249 } 250 dst->SetLiteralType(JSTaggedValue(src->GetLiteralType())); 251 return dst; 252 } 253 CheckUnsharedConstpool(JSTaggedValue constpool)254 static bool CheckUnsharedConstpool(JSTaggedValue constpool) 255 { 256 int32_t index = ConstantPool::Cast(constpool.GetTaggedObject())->GetUnsharedConstpoolIndex(); 257 if (index == CONSTPOOL_TYPE_FLAG) { 258 return true; 259 } 260 return false; 261 } 262 SetUnsharedConstpoolIndex(const JSTaggedValue index)263 inline void SetUnsharedConstpoolIndex(const JSTaggedValue index) 264 { 265 Barriers::SetPrimitive(GetData(), GetUnsharedConstpoolIndexOffset(), index); 266 } 267 GetUnsharedConstpoolIndex()268 inline int32_t GetUnsharedConstpoolIndex() const 269 { 270 return Barriers::GetValue<JSTaggedValue>(GetData(), GetUnsharedConstpoolIndexOffset()).GetInt(); 271 } 272 SetSharedConstpoolId(const JSTaggedValue index)273 inline void SetSharedConstpoolId(const JSTaggedValue index) 274 { 275 Barriers::SetPrimitive(GetData(), GetSharedConstpoolIdOffset(), index); 276 } 277 GetSharedConstpoolId()278 inline JSTaggedValue GetSharedConstpoolId() const 279 { 280 return Barriers::GetValue<JSTaggedValue>(GetData(), GetSharedConstpoolIdOffset()); 281 } 282 GetEntityId(uint32_t index)283 panda_file::File::EntityId GetEntityId(uint32_t index) const 284 { 285 JSPandaFile *jsPandaFile = GetJSPandaFile(); 286 panda_file::File::IndexHeader *indexHeader = GetIndexHeader(); 287 Span<const panda_file::File::EntityId> indexs = jsPandaFile->GetMethodIndex(indexHeader); 288 return indexs[index]; 289 } 290 GetMethodIndexByEntityId(panda_file::File::EntityId entityId)291 int GetMethodIndexByEntityId(panda_file::File::EntityId entityId) const 292 { 293 JSPandaFile *jsPandaFile = GetJSPandaFile(); 294 panda_file::File::IndexHeader *indexHeader = GetIndexHeader(); 295 Span<const panda_file::File::EntityId> indexs = jsPandaFile->GetMethodIndex(indexHeader); 296 int size = static_cast<int>(indexs.size()); 297 for (int i = 0; i < size; i++) { 298 if (indexs[i] == entityId) { 299 return i; 300 } 301 } 302 return -1; 303 } 304 SetIndexHeader(const panda_file::File::IndexHeader * indexHeader)305 inline void SetIndexHeader(const panda_file::File::IndexHeader *indexHeader) 306 { 307 Barriers::SetPrimitive(GetData(), GetIndexHeaderOffset(), indexHeader); 308 } 309 GetIndexHeader()310 inline panda_file::File::IndexHeader *GetIndexHeader() const 311 { 312 return Barriers::GetValue<panda_file::File::IndexHeader *>(GetData(), GetIndexHeaderOffset()); 313 } 314 ComputeSize(uint32_t cacheSize)315 static size_t ComputeSize(uint32_t cacheSize) 316 { 317 return TaggedArray::ComputeSize( 318 JSTaggedValue::TaggedTypeSize(), cacheSize + EXTEND_DATA_NUM + RESERVED_POOL_LENGTH); 319 } 320 321 void InitializeWithSpecialValue(JSThread *thread, JSTaggedValue initValue, 322 uint32_t capacity, uint32_t extraLength = 0) 323 { 324 ASSERT(initValue.IsSpecial()); 325 SetLength(capacity + EXTEND_DATA_NUM + RESERVED_POOL_LENGTH); 326 SetExtraLength(extraLength); 327 for (uint32_t i = 0; i < capacity; i++) { 328 size_t offset = JSTaggedValue::TaggedTypeSize() * i; 329 Barriers::SetPrimitive<JSTaggedType>(GetData(), offset, initValue.GetRawData()); 330 } 331 JSHandle<TaggedArray> array(thread->GlobalConstants()->GetHandledEmptyArray()); 332 SetAotSymbolInfo(thread, array.GetTaggedValue()); 333 SetProtoTransTableInfo(thread, JSTaggedValue::Undefined()); 334 SetAotHClassInfo(thread, array.GetTaggedValue()); 335 SetAotArrayInfo(thread, array.GetTaggedValue()); 336 SetConstantIndexInfo(thread, array.GetTaggedValue()); 337 SetJSPandaFile(nullptr); 338 SetIndexHeader(nullptr); 339 SetUnsharedConstpoolIndex(JSTaggedValue(CONSTPOOL_TYPE_FLAG)); 340 SetSharedConstpoolId(JSTaggedValue(CONSTPOOL_INVALID_ID)); 341 } 342 GetCacheLength()343 inline uint32_t GetCacheLength() const 344 { 345 return GetLength() - RESERVED_POOL_LENGTH; 346 } 347 GetConstpoolLength()348 inline uint32_t GetConstpoolLength() const 349 { 350 return GetLength() - RESERVED_POOL_LENGTH - EXTEND_DATA_NUM; 351 } 352 SetJSPandaFile(const void * jsPandaFile)353 inline void SetJSPandaFile(const void *jsPandaFile) 354 { 355 Barriers::SetPrimitive(GetData(), GetJSPandaFileOffset(), jsPandaFile); 356 } 357 GetJSPandaFile()358 inline JSPandaFile *GetJSPandaFile() const 359 { 360 return Barriers::GetValue<JSPandaFile *>(GetData(), GetJSPandaFileOffset()); 361 } 362 InitConstantPoolTail(const JSThread * thread,JSHandle<ConstantPool> constPool)363 inline void InitConstantPoolTail(const JSThread *thread, JSHandle<ConstantPool> constPool) 364 { 365 SetAotArrayInfo(thread, constPool->GetAotArrayInfo()); 366 SetAotHClassInfo(thread, constPool->GetAotHClassInfo()); 367 SetConstantIndexInfo(thread, constPool->GetConstantIndexInfo()); 368 SetAotSymbolInfo(thread, constPool->GetAotSymbolInfo()); 369 SetProtoTransTableInfo(thread, constPool->GetProtoTransTableInfo()); 370 } 371 SetConstantIndexInfo(const JSThread * thread,JSTaggedValue info)372 inline void SetConstantIndexInfo(const JSThread *thread, JSTaggedValue info) 373 { 374 Set(thread, (GetLength() - CONSTANT_INDEX_INFO_INDEX), info); 375 } 376 GetConstantIndexInfo()377 inline JSTaggedValue GetConstantIndexInfo() const 378 { 379 return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetConstantIndexInfoOffset())); 380 } 381 SetAotArrayInfo(const JSThread * thread,JSTaggedValue info)382 inline void SetAotArrayInfo(const JSThread *thread, JSTaggedValue info) 383 { 384 Set(thread, (GetLength() - AOT_ARRAY_INFO_INDEX), info); 385 } 386 GetAotArrayInfo()387 inline JSTaggedValue GetAotArrayInfo() const 388 { 389 return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetAotArrayInfoOffset())); 390 } 391 GetAotSymbolInfo()392 inline JSTaggedValue GetAotSymbolInfo() const 393 { 394 return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetAotSymbolInfoOffset())); 395 } 396 GetProtoTransTableInfo()397 inline JSTaggedValue GetProtoTransTableInfo() const 398 { 399 return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetProtoTransTableInfoOffset())); 400 } 401 GetSymbolFromSymbolInfo(JSHandle<TaggedArray> symbolInfoHandler,uint64_t id)402 static JSTaggedValue GetSymbolFromSymbolInfo(JSHandle<TaggedArray> symbolInfoHandler, uint64_t id) 403 { 404 uint32_t len = symbolInfoHandler->GetLength(); 405 for (uint32_t j = 0; j < len; j += 2) { // 2: symbolId, symbol 406 ASSERT(j + 1 < len); 407 uint64_t symbolId = symbolInfoHandler->Get(j).GetRawData(); 408 if (symbolId == id) { 409 return symbolInfoHandler->Get(j + 1); 410 } 411 } 412 return JSTaggedValue::Hole(); 413 } 414 GetSymbolFromSymbolInfo(JSTaggedValue symbolInfo,uint64_t id)415 static JSTaggedValue GetSymbolFromSymbolInfo(JSTaggedValue symbolInfo, uint64_t id) 416 { 417 TaggedArray* info = TaggedArray::Cast(symbolInfo.GetTaggedObject()); 418 uint32_t len = info->GetLength(); 419 for (uint32_t j = 0; j < len; j += 2) { // 2: symbolId, symbol 420 ASSERT(j + 1 < len); 421 uint64_t symbolId = info->Get(j).GetRawData(); 422 if (symbolId == id) { 423 return info->Get(j + 1); 424 } 425 } 426 return JSTaggedValue::Hole(); 427 } 428 SetAotHClassInfoWithBarrier(JSThread * thread,JSTaggedValue info)429 inline void SetAotHClassInfoWithBarrier(JSThread *thread, JSTaggedValue info) 430 { 431 Set(thread, (GetLength() - AOT_HCLASS_INFO_INDEX), info); 432 } 433 SetAotHClassInfo(const JSThread * thread,JSTaggedValue info)434 inline void SetAotHClassInfo(const JSThread *thread, JSTaggedValue info) 435 { 436 Set(thread, (GetLength() - AOT_HCLASS_INFO_INDEX), info); 437 } 438 GetAotHClassInfo()439 inline JSTaggedValue GetAotHClassInfo() const 440 { 441 return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetAotHClassInfoOffset())); 442 } 443 SetAotSymbolInfo(const JSThread * thread,JSTaggedValue info)444 inline void SetAotSymbolInfo(const JSThread *thread, JSTaggedValue info) 445 { 446 Set(thread, (GetLength() - AOT_SYMBOL_INFO_INDEX), info); 447 } 448 SetProtoTransTableInfo(const JSThread * thread,JSTaggedValue info)449 inline void SetProtoTransTableInfo(const JSThread *thread, JSTaggedValue info) 450 { 451 Set(thread, (GetLength() - PROTO_TRANS_TABLE_INFO_INDEX), info); 452 } 453 SetObjectToCache(JSThread * thread,uint32_t index,JSTaggedValue value)454 inline void SetObjectToCache(JSThread *thread, uint32_t index, JSTaggedValue value) 455 { 456 Set(thread, index, value); 457 } 458 CASSetObjectToCache(JSThread * thread,const JSTaggedValue constpool,uint32_t index,JSTaggedValue value)459 static void CASSetObjectToCache( 460 JSThread *thread, const JSTaggedValue constpool, uint32_t index, JSTaggedValue value) 461 { 462 const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); 463 JSHandle<ConstantPool> constpoolHandle(thread, constpool); 464 std::atomic<JSTaggedValue> *atomicVal = reinterpret_cast<std::atomic<JSTaggedValue> *>( 465 reinterpret_cast<uintptr_t>(taggedPool) + DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize()); 466 JSTaggedValue tempVal = taggedPool->GetObjectFromCache(index); 467 JSTaggedValue expected = IsLoadedMethodInfoFromAOT(taggedPool->GetJSPandaFile(), tempVal) ? tempVal : 468 JSTaggedValue::Hole(); 469 JSTaggedValue desired = value; 470 if (std::atomic_compare_exchange_strong_explicit(atomicVal, &expected, desired, 471 std::memory_order_release, std::memory_order_relaxed)) { 472 // set val by Barrier. 473 constpoolHandle->SetObjectToCache(thread, index, value); 474 } 475 } 476 GetObjectFromCache(uint32_t index)477 inline JSTaggedValue GetObjectFromCache(uint32_t index) const 478 { 479 return Get(index); 480 } 481 GetMethodFromCache(JSThread * thread,JSTaggedValue constpool,uint32_t index)482 static JSTaggedValue GetMethodFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index) 483 { 484 const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); 485 auto val = taggedPool->GetObjectFromCache(index); 486 JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile(); 487 488 // For AOT 489 bool isLoadedAOT = jsPandaFile->IsLoadedAOT(); 490 bool hasEntryIndex = false; 491 uint32_t entryIndex = 0; 492 if (IsLoadedMethodInfoFromAOT(jsPandaFile, val)) { 493 int entryIndexVal = 0; // 0: only one method 494 if (val.IsInt()) { 495 // For MethodInfo which does not have ihc infos, we store codeEntry directly. 496 entryIndexVal = val.GetInt(); 497 } else { 498 JSHandle<AOTLiteralInfo> entryIndexes(thread, val); 499 entryIndexVal = entryIndexes->GetObjectFromCache(0).GetInt(); // 0: only one method 500 } 501 if (entryIndexVal != static_cast<int>(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE)) { 502 hasEntryIndex = true; 503 entryIndex = static_cast<uint32_t>(entryIndexVal); 504 } 505 val = JSTaggedValue::Hole(); 506 } 507 508 if (!val.IsHole()) { 509 return val; 510 } 511 512 if (!taggedPool->GetJSPandaFile()->IsNewVersion()) { 513 JSTaggedValue unsharedCp = thread->GetCurrentEcmaContext()->FindOrCreateUnsharedConstpool(constpool); 514 taggedPool = ConstantPool::Cast(unsharedCp.GetTaggedObject()); 515 return taggedPool->Get(index); 516 } 517 518 [[maybe_unused]] EcmaHandleScope handleScope(thread); 519 ASSERT(jsPandaFile->IsNewVersion()); 520 JSHandle<ConstantPool> constpoolHandle(thread, constpool); 521 EcmaVM *vm = thread->GetEcmaVM(); 522 523 EntityId id = constpoolHandle->GetEntityId(index); 524 MethodLiteral *methodLiteral = jsPandaFile->FindMethodLiteral(id.GetOffset()); 525 CHECK_INPUT_NULLPTR(methodLiteral, 526 "GetMethodFromCache:methodLiteral is nullptr, offset: " + std::to_string(id.GetOffset())); 527 ObjectFactory *factory = vm->GetFactory(); 528 JSHandle<Method> method = factory->NewSMethod( 529 jsPandaFile, methodLiteral, constpoolHandle, entryIndex, isLoadedAOT && hasEntryIndex); 530 531 CASSetObjectToCache(thread, constpoolHandle.GetTaggedValue(), index, method.GetTaggedValue()); 532 return method.GetTaggedValue(); 533 } 534 535 static JSTaggedValue PUBLIC_API GetMethodFromCache(JSTaggedValue constpool, uint32_t index); 536 537 static void PUBLIC_API UpdateConstpoolWhenDeserialAI(EcmaVM *vm, JSHandle<ConstantPool> aiCP, 538 JSHandle<ConstantPool> sharedCP, JSHandle<ConstantPool> unsharedCP); 539 540 static bool PUBLIC_API IsAotMethodLiteralInfo(JSTaggedValue literalInfo); 541 542 static JSTaggedValue GetClassLiteralFromCache(JSThread *thread, JSHandle<ConstantPool> constpool, 543 uint32_t literal, CString entry, JSHandle<JSTaggedValue> sendableEnv = JSHandle<JSTaggedValue>(), 544 ClassKind kind = ClassKind::NON_SENDABLE); 545 546 static JSHandle<TaggedArray> GetFieldLiteral(JSThread *thread, JSHandle<ConstantPool> constpool, 547 uint32_t literal, CString entry); 548 549 template <ConstPoolType type> GetLiteralFromCache(JSThread * thread,JSTaggedValue constpool,uint32_t index,CString entry)550 static JSTaggedValue GetLiteralFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index, CString entry) 551 { 552 static_assert(type == ConstPoolType::OBJECT_LITERAL || type == ConstPoolType::ARRAY_LITERAL); 553 [[maybe_unused]] EcmaHandleScope handleScope(thread); 554 const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); 555 auto val = taggedPool->GetObjectFromCache(index); 556 JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile(); 557 558 // For AOT 559 bool isLoadedAOT = jsPandaFile->IsLoadedAOT(); 560 JSHandle<AOTLiteralInfo> entryIndexes(thread, JSTaggedValue::Undefined()); 561 if (isLoadedAOT && val.IsAOTLiteralInfo()) { 562 entryIndexes = JSHandle<AOTLiteralInfo>(thread, val); 563 val = JSTaggedValue::Hole(); 564 } 565 566 if (val.IsHole()) { 567 JSHandle<ConstantPool> constpoolHandle(thread, constpool); 568 569 ASSERT(jsPandaFile->IsNewVersion()); 570 panda_file::File::EntityId id = taggedPool->GetEntityId(index); 571 bool needSetAotFlag = isLoadedAOT && !entryIndexes.GetTaggedValue().IsUndefined(); 572 // New inst 573 switch (type) { 574 case ConstPoolType::OBJECT_LITERAL: { 575 JSMutableHandle<TaggedArray> elements(thread, JSTaggedValue::Undefined()); 576 JSMutableHandle<TaggedArray> properties(thread, JSTaggedValue::Undefined()); 577 LiteralDataExtractor::ExtractObjectDatas(thread, jsPandaFile, id, elements, 578 properties, constpoolHandle, entry, needSetAotFlag, entryIndexes); 579 JSTaggedValue ihcVal = JSTaggedValue::Undefined(); 580 if (needSetAotFlag) { 581 ihcVal = entryIndexes->GetIhc(); 582 if (!ihcVal.IsUndefined()) { 583 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 584 JSHClass::Cast(ihcVal.GetTaggedObject())->SetPrototype(thread, 585 env->GetObjectFunctionPrototype()); 586 } 587 } 588 JSHandle<JSObject> obj = JSObject::CreateObjectFromProperties(thread, properties, ihcVal); 589 auto profiler = thread->GetEcmaVM()->GetPGOProfiler(); 590 profiler->RecordProfileType(obj->GetClass(), jsPandaFile, id.GetOffset()); 591 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 592 JSMutableHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined()); 593 size_t elementsLen = elements->GetLength(); 594 for (size_t i = 0; i < elementsLen; i += 2) { // 2: Each literal buffer has a pair of key-value. 595 key.Update(elements->Get(i)); 596 if (key->IsHole()) { 597 break; 598 } 599 valueHandle.Update(elements->Get(i + 1)); 600 JSObject::DefinePropertyByLiteral(thread, obj, key, valueHandle); 601 } 602 val = obj.GetTaggedValue(); 603 break; 604 } 605 case ConstPoolType::ARRAY_LITERAL: { 606 // literal fetching from AOT ArrayInfos 607 JSMutableHandle<TaggedArray> literal(thread, JSTaggedValue::Undefined()); 608 #if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC 609 ElementsKind dataKind = ElementsKind::GENERIC; 610 #else 611 ElementsKind dataKind = ElementsKind::NONE; 612 #endif 613 literal.Update(LiteralDataExtractor::GetDatasIgnoreType(thread, jsPandaFile, id, 614 constpoolHandle, entry, 615 needSetAotFlag, entryIndexes, 616 &dataKind)); 617 uint32_t length = literal->GetLength(); 618 JSHandle<JSArray> arr(JSArray::ArrayCreate(thread, JSTaggedNumber(length), ArrayMode::LITERAL)); 619 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 620 arr->SetElements(thread, literal); 621 if (thread->GetEcmaVM()->IsEnablePGOProfiler() || thread->GetEcmaVM()->IsEnableElementsKind()) { 622 // for all JSArray, the initial ElementsKind should be NONE 623 // Because AOT Stable Array Deopt check, we have support arrayLiteral elementskind 624 // If array is loaded from AOT, no need to do migration. 625 auto globalConstant = const_cast<GlobalEnvConstants *>(thread->GlobalConstants()); 626 auto classIndex = static_cast<size_t>(ConstantIndex::ELEMENT_NONE_HCLASS_INDEX); 627 auto hclassVal = globalConstant->GetGlobalConstantObject(classIndex); 628 arr->SynchronizedSetClass(thread, JSHClass::Cast(hclassVal.GetTaggedObject())); 629 ElementsKind oldKind = arr->GetClass()->GetElementsKind(); 630 JSHClass::TransitToElementsKind(thread, arr, dataKind); 631 ElementsKind newKind = arr->GetClass()->GetElementsKind(); 632 JSHandle<JSObject> receiver(arr); 633 Elements::MigrateArrayWithKind(thread, receiver, oldKind, newKind); 634 } 635 val = arr.GetTaggedValue(); 636 break; 637 } 638 default: 639 LOG_FULL(FATAL) << "Unknown type: " << static_cast<uint8_t>(type); 640 UNREACHABLE(); 641 } 642 constpoolHandle->SetObjectToCache(thread, index, val); 643 } 644 645 return val; 646 } 647 648 template <ConstPoolType type> GetLiteralFromCache(JSTaggedValue constpool,uint32_t index,CString entry)649 static JSTaggedValue GetLiteralFromCache(JSTaggedValue constpool, uint32_t index, [[maybe_unused]] CString entry) 650 { 651 const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); 652 auto val = taggedPool->GetObjectFromCache(index); 653 JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile(); 654 655 bool isLoadedAOT = jsPandaFile->IsLoadedAOT(); 656 if (isLoadedAOT && val.IsAOTLiteralInfo()) { 657 val = JSTaggedValue::Hole(); 658 } 659 return val.IsHole() ? JSTaggedValue::Undefined() : val; 660 } 661 GetIdFromCache(JSTaggedValue constpool,uint32_t index)662 static panda_file::File::EntityId GetIdFromCache(JSTaggedValue constpool, uint32_t index) 663 { 664 const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); 665 panda_file::File::EntityId id = taggedPool->GetEntityId(index); 666 return id; 667 } 668 669 template <ConstPoolType type> GetLiteralFromCache(JSThread * thread,JSTaggedValue constpool,uint32_t index,JSTaggedValue module)670 static JSTaggedValue GetLiteralFromCache(JSThread *thread, JSTaggedValue constpool, 671 uint32_t index, JSTaggedValue module) 672 { 673 CString entry = ModuleManager::GetRecordName(module); 674 return GetLiteralFromCache<type>(thread, constpool, index, entry); 675 } 676 677 static JSTaggedValue PUBLIC_API GetStringFromCacheForJit(JSThread *thread, JSTaggedValue constpool, uint32_t index, 678 bool allowAlloc = true); 679 680 static JSTaggedValue PUBLIC_API GetStringFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index); 681 682 DECL_VISIT_ARRAY(DATA_OFFSET, GetCacheLength(), GetLength()); 683 DECL_DUMP()684 DECL_DUMP() 685 686 private: 687 inline size_t GetJSPandaFileOffset() const 688 { 689 return JSTaggedValue::TaggedTypeSize() * (GetLength() - JS_PANDA_FILE_INDEX); 690 } 691 GetIndexHeaderOffset()692 inline size_t GetIndexHeaderOffset() const 693 { 694 return JSTaggedValue::TaggedTypeSize() * (GetLength() - INDEX_HEADER_INDEX); 695 } 696 GetConstantIndexInfoOffset()697 inline size_t GetConstantIndexInfoOffset() const 698 { 699 return JSTaggedValue::TaggedTypeSize() * (GetLength() - CONSTANT_INDEX_INFO_INDEX); 700 } 701 GetAotArrayInfoOffset()702 inline size_t GetAotArrayInfoOffset() const 703 { 704 return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_ARRAY_INFO_INDEX); 705 } 706 GetAotHClassInfoOffset()707 inline size_t GetAotHClassInfoOffset() const 708 { 709 return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_HCLASS_INFO_INDEX); 710 } 711 GetUnsharedConstpoolIndexOffset()712 inline size_t GetUnsharedConstpoolIndexOffset() const 713 { 714 return JSTaggedValue::TaggedTypeSize() * (GetLength() - UNSHARED_CONSTPOOL_INDEX); 715 } 716 GetSharedConstpoolIdOffset()717 inline size_t GetSharedConstpoolIdOffset() const 718 { 719 return JSTaggedValue::TaggedTypeSize() * (GetLength() - SHARED_CONSTPOOL_ID); 720 } 721 GetAotSymbolInfoOffset()722 inline size_t GetAotSymbolInfoOffset() const 723 { 724 return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_SYMBOL_INFO_INDEX); 725 } 726 GetProtoTransTableInfoOffset()727 inline size_t GetProtoTransTableInfoOffset() const 728 { 729 return JSTaggedValue::TaggedTypeSize() * (GetLength() - PROTO_TRANS_TABLE_INFO_INDEX); 730 } 731 GetLastOffset()732 inline size_t GetLastOffset() const 733 { 734 return JSTaggedValue::TaggedTypeSize() * GetLength() + DATA_OFFSET; 735 } 736 IsLoadedMethodInfoFromAOT(const JSPandaFile * pf,JSTaggedValue cachedVal)737 static bool IsLoadedMethodInfoFromAOT(const JSPandaFile *pf, JSTaggedValue cachedVal) 738 { 739 return pf->IsLoadedAOT() && (cachedVal.IsAOTLiteralInfo() || cachedVal.IsInt()); 740 }; 741 742 static JSHandle<JSTaggedValue> GetDeserializedConstantPool( 743 EcmaVM *vm, const JSPandaFile *jsPandaFile, int32_t cpID); 744 static void MergeObjectLiteralHClassCache(EcmaVM *vm, const JSHandle<JSTaggedValue> &pool); 745 }; 746 } // namespace ecmascript 747 } // namespace panda 748 #endif // ECMASCRIPT_JSPANDAFILE_PROGRAM_OBJECT_H 749