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 #include "ecmascript/pgo_profiler/pgo_profiler_loader.h"
17
18 #include "ecmascript/log_wrapper.h"
19 #include "ecmascript/pgo_profiler/pgo_profiler_info.h"
20 #include "ecmascript/platform/file.h"
21
22 namespace panda::ecmascript {
Load()23 bool PGOProfilerLoader::Load()
24 {
25 if (isLoaded_) {
26 Clear();
27 }
28 if (!LoadAPBinaryFile()) {
29 return false;
30 }
31 void *addr = fileMapAddr_.GetOriginAddr();
32
33 if (!PGOProfilerHeader::ParseFromBinary(addr, &header_)) {
34 UnLoadAPBinaryFile();
35 LOG_ECMA(ERROR) << "Parse profiler header failed";
36 return false;
37 }
38 pandaFileInfos_.ParseFromBinary(addr, header_->GetPandaInfoSection());
39 if (!recordSimpleInfos_) {
40 recordSimpleInfos_ = std::make_unique<PGORecordSimpleInfos>(hotnessThreshold_);
41 }
42 recordSimpleInfos_->ParseFromBinary(addr, header_->GetRecordInfoSection());
43 UnLoadAPBinaryFile();
44
45 isLoaded_ = true;
46 return true;
47 }
48
Verify(uint32_t checksum)49 bool PGOProfilerLoader::Verify(uint32_t checksum)
50 {
51 if (!isLoaded_) {
52 return false;
53 }
54 isVerifySuccess_ = pandaFileInfos_.CheckSum(checksum);
55 return isVerifySuccess_;
56 }
57
LoadAndVerify(uint32_t checksum)58 bool PGOProfilerLoader::LoadAndVerify(uint32_t checksum)
59 {
60 // The file does not exist. Enter full compiler mode.
61 if (inPath_.empty()) {
62 LOG_ECMA(INFO) << "When the file is empty. Enter full compiler mode.";
63 Clear();
64 return true;
65 }
66 if (Load() && Verify(checksum)) {
67 return true;
68 }
69 return false;
70 }
71
LoadFull()72 bool PGOProfilerLoader::LoadFull()
73 {
74 if (isLoaded_) {
75 Clear();
76 }
77 if (!LoadAPBinaryFile()) {
78 return false;
79 }
80 void *addr = fileMapAddr_.GetOriginAddr();
81
82 if (!PGOProfilerHeader::ParseFromBinary(addr, &header_)) {
83 UnLoadAPBinaryFile();
84 LOG_ECMA(ERROR) << "Parse profiler header failed";
85 return false;
86 }
87 pandaFileInfos_.ParseFromBinary(addr, header_->GetPandaInfoSection());
88 if (!recordDetailInfos_) {
89 recordDetailInfos_ = std::make_unique<PGORecordDetailInfos>(hotnessThreshold_);
90 }
91 recordDetailInfos_->ParseFromBinary(addr, header_->GetRecordInfoSection());
92
93 isLoaded_ = true;
94 return true;
95 }
96
SaveAPTextFile(const std::string & outPath)97 bool PGOProfilerLoader::SaveAPTextFile(const std::string &outPath)
98 {
99 if (!isLoaded_) {
100 return false;
101 }
102 std::string realOutPath;
103 if (!RealPath(outPath, realOutPath, false)) {
104 return false;
105 }
106 std::ofstream fileStream(realOutPath.c_str());
107 if (!fileStream.is_open()) {
108 LOG_ECMA(ERROR) << "The file path(" << realOutPath << ") open failure!";
109 return false;
110 }
111
112 if (!header_->ProcessToText(fileStream)) {
113 return false;
114 }
115 pandaFileInfos_.ProcessToText(fileStream);
116 recordDetailInfos_->ProcessToText(fileStream);
117 return true;
118 }
119
LoadAPBinaryFile()120 bool PGOProfilerLoader::LoadAPBinaryFile()
121 {
122 std::string realPath;
123 if (!RealPath(inPath_, realPath)) {
124 return false;
125 }
126
127 static const std::string endString = ".ap";
128 if (realPath.compare(realPath.length() - endString.length(), endString.length(), endString)) {
129 LOG_ECMA(ERROR) << "The file path( " << realPath << ") does not end with .ap";
130 return false;
131 }
132 LOG_ECMA(INFO) << "Load profiler from file:" << realPath;
133 fileMapAddr_ = FileMap(realPath.c_str(), FILE_RDONLY, PAGE_PROT_READ);
134 if (fileMapAddr_.GetOriginAddr() == nullptr) {
135 LOG_ECMA(ERROR) << "File mmap failed";
136 return false;
137 }
138 return true;
139 }
140
UnLoadAPBinaryFile()141 void PGOProfilerLoader::UnLoadAPBinaryFile()
142 {
143 if (fileMapAddr_.GetOriginAddr() != nullptr && fileMapAddr_.GetSize() > 0) {
144 FileUnMap(fileMapAddr_);
145 fileMapAddr_.Reset();
146 }
147 }
148
Clear()149 void PGOProfilerLoader::Clear()
150 {
151 if (isLoaded_) {
152 UnLoadAPBinaryFile();
153 isVerifySuccess_ = true;
154 hotnessThreshold_ = 0;
155 PGOProfilerHeader::Destroy(&header_);
156 pandaFileInfos_.Clear();
157 if (recordDetailInfos_) {
158 recordDetailInfos_->Clear();
159 }
160 if (recordSimpleInfos_) {
161 recordSimpleInfos_->Clear();
162 }
163 isLoaded_ = false;
164 }
165 }
166
Match(const CString & recordName,EntityId methodId)167 bool PGOProfilerLoader::Match(const CString &recordName, EntityId methodId)
168 {
169 if (!isLoaded_) {
170 return true;
171 }
172 if (!isVerifySuccess_) {
173 return false;
174 }
175 return recordSimpleInfos_->Match(recordName, methodId);
176 }
177 } // namespace panda::ecmascript
178