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/. */
11 #include "gc/Marking.h"
12 #include "js/HashTable.h"
13 #include "vm/Runtime.h"
17 // A WeakCache is used to map a key to a value similar to an HashMap except
18 // that its entries are garbage collected. An entry is kept as long as
19 // both the key and value are marked.
21 // No mark function is provided with this weak container. However, this weak
22 // container should take part in the sweep phase.
23 template <class Key
, class Value
,
24 class HashPolicy
= DefaultHasher
<Key
>,
25 class AllocPolicy
= RuntimeAllocPolicy
>
26 class WeakCache
: public HashMap
<Key
, Value
, HashPolicy
, AllocPolicy
> {
28 typedef HashMap
<Key
, Value
, HashPolicy
, AllocPolicy
> Base
;
29 typedef typename
Base::Range Range
;
30 typedef typename
Base::Enum Enum
;
33 explicit WeakCache(JSRuntime
* rt
) : Base(rt
) { }
34 explicit WeakCache(JSContext
* cx
) : Base(cx
->runtime()) { }
37 // Sweep all entries which have unmarked key or value.
38 void sweep(FreeOp
* fop
) {
39 // Remove all entries whose keys/values remain unmarked.
40 for (Enum
e(*this); !e
.empty(); e
.popFront()) {
41 // Checking IsMarked() may update the location of the Key (or Value).
42 // Pass in a stack local, then manually update the backing heap store.
44 bool isKeyDying
= gc::IsAboutToBeFinalized(&k
);
46 if (isKeyDying
|| gc::IsAboutToBeFinalized(e
.front().value
)) {
49 // Potentially update the location of the Key.
50 // The Value had its heap addresses correctly passed to IsMarked(),
51 // and therefore has already been updated if necessary.
57 // Once we've swept, all remaining edges should stay within the
58 // known-live part of the graph.
59 for (Range r
= Base::all(); !r
.empty(); r
.popFront()) {
62 JS_ASSERT(!gc::IsAboutToBeFinalized(&k
));
63 JS_ASSERT(!gc::IsAboutToBeFinalized(r
.front().value
));
65 // Assert that IsMarked() did not perform relocation.
66 JS_ASSERT(k
== r
.front().key
);
72 // A WeakValueCache is similar to a WeakCache, except keys are never marked.
73 // This is useful for weak maps where the keys are primitive values such as uint32_t.
74 template <class Key
, class Value
,
75 class HashPolicy
= DefaultHasher
<Key
>,
76 class AllocPolicy
= RuntimeAllocPolicy
>
77 class WeakValueCache
: public HashMap
<Key
, Value
, HashPolicy
, AllocPolicy
>
80 typedef HashMap
<Key
, Value
, HashPolicy
, AllocPolicy
> Base
;
81 typedef typename
Base::Range Range
;
82 typedef typename
Base::Enum Enum
;
84 explicit WeakValueCache(JSRuntime
* rt
) : Base(rt
) { }
85 explicit WeakValueCache(JSContext
* cx
) : Base(cx
->runtime()) { }
88 // Sweep all entries which have unmarked key or value.
89 void sweep(FreeOp
* fop
) {
90 // Remove all entries whose values remain unmarked.
91 for (Enum
e(*this); !e
.empty(); e
.popFront()) {
92 if (gc::IsAboutToBeFinalized(e
.front().value()))
97 // Once we've swept, all remaining edges should stay within the
98 // known-live part of the graph.
99 for (Range r
= Base::all(); !r
.empty(); r
.popFront())
100 JS_ASSERT(!gc::IsAboutToBeFinalized(r
.front().value()));
107 #endif /* jsweakcache_h */