summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/wtf
diff options
context:
space:
mode:
authorFeng Qian <>2009-04-10 18:11:29 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2009-04-10 18:11:29 -0700
commit8f72e70a9fd78eec56623b3a62e68f16b7b27e28 (patch)
tree181bf9a400c30a1bf34ea6d72560e8d00111d549 /JavaScriptCore/wtf
parent7ed56f225e0ade046e1c2178977f72b2d896f196 (diff)
downloadexternal_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.zip
external_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.tar.gz
external_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.tar.bz2
AI 145796: Land the WebKit merge @r42026.
Automated import of CL 145796
Diffstat (limited to 'JavaScriptCore/wtf')
-rw-r--r--JavaScriptCore/wtf/Assertions.h2
-rw-r--r--JavaScriptCore/wtf/ByteArray.h3
-rw-r--r--JavaScriptCore/wtf/CrossThreadRefCounted.h165
-rw-r--r--JavaScriptCore/wtf/CurrentTime.cpp74
-rw-r--r--JavaScriptCore/wtf/Deque.h121
-rw-r--r--JavaScriptCore/wtf/FastMalloc.cpp223
-rw-r--r--JavaScriptCore/wtf/HashTraits.h43
-rw-r--r--JavaScriptCore/wtf/MainThread.cpp73
-rw-r--r--JavaScriptCore/wtf/MainThread.h4
-rw-r--r--JavaScriptCore/wtf/MessageQueue.h40
-rw-r--r--JavaScriptCore/wtf/OwnPtr.h11
-rw-r--r--JavaScriptCore/wtf/Platform.h56
-rw-r--r--JavaScriptCore/wtf/RefCounted.h12
-rw-r--r--JavaScriptCore/wtf/RetainPtr.h11
-rw-r--r--JavaScriptCore/wtf/TCPageMap.h33
-rw-r--r--JavaScriptCore/wtf/TCSystemAlloc.cpp44
-rw-r--r--JavaScriptCore/wtf/TCSystemAlloc.h8
-rw-r--r--JavaScriptCore/wtf/ThreadSpecific.h16
-rw-r--r--JavaScriptCore/wtf/ThreadSpecificWin.cpp17
-rw-r--r--JavaScriptCore/wtf/Threading.cpp22
-rw-r--r--JavaScriptCore/wtf/Threading.h64
-rw-r--r--JavaScriptCore/wtf/ThreadingGtk.cpp4
-rw-r--r--JavaScriptCore/wtf/ThreadingNone.cpp1
-rw-r--r--JavaScriptCore/wtf/ThreadingPthreads.cpp49
-rw-r--r--JavaScriptCore/wtf/ThreadingQt.cpp16
-rw-r--r--JavaScriptCore/wtf/ThreadingWin.cpp24
-rw-r--r--JavaScriptCore/wtf/TypeTraits.cpp120
-rw-r--r--JavaScriptCore/wtf/TypeTraits.h133
-rw-r--r--JavaScriptCore/wtf/Vector.h17
-rw-r--r--JavaScriptCore/wtf/VectorTraits.h19
-rw-r--r--JavaScriptCore/wtf/android/MainThreadAndroid.cpp4
-rw-r--r--JavaScriptCore/wtf/chromium/ChromiumThreading.h45
-rw-r--r--JavaScriptCore/wtf/chromium/MainThreadChromium.cpp49
-rw-r--r--JavaScriptCore/wtf/dtoa.cpp24
-rw-r--r--JavaScriptCore/wtf/gtk/MainThreadGtk.cpp7
-rw-r--r--JavaScriptCore/wtf/mac/MainThreadMac.mm14
-rw-r--r--JavaScriptCore/wtf/qt/MainThreadQt.cpp5
-rw-r--r--JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h5
-rw-r--r--JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h6
-rw-r--r--JavaScriptCore/wtf/win/MainThreadWin.cpp6
-rw-r--r--JavaScriptCore/wtf/wx/MainThreadWx.cpp6
41 files changed, 1225 insertions, 371 deletions
diff --git a/JavaScriptCore/wtf/Assertions.h b/JavaScriptCore/wtf/Assertions.h
index c17e501..9643517 100644
--- a/JavaScriptCore/wtf/Assertions.h
+++ b/JavaScriptCore/wtf/Assertions.h
@@ -194,7 +194,7 @@ while (0)
/* COMPILE_ASSERT */
#ifndef COMPILE_ASSERT
-#define COMPILE_ASSERT(exp, name) typedef int dummy##name [(exp) ? 1 : -1];
+#define COMPILE_ASSERT(exp, name) typedef int dummy##name [(exp) ? 1 : -1]
#endif
/* FATAL */
diff --git a/JavaScriptCore/wtf/ByteArray.h b/JavaScriptCore/wtf/ByteArray.h
index 865c30e..33f0877 100644
--- a/JavaScriptCore/wtf/ByteArray.h
+++ b/JavaScriptCore/wtf/ByteArray.h
@@ -69,8 +69,7 @@ namespace WTF {
private:
ByteArray(size_t size)
- : RefCountedBase(1)
- , m_size(size)
+ : m_size(size)
{
}
size_t m_size;
diff --git a/JavaScriptCore/wtf/CrossThreadRefCounted.h b/JavaScriptCore/wtf/CrossThreadRefCounted.h
new file mode 100644
index 0000000..82f1ba1
--- /dev/null
+++ b/JavaScriptCore/wtf/CrossThreadRefCounted.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CrossThreadRefCounted_h
+#define CrossThreadRefCounted_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Threading.h>
+#include <wtf/TypeTraits.h>
+
+namespace WTF {
+
+ // Used to allowing sharing data across classes and threads (like ThreadedSafeShared).
+ //
+ // Why not just use ThreadSafeShared?
+ // ThreadSafeShared can have a significant perf impact when used in low level classes
+ // (like UString) that get ref/deref'ed a lot. This class has the benefit of doing fast ref
+ // counts like RefPtr whenever possible, but it has the downside that you need to copy it
+ // to use it on another thread.
+ //
+ // Is this class threadsafe?
+ // While each instance of the class is not threadsafe, the copied instance is threadsafe
+ // with respect to the original and any other copies. The underlying m_data is jointly
+ // owned by the original instance and all copies.
+ template<class T>
+ class CrossThreadRefCounted : Noncopyable {
+ public:
+ static PassRefPtr<CrossThreadRefCounted<T> > create(T* data)
+ {
+ return adoptRef(new CrossThreadRefCounted<T>(data, 0));
+ }
+
+ // Used to make an instance that can be used on another thread.
+ PassRefPtr<CrossThreadRefCounted<T> > crossThreadCopy();
+
+ void ref();
+ void deref();
+ T* release();
+
+#ifndef NDEBUG
+ bool mayBePassedToAnotherThread() const { ASSERT(!m_threadId); return m_refCounter.hasOneRef(); }
+#endif
+
+ private:
+ CrossThreadRefCounted(T* data, ThreadSafeSharedBase* threadedCounter)
+ : m_threadSafeRefCounter(threadedCounter)
+ , m_data(data)
+#ifndef NDEBUG
+ , m_threadId(0)
+#endif
+ {
+ }
+
+ ~CrossThreadRefCounted()
+ {
+ if (!m_threadSafeRefCounter)
+ delete m_data;
+ }
+
+ void threadSafeDeref();
+
+ RefCountedBase m_refCounter;
+ ThreadSafeSharedBase* m_threadSafeRefCounter;
+ T* m_data;
+#ifndef NDEBUG
+ ThreadIdentifier m_threadId;
+#endif
+ };
+
+ template<class T>
+ void CrossThreadRefCounted<T>::ref()
+ {
+ ASSERT(!m_threadId || m_threadId == currentThread());
+ m_refCounter.ref();
+#ifndef NDEBUG
+ // Store the threadId as soon as the ref count gets to 2.
+ // The class gets created with a ref count of 1 and then passed
+ // to another thread where to ref count get increased. This
+ // is a heuristic but it seems to always work and has helped
+ // find some bugs.
+ if (!m_threadId && m_refCounter.refCount() == 2)
+ m_threadId = currentThread();
+#endif
+ }
+
+ template<class T>
+ void CrossThreadRefCounted<T>::deref()
+ {
+ ASSERT(!m_threadId || m_threadId == currentThread());
+ if (m_refCounter.derefBase()) {
+ threadSafeDeref();
+ delete this;
+ } else {
+#ifndef NDEBUG
+ // Clear the threadId when the ref goes to 1 because it
+ // is safe to be passed to another thread at this point.
+ if (m_threadId && m_refCounter.refCount() == 1)
+ m_threadId = 0;
+#endif
+ }
+ }
+
+ template<class T>
+ T* CrossThreadRefCounted<T>::release()
+ {
+ ASSERT(!isShared());
+
+ T* data = m_data;
+ m_data = 0;
+ return data;
+ }
+
+ template<class T>
+ PassRefPtr<CrossThreadRefCounted<T> > CrossThreadRefCounted<T>::crossThreadCopy()
+ {
+ if (m_threadSafeRefCounter)
+ m_threadSafeRefCounter->ref();
+ else
+ m_threadSafeRefCounter = new ThreadSafeSharedBase(2);
+ return adoptRef(new CrossThreadRefCounted<T>(m_data, m_threadSafeRefCounter));
+ }
+
+
+ template<class T>
+ void CrossThreadRefCounted<T>::threadSafeDeref()
+ {
+ if (m_threadSafeRefCounter && m_threadSafeRefCounter->derefBase()) {
+ delete m_threadSafeRefCounter;
+ m_threadSafeRefCounter = 0;
+ }
+ }
+} // namespace WTF
+
+using WTF::CrossThreadRefCounted;
+
+#endif // CrossThreadRefCounted_h
diff --git a/JavaScriptCore/wtf/CurrentTime.cpp b/JavaScriptCore/wtf/CurrentTime.cpp
index d9ea448..74984c1 100644
--- a/JavaScriptCore/wtf/CurrentTime.cpp
+++ b/JavaScriptCore/wtf/CurrentTime.cpp
@@ -32,13 +32,9 @@
#include "config.h"
#include "CurrentTime.h"
-#if PLATFORM(MAC)
-#include <CoreFoundation/CFDate.h>
-#elif PLATFORM(GTK)
-#include <glib.h>
-#elif PLATFORM(WX)
-#include <wx/datetime.h>
-#elif PLATFORM(WIN_OS)
+#if PLATFORM(WIN_OS)
+// Windows is first since we want to use hires timers, despite PLATFORM(CF)
+// being defined.
// If defined, WIN32_LEAN_AND_MEAN disables timeBeginPeriod/timeEndPeriod.
#undef WIN32_LEAN_AND_MEAN
#include <windows.h>
@@ -47,6 +43,12 @@
#include <sys/timeb.h>
#include <sys/types.h>
#include <time.h>
+#elif PLATFORM(CF)
+#include <CoreFoundation/CFDate.h>
+#elif PLATFORM(GTK)
+#include <glib.h>
+#elif PLATFORM(WX)
+#include <wx/datetime.h>
#else // Posix systems relying on the gettimeofday()
#include <sys/time.h>
#endif
@@ -55,35 +57,7 @@ namespace WTF {
const double msPerSecond = 1000.0;
-#if PLATFORM(MAC)
-
-double currentTime()
-{
- return CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970;
-}
-
-#elif PLATFORM(GTK)
-
-// Note: GTK on Windows will pick up the PLATFORM(WIN) implementation above which provides
-// better accuracy compared with Windows implementation of g_get_current_time:
-// (http://www.google.com/codesearch/p?hl=en#HHnNRjks1t0/glib-2.5.2/glib/gmain.c&q=g_get_current_time).
-// Non-Windows GTK builds could use gettimeofday() directly but for the sake of consistency lets use GTK function.
-double currentTime()
-{
- GTimeVal now;
- g_get_current_time(&now);
- return static_cast<double>(now.tv_sec) + static_cast<double>(now.tv_usec / 1000000.0);
-}
-
-#elif PLATFORM(WX)
-
-double currentTime()
-{
- wxDateTime now = wxDateTime::UNow();
- return (double)now.GetTicks() + (double)(now.GetMillisecond() / 1000.0);
-}
-
-#elif PLATFORM(WIN_OS)
+#if PLATFORM(WIN_OS)
static LARGE_INTEGER qpcFrequency;
static bool syncedTime;
@@ -210,6 +184,34 @@ double currentTime()
return utc / 1000.0;
}
+#elif PLATFORM(CF)
+
+double currentTime()
+{
+ return CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970;
+}
+
+#elif PLATFORM(GTK)
+
+// Note: GTK on Windows will pick up the PLATFORM(WIN) implementation above which provides
+// better accuracy compared with Windows implementation of g_get_current_time:
+// (http://www.google.com/codesearch/p?hl=en#HHnNRjks1t0/glib-2.5.2/glib/gmain.c&q=g_get_current_time).
+// Non-Windows GTK builds could use gettimeofday() directly but for the sake of consistency lets use GTK function.
+double currentTime()
+{
+ GTimeVal now;
+ g_get_current_time(&now);
+ return static_cast<double>(now.tv_sec) + static_cast<double>(now.tv_usec / 1000000.0);
+}
+
+#elif PLATFORM(WX)
+
+double currentTime()
+{
+ wxDateTime now = wxDateTime::UNow();
+ return (double)now.GetTicks() + (double)(now.GetMillisecond() / 1000.0);
+}
+
#else // Other Posix systems rely on the gettimeofday().
double currentTime()
diff --git a/JavaScriptCore/wtf/Deque.h b/JavaScriptCore/wtf/Deque.h
index 70c546b..c371d38 100644
--- a/JavaScriptCore/wtf/Deque.h
+++ b/JavaScriptCore/wtf/Deque.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -75,9 +76,14 @@ namespace WTF {
template<typename U> void append(const U&);
template<typename U> void prepend(const U&);
void removeFirst();
+ void remove(iterator&);
+ void remove(const_iterator&);
void clear();
+ template<typename Predicate>
+ iterator findIf(Predicate&);
+
private:
friend class DequeIteratorBase<T>;
@@ -85,6 +91,7 @@ namespace WTF {
typedef VectorTypeOperations<T> TypeOperations;
typedef DequeIteratorBase<T> IteratorBase;
+ void remove(size_t position);
void invalidateIterators();
void destroyAll();
void checkValidity() const;
@@ -124,6 +131,7 @@ namespace WTF {
private:
void addToIteratorsList();
+ void removeFromIteratorsList();
void checkValidity() const;
void checkValidity(const Base&) const;
@@ -348,7 +356,7 @@ namespace WTF {
destroyAll();
}
- template <typename T>
+ template<typename T>
inline void Deque<T>::swap(Deque<T>& other)
{
checkValidity();
@@ -361,7 +369,7 @@ namespace WTF {
other.checkValidity();
}
- template <typename T>
+ template<typename T>
inline void Deque<T>::clear()
{
checkValidity();
@@ -373,6 +381,18 @@ namespace WTF {
}
template<typename T>
+ template<typename Predicate>
+ inline DequeIterator<T> Deque<T>::findIf(Predicate& predicate)
+ {
+ iterator end_iterator = end();
+ for (iterator it = begin(); it != end_iterator; ++it) {
+ if (predicate(*it))
+ return it;
+ }
+ return end_iterator;
+ }
+
+ template<typename T>
inline void Deque<T>::expandCapacityIfNeeded()
{
if (m_start) {
@@ -447,10 +467,48 @@ namespace WTF {
checkValidity();
}
+ template<typename T>
+ inline void Deque<T>::remove(iterator& it)
+ {
+ it.checkValidity();
+ remove(it.m_index);
+ }
+
+ template<typename T>
+ inline void Deque<T>::remove(const_iterator& it)
+ {
+ it.checkValidity();
+ remove(it.m_index);
+ }
+
+ template<typename T>
+ inline void Deque<T>::remove(size_t position)
+ {
+ if (position == m_end)
+ return;
+
+ checkValidity();
+ invalidateIterators();
+
+ T* buffer = m_buffer.buffer();
+ TypeOperations::destruct(&buffer[position], &buffer[position + 1]);
+
+ // Find which segment of the circular buffer contained the remove element, and only move elements in that part.
+ if (position >= m_start) {
+ TypeOperations::moveOverlapping(buffer + m_start, buffer + position, buffer + m_start + 1);
+ m_start = (m_start + 1) % m_buffer.capacity();
+ } else {
+ TypeOperations::moveOverlapping(buffer + position + 1, buffer + m_end, buffer + position);
+ m_end = (m_end - 1 + m_buffer.capacity()) % m_buffer.capacity();
+ }
+ checkValidity();
+ }
+
#ifdef NDEBUG
template<typename T> inline void DequeIteratorBase<T>::checkValidity() const { }
template<typename T> inline void DequeIteratorBase<T>::checkValidity(const DequeIteratorBase<T>&) const { }
template<typename T> inline void DequeIteratorBase<T>::addToIteratorsList() { }
+ template<typename T> inline void DequeIteratorBase<T>::removeFromIteratorsList() { }
#else
template<typename T>
void DequeIteratorBase<T>::checkValidity() const
@@ -480,6 +538,30 @@ namespace WTF {
}
m_previous = 0;
}
+
+ template<typename T>
+ void DequeIteratorBase<T>::removeFromIteratorsList()
+ {
+ if (!m_deque) {
+ ASSERT(!m_next);
+ ASSERT(!m_previous);
+ } else {
+ if (m_next) {
+ ASSERT(m_next->m_previous == this);
+ m_next->m_previous = m_previous;
+ }
+ if (m_previous) {
+ ASSERT(m_deque->m_iterators != this);
+ ASSERT(m_previous->m_next == this);
+ m_previous->m_next = m_next;
+ } else {
+ ASSERT(m_deque->m_iterators == this);
+ m_deque->m_iterators = m_next;
+ }
+ }
+ m_next = 0;
+ m_previous = 0;
+ }
#endif
template<typename T>
@@ -507,30 +589,25 @@ namespace WTF {
}
template<typename T>
+ inline DequeIteratorBase<T>& DequeIteratorBase<T>::operator=(const Base& other)
+ {
+ checkValidity();
+ other.checkValidity();
+ removeFromIteratorsList();
+
+ m_deque = other.m_deque;
+ m_index = other.m_index;
+ addToIteratorsList();
+ checkValidity();
+ return *this;
+ }
+
+ template<typename T>
inline DequeIteratorBase<T>::~DequeIteratorBase()
{
#ifndef NDEBUG
- // Delete iterator from doubly-linked list of iterators.
- if (!m_deque) {
- ASSERT(!m_next);
- ASSERT(!m_previous);
- } else {
- if (m_next) {
- ASSERT(m_next->m_previous == this);
- m_next->m_previous = m_previous;
- }
- if (m_previous) {
- ASSERT(m_deque->m_iterators != this);
- ASSERT(m_previous->m_next == this);
- m_previous->m_next = m_next;
- } else {
- ASSERT(m_deque->m_iterators == this);
- m_deque->m_iterators = m_next;
- }
- }
+ removeFromIteratorsList();
m_deque = 0;
- m_next = 0;
- m_previous = 0;
#endif
}
diff --git a/JavaScriptCore/wtf/FastMalloc.cpp b/JavaScriptCore/wtf/FastMalloc.cpp
index 88c10ca..bcac242 100644
--- a/JavaScriptCore/wtf/FastMalloc.cpp
+++ b/JavaScriptCore/wtf/FastMalloc.cpp
@@ -94,7 +94,7 @@
#define FORCE_SYSTEM_MALLOC 1
#endif
-#define TCMALLOC_TRACK_DECOMMITED_SPANS (HAVE(VIRTUALALLOC))
+#define TCMALLOC_TRACK_DECOMMITED_SPANS (HAVE(VIRTUALALLOC) || HAVE(MADV_FREE_REUSE))
#ifndef NDEBUG
namespace WTF {
@@ -321,9 +321,11 @@ namespace WTF {
#define CHECK_CONDITION ASSERT
#if PLATFORM(DARWIN)
+class Span;
+class TCMalloc_Central_FreeListPadded;
class TCMalloc_PageHeap;
class TCMalloc_ThreadCache;
-class TCMalloc_Central_FreeListPadded;
+template <typename T> class PageHeapAllocator;
class FastMallocZone {
public:
@@ -339,7 +341,7 @@ public:
static void statistics(malloc_zone_t*, malloc_statistics_t* stats) { memset(stats, 0, sizeof(malloc_statistics_t)); }
private:
- FastMallocZone(TCMalloc_PageHeap*, TCMalloc_ThreadCache**, TCMalloc_Central_FreeListPadded*);
+ FastMallocZone(TCMalloc_PageHeap*, TCMalloc_ThreadCache**, TCMalloc_Central_FreeListPadded*, PageHeapAllocator<Span>*, PageHeapAllocator<TCMalloc_ThreadCache>*);
static size_t size(malloc_zone_t*, const void*);
static void* zoneMalloc(malloc_zone_t*, size_t);
static void* zoneCalloc(malloc_zone_t*, size_t numItems, size_t size);
@@ -352,6 +354,8 @@ private:
TCMalloc_PageHeap* m_pageHeap;
TCMalloc_ThreadCache** m_threadHeaps;
TCMalloc_Central_FreeListPadded* m_centralCaches;
+ PageHeapAllocator<Span>* m_spanAllocator;
+ PageHeapAllocator<TCMalloc_ThreadCache>* m_pageHeapAllocator;
};
#endif
@@ -820,6 +824,9 @@ class PageHeapAllocator {
char* free_area_;
size_t free_avail_;
+ // Linked list of all regions allocated by this allocator
+ void* allocated_regions_;
+
// Free list of already carved objects
void* free_list_;
@@ -830,6 +837,7 @@ class PageHeapAllocator {
void Init() {
ASSERT(kAlignedSize <= kAllocIncrement);
inuse_ = 0;
+ allocated_regions_ = 0;
free_area_ = NULL;
free_avail_ = 0;
free_list_ = NULL;
@@ -844,9 +852,14 @@ class PageHeapAllocator {
} else {
if (free_avail_ < kAlignedSize) {
// Need more room
- free_area_ = reinterpret_cast<char*>(MetaDataAlloc(kAllocIncrement));
- if (free_area_ == NULL) CRASH();
- free_avail_ = kAllocIncrement;
+ char* new_allocation = reinterpret_cast<char*>(MetaDataAlloc(kAllocIncrement));
+ if (!new_allocation)
+ CRASH();
+
+ *(void**)new_allocation = allocated_regions_;
+ allocated_regions_ = new_allocation;
+ free_area_ = new_allocation + kAlignedSize;
+ free_avail_ = kAllocIncrement - kAlignedSize;
}
result = free_area_;
free_area_ += kAlignedSize;
@@ -863,6 +876,18 @@ class PageHeapAllocator {
}
int inuse() const { return inuse_; }
+
+#if defined(WTF_CHANGES) && PLATFORM(DARWIN)
+ template <class Recorder>
+ void recordAdministrativeRegions(Recorder& recorder, const RemoteMemoryReader& reader)
+ {
+ vm_address_t adminAllocation = reinterpret_cast<vm_address_t>(allocated_regions_);
+ while (adminAllocation) {
+ recorder.recordRegion(adminAllocation, kAllocIncrement);
+ adminAllocation = *reader(reinterpret_cast<vm_address_t*>(adminAllocation));
+ }
+ }
+#endif
};
// -------------------------------------------------------------------------
@@ -1378,8 +1403,14 @@ static ALWAYS_INLINE void mergeDecommittedStates(Span*, Span*) { }
#else
static ALWAYS_INLINE void mergeDecommittedStates(Span* destination, Span* other)
{
- if (other->decommitted)
+ if (destination->decommitted && !other->decommitted) {
+ TCMalloc_SystemRelease(reinterpret_cast<void*>(other->start << kPageShift),
+ static_cast<size_t>(other->length << kPageShift));
+ } else if (other->decommitted && !destination->decommitted) {
+ TCMalloc_SystemRelease(reinterpret_cast<void*>(destination->start << kPageShift),
+ static_cast<size_t>(destination->length << kPageShift));
destination->decommitted = true;
+ }
}
#endif
@@ -3571,7 +3602,7 @@ extern "C" struct mallinfo mallinfo(void) {
#if defined(__GLIBC__)
extern "C" {
-# if defined(__GNUC__) && !defined(__MACH__) && defined(HAVE___ATTRIBUTE__)
+#if COMPILER(GCC) && !defined(__MACH__) && defined(HAVE___ATTRIBUTE__)
// Potentially faster variants that use the gcc alias extension.
// Mach-O (Darwin) does not support weak aliases, hence the __MACH__ check.
# define ALIAS(x) __attribute__ ((weak, alias (x)))
@@ -3630,6 +3661,7 @@ public:
void visit(void* ptr) { m_freeObjects.add(ptr); }
bool isFreeObject(void* ptr) const { return m_freeObjects.contains(ptr); }
+ bool isFreeObject(vm_address_t ptr) const { return isFreeObject(reinterpret_cast<void*>(ptr)); }
size_t freeObjectCount() const { return m_freeObjects.size(); }
void findFreeObjects(TCMalloc_ThreadCache* threadCache)
@@ -3680,7 +3712,9 @@ class PageMapMemoryUsageRecorder {
vm_range_recorder_t* m_recorder;
const RemoteMemoryReader& m_reader;
const FreeObjectFinder& m_freeObjectFinder;
- mutable HashSet<void*> m_seenPointers;
+
+ HashSet<void*> m_seenPointers;
+ Vector<Span*> m_coalescedSpans;
public:
PageMapMemoryUsageRecorder(task_t task, void* context, unsigned typeMask, vm_range_recorder_t* recorder, const RemoteMemoryReader& reader, const FreeObjectFinder& freeObjectFinder)
@@ -3692,51 +3726,133 @@ public:
, m_freeObjectFinder(freeObjectFinder)
{ }
- int visit(void* ptr) const
+ ~PageMapMemoryUsageRecorder()
+ {
+ ASSERT(!m_coalescedSpans.size());
+ }
+
+ void recordPendingRegions()
+ {
+ Span* lastSpan = m_coalescedSpans[m_coalescedSpans.size() - 1];
+ vm_range_t ptrRange = { m_coalescedSpans[0]->start << kPageShift, 0 };
+ ptrRange.size = (lastSpan->start << kPageShift) - ptrRange.address + (lastSpan->length * kPageSize);
+
+ // Mark the memory region the spans represent as a candidate for containing pointers
+ if (m_typeMask & MALLOC_PTR_REGION_RANGE_TYPE)
+ (*m_recorder)(m_task, m_context, MALLOC_PTR_REGION_RANGE_TYPE, &ptrRange, 1);
+
+ if (!(m_typeMask & MALLOC_PTR_IN_USE_RANGE_TYPE)) {
+ m_coalescedSpans.clear();
+ return;
+ }
+
+ Vector<vm_range_t, 1024> allocatedPointers;
+ for (size_t i = 0; i < m_coalescedSpans.size(); ++i) {
+ Span *theSpan = m_coalescedSpans[i];
+ if (theSpan->free)
+ continue;
+
+ vm_address_t spanStartAddress = theSpan->start << kPageShift;
+ vm_size_t spanSizeInBytes = theSpan->length * kPageSize;
+
+ if (!theSpan->sizeclass) {
+ // If it's an allocated large object span, mark it as in use
+ if (!m_freeObjectFinder.isFreeObject(spanStartAddress))
+ allocatedPointers.append((vm_range_t){spanStartAddress, spanSizeInBytes});
+ } else {
+ const size_t objectSize = ByteSizeForClass(theSpan->sizeclass);
+
+ // Mark each allocated small object within the span as in use
+ const vm_address_t endOfSpan = spanStartAddress + spanSizeInBytes;
+ for (vm_address_t object = spanStartAddress; object + objectSize <= endOfSpan; object += objectSize) {
+ if (!m_freeObjectFinder.isFreeObject(object))
+ allocatedPointers.append((vm_range_t){object, objectSize});
+ }
+ }
+ }
+
+ (*m_recorder)(m_task, m_context, MALLOC_PTR_IN_USE_RANGE_TYPE, allocatedPointers.data(), allocatedPointers.size());
+
+ m_coalescedSpans.clear();
+ }
+
+ int visit(void* ptr)
{
if (!ptr)
return 1;
Span* span = m_reader(reinterpret_cast<Span*>(ptr));
+ if (!span->start)
+ return 1;
+
if (m_seenPointers.contains(ptr))
return span->length;
m_seenPointers.add(ptr);
- // Mark the memory used for the Span itself as an administrative region
- vm_range_t ptrRange = { reinterpret_cast<vm_address_t>(ptr), sizeof(Span) };
- if (m_typeMask & (MALLOC_PTR_REGION_RANGE_TYPE | MALLOC_ADMIN_REGION_RANGE_TYPE))
- (*m_recorder)(m_task, m_context, MALLOC_ADMIN_REGION_RANGE_TYPE, &ptrRange, 1);
+ if (!m_coalescedSpans.size()) {
+ m_coalescedSpans.append(span);
+ return span->length;
+ }
- ptrRange.address = span->start << kPageShift;
- ptrRange.size = span->length * kPageSize;
+ Span* previousSpan = m_coalescedSpans[m_coalescedSpans.size() - 1];
+ vm_address_t previousSpanStartAddress = previousSpan->start << kPageShift;
+ vm_size_t previousSpanSizeInBytes = previousSpan->length * kPageSize;
- // Mark the memory region the span represents as candidates for containing pointers
- if (m_typeMask & (MALLOC_PTR_REGION_RANGE_TYPE | MALLOC_ADMIN_REGION_RANGE_TYPE))
- (*m_recorder)(m_task, m_context, MALLOC_PTR_REGION_RANGE_TYPE, &ptrRange, 1);
+ // If the new span is adjacent to the previous span, do nothing for now.
+ vm_address_t spanStartAddress = span->start << kPageShift;
+ if (spanStartAddress == previousSpanStartAddress + previousSpanSizeInBytes) {
+ m_coalescedSpans.append(span);
+ return span->length;
+ }
- if (!span->free && (m_typeMask & MALLOC_PTR_IN_USE_RANGE_TYPE)) {
- // If it's an allocated large object span, mark it as in use
- if (span->sizeclass == 0 && !m_freeObjectFinder.isFreeObject(reinterpret_cast<void*>(ptrRange.address)))
- (*m_recorder)(m_task, m_context, MALLOC_PTR_IN_USE_RANGE_TYPE, &ptrRange, 1);
- else if (span->sizeclass) {
- const size_t byteSize = ByteSizeForClass(span->sizeclass);
- unsigned totalObjects = (span->length << kPageShift) / byteSize;
- ASSERT(span->refcount <= totalObjects);
- char* ptr = reinterpret_cast<char*>(span->start << kPageShift);
+ // New span is not adjacent to previous span, so record the spans coalesced so far.
+ recordPendingRegions();
+ m_coalescedSpans.append(span);
- // Mark each allocated small object within the span as in use
- for (unsigned i = 0; i < totalObjects; i++) {
- char* thisObject = ptr + (i * byteSize);
- if (m_freeObjectFinder.isFreeObject(thisObject))
- continue;
+ return span->length;
+ }
+};
- vm_range_t objectRange = { reinterpret_cast<vm_address_t>(thisObject), byteSize };
- (*m_recorder)(m_task, m_context, MALLOC_PTR_IN_USE_RANGE_TYPE, &objectRange, 1);
- }
- }
+class AdminRegionRecorder {
+ task_t m_task;
+ void* m_context;
+ unsigned m_typeMask;
+ vm_range_recorder_t* m_recorder;
+ const RemoteMemoryReader& m_reader;
+
+ Vector<vm_range_t, 1024> m_pendingRegions;
+
+public:
+ AdminRegionRecorder(task_t task, void* context, unsigned typeMask, vm_range_recorder_t* recorder, const RemoteMemoryReader& reader)
+ : m_task(task)
+ , m_context(context)
+ , m_typeMask(typeMask)
+ , m_recorder(recorder)
+ , m_reader(reader)
+ { }
+
+ void recordRegion(vm_address_t ptr, size_t size)
+ {
+ if (m_typeMask & MALLOC_ADMIN_REGION_RANGE_TYPE)
+ m_pendingRegions.append((vm_range_t){ ptr, size });
+ }
+
+ void visit(void *ptr, size_t size)
+ {
+ recordRegion(reinterpret_cast<vm_address_t>(ptr), size);
+ }
+
+ void recordPendingRegions()
+ {
+ if (m_pendingRegions.size()) {
+ (*m_recorder)(m_task, m_context, MALLOC_ADMIN_REGION_RANGE_TYPE, m_pendingRegions.data(), m_pendingRegions.size());
+ m_pendingRegions.clear();
}
+ }
- return span->length;
+ ~AdminRegionRecorder()
+ {
+ ASSERT(!m_pendingRegions.size());
}
};
@@ -3759,10 +3875,22 @@ kern_return_t FastMallocZone::enumerate(task_t task, void* context, unsigned typ
TCMalloc_PageHeap::PageMap* pageMap = &pageHeap->pagemap_;
PageMapFreeObjectFinder pageMapFinder(memoryReader, finder);
- pageMap->visit(pageMapFinder, memoryReader);
+ pageMap->visitValues(pageMapFinder, memoryReader);
PageMapMemoryUsageRecorder usageRecorder(task, context, typeMask, recorder, memoryReader, finder);
- pageMap->visit(usageRecorder, memoryReader);
+ pageMap->visitValues(usageRecorder, memoryReader);
+ usageRecorder.recordPendingRegions();
+
+ AdminRegionRecorder adminRegionRecorder(task, context, typeMask, recorder, memoryReader);
+ pageMap->visitAllocations(adminRegionRecorder, memoryReader);
+
+ PageHeapAllocator<Span>* spanAllocator = memoryReader(mzone->m_spanAllocator);
+ PageHeapAllocator<TCMalloc_ThreadCache>* pageHeapAllocator = memoryReader(mzone->m_pageHeapAllocator);
+
+ spanAllocator->recordAdministrativeRegions(adminRegionRecorder, memoryReader);
+ pageHeapAllocator->recordAdministrativeRegions(adminRegionRecorder, memoryReader);
+
+ adminRegionRecorder.recordPendingRegions();
return 0;
}
@@ -3803,15 +3931,24 @@ void* FastMallocZone::zoneRealloc(malloc_zone_t*, void*, size_t)
extern "C" {
malloc_introspection_t jscore_fastmalloc_introspection = { &FastMallocZone::enumerate, &FastMallocZone::goodSize, &FastMallocZone::check, &FastMallocZone::print,
- &FastMallocZone::log, &FastMallocZone::forceLock, &FastMallocZone::forceUnlock, &FastMallocZone::statistics };
+ &FastMallocZone::log, &FastMallocZone::forceLock, &FastMallocZone::forceUnlock, &FastMallocZone::statistics
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ , 0 // zone_locked will not be called on the zone unless it advertises itself as version five or higher.
+#endif
+
+ };
}
-FastMallocZone::FastMallocZone(TCMalloc_PageHeap* pageHeap, TCMalloc_ThreadCache** threadHeaps, TCMalloc_Central_FreeListPadded* centralCaches)
+FastMallocZone::FastMallocZone(TCMalloc_PageHeap* pageHeap, TCMalloc_ThreadCache** threadHeaps, TCMalloc_Central_FreeListPadded* centralCaches, PageHeapAllocator<Span>* spanAllocator, PageHeapAllocator<TCMalloc_ThreadCache>* pageHeapAllocator)
: m_pageHeap(pageHeap)
, m_threadHeaps(threadHeaps)
, m_centralCaches(centralCaches)
+ , m_spanAllocator(spanAllocator)
+ , m_pageHeapAllocator(pageHeapAllocator)
{
memset(&m_zone, 0, sizeof(m_zone));
+ m_zone.version = 4;
m_zone.zone_name = "JavaScriptCore FastMalloc";
m_zone.size = &FastMallocZone::size;
m_zone.malloc = &FastMallocZone::zoneMalloc;
@@ -3827,7 +3964,7 @@ FastMallocZone::FastMallocZone(TCMalloc_PageHeap* pageHeap, TCMalloc_ThreadCache
void FastMallocZone::init()
{
- static FastMallocZone zone(pageheap, &thread_heaps, static_cast<TCMalloc_Central_FreeListPadded*>(central_cache));
+ static FastMallocZone zone(pageheap, &thread_heaps, static_cast<TCMalloc_Central_FreeListPadded*>(central_cache), &span_allocator, &threadheap_allocator);
}
#endif
diff --git a/JavaScriptCore/wtf/HashTraits.h b/JavaScriptCore/wtf/HashTraits.h
index b3c0b7a..c8d40f7 100644
--- a/JavaScriptCore/wtf/HashTraits.h
+++ b/JavaScriptCore/wtf/HashTraits.h
@@ -21,8 +21,8 @@
#ifndef WTF_HashTraits_h
#define WTF_HashTraits_h
-#include "Assertions.h"
#include "HashFunctions.h"
+#include "TypeTraits.h"
#include <utility>
#include <limits>
@@ -31,47 +31,6 @@ namespace WTF {
using std::pair;
using std::make_pair;
- template<typename T> struct IsInteger { static const bool value = false; };
- template<> struct IsInteger<bool> { static const bool value = true; };
- template<> struct IsInteger<char> { static const bool value = true; };
- template<> struct IsInteger<signed char> { static const bool value = true; };
- template<> struct IsInteger<unsigned char> { static const bool value = true; };
- template<> struct IsInteger<short> { static const bool value = true; };
- template<> struct IsInteger<unsigned short> { static const bool value = true; };
- template<> struct IsInteger<int> { static const bool value = true; };
- template<> struct IsInteger<unsigned int> { static const bool value = true; };
- template<> struct IsInteger<long> { static const bool value = true; };
- template<> struct IsInteger<unsigned long> { static const bool value = true; };
- template<> struct IsInteger<long long> { static const bool value = true; };
- template<> struct IsInteger<unsigned long long> { static const bool value = true; };
-
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
- template<> struct IsInteger<wchar_t> { static const bool value = true; };
-#endif
-
- COMPILE_ASSERT(IsInteger<bool>::value, WTF_IsInteger_bool_true);
- COMPILE_ASSERT(IsInteger<char>::value, WTF_IsInteger_char_true);
- COMPILE_ASSERT(IsInteger<signed char>::value, WTF_IsInteger_signed_char_true);
- COMPILE_ASSERT(IsInteger<unsigned char>::value, WTF_IsInteger_unsigned_char_true);
- COMPILE_ASSERT(IsInteger<short>::value, WTF_IsInteger_short_true);
- COMPILE_ASSERT(IsInteger<unsigned short>::value, WTF_IsInteger_unsigned_short_true);
- COMPILE_ASSERT(IsInteger<int>::value, WTF_IsInteger_int_true);
- COMPILE_ASSERT(IsInteger<unsigned int>::value, WTF_IsInteger_unsigned_int_true);
- COMPILE_ASSERT(IsInteger<long>::value, WTF_IsInteger_long_true);
- COMPILE_ASSERT(IsInteger<unsigned long>::value, WTF_IsInteger_unsigned_long_true);
- COMPILE_ASSERT(IsInteger<long long>::value, WTF_IsInteger_long_long_true);
- COMPILE_ASSERT(IsInteger<unsigned long long>::value, WTF_IsInteger_unsigned_long_long_true);
-
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
- COMPILE_ASSERT(IsInteger<wchar_t>::value, WTF_IsInteger_wchar_t_true);
-#endif
-
- COMPILE_ASSERT(!IsInteger<char*>::value, WTF_IsInteger_char_pointer_false);
- COMPILE_ASSERT(!IsInteger<const char* >::value, WTF_IsInteger_const_char_pointer_false);
- COMPILE_ASSERT(!IsInteger<volatile char* >::value, WTF_IsInteger_volatile_char_pointer__false);
- COMPILE_ASSERT(!IsInteger<double>::value, WTF_IsInteger_double_false);
- COMPILE_ASSERT(!IsInteger<float>::value, WTF_IsInteger_float_false);
-
template<typename T> struct HashTraits;
template<bool isInteger, typename T> struct GenericHashTraitsBase;
diff --git a/JavaScriptCore/wtf/MainThread.cpp b/JavaScriptCore/wtf/MainThread.cpp
index c7a6caa..3c19b7a 100644
--- a/JavaScriptCore/wtf/MainThread.cpp
+++ b/JavaScriptCore/wtf/MainThread.cpp
@@ -29,26 +29,25 @@
#include "config.h"
#include "MainThread.h"
+#include "CurrentTime.h"
+#include "Deque.h"
#include "StdLibExtras.h"
#include "Threading.h"
-#include "Vector.h"
namespace WTF {
struct FunctionWithContext {
MainThreadFunction* function;
void* context;
- ThreadCondition* syncFlag;
- FunctionWithContext(MainThreadFunction* function = 0, void* context = 0, ThreadCondition* syncFlag = 0)
+ FunctionWithContext(MainThreadFunction* function = 0, void* context = 0)
: function(function)
, context(context)
- , syncFlag(syncFlag)
{
}
};
-typedef Vector<FunctionWithContext> FunctionQueue;
+typedef Deque<FunctionWithContext> FunctionQueue;
static bool callbacksPaused; // This global variable is only accessed from main thread.
@@ -64,12 +63,14 @@ static FunctionQueue& functionQueue()
return staticFunctionQueue;
}
-#if !PLATFORM(WIN)
void initializeMainThread()
{
mainThreadFunctionQueueMutex();
+ initializeMainThreadPlatform();
}
-#endif
+
+// 0.1 sec delays in UI is approximate threshold when they become noticeable. Have a limit that's half of that.
+static const double maxRunLoopSuspensionTime = 0.05;
void dispatchFunctionsFromMainThread()
{
@@ -78,52 +79,42 @@ void dispatchFunctionsFromMainThread()
if (callbacksPaused)
return;
- FunctionQueue queueCopy;
- {
- MutexLocker locker(mainThreadFunctionQueueMutex());
- queueCopy.swap(functionQueue());
- }
+ double startTime = currentTime();
+
+ FunctionWithContext invocation;
+ while (true) {
+ {
+ MutexLocker locker(mainThreadFunctionQueueMutex());
+ if (!functionQueue().size())
+ break;
+ invocation = functionQueue().first();
+ functionQueue().removeFirst();
+ }
- for (unsigned i = 0; i < queueCopy.size(); ++i) {
- FunctionWithContext& invocation = queueCopy[i];
invocation.function(invocation.context);
- if (invocation.syncFlag)
- invocation.syncFlag->signal();
+
+ // If we are running accumulated functions for too long so UI may become unresponsive, we need to
+ // yield so the user input can be processed. Otherwise user may not be able to even close the window.
+ // This code has effect only in case the scheduleDispatchFunctionsOnMainThread() is implemented in a way that
+ // allows input events to be processed before we are back here.
+ if (currentTime() - startTime > maxRunLoopSuspensionTime) {
+ scheduleDispatchFunctionsOnMainThread();
+ break;
+ }
}
}
void callOnMainThread(MainThreadFunction* function, void* context)
{
ASSERT(function);
-
+ bool needToSchedule = false;
{
MutexLocker locker(mainThreadFunctionQueueMutex());
+ needToSchedule = functionQueue().size() == 0;
functionQueue().append(FunctionWithContext(function, context));
}
-
- scheduleDispatchFunctionsOnMainThread();
-}
-
-void callOnMainThreadAndWait(MainThreadFunction* function, void* context)
-{
- ASSERT(function);
-
- if (isMainThread()) {
- function(context);
- return;
- }
-
- ThreadCondition syncFlag;
- Mutex conditionMutex;
-
- {
- MutexLocker locker(mainThreadFunctionQueueMutex());
- functionQueue().append(FunctionWithContext(function, context, &syncFlag));
- conditionMutex.lock();
- }
-
- scheduleDispatchFunctionsOnMainThread();
- syncFlag.wait(conditionMutex);
+ if (needToSchedule)
+ scheduleDispatchFunctionsOnMainThread();
}
void setMainThreadCallbacksPaused(bool paused)
diff --git a/JavaScriptCore/wtf/MainThread.h b/JavaScriptCore/wtf/MainThread.h
index 953b986..01ce804 100644
--- a/JavaScriptCore/wtf/MainThread.h
+++ b/JavaScriptCore/wtf/MainThread.h
@@ -37,7 +37,6 @@ class Mutex;
typedef void MainThreadFunction(void*);
void callOnMainThread(MainThreadFunction*, void* context);
-void callOnMainThreadAndWait(MainThreadFunction*, void* context);
void setMainThreadCallbacksPaused(bool paused);
@@ -45,9 +44,10 @@ void setMainThreadCallbacksPaused(bool paused);
void initializeMainThread();
// These functions are internal to the callOnMainThread implementation.
-void dispatchFunctionsFromMainThread();
+void initializeMainThreadPlatform();
void scheduleDispatchFunctionsOnMainThread();
Mutex& mainThreadFunctionQueueMutex();
+void dispatchFunctionsFromMainThread();
} // namespace WTF
diff --git a/JavaScriptCore/wtf/MessageQueue.h b/JavaScriptCore/wtf/MessageQueue.h
index 19c5c10..9549f37 100644
--- a/JavaScriptCore/wtf/MessageQueue.h
+++ b/JavaScriptCore/wtf/MessageQueue.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,6 +30,7 @@
#ifndef MessageQueue_h
#define MessageQueue_h
+#include <limits>
#include <wtf/Assertions.h>
#include <wtf/Deque.h>
#include <wtf/Noncopyable.h>
@@ -50,7 +52,8 @@ namespace WTF {
void append(const DataType&);
void prepend(const DataType&);
bool waitForMessage(DataType&);
- MessageQueueWaitResult waitForMessageTimed(DataType&, double absoluteTime);
+ template<typename Predicate>
+ MessageQueueWaitResult waitForMessageFilteredWithTimeout(DataType&, Predicate&, double absoluteTime);
void kill();
bool tryGetMessage(DataType&);
@@ -59,7 +62,11 @@ namespace WTF {
// The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time.
bool isEmpty();
+ static double infiniteTime() { return std::numeric_limits<double>::max(); }
+
private:
+ static bool alwaysTruePredicate(DataType&) { return true; }
+
mutable Mutex m_mutex;
ThreadCondition m_condition;
Deque<DataType> m_queue;
@@ -85,38 +92,33 @@ namespace WTF {
template<typename DataType>
inline bool MessageQueue<DataType>::waitForMessage(DataType& result)
{
- MutexLocker lock(m_mutex);
-
- while (!m_killed && m_queue.isEmpty())
- m_condition.wait(m_mutex);
-
- if (m_killed)
- return false;
-
- ASSERT(!m_queue.isEmpty());
- result = m_queue.first();
- m_queue.removeFirst();
- return true;
+ MessageQueueWaitResult exitReason = waitForMessageFilteredWithTimeout(result, MessageQueue<DataType>::alwaysTruePredicate, infiniteTime());
+ ASSERT(exitReason == MessageQueueTerminated || exitReason == MessageQueueMessageReceived);
+ return exitReason == MessageQueueMessageReceived;
}
template<typename DataType>
- inline MessageQueueWaitResult MessageQueue<DataType>::waitForMessageTimed(DataType& result, double absoluteTime)
+ template<typename Predicate>
+ inline MessageQueueWaitResult MessageQueue<DataType>::waitForMessageFilteredWithTimeout(DataType& result, Predicate& predicate, double absoluteTime)
{
MutexLocker lock(m_mutex);
bool timedOut = false;
- while (!m_killed && !timedOut && m_queue.isEmpty())
+ DequeConstIterator<DataType> found = m_queue.end();
+ while (!m_killed && !timedOut && (found = m_queue.findIf(predicate)) == m_queue.end())
timedOut = !m_condition.timedWait(m_mutex, absoluteTime);
+ ASSERT(!timedOut || absoluteTime != infiniteTime());
+
if (m_killed)
return MessageQueueTerminated;
if (timedOut)
return MessageQueueTimeout;
- ASSERT(!m_queue.isEmpty());
- result = m_queue.first();
- m_queue.removeFirst();
+ ASSERT(found != m_queue.end());
+ result = *found;
+ m_queue.remove(found);
return MessageQueueMessageReceived;
}
@@ -157,7 +159,7 @@ namespace WTF {
MutexLocker lock(m_mutex);
return m_killed;
}
-}
+} // namespace WTF
using WTF::MessageQueue;
// MessageQueueWaitResult enum and all its values.
diff --git a/JavaScriptCore/wtf/OwnPtr.h b/JavaScriptCore/wtf/OwnPtr.h
index 256b55c..af939e7 100644
--- a/JavaScriptCore/wtf/OwnPtr.h
+++ b/JavaScriptCore/wtf/OwnPtr.h
@@ -21,10 +21,11 @@
#ifndef WTF_OwnPtr_h
#define WTF_OwnPtr_h
+#include "Assertions.h"
+#include "Noncopyable.h"
+#include "TypeTraits.h"
#include <algorithm>
#include <memory>
-#include <wtf/Assertions.h>
-#include <wtf/Noncopyable.h>
#if PLATFORM(WIN)
@@ -41,10 +42,6 @@ namespace WTF {
// Unlike most of our smart pointers, OwnPtr can take either the pointer type or the pointed-to type.
- // FIXME: Share a single RemovePointer class template with RetainPtr.
- template <typename T> struct OwnPtrRemovePointer { typedef T type; };
- template <typename T> struct OwnPtrRemovePointer<T*> { typedef T type; };
-
template <typename T> inline void deleteOwnedPtr(T* ptr)
{
typedef char known[sizeof(T) ? 1 : -1];
@@ -63,7 +60,7 @@ namespace WTF {
template <typename T> class OwnPtr : Noncopyable {
public:
- typedef typename OwnPtrRemovePointer<T>::type ValueType;
+ typedef typename RemovePointer<T>::Type ValueType;
typedef ValueType* PtrType;
explicit OwnPtr(PtrType ptr = 0) : m_ptr(ptr) { }
diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h
index fea00c4..1813114 100644
--- a/JavaScriptCore/wtf/Platform.h
+++ b/JavaScriptCore/wtf/Platform.h
@@ -40,6 +40,12 @@
/* be used regardless of operating environment */
#ifdef __APPLE__
#define WTF_PLATFORM_DARWIN 1
+#include <AvailabilityMacros.h>
+#if !defined(MAC_OS_X_VERSION_10_5) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
+#define BUILDING_ON_TIGER 1
+#elif !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
+#define BUILDING_ON_LEOPARD 1
+#endif
#endif
/* PLATFORM(WIN_OS) */
@@ -238,6 +244,11 @@
#define WTF_PLATFORM_X86_64 1
#endif
+/* PLATFORM(SH4) */
+#if defined(__SH4__)
+#define WTF_PLATFORM_SH4 1
+#endif
+
/* PLATFORM(SPARC64) */
#if defined(__sparc64__)
#define WTF_PLATFORM_SPARC64 1
@@ -268,8 +279,14 @@
#endif
#endif
+/* COMPILER(RVCT) */
+#if defined(__CC_ARM) || defined(__ARMCC__)
+#define WTF_COMPILER_RVCT 1
+#endif
+
/* COMPILER(GCC) */
-#if defined(__GNUC__)
+/* --gnu option of the RVCT compiler also defines __GNUC__ */
+#if defined(__GNUC__) && !COMPILER(RVCT)
#define WTF_COMPILER_GCC 1
#endif
@@ -290,11 +307,6 @@
#define WTF_COMPILER_CYGWIN 1
#endif
-/* COMPILER(RVCT) */
-#if defined(__CC_ARM) || defined(__ARMCC__)
-#define WTF_COMPILER_RVCT 1
-#endif
-
/* COMPILER(WINSCW) */
#if defined(__WINSCW__)
#define WTF_COMPILER_WINSCW 1
@@ -325,9 +337,7 @@
#define ENABLE_DASHBOARD_SUPPORT 1
#endif
#define HAVE_READLINE 1
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
-#define HAVE_DTRACE 1
-#endif
+#define HAVE_RUNLOOP_TIMER 1
#endif
#if PLATFORM(CHROMIUM) && PLATFORM(DARWIN)
@@ -363,6 +373,7 @@
#if PLATFORM(DARWIN)
#define HAVE_ERRNO_H 1
+#define HAVE_LANGINFO_H 1
#define HAVE_MMAP 1
#define HAVE_MERGESORT 1
#define HAVE_SBRK 1
@@ -371,6 +382,10 @@
#define HAVE_SYS_TIME_H 1
#define HAVE_SYS_TIMEB_H 1
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+#define HAVE_MADV_FREE_REUSE 1
+#endif
+
#elif PLATFORM(WIN_OS)
#define HAVE_FLOAT_H 1
@@ -394,11 +409,22 @@
#define HAVE_SYS_PARAM_H 1
#endif
+#elif PLATFORM(ANDROID)
+
+#define HAVE_ERRNO_H 1
+#define HAVE_LANGINFO_H 0
+#define HAVE_MMAP 1
+#define HAVE_SBRK 1
+#define HAVE_STRINGS_H 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYS_TIME_H 1
+
#else
/* FIXME: is this actually used or do other platforms generate their own config.h? */
#define HAVE_ERRNO_H 1
+#define HAVE_LANGINFO_H 1
#define HAVE_MMAP 1
#define HAVE_SBRK 1
#define HAVE_STRINGS_H 1
@@ -466,14 +492,22 @@
#define ENABLE_ARCHIVE 1
#endif
+#if !defined(ENABLE_ON_FIRST_TEXTAREA_FOCUS_SELECT_ALL)
+#define ENABLE_ON_FIRST_TEXTAREA_FOCUS_SELECT_ALL 0
+#endif
+
#if !defined(WTF_USE_ALTERNATE_JSIMMEDIATE) && PLATFORM(X86_64) && PLATFORM(MAC)
#define WTF_USE_ALTERNATE_JSIMMEDIATE 1
#endif
+#if !defined(ENABLE_REPAINT_THROTTLING)
+#define ENABLE_REPAINT_THROTTLING 0
+#endif
+
#if !defined(ENABLE_JIT)
-/* x86-64 support is under development. */
+/* The JIT is tested & working on x86_64 Mac */
#if PLATFORM(X86_64) && PLATFORM(MAC)
- #define ENABLE_JIT 0
+ #define ENABLE_JIT 1
#define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1
/* The JIT is tested & working on x86 Mac */
#elif PLATFORM(X86) && PLATFORM(MAC)
diff --git a/JavaScriptCore/wtf/RefCounted.h b/JavaScriptCore/wtf/RefCounted.h
index ac8e167..93ee0da 100644
--- a/JavaScriptCore/wtf/RefCounted.h
+++ b/JavaScriptCore/wtf/RefCounted.h
@@ -49,8 +49,8 @@ public:
}
protected:
- RefCountedBase(int initialRefCount)
- : m_refCount(initialRefCount)
+ RefCountedBase()
+ : m_refCount(1)
#ifndef NDEBUG
, m_deletionHasBegun(false)
#endif
@@ -76,6 +76,9 @@ protected:
}
protected:
+ template<class T>
+ friend class CrossThreadRefCounted;
+
int m_refCount;
#ifndef NDEBUG
bool m_deletionHasBegun;
@@ -85,11 +88,6 @@ protected:
template<class T> class RefCounted : public RefCountedBase {
public:
- RefCounted(int initialRefCount = 1)
- : RefCountedBase(initialRefCount)
- {
- }
-
void deref()
{
if (derefBase())
diff --git a/JavaScriptCore/wtf/RetainPtr.h b/JavaScriptCore/wtf/RetainPtr.h
index a66a127..77f25e0 100644
--- a/JavaScriptCore/wtf/RetainPtr.h
+++ b/JavaScriptCore/wtf/RetainPtr.h
@@ -21,6 +21,7 @@
#ifndef RetainPtr_h
#define RetainPtr_h
+#include "TypeTraits.h"
#include <algorithm>
#include <CoreFoundation/CoreFoundation.h>
@@ -30,14 +31,6 @@
namespace WTF {
- template <typename T> struct RemovePointer {
- typedef T type;
- };
-
- template <typename T> struct RemovePointer<T*> {
- typedef T type;
- };
-
// Unlike most most of our smart pointers, RetainPtr can take either the pointer type or the pointed-to type,
// so both RetainPtr<NSDictionary> and RetainPtr<CFDictionaryRef> will work.
@@ -56,7 +49,7 @@ namespace WTF {
template <typename T> class RetainPtr {
public:
- typedef typename RemovePointer<T>::type ValueType;
+ typedef typename RemovePointer<T>::Type ValueType;
typedef ValueType* PtrType;
RetainPtr() : m_ptr(0) {}
diff --git a/JavaScriptCore/wtf/TCPageMap.h b/JavaScriptCore/wtf/TCPageMap.h
index 3e6b80e..9ffd77b 100644
--- a/JavaScriptCore/wtf/TCPageMap.h
+++ b/JavaScriptCore/wtf/TCPageMap.h
@@ -54,7 +54,6 @@
#endif
#include <string.h>
-
#include "Assertions.h"
// Single-level array
@@ -164,7 +163,7 @@ class TCMalloc_PageMap2 {
#ifdef WTF_CHANGES
template<class Visitor, class MemoryReader>
- void visit(const Visitor& visitor, const MemoryReader& reader)
+ void visitValues(Visitor& visitor, const MemoryReader& reader)
{
for (int i = 0; i < ROOT_LENGTH; i++) {
if (!root_[i])
@@ -175,6 +174,14 @@ class TCMalloc_PageMap2 {
;
}
}
+
+ template<class Visitor, class MemoryReader>
+ void visitAllocations(Visitor& visitor, const MemoryReader&) {
+ for (int i = 0; i < ROOT_LENGTH; i++) {
+ if (root_[i])
+ visitor.visit(root_[i], sizeof(Leaf));
+ }
+ }
#endif
};
@@ -266,7 +273,7 @@ class TCMalloc_PageMap3 {
#ifdef WTF_CHANGES
template<class Visitor, class MemoryReader>
- void visit(const Visitor& visitor, const MemoryReader& reader) {
+ void visitValues(Visitor& visitor, const MemoryReader& reader) {
Node* root = reader(root_);
for (int i = 0; i < INTERIOR_LENGTH; i++) {
if (!root->ptrs[i])
@@ -283,6 +290,26 @@ class TCMalloc_PageMap3 {
}
}
}
+
+ template<class Visitor, class MemoryReader>
+ void visitAllocations(Visitor& visitor, const MemoryReader& reader) {
+ visitor.visit(root_, sizeof(Node));
+
+ Node* root = reader(root_);
+ for (int i = 0; i < INTERIOR_LENGTH; i++) {
+ if (!root->ptrs[i])
+ continue;
+
+ visitor.visit(root->ptrs[i], sizeof(Node));
+ Node* n = reader(root->ptrs[i]);
+ for (int j = 0; j < INTERIOR_LENGTH; j++) {
+ if (!n->ptrs[j])
+ continue;
+
+ visitor.visit(n->ptrs[j], sizeof(Leaf));
+ }
+ }
+ }
#endif
};
diff --git a/JavaScriptCore/wtf/TCSystemAlloc.cpp b/JavaScriptCore/wtf/TCSystemAlloc.cpp
index 3a8908d..bf2dcb1 100644
--- a/JavaScriptCore/wtf/TCSystemAlloc.cpp
+++ b/JavaScriptCore/wtf/TCSystemAlloc.cpp
@@ -381,9 +381,17 @@ void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size, size_t alignment) {
return NULL;
}
+#if HAVE(MADV_FREE_REUSE)
+
+void TCMalloc_SystemRelease(void* start, size_t length)
+{
+ while (madvise(start, length, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
+}
+
+#elif HAVE(MADV_DONTNEED)
+
void TCMalloc_SystemRelease(void* start, size_t length)
{
-#if HAVE(MADV_DONTNEED)
if (FLAGS_malloc_devmem_start) {
// It's not safe to use MADV_DONTNEED if we've been mapping
// /dev/mem for heap memory
@@ -414,25 +422,41 @@ void TCMalloc_SystemRelease(void* start, size_t length)
errno == EAGAIN) {
// NOP
}
- return;
}
-#endif
+}
-#if HAVE(MMAP)
+#elif HAVE(MMAP)
+
+void TCMalloc_SystemRelease(void* start, size_t length)
+{
void* newAddress = mmap(start, length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
// If the mmap failed then that's ok, we just won't return the memory to the system.
ASSERT_UNUSED(newAddress, newAddress == start || newAddress == reinterpret_cast<void*>(MAP_FAILED));
- return;
-#endif
+}
+
+#else
+
+// Platforms that don't support returning memory use an empty inline version of TCMalloc_SystemRelease
+// declared in TCSystemAlloc.h
-#if !HAVE(MADV_DONTNEED) && !HAVE(MMAP)
- UNUSED_PARAM(start);
- UNUSED_PARAM(length);
#endif
+
+#if HAVE(MADV_FREE_REUSE)
+
+void TCMalloc_SystemCommit(void* start, size_t length)
+{
+ while (madvise(start, length, MADV_FREE_REUSE) == -1 && errno == EAGAIN) { }
}
-#if HAVE(VIRTUALALLOC)
+#elif HAVE(VIRTUALALLOC)
+
void TCMalloc_SystemCommit(void*, size_t)
{
}
+
+#else
+
+// Platforms that don't need to explicitly commit memory use an empty inline version of TCMalloc_SystemCommit
+// declared in TCSystemAlloc.h
+
#endif
diff --git a/JavaScriptCore/wtf/TCSystemAlloc.h b/JavaScriptCore/wtf/TCSystemAlloc.h
index d82e860..f2c915e 100644
--- a/JavaScriptCore/wtf/TCSystemAlloc.h
+++ b/JavaScriptCore/wtf/TCSystemAlloc.h
@@ -62,9 +62,13 @@ extern void* TCMalloc_SystemAlloc(size_t bytes, size_t *actual_bytes,
// be released, partial pages will not.)
extern void TCMalloc_SystemRelease(void* start, size_t length);
-#if HAVE(VIRTUALALLOC)
extern void TCMalloc_SystemCommit(void* start, size_t length);
-#else
+
+#if !HAVE(MADV_FREE_REUSE) && !HAVE(MADV_DONTNEED) && !HAVE(MMAP)
+inline void TCMalloc_SystemRelease(void*, size_t) { }
+#endif
+
+#if !HAVE(VIRTUALALLOC) && !HAVE(MADV_FREE_REUSE)
inline void TCMalloc_SystemCommit(void*, size_t) { }
#endif
diff --git a/JavaScriptCore/wtf/ThreadSpecific.h b/JavaScriptCore/wtf/ThreadSpecific.h
index 7603802..8aaaf5f 100644
--- a/JavaScriptCore/wtf/ThreadSpecific.h
+++ b/JavaScriptCore/wtf/ThreadSpecific.h
@@ -129,8 +129,8 @@ inline void ThreadSpecific<T>::set(T* ptr)
// 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed number should be far enough.
const int kMaxTlsKeySize = 256;
-extern long g_tls_key_count;
-extern DWORD g_tls_keys[kMaxTlsKeySize];
+long& tlsKeyCount();
+DWORD* tlsKeys();
template<typename T>
inline ThreadSpecific<T>::ThreadSpecific()
@@ -140,23 +140,23 @@ inline ThreadSpecific<T>::ThreadSpecific()
if (tls_key == TLS_OUT_OF_INDEXES)
CRASH();
- m_index = InterlockedIncrement(&g_tls_key_count) - 1;
+ m_index = InterlockedIncrement(&tlsKeyCount()) - 1;
if (m_index >= kMaxTlsKeySize)
CRASH();
- g_tls_keys[m_index] = tls_key;
+ tlsKeys()[m_index] = tls_key;
}
template<typename T>
inline ThreadSpecific<T>::~ThreadSpecific()
{
// Does not invoke destructor functions. They will be called from ThreadSpecificThreadExit when the thread is detached.
- TlsFree(g_tls_keys[m_index]);
+ TlsFree(tlsKeys()[m_index]);
}
template<typename T>
inline T* ThreadSpecific<T>::get()
{
- Data* data = static_cast<Data*>(TlsGetValue(g_tls_keys[m_index]));
+ Data* data = static_cast<Data*>(TlsGetValue(tlsKeys()[m_index]));
return data ? data->value : 0;
}
@@ -166,7 +166,7 @@ inline void ThreadSpecific<T>::set(T* ptr)
ASSERT(!get());
Data* data = new Data(ptr, this);
data->destructor = &ThreadSpecific<T>::destroy;
- TlsSetValue(g_tls_keys[m_index], data);
+ TlsSetValue(tlsKeys()[m_index], data);
}
#else
@@ -190,7 +190,7 @@ inline void ThreadSpecific<T>::destroy(void* ptr)
#if USE(PTHREADS)
pthread_setspecific(data->owner->m_key, 0);
#elif PLATFORM(WIN_OS)
- TlsSetValue(g_tls_keys[data->owner->m_index], 0);
+ TlsSetValue(tlsKeys()[data->owner->m_index], 0);
#else
#error ThreadSpecific is not implemented for this platform.
#endif
diff --git a/JavaScriptCore/wtf/ThreadSpecificWin.cpp b/JavaScriptCore/wtf/ThreadSpecificWin.cpp
index 1a3febb..f2c0cad 100644
--- a/JavaScriptCore/wtf/ThreadSpecificWin.cpp
+++ b/JavaScriptCore/wtf/ThreadSpecificWin.cpp
@@ -29,14 +29,23 @@
namespace WTF {
-long g_tls_key_count = 0;
-DWORD g_tls_keys[kMaxTlsKeySize];
+long& tlsKeyCount()
+{
+ static long count;
+ return count;
+}
+
+DWORD* tlsKeys()
+{
+ static DWORD keys[kMaxTlsKeySize];
+ return keys;
+}
void ThreadSpecificThreadExit()
{
- for (long i = 0; i < g_tls_key_count; i++) {
+ for (long i = 0; i < tlsKeyCount(); i++) {
// The layout of ThreadSpecific<T>::Data does not depend on T. So we are safe to do the static cast to ThreadSpecific<int> in order to access its data member.
- ThreadSpecific<int>::Data* data = static_cast<ThreadSpecific<int>::Data*>(TlsGetValue(g_tls_keys[i]));
+ ThreadSpecific<int>::Data* data = static_cast<ThreadSpecific<int>::Data*>(TlsGetValue(tlsKeys()[i]));
if (data)
data->destructor(data);
}
diff --git a/JavaScriptCore/wtf/Threading.cpp b/JavaScriptCore/wtf/Threading.cpp
index 41c9135..bd25ee7 100644
--- a/JavaScriptCore/wtf/Threading.cpp
+++ b/JavaScriptCore/wtf/Threading.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,16 +26,21 @@
#include "config.h"
#include "Threading.h"
+#include <string.h>
+
namespace WTF {
struct NewThreadContext {
- NewThreadContext(ThreadFunction entryPoint, void* data)
+ NewThreadContext(ThreadFunction entryPoint, void* data, const char* name)
: entryPoint(entryPoint)
, data(data)
- { }
+ , name(name)
+ {
+ }
ThreadFunction entryPoint;
void* data;
+ const char* name;
Mutex creationMutex;
};
@@ -44,6 +49,8 @@ static void* threadEntryPoint(void* contextData)
{
NewThreadContext* context = reinterpret_cast<NewThreadContext*>(contextData);
+ setThreadNameInternal(context->name);
+
// Block until our creating thread has completed any extra setup work
{
MutexLocker locker(context->creationMutex);
@@ -59,7 +66,14 @@ static void* threadEntryPoint(void* contextData)
ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name)
{
- NewThreadContext* context = new NewThreadContext(entryPoint, data);
+ // Visual Studio has a 31-character limit on thread names. Longer names will
+ // be truncated silently, but we'd like callers to know about the limit.
+#if !LOG_DISABLED
+ if (strlen(name) > 31)
+ LOG_ERROR("Thread name \"%s\" is longer than 31 characters and will be truncated by Visual Studio", name);
+#endif
+
+ NewThreadContext* context = new NewThreadContext(entryPoint, data, name);
// Prevent the thread body from executing until we've established the thread identifier
MutexLocker locker(context->creationMutex);
diff --git a/JavaScriptCore/wtf/Threading.h b/JavaScriptCore/wtf/Threading.h
index 1c0dab1..e562f35 100644
--- a/JavaScriptCore/wtf/Threading.h
+++ b/JavaScriptCore/wtf/Threading.h
@@ -110,10 +110,17 @@ namespace WTF {
typedef uint32_t ThreadIdentifier;
typedef void* (*ThreadFunction)(void* argument);
-// Returns 0 if thread creation failed
+// Returns 0 if thread creation failed.
+// The thread name must be a literal since on some platforms it's passed in to the thread.
ThreadIdentifier createThread(ThreadFunction, void*, const char* threadName);
+
+// Internal platform-specific createThread implementation.
ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char* threadName);
+// Called in the thread during initialization.
+// Helpful for platforms where the thread name must be set from within the thread.
+void setThreadNameInternal(const char* threadName);
+
ThreadIdentifier currentThread();
bool isMainThread();
int waitForThreadCompletion(ThreadIdentifier, void**);
@@ -212,9 +219,9 @@ inline int atomicDecrement(int volatile* addend) { return __gnu_cxx::__exchange_
#endif
-template<class T> class ThreadSafeShared : Noncopyable {
+class ThreadSafeSharedBase : Noncopyable {
public:
- ThreadSafeShared(int initialRefCount = 1)
+ ThreadSafeSharedBase(int initialRefCount = 1)
: m_refCount(initialRefCount)
{
}
@@ -229,20 +236,6 @@ public:
#endif
}
- void deref()
- {
-#if USE(LOCKFREE_THREADSAFESHARED)
- if (atomicDecrement(&m_refCount) <= 0)
-#else
- {
- MutexLocker locker(m_mutex);
- --m_refCount;
- }
- if (m_refCount <= 0)
-#endif
- delete static_cast<T*>(this);
- }
-
bool hasOneRef()
{
return refCount() == 1;
@@ -256,13 +249,50 @@ public:
return static_cast<int const volatile &>(m_refCount);
}
+protected:
+ // Returns whether the pointer should be freed or not.
+ bool derefBase()
+ {
+#if USE(LOCKFREE_THREADSAFESHARED)
+ if (atomicDecrement(&m_refCount) <= 0)
+ return true;
+#else
+ int refCount;
+ {
+ MutexLocker locker(m_mutex);
+ --m_refCount;
+ refCount = m_refCount;
+ }
+ if (refCount <= 0)
+ return true;
+#endif
+ return false;
+ }
+
private:
+ template<class T>
+ friend class CrossThreadRefCounted;
+
int m_refCount;
#if !USE(LOCKFREE_THREADSAFESHARED)
mutable Mutex m_mutex;
#endif
};
+template<class T> class ThreadSafeShared : public ThreadSafeSharedBase {
+public:
+ ThreadSafeShared(int initialRefCount = 1)
+ : ThreadSafeSharedBase(initialRefCount)
+ {
+ }
+
+ void deref()
+ {
+ if (derefBase())
+ delete static_cast<T*>(this);
+ }
+};
+
// This function must be called from the main thread. It is safe to call it repeatedly.
// Darwin is an exception to this rule: it is OK to call it from any thread, the only requirement is that the calls are not reentrant.
void initializeThreading();
diff --git a/JavaScriptCore/wtf/ThreadingGtk.cpp b/JavaScriptCore/wtf/ThreadingGtk.cpp
index 24c34ca..b4f4de1 100644
--- a/JavaScriptCore/wtf/ThreadingGtk.cpp
+++ b/JavaScriptCore/wtf/ThreadingGtk.cpp
@@ -138,6 +138,10 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con
return threadID;
}
+void setThreadNameInternal(const char*)
+{
+}
+
int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
{
ASSERT(threadID);
diff --git a/JavaScriptCore/wtf/ThreadingNone.cpp b/JavaScriptCore/wtf/ThreadingNone.cpp
index 0be2a4b..24431fc 100644
--- a/JavaScriptCore/wtf/ThreadingNone.cpp
+++ b/JavaScriptCore/wtf/ThreadingNone.cpp
@@ -34,6 +34,7 @@ namespace WTF {
void initializeThreading() { }
ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char*) { return 0; }
+void setThreadNameInternal(const char*) { }
int waitForThreadCompletion(ThreadIdentifier, void**) { return 0; }
void detachThread(ThreadIdentifier) { }
ThreadIdentifier currentThread() { return 0; }
diff --git a/JavaScriptCore/wtf/ThreadingPthreads.cpp b/JavaScriptCore/wtf/ThreadingPthreads.cpp
index 105e42a..42133bc 100644
--- a/JavaScriptCore/wtf/ThreadingPthreads.cpp
+++ b/JavaScriptCore/wtf/ThreadingPthreads.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
*
* Redistribution and use in source and binary forms, with or without
@@ -26,18 +26,18 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
#include "config.h"
#include "Threading.h"
-#include "StdLibExtras.h"
-
#if USE(PTHREADS)
#include "CurrentTime.h"
#include "HashMap.h"
#include "MainThread.h"
#include "RandomNumberSeed.h"
-
+#include "StdLibExtras.h"
+#include "UnusedParam.h"
#include <errno.h>
#include <limits.h>
#include <sys/time.h>
@@ -48,7 +48,7 @@ typedef HashMap<ThreadIdentifier, pthread_t> ThreadMap;
static Mutex* atomicallyInitializedStaticMutex;
-#if !PLATFORM(DARWIN)
+#if !PLATFORM(DARWIN) || PLATFORM(CHROMIUM)
static ThreadIdentifier mainThreadIdentifier; // The thread that was the first to call initializeThreading(), which must be the main thread.
#endif
@@ -64,7 +64,7 @@ void initializeThreading()
atomicallyInitializedStaticMutex = new Mutex;
threadMapMutex();
initializeRandomNumberGenerator();
-#if !PLATFORM(DARWIN)
+#if !PLATFORM(DARWIN) || PLATFORM(CHROMIUM)
mainThreadIdentifier = currentThread();
#endif
initializeMainThread();
@@ -133,7 +133,7 @@ static void clearPthreadHandleForIdentifier(ThreadIdentifier id)
ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
{
pthread_t threadHandle;
- if (pthread_create(&threadHandle, NULL, entryPoint, data)) {
+ if (pthread_create(&threadHandle, 0, entryPoint, data)) {
LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
return 0;
}
@@ -141,6 +141,15 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con
return establishIdentifierForPthreadHandle(threadHandle);
}
+void setThreadNameInternal(const char* threadName)
+{
+#if PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ pthread_setname_np(threadName);
+#else
+ UNUSED_PARAM(threadName);
+#endif
+}
+
int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
{
ASSERT(threadID);
@@ -176,7 +185,7 @@ ThreadIdentifier currentThread()
bool isMainThread()
{
-#if PLATFORM(DARWIN)
+#if PLATFORM(DARWIN) && !PLATFORM(CHROMIUM)
return pthread_main_np();
#else
return currentThread() == mainThreadIdentifier;
@@ -195,8 +204,8 @@ Mutex::~Mutex()
void Mutex::lock()
{
- if (pthread_mutex_lock(&m_mutex) != 0)
- ASSERT(false);
+ int result = pthread_mutex_lock(&m_mutex);
+ ASSERT_UNUSED(result, !result);
}
bool Mutex::tryLock()
@@ -205,17 +214,17 @@ bool Mutex::tryLock()
if (result == 0)
return true;
- else if (result == EBUSY)
+ if (result == EBUSY)
return false;
- ASSERT(false);
+ ASSERT_NOT_REACHED();
return false;
}
void Mutex::unlock()
{
- if (pthread_mutex_unlock(&m_mutex) != 0)
- ASSERT(false);
+ int result = pthread_mutex_unlock(&m_mutex);
+ ASSERT_UNUSED(result, !result);
}
ThreadCondition::ThreadCondition()
@@ -230,8 +239,8 @@ ThreadCondition::~ThreadCondition()
void ThreadCondition::wait(Mutex& mutex)
{
- if (pthread_cond_wait(&m_condition, &mutex.impl()) != 0)
- ASSERT(false);
+ int result = pthread_cond_wait(&m_condition, &mutex.impl());
+ ASSERT_UNUSED(result, !result);
}
bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
@@ -256,14 +265,14 @@ bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
void ThreadCondition::signal()
{
- if (pthread_cond_signal(&m_condition) != 0)
- ASSERT(false);
+ int result = pthread_cond_signal(&m_condition);
+ ASSERT_UNUSED(result, !result);
}
void ThreadCondition::broadcast()
{
- if (pthread_cond_broadcast(&m_condition) != 0)
- ASSERT(false);
+ int result = pthread_cond_broadcast(&m_condition);
+ ASSERT_UNUSED(result, !result);
}
} // namespace WTF
diff --git a/JavaScriptCore/wtf/ThreadingQt.cpp b/JavaScriptCore/wtf/ThreadingQt.cpp
index 55a479b..1fdd2bb 100644
--- a/JavaScriptCore/wtf/ThreadingQt.cpp
+++ b/JavaScriptCore/wtf/ThreadingQt.cpp
@@ -162,6 +162,10 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con
return establishIdentifierForThread(threadRef);
}
+void setThreadNameInternal(const char*)
+{
+}
+
int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
{
ASSERT(threadID);
@@ -191,7 +195,7 @@ ThreadIdentifier currentThread()
bool isMainThread()
{
- return currentThread() == mainThreadIdentifier;
+ return QThread::currentThread() == QCoreApplication::instance()->thread();
}
Mutex::Mutex()
@@ -242,11 +246,13 @@ bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
if (absoluteTime < currentTime)
return false;
- double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0;
- // Qt defines wait for up to ULONG_MAX milliseconds.
- if (intervalMilliseconds >= ULONG_MAX)
- intervalMilliseconds = ULONG_MAX;
+ // Time is too far in the future (and would overflow unsigned long) - wait forever.
+ if (absoluteTime - currentTime > static_cast<double>(INT_MAX) / 1000.0) {
+ wait(mutex);
+ return true;
+ }
+ double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0;
return m_condition->wait(mutex.impl(), static_cast<unsigned long>(intervalMilliseconds));
}
diff --git a/JavaScriptCore/wtf/ThreadingWin.cpp b/JavaScriptCore/wtf/ThreadingWin.cpp
index 399fb38..415ba53 100644
--- a/JavaScriptCore/wtf/ThreadingWin.cpp
+++ b/JavaScriptCore/wtf/ThreadingWin.cpp
@@ -98,7 +98,7 @@
namespace WTF {
-// MS_VC_EXCEPTION, THREADNAME_INFO, and setThreadName all come from <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>.
+// MS_VC_EXCEPTION, THREADNAME_INFO, and setThreadNameInternal all come from <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>.
static const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push, 8)
@@ -110,16 +110,12 @@ typedef struct tagTHREADNAME_INFO {
} THREADNAME_INFO;
#pragma pack(pop)
-static void setThreadName(DWORD dwThreadID, LPCSTR szThreadName)
+void setThreadNameInternal(const char* szThreadName)
{
- // Visual Studio has a 31-character limit on thread names. Longer names will
- // be truncated silently, but we'd like callers to know about the limit.
- ASSERT_ARG(szThreadName, strlen(szThreadName) <= 31);
-
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = szThreadName;
- info.dwThreadID = dwThreadID;
+ info.dwThreadID = GetCurrentThreadId();
info.dwFlags = 0;
__try {
@@ -157,7 +153,7 @@ void initializeThreading()
initializeRandomNumberGenerator();
initializeMainThread();
mainThreadIdentifier = currentThread();
- setThreadName(mainThreadIdentifier, "Main Thread");
+ setThreadNameInternal("Main Thread");
}
}
@@ -220,9 +216,6 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con
return 0;
}
- if (threadName)
- setThreadName(threadIdentifier, threadName);
-
threadID = static_cast<ThreadIdentifier>(threadIdentifier);
storeThreadHandleByIdentifier(threadIdentifier, threadHandle);
@@ -457,10 +450,13 @@ bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
if (absoluteTime < currentTime)
return false;
- double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0;
- if (intervalMilliseconds >= INT_MAX)
- intervalMilliseconds = INT_MAX;
+ // Time is too far in the future (and would overflow unsigned long) - wait forever.
+ if (absoluteTime - currentTime > static_cast<double>(INT_MAX) / 1000.0) {
+ wait(mutex);
+ return true;
+ }
+ double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0;
return m_condition.timedWait(mutex.impl(), static_cast<unsigned long>(intervalMilliseconds));
}
diff --git a/JavaScriptCore/wtf/TypeTraits.cpp b/JavaScriptCore/wtf/TypeTraits.cpp
new file mode 100644
index 0000000..36fc6c6
--- /dev/null
+++ b/JavaScriptCore/wtf/TypeTraits.cpp
@@ -0,0 +1,120 @@
+ /*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "TypeTraits.h"
+
+#include "Assertions.h"
+
+namespace WTF {
+
+COMPILE_ASSERT(IsInteger<bool>::value, WTF_IsInteger_bool_true);
+COMPILE_ASSERT(IsInteger<char>::value, WTF_IsInteger_char_true);
+COMPILE_ASSERT(IsInteger<signed char>::value, WTF_IsInteger_signed_char_true);
+COMPILE_ASSERT(IsInteger<unsigned char>::value, WTF_IsInteger_unsigned_char_true);
+COMPILE_ASSERT(IsInteger<short>::value, WTF_IsInteger_short_true);
+COMPILE_ASSERT(IsInteger<unsigned short>::value, WTF_IsInteger_unsigned_short_true);
+COMPILE_ASSERT(IsInteger<int>::value, WTF_IsInteger_int_true);
+COMPILE_ASSERT(IsInteger<unsigned int>::value, WTF_IsInteger_unsigned_int_true);
+COMPILE_ASSERT(IsInteger<long>::value, WTF_IsInteger_long_true);
+COMPILE_ASSERT(IsInteger<unsigned long>::value, WTF_IsInteger_unsigned_long_true);
+COMPILE_ASSERT(IsInteger<long long>::value, WTF_IsInteger_long_long_true);
+COMPILE_ASSERT(IsInteger<unsigned long long>::value, WTF_IsInteger_unsigned_long_long_true);
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+COMPILE_ASSERT(IsInteger<wchar_t>::value, WTF_IsInteger_wchar_t_true);
+#endif
+COMPILE_ASSERT(!IsInteger<char*>::value, WTF_IsInteger_char_pointer_false);
+COMPILE_ASSERT(!IsInteger<const char*>::value, WTF_IsInteger_const_char_pointer_false);
+COMPILE_ASSERT(!IsInteger<volatile char*>::value, WTF_IsInteger_volatile_char_pointer_false);
+COMPILE_ASSERT(!IsInteger<double>::value, WTF_IsInteger_double_false);
+COMPILE_ASSERT(!IsInteger<float>::value, WTF_IsInteger_float_false);
+
+COMPILE_ASSERT(IsPod<bool>::value, WTF_IsPod_bool_true);
+COMPILE_ASSERT(IsPod<char>::value, WTF_IsPod_char_true);
+COMPILE_ASSERT(IsPod<signed char>::value, WTF_IsPod_signed_char_true);
+COMPILE_ASSERT(IsPod<unsigned char>::value, WTF_IsPod_unsigned_char_true);
+COMPILE_ASSERT(IsPod<short>::value, WTF_IsPod_short_true);
+COMPILE_ASSERT(IsPod<unsigned short>::value, WTF_IsPod_unsigned_short_true);
+COMPILE_ASSERT(IsPod<int>::value, WTF_IsPod_int_true);
+COMPILE_ASSERT(IsPod<unsigned int>::value, WTF_IsPod_unsigned_int_true);
+COMPILE_ASSERT(IsPod<long>::value, WTF_IsPod_long_true);
+COMPILE_ASSERT(IsPod<unsigned long>::value, WTF_IsPod_unsigned_long_true);
+COMPILE_ASSERT(IsPod<long long>::value, WTF_IsPod_long_long_true);
+COMPILE_ASSERT(IsPod<unsigned long long>::value, WTF_IsPod_unsigned_long_long_true);
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+COMPILE_ASSERT(IsPod<wchar_t>::value, WTF_IsPod_wchar_t_true);
+#endif
+COMPILE_ASSERT(IsPod<char*>::value, WTF_IsPod_char_pointer_true);
+COMPILE_ASSERT(IsPod<const char*>::value, WTF_IsPod_const_char_pointer_true);
+COMPILE_ASSERT(IsPod<volatile char*>::value, WTF_IsPod_volatile_char_pointer_true);
+COMPILE_ASSERT(IsPod<double>::value, WTF_IsPod_double_true);
+COMPILE_ASSERT(IsPod<long double>::value, WTF_IsPod_long_double_true);
+COMPILE_ASSERT(IsPod<float>::value, WTF_IsPod_float_true);
+COMPILE_ASSERT(!IsPod<IsPod<bool> >::value, WTF_IsPod_struct_false);
+
+enum IsConvertibleToIntegerCheck { };
+COMPILE_ASSERT(IsConvertibleToInteger<IsConvertibleToIntegerCheck>::value, WTF_IsConvertibleToInteger_enum_true);
+COMPILE_ASSERT(IsConvertibleToInteger<bool>::value, WTF_IsConvertibleToInteger_bool_true);
+COMPILE_ASSERT(IsConvertibleToInteger<char>::value, WTF_IsConvertibleToInteger_char_true);
+COMPILE_ASSERT(IsConvertibleToInteger<signed char>::value, WTF_IsConvertibleToInteger_signed_char_true);
+COMPILE_ASSERT(IsConvertibleToInteger<unsigned char>::value, WTF_IsConvertibleToInteger_unsigned_char_true);
+COMPILE_ASSERT(IsConvertibleToInteger<short>::value, WTF_IsConvertibleToInteger_short_true);
+COMPILE_ASSERT(IsConvertibleToInteger<unsigned short>::value, WTF_IsConvertibleToInteger_unsigned_short_true);
+COMPILE_ASSERT(IsConvertibleToInteger<int>::value, WTF_IsConvertibleToInteger_int_true);
+COMPILE_ASSERT(IsConvertibleToInteger<unsigned int>::value, WTF_IsConvertibleToInteger_unsigned_int_true);
+COMPILE_ASSERT(IsConvertibleToInteger<long>::value, WTF_IsConvertibleToInteger_long_true);
+COMPILE_ASSERT(IsConvertibleToInteger<unsigned long>::value, WTF_IsConvertibleToInteger_unsigned_long_true);
+COMPILE_ASSERT(IsConvertibleToInteger<long long>::value, WTF_IsConvertibleToInteger_long_long_true);
+COMPILE_ASSERT(IsConvertibleToInteger<unsigned long long>::value, WTF_IsConvertibleToInteger_unsigned_long_long_true);
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+COMPILE_ASSERT(IsConvertibleToInteger<wchar_t>::value, WTF_IsConvertibleToInteger_wchar_t_true);
+#endif
+COMPILE_ASSERT(IsConvertibleToInteger<double>::value, WTF_IsConvertibleToInteger_double_true);
+COMPILE_ASSERT(IsConvertibleToInteger<long double>::value, WTF_IsConvertibleToInteger_long_double_true);
+COMPILE_ASSERT(IsConvertibleToInteger<float>::value, WTF_IsConvertibleToInteger_float_true);
+COMPILE_ASSERT(!IsConvertibleToInteger<char*>::value, WTF_IsConvertibleToInteger_char_pointer_false);
+COMPILE_ASSERT(!IsConvertibleToInteger<const char*>::value, WTF_IsConvertibleToInteger_const_char_pointer_false);
+COMPILE_ASSERT(!IsConvertibleToInteger<volatile char*>::value, WTF_IsConvertibleToInteger_volatile_char_pointer_false);
+COMPILE_ASSERT(!IsConvertibleToInteger<IsConvertibleToInteger<bool> >::value, WTF_IsConvertibleToInteger_struct_false);
+
+COMPILE_ASSERT((IsSameType<bool, bool>::value), WTF_IsSameType_bool_true);
+COMPILE_ASSERT((IsSameType<int*, int*>::value), WTF_IsSameType_int_pointer_true);
+COMPILE_ASSERT((!IsSameType<int, int*>::value), WTF_IsSameType_int_int_pointer_false);
+COMPILE_ASSERT((!IsSameType<bool, const bool>::value), WTF_IsSameType_const_change_false);
+COMPILE_ASSERT((!IsSameType<bool, volatile bool>::value), WTF_IsSameType_volatile_change_false);
+
+COMPILE_ASSERT((IsSameType<bool, RemoveConst<const bool>::Type>::value), WTF_test_RemoveConst_const_bool);
+COMPILE_ASSERT((!IsSameType<bool, RemoveConst<volatile bool>::Type>::value), WTF_test_RemoveConst_volatile_bool);
+
+COMPILE_ASSERT((IsSameType<bool, RemoveVolatile<bool>::Type>::value), WTF_test_RemoveVolatile_bool);
+COMPILE_ASSERT((!IsSameType<bool, RemoveVolatile<const bool>::Type>::value), WTF_test_RemoveVolatile_const_bool);
+COMPILE_ASSERT((IsSameType<bool, RemoveVolatile<volatile bool>::Type>::value), WTF_test_RemoveVolatile_volatile_bool);
+
+COMPILE_ASSERT((IsSameType<bool, RemoveConstVolatile<bool>::Type>::value), WTF_test_RemoveConstVolatile_bool);
+COMPILE_ASSERT((IsSameType<bool, RemoveConstVolatile<const bool>::Type>::value), WTF_test_RemoveConstVolatile_const_bool);
+COMPILE_ASSERT((IsSameType<bool, RemoveConstVolatile<volatile bool>::Type>::value), WTF_test_RemoveConstVolatile_volatile_bool);
+COMPILE_ASSERT((IsSameType<bool, RemoveConstVolatile<const volatile bool>::Type>::value), WTF_test_RemoveConstVolatile_const_volatile_bool);
+
+COMPILE_ASSERT((IsSameType<int, RemovePointer<int>::Type>::value), WTF_Test_RemovePointer_int);
+COMPILE_ASSERT((IsSameType<int, RemovePointer<int*>::Type>::value), WTF_Test_RemovePointer_int_pointer);
+COMPILE_ASSERT((!IsSameType<int, RemovePointer<int**>::Type>::value), WTF_Test_RemovePointer_int_pointer_pointer);
+
+} // namespace WTF
diff --git a/JavaScriptCore/wtf/TypeTraits.h b/JavaScriptCore/wtf/TypeTraits.h
new file mode 100644
index 0000000..2aeabcf
--- /dev/null
+++ b/JavaScriptCore/wtf/TypeTraits.h
@@ -0,0 +1,133 @@
+ /*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TypeTraits_h
+#define TypeTraits_h
+
+#include "Platform.h"
+
+namespace WTF {
+
+ // The following are provided in this file:
+ //
+ // IsInteger<T>::value
+ // IsPod<T>::value, see the definition for a note about its limitations
+ // IsConvertibleToInteger<T>::value
+ //
+ // IsSameType<T, U>::value
+ //
+ // RemovePointer<T>::Type
+ // RemoveConst<T>::Type
+ // RemoveVolatile<T>::Type
+ // RemoveConstVolatile<T>::Type
+ //
+ // COMPILE_ASSERT's in TypeTraits.cpp illustrate their usage and what they do.
+
+ template<typename T> struct IsInteger { static const bool value = false; };
+ template<> struct IsInteger<bool> { static const bool value = true; };
+ template<> struct IsInteger<char> { static const bool value = true; };
+ template<> struct IsInteger<signed char> { static const bool value = true; };
+ template<> struct IsInteger<unsigned char> { static const bool value = true; };
+ template<> struct IsInteger<short> { static const bool value = true; };
+ template<> struct IsInteger<unsigned short> { static const bool value = true; };
+ template<> struct IsInteger<int> { static const bool value = true; };
+ template<> struct IsInteger<unsigned int> { static const bool value = true; };
+ template<> struct IsInteger<long> { static const bool value = true; };
+ template<> struct IsInteger<unsigned long> { static const bool value = true; };
+ template<> struct IsInteger<long long> { static const bool value = true; };
+ template<> struct IsInteger<unsigned long long> { static const bool value = true; };
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+ template<> struct IsInteger<wchar_t> { static const bool value = true; };
+#endif
+
+ // IsPod is misnamed as it doesn't cover all plain old data (pod) types.
+ // Specifically, it doesn't allow for enums or for structs.
+ template <typename T> struct IsPod { static const bool value = IsInteger<T>::value; };
+ template <> struct IsPod<float> { static const bool value = true; };
+ template <> struct IsPod<double> { static const bool value = true; };
+ template <> struct IsPod<long double> { static const bool value = true; };
+ template <typename P> struct IsPod<P*> { static const bool value = true; };
+
+ template<typename T> class IsConvertibleToInteger {
+ // Avoid "possible loss of data" warning when using Microsoft's C++ compiler
+ // by not converting int's to doubles.
+ template<bool performCheck, typename U> class IsConvertibleToDouble;
+ template<typename U> class IsConvertibleToDouble<false, U> {
+ public:
+ static const bool value = false;
+ };
+
+ template<typename U> class IsConvertibleToDouble<true, U> {
+ typedef char YesType;
+ struct NoType {
+ char padding[8];
+ };
+
+ static YesType floatCheck(long double);
+ static NoType floatCheck(...);
+ static T& t;
+ public:
+ static const bool value = sizeof(floatCheck(t)) == sizeof(YesType);
+ };
+
+ public:
+ static const bool value = IsInteger<T>::value || IsConvertibleToDouble<!IsInteger<T>::value, T>::value;
+ };
+
+ template <typename T, typename U> struct IsSameType {
+ static const bool value = false;
+ };
+
+ template <typename T> struct IsSameType<T, T> {
+ static const bool value = true;
+ };
+
+ template <typename T> struct RemoveConst {
+ typedef T Type;
+ };
+
+ template <typename T> struct RemoveConst<const T> {
+ typedef T Type;
+ };
+
+ template <typename T> struct RemoveVolatile {
+ typedef T Type;
+ };
+
+ template <typename T> struct RemoveVolatile<volatile T> {
+ typedef T Type;
+ };
+
+ template <typename T> struct RemoveConstVolatile {
+ typedef typename RemoveVolatile<typename RemoveConst<T>::Type>::Type Type;
+ };
+
+ template <typename T> struct RemovePointer {
+ typedef T Type;
+ };
+
+ template <typename T> struct RemovePointer<T*> {
+ typedef T Type;
+ };
+
+} // namespace WTF
+
+#endif // TypeTraits_h
diff --git a/JavaScriptCore/wtf/Vector.h b/JavaScriptCore/wtf/Vector.h
index 880b45d..190226d 100644
--- a/JavaScriptCore/wtf/Vector.h
+++ b/JavaScriptCore/wtf/Vector.h
@@ -377,7 +377,8 @@ namespace WTF {
VectorBuffer(size_t capacity)
: Base(inlineBuffer(), inlineCapacity)
{
- allocateBuffer(capacity);
+ if (capacity > inlineCapacity)
+ Base::allocateBuffer(capacity);
}
~VectorBuffer()
@@ -389,6 +390,10 @@ namespace WTF {
{
if (newCapacity > inlineCapacity)
Base::allocateBuffer(newCapacity);
+ else {
+ m_buffer = inlineBuffer();
+ m_capacity = inlineCapacity;
+ }
}
void deallocateBuffer(T* bufferToDeallocate)
@@ -503,6 +508,7 @@ namespace WTF {
void grow(size_t size);
void resize(size_t size);
void reserveCapacity(size_t newCapacity);
+ void reserveInitialCapacity(size_t initialCapacity);
void shrinkCapacity(size_t newCapacity);
void shrinkToFit() { shrinkCapacity(size()); }
@@ -733,6 +739,15 @@ namespace WTF {
}
template<typename T, size_t inlineCapacity>
+ inline void Vector<T, inlineCapacity>::reserveInitialCapacity(size_t initialCapacity)
+ {
+ ASSERT(!m_size);
+ ASSERT(capacity() == inlineCapacity);
+ if (initialCapacity > inlineCapacity)
+ m_buffer.allocateBuffer(initialCapacity);
+ }
+
+ template<typename T, size_t inlineCapacity>
void Vector<T, inlineCapacity>::shrinkCapacity(size_t newCapacity)
{
if (newCapacity >= capacity())
diff --git a/JavaScriptCore/wtf/VectorTraits.h b/JavaScriptCore/wtf/VectorTraits.h
index 6efe36c..7974b9a 100644
--- a/JavaScriptCore/wtf/VectorTraits.h
+++ b/JavaScriptCore/wtf/VectorTraits.h
@@ -22,6 +22,7 @@
#define WTF_VectorTraits_h
#include "RefPtr.h"
+#include "TypeTraits.h"
#include <utility>
#include <memory>
@@ -29,24 +30,6 @@ using std::pair;
namespace WTF {
- template <typename T> struct IsPod { static const bool value = false; };
- template <> struct IsPod<bool> { static const bool value = true; };
- template <> struct IsPod<char> { static const bool value = true; };
- template <> struct IsPod<signed char> { static const bool value = true; };
- template <> struct IsPod<unsigned char> { static const bool value = true; };
- template <> struct IsPod<short> { static const bool value = true; };
- template <> struct IsPod<unsigned short> { static const bool value = true; };
- template <> struct IsPod<int> { static const bool value = true; };
- template <> struct IsPod<unsigned int> { static const bool value = true; };
- template <> struct IsPod<long> { static const bool value = true; };
- template <> struct IsPod<unsigned long> { static const bool value = true; };
- template <> struct IsPod<long long> { static const bool value = true; };
- template <> struct IsPod<unsigned long long> { static const bool value = true; };
- template <> struct IsPod<float> { static const bool value = true; };
- template <> struct IsPod<double> { static const bool value = true; };
- template <> struct IsPod<long double> { static const bool value = true; };
- template <typename P> struct IsPod<P *> { static const bool value = true; };
-
template<bool isPod, typename T>
class VectorTraitsBase;
diff --git a/JavaScriptCore/wtf/android/MainThreadAndroid.cpp b/JavaScriptCore/wtf/android/MainThreadAndroid.cpp
index d00c0ab..ab0d3bf 100644
--- a/JavaScriptCore/wtf/android/MainThreadAndroid.cpp
+++ b/JavaScriptCore/wtf/android/MainThreadAndroid.cpp
@@ -38,6 +38,10 @@ static void timeoutFired(void* )
dispatchFunctionsFromMainThread();
}
+void initializeMainThreadPlatform()
+{
+}
+
void scheduleDispatchFunctionsOnMainThread()
{
JavaSharedClient::EnqueueFunctionPtr(timeoutFired, 0);
diff --git a/JavaScriptCore/wtf/chromium/ChromiumThreading.h b/JavaScriptCore/wtf/chromium/ChromiumThreading.h
new file mode 100644
index 0000000..e9b1f39
--- /dev/null
+++ b/JavaScriptCore/wtf/chromium/ChromiumThreading.h
@@ -0,0 +1,45 @@
+/*
+* Copyright (C) 2009 Google Inc. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following disclaimer
+* in the documentation and/or other materials provided with the
+* distribution.
+* * Neither the name of Google Inc. nor the names of its
+* contributors may be used to endorse or promote products derived from
+* this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef ChromiumThreading_h
+#define ChromiumThreading_h
+
+namespace WTF {
+
+ // An interface to the embedding layer, which provides threading support.
+ class ChromiumThreading {
+ public:
+ static void initializeMainThread();
+ static void scheduleDispatchFunctionsOnMainThread();
+ };
+
+} // namespace WTF
+
+#endif // ChromiumThreading_h
diff --git a/JavaScriptCore/wtf/chromium/MainThreadChromium.cpp b/JavaScriptCore/wtf/chromium/MainThreadChromium.cpp
new file mode 100644
index 0000000..394370f
--- /dev/null
+++ b/JavaScriptCore/wtf/chromium/MainThreadChromium.cpp
@@ -0,0 +1,49 @@
+/*
+* Copyright (C) 2009 Google Inc. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following disclaimer
+* in the documentation and/or other materials provided with the
+* distribution.
+* * Neither the name of Google Inc. nor the names of its
+* contributors may be used to endorse or promote products derived from
+* this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "config.h"
+#include "MainThread.h"
+
+#include "ChromiumThreading.h"
+
+namespace WTF {
+
+void initializeMainThreadPlatform()
+{
+ ChromiumThreading::initializeMainThread();
+}
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+ ChromiumThreading::scheduleDispatchFunctionsOnMainThread();
+}
+
+} // namespace WTF
+
diff --git a/JavaScriptCore/wtf/dtoa.cpp b/JavaScriptCore/wtf/dtoa.cpp
index c9e8d30..c104dad 100644
--- a/JavaScriptCore/wtf/dtoa.cpp
+++ b/JavaScriptCore/wtf/dtoa.cpp
@@ -824,16 +824,16 @@ static double b2d(Bigint* a, int* e)
*e = 32 - k;
#ifdef Pack_32
if (k < Ebits) {
- d0 = Exp_1 | y >> Ebits - k;
+ d0 = Exp_1 | (y >> (Ebits - k));
w = xa > xa0 ? *--xa : 0;
- d1 = y << (32 - Ebits) + k | w >> Ebits - k;
+ d1 = (y << (32 - Ebits + k)) | (w >> (Ebits - k));
goto ret_d;
}
z = xa > xa0 ? *--xa : 0;
if (k -= Ebits) {
- d0 = Exp_1 | y << k | z >> 32 - k;
+ d0 = Exp_1 | (y << k) | (z >> (32 - k));
y = xa > xa0 ? *--xa : 0;
- d1 = z << k | y >> 32 - k;
+ d1 = (z << k) | (y >> (32 - k));
} else {
d0 = Exp_1 | y;
d1 = z;
@@ -889,7 +889,7 @@ static Bigint* d2b(double d, int* e, int* bits)
#ifdef Pack_32
if ((y = d1)) {
if ((k = lo0bits(&y))) {
- x[0] = y | z << 32 - k;
+ x[0] = y | (z << (32 - k));
z >>= k;
} else
x[0] = y;
@@ -1349,7 +1349,7 @@ ovfl:
if (j >= 53)
word0(rv) = (P + 2) * Exp_msk1;
else
- word0(rv) &= 0xffffffff << j - 32;
+ word0(rv) &= 0xffffffff << (j - 32);
} else
word1(rv) &= 0xffffffff << j;
}
@@ -2011,8 +2011,8 @@ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve)
/* d is denormalized */
i = bbits + be + (Bias + (P - 1) - 1);
- x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
- : word1(d) << 32 - i;
+ x = (i > 32) ? (word0(d) << (64 - i)) | (word1(d) >> (i - 32))
+ : word1(d) << (32 - i);
dval(d2) = x;
word0(d2) -= 31 * Exp_msk1; /* adjust exponent */
i -= (Bias + (P - 1) - 1) + 1;
@@ -2193,7 +2193,7 @@ fast_failed:
}
if (i == ilim) {
dval(d) += dval(d);
- if (dval(d) > ds || dval(d) == ds && L & 1) {
+ if (dval(d) > ds || (dval(d) == ds && (L & 1))) {
bump_up:
while (*--s == '9')
if (s == s0) {
@@ -2334,7 +2334,7 @@ bump_up:
*s++ = dig;
goto ret;
}
- if (j < 0 || j == 0 && !(word1(d) & 1)) {
+ if (j < 0 || (j == 0 && !(word1(d) & 1))) {
if (!b->x[0] && b->wds <= 1) {
#ifdef SET_INEXACT
inexact = 0;
@@ -2344,7 +2344,7 @@ bump_up:
if (j1 > 0) {
b = lshift(b, 1);
j1 = cmp(b, S);
- if ((j1 > 0 || j1 == 0 && dig & 1) && dig++ == '9')
+ if ((j1 > 0 || (j1 == 0 && (dig & 1))) && dig++ == '9')
goto round_9_up;
}
accept_dig:
@@ -2389,7 +2389,7 @@ round_9_up:
b = lshift(b, 1);
j = cmp(b, S);
- if (j > 0 || j == 0 && dig & 1) {
+ if (j > 0 || (j == 0 && (dig & 1))) {
roundoff:
while (*--s == '9')
if (s == s0) {
diff --git a/JavaScriptCore/wtf/gtk/MainThreadGtk.cpp b/JavaScriptCore/wtf/gtk/MainThreadGtk.cpp
index a6e061f..7624247 100644
--- a/JavaScriptCore/wtf/gtk/MainThreadGtk.cpp
+++ b/JavaScriptCore/wtf/gtk/MainThreadGtk.cpp
@@ -34,6 +34,10 @@
namespace WTF {
+void initializeMainThreadPlatform()
+{
+}
+
static gboolean timeoutFired(gpointer)
{
dispatchFunctionsFromMainThread();
@@ -45,5 +49,4 @@ void scheduleDispatchFunctionsOnMainThread()
g_timeout_add(0, timeoutFired, 0);
}
-
-}
+} // namespace WTF
diff --git a/JavaScriptCore/wtf/mac/MainThreadMac.mm b/JavaScriptCore/wtf/mac/MainThreadMac.mm
index b04ef0e..c79acc1 100644
--- a/JavaScriptCore/wtf/mac/MainThreadMac.mm
+++ b/JavaScriptCore/wtf/mac/MainThreadMac.mm
@@ -30,6 +30,7 @@
#import "MainThread.h"
#import <Foundation/NSThread.h>
+#import <wtf/Assertions.h>
@interface WTFMainThreadCaller : NSObject {
}
@@ -47,11 +48,18 @@
namespace WTF {
+static WTFMainThreadCaller* staticMainThreadCaller = nil;
+
+void initializeMainThreadPlatform()
+{
+ ASSERT(!staticMainThreadCaller);
+ staticMainThreadCaller = [[WTFMainThreadCaller alloc] init];
+}
+
void scheduleDispatchFunctionsOnMainThread()
{
- WTFMainThreadCaller *caller = [[WTFMainThreadCaller alloc] init];
- [caller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO];
- [caller release];
+ ASSERT(staticMainThreadCaller);
+ [staticMainThreadCaller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO];
}
} // namespace WTF
diff --git a/JavaScriptCore/wtf/qt/MainThreadQt.cpp b/JavaScriptCore/wtf/qt/MainThreadQt.cpp
index 1914600..7b2d0f2 100644
--- a/JavaScriptCore/wtf/qt/MainThreadQt.cpp
+++ b/JavaScriptCore/wtf/qt/MainThreadQt.cpp
@@ -58,12 +58,15 @@ void MainThreadInvoker::dispatch()
Q_GLOBAL_STATIC(MainThreadInvoker, webkit_main_thread_invoker)
+void initializeMainThreadPlatform()
+{
+}
void scheduleDispatchFunctionsOnMainThread()
{
QMetaObject::invokeMethod(webkit_main_thread_invoker(), "dispatch", Qt::QueuedConnection);
}
-}
+} // namespace WTF
#include "MainThreadQt.moc"
diff --git a/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h b/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h
index 608aea6..de5e082 100644
--- a/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h
+++ b/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h
@@ -179,6 +179,11 @@ inline bool isPunct(UChar32 c)
return !!u_ispunct(c);
}
+inline bool hasLineBreakingPropertyComplexContext(UChar32 c)
+{
+ return u_getIntPropertyValue(c, UCHAR_LINE_BREAK) == U_LB_COMPLEX_CONTEXT;
+}
+
inline UChar32 mirroredChar(UChar32 c)
{
return u_charMirror(c);
diff --git a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h
index d7d78ce..f65e292 100644
--- a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h
+++ b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h
@@ -352,6 +352,12 @@ inline bool isLower(UChar32 c)
return QChar::category(c) == QChar::Letter_Lowercase;
}
+inline bool hasLineBreakingPropertyComplexContext(UChar32)
+{
+ // FIXME: Implement this to return whether the character has line breaking property SA (Complex Context).
+ return false;
+}
+
inline UChar32 mirroredChar(UChar32 c)
{
return QChar::mirroredChar(c);
diff --git a/JavaScriptCore/wtf/win/MainThreadWin.cpp b/JavaScriptCore/wtf/win/MainThreadWin.cpp
index 5f0163c..b828b7d 100644
--- a/JavaScriptCore/wtf/win/MainThreadWin.cpp
+++ b/JavaScriptCore/wtf/win/MainThreadWin.cpp
@@ -50,13 +50,11 @@ LRESULT CALLBACK ThreadingWindowWndProc(HWND hWnd, UINT message, WPARAM wParam,
return 0;
}
-void initializeMainThread()
+void initializeMainThreadPlatform()
{
if (threadingWindowHandle)
return;
- mainThreadFunctionQueueMutex();
-
WNDCLASSEX wcex;
memset(&wcex, 0, sizeof(WNDCLASSEX));
wcex.cbSize = sizeof(WNDCLASSEX);
@@ -75,4 +73,4 @@ void scheduleDispatchFunctionsOnMainThread()
PostMessage(threadingWindowHandle, threadingFiredMessage, 0, 0);
}
-} // namespace WebCore
+} // namespace WTF
diff --git a/JavaScriptCore/wtf/wx/MainThreadWx.cpp b/JavaScriptCore/wtf/wx/MainThreadWx.cpp
index 3166331..bcd5f05 100644
--- a/JavaScriptCore/wtf/wx/MainThreadWx.cpp
+++ b/JavaScriptCore/wtf/wx/MainThreadWx.cpp
@@ -31,8 +31,12 @@
namespace WTF {
-void scheduleDispatchFunctionsOnMainThread()
+void initializeMainThreadPlatform()
{
}
+void scheduleDispatchFunctionsOnMainThread()
+{
}
+
+} // namespace WTF