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 #ifndef ECMASCRIPT_PGO_PROFILER_PGO_UTILS_H 17 #define ECMASCRIPT_PGO_PROFILER_PGO_UTILS_H 18 19 #include <list> 20 #include <string> 21 22 #include "ecmascript/common.h" 23 #include "ecmascript/log.h" 24 #include "ecmascript/log_wrapper.h" 25 #include "ecmascript/platform/mutex.h" 26 #include "libpandafile/file.h" 27 #include "mem/mem.h" 28 29 namespace panda::ecmascript::pgo { 30 static constexpr Alignment ALIGN_SIZE = Alignment::LOG_ALIGN_4; 31 using PGOMethodId = panda_file::File::EntityId; 32 using ApEntityId = uint32_t; 33 34 class DumpUtils { 35 public: 36 static const std::string ELEMENT_SEPARATOR; 37 static const std::string BLOCK_SEPARATOR; 38 static const std::string TYPE_SEPARATOR; 39 static const std::string BLOCK_START; 40 static const std::string ARRAY_START; 41 static const std::string ARRAY_END; 42 static const std::string NEW_LINE; 43 static const std::string SPACE; 44 static const std::string BLOCK_AND_ARRAY_START; 45 static const std::string VERSION_HEADER; 46 static const std::string PANDA_FILE_INFO_HEADER; 47 static const uint32_t HEX_FORMAT_WIDTH_FOR_32BITS; 48 }; 49 50 class DumpJsonUtils { 51 public: 52 static inline const std::string ABC_FILE_POOL = "abcFilePool"; 53 static inline const std::string ABC_FILE = "abcFile"; 54 static inline const std::string RECORD_DETAIL = "recordDetail"; 55 static inline const std::string MODULE_NAME = "moduleName"; 56 static inline const std::string FUNCTION = "function"; 57 static inline const std::string FUNCTION_NAME = "functionName"; 58 static inline const std::string TYPE = "type"; 59 static inline const std::string TYPE_OFFSET = "typeOffset"; 60 static inline const std::string TYPE_NAME = "typeName"; 61 static inline const std::string IS_ROOT = "isRoot"; 62 static inline const std::string KIND = "kind"; 63 static inline const std::string ABC_ID = "abcId"; 64 static inline const std::string ID = "id"; 65 }; 66 67 class ApNameUtils { 68 public: 69 static const std::string AP_SUFFIX; 70 static const std::string RUNTIME_AP_PREFIX; 71 static const std::string MERGED_AP_PREFIX; 72 static const std::string DEFAULT_AP_NAME; 73 static std::string PUBLIC_API GetRuntimeApName(const std::string &ohosModuleName); 74 static std::string PUBLIC_API GetMergedApName(const std::string &ohosModuleName); 75 static std::string PUBLIC_API GetOhosPkgApName(const std::string &ohosModuleName); 76 77 private: 78 static std::string GetBriefApName(const std::string &ohosModuleName); 79 }; 80 81 class ConcurrentGuardValues { 82 public: 83 mutable std::atomic_int last_tid {0}; 84 mutable std::atomic_int count {0}; 85 static const int MAX_LOG_COUNT = 30; 86 AddLog(std::string str)87 void AddLog(std::string str) 88 { 89 LockHolder lock(mutex_); 90 if (log_.size() >= MAX_LOG_COUNT) { 91 log_.pop_front(); 92 } 93 log_.push_back(str + ", tid: " + std::to_string(Gettid())); 94 } 95 AddLogWithDebugLog(std::string str)96 void AddLogWithDebugLog(std::string str) 97 { 98 AddLog(str); 99 LOG_ECMA(DEBUG) << str; 100 } 101 ClearLog()102 void ClearLog() 103 { 104 LockHolder lock(mutex_); 105 log_.clear(); 106 } 107 PrintLog()108 void PrintLog() 109 { 110 LockHolder lock(mutex_); 111 std::ostringstream os; 112 os << "concurrent guard logs: " << std::endl; 113 for (auto& str: log_) { 114 os << str << std::endl; 115 } 116 LOG_ECMA(INFO) << os.str(); 117 } 118 Gettid()119 int Gettid() 120 { 121 return os::thread::GetCurrentThreadId(); 122 } 123 124 private: 125 std::list<std::string> log_; 126 Mutex mutex_; 127 }; 128 129 class ConcurrentGuard { 130 private: 131 std::string operation_; 132 133 public: ConcurrentGuard(ConcurrentGuardValues& v, std::string operation = �)134 ConcurrentGuard(ConcurrentGuardValues& v, std::string operation = ""): operation_(operation), v_(v) 135 { 136 v_.AddLogWithDebugLog("[ConcurrentGuard] " + operation_ + " start"); 137 auto tid = v_.Gettid(); 138 auto except = 0; 139 // Support reenter 140 if (!v_.count.compare_exchange_strong(except, 1) && v_.last_tid != tid) { 141 v_.PrintLog(); 142 LOG_ECMA(FATAL) << "[ConcurrentGuard] total thead count should be 0, but get " << except 143 << ", current tid: " << tid << ", last tid: " << v_.last_tid; 144 } 145 v_.last_tid = tid; 146 } ~ConcurrentGuard()147 ~ConcurrentGuard() 148 { 149 auto tid = v_.Gettid(); 150 auto except = 1; 151 // Support reenter 152 if (!v_.count.compare_exchange_strong(except, 0) && v_.last_tid != tid) { 153 v_.PrintLog(); 154 LOG_ECMA(FATAL) << "[ConcurrentGuard] total thead count should be 1, but get " << except 155 << ", current tid: " << tid << ", last tid: " << v_.last_tid; 156 } 157 v_.AddLogWithDebugLog("[ConcurrentGuard] " + operation_ + " end"); 158 }; 159 160 private: 161 ConcurrentGuardValues& v_; 162 }; 163 } // namespace panda::ecmascript::pgo 164 #endif // ECMASCRIPT_PGO_PROFILER_PGO_UTILS_H 165