WebKit Bugzilla
Attachment 357980 Details for
Bug 192975
: ThreadTimers should not store a raw pointer in its heap
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
WIP2
wip192975b.patch (text/plain), 21.36 KB, created by
Ryosuke Niwa
on 2018-12-21 14:39:47 PST
(
hide
)
Description:
WIP2
Filename:
MIME Type:
Creator:
Ryosuke Niwa
Created:
2018-12-21 14:39:47 PST
Size:
21.36 KB
patch
obsolete
>Index: Source/WebCore/WebCore.xcodeproj/project.pbxproj >=================================================================== >--- Source/WebCore/WebCore.xcodeproj/project.pbxproj (revision 239401) >+++ Source/WebCore/WebCore.xcodeproj/project.pbxproj (working copy) >@@ -452,7 +452,7 @@ > 159741DB1B7D140100201C92 /* JSMediaDeviceInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 157CC2621B7C1CA400D8D075 /* JSMediaDeviceInfo.h */; }; > 15C7708D100D3C6B005BA267 /* ValidityState.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C7708A100D3C6A005BA267 /* ValidityState.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 15C77093100D3CA8005BA267 /* JSValidityState.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C77091100D3CA8005BA267 /* JSValidityState.h */; }; >- 185BCF290F3279CE000EA262 /* ThreadTimers.h in Headers */ = {isa = PBXBuildFile; fileRef = 185BCF270F3279CE000EA262 /* ThreadTimers.h */; }; >+ 185BCF290F3279CE000EA262 /* ThreadTimers.h in Headers */ = {isa = PBXBuildFile; fileRef = 185BCF270F3279CE000EA262 /* ThreadTimers.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 188604B40F2E654A000B6443 /* DOMTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 188604B20F2E654A000B6443 /* DOMTimer.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 18F831B80FD48C7800D8C56B /* WorkerLoaderProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 18F831B70FD48C7800D8C56B /* WorkerLoaderProxy.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 1921327511C0E6BB00456238 /* SVGFEConvolveMatrixElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 1921327211C0E6BB00456238 /* SVGFEConvolveMatrixElement.h */; }; >Index: Source/WebCore/platform/ThreadTimers.cpp >=================================================================== >--- Source/WebCore/platform/ThreadTimers.cpp (revision 239401) >+++ Source/WebCore/platform/ThreadTimers.cpp (working copy) >@@ -75,12 +75,28 @@ > { > if (!m_sharedTimer) > return; >- >- if (m_firingTimers || m_timerHeap.isEmpty()) { >+ >+ if (m_firingTimers) { > m_pendingSharedTimerFireTime = MonotonicTime { }; > m_sharedTimer->stop(); >+ } >+ >+ WeakPtr<TimerBase> firstTimer; >+ while (!m_timerHeap.isEmpty()) { >+ auto& item = m_timerHeap.first(); >+ if (item.timer) { >+ firstTimer = item.timer; >+ break; >+ } >+ TimerBase::heapDeleteNullMin(m_timerHeap); >+ } >+ ASSERT(firstTimer || m_timerHeap.isEmpty()); >+ >+ if (m_timerHeap.isEmpty()) { >+ m_pendingSharedTimerFireTime = MonotonicTime { }; >+ m_sharedTimer->stop(); > } else { >- MonotonicTime nextFireTime = m_timerHeap.first()->m_nextFireTime; >+ MonotonicTime nextFireTime = firstTimer->m_nextFireTime; > MonotonicTime currentMonotonicTime = MonotonicTime::now(); > if (m_pendingSharedTimerFireTime) { > // No need to restart the timer if both the pending fire time and the new fire time are in the past. >@@ -104,10 +120,20 @@ > MonotonicTime fireTime = MonotonicTime::now(); > MonotonicTime timeToQuit = fireTime + maxDurationOfFiringTimers; > >- while (!m_timerHeap.isEmpty() && m_timerHeap.first()->m_nextFireTime <= fireTime) { >- TimerBase* timer = m_timerHeap.first(); >+ while (!m_timerHeap.isEmpty()) { >+ auto& item = m_timerHeap.first(); >+ auto* timer = item.timer.get(); >+ if (!timer) { >+ TimerBase::heapDeleteNullMin(m_timerHeap); >+ continue; >+ } >+ >+ if (timer->m_nextFireTime > fireTime) >+ break; >+ > timer->m_nextFireTime = MonotonicTime { }; > timer->m_unalignedNextFireTime = MonotonicTime { }; >+ m_timerHeap[timer->m_heapIndex].time = MonotonicTime { }; > timer->heapDeleteMin(); > > Seconds interval = timer->repeatInterval(); >Index: Source/WebCore/platform/ThreadTimers.h >=================================================================== >--- Source/WebCore/platform/ThreadTimers.h (revision 239401) >+++ Source/WebCore/platform/ThreadTimers.h (working copy) >@@ -33,33 +33,51 @@ > > namespace WebCore { > >- class SharedTimer; >- class TimerBase; >+class SharedTimer; >+class TimerBase; > >- // A collection of timers per thread. Kept in ThreadGlobalData. >- class ThreadTimers { >- WTF_MAKE_NONCOPYABLE(ThreadTimers); WTF_MAKE_FAST_ALLOCATED; >- public: >- ThreadTimers(); >+struct ThreadTimerHeapItem { >+ ThreadTimerHeapItem(TimerBase&, MonotonicTime, unsigned); > >- // On a thread different then main, we should set the thread's instance of the SharedTimer. >- void setSharedTimer(SharedTimer*); >+ ThreadTimerHeapItem(const ThreadTimerHeapItem&); >+ ThreadTimerHeapItem(ThreadTimerHeapItem&&); > >- Vector<TimerBase*>& timerHeap() { return m_timerHeap; } >+ ThreadTimerHeapItem& operator=(const ThreadTimerHeapItem&); >+ ThreadTimerHeapItem& operator=(ThreadTimerHeapItem&&); > >- void updateSharedTimer(); >- void fireTimersInNestedEventLoop(); >+ bool operator==(const ThreadTimerHeapItem&) const; > >- private: >- void sharedTimerFiredInternal(); >- void fireTimersInNestedEventLoopInternal(); >+ WeakPtr<TimerBase> timer; >+ MonotonicTime time; >+ unsigned insertionOrder { 0 }; >+}; > >- Vector<TimerBase*> m_timerHeap; >- SharedTimer* m_sharedTimer { nullptr }; // External object, can be a run loop on a worker thread. Normally set/reset by worker thread. >- bool m_firingTimers { false }; // Reentrancy guard. >- MonotonicTime m_pendingSharedTimerFireTime; >- }; >+typedef Vector<ThreadTimerHeapItem> ThreadTimerHeap; >+ >+// A collection of timers per thread. Kept in ThreadGlobalData. >+class ThreadTimers { >+ WTF_MAKE_NONCOPYABLE(ThreadTimers); WTF_MAKE_FAST_ALLOCATED; >+public: >+ ThreadTimers(); > >+ // On a thread different then main, we should set the thread's instance of the SharedTimer. >+ void setSharedTimer(SharedTimer*); >+ >+ ThreadTimerHeap& timerHeap() { return m_timerHeap; } >+ >+ void updateSharedTimer(); >+ void fireTimersInNestedEventLoop(); >+ >+private: >+ void sharedTimerFiredInternal(); >+ void fireTimersInNestedEventLoopInternal(); >+ >+ ThreadTimerHeap m_timerHeap; >+ SharedTimer* m_sharedTimer { nullptr }; // External object, can be a run loop on a worker thread. Normally set/reset by worker thread. >+ bool m_firingTimers { false }; // Reentrancy guard. >+ MonotonicTime m_pendingSharedTimerFireTime; >+}; >+ > } > > #endif >Index: Source/WebCore/platform/Timer.cpp >=================================================================== >--- Source/WebCore/platform/Timer.cpp (revision 239401) >+++ Source/WebCore/platform/Timer.cpp (working copy) >@@ -45,12 +45,46 @@ > > class TimerHeapReference; > >+inline ThreadTimerHeapItem::ThreadTimerHeapItem(TimerBase& timer, MonotonicTime time, unsigned insertionOrder) >+ : timer(makeWeakPtr(timer)) >+ , time(time) >+ , insertionOrder(insertionOrder) >+{ } >+ >+inline ThreadTimerHeapItem::ThreadTimerHeapItem(const ThreadTimerHeapItem&) = default; >+inline ThreadTimerHeapItem::ThreadTimerHeapItem(ThreadTimerHeapItem&&) = default; >+ >+inline ThreadTimerHeapItem& ThreadTimerHeapItem::operator=(const ThreadTimerHeapItem& other) >+{ >+ timer = other.timer; >+ time = other.time; >+ insertionOrder = other.insertionOrder; >+ return *this; >+} >+ >+inline ThreadTimerHeapItem& ThreadTimerHeapItem::operator=(ThreadTimerHeapItem&& other) >+{ >+ timer = WTFMove(other.timer); >+ time = other.time; >+ insertionOrder = other.insertionOrder; >+ >+ other.time = MonotonicTime { }; >+ other.insertionOrder = 0; >+ return *this; >+} >+ >+inline bool ThreadTimerHeapItem::operator==(const ThreadTimerHeapItem& other) const >+{ >+ ASSERT((timer == other.timer) == (time == other.time && insertionOrder == other.insertionOrder)); >+ return timer == other.timer; >+} >+ > // Timers are stored in a heap data structure, used to implement a priority queue. > // This allows us to efficiently determine which timer needs to fire the soonest. > // Then we set a single shared system timer to fire at that time. > // > // When a timer's "next fire time" changes, we need to move it around in the priority queue. >-static Vector<TimerBase*>& threadGlobalTimerHeap() >+static ThreadTimerHeap& threadGlobalTimerHeap() > { > return threadGlobalData().threadTimers().timerHeap(); > } >@@ -58,52 +92,73 @@ > > class TimerHeapPointer { > public: >- TimerHeapPointer(TimerBase** pointer) : m_pointer(pointer) { } >+ TimerHeapPointer(ThreadTimerHeapItem* pointer) : m_pointer(pointer) { } > TimerHeapReference operator*() const; >- TimerBase* operator->() const { return *m_pointer; } >+ ThreadTimerHeapItem& operator->() const { return *m_pointer; } > private: >- TimerBase** m_pointer; >+ ThreadTimerHeapItem* m_pointer; > }; > > class TimerHeapReference { > public: >- TimerHeapReference(TimerBase*& reference) : m_reference(reference) { } >- operator TimerBase*() const { return m_reference; } >+ TimerHeapReference(ThreadTimerHeapItem& reference) >+ : m_reference(reference) >+ { } >+ >+ TimerHeapReference(const TimerHeapReference& other) >+ : m_reference(other.m_reference) >+ { } >+ >+ operator ThreadTimerHeapItem&() const { return m_reference; } > TimerHeapPointer operator&() const { return &m_reference; } >- TimerHeapReference& operator=(TimerBase*); >- TimerHeapReference& operator=(TimerHeapReference); >+ TimerHeapReference& operator=(TimerHeapReference&&); >+ TimerHeapReference& operator=(ThreadTimerHeapItem&&); >+ >+ void updateHeapIndex(); >+ > private: >- TimerBase*& m_reference; >+ ThreadTimerHeapItem& m_reference; > }; > > inline TimerHeapReference TimerHeapPointer::operator*() const > { >- return *m_pointer; >+ return TimerHeapReference { *m_pointer }; > } > >-inline TimerHeapReference& TimerHeapReference::operator=(TimerBase* timer) >+inline TimerHeapReference& TimerHeapReference::operator=(TimerHeapReference&& other) > { >- m_reference = timer; >- Vector<TimerBase*>& heap = timer->timerHeap(); >- if (&m_reference >= heap.data() && &m_reference < heap.data() + heap.size()) >- timer->m_heapIndex = &m_reference - heap.data(); >+ m_reference = WTFMove(other.m_reference); >+ updateHeapIndex(); > return *this; > } > >-inline TimerHeapReference& TimerHeapReference::operator=(TimerHeapReference b) >+inline TimerHeapReference& TimerHeapReference::operator=(ThreadTimerHeapItem&& timer) > { >- TimerBase* timer = b; >- return *this = timer; >+ m_reference = WTFMove(timer); >+ updateHeapIndex(); >+ return *this; > } > >+inline void TimerHeapReference::updateHeapIndex() >+{ >+ auto timerWeakPtr = m_reference.timer; >+ if (!timerWeakPtr) >+ return; >+ >+ auto& timer = *timerWeakPtr; >+ auto& heap = timer.timerHeap(); >+ if (&m_reference >= heap.data() && &m_reference < heap.data() + heap.size()) >+ timer.m_heapIndex = &m_reference - heap.data(); >+} >+ > inline void swap(TimerHeapReference a, TimerHeapReference b) > { >- TimerBase* timerA = a; >- TimerBase* timerB = b; >+ ThreadTimerHeapItem timerA = a; >+ ThreadTimerHeapItem timerB = b; > > // Invoke the assignment operator, since that takes care of updating m_heapIndex. >- a = timerB; >- b = timerA; >+ a = WTFMove(timerB); >+ b = WTFMove(timerA); > } > > // ---------------- >@@ -110,9 +165,9 @@ > > // Class to represent iterators in the heap when calling the standard library heap algorithms. > // Uses a custom pointer and reference type that update indices for pointers in the heap. >-class TimerHeapIterator : public std::iterator<std::random_access_iterator_tag, TimerBase*, ptrdiff_t, TimerHeapPointer, TimerHeapReference> { >+class TimerHeapIterator : public std::iterator<std::random_access_iterator_tag, ThreadTimerHeapItem, ptrdiff_t, TimerHeapPointer, TimerHeapReference> { > public: >- explicit TimerHeapIterator(TimerBase** pointer) : m_pointer(pointer) { checkConsistency(); } >+ explicit TimerHeapIterator(ThreadTimerHeapItem* pointer) : m_pointer(pointer) { checkConsistency(); } > > TimerHeapIterator& operator++() { checkConsistency(); ++m_pointer; checkConsistency(); return *this; } > TimerHeapIterator operator++(int) { checkConsistency(1); return TimerHeapIterator(m_pointer++); } >@@ -125,7 +180,7 @@ > > TimerHeapReference operator*() const { return TimerHeapReference(*m_pointer); } > TimerHeapReference operator[](ptrdiff_t i) const { return TimerHeapReference(m_pointer[i]); } >- TimerBase* operator->() const { return *m_pointer; } >+ ThreadTimerHeapItem& operator->() const { return *m_pointer; } > > private: > void checkConsistency(ptrdiff_t offset = 0) const >@@ -149,7 +204,7 @@ > friend TimerHeapIterator operator-(TimerHeapIterator, size_t); > friend ptrdiff_t operator-(TimerHeapIterator, TimerHeapIterator); > >- TimerBase** m_pointer; >+ ThreadTimerHeapItem* m_pointer; > }; > > inline bool operator==(TimerHeapIterator a, TimerHeapIterator b) { return a.m_pointer == b.m_pointer; } >@@ -169,24 +224,39 @@ > > class TimerHeapLessThanFunction { > public: >- bool operator()(const TimerBase*, const TimerBase*) const; >+ static bool compare(const TimerBase& a, const ThreadTimerHeapItem& b) >+ { >+ ASSERT(!b.timer || (b.time == b.timer->m_nextFireTime && b.insertionOrder == b.timer->m_heapInsertionOrder)); >+ return compare(a.m_nextFireTime, a.m_heapInsertionOrder, b.time, b.insertionOrder); >+ } >+ >+ static bool compare(const ThreadTimerHeapItem& a, const TimerBase& b) >+ { >+ ASSERT(!a.timer || (a.time == a.timer->m_nextFireTime && a.insertionOrder == a.timer->m_heapInsertionOrder)); >+ return compare(a.time, a.insertionOrder, b.m_nextFireTime, b.m_heapInsertionOrder); >+ } >+ >+ bool operator()(const ThreadTimerHeapItem& a, const ThreadTimerHeapItem& b) const >+ { >+ ASSERT(!a.timer || (a.time == a.timer->m_nextFireTime && a.insertionOrder == a.timer->m_heapInsertionOrder)); >+ ASSERT(!b.timer || (b.time == b.timer->m_nextFireTime && b.insertionOrder == b.timer->m_heapInsertionOrder)); >+ return compare(a.time, a.insertionOrder, b.time, b.insertionOrder); >+ } >+ >+private: >+ static bool compare(MonotonicTime aTime, unsigned aOrder, MonotonicTime bTime, unsigned bOrder) >+ { >+ // The comparisons below are "backwards" because the heap puts the largest >+ // element first and we want the lowest time to be the first one in the heap. >+ if (bTime != aTime) >+ return bTime < aTime; >+ // We need to look at the difference of the insertion orders instead of comparing the two >+ // outright in case of overflow. >+ unsigned difference = aOrder - bOrder; >+ return difference < std::numeric_limits<unsigned>::max() / 2; >+ } > }; > >-inline bool TimerHeapLessThanFunction::operator()(const TimerBase* a, const TimerBase* b) const >-{ >- // The comparisons below are "backwards" because the heap puts the largest >- // element first and we want the lowest time to be the first one in the heap. >- MonotonicTime aFireTime = a->m_nextFireTime; >- MonotonicTime bFireTime = b->m_nextFireTime; >- if (bFireTime != aFireTime) >- return bFireTime < aFireTime; >- >- // We need to look at the difference of the insertion orders instead of comparing the two >- // outright in case of overflow. >- unsigned difference = a->m_heapInsertionOrder - b->m_heapInsertionOrder; >- return difference < std::numeric_limits<unsigned>::max() / 2; >-} >- > // ---------------- > > static bool shouldSuppressThreadSafetyCheck() >@@ -250,7 +320,15 @@ > ASSERT(!timerHeap().isEmpty()); > ASSERT(m_heapIndex >= 0); > ASSERT(m_heapIndex < static_cast<int>(timerHeap().size())); >- ASSERT(timerHeap()[m_heapIndex] == this); >+ ASSERT(timerHeap()[m_heapIndex].timer == this); >+ ASSERT(timerHeap()[m_heapIndex].time == m_nextFireTime); >+ ASSERT(timerHeap()[m_heapIndex].insertionOrder == m_heapInsertionOrder); >+#if !ASSERT_DISABLED >+ ASSERT(timerHeap().size() < INT_MAX); >+ int size = timerHeap().size(); >+ for (int i = 0; i < size; i++) >+ ASSERT(timerHeap()[i].timer->m_heapIndex == i); >+#endif > } > > inline void TimerBase::checkConsistency() const >@@ -265,7 +343,7 @@ > { > ASSERT(static_cast<bool>(m_nextFireTime)); > checkHeapIndex(); >- TimerBase** heapData = timerHeap().data(); >+ auto* heapData = timerHeap().data(); > push_heap(TimerHeapIterator(heapData), TimerHeapIterator(heapData + m_heapIndex + 1), TimerHeapLessThanFunction()); > checkHeapIndex(); > } >@@ -296,7 +374,7 @@ > inline void TimerBase::heapInsert() > { > ASSERT(!inHeap()); >- timerHeap().append(this); >+ timerHeap().append(ThreadTimerHeapItem { *this, m_nextFireTime, m_heapInsertionOrder }); > m_heapIndex = timerHeap().size() - 1; > heapDecreaseKey(); > } >@@ -306,37 +384,44 @@ > // Temporarily force this timer to have the minimum key so we can pop it. > MonotonicTime fireTime = m_nextFireTime; > m_nextFireTime = -MonotonicTime::infinity(); >+ timerHeap()[m_heapIndex].time = m_nextFireTime; > heapDecreaseKey(); > heapPopMin(); > m_nextFireTime = fireTime; >+ timerHeap()[m_heapIndex].time = fireTime; > } > > void TimerBase::heapPopMin() > { >- ASSERT(this == timerHeap().first()); >+ ASSERT(this == timerHeap().first().timer); > checkHeapIndex(); >- Vector<TimerBase*>& heap = timerHeap(); >- TimerBase** heapData = heap.data(); >+ auto& heap = timerHeap(); >+ auto* heapData = heap.data(); > pop_heap(TimerHeapIterator(heapData), TimerHeapIterator(heapData + heap.size()), TimerHeapLessThanFunction()); > checkHeapIndex(); >- ASSERT(this == timerHeap().last()); >+ ASSERT(this == timerHeap().last().timer); > } > >-static inline bool parentHeapPropertyHolds(const TimerBase* current, const Vector<TimerBase*>& heap, unsigned currentIndex) >+void TimerBase::heapDeleteNullMin(ThreadTimerHeap& heap) > { >+ RELEASE_ASSERT(!heap.first().timer); >+ auto* heapData = heap.data(); >+ pop_heap(TimerHeapIterator(heapData), TimerHeapIterator(heapData + heap.size()), TimerHeapLessThanFunction()); >+} >+ >+static inline bool parentHeapPropertyHolds(const TimerBase* current, const ThreadTimerHeap& heap, unsigned currentIndex) >+{ > if (!currentIndex) > return true; > unsigned parentIndex = (currentIndex - 1) / 2; >- TimerHeapLessThanFunction compareHeapPosition; >- return compareHeapPosition(current, heap[parentIndex]); >+ return TimerHeapLessThanFunction::compare(*current, heap[parentIndex]); > } > >-static inline bool childHeapPropertyHolds(const TimerBase* current, const Vector<TimerBase*>& heap, unsigned childIndex) >+static inline bool childHeapPropertyHolds(const TimerBase* current, const ThreadTimerHeap& heap, unsigned childIndex) > { > if (childIndex >= heap.size()) > return true; >- TimerHeapLessThanFunction compareHeapPosition; >- return compareHeapPosition(heap[childIndex], current); >+ return TimerHeapLessThanFunction::compare(heap[childIndex], *current); > } > > bool TimerBase::hasValidHeapPosition() const >@@ -347,7 +432,7 @@ > // Check if the heap property still holds with the new fire time. If it does we don't need to do anything. > // This assumes that the STL heap is a standard binary heap. In an unlikely event it is not, the assertions > // in updateHeapIfNeeded() will get hit. >- const Vector<TimerBase*>& heap = timerHeap(); >+ const auto& heap = timerHeap(); > if (!parentHeapPropertyHolds(this, heap, m_heapIndex)) > return false; > unsigned childIndex1 = 2 * m_heapIndex + 1; >@@ -357,11 +442,18 @@ > > void TimerBase::updateHeapIfNeeded(MonotonicTime oldTime) > { >+ if (oldTime) { >+ auto& item = timerHeap()[m_heapIndex]; >+ item.time = m_nextFireTime; >+ item.insertionOrder = m_heapInsertionOrder; >+ } >+ > if (m_nextFireTime && hasValidHeapPosition()) > return; > #ifndef NDEBUG > int oldHeapIndex = m_heapIndex; > #endif >+ > if (!oldTime) > heapInsert(); > else if (!m_nextFireTime) >@@ -370,6 +462,7 @@ > heapDecreaseKey(); > else > heapIncreaseKey(); >+ > ASSERT(m_heapIndex != oldHeapIndex); > ASSERT(!inHeap() || hasValidHeapPosition()); > } >Index: Source/WebCore/platform/Timer.h >=================================================================== >--- Source/WebCore/platform/Timer.h (revision 239401) >+++ Source/WebCore/platform/Timer.h (working copy) >@@ -33,6 +33,8 @@ > #include <wtf/Seconds.h> > #include <wtf/Threading.h> > #include <wtf/Vector.h> >+#include <wtf/WeakPtr.h> >+#include "ThreadTimers.h" > > #if PLATFORM(IOS_FAMILY) > #include "WebCoreThread.h" >@@ -40,11 +42,7 @@ > > namespace WebCore { > >-// Time intervals are all in seconds. >- >-class TimerHeapElement; >- >-class TimerBase { >+class TimerBase : public CanMakeWeakPtr<TimerBase> { > WTF_MAKE_NONCOPYABLE(TimerBase); > WTF_MAKE_FAST_ALLOCATED; > public: >@@ -92,8 +90,9 @@ > void heapInsert(); > void heapPop(); > void heapPopMin(); >+ static void heapDeleteNullMin(ThreadTimerHeap&); > >- Vector<TimerBase*>& timerHeap() const { ASSERT(m_cachedThreadGlobalTimerHeap); return *m_cachedThreadGlobalTimerHeap; } >+ ThreadTimerHeap& timerHeap() const { ASSERT(m_cachedThreadGlobalTimerHeap); return *m_cachedThreadGlobalTimerHeap; } > > MonotonicTime m_nextFireTime; // 0 if inactive > MonotonicTime m_unalignedNextFireTime; // m_nextFireTime not considering alignment interval >@@ -101,7 +100,7 @@ > signed int m_heapIndex : 31; // -1 if not in heap > bool m_wasDeleted : 1; > unsigned m_heapInsertionOrder; // Used to keep order among equal-fire-time timers >- Vector<TimerBase*>* m_cachedThreadGlobalTimerHeap { nullptr }; >+ ThreadTimerHeap* m_cachedThreadGlobalTimerHeap { nullptr }; > > Ref<Thread> m_thread { Thread::current() }; >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 192975
:
357931
|
357980
|
358010
|
358055
|
358766
|
358771