summaryrefslogtreecommitdiffstats
path: root/WebCore/bindings/v8/DOMDataStore.h
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/bindings/v8/DOMDataStore.h')
-rw-r--r--WebCore/bindings/v8/DOMDataStore.h169
1 files changed, 165 insertions, 4 deletions
diff --git a/WebCore/bindings/v8/DOMDataStore.h b/WebCore/bindings/v8/DOMDataStore.h
index b127089..54a49e7 100644
--- a/WebCore/bindings/v8/DOMDataStore.h
+++ b/WebCore/bindings/v8/DOMDataStore.h
@@ -32,6 +32,7 @@
#define DOMDataStore_h
#include "DOMObjectsInclude.h"
+#include "V8Node.h"
#include <v8.h>
#include <wtf/HashMap.h>
@@ -49,6 +50,95 @@ namespace WebCore {
typedef WTF::Vector<DOMDataStore*> DOMDataList;
+ 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(typename Traits::Visitor* visitor)
+ {
+ if (!m_chunks)
+ return;
+
+ visitEntries(m_chunks->m_entries, m_current, visitor);
+ for (Chunk* chunk = m_chunks->m_previous; chunk; chunk = chunk->m_previous)
+ visitEntries(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(T* first, T* last, typename Traits::Visitor* visitor)
+ {
+ for (T* entry = first; entry < last; entry++)
+ Traits::visit(entry, visitor);
+ }
+
+ Chunk* m_chunks;
+ T* m_current;
+ T* m_last;
+ };
+
// DOMDataStore
//
// DOMDataStore is the backing store that holds the maps between DOM objects
@@ -82,12 +172,83 @@ namespace WebCore {
forgetDelayedObject(m_domData, object);
}
- void forgetOnly(KeyType* object) { DOMWrapperMap<KeyType>::forget(object); }
-
private:
DOMData* m_domData;
};
+ 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(Visitor* visitor)
+ {
+ m_table.visit(visitor);
+ }
+
+ virtual bool removeIfPresent(Node* key, v8::Persistent<v8::Data> value);
+
+ 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(v8::Persistent<v8::Object>* entry, Visitor* visitor)
+ {
+ Node* node = V8Node::toNative(*entry);
+ ASSERT(node->wrapper() == entry);
+
+ visitor->visitDOMWrapper(node, *entry);
+ }
+ };
+
+ typedef ChunkedTable<v8::Persistent<v8::Object>, numberOfEntries, ChunkedTableTraits> Table;
+ Table m_table;
+ };
+
DOMDataStore(DOMData*);
virtual ~DOMDataStore();
@@ -104,7 +265,7 @@ namespace WebCore {
void* getDOMWrapperMap(DOMWrapperMapType);
- InternalDOMWrapperMap<Node>& domNodeMap() { return *m_domNodeMap; }
+ DOMNodeMapping& domNodeMap() { return *m_domNodeMap; }
InternalDOMWrapperMap<void>& domObjectMap() { return *m_domObjectMap; }
InternalDOMWrapperMap<void>& activeDomObjectMap() { return *m_activeDomObjectMap; }
#if ENABLE(SVG)
@@ -124,7 +285,7 @@ namespace WebCore {
static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
#endif
- InternalDOMWrapperMap<Node>* m_domNodeMap;
+ DOMNodeMapping* m_domNodeMap;
InternalDOMWrapperMap<void>* m_domObjectMap;
InternalDOMWrapperMap<void>* m_activeDomObjectMap;
#if ENABLE(SVG)