1/*
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 */
26
27#ifndef WTFThreadData_h
28#define WTFThreadData_h
29
30#include <wtf/HashMap.h>
31#include <wtf/HashSet.h>
32#include <wtf/Noncopyable.h>
33#include <wtf/StackBounds.h>
34#include <wtf/text/StringHash.h>
35
36// This was ENABLE(WORKERS) in WebCore, but this is not defined when compiling JSC.
37// However this check was not correct anyway, re this comment:
38//    // FIXME: Workers are not necessarily the only feature that make per-thread global data necessary.
39//    // We need to check for e.g. database objects manipulating strings on secondary threads.
40// Always enabling this is safe, and should be a better option until we can come up
41// with a better define.
42#define WTFTHREADDATA_MULTITHREADED 1
43
44#if WTFTHREADDATA_MULTITHREADED
45#include <wtf/ThreadSpecific.h>
46#include <wtf/Threading.h>
47#endif
48
49#if USE(JSC)
50// FIXME: This is a temporary layering violation while we move more string code to WTF.
51namespace JSC {
52
53typedef HashMap<const char*, RefPtr<StringImpl>, PtrHash<const char*> > LiteralIdentifierTable;
54
55class IdentifierTable {
56    WTF_MAKE_FAST_ALLOCATED;
57public:
58    ~IdentifierTable();
59
60    std::pair<HashSet<StringImpl*>::iterator, bool> add(StringImpl* value);
61    template<typename U, typename V>
62    std::pair<HashSet<StringImpl*>::iterator, bool> add(U value);
63
64    bool remove(StringImpl* r)
65    {
66        HashSet<StringImpl*>::iterator iter = m_table.find(r);
67        if (iter == m_table.end())
68            return false;
69        m_table.remove(iter);
70        return true;
71    }
72
73    LiteralIdentifierTable& literalTable() { return m_literalTable; }
74
75private:
76    HashSet<StringImpl*> m_table;
77    LiteralIdentifierTable m_literalTable;
78};
79
80}
81#endif
82
83namespace WTF {
84
85class AtomicStringTable;
86
87typedef void (*AtomicStringTableDestructor)(AtomicStringTable*);
88
89class WTFThreadData {
90    WTF_MAKE_NONCOPYABLE(WTFThreadData);
91public:
92    WTFThreadData();
93    ~WTFThreadData();
94
95    AtomicStringTable* atomicStringTable()
96    {
97        return m_atomicStringTable;
98    }
99
100#if USE(JSC)
101    JSC::IdentifierTable* currentIdentifierTable()
102    {
103        return m_currentIdentifierTable;
104    }
105
106    JSC::IdentifierTable* setCurrentIdentifierTable(JSC::IdentifierTable* identifierTable)
107    {
108        JSC::IdentifierTable* oldIdentifierTable = m_currentIdentifierTable;
109        m_currentIdentifierTable = identifierTable;
110        return oldIdentifierTable;
111    }
112
113    void resetCurrentIdentifierTable()
114    {
115        m_currentIdentifierTable = m_defaultIdentifierTable;
116    }
117
118    const StackBounds& stack() const
119    {
120        return m_stackBounds;
121    }
122#endif
123
124private:
125    AtomicStringTable* m_atomicStringTable;
126    AtomicStringTableDestructor m_atomicStringTableDestructor;
127
128#if USE(JSC)
129    JSC::IdentifierTable* m_defaultIdentifierTable;
130    JSC::IdentifierTable* m_currentIdentifierTable;
131    StackBounds m_stackBounds;
132#endif
133
134#if WTFTHREADDATA_MULTITHREADED
135    static JS_EXPORTDATA ThreadSpecific<WTFThreadData>* staticData;
136#else
137    static JS_EXPORTDATA WTFThreadData* staticData;
138#endif
139    friend WTFThreadData& wtfThreadData();
140    friend class AtomicStringTable;
141};
142
143inline WTFThreadData& wtfThreadData()
144{
145#if WTFTHREADDATA_MULTITHREADED
146    // WRT WebCore:
147    //    WTFThreadData is used on main thread before it could possibly be used
148    //    on secondary ones, so there is no need for synchronization here.
149    // WRT JavaScriptCore:
150    //    wtfThreadData() is initially called from initializeThreading(), ensuring
151    //    this is initially called in a pthread_once locked context.
152    if (!WTFThreadData::staticData)
153        WTFThreadData::staticData = new ThreadSpecific<WTFThreadData>;
154    return **WTFThreadData::staticData;
155#else
156    if (!WTFThreadData::staticData) {
157        WTFThreadData::staticData = static_cast<WTFThreadData*>(fastMalloc(sizeof(WTFThreadData)));
158        // WTFThreadData constructor indirectly uses staticData, so we need to set up the memory before invoking it.
159        new (WTFThreadData::staticData) WTFThreadData;
160    }
161    return *WTFThreadData::staticData;
162#endif
163}
164
165} // namespace WTF
166
167using WTF::WTFThreadData;
168using WTF::wtfThreadData;
169
170#endif // WTFThreadData_h
171