diff options
Diffstat (limited to 'Source/WebCore/bindings/v8/IntrusiveDOMWrapperMap.h')
-rw-r--r-- | Source/WebCore/bindings/v8/IntrusiveDOMWrapperMap.h | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/Source/WebCore/bindings/v8/IntrusiveDOMWrapperMap.h b/Source/WebCore/bindings/v8/IntrusiveDOMWrapperMap.h new file mode 100644 index 0000000..5c066f0 --- /dev/null +++ b/Source/WebCore/bindings/v8/IntrusiveDOMWrapperMap.h @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef IntrusiveDOMWrapperMap_h +#define IntrusiveDOMWrapperMap_h + +#include "DOMDataStore.h" +#include "V8Node.h" + +namespace WebCore { + +template <class T, int CHUNK_SIZE, class Traits> +class ChunkedTable { + public: + ChunkedTable() : m_chunks(0), m_current(0), m_last(0) { } + + T* add(T element) + { + if (m_current == m_last) { + m_chunks = new Chunk(m_chunks); + m_current = m_chunks->m_entries; + m_last = m_current + CHUNK_SIZE; + } + ASSERT((m_chunks->m_entries <= m_current) && (m_current < m_last)); + T* p = m_current++; + *p = element; + return p; + } + + void remove(T* element) + { + ASSERT(element); + ASSERT(m_current > m_chunks->m_entries); + m_current--; + if (element != m_current) + Traits::move(element, m_current); + if (m_current == m_chunks->m_entries) { + Chunk* toDelete = m_chunks; + m_chunks = toDelete->m_previous; + m_current = m_last = m_chunks ? m_chunks->m_entries + CHUNK_SIZE : 0; + delete toDelete; + } + ASSERT(!m_chunks || ((m_chunks->m_entries < m_current) && (m_current <= m_last))); + } + + void clear() + { + if (!m_chunks) + return; + + clearEntries(m_chunks->m_entries, m_current); + Chunk* last = m_chunks; + while (true) { + Chunk* previous = last->m_previous; + if (!previous) + break; + delete last; + clearEntries(previous->m_entries, previous->m_entries + CHUNK_SIZE); + last = previous; + } + + m_chunks = last; + m_current = m_chunks->m_entries; + m_last = m_current + CHUNK_SIZE; + } + + void visit(DOMDataStore* store, typename Traits::Visitor* visitor) + { + if (!m_chunks) + return; + + visitEntries(store, m_chunks->m_entries, m_current, visitor); + for (Chunk* chunk = m_chunks->m_previous; chunk; chunk = chunk->m_previous) + visitEntries(store, chunk->m_entries, chunk->m_entries + CHUNK_SIZE, visitor); + } + + private: + struct Chunk { + explicit Chunk(Chunk* previous) : m_previous(previous) { } + Chunk* const m_previous; + T m_entries[CHUNK_SIZE]; + }; + + static void clearEntries(T* first, T* last) + { + for (T* entry = first; entry < last; entry++) + Traits::clear(entry); + } + + static void visitEntries(DOMDataStore* store, T* first, T* last, typename Traits::Visitor* visitor) + { + for (T* entry = first; entry < last; entry++) + Traits::visit(store, entry, visitor); + } + + Chunk* m_chunks; + T* m_current; + T* m_last; +}; + + +class IntrusiveDOMWrapperMap : public AbstractWeakReferenceMap<Node, v8::Object> { +public: + IntrusiveDOMWrapperMap(v8::WeakReferenceCallback callback) + : AbstractWeakReferenceMap<Node, v8::Object>(callback) { } + + virtual v8::Persistent<v8::Object> get(Node* obj) + { + v8::Persistent<v8::Object>* wrapper = obj->wrapper(); + return wrapper ? *wrapper : v8::Persistent<v8::Object>(); + } + + virtual void set(Node* obj, v8::Persistent<v8::Object> wrapper) + { + ASSERT(obj); + ASSERT(!obj->wrapper()); + v8::Persistent<v8::Object>* entry = m_table.add(wrapper); + obj->setWrapper(entry); + wrapper.MakeWeak(obj, weakReferenceCallback()); + } + + virtual bool contains(Node* obj) + { + return obj->wrapper(); + } + + virtual void visit(DOMDataStore* store, Visitor* visitor) + { + m_table.visit(store, visitor); + } + + virtual bool removeIfPresent(Node* obj, v8::Persistent<v8::Object> value) + { + ASSERT(obj); + v8::Persistent<v8::Object>* entry = obj->wrapper(); + if (!entry) + return false; + if (*entry != value) + return false; + obj->clearWrapper(); + m_table.remove(entry); + value.Dispose(); + return true; + } + + + virtual void clear() + { + m_table.clear(); + } + +private: + static int const numberOfEntries = (1 << 10) - 1; + + struct ChunkedTableTraits { + typedef IntrusiveDOMWrapperMap::Visitor Visitor; + + static void move(v8::Persistent<v8::Object>* target, v8::Persistent<v8::Object>* source) + { + *target = *source; + Node* node = V8Node::toNative(*target); + ASSERT(node); + node->setWrapper(target); + } + + static void clear(v8::Persistent<v8::Object>* entry) + { + Node* node = V8Node::toNative(*entry); + ASSERT(node->wrapper() == entry); + + node->clearWrapper(); + entry->Dispose(); + } + + static void visit(DOMDataStore* store, v8::Persistent<v8::Object>* entry, Visitor* visitor) + { + Node* node = V8Node::toNative(*entry); + ASSERT(node->wrapper() == entry); + + visitor->visitDOMWrapper(store, node, *entry); + } + }; + + typedef ChunkedTable<v8::Persistent<v8::Object>, numberOfEntries, ChunkedTableTraits> Table; + Table m_table; +}; + +} // namespace WebCore + +#endif |