Perf: Remove more breakpoint checking in the interpreter. Move filtering earlier in the logging chain
This commit is contained in:
		| @@ -26,6 +26,10 @@ | ||||
|  | ||||
| namespace Log { | ||||
|  | ||||
| Filter filter; | ||||
| void SetGlobalFilter(const Filter& f) { | ||||
|     filter = f; | ||||
| } | ||||
| /** | ||||
|  * Static state as a singleton. | ||||
|  */ | ||||
| @@ -58,14 +62,6 @@ public: | ||||
|         backends.erase(it, backends.end()); | ||||
|     } | ||||
|  | ||||
|     const Filter& GetGlobalFilter() const { | ||||
|         return filter; | ||||
|     } | ||||
|  | ||||
|     void SetGlobalFilter(const Filter& f) { | ||||
|         filter = f; | ||||
|     } | ||||
|  | ||||
|     Backend* GetBackend(std::string_view backend_name) { | ||||
|         const auto it = | ||||
|             std::find_if(backends.begin(), backends.end(), | ||||
| @@ -283,10 +279,6 @@ const char* GetLevelName(Level log_level) { | ||||
|     return "Invalid"; | ||||
| } | ||||
|  | ||||
| void SetGlobalFilter(const Filter& filter) { | ||||
|     Impl::Instance().SetGlobalFilter(filter); | ||||
| } | ||||
|  | ||||
| void AddBackend(std::unique_ptr<Backend> backend) { | ||||
|     Impl::Instance().AddBackend(std::move(backend)); | ||||
| } | ||||
| @@ -303,10 +295,6 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, | ||||
|                        unsigned int line_num, const char* function, const char* format, | ||||
|                        const fmt::format_args& args) { | ||||
|     auto& instance = Impl::Instance(); | ||||
|     const auto& filter = instance.GetGlobalFilter(); | ||||
|     if (!filter.CheckMessage(log_class, log_level)) | ||||
|         return; | ||||
|  | ||||
|     instance.PushEntry(log_class, log_level, filename, line_num, function, | ||||
|                        fmt::vformat(format, args)); | ||||
| } | ||||
|   | ||||
| @@ -14,8 +14,6 @@ | ||||
|  | ||||
| namespace Log { | ||||
|  | ||||
| class Filter; | ||||
|  | ||||
| /** | ||||
|  * A log entry. Log entries are store in a structured format to permit more varied output | ||||
|  * formatting on different frontends, as well as facilitating filtering and aggregation. | ||||
| @@ -136,10 +134,4 @@ const char* GetLogClassName(Class log_class); | ||||
|  */ | ||||
| const char* GetLevelName(Level log_level); | ||||
|  | ||||
| /** | ||||
|  * The global filter will prevent any messages from even being processed if they are filtered. Each | ||||
|  * backend can have a filter, but if the level is lower than the global filter, the backend will | ||||
|  * never get the message | ||||
|  */ | ||||
| void SetGlobalFilter(const Filter& filter); | ||||
| } // namespace Log | ||||
|   | ||||
| @@ -11,41 +11,4 @@ | ||||
|  | ||||
| namespace Log { | ||||
|  | ||||
| /** | ||||
|  * Implements a log message filter which allows different log classes to have different minimum | ||||
|  * severity levels. The filter can be changed at runtime and can be parsed from a string to allow | ||||
|  * editing via the interface or loading from a configuration file. | ||||
|  */ | ||||
| class Filter { | ||||
| public: | ||||
|     /// Initializes the filter with all classes having `default_level` as the minimum level. | ||||
|     explicit Filter(Level default_level = Level::Info); | ||||
|  | ||||
|     /// Resets the filter so that all classes have `level` as the minimum displayed level. | ||||
|     void ResetAll(Level level); | ||||
|     /// Sets the minimum level of `log_class` (and not of its subclasses) to `level`. | ||||
|     void SetClassLevel(Class log_class, Level level); | ||||
|  | ||||
|     /** | ||||
|      * Parses a filter string and applies it to this filter. | ||||
|      * | ||||
|      * A filter string consists of a space-separated list of filter rules, each of the format | ||||
|      * `<class>:<level>`. `<class>` is a log class name, with subclasses separated using periods. | ||||
|      * `*` is allowed as a class name and will reset all filters to the specified level. `<level>` | ||||
|      * a severity level name which will be set as the minimum logging level of the matched classes. | ||||
|      * Rules are applied left to right, with each rule overriding previous ones in the sequence. | ||||
|      * | ||||
|      * A few examples of filter rules: | ||||
|      *  - `*:Info` -- Resets the level of all classes to Info. | ||||
|      *  - `Service:Info` -- Sets the level of Service to Info. | ||||
|      *  - `Service.FS:Trace` -- Sets the level of the Service.FS class to Trace. | ||||
|      */ | ||||
|     void ParseFilterString(std::string_view filter_view); | ||||
|  | ||||
|     /// Matches class/level combination against the filter, returning true if it passed. | ||||
|     bool CheckMessage(Class log_class, Level level) const; | ||||
|  | ||||
| private: | ||||
|     std::array<Level, static_cast<std::size_t>(Class::Count)> class_levels; | ||||
| }; | ||||
| } // namespace Log | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <array> | ||||
| #include <fmt/format.h> | ||||
| #include "common/common_types.h" | ||||
|  | ||||
| @@ -113,6 +114,47 @@ enum class Class : ClassType { | ||||
|     Count              ///< Total number of logging classes | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Implements a log message filter which allows different log classes to have different minimum | ||||
|  * severity levels. The filter can be changed at runtime and can be parsed from a string to allow | ||||
|  * editing via the interface or loading from a configuration file. | ||||
|  */ | ||||
| class Filter { | ||||
| public: | ||||
|     /// Initializes the filter with all classes having `default_level` as the minimum level. | ||||
|     explicit Filter(Level default_level = Level::Info); | ||||
|  | ||||
|     /// Resets the filter so that all classes have `level` as the minimum displayed level. | ||||
|     void ResetAll(Level level); | ||||
|     /// Sets the minimum level of `log_class` (and not of its subclasses) to `level`. | ||||
|     void SetClassLevel(Class log_class, Level level); | ||||
|  | ||||
|     /** | ||||
|      * Parses a filter string and applies it to this filter. | ||||
|      * | ||||
|      * A filter string consists of a space-separated list of filter rules, each of the format | ||||
|      * `<class>:<level>`. `<class>` is a log class name, with subclasses separated using periods. | ||||
|      * `*` is allowed as a class name and will reset all filters to the specified level. `<level>` | ||||
|      * a severity level name which will be set as the minimum logging level of the matched classes. | ||||
|      * Rules are applied left to right, with each rule overriding previous ones in the sequence. | ||||
|      * | ||||
|      * A few examples of filter rules: | ||||
|      *  - `*:Info` -- Resets the level of all classes to Info. | ||||
|      *  - `Service:Info` -- Sets the level of Service to Info. | ||||
|      *  - `Service.FS:Trace` -- Sets the level of the Service.FS class to Trace. | ||||
|      */ | ||||
|     void ParseFilterString(std::string_view filter_view); | ||||
|  | ||||
|     /// Matches class/level combination against the filter, returning true if it passed. | ||||
|     bool CheckMessage(Class log_class, Level level) const; | ||||
|  | ||||
| private: | ||||
|     std::array<Level, static_cast<std::size_t>(Class::Count)> class_levels; | ||||
| }; | ||||
| extern Filter filter; | ||||
|  | ||||
| void SetGlobalFilter(const Filter& f); | ||||
|  | ||||
| /// Logs a message to the global logger, using fmt | ||||
| void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, | ||||
|                        unsigned int line_num, const char* function, const char* format, | ||||
| @@ -121,6 +163,9 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, | ||||
| template <typename... Args> | ||||
| void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_num, | ||||
|                    const char* function, const char* format, const Args&... args) { | ||||
|     if (!filter.CheckMessage(log_class, log_level)) | ||||
|         return; | ||||
|  | ||||
|     FmtLogMessageImpl(log_class, log_level, filename, line_num, function, format, | ||||
|                       fmt::make_format_args(args...)); | ||||
| } | ||||
|   | ||||
| @@ -953,6 +953,9 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||
| #define INC_PC(l) ptr += sizeof(arm_inst) + l | ||||
| #define INC_PC_STUB ptr += sizeof(arm_inst) | ||||
|  | ||||
| #ifdef ANDROID | ||||
| #define GDB_BP_CHECK | ||||
| #else | ||||
| #define GDB_BP_CHECK                                                                               \ | ||||
|     cpu->Cpsr &= ~(1 << 5);                                                                        \ | ||||
|     cpu->Cpsr |= cpu->TFlag << 5;                                                                  \ | ||||
| @@ -965,6 +968,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||
|             goto END;                                                                              \ | ||||
|         }                                                                                          \ | ||||
|     } | ||||
| #endif | ||||
|  | ||||
| // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a | ||||
| // clunky switch statement. | ||||
| @@ -1652,11 +1656,13 @@ DISPATCH : { | ||||
|             goto END; | ||||
|     } | ||||
|  | ||||
| #ifndef ANDROID | ||||
|     // Find breakpoint if one exists within the block | ||||
|     if (GDBStub::IsConnected()) { | ||||
|         breakpoint_data = | ||||
|             GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     inst_base = (arm_inst*)&trans_cache_buf[ptr]; | ||||
|     GOTO_NEXT_INST; | ||||
|   | ||||
| @@ -182,13 +182,16 @@ void ARMul_State::ResetMPCoreCP15Registers() { | ||||
|     CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = 0x00000000; | ||||
|     CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000; | ||||
| } | ||||
|  | ||||
| #ifdef ANDROID | ||||
| static void CheckMemoryBreakpoint(u32 address, GDBStub::BreakpointType type) {} | ||||
| #else | ||||
| static void CheckMemoryBreakpoint(u32 address, GDBStub::BreakpointType type) { | ||||
|     if (GDBStub::IsServerEnabled() && GDBStub::CheckBreakpoint(address, type)) { | ||||
|         LOG_DEBUG(Debug, "Found memory breakpoint @ {:08x}", address); | ||||
|         GDBStub::Break(true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
|  | ||||
| u8 ARMul_State::ReadMemory8(u32 address) const { | ||||
|     CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 James Rowe
					James Rowe