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