tor-browser

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

HashUtil.h (2520B)


      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 #ifndef gc_HashUtil_h
      8 #define gc_HashUtil_h
      9 
     10 #include <type_traits>
     11 
     12 #include "vm/JSContext.h"
     13 
     14 namespace js {
     15 
     16 /*
     17 * Used to add entries to a js::HashMap or HashSet where the key depends on a GC
     18 * thing that may be moved by generational or compacting GC between the call to
     19 * lookupForAdd() and relookupOrAdd().
     20 */
     21 template <class T>
     22 struct DependentAddPtr {
     23  using AddPtr = typename T::AddPtr;
     24  using Entry = typename T::Entry;
     25 
     26  template <class Lookup>
     27  DependentAddPtr(const JSContext* cx, T& table, const Lookup& lookup)
     28      : addPtr(table.lookupForAdd(lookup)),
     29        originalGcNumber(cx->runtime()->gc.gcNumber()) {}
     30 
     31  DependentAddPtr(DependentAddPtr&& other)
     32      : addPtr(other.addPtr), originalGcNumber(other.originalGcNumber) {}
     33 
     34  template <class KeyInput, class ValueInput>
     35  bool add(JSContext* cx, T& table, const KeyInput& key,
     36           const ValueInput& value) {
     37    refreshAddPtr(cx, table, key);
     38    if (!table.relookupOrAdd(addPtr, key, value)) {
     39      ReportOutOfMemory(cx);
     40      return false;
     41    }
     42    return true;
     43  }
     44 
     45  template <class KeyInput>
     46  void remove(JSContext* cx, T& table, const KeyInput& key) {
     47    refreshAddPtr(cx, table, key);
     48    if (addPtr) {
     49      table.remove(addPtr);
     50    }
     51  }
     52 
     53  bool found() const { return addPtr.found(); }
     54  explicit operator bool() const { return found(); }
     55  const Entry& operator*() const { return *addPtr; }
     56  const Entry* operator->() const { return &*addPtr; }
     57 
     58 private:
     59  AddPtr addPtr;
     60  const uint64_t originalGcNumber;
     61 
     62  template <class KeyInput>
     63  void refreshAddPtr(JSContext* cx, T& table, const KeyInput& key) {
     64    bool gcHappened = originalGcNumber != cx->runtime()->gc.gcNumber();
     65    if (gcHappened) {
     66      addPtr = table.lookupForAdd(key);
     67    }
     68  }
     69 
     70  DependentAddPtr() = delete;
     71  DependentAddPtr(const DependentAddPtr&) = delete;
     72  DependentAddPtr& operator=(const DependentAddPtr&) = delete;
     73 };
     74 
     75 template <typename T, typename Lookup>
     76 inline auto MakeDependentAddPtr(const JSContext* cx, T& table,
     77                                const Lookup& lookup) {
     78  using Ptr = DependentAddPtr<std::remove_reference_t<decltype(table)>>;
     79  return Ptr(cx, table, lookup);
     80 }
     81 
     82 }  // namespace js
     83 
     84 #endif