Line data Source code
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>
28 178331 : DependentAddPtr(const JSContext* cx, const T& table, const Lookup& lookup)
29 : : addPtr(table.lookupForAdd(lookup))
30 178331 : , originalGcNumber(cx->zone()->gcNumber())
31 178329 : {}
32 :
33 5963 : DependentAddPtr(DependentAddPtr&& other)
34 : : addPtr(other.addPtr)
35 5963 : , originalGcNumber(other.originalGcNumber)
36 5963 : {}
37 :
38 : template <class KeyInput, class ValueInput>
39 15376 : bool add(JSContext* cx, T& table, const KeyInput& key, const ValueInput& value) {
40 15376 : refreshAddPtr(cx, table, key);
41 15376 : if (!table.relookupOrAdd(addPtr, key, value)) {
42 0 : ReportOutOfMemory(cx);
43 0 : return false;
44 : }
45 15376 : return true;
46 : }
47 :
48 : template <class KeyInput>
49 0 : void remove(JSContext* cx, T& table, const KeyInput& key) {
50 0 : refreshAddPtr(cx, table, key);
51 0 : table.remove(addPtr);
52 0 : }
53 :
54 178329 : bool found() const { return addPtr.found(); }
55 178329 : explicit operator bool() const { return found(); }
56 37183 : const Entry& operator*() const { return *addPtr; }
57 137806 : const Entry* operator->() const { return &*addPtr; }
58 :
59 : private:
60 : AddPtr addPtr ;
61 : const uint64_t originalGcNumber;
62 :
63 : template <class KeyInput>
64 15376 : void refreshAddPtr(JSContext* cx, T& table, const KeyInput& key) {
65 15376 : bool gcHappened = originalGcNumber != cx->zone()->gcNumber();
66 15376 : if (gcHappened)
67 0 : addPtr = table.lookupForAdd(key);
68 15376 : }
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
77 163327 : MakeDependentAddPtr(const JSContext* cx, T& table, const Lookup& lookup)
78 : -> DependentAddPtr<typename mozilla::RemoveReference<decltype(table)>::Type>
79 : {
80 : using Ptr = DependentAddPtr<typename mozilla::RemoveReference<decltype(table)>::Type>;
81 163327 : return Ptr(cx, table, lookup);
82 : }
83 :
84 : } // namespace js
85 :
86 : #endif
|