Use a map for app::m_Timers

Currently the timers is a vector. When we cancel a timer we have an O(n) operation
to remove the timer. If there are a lot of timers (which this test has > 16k) this can
take a long time. The impact is a lot lower in Release, but the test is very slow in Debug.

From Linux on waterfall:
  [ RUN      ] FPDFFormFillEmbeddertest.BUG_634716
  [       OK ] FPDFFormFillEmbeddertest.BUG_634716 (7855 ms)

From Linux try bot:
  [ RUN      ] FPDFFormFillEmbeddertest.BUG_634716
  [       OK ] FPDFFormFillEmbeddertest.BUG_634716 (431 ms)

From Linux XFA Rel GYP on waterfall:
  [ RUN      ] FPDFFormFillEmbeddertest.BUG_634716
  [       OK ] FPDFFormFillEmbeddertest.BUG_634716 (185 ms)

From Linux XFA Rel GYP try bot:
  [ RUN      ] FPDFFormFillEmbeddertest.BUG_634716
  [       OK ] FPDFFormFillEmbeddertest.BUG_634716 (72 ms)

Review-Url: https://codereview.chromium.org/2251333002
diff --git a/fpdfsdk/javascript/app.cpp b/fpdfsdk/javascript/app.cpp
index 97c97eb..573de40 100644
--- a/fpdfsdk/javascript/app.cpp
+++ b/fpdfsdk/javascript/app.cpp
@@ -509,15 +509,18 @@
 
   uint32_t dwInterval = params.size() > 1 ? params[1].ToInt(pRuntime) : 1000;
   CPDFDoc_Environment* pApp = pRuntime->GetReaderApp();
-  m_Timers.push_back(std::unique_ptr<GlobalTimer>(
-      new GlobalTimer(this, pApp, pRuntime, 0, script, dwInterval, 0)));
+
+  std::unique_ptr<GlobalTimer> timer(
+      new GlobalTimer(this, pApp, pRuntime, 0, script, dwInterval, 0));
+  GlobalTimer* timerRef = timer.get();
+  m_Timers[timerRef] = std::move(timer);
 
   v8::Local<v8::Object> pRetObj =
       pRuntime->NewFxDynamicObj(CJS_TimerObj::g_nObjDefnID);
   CJS_TimerObj* pJS_TimerObj =
       static_cast<CJS_TimerObj*>(pRuntime->GetObjectPrivate(pRetObj));
   TimerObj* pTimerObj = static_cast<TimerObj*>(pJS_TimerObj->GetEmbedObject());
-  pTimerObj->SetTimer(m_Timers.back().get());
+  pTimerObj->SetTimer(timerRef);
 
   vRet = CJS_Value(pRuntime, pRetObj);
   return TRUE;
@@ -543,8 +546,11 @@
 
   uint32_t dwTimeOut = params.size() > 1 ? params[1].ToInt(pRuntime) : 1000;
   CPDFDoc_Environment* pApp = pRuntime->GetReaderApp();
-  m_Timers.push_back(std::unique_ptr<GlobalTimer>(
-      new GlobalTimer(this, pApp, pRuntime, 1, script, dwTimeOut, dwTimeOut)));
+
+  std::unique_ptr<GlobalTimer> timer(
+      new GlobalTimer(this, pApp, pRuntime, 1, script, dwTimeOut, dwTimeOut));
+  GlobalTimer* timerRef = timer.get();
+  m_Timers[timerRef] = std::move(timer);
 
   v8::Local<v8::Object> pRetObj =
       pRuntime->NewFxDynamicObj(CJS_TimerObj::g_nObjDefnID);
@@ -553,7 +559,7 @@
       static_cast<CJS_TimerObj*>(pRuntime->GetObjectPrivate(pRetObj));
 
   TimerObj* pTimerObj = static_cast<TimerObj*>(pJS_TimerObj->GetEmbedObject());
-  pTimerObj->SetTimer(m_Timers.back().get());
+  pTimerObj->SetTimer(timerRef);
 
   vRet = CJS_Value(pRuntime, pRetObj);
   return TRUE;
@@ -620,13 +626,7 @@
 }
 
 void app::CancelProc(GlobalTimer* pTimer) {
-  auto iter = std::find_if(m_Timers.begin(), m_Timers.end(),
-                           [pTimer](const std::unique_ptr<GlobalTimer>& that) {
-                             return pTimer == that.get();
-                           });
-
-  if (iter != m_Timers.end())
-    m_Timers.erase(iter);
+  m_Timers.erase(pTimer);
 }
 
 void app::RunJsScript(CJS_Runtime* pRuntime, const CFX_WideString& wsScript) {
diff --git a/fpdfsdk/javascript/app.h b/fpdfsdk/javascript/app.h
index 97db59e..911d865 100644
--- a/fpdfsdk/javascript/app.h
+++ b/fpdfsdk/javascript/app.h
@@ -7,6 +7,7 @@
 #ifndef FPDFSDK_JAVASCRIPT_APP_H_
 #define FPDFSDK_JAVASCRIPT_APP_H_
 
+#include <map>
 #include <memory>
 #include <vector>
 
@@ -165,7 +166,7 @@
 
   bool m_bCalculate;
   bool m_bRuntimeHighLight;
-  std::vector<std::unique_ptr<GlobalTimer>> m_Timers;
+  std::map<GlobalTimer*, std::unique_ptr<GlobalTimer>> m_Timers;
 };
 
 class CJS_App : public CJS_Object {