• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 #include "ecmascript/compiler/aot_file/an_file_data_manager.h"
16 #include "ecmascript/js_file_path.h"
17 #include "ecmascript/platform/file.h"
18 
19 namespace panda::ecmascript {
GetInstance()20 AnFileDataManager *AnFileDataManager::GetInstance()
21 {
22     static AnFileDataManager *anFileDataManager = new AnFileDataManager();
23     return anFileDataManager;
24 }
25 
~AnFileDataManager()26 AnFileDataManager::~AnFileDataManager()
27 {
28     SafeDestroyAllData();
29 }
30 
DestroyFileMapMem(MemMap & fileMapMem)31 void AnFileDataManager::DestroyFileMapMem(MemMap &fileMapMem)
32 {
33     if (fileMapMem.GetOriginAddr() != nullptr && fileMapMem.GetSize() > 0) {
34         FileUnMap(fileMapMem);
35         fileMapMem.Reset();
36     }
37 }
38 
SafeDestroyAllData()39 void AnFileDataManager::SafeDestroyAllData()
40 {
41     WriteLockHolder lock(lock_);
42     if (loadedStub_ != nullptr) {
43         ExecutedMemoryAllocator::DestroyBuf(loadedStub_->GetStubsMem());
44         loadedStub_ = nullptr;
45     }
46 
47     for (auto &iter : loadedAn_) {
48         DestroyFileMapMem(iter->GetFileMapMem());
49     }
50     loadedAn_.clear();
51     anFileNameToIndexMap_.clear();
52 }
53 
SafeDestroyAnData(const std::string & fileName)54 void AnFileDataManager::SafeDestroyAnData(const std::string &fileName)
55 {
56     WriteLockHolder lock(lock_);
57     std::string anBasename = JSFilePath::GetBaseName(fileName);
58     auto index = UnSafeGetFileInfoIndex(anBasename);
59     if (index == INVALID_INDEX) {
60         return;
61     }
62     auto info = UnSafeGetAnFileInfo(index);
63     info->Destroy();
64 }
65 
SafeLoad(const std::string & fileName,Type type)66 bool AnFileDataManager::SafeLoad(const std::string &fileName, Type type)
67 {
68     WriteLockHolder lock(lock_);
69     if (type == Type::STUB) {
70         if (loadedStub_ != nullptr) {
71             return true;
72         }
73         return UnsafeLoadFromStub();
74     } else {
75         const std::shared_ptr<const AOTFileInfo> aotFileInfo = UnsafeFind(fileName);
76         if (aotFileInfo != nullptr) {
77             return true;
78         }
79         return UnsafeLoadFromAOT(fileName);
80     }
81 }
82 
UnsafeFind(const std::string & fileName) const83 std::shared_ptr<AnFileInfo> AnFileDataManager::UnsafeFind(const std::string &fileName) const
84 {
85     // note: This method is not thread-safe
86     // need to ensure that the instance of AnFileDataManager has been locked before use
87     const auto iter = anFileNameToIndexMap_.find(fileName);
88     if (iter == anFileNameToIndexMap_.end()) {
89         return nullptr;
90     }
91     uint32_t index = iter->second;
92     return loadedAn_.at(index);
93 }
94 
UnsafeLoadFromStub()95 bool AnFileDataManager::UnsafeLoadFromStub()
96 {
97     // note: This method is not thread-safe
98     // need to ensure that the instance of AnFileDataManager has been locked before use
99     loadedStub_ = std::make_shared<StubFileInfo>(StubFileInfo());
100 #if defined(PANDA_TARGET_OHOS)
101     return loadedStub_->MmapLoad();
102 #else
103     return loadedStub_->Load();
104 #endif
105 }
106 
Dump() const107 void AnFileDataManager::Dump() const
108 {
109     loadedStub_->Dump();
110     for (const auto& an : loadedAn_) {
111         an->Dump();
112     }
113 }
114 
UnsafeLoadFromAOT(const std::string & fileName)115 bool AnFileDataManager::UnsafeLoadFromAOT(const std::string &fileName)
116 {
117     // note: This method is not thread-safe
118     // need to ensure that the instance of AnFileDataManager has been locked before use
119     std::shared_ptr<AnFileInfo> info = std::make_shared<AnFileInfo>(AnFileInfo());
120     if (!info->Load(fileName)) {
121         return false;
122     }
123     std::string anBasename = JSFilePath::GetBaseName(fileName);
124     anFileNameToIndexMap_.insert({anBasename, loadedAn_.size()});
125     loadedAn_.emplace_back(info);
126     return true;
127 }
128 
UnSafeGetFileInfoIndex(const std::string & fileName)129 uint32_t AnFileDataManager::UnSafeGetFileInfoIndex(const std::string &fileName)
130 {
131     auto iter = anFileNameToIndexMap_.find(fileName);
132     if (iter == anFileNameToIndexMap_.end()) {
133         return INVALID_INDEX;
134     }
135     return anFileNameToIndexMap_.at(fileName);
136 }
137 
SafeGetFileInfoIndex(const std::string & fileName)138 uint32_t AnFileDataManager::SafeGetFileInfoIndex(const std::string &fileName)
139 {
140     ReadLockHolder lock(lock_);
141     return UnSafeGetFileInfoIndex(fileName);
142 }
143 
SafeGetAnFileInfo(uint32_t index)144 std::shared_ptr<AnFileInfo> AnFileDataManager::SafeGetAnFileInfo(uint32_t index)
145 {
146     ReadLockHolder lock(lock_);
147     return UnSafeGetAnFileInfo(index);
148 }
149 
SafeGetStubFileInfo()150 std::shared_ptr<StubFileInfo> AnFileDataManager::SafeGetStubFileInfo()
151 {
152     ReadLockHolder lock(lock_);
153     return loadedStub_;
154 }
155 
156 // Using for cpuprofiler to check if the ReadLock can be held in signal handler, to avoid the reentrancy deadlock.
SafeTryReadLock()157 bool AnFileDataManager::SafeTryReadLock()
158 {
159     // Try to acquire the lock when the signal callback starts to execute. At this time, the vm thread is interrupted,
160     // so the status of whether the lock is held by vm thread will not change until the signal callback ends. If the
161     // attempt is successful, it means that the current vm thread does not hold the lock,the reentrancy problem will
162     // not occur in the callback.
163     if (lock_.TryReadLock()) {
164         lock_.Unlock();
165         return true;
166     }
167     return false;
168 }
169 
SafeInsideStub(uintptr_t pc)170 bool AnFileDataManager::SafeInsideStub(uintptr_t pc)
171 {
172     ReadLockHolder lock(lock_);
173     if (loadedStub_ == nullptr) {
174         LOG_COMPILER(ERROR) << "SafeInsideStub: The stub file is not loaded.";
175         return false;
176     }
177 
178     uint64_t stubStartAddr = loadedStub_->GetAsmStubAddr();
179     uint64_t stubEndAddr = stubStartAddr + loadedStub_->GetAsmStubSize();
180     if (pc >= stubStartAddr && pc <= stubEndAddr) {
181         return true;
182     }
183 
184     const std::vector<ModuleSectionDes> &des = loadedStub_->GetCodeUnits();
185     for (const auto &curDes : des) {
186         if (curDes.ContainCode(pc)) {
187             return true;
188         }
189     }
190 
191     return false;
192 }
193 
SafeInsideAOT(uintptr_t pc)194 bool AnFileDataManager::SafeInsideAOT(uintptr_t pc)
195 {
196     ReadLockHolder lock(lock_);
197     for (auto &info : loadedAn_) {
198         const std::vector<ModuleSectionDes> &des = info->GetCodeUnits();
199         for (const auto &curDes : des) {
200             if (curDes.ContainCode(pc)) {
201                 return true;
202             }
203         }
204     }
205     return false;
206 }
207 
SafeCalCallSiteInfo(uintptr_t retAddr)208 AOTFileInfo::CallSiteInfo AnFileDataManager::SafeCalCallSiteInfo(uintptr_t retAddr)
209 {
210     ReadLockHolder lock(lock_);
211     AOTFileInfo::CallSiteInfo callsiteInfo;
212 
213     bool ans = false;
214     if (loadedStub_ != nullptr) {
215         ans = loadedStub_->CalCallSiteInfo(retAddr, callsiteInfo);
216     }
217     if (ans) {
218         return callsiteInfo;
219     }
220     // aot
221     for (auto &info : loadedAn_) {
222         ans = info->CalCallSiteInfo(retAddr, callsiteInfo);
223         if (ans) {
224             return callsiteInfo;
225         }
226     }
227     return callsiteInfo;
228 }
229 }  // namespace panda::ecmascript
230