summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/bindings/v8/IntrusiveDOMWrapperMap.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/bindings/v8/IntrusiveDOMWrapperMap.h')
-rw-r--r--Source/WebCore/bindings/v8/IntrusiveDOMWrapperMap.h217
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