|
Lines 34-39
WebCore/bindings/v8/V8DOMMap.cpp_sec1
|
| 34 |
#include "DOMObjectsInclude.h" |
34 |
#include "DOMObjectsInclude.h" |
| 35 |
|
35 |
|
| 36 |
#include <v8.h> |
36 |
#include <v8.h> |
|
|
37 |
|
| 37 |
#include <wtf/HashMap.h> |
38 |
#include <wtf/HashMap.h> |
| 38 |
#include <wtf/MainThread.h> |
39 |
#include <wtf/MainThread.h> |
| 39 |
#include <wtf/Noncopyable.h> |
40 |
#include <wtf/Noncopyable.h> |
|
Lines 42-47
WebCore/bindings/v8/V8DOMMap.cpp_sec2
|
| 42 |
#include <wtf/ThreadSpecific.h> |
43 |
#include <wtf/ThreadSpecific.h> |
| 43 |
#include <wtf/Vector.h> |
44 |
#include <wtf/Vector.h> |
| 44 |
|
45 |
|
|
|
46 |
#include "V8IsolatedWorld.h" |
| 47 |
|
| 45 |
namespace WebCore { |
48 |
namespace WebCore { |
| 46 |
|
49 |
|
| 47 |
// DOM binding algorithm: |
50 |
// DOM binding algorithm: |
|
Lines 90-127
namespace WebCore {
WebCore/bindings/v8/V8DOMMap.cpp_sec3
|
| 90 |
// all objects in the delayed queue and the thread map and deref all of |
93 |
// all objects in the delayed queue and the thread map and deref all of |
| 91 |
// them. |
94 |
// them. |
| 92 |
|
95 |
|
| 93 |
static void weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject); |
|
|
| 94 |
static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject); |
96 |
static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject); |
| 95 |
|
97 |
static void weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject); |
|
|
98 |
void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject); |
| 96 |
#if ENABLE(SVG) |
99 |
#if ENABLE(SVG) |
| 97 |
static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject); |
100 |
static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject); |
| 98 |
|
|
|
| 99 |
// SVG non-node elements may have a reference to a context node which should be notified when the element is change. |
101 |
// SVG non-node elements may have a reference to a context node which should be notified when the element is change. |
| 100 |
static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject); |
102 |
static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject); |
| 101 |
#endif |
103 |
#endif |
| 102 |
|
104 |
|
| 103 |
// This is to ensure that we will deref DOM objects from the owning thread, not the GC thread. |
105 |
class DOMData; |
| 104 |
// The helper function will be scheduled by the GC thread to get called from the owning thread. |
106 |
class DOMDataStore; |
| 105 |
static void derefDelayedObjectsInCurrentThread(void*); |
107 |
typedef WTF::Vector<DOMDataStore*> DOMDataList; |
| 106 |
|
108 |
|
| 107 |
// A list of all ThreadSpecific DOM Data objects. Traversed during GC to find a thread-specific map that |
109 |
// DOMDataStore |
| 108 |
// contains the object - so we can schedule the object to be deleted on the thread which created it. |
110 |
// |
| 109 |
class ThreadSpecificDOMData; |
111 |
// DOMDataStore is the backing store that holds the maps between DOM objects |
| 110 |
typedef WTF::Vector<ThreadSpecificDOMData*> DOMDataList; |
112 |
// and JavaScript objects. In general, each thread can have multiple backing |
| 111 |
static DOMDataList& domDataList() |
113 |
// stores, one per isolated world. |
| 112 |
{ |
114 |
// |
| 113 |
DEFINE_STATIC_LOCAL(DOMDataList, staticDOMDataList, ()); |
115 |
// This class doesn't manage the lifetime of the store. The data store |
| 114 |
return staticDOMDataList; |
116 |
// lifetime is managed by subclasses. |
| 115 |
} |
117 |
// |
| 116 |
|
118 |
class DOMDataStore : Noncopyable { |
| 117 |
// Mutex to protect against concurrent access of DOMDataList. |
|
|
| 118 |
static WTF::Mutex& domDataListMutex() |
| 119 |
{ |
| 120 |
DEFINE_STATIC_LOCAL(WTF::Mutex, staticDOMDataListMutex, ()); |
| 121 |
return staticDOMDataListMutex; |
| 122 |
} |
| 123 |
|
| 124 |
class ThreadSpecificDOMData : Noncopyable { |
| 125 |
public: |
119 |
public: |
| 126 |
enum DOMWrapperMapType { |
120 |
enum DOMWrapperMapType { |
| 127 |
DOMNodeMap, |
121 |
DOMNodeMap, |
|
Lines 133-145
public:
WebCore/bindings/v8/V8DOMMap.cpp_sec4
|
| 133 |
#endif |
127 |
#endif |
| 134 |
}; |
128 |
}; |
| 135 |
|
129 |
|
| 136 |
typedef WTF::HashMap<void*, V8ClassIndex::V8WrapperType> DelayedObjectMap; |
|
|
| 137 |
|
| 138 |
template <class KeyType> |
130 |
template <class KeyType> |
| 139 |
class InternalDOMWrapperMap : public DOMWrapperMap<KeyType> { |
131 |
class InternalDOMWrapperMap : public DOMWrapperMap<KeyType> { |
| 140 |
public: |
132 |
public: |
| 141 |
InternalDOMWrapperMap(v8::WeakReferenceCallback callback) |
133 |
InternalDOMWrapperMap(DOMData* domData, v8::WeakReferenceCallback callback) |
| 142 |
: DOMWrapperMap<KeyType>(callback) { } |
134 |
: DOMWrapperMap<KeyType>(callback) |
|
|
135 |
, m_domData(domData) { } |
| 143 |
|
136 |
|
| 144 |
virtual void forget(KeyType*); |
137 |
virtual void forget(KeyType*); |
| 145 |
|
138 |
|
|
Lines 147-175
public:
WebCore/bindings/v8/V8DOMMap.cpp_sec5
|
| 147 |
{ |
140 |
{ |
| 148 |
DOMWrapperMap<KeyType>::forget(object); |
141 |
DOMWrapperMap<KeyType>::forget(object); |
| 149 |
} |
142 |
} |
|
|
143 |
|
| 144 |
private: |
| 145 |
DOMData* m_domData; |
| 150 |
}; |
146 |
}; |
| 151 |
|
147 |
|
| 152 |
ThreadSpecificDOMData() |
148 |
// A list of all DOMDataStore objects. Traversed during GC to find a thread-specific map that |
| 153 |
: m_domNodeMap(0) |
149 |
// contains the object - so we can schedule the object to be deleted on the thread which created it. |
| 154 |
, m_domObjectMap(0) |
150 |
static DOMDataList& allStores() |
| 155 |
, m_activeDomObjectMap(0) |
|
|
| 156 |
#if ENABLE(SVG) |
| 157 |
, m_domSvgElementInstanceMap(0) |
| 158 |
, m_domSvgObjectWithContextMap(0) |
| 159 |
#endif |
| 160 |
, m_delayedProcessingScheduled(false) |
| 161 |
, m_isMainThread(WTF::isMainThread()) |
| 162 |
{ |
151 |
{ |
| 163 |
WTF::MutexLocker locker(domDataListMutex()); |
152 |
DEFINE_STATIC_LOCAL(DOMDataList, staticDOMDataList, ()); |
| 164 |
domDataList().append(this); |
153 |
return staticDOMDataList; |
| 165 |
} |
154 |
} |
| 166 |
|
155 |
|
| 167 |
virtual ~ThreadSpecificDOMData() |
156 |
// Mutex to protect against concurrent access of DOMDataList. |
|
|
157 |
static WTF::Mutex& allStoresMutex() |
| 168 |
{ |
158 |
{ |
| 169 |
WTF::MutexLocker locker(domDataListMutex()); |
159 |
DEFINE_STATIC_LOCAL(WTF::Mutex, staticDOMDataListMutex, ()); |
| 170 |
domDataList().remove(domDataList().find(this)); |
160 |
return staticDOMDataListMutex; |
| 171 |
} |
161 |
} |
| 172 |
|
162 |
|
|
|
163 |
DOMDataStore(DOMData* domData); |
| 164 |
virtual ~DOMDataStore(); |
| 165 |
|
| 166 |
DOMData* domData() const { return m_domData; } |
| 167 |
|
| 173 |
void* getDOMWrapperMap(DOMWrapperMapType type) |
168 |
void* getDOMWrapperMap(DOMWrapperMapType type) |
| 174 |
{ |
169 |
{ |
| 175 |
switch (type) { |
170 |
switch (type) { |
|
Lines 199-209
public:
WebCore/bindings/v8/V8DOMMap.cpp_sec6
|
| 199 |
InternalDOMWrapperMap<void>& domSvgObjectWithContextMap() { return *m_domSvgObjectWithContextMap; } |
194 |
InternalDOMWrapperMap<void>& domSvgObjectWithContextMap() { return *m_domSvgObjectWithContextMap; } |
| 200 |
#endif |
195 |
#endif |
| 201 |
|
196 |
|
| 202 |
DelayedObjectMap& delayedObjectMap() { return m_delayedObjectMap; } |
|
|
| 203 |
bool delayedProcessingScheduled() const { return m_delayedProcessingScheduled; } |
| 204 |
void setDelayedProcessingScheduled(bool value) { m_delayedProcessingScheduled = value; } |
| 205 |
bool isMainThread() const { return m_isMainThread; } |
| 206 |
|
| 207 |
protected: |
197 |
protected: |
| 208 |
InternalDOMWrapperMap<Node>* m_domNodeMap; |
198 |
InternalDOMWrapperMap<Node>* m_domNodeMap; |
| 209 |
InternalDOMWrapperMap<void>* m_domObjectMap; |
199 |
InternalDOMWrapperMap<void>* m_domObjectMap; |
|
Lines 213-244
protected:
WebCore/bindings/v8/V8DOMMap.cpp_sec7
|
| 213 |
InternalDOMWrapperMap<void>* m_domSvgObjectWithContextMap; |
203 |
InternalDOMWrapperMap<void>* m_domSvgObjectWithContextMap; |
| 214 |
#endif |
204 |
#endif |
| 215 |
|
205 |
|
| 216 |
// Stores all the DOM objects that are delayed to be processed when the owning thread gains control. |
206 |
private: |
| 217 |
DelayedObjectMap m_delayedObjectMap; |
207 |
// A back-pointer to the DOMData to which we belong. |
| 218 |
|
208 |
DOMData* m_domData; |
| 219 |
// The flag to indicate if the task to do the delayed process has already been posted. |
|
|
| 220 |
bool m_delayedProcessingScheduled; |
| 221 |
|
| 222 |
bool m_isMainThread; |
| 223 |
}; |
209 |
}; |
| 224 |
|
210 |
|
| 225 |
// This encapsulates thread-specific DOM data for non-main thread. All the maps in it are created dynamically. |
211 |
// ScopedDOMDataStore |
| 226 |
class NonMainThreadSpecificDOMData : public ThreadSpecificDOMData { |
212 |
// |
|
|
213 |
// ScopedDOMDataStore is a DOMDataStore that controls limits the lifetime of |
| 214 |
// the store to the lifetime of the object itself. In other words, when the |
| 215 |
// ScopedDOMDataStore object is deallocated, the maps that belong to the store |
| 216 |
// are deallocated as well. |
| 217 |
// |
| 218 |
class ScopedDOMDataStore : public DOMDataStore { |
| 227 |
public: |
219 |
public: |
| 228 |
NonMainThreadSpecificDOMData() |
220 |
ScopedDOMDataStore(DOMData* domData) : DOMDataStore(domData) |
| 229 |
{ |
221 |
{ |
| 230 |
m_domNodeMap = new InternalDOMWrapperMap<Node>(&weakNodeCallback); |
222 |
m_domNodeMap = new InternalDOMWrapperMap<Node>(domData, weakNodeCallback); |
| 231 |
m_domObjectMap = new InternalDOMWrapperMap<void>(weakDOMObjectCallback); |
223 |
m_domObjectMap = new InternalDOMWrapperMap<void>(domData, weakDOMObjectCallback); |
| 232 |
m_activeDomObjectMap = new InternalDOMWrapperMap<void>(weakActiveDOMObjectCallback); |
224 |
m_activeDomObjectMap = new InternalDOMWrapperMap<void>(domData, weakActiveDOMObjectCallback); |
| 233 |
#if ENABLE(SVG) |
225 |
#if ENABLE(SVG) |
| 234 |
m_domSvgElementInstanceMap = new InternalDOMWrapperMap<SVGElementInstance>(weakSVGElementInstanceCallback); |
226 |
m_domSvgElementInstanceMap = new InternalDOMWrapperMap<SVGElementInstance>(domData, weakSVGElementInstanceCallback); |
| 235 |
m_domSvgObjectWithContextMap = new InternalDOMWrapperMap<void>(weakSVGObjectWithContextCallback); |
227 |
m_domSvgObjectWithContextMap = new InternalDOMWrapperMap<void>(domData, weakSVGObjectWithContextCallback); |
| 236 |
#endif |
228 |
#endif |
| 237 |
} |
229 |
} |
| 238 |
|
230 |
|
| 239 |
// This is called when WTF thread is tearing down. |
231 |
// This can be called when WTF thread is tearing down. |
| 240 |
// We assume that all child threads running V8 instances are created by WTF. |
232 |
// We assume that all child threads running V8 instances are created by WTF. |
| 241 |
virtual ~NonMainThreadSpecificDOMData() |
233 |
virtual ~ScopedDOMDataStore() |
| 242 |
{ |
234 |
{ |
| 243 |
delete m_domNodeMap; |
235 |
delete m_domNodeMap; |
| 244 |
delete m_domObjectMap; |
236 |
delete m_domObjectMap; |
|
Lines 250-267
public:
WebCore/bindings/v8/V8DOMMap.cpp_sec8
|
| 250 |
} |
242 |
} |
| 251 |
}; |
243 |
}; |
| 252 |
|
244 |
|
| 253 |
// This encapsulates thread-specific DOM data for the main thread. All the maps in it are static. |
245 |
// StaticDOMDataStore |
| 254 |
// This is because we are unable to rely on WTF::ThreadSpecificThreadExit to do the cleanup since |
246 |
// |
| 255 |
// the place that tears down the main thread can not call any WTF functions. |
247 |
// StaticDOMDataStore is a DOMDataStore that manages the lifetime of the store |
| 256 |
class MainThreadSpecificDOMData : public ThreadSpecificDOMData { |
248 |
// statically. This encapsulates thread-specific DOM data for the main |
|
|
249 |
// thread. All the maps in it are static. This is because we are unable to |
| 250 |
// rely on WTF::ThreadSpecificThreadExit to do the cleanup since the place that |
| 251 |
// tears down the main thread can not call any WTF functions. |
| 252 |
class StaticDOMDataStore : public DOMDataStore { |
| 257 |
public: |
253 |
public: |
| 258 |
MainThreadSpecificDOMData() |
254 |
StaticDOMDataStore(DOMData* domData) |
| 259 |
: m_staticDomNodeMap(weakNodeCallback) |
255 |
: DOMDataStore(domData) |
| 260 |
, m_staticDomObjectMap(weakDOMObjectCallback) |
256 |
, m_staticDomNodeMap(domData, weakNodeCallback) |
| 261 |
, m_staticActiveDomObjectMap(weakActiveDOMObjectCallback) |
257 |
, m_staticDomObjectMap(domData, weakDOMObjectCallback) |
|
|
258 |
, m_staticActiveDomObjectMap(domData, weakActiveDOMObjectCallback) |
| 262 |
#if ENABLE(SVG) |
259 |
#if ENABLE(SVG) |
| 263 |
, m_staticDomSvgElementInstanceMap(weakSVGElementInstanceCallback) |
260 |
, m_staticDomSvgElementInstanceMap(domData, weakSVGElementInstanceCallback) |
| 264 |
, m_staticDomSvgObjectWithContextMap(weakSVGObjectWithContextCallback) |
261 |
, m_staticDomSvgObjectWithContextMap(domData, weakSVGObjectWithContextCallback) |
| 265 |
#endif |
262 |
#endif |
| 266 |
{ |
263 |
{ |
| 267 |
m_domNodeMap = &m_staticDomNodeMap; |
264 |
m_domNodeMap = &m_staticDomNodeMap; |
|
Lines 281-378
private:
WebCore/bindings/v8/V8DOMMap.cpp_sec9
|
| 281 |
InternalDOMWrapperMap<void> m_staticDomSvgObjectWithContextMap; |
278 |
InternalDOMWrapperMap<void> m_staticDomSvgObjectWithContextMap; |
| 282 |
}; |
279 |
}; |
| 283 |
|
280 |
|
| 284 |
DEFINE_STATIC_LOCAL(WTF::ThreadSpecific<NonMainThreadSpecificDOMData>, threadSpecificDOMData, ()); |
281 |
typedef WTF::Vector<DOMDataStore*> DOMDataStoreList; |
| 285 |
|
282 |
|
| 286 |
template<typename T> |
283 |
// DOMData |
| 287 |
static void handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMWrapperMapType mapType, V8ClassIndex::V8WrapperType objectType, T*); |
284 |
// |
|
|
285 |
// DOMData represents the all the DOM wrappers for a given thread. In |
| 286 |
// particular, DOMData holds wrappers for all the isolated worlds in the |
| 287 |
// thread. The DOMData for the main thread and the DOMData for child threads |
| 288 |
// use different subclasses. |
| 289 |
// |
| 290 |
class DOMData: Noncopyable { |
| 291 |
public: |
| 292 |
DOMData() |
| 293 |
: m_delayedProcessingScheduled(false) |
| 294 |
, m_isMainThread(WTF::isMainThread()) |
| 295 |
, m_owningThread(WTF::currentThread()) |
| 296 |
{ |
| 297 |
} |
| 288 |
|
298 |
|
| 289 |
ThreadSpecificDOMData& getThreadSpecificDOMData() |
299 |
static DOMData* getCurrent(); |
| 290 |
{ |
300 |
virtual DOMDataStore& getStore() = 0; |
| 291 |
if (WTF::isMainThread()) { |
301 |
|
| 292 |
DEFINE_STATIC_LOCAL(MainThreadSpecificDOMData, mainThreadSpecificDOMData, ()); |
302 |
template<typename T> |
| 293 |
return mainThreadSpecificDOMData; |
303 |
static void handleWeakObject(DOMDataStore::DOMWrapperMapType mapType, v8::Handle<v8::Object> v8Object, T* domObject); |
|
|
304 |
|
| 305 |
void forgetDelayedObject(void* object) { m_delayedObjectMap.take(object); } |
| 306 |
|
| 307 |
// This is to ensure that we will deref DOM objects from the owning thread, |
| 308 |
// not the GC thread. The helper function will be scheduled by the GC |
| 309 |
// thread to get called from the owning thread. |
| 310 |
static void derefDelayedObjectsInCurrentThread(void*); |
| 311 |
void derefDelayedObjects(); |
| 312 |
|
| 313 |
template<typename T> |
| 314 |
static void removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap); |
| 315 |
|
| 316 |
ThreadIdentifier owningThread() const { return m_owningThread; } |
| 317 |
|
| 318 |
private: |
| 319 |
typedef WTF::HashMap<void*, V8ClassIndex::V8WrapperType> DelayedObjectMap; |
| 320 |
|
| 321 |
void ensureDeref(V8ClassIndex::V8WrapperType type, void* domObject); |
| 322 |
static void derefObject(V8ClassIndex::V8WrapperType type, void* domObject); |
| 323 |
|
| 324 |
// Stores all the DOM objects that are delayed to be processed when the owning thread gains control. |
| 325 |
DelayedObjectMap m_delayedObjectMap; |
| 326 |
|
| 327 |
// The flag to indicate if the task to do the delayed process has already been posted. |
| 328 |
bool m_delayedProcessingScheduled; |
| 329 |
|
| 330 |
bool m_isMainThread; |
| 331 |
ThreadIdentifier m_owningThread; |
| 332 |
}; |
| 333 |
|
| 334 |
class MainThreadDOMData : public DOMData { |
| 335 |
public: |
| 336 |
MainThreadDOMData() : m_defaultStore(this) { } |
| 337 |
|
| 338 |
DOMDataStore& getStore() |
| 339 |
{ |
| 340 |
ASSERT(WTF::isMainThread()); |
| 341 |
V8IsolatedWorld* world = V8IsolatedWorld::getEntered(); |
| 342 |
if (world) |
| 343 |
return *world->getDOMDataStore(); |
| 344 |
return m_defaultStore; |
| 345 |
} |
| 346 |
|
| 347 |
private: |
| 348 |
StaticDOMDataStore m_defaultStore; |
| 349 |
// Note: The DOMDataStores for isolated world are owned by the world object. |
| 350 |
}; |
| 351 |
|
| 352 |
class ChildThreadDOMData : public DOMData { |
| 353 |
public: |
| 354 |
ChildThreadDOMData() : m_defaultStore(this) { } |
| 355 |
|
| 356 |
DOMDataStore& getStore() { |
| 357 |
ASSERT(!WTF::isMainThread()); |
| 358 |
// Currently, child threads have only one world. |
| 359 |
return m_defaultStore; |
| 294 |
} |
360 |
} |
| 295 |
return *threadSpecificDOMData; |
361 |
|
|
|
362 |
private: |
| 363 |
ScopedDOMDataStore m_defaultStore; |
| 364 |
}; |
| 365 |
|
| 366 |
DOMDataStore::DOMDataStore(DOMData* domData) |
| 367 |
: m_domNodeMap(0) |
| 368 |
, m_domObjectMap(0) |
| 369 |
, m_activeDomObjectMap(0) |
| 370 |
#if ENABLE(SVG) |
| 371 |
, m_domSvgElementInstanceMap(0) |
| 372 |
, m_domSvgObjectWithContextMap(0) |
| 373 |
#endif |
| 374 |
, m_domData(domData) |
| 375 |
{ |
| 376 |
WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
| 377 |
DOMDataStore::allStores().append(this); |
| 378 |
} |
| 379 |
|
| 380 |
DOMDataStore::~DOMDataStore() |
| 381 |
{ |
| 382 |
WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
| 383 |
DOMDataStore::allStores().remove(DOMDataStore::allStores().find(this)); |
| 384 |
} |
| 385 |
|
| 386 |
DOMDataStoreHandle::DOMDataStoreHandle() |
| 387 |
: m_store(new ScopedDOMDataStore(DOMData::getCurrent())) |
| 388 |
{ |
| 389 |
} |
| 390 |
|
| 391 |
DOMDataStoreHandle::~DOMDataStoreHandle() |
| 392 |
{ |
| 296 |
} |
393 |
} |
| 297 |
|
394 |
|
| 298 |
template <class KeyType> |
395 |
template <class KeyType> |
| 299 |
void ThreadSpecificDOMData::InternalDOMWrapperMap<KeyType>::forget(KeyType* object) |
396 |
void DOMDataStore::InternalDOMWrapperMap<KeyType>::forget(KeyType* object) |
| 300 |
{ |
397 |
{ |
| 301 |
DOMWrapperMap<KeyType>::forget(object); |
398 |
DOMWrapperMap<KeyType>::forget(object); |
| 302 |
|
399 |
m_domData->forgetDelayedObject(object); |
| 303 |
ThreadSpecificDOMData::DelayedObjectMap& delayedObjectMap = getThreadSpecificDOMData().delayedObjectMap(); |
|
|
| 304 |
delayedObjectMap.take(object); |
| 305 |
} |
400 |
} |
| 306 |
|
401 |
|
| 307 |
DOMWrapperMap<Node>& getDOMNodeMap() |
402 |
DOMWrapperMap<Node>& getDOMNodeMap() |
| 308 |
{ |
403 |
{ |
| 309 |
return getThreadSpecificDOMData().domNodeMap(); |
404 |
return DOMData::getCurrent()->getStore().domNodeMap(); |
| 310 |
} |
405 |
} |
| 311 |
|
406 |
|
| 312 |
DOMWrapperMap<void>& getDOMObjectMap() |
407 |
DOMWrapperMap<void>& getDOMObjectMap() |
| 313 |
{ |
408 |
{ |
| 314 |
return getThreadSpecificDOMData().domObjectMap(); |
409 |
return DOMData::getCurrent()->getStore().domObjectMap(); |
| 315 |
} |
410 |
} |
| 316 |
|
411 |
|
| 317 |
DOMWrapperMap<void>& getActiveDOMObjectMap() |
412 |
DOMWrapperMap<void>& getActiveDOMObjectMap() |
| 318 |
{ |
413 |
{ |
| 319 |
return getThreadSpecificDOMData().activeDomObjectMap(); |
414 |
return DOMData::getCurrent()->getStore().activeDomObjectMap(); |
| 320 |
} |
415 |
} |
| 321 |
|
416 |
|
| 322 |
#if ENABLE(SVG) |
417 |
#if ENABLE(SVG) |
| 323 |
DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap() |
|
|
| 324 |
{ |
| 325 |
return getThreadSpecificDOMData().domSvgElementInstanceMap(); |
| 326 |
} |
| 327 |
|
418 |
|
| 328 |
static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject) |
419 |
DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap() |
| 329 |
{ |
420 |
{ |
| 330 |
SVGElementInstance* instance = static_cast<SVGElementInstance*>(domObject); |
421 |
return DOMData::getCurrent()->getStore().domSvgElementInstanceMap(); |
| 331 |
|
|
|
| 332 |
ThreadSpecificDOMData::InternalDOMWrapperMap<SVGElementInstance>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<SVGElementInstance>&>(getDOMSVGElementInstanceMap()); |
| 333 |
if (map.contains(instance)) { |
| 334 |
instance->deref(); |
| 335 |
map.forgetOnly(instance); |
| 336 |
} else |
| 337 |
handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMSVGElementInstanceMap, V8ClassIndex::SVGELEMENTINSTANCE, instance); |
| 338 |
} |
422 |
} |
| 339 |
|
423 |
|
| 340 |
// Map of SVG objects with contexts to V8 objects |
424 |
// Map of SVG objects with contexts to V8 objects |
| 341 |
DOMWrapperMap<void>& getDOMSVGObjectWithContextMap() |
425 |
DOMWrapperMap<void>& getDOMSVGObjectWithContextMap() |
| 342 |
{ |
426 |
{ |
| 343 |
return getThreadSpecificDOMData().domSvgObjectWithContextMap(); |
427 |
return DOMData::getCurrent()->getStore().domSvgObjectWithContextMap(); |
| 344 |
} |
428 |
} |
| 345 |
|
429 |
|
| 346 |
static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject) |
430 |
#endif // ENABLE(SVG) |
| 347 |
{ |
|
|
| 348 |
v8::HandleScope scope; |
| 349 |
ASSERT(v8Object->IsObject()); |
| 350 |
|
| 351 |
V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(v8Object)); |
| 352 |
|
| 353 |
ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getDOMSVGObjectWithContextMap()); |
| 354 |
if (map.contains(domObject)) { |
| 355 |
// The forget function removes object from the map and disposes the wrapper. |
| 356 |
map.forgetOnly(domObject); |
| 357 |
|
431 |
|
| 358 |
switch (type) { |
432 |
// static |
| 359 |
#define MakeCase(type, name) \ |
433 |
DOMData* DOMData::getCurrent() |
| 360 |
case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; |
434 |
{ |
| 361 |
SVG_OBJECT_TYPES(MakeCase) |
435 |
if (WTF::isMainThread()) { |
| 362 |
#undef MakeCase |
436 |
DEFINE_STATIC_LOCAL(MainThreadDOMData, mainThreadDOMData, ()); |
| 363 |
#define MakeCase(type, name) \ |
437 |
return &mainThreadDOMData; |
| 364 |
case V8ClassIndex::type: \ |
438 |
} |
| 365 |
static_cast<V8SVGPODTypeWrapper<name>*>(domObject)->deref(); break; |
439 |
DEFINE_STATIC_LOCAL(WTF::ThreadSpecific<ChildThreadDOMData>, childThreadDOMData, ()); |
| 366 |
SVG_POD_NATIVE_TYPES(MakeCase) |
440 |
return childThreadDOMData; |
| 367 |
#undef MakeCase |
|
|
| 368 |
default: |
| 369 |
ASSERT_NOT_REACHED(); |
| 370 |
break; |
| 371 |
} |
| 372 |
} else |
| 373 |
handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMSVGObjectWithContextMap, type, domObject); |
| 374 |
} |
441 |
} |
| 375 |
#endif // ENABLE(SVG) |
|
|
| 376 |
|
442 |
|
| 377 |
// Called when the dead object is not in GC thread's map. Go through all thread maps to find the one containing it. |
443 |
// Called when the dead object is not in GC thread's map. Go through all thread maps to find the one containing it. |
| 378 |
// Then clear the JS reference and push the DOM object into the delayed queue for it to be deref-ed at later time from the owning thread. |
444 |
// Then clear the JS reference and push the DOM object into the delayed queue for it to be deref-ed at later time from the owning thread. |
|
Lines 380-410
static void weakSVGObjectWithContextCall
WebCore/bindings/v8/V8DOMMap.cpp_sec10
|
| 380 |
// * This can be called on any thread that has GC running. |
446 |
// * This can be called on any thread that has GC running. |
| 381 |
// * Only one V8 instance is running at a time due to V8::Locker. So we don't need to worry about concurrency. |
447 |
// * Only one V8 instance is running at a time due to V8::Locker. So we don't need to worry about concurrency. |
| 382 |
template<typename T> |
448 |
template<typename T> |
| 383 |
static void handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMWrapperMapType mapType, V8ClassIndex::V8WrapperType objectType, T* object) |
449 |
// static |
|
|
450 |
void DOMData::handleWeakObject(DOMDataStore::DOMWrapperMapType mapType, v8::Handle<v8::Object> v8Object, T* domObject) |
| 384 |
{ |
451 |
{ |
| 385 |
WTF::MutexLocker locker(domDataListMutex()); |
452 |
|
| 386 |
DOMDataList& list = domDataList(); |
453 |
WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
|
|
454 |
DOMDataList& list = DOMDataStore::allStores(); |
| 387 |
for (size_t i = 0; i < list.size(); ++i) { |
455 |
for (size_t i = 0; i < list.size(); ++i) { |
| 388 |
ThreadSpecificDOMData* threadData = list[i]; |
456 |
DOMDataStore* store = list[i]; |
|
|
457 |
|
| 458 |
DOMDataStore::InternalDOMWrapperMap<T>* domMap = static_cast<DOMDataStore::InternalDOMWrapperMap<T>*>(store->getDOMWrapperMap(mapType)); |
| 389 |
|
459 |
|
| 390 |
ThreadSpecificDOMData::InternalDOMWrapperMap<T>* domMap = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<T>*>(threadData->getDOMWrapperMap(mapType)); |
460 |
v8::Handle<v8::Object> wrapper = domMap->get(domObject); |
| 391 |
if (domMap->contains(object)) { |
461 |
if (*wrapper == *v8Object) { |
| 392 |
// Clear the JS reference. |
462 |
// Clear the JS reference. |
| 393 |
domMap->forgetOnly(object); |
463 |
domMap->forgetOnly(domObject); |
|
|
464 |
store->domData()->ensureDeref(V8Proxy::GetDOMWrapperType(v8Object), domObject); |
| 465 |
} |
| 466 |
} |
| 467 |
} |
| 394 |
|
468 |
|
| 395 |
// Push into the delayed queue. |
469 |
void DOMData::ensureDeref(V8ClassIndex::V8WrapperType type, void* domObject) |
| 396 |
threadData->delayedObjectMap().set(object, objectType); |
470 |
{ |
|
|
471 |
if (m_owningThread == WTF::currentThread()) { |
| 472 |
// No need to delay the work. We can deref right now. |
| 473 |
derefObject(type, domObject); |
| 474 |
return; |
| 475 |
} |
| 397 |
|
476 |
|
| 398 |
// Post a task to the owning thread in order to process the delayed queue. |
477 |
// We need to do the deref on the correct thread. |
| 399 |
// FIXME: For now, we can only post to main thread due to WTF task posting limitation. We will fix this when we work on nested worker. |
478 |
m_delayedObjectMap.set(domObject, type); |
| 400 |
if (!threadData->delayedProcessingScheduled()) { |
|
|
| 401 |
threadData->setDelayedProcessingScheduled(true); |
| 402 |
if (threadData->isMainThread()) |
| 403 |
WTF::callOnMainThread(&derefDelayedObjectsInCurrentThread, 0); |
| 404 |
} |
| 405 |
|
479 |
|
| 406 |
break; |
480 |
// Post a task to the owning thread in order to process the delayed queue. |
| 407 |
} |
481 |
// FIXME: For now, we can only post to main thread due to WTF task posting limitation. We will fix this when we work on nested worker. |
|
|
482 |
if (!m_delayedProcessingScheduled) { |
| 483 |
m_delayedProcessingScheduled = true; |
| 484 |
if (isMainThread()) |
| 485 |
WTF::callOnMainThread(&derefDelayedObjectsInCurrentThread, 0); |
| 408 |
} |
486 |
} |
| 409 |
} |
487 |
} |
| 410 |
|
488 |
|
|
Lines 414-478
static void weakDOMObjectCallback(v8::Pe
WebCore/bindings/v8/V8DOMMap.cpp_sec11
|
| 414 |
{ |
492 |
{ |
| 415 |
v8::HandleScope scope; |
493 |
v8::HandleScope scope; |
| 416 |
ASSERT(v8Object->IsObject()); |
494 |
ASSERT(v8Object->IsObject()); |
| 417 |
|
495 |
DOMData::handleWeakObject(DOMDataStore::DOMObjectMap, v8::Handle<v8::Object>::Cast(v8Object), domObject); |
| 418 |
V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(v8Object)); |
|
|
| 419 |
|
| 420 |
ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getDOMObjectMap()); |
| 421 |
if (map.contains(domObject)) { |
| 422 |
// The forget function removes object from the map and disposes the wrapper. |
| 423 |
map.forgetOnly(domObject); |
| 424 |
|
| 425 |
switch (type) { |
| 426 |
#define MakeCase(type, name) \ |
| 427 |
case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; |
| 428 |
DOM_OBJECT_TYPES(MakeCase) |
| 429 |
#undef MakeCase |
| 430 |
default: |
| 431 |
ASSERT_NOT_REACHED(); |
| 432 |
break; |
| 433 |
} |
| 434 |
} else |
| 435 |
handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMObjectMap, type, domObject); |
| 436 |
} |
496 |
} |
| 437 |
|
497 |
|
| 438 |
void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject) |
498 |
void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject) |
| 439 |
{ |
499 |
{ |
| 440 |
v8::HandleScope scope; |
500 |
v8::HandleScope scope; |
| 441 |
ASSERT(v8Object->IsObject()); |
501 |
ASSERT(v8Object->IsObject()); |
|
|
502 |
DOMData::handleWeakObject(DOMDataStore::ActiveDOMObjectMap, v8::Handle<v8::Object>::Cast(v8Object), domObject); |
| 503 |
} |
| 442 |
|
504 |
|
| 443 |
V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(v8Object)); |
505 |
static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject) |
|
|
506 |
{ |
| 507 |
v8::HandleScope scope; |
| 508 |
ASSERT(v8Object->IsObject()); |
| 509 |
DOMData::handleWeakObject<Node>(DOMDataStore::DOMNodeMap, v8::Handle<v8::Object>::Cast(v8Object), static_cast<Node*>(domObject)); |
| 510 |
} |
| 444 |
|
511 |
|
| 445 |
ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getActiveDOMObjectMap()); |
512 |
#if ENABLE(SVG) |
| 446 |
if (map.contains(domObject)) { |
|
|
| 447 |
// The forget function removes object from the map and disposes the wrapper. |
| 448 |
map.forgetOnly(domObject); |
| 449 |
|
513 |
|
| 450 |
switch (type) { |
514 |
static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject) |
| 451 |
#define MakeCase(type, name) \ |
515 |
{ |
| 452 |
case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; |
516 |
v8::HandleScope scope; |
| 453 |
ACTIVE_DOM_OBJECT_TYPES(MakeCase) |
517 |
ASSERT(v8Object->IsObject()); |
| 454 |
#undef MakeCase |
518 |
DOMData::handleWeakObject(DOMDataStore::DOMSVGElementInstanceMap, v8::Handle<v8::Object>::Cast(v8Object), static_cast<SVGElementInstance*>(domObject)); |
| 455 |
default: |
|
|
| 456 |
ASSERT_NOT_REACHED(); |
| 457 |
break; |
| 458 |
} |
| 459 |
} else |
| 460 |
handleWeakObjectInOwningThread(ThreadSpecificDOMData::ActiveDOMObjectMap, type, domObject); |
| 461 |
} |
519 |
} |
| 462 |
|
520 |
|
| 463 |
static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject) |
521 |
static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject) |
| 464 |
{ |
522 |
{ |
| 465 |
Node* node = static_cast<Node*>(domObject); |
523 |
v8::HandleScope scope; |
| 466 |
|
524 |
ASSERT(v8Object->IsObject()); |
| 467 |
ThreadSpecificDOMData::InternalDOMWrapperMap<Node>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<Node>&>(getDOMNodeMap()); |
525 |
DOMData::handleWeakObject(DOMDataStore::DOMSVGObjectWithContextMap, v8::Handle<v8::Object>::Cast(v8Object), domObject); |
| 468 |
if (map.contains(node)) { |
|
|
| 469 |
map.forgetOnly(node); |
| 470 |
node->deref(); |
| 471 |
} else |
| 472 |
handleWeakObjectInOwningThread<Node>(ThreadSpecificDOMData::DOMNodeMap, V8ClassIndex::NODE, node); |
| 473 |
} |
526 |
} |
| 474 |
|
527 |
|
| 475 |
static void derefObject(V8ClassIndex::V8WrapperType type, void* domObject) |
528 |
#endif // ENABLE(SVG) |
|
|
529 |
|
| 530 |
// static |
| 531 |
void DOMData::derefObject(V8ClassIndex::V8WrapperType type, void* domObject) |
| 476 |
{ |
532 |
{ |
| 477 |
switch (type) { |
533 |
switch (type) { |
| 478 |
case V8ClassIndex::NODE: |
534 |
case V8ClassIndex::NODE: |
|
Lines 503-528
static void derefObject(V8ClassIndex::V8
WebCore/bindings/v8/V8DOMMap.cpp_sec12
|
| 503 |
} |
559 |
} |
| 504 |
} |
560 |
} |
| 505 |
|
561 |
|
| 506 |
static void derefDelayedObjects() |
562 |
void DOMData::derefDelayedObjects() |
| 507 |
{ |
563 |
{ |
| 508 |
WTF::MutexLocker locker(domDataListMutex()); |
564 |
WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
| 509 |
|
565 |
|
| 510 |
getThreadSpecificDOMData().setDelayedProcessingScheduled(false); |
566 |
m_delayedProcessingScheduled = false; |
| 511 |
|
567 |
|
| 512 |
ThreadSpecificDOMData::DelayedObjectMap& delayedObjectMap = getThreadSpecificDOMData().delayedObjectMap(); |
568 |
for (DelayedObjectMap::iterator iter(m_delayedObjectMap.begin()); iter != m_delayedObjectMap.end(); ++iter) |
| 513 |
for (ThreadSpecificDOMData::DelayedObjectMap::iterator iter(delayedObjectMap.begin()); iter != delayedObjectMap.end(); ++iter) { |
|
|
| 514 |
derefObject(iter->second, iter->first); |
569 |
derefObject(iter->second, iter->first); |
| 515 |
} |
570 |
|
| 516 |
delayedObjectMap.clear(); |
571 |
m_delayedObjectMap.clear(); |
| 517 |
} |
572 |
} |
| 518 |
|
573 |
|
| 519 |
static void derefDelayedObjectsInCurrentThread(void*) |
574 |
// static |
|
|
575 |
void DOMData::derefDelayedObjectsInCurrentThread(void*) |
| 520 |
{ |
576 |
{ |
| 521 |
derefDelayedObjects(); |
577 |
getCurrent()->derefDelayedObjects(); |
| 522 |
} |
578 |
} |
| 523 |
|
579 |
|
|
|
580 |
// static |
| 524 |
template<typename T> |
581 |
template<typename T> |
| 525 |
static void removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap) |
582 |
void DOMData::removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap) |
| 526 |
{ |
583 |
{ |
| 527 |
for (typename WTF::HashMap<T*, v8::Object*>::iterator iter(domMap.impl().begin()); iter != domMap.impl().end(); ++iter) { |
584 |
for (typename WTF::HashMap<T*, v8::Object*>::iterator iter(domMap.impl().begin()); iter != domMap.impl().end(); ++iter) { |
| 528 |
T* domObject = static_cast<T*>(iter->first); |
585 |
T* domObject = static_cast<T*>(iter->first); |
|
Lines 544-566
static void removeAllDOMObjectsInCurrent
WebCore/bindings/v8/V8DOMMap.cpp_sec13
|
| 544 |
v8::HandleScope scope; |
601 |
v8::HandleScope scope; |
| 545 |
|
602 |
|
| 546 |
// Deref all objects in the delayed queue. |
603 |
// Deref all objects in the delayed queue. |
| 547 |
derefDelayedObjects(); |
604 |
DOMData::getCurrent()->derefDelayedObjects(); |
| 548 |
|
605 |
|
| 549 |
// Remove all DOM nodes. |
606 |
// Remove all DOM nodes. |
| 550 |
removeObjectsFromWrapperMap<Node>(getDOMNodeMap()); |
607 |
DOMData::removeObjectsFromWrapperMap<Node>(getDOMNodeMap()); |
| 551 |
|
608 |
|
| 552 |
// Remove all DOM objects in the wrapper map. |
609 |
// Remove all DOM objects in the wrapper map. |
| 553 |
removeObjectsFromWrapperMap<void>(getDOMObjectMap()); |
610 |
DOMData::removeObjectsFromWrapperMap<void>(getDOMObjectMap()); |
| 554 |
|
611 |
|
| 555 |
// Remove all active DOM objects in the wrapper map. |
612 |
// Remove all active DOM objects in the wrapper map. |
| 556 |
removeObjectsFromWrapperMap<void>(getActiveDOMObjectMap()); |
613 |
DOMData::removeObjectsFromWrapperMap<void>(getActiveDOMObjectMap()); |
| 557 |
|
614 |
|
| 558 |
#if ENABLE(SVG) |
615 |
#if ENABLE(SVG) |
| 559 |
// Remove all SVG element instances in the wrapper map. |
616 |
// Remove all SVG element instances in the wrapper map. |
| 560 |
removeObjectsFromWrapperMap<SVGElementInstance>(getDOMSVGElementInstanceMap()); |
617 |
DOMData::removeObjectsFromWrapperMap<SVGElementInstance>(getDOMSVGElementInstanceMap()); |
| 561 |
|
618 |
|
| 562 |
// Remove all SVG objects with context in the wrapper map. |
619 |
// Remove all SVG objects with context in the wrapper map. |
| 563 |
removeObjectsFromWrapperMap<void>(getDOMSVGObjectWithContextMap()); |
620 |
DOMData::removeObjectsFromWrapperMap<void>(getDOMSVGObjectWithContextMap()); |
| 564 |
#endif |
621 |
#endif |
| 565 |
} |
622 |
} |
| 566 |
|
623 |
|
|
Lines 574-577
void removeAllDOMObjectsInCurrentThread(
WebCore/bindings/v8/V8DOMMap.cpp_sec14
|
| 574 |
removeAllDOMObjectsInCurrentThreadHelper(); |
631 |
removeAllDOMObjectsInCurrentThreadHelper(); |
| 575 |
} |
632 |
} |
| 576 |
|
633 |
|
|
|
634 |
|
| 635 |
void visitDOMNodesInCurrentThread(DOMWrapperMap<Node>::Visitor* visitor) |
| 636 |
{ |
| 637 |
v8::HandleScope scope; |
| 638 |
|
| 639 |
WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
| 640 |
DOMDataList& list = DOMDataStore::allStores(); |
| 641 |
for (size_t i = 0; i < list.size(); ++i) { |
| 642 |
DOMDataStore* store = list[i]; |
| 643 |
if (!store->domData()->owningThread() == WTF::currentThread()) |
| 644 |
continue; |
| 645 |
|
| 646 |
HashMap<Node*, v8::Object*>& map = store->domNodeMap().impl(); |
| 647 |
for (HashMap<Node*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) |
| 648 |
visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); |
| 649 |
} |
| 650 |
} |
| 651 |
|
| 652 |
void visitDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor) |
| 653 |
{ |
| 654 |
v8::HandleScope scope; |
| 655 |
|
| 656 |
WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
| 657 |
DOMDataList& list = DOMDataStore::allStores(); |
| 658 |
for (size_t i = 0; i < list.size(); ++i) { |
| 659 |
DOMDataStore* store = list[i]; |
| 660 |
if (!store->domData()->owningThread() == WTF::currentThread()) |
| 661 |
continue; |
| 662 |
|
| 663 |
HashMap<void*, v8::Object*> & map = store->domObjectMap().impl(); |
| 664 |
for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) |
| 665 |
visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); |
| 666 |
} |
| 667 |
} |
| 668 |
|
| 669 |
void visitActiveDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor) |
| 670 |
{ |
| 671 |
v8::HandleScope scope; |
| 672 |
|
| 673 |
WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
| 674 |
DOMDataList& list = DOMDataStore::allStores(); |
| 675 |
for (size_t i = 0; i < list.size(); ++i) { |
| 676 |
DOMDataStore* store = list[i]; |
| 677 |
if (!store->domData()->owningThread() == WTF::currentThread()) |
| 678 |
continue; |
| 679 |
|
| 680 |
HashMap<void*, v8::Object*>& map = store->activeDomObjectMap().impl(); |
| 681 |
for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) |
| 682 |
visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); |
| 683 |
} |
| 684 |
} |
| 685 |
|
| 686 |
#if ENABLE(SVG) |
| 687 |
|
| 688 |
void visitDOMSVGElementInstancesInCurrentThread(DOMWrapperMap<SVGElementInstance>::Visitor* visitor) |
| 689 |
{ |
| 690 |
v8::HandleScope scope; |
| 691 |
|
| 692 |
WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
| 693 |
DOMDataList& list = DOMDataStore::allStores(); |
| 694 |
for (size_t i = 0; i < list.size(); ++i) { |
| 695 |
DOMDataStore* store = list[i]; |
| 696 |
if (!store->domData()->owningThread() == WTF::currentThread()) |
| 697 |
continue; |
| 698 |
|
| 699 |
HashMap<SVGElementInstance*, v8::Object*> & map = store->domSvgElementInstanceMap().impl(); |
| 700 |
for (HashMap<SVGElementInstance*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) |
| 701 |
visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); |
| 702 |
} |
| 703 |
} |
| 704 |
|
| 705 |
void visitSVGObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor) |
| 706 |
{ |
| 707 |
v8::HandleScope scope; |
| 708 |
|
| 709 |
WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
| 710 |
DOMDataList& list = DOMDataStore::allStores(); |
| 711 |
for (size_t i = 0; i < list.size(); ++i) { |
| 712 |
DOMDataStore* store = list[i]; |
| 713 |
if (!store->domData()->owningThread() == WTF::currentThread()) |
| 714 |
continue; |
| 715 |
|
| 716 |
HashMap<void*, v8::Object*>& map = store->domSvgObjectWithContextMap().impl(); |
| 717 |
for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) |
| 718 |
visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); |
| 719 |
} |
| 720 |
} |
| 721 |
|
| 722 |
#endif |
| 723 |
|
| 577 |
} // namespace WebCore |
724 |
} // namespace WebCore |