tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

XPCMaps.h (10134B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 /* Private maps (hashtables). */
      8 
      9 #ifndef xpcmaps_h___
     10 #define xpcmaps_h___
     11 
     12 #include "mozilla/AllocPolicy.h"
     13 #include "mozilla/MemoryReporting.h"
     14 #include "mozilla/HashTable.h"
     15 
     16 #include "js/GCHashTable.h"
     17 
     18 /***************************************************************************/
     19 // default initial sizes for maps (hashtables)
     20 
     21 #define XPC_JS_MAP_LENGTH 32
     22 
     23 #define XPC_NATIVE_MAP_LENGTH 8
     24 #define XPC_NATIVE_PROTO_MAP_LENGTH 8
     25 #define XPC_DYING_NATIVE_PROTO_MAP_LENGTH 8
     26 #define XPC_NATIVE_INTERFACE_MAP_LENGTH 32
     27 #define XPC_NATIVE_SET_MAP_LENGTH 32
     28 #define XPC_WRAPPER_MAP_LENGTH 8
     29 
     30 /*************************/
     31 
     32 class JSObject2WrappedJSMap {
     33  using Map = js::HashMap<JS::Heap<JSObject*>, nsXPCWrappedJS*,
     34                          js::StableCellHasher<JS::Heap<JSObject*>>,
     35                          InfallibleAllocPolicy>;
     36 
     37 public:
     38  JSObject2WrappedJSMap() = default;
     39 
     40  inline nsXPCWrappedJS* Find(JSObject* Obj) {
     41    MOZ_ASSERT(Obj, "bad param");
     42    Map::Ptr p = mTable.lookup(Obj);
     43    return p ? p->value() : nullptr;
     44  }
     45 
     46 #ifdef DEBUG
     47  inline bool HasWrapper(nsXPCWrappedJS* wrapper) {
     48    for (auto iter = mTable.iter(); !iter.done(); iter.next()) {
     49      if (iter.get().value() == wrapper) {
     50        return true;
     51      }
     52    }
     53    return false;
     54  }
     55 #endif
     56 
     57  inline nsXPCWrappedJS* Add(JSContext* cx, nsXPCWrappedJS* wrapper) {
     58    MOZ_ASSERT(wrapper, "bad param");
     59    JSObject* obj = wrapper->GetJSObjectPreserveColor();
     60    Map::AddPtr p = mTable.lookupForAdd(obj);
     61    if (p) {
     62      return p->value();
     63    }
     64    if (!mTable.add(p, obj, wrapper)) {
     65      return nullptr;
     66    }
     67    return wrapper;
     68  }
     69 
     70  inline void Remove(nsXPCWrappedJS* wrapper) {
     71    MOZ_ASSERT(wrapper, "bad param");
     72    mTable.remove(wrapper->GetJSObjectPreserveColor());
     73  }
     74 
     75  inline uint32_t Count() { return mTable.count(); }
     76 
     77  inline void Dump(int16_t depth) {
     78    for (auto iter = mTable.iter(); !iter.done(); iter.next()) {
     79      iter.get().value()->DebugDump(depth);
     80    }
     81  }
     82 
     83  void UpdateWeakPointersAfterGC(JSTracer* trc);
     84 
     85  void ShutdownMarker();
     86 
     87  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
     88 
     89  // Report the sum of SizeOfIncludingThis() for all wrapped JS in the map.
     90  // Each wrapped JS is only in one map.
     91  size_t SizeOfWrappedJS(mozilla::MallocSizeOf mallocSizeOf) const;
     92 
     93 private:
     94  Map mTable{XPC_JS_MAP_LENGTH};
     95 };
     96 
     97 /*************************/
     98 
     99 class Native2WrappedNativeMap {
    100  using Map = mozilla::HashMap<nsISupports*, XPCWrappedNative*,
    101                               mozilla::DefaultHasher<nsISupports*>,
    102                               mozilla::MallocAllocPolicy>;
    103 
    104 public:
    105  Native2WrappedNativeMap();
    106 
    107  XPCWrappedNative* Find(nsISupports* obj) const {
    108    MOZ_ASSERT(obj, "bad param");
    109    Map::Ptr ptr = mMap.lookup(obj);
    110    return ptr ? ptr->value() : nullptr;
    111  }
    112 
    113  XPCWrappedNative* Add(XPCWrappedNative* wrapper) {
    114    MOZ_ASSERT(wrapper, "bad param");
    115    nsISupports* obj = wrapper->GetIdentityObject();
    116    Map::AddPtr ptr = mMap.lookupForAdd(obj);
    117    MOZ_ASSERT(!ptr, "wrapper already in new scope!");
    118    if (ptr) {
    119      return ptr->value();
    120    }
    121    if (!mMap.add(ptr, obj, wrapper)) {
    122      return nullptr;
    123    }
    124    return wrapper;
    125  }
    126 
    127  void Clear() { mMap.clear(); }
    128 
    129  uint32_t Count() { return mMap.count(); }
    130 
    131  Map::Iterator Iter() { return mMap.iter(); }
    132  Map::ModIterator ModIter() { return mMap.modIter(); }
    133 
    134  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
    135 
    136 private:
    137  Map mMap;
    138 };
    139 
    140 /*************************/
    141 
    142 struct IIDHasher {
    143  using Key = const nsIID*;
    144  using Lookup = Key;
    145 
    146  // Note this is returning the hash of the bit pattern of the first part of the
    147  // nsID, not the hash of the pointer to the nsID.
    148  static mozilla::HashNumber hash(Lookup lookup) {
    149    uintptr_t v;
    150    memcpy(&v, lookup, sizeof(v));
    151    return mozilla::HashGeneric(v);
    152  }
    153 
    154  static bool match(Key key, Lookup lookup) { return key->Equals(*lookup); }
    155 };
    156 
    157 class IID2NativeInterfaceMap {
    158  using Map = mozilla::HashMap<const nsIID*, XPCNativeInterface*, IIDHasher,
    159                               mozilla::MallocAllocPolicy>;
    160 
    161 public:
    162  IID2NativeInterfaceMap();
    163 
    164  XPCNativeInterface* Find(REFNSIID iid) const {
    165    Map::Ptr ptr = mMap.lookup(&iid);
    166    return ptr ? ptr->value() : nullptr;
    167  }
    168 
    169  bool AddNew(XPCNativeInterface* iface) {
    170    MOZ_ASSERT(iface, "bad param");
    171    const nsIID* iid = iface->GetIID();
    172    return mMap.putNew(iid, iface);
    173  }
    174 
    175  void Remove(XPCNativeInterface* iface) {
    176    MOZ_ASSERT(iface, "bad param");
    177    mMap.remove(iface->GetIID());
    178  }
    179 
    180  uint32_t Count() { return mMap.count(); }
    181 
    182  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
    183 
    184  void Trace(JSTracer* trc);
    185 
    186 private:
    187  Map mMap;
    188 };
    189 
    190 /*************************/
    191 
    192 class ClassInfo2NativeSetMap {
    193  using Map = mozilla::HashMap<nsIClassInfo*, RefPtr<XPCNativeSet>,
    194                               mozilla::DefaultHasher<nsIClassInfo*>,
    195                               mozilla::MallocAllocPolicy>;
    196 
    197 public:
    198  ClassInfo2NativeSetMap();
    199 
    200  XPCNativeSet* Find(nsIClassInfo* info) const {
    201    auto ptr = mMap.lookup(info);
    202    return ptr ? ptr->value().get() : nullptr;
    203  }
    204 
    205  XPCNativeSet* Add(nsIClassInfo* info, XPCNativeSet* set) {
    206    MOZ_ASSERT(info, "bad param");
    207    auto ptr = mMap.lookupForAdd(info);
    208    if (ptr) {
    209      return ptr->value();
    210    }
    211    if (!mMap.add(ptr, info, set)) {
    212      return nullptr;
    213    }
    214    return set;
    215  }
    216 
    217  void Remove(nsIClassInfo* info) {
    218    MOZ_ASSERT(info, "bad param");
    219    mMap.remove(info);
    220  }
    221 
    222  uint32_t Count() { return mMap.count(); }
    223 
    224  // ClassInfo2NativeSetMap holds pointers to *some* XPCNativeSets.
    225  // So we don't want to count those XPCNativeSets, because they are better
    226  // counted elsewhere (i.e. in XPCJSContext::mNativeSetMap, which holds
    227  // pointers to *all* XPCNativeSets).  Hence the "Shallow".
    228  size_t ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
    229 
    230 private:
    231  Map mMap;
    232 };
    233 
    234 /*************************/
    235 
    236 class ClassInfo2WrappedNativeProtoMap {
    237  using Map = mozilla::HashMap<nsIClassInfo*, XPCWrappedNativeProto*,
    238                               mozilla::DefaultHasher<nsIClassInfo*>,
    239                               mozilla::MallocAllocPolicy>;
    240 
    241 public:
    242  ClassInfo2WrappedNativeProtoMap();
    243 
    244  XPCWrappedNativeProto* Find(nsIClassInfo* info) const {
    245    auto ptr = mMap.lookup(info);
    246    return ptr ? ptr->value() : nullptr;
    247  }
    248 
    249  XPCWrappedNativeProto* Add(nsIClassInfo* info, XPCWrappedNativeProto* proto) {
    250    MOZ_ASSERT(info, "bad param");
    251    auto ptr = mMap.lookupForAdd(info);
    252    if (ptr) {
    253      return ptr->value();
    254    }
    255    if (!mMap.add(ptr, info, proto)) {
    256      return nullptr;
    257    }
    258    return proto;
    259  }
    260 
    261  void Clear() { mMap.clear(); }
    262 
    263  uint32_t Count() { return mMap.count(); }
    264 
    265  Map::Iterator Iter() { return mMap.iter(); }
    266  Map::ModIterator ModIter() { return mMap.modIter(); }
    267 
    268  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
    269 
    270 private:
    271  Map mMap;
    272 };
    273 
    274 /*************************/
    275 
    276 struct NativeSetHasher {
    277  using Key = XPCNativeSet*;
    278  using Lookup = const XPCNativeSetKey*;
    279 
    280  static mozilla::HashNumber hash(Lookup lookup) { return lookup->Hash(); }
    281  static bool match(Key key, Lookup lookup);
    282 };
    283 
    284 class NativeSetMap {
    285  using Set = mozilla::HashSet<XPCNativeSet*, NativeSetHasher,
    286                               mozilla::MallocAllocPolicy>;
    287 
    288 public:
    289  NativeSetMap();
    290 
    291  XPCNativeSet* Find(const XPCNativeSetKey* key) const {
    292    auto ptr = mSet.lookup(key);
    293    return ptr ? *ptr : nullptr;
    294  }
    295 
    296  XPCNativeSet* Add(const XPCNativeSetKey* key, XPCNativeSet* set) {
    297    MOZ_ASSERT(key, "bad param");
    298    MOZ_ASSERT(set, "bad param");
    299    auto ptr = mSet.lookupForAdd(key);
    300    if (ptr) {
    301      return *ptr;
    302    }
    303    if (!mSet.add(ptr, set)) {
    304      return nullptr;
    305    }
    306    return set;
    307  }
    308 
    309  bool AddNew(const XPCNativeSetKey* key, XPCNativeSet* set) {
    310    XPCNativeSet* set2 = Add(key, set);
    311    if (!set2) {
    312      return false;
    313    }
    314 #ifdef DEBUG
    315    XPCNativeSetKey key2(set);
    316    MOZ_ASSERT(key->Hash() == key2.Hash());
    317    MOZ_ASSERT(set2 == set, "Should not have found an existing entry");
    318 #endif
    319    return true;
    320  }
    321 
    322  void Remove(XPCNativeSet* set) {
    323    MOZ_ASSERT(set, "bad param");
    324 
    325    XPCNativeSetKey key(set);
    326    mSet.remove(&key);
    327  }
    328 
    329  uint32_t Count() { return mSet.count(); }
    330 
    331  Set::Iterator Iter() { return mSet.iter(); }
    332 
    333  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
    334 
    335 private:
    336  Set mSet;
    337 };
    338 
    339 /***************************************************************************/
    340 
    341 class JSObject2JSObjectMap {
    342  using Map = JS::GCHashMap<JS::Heap<JSObject*>, JS::Heap<JSObject*>,
    343                            js::StableCellHasher<JS::Heap<JSObject*>>,
    344                            js::SystemAllocPolicy>;
    345 
    346 public:
    347  JSObject2JSObjectMap() = default;
    348 
    349  inline JSObject* Find(JSObject* key) {
    350    MOZ_ASSERT(key, "bad param");
    351    if (Map::Ptr p = mTable.lookup(key)) {
    352      return p->value();
    353    }
    354    return nullptr;
    355  }
    356 
    357  /* Note: If the entry already exists, return the old value. */
    358  inline JSObject* Add(JSContext* cx, JSObject* key, JSObject* value) {
    359    MOZ_ASSERT(key, "bad param");
    360    Map::AddPtr p = mTable.lookupForAdd(key);
    361    if (p) {
    362      JSObject* oldValue = p->value();
    363      p->value() = value;
    364      return oldValue;
    365    }
    366    if (!mTable.add(p, key, value)) {
    367      return nullptr;
    368    }
    369    MOZ_ASSERT(xpc::ObjectScope(key)->mWaiverWrapperMap == this);
    370    return value;
    371  }
    372 
    373  inline void Remove(JSObject* key) {
    374    MOZ_ASSERT(key, "bad param");
    375    mTable.remove(key);
    376  }
    377 
    378  inline uint32_t Count() { return mTable.count(); }
    379 
    380  void UpdateWeakPointers(JSTracer* trc) { mTable.traceWeak(trc); }
    381 
    382 private:
    383  Map mTable{XPC_WRAPPER_MAP_LENGTH};
    384 };
    385 
    386 #endif /* xpcmaps_h___ */