File: CallbackStack.h

package info (click to toggle)
chromium-browser 41.0.2272.118-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 2,189,132 kB
  • sloc: cpp: 9,691,462; ansic: 3,341,451; python: 712,689; asm: 518,779; xml: 208,926; java: 169,820; sh: 119,353; perl: 68,907; makefile: 28,311; yacc: 13,305; objc: 11,385; tcl: 3,186; cs: 2,225; sql: 2,217; lex: 2,215; lisp: 1,349; pascal: 1,256; awk: 407; ruby: 155; sed: 53; php: 14; exp: 11
file content (143 lines) | stat: -rw-r--r-- 3,249 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CallbackStack_h
#define CallbackStack_h

#include "platform/heap/ThreadState.h"

namespace blink {

// The CallbackStack contains all the visitor callbacks used to trace and mark
// objects. A specific CallbackStack instance contains at most bufferSize elements.
// If more space is needed a new CallbackStack instance is created and chained
// together with the former instance. I.e. a logical CallbackStack can be made of
// multiple chained CallbackStack object instances.
class CallbackStack {
public:
    class Item {
    public:
        Item() { }
        Item(void* object, VisitorCallback callback)
            : m_object(object)
            , m_callback(callback)
        {
        }
        void* object() { return m_object; }
        VisitorCallback callback() { return m_callback; }
        void call(Visitor* visitor) { m_callback(visitor, m_object); }

    private:
        void* m_object;
        VisitorCallback m_callback;
    };

    CallbackStack();
    ~CallbackStack();

    void clear();

    Item* allocateEntry();
    Item* pop();

    bool isEmpty() const;

    void invokeEphemeronCallbacks(Visitor*);

#if ENABLE(ASSERT)
    bool hasCallbackForObject(const void*);
#endif

    static const size_t blockSize = 8192;

private:
    class Block {
    public:
        explicit Block(Block* next)
            : m_limit(&(m_buffer[blockSize]))
            , m_current(&(m_buffer[0]))
            , m_next(next)
        {
            clearUnused();
        }

        ~Block()
        {
            clearUnused();
        }

        void clear();

        Block* next() const { return m_next; }
        void setNext(Block* next) { m_next = next; }

        bool isEmptyBlock() const
        {
            return m_current == &(m_buffer[0]);
        }

        size_t size() const
        {
            return blockSize - (m_limit - m_current);
        }

        Item* allocateEntry()
        {
            if (LIKELY(m_current < m_limit))
                return m_current++;
            return 0;
        }

        Item* pop()
        {
            if (UNLIKELY(isEmptyBlock()))
                return 0;
            return --m_current;
        }

        void invokeEphemeronCallbacks(Visitor*);
#if ENABLE(ASSERT)
        bool hasCallbackForObject(const void*);
#endif

    private:
        void clearUnused();

        Item m_buffer[blockSize];
        Item* m_limit;
        Item* m_current;
        Block* m_next;
    };

    Item* popSlow();
    Item* allocateEntrySlow();
    void invokeOldestCallbacks(Block*, Block*, Visitor*);
    bool hasJustOneBlock() const;
    void swap(CallbackStack* other);

    Block* m_first;
    Block* m_last;
};

ALWAYS_INLINE CallbackStack::Item* CallbackStack::allocateEntry()
{
    Item* item = m_first->allocateEntry();
    if (LIKELY(!!item))
        return item;

    return allocateEntrySlow();
}

ALWAYS_INLINE CallbackStack::Item* CallbackStack::pop()
{
    Item* item = m_first->pop();
    if (LIKELY(!!item))
        return item;

    return popSlow();
}

} // namespace blink

#endif // CallbackStack_h