OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2009 Google Inc. All rights reserved. | 2 * Copyright (C) 2009 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 24 matching lines...) Expand all Loading... |
35 | 35 |
36 #include <v8.h> | 36 #include <v8.h> |
37 #include <wtf/HashMap.h> | 37 #include <wtf/HashMap.h> |
38 #include <wtf/MainThread.h> | 38 #include <wtf/MainThread.h> |
39 #include <wtf/Noncopyable.h> | 39 #include <wtf/Noncopyable.h> |
40 #include <wtf/StdLibExtras.h> | 40 #include <wtf/StdLibExtras.h> |
41 #include <wtf/Threading.h> | 41 #include <wtf/Threading.h> |
42 #include <wtf/ThreadSpecific.h> | 42 #include <wtf/ThreadSpecific.h> |
43 #include <wtf/Vector.h> | 43 #include <wtf/Vector.h> |
44 | 44 |
| 45 #include "v8_isolated_world.h" |
| 46 |
45 namespace WebCore { | 47 namespace WebCore { |
46 | 48 |
47 // DOM binding algorithm: | 49 // DOM binding algorithm: |
48 // | 50 // |
49 // There are two kinds of DOM objects: | 51 // There are two kinds of DOM objects: |
50 // 1. DOM tree nodes, such as Document, HTMLElement, ... | 52 // 1. DOM tree nodes, such as Document, HTMLElement, ... |
51 // there classes implement TreeShared<T> interface; | 53 // there classes implement TreeShared<T> interface; |
52 // 2. Non-node DOM objects, such as CSSRule, Location, etc. | 54 // 2. Non-node DOM objects, such as CSSRule, Location, etc. |
53 // these classes implement a ref-counted scheme. | 55 // these classes implement a ref-counted scheme. |
54 // | 56 // |
(...skipping 28 matching lines...) Expand all Loading... |
83 // 2.1. If the dead object is in GC thread's map, remove the JS reference | 85 // 2.1. If the dead object is in GC thread's map, remove the JS reference |
84 // and deref the DOM object. | 86 // and deref the DOM object. |
85 // 2.2. Otherwise, go through all thread maps to find the owning thread. | 87 // 2.2. Otherwise, go through all thread maps to find the owning thread. |
86 // Remove the JS reference from the owning thread's map and move the | 88 // Remove the JS reference from the owning thread's map and move the |
87 // DOM object to a delayed queue. Post a task to the owning thread | 89 // DOM object to a delayed queue. Post a task to the owning thread |
88 // to have it deref-ed from the owning thread at later time. | 90 // to have it deref-ed from the owning thread at later time. |
89 // 3. When a thread is tearing down, invoke a cleanup routine to go through | 91 // 3. When a thread is tearing down, invoke a cleanup routine to go through |
90 // all objects in the delayed queue and the thread map and deref all of | 92 // all objects in the delayed queue and the thread map and deref all of |
91 // them. | 93 // them. |
92 | 94 |
| 95 static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject
); |
93 static void weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domO
bject); | 96 static void weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domO
bject); |
94 static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject
); | 97 void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domOb
ject); |
95 | |
96 #if ENABLE(SVG) | 98 #if ENABLE(SVG) |
97 static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, v
oid* domObject); | 99 static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, v
oid* domObject); |
98 | |
99 // SVG non-node elements may have a reference to a context node which should be
notified when the element is change. | 100 // 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); | 101 static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object,
void* domObject); |
101 #endif | 102 #endif |
102 | 103 |
103 // This is to ensure that we will deref DOM objects from the owning thread, not
the GC thread. | 104 class DOMData; |
104 // The helper function will be scheduled by the GC thread to get called from the
owning thread. | 105 class DOMDataStore; |
105 static void derefDelayedObjectsInCurrentThread(void*); | 106 typedef WTF::Vector<DOMDataStore*> DOMDataList; |
106 | 107 |
107 // A list of all ThreadSpecific DOM Data objects. Traversed during GC to find a
thread-specific map that | 108 // DOMDataStore |
108 // contains the object - so we can schedule the object to be deleted on the thre
ad which created it. | 109 // |
109 class ThreadSpecificDOMData; | 110 // DOMDataStore is the backing store that holds the maps between DOM objects |
110 typedef WTF::Vector<ThreadSpecificDOMData*> DOMDataList; | 111 // and JavaScript objects. In general, each thread can have multiple backing |
111 static DOMDataList& domDataList() | 112 // stores, one per isolated world. |
112 { | 113 // |
113 DEFINE_STATIC_LOCAL(DOMDataList, staticDOMDataList, ()); | 114 // This class doesn't manage the lifetime of the store. The data store |
114 return staticDOMDataList; | 115 // lifetime is managed by subclasses. |
115 } | 116 // |
116 | 117 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: | 118 public: |
126 enum DOMWrapperMapType { | 119 enum DOMWrapperMapType { |
127 DOMNodeMap, | 120 DOMNodeMap, |
128 DOMObjectMap, | 121 DOMObjectMap, |
129 ActiveDOMObjectMap, | 122 ActiveDOMObjectMap, |
130 #if ENABLE(SVG) | 123 #if ENABLE(SVG) |
131 DOMSVGElementInstanceMap, | 124 DOMSVGElementInstanceMap, |
132 DOMSVGObjectWithContextMap | 125 DOMSVGObjectWithContextMap |
133 #endif | 126 #endif |
134 }; | 127 }; |
135 | 128 |
136 typedef WTF::HashMap<void*, V8ClassIndex::V8WrapperType> DelayedObjectMap; | |
137 | |
138 template <class KeyType> | 129 template <class KeyType> |
139 class InternalDOMWrapperMap : public DOMWrapperMap<KeyType> { | 130 class InternalDOMWrapperMap : public DOMWrapperMap<KeyType> { |
140 public: | 131 public: |
141 InternalDOMWrapperMap(v8::WeakReferenceCallback callback) | 132 InternalDOMWrapperMap(DOMData* domData, v8::WeakReferenceCallback callba
ck) |
142 : DOMWrapperMap<KeyType>(callback) { } | 133 : DOMWrapperMap<KeyType>(callback) |
| 134 , m_domData(domData) { } |
143 | 135 |
144 virtual void forget(KeyType*); | 136 virtual void forget(KeyType*); |
145 | 137 |
146 void forgetOnly(KeyType* object) | 138 void forgetOnly(KeyType* object) |
147 { | 139 { |
148 DOMWrapperMap<KeyType>::forget(object); | 140 DOMWrapperMap<KeyType>::forget(object); |
149 } | 141 } |
| 142 |
| 143 private: |
| 144 DOMData* m_domData; |
150 }; | 145 }; |
151 | 146 |
152 ThreadSpecificDOMData() | 147 // A list of all DOMDataStore objects. Traversed during GC to find a thread
-specific map that |
153 : m_domNodeMap(0) | 148 // contains the object - so we can schedule the object to be deleted on the
thread which created it. |
154 , m_domObjectMap(0) | 149 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 { | 150 { |
163 WTF::MutexLocker locker(domDataListMutex()); | 151 DEFINE_STATIC_LOCAL(DOMDataList, staticDOMDataList, ()); |
164 domDataList().append(this); | 152 return staticDOMDataList; |
165 } | 153 } |
166 | 154 |
167 virtual ~ThreadSpecificDOMData() | 155 // Mutex to protect against concurrent access of DOMDataList. |
| 156 static WTF::Mutex& allStoresMutex() |
168 { | 157 { |
169 WTF::MutexLocker locker(domDataListMutex()); | 158 DEFINE_STATIC_LOCAL(WTF::Mutex, staticDOMDataListMutex, ()); |
170 domDataList().remove(domDataList().find(this)); | 159 return staticDOMDataListMutex; |
171 } | 160 } |
172 | 161 |
| 162 DOMDataStore(DOMData* domData); |
| 163 virtual ~DOMDataStore(); |
| 164 |
| 165 DOMData* domData() const { return m_domData; } |
| 166 |
173 void* getDOMWrapperMap(DOMWrapperMapType type) | 167 void* getDOMWrapperMap(DOMWrapperMapType type) |
174 { | 168 { |
175 switch (type) { | 169 switch (type) { |
176 case DOMNodeMap: | 170 case DOMNodeMap: |
177 return m_domNodeMap; | 171 return m_domNodeMap; |
178 case DOMObjectMap: | 172 case DOMObjectMap: |
179 return m_domObjectMap; | 173 return m_domObjectMap; |
180 case ActiveDOMObjectMap: | 174 case ActiveDOMObjectMap: |
181 return m_activeDomObjectMap; | 175 return m_activeDomObjectMap; |
182 #if ENABLE(SVG) | 176 #if ENABLE(SVG) |
183 case DOMSVGElementInstanceMap: | 177 case DOMSVGElementInstanceMap: |
184 return m_domSvgElementInstanceMap; | 178 return m_domSvgElementInstanceMap; |
185 case DOMSVGObjectWithContextMap: | 179 case DOMSVGObjectWithContextMap: |
186 return m_domSvgObjectWithContextMap; | 180 return m_domSvgObjectWithContextMap; |
187 #endif | 181 #endif |
188 } | 182 } |
189 | 183 |
190 ASSERT_NOT_REACHED(); | 184 ASSERT_NOT_REACHED(); |
191 return 0; | 185 return 0; |
192 } | 186 } |
193 | 187 |
194 InternalDOMWrapperMap<Node>& domNodeMap() { return *m_domNodeMap; } | 188 InternalDOMWrapperMap<Node>& domNodeMap() { return *m_domNodeMap; } |
195 InternalDOMWrapperMap<void>& domObjectMap() { return *m_domObjectMap; } | 189 InternalDOMWrapperMap<void>& domObjectMap() { return *m_domObjectMap; } |
196 InternalDOMWrapperMap<void>& activeDomObjectMap() { return *m_activeDomObjec
tMap; } | 190 InternalDOMWrapperMap<void>& activeDomObjectMap() { return *m_activeDomObjec
tMap; } |
197 #if ENABLE(SVG) | 191 #if ENABLE(SVG) |
198 InternalDOMWrapperMap<SVGElementInstance>& domSvgElementInstanceMap() { retu
rn *m_domSvgElementInstanceMap; } | 192 InternalDOMWrapperMap<SVGElementInstance>& domSvgElementInstanceMap() { retu
rn *m_domSvgElementInstanceMap; } |
199 InternalDOMWrapperMap<void>& domSvgObjectWithContextMap() { return *m_domSvg
ObjectWithContextMap; } | 193 InternalDOMWrapperMap<void>& domSvgObjectWithContextMap() { return *m_domSvg
ObjectWithContextMap; } |
200 #endif | 194 #endif |
201 | 195 |
202 DelayedObjectMap& delayedObjectMap() { return m_delayedObjectMap; } | |
203 bool delayedProcessingScheduled() const { return m_delayedProcessingSchedule
d; } | |
204 void setDelayedProcessingScheduled(bool value) { m_delayedProcessingSchedule
d = value; } | |
205 bool isMainThread() const { return m_isMainThread; } | |
206 | |
207 protected: | 196 protected: |
208 InternalDOMWrapperMap<Node>* m_domNodeMap; | 197 InternalDOMWrapperMap<Node>* m_domNodeMap; |
209 InternalDOMWrapperMap<void>* m_domObjectMap; | 198 InternalDOMWrapperMap<void>* m_domObjectMap; |
210 InternalDOMWrapperMap<void>* m_activeDomObjectMap; | 199 InternalDOMWrapperMap<void>* m_activeDomObjectMap; |
211 #if ENABLE(SVG) | 200 #if ENABLE(SVG) |
212 InternalDOMWrapperMap<SVGElementInstance>* m_domSvgElementInstanceMap; | 201 InternalDOMWrapperMap<SVGElementInstance>* m_domSvgElementInstanceMap; |
213 InternalDOMWrapperMap<void>* m_domSvgObjectWithContextMap; | 202 InternalDOMWrapperMap<void>* m_domSvgObjectWithContextMap; |
214 #endif | 203 #endif |
215 | 204 |
216 // Stores all the DOM objects that are delayed to be processed when the owni
ng thread gains control. | 205 private: |
217 DelayedObjectMap m_delayedObjectMap; | 206 // A back-pointer to the DOMData to which we belong. |
218 | 207 DOMData* m_domData; |
219 // The flag to indicate if the task to do the delayed process has already be
en posted. | |
220 bool m_delayedProcessingScheduled; | |
221 | |
222 bool m_isMainThread; | |
223 }; | 208 }; |
224 | 209 |
225 // This encapsulates thread-specific DOM data for non-main thread. All the maps
in it are created dynamically. | 210 // ScopedDOMDataStore |
226 class NonMainThreadSpecificDOMData : public ThreadSpecificDOMData { | 211 // |
| 212 // ScopedDOMDataStore is a DOMDataStore that controls limits the lifetime of |
| 213 // the store to the lifetime of the object itself. In other words, when the |
| 214 // ScopedDOMDataStore object is deallocated, the maps that belong to the store |
| 215 // are deallocated as well. |
| 216 // |
| 217 class ScopedDOMDataStore : public DOMDataStore { |
227 public: | 218 public: |
228 NonMainThreadSpecificDOMData() | 219 ScopedDOMDataStore(DOMData* domData) : DOMDataStore(domData) |
229 { | 220 { |
230 m_domNodeMap = new InternalDOMWrapperMap<Node>(&weakNodeCallback); | 221 m_domNodeMap = new InternalDOMWrapperMap<Node>(domData, weakNodeCallback
); |
231 m_domObjectMap = new InternalDOMWrapperMap<void>(weakDOMObjectCallback); | 222 m_domObjectMap = new InternalDOMWrapperMap<void>(domData, weakDOMObjectC
allback); |
232 m_activeDomObjectMap = new InternalDOMWrapperMap<void>(weakActiveDOMObje
ctCallback); | 223 m_activeDomObjectMap = new InternalDOMWrapperMap<void>(domData, weakActi
veDOMObjectCallback); |
233 #if ENABLE(SVG) | 224 #if ENABLE(SVG) |
234 m_domSvgElementInstanceMap = new InternalDOMWrapperMap<SVGElementInstanc
e>(weakSVGElementInstanceCallback); | 225 m_domSvgElementInstanceMap = new InternalDOMWrapperMap<SVGElementInstanc
e>(domData, weakSVGElementInstanceCallback); |
235 m_domSvgObjectWithContextMap = new InternalDOMWrapperMap<void>(weakSVGOb
jectWithContextCallback); | 226 m_domSvgObjectWithContextMap = new InternalDOMWrapperMap<void>(domData,
weakSVGObjectWithContextCallback); |
236 #endif | 227 #endif |
237 } | 228 } |
238 | 229 |
239 // This is called when WTF thread is tearing down. | 230 // This can be called when WTF thread is tearing down. |
240 // We assume that all child threads running V8 instances are created by WTF. | 231 // We assume that all child threads running V8 instances are created by WTF. |
241 virtual ~NonMainThreadSpecificDOMData() | 232 virtual ~ScopedDOMDataStore() |
242 { | 233 { |
243 delete m_domNodeMap; | 234 delete m_domNodeMap; |
244 delete m_domObjectMap; | 235 delete m_domObjectMap; |
245 delete m_activeDomObjectMap; | 236 delete m_activeDomObjectMap; |
246 #if ENABLE(SVG) | 237 #if ENABLE(SVG) |
247 delete m_domSvgElementInstanceMap; | 238 delete m_domSvgElementInstanceMap; |
248 delete m_domSvgObjectWithContextMap; | 239 delete m_domSvgObjectWithContextMap; |
249 #endif | 240 #endif |
250 } | 241 } |
251 }; | 242 }; |
252 | 243 |
253 // This encapsulates thread-specific DOM data for the main thread. All the maps
in it are static. | 244 // StaticDOMDataStore |
254 // This is because we are unable to rely on WTF::ThreadSpecificThreadExit to do
the cleanup since | 245 // |
255 // the place that tears down the main thread can not call any WTF functions. | 246 // StaticDOMDataStore is a DOMDataStore that manages the lifetime of the store |
256 class MainThreadSpecificDOMData : public ThreadSpecificDOMData { | 247 // statically. This encapsulates thread-specific DOM data for the main |
| 248 // thread. All the maps in it are static. This is because we are unable to |
| 249 // rely on WTF::ThreadSpecificThreadExit to do the cleanup since the place that |
| 250 // tears down the main thread can not call any WTF functions. |
| 251 class StaticDOMDataStore : public DOMDataStore { |
257 public: | 252 public: |
258 MainThreadSpecificDOMData() | 253 StaticDOMDataStore(DOMData* domData) |
259 : m_staticDomNodeMap(weakNodeCallback) | 254 : DOMDataStore(domData) |
260 , m_staticDomObjectMap(weakDOMObjectCallback) | 255 , m_staticDomNodeMap(domData, weakNodeCallback) |
261 , m_staticActiveDomObjectMap(weakActiveDOMObjectCallback) | 256 , m_staticDomObjectMap(domData, weakDOMObjectCallback) |
| 257 , m_staticActiveDomObjectMap(domData, weakActiveDOMObjectCallback) |
262 #if ENABLE(SVG) | 258 #if ENABLE(SVG) |
263 , m_staticDomSvgElementInstanceMap(weakSVGElementInstanceCallback) | 259 , m_staticDomSvgElementInstanceMap(domData, weakSVGElementInstanceCallba
ck) |
264 , m_staticDomSvgObjectWithContextMap(weakSVGObjectWithContextCallback) | 260 , m_staticDomSvgObjectWithContextMap(domData, weakSVGObjectWithContextCa
llback) |
265 #endif | 261 #endif |
266 { | 262 { |
267 m_domNodeMap = &m_staticDomNodeMap; | 263 m_domNodeMap = &m_staticDomNodeMap; |
268 m_domObjectMap = &m_staticDomObjectMap; | 264 m_domObjectMap = &m_staticDomObjectMap; |
269 m_activeDomObjectMap = &m_staticActiveDomObjectMap; | 265 m_activeDomObjectMap = &m_staticActiveDomObjectMap; |
270 #if ENABLE(SVG) | 266 #if ENABLE(SVG) |
271 m_domSvgElementInstanceMap = &m_staticDomSvgElementInstanceMap; | 267 m_domSvgElementInstanceMap = &m_staticDomSvgElementInstanceMap; |
272 m_domSvgObjectWithContextMap = &m_staticDomSvgObjectWithContextMap; | 268 m_domSvgObjectWithContextMap = &m_staticDomSvgObjectWithContextMap; |
273 #endif | 269 #endif |
274 } | 270 } |
275 | 271 |
276 private: | 272 private: |
277 InternalDOMWrapperMap<Node> m_staticDomNodeMap; | 273 InternalDOMWrapperMap<Node> m_staticDomNodeMap; |
278 InternalDOMWrapperMap<void> m_staticDomObjectMap; | 274 InternalDOMWrapperMap<void> m_staticDomObjectMap; |
279 InternalDOMWrapperMap<void> m_staticActiveDomObjectMap; | 275 InternalDOMWrapperMap<void> m_staticActiveDomObjectMap; |
280 InternalDOMWrapperMap<SVGElementInstance> m_staticDomSvgElementInstanceMap; | 276 InternalDOMWrapperMap<SVGElementInstance> m_staticDomSvgElementInstanceMap; |
281 InternalDOMWrapperMap<void> m_staticDomSvgObjectWithContextMap; | 277 InternalDOMWrapperMap<void> m_staticDomSvgObjectWithContextMap; |
282 }; | 278 }; |
283 | 279 |
284 DEFINE_STATIC_LOCAL(WTF::ThreadSpecific<NonMainThreadSpecificDOMData>, threadSpe
cificDOMData, ()); | 280 typedef WTF::Vector<DOMDataStore*> DOMDataStoreList; |
285 | 281 |
286 template<typename T> | 282 // DOMData |
287 static void handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMWrapperMapT
ype mapType, V8ClassIndex::V8WrapperType objectType, T*); | 283 // |
| 284 // DOMData represents the all the DOM wrappers for a given thread. In |
| 285 // particular, DOMData holds wrappers for all the isolated worlds in the |
| 286 // thread. The DOMData for the main thread and the DOMData for child threads |
| 287 // use different subclasses. |
| 288 // |
| 289 class DOMData: Noncopyable { |
| 290 public: |
| 291 DOMData() |
| 292 : m_delayedProcessingScheduled(false) |
| 293 , m_isMainThread(WTF::isMainThread()) |
| 294 , m_owningThread(WTF::currentThread()) |
| 295 { |
| 296 } |
288 | 297 |
289 ThreadSpecificDOMData& getThreadSpecificDOMData() | 298 static DOMData* getCurrent(); |
| 299 virtual DOMDataStore& getStore() = 0; |
| 300 |
| 301 template<typename T> |
| 302 static void handleWeakObject(DOMDataStore::DOMWrapperMapType mapType, |
| 303 v8::Handle<v8::Object> v8Object, |
| 304 T* domObject); |
| 305 |
| 306 void forgetDelayedObject(void* object) { m_delayedObjectMap.take(object); } |
| 307 |
| 308 // This is to ensure that we will deref DOM objects from the owning thread, |
| 309 // not the GC thread. The helper function will be scheduled by the GC |
| 310 // thread to get called from the owning thread. |
| 311 static void derefDelayedObjectsInCurrentThread(void*); |
| 312 void derefDelayedObjects(); |
| 313 |
| 314 template<typename T> |
| 315 static void removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap); |
| 316 |
| 317 ThreadIdentifier owningThread() const { return m_owningThread; } |
| 318 |
| 319 private: |
| 320 typedef WTF::HashMap<void*, V8ClassIndex::V8WrapperType> DelayedObjectMap; |
| 321 |
| 322 void ensureDeref(V8ClassIndex::V8WrapperType type, void* domObject); |
| 323 static void derefObject(V8ClassIndex::V8WrapperType type, void* domObject); |
| 324 |
| 325 // Stores all the DOM objects that are delayed to be processed when the owni
ng thread gains control. |
| 326 DelayedObjectMap m_delayedObjectMap; |
| 327 |
| 328 // The flag to indicate if the task to do the delayed process has already be
en posted. |
| 329 bool m_delayedProcessingScheduled; |
| 330 |
| 331 bool m_isMainThread; |
| 332 ThreadIdentifier m_owningThread; |
| 333 }; |
| 334 |
| 335 class MainThreadDOMData : public DOMData { |
| 336 public: |
| 337 MainThreadDOMData() : m_defaultStore(this) { } |
| 338 |
| 339 DOMDataStore& getStore() |
| 340 { |
| 341 ASSERT(WTF::isMainThread()); |
| 342 V8IsolatedWorld* world = V8IsolatedWorld::getEntered(); |
| 343 if (world) |
| 344 return *world->getDOMDataStore(); |
| 345 return m_defaultStore; |
| 346 } |
| 347 |
| 348 private: |
| 349 StaticDOMDataStore m_defaultStore; |
| 350 // Note: The DOMDataStores for isolated world are owned by the world object. |
| 351 }; |
| 352 |
| 353 class ChildThreadDOMData : public DOMData { |
| 354 public: |
| 355 ChildThreadDOMData() : m_defaultStore(this) { } |
| 356 |
| 357 DOMDataStore& getStore() { |
| 358 ASSERT(!WTF::isMainThread()); |
| 359 // Currently, child threads have only one world. |
| 360 return m_defaultStore; |
| 361 } |
| 362 |
| 363 private: |
| 364 ScopedDOMDataStore m_defaultStore; |
| 365 }; |
| 366 |
| 367 DOMDataStore::DOMDataStore(DOMData* domData) |
| 368 : m_domNodeMap(0) |
| 369 , m_domObjectMap(0) |
| 370 , m_activeDomObjectMap(0) |
| 371 #if ENABLE(SVG) |
| 372 , m_domSvgElementInstanceMap(0) |
| 373 , m_domSvgObjectWithContextMap(0) |
| 374 #endif |
| 375 , m_domData(domData) |
290 { | 376 { |
291 if (WTF::isMainThread()) { | 377 WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
292 DEFINE_STATIC_LOCAL(MainThreadSpecificDOMData, mainThreadSpecificDOMData
, ()); | 378 DOMDataStore::allStores().append(this); |
293 return mainThreadSpecificDOMData; | 379 } |
294 } | 380 |
295 return *threadSpecificDOMData; | 381 DOMDataStore::~DOMDataStore() |
| 382 { |
| 383 WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
| 384 DOMDataStore::allStores().remove(DOMDataStore::allStores().find(this)); |
| 385 } |
| 386 |
| 387 DOMDataStoreHandle::DOMDataStoreHandle() |
| 388 : m_store(new ScopedDOMDataStore(DOMData::getCurrent())) // TODO: Fix! |
| 389 { |
| 390 } |
| 391 |
| 392 DOMDataStoreHandle::~DOMDataStoreHandle() |
| 393 { |
296 } | 394 } |
297 | 395 |
298 template <class KeyType> | 396 template <class KeyType> |
299 void ThreadSpecificDOMData::InternalDOMWrapperMap<KeyType>::forget(KeyType* obje
ct) | 397 void DOMDataStore::InternalDOMWrapperMap<KeyType>::forget(KeyType* object) |
300 { | 398 { |
301 DOMWrapperMap<KeyType>::forget(object); | 399 DOMWrapperMap<KeyType>::forget(object); |
302 | 400 m_domData->forgetDelayedObject(object); |
303 ThreadSpecificDOMData::DelayedObjectMap& delayedObjectMap = getThreadSpecifi
cDOMData().delayedObjectMap(); | |
304 delayedObjectMap.take(object); | |
305 } | 401 } |
306 | 402 |
307 DOMWrapperMap<Node>& getDOMNodeMap() | 403 DOMWrapperMap<Node>& getDOMNodeMap() |
308 { | 404 { |
309 return getThreadSpecificDOMData().domNodeMap(); | 405 return DOMData::getCurrent()->getStore().domNodeMap(); |
310 } | 406 } |
311 | 407 |
312 DOMWrapperMap<void>& getDOMObjectMap() | 408 DOMWrapperMap<void>& getDOMObjectMap() |
313 { | 409 { |
314 return getThreadSpecificDOMData().domObjectMap(); | 410 return DOMData::getCurrent()->getStore().domObjectMap(); |
315 } | 411 } |
316 | 412 |
317 DOMWrapperMap<void>& getActiveDOMObjectMap() | 413 DOMWrapperMap<void>& getActiveDOMObjectMap() |
318 { | 414 { |
319 return getThreadSpecificDOMData().activeDomObjectMap(); | 415 return DOMData::getCurrent()->getStore().activeDomObjectMap(); |
320 } | 416 } |
321 | 417 |
322 #if ENABLE(SVG) | 418 #if ENABLE(SVG) |
| 419 |
323 DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap() | 420 DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap() |
324 { | 421 { |
325 return getThreadSpecificDOMData().domSvgElementInstanceMap(); | 422 return DOMData::getCurrent()->getStore().domSvgElementInstanceMap(); |
326 } | |
327 | |
328 static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, v
oid* domObject) | |
329 { | |
330 SVGElementInstance* instance = static_cast<SVGElementInstance*>(domObject); | |
331 | |
332 ThreadSpecificDOMData::InternalDOMWrapperMap<SVGElementInstance>& map = stat
ic_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<SVGElementInstance>&>(getDO
MSVGElementInstanceMap()); | |
333 if (map.contains(instance)) { | |
334 instance->deref(); | |
335 map.forgetOnly(instance); | |
336 } else | |
337 handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMSVGElementInsta
nceMap, V8ClassIndex::SVGELEMENTINSTANCE, instance); | |
338 } | 423 } |
339 | 424 |
340 // Map of SVG objects with contexts to V8 objects | 425 // Map of SVG objects with contexts to V8 objects |
341 DOMWrapperMap<void>& getDOMSVGObjectWithContextMap() | 426 DOMWrapperMap<void>& getDOMSVGObjectWithContextMap() |
342 { | 427 { |
343 return getThreadSpecificDOMData().domSvgObjectWithContextMap(); | 428 return DOMData::getCurrent()->getStore().domSvgObjectWithContextMap(); |
344 } | 429 } |
345 | 430 |
346 static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object,
void* domObject) | 431 #endif // ENABLE(SVG) |
| 432 |
| 433 // static |
| 434 DOMData* DOMData::getCurrent() |
347 { | 435 { |
348 v8::HandleScope scope; | 436 if (WTF::isMainThread()) { |
349 ASSERT(v8Object->IsObject()); | 437 DEFINE_STATIC_LOCAL(MainThreadDOMData, mainThreadDOMData, ()); |
350 | 438 return &mainThreadDOMData; |
351 V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8:
:Object>::Cast(v8Object)); | 439 } |
352 | 440 DEFINE_STATIC_LOCAL(WTF::ThreadSpecific<ChildThreadDOMData>, childThreadDOMD
ata, ()); |
353 ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<Thread
SpecificDOMData::InternalDOMWrapperMap<void>&>(getDOMSVGObjectWithContextMap()); | 441 return childThreadDOMData; |
354 if (map.contains(domObject)) { | |
355 // The forget function removes object from the map and disposes the wrap
per. | |
356 map.forgetOnly(domObject); | |
357 | |
358 switch (type) { | |
359 #define MakeCase(type, name) \ | |
360 case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); bre
ak; | |
361 SVG_OBJECT_TYPES(MakeCase) | |
362 #undef MakeCase | |
363 #define MakeCase(type, name) \ | |
364 case V8ClassIndex::type: \ | |
365 static_cast<V8SVGPODTypeWrapper<name>*>(domObject)->deref(); bre
ak; | |
366 SVG_POD_NATIVE_TYPES(MakeCase) | |
367 #undef MakeCase | |
368 default: | |
369 ASSERT_NOT_REACHED(); | |
370 break; | |
371 } | |
372 } else | |
373 handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMSVGObjectWithCo
ntextMap, type, domObject); | |
374 } | 442 } |
375 #endif // ENABLE(SVG) | |
376 | 443 |
377 // Called when the dead object is not in GC thread's map. Go through all thread
maps to find the one containing it. | 444 // 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 fo
r it to be deref-ed at later time from the owning thread. | 445 // Then clear the JS reference and push the DOM object into the delayed queue fo
r it to be deref-ed at later time from the owning thread. |
379 // * This is called when the GC thread is not the owning thread. | 446 // * This is called when the GC thread is not the owning thread. |
380 // * This can be called on any thread that has GC running. | 447 // * 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 ne
ed to worry about concurrency. | 448 // * Only one V8 instance is running at a time due to V8::Locker. So we don't ne
ed to worry about concurrency. |
382 template<typename T> | 449 template<typename T> |
383 static void handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMWrapperMapT
ype mapType, V8ClassIndex::V8WrapperType objectType, T* object) | 450 // static |
| 451 void DOMData::handleWeakObject(DOMDataStore::DOMWrapperMapType mapType, v8::Hand
le<v8::Object> v8Object, T* domObject) |
384 { | 452 { |
385 WTF::MutexLocker locker(domDataListMutex()); | 453 |
386 DOMDataList& list = domDataList(); | 454 WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
| 455 DOMDataList& list = DOMDataStore::allStores(); |
387 for (size_t i = 0; i < list.size(); ++i) { | 456 for (size_t i = 0; i < list.size(); ++i) { |
388 ThreadSpecificDOMData* threadData = list[i]; | 457 DOMDataStore* store = list[i]; |
389 | 458 |
390 ThreadSpecificDOMData::InternalDOMWrapperMap<T>* domMap = static_cast<Th
readSpecificDOMData::InternalDOMWrapperMap<T>*>(threadData->getDOMWrapperMap(map
Type)); | 459 DOMDataStore::InternalDOMWrapperMap<T>* domMap = static_cast<DOMDataStor
e::InternalDOMWrapperMap<T>*>(store->getDOMWrapperMap(mapType)); |
391 if (domMap->contains(object)) { | 460 |
| 461 v8::Handle<v8::Object> wrapper = domMap->get(domObject); |
| 462 if (*wrapper == *v8Object) { |
392 // Clear the JS reference. | 463 // Clear the JS reference. |
393 domMap->forgetOnly(object); | 464 domMap->forgetOnly(domObject); |
394 | 465 store->domData()->ensureDeref(V8Proxy::GetDOMWrapperType(v8Object),
domObject); |
395 // Push into the delayed queue. | |
396 threadData->delayedObjectMap().set(object, objectType); | |
397 | |
398 // Post a task to the owning thread in order to process the delayed
queue. | |
399 // FIXME: For now, we can only post to main thread due to WTF task p
osting limitation. We will fix this when we work on nested worker. | |
400 if (!threadData->delayedProcessingScheduled()) { | |
401 threadData->setDelayedProcessingScheduled(true); | |
402 if (threadData->isMainThread()) | |
403 WTF::callOnMainThread(&derefDelayedObjectsInCurrentThread, 0
); | |
404 } | |
405 | |
406 break; | |
407 } | 466 } |
408 } | 467 } |
409 } | 468 } |
410 | 469 |
| 470 void DOMData::ensureDeref(V8ClassIndex::V8WrapperType type, void* domObject) |
| 471 { |
| 472 if (m_owningThread == WTF::currentThread()) { |
| 473 // No need to delay the work. We can deref right now. |
| 474 derefObject(type, domObject); |
| 475 return; |
| 476 } |
| 477 |
| 478 // We need to do the deref on the correct thread. |
| 479 m_delayedObjectMap.set(domObject, type); |
| 480 |
| 481 // Post a task to the owning thread in order to process the delayed queue. |
| 482 // FIXME: For now, we can only post to main thread due to WTF task posting l
imitation. We will fix this when we work on nested worker. |
| 483 if (!m_delayedProcessingScheduled) { |
| 484 m_delayedProcessingScheduled = true; |
| 485 if (isMainThread()) |
| 486 WTF::callOnMainThread(&derefDelayedObjectsInCurrentThread, 0); |
| 487 } |
| 488 } |
| 489 |
411 // Called when the object is near death (not reachable from JS roots). | 490 // Called when the object is near death (not reachable from JS roots). |
412 // It is time to remove the entry from the table and dispose the handle. | 491 // It is time to remove the entry from the table and dispose the handle. |
413 static void weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domO
bject) | 492 static void weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domO
bject) |
414 { | 493 { |
415 v8::HandleScope scope; | 494 v8::HandleScope scope; |
416 ASSERT(v8Object->IsObject()); | 495 ASSERT(v8Object->IsObject()); |
417 | 496 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<Thread
SpecificDOMData::InternalDOMWrapperMap<void>&>(getDOMObjectMap()); | |
421 if (map.contains(domObject)) { | |
422 // The forget function removes object from the map and disposes the wrap
per. | |
423 map.forgetOnly(domObject); | |
424 | |
425 switch (type) { | |
426 #define MakeCase(type, name) \ | |
427 case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); bre
ak; | |
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 } | 497 } |
437 | 498 |
438 void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domOb
ject) | 499 void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domOb
ject) |
439 { | 500 { |
440 v8::HandleScope scope; | 501 v8::HandleScope scope; |
441 ASSERT(v8Object->IsObject()); | 502 ASSERT(v8Object->IsObject()); |
442 | 503 DOMData::handleWeakObject(DOMDataStore::ActiveDOMObjectMap, v8::Handle<v8::O
bject>::Cast(v8Object), domObject); |
443 V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8:
:Object>::Cast(v8Object)); | |
444 | |
445 ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<Thread
SpecificDOMData::InternalDOMWrapperMap<void>&>(getActiveDOMObjectMap()); | |
446 if (map.contains(domObject)) { | |
447 // The forget function removes object from the map and disposes the wrap
per. | |
448 map.forgetOnly(domObject); | |
449 | |
450 switch (type) { | |
451 #define MakeCase(type, name) \ | |
452 case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); bre
ak; | |
453 ACTIVE_DOM_OBJECT_TYPES(MakeCase) | |
454 #undef MakeCase | |
455 default: | |
456 ASSERT_NOT_REACHED(); | |
457 break; | |
458 } | |
459 } else | |
460 handleWeakObjectInOwningThread(ThreadSpecificDOMData::ActiveDOMObjectMap
, type, domObject); | |
461 } | 504 } |
462 | 505 |
463 static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject
) | 506 static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject
) |
464 { | 507 { |
465 Node* node = static_cast<Node*>(domObject); | 508 v8::HandleScope scope; |
466 | 509 ASSERT(v8Object->IsObject()); |
467 ThreadSpecificDOMData::InternalDOMWrapperMap<Node>& map = static_cast<Thread
SpecificDOMData::InternalDOMWrapperMap<Node>&>(getDOMNodeMap()); | 510 DOMData::handleWeakObject<Node>(DOMDataStore::DOMNodeMap, v8::Handle<v8::Obj
ect>::Cast(v8Object), static_cast<Node*>(domObject)); |
468 if (map.contains(node)) { | |
469 map.forgetOnly(node); | |
470 node->deref(); | |
471 } else | |
472 handleWeakObjectInOwningThread<Node>(ThreadSpecificDOMData::DOMNodeMap,
V8ClassIndex::NODE, node); | |
473 } | 511 } |
474 | 512 |
475 static void derefObject(V8ClassIndex::V8WrapperType type, void* domObject) | 513 #if ENABLE(SVG) |
| 514 |
| 515 static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, v
oid* domObject) |
| 516 { |
| 517 v8::HandleScope scope; |
| 518 ASSERT(v8Object->IsObject()); |
| 519 DOMData::handleWeakObject(DOMDataStore::DOMSVGElementInstanceMap, v8::Handle
<v8::Object>::Cast(v8Object), static_cast<SVGElementInstance*>(domObject)); |
| 520 } |
| 521 |
| 522 static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object,
void* domObject) |
| 523 { |
| 524 v8::HandleScope scope; |
| 525 ASSERT(v8Object->IsObject()); |
| 526 DOMData::handleWeakObject(DOMDataStore::DOMSVGObjectWithContextMap, v8::Hand
le<v8::Object>::Cast(v8Object), domObject); |
| 527 } |
| 528 |
| 529 #endif // ENABLE(SVG) |
| 530 |
| 531 // static |
| 532 void DOMData::derefObject(V8ClassIndex::V8WrapperType type, void* domObject) |
476 { | 533 { |
477 switch (type) { | 534 switch (type) { |
478 case V8ClassIndex::NODE: | 535 case V8ClassIndex::NODE: |
479 static_cast<Node*>(domObject)->deref(); | 536 static_cast<Node*>(domObject)->deref(); |
480 break; | 537 break; |
481 | 538 |
482 #define MakeCase(type, name) \ | 539 #define MakeCase(type, name) \ |
483 case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; | 540 case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; |
484 DOM_OBJECT_TYPES(MakeCase) // This includes both active and non-active. | 541 DOM_OBJECT_TYPES(MakeCase) // This includes both active and non-active. |
485 #undef MakeCase | 542 #undef MakeCase |
(...skipping 10 matching lines...) Expand all Loading... |
496 SVG_POD_NATIVE_TYPES(MakeCase) | 553 SVG_POD_NATIVE_TYPES(MakeCase) |
497 #undef MakeCase | 554 #undef MakeCase |
498 #endif | 555 #endif |
499 | 556 |
500 default: | 557 default: |
501 ASSERT_NOT_REACHED(); | 558 ASSERT_NOT_REACHED(); |
502 break; | 559 break; |
503 } | 560 } |
504 } | 561 } |
505 | 562 |
506 static void derefDelayedObjects() | 563 void DOMData::derefDelayedObjects() |
507 { | 564 { |
508 WTF::MutexLocker locker(domDataListMutex()); | 565 WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
509 | 566 |
510 getThreadSpecificDOMData().setDelayedProcessingScheduled(false); | 567 m_delayedProcessingScheduled = false; |
511 | 568 |
512 ThreadSpecificDOMData::DelayedObjectMap& delayedObjectMap = getThreadSpecifi
cDOMData().delayedObjectMap(); | 569 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); | 570 derefObject(iter->second, iter->first); |
515 } | 571 |
516 delayedObjectMap.clear(); | 572 m_delayedObjectMap.clear(); |
517 } | 573 } |
518 | 574 |
519 static void derefDelayedObjectsInCurrentThread(void*) | 575 // static |
| 576 void DOMData::derefDelayedObjectsInCurrentThread(void*) |
520 { | 577 { |
521 derefDelayedObjects(); | 578 getCurrent()->derefDelayedObjects(); |
522 } | 579 } |
523 | 580 |
| 581 // static |
524 template<typename T> | 582 template<typename T> |
525 static void removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap) | 583 void DOMData::removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap) |
526 { | 584 { |
527 for (typename WTF::HashMap<T*, v8::Object*>::iterator iter(domMap.impl().beg
in()); iter != domMap.impl().end(); ++iter) { | 585 for (typename WTF::HashMap<T*, v8::Object*>::iterator iter(domMap.impl().beg
in()); iter != domMap.impl().end(); ++iter) { |
528 T* domObject = static_cast<T*>(iter->first); | 586 T* domObject = static_cast<T*>(iter->first); |
529 v8::Persistent<v8::Object> v8Object(iter->second); | 587 v8::Persistent<v8::Object> v8Object(iter->second); |
530 | 588 |
531 V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle
<v8::Object>::Cast(v8Object)); | 589 V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle
<v8::Object>::Cast(v8Object)); |
532 | 590 |
533 // Deref the DOM object. | 591 // Deref the DOM object. |
534 derefObject(type, domObject); | 592 derefObject(type, domObject); |
535 | 593 |
536 // Clear the JS wrapper. | 594 // Clear the JS wrapper. |
537 v8Object.Dispose(); | 595 v8Object.Dispose(); |
538 } | 596 } |
539 domMap.impl().clear(); | 597 domMap.impl().clear(); |
540 } | 598 } |
541 | 599 |
542 static void removeAllDOMObjectsInCurrentThreadHelper() | 600 static void removeAllDOMObjectsInCurrentThreadHelper() |
543 { | 601 { |
544 v8::HandleScope scope; | 602 v8::HandleScope scope; |
545 | 603 |
546 // Deref all objects in the delayed queue. | 604 // Deref all objects in the delayed queue. |
547 derefDelayedObjects(); | 605 DOMData::getCurrent()->derefDelayedObjects(); |
548 | 606 |
549 // Remove all DOM nodes. | 607 // Remove all DOM nodes. |
550 removeObjectsFromWrapperMap<Node>(getDOMNodeMap()); | 608 DOMData::removeObjectsFromWrapperMap<Node>(getDOMNodeMap()); |
551 | 609 |
552 // Remove all DOM objects in the wrapper map. | 610 // Remove all DOM objects in the wrapper map. |
553 removeObjectsFromWrapperMap<void>(getDOMObjectMap()); | 611 DOMData::removeObjectsFromWrapperMap<void>(getDOMObjectMap()); |
554 | 612 |
555 // Remove all active DOM objects in the wrapper map. | 613 // Remove all active DOM objects in the wrapper map. |
556 removeObjectsFromWrapperMap<void>(getActiveDOMObjectMap()); | 614 DOMData::removeObjectsFromWrapperMap<void>(getActiveDOMObjectMap()); |
557 | 615 |
558 #if ENABLE(SVG) | 616 #if ENABLE(SVG) |
559 // Remove all SVG element instances in the wrapper map. | 617 // Remove all SVG element instances in the wrapper map. |
560 removeObjectsFromWrapperMap<SVGElementInstance>(getDOMSVGElementInstanceMap(
)); | 618 DOMData::removeObjectsFromWrapperMap<SVGElementInstance>(getDOMSVGElementIns
tanceMap()); |
561 | 619 |
562 // Remove all SVG objects with context in the wrapper map. | 620 // Remove all SVG objects with context in the wrapper map. |
563 removeObjectsFromWrapperMap<void>(getDOMSVGObjectWithContextMap()); | 621 DOMData::removeObjectsFromWrapperMap<void>(getDOMSVGObjectWithContextMap()); |
564 #endif | 622 #endif |
565 } | 623 } |
566 | 624 |
567 void removeAllDOMObjectsInCurrentThread() | 625 void removeAllDOMObjectsInCurrentThread() |
568 { | 626 { |
569 // Use the locker only if it has already been invoked before, as by worker t
hread. | 627 // Use the locker only if it has already been invoked before, as by worker t
hread. |
570 if (v8::Locker::IsActive()) { | 628 if (v8::Locker::IsActive()) { |
571 v8::Locker locker; | 629 v8::Locker locker; |
572 removeAllDOMObjectsInCurrentThreadHelper(); | 630 removeAllDOMObjectsInCurrentThreadHelper(); |
573 } else | 631 } else |
574 removeAllDOMObjectsInCurrentThreadHelper(); | 632 removeAllDOMObjectsInCurrentThreadHelper(); |
575 } | 633 } |
576 | 634 |
| 635 |
| 636 void visitDOMNodesInCurrentThread(DOMWrapperMap<Node>::Visitor* visitor) { |
| 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.e
nd(); ++it) |
| 648 visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->s
econd)); |
| 649 } |
| 650 } |
| 651 |
| 652 void visitDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor) { |
| 653 v8::HandleScope scope; |
| 654 |
| 655 WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
| 656 DOMDataList& list = DOMDataStore::allStores(); |
| 657 for (size_t i = 0; i < list.size(); ++i) { |
| 658 DOMDataStore* store = list[i]; |
| 659 if (!store->domData()->owningThread() == WTF::currentThread()) |
| 660 continue; |
| 661 |
| 662 HashMap<void*, v8::Object*> & map = store->domObjectMap().impl(); |
| 663 for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.e
nd(); ++it) |
| 664 visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->s
econd)); |
| 665 } |
| 666 } |
| 667 |
| 668 void visitActiveDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor)
{ |
| 669 v8::HandleScope scope; |
| 670 |
| 671 WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
| 672 DOMDataList& list = DOMDataStore::allStores(); |
| 673 for (size_t i = 0; i < list.size(); ++i) { |
| 674 DOMDataStore* store = list[i]; |
| 675 if (!store->domData()->owningThread() == WTF::currentThread()) |
| 676 continue; |
| 677 |
| 678 HashMap<void*, v8::Object*>& map = store->activeDomObjectMap().impl(); |
| 679 for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.e
nd(); ++it) |
| 680 visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->s
econd)); |
| 681 } |
| 682 } |
| 683 |
| 684 #if ENABLE(SVG) |
| 685 |
| 686 void visitDOMSVGElementInstancesInCurrentThread(DOMWrapperMap<SVGElementInstance
>::Visitor* visitor) { |
| 687 v8::HandleScope scope; |
| 688 |
| 689 WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
| 690 DOMDataList& list = DOMDataStore::allStores(); |
| 691 for (size_t i = 0; i < list.size(); ++i) { |
| 692 DOMDataStore* store = list[i]; |
| 693 if (!store->domData()->owningThread() == WTF::currentThread()) |
| 694 continue; |
| 695 |
| 696 HashMap<SVGElementInstance*, v8::Object*> & map = store->domSvgElementIn
stanceMap().impl(); |
| 697 for (HashMap<SVGElementInstance*, v8::Object*>::iterator it = map.begin(
); it != map.end(); ++it) |
| 698 visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->s
econd)); |
| 699 } |
| 700 } |
| 701 |
| 702 void visitSVGObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor) { |
| 703 v8::HandleScope scope; |
| 704 |
| 705 WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); |
| 706 DOMDataList& list = DOMDataStore::allStores(); |
| 707 for (size_t i = 0; i < list.size(); ++i) { |
| 708 DOMDataStore* store = list[i]; |
| 709 if (!store->domData()->owningThread() == WTF::currentThread()) |
| 710 continue; |
| 711 |
| 712 HashMap<void*, v8::Object*>& map = store->domSvgObjectWithContextMap().i
mpl(); |
| 713 for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.e
nd(); ++it) |
| 714 visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->s
econd)); |
| 715 } |
| 716 } |
| 717 |
| 718 #endif |
| 719 |
577 } // namespace WebCore | 720 } // namespace WebCore |
OLD | NEW |