From b77430df7035ed2baba4705ff53861df8a5b3e21 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Thu, 17 Oct 2019 16:10:24 -0400
Subject: [PATCH] apm/controller: Make SetPerformanceConfiguration() use an
 array of pairs over a map

While a map is an OK way to do lookups (and usually recommended in most
cases), this is a map that lives for the entire duration of the program
and only deallocates its contents when the program terminates.

Given the total size of the map is quite small, we can simply use a
std::array of pairs and utilize std::find_if to perform the same
behavior without loss of performance.

This eliminates a static constructor and places the data into the
read-only segment.

While we're at it, we can also handle malformed inputs instead of
directly dereferencing the resulting iterator.
---
 src/core/hle/service/apm/controller.cpp | 46 ++++++++++++++++++-------
 1 file changed, 33 insertions(+), 13 deletions(-)

diff --git a/src/core/hle/service/apm/controller.cpp b/src/core/hle/service/apm/controller.cpp
index d9e8d247da..25a886238c 100644
--- a/src/core/hle/service/apm/controller.cpp
+++ b/src/core/hle/service/apm/controller.cpp
@@ -2,6 +2,10 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include <algorithm>
+#include <array>
+#include <utility>
+
 #include "common/logging/log.h"
 #include "core/core_timing.h"
 #include "core/hle/service/apm/controller.h"
@@ -9,8 +13,7 @@
 
 namespace Service::APM {
 
-constexpr PerformanceConfiguration DEFAULT_PERFORMANCE_CONFIGURATION =
-    PerformanceConfiguration::Config7;
+constexpr auto DEFAULT_PERFORMANCE_CONFIGURATION = PerformanceConfiguration::Config7;
 
 Controller::Controller(Core::Timing::CoreTiming& core_timing)
     : core_timing{core_timing}, configs{
@@ -22,18 +25,35 @@ Controller::~Controller() = default;
 
 void Controller::SetPerformanceConfiguration(PerformanceMode mode,
                                              PerformanceConfiguration config) {
-    static const std::map<PerformanceConfiguration, u32> PCONFIG_TO_SPEED_MAP{
-        {PerformanceConfiguration::Config1, 1020},  {PerformanceConfiguration::Config2, 1020},
-        {PerformanceConfiguration::Config3, 1224},  {PerformanceConfiguration::Config4, 1020},
-        {PerformanceConfiguration::Config5, 1020},  {PerformanceConfiguration::Config6, 1224},
-        {PerformanceConfiguration::Config7, 1020},  {PerformanceConfiguration::Config8, 1020},
-        {PerformanceConfiguration::Config9, 1020},  {PerformanceConfiguration::Config10, 1020},
-        {PerformanceConfiguration::Config11, 1020}, {PerformanceConfiguration::Config12, 1020},
-        {PerformanceConfiguration::Config13, 1785}, {PerformanceConfiguration::Config14, 1785},
-        {PerformanceConfiguration::Config15, 1020}, {PerformanceConfiguration::Config16, 1020},
-    };
+    static constexpr std::array<std::pair<PerformanceConfiguration, u32>, 16> config_to_speed{{
+        {PerformanceConfiguration::Config1, 1020},
+        {PerformanceConfiguration::Config2, 1020},
+        {PerformanceConfiguration::Config3, 1224},
+        {PerformanceConfiguration::Config4, 1020},
+        {PerformanceConfiguration::Config5, 1020},
+        {PerformanceConfiguration::Config6, 1224},
+        {PerformanceConfiguration::Config7, 1020},
+        {PerformanceConfiguration::Config8, 1020},
+        {PerformanceConfiguration::Config9, 1020},
+        {PerformanceConfiguration::Config10, 1020},
+        {PerformanceConfiguration::Config11, 1020},
+        {PerformanceConfiguration::Config12, 1020},
+        {PerformanceConfiguration::Config13, 1785},
+        {PerformanceConfiguration::Config14, 1785},
+        {PerformanceConfiguration::Config15, 1020},
+        {PerformanceConfiguration::Config16, 1020},
+    }};
 
-    SetClockSpeed(PCONFIG_TO_SPEED_MAP.find(config)->second);
+    const auto iter = std::find_if(config_to_speed.cbegin(), config_to_speed.cend(),
+                                   [config](const auto& entry) { return entry.first == config; });
+
+    if (iter == config_to_speed.cend()) {
+        LOG_ERROR(Service_APM, "Invalid performance configuration value provided: {}",
+                  static_cast<u32>(config));
+        return;
+    }
+
+    SetClockSpeed(iter->second);
     configs.insert_or_assign(mode, config);
 }