1 /**
2 * Copyright (c) 2021-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 #include "runtime/include/file_manager.h"
17 #include "runtime/include/runtime.h"
18 #include "libpandabase/os/filesystem.h"
19
20 namespace panda {
21
LoadAbcFile(std::string_view location,panda_file::File::OpenMode open_mode)22 bool FileManager::LoadAbcFile(std::string_view location, panda_file::File::OpenMode open_mode)
23 {
24 auto pf = panda_file::OpenPandaFile(location, "", open_mode);
25 if (pf == nullptr) {
26 LOG(ERROR, PANDAFILE) << "Load panda file failed: " << location;
27 return false;
28 }
29 auto runtime = Runtime::GetCurrent();
30 if (Runtime::GetOptions().IsEnableAn()) {
31 TryLoadAnFileForLocation(location);
32 auto aot_file = runtime->GetClassLinker()->GetAotManager()->FindPandaFile(std::string(location));
33 if (aot_file != nullptr) {
34 pf->SetClassHashTable(aot_file->GetClassHashTable());
35 }
36 }
37 runtime->GetClassLinker()->AddPandaFile(std::move(pf));
38 return true;
39 }
40
TryLoadAnFileForLocation(std::string_view panda_file_location)41 bool FileManager::TryLoadAnFileForLocation(std::string_view panda_file_location)
42 {
43 auto an_location = FileManager::ResolveAnFilePath(panda_file_location);
44 if (an_location.empty()) {
45 return true;
46 }
47 auto res = FileManager::LoadAnFile(an_location, false);
48 if (res && res.Value()) {
49 LOG(INFO, PANDAFILE) << "Successfully load .an file for '" << panda_file_location << "': '" << an_location
50 << "'";
51 } else if (!res) {
52 LOG(INFO, PANDAFILE) << "Failed to load AOT file: '" << an_location << "': " << res.Error();
53 } else {
54 LOG(INFO, PANDAFILE) << "Failed to load '" << an_location << "' with unknown reason";
55 }
56 return true;
57 }
58
LoadAnFile(std::string_view an_location,bool force)59 Expected<bool, std::string> FileManager::LoadAnFile(std::string_view an_location, bool force)
60 {
61 PandaRuntimeInterface runtime_iface;
62 auto runtime = Runtime::GetCurrent();
63 auto gc_type = Runtime::GetGCType(Runtime::GetOptions(), plugins::RuntimeTypeToLang(runtime->GetRuntimeType()));
64 ASSERT(gc_type != panda::mem::GCType::INVALID_GC);
65 auto real_an_file_path = os::GetAbsolutePath(an_location);
66 return runtime->GetClassLinker()->GetAotManager()->AddFile(real_an_file_path, &runtime_iface,
67 static_cast<uint32_t>(gc_type), force);
68 }
69
ResolveAnFilePath(std::string_view abc_path)70 PandaString FileManager::ResolveAnFilePath(std::string_view abc_path)
71 {
72 // check whether an aot version of this file already exist
73 // Todo(Wentao):
74 // 1. search ark native file file base on ARCH info from runtime.
75 // 2. allow searching an file out of same path of ark bytecode file.
76 const PandaString &an_path_suffix = ".an";
77 PandaString::size_type pos_start = abc_path.find_last_of('/');
78 PandaString::size_type pos_end = abc_path.find_last_of('.');
79 if (pos_start != std::string_view::npos && pos_end != std::string_view::npos) {
80 LOG(DEBUG, PANDAFILE) << "current abc file path: " << abc_path;
81 PandaString abc_path_prefix = PandaString(abc_path.substr(0, pos_start));
82 PandaString an_file_path =
83 abc_path_prefix + PandaString(abc_path.substr(pos_start, pos_end - pos_start)) + an_path_suffix;
84
85 const char *filename = an_file_path.c_str();
86 if (access(filename, F_OK) == 0) {
87 return an_file_path;
88 }
89 }
90 LOG(DEBUG, PANDAFILE) << "There is no corresponding .an file for " << abc_path;
91 return "";
92 }
93
94 } // namespace panda
95