Browse Source

refactor: omit redundant map searches (#19929)

* refactor: don't walk maps twice to remove elements

* refactor: don't walk maps twice to read elements

* refactor: don't walk maps twice to insert elements

* refactor: don't walk map 3x on UvTaskRunner timeout

* refactor: more don't-walk-maps-twice cleanup

* fixup! refactor: don't walk maps twice to insert elements

* refactor: don't walk containers twice when erasing

* refactor: omit excess lookups in RemoteObjectFreer
Charles Kerr 5 years ago
parent
commit
987300c97a

+ 5 - 4
shell/app/uv_task_runner.cc

@@ -42,12 +42,13 @@ bool UvTaskRunner::PostNonNestableDelayedTask(const base::Location& from_here,
 
 // static
 void UvTaskRunner::OnTimeout(uv_timer_t* timer) {
-  UvTaskRunner* self = static_cast<UvTaskRunner*>(timer->data);
-  if (!base::Contains(self->tasks_, timer))
+  auto& tasks = static_cast<UvTaskRunner*>(timer->data)->tasks_;
+  const auto iter = tasks.find(timer);
+  if (iter == std::end(tasks))
     return;
 
-  std::move(self->tasks_[timer]).Run();
-  self->tasks_.erase(timer);
+  std::move(iter->second).Run();
+  tasks.erase(iter);
   uv_timer_stop(timer);
   uv_close(reinterpret_cast<uv_handle_t*>(timer), UvTaskRunner::OnClose);
 }

+ 1 - 2
shell/browser/api/atom_api_global_shortcut.cc

@@ -107,10 +107,9 @@ bool GlobalShortcut::Register(const ui::Accelerator& accelerator,
 }
 
 void GlobalShortcut::Unregister(const ui::Accelerator& accelerator) {
-  if (!base::Contains(accelerator_callback_map_, accelerator))
+  if (accelerator_callback_map_.erase(accelerator) == 0)
     return;
 
-  accelerator_callback_map_.erase(accelerator);
   GlobalShortcutListener::GetInstance()->UnregisterAccelerator(accelerator,
                                                                this);
 }

+ 11 - 22
shell/browser/api/atom_api_protocol_ns.cc

@@ -176,21 +176,15 @@ void ProtocolNS::RegisterURLLoaderFactories(
 ProtocolError ProtocolNS::RegisterProtocol(ProtocolType type,
                                            const std::string& scheme,
                                            const ProtocolHandler& handler) {
-  ProtocolError error = ProtocolError::OK;
-  if (!base::Contains(handlers_, scheme))
-    handlers_[scheme] = std::make_pair(type, handler);
-  else
-    error = ProtocolError::REGISTERED;
-  return error;
+  const bool added = base::TryEmplace(handlers_, scheme, type, handler).second;
+  return added ? ProtocolError::OK : ProtocolError::REGISTERED;
 }
 
 void ProtocolNS::UnregisterProtocol(const std::string& scheme,
                                     mate::Arguments* args) {
-  ProtocolError error = ProtocolError::OK;
-  if (base::Contains(handlers_, scheme))
-    handlers_.erase(scheme);
-  else
-    error = ProtocolError::NOT_REGISTERED;
+  const bool removed = handlers_.erase(scheme) != 0;
+  const auto error =
+      removed ? ProtocolError::OK : ProtocolError::NOT_REGISTERED;
   HandleOptionalCallback(args, error);
 }
 
@@ -201,21 +195,16 @@ bool ProtocolNS::IsProtocolRegistered(const std::string& scheme) {
 ProtocolError ProtocolNS::InterceptProtocol(ProtocolType type,
                                             const std::string& scheme,
                                             const ProtocolHandler& handler) {
-  ProtocolError error = ProtocolError::OK;
-  if (!base::Contains(intercept_handlers_, scheme))
-    intercept_handlers_[scheme] = std::make_pair(type, handler);
-  else
-    error = ProtocolError::INTERCEPTED;
-  return error;
+  const bool added =
+      base::TryEmplace(intercept_handlers_, scheme, type, handler).second;
+  return added ? ProtocolError::OK : ProtocolError::INTERCEPTED;
 }
 
 void ProtocolNS::UninterceptProtocol(const std::string& scheme,
                                      mate::Arguments* args) {
-  ProtocolError error = ProtocolError::OK;
-  if (base::Contains(intercept_handlers_, scheme))
-    intercept_handlers_.erase(scheme);
-  else
-    error = ProtocolError::NOT_INTERCEPTED;
+  const bool removed = intercept_handlers_.erase(scheme) != 0;
+  const auto error =
+      removed ? ProtocolError::OK : ProtocolError::NOT_INTERCEPTED;
   HandleOptionalCallback(args, error);
 }
 

+ 0 - 3
shell/browser/api/atom_api_top_level_window.cc

@@ -972,9 +972,6 @@ bool TopLevelWindow::HookWindowMessage(UINT message,
 }
 
 void TopLevelWindow::UnhookWindowMessage(UINT message) {
-  if (!base::Contains(messages_callback_map_, message))
-    return;
-
   messages_callback_map_.erase(message);
 }
 

+ 9 - 6
shell/browser/api/atom_api_web_request_ns.cc

@@ -396,10 +396,11 @@ template <typename... Args>
 void WebRequestNS::HandleSimpleEvent(SimpleEvent event,
                                      extensions::WebRequestInfo* request_info,
                                      Args... args) {
-  if (!base::Contains(simple_listeners_, event))
+  const auto iter = simple_listeners_.find(event);
+  if (iter == std::end(simple_listeners_))
     return;
 
-  const auto& info = simple_listeners_[event];
+  const auto& info = iter->second;
   if (!MatchesFilterCondition(request_info, info.url_patterns))
     return;
 
@@ -416,10 +417,11 @@ int WebRequestNS::HandleResponseEvent(ResponseEvent event,
                                       net::CompletionOnceCallback callback,
                                       Out out,
                                       Args... args) {
-  if (!base::Contains(response_listeners_, event))
+  const auto iter = response_listeners_.find(event);
+  if (iter == std::end(response_listeners_))
     return net::OK;
 
-  const auto& info = response_listeners_[event];
+  const auto& info = iter->second;
   if (!MatchesFilterCondition(request_info, info.url_patterns))
     return net::OK;
 
@@ -441,7 +443,8 @@ template <typename T>
 void WebRequestNS::OnListenerResult(uint64_t id,
                                     T out,
                                     v8::Local<v8::Value> response) {
-  if (!base::Contains(callbacks_, id))
+  const auto iter = callbacks_.find(id);
+  if (iter == std::end(callbacks_))
     return;
 
   int result = net::OK;
@@ -461,7 +464,7 @@ void WebRequestNS::OnListenerResult(uint64_t id,
   // asynchronously, because it used to work on IO thread before NetworkService.
   base::SequencedTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callbacks_[id]), result));
-  callbacks_.erase(id);
+  callbacks_.erase(iter);
 }
 
 // static

+ 3 - 2
shell/browser/atom_browser_client.cc

@@ -197,8 +197,9 @@ content::WebContents* AtomBrowserClient::GetWebContentsFromProcessID(
     int process_id) {
   // If the process is a pending process, we should use the web contents
   // for the frame host passed into RegisterPendingProcess.
-  if (base::Contains(pending_processes_, process_id))
-    return pending_processes_[process_id];
+  const auto iter = pending_processes_.find(process_id);
+  if (iter != std::end(pending_processes_))
+    return iter->second;
 
   // Certain render process will be created with no associated render view,
   // for example: ServiceWorker.

+ 3 - 2
shell/browser/ui/accelerator_util.cc

@@ -89,8 +89,9 @@ void GenerateAcceleratorTable(AcceleratorTable* table,
 
 bool TriggerAcceleratorTableCommand(AcceleratorTable* table,
                                     const ui::Accelerator& accelerator) {
-  if (base::Contains(*table, accelerator)) {
-    const accelerator_util::MenuItem& item = (*table)[accelerator];
+  const auto iter = table->find(accelerator);
+  if (iter != std::end(*table)) {
+    const accelerator_util::MenuItem& item = iter->second;
     if (item.model->IsEnabledAt(item.position)) {
       const auto event_flags =
           accelerator.MaskOutKeyEventFlags(accelerator.modifiers());

+ 6 - 10
shell/browser/ui/atom_menu_model.cc

@@ -25,11 +25,9 @@ void AtomMenuModel::SetToolTip(int index, const base::string16& toolTip) {
 }
 
 base::string16 AtomMenuModel::GetToolTipAt(int index) {
-  int command_id = GetCommandIdAt(index);
-  if (base::Contains(toolTips_, command_id))
-    return toolTips_[command_id];
-  else
-    return base::string16();
+  const int command_id = GetCommandIdAt(index);
+  const auto iter = toolTips_.find(command_id);
+  return iter == std::end(toolTips_) ? base::string16() : iter->second;
 }
 
 void AtomMenuModel::SetRole(int index, const base::string16& role) {
@@ -38,11 +36,9 @@ void AtomMenuModel::SetRole(int index, const base::string16& role) {
 }
 
 base::string16 AtomMenuModel::GetRoleAt(int index) {
-  int command_id = GetCommandIdAt(index);
-  if (base::Contains(roles_, command_id))
-    return roles_[command_id];
-  else
-    return base::string16();
+  const int command_id = GetCommandIdAt(index);
+  const auto iter = roles_.find(command_id);
+  return iter == std::end(roles_) ? base::string16() : iter->second;
 }
 
 bool AtomMenuModel::GetAcceleratorAtWithParams(

+ 3 - 2
shell/browser/ui/win/taskbar_host.cc

@@ -199,8 +199,9 @@ bool TaskbarHost::SetThumbnailToolTip(HWND window, const std::string& tooltip) {
 }
 
 bool TaskbarHost::HandleThumbarButtonEvent(int button_id) {
-  if (base::Contains(callback_map_, button_id)) {
-    auto callback = callback_map_[button_id];
+  const auto iter = callback_map_.find(button_id);
+  if (iter != std::end(callback_map_)) {
+    auto callback = iter->second;
     if (!callback.is_null())
       callback.Run();
     return true;

+ 12 - 14
shell/browser/web_view_manager.cc

@@ -28,11 +28,9 @@ void WebViewManager::AddGuest(int guest_instance_id,
 }
 
 void WebViewManager::RemoveGuest(int guest_instance_id) {
-  if (!base::Contains(web_contents_embedder_map_, guest_instance_id))
+  if (web_contents_embedder_map_.erase(guest_instance_id) == 0)
     return;
 
-  web_contents_embedder_map_.erase(guest_instance_id);
-
   // Remove the record of element in embedder too.
   for (const auto& element : element_instance_id_to_guest_map_)
     if (element.second == guest_instance_id) {
@@ -42,24 +40,24 @@ void WebViewManager::RemoveGuest(int guest_instance_id) {
 }
 
 content::WebContents* WebViewManager::GetEmbedder(int guest_instance_id) {
-  if (base::Contains(web_contents_embedder_map_, guest_instance_id))
-    return web_contents_embedder_map_[guest_instance_id].embedder;
-  else
-    return nullptr;
+  const auto iter = web_contents_embedder_map_.find(guest_instance_id);
+  return iter == std::end(web_contents_embedder_map_) ? nullptr
+                                                      : iter->second.embedder;
 }
 
 content::WebContents* WebViewManager::GetGuestByInstanceID(
     int owner_process_id,
     int element_instance_id) {
-  ElementInstanceKey key(owner_process_id, element_instance_id);
-  if (!base::Contains(element_instance_id_to_guest_map_, key))
+  const ElementInstanceKey key(owner_process_id, element_instance_id);
+  const auto guest_iter = element_instance_id_to_guest_map_.find(key);
+  if (guest_iter == std::end(element_instance_id_to_guest_map_))
     return nullptr;
 
-  int guest_instance_id = element_instance_id_to_guest_map_[key];
-  if (base::Contains(web_contents_embedder_map_, guest_instance_id))
-    return web_contents_embedder_map_[guest_instance_id].web_contents;
-  else
-    return nullptr;
+  const int guest_instance_id = guest_iter->second;
+  const auto iter = web_contents_embedder_map_.find(guest_instance_id);
+  return iter == std::end(web_contents_embedder_map_)
+             ? nullptr
+             : iter->second.web_contents;
 }
 
 bool WebViewManager::ForEachGuest(content::WebContents* embedder_web_contents,

+ 17 - 6
shell/common/api/remote_object_freer.cc

@@ -65,16 +65,27 @@ void RemoteObjectFreer::RunDestructor() {
   if (!render_frame)
     return;
 
+  // Reset our local ref count in case we are in a GC race condition
+  // and will get more references in an inbound IPC message
+  int ref_count = 0;
+  const auto objects_it = ref_mapper_.find(context_id_);
+  if (objects_it != std::end(ref_mapper_)) {
+    auto& objects = objects_it->second;
+    const auto ref_it = objects.find(object_id_);
+    if (ref_it != std::end(objects)) {
+      ref_count = ref_it->second;
+      objects.erase(ref_it);
+    }
+    if (objects.empty())
+      ref_mapper_.erase(objects_it);
+  }
+
   auto* channel = "ELECTRON_BROWSER_DEREFERENCE";
+
   base::ListValue args;
   args.AppendString(context_id_);
   args.AppendInteger(object_id_);
-  args.AppendInteger(ref_mapper_[context_id_][object_id_]);
-  // Reset our local ref count in case we are in a GC race condition and will
-  // get more references in an inbound IPC message
-  ref_mapper_[context_id_].erase(object_id_);
-  if (ref_mapper_[context_id_].empty())
-    ref_mapper_.erase(context_id_);
+  args.AppendInteger(ref_count);
 
   mojom::ElectronBrowserAssociatedPtr electron_ptr;
   render_frame->GetRemoteAssociatedInterfaces()->GetInterface(

+ 15 - 7
shell/common/asar/asar_util.cc

@@ -30,14 +30,22 @@ const base::FilePath::CharType kAsarExtension[] = FILE_PATH_LITERAL(".asar");
 std::shared_ptr<Archive> GetOrCreateAsarArchive(const base::FilePath& path) {
   if (!g_archive_map_tls.Pointer()->Get())
     g_archive_map_tls.Pointer()->Set(new ArchiveMap);
-  ArchiveMap& archive_map = *g_archive_map_tls.Pointer()->Get();
-  if (!base::Contains(archive_map, path)) {
-    std::shared_ptr<Archive> archive(new Archive(path));
-    if (!archive->Init())
-      return nullptr;
-    archive_map[path] = archive;
+  ArchiveMap& map = *g_archive_map_tls.Pointer()->Get();
+
+  // if we have it, return it
+  const auto lower = map.lower_bound(path);
+  if (lower != std::end(map) && !map.key_comp()(path, lower->first))
+    return lower->second;
+
+  // if we can create it, return it
+  auto archive = std::make_shared<Archive>(path);
+  if (archive->Init()) {
+    base::TryEmplace(map, lower, path, archive);
+    return archive;
   }
-  return archive_map[path];
+
+  // didn't have it, couldn't create it
+  return nullptr;
 }
 
 void ClearArchives() {

+ 2 - 4
shell/renderer/atom_renderer_client.cc

@@ -153,14 +153,12 @@ void AtomRendererClient::DidCreateScriptContext(
 void AtomRendererClient::WillReleaseScriptContext(
     v8::Handle<v8::Context> context,
     content::RenderFrame* render_frame) {
-  if (injected_frames_.find(render_frame) == injected_frames_.end())
+  if (injected_frames_.erase(render_frame) == 0)
     return;
-  injected_frames_.erase(render_frame);
 
   node::Environment* env = node::Environment::GetCurrent(context);
-  if (environments_.find(env) == environments_.end())
+  if (environments_.erase(env) == 0)
     return;
-  environments_.erase(env);
 
   mate::EmitEvent(env->isolate(), env->process_object(), "exit");
 

+ 1 - 2
shell/renderer/atom_sandboxed_renderer_client.cc

@@ -294,9 +294,8 @@ void AtomSandboxedRendererClient::SetupExtensionWorldOverrides(
 void AtomSandboxedRendererClient::WillReleaseScriptContext(
     v8::Handle<v8::Context> context,
     content::RenderFrame* render_frame) {
-  if (injected_frames_.find(render_frame) == injected_frames_.end())
+  if (injected_frames_.erase(render_frame) == 0)
     return;
-  injected_frames_.erase(render_frame);
 
   auto* isolate = context->GetIsolate();
   v8::HandleScope handle_scope(isolate);