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 16#include "ecmascript/pgo_profiler/pgo_profiler_manager.h" 17#include <fstream> 18 19#include "ecmascript/platform/file.h" 20namespace panda::ecmascript::pgo { 21namespace { 22 constexpr int32_t PGO_SAVING_SIGNAL = 50; 23} // namespace 24 25PGOProfilerManager* PGOProfilerManager::GetInstance() 26{ 27 static PGOProfilerManager* instance = new PGOProfilerManager(); 28 return instance; 29} 30 31bool PGOProfilerManager::MergeApFiles(const std::string &inFiles, const std::string &outPath, uint32_t hotnessThreshold, 32 ApGenMode mode) 33{ 34 arg_list_t apFileNames = base::StringHelper::SplitString(inFiles, GetFileDelimiter()); 35 PGOProfilerEncoder merger(outPath, hotnessThreshold, mode); 36 if (!merger.InitializeData()) { 37 LOG_ECMA(ERROR) << "PGO Profiler encoder initialized failed. outPath: " << outPath 38 << " ,hotnessThreshold: " << hotnessThreshold; 39 return false; 40 } 41 bool hasMerged = false; 42 std::string firstApFileName; 43 for (const auto &fileName : apFileNames) { 44 if (!base::StringHelper::EndsWith(fileName, ".ap")) { 45 LOG_ECMA(ERROR) << "The file path (" << fileName << ") does not end with .ap"; 46 continue; 47 } 48 PGOProfilerDecoder decoder(fileName, hotnessThreshold); 49 if (!decoder.LoadFull(merger.GetAbcFilePool())) { 50 LOG_ECMA(ERROR) << "Fail to load file path (" << fileName << "), skip it."; 51 continue; 52 } 53 if (!hasMerged) { 54 firstApFileName = fileName; 55 } else { 56 if (!merger.VerifyPandaFileMatched(decoder.GetPandaFileInfos(), firstApFileName, fileName)) { 57 continue; 58 } 59 } 60 if (!decoder.IsCompatibleWithAOTFile()) { 61 LOG_ECMA(ERROR) << "The ap file (" << fileName << ") is not compatible with AOT version. skip it"; 62 continue; 63 } 64 merger.Merge(decoder.GetRecordDetailInfos()); 65 merger.Merge(decoder.GetPandaFileInfos()); 66 hasMerged = true; 67 } 68 if (!hasMerged) { 69 LOG_ECMA(ERROR) 70 << "No ap file pass verify, no ap file compatible an version, no ap file processed. Input files: " 71 << inFiles; 72 GetInstance()->SetIsApFileCompatible(false); 73 return false; 74 } 75 GetInstance()->SetIsApFileCompatible(true); 76 merger.Save(); 77 return true; 78} 79 80bool PGOProfilerManager::MergeApFiles(uint32_t checksum, PGOProfilerDecoder &merger) 81{ 82 uint32_t hotnessThreshold = merger.GetHotnessThreshold(); 83 std::string inFiles(merger.GetInPath()); 84 arg_list_t pandaFileNames = base::StringHelper::SplitString(inFiles, GetFileDelimiter()); 85 if (pandaFileNames.empty()) { 86 return true; 87 } 88 merger.InitMergeData(); 89 bool hasMerged = false; 90 std::string firstApFileName; 91 for (const auto &fileName : pandaFileNames) { 92 PGOProfilerDecoder decoder(fileName, hotnessThreshold); 93 if (!decoder.LoadAndVerify(checksum, merger.GetAbcFilePool())) { 94 LOG_ECMA(ERROR) << "Load and verify file (" << fileName << ") failed, skip it."; 95 continue; 96 } 97 if (!hasMerged) { 98 firstApFileName = fileName; 99 } else { 100 if (!merger.GetPandaFileInfos().VerifyChecksum(decoder.GetPandaFileInfos(), firstApFileName, fileName)) { 101 continue; 102 } 103 } 104 if (!decoder.IsCompatibleWithAOTFile()) { 105 LOG_ECMA(ERROR) << "The ap file (" << fileName << ") is not compatible with AOT version. skip it"; 106 continue; 107 } 108 merger.Merge(decoder); 109 hasMerged = true; 110 } 111 if (!hasMerged) { 112 LOG_ECMA(ERROR) 113 << "No ap file pass verify, no ap file compatible an version, no ap file processed. Input files: " 114 << inFiles; 115 GetInstance()->SetIsApFileCompatible(false); 116 return false; 117 } 118 GetInstance()->SetIsApFileCompatible(true); 119 return true; 120} 121 122void PGOProfilerManager::RegisterSavingSignal() 123{ 124 LOG_ECMA(INFO) << "Register Pgo Saving Signal"; 125 if (encoder_ == nullptr) { 126 LOG_ECMA(ERROR) << "Can not register pgo saving signal, because encoder is null."; 127 return; 128 } 129 if (!encoder_->IsInitialized()) { 130 LOG_ECMA(DEBUG) << "Can not register pgo saving signal, because encoder is initialized."; 131 return; 132 } 133 signal(PGO_SAVING_SIGNAL, SavingSignalHandler); 134 enableSignalSaving_ = true; 135} 136 137void PGOProfilerManager::SavingSignalHandler(int signo) 138{ 139 if (signo != PGO_SAVING_SIGNAL) { 140 return; 141 } 142 143 PGOProfilerManager::GetInstance()->ForceSave(); 144} 145} // namespace panda::ecmascript::pgo 146