14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2022-2024 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci#include "ecmascript/patch/patch_loader.h" 164514f5e3Sopenharmony_ci 174514f5e3Sopenharmony_ci#include "ecmascript/interpreter/interpreter-inl.h" 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_cinamespace panda::ecmascript { 204514f5e3Sopenharmony_ciPatchErrorCode PatchLoader::LoadPatchInternal(JSThread *thread, const JSPandaFile *baseFile, 214514f5e3Sopenharmony_ci const JSPandaFile *patchFile, PatchInfo &patchInfo, 224514f5e3Sopenharmony_ci const CMap<uint32_t, CString> &baseClassInfo) 234514f5e3Sopenharmony_ci{ 244514f5e3Sopenharmony_ci DISALLOW_GARBAGE_COLLECTION; 254514f5e3Sopenharmony_ci EcmaVM *vm = thread->GetEcmaVM(); 264514f5e3Sopenharmony_ci 274514f5e3Sopenharmony_ci // hot reload and hot patch only support merge-abc file. 284514f5e3Sopenharmony_ci if (baseFile->IsBundlePack() || patchFile->IsBundlePack()) { 294514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "base or patch is not merge abc!"; 304514f5e3Sopenharmony_ci return PatchErrorCode::PACKAGE_NOT_ESMODULE; 314514f5e3Sopenharmony_ci } 324514f5e3Sopenharmony_ci 334514f5e3Sopenharmony_ci // Generate patchInfo for hot reload, hot patch and cold patch. 344514f5e3Sopenharmony_ci patchInfo = PatchLoader::GeneratePatchInfo(patchFile); 354514f5e3Sopenharmony_ci 364514f5e3Sopenharmony_ci if (!thread->GetCurrentEcmaContext()->HasCachedConstpool(baseFile)) { 374514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "cold patch!"; 384514f5e3Sopenharmony_ci vm->GetJsDebuggerManager()->GetHotReloadManager()->NotifyPatchLoaded(baseFile, patchFile); 394514f5e3Sopenharmony_ci return PatchErrorCode::SUCCESS; 404514f5e3Sopenharmony_ci } 414514f5e3Sopenharmony_ci 424514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 434514f5e3Sopenharmony_ci 444514f5e3Sopenharmony_ci // store base constpool in global object for avoid gc. 454514f5e3Sopenharmony_ci GlobalHandleCollection gloalHandleCollection(thread); 464514f5e3Sopenharmony_ci for (uint32_t idx = 0; idx < baseFile->GetConstpoolNum(); idx++) { 474514f5e3Sopenharmony_ci JSTaggedValue constpool = thread->GetCurrentEcmaContext()->FindConstpool(baseFile, idx); 484514f5e3Sopenharmony_ci if (!constpool.IsHole()) { 494514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> constpoolHandle = 504514f5e3Sopenharmony_ci gloalHandleCollection.NewHandle<JSTaggedValue>(constpool.GetRawData()); 514514f5e3Sopenharmony_ci patchInfo.baseConstpools.emplace_back(constpoolHandle); 524514f5e3Sopenharmony_ci } 534514f5e3Sopenharmony_ci } 544514f5e3Sopenharmony_ci 554514f5e3Sopenharmony_ci // create empty patch constpool for replace method constpool. 564514f5e3Sopenharmony_ci thread->GetCurrentEcmaContext()->CreateAllConstpool(patchFile); 574514f5e3Sopenharmony_ci FindAndReplaceSameMethod(thread, baseFile, patchFile, patchInfo, baseClassInfo); 584514f5e3Sopenharmony_ci 594514f5e3Sopenharmony_ci // cached patch modules can only be clear before load patch. 604514f5e3Sopenharmony_ci thread->GetCurrentEcmaContext()->ClearPatchModules(); 614514f5e3Sopenharmony_ci // execute patch func_main_0 for hot reload, and patch_main_0 for hot patch. 624514f5e3Sopenharmony_ci ExecuteFuncOrPatchMain(thread, patchFile, patchInfo); 634514f5e3Sopenharmony_ci UpdateJSFunction(thread, patchInfo); 644514f5e3Sopenharmony_ci 654514f5e3Sopenharmony_ci vm->GetJsDebuggerManager()->GetHotReloadManager()->NotifyPatchLoaded(baseFile, patchFile); 664514f5e3Sopenharmony_ci return PatchErrorCode::SUCCESS; 674514f5e3Sopenharmony_ci} 684514f5e3Sopenharmony_ci 694514f5e3Sopenharmony_civoid PatchLoader::ExecuteFuncOrPatchMain( 704514f5e3Sopenharmony_ci JSThread *thread, const JSPandaFile *jsPandaFile, const PatchInfo &patchInfo, bool loadPatch) 714514f5e3Sopenharmony_ci{ 724514f5e3Sopenharmony_ci ThreadManagedScope managedScope(thread); 734514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "execute main begin"; 744514f5e3Sopenharmony_ci EcmaContext *context = thread->GetCurrentEcmaContext(); 754514f5e3Sopenharmony_ci context->SetStageOfHotReload(StageOfHotReload::BEGIN_EXECUTE_PATCHMAIN); 764514f5e3Sopenharmony_ci 774514f5e3Sopenharmony_ci const auto &replacedRecordNames = patchInfo.replacedRecordNames; 784514f5e3Sopenharmony_ci 794514f5e3Sopenharmony_ci // Resolve all patch module records. 804514f5e3Sopenharmony_ci CMap<CString, JSHandle<JSTaggedValue>> moduleRecords {}; 814514f5e3Sopenharmony_ci 824514f5e3Sopenharmony_ci ModuleManager *moduleManager = context->GetModuleManager(); 834514f5e3Sopenharmony_ci CString fileName = jsPandaFile->GetJSPandaFileDesc(); 844514f5e3Sopenharmony_ci for (const auto &recordName : replacedRecordNames) { 854514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> moduleRecord = moduleManager-> 864514f5e3Sopenharmony_ci HostResolveImportedModuleWithMergeForHotReload(fileName, recordName, false); 874514f5e3Sopenharmony_ci moduleRecords.emplace(recordName, moduleRecord); 884514f5e3Sopenharmony_ci } 894514f5e3Sopenharmony_ci 904514f5e3Sopenharmony_ci for (const auto &recordName : replacedRecordNames) { 914514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "func main record name " << recordName; 924514f5e3Sopenharmony_ci JSHandle<Program> program = 934514f5e3Sopenharmony_ci JSPandaFileManager::GetInstance()->GenerateProgram(thread->GetEcmaVM(), jsPandaFile, recordName); 944514f5e3Sopenharmony_ci if (program.IsEmpty()) { 954514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "program is empty, invoke entrypoint failed"; 964514f5e3Sopenharmony_ci continue; 974514f5e3Sopenharmony_ci } 984514f5e3Sopenharmony_ci 994514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> moduleRecord = moduleRecords[recordName]; 1004514f5e3Sopenharmony_ci SourceTextModule::Instantiate(thread, moduleRecord, false); 1014514f5e3Sopenharmony_ci RETURN_IF_ABRUPT_COMPLETION(thread); 1024514f5e3Sopenharmony_ci JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(moduleRecord); 1034514f5e3Sopenharmony_ci SourceTextModule::Evaluate(thread, module); 1044514f5e3Sopenharmony_ci } 1054514f5e3Sopenharmony_ci 1064514f5e3Sopenharmony_ci if (loadPatch) { 1074514f5e3Sopenharmony_ci context->SetStageOfHotReload(StageOfHotReload::LOAD_END_EXECUTE_PATCHMAIN); 1084514f5e3Sopenharmony_ci } else { 1094514f5e3Sopenharmony_ci context->SetStageOfHotReload(StageOfHotReload::UNLOAD_END_EXECUTE_PATCHMAIN); 1104514f5e3Sopenharmony_ci } 1114514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "execute main end"; 1124514f5e3Sopenharmony_ci} 1134514f5e3Sopenharmony_ci 1144514f5e3Sopenharmony_ciPatchErrorCode PatchLoader::UnloadPatchInternal(JSThread *thread, const CString &patchFileName, 1154514f5e3Sopenharmony_ci const CString &baseFileName, PatchInfo &patchInfo) 1164514f5e3Sopenharmony_ci{ 1174514f5e3Sopenharmony_ci std::shared_ptr<JSPandaFile> baseFile = JSPandaFileManager::GetInstance()->FindJSPandaFile(baseFileName); 1184514f5e3Sopenharmony_ci if (baseFile == nullptr) { 1194514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "find base jsPandafile failed"; 1204514f5e3Sopenharmony_ci return PatchErrorCode::FILE_NOT_EXECUTED; 1214514f5e3Sopenharmony_ci } 1224514f5e3Sopenharmony_ci 1234514f5e3Sopenharmony_ci std::shared_ptr<JSPandaFile> patchFile = JSPandaFileManager::GetInstance()->FindJSPandaFile(patchFileName); 1244514f5e3Sopenharmony_ci if (patchFile == nullptr) { 1254514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "find patch jsPandafile failed"; 1264514f5e3Sopenharmony_ci return PatchErrorCode::FILE_NOT_FOUND; 1274514f5e3Sopenharmony_ci } 1284514f5e3Sopenharmony_ci 1294514f5e3Sopenharmony_ci const auto &baseMethodInfo = patchInfo.baseMethodInfo; 1304514f5e3Sopenharmony_ci if (baseMethodInfo.empty()) { 1314514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "no method need to unload"; 1324514f5e3Sopenharmony_ci return PatchErrorCode::SUCCESS; 1334514f5e3Sopenharmony_ci } 1344514f5e3Sopenharmony_ci 1354514f5e3Sopenharmony_ci EcmaVM *vm = thread->GetEcmaVM(); 1364514f5e3Sopenharmony_ci EcmaContext *context = thread->GetCurrentEcmaContext(); 1374514f5e3Sopenharmony_ci auto baseConstpoolValues = context->FindConstpools(baseFile.get()); 1384514f5e3Sopenharmony_ci if (!baseConstpoolValues.has_value()) { 1394514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "base constpool is empty"; 1404514f5e3Sopenharmony_ci return PatchErrorCode::INTERNAL_ERROR; 1414514f5e3Sopenharmony_ci } 1424514f5e3Sopenharmony_ci 1434514f5e3Sopenharmony_ci patchInfo.replacedPatchMethods.clear(); 1444514f5e3Sopenharmony_ci for (const auto &item : baseMethodInfo) { 1454514f5e3Sopenharmony_ci const auto &methodIndex = item.first; 1464514f5e3Sopenharmony_ci JSTaggedValue baseConstpool = baseConstpoolValues.value().get()[methodIndex.constpoolNum]; 1474514f5e3Sopenharmony_ci 1484514f5e3Sopenharmony_ci Method *patchMethod = GetPatchMethod(thread, methodIndex, baseConstpool); 1494514f5e3Sopenharmony_ci 1504514f5e3Sopenharmony_ci MethodLiteral *baseMethodLiteral = item.second; 1514514f5e3Sopenharmony_ci EntityId baseMethodId = baseMethodLiteral->GetMethodId(); 1524514f5e3Sopenharmony_ci JSTaggedValue baseConstpoolValue = context->FindConstpool(baseFile.get(), baseMethodId); 1534514f5e3Sopenharmony_ci // After the method replaced, the methodId is baseMethodId, 1544514f5e3Sopenharmony_ci // and the JSPandaFile of replaced method is baseFile 1554514f5e3Sopenharmony_ci ReplacedMethod replacedMethod {baseMethodId, baseFileName}; 1564514f5e3Sopenharmony_ci patchInfo.replacedPatchMethods.emplace(replacedMethod, patchMethod->GetRecordNameStr()); 1574514f5e3Sopenharmony_ci ReplaceMethod(thread, patchMethod, baseMethodLiteral, baseConstpoolValue); 1584514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "Replace base method: " 1594514f5e3Sopenharmony_ci << patchMethod->GetRecordNameStr() 1604514f5e3Sopenharmony_ci << ":" << patchMethod->GetMethodName(); 1614514f5e3Sopenharmony_ci } 1624514f5e3Sopenharmony_ci 1634514f5e3Sopenharmony_ci context->ClearPatchModules(); 1644514f5e3Sopenharmony_ci // execute base func_main_0 for recover global object. 1654514f5e3Sopenharmony_ci ExecuteFuncOrPatchMain(thread, baseFile.get(), patchInfo, false); 1664514f5e3Sopenharmony_ci UpdateJSFunction(thread, patchInfo); 1674514f5e3Sopenharmony_ci 1684514f5e3Sopenharmony_ci vm->GetJsDebuggerManager()->GetHotReloadManager()->NotifyPatchUnloaded(patchFile.get()); 1694514f5e3Sopenharmony_ci 1704514f5e3Sopenharmony_ci // release base constpool. 1714514f5e3Sopenharmony_ci CVector<JSHandle<JSTaggedValue>> &baseConstpools = patchInfo.baseConstpools; 1724514f5e3Sopenharmony_ci GlobalHandleCollection gloalHandleCollection(thread); 1734514f5e3Sopenharmony_ci for (auto &item : baseConstpools) { 1744514f5e3Sopenharmony_ci gloalHandleCollection.Dispose(item); 1754514f5e3Sopenharmony_ci } 1764514f5e3Sopenharmony_ci 1774514f5e3Sopenharmony_ci ClearPatchInfo(thread, patchFileName); 1784514f5e3Sopenharmony_ci return PatchErrorCode::SUCCESS; 1794514f5e3Sopenharmony_ci} 1804514f5e3Sopenharmony_ci 1814514f5e3Sopenharmony_ciMethod *PatchLoader::GetPatchMethod(JSThread *thread, 1824514f5e3Sopenharmony_ci const BaseMethodIndex &methodIndex, const JSTaggedValue constpoolVal) 1834514f5e3Sopenharmony_ci{ 1844514f5e3Sopenharmony_ci uint32_t constpoolIndex = methodIndex.constpoolIndex; 1854514f5e3Sopenharmony_ci uint32_t literalIndex = methodIndex.literalIndex; 1864514f5e3Sopenharmony_ci Method *patchMethod = nullptr; 1874514f5e3Sopenharmony_ci ConstantPool *baseConstpool = ConstantPool::Cast(constpoolVal.GetTaggedObject()); 1884514f5e3Sopenharmony_ci if (literalIndex == UINT32_MAX) { 1894514f5e3Sopenharmony_ci JSTaggedValue value = baseConstpool->GetObjectFromCache(constpoolIndex); 1904514f5e3Sopenharmony_ci ASSERT(value.IsMethod()); 1914514f5e3Sopenharmony_ci patchMethod = Method::Cast(value.GetTaggedObject()); 1924514f5e3Sopenharmony_ci } else { 1934514f5e3Sopenharmony_ci ClassLiteral *classLiteral; 1944514f5e3Sopenharmony_ci if (baseConstpool->GetObjectFromCache(constpoolIndex).IsHole()) { 1954514f5e3Sopenharmony_ci JSTaggedValue unsharedBaseConstpool = thread->GetCurrentEcmaContext()-> 1964514f5e3Sopenharmony_ci FindOrCreateUnsharedConstpool(constpoolVal); 1974514f5e3Sopenharmony_ci classLiteral = ClassLiteral::Cast( 1984514f5e3Sopenharmony_ci ConstantPool::Cast(unsharedBaseConstpool.GetTaggedObject())->GetObjectFromCache(constpoolIndex)); 1994514f5e3Sopenharmony_ci } else { 2004514f5e3Sopenharmony_ci classLiteral = ClassLiteral::Cast(baseConstpool->GetObjectFromCache(constpoolIndex)); 2014514f5e3Sopenharmony_ci } 2024514f5e3Sopenharmony_ci TaggedArray *literalArray = TaggedArray::Cast(classLiteral->GetArray()); 2034514f5e3Sopenharmony_ci JSTaggedValue value = literalArray->Get(thread, literalIndex); 2044514f5e3Sopenharmony_ci ASSERT(value.IsFunctionTemplate()); 2054514f5e3Sopenharmony_ci FunctionTemplate *func = FunctionTemplate::Cast(value.GetTaggedObject()); 2064514f5e3Sopenharmony_ci patchMethod = Method::Cast(func->GetMethod().GetTaggedObject()); 2074514f5e3Sopenharmony_ci } 2084514f5e3Sopenharmony_ci return patchMethod; 2094514f5e3Sopenharmony_ci} 2104514f5e3Sopenharmony_ci 2114514f5e3Sopenharmony_civoid PatchLoader::ClearPatchInfo(JSThread *thread, const CString &patchFileName) 2124514f5e3Sopenharmony_ci{ 2134514f5e3Sopenharmony_ci EcmaVM *vm = thread->GetEcmaVM(); 2144514f5e3Sopenharmony_ci 2154514f5e3Sopenharmony_ci vm->GetGlobalEnv()->SetGlobalPatch(thread, vm->GetFactory()->EmptyArray()); 2164514f5e3Sopenharmony_ci 2174514f5e3Sopenharmony_ci // For release patch constpool and JSPandaFile. 2184514f5e3Sopenharmony_ci vm->CollectGarbage(TriggerGCType::FULL_GC); 2194514f5e3Sopenharmony_ci 2204514f5e3Sopenharmony_ci std::shared_ptr<JSPandaFile> patchFile = JSPandaFileManager::GetInstance()->FindJSPandaFile(patchFileName); 2214514f5e3Sopenharmony_ci if (patchFile != nullptr) { 2224514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "patch jsPandaFile is not nullptr"; 2234514f5e3Sopenharmony_ci } 2244514f5e3Sopenharmony_ci} 2254514f5e3Sopenharmony_ci 2264514f5e3Sopenharmony_civoid PatchLoader::ReplaceMethod(JSThread *thread, 2274514f5e3Sopenharmony_ci Method *destMethod, 2284514f5e3Sopenharmony_ci MethodLiteral *srcMethodLiteral, 2294514f5e3Sopenharmony_ci JSTaggedValue srcConstpool) 2304514f5e3Sopenharmony_ci{ 2314514f5e3Sopenharmony_ci // Update destmethod exclude ExtraLiteralInfo(FunctionKind). Method FunctionKind will be set after 2324514f5e3Sopenharmony_ci // building class inheritance relationship or defining gettersetter by value. 2334514f5e3Sopenharmony_ci // 2344514f5e3Sopenharmony_ci // HotReload of class inheritance will be affected. 2354514f5e3Sopenharmony_ci destMethod->SetCallField(srcMethodLiteral->GetCallField()); 2364514f5e3Sopenharmony_ci destMethod->SetLiteralInfo(srcMethodLiteral->GetLiteralInfo()); 2374514f5e3Sopenharmony_ci destMethod->SetCodeEntryOrLiteral(reinterpret_cast<uintptr_t>(srcMethodLiteral)); 2384514f5e3Sopenharmony_ci destMethod->SetNativePointerOrBytecodeArray(const_cast<void *>(srcMethodLiteral->GetNativePointer())); 2394514f5e3Sopenharmony_ci destMethod->SetConstantPool(thread, srcConstpool); 2404514f5e3Sopenharmony_ci destMethod->SetAotCodeBit(false); 2414514f5e3Sopenharmony_ci destMethod->SetFpDelta(0); 2424514f5e3Sopenharmony_ci} 2434514f5e3Sopenharmony_ci 2444514f5e3Sopenharmony_ci// Iterator heap to update module in JSFunction. 2454514f5e3Sopenharmony_civoid PatchLoader::UpdateJSFunction(JSThread *thread, PatchInfo &patchInfo) 2464514f5e3Sopenharmony_ci{ 2474514f5e3Sopenharmony_ci auto &replacedPatchMethods = patchInfo.replacedPatchMethods; 2484514f5e3Sopenharmony_ci const Heap *heap = thread->GetEcmaVM()->GetHeap(); 2494514f5e3Sopenharmony_ci heap->GetSweeper()->EnsureAllTaskFinished(); 2504514f5e3Sopenharmony_ci heap->IterateOverObjects([&replacedPatchMethods, thread]([[maybe_unused]] TaggedObject *obj) { 2514514f5e3Sopenharmony_ci if (JSTaggedValue(obj).IsJSFunction()) { 2524514f5e3Sopenharmony_ci JSFunction *function = JSFunction::Cast(obj); 2534514f5e3Sopenharmony_ci EntityId methodId = Method::Cast(function->GetMethod())->GetMethodId(); 2544514f5e3Sopenharmony_ci const JSPandaFile *jsPandaFile = Method::Cast(function->GetMethod())->GetJSPandaFile(); 2554514f5e3Sopenharmony_ci CString fileName {}; 2564514f5e3Sopenharmony_ci if (jsPandaFile != nullptr) { 2574514f5e3Sopenharmony_ci fileName = jsPandaFile->GetJSPandaFileDesc(); 2584514f5e3Sopenharmony_ci } 2594514f5e3Sopenharmony_ci ReplacedMethod replacedMethod {methodId, fileName}; 2604514f5e3Sopenharmony_ci if (replacedPatchMethods.count(replacedMethod) > 0) { 2614514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> moduleRecord = 2624514f5e3Sopenharmony_ci thread->GetCurrentEcmaContext()->FindPatchModule(replacedPatchMethods[replacedMethod]); 2634514f5e3Sopenharmony_ci function->SetModule(thread, moduleRecord.GetTaggedValue()); 2644514f5e3Sopenharmony_ci function->SetRawProfileTypeInfo(thread, thread->GlobalConstants()->GetEmptyProfileTypeInfoCell(), 2654514f5e3Sopenharmony_ci SKIP_BARRIER); 2664514f5e3Sopenharmony_ci } 2674514f5e3Sopenharmony_ci } else if (JSTaggedValue(obj).IsFunctionTemplate()) { 2684514f5e3Sopenharmony_ci auto funcTemp = FunctionTemplate::Cast(obj); 2694514f5e3Sopenharmony_ci EntityId methodId = Method::Cast(funcTemp->GetMethod())->GetMethodId(); 2704514f5e3Sopenharmony_ci const JSPandaFile *jsPandaFile = Method::Cast(funcTemp->GetMethod())->GetJSPandaFile(); 2714514f5e3Sopenharmony_ci CString fileName {}; 2724514f5e3Sopenharmony_ci if (jsPandaFile != nullptr) { 2734514f5e3Sopenharmony_ci fileName = jsPandaFile->GetJSPandaFileDesc(); 2744514f5e3Sopenharmony_ci } 2754514f5e3Sopenharmony_ci ReplacedMethod replacedMethod {methodId, fileName}; 2764514f5e3Sopenharmony_ci if (replacedPatchMethods.count(replacedMethod) > 0) { 2774514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> moduleRecord = 2784514f5e3Sopenharmony_ci thread->GetCurrentEcmaContext()->FindPatchModule(replacedPatchMethods[replacedMethod]); 2794514f5e3Sopenharmony_ci funcTemp->SetModule(thread, moduleRecord.GetTaggedValue()); 2804514f5e3Sopenharmony_ci funcTemp->SetRawProfileTypeInfo(thread, thread->GlobalConstants()->GetEmptyProfileTypeInfoCell(), 2814514f5e3Sopenharmony_ci SKIP_BARRIER); 2824514f5e3Sopenharmony_ci } 2834514f5e3Sopenharmony_ci } 2844514f5e3Sopenharmony_ci }); 2854514f5e3Sopenharmony_ci} 2864514f5e3Sopenharmony_ci 2874514f5e3Sopenharmony_civoid PatchLoader::UpdateModuleForColdPatch(JSThread *thread, EntityId methodId, CString &recordName, bool hasModule) 2884514f5e3Sopenharmony_ci{ 2894514f5e3Sopenharmony_ci const Heap *heap = thread->GetEcmaVM()->GetHeap(); 2904514f5e3Sopenharmony_ci heap->GetSweeper()->EnsureAllTaskFinished(); 2914514f5e3Sopenharmony_ci heap->IterateOverObjects([methodId, &recordName, hasModule, thread]([[maybe_unused]] TaggedObject *obj) { 2924514f5e3Sopenharmony_ci if (JSTaggedValue(obj).IsJSFunction()) { 2934514f5e3Sopenharmony_ci JSFunction *function = nullptr; 2944514f5e3Sopenharmony_ci function = JSFunction::Cast(obj); 2954514f5e3Sopenharmony_ci EntityId methodIdLoop = Method::Cast(function->GetMethod())->GetMethodId(); 2964514f5e3Sopenharmony_ci if (methodId == methodIdLoop) { 2974514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> moduleRecord = 2984514f5e3Sopenharmony_ci thread->GetCurrentEcmaContext()->FindPatchModule(recordName); 2994514f5e3Sopenharmony_ci if (hasModule) { 3004514f5e3Sopenharmony_ci function->SetModule(thread, moduleRecord.GetTaggedValue()); 3014514f5e3Sopenharmony_ci } else { 3024514f5e3Sopenharmony_ci function->SetModule(thread, JSTaggedValue::Undefined()); 3034514f5e3Sopenharmony_ci } 3044514f5e3Sopenharmony_ci } 3054514f5e3Sopenharmony_ci } else if (JSTaggedValue(obj).IsFunctionTemplate()) { 3064514f5e3Sopenharmony_ci auto funcTemp = FunctionTemplate::Cast(obj); 3074514f5e3Sopenharmony_ci EntityId methodIdLoop = Method::Cast(funcTemp->GetMethod())->GetMethodId(); 3084514f5e3Sopenharmony_ci if (methodId == methodIdLoop) { 3094514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> moduleRecord = 3104514f5e3Sopenharmony_ci thread->GetCurrentEcmaContext()->FindPatchModule(recordName); 3114514f5e3Sopenharmony_ci if (hasModule) { 3124514f5e3Sopenharmony_ci funcTemp->SetModule(thread, moduleRecord.GetTaggedValue()); 3134514f5e3Sopenharmony_ci } else { 3144514f5e3Sopenharmony_ci funcTemp->SetModule(thread, JSTaggedValue::Undefined()); 3154514f5e3Sopenharmony_ci } 3164514f5e3Sopenharmony_ci } 3174514f5e3Sopenharmony_ci } 3184514f5e3Sopenharmony_ci }); 3194514f5e3Sopenharmony_ci} 3204514f5e3Sopenharmony_ci 3214514f5e3Sopenharmony_civoid PatchLoader::FindAndReplaceSameMethod(JSThread *thread, const JSPandaFile *baseFile, 3224514f5e3Sopenharmony_ci const JSPandaFile *patchFile, PatchInfo &patchInfo, 3234514f5e3Sopenharmony_ci const CMap<uint32_t, CString> &baseClassInfo) 3244514f5e3Sopenharmony_ci{ 3254514f5e3Sopenharmony_ci auto context = thread->GetCurrentEcmaContext(); 3264514f5e3Sopenharmony_ci const CMap<int32_t, JSTaggedValue> &baseConstpoolValues = context->FindConstpools(baseFile).value(); 3274514f5e3Sopenharmony_ci for (const auto &item : baseConstpoolValues) { 3284514f5e3Sopenharmony_ci if (item.second.IsHole()) { 3294514f5e3Sopenharmony_ci continue; 3304514f5e3Sopenharmony_ci } 3314514f5e3Sopenharmony_ci 3324514f5e3Sopenharmony_ci ConstantPool *baseConstpool = ConstantPool::Cast(item.second.GetTaggedObject()); 3334514f5e3Sopenharmony_ci uint32_t constpoolNum = item.first; 3344514f5e3Sopenharmony_ci uint32_t baseConstpoolSize = baseConstpool->GetCacheLength(); 3354514f5e3Sopenharmony_ci for (uint32_t constpoolIndex = 0; constpoolIndex < baseConstpoolSize; constpoolIndex++) { 3364514f5e3Sopenharmony_ci JSTaggedValue constpoolValue = baseConstpool->GetObjectFromCache(constpoolIndex); 3374514f5e3Sopenharmony_ci if (!constpoolValue.IsMethod() && !constpoolValue.IsClassLiteral()) { 3384514f5e3Sopenharmony_ci continue; 3394514f5e3Sopenharmony_ci } 3404514f5e3Sopenharmony_ci 3414514f5e3Sopenharmony_ci // For normal function and class constructor. 3424514f5e3Sopenharmony_ci if (constpoolValue.IsMethod()) { 3434514f5e3Sopenharmony_ci Method *baseMethod = Method::Cast(constpoolValue.GetTaggedObject()); 3444514f5e3Sopenharmony_ci EntityId baseMethodId = baseMethod->GetMethodId(); 3454514f5e3Sopenharmony_ci MethodLiteral *patchMethodLiteral = 3464514f5e3Sopenharmony_ci FindSameMethod(patchInfo, baseFile, baseMethodId, baseClassInfo); 3474514f5e3Sopenharmony_ci if (patchMethodLiteral == nullptr) { 3484514f5e3Sopenharmony_ci continue; 3494514f5e3Sopenharmony_ci } 3504514f5e3Sopenharmony_ci 3514514f5e3Sopenharmony_ci EntityId patchMethodId = patchMethodLiteral->GetMethodId(); 3524514f5e3Sopenharmony_ci // After the method replaced, the methodId is patchMethodId, 3534514f5e3Sopenharmony_ci // and the JSPandaFile of replaced method is patchFile 3544514f5e3Sopenharmony_ci CString patchFileName = patchFile->GetJSPandaFileDesc(); 3554514f5e3Sopenharmony_ci ReplacedMethod replacedMethod {patchMethodId, patchFileName}; 3564514f5e3Sopenharmony_ci JSTaggedValue patchConstpoolValue = context->FindConstpool(patchFile, patchMethodId); 3574514f5e3Sopenharmony_ci patchInfo.replacedPatchMethods.emplace(replacedMethod, baseMethod->GetRecordNameStr()); 3584514f5e3Sopenharmony_ci ReplaceMethod(thread, baseMethod, patchMethodLiteral, patchConstpoolValue); 3594514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "Replace base method: " 3604514f5e3Sopenharmony_ci << baseMethod->GetRecordNameStr() << ": " 3614514f5e3Sopenharmony_ci << baseMethod->GetMethodName(); 3624514f5e3Sopenharmony_ci 3634514f5e3Sopenharmony_ci BaseMethodIndex indexs = {constpoolNum, constpoolIndex}; 3644514f5e3Sopenharmony_ci SaveBaseMethodInfo(patchInfo, baseFile, baseMethodId, indexs); 3654514f5e3Sopenharmony_ci } else if (constpoolValue.IsClassLiteral()) { 3664514f5e3Sopenharmony_ci // For class literal. 3674514f5e3Sopenharmony_ci FindAndReplaceClassLiteral(thread, baseFile, patchFile, constpoolValue, patchInfo, 3684514f5e3Sopenharmony_ci constpoolIndex, constpoolNum, baseClassInfo); 3694514f5e3Sopenharmony_ci } 3704514f5e3Sopenharmony_ci } 3714514f5e3Sopenharmony_ci 3724514f5e3Sopenharmony_ci JSTaggedValue unsharedConstpool = context->FindOrCreateUnsharedConstpool(item.second); 3734514f5e3Sopenharmony_ci ConstantPool *baseUnsharedConstpool = ConstantPool::Cast(unsharedConstpool.GetTaggedObject()); 3744514f5e3Sopenharmony_ci const uint32_t len = baseUnsharedConstpool->GetCacheLength(); 3754514f5e3Sopenharmony_ci for (uint32_t constpoolIndex = 0; constpoolIndex < len; constpoolIndex++) { 3764514f5e3Sopenharmony_ci JSTaggedValue constpoolValue = baseUnsharedConstpool->GetObjectFromCache(constpoolIndex); 3774514f5e3Sopenharmony_ci if (!constpoolValue.IsMethod() && !constpoolValue.IsClassLiteral()) { 3784514f5e3Sopenharmony_ci continue; 3794514f5e3Sopenharmony_ci } 3804514f5e3Sopenharmony_ci if (constpoolValue.IsClassLiteral()) { 3814514f5e3Sopenharmony_ci FindAndReplaceClassLiteral(thread, baseFile, patchFile, constpoolValue, patchInfo, 3824514f5e3Sopenharmony_ci constpoolIndex, constpoolNum, baseClassInfo); 3834514f5e3Sopenharmony_ci } 3844514f5e3Sopenharmony_ci } 3854514f5e3Sopenharmony_ci } 3864514f5e3Sopenharmony_ci} 3874514f5e3Sopenharmony_civoid PatchLoader::FindAndReplaceClassLiteral(JSThread *thread, const JSPandaFile *baseFile, 3884514f5e3Sopenharmony_ci const JSPandaFile *patchFile, JSTaggedValue constpoolValue, 3894514f5e3Sopenharmony_ci PatchInfo &patchInfo, uint32_t constpoolIndex, 3904514f5e3Sopenharmony_ci uint32_t constpoolNum, const CMap<uint32_t, CString> &baseClassInfo) 3914514f5e3Sopenharmony_ci{ 3924514f5e3Sopenharmony_ci // For class literal. 3934514f5e3Sopenharmony_ci ClassLiteral *classLiteral = ClassLiteral::Cast(constpoolValue); 3944514f5e3Sopenharmony_ci TaggedArray *literalArray = TaggedArray::Cast(classLiteral->GetArray()); 3954514f5e3Sopenharmony_ci uint32_t literalLength = literalArray->GetLength(); 3964514f5e3Sopenharmony_ci for (uint32_t literalIndex = 0; literalIndex < literalLength; literalIndex++) { 3974514f5e3Sopenharmony_ci JSTaggedValue literalItem = literalArray->Get(thread, literalIndex); 3984514f5e3Sopenharmony_ci if (!literalItem.IsFunctionTemplate()) { 3994514f5e3Sopenharmony_ci continue; 4004514f5e3Sopenharmony_ci } 4014514f5e3Sopenharmony_ci 4024514f5e3Sopenharmony_ci // Every record is the same in current class literal. 4034514f5e3Sopenharmony_ci FunctionTemplate *func = FunctionTemplate::Cast(literalItem.GetTaggedObject()); 4044514f5e3Sopenharmony_ci Method *baseMethod = Method::Cast(func->GetMethod().GetTaggedObject()); 4054514f5e3Sopenharmony_ci EntityId baseMethodId = baseMethod->GetMethodId(); 4064514f5e3Sopenharmony_ci MethodLiteral *patchMethodLiteral = 4074514f5e3Sopenharmony_ci FindSameMethod(patchInfo, baseFile, baseMethodId, baseClassInfo); 4084514f5e3Sopenharmony_ci if (patchMethodLiteral == nullptr) { 4094514f5e3Sopenharmony_ci continue; 4104514f5e3Sopenharmony_ci } 4114514f5e3Sopenharmony_ci 4124514f5e3Sopenharmony_ci EntityId patchMethodId = patchMethodLiteral->GetMethodId(); 4134514f5e3Sopenharmony_ci CString patchFileName = patchFile->GetJSPandaFileDesc(); 4144514f5e3Sopenharmony_ci // After the method replaced, the methodId is patchMethodId, 4154514f5e3Sopenharmony_ci // and the JSPandaFile of replaced method is patchFile 4164514f5e3Sopenharmony_ci ReplacedMethod replacedMethod {patchMethodId, patchFileName}; 4174514f5e3Sopenharmony_ci JSTaggedValue patchConstpoolValue = thread->GetCurrentEcmaContext()->FindConstpool(patchFile, patchMethodId); 4184514f5e3Sopenharmony_ci patchInfo.replacedPatchMethods.emplace(replacedMethod, baseMethod->GetRecordNameStr()); 4194514f5e3Sopenharmony_ci ReplaceMethod(thread, baseMethod, patchMethodLiteral, patchConstpoolValue); 4204514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "Replace base method: " 4214514f5e3Sopenharmony_ci << baseMethod->GetRecordNameStr() << ": " 4224514f5e3Sopenharmony_ci << baseMethod->GetMethodName(); 4234514f5e3Sopenharmony_ci 4244514f5e3Sopenharmony_ci BaseMethodIndex indexs = {constpoolNum, constpoolIndex, literalIndex}; 4254514f5e3Sopenharmony_ci SaveBaseMethodInfo(patchInfo, baseFile, baseMethodId, indexs); 4264514f5e3Sopenharmony_ci } 4274514f5e3Sopenharmony_ci} 4284514f5e3Sopenharmony_ci 4294514f5e3Sopenharmony_ciMethodLiteral* PatchLoader::FindSameMethod(PatchInfo &patchInfo, const JSPandaFile *baseFile, 4304514f5e3Sopenharmony_ci EntityId baseMethodId, const CMap<uint32_t, CString> &baseClassInfo) 4314514f5e3Sopenharmony_ci{ 4324514f5e3Sopenharmony_ci const CUnorderedMap<PatchMethodIndex, MethodLiteral*, PatchMethodIndex::Hash> &patchMethodLiterals = 4334514f5e3Sopenharmony_ci patchInfo.patchMethodLiterals; 4344514f5e3Sopenharmony_ci if (!baseMethodId.IsValid() || baseMethodId.GetOffset() >= baseFile->GetFileSize()) { 4354514f5e3Sopenharmony_ci return nullptr; 4364514f5e3Sopenharmony_ci } 4374514f5e3Sopenharmony_ci CString baseRecordName = MethodLiteral::GetRecordName(baseFile, baseMethodId); 4384514f5e3Sopenharmony_ci CString baseClassName = "default"; 4394514f5e3Sopenharmony_ci auto iter = baseClassInfo.find(baseMethodId.GetOffset()); 4404514f5e3Sopenharmony_ci if (iter != baseClassInfo.end()) { 4414514f5e3Sopenharmony_ci baseClassName = iter->second; 4424514f5e3Sopenharmony_ci } 4434514f5e3Sopenharmony_ci CString baseMethodName = GetRealName(baseFile, baseMethodId, baseClassName); 4444514f5e3Sopenharmony_ci PatchMethodIndex patchMethodIndex = {baseRecordName, baseClassName, baseMethodName}; 4454514f5e3Sopenharmony_ci auto methodIter = patchMethodLiterals.find(patchMethodIndex); 4464514f5e3Sopenharmony_ci if (methodIter == patchMethodLiterals.end()) { 4474514f5e3Sopenharmony_ci return nullptr; 4484514f5e3Sopenharmony_ci } 4494514f5e3Sopenharmony_ci 4504514f5e3Sopenharmony_ci // Reserved for HotPatch. 4514514f5e3Sopenharmony_ci patchInfo.replacedRecordNames.emplace(baseRecordName); 4524514f5e3Sopenharmony_ci return methodIter->second; 4534514f5e3Sopenharmony_ci} 4544514f5e3Sopenharmony_ci 4554514f5e3Sopenharmony_civoid PatchLoader::SaveBaseMethodInfo(PatchInfo &patchInfo, const JSPandaFile *baseFile, 4564514f5e3Sopenharmony_ci EntityId baseMethodId, const BaseMethodIndex &indexs) 4574514f5e3Sopenharmony_ci{ 4584514f5e3Sopenharmony_ci CUnorderedMap<BaseMethodIndex, MethodLiteral *, BaseMethodIndex::Hash> &baseMethodInfo = patchInfo.baseMethodInfo; 4594514f5e3Sopenharmony_ci MethodLiteral *baseMethodLiteral = baseFile->FindMethodLiteral(baseMethodId.GetOffset()); 4604514f5e3Sopenharmony_ci CHECK_INPUT_NULLPTR(baseMethodLiteral, "SaveBaseMethodInfo:baseMethodLiteral is nullptr, offset: " 4614514f5e3Sopenharmony_ci + std::to_string(baseMethodId.GetOffset())); 4624514f5e3Sopenharmony_ci baseMethodInfo.emplace(indexs, baseMethodLiteral); 4634514f5e3Sopenharmony_ci} 4644514f5e3Sopenharmony_ci 4654514f5e3Sopenharmony_ciPatchInfo PatchLoader::GeneratePatchInfo(const JSPandaFile *patchFile) 4664514f5e3Sopenharmony_ci{ 4674514f5e3Sopenharmony_ci CMap<uint32_t, CString> patchClassInfo = CollectClassInfo(patchFile); 4684514f5e3Sopenharmony_ci 4694514f5e3Sopenharmony_ci const auto &map = patchFile->GetMethodLiteralMap(); 4704514f5e3Sopenharmony_ci CUnorderedMap<PatchMethodIndex, MethodLiteral*, PatchMethodIndex::Hash> patchMethodLiterals; 4714514f5e3Sopenharmony_ci PatchInfo patchInfo; 4724514f5e3Sopenharmony_ci for (const auto &item : map) { 4734514f5e3Sopenharmony_ci MethodLiteral *methodLiteral = item.second; 4744514f5e3Sopenharmony_ci EntityId methodId = EntityId(item.first); 4754514f5e3Sopenharmony_ci CString className = "default"; // for normal method and constructor. 4764514f5e3Sopenharmony_ci auto iter = patchClassInfo.find(methodId.GetOffset()); 4774514f5e3Sopenharmony_ci if (iter!= patchClassInfo.end()) { 4784514f5e3Sopenharmony_ci className = iter->second; 4794514f5e3Sopenharmony_ci } 4804514f5e3Sopenharmony_ci CString methodName = GetRealName(patchFile, methodId, className); 4814514f5e3Sopenharmony_ci if (methodName == JSPandaFile::PATCH_FUNCTION_NAME_0 || 4824514f5e3Sopenharmony_ci methodName == JSPandaFile::PATCH_FUNCTION_NAME_1) { 4834514f5e3Sopenharmony_ci continue; 4844514f5e3Sopenharmony_ci } 4854514f5e3Sopenharmony_ci 4864514f5e3Sopenharmony_ci // if patchFile only include varibales, add recordName specially. 4874514f5e3Sopenharmony_ci CString recordName = MethodLiteral::GetRecordName(patchFile, methodId); 4884514f5e3Sopenharmony_ci if (methodName == JSPandaFile::ENTRY_FUNCTION_NAME) { 4894514f5e3Sopenharmony_ci patchInfo.replacedRecordNames.emplace(recordName); 4904514f5e3Sopenharmony_ci } 4914514f5e3Sopenharmony_ci 4924514f5e3Sopenharmony_ci PatchMethodIndex patchMethodIndex = {recordName, className, methodName}; 4934514f5e3Sopenharmony_ci if (patchMethodLiterals.find(patchMethodIndex) == patchMethodLiterals.end()) { 4944514f5e3Sopenharmony_ci patchMethodLiterals.emplace(patchMethodIndex, methodLiteral); 4954514f5e3Sopenharmony_ci } 4964514f5e3Sopenharmony_ci } 4974514f5e3Sopenharmony_ci 4984514f5e3Sopenharmony_ci patchInfo.patchFileName = patchFile->GetJSPandaFileDesc(); 4994514f5e3Sopenharmony_ci patchInfo.patchMethodLiterals = std::move(patchMethodLiterals); 5004514f5e3Sopenharmony_ci return patchInfo; 5014514f5e3Sopenharmony_ci} 5024514f5e3Sopenharmony_ci 5034514f5e3Sopenharmony_ciCMap<uint32_t, CString> PatchLoader::CollectClassInfo(const JSPandaFile *jsPandaFile) 5044514f5e3Sopenharmony_ci{ 5054514f5e3Sopenharmony_ci CMap<uint32_t, CString> classInfo {}; 5064514f5e3Sopenharmony_ci auto &pandaFile = *jsPandaFile->GetPandaFile(); 5074514f5e3Sopenharmony_ci auto classes = jsPandaFile->GetClasses(); 5084514f5e3Sopenharmony_ci const auto &map = jsPandaFile->GetMethodLiteralMap(); 5094514f5e3Sopenharmony_ci for (size_t i = 0; i < classes.Size(); i++) { 5104514f5e3Sopenharmony_ci EntityId classId(classes[i]); 5114514f5e3Sopenharmony_ci if (!classId.IsValid() || jsPandaFile->IsExternal(classId)) { 5124514f5e3Sopenharmony_ci continue; 5134514f5e3Sopenharmony_ci } 5144514f5e3Sopenharmony_ci 5154514f5e3Sopenharmony_ci panda_file::ClassDataAccessor cda(pandaFile, classId); 5164514f5e3Sopenharmony_ci cda.EnumerateMethods([&pandaFile, &map, &classInfo, jsPandaFile](panda_file::MethodDataAccessor &mda) { 5174514f5e3Sopenharmony_ci EntityId methodId = mda.GetMethodId(); 5184514f5e3Sopenharmony_ci auto iter = map.find(methodId.GetOffset()); 5194514f5e3Sopenharmony_ci MethodLiteral *methodLiteral = nullptr; 5204514f5e3Sopenharmony_ci if (iter != map.end()) { 5214514f5e3Sopenharmony_ci methodLiteral = iter->second; 5224514f5e3Sopenharmony_ci } 5234514f5e3Sopenharmony_ci 5244514f5e3Sopenharmony_ci auto codeId = mda.GetCodeId(); 5254514f5e3Sopenharmony_ci ASSERT(codeId.has_value()); 5264514f5e3Sopenharmony_ci panda_file::CodeDataAccessor codeDataAccessor(pandaFile, codeId.value()); 5274514f5e3Sopenharmony_ci uint32_t codeSize = codeDataAccessor.GetCodeSize(); 5284514f5e3Sopenharmony_ci const uint8_t *insns = codeDataAccessor.GetInstructions(); 5294514f5e3Sopenharmony_ci 5304514f5e3Sopenharmony_ci auto bcIns = BytecodeInst(insns); 5314514f5e3Sopenharmony_ci auto bcInsLast = bcIns.JumpTo(codeSize); 5324514f5e3Sopenharmony_ci while (bcIns.GetAddress() != bcInsLast.GetAddress()) { 5334514f5e3Sopenharmony_ci BytecodeInstruction::Opcode opcode = static_cast<BytecodeInstruction::Opcode>(bcIns.GetOpcode()); 5344514f5e3Sopenharmony_ci if (opcode == BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8 || 5354514f5e3Sopenharmony_ci opcode == BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8) { 5364514f5e3Sopenharmony_ci EntityId entityId; 5374514f5e3Sopenharmony_ci EntityId literalId; 5384514f5e3Sopenharmony_ci if (opcode == BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8) { 5394514f5e3Sopenharmony_ci entityId = jsPandaFile->ResolveMethodIndex(methodLiteral->GetMethodId(), 5404514f5e3Sopenharmony_ci (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 0>()).AsRawValue()); 5414514f5e3Sopenharmony_ci literalId = jsPandaFile->ResolveMethodIndex(methodLiteral->GetMethodId(), 5424514f5e3Sopenharmony_ci (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 1>()).AsRawValue()); 5434514f5e3Sopenharmony_ci } else if (opcode == BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8) { 5444514f5e3Sopenharmony_ci entityId = jsPandaFile->ResolveMethodIndex(methodLiteral->GetMethodId(), 5454514f5e3Sopenharmony_ci (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 0>()).AsRawValue()); 5464514f5e3Sopenharmony_ci literalId = jsPandaFile->ResolveMethodIndex(methodLiteral->GetMethodId(), 5474514f5e3Sopenharmony_ci (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 1>()).AsRawValue()); 5484514f5e3Sopenharmony_ci } 5494514f5e3Sopenharmony_ci CString className = ""; 5504514f5e3Sopenharmony_ci className = GetRealName(jsPandaFile, entityId, className); 5514514f5e3Sopenharmony_ci CString recordName = MethodLiteral::GetRecordName(jsPandaFile, methodId); 5524514f5e3Sopenharmony_ci 5534514f5e3Sopenharmony_ci LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor(); 5544514f5e3Sopenharmony_ci lda.EnumerateLiteralVals(literalId, [&classInfo, className] 5554514f5e3Sopenharmony_ci (const LiteralValue &value, const LiteralTag &tag) { 5564514f5e3Sopenharmony_ci switch (tag) { 5574514f5e3Sopenharmony_ci case LiteralTag::METHOD: 5584514f5e3Sopenharmony_ci case LiteralTag::GENERATORMETHOD: { 5594514f5e3Sopenharmony_ci uint32_t methodOffset = std::get<uint32_t>(value); 5604514f5e3Sopenharmony_ci classInfo.emplace(methodOffset, std::move(className)); 5614514f5e3Sopenharmony_ci break; 5624514f5e3Sopenharmony_ci } 5634514f5e3Sopenharmony_ci default: { 5644514f5e3Sopenharmony_ci break; 5654514f5e3Sopenharmony_ci } 5664514f5e3Sopenharmony_ci } 5674514f5e3Sopenharmony_ci }); 5684514f5e3Sopenharmony_ci } 5694514f5e3Sopenharmony_ci auto nextInst = bcIns.GetNext(); 5704514f5e3Sopenharmony_ci bcIns = nextInst; 5714514f5e3Sopenharmony_ci } 5724514f5e3Sopenharmony_ci }); 5734514f5e3Sopenharmony_ci } 5744514f5e3Sopenharmony_ci return classInfo; 5754514f5e3Sopenharmony_ci} 5764514f5e3Sopenharmony_ci 5774514f5e3Sopenharmony_ciCString PatchLoader::GetRealName(const JSPandaFile *jsPandaFile, EntityId entityId, CString &className) 5784514f5e3Sopenharmony_ci{ 5794514f5e3Sopenharmony_ci std::string methodName(MethodLiteral::GetMethodName(jsPandaFile, entityId)); 5804514f5e3Sopenharmony_ci size_t poiIndex = methodName.find_last_of('#'); 5814514f5e3Sopenharmony_ci ASSERT(methodName.size() > 0); 5824514f5e3Sopenharmony_ci if (poiIndex != std::string::npos && poiIndex < methodName.size() - 1 && className != "default") { 5834514f5e3Sopenharmony_ci methodName = methodName.substr(poiIndex + 1); // #...#functionName 5844514f5e3Sopenharmony_ci if (methodName.find('^') != std::string::npos) { 5854514f5e3Sopenharmony_ci poiIndex = methodName.find_last_of('^'); 5864514f5e3Sopenharmony_ci methodName = methodName.substr(0, poiIndex); // #...#functionName^1 5874514f5e3Sopenharmony_ci } 5884514f5e3Sopenharmony_ci } 5894514f5e3Sopenharmony_ci return ConvertToString(methodName); 5904514f5e3Sopenharmony_ci} 5914514f5e3Sopenharmony_ci} // namespace panda::ecmascript 592