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 22 matching lines...) Expand all Loading... |
33 | 33 |
34 #include "DOMObjectsInclude.h" | 34 #include "DOMObjectsInclude.h" |
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 | 44 |
44 namespace WebCore { | 45 namespace WebCore { |
45 | 46 |
46 // DOM binding algorithm: | 47 // DOM binding algorithm: |
47 // | 48 // |
48 // There are two kinds of DOM objects: | 49 // There are two kinds of DOM objects: |
49 // 1. DOM tree nodes, such as Document, HTMLElement, ... | 50 // 1. DOM tree nodes, such as Document, HTMLElement, ... |
50 // there classes implement TreeShared<T> interface; | 51 // there classes implement TreeShared<T> interface; |
51 // 2. Non-node DOM objects, such as CSSRule, Location, etc. | 52 // 2. Non-node DOM objects, such as CSSRule, Location, etc. |
52 // these classes implement a ref-counted scheme. | 53 // these classes implement a ref-counted scheme. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, v
oid* domObject); | 97 static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, v
oid* domObject); |
97 | 98 |
98 // SVG non-node elements may have a reference to a context node which should be
notified when the element is change. | 99 // SVG non-node elements may have a reference to a context node which should be
notified when the element is change. |
99 static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object,
void* domObject); | 100 static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object,
void* domObject); |
100 #endif | 101 #endif |
101 | 102 |
102 // This is to ensure that we will deref DOM objects from the owning thread, not
the GC thread. | 103 // This is to ensure that we will deref DOM objects from the owning thread, not
the GC thread. |
103 // The helper function will be scheduled by the GC thread to get called from the
owning thread. | 104 // The helper function will be scheduled by the GC thread to get called from the
owning thread. |
104 static void derefDelayedObjectsInCurrentThread(void*); | 105 static void derefDelayedObjectsInCurrentThread(void*); |
105 | 106 |
106 // This should be called to remove all DOM objects associated with the current t
hread when it is tearing down. | 107 // A list of all ThreadSpecific DOM Data objects. Traversed during GC to find a
thread-specific map that |
107 static void removeAllDOMObjectsInCurrentThread(); | 108 // contains the object - so we can schedule the object to be deleted on the thre
ad which created it. |
108 | |
109 // A map from a thread ID to thread's specific data. | |
110 class ThreadSpecificDOMData; | 109 class ThreadSpecificDOMData; |
111 typedef WTF::HashMap<WTF::ThreadIdentifier, ThreadSpecificDOMData*> DOMThreadMap
; | 110 typedef WTF::Vector<ThreadSpecificDOMData*> DOMDataList; |
112 static DOMThreadMap& domThreadMap() | 111 static DOMDataList& domDataList() |
113 { | 112 { |
114 DEFINE_STATIC_LOCAL(DOMThreadMap, staticDOMThreadMap, ()); | 113 DEFINE_STATIC_LOCAL(DOMDataList, staticDOMDataList, ()); |
115 return staticDOMThreadMap; | 114 return staticDOMDataList; |
116 } | 115 } |
117 | 116 |
118 // Mutex to protect against concurrent access of domThreadMap. | 117 // Mutex to protect against concurrent access of DOMDataList. |
119 static WTF::Mutex& domThreadMapMutex() | 118 static WTF::Mutex& domDataListMutex() |
120 { | 119 { |
121 DEFINE_STATIC_LOCAL(WTF::Mutex, staticDOMThreadMapMutex, ()); | 120 DEFINE_STATIC_LOCAL(WTF::Mutex, staticDOMDataListMutex, ()); |
122 return staticDOMThreadMapMutex; | 121 return staticDOMDataListMutex; |
123 } | 122 } |
124 | 123 |
125 class ThreadSpecificDOMData : Noncopyable { | 124 class ThreadSpecificDOMData : Noncopyable { |
126 public: | 125 public: |
127 enum DOMWrapperMapType { | 126 enum DOMWrapperMapType { |
128 DOMNodeMap, | 127 DOMNodeMap, |
129 DOMObjectMap, | 128 DOMObjectMap, |
130 ActiveDOMObjectMap, | 129 ActiveDOMObjectMap, |
131 #if ENABLE(SVG) | 130 #if ENABLE(SVG) |
132 DOMSVGElementInstanceMap, | 131 DOMSVGElementInstanceMap, |
(...skipping 21 matching lines...) Expand all Loading... |
154 : m_domNodeMap(0) | 153 : m_domNodeMap(0) |
155 , m_domObjectMap(0) | 154 , m_domObjectMap(0) |
156 , m_activeDomObjectMap(0) | 155 , m_activeDomObjectMap(0) |
157 #if ENABLE(SVG) | 156 #if ENABLE(SVG) |
158 , m_domSvgElementInstanceMap(0) | 157 , m_domSvgElementInstanceMap(0) |
159 , m_domSvgObjectWithContextMap(0) | 158 , m_domSvgObjectWithContextMap(0) |
160 #endif | 159 #endif |
161 , m_delayedProcessingScheduled(false) | 160 , m_delayedProcessingScheduled(false) |
162 , m_isMainThread(WTF::isMainThread()) | 161 , m_isMainThread(WTF::isMainThread()) |
163 { | 162 { |
164 WTF::MutexLocker locker(domThreadMapMutex()); | 163 WTF::MutexLocker locker(domDataListMutex()); |
165 domThreadMap().set(WTF::currentThread(), this); | 164 domDataList().append(this); |
166 } | 165 } |
167 | 166 |
168 virtual ~ThreadSpecificDOMData() | 167 virtual ~ThreadSpecificDOMData() |
169 { | 168 { |
170 WTF::MutexLocker locker(domThreadMapMutex()); | 169 WTF::MutexLocker locker(domDataListMutex()); |
171 domThreadMap().remove(WTF::currentThread()); | 170 domDataList().remove(domDataList().find(this)); |
172 } | 171 } |
173 | 172 |
174 void* getDOMWrapperMap(DOMWrapperMapType type) | 173 void* getDOMWrapperMap(DOMWrapperMapType type) |
175 { | 174 { |
176 switch (type) { | 175 switch (type) { |
177 case DOMNodeMap: | 176 case DOMNodeMap: |
178 return m_domNodeMap; | 177 return m_domNodeMap; |
179 case DOMObjectMap: | 178 case DOMObjectMap: |
180 return m_domObjectMap; | 179 return m_domObjectMap; |
181 case ActiveDOMObjectMap: | 180 case ActiveDOMObjectMap: |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 #if ENABLE(SVG) | 233 #if ENABLE(SVG) |
235 m_domSvgElementInstanceMap = new InternalDOMWrapperMap<SVGElementInstanc
e>(weakSVGElementInstanceCallback); | 234 m_domSvgElementInstanceMap = new InternalDOMWrapperMap<SVGElementInstanc
e>(weakSVGElementInstanceCallback); |
236 m_domSvgObjectWithContextMap = new InternalDOMWrapperMap<void>(weakSVGOb
jectWithContextCallback); | 235 m_domSvgObjectWithContextMap = new InternalDOMWrapperMap<void>(weakSVGOb
jectWithContextCallback); |
237 #endif | 236 #endif |
238 } | 237 } |
239 | 238 |
240 // This is called when WTF thread is tearing down. | 239 // This is called when WTF thread is tearing down. |
241 // We assume that all child threads running V8 instances are created by WTF. | 240 // We assume that all child threads running V8 instances are created by WTF. |
242 virtual ~NonMainThreadSpecificDOMData() | 241 virtual ~NonMainThreadSpecificDOMData() |
243 { | 242 { |
244 removeAllDOMObjectsInCurrentThread(); | |
245 | |
246 delete m_domNodeMap; | 243 delete m_domNodeMap; |
247 delete m_domObjectMap; | 244 delete m_domObjectMap; |
248 delete m_activeDomObjectMap; | 245 delete m_activeDomObjectMap; |
249 #if ENABLE(SVG) | 246 #if ENABLE(SVG) |
250 delete m_domSvgElementInstanceMap; | 247 delete m_domSvgElementInstanceMap; |
251 delete m_domSvgObjectWithContextMap; | 248 delete m_domSvgObjectWithContextMap; |
252 #endif | 249 #endif |
253 } | 250 } |
254 }; | 251 }; |
255 | 252 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 #endif // ENABLE(SVG) | 375 #endif // ENABLE(SVG) |
379 | 376 |
380 // Called when the dead object is not in GC thread's map. Go through all thread
maps to find the one containing it. | 377 // Called when the dead object is not in GC thread's map. Go through all thread
maps to find the one containing it. |
381 // 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. | 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. |
382 // * This is called when the GC thread is not the owning thread. | 379 // * This is called when the GC thread is not the owning thread. |
383 // * This can be called on any thread that has GC running. | 380 // * This can be called on any thread that has GC running. |
384 // * Only one V8 instance is running at a time due to V8::Locker. So we don't ne
ed to worry about concurrency. | 381 // * Only one V8 instance is running at a time due to V8::Locker. So we don't ne
ed to worry about concurrency. |
385 template<typename T> | 382 template<typename T> |
386 static void handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMWrapperMapT
ype mapType, V8ClassIndex::V8WrapperType objectType, T* object) | 383 static void handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMWrapperMapT
ype mapType, V8ClassIndex::V8WrapperType objectType, T* object) |
387 { | 384 { |
388 WTF::MutexLocker locker(domThreadMapMutex()); | 385 WTF::MutexLocker locker(domDataListMutex()); |
389 for (typename DOMThreadMap::iterator iter(domThreadMap().begin()); iter != d
omThreadMap().end(); ++iter) { | 386 DOMDataList& list = domDataList(); |
390 WTF::ThreadIdentifier threadID = iter->first; | 387 for (size_t i = 0; i < list.size(); ++i) { |
391 ThreadSpecificDOMData* threadData = iter->second; | 388 ThreadSpecificDOMData* threadData = list[i]; |
392 | |
393 // Skip the current thread that is GC thread. | |
394 if (threadID == WTF::currentThread()) { | |
395 ASSERT(!static_cast<DOMWrapperMap<T>*>(threadData->getDOMWrapperMap(
mapType))->contains(object)); | |
396 continue; | |
397 } | |
398 | 389 |
399 ThreadSpecificDOMData::InternalDOMWrapperMap<T>* domMap = static_cast<Th
readSpecificDOMData::InternalDOMWrapperMap<T>*>(threadData->getDOMWrapperMap(map
Type)); | 390 ThreadSpecificDOMData::InternalDOMWrapperMap<T>* domMap = static_cast<Th
readSpecificDOMData::InternalDOMWrapperMap<T>*>(threadData->getDOMWrapperMap(map
Type)); |
400 if (domMap->contains(object)) { | 391 if (domMap->contains(object)) { |
401 // Clear the JS reference. | 392 // Clear the JS reference. |
402 domMap->forgetOnly(object); | 393 domMap->forgetOnly(object); |
403 | 394 |
404 // Push into the delayed queue. | 395 // Push into the delayed queue. |
405 threadData->delayedObjectMap().set(object, objectType); | 396 threadData->delayedObjectMap().set(object, objectType); |
406 | 397 |
407 // Post a task to the owning thread in order to process the delayed
queue. | 398 // Post a task to the owning thread in order to process the delayed
queue. |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 #endif | 498 #endif |
508 | 499 |
509 default: | 500 default: |
510 ASSERT_NOT_REACHED(); | 501 ASSERT_NOT_REACHED(); |
511 break; | 502 break; |
512 } | 503 } |
513 } | 504 } |
514 | 505 |
515 static void derefDelayedObjects() | 506 static void derefDelayedObjects() |
516 { | 507 { |
517 WTF::MutexLocker locker(domThreadMapMutex()); | 508 WTF::MutexLocker locker(domDataListMutex()); |
518 | 509 |
519 getThreadSpecificDOMData().setDelayedProcessingScheduled(false); | 510 getThreadSpecificDOMData().setDelayedProcessingScheduled(false); |
520 | 511 |
521 ThreadSpecificDOMData::DelayedObjectMap& delayedObjectMap = getThreadSpecifi
cDOMData().delayedObjectMap(); | 512 ThreadSpecificDOMData::DelayedObjectMap& delayedObjectMap = getThreadSpecifi
cDOMData().delayedObjectMap(); |
522 for (ThreadSpecificDOMData::DelayedObjectMap::iterator iter(delayedObjectMap
.begin()); iter != delayedObjectMap.end(); ++iter) { | 513 for (ThreadSpecificDOMData::DelayedObjectMap::iterator iter(delayedObjectMap
.begin()); iter != delayedObjectMap.end(); ++iter) { |
523 derefObject(iter->second, iter->first); | 514 derefObject(iter->second, iter->first); |
524 } | 515 } |
525 delayedObjectMap.clear(); | 516 delayedObjectMap.clear(); |
526 } | 517 } |
527 | 518 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
566 | 557 |
567 #if ENABLE(SVG) | 558 #if ENABLE(SVG) |
568 // Remove all SVG element instances in the wrapper map. | 559 // Remove all SVG element instances in the wrapper map. |
569 removeObjectsFromWrapperMap<SVGElementInstance>(getDOMSVGElementInstanceMap(
)); | 560 removeObjectsFromWrapperMap<SVGElementInstance>(getDOMSVGElementInstanceMap(
)); |
570 | 561 |
571 // Remove all SVG objects with context in the wrapper map. | 562 // Remove all SVG objects with context in the wrapper map. |
572 removeObjectsFromWrapperMap<void>(getDOMSVGObjectWithContextMap()); | 563 removeObjectsFromWrapperMap<void>(getDOMSVGObjectWithContextMap()); |
573 #endif | 564 #endif |
574 } | 565 } |
575 | 566 |
576 static void removeAllDOMObjectsInCurrentThread() | 567 void removeAllDOMObjectsInCurrentThread() |
577 { | 568 { |
578 // Use the locker only if it has already been invoked before, as by worker t
hread. | 569 // Use the locker only if it has already been invoked before, as by worker t
hread. |
579 if (v8::Locker::IsActive()) { | 570 if (v8::Locker::IsActive()) { |
580 v8::Locker locker; | 571 v8::Locker locker; |
581 removeAllDOMObjectsInCurrentThreadHelper(); | 572 removeAllDOMObjectsInCurrentThreadHelper(); |
582 } else | 573 } else |
583 removeAllDOMObjectsInCurrentThreadHelper(); | 574 removeAllDOMObjectsInCurrentThreadHelper(); |
584 } | 575 } |
585 | 576 |
586 } // namespace WebCore | 577 } // namespace WebCore |
OLD | NEW |