1/*
2 * Copyright (c) 2022 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 ES2PANDA_UTIL_PATCHFIX_H
17#define ES2PANDA_UTIL_PATCHFIX_H
18
19#include <assembly-function.h>
20#include <assembly-ins.h>
21#include <assembly-literals.h>
22#include <assembly-program.h>
23#include <libpandabase/utils/arena_containers.h>
24#include <util/helpers.h>
25#include <util/symbolTable.h>
26
27#include <mutex>
28
29namespace panda::es2panda::binder {
30class VariableScope;
31}  // namespace panda::es2panda::binder
32
33namespace panda::es2panda::compiler {
34class PandaGen;
35}  // namespace panda::es2panda::compiler
36
37namespace panda::es2panda::util {
38
39enum class PatchFixKind { DUMPSYMBOLTABLE, HOTFIX, COLDFIX, HOTRELOAD, COLDRELOAD };
40
41class PatchFix {
42    using LiteralBuffers = ArenaVector<std::pair<int32_t, std::vector<panda::pandasm::LiteralArray::Literal>>>;
43
44public:
45    PatchFix(bool generateSymbolFile, bool generatePatch, PatchFixKind patchFixKind, const std::string &recordName,
46        util::SymbolTable *symbolTable)
47        : generateSymbolFile_(generateSymbolFile), generatePatch_(generatePatch), patchFixKind_(patchFixKind),
48        recordName_(recordName),
49        symbolTable_(symbolTable),
50        allocator_(SpaceType::SPACE_TYPE_COMPILER, nullptr, true),
51        topScopeLexEnvs_(allocator_.Adapter()),
52        patchFuncNames_(allocator_.Adapter()),
53        newFuncNames_(allocator_.Adapter()),
54        funcDefineIns_(allocator_.Adapter()),
55        modifiedClassNames_(allocator_.Adapter()),
56        classMemberFunctions_(allocator_.Adapter()),
57        funcDefinedClasses_(allocator_.Adapter()),
58        targetApiVersion_(symbolTable->GetTargetApiVersion()),
59        targetApiSubVersion_(symbolTable->GetTargetApiSubVersion()) {
60            originFunctionInfo_ = symbolTable_->GetOriginFunctionInfo();
61            originModuleInfo_ = symbolTable_->GetOriginModuleInfo();
62            originRecordHashFunctionNames_ = symbolTable_->GetOriginRecordHashFunctionNames();
63            patchMain0_ = recordName_ + ".patch_main_0";
64            patchMain1_ = recordName_ + ".patch_main_1";
65            funcMain0_ = recordName_ + ".func_main_0";
66        }
67
68    void Finalize(panda::pandasm::Program **prog);
69    bool IsScopeValidToPatchLexical(binder::VariableScope *scope) const;
70    uint32_t GetSlotIdFromSymbolTable(const std::string &variableName);
71    uint32_t GetEnvSizeOfFuncMain0();
72    void AllocSlotfromPatchEnv(const std::string &variableName);
73    uint32_t GetPatchLexicalIdx(const std::string &variableName);
74    bool IsAdditionalVarInPatch(uint32_t slot);
75    void ProcessFunction(const compiler::PandaGen *pg, panda::pandasm::Function *func, LiteralBuffers &literalBuffers);
76    void ProcessModule(const std::string &recordName, std::vector<panda::pandasm::LiteralArray::Literal> &moduleBuffer);
77    void ProcessJsonContentRecord(const std::string &recordName, const std::string &jsonFileContent);
78    void CheckAndRestoreSpecialFunctionName(uint32_t globalIndexForSpecialFunc, std::string &funcName,
79        std::string recordName);
80    bool IsDumpSymbolTable() const;
81    bool IsHotFix() const;
82    bool IsColdFix() const;
83    bool IsHotReload() const;
84    bool IsColdReload() const;
85
86private:
87    void DumpFunctionInfo(const compiler::PandaGen *pg, panda::pandasm::Function *func, LiteralBuffers &literalBuffers);
88    void HandleFunction(const compiler::PandaGen *pg, panda::pandasm::Function *func, LiteralBuffers &literalBuffers);
89    void CollectFunctionsWithDefinedClasses(std::string funcName, std::string className);
90    std::vector<std::pair<std::string, std::string>> GenerateFunctionAndClassHash(panda::pandasm::Function *func,
91        LiteralBuffers &literalBuffers);
92    void DumpModuleInfo(const std::string &recordName,
93        std::vector<panda::pandasm::LiteralArray::Literal> &moduleBuffer);
94    void ValidateModuleInfo(const std::string &recordName,
95        std::vector<panda::pandasm::LiteralArray::Literal> &moduleBuffer);
96    void DumpJsonContentRecInfo(const std::string &recordName, const std::string &jsonFileContent);
97    void ValidateJsonContentRecInfo(const std::string &recordName, const std::string &jsonFileContent);
98
99    std::string ExpandLiteral(int64_t bufferIdx, LiteralBuffers &literalBuffers);
100    std::string ConvertLiteralToString(std::vector<panda::pandasm::LiteralArray::Literal> &literalBuffer);
101    void CollectFuncDefineIns(panda::pandasm::Function *func);
102    void AddHeadAndTailInsForPatchFuncMain0(std::vector<panda::pandasm::Ins> &ins);
103    void AddTailInsForPatchFuncMain1(std::vector<panda::pandasm::Ins> &ins);
104    void CreateFunctionPatchMain0AndMain1(panda::pandasm::Function &patchFuncMain0,
105        panda::pandasm::Function &patchFuncMain1);
106    bool IsAnonymousOrSpecialOrDuplicateFunction(const std::string &funcName);
107    bool CompareLexenv(const std::string &funcName, const compiler::PandaGen *pg,
108        SymbolTable::OriginFunctionInfo &bytecodeInfo);
109    bool CompareClassHash(std::vector<std::pair<std::string, std::string>> &hashList,
110        SymbolTable::OriginFunctionInfo &bytecodeInfo);
111    void CollectClassMemberFunctions(const std::string &className, int64_t bufferIdx, LiteralBuffers &literalBuffers);
112    std::vector<std::string> GetLiteralMethods(int64_t bufferIdx, LiteralBuffers &literalBuffers);
113    void HandleModifiedClasses(panda::pandasm::Program *prog);
114    void HandleModifiedDefinedClassFunc(panda::pandasm::Program *prog);
115    int64_t GetLiteralIdxFromStringId(const std::string &stringId);
116
117    std::mutex m_;
118    uint32_t topScopeIdx_ {0};
119    bool patchError_ {false};
120    bool generateSymbolFile_ {false};
121    bool generatePatch_ {false};
122    PatchFixKind patchFixKind_;
123    std::string recordName_;
124    std::string funcMain0_;
125    std::string patchMain0_;  // stores newly added function define ins, runtime will execute
126    std::string patchMain1_;  // stores modified function and class define ins, runtime will scan but not execute
127
128    util::SymbolTable* symbolTable_ {nullptr};
129    ArenaAllocator allocator_;
130    ArenaUnorderedMap<std::string, util::SymbolTable::OriginFunctionInfo> *originFunctionInfo_ {nullptr};
131    ArenaUnorderedMap<std::string, std::string> *originModuleInfo_ {nullptr};
132    ArenaUnorderedMap<std::string, std::unordered_map<std::string, std::string>> *originRecordHashFunctionNames_ {
133        nullptr};
134    ArenaUnorderedMap<std::string, uint32_t> topScopeLexEnvs_;
135    ArenaSet<std::string> patchFuncNames_;
136    ArenaSet<std::string> newFuncNames_;
137    ArenaVector<panda::pandasm::Ins> funcDefineIns_;
138    ArenaSet<std::string> modifiedClassNames_;
139    ArenaUnorderedMap<std::string, std::vector<std::string>> classMemberFunctions_;
140    ArenaUnorderedMap<std::string, std::vector<std::string>> funcDefinedClasses_;
141    int targetApiVersion_ {0};
142    std::string targetApiSubVersion_;
143};
144
145} // namespace panda::es2panda::util
146#endif // ES2PANDA_UTIL_PATCHFIX_H
147