1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 * vim: set ts=8 sts=4 et sw=4 tw=99: 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 jshashutil_h 8 #define jshashutil_h 9 10 #include "jscntxt.h" 11 12 #include "gc/Zone.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 { 24 typedef typename T::AddPtr AddPtr; 25 typedef typename T::Entry Entry; 26 27 template <class Lookup> DependentAddPtrDependentAddPtr28 DependentAddPtr(const ExclusiveContext* cx, const T& table, const Lookup& lookup) 29 : addPtr(table.lookupForAdd(lookup)) 30 , originalGcNumber(cx->zone()->gcNumber()) 31 {} 32 33 template <class KeyInput, class ValueInput> addDependentAddPtr34 bool add(ExclusiveContext* cx, T& table, const KeyInput& key, const ValueInput& value) { 35 bool gcHappened = originalGcNumber != cx->zone()->gcNumber(); 36 if (gcHappened) 37 addPtr = table.lookupForAdd(key); 38 if (!table.relookupOrAdd(addPtr, key, value)) { 39 ReportOutOfMemory(cx); 40 return false; 41 } 42 return true; 43 } 44 45 foundDependentAddPtr46 bool found() const { return addPtr.found(); } 47 explicit operator bool() const { return found(); } 48 const Entry& operator*() const { return *addPtr; } 49 const Entry* operator->() const { return &*addPtr; } 50 51 private: 52 AddPtr addPtr ; 53 const uint64_t originalGcNumber; 54 55 DependentAddPtr() = delete; 56 DependentAddPtr(const DependentAddPtr&) = delete; 57 DependentAddPtr& operator=(const DependentAddPtr&) = delete; 58 }; 59 60 } // namespace js 61 62 #endif 63