• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 ECMASCRIPT_PATCH_PATCH_LOADER_H
17 #define ECMASCRIPT_PATCH_PATCH_LOADER_H
18 
19 #include "ecmascript/jspandafile/js_pandafile.h"
20 #include "ecmascript/js_tagged_value.h"
21 #include "ecmascript/js_thread.h"
22 #include "ecmascript/mem/c_containers.h"
23 #include "ecmascript/napi/include/jsnapi.h"
24 
25 namespace panda::ecmascript {
26 using PatchErrorCode = panda::JSNApi::PatchErrorCode;
27 using JSRecordInfo = JSPandaFile::JSRecordInfo;
28 using LiteralDataAccessor = panda_file::LiteralDataAccessor;
29 using LiteralValue = panda_file::LiteralDataAccessor::LiteralValue;
30 using LiteralTag = panda_file::LiteralTag;
31 class ConstantPool;
32 
33 struct BaseMethodIndex {
34     uint32_t constpoolNum {UINT32_MAX};
35     uint32_t constpoolIndex {UINT32_MAX};
36     uint32_t literalIndex {UINT32_MAX};
37     struct Hash {
operatorBaseMethodIndex::Hash38         std::size_t operator()(const BaseMethodIndex &baseMethodIndex) const
39         {
40             return std::hash<uint32_t>{}(baseMethodIndex.constpoolNum) ^ (std::hash<uint32_t>{}(
41                 baseMethodIndex.constpoolIndex) << 1) ^ std::hash<uint32_t>{}(baseMethodIndex.literalIndex);
42         }
43     };
44 
45     bool operator==(const BaseMethodIndex &baseMethodIndex) const
46     {
47         return constpoolNum == baseMethodIndex.constpoolNum && constpoolIndex == baseMethodIndex.constpoolIndex &&
48             literalIndex == baseMethodIndex.literalIndex;
49     }
50 };
51 
52 struct PatchMethodIndex {
53     CString recordName;
54     CString className;
55     CString methodName;
56     struct Hash {
operatorPatchMethodIndex::Hash57         std::size_t operator()(const PatchMethodIndex &patchMethodIndex) const
58         {
59             return std::hash<CString>{}(patchMethodIndex.recordName) ^
60                 std::hash<CString>{}(patchMethodIndex.className) ^ std::hash<CString>{}(patchMethodIndex.methodName);
61         }
62     };
63 
64     bool operator==(const PatchMethodIndex &patchMethodIndex) const
65     {
66         return recordName == patchMethodIndex.recordName && className == patchMethodIndex.className &&
67             methodName == patchMethodIndex.methodName;
68     }
69 };
70 
71 struct PatchInfo {
72     // patch file name.
73     CString patchFileName;
74     // patch methodLiterals for load patch, <recordName, <methodName, MethodLiteral>>
75     CUnorderedMap<PatchMethodIndex, MethodLiteral*, PatchMethodIndex::Hash> patchMethodLiterals;
76     // base method info for unload patch, <BaseMethodIndex, base MethodLiteral>
77     CUnorderedMap<BaseMethodIndex, MethodLiteral *, BaseMethodIndex::Hash> baseMethodInfo;
78     // save base constpool in global for avoid gc.
79     CVector<JSHandle<JSTaggedValue>> baseConstpools;
80     // patch replaced recordNames.
81     CUnorderedSet<CString> replacedRecordNames;
82 };
83 
84 enum class StageOfHotReload : int32_t {
85     BEGIN_EXECUTE_PATCHMAIN = -1, // -1: For intercepting Evaluate()
86     INITIALIZE_STAGE_OF_HOTRELOAD, // 0 : initialize stageOfHotreload_ in ecma_context.h
87     LOAD_END_EXECUTE_PATCHMAIN, // 1: for Interceptint get module var
88     UNLOAD_END_EXECUTE_PATCHMAIN // 2 :for execute abc normally
89 };
90 
91 class PatchLoader {
92 public:
93     PatchLoader() = default;
94     ~PatchLoader() = default;
95     NO_COPY_SEMANTIC(PatchLoader);
96     NO_MOVE_SEMANTIC(PatchLoader);
97 
98     static PatchErrorCode LoadPatchInternal(JSThread *thread, const JSPandaFile *baseFile,
99                                             const JSPandaFile *patchFile, PatchInfo &patchInfo,
100                                             const CMap<uint32_t, CString> &baseClassInfo);
101     static PatchErrorCode UnloadPatchInternal(JSThread *thread, const CString &patchFileName,
102                                               const CString &baseFileName, PatchInfo &patchInfo);
103 
104     static MethodLiteral *FindSameMethod(PatchInfo &patchInfo, const JSPandaFile *baseFile,
105                                          EntityId baseMethodId, const CMap<uint32_t, CString> &baseClassInfo);
106     static void ExecuteFuncOrPatchMain(
107         JSThread *thread, const JSPandaFile *jsPandaFile, const PatchInfo &patchInfo, bool loadPatch = true);
108     static CMap<uint32_t, CString> CollectClassInfo(const JSPandaFile *jsPandaFile);
109 
110 private:
111     static PatchInfo GeneratePatchInfo(const JSPandaFile *patchFile);
112     static CString GetRealName(const JSPandaFile *jsPandaFile, EntityId entityId, CString &className);
113     static void FindAndReplaceSameMethod(JSThread *thread,
114                                          const JSPandaFile *baseFile,
115                                          const JSPandaFile *patchFile,
116                                          PatchInfo &patchInfo,
117                                          const CMap<uint32_t, CString> &baseClassInfo);
118     static void SaveBaseMethodInfo(PatchInfo &patchInfo, const JSPandaFile *baseFile,
119                                    EntityId baseMethodId, const BaseMethodIndex &indexs);
120     static void ReplaceMethod(JSThread *thread,
121                               Method *destMethod,
122                               MethodLiteral *srcMethodLiteral,
123                               JSTaggedValue srcConstpool);
124 
125     static void ClearPatchInfo(JSThread *thread, const CString &patchFileName);
126 
127     static void ReplaceModuleOfMethod(JSThread *thread, const JSPandaFile *baseFile, PatchInfo &patchInfo);
128     static Method *GetPatchMethod(JSThread *thread,
129         const BaseMethodIndex &methodIndex, const ConstantPool *baseConstpool);
130 };
131 }  // namespace panda::ecmascript
132 #endif // ECMASCRIPT_PATCH_PATCH_LOADER_H
133