Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/js/RefCounted.h
Line
Count
Source (jump to first uncovered line)
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 js_RefCounted_h
8
#define js_RefCounted_h
9
10
#include "mozilla/Atomics.h"
11
#include "mozilla/RefCountType.h"
12
13
#include "js/Utility.h"
14
15
// These types implement the same interface as mozilla::(Atomic)RefCounted and
16
// must be used instead of mozilla::(Atomic)RefCounted for everything in
17
// SpiderMonkey. There are two reasons:
18
//  - Release() needs to call js_delete, not delete
19
//  - SpiderMonkey does not have MOZILLA_INTERNAL_API defined which can lead
20
//    to ODR violations that show up as spurious leak reports when ref-counted
21
//    types are allocated by SpiderMonkey and released by Gecko (or vice versa).
22
23
namespace js {
24
25
template <typename T>
26
class RefCounted
27
{
28
    static const MozRefCountType DEAD = 0xffffdead;
29
30
  protected:
31
    RefCounted() : mRefCnt(0) {}
32
    ~RefCounted() { MOZ_ASSERT(mRefCnt == DEAD); }
33
34
  public:
35
    void AddRef() const
36
    {
37
        MOZ_ASSERT(int32_t(mRefCnt) >= 0);
38
        ++mRefCnt;
39
    }
40
41
    void Release() const
42
    {
43
      MOZ_ASSERT(int32_t(mRefCnt) > 0);
44
      MozRefCountType cnt = --mRefCnt;
45
      if (0 == cnt) {
46
#ifdef DEBUG
47
          mRefCnt = DEAD;
48
#endif
49
          js_delete(const_cast<T*>(static_cast<const T*>(this)));
50
      }
51
    }
52
53
  private:
54
    mutable MozRefCountType mRefCnt;
55
};
56
57
template <typename T>
58
class AtomicRefCounted
59
{
60
    // On 64-bit systems, if the refcount type is small (say, 32 bits), there's
61
    // a risk that it could overflow.  So require it to be large enough.
62
63
    static_assert(sizeof(MozRefCountType) == sizeof(uintptr_t),
64
                  "You're at risk for ref count overflow.");
65
66
    static const MozRefCountType DEAD = ~MozRefCountType(0xffff) | 0xdead;
67
68
  protected:
69
0
    AtomicRefCounted() : mRefCnt(0) {}
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::Metadata>::AtomicRefCounted()
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::ElemSegment>::AtomicRefCounted()
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::ShareableBytes>::AtomicRefCounted()
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::Code>::AtomicRefCounted()
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::CompileArgs>::AtomicRefCounted()
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::DataSegment>::AtomicRefCounted()
Unexecuted instantiation: js::AtomicRefCounted<JS::WasmModule>::AtomicRefCounted()
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::Table>::AtomicRefCounted()
70
0
    ~AtomicRefCounted() { MOZ_ASSERT(mRefCnt == DEAD); }
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::ElemSegment>::~AtomicRefCounted()
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::ShareableBytes>::~AtomicRefCounted()
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::CompileArgs>::~AtomicRefCounted()
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::Metadata>::~AtomicRefCounted()
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::DataSegment>::~AtomicRefCounted()
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::Code>::~AtomicRefCounted()
Unexecuted instantiation: js::AtomicRefCounted<JS::WasmModule>::~AtomicRefCounted()
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::Table>::~AtomicRefCounted()
71
72
  public:
73
    void AddRef() const
74
0
    {
75
0
        ++mRefCnt;
76
0
        MOZ_ASSERT(mRefCnt != DEAD);
77
0
    }
Unexecuted instantiation: js::AtomicRefCounted<JS::WasmModule>::AddRef() const
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::Code>::AddRef() const
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::ShareableBytes>::AddRef() const
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::Metadata>::AddRef() const
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::ElemSegment>::AddRef() const
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::CompileArgs>::AddRef() const
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::DataSegment>::AddRef() const
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::Table>::AddRef() const
78
79
    void Release() const
80
0
    {
81
0
        MOZ_ASSERT(mRefCnt != 0);
82
0
        MozRefCountType cnt = --mRefCnt;
83
0
        if (0 == cnt) {
84
#ifdef DEBUG
85
            mRefCnt = DEAD;
86
#endif
87
            js_delete(const_cast<T*>(static_cast<const T*>(this)));
88
0
        }
89
0
    }
Unexecuted instantiation: js::AtomicRefCounted<JS::WasmModule>::Release() const
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::ShareableBytes>::Release() const
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::ElemSegment>::Release() const
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::DataSegment>::Release() const
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::Code>::Release() const
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::Metadata>::Release() const
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::CompileArgs>::Release() const
Unexecuted instantiation: js::AtomicRefCounted<js::wasm::Table>::Release() const
90
91
  private:
92
    mutable mozilla::Atomic<MozRefCountType> mRefCnt;
93
};
94
95
} // namespace js
96
97
#endif /* js_RefCounted_h */