• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 #include "aot_manager.h"
17 #include "os/filesystem.h"
18 #include "events/events.h"
19 
20 namespace ark::compiler {
21 class RuntimeInterface;
22 
AddFile(const std::string & fileName,RuntimeInterface * runtime,uint32_t gcType,bool force)23 Expected<bool, std::string> AotManager::AddFile(const std::string &fileName, RuntimeInterface *runtime, uint32_t gcType,
24                                                 bool force)
25 {
26     if (GetFile(fileName) != nullptr) {
27         LOG(DEBUG, AOT) << "Trying to add already existing AOT file: '" << fileName << "'";
28         return true;
29     }
30     auto aotFile = AotFile::Open(fileName, gcType);
31     if (!aotFile) {
32         EVENT_AOT_MANAGER(fileName, events::AotManagerAction::OPEN_FAILED);
33         return Unexpected("AotFile::Open failed: " + aotFile.Error());
34     }
35     if (runtime != nullptr) {
36         aotFile.Value()->PatchTable(runtime);
37         aotFile.Value()->InitializeGot(runtime);
38     }
39 
40     LOG(DEBUG, AOT) << "AOT file '" << fileName << "' has been loaded, code=" << aotFile.Value()->GetCode()
41                     << ", code_size=" << aotFile.Value()->GetCodeSize();
42     LOG(DEBUG, AOT) << "  It contains the following panda files:";
43     for (auto header : aotFile.Value()->FileHeaders()) {
44         LOG(DEBUG, AOT) << "  " << aotFile.Value()->GetString(header.fileNameStr);
45     }
46     aotFiles_.push_back(std::move(aotFile.Value()));
47     auto &aotInsertFile = aotFiles_[aotFiles_.size() - 1];
48     for (auto header : aotInsertFile->FileHeaders()) {
49         auto pfName = aotInsertFile->GetString(header.fileNameStr);
50         auto fileHeader = aotInsertFile->FindPandaFile(pfName);
51         if (force) {
52             filesMap_[pfName] = AotPandaFile(aotInsertFile.get(), fileHeader);
53         } else {
54             filesMap_.emplace(std::make_pair(pfName, AotPandaFile(aotInsertFile.get(), fileHeader)));
55         }
56     }
57     EVENT_AOT_MANAGER(fileName, events::AotManagerAction::ADDED);
58     return true;
59 }
60 
FindPandaFile(const std::string & fileName)61 const AotPandaFile *AotManager::FindPandaFile(const std::string &fileName)
62 {
63     if (fileName.empty()) {
64         return nullptr;
65     }
66     auto it = filesMap_.find(fileName);
67     if (it != filesMap_.end()) {
68         return &it->second;
69     }
70     return nullptr;
71 }
72 
GetFile(const std::string & fileName) const73 const AotFile *AotManager::GetFile(const std::string &fileName) const
74 {
75     auto res = std::find_if(aotFiles_.begin(), aotFiles_.end(),
76                             [&fileName](auto &file) { return fileName == file->GetFileName(); });
77     return res == aotFiles_.end() ? nullptr : (*res).get();
78 }
79 
80 /* We need such kind of complex print because line length of some tool is limited by 4000 characters */
FancyClassContextPrint(std::string_view context)81 static void FancyClassContextPrint(std::string_view context)
82 {
83     constexpr char DELIMITER = ':';
84     size_t start = 0;
85     size_t end = context.find(DELIMITER, start);
86     while (end != std::string::npos) {
87         LOG(ERROR, AOT) << "\t\t" << context.substr(start, end - start);
88         start = end + 1;
89         end = context.find(DELIMITER, start);
90     }
91     LOG(ERROR, AOT) << "\t\t" << context.substr(start);
92 }
93 
CheckFilesInClassContext(std::string_view context,std::string_view aotContext)94 static bool CheckFilesInClassContext(std::string_view context, std::string_view aotContext)
95 {
96     constexpr char DELIMITER = ':';
97     size_t start = 0;
98     size_t end = aotContext.find(DELIMITER, start);
99     while (end != std::string::npos) {
100         auto fileContext = aotContext.substr(start, end - start);
101         if (context.find(fileContext) == std::string::npos) {
102             LOG(ERROR, AOT) << "Cannot found file " << fileContext << " in runtime context";
103             return false;
104         }
105         start = end + 1;
106         end = aotContext.find(DELIMITER, start);
107     }
108     return true;
109 }
110 
VerifyClassHierarchy()111 void AotManager::VerifyClassHierarchy()
112 {
113     auto completeContext = bootClassContext_;
114     if (!appClassContext_.empty()) {
115         if (!completeContext.empty()) {
116             completeContext.append(":");
117         }
118         completeContext.append(appClassContext_);
119     }
120     auto verifyAot = [this, &completeContext](auto &aotFile) {
121         auto context = aotFile->IsBootPandaFile() ? bootClassContext_ : completeContext;
122         bool isCheck = true;
123 
124         if (aotFile->IsCompiledWithCha()) {
125             // Aot file context must be prefix of current runtime context
126             if (context.rfind(aotFile->GetClassContext(), 0) != 0) {
127                 isCheck = false;
128                 EVENT_AOT_MANAGER(aotFile->GetFileName(), events::AotManagerAction::CHA_VERIFY_FAILED);
129             }
130         } else {
131             // Aot file context must be contained in current runtime context
132             if (!CheckFilesInClassContext(context, aotFile->GetClassContext())) {
133                 isCheck = false;
134                 EVENT_AOT_MANAGER(aotFile->GetFileName(), events::AotManagerAction::FILE_VERIFY_FAILED);
135             }
136         }
137         if (!isCheck) {
138             auto bootPref = aotFile->IsBootPandaFile() ? "boot " : "";
139             LOG(ERROR, AOT) << "Cannot use " << bootPref << "AOT file '" << aotFile->GetFileName() << '\'';
140             LOG(ERROR, AOT) << "\tRuntime " << bootPref << "class context: ";
141             FancyClassContextPrint(context);
142             LOG(ERROR, AOT) << "\tAOT class context: ";
143             FancyClassContextPrint(aotFile->GetClassContext());
144             LOG(FATAL, AOT) << "Aborting due to mismatched class hierarchy";
145             return true;
146         }
147         EVENT_AOT_MANAGER(aotFile->GetFileName(), events::AotManagerAction::VERIFIED);
148         return false;
149     };
150 
151     for (auto &curAotFile : aotFiles_) {
152         verifyAot(curAotFile);
153     }
154 }
155 
RegisterAotStringRoot(ObjectHeader ** slot,bool isYoung)156 void AotManager::RegisterAotStringRoot(ObjectHeader **slot, bool isYoung)
157 {
158     os::memory::LockHolder lock(aotStringRootsLock_);
159     aotStringGcRoots_.push_back(slot);
160     // Atomic with acquire order reason: data race with aot_string_gc_roots_count_ with dependecies on reads after the
161     // load which should become visible
162     size_t rootsCount = aotStringGcRootsCount_.load(std::memory_order_acquire);
163     if (aotStringYoungSet_.size() <= rootsCount / MASK_WIDTH) {
164         aotStringYoungSet_.push_back(0);
165     }
166     if (isYoung) {
167         hasYoungAotStringRefs_ = true;
168         aotStringYoungSet_[rootsCount / MASK_WIDTH] |= 1ULL << (rootsCount % MASK_WIDTH);
169     }
170     // Atomic with acq_rel order reason: data race with aot_string_gc_roots_count_ with dependecies on reads after the
171     // load and on writes before the store
172     aotStringGcRootsCount_.fetch_add(1, std::memory_order_acq_rel);
173 }
174 
operator ()(const panda_file::File & pf)175 bool AotClassContextCollector::operator()(const panda_file::File &pf)
176 {
177     if (!acc_->empty()) {
178         acc_->append(":");
179     }
180     if (useAbsPath_) {
181         acc_->append(os::GetAbsolutePath(pf.GetFilename()));
182     } else {
183         acc_->append(pf.GetFilename());
184     }
185     acc_->append("*");
186     acc_->append(pf.GetPaddedChecksum());
187     return true;
188 }
189 
190 }  // namespace ark::compiler
191