js/src/jsweakcache.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/jsweakcache.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,107 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef jsweakcache_h
    1.11 +#define jsweakcache_h
    1.12 +
    1.13 +#include "jscntxt.h"
    1.14 +#include "gc/Marking.h"
    1.15 +#include "js/HashTable.h"
    1.16 +#include "vm/Runtime.h"
    1.17 +
    1.18 +namespace js {
    1.19 +
    1.20 +// A WeakCache is used to map a key to a value similar to an HashMap except
    1.21 +// that its entries are garbage collected.  An entry is kept as long as
    1.22 +// both the key and value are marked.
    1.23 +//
    1.24 +// No mark function is provided with this weak container.  However, this weak
    1.25 +// container should take part in the sweep phase.
    1.26 +template <class Key, class Value,
    1.27 +          class HashPolicy = DefaultHasher<Key>,
    1.28 +          class AllocPolicy = RuntimeAllocPolicy>
    1.29 +class WeakCache : public HashMap<Key, Value, HashPolicy, AllocPolicy> {
    1.30 +  private:
    1.31 +    typedef HashMap<Key, Value, HashPolicy, AllocPolicy> Base;
    1.32 +    typedef typename Base::Range Range;
    1.33 +    typedef typename Base::Enum Enum;
    1.34 +
    1.35 +  public:
    1.36 +    explicit WeakCache(JSRuntime *rt) : Base(rt) { }
    1.37 +    explicit WeakCache(JSContext *cx) : Base(cx->runtime()) { }
    1.38 +
    1.39 +  public:
    1.40 +    // Sweep all entries which have unmarked key or value.
    1.41 +    void sweep(FreeOp *fop) {
    1.42 +        // Remove all entries whose keys/values remain unmarked.
    1.43 +        for (Enum e(*this); !e.empty(); e.popFront()) {
    1.44 +            // Checking IsMarked() may update the location of the Key (or Value).
    1.45 +            // Pass in a stack local, then manually update the backing heap store.
    1.46 +            Key k(e.front().key);
    1.47 +            bool isKeyDying = gc::IsAboutToBeFinalized(&k);
    1.48 +
    1.49 +            if (isKeyDying || gc::IsAboutToBeFinalized(e.front().value)) {
    1.50 +                e.removeFront();
    1.51 +            } else {
    1.52 +                // Potentially update the location of the Key.
    1.53 +                // The Value had its heap addresses correctly passed to IsMarked(),
    1.54 +                // and therefore has already been updated if necessary.
    1.55 +                // e.rekeyFront(k);
    1.56 +            }
    1.57 +        }
    1.58 +
    1.59 +#if DEBUG
    1.60 +        // Once we've swept, all remaining edges should stay within the
    1.61 +        // known-live part of the graph.
    1.62 +        for (Range r = Base::all(); !r.empty(); r.popFront()) {
    1.63 +            Key k(r.front().key);
    1.64 +
    1.65 +            JS_ASSERT(!gc::IsAboutToBeFinalized(&k));
    1.66 +            JS_ASSERT(!gc::IsAboutToBeFinalized(r.front().value));
    1.67 +
    1.68 +            // Assert that IsMarked() did not perform relocation.
    1.69 +            JS_ASSERT(k == r.front().key);
    1.70 +        }
    1.71 +#endif
    1.72 +    }
    1.73 +};
    1.74 +
    1.75 +// A WeakValueCache is similar to a WeakCache, except keys are never marked.
    1.76 +// This is useful for weak maps where the keys are primitive values such as uint32_t.
    1.77 +template <class Key, class Value,
    1.78 +          class HashPolicy = DefaultHasher<Key>,
    1.79 +          class AllocPolicy = RuntimeAllocPolicy>
    1.80 +class WeakValueCache : public HashMap<Key, Value, HashPolicy, AllocPolicy>
    1.81 +{
    1.82 +  public:
    1.83 +    typedef HashMap<Key, Value, HashPolicy, AllocPolicy> Base;
    1.84 +    typedef typename Base::Range Range;
    1.85 +    typedef typename Base::Enum Enum;
    1.86 +
    1.87 +    explicit WeakValueCache(JSRuntime *rt) : Base(rt) { }
    1.88 +    explicit WeakValueCache(JSContext *cx) : Base(cx->runtime()) { }
    1.89 +
    1.90 +  public:
    1.91 +    // Sweep all entries which have unmarked key or value.
    1.92 +    void sweep(FreeOp *fop) {
    1.93 +        // Remove all entries whose values remain unmarked.
    1.94 +        for (Enum e(*this); !e.empty(); e.popFront()) {
    1.95 +            if (gc::IsAboutToBeFinalized(e.front().value()))
    1.96 +                e.removeFront();
    1.97 +        }
    1.98 +
    1.99 +#if DEBUG
   1.100 +        // Once we've swept, all remaining edges should stay within the
   1.101 +        // known-live part of the graph.
   1.102 +        for (Range r = Base::all(); !r.empty(); r.popFront())
   1.103 +            JS_ASSERT(!gc::IsAboutToBeFinalized(r.front().value()));
   1.104 +#endif
   1.105 +    }
   1.106 +};
   1.107 +
   1.108 +} // namespace js
   1.109 +
   1.110 +#endif /* jsweakcache_h */

mercurial