From 759a46f3d61c029cbfdcc96904fa1450ea8bb410 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 May 2016 20:40:48 +0900 Subject: [PATCH] Use DoubleIDWeakMap for |rendererFunctions| --- atom/common/api/atom_api_v8_util.cc | 51 +++++++++++++++++++++++++++++ atom/common/key_weak_map.h | 4 +-- lib/browser/rpc-server.js | 15 ++------- 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/atom/common/api/atom_api_v8_util.cc b/atom/common/api/atom_api_v8_util.cc index dcaa2ee5a748..e9e755a9e490 100644 --- a/atom/common/api/atom_api_v8_util.cc +++ b/atom/common/api/atom_api_v8_util.cc @@ -3,15 +3,64 @@ // found in the LICENSE file. #include +#include #include "atom/common/api/atom_api_key_weak_map.h" #include "atom/common/api/remote_callback_freer.h" #include "atom/common/api/remote_object_freer.h" #include "atom/common/native_mate_converters/content_converter.h" #include "atom/common/node_includes.h" +#include "base/hash.h" #include "native_mate/dictionary.h" #include "v8/include/v8-profiler.h" +namespace base { + +// Following code should be removed after we upgraded to Chrome 50. +template +inline size_t HashInts(T1 value1, T2 value2) { + // This condition is expected to be compile-time evaluated and optimised away + // in release builds. + if (sizeof(T1) > sizeof(uint32_t) || (sizeof(T2) > sizeof(uint32_t))) + return HashInts64(value1, value2); + + return HashInts32(value1, value2); +} + +} // namespace base + +namespace std { + +// The hash function used by DoubleIDWeakMap. +template +struct hash> { + std::size_t operator()(std::pair value) const { + return base::HashInts(value.first, value.second); + } +}; + +} // namespace std + +namespace mate { + +template +struct Converter> { + static bool FromV8(v8::Isolate* isolate, + v8::Local val, + std::pair* out) { + if (!val->IsArray()) + return false; + + v8::Local array(v8::Local::Cast(val)); + if (array->Length() != 2) + return false; + return Converter::FromV8(isolate, array->Get(0), &out->first) && + Converter::FromV8(isolate, array->Get(1), &out->second); + } +}; + +} // namespace mate + namespace { v8::Local GetHiddenValue(v8::Isolate* isolate, @@ -69,6 +118,8 @@ void Initialize(v8::Local exports, v8::Local unused, dict.SetMethod("setRemoteCallbackFreer", &atom::RemoteCallbackFreer::BindTo); dict.SetMethod("setRemoteObjectFreer", &atom::RemoteObjectFreer::BindTo); dict.SetMethod("createIDWeakMap", &atom::api::KeyWeakMap::Create); + dict.SetMethod("createDoubleIDWeakMap", + &atom::api::KeyWeakMap>::Create); } } // namespace diff --git a/atom/common/key_weak_map.h b/atom/common/key_weak_map.h index 2d13c8170ad1..786779b14df8 100644 --- a/atom/common/key_weak_map.h +++ b/atom/common/key_weak_map.h @@ -70,10 +70,8 @@ class KeyWeakMap { // Remove object with |key| in the WeakMap. void Remove(const K& key) { auto iter = map_.find(key); - if (iter == map_.end()) { - LOG(WARNING) << "Removing unexist object with ID " << key; + if (iter == map_.end()) return; - } iter->second.second->ClearWeak(); map_.erase(iter); diff --git a/lib/browser/rpc-server.js b/lib/browser/rpc-server.js index afb505018715..b4512bfacce6 100644 --- a/lib/browser/rpc-server.js +++ b/lib/browser/rpc-server.js @@ -13,18 +13,7 @@ const FUNCTION_PROPERTIES = [ // The remote functions in renderer processes. // id => Function -let rendererFunctions = v8Util.createIDWeakMap() - -// Merge two IDs together. -let mergeIds = function (webContentsId, metaId) { - const PADDING_BITS = 20 - if ((webContentsId << PADDING_BITS) < 0) { - throw new Error(`webContents ID is too large: ${webContentsId}`) - } else if (metaId > (1 << PADDING_BITS)) { - throw new Error(`Object ID is too large: ${metaId}`) - } - return (webContentsId << PADDING_BITS) + metaId -} +let rendererFunctions = v8Util.createDoubleIDWeakMap() // Return the description of object's members: let getObjectMembers = function (object) { @@ -179,7 +168,7 @@ var unwrapArgs = function (sender, args) { // Merge webContentsId and meta.id, since meta.id can be the same in // different webContents. const webContentsId = sender.getId() - const objectId = mergeIds(webContentsId, meta.id) + const objectId = [webContentsId, meta.id] // Cache the callbacks in renderer. if (rendererFunctions.has(objectId)) {