* Copyright (c) 2022-2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ES2PANDA_UTIL_PATCHFIX_H
#define ES2PANDA_UTIL_PATCHFIX_H
#include <assembly-function.h>
#include <assembly-ins.h>
#include <assembly-literals.h>
#include <assembly-program.h>
#include <utils/arena_containers.h>
#include <util/helpers.h>
#include <util/symbolTable.h>
#include <mutex>
namespace panda::es2panda::binder {
class VariableScope;
}
namespace panda::es2panda::compiler {
class PandaGen;
}
namespace panda::es2panda::util {
enum class PatchFixKind { DUMPSYMBOLTABLE, HOTFIX, COLDFIX, HOTRELOAD, COLDRELOAD };
class PatchFix {
using LiteralBuffers = ArenaVector<std::pair<int32_t, std::vector<panda::pandasm::LiteralArray::Literal>>>;
public:
PatchFix(bool generateSymbolFile, bool generatePatch, PatchFixKind patchFixKind, const std::string &recordName,
util::SymbolTable *symbolTable)
: generateSymbolFile_(generateSymbolFile), generatePatch_(generatePatch), patchFixKind_(patchFixKind),
recordName_(recordName),
symbolTable_(symbolTable),
allocator_(SpaceType::SPACE_TYPE_COMPILER, nullptr, true),
topScopeLexEnvs_(allocator_.Adapter()),
patchFuncNames_(allocator_.Adapter()),
newFuncNames_(allocator_.Adapter()),
funcDefineIns_(allocator_.Adapter()),
modifiedClassNames_(allocator_.Adapter()),
classMemberFunctions_(allocator_.Adapter()),
funcDefinedClasses_(allocator_.Adapter()),
targetApiVersion_(symbolTable->GetTargetApiVersion()),
targetApiSubVersion_(symbolTable->GetTargetApiSubVersion()) {
originFunctionInfo_ = symbolTable_->GetOriginFunctionInfo();
originModuleInfo_ = symbolTable_->GetOriginModuleInfo();
originRecordHashFunctionNames_ = symbolTable_->GetOriginRecordHashFunctionNames();
patchMain0_ = recordName_ + ".patch_main_0";
patchMain1_ = recordName_ + ".patch_main_1";
funcMain0_ = recordName_ + ".func_main_0";
}
void Finalize(panda::pandasm::Program **prog);
bool IsScopeValidToPatchLexical(binder::VariableScope *scope) const;
uint32_t GetSlotIdFromSymbolTable(const std::string &variableName);
uint32_t GetEnvSizeOfFuncMain0();
void AllocSlotfromPatchEnv(const std::string &variableName);
uint32_t GetPatchLexicalIdx(const std::string &variableName);
bool IsAdditionalVarInPatch(uint32_t slot);
void ProcessFunction(const compiler::PandaGen *pg, panda::pandasm::Function *func, LiteralBuffers &literalBuffers);
void ProcessModule(const std::string &recordName, std::vector<panda::pandasm::LiteralArray::Literal> &moduleBuffer);
void ProcessJsonContentRecord(const std::string &recordName, const std::string &jsonFileContent);
void CheckAndRestoreSpecialFunctionName(uint32_t globalIndexForSpecialFunc, std::string &funcName,
std::string recordName);
bool IsDumpSymbolTable() const;
bool IsHotFix() const;
bool IsColdFix() const;
bool IsHotReload() const;
bool IsColdReload() const;
private:
void DumpFunctionInfo(const compiler::PandaGen *pg, panda::pandasm::Function *func, LiteralBuffers &literalBuffers);
void HandleFunction(const compiler::PandaGen *pg, panda::pandasm::Function *func, LiteralBuffers &literalBuffers);
void CollectFunctionsWithDefinedClasses(std::string funcName, std::string className);
std::vector<std::pair<std::string, std::string>> GenerateFunctionAndClassHash(panda::pandasm::Function *func,
LiteralBuffers &literalBuffers);
void DumpModuleInfo(const std::string &recordName,
std::vector<panda::pandasm::LiteralArray::Literal> &moduleBuffer);
void ValidateModuleInfo(const std::string &recordName,
std::vector<panda::pandasm::LiteralArray::Literal> &moduleBuffer);
void DumpJsonContentRecInfo(const std::string &recordName, const std::string &jsonFileContent);
void ValidateJsonContentRecInfo(const std::string &recordName, const std::string &jsonFileContent);
std::string ExpandLiteral(int64_t bufferIdx, LiteralBuffers &literalBuffers);
std::string ConvertLiteralToString(std::vector<panda::pandasm::LiteralArray::Literal> &literalBuffer);
void CollectFuncDefineIns(panda::pandasm::Function *func);
void AddHeadAndTailInsForPatchFuncMain0(std::vector<panda::pandasm::InsPtr> &ins);
void AddTailInsForPatchFuncMain1(std::vector<panda::pandasm::InsPtr> &ins);
void CreateFunctionPatchMain0AndMain1(panda::pandasm::Function &patchFuncMain0,
panda::pandasm::Function &patchFuncMain1);
bool IsAnonymousOrSpecialOrDuplicateFunction(const std::string &funcName);
bool CompareLexenv(const std::string &funcName, const compiler::PandaGen *pg,
SymbolTable::OriginFunctionInfo &bytecodeInfo);
bool CompareClassHash(std::vector<std::pair<std::string, std::string>> &hashList,
SymbolTable::OriginFunctionInfo &bytecodeInfo);
void CollectClassMemberFunctions(const std::string &className, int64_t bufferIdx, LiteralBuffers &literalBuffers);
std::vector<std::string> GetLiteralMethods(int64_t bufferIdx, LiteralBuffers &literalBuffers);
void HandleModifiedClasses(panda::pandasm::Program *prog);
void HandleModifiedDefinedClassFunc(panda::pandasm::Program *prog);
int64_t GetLiteralIdxFromStringId(const std::string &stringId);
std::mutex m_;
uint32_t topScopeIdx_ {0};
bool patchError_ {false};
bool generateSymbolFile_ {false};
bool generatePatch_ {false};
PatchFixKind patchFixKind_;
std::string recordName_;
std::string funcMain0_;
std::string patchMain0_;
std::string patchMain1_;
std::stringstream errMsg_;
util::SymbolTable* symbolTable_ {nullptr};
ArenaAllocator allocator_;
ArenaUnorderedMap<std::string, util::SymbolTable::OriginFunctionInfo> *originFunctionInfo_ {nullptr};
ArenaUnorderedMap<std::string, std::string> *originModuleInfo_ {nullptr};
ArenaUnorderedMap<std::string, std::unordered_map<std::string, std::string>> *originRecordHashFunctionNames_ {
nullptr};
ArenaUnorderedMap<std::string, uint32_t> topScopeLexEnvs_;
ArenaSet<std::string> patchFuncNames_;
ArenaSet<std::string> newFuncNames_;
ArenaVector<panda::pandasm::Ins *> funcDefineIns_;
ArenaSet<std::string> modifiedClassNames_;
ArenaUnorderedMap<std::string, std::vector<std::string>> classMemberFunctions_;
ArenaUnorderedMap<std::string, std::vector<std::string>> funcDefinedClasses_;
int targetApiVersion_ {0};
std::string targetApiSubVersion_;
};
}
#endif