PageRenderTime 35ms CodeModel.GetById 15ms app.highlight 16ms RepoModel.GetById 2ms app.codeStats 0ms

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

https://github.com/aharish/totoro-gb-opensource-update2
C++ | 209 lines | 110 code | 23 blank | 76 comment | 7 complexity | 0dd5080bfc0b839dee29c04f24dce0e5 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#include "config.h"
 32#include "DOMDataStore.h"
 33
 34#include "DOMData.h"
 35
 36namespace WebCore {
 37
 38// DOM binding algorithm:
 39//
 40// There are two kinds of DOM objects:
 41// 1. DOM tree nodes, such as Document, HTMLElement, ...
 42//    there classes implement TreeShared<T> interface;
 43// 2. Non-node DOM objects, such as CSSRule, Location, etc.
 44//    these classes implement a ref-counted scheme.
 45//
 46// A DOM object may have a JS wrapper object. If a tree node
 47// is alive, its JS wrapper must be kept alive even it is not
 48// reachable from JS roots.
 49// However, JS wrappers of non-node objects can go away if
 50// not reachable from other JS objects. It works like a cache.
 51//
 52// DOM objects are ref-counted, and JS objects are traced from
 53// a set of root objects. They can create a cycle. To break
 54// cycles, we do following:
 55//   Handles from DOM objects to JS wrappers are always weak,
 56// so JS wrappers of non-node object cannot create a cycle.
 57//   Before starting a global GC, we create a virtual connection
 58// between nodes in the same tree in the JS heap. If the wrapper
 59// of one node in a tree is alive, wrappers of all nodes in
 60// the same tree are considered alive. This is done by creating
 61// object groups in GC prologue callbacks. The mark-compact
 62// collector will remove these groups after each GC.
 63//
 64// DOM objects should be deref-ed from the owning thread, not the GC thread
 65// that does not own them. In V8, GC can kick in from any thread. To ensure
 66// that DOM objects are always deref-ed from the owning thread when running
 67// V8 in multi-threading environment, we do following:
 68// 1. Maintain a thread specific DOM wrapper map for each object map.
 69//    (We're using TLS support from WTF instead of base since V8Bindings
 70//     does not depend on base. We further assume that all child threads
 71//     running V8 instances are created by WTF and thus a destructor will
 72//     be called to clean up all thread specific data.)
 73// 2. When GC happens:
 74//    2.1. If the dead object is in GC thread's map, remove the JS reference
 75//         and deref the DOM object.
 76//    2.2. Otherwise, go through all thread maps to find the owning thread.
 77//         Remove the JS reference from the owning thread's map and move the
 78//         DOM object to a delayed queue. Post a task to the owning thread
 79//         to have it deref-ed from the owning thread at later time.
 80// 3. When a thread is tearing down, invoke a cleanup routine to go through
 81//    all objects in the delayed queue and the thread map and deref all of
 82//    them.
 83
 84
 85DOMDataStore::DOMDataStore(DOMData* domData)
 86    : m_domNodeMap(0)
 87    , m_domObjectMap(0)
 88    , m_activeDomObjectMap(0)
 89#if ENABLE(SVG)
 90    , m_domSvgElementInstanceMap(0)
 91    , m_domSvgObjectWithContextMap(0)
 92#endif
 93    , m_domData(domData)
 94{
 95    WTF::MutexLocker locker(DOMDataStore::allStoresMutex());
 96    DOMDataStore::allStores().append(this);
 97}
 98
 99DOMDataStore::~DOMDataStore()
100{
101    WTF::MutexLocker locker(DOMDataStore::allStoresMutex());
102    DOMDataStore::allStores().remove(DOMDataStore::allStores().find(this));
103}
104
105DOMDataList& DOMDataStore::allStores()
106{
107  DEFINE_STATIC_LOCAL(DOMDataList, staticDOMDataList, ());
108  return staticDOMDataList;
109}
110
111WTF::Mutex& DOMDataStore::allStoresMutex()
112{
113    DEFINE_STATIC_LOCAL(WTF::Mutex, staticDOMDataListMutex, ());
114    return staticDOMDataListMutex;
115}
116
117void DOMDataStore::forgetDelayedObject(DOMData* domData, void* object)
118{
119    domData->forgetDelayedObject(object);
120}
121
122void* DOMDataStore::getDOMWrapperMap(DOMWrapperMapType type)
123{
124    switch (type) {
125    case DOMNodeMap:
126        return m_domNodeMap;
127    case DOMObjectMap:
128        return m_domObjectMap;
129    case ActiveDOMObjectMap:
130        return m_activeDomObjectMap;
131#if ENABLE(SVG)
132    case DOMSVGElementInstanceMap:
133        return m_domSvgElementInstanceMap;
134    case DOMSVGObjectWithContextMap:
135        return m_domSvgObjectWithContextMap;
136#endif
137    }
138
139    ASSERT_NOT_REACHED();
140    return 0;
141}
142
143// Called when the object is near death (not reachable from JS roots).
144// It is time to remove the entry from the table and dispose the handle.
145void DOMDataStore::weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject)
146{
147    v8::HandleScope scope;
148    ASSERT(v8Object->IsObject());
149    DOMData::handleWeakObject(DOMDataStore::DOMObjectMap, v8::Persistent<v8::Object>::Cast(v8Object), domObject);
150}
151
152void DOMDataStore::weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject)
153{
154    v8::HandleScope scope;
155    ASSERT(v8Object->IsObject());
156    DOMData::handleWeakObject(DOMDataStore::ActiveDOMObjectMap, v8::Persistent<v8::Object>::Cast(v8Object), domObject);
157}
158
159void DOMDataStore::weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject)
160{
161    ASSERT(WTF::isMainThread());
162
163    Node* node = static_cast<Node*>(domObject);
164
165    WTF::MutexLocker locker(DOMDataStore::allStoresMutex());
166    DOMDataList& list = DOMDataStore::allStores();
167    for (size_t i = 0; i < list.size(); ++i) {
168        DOMDataStore* store = list[i];
169        if (store->domNodeMap().removeIfPresent(node, v8Object)) {
170            ASSERT(store->domData()->owningThread() == WTF::currentThread());
171            node->deref();  // Nobody overrides Node::deref so it's safe
172            break;  // There might be at most one wrapper for the node in world's maps
173        }
174    }
175}
176
177bool DOMDataStore::IntrusiveDOMWrapperMap::removeIfPresent(Node* obj, v8::Persistent<v8::Data> value)
178{
179    ASSERT(obj);
180    v8::Persistent<v8::Object>* entry = obj->wrapper();
181    if (!entry)
182        return false;
183    if (*entry != value)
184        return false;
185    obj->clearWrapper();
186    m_table.remove(entry);
187    value.Dispose();
188    return true;
189}
190
191#if ENABLE(SVG)
192
193void DOMDataStore::weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject)
194{
195    v8::HandleScope scope;
196    ASSERT(v8Object->IsObject());
197    DOMData::handleWeakObject(DOMDataStore::DOMSVGElementInstanceMap, v8::Persistent<v8::Object>::Cast(v8Object), static_cast<SVGElementInstance*>(domObject));
198}
199
200void DOMDataStore::weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject)
201{
202    v8::HandleScope scope;
203    ASSERT(v8Object->IsObject());
204    DOMData::handleWeakObject(DOMDataStore::DOMSVGObjectWithContextMap, v8::Persistent<v8::Object>::Cast(v8Object), domObject);
205}
206
207#endif  // ENABLE(SVG)
208
209} // namespace WebCore