• 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     os::memory::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     os::memory::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     os::memory::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     return loadedStub_->Load();
101 }
102 
Dump() const103 void AnFileDataManager::Dump() const
104 {
105     loadedStub_->Dump();
106     for (const auto& an : loadedAn_) {
107         an->Dump();
108     }
109 }
110 
UnsafeLoadFromAOT(const std::string & fileName)111 bool AnFileDataManager::UnsafeLoadFromAOT(const std::string &fileName)
112 {
113     // note: This method is not thread-safe
114     // need to ensure that the instance of AnFileDataManager has been locked before use
115     std::shared_ptr<AnFileInfo> info = std::make_shared<AnFileInfo>(AnFileInfo());
116     if (!info->Load(fileName)) {
117         return false;
118     }
119     std::string anBasename = JSFilePath::GetBaseName(fileName);
120     anFileNameToIndexMap_.insert({anBasename, loadedAn_.size()});
121     loadedAn_.emplace_back(info);
122     return true;
123 }
124 
UnSafeGetFileInfoIndex(const std::string & fileName)125 uint32_t AnFileDataManager::UnSafeGetFileInfoIndex(const std::string &fileName)
126 {
127     auto iter = anFileNameToIndexMap_.find(fileName);
128     if (iter == anFileNameToIndexMap_.end()) {
129         return INVALID_INDEX;
130     }
131     return anFileNameToIndexMap_.at(fileName);
132 }
133 
SafeGetFileInfoIndex(const std::string & fileName)134 uint32_t AnFileDataManager::SafeGetFileInfoIndex(const std::string &fileName)
135 {
136     os::memory::ReadLockHolder lock(lock_);
137     return UnSafeGetFileInfoIndex(fileName);
138 }
139 
SafeGetAnFileInfo(uint32_t index)140 std::shared_ptr<AnFileInfo> AnFileDataManager::SafeGetAnFileInfo(uint32_t index)
141 {
142     os::memory::ReadLockHolder lock(lock_);
143     return UnSafeGetAnFileInfo(index);
144 }
145 
SafeGetStubFileInfo()146 std::shared_ptr<StubFileInfo> AnFileDataManager::SafeGetStubFileInfo()
147 {
148     os::memory::ReadLockHolder lock(lock_);
149     return loadedStub_;
150 }
151 
152 // Using for cpuprofiler to check if the ReadLock can be held in signal handler, to avoid the reentrancy deadlock.
SafeTryReadLock()153 bool AnFileDataManager::SafeTryReadLock()
154 {
155     // Try to acquire the lock when the signal callback starts to execute. At this time, the vm thread is interrupted,
156     // so the status of whether the lock is held by vm thread will not change until the signal callback ends. If the
157     // attempt is successful, it means that the current vm thread does not hold the lock,the reentrancy problem will
158     // not occur in the callback.
159     if (lock_.TryReadLock()) {
160         lock_.Unlock();
161         return true;
162     }
163     return false;
164 }
165 
SafeInsideStub(uintptr_t pc)166 bool AnFileDataManager::SafeInsideStub(uintptr_t pc)
167 {
168     os::memory::ReadLockHolder lock(lock_);
169     if (loadedStub_ == nullptr) {
170         LOG_COMPILER(ERROR) << "SafeInsideStub: The stub file is not loaded.";
171         return false;
172     }
173 
174     uint64_t stubStartAddr = loadedStub_->GetAsmStubAddr();
175     uint64_t stubEndAddr = stubStartAddr + loadedStub_->GetAsmStubSize();
176     if (pc >= stubStartAddr && pc <= stubEndAddr) {
177         return true;
178     }
179 
180     const std::vector<ModuleSectionDes> &des = loadedStub_->GetCodeUnits();
181     for (const auto &curDes : des) {
182         if (curDes.ContainCode(pc)) {
183             return true;
184         }
185     }
186 
187     return false;
188 }
189 
SafeInsideAOT(uintptr_t pc)190 bool AnFileDataManager::SafeInsideAOT(uintptr_t pc)
191 {
192     os::memory::ReadLockHolder lock(lock_);
193     for (auto &info : loadedAn_) {
194         const std::vector<ModuleSectionDes> &des = info->GetCodeUnits();
195         for (const auto &curDes : des) {
196             if (curDes.ContainCode(pc)) {
197                 return true;
198             }
199         }
200     }
201     return false;
202 }
203 
SafeCalCallSiteInfo(uintptr_t retAddr)204 AOTFileInfo::CallSiteInfo AnFileDataManager::SafeCalCallSiteInfo(uintptr_t retAddr)
205 {
206     os::memory::ReadLockHolder lock(lock_);
207     AOTFileInfo::CallSiteInfo callsiteInfo;
208 
209     bool ans = false;
210     if (loadedStub_ != nullptr) {
211         ans = loadedStub_->CalCallSiteInfo(retAddr, callsiteInfo);
212     }
213     if (ans) {
214         return callsiteInfo;
215     }
216     // aot
217     for (auto &info : loadedAn_) {
218         ans = info->CalCallSiteInfo(retAddr, callsiteInfo);
219         if (ans) {
220             return callsiteInfo;
221         }
222     }
223     return callsiteInfo;
224 }
225 }  // namespace panda::ecmascript
226