From 9f4501acebe91a80045a5927ca89c363825bba37 Mon Sep 17 00:00:00 2001 From: James Rowe Date: Sun, 14 Jul 2019 10:20:00 -0600 Subject: [PATCH] Perf: Remove more breakpoint checking in the interpreter. Move filtering earlier in the logging chain --- src/common/logging/backend.cpp | 20 ++------- src/common/logging/backend.h | 8 ---- src/common/logging/filter.h | 37 --------------- src/common/logging/log.h | 45 +++++++++++++++++++ .../arm/dyncom/arm_dyncom_interpreter.cpp | 6 +++ src/core/arm/skyeye_common/armstate.cpp | 5 ++- 6 files changed, 59 insertions(+), 62 deletions(-) diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 90608157e..a4a62713d 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -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) { 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)); } diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h index a6714ffd0..b0c78937f 100644 --- a/src/common/logging/backend.h +++ b/src/common/logging/backend.h @@ -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 diff --git a/src/common/logging/filter.h b/src/common/logging/filter.h index bbadbcba1..cb48bcb37 100644 --- a/src/common/logging/filter.h +++ b/src/common/logging/filter.h @@ -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 - * `:`. `` 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. `` - * 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(Class::Count)> class_levels; -}; } // namespace Log diff --git a/src/common/logging/log.h b/src/common/logging/log.h index a14e2ff37..becdfbeab 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -4,6 +4,7 @@ #pragma once +#include #include #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 + * `:`. `` 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. `` + * 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(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 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...)); } diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 7ba67320b..72e1ebe06 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -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; diff --git a/src/core/arm/skyeye_common/armstate.cpp b/src/core/arm/skyeye_common/armstate.cpp index 775618a8b..5e773b0e3 100644 --- a/src/core/arm/skyeye_common/armstate.cpp +++ b/src/core/arm/skyeye_common/armstate.cpp @@ -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);