Use DoubleIDWeakMap for |rendererFunctions|
authorCheng Zhao <zcbenz@gmail.com>
Wed, 11 May 2016 11:40:48 +0000 (20:40 +0900)
committerCheng Zhao <zcbenz@gmail.com>
Wed, 11 May 2016 11:40:48 +0000 (20:40 +0900)
atom/common/api/atom_api_v8_util.cc
atom/common/key_weak_map.h
lib/browser/rpc-server.js

index dcaa2ee5a748cd6e23c69b9776e41a2a03eafb8b..e9e755a9e490b185550155d505d9690184f0c19a 100644 (file)
@@ -3,15 +3,64 @@
 // found in the LICENSE file.
 
 #include <string>
+#include <utility>
 
 #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 <typename T1, typename T2>
+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 <typename Type1, typename Type2>
+struct hash<std::pair<Type1, Type2>> {
+  std::size_t operator()(std::pair<Type1, Type2> value) const {
+    return base::HashInts<Type1, Type2>(value.first, value.second);
+  }
+};
+
+}  // namespace std
+
+namespace mate {
+
+template<typename Type1, typename Type2>
+struct Converter<std::pair<Type1, Type2>> {
+  static bool FromV8(v8::Isolate* isolate,
+                     v8::Local<v8::Value> val,
+                     std::pair<Type1, Type2>* out) {
+    if (!val->IsArray())
+      return false;
+
+    v8::Local<v8::Array> array(v8::Local<v8::Array>::Cast(val));
+    if (array->Length() != 2)
+      return false;
+    return Converter<Type1>::FromV8(isolate, array->Get(0), &out->first) &&
+           Converter<Type2>::FromV8(isolate, array->Get(1), &out->second);
+  }
+};
+
+}  // namespace mate
+
 namespace {
 
 v8::Local<v8::Value> GetHiddenValue(v8::Isolate* isolate,
@@ -69,6 +118,8 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
   dict.SetMethod("setRemoteCallbackFreer", &atom::RemoteCallbackFreer::BindTo);
   dict.SetMethod("setRemoteObjectFreer", &atom::RemoteObjectFreer::BindTo);
   dict.SetMethod("createIDWeakMap", &atom::api::KeyWeakMap<int32_t>::Create);
+  dict.SetMethod("createDoubleIDWeakMap",
+                 &atom::api::KeyWeakMap<std::pair<int32_t, int32_t>>::Create);
 }
 
 }  // namespace
index 2d13c8170ad1cb44125a49664cbdf3a4d025a6f9..786779b14df82cdf5517fef9df793c9d3d913407 100644 (file)
@@ -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);
index afb50501871589b93e768d17e7f0ee2dfb337645..b4512bfacce6e47bb6f3ca786501a18d334e79d4 100644 (file)
@@ -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)) {