PageRenderTime 61ms CodeModel.GetById 11ms app.highlight 45ms RepoModel.GetById 1ms app.codeStats 0ms

/platform/external/webkit/WebCore/bindings/v8/DOMDataStore.h

https://github.com/aharish/totoro-gb-opensource-update2
C Header | 303 lines | 209 code | 49 blank | 45 comment | 18 complexity | 88d4194d6df1a15dd7983abf1c6de888 MD5 | raw file
  1/*
  2 * Copyright (C) 2009 Google 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 are
  6 * met:
  7 *
  8 *     * Redistributions of source code must retain the above copyright
  9 * notice, this list of conditions and the following disclaimer.
 10 *     * Redistributions in binary form must reproduce the above
 11 * copyright notice, this list of conditions and the following disclaimer
 12 * in the documentation and/or other materials provided with the
 13 * distribution.
 14 *     * Neither the name of Google Inc. nor the names of its
 15 * contributors may be used to endorse or promote products derived from
 16 * this software without specific prior written permission.
 17 *
 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 29 */
 30
 31#ifndef DOMDataStore_h
 32#define DOMDataStore_h
 33
 34#include "DOMObjectsInclude.h"
 35#include "V8Node.h"
 36
 37#include <v8.h>
 38#include <wtf/HashMap.h>
 39#include <wtf/MainThread.h>
 40#include <wtf/Noncopyable.h>
 41#include <wtf/OwnPtr.h>
 42#include <wtf/StdLibExtras.h>
 43#include <wtf/Threading.h>
 44#include <wtf/ThreadSpecific.h>
 45#include <wtf/Vector.h>
 46
 47namespace WebCore {
 48
 49    class DOMData;
 50
 51    typedef WTF::Vector<DOMDataStore*> DOMDataList;
 52
 53    template <class T, int CHUNK_SIZE, class Traits>
 54    class ChunkedTable {
 55      public:
 56        ChunkedTable() : m_chunks(0), m_current(0), m_last(0) { }
 57
 58        T* add(T element)
 59        {
 60            if (m_current == m_last) {
 61                m_chunks = new Chunk(m_chunks);
 62                m_current = m_chunks->m_entries;
 63                m_last = m_current + CHUNK_SIZE;
 64            }
 65            ASSERT((m_chunks->m_entries <= m_current) && (m_current < m_last));
 66            T* p = m_current++;
 67            *p = element;
 68            return p;
 69        }
 70
 71        void remove(T* element)
 72        {
 73            ASSERT(element);
 74            ASSERT(m_current > m_chunks->m_entries);
 75            m_current--;
 76            if (element != m_current)
 77                Traits::move(element, m_current);
 78            if (m_current == m_chunks->m_entries) {
 79                Chunk* toDelete = m_chunks;
 80                m_chunks = toDelete->m_previous;
 81                m_current = m_last = m_chunks ? m_chunks->m_entries + CHUNK_SIZE : 0;
 82                delete toDelete;
 83            }
 84            ASSERT(!m_chunks || ((m_chunks->m_entries < m_current) && (m_current <= m_last)));
 85        }
 86
 87        void clear()
 88        {
 89            if (!m_chunks)
 90                return;
 91
 92            clearEntries(m_chunks->m_entries, m_current);
 93            Chunk* last = m_chunks;
 94            while (true) {
 95                Chunk* previous = last->m_previous;
 96                if (!previous)
 97                    break;
 98                delete last;
 99                clearEntries(previous->m_entries, previous->m_entries + CHUNK_SIZE);
100                last = previous;
101            }
102
103            m_chunks = last;
104            m_current = m_chunks->m_entries;
105            m_last = m_current + CHUNK_SIZE;
106        }
107
108        void visit(typename Traits::Visitor* visitor)
109        {
110            if (!m_chunks)
111                return;
112
113            visitEntries(m_chunks->m_entries, m_current, visitor);
114            for (Chunk* chunk = m_chunks->m_previous; chunk; chunk = chunk->m_previous)
115                visitEntries(chunk->m_entries, chunk->m_entries + CHUNK_SIZE, visitor);
116        }
117
118      private:
119        struct Chunk {
120            explicit Chunk(Chunk* previous) : m_previous(previous) { }
121            Chunk* const m_previous;
122            T m_entries[CHUNK_SIZE];
123        };
124
125        static void clearEntries(T* first, T* last)
126        {
127            for (T* entry = first; entry < last; entry++)
128                Traits::clear(entry);
129        }
130
131        static void visitEntries(T* first, T* last, typename Traits::Visitor* visitor)
132        {
133            for (T* entry = first; entry < last; entry++)
134                Traits::visit(entry, visitor);
135        }
136
137        Chunk* m_chunks;
138        T* m_current;
139        T* m_last;
140    };
141
142    // DOMDataStore
143    //
144    // DOMDataStore is the backing store that holds the maps between DOM objects
145    // and JavaScript objects.  In general, each thread can have multiple backing
146    // stores, one per isolated world.
147    //
148    // This class doesn't manage the lifetime of the store.  The data store
149    // lifetime is managed by subclasses.
150    //
151    class DOMDataStore : public Noncopyable {
152    public:
153        enum DOMWrapperMapType {
154            DOMNodeMap,
155            DOMObjectMap,
156            ActiveDOMObjectMap,
157#if ENABLE(SVG)
158            DOMSVGElementInstanceMap,
159            DOMSVGObjectWithContextMap
160#endif
161        };
162
163        template <class KeyType>
164        class InternalDOMWrapperMap : public DOMWrapperMap<KeyType> {
165        public:
166            InternalDOMWrapperMap(DOMData* domData, v8::WeakReferenceCallback callback)
167                : DOMWrapperMap<KeyType>(callback), m_domData(domData) { }
168
169            virtual void forget(KeyType* object)
170            {
171                DOMWrapperMap<KeyType>::forget(object);
172                forgetDelayedObject(m_domData, object);
173            }
174
175        private:
176            DOMData* m_domData;
177        };
178
179        class IntrusiveDOMWrapperMap : public AbstractWeakReferenceMap<Node, v8::Object> {
180        public:
181            IntrusiveDOMWrapperMap(v8::WeakReferenceCallback callback)
182                : AbstractWeakReferenceMap<Node, v8::Object>(callback) { }
183
184            virtual v8::Persistent<v8::Object> get(Node* obj)
185            {
186                v8::Persistent<v8::Object>* wrapper = obj->wrapper();
187                return wrapper ? *wrapper : v8::Persistent<v8::Object>();
188            }
189
190            virtual void set(Node* obj, v8::Persistent<v8::Object> wrapper)
191            {
192                ASSERT(obj);
193                ASSERT(!obj->wrapper());
194                v8::Persistent<v8::Object>* entry = m_table.add(wrapper);
195                obj->setWrapper(entry);
196                wrapper.MakeWeak(obj, weakReferenceCallback());
197            }
198
199            virtual bool contains(Node* obj)
200            {
201                return obj->wrapper();
202            }
203
204            virtual void visit(Visitor* visitor)
205            {
206                m_table.visit(visitor);
207            }
208
209            virtual bool removeIfPresent(Node* key, v8::Persistent<v8::Data> value);
210
211            virtual void clear()
212            {
213                m_table.clear();
214            }
215
216        private:
217            static int const numberOfEntries = (1 << 10) - 1;
218
219            struct ChunkedTableTraits {
220                typedef IntrusiveDOMWrapperMap::Visitor Visitor;
221
222                static void move(v8::Persistent<v8::Object>* target, v8::Persistent<v8::Object>* source)
223                {
224                    *target = *source;
225                    Node* node = V8Node::toNative(*target);
226                    ASSERT(node);
227                    node->setWrapper(target);
228                }
229
230                static void clear(v8::Persistent<v8::Object>* entry)
231                {
232                    Node* node = V8Node::toNative(*entry);
233                    ASSERT(node->wrapper() == entry);
234
235                    node->clearWrapper();
236                    entry->Dispose();
237                }
238
239                static void visit(v8::Persistent<v8::Object>* entry, Visitor* visitor)
240                {
241                    Node* node = V8Node::toNative(*entry);
242                    ASSERT(node->wrapper() == entry);
243
244                    visitor->visitDOMWrapper(node, *entry);
245                }
246            };
247
248            typedef ChunkedTable<v8::Persistent<v8::Object>, numberOfEntries, ChunkedTableTraits> Table;
249            Table m_table;
250        };
251
252        DOMDataStore(DOMData*);
253        virtual ~DOMDataStore();
254
255        // A list of all DOMDataStore objects.  Traversed during GC to find a thread-specific map that
256        // contains the object - so we can schedule the object to be deleted on the thread which created it.
257        static DOMDataList& allStores();
258        // Mutex to protect against concurrent access of DOMDataList.
259        static WTF::Mutex& allStoresMutex();
260
261        // Helper function to avoid circular includes.
262        static void forgetDelayedObject(DOMData*, void* object);
263
264        DOMData* domData() const { return m_domData; }
265
266        void* getDOMWrapperMap(DOMWrapperMapType);
267
268        DOMNodeMapping& domNodeMap() { return *m_domNodeMap; }
269        InternalDOMWrapperMap<void>& domObjectMap() { return *m_domObjectMap; }
270        InternalDOMWrapperMap<void>& activeDomObjectMap() { return *m_activeDomObjectMap; }
271#if ENABLE(SVG)
272        InternalDOMWrapperMap<SVGElementInstance>& domSvgElementInstanceMap() { return *m_domSvgElementInstanceMap; }
273        InternalDOMWrapperMap<void>& domSvgObjectWithContextMap() { return *m_domSvgObjectWithContextMap; }
274#endif
275
276        // Need by V8GCController.
277        static void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
278
279    protected:
280        static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
281        static void weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
282#if ENABLE(SVG)
283        static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
284        // SVG non-node elements may have a reference to a context node which should be notified when the element is change.
285        static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
286#endif
287        
288        DOMNodeMapping* m_domNodeMap;
289        InternalDOMWrapperMap<void>* m_domObjectMap;
290        InternalDOMWrapperMap<void>* m_activeDomObjectMap;
291#if ENABLE(SVG)
292        InternalDOMWrapperMap<SVGElementInstance>* m_domSvgElementInstanceMap;
293        InternalDOMWrapperMap<void>* m_domSvgObjectWithContextMap;
294#endif
295
296    private:
297        // A back-pointer to the DOMData to which we belong.
298        DOMData* m_domData;
299    };
300
301} // namespace WebCore
302
303#endif // DOMDataStore_h