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 SetAotHClassInfo(const JSThread * thread,JSTaggedValue info)429 inline void SetAotHClassInfo(const JSThread *thread, JSTaggedValue info) 430 { 431 Set(thread, (GetLength() - AOT_HCLASS_INFO_INDEX), info); 432 } 433 GetAotHClassInfo()434 inline JSTaggedValue GetAotHClassInfo() const 435 { 436 return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetAotHClassInfoOffset())); 437 } 438 SetAotSymbolInfo(const JSThread * thread,JSTaggedValue info)439 inline void SetAotSymbolInfo(const JSThread *thread, JSTaggedValue info) 440 { 441 Set(thread, (GetLength() - AOT_SYMBOL_INFO_INDEX), info); 442 } 443 SetProtoTransTableInfo(const JSThread * thread,JSTaggedValue info)444 inline void SetProtoTransTableInfo(const JSThread *thread, JSTaggedValue info) 445 { 446 Set(thread, (GetLength() - PROTO_TRANS_TABLE_INFO_INDEX), info); 447 } 448 SetObjectToCache(JSThread * thread,uint32_t index,JSTaggedValue value)449 inline void SetObjectToCache(JSThread *thread, uint32_t index, JSTaggedValue value) 450 { 451 Set(thread, index, value); 452 } 453 CASSetObjectToCache(JSThread * thread,const JSTaggedValue constpool,uint32_t index,JSTaggedValue value)454 static void CASSetObjectToCache( 455 JSThread *thread, const JSTaggedValue constpool, uint32_t index, JSTaggedValue value) 456 { 457 const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); 458 JSHandle<ConstantPool> constpoolHandle(thread, constpool); 459 std::atomic<JSTaggedValue> *atomicVal = reinterpret_cast<std::atomic<JSTaggedValue> *>( 460 reinterpret_cast<uintptr_t>(taggedPool) + DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize()); 461 JSTaggedValue tempVal = taggedPool->GetObjectFromCache(index); 462 JSTaggedValue expected = IsLoadedMethodInfoFromAOT(taggedPool->GetJSPandaFile(), tempVal) ? tempVal : 463 JSTaggedValue::Hole(); 464 JSTaggedValue desired = value; 465 if (std::atomic_compare_exchange_strong_explicit(atomicVal, &expected, desired, 466 std::memory_order_release, std::memory_order_relaxed)) { 467 // set val by Barrier. 468 constpoolHandle->SetObjectToCache(thread, index, value); 469 } 470 } 471 GetObjectFromCache(uint32_t index)472 inline JSTaggedValue GetObjectFromCache(uint32_t index) const 473 { 474 return Get(index); 475 } 476 GetMethodFromCache(JSThread * thread,JSTaggedValue constpool,uint32_t index)477 static JSTaggedValue GetMethodFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index) 478 { 479 const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); 480 auto val = taggedPool->GetObjectFromCache(index); 481 JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile(); 482 483 // For AOT 484 bool isLoadedAOT = jsPandaFile->IsLoadedAOT(); 485 bool hasEntryIndex = false; 486 uint32_t entryIndex = 0; 487 if (IsLoadedMethodInfoFromAOT(jsPandaFile, val)) { 488 int entryIndexVal = 0; // 0: only one method 489 if (val.IsInt()) { 490 // For MethodInfo which does not have ihc infos, we store codeEntry directly. 491 entryIndexVal = val.GetInt(); 492 } else { 493 JSHandle<AOTLiteralInfo> entryIndexes(thread, val); 494 entryIndexVal = entryIndexes->GetObjectFromCache(0).GetInt(); // 0: only one method 495 } 496 if (entryIndexVal != static_cast<int>(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE)) { 497 hasEntryIndex = true; 498 entryIndex = static_cast<uint32_t>(entryIndexVal); 499 } 500 val = JSTaggedValue::Hole(); 501 } 502 503 if (!val.IsHole()) { 504 return val; 505 } 506 507 if (!taggedPool->GetJSPandaFile()->IsNewVersion()) { 508 JSTaggedValue unsharedCp = thread->GetCurrentEcmaContext()->FindOrCreateUnsharedConstpool(constpool); 509 taggedPool = ConstantPool::Cast(unsharedCp.GetTaggedObject()); 510 return taggedPool->Get(index); 511 } 512 513 [[maybe_unused]] EcmaHandleScope handleScope(thread); 514 ASSERT(jsPandaFile->IsNewVersion()); 515 JSHandle<ConstantPool> constpoolHandle(thread, constpool); 516 EcmaVM *vm = thread->GetEcmaVM(); 517 518 EntityId id = constpoolHandle->GetEntityId(index); 519 MethodLiteral *methodLiteral = jsPandaFile->FindMethodLiteral(id.GetOffset()); 520 CHECK_INPUT_NULLPTR(methodLiteral, 521 "GetMethodFromCache:methodLiteral is nullptr, offset: " + std::to_string(id.GetOffset())); 522 ObjectFactory *factory = vm->GetFactory(); 523 JSHandle<Method> method = factory->NewSMethod( 524 jsPandaFile, methodLiteral, constpoolHandle, entryIndex, isLoadedAOT && hasEntryIndex); 525 526 CASSetObjectToCache(thread, constpoolHandle.GetTaggedValue(), index, method.GetTaggedValue()); 527 return method.GetTaggedValue(); 528 } 529 530 static JSTaggedValue PUBLIC_API GetMethodFromCache(JSTaggedValue constpool, uint32_t index); 531 532 static void PUBLIC_API UpdateConstpoolWhenDeserialAI(EcmaVM *vm, JSHandle<ConstantPool> aiCP, 533 JSHandle<ConstantPool> sharedCP, JSHandle<ConstantPool> unsharedCP); 534 535 static bool PUBLIC_API IsAotMethodLiteralInfo(JSTaggedValue literalInfo); 536 537 static JSTaggedValue GetClassLiteralFromCache(JSThread *thread, JSHandle<ConstantPool> constpool, 538 uint32_t literal, CString entry, JSHandle<JSTaggedValue> sendableEnv = JSHandle<JSTaggedValue>(), 539 ClassKind kind = ClassKind::NON_SENDABLE); 540 541 static JSHandle<TaggedArray> GetFieldLiteral(JSThread *thread, JSHandle<ConstantPool> constpool, 542 uint32_t literal, CString entry); 543 544 template <ConstPoolType type> GetLiteralFromCache(JSThread * thread,JSTaggedValue constpool,uint32_t index,CString entry)545 static JSTaggedValue GetLiteralFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index, CString entry) 546 { 547 static_assert(type == ConstPoolType::OBJECT_LITERAL || type == ConstPoolType::ARRAY_LITERAL); 548 [[maybe_unused]] EcmaHandleScope handleScope(thread); 549 const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); 550 auto val = taggedPool->GetObjectFromCache(index); 551 JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile(); 552 553 // For AOT 554 bool isLoadedAOT = jsPandaFile->IsLoadedAOT(); 555 JSHandle<AOTLiteralInfo> entryIndexes(thread, JSTaggedValue::Undefined()); 556 if (isLoadedAOT && val.IsAOTLiteralInfo()) { 557 entryIndexes = JSHandle<AOTLiteralInfo>(thread, val); 558 val = JSTaggedValue::Hole(); 559 } 560 561 if (val.IsHole()) { 562 JSHandle<ConstantPool> constpoolHandle(thread, constpool); 563 564 ASSERT(jsPandaFile->IsNewVersion()); 565 panda_file::File::EntityId id = taggedPool->GetEntityId(index); 566 bool needSetAotFlag = isLoadedAOT && !entryIndexes.GetTaggedValue().IsUndefined(); 567 // New inst 568 switch (type) { 569 case ConstPoolType::OBJECT_LITERAL: { 570 JSMutableHandle<TaggedArray> elements(thread, JSTaggedValue::Undefined()); 571 JSMutableHandle<TaggedArray> properties(thread, JSTaggedValue::Undefined()); 572 LiteralDataExtractor::ExtractObjectDatas(thread, jsPandaFile, id, elements, 573 properties, constpoolHandle, entry, needSetAotFlag, entryIndexes); 574 JSTaggedValue ihcVal = JSTaggedValue::Undefined(); 575 if (needSetAotFlag) { 576 ihcVal = entryIndexes->GetIhc(); 577 if (!ihcVal.IsUndefined()) { 578 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 579 JSHClass::Cast(ihcVal.GetTaggedObject())->SetPrototype(thread, 580 env->GetObjectFunctionPrototype()); 581 JSHClass::EnableProtoChangeMarker(thread, JSHandle<JSHClass>(thread, ihcVal)); 582 } 583 } 584 JSHandle<JSObject> obj = JSObject::CreateObjectFromProperties(thread, properties, ihcVal); 585 auto profiler = thread->GetEcmaVM()->GetPGOProfiler(); 586 profiler->RecordProfileType(obj->GetClass(), jsPandaFile, id.GetOffset()); 587 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 588 JSMutableHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined()); 589 size_t elementsLen = elements->GetLength(); 590 for (size_t i = 0; i < elementsLen; i += 2) { // 2: Each literal buffer has a pair of key-value. 591 key.Update(elements->Get(i)); 592 if (key->IsHole()) { 593 break; 594 } 595 valueHandle.Update(elements->Get(i + 1)); 596 JSObject::DefinePropertyByLiteral(thread, obj, key, valueHandle); 597 } 598 val = obj.GetTaggedValue(); 599 break; 600 } 601 case ConstPoolType::ARRAY_LITERAL: { 602 // literal fetching from AOT ArrayInfos 603 JSMutableHandle<TaggedArray> literal(thread, JSTaggedValue::Undefined()); 604 #if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC 605 ElementsKind dataKind = ElementsKind::GENERIC; 606 #else 607 ElementsKind dataKind = ElementsKind::NONE; 608 #endif 609 literal.Update(LiteralDataExtractor::GetDatasIgnoreType(thread, jsPandaFile, id, 610 constpoolHandle, entry, 611 needSetAotFlag, entryIndexes, 612 &dataKind)); 613 uint32_t length = literal->GetLength(); 614 JSHandle<JSArray> arr(JSArray::ArrayCreate(thread, JSTaggedNumber(length), ArrayMode::LITERAL)); 615 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 616 arr->SetElements(thread, literal); 617 if (thread->GetEcmaVM()->IsEnablePGOProfiler() || thread->GetEcmaVM()->IsEnableElementsKind()) { 618 // for all JSArray, the initial ElementsKind should be NONE 619 // Because AOT Stable Array Deopt check, we have support arrayLiteral elementskind 620 // If array is loaded from AOT, no need to do migration. 621 auto globalConstant = const_cast<GlobalEnvConstants *>(thread->GlobalConstants()); 622 auto classIndex = static_cast<size_t>(ConstantIndex::ELEMENT_NONE_HCLASS_INDEX); 623 auto hclassVal = globalConstant->GetGlobalConstantObject(classIndex); 624 arr->SynchronizedSetClass(thread, JSHClass::Cast(hclassVal.GetTaggedObject())); 625 ElementsKind oldKind = arr->GetClass()->GetElementsKind(); 626 JSHClass::TransitToElementsKind(thread, arr, dataKind); 627 ElementsKind newKind = arr->GetClass()->GetElementsKind(); 628 JSHandle<JSObject> receiver(arr); 629 Elements::MigrateArrayWithKind(thread, receiver, oldKind, newKind); 630 } 631 val = arr.GetTaggedValue(); 632 break; 633 } 634 default: 635 LOG_FULL(FATAL) << "Unknown type: " << static_cast<uint8_t>(type); 636 UNREACHABLE(); 637 } 638 constpoolHandle->SetObjectToCache(thread, index, val); 639 } 640 641 return val; 642 } 643 644 template <ConstPoolType type> GetLiteralFromCache(JSTaggedValue constpool,uint32_t index,CString entry)645 static JSTaggedValue GetLiteralFromCache(JSTaggedValue constpool, uint32_t index, [[maybe_unused]] CString entry) 646 { 647 const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); 648 auto val = taggedPool->GetObjectFromCache(index); 649 JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile(); 650 651 bool isLoadedAOT = jsPandaFile->IsLoadedAOT(); 652 if (isLoadedAOT && val.IsAOTLiteralInfo()) { 653 val = JSTaggedValue::Hole(); 654 } 655 return val.IsHole() ? JSTaggedValue::Undefined() : val; 656 } 657 GetIdFromCache(JSTaggedValue constpool,uint32_t index)658 static panda_file::File::EntityId GetIdFromCache(JSTaggedValue constpool, uint32_t index) 659 { 660 const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); 661 panda_file::File::EntityId id = taggedPool->GetEntityId(index); 662 return id; 663 } 664 665 template <ConstPoolType type> GetLiteralFromCache(JSThread * thread,JSTaggedValue constpool,uint32_t index,JSTaggedValue module)666 static JSTaggedValue GetLiteralFromCache(JSThread *thread, JSTaggedValue constpool, 667 uint32_t index, JSTaggedValue module) 668 { 669 CString entry = ModuleManager::GetRecordName(module); 670 return GetLiteralFromCache<type>(thread, constpool, index, entry); 671 } 672 673 static JSTaggedValue PUBLIC_API GetStringFromCacheForJit(JSThread *thread, JSTaggedValue constpool, uint32_t index, 674 bool allowAlloc = true); 675 676 static JSTaggedValue PUBLIC_API GetStringFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index); 677 678 DECL_VISIT_ARRAY(DATA_OFFSET, GetCacheLength(), GetLength()); 679 DECL_DUMP()680 DECL_DUMP() 681 682 private: 683 inline size_t GetJSPandaFileOffset() const 684 { 685 return JSTaggedValue::TaggedTypeSize() * (GetLength() - JS_PANDA_FILE_INDEX); 686 } 687 GetIndexHeaderOffset()688 inline size_t GetIndexHeaderOffset() const 689 { 690 return JSTaggedValue::TaggedTypeSize() * (GetLength() - INDEX_HEADER_INDEX); 691 } 692 GetConstantIndexInfoOffset()693 inline size_t GetConstantIndexInfoOffset() const 694 { 695 return JSTaggedValue::TaggedTypeSize() * (GetLength() - CONSTANT_INDEX_INFO_INDEX); 696 } 697 GetAotArrayInfoOffset()698 inline size_t GetAotArrayInfoOffset() const 699 { 700 return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_ARRAY_INFO_INDEX); 701 } 702 GetAotHClassInfoOffset()703 inline size_t GetAotHClassInfoOffset() const 704 { 705 return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_HCLASS_INFO_INDEX); 706 } 707 GetUnsharedConstpoolIndexOffset()708 inline size_t GetUnsharedConstpoolIndexOffset() const 709 { 710 return JSTaggedValue::TaggedTypeSize() * (GetLength() - UNSHARED_CONSTPOOL_INDEX); 711 } 712 GetSharedConstpoolIdOffset()713 inline size_t GetSharedConstpoolIdOffset() const 714 { 715 return JSTaggedValue::TaggedTypeSize() * (GetLength() - SHARED_CONSTPOOL_ID); 716 } 717 GetAotSymbolInfoOffset()718 inline size_t GetAotSymbolInfoOffset() const 719 { 720 return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_SYMBOL_INFO_INDEX); 721 } 722 GetProtoTransTableInfoOffset()723 inline size_t GetProtoTransTableInfoOffset() const 724 { 725 return JSTaggedValue::TaggedTypeSize() * (GetLength() - PROTO_TRANS_TABLE_INFO_INDEX); 726 } 727 GetLastOffset()728 inline size_t GetLastOffset() const 729 { 730 return JSTaggedValue::TaggedTypeSize() * GetLength() + DATA_OFFSET; 731 } 732 IsLoadedMethodInfoFromAOT(const JSPandaFile * pf,JSTaggedValue cachedVal)733 static bool IsLoadedMethodInfoFromAOT(const JSPandaFile *pf, JSTaggedValue cachedVal) 734 { 735 return pf->IsLoadedAOT() && (cachedVal.IsAOTLiteralInfo() || cachedVal.IsInt()); 736 }; 737 738 static JSHandle<JSTaggedValue> GetDeserializedConstantPool( 739 EcmaVM *vm, const JSPandaFile *jsPandaFile, int32_t cpID); 740 static void MergeObjectLiteralHClassCache(EcmaVM *vm, const JSHandle<JSTaggedValue> &pool); 741 }; 742 } // namespace ecmascript 743 } // namespace panda 744 #endif // ECMASCRIPT_JSPANDAFILE_PROGRAM_OBJECT_H 745