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 #ifndef ECMASCRIPT_LOG_H 17 #define ECMASCRIPT_LOG_H 18 19 #include <cstdint> 20 #include <iostream> 21 #include <sstream> 22 23 #include "ecmascript/common.h" 24 #include "ecmascript/napi/include/jsnapi.h" 25 26 #ifdef ENABLE_HILOG 27 #if defined(__clang__) 28 #pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" 29 #elif defined(__GNUC__) 30 #pragma GCC diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" 31 #endif 32 #include "hilog/log.h" 33 #undef LOG_DOMAIN 34 #define LOG_DOMAIN 0xD003F00 35 #undef LOG_TAG 36 #define LOG_TAG "ArkCompiler" 37 #endif 38 39 40 using LOG_LEVEL = panda::RuntimeOption::LOG_LEVEL; 41 enum Level { 42 VERBOSE, 43 DEBUG, 44 INFO, 45 WARN, 46 ERROR, 47 FATAL, 48 }; 49 50 using ComponentMark = uint64_t; 51 enum Component { 52 NONE = 0ULL, 53 GC = 1ULL << 0ULL, 54 INTERPRETER = 1ULL << 1ULL, 55 COMPILER = 1ULL << 2ULL, 56 DEBUGGER = 1ULL << 3ULL, 57 ECMASCRIPT = 1ULL << 4ULL, 58 BUILTINS = 1ULL << 5ULL, 59 TRACE = 1ULL << 6ULL, 60 JIT = 1UL << 7ULL, 61 BASELINEJIT = 1UL << 8ULL, 62 SA = 1ULL << 9ULL, 63 PGO = 1ULL << 10ULL, 64 NO_TAG = 0xFFFFFFFFULL >> 1ULL, 65 ALL = 0xFFFFFFFFULL, 66 }; 67 68 namespace panda::ecmascript { 69 #ifdef ENABLE_HILOG 70 71 #if ECMASCRIPT_ENABLE_VERBOSE_LEVEL_LOG 72 // print Debug level log if enable Verbose log 73 #define LOG_VERBOSE LOG_DEBUG 74 #else 75 #define LOG_VERBOSE LOG_LEVEL_MIN 76 #endif 77 #endif // ENABLE_HILOG 78 79 class JSRuntimeOptions; 80 class PUBLIC_API Log { 81 public: 82 static void Initialize(const JSRuntimeOptions &options); LogIsLoggable(Level level,Component component)83 static inline bool LogIsLoggable(Level level, Component component) 84 { 85 switch (component) 86 { 87 case Component::SA: 88 return ((components_ & component) != 0ULL); 89 default: 90 return (level >= level_) && ((components_ & component) != 0ULL); 91 } 92 } GetComponentStr(Component component)93 static inline std::string GetComponentStr(Component component) 94 { 95 switch (component) 96 { 97 case Component::NO_TAG: 98 return ""; 99 case Component::GC: 100 return "[gc] "; 101 case Component::ECMASCRIPT: 102 return "[ecmascript] "; 103 case Component::PGO: 104 return "[pgo] "; 105 case Component::INTERPRETER: 106 return "[interpreter] "; 107 case Component::DEBUGGER: 108 return "[debugger] "; 109 case Component::COMPILER: 110 return "[compiler] "; 111 case Component::BUILTINS: 112 return "[builtins] "; 113 case Component::TRACE: 114 return "[trace] "; 115 case Component::JIT: 116 return "[jit] "; 117 case Component::BASELINEJIT: 118 return "[baselinejit] "; 119 case Component::SA: 120 return "[sa] "; 121 case Component::ALL: 122 return "[default] "; 123 default: 124 return "[unknown] "; 125 } 126 } 127 static std::string LevelToString(Level level); 128 static Level ConvertFromRuntime(LOG_LEVEL level); 129 130 private: 131 static void SetLogLevelFromString(const std::string& level); 132 static void SetLogComponentFromString(const std::vector<std::string>& components); 133 static int32_t PrintLogger(int32_t, int32_t level, const char *, const char *, const char *message); 134 135 static Level level_; 136 static ComponentMark components_; 137 }; 138 139 #if defined(ENABLE_HILOG) 140 template<LogLevel level, Component component> 141 class HiLog { 142 public: HiLog()143 HiLog() 144 { 145 std::string str = Log::GetComponentStr(component); 146 stream_ << str; 147 } ~HiLog()148 ~HiLog() 149 { 150 if constexpr (level == LOG_LEVEL_MIN) { 151 // print nothing 152 } else if constexpr (level == LOG_DEBUG) { 153 HILOG_DEBUG(LOG_CORE, "%{public}s", stream_.str().c_str()); 154 } else if constexpr (level == LOG_INFO) { 155 HILOG_INFO(LOG_CORE, "%{public}s", stream_.str().c_str()); 156 } else if constexpr (level == LOG_WARN) { 157 HILOG_WARN(LOG_CORE, "%{public}s", stream_.str().c_str()); 158 } else if constexpr (level == LOG_ERROR) { 159 HILOG_ERROR(LOG_CORE, "%{public}s", stream_.str().c_str()); 160 } else { 161 HILOG_FATAL(LOG_CORE, "%{public}s", stream_.str().c_str()); 162 std::abort(); 163 } 164 } 165 template<class type> 166 std::ostream &operator <<(type input) 167 { 168 stream_ << input; 169 return stream_; 170 } 171 172 private: 173 std::ostringstream stream_; 174 }; 175 #elif defined(ENABLE_ANLOG) // ENABLE_ANLOG 176 template<Level level> 177 class PUBLIC_API AndroidLog { 178 public: AndroidLog()179 AndroidLog() 180 { 181 std::string str = "[default] "; 182 stream_ << str; 183 } 184 ~AndroidLog(); 185 186 template<class type> 187 std::ostream &operator <<(type input) 188 { 189 stream_ << input; 190 return stream_; 191 } 192 193 private: 194 std::ostringstream stream_; 195 }; 196 #else 197 template<Level level, Component component> 198 class StdLog { 199 public: StdLog()200 StdLog() 201 { 202 std::string str = Log::GetComponentStr(component); 203 stream_ << str; 204 } ~StdLog()205 ~StdLog() 206 { 207 if constexpr (level == FATAL || level == ERROR) { 208 std::cerr << stream_.str().c_str() << std::endl; 209 } else { 210 std::cout << stream_.str().c_str() << std::endl; 211 } 212 213 if constexpr (level == FATAL) { 214 std::abort(); 215 } 216 } 217 218 template<class type> 219 std::ostream &operator <<(type input) 220 { 221 stream_ << input; 222 return stream_; 223 } 224 225 private: 226 std::ostringstream stream_; 227 }; 228 #endif 229 230 #if defined(ENABLE_HILOG) 231 #define ARK_LOG(level, component) panda::ecmascript::Log::LogIsLoggable(level, component) && \ 232 panda::ecmascript::HiLog<LOG_##level, (component)>() 233 #elif defined(ENABLE_ANLOG) 234 #define ARK_LOG(level, component) panda::ecmascript::AndroidLog<(level)>() 235 #else 236 #if defined(OHOS_UNIT_TEST) 237 #define ARK_LOG(level, component) ((level >= INFO) || panda::ecmascript::Log::LogIsLoggable(level, component)) && \ 238 panda::ecmascript::StdLog<(level), (component)>() 239 #else 240 #define ARK_LOG(level, component) panda::ecmascript::Log::LogIsLoggable(level, component) && \ 241 panda::ecmascript::StdLog<(level), (component)>() 242 #endif 243 #endif 244 } // namespace panda::ecmascript 245 #endif // ECMASCRIPT_LOG_H 246