/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. #ifndef DOMDataStore_h
  31. #define DOMDataStore_h
  32. #include "DOMObjectsInclude.h"
  33. #include "V8Node.h"
  34. #include <v8.h>
  35. #include <wtf/HashMap.h>
  36. #include <wtf/MainThread.h>
  37. #include <wtf/Noncopyable.h>
  38. #include <wtf/OwnPtr.h>
  39. #include <wtf/StdLibExtras.h>
  40. #include <wtf/Threading.h>
  41. #include <wtf/ThreadSpecific.h>
  42. #include <wtf/Vector.h>
  43. namespace WebCore {
  44. class DOMData;
  45. typedef WTF::Vector<DOMDataStore*> DOMDataList;
  46. template <class T, int CHUNK_SIZE, class Traits>
  47. class ChunkedTable {
  48. public:
  49. ChunkedTable() : m_chunks(0), m_current(0), m_last(0) { }
  50. T* add(T element)
  51. {
  52. if (m_current == m_last) {
  53. m_chunks = new Chunk(m_chunks);
  54. m_current = m_chunks->m_entries;
  55. m_last = m_current + CHUNK_SIZE;
  56. }
  57. ASSERT((m_chunks->m_entries <= m_current) && (m_current < m_last));
  58. T* p = m_current++;
  59. *p = element;
  60. return p;
  61. }
  62. void remove(T* element)
  63. {
  64. ASSERT(element);
  65. ASSERT(m_current > m_chunks->m_entries);
  66. m_current--;
  67. if (element != m_current)
  68. Traits::move(element, m_current);
  69. if (m_current == m_chunks->m_entries) {
  70. Chunk* toDelete = m_chunks;
  71. m_chunks = toDelete->m_previous;
  72. m_current = m_last = m_chunks ? m_chunks->m_entries + CHUNK_SIZE : 0;
  73. delete toDelete;
  74. }
  75. ASSERT(!m_chunks || ((m_chunks->m_entries < m_current) && (m_current <= m_last)));
  76. }
  77. void clear()
  78. {
  79. if (!m_chunks)
  80. return;
  81. clearEntries(m_chunks->m_entries, m_current);
  82. Chunk* last = m_chunks;
  83. while (true) {
  84. Chunk* previous = last->m_previous;
  85. if (!previous)
  86. break;
  87. delete last;
  88. clearEntries(previous->m_entries, previous->m_entries + CHUNK_SIZE);
  89. last = previous;
  90. }
  91. m_chunks = last;
  92. m_current = m_chunks->m_entries;
  93. m_last = m_current + CHUNK_SIZE;
  94. }
  95. void visit(typename Traits::Visitor* visitor)
  96. {
  97. if (!m_chunks)
  98. return;
  99. visitEntries(m_chunks->m_entries, m_current, visitor);
  100. for (Chunk* chunk = m_chunks->m_previous; chunk; chunk = chunk->m_previous)
  101. visitEntries(chunk->m_entries, chunk->m_entries + CHUNK_SIZE, visitor);
  102. }
  103. private:
  104. struct Chunk {
  105. explicit Chunk(Chunk* previous) : m_previous(previous) { }
  106. Chunk* const m_previous;
  107. T m_entries[CHUNK_SIZE];
  108. };
  109. static void clearEntries(T* first, T* last)
  110. {
  111. for (T* entry = first; entry < last; entry++)
  112. Traits::clear(entry);
  113. }
  114. static void visitEntries(T* first, T* last, typename Traits::Visitor* visitor)
  115. {
  116. for (T* entry = first; entry < last; entry++)
  117. Traits::visit(entry, visitor);
  118. }
  119. Chunk* m_chunks;
  120. T* m_current;
  121. T* m_last;
  122. };
  123. // DOMDataStore
  124. //
  125. // DOMDataStore is the backing store that holds the maps between DOM objects
  126. // and JavaScript objects. In general, each thread can have multiple backing
  127. // stores, one per isolated world.
  128. //
  129. // This class doesn't manage the lifetime of the store. The data store
  130. // lifetime is managed by subclasses.
  131. //
  132. class DOMDataStore : public Noncopyable {
  133. public:
  134. enum DOMWrapperMapType {
  135. DOMNodeMap,
  136. DOMObjectMap,
  137. ActiveDOMObjectMap,
  138. #if ENABLE(SVG)
  139. DOMSVGElementInstanceMap,
  140. DOMSVGObjectWithContextMap
  141. #endif
  142. };
  143. template <class KeyType>
  144. class InternalDOMWrapperMap : public DOMWrapperMap<KeyType> {
  145. public:
  146. InternalDOMWrapperMap(DOMData* domData, v8::WeakReferenceCallback callback)
  147. : DOMWrapperMap<KeyType>(callback), m_domData(domData) { }
  148. virtual void forget(KeyType* object)
  149. {
  150. DOMWrapperMap<KeyType>::forget(object);
  151. forgetDelayedObject(m_domData, object);
  152. }
  153. private:
  154. DOMData* m_domData;
  155. };
  156. class IntrusiveDOMWrapperMap : public AbstractWeakReferenceMap<Node, v8::Object> {
  157. public:
  158. IntrusiveDOMWrapperMap(v8::WeakReferenceCallback callback)
  159. : AbstractWeakReferenceMap<Node, v8::Object>(callback) { }
  160. virtual v8::Persistent<v8::Object> get(Node* obj)
  161. {
  162. v8::Persistent<v8::Object>* wrapper = obj->wrapper();
  163. return wrapper ? *wrapper : v8::Persistent<v8::Object>();
  164. }
  165. virtual void set(Node* obj, v8::Persistent<v8::Object> wrapper)
  166. {
  167. ASSERT(obj);
  168. ASSERT(!obj->wrapper());
  169. v8::Persistent<v8::Object>* entry = m_table.add(wrapper);
  170. obj->setWrapper(entry);
  171. wrapper.MakeWeak(obj, weakReferenceCallback());
  172. }
  173. virtual bool contains(Node* obj)
  174. {
  175. return obj->wrapper();
  176. }
  177. virtual void visit(Visitor* visitor)
  178. {
  179. m_table.visit(visitor);
  180. }
  181. virtual bool removeIfPresent(Node* key, v8::Persistent<v8::Data> value);
  182. virtual void clear()
  183. {
  184. m_table.clear();
  185. }
  186. private:
  187. static int const numberOfEntries = (1 << 10) - 1;
  188. struct ChunkedTableTraits {
  189. typedef IntrusiveDOMWrapperMap::Visitor Visitor;
  190. static void move(v8::Persistent<v8::Object>* target, v8::Persistent<v8::Object>* source)
  191. {
  192. *target = *source;
  193. Node* node = V8Node::toNative(*target);
  194. ASSERT(node);
  195. node->setWrapper(target);
  196. }
  197. static void clear(v8::Persistent<v8::Object>* entry)
  198. {
  199. Node* node = V8Node::toNative(*entry);
  200. ASSERT(node->wrapper() == entry);
  201. node->clearWrapper();
  202. entry->Dispose();
  203. }
  204. static void visit(v8::Persistent<v8::Object>* entry, Visitor* visitor)
  205. {
  206. Node* node = V8Node::toNative(*entry);
  207. ASSERT(node->wrapper() == entry);
  208. visitor->visitDOMWrapper(node, *entry);
  209. }
  210. };
  211. typedef ChunkedTable<v8::Persistent<v8::Object>, numberOfEntries, ChunkedTableTraits> Table;
  212. Table m_table;
  213. };
  214. DOMDataStore(DOMData*);
  215. virtual ~DOMDataStore();
  216. // A list of all DOMDataStore objects. Traversed during GC to find a thread-specific map that
  217. // contains the object - so we can schedule the object to be deleted on the thread which created it.
  218. static DOMDataList& allStores();
  219. // Mutex to protect against concurrent access of DOMDataList.
  220. static WTF::Mutex& allStoresMutex();
  221. // Helper function to avoid circular includes.
  222. static void forgetDelayedObject(DOMData*, void* object);
  223. DOMData* domData() const { return m_domData; }
  224. void* getDOMWrapperMap(DOMWrapperMapType);
  225. DOMNodeMapping& domNodeMap() { return *m_domNodeMap; }
  226. InternalDOMWrapperMap<void>& domObjectMap() { return *m_domObjectMap; }
  227. InternalDOMWrapperMap<void>& activeDomObjectMap() { return *m_activeDomObjectMap; }
  228. #if ENABLE(SVG)
  229. InternalDOMWrapperMap<SVGElementInstance>& domSvgElementInstanceMap() { return *m_domSvgElementInstanceMap; }
  230. InternalDOMWrapperMap<void>& domSvgObjectWithContextMap() { return *m_domSvgObjectWithContextMap; }
  231. #endif
  232. // Need by V8GCController.
  233. static void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
  234. protected:
  235. static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
  236. static void weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
  237. #if ENABLE(SVG)
  238. static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
  239. // SVG non-node elements may have a reference to a context node which should be notified when the element is change.
  240. static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject);
  241. #endif
  242. DOMNodeMapping* m_domNodeMap;
  243. InternalDOMWrapperMap<void>* m_domObjectMap;
  244. InternalDOMWrapperMap<void>* m_activeDomObjectMap;
  245. #if ENABLE(SVG)
  246. InternalDOMWrapperMap<SVGElementInstance>* m_domSvgElementInstanceMap;
  247. InternalDOMWrapperMap<void>* m_domSvgObjectWithContextMap;
  248. #endif
  249. private:
  250. // A back-pointer to the DOMData to which we belong.
  251. DOMData* m_domData;
  252. };
  253. } // namespace WebCore
  254. #endif // DOMDataStore_h