From 2d868ecb8d0baecdda4fb2f80a0f3ef58690fb6c Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 4 Sep 2024 22:53:06 -0500 Subject: [PATCH] perf: use v8::Local as the key in ObjectCache (#43519) * perf: use v8::Object* as direct keys instead of using hash + a linked list * refactor: use v8::Local as the key --- .../api/context_bridge/object_cache.cc | 33 +++++-------------- .../api/context_bridge/object_cache.h | 26 +++++++++------ 2 files changed, 25 insertions(+), 34 deletions(-) diff --git a/shell/renderer/api/context_bridge/object_cache.cc b/shell/renderer/api/context_bridge/object_cache.cc index 55155845713d..d7a21e655fee 100644 --- a/shell/renderer/api/context_bridge/object_cache.cc +++ b/shell/renderer/api/context_bridge/object_cache.cc @@ -12,37 +12,22 @@ namespace electron::api::context_bridge { ObjectCache::ObjectCache() = default; ObjectCache::~ObjectCache() = default; -void ObjectCache::CacheProxiedObject(v8::Local from, +void ObjectCache::CacheProxiedObject(const v8::Local from, v8::Local proxy_value) { - if (from->IsObject() && !from->IsNullOrUndefined()) { - auto obj = from.As(); - int hash = obj->GetIdentityHash(); - - proxy_map_[hash].emplace_front(from, proxy_value); - } + if (from->IsObject() && !from->IsNullOrUndefined()) + proxy_map_.insert_or_assign(from.As(), proxy_value); } v8::MaybeLocal ObjectCache::GetCachedProxiedObject( - v8::Local from) const { + const v8::Local from) const { if (!from->IsObject() || from->IsNullOrUndefined()) - return v8::MaybeLocal(); + return {}; - auto obj = from.As(); - int hash = obj->GetIdentityHash(); - auto iter = proxy_map_.find(hash); - if (iter == proxy_map_.end()) - return v8::MaybeLocal(); + const auto iter = proxy_map_.find(from.As()); + if (iter == proxy_map_.end() || iter->second.IsEmpty()) + return {}; - auto& list = iter->second; - for (const auto& pair : list) { - auto from_cmp = pair.first; - if (from_cmp == from) { - if (pair.second.IsEmpty()) - return v8::MaybeLocal(); - return pair.second; - } - } - return v8::MaybeLocal(); + return iter->second; } } // namespace electron::api::context_bridge diff --git a/shell/renderer/api/context_bridge/object_cache.h b/shell/renderer/api/context_bridge/object_cache.h index 680857f3585d..340d1bebc28a 100644 --- a/shell/renderer/api/context_bridge/object_cache.h +++ b/shell/renderer/api/context_bridge/object_cache.h @@ -5,19 +5,18 @@ #ifndef ELECTRON_SHELL_RENDERER_API_CONTEXT_BRIDGE_OBJECT_CACHE_H_ #define ELECTRON_SHELL_RENDERER_API_CONTEXT_BRIDGE_OBJECT_CACHE_H_ -#include #include -#include -#include "content/public/renderer/render_frame.h" -#include "content/public/renderer/render_frame_observer.h" -#include "shell/renderer/electron_render_frame_observer.h" -#include "third_party/blink/public/web/web_local_frame.h" +#include "v8/include/v8-local-handle.h" +#include "v8/include/v8-object.h" namespace electron::api::context_bridge { -using ObjectCachePair = std::pair, v8::Local>; - +/** + * NB: This is designed for context_bridge. Beware using it elsewhere! + * Since it's a v8::Local-to-v8::Local cache, be careful to destroy it + * before destroying the HandleScope that keeps the locals alive. + */ class ObjectCache final { public: ObjectCache(); @@ -29,8 +28,15 @@ class ObjectCache final { v8::Local from) const; private: - // object_identity ==> [from_value, proxy_value] - std::unordered_map> proxy_map_; + struct Hash { + std::size_t operator()(const v8::Local& obj) const { + return obj->GetIdentityHash(); + } + }; + + // from_object ==> proxy_value + std::unordered_map, v8::Local, Hash> + proxy_map_; }; } // namespace electron::api::context_bridge