diff options
author | Jason Barron <jbarron@trolltech.com> | 2009-06-30 09:21:56 (GMT) |
---|---|---|
committer | Jason Barron <jbarron@trolltech.com> | 2009-06-30 09:21:56 (GMT) |
commit | 197df24edfe095a10e2bf65116796e027fea44e2 (patch) | |
tree | 4ffb08f614b550298663f90297c9e559ecb47a3c /src/3rdparty/webkit/JavaScriptCore/wtf | |
parent | 1e84894225e31adf80a7a33da7f655fb5c38ea0e (diff) | |
parent | e3c1039d4d10aa383a1f681e7dd9c1129d22d8ca (diff) | |
download | Qt-197df24edfe095a10e2bf65116796e027fea44e2.zip Qt-197df24edfe095a10e2bf65116796e027fea44e2.tar.gz Qt-197df24edfe095a10e2bf65116796e027fea44e2.tar.bz2 |
Merge commit 'qt/master-stable' into 4.6-merged
Conflicts:
.gitignore
configure.exe
src/corelib/concurrent/qtconcurrentthreadengine.h
src/corelib/global/qnamespace.h
src/gui/graphicsview/qgraphicssceneevent.h
src/gui/kernel/qapplication.cpp
src/gui/kernel/qapplication.h
src/gui/kernel/qapplication_p.h
src/gui/kernel/qapplication_qws.cpp
src/gui/kernel/qwidget.h
src/gui/painting/qpaintengine_raster.cpp
src/gui/text/qfontdatabase.cpp
src/network/access/qnetworkaccesshttpbackend.cpp
tests/auto/network-settings.h
tests/auto/qscriptjstestsuite/qscriptjstestsuite.pro
tests/auto/qvariant/tst_qvariant.cpp
Diffstat (limited to 'src/3rdparty/webkit/JavaScriptCore/wtf')
70 files changed, 5954 insertions, 1388 deletions
diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/ASCIICType.h b/src/3rdparty/webkit/JavaScriptCore/wtf/ASCIICType.h index 0c2ca70..0c3c29f 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/ASCIICType.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/ASCIICType.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007, 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 @@ -149,4 +149,18 @@ namespace WTF { inline bool isASCIIPrintable(int c) { return c >= ' ' && c <= '~'; } } +using WTF::isASCII; +using WTF::isASCIIAlpha; +using WTF::isASCIIAlphanumeric; +using WTF::isASCIIDigit; +using WTF::isASCIIHexDigit; +using WTF::isASCIILower; +using WTF::isASCIIOctalDigit; +using WTF::isASCIIPrintable; +using WTF::isASCIISpace; +using WTF::isASCIIUpper; +using WTF::toASCIIHexValue; +using WTF::toASCIILower; +using WTF::toASCIIUpper; + #endif diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/AVLTree.h b/src/3rdparty/webkit/JavaScriptCore/wtf/AVLTree.h index 18db8ff..d7470e7 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/AVLTree.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/AVLTree.h @@ -764,7 +764,7 @@ AVLTree<Abstractor, maxDepth, BSet>::remove(key k) handle h = abs.root; handle parent = null(), child; - int cmp, cmp_shortened_sub_with_path; + int cmp, cmp_shortened_sub_with_path = 0; for (;;) { if (h == null()) diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/AlwaysInline.h b/src/3rdparty/webkit/JavaScriptCore/wtf/AlwaysInline.h index d39b2b9..64fdd99 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/AlwaysInline.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/AlwaysInline.h @@ -22,7 +22,7 @@ #ifndef ALWAYS_INLINE #if COMPILER(GCC) && defined(NDEBUG) && !COMPILER(MINGW) -#define ALWAYS_INLINE inline __attribute__ ((__always_inline__)) +#define ALWAYS_INLINE inline __attribute__((__always_inline__)) #elif COMPILER(MSVC) && defined(NDEBUG) #define ALWAYS_INLINE __forceinline #else @@ -32,7 +32,7 @@ #ifndef NEVER_INLINE #if COMPILER(GCC) -#define NEVER_INLINE __attribute__ ((__noinline__)) +#define NEVER_INLINE __attribute__((__noinline__)) #else #define NEVER_INLINE #endif @@ -53,3 +53,11 @@ #define LIKELY(x) (x) #endif #endif + +#ifndef NO_RETURN +#if COMPILER(GCC) +#define NO_RETURN __attribute((__noreturn__)) +#else +#define NO_RETURN +#endif +#endif diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.cpp index 6e04fe1..098186e 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.cpp @@ -34,7 +34,7 @@ #include <CoreFoundation/CFString.h> #endif -#if COMPILER(MSVC) && !PLATFORM(WIN_CE) +#if COMPILER(MSVC) && !PLATFORM(WINCE) #ifndef WINVER #define WINVER 0x0500 #endif @@ -54,7 +54,7 @@ static void vprintf_stderr_common(const char* format, va_list args) if (strstr(format, "%@")) { CFStringRef cfFormat = CFStringCreateWithCString(NULL, format, kCFStringEncodingUTF8); CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, cfFormat, args); - + int length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); char* buffer = (char*)malloc(length + 1); @@ -66,7 +66,7 @@ static void vprintf_stderr_common(const char* format, va_list args) CFRelease(str); CFRelease(cfFormat); } else -#elif COMPILER(MSVC) && !PLATFORM(WIN_CE) +#elif COMPILER(MSVC) && !PLATFORM(WINCE) if (IsDebuggerPresent()) { size_t size = 1024; diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.h b/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.h index c17e501..ad66d06 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.h @@ -128,7 +128,7 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann /* ASSERT, ASSERT_WITH_MESSAGE, ASSERT_NOT_REACHED */ -#if PLATFORM(WIN_CE) +#if PLATFORM(WINCE) && !PLATFORM(TORCHMOBILE) /* FIXME: We include this here only to avoid a conflict with the ASSERT macro. */ #include <windows.h> #undef min @@ -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/src/3rdparty/webkit/JavaScriptCore/wtf/ByteArray.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/ByteArray.cpp new file mode 100644 index 0000000..526f147 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/ByteArray.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 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 + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "ByteArray.h" + +namespace WTF { + +PassRefPtr<ByteArray> ByteArray::create(size_t size) +{ + unsigned char* buffer = new unsigned char[size + sizeof(ByteArray) - sizeof(size_t)]; + ASSERT((reinterpret_cast<size_t>(buffer) & 3) == 0); + return adoptRef(new (buffer) ByteArray(size)); +} + +} diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/ByteArray.h b/src/3rdparty/webkit/JavaScriptCore/wtf/ByteArray.h new file mode 100644 index 0000000..33f0877 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/ByteArray.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 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 + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 ByteArray_h +#define ByteArray_h + +#include "wtf/PassRefPtr.h" +#include "wtf/RefCounted.h" + +namespace WTF { + class ByteArray : public RefCountedBase { + public: + unsigned length() const { return m_size; } + + void set(unsigned index, double value) + { + if (index >= m_size) + return; + if (!(value > 0)) // Clamp NaN to 0 + value = 0; + else if (value > 255) + value = 255; + m_data[index] = static_cast<unsigned char>(value + 0.5); + } + + bool get(unsigned index, unsigned char& result) const + { + if (index >= m_size) + return false; + result = m_data[index]; + return true; + } + + unsigned char* data() { return m_data; } + + void deref() + { + if (derefBase()) { + // We allocated with new unsigned char[] in create(), + // and then used placement new to construct the object. + this->~ByteArray(); + delete[] reinterpret_cast<unsigned char*>(this); + } + } + + static PassRefPtr<ByteArray> create(size_t size); + + private: + ByteArray(size_t size) + : m_size(size) + { + } + size_t m_size; + unsigned char m_data[sizeof(size_t)]; + }; +} + +#endif diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/CONTRIBUTORS.pthreads-win32 b/src/3rdparty/webkit/JavaScriptCore/wtf/CONTRIBUTORS.pthreads-win32 new file mode 100644 index 0000000..7de0f26 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/CONTRIBUTORS.pthreads-win32 @@ -0,0 +1,137 @@ +This is a copy of CONTRIBUTORS file for the Pthreads-win32 library, downloaded +from http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/pthreads/CONTRIBUTORS?rev=1.32&cvsroot=pthreads-win32 + +Included here to compliment the Pthreads-win32 license header in wtf/ThreadingWin.cpp file. +WebKit is using derived sources of ThreadCondition code from Pthreads-win32. + +------------------------------------------------------------------------------- + +Contributors (in approximate order of appearance) + +[See also the ChangeLog file where individuals are +attributed in log entries. Likewise in the FAQ file.] + +Ben Elliston bje at cygnus dot com + Initiated the project; + setup the project infrastructure (CVS, web page, etc.); + early prototype routines. +Ross Johnson rpj at callisto dot canberra dot edu dot au + early prototype routines; + ongoing project coordination/maintenance; + implementation of spin locks and barriers; + various enhancements; + bug fixes; + documentation; + testsuite. +Robert Colquhoun rjc at trump dot net dot au + Early bug fixes. +John E. Bossom John dot Bossom at cognos dot com + Contributed substantial original working implementation; + bug fixes; + ongoing guidance and standards interpretation. +Anders Norlander anorland at hem2 dot passagen dot se + Early enhancements and runtime checking for supported + Win32 routines. +Tor Lillqvist tml at iki dot fi + General enhancements; + early bug fixes to condition variables. +Scott Lightner scott at curriculum dot com + Bug fix. +Kevin Ruland Kevin dot Ruland at anheuser-busch dot com + Various bug fixes. +Mike Russo miker at eai dot com + Bug fix. +Mark E. Armstrong avail at pacbell dot net + Bug fixes. +Lorin Hochstein lmh at xiphos dot ca + general bug fixes; bug fixes to condition variables. +Peter Slacik Peter dot Slacik at tatramed dot sk + Bug fixes. +Mumit Khan khan at xraylith dot wisc dot edu + Fixes to work with Mingw32. +Milan Gardian mg at tatramed dot sk + Bug fixes and reports/analyses of obscure problems. +Aurelio Medina aureliom at crt dot com + First implementation of read-write locks. +Graham Dumpleton Graham dot Dumpleton at ra dot pad dot otc dot telstra dot com dot au + Bug fix in condition variables. +Tristan Savatier tristan at mpegtv dot com + WinCE port. +Erik Hensema erik at hensema dot xs4all dot nl + Bug fixes. +Rich Peters rpeters at micro-magic dot com +Todd Owen towen at lucidcalm dot dropbear dot id dot au + Bug fixes to dll loading. +Jason Nye jnye at nbnet dot nb dot ca + Implementation of async cancelation. +Fred Forester fforest at eticomm dot net +Kevin D. Clark kclark at cabletron dot com +David Baggett dmb at itasoftware dot com + Bug fixes. +Paul Redondo paul at matchvision dot com +Scott McCaskill scott at 3dfx dot com + Bug fixes. +Jef Gearhart jgearhart at tpssys dot com + Bug fix. +Arthur Kantor akantor at bexusa dot com + Mutex enhancements. +Steven Reddie smr at essemer dot com dot au + Bug fix. +Alexander Terekhov TEREKHOV at de dot ibm dot com + Re-implemented and improved read-write locks; + (with Louis Thomas) re-implemented and improved + condition variables; + enhancements to semaphores; + enhancements to mutexes; + new mutex implementation in 'futex' style; + suggested a robust implementation of pthread_once + similar to that implemented by V.Kliathcko; + system clock change handling re CV timeouts; + bug fixes. +Thomas Pfaff tpfaff at gmx dot net + Changes to make C version usable with C++ applications; + re-implemented mutex routines to avoid Win32 mutexes + and TryEnterCriticalSection; + procedure to fix Mingw32 thread-safety issues. +Franco Bez franco dot bez at gmx dot de + procedure to fix Mingw32 thread-safety issues. +Louis Thomas lthomas at arbitrade dot com + (with Alexander Terekhov) re-implemented and improved + condition variables. +David Korn dgk at research dot att dot com + Ported to UWIN. +Phil Frisbie, Jr. phil at hawksoft dot com + Bug fix. +Ralf Brese Ralf dot Brese at pdb4 dot siemens dot de + Bug fix. +prionx at juno dot com prionx at juno dot com + Bug fixes. +Max Woodbury mtew at cds dot duke dot edu + POSIX versioning conditionals; + reduced namespace pollution; + idea to separate routines to reduce statically + linked image sizes. +Rob Fanner rfanner at stonethree dot com + Bug fix. +Michael Johnson michaelj at maine dot rr dot com + Bug fix. +Nicolas Barry boozai at yahoo dot com + Bug fixes. +Piet van Bruggen pietvb at newbridges dot nl + Bug fix. +Makoto Kato raven at oldskool dot jp + AMD64 port. +Panagiotis E. Hadjidoukas peh at hpclab dot ceid dot upatras dot gr + Contributed the QueueUserAPCEx package which + makes preemptive async cancelation possible. +Will Bryant will dot bryant at ecosm dot com + Borland compiler patch and makefile. +Anuj Goyal anuj dot goyal at gmail dot com + Port to Digital Mars compiler. +Gottlob Frege gottlobfrege at gmail dot com + re-implemented pthread_once (version 2) + (pthread_once cancellation added by rpj). +Vladimir Kliatchko vladimir at kliatchko dot com + reimplemented pthread_once with the same form + as described by A.Terekhov (later version 2); + implementation of MCS (Mellor-Crummey/Scott) locks.
\ No newline at end of file diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/CrossThreadRefCounted.h b/src/3rdparty/webkit/JavaScriptCore/wtf/CrossThreadRefCounted.h new file mode 100644 index 0000000..281dfa6 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/CrossThreadRefCounted.h @@ -0,0 +1,169 @@ +/* + * 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> + +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(); + + bool isShared() const + { + return !m_refCounter.hasOneRef() || (m_threadSafeRefCounter && !m_threadSafeRefCounter->hasOneRef()); + } + +#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/src/3rdparty/webkit/JavaScriptCore/wtf/CurrentTime.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/CurrentTime.cpp new file mode 100644 index 0000000..73c2c5c --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/CurrentTime.cpp @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2008 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 "CurrentTime.h" + +#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> +#include <math.h> +#include <stdint.h> +#if HAVE(SYS_TIMEB_H) +#include <sys/timeb.h> +#endif +#if !PLATFORM(WINCE) +#include <sys/types.h> +#endif +#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 + +namespace WTF { + +const double msPerSecond = 1000.0; + +#if PLATFORM(WIN_OS) + +static LARGE_INTEGER qpcFrequency; +static bool syncedTime; + +static double highResUpTime() +{ + // We use QPC, but only after sanity checking its result, due to bugs: + // http://support.microsoft.com/kb/274323 + // http://support.microsoft.com/kb/895980 + // http://msdn.microsoft.com/en-us/library/ms644904.aspx ("...you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL)." + + static LARGE_INTEGER qpcLast; + static DWORD tickCountLast; + static bool inited; + + LARGE_INTEGER qpc; + QueryPerformanceCounter(&qpc); + DWORD tickCount = GetTickCount(); + + if (inited) { + __int64 qpcElapsed = ((qpc.QuadPart - qpcLast.QuadPart) * 1000) / qpcFrequency.QuadPart; + __int64 tickCountElapsed; + if (tickCount >= tickCountLast) + tickCountElapsed = (tickCount - tickCountLast); + else { +#if COMPILER(MINGW) + __int64 tickCountLarge = tickCount + 0x100000000ULL; +#else + __int64 tickCountLarge = tickCount + 0x100000000I64; +#endif + tickCountElapsed = tickCountLarge - tickCountLast; + } + + // force a re-sync if QueryPerformanceCounter differs from GetTickCount by more than 500ms. + // (500ms value is from http://support.microsoft.com/kb/274323) + __int64 diff = tickCountElapsed - qpcElapsed; + if (diff > 500 || diff < -500) + syncedTime = false; + } else + inited = true; + + qpcLast = qpc; + tickCountLast = tickCount; + + return (1000.0 * qpc.QuadPart) / static_cast<double>(qpcFrequency.QuadPart); +} + +static double lowResUTCTime() +{ +#if PLATFORM(WINCE) + SYSTEMTIME systemTime; + GetSystemTime(&systemTime); + struct tm tmtime; + tmtime.tm_year = systemTime.wYear - 1900; + tmtime.tm_mon = systemTime.wMonth - 1; + tmtime.tm_mday = systemTime.wDay; + tmtime.tm_wday = systemTime.wDayOfWeek; + tmtime.tm_hour = systemTime.wHour; + tmtime.tm_min = systemTime.wMinute; + tmtime.tm_sec = systemTime.wSecond; + time_t timet = mktime(&tmtime); + return timet * msPerSecond + systemTime.wMilliseconds; +#else + struct _timeb timebuffer; + _ftime(&timebuffer); + return timebuffer.time * msPerSecond + timebuffer.millitm; +#endif +} + +static bool qpcAvailable() +{ + static bool available; + static bool checked; + + if (checked) + return available; + + available = QueryPerformanceFrequency(&qpcFrequency); + checked = true; + return available; +} + +double currentTime() +{ + // Use a combination of ftime and QueryPerformanceCounter. + // ftime returns the information we want, but doesn't have sufficient resolution. + // QueryPerformanceCounter has high resolution, but is only usable to measure time intervals. + // To combine them, we call ftime and QueryPerformanceCounter initially. Later calls will use QueryPerformanceCounter + // by itself, adding the delta to the saved ftime. We periodically re-sync to correct for drift. + static bool started; + static double syncLowResUTCTime; + static double syncHighResUpTime; + static double lastUTCTime; + + double lowResTime = lowResUTCTime(); + + if (!qpcAvailable()) + return lowResTime / 1000.0; + + double highResTime = highResUpTime(); + + if (!syncedTime) { + timeBeginPeriod(1); // increase time resolution around low-res time getter + syncLowResUTCTime = lowResTime = lowResUTCTime(); + timeEndPeriod(1); // restore time resolution + syncHighResUpTime = highResTime; + syncedTime = true; + } + + double highResElapsed = highResTime - syncHighResUpTime; + double utc = syncLowResUTCTime + highResElapsed; + + // force a clock re-sync if we've drifted + double lowResElapsed = lowResTime - syncLowResUTCTime; + const double maximumAllowedDriftMsec = 15.625 * 2.0; // 2x the typical low-res accuracy + if (fabs(highResElapsed - lowResElapsed) > maximumAllowedDriftMsec) + syncedTime = false; + + // make sure time doesn't run backwards (only correct if difference is < 2 seconds, since DST or clock changes could occur) + const double backwardTimeLimit = 2000.0; + if (utc < lastUTCTime && (lastUTCTime - utc) < backwardTimeLimit) + return lastUTCTime / 1000.0; + lastUTCTime = utc; + 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() +{ + struct timeval now; + struct timezone zone; + + gettimeofday(&now, &zone); + return static_cast<double>(now.tv_sec) + (double)(now.tv_usec / 1000000.0); +} + +#endif + +} // namespace WTF diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/CurrentTime.h b/src/3rdparty/webkit/JavaScriptCore/wtf/CurrentTime.h new file mode 100644 index 0000000..31f1ec8 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/CurrentTime.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2008 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 CurrentTime_h +#define CurrentTime_h + +namespace WTF { + + // Returns the current system (UTC) time in seconds, starting January 1, 1970. + // Precision varies depending on a platform but usually is as good or better + // than a millisecond. + double currentTime(); + +} // namespace WTF + +using WTF::currentTime; + +#endif // CurrentTime_h + diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/DateMath.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/DateMath.cpp new file mode 100644 index 0000000..47c9d44 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/DateMath.cpp @@ -0,0 +1,911 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Alternatively, the contents of this file may be used under the terms + * of either the Mozilla Public License Version 1.1, found at + * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public + * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html + * (the "GPL"), in which case the provisions of the MPL or the GPL are + * applicable instead of those above. If you wish to allow use of your + * version of this file only under the terms of one of those two + * licenses (the MPL or the GPL) and not to allow others to use your + * version of this file under the LGPL, indicate your decision by + * deletingthe provisions above and replace them with the notice and + * other provisions required by the MPL or the GPL, as the case may be. + * If you do not delete the provisions above, a recipient may use your + * version of this file under any of the LGPL, the MPL or the GPL. + */ + +#include "config.h" +#include "DateMath.h" + +#include "Assertions.h" +#include "ASCIICType.h" +#include "CurrentTime.h" +#include "MathExtras.h" +#include "StringExtras.h" + +#include <algorithm> +#include <limits.h> +#include <limits> +#include <stdint.h> +#include <time.h> + + +#if HAVE(ERRNO_H) +#include <errno.h> +#endif + +#if PLATFORM(DARWIN) +#include <notify.h> +#endif + +#if HAVE(SYS_TIME_H) +#include <sys/time.h> +#endif + +#if HAVE(SYS_TIMEB_H) +#include <sys/timeb.h> +#endif + +#define NaN std::numeric_limits<double>::quiet_NaN() + +namespace WTF { + +/* Constants */ + +static const double minutesPerDay = 24.0 * 60.0; +static const double secondsPerDay = 24.0 * 60.0 * 60.0; +static const double secondsPerYear = 24.0 * 60.0 * 60.0 * 365.0; + +static const double usecPerSec = 1000000.0; + +static const double maxUnixTime = 2145859200.0; // 12/31/2037 + +// Day of year for the first day of each month, where index 0 is January, and day 0 is January 1. +// First for non-leap years, then for leap years. +static const int firstDayOfMonth[2][12] = { + {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, + {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335} +}; + +static inline bool isLeapYear(int year) +{ + if (year % 4 != 0) + return false; + if (year % 400 == 0) + return true; + if (year % 100 == 0) + return false; + return true; +} + +static inline int daysInYear(int year) +{ + return 365 + isLeapYear(year); +} + +static inline double daysFrom1970ToYear(int year) +{ + // The Gregorian Calendar rules for leap years: + // Every fourth year is a leap year. 2004, 2008, and 2012 are leap years. + // However, every hundredth year is not a leap year. 1900 and 2100 are not leap years. + // Every four hundred years, there's a leap year after all. 2000 and 2400 are leap years. + + static const int leapDaysBefore1971By4Rule = 1970 / 4; + static const int excludedLeapDaysBefore1971By100Rule = 1970 / 100; + static const int leapDaysBefore1971By400Rule = 1970 / 400; + + const double yearMinusOne = year - 1; + const double yearsToAddBy4Rule = floor(yearMinusOne / 4.0) - leapDaysBefore1971By4Rule; + const double yearsToExcludeBy100Rule = floor(yearMinusOne / 100.0) - excludedLeapDaysBefore1971By100Rule; + const double yearsToAddBy400Rule = floor(yearMinusOne / 400.0) - leapDaysBefore1971By400Rule; + + return 365.0 * (year - 1970) + yearsToAddBy4Rule - yearsToExcludeBy100Rule + yearsToAddBy400Rule; +} + +static inline double msToDays(double ms) +{ + return floor(ms / msPerDay); +} + +static inline int msToYear(double ms) +{ + int approxYear = static_cast<int>(floor(ms / (msPerDay * 365.2425)) + 1970); + double msFromApproxYearTo1970 = msPerDay * daysFrom1970ToYear(approxYear); + if (msFromApproxYearTo1970 > ms) + return approxYear - 1; + if (msFromApproxYearTo1970 + msPerDay * daysInYear(approxYear) <= ms) + return approxYear + 1; + return approxYear; +} + +static inline int dayInYear(double ms, int year) +{ + return static_cast<int>(msToDays(ms) - daysFrom1970ToYear(year)); +} + +static inline double msToMilliseconds(double ms) +{ + double result = fmod(ms, msPerDay); + if (result < 0) + result += msPerDay; + return result; +} + +// 0: Sunday, 1: Monday, etc. +static inline int msToWeekDay(double ms) +{ + int wd = (static_cast<int>(msToDays(ms)) + 4) % 7; + if (wd < 0) + wd += 7; + return wd; +} + +static inline int msToSeconds(double ms) +{ + double result = fmod(floor(ms / msPerSecond), secondsPerMinute); + if (result < 0) + result += secondsPerMinute; + return static_cast<int>(result); +} + +static inline int msToMinutes(double ms) +{ + double result = fmod(floor(ms / msPerMinute), minutesPerHour); + if (result < 0) + result += minutesPerHour; + return static_cast<int>(result); +} + +static inline int msToHours(double ms) +{ + double result = fmod(floor(ms/msPerHour), hoursPerDay); + if (result < 0) + result += hoursPerDay; + return static_cast<int>(result); +} + +static inline int monthFromDayInYear(int dayInYear, bool leapYear) +{ + const int d = dayInYear; + int step; + + if (d < (step = 31)) + return 0; + step += (leapYear ? 29 : 28); + if (d < step) + return 1; + if (d < (step += 31)) + return 2; + if (d < (step += 30)) + return 3; + if (d < (step += 31)) + return 4; + if (d < (step += 30)) + return 5; + if (d < (step += 31)) + return 6; + if (d < (step += 31)) + return 7; + if (d < (step += 30)) + return 8; + if (d < (step += 31)) + return 9; + if (d < (step += 30)) + return 10; + return 11; +} + +static inline bool checkMonth(int dayInYear, int& startDayOfThisMonth, int& startDayOfNextMonth, int daysInThisMonth) +{ + startDayOfThisMonth = startDayOfNextMonth; + startDayOfNextMonth += daysInThisMonth; + return (dayInYear <= startDayOfNextMonth); +} + +static inline int dayInMonthFromDayInYear(int dayInYear, bool leapYear) +{ + const int d = dayInYear; + int step; + int next = 30; + + if (d <= next) + return d + 1; + const int daysInFeb = (leapYear ? 29 : 28); + if (checkMonth(d, step, next, daysInFeb)) + return d - step; + if (checkMonth(d, step, next, 31)) + return d - step; + if (checkMonth(d, step, next, 30)) + return d - step; + if (checkMonth(d, step, next, 31)) + return d - step; + if (checkMonth(d, step, next, 30)) + return d - step; + if (checkMonth(d, step, next, 31)) + return d - step; + if (checkMonth(d, step, next, 31)) + return d - step; + if (checkMonth(d, step, next, 30)) + return d - step; + if (checkMonth(d, step, next, 31)) + return d - step; + if (checkMonth(d, step, next, 30)) + return d - step; + step = next; + return d - step; +} + +static inline int monthToDayInYear(int month, bool isLeapYear) +{ + return firstDayOfMonth[isLeapYear][month]; +} + +static inline double timeToMS(double hour, double min, double sec, double ms) +{ + return (((hour * minutesPerHour + min) * secondsPerMinute + sec) * msPerSecond + ms); +} + +static int dateToDayInYear(int year, int month, int day) +{ + year += month / 12; + + month %= 12; + if (month < 0) { + month += 12; + --year; + } + + int yearday = static_cast<int>(floor(daysFrom1970ToYear(year))); + int monthday = monthToDayInYear(month, isLeapYear(year)); + + return yearday + monthday + day - 1; +} + +double getCurrentUTCTime() +{ + return floor(getCurrentUTCTimeWithMicroseconds()); +} + +// Returns current time in milliseconds since 1 Jan 1970. +double getCurrentUTCTimeWithMicroseconds() +{ + return currentTime() * 1000.0; +} + +void getLocalTime(const time_t* localTime, struct tm* localTM) +{ +#if COMPILER(MSVC7) || COMPILER(MINGW) || PLATFORM(WINCE) + *localTM = *localtime(localTime); +#elif COMPILER(MSVC) + localtime_s(localTM, localTime); +#else + localtime_r(localTime, localTM); +#endif +} + +// There is a hard limit at 2038 that we currently do not have a workaround +// for (rdar://problem/5052975). +static inline int maximumYearForDST() +{ + return 2037; +} + +static inline int minimumYearForDST() +{ + // Because of the 2038 issue (see maximumYearForDST) if the current year is + // greater than the max year minus 27 (2010), we want to use the max year + // minus 27 instead, to ensure there is a range of 28 years that all years + // can map to. + return std::min(msToYear(getCurrentUTCTime()), maximumYearForDST() - 27) ; +} + +/* + * Find an equivalent year for the one given, where equivalence is deterined by + * the two years having the same leapness and the first day of the year, falling + * on the same day of the week. + * + * This function returns a year between this current year and 2037, however this + * function will potentially return incorrect results if the current year is after + * 2010, (rdar://problem/5052975), if the year passed in is before 1900 or after + * 2100, (rdar://problem/5055038). + */ +int equivalentYearForDST(int year) +{ + // It is ok if the cached year is not the current year as long as the rules + // for DST did not change between the two years; if they did the app would need + // to be restarted. + static int minYear = minimumYearForDST(); + int maxYear = maximumYearForDST(); + + int difference; + if (year > maxYear) + difference = minYear - year; + else if (year < minYear) + difference = maxYear - year; + else + return year; + + int quotient = difference / 28; + int product = (quotient) * 28; + + year += product; + ASSERT((year >= minYear && year <= maxYear) || (product - year == static_cast<int>(NaN))); + return year; +} + +static int32_t calculateUTCOffset() +{ + time_t localTime = time(0); + tm localt; + getLocalTime(&localTime, &localt); + + // Get the difference between this time zone and UTC on the 1st of January of this year. + localt.tm_sec = 0; + localt.tm_min = 0; + localt.tm_hour = 0; + localt.tm_mday = 1; + localt.tm_mon = 0; + // Not setting localt.tm_year! + localt.tm_wday = 0; + localt.tm_yday = 0; + localt.tm_isdst = 0; +#if PLATFORM(WIN_OS) || PLATFORM(SOLARIS) || COMPILER(RVCT) + // Using a canned date of 01/01/2009 on platforms with weaker date-handling foo. + localt.tm_year = 109; + time_t utcOffset = 1230768000 - mktime(&localt); +#else + localt.tm_zone = 0; + localt.tm_gmtoff = 0; + time_t utcOffset = timegm(&localt) - mktime(&localt); +#endif + + return static_cast<int32_t>(utcOffset * 1000); +} + +#if PLATFORM(DARWIN) +static int32_t s_cachedUTCOffset; // In milliseconds. An assumption here is that access to an int32_t variable is atomic on platforms that take this code path. +static bool s_haveCachedUTCOffset; +static int s_notificationToken; +#endif + +/* + * Get the difference in milliseconds between this time zone and UTC (GMT) + * NOT including DST. + */ +double getUTCOffset() +{ +#if PLATFORM(DARWIN) + if (s_haveCachedUTCOffset) { + int notified; + uint32_t status = notify_check(s_notificationToken, ¬ified); + if (status == NOTIFY_STATUS_OK && !notified) + return s_cachedUTCOffset; + } +#endif + + int32_t utcOffset = calculateUTCOffset(); + +#if PLATFORM(DARWIN) + // Theoretically, it is possible that several threads will be executing this code at once, in which case we will have a race condition, + // and a newer value may be overwritten. In practice, time zones don't change that often. + s_cachedUTCOffset = utcOffset; +#endif + + return utcOffset; +} + +/* + * Get the DST offset for the time passed in. Takes + * seconds (not milliseconds) and cannot handle dates before 1970 + * on some OS' + */ +static double getDSTOffsetSimple(double localTimeSeconds, double utcOffset) +{ + if (localTimeSeconds > maxUnixTime) + localTimeSeconds = maxUnixTime; + else if (localTimeSeconds < 0) // Go ahead a day to make localtime work (does not work with 0) + localTimeSeconds += secondsPerDay; + + //input is UTC so we have to shift back to local time to determine DST thus the + getUTCOffset() + double offsetTime = (localTimeSeconds * msPerSecond) + utcOffset; + + // Offset from UTC but doesn't include DST obviously + int offsetHour = msToHours(offsetTime); + int offsetMinute = msToMinutes(offsetTime); + + // FIXME: time_t has a potential problem in 2038 + time_t localTime = static_cast<time_t>(localTimeSeconds); + + tm localTM; + getLocalTime(&localTime, &localTM); + + double diff = ((localTM.tm_hour - offsetHour) * secondsPerHour) + ((localTM.tm_min - offsetMinute) * 60); + + if (diff < 0) + diff += secondsPerDay; + + return (diff * msPerSecond); +} + +// Get the DST offset, given a time in UTC +static double getDSTOffset(double ms, double utcOffset) +{ + // On Mac OS X, the call to localtime (see getDSTOffsetSimple) will return historically accurate + // DST information (e.g. New Zealand did not have DST from 1946 to 1974) however the JavaScript + // standard explicitly dictates that historical information should not be considered when + // determining DST. For this reason we shift away from years that localtime can handle but would + // return historically accurate information. + int year = msToYear(ms); + int equivalentYear = equivalentYearForDST(year); + if (year != equivalentYear) { + bool leapYear = isLeapYear(year); + int dayInYearLocal = dayInYear(ms, year); + int dayInMonth = dayInMonthFromDayInYear(dayInYearLocal, leapYear); + int month = monthFromDayInYear(dayInYearLocal, leapYear); + int day = dateToDayInYear(equivalentYear, month, dayInMonth); + ms = (day * msPerDay) + msToMilliseconds(ms); + } + + return getDSTOffsetSimple(ms / msPerSecond, utcOffset); +} + +double gregorianDateTimeToMS(const GregorianDateTime& t, double milliSeconds, bool inputIsUTC) +{ + int day = dateToDayInYear(t.year + 1900, t.month, t.monthDay); + double ms = timeToMS(t.hour, t.minute, t.second, milliSeconds); + double result = (day * msPerDay) + ms; + + if (!inputIsUTC) { // convert to UTC + double utcOffset = getUTCOffset(); + result -= utcOffset; + result -= getDSTOffset(result, utcOffset); + } + + return result; +} + +void msToGregorianDateTime(double ms, bool outputIsUTC, GregorianDateTime& tm) +{ + // input is UTC + double dstOff = 0.0; + const double utcOff = getUTCOffset(); + + if (!outputIsUTC) { // convert to local time + dstOff = getDSTOffset(ms, utcOff); + ms += dstOff + utcOff; + } + + const int year = msToYear(ms); + tm.second = msToSeconds(ms); + tm.minute = msToMinutes(ms); + tm.hour = msToHours(ms); + tm.weekDay = msToWeekDay(ms); + tm.yearDay = dayInYear(ms, year); + tm.monthDay = dayInMonthFromDayInYear(tm.yearDay, isLeapYear(year)); + tm.month = monthFromDayInYear(tm.yearDay, isLeapYear(year)); + tm.year = year - 1900; + tm.isDST = dstOff != 0.0; + + tm.utcOffset = static_cast<long>((dstOff + utcOff) / msPerSecond); + tm.timeZone = NULL; +} + +void initializeDates() +{ +#ifndef NDEBUG + static bool alreadyInitialized; + ASSERT(!alreadyInitialized++); +#endif + + equivalentYearForDST(2000); // Need to call once to initialize a static used in this function. +#if PLATFORM(DARWIN) + // Register for a notification whenever the time zone changes. + uint32_t status = notify_register_check("com.apple.system.timezone", &s_notificationToken); + if (status == NOTIFY_STATUS_OK) { + s_cachedUTCOffset = calculateUTCOffset(); + s_haveCachedUTCOffset = true; + } +#endif +} + +static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, int second) +{ + double days = (day - 32075) + + floor(1461 * (year + 4800.0 + (mon - 14) / 12) / 4) + + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12 + - floor(3 * ((year + 4900.0 + (mon - 14) / 12) / 100) / 4) + - 2440588; + return ((days * hoursPerDay + hour) * minutesPerHour + minute) * secondsPerMinute + second; +} + +// We follow the recommendation of RFC 2822 to consider all +// obsolete time zones not listed here equivalent to "-0000". +static const struct KnownZone { +#if !PLATFORM(WIN_OS) + const +#endif + char tzName[4]; + int tzOffset; +} known_zones[] = { + { "UT", 0 }, + { "GMT", 0 }, + { "EST", -300 }, + { "EDT", -240 }, + { "CST", -360 }, + { "CDT", -300 }, + { "MST", -420 }, + { "MDT", -360 }, + { "PST", -480 }, + { "PDT", -420 } +}; + +inline static void skipSpacesAndComments(const char*& s) +{ + int nesting = 0; + char ch; + while ((ch = *s)) { + if (!isASCIISpace(ch)) { + if (ch == '(') + nesting++; + else if (ch == ')' && nesting > 0) + nesting--; + else if (nesting == 0) + break; + } + s++; + } +} + +// returns 0-11 (Jan-Dec); -1 on failure +static int findMonth(const char* monthStr) +{ + ASSERT(monthStr); + char needle[4]; + for (int i = 0; i < 3; ++i) { + if (!*monthStr) + return -1; + needle[i] = static_cast<char>(toASCIILower(*monthStr++)); + } + needle[3] = '\0'; + const char *haystack = "janfebmaraprmayjunjulaugsepoctnovdec"; + const char *str = strstr(haystack, needle); + if (str) { + int position = static_cast<int>(str - haystack); + if (position % 3 == 0) + return position / 3; + } + return -1; +} + +static bool parseLong(const char* string, char** stopPosition, int base, long* result) +{ + *result = strtol(string, stopPosition, base); + // Avoid the use of errno as it is not available on Windows CE + if (string == *stopPosition || *result == LONG_MIN || *result == LONG_MAX) + return false; + return true; +} + +double parseDateFromNullTerminatedCharacters(const char* dateString) +{ + // This parses a date in the form: + // Tuesday, 09-Nov-99 23:12:40 GMT + // or + // Sat, 01-Jan-2000 08:00:00 GMT + // or + // Sat, 01 Jan 2000 08:00:00 GMT + // or + // 01 Jan 99 22:00 +0100 (exceptions in rfc822/rfc2822) + // ### non RFC formats, added for Javascript: + // [Wednesday] January 09 1999 23:12:40 GMT + // [Wednesday] January 09 23:12:40 GMT 1999 + // + // We ignore the weekday. + + // Skip leading space + skipSpacesAndComments(dateString); + + long month = -1; + const char *wordStart = dateString; + // Check contents of first words if not number + while (*dateString && !isASCIIDigit(*dateString)) { + if (isASCIISpace(*dateString) || *dateString == '(') { + if (dateString - wordStart >= 3) + month = findMonth(wordStart); + skipSpacesAndComments(dateString); + wordStart = dateString; + } else + dateString++; + } + + // Missing delimiter between month and day (like "January29")? + if (month == -1 && wordStart != dateString) + month = findMonth(wordStart); + + skipSpacesAndComments(dateString); + + if (!*dateString) + return NaN; + + // ' 09-Nov-99 23:12:40 GMT' + char* newPosStr; + long day; + if (!parseLong(dateString, &newPosStr, 10, &day)) + return NaN; + dateString = newPosStr; + + if (!*dateString) + return NaN; + + if (day < 0) + return NaN; + + long year = 0; + if (day > 31) { + // ### where is the boundary and what happens below? + if (*dateString != '/') + return NaN; + // looks like a YYYY/MM/DD date + if (!*++dateString) + return NaN; + year = day; + if (!parseLong(dateString, &newPosStr, 10, &month)) + return NaN; + month -= 1; + dateString = newPosStr; + if (*dateString++ != '/' || !*dateString) + return NaN; + if (!parseLong(dateString, &newPosStr, 10, &day)) + return NaN; + dateString = newPosStr; + } else if (*dateString == '/' && month == -1) { + dateString++; + // This looks like a MM/DD/YYYY date, not an RFC date. + month = day - 1; // 0-based + if (!parseLong(dateString, &newPosStr, 10, &day)) + return NaN; + if (day < 1 || day > 31) + return NaN; + dateString = newPosStr; + if (*dateString == '/') + dateString++; + if (!*dateString) + return NaN; + } else { + if (*dateString == '-') + dateString++; + + skipSpacesAndComments(dateString); + + if (*dateString == ',') + dateString++; + + if (month == -1) { // not found yet + month = findMonth(dateString); + if (month == -1) + return NaN; + + while (*dateString && *dateString != '-' && *dateString != ',' && !isASCIISpace(*dateString)) + dateString++; + + if (!*dateString) + return NaN; + + // '-99 23:12:40 GMT' + if (*dateString != '-' && *dateString != '/' && *dateString != ',' && !isASCIISpace(*dateString)) + return NaN; + dateString++; + } + } + + if (month < 0 || month > 11) + return NaN; + + // '99 23:12:40 GMT' + if (year <= 0 && *dateString) { + if (!parseLong(dateString, &newPosStr, 10, &year)) + return NaN; + } + + // Don't fail if the time is missing. + long hour = 0; + long minute = 0; + long second = 0; + if (!*newPosStr) + dateString = newPosStr; + else { + // ' 23:12:40 GMT' + if (!(isASCIISpace(*newPosStr) || *newPosStr == ',')) { + if (*newPosStr != ':') + return NaN; + // There was no year; the number was the hour. + year = -1; + } else { + // in the normal case (we parsed the year), advance to the next number + dateString = ++newPosStr; + skipSpacesAndComments(dateString); + } + + parseLong(dateString, &newPosStr, 10, &hour); + // Do not check for errno here since we want to continue + // even if errno was set becasue we are still looking + // for the timezone! + + // Read a number? If not, this might be a timezone name. + if (newPosStr != dateString) { + dateString = newPosStr; + + if (hour < 0 || hour > 23) + return NaN; + + if (!*dateString) + return NaN; + + // ':12:40 GMT' + if (*dateString++ != ':') + return NaN; + + if (!parseLong(dateString, &newPosStr, 10, &minute)) + return NaN; + dateString = newPosStr; + + if (minute < 0 || minute > 59) + return NaN; + + // ':40 GMT' + if (*dateString && *dateString != ':' && !isASCIISpace(*dateString)) + return NaN; + + // seconds are optional in rfc822 + rfc2822 + if (*dateString ==':') { + dateString++; + + if (!parseLong(dateString, &newPosStr, 10, &second)) + return NaN; + dateString = newPosStr; + + if (second < 0 || second > 59) + return NaN; + } + + skipSpacesAndComments(dateString); + + if (strncasecmp(dateString, "AM", 2) == 0) { + if (hour > 12) + return NaN; + if (hour == 12) + hour = 0; + dateString += 2; + skipSpacesAndComments(dateString); + } else if (strncasecmp(dateString, "PM", 2) == 0) { + if (hour > 12) + return NaN; + if (hour != 12) + hour += 12; + dateString += 2; + skipSpacesAndComments(dateString); + } + } + } + + bool haveTZ = false; + int offset = 0; + + // Don't fail if the time zone is missing. + // Some websites omit the time zone (4275206). + if (*dateString) { + if (strncasecmp(dateString, "GMT", 3) == 0 || strncasecmp(dateString, "UTC", 3) == 0) { + dateString += 3; + haveTZ = true; + } + + if (*dateString == '+' || *dateString == '-') { + long o; + if (!parseLong(dateString, &newPosStr, 10, &o)) + return NaN; + dateString = newPosStr; + + if (o < -9959 || o > 9959) + return NaN; + + int sgn = (o < 0) ? -1 : 1; + o = abs(o); + if (*dateString != ':') { + offset = ((o / 100) * 60 + (o % 100)) * sgn; + } else { // GMT+05:00 + long o2; + if (!parseLong(dateString, &newPosStr, 10, &o2)) + return NaN; + dateString = newPosStr; + offset = (o * 60 + o2) * sgn; + } + haveTZ = true; + } else { + for (int i = 0; i < int(sizeof(known_zones) / sizeof(KnownZone)); i++) { + if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) { + offset = known_zones[i].tzOffset; + dateString += strlen(known_zones[i].tzName); + haveTZ = true; + break; + } + } + } + } + + skipSpacesAndComments(dateString); + + if (*dateString && year == -1) { + if (!parseLong(dateString, &newPosStr, 10, &year)) + return NaN; + dateString = newPosStr; + } + + skipSpacesAndComments(dateString); + + // Trailing garbage + if (*dateString) + return NaN; + + // Y2K: Handle 2 digit years. + if (year >= 0 && year < 100) { + if (year < 50) + year += 2000; + else + year += 1900; + } + + // fall back to local timezone + if (!haveTZ) { + GregorianDateTime t; + t.monthDay = day; + t.month = month; + t.year = year - 1900; + t.isDST = -1; + t.second = second; + t.minute = minute; + t.hour = hour; + + // Use our gregorianDateTimeToMS() rather than mktime() as the latter can't handle the full year range. + return gregorianDateTimeToMS(t, 0, false); + } + + return (ymdhmsToSeconds(year, month + 1, day, hour, minute, second) - (offset * 60.0)) * msPerSecond; +} + +double timeClip(double t) +{ + if (!isfinite(t)) + return NaN; + if (fabs(t) > 8.64E15) + return NaN; + return trunc(t); +} + + +} // namespace WTF diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/DateMath.h b/src/3rdparty/webkit/JavaScriptCore/wtf/DateMath.h new file mode 100644 index 0000000..8690a49 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/DateMath.h @@ -0,0 +1,187 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + */ + +#ifndef DateMath_h +#define DateMath_h + +#include <time.h> +#include <string.h> +#include <wtf/Noncopyable.h> + +namespace WTF { + +struct GregorianDateTime; + +void initializeDates(); +void msToGregorianDateTime(double, bool outputIsUTC, GregorianDateTime&); +double gregorianDateTimeToMS(const GregorianDateTime&, double, bool inputIsUTC); +double getUTCOffset(); +int equivalentYearForDST(int year); +double getCurrentUTCTime(); +double getCurrentUTCTimeWithMicroseconds(); +void getLocalTime(const time_t*, tm*); + +// Not really math related, but this is currently the only shared place to put these. +double parseDateFromNullTerminatedCharacters(const char*); +double timeClip(double); + +const char * const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; +const char * const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +const double hoursPerDay = 24.0; +const double minutesPerHour = 60.0; +const double secondsPerHour = 60.0 * 60.0; +const double secondsPerMinute = 60.0; +const double msPerSecond = 1000.0; +const double msPerMinute = 60.0 * 1000.0; +const double msPerHour = 60.0 * 60.0 * 1000.0; +const double msPerDay = 24.0 * 60.0 * 60.0 * 1000.0; + +// Intentionally overridding the default tm of the system +// Tee members of tm differ on various operating systems. +struct GregorianDateTime : Noncopyable { + GregorianDateTime() + : second(0) + , minute(0) + , hour(0) + , weekDay(0) + , monthDay(0) + , yearDay(0) + , month(0) + , year(0) + , isDST(0) + , utcOffset(0) + , timeZone(0) + { + } + + ~GregorianDateTime() + { + delete [] timeZone; + } + + GregorianDateTime(const tm& inTm) + : second(inTm.tm_sec) + , minute(inTm.tm_min) + , hour(inTm.tm_hour) + , weekDay(inTm.tm_wday) + , monthDay(inTm.tm_mday) + , yearDay(inTm.tm_yday) + , month(inTm.tm_mon) + , year(inTm.tm_year) + , isDST(inTm.tm_isdst) + { +#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS) && !COMPILER(RVCT) + utcOffset = static_cast<int>(inTm.tm_gmtoff); + + int inZoneSize = strlen(inTm.tm_zone) + 1; + timeZone = new char[inZoneSize]; + strncpy(timeZone, inTm.tm_zone, inZoneSize); +#else + utcOffset = static_cast<int>(getUTCOffset() / msPerSecond + (isDST ? secondsPerHour : 0)); + timeZone = 0; +#endif + } + + operator tm() const + { + tm ret; + memset(&ret, 0, sizeof(ret)); + + ret.tm_sec = second; + ret.tm_min = minute; + ret.tm_hour = hour; + ret.tm_wday = weekDay; + ret.tm_mday = monthDay; + ret.tm_yday = yearDay; + ret.tm_mon = month; + ret.tm_year = year; + ret.tm_isdst = isDST; + +#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS) && !COMPILER(RVCT) + ret.tm_gmtoff = static_cast<long>(utcOffset); + ret.tm_zone = timeZone; +#endif + + return ret; + } + + void copyFrom(const GregorianDateTime& rhs) + { + second = rhs.second; + minute = rhs.minute; + hour = rhs.hour; + weekDay = rhs.weekDay; + monthDay = rhs.monthDay; + yearDay = rhs.yearDay; + month = rhs.month; + year = rhs.year; + isDST = rhs.isDST; + utcOffset = rhs.utcOffset; + if (rhs.timeZone) { + int inZoneSize = strlen(rhs.timeZone) + 1; + timeZone = new char[inZoneSize]; + strncpy(timeZone, rhs.timeZone, inZoneSize); + } else + timeZone = 0; + } + + int second; + int minute; + int hour; + int weekDay; + int monthDay; + int yearDay; + int month; + int year; + int isDST; + int utcOffset; + char* timeZone; +}; + +static inline int gmtoffset(const GregorianDateTime& t) +{ + return t.utcOffset; +} + +} // namespace WTF + +#endif // DateMath_h diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/Deque.h b/src/3rdparty/webkit/JavaScriptCore/wtf/Deque.h index 70c546b..3c3d378 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/Deque.h +++ b/src/3rdparty/webkit/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 @@ -43,7 +44,7 @@ namespace WTF { template<typename T> class DequeConstReverseIterator; template<typename T> - class Deque { + class Deque : public FastAllocBase { public: typedef DequeIterator<T> iterator; typedef DequeConstIterator<T> const_iterator; @@ -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/src/3rdparty/webkit/JavaScriptCore/wtf/FastAllocBase.h b/src/3rdparty/webkit/JavaScriptCore/wtf/FastAllocBase.h new file mode 100644 index 0000000..1c81856 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/FastAllocBase.h @@ -0,0 +1,403 @@ +/* + * Copyright (C) 2008, 2009 Paul Pedriana <ppedriana@ea.com>. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 FastAllocBase_h +#define FastAllocBase_h + +// Provides customizable overrides of fastMalloc/fastFree and operator new/delete +// +// Provided functionality: +// namespace WTF { +// class FastAllocBase; +// +// T* fastNew<T>(); +// T* fastNew<T>(arg); +// T* fastNew<T>(arg, arg); +// T* fastNewArray<T>(count); +// void fastDelete(T* p); +// void fastDeleteArray(T* p); +// void fastNonNullDelete(T* p); +// void fastNonNullDeleteArray(T* p); +// } +// +// FastDelete assumes that the underlying +// +// Example usage: +// class Widget : public FastAllocBase { ... }; +// +// char* charPtr = fastNew<char>(); +// fastDelete(charPtr); +// +// char* charArrayPtr = fastNewArray<char>(37); +// fastDeleteArray(charArrayPtr); +// +// void** voidPtrPtr = fastNew<void*>(); +// fastDelete(voidPtrPtr); +// +// void** voidPtrArrayPtr = fastNewArray<void*>(37); +// fastDeleteArray(voidPtrArrayPtr); +// +// POD* podPtr = fastNew<POD>(); +// fastDelete(podPtr); +// +// POD* podArrayPtr = fastNewArray<POD>(37); +// fastDeleteArray(podArrayPtr); +// +// Object* objectPtr = fastNew<Object>(); +// fastDelete(objectPtr); +// +// Object* objectArrayPtr = fastNewArray<Object>(37); +// fastDeleteArray(objectArrayPtr); +// + +#include <new> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include "FastMalloc.h" +#include "TypeTraits.h" +#include <wtf/Assertions.h> + +namespace WTF { + + class FastAllocBase { + public: + // Placement operator new. + void* operator new(size_t, void* p) { return p; } + void* operator new[](size_t, void* p) { return p; } + + void* operator new(size_t size) + { + void* p = fastMalloc(size); + fastMallocMatchValidateMalloc(p, Internal::AllocTypeClassNew); + return p; + } + + void operator delete(void* p) + { + fastMallocMatchValidateFree(p, Internal::AllocTypeClassNew); + fastFree(p); + } + + void* operator new[](size_t size) + { + void* p = fastMalloc(size); + fastMallocMatchValidateMalloc(p, Internal::AllocTypeClassNewArray); + return p; + } + + void operator delete[](void* p) + { + fastMallocMatchValidateFree(p, Internal::AllocTypeClassNewArray); + fastFree(p); + } + }; + + // fastNew / fastDelete + + template <typename T> + inline T* fastNew() + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new(p) T; + } + + template <typename T, typename Arg1> + inline T* fastNew(Arg1 arg1) + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new(p) T(arg1); + } + + template <typename T, typename Arg1, typename Arg2> + inline T* fastNew(Arg1 arg1, Arg2 arg2) + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new(p) T(arg1, arg2); + } + + template <typename T, typename Arg1, typename Arg2, typename Arg3> + inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3) + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new(p) T(arg1, arg2, arg3); + } + + template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4> + inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new(p) T(arg1, arg2, arg3, arg4); + } + + template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> + inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new(p) T(arg1, arg2, arg3, arg4, arg5); + } + + namespace Internal { + + // We define a union of pointer to an integer and pointer to T. + // When non-POD arrays are allocated we add a few leading bytes to tell what + // the size of the array is. We return to the user the pointer to T. + // The way to think of it is as if we allocate a struct like so: + // struct Array { + // AllocAlignmentInteger m_size; + // T m_T[array count]; + // }; + + template <typename T> + union ArraySize { + AllocAlignmentInteger* size; + T* t; + }; + + // This is a support template for fastNewArray. + // This handles the case wherein T has a trivial ctor and a trivial dtor. + template <typename T, bool trivialCtor, bool trivialDtor> + struct NewArrayImpl { + static T* fastNewArray(size_t count) + { + T* p = static_cast<T*>(fastMalloc(sizeof(T) * count)); + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); + return p; + } + }; + + // This is a support template for fastNewArray. + // This handles the case wherein T has a non-trivial ctor and a trivial dtor. + template <typename T> + struct NewArrayImpl<T, false, true> { + static T* fastNewArray(size_t count) + { + T* p = static_cast<T*>(fastMalloc(sizeof(T) * count)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); + + for (T* pObject = p, *pObjectEnd = pObject + count; pObject != pObjectEnd; ++pObject) + ::new(pObject) T; + + return p; + } + }; + + // This is a support template for fastNewArray. + // This handles the case wherein T has a trivial ctor and a non-trivial dtor. + template <typename T> + struct NewArrayImpl<T, true, false> { + static T* fastNewArray(size_t count) + { + void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count)); + ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) }; + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); + *a.size++ = count; + // No need to construct the objects in this case. + + return a.t; + } + }; + + // This is a support template for fastNewArray. + // This handles the case wherein T has a non-trivial ctor and a non-trivial dtor. + template <typename T> + struct NewArrayImpl<T, false, false> { + static T* fastNewArray(size_t count) + { + void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count)); + ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) }; + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); + *a.size++ = count; + + for (T* pT = a.t, *pTEnd = pT + count; pT != pTEnd; ++pT) + ::new(pT) T; + + return a.t; + } + }; + } // namespace Internal + + template <typename T> + inline T* fastNewArray(size_t count) + { + return Internal::NewArrayImpl<T, WTF::HasTrivialConstructor<T>::value, WTF::HasTrivialDestructor<T>::value>::fastNewArray(count); + } + + template <typename T> + inline void fastDelete(T* p) + { + if (!p) + return; + + fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew); + p->~T(); + fastFree(p); + } + + namespace Internal { + // This is a support template for fastDeleteArray. + // This handles the case wherein T has a trivial dtor. + template <typename T, bool trivialDtor> + struct DeleteArrayImpl { + static void fastDeleteArray(void* p) + { + // No need to destruct the objects in this case. + // We expect that fastFree checks for null. + fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray); + fastFree(p); + } + }; + + // This is a support template for fastDeleteArray. + // This handles the case wherein T has a non-trivial dtor. + template <typename T> + struct DeleteArrayImpl<T, false> { + static void fastDeleteArray(T* p) + { + if (!p) + return; + + ArraySize<T> a; + a.t = p; + a.size--; // Decrement size pointer + + T* pEnd = p + *a.size; + while (pEnd-- != p) + pEnd->~T(); + + fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray); + fastFree(a.size); + } + }; + + } // namespace Internal + + template <typename T> + void fastDeleteArray(T* p) + { + Internal::DeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastDeleteArray(p); + } + + + template <typename T> + inline void fastNonNullDelete(T* p) + { + fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew); + p->~T(); + fastFree(p); + } + + namespace Internal { + // This is a support template for fastDeleteArray. + // This handles the case wherein T has a trivial dtor. + template <typename T, bool trivialDtor> + struct NonNullDeleteArrayImpl { + static void fastNonNullDeleteArray(void* p) + { + fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray); + // No need to destruct the objects in this case. + fastFree(p); + } + }; + + // This is a support template for fastDeleteArray. + // This handles the case wherein T has a non-trivial dtor. + template <typename T> + struct NonNullDeleteArrayImpl<T, false> { + static void fastNonNullDeleteArray(T* p) + { + ArraySize<T> a; + a.t = p; + a.size--; + + T* pEnd = p + *a.size; + while (pEnd-- != p) + pEnd->~T(); + + fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray); + fastFree(a.size); + } + }; + + } // namespace Internal + + template <typename T> + void fastNonNullDeleteArray(T* p) + { + Internal::NonNullDeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastNonNullDeleteArray(p); + } + + +} // namespace WTF + +// Using WTF::FastAllocBase to avoid using FastAllocBase's explicit qualification by WTF::. +using WTF::FastAllocBase; + +#endif // FastAllocBase_h diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/FastMalloc.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/FastMalloc.cpp index 4387d61..c65ba85 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/FastMalloc.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/FastMalloc.cpp @@ -78,6 +78,7 @@ #include "FastMalloc.h" #include "Assertions.h" +#include <limits> #if ENABLE(JSC_MULTIPLE_THREADS) #include <pthread.h> #endif @@ -94,7 +95,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 { @@ -151,6 +152,19 @@ void fastMallocAllow() namespace WTF { +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + +namespace Internal { + +void fastMallocMatchFailed(void*) +{ + CRASH(); +} + +} // namespace Internal + +#endif + void* fastZeroedMalloc(size_t n) { void* result = fastMalloc(n); @@ -183,13 +197,34 @@ namespace WTF { void* tryFastMalloc(size_t n) { ASSERT(!isForbidden()); + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= n) // If overflow would occur... + return 0; + + void* result = malloc(n + sizeof(AllocAlignmentInteger)); + if (!result) + return 0; + + *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc; + result = static_cast<AllocAlignmentInteger*>(result) + 1; + + return result; +#else return malloc(n); +#endif } void* fastMalloc(size_t n) { ASSERT(!isForbidden()); + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + void* result = tryFastMalloc(n); +#else void* result = malloc(n); +#endif + if (!result) CRASH(); return result; @@ -198,13 +233,36 @@ void* fastMalloc(size_t n) void* tryFastCalloc(size_t n_elements, size_t element_size) { ASSERT(!isForbidden()); + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + size_t totalBytes = n_elements * element_size; + if (n_elements > 1 && element_size && (totalBytes / element_size) != n_elements || (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= totalBytes)) + return 0; + + totalBytes += sizeof(AllocAlignmentInteger); + void* result = malloc(totalBytes); + if (!result) + return 0; + + memset(result, 0, totalBytes); + *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc; + result = static_cast<AllocAlignmentInteger*>(result) + 1; + return result; +#else return calloc(n_elements, element_size); +#endif } void* fastCalloc(size_t n_elements, size_t element_size) { ASSERT(!isForbidden()); + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + void* result = tryFastCalloc(n_elements, element_size); +#else void* result = calloc(n_elements, element_size); +#endif + if (!result) CRASH(); return result; @@ -213,19 +271,57 @@ void* fastCalloc(size_t n_elements, size_t element_size) void fastFree(void* p) { ASSERT(!isForbidden()); + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + if (!p) + return; + + AllocAlignmentInteger* header = Internal::fastMallocMatchValidationValue(p); + if (*header != Internal::AllocTypeMalloc) + Internal::fastMallocMatchFailed(p); + free(header); +#else free(p); +#endif } void* tryFastRealloc(void* p, size_t n) { ASSERT(!isForbidden()); + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + if (p) { + if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= n) // If overflow would occur... + return 0; + AllocAlignmentInteger* header = Internal::fastMallocMatchValidationValue(p); + if (*header != Internal::AllocTypeMalloc) + Internal::fastMallocMatchFailed(p); + void* result = realloc(header, n + sizeof(AllocAlignmentInteger)); + if (!result) + return 0; + + // This should not be needed because the value is already there: + // *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc; + result = static_cast<AllocAlignmentInteger*>(result) + 1; + return result; + } else { + return fastMalloc(n); + } +#else return realloc(p, n); +#endif } void* fastRealloc(void* p, size_t n) { ASSERT(!isForbidden()); + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + void* result = tryFastRealloc(p, n); +#else void* result = realloc(p, n); +#endif + if (!result) CRASH(); return result; @@ -265,6 +361,7 @@ extern "C" const int jscore_fastmalloc_introspection = 0; #include "TCSystemAlloc.h" #include <algorithm> #include <errno.h> +#include <limits> #include <new> #include <pthread.h> #include <stdarg.h> @@ -321,9 +418,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 +438,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 +451,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 +921,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 +934,7 @@ class PageHeapAllocator { void Init() { ASSERT(kAlignedSize <= kAllocIncrement); inuse_ = 0; + allocated_regions_ = 0; free_area_ = NULL; free_avail_ = 0; free_list_ = NULL; @@ -844,9 +949,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 +973,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 }; // ------------------------------------------------------------------------- @@ -1037,11 +1159,30 @@ template <int BITS> class MapSelector { typedef PackedCache<BITS, uint64_t> CacheType; }; +#if defined(WTF_CHANGES) +#if PLATFORM(X86_64) +// On all known X86-64 platforms, the upper 16 bits are always unused and therefore +// can be excluded from the PageMap key. +// See http://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details + +static const size_t kBitsUnusedOn64Bit = 16; +#else +static const size_t kBitsUnusedOn64Bit = 0; +#endif + +// A three-level map for 64-bit machines +template <> class MapSelector<64> { + public: + typedef TCMalloc_PageMap3<64 - kPageShift - kBitsUnusedOn64Bit> Type; + typedef PackedCache<64, uint64_t> CacheType; +}; +#endif + // A two-level map for 32-bit machines template <> class MapSelector<32> { public: - typedef TCMalloc_PageMap2<32-kPageShift> Type; - typedef PackedCache<32-kPageShift, uint16_t> CacheType; + typedef TCMalloc_PageMap2<32 - kPageShift> Type; + typedef PackedCache<32 - kPageShift, uint16_t> CacheType; }; // ------------------------------------------------------------------------- @@ -1359,8 +1500,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 @@ -3244,7 +3391,20 @@ template <bool crashOnFailure> ALWAYS_INLINE #endif void* malloc(size_t size) { - void* result = do_malloc(size); +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= size) // If overflow would occur... + return 0; + size += sizeof(AllocAlignmentInteger); + void* result = do_malloc(size); + if (!result) + return 0; + + *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc; + result = static_cast<AllocAlignmentInteger*>(result) + 1; +#else + void* result = do_malloc(size); +#endif + #ifndef WTF_CHANGES MallocHook::InvokeNewHook(result, size); #endif @@ -3258,7 +3418,18 @@ void free(void* ptr) { #ifndef WTF_CHANGES MallocHook::InvokeDeleteHook(ptr); #endif - do_free(ptr); + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + if (!ptr) + return; + + AllocAlignmentInteger* header = Internal::fastMallocMatchValidationValue(ptr); + if (*header != Internal::AllocTypeMalloc) + Internal::fastMallocMatchFailed(ptr); + do_free(header); +#else + do_free(ptr); +#endif } #ifndef WTF_CHANGES @@ -3281,22 +3452,39 @@ template <bool crashOnFailure> ALWAYS_INLINE #endif void* calloc(size_t n, size_t elem_size) { - const size_t totalBytes = n * elem_size; + size_t totalBytes = n * elem_size; // Protect against overflow if (n > 1 && elem_size && (totalBytes / elem_size) != n) return 0; - - void* result = do_malloc(totalBytes); - if (result != NULL) { + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= totalBytes) // If overflow would occur... + return 0; + + totalBytes += sizeof(AllocAlignmentInteger); + void* result = do_malloc(totalBytes); + if (!result) + return 0; + memset(result, 0, totalBytes); - } + *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc; + result = static_cast<AllocAlignmentInteger*>(result) + 1; +#else + void* result = do_malloc(totalBytes); + if (result != NULL) { + memset(result, 0, totalBytes); + } +#endif + #ifndef WTF_CHANGES MallocHook::InvokeNewHook(result, totalBytes); #endif return result; } +// Since cfree isn't used anywhere, we don't compile it in. +#ifndef WTF_CHANGES #ifndef WTF_CHANGES extern "C" #endif @@ -3306,6 +3494,7 @@ void cfree(void* ptr) { #endif do_free(ptr); } +#endif #ifndef WTF_CHANGES extern "C" @@ -3328,10 +3517,14 @@ ALWAYS_INLINE #endif void* realloc(void* old_ptr, size_t new_size) { if (old_ptr == NULL) { +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + void* result = malloc(new_size); +#else void* result = do_malloc(new_size); #ifndef WTF_CHANGES MallocHook::InvokeNewHook(result, new_size); #endif +#endif return result; } if (new_size == 0) { @@ -3342,6 +3535,16 @@ void* realloc(void* old_ptr, size_t new_size) { return NULL; } +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= new_size) // If overflow would occur... + return 0; + new_size += sizeof(AllocAlignmentInteger); + AllocAlignmentInteger* header = Internal::fastMallocMatchValidationValue(old_ptr); + if (*header != Internal::AllocTypeMalloc) + Internal::fastMallocMatchFailed(old_ptr); + old_ptr = header; +#endif + // Get the size of the old entry const PageID p = reinterpret_cast<uintptr_t>(old_ptr) >> kPageShift; size_t cl = pageheap->GetSizeClassIfCached(p); @@ -3378,8 +3581,14 @@ void* realloc(void* old_ptr, size_t new_size) { // that we already know the sizeclass of old_ptr. The benefit // would be small, so don't bother. do_free(old_ptr); +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + new_ptr = static_cast<AllocAlignmentInteger*>(new_ptr) + 1; +#endif return new_ptr; } else { +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + old_ptr = pByte + sizeof(AllocAlignmentInteger); // Set old_ptr back to the user pointer. +#endif return old_ptr; } } @@ -3608,6 +3817,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) @@ -3658,7 +3868,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) @@ -3670,51 +3882,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()); } }; @@ -3737,10 +4031,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; } @@ -3781,15 +4087,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) && !PLATFORM(IPHONE) + , 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; @@ -3805,7 +4120,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/src/3rdparty/webkit/JavaScriptCore/wtf/FastMalloc.h b/src/3rdparty/webkit/JavaScriptCore/wtf/FastMalloc.h index f1264ac..9e13cf9 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/FastMalloc.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/FastMalloc.h @@ -56,6 +56,95 @@ namespace WTF { }; FastMallocStatistics fastMallocStatistics(); + // This defines a type which holds an unsigned integer and is the same + // size as the minimally aligned memory allocation. + typedef unsigned long long AllocAlignmentInteger; + + namespace Internal { + enum AllocType { // Start with an unusual number instead of zero, because zero is common. + AllocTypeMalloc = 0x375d6750, // Encompasses fastMalloc, fastZeroedMalloc, fastCalloc, fastRealloc. + AllocTypeClassNew, // Encompasses class operator new from FastAllocBase. + AllocTypeClassNewArray, // Encompasses class operator new[] from FastAllocBase. + AllocTypeFastNew, // Encompasses fastNew. + AllocTypeFastNewArray, // Encompasses fastNewArray. + AllocTypeNew, // Encompasses global operator new. + AllocTypeNewArray // Encompasses global operator new[]. + }; + } + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + + // Malloc validation is a scheme whereby a tag is attached to an + // allocation which identifies how it was originally allocated. + // This allows us to verify that the freeing operation matches the + // allocation operation. If memory is allocated with operator new[] + // but freed with free or delete, this system would detect that. + // In the implementation here, the tag is an integer prepended to + // the allocation memory which is assigned one of the AllocType + // enumeration values. An alternative implementation of this + // scheme could store the tag somewhere else or ignore it. + // Users of FastMalloc don't need to know or care how this tagging + // is implemented. + + namespace Internal { + + // Return the AllocType tag associated with the allocated block p. + inline AllocType fastMallocMatchValidationType(const void* p) + { + const AllocAlignmentInteger* type = static_cast<const AllocAlignmentInteger*>(p) - 1; + return static_cast<AllocType>(*type); + } + + // Return the address of the AllocType tag associated with the allocated block p. + inline AllocAlignmentInteger* fastMallocMatchValidationValue(void* p) + { + return reinterpret_cast<AllocAlignmentInteger*>(static_cast<char*>(p) - sizeof(AllocAlignmentInteger)); + } + + // Set the AllocType tag to be associaged with the allocated block p. + inline void setFastMallocMatchValidationType(void* p, AllocType allocType) + { + AllocAlignmentInteger* type = static_cast<AllocAlignmentInteger*>(p) - 1; + *type = static_cast<AllocAlignmentInteger>(allocType); + } + + // Handle a detected alloc/free mismatch. By default this calls CRASH(). + void fastMallocMatchFailed(void* p); + + } // namespace Internal + + // This is a higher level function which is used by FastMalloc-using code. + inline void fastMallocMatchValidateMalloc(void* p, Internal::AllocType allocType) + { + if (!p) + return; + + Internal::setFastMallocMatchValidationType(p, allocType); + } + + // This is a higher level function which is used by FastMalloc-using code. + inline void fastMallocMatchValidateFree(void* p, Internal::AllocType allocType) + { + if (!p) + return; + + if (Internal::fastMallocMatchValidationType(p) != allocType) + Internal::fastMallocMatchFailed(p); + Internal::setFastMallocMatchValidationType(p, Internal::AllocTypeMalloc); // Set it to this so that fastFree thinks it's OK. + } + +#else + + inline void fastMallocMatchValidateMalloc(void*, Internal::AllocType) + { + } + + inline void fastMallocMatchValidateFree(void*, Internal::AllocType) + { + } + +#endif + } // namespace WTF using WTF::fastMalloc; diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/GOwnPtr.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/GOwnPtr.cpp index 58869f4..432885f 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/GOwnPtr.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/GOwnPtr.cpp @@ -56,4 +56,10 @@ template <> void freeOwnedGPtr<GDir>(GDir* ptr) g_dir_close(ptr); } +template <> void freeOwnedGPtr<GHashTable>(GHashTable* ptr) +{ + if (ptr) + g_hash_table_unref(ptr); +} + } // namespace WTF diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/GOwnPtr.h b/src/3rdparty/webkit/JavaScriptCore/wtf/GOwnPtr.h index bbb793a..8d03ff2 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/GOwnPtr.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/GOwnPtr.h @@ -35,6 +35,7 @@ namespace WTF { template<> void freeOwnedGPtr<GMutex>(GMutex*); template<> void freeOwnedGPtr<GPatternSpec>(GPatternSpec*); template<> void freeOwnedGPtr<GDir>(GDir*); + template<> void freeOwnedGPtr<GHashTable>(GHashTable*); template <typename T> class GOwnPtr : Noncopyable { public: diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/HashCountedSet.h b/src/3rdparty/webkit/JavaScriptCore/wtf/HashCountedSet.h index 6fc0234..1a422d8 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/HashCountedSet.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/HashCountedSet.h @@ -22,13 +22,14 @@ #define WTF_HashCountedSet_h #include "Assertions.h" +#include "FastAllocBase.h" #include "HashMap.h" #include "Vector.h" namespace WTF { template<typename Value, typename HashFunctions = typename DefaultHash<Value>::Hash, - typename Traits = HashTraits<Value> > class HashCountedSet { + typename Traits = HashTraits<Value> > class HashCountedSet : public FastAllocBase { private: typedef HashMap<Value, unsigned, HashFunctions, Traits> ImplType; public: diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/HashMap.h b/src/3rdparty/webkit/JavaScriptCore/wtf/HashMap.h index c5b75ff..3de5ee6 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/HashMap.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/HashMap.h @@ -29,7 +29,7 @@ namespace WTF { template<typename KeyArg, typename MappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash, typename KeyTraitsArg = HashTraits<KeyArg>, typename MappedTraitsArg = HashTraits<MappedArg> > - class HashMap { + class HashMap : public FastAllocBase { private: typedef KeyTraitsArg KeyTraits; typedef MappedTraitsArg MappedTraits; diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/HashSet.h b/src/3rdparty/webkit/JavaScriptCore/wtf/HashSet.h index da99f2c..d664c67 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/HashSet.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/HashSet.h @@ -21,6 +21,7 @@ #ifndef WTF_HashSet_h #define WTF_HashSet_h +#include "FastAllocBase.h" #include "HashTable.h" namespace WTF { @@ -32,7 +33,7 @@ namespace WTF { template<typename T> struct IdentityExtractor; template<typename ValueArg, typename HashArg = typename DefaultHash<ValueArg>::Hash, - typename TraitsArg = HashTraits<ValueArg> > class HashSet { + typename TraitsArg = HashTraits<ValueArg> > class HashSet : public FastAllocBase { private: typedef HashArg HashFunctions; typedef TraitsArg ValueTraits; diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/HashTraits.h b/src/3rdparty/webkit/JavaScriptCore/wtf/HashTraits.h index b3c0b7a..c8d40f7 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/HashTraits.h +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/JavaScriptCore/wtf/MainThread.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/MainThread.cpp index c7a6caa..3c19b7a 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/MainThread.cpp +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/JavaScriptCore/wtf/MainThread.h b/src/3rdparty/webkit/JavaScriptCore/wtf/MainThread.h index 953b986..01ce804 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/MainThread.h +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/JavaScriptCore/wtf/MathExtras.h b/src/3rdparty/webkit/JavaScriptCore/wtf/MathExtras.h index 76488b4..324300d 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/MathExtras.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/MathExtras.h @@ -39,10 +39,8 @@ #endif #if COMPILER(MSVC) -#if PLATFORM(WIN_CE) +#if PLATFORM(WINCE) #include <stdlib.h> -#else -#include <xmath.h> #endif #include <limits> diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/MessageQueue.h b/src/3rdparty/webkit/JavaScriptCore/wtf/MessageQueue.h index 481211d..7721dba 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/MessageQueue.h +++ b/src/3rdparty/webkit/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> @@ -36,14 +38,23 @@ namespace WTF { + enum MessageQueueWaitResult { + MessageQueueTerminated, // Queue was destroyed while waiting for message. + MessageQueueTimeout, // Timeout was specified and it expired. + MessageQueueMessageReceived, // A message was successfully received and returned. + }; + template<typename DataType> class MessageQueue : Noncopyable { public: - MessageQueue() : m_killed(false) {} + MessageQueue() : m_killed(false) { } void append(const DataType&); + bool appendAndCheckEmpty(const DataType&); void prepend(const DataType&); bool waitForMessage(DataType&); + template<typename Predicate> + MessageQueueWaitResult waitForMessageFilteredWithTimeout(DataType&, Predicate&, double absoluteTime); void kill(); bool tryGetMessage(DataType&); @@ -52,7 +63,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; @@ -67,6 +82,17 @@ namespace WTF { m_condition.signal(); } + // Returns true if the queue was empty before the item was added. + template<typename DataType> + inline bool MessageQueue<DataType>::appendAndCheckEmpty(const DataType& message) + { + MutexLocker lock(m_mutex); + bool wasEmpty = m_queue.isEmpty(); + m_queue.append(message); + m_condition.signal(); + return wasEmpty; + } + template<typename DataType> inline void MessageQueue<DataType>::prepend(const DataType& message) { @@ -78,18 +104,34 @@ namespace WTF { template<typename DataType> inline bool MessageQueue<DataType>::waitForMessage(DataType& result) { + MessageQueueWaitResult exitReason = waitForMessageFilteredWithTimeout(result, MessageQueue<DataType>::alwaysTruePredicate, infiniteTime()); + ASSERT(exitReason == MessageQueueTerminated || exitReason == MessageQueueMessageReceived); + return exitReason == MessageQueueMessageReceived; + } + + template<typename DataType> + template<typename Predicate> + inline MessageQueueWaitResult MessageQueue<DataType>::waitForMessageFilteredWithTimeout(DataType& result, Predicate& predicate, double absoluteTime) + { MutexLocker lock(m_mutex); - - while (!m_killed && m_queue.isEmpty()) - m_condition.wait(m_mutex); + bool timedOut = false; + + 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 false; + return MessageQueueTerminated; - ASSERT(!m_queue.isEmpty()); - result = m_queue.first(); - m_queue.removeFirst(); - return true; + if (timedOut) + return MessageQueueTimeout; + + ASSERT(found != m_queue.end()); + result = *found; + m_queue.remove(found); + return MessageQueueMessageReceived; } template<typename DataType> @@ -129,8 +171,13 @@ namespace WTF { MutexLocker lock(m_mutex); return m_killed; } -} +} // namespace WTF using WTF::MessageQueue; +// MessageQueueWaitResult enum and all its values. +using WTF::MessageQueueWaitResult; +using WTF::MessageQueueTerminated; +using WTF::MessageQueueTimeout; +using WTF::MessageQueueMessageReceived; #endif // MessageQueue_h diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/NotFound.h b/src/3rdparty/webkit/JavaScriptCore/wtf/NotFound.h index f0bb866..4263bce 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/NotFound.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/NotFound.h @@ -32,4 +32,6 @@ namespace WTF { } // namespace WTF +using WTF::notFound; + #endif // NotFound_h diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/OwnFastMallocPtr.h b/src/3rdparty/webkit/JavaScriptCore/wtf/OwnFastMallocPtr.h new file mode 100644 index 0000000..5c0d064 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/OwnFastMallocPtr.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2006, 2007 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 OwnFastMallocPtr_h +#define OwnFastMallocPtr_h + +#include "FastMalloc.h" +#include "Noncopyable.h" + +namespace WTF { + + template<class T> class OwnFastMallocPtr : Noncopyable { + public: + explicit OwnFastMallocPtr(T* ptr) : m_ptr(ptr) + { + } + + ~OwnFastMallocPtr() + { + fastFree(m_ptr); + } + + T* get() const { return m_ptr; } + T* release() { T* ptr = m_ptr; m_ptr = 0; return ptr; } + + private: + T* m_ptr; + }; + +} // namespace WTF + +using WTF::OwnFastMallocPtr; + +#endif // OwnFastMallocPtr_h diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/OwnPtr.h b/src/3rdparty/webkit/JavaScriptCore/wtf/OwnPtr.h index 256b55c..9e4bd32 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/OwnPtr.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/OwnPtr.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009 Apple 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 @@ -21,53 +21,35 @@ #ifndef WTF_OwnPtr_h #define WTF_OwnPtr_h +#include "Assertions.h" +#include "Noncopyable.h" +#include "OwnPtrCommon.h" +#include "TypeTraits.h" #include <algorithm> #include <memory> -#include <wtf/Assertions.h> -#include <wtf/Noncopyable.h> - -#if PLATFORM(WIN) - -typedef struct HBITMAP__* HBITMAP; -typedef struct HBRUSH__* HBRUSH; -typedef struct HFONT__* HFONT; -typedef struct HPALETTE__* HPALETTE; -typedef struct HPEN__* HPEN; -typedef struct HRGN__* HRGN; - -#endif 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]; - if (sizeof(known)) - delete ptr; - } - -#if PLATFORM(WIN) - void deleteOwnedPtr(HBITMAP); - void deleteOwnedPtr(HBRUSH); - void deleteOwnedPtr(HFONT); - void deleteOwnedPtr(HPALETTE); - void deleteOwnedPtr(HPEN); - void deleteOwnedPtr(HRGN); -#endif + template <typename T> class PassOwnPtr; 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) { } OwnPtr(std::auto_ptr<ValueType> autoPtr) : m_ptr(autoPtr.release()) { } + // See comment in PassOwnPtr.h for why this takes a const reference. + template <typename U> OwnPtr(const PassOwnPtr<U>& o); + + // This copy constructor is used implicitly by gcc when it generates + // transients for assigning a PassOwnPtr<T> object to a stack-allocated + // OwnPtr<T> object. It should never be called explicitly and gcc + // should optimize away the constructor when generating code. + OwnPtr(const OwnPtr<ValueType>& o); + ~OwnPtr() { deleteOwnedPtr(m_ptr); } PtrType get() const { return m_ptr; } @@ -89,19 +71,50 @@ namespace WTF { typedef PtrType OwnPtr::*UnspecifiedBoolType; operator UnspecifiedBoolType() const { return m_ptr ? &OwnPtr::m_ptr : 0; } + OwnPtr& operator=(const PassOwnPtr<T>&); + template <typename U> OwnPtr& operator=(const PassOwnPtr<U>&); + void swap(OwnPtr& o) { std::swap(m_ptr, o.m_ptr); } private: PtrType m_ptr; }; - - template <typename T> inline void swap(OwnPtr<T>& a, OwnPtr<T>& b) { a.swap(b); } + + template <typename T> template <typename U> inline OwnPtr<T>::OwnPtr(const PassOwnPtr<U>& o) + : m_ptr(o.release()) + { + } + + template <typename T> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<T>& o) + { + T* ptr = m_ptr; + m_ptr = o.release(); + ASSERT(!ptr || m_ptr != ptr); + if (ptr) + deleteOwnedPtr(ptr); + return *this; + } + + template <typename T> template <typename U> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<U>& o) + { + T* ptr = m_ptr; + m_ptr = o.release(); + ASSERT(!ptr || m_ptr != ptr); + if (ptr) + deleteOwnedPtr(ptr); + return *this; + } + + template <typename T> inline void swap(OwnPtr<T>& a, OwnPtr<T>& b) + { + a.swap(b); + } template <typename T, typename U> inline bool operator==(const OwnPtr<T>& a, U* b) - { + { return a.get() == b; } - + template <typename T, typename U> inline bool operator==(T* a, const OwnPtr<U>& b) { return a == b.get(); @@ -113,10 +126,10 @@ namespace WTF { } template <typename T, typename U> inline bool operator!=(T* a, const OwnPtr<U>& b) - { + { return a != b.get(); } - + template <typename T> inline typename OwnPtr<T>::PtrType getPtr(const OwnPtr<T>& p) { return p.get(); diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/OwnPtrCommon.h b/src/3rdparty/webkit/JavaScriptCore/wtf/OwnPtrCommon.h new file mode 100644 index 0000000..6cd8bdd --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/OwnPtrCommon.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 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 + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 WTF_OwnPtrCommon_h +#define WTF_OwnPtrCommon_h + +#if PLATFORM(WIN) +typedef struct HBITMAP__* HBITMAP; +typedef struct HBRUSH__* HBRUSH; +typedef struct HFONT__* HFONT; +typedef struct HPALETTE__* HPALETTE; +typedef struct HPEN__* HPEN; +typedef struct HRGN__* HRGN; +#endif + +namespace WTF { + + template <typename T> inline void deleteOwnedPtr(T* ptr) + { + typedef char known[sizeof(T) ? 1 : -1]; + if (sizeof(known)) + delete ptr; + } + +#if PLATFORM(WIN) + void deleteOwnedPtr(HBITMAP); + void deleteOwnedPtr(HBRUSH); + void deleteOwnedPtr(HFONT); + void deleteOwnedPtr(HPALETTE); + void deleteOwnedPtr(HPEN); + void deleteOwnedPtr(HRGN); +#endif + +} // namespace WTF + +#endif // WTF_OwnPtrCommon_h diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/PassOwnPtr.h b/src/3rdparty/webkit/JavaScriptCore/wtf/PassOwnPtr.h new file mode 100644 index 0000000..ae70457 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/PassOwnPtr.h @@ -0,0 +1,177 @@ +/* + * Copyright (C) 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 + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 WTF_PassOwnPtr_h +#define WTF_PassOwnPtr_h + +#include "Assertions.h" +#include "OwnPtrCommon.h" +#include "TypeTraits.h" + +namespace WTF { + + // Unlike most of our smart pointers, PassOwnPtr can take either the pointer type or the pointed-to type. + + template <typename T> class OwnPtr; + + template <typename T> class PassOwnPtr { + public: + typedef typename RemovePointer<T>::Type ValueType; + typedef ValueType* PtrType; + + PassOwnPtr(PtrType ptr = 0) : m_ptr(ptr) { } + // It somewhat breaks the type system to allow transfer of ownership out of + // a const PassOwnPtr. However, it makes it much easier to work with PassOwnPtr + // temporaries, and we don't really have a need to use real const PassOwnPtrs + // anyway. + PassOwnPtr(const PassOwnPtr& o) : m_ptr(o.release()) { } + template <typename U> PassOwnPtr(const PassOwnPtr<U>& o) : m_ptr(o.release()) { } + + ~PassOwnPtr() { deleteOwnedPtr(m_ptr); } + + PtrType get() const { return m_ptr; } + + void clear() { m_ptr = 0; } + PtrType release() const { PtrType ptr = m_ptr; m_ptr = 0; return ptr; } + + ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; } + PtrType operator->() const { ASSERT(m_ptr); return m_ptr; } + + bool operator!() const { return !m_ptr; } + + // This conversion operator allows implicit conversion to bool but not to other integer types. + typedef PtrType PassOwnPtr::*UnspecifiedBoolType; + operator UnspecifiedBoolType() const { return m_ptr ? &PassOwnPtr::m_ptr : 0; } + + PassOwnPtr& operator=(T*); + PassOwnPtr& operator=(const PassOwnPtr<T>&); + template <typename U> PassOwnPtr& operator=(const PassOwnPtr<U>&); + + private: + mutable PtrType m_ptr; + }; + + template <typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(T* optr) + { + T* ptr = m_ptr; + m_ptr = optr; + ASSERT(!ptr || m_ptr != ptr); + if (ptr) + deleteOwnedPtr(ptr); + return *this; + } + + template <typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<T>& optr) + { + T* ptr = m_ptr; + m_ptr = optr.release(); + ASSERT(!ptr || m_ptr != ptr); + if (ptr) + deleteOwnedPtr(ptr); + return *this; + } + + template <typename T> template <typename U> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<U>& optr) + { + T* ptr = m_ptr; + m_ptr = optr.release(); + ASSERT(!ptr || m_ptr != ptr); + if (ptr) + deleteOwnedPtr(ptr); + return *this; + } + + template <typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b) + { + return a.get() == b.get(); + } + + template <typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const OwnPtr<U>& b) + { + return a.get() == b.get(); + } + + template <typename T, typename U> inline bool operator==(const OwnPtr<T>& a, const PassOwnPtr<U>& b) + { + return a.get() == b.get(); + } + + template <typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, U* b) + { + return a.get() == b; + } + + template <typename T, typename U> inline bool operator==(T* a, const PassOwnPtr<U>& b) + { + return a == b.get(); + } + + template <typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b) + { + return a.get() != b.get(); + } + + template <typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const OwnPtr<U>& b) + { + return a.get() != b.get(); + } + + template <typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, const PassOwnPtr<U>& b) + { + return a.get() != b.get(); + } + + template <typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, U* b) + { + return a.get() != b; + } + + template <typename T, typename U> inline bool operator!=(T* a, const PassOwnPtr<U>& b) + { + return a != b.get(); + } + + template <typename T, typename U> inline PassOwnPtr<T> static_pointer_cast(const PassOwnPtr<U>& p) + { + return PassOwnPtr<T>(static_cast<T*>(p.release())); + } + + template <typename T, typename U> inline PassOwnPtr<T> const_pointer_cast(const PassOwnPtr<U>& p) + { + return PassOwnPtr<T>(const_cast<T*>(p.release())); + } + + template <typename T> inline T* getPtr(const PassOwnPtr<T>& p) + { + return p.get(); + } + +} // namespace WTF + +using WTF::PassOwnPtr; +using WTF::const_pointer_cast; +using WTF::static_pointer_cast; + +#endif // WTF_PassOwnPtr_h diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/PassRefPtr.h b/src/3rdparty/webkit/JavaScriptCore/wtf/PassRefPtr.h index c1dc309..d80ed62 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/PassRefPtr.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/PassRefPtr.h @@ -40,7 +40,7 @@ namespace WTF { PassRefPtr(const PassRefPtr& o) : m_ptr(o.releaseRef()) {} template <typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.releaseRef()) { } - ALWAYS_INLINE ~PassRefPtr() { if (T* ptr = m_ptr) ptr->deref(); } + ALWAYS_INLINE ~PassRefPtr() { if (UNLIKELY(m_ptr != 0)) m_ptr->deref(); } template <class U> PassRefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { if (T* ptr = m_ptr) ptr->ref(); } diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/Platform.h b/src/3rdparty/webkit/JavaScriptCore/wtf/Platform.h index 6c27123..c82d1f7 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/Platform.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/Platform.h @@ -40,6 +40,13 @@ /* 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 +#include <TargetConditionals.h> #endif /* PLATFORM(WIN_OS) */ @@ -49,15 +56,22 @@ #define WTF_PLATFORM_WIN_OS 1 #endif -/* PLATFORM(WIN_CE) */ +/* PLATFORM(WINCE) */ /* Operating system level dependencies for Windows CE that should be used */ /* regardless of operating environment */ /* Note that for this platform PLATFORM(WIN_OS) is also defined. */ #if defined(_WIN32_WCE) -#define WTF_PLATFORM_WIN_CE 1 +#define WTF_PLATFORM_WINCE 1 #include <ce_time.h> #endif +/* PLATFORM(LINUX) */ +/* Operating system level dependencies for Linux-like systems that */ +/* should be used regardless of operating environment */ +#ifdef __linux__ +#define WTF_PLATFORM_LINUX 1 +#endif + /* PLATFORM(FREEBSD) */ /* Operating system level dependencies for FreeBSD-like systems that */ /* should be used regardless of operating environment */ @@ -137,11 +151,30 @@ #define WTF_PLATFORM_WIN 1 #endif +/* PLATFORM(IPHONE) */ +#if (defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) +#define WTF_PLATFORM_IPHONE 1 +#endif + +/* PLATFORM(IPHONE_SIMULATOR) */ +#if defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR +#define WTF_PLATFORM_IPHONE 1 +#define WTF_PLATFORM_IPHONE_SIMULATOR 1 +#else +#define WTF_PLATFORM_IPHONE_SIMULATOR 0 +#endif + +#if !defined(WTF_PLATFORM_IPHONE) +#define WTF_PLATFORM_IPHONE 0 +#endif + /* Graphics engines */ /* PLATFORM(CG) and PLATFORM(CI) */ -#if PLATFORM(MAC) +#if PLATFORM(MAC) || PLATFORM(IPHONE) #define WTF_PLATFORM_CG 1 +#endif +#if PLATFORM(MAC) && !PLATFORM(IPHONE) #define WTF_PLATFORM_CI 1 #endif @@ -195,7 +228,29 @@ #if !defined(__ARM_EABI__) #define WTF_PLATFORM_FORCE_PACK 1 #endif +#define ARM_ARCH_VERSION 3 +#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) +#undef ARM_ARCH_VERSION +#define ARM_ARCH_VERSION 4 +#endif +#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \ + || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \ + || defined(__ARM_ARCH_5TEJ__) +#undef ARM_ARCH_VERSION +#define ARM_ARCH_VERSION 5 +#endif +#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \ + || defined(__ARM_ARCH_6ZK__) +#undef ARM_ARCH_VERSION +#define ARM_ARCH_VERSION 6 #endif +#if defined(__ARM_ARCH_7A__) +#undef ARM_ARCH_VERSION +#define ARM_ARCH_VERSION 7 +#endif +#endif /* ARM */ +#define PLATFORM_ARM_ARCH(N) (PLATFORM(ARM) && ARM_ARCH_VERSION >= N) /* PLATFORM(X86) */ #if defined(__i386__) \ @@ -208,23 +263,27 @@ /* PLATFORM(X86_64) */ #if defined(__x86_64__) \ - || defined(__ia64__) \ || defined(_M_X64) #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 #define WTF_PLATFORM_BIG_ENDIAN 1 #endif -/* PLATFORM(WIN_CE) && PLATFORM(QT) +/* PLATFORM(WINCE) && PLATFORM(QT) We can not determine the endianess at compile time. For Qt for Windows CE the endianess is specified in the device specific makespec */ -#if PLATFORM(WIN_CE) && PLATFORM(QT) +#if PLATFORM(WINCE) && PLATFORM(QT) # include <QtGlobal> # undef WTF_PLATFORM_BIG_ENDIAN # undef WTF_PLATFORM_MIDDLE_ENDIAN @@ -276,7 +335,7 @@ #define WTF_COMPILER_WINSCW 1 #endif -#if (PLATFORM(MAC) || PLATFORM(WIN)) && !defined(ENABLE_JSC_MULTIPLE_THREADS) +#if (PLATFORM(IPHONE) || PLATFORM(MAC) || PLATFORM(WIN)) && !defined(ENABLE_JSC_MULTIPLE_THREADS) #define ENABLE_JSC_MULTIPLE_THREADS 1 #endif @@ -291,7 +350,7 @@ #define WTF_USE_ICU_UNICODE 1 #endif -#if PLATFORM(MAC) +#if PLATFORM(MAC) && !PLATFORM(IPHONE) #define WTF_PLATFORM_CF 1 #define WTF_USE_PTHREADS 1 #if !defined(ENABLE_MAC_JAVA_BRIDGE) @@ -301,9 +360,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) @@ -311,11 +368,24 @@ #define WTF_USE_PTHREADS 1 #endif +#if PLATFORM(IPHONE) +#define WTF_PLATFORM_CF 1 +#define WTF_USE_PTHREADS 1 +#define ENABLE_FTPDIR 1 +#define ENABLE_MAC_JAVA_BRIDGE 0 +#define ENABLE_ICONDATABASE 0 +#define ENABLE_GEOLOCATION 1 +#define ENABLE_NETSCAPE_PLUGIN_API 0 +#define HAVE_READLINE 1 +#define ENABLE_REPAINT_THROTTLING 1 +#endif + #if PLATFORM(WIN) #define WTF_USE_WININET 1 #endif #if PLATFORM(WX) +#define ENABLE_ASSEMBLER 1 #define WTF_USE_CURL 1 #define WTF_USE_PTHREADS 1 #endif @@ -327,18 +397,15 @@ #endif #if !defined(HAVE_ACCESSIBILITY) -#if PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(CHROMIUM) +#if PLATFORM(IPHONE) || PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(CHROMIUM) #define HAVE_ACCESSIBILITY 1 #endif #endif /* !defined(HAVE_ACCESSIBILITY) */ -#if COMPILER(GCC) -#define HAVE_COMPUTED_GOTO 1 -#endif - #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 @@ -347,10 +414,19 @@ #define HAVE_SYS_TIME_H 1 #define HAVE_SYS_TIMEB_H 1 +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !PLATFORM(IPHONE) +#define HAVE_MADV_FREE_REUSE 1 +#define HAVE_MADV_FREE 1 +#endif + +#if PLATFORM(IPHONE) +#define HAVE_MADV_FREE 1 +#endif + #elif PLATFORM(WIN_OS) #define HAVE_FLOAT_H 1 -#if PLATFORM(WIN_CE) +#if PLATFORM(WINCE) #define HAVE_ERRNO_H 0 #else #define HAVE_SYS_TIMEB_H 1 @@ -375,6 +451,7 @@ /* 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 @@ -385,6 +462,12 @@ /* ENABLE macro defaults */ +/* fastMalloc match validation allows for runtime verification that + new is matched by delete, fastMalloc is matched by fastFree, etc. */ +#if !defined(ENABLE_FAST_MALLOC_MATCH_VALIDATION) +#define ENABLE_FAST_MALLOC_MATCH_VALIDATION 0 +#endif + #if !defined(ENABLE_ICONDATABASE) #define ENABLE_ICONDATABASE 1 #endif @@ -417,16 +500,15 @@ #define ENABLE_OPCODE_STATS 0 #endif -#if !defined(ENABLE_CODEBLOCK_SAMPLING) +#define ENABLE_SAMPLING_COUNTERS 0 +#define ENABLE_SAMPLING_FLAGS 0 +#define ENABLE_OPCODE_SAMPLING 0 #define ENABLE_CODEBLOCK_SAMPLING 0 +#if ENABLE(CODEBLOCK_SAMPLING) && !ENABLE(OPCODE_SAMPLING) +#error "CODEBLOCK_SAMPLING requires OPCODE_SAMPLING" #endif - -#if ENABLE(CODEBLOCK_SAMPLING) && !defined(ENABLE_OPCODE_SAMPLING) -#define ENABLE_OPCODE_SAMPLING 1 -#endif - -#if !defined(ENABLE_OPCODE_SAMPLING) -#define ENABLE_OPCODE_SAMPLING 0 +#if ENABLE(OPCODE_SAMPLING) || ENABLE(SAMPLING_FLAGS) +#define ENABLE_SAMPLING_THREAD 1 #endif #if !defined(ENABLE_GEOLOCATION) @@ -437,51 +519,95 @@ #define ENABLE_TEXT_CARET 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 WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1 - #define ENABLE_JIT_OPTIMIZE_CALL 1 - #define ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS 1 - #define WTF_USE_ALTERNATE_JSIMMEDIATE 1 + #define ENABLE_JIT 1 /* The JIT is tested & working on x86 Mac */ #elif PLATFORM(X86) && PLATFORM(MAC) #define ENABLE_JIT 1 #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1 - #define ENABLE_JIT_OPTIMIZE_CALL 1 - #define ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS 1 - #define ENABLE_JIT_OPTIMIZE_ARITHMETIC 1 +#elif PLATFORM_ARM_ARCH(7) && PLATFORM(IPHONE) + /* Under development, temporarily disabled until 16Mb link range limit in assembler is fixed. */ + #define ENABLE_JIT 0 + #define ENABLE_JIT_OPTIMIZE_NATIVE_CALL 0 /* The JIT is tested & working on x86 Windows */ #elif PLATFORM(X86) && PLATFORM(WIN) #define ENABLE_JIT 1 - #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1 - #define ENABLE_JIT_OPTIMIZE_CALL 1 - #define ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS 1 - #define ENABLE_JIT_OPTIMIZE_ARITHMETIC 1 #endif #endif -#if ENABLE(JIT) -#if !(USE(JIT_STUB_ARGUMENT_VA_LIST) || USE(JIT_STUB_ARGUMENT_REGISTER) || USE(JIT_STUB_ARGUMENT_STACK)) -#error Please define one of the JIT_STUB_ARGUMENT settings. -#elif (USE(JIT_STUB_ARGUMENT_VA_LIST) && USE(JIT_STUB_ARGUMENT_REGISTER)) \ - || (USE(JIT_STUB_ARGUMENT_VA_LIST) && USE(JIT_STUB_ARGUMENT_STACK)) \ - || (USE(JIT_STUB_ARGUMENT_REGISTER) && USE(JIT_STUB_ARGUMENT_STACK)) -#error Please do not define more than one of the JIT_STUB_ARGUMENT settings. +#ifndef ENABLE_JIT_OPTIMIZE_CALL +#define ENABLE_JIT_OPTIMIZE_CALL 1 #endif +#ifndef ENABLE_JIT_OPTIMIZE_NATIVE_CALL +#define ENABLE_JIT_OPTIMIZE_NATIVE_CALL 1 +#endif +#ifndef ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS +#define ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS 1 +#endif +#ifndef ENABLE_JIT_OPTIMIZE_ARITHMETIC +#define ENABLE_JIT_OPTIMIZE_ARITHMETIC 1 +#endif +#ifndef ENABLE_JIT_OPTIMIZE_METHOD_CALLS +#define ENABLE_JIT_OPTIMIZE_METHOD_CALLS 1 #endif -/* WREC supports x86 & x86-64, and has been tested on Mac and Windows ('cept on 64-bit on Mac). */ -#if (!defined(ENABLE_WREC) && PLATFORM(X86) && PLATFORM(MAC)) \ - || (!defined(ENABLE_WREC) && PLATFORM(X86_64) && PLATFORM(MAC)) \ - || (!defined(ENABLE_WREC) && PLATFORM(X86) && PLATFORM(WIN)) -#define ENABLE_WREC 1 +#if PLATFORM(X86) && COMPILER(MSVC) +#define JSC_HOST_CALL __fastcall +#elif PLATFORM(X86) && COMPILER(GCC) +#define JSC_HOST_CALL __attribute__ ((fastcall)) +#else +#define JSC_HOST_CALL #endif -#if ENABLE(JIT) || ENABLE(WREC) +#if COMPILER(GCC) && !ENABLE(JIT) +#define HAVE_COMPUTED_GOTO 1 +#endif + +#if ENABLE(JIT) && defined(COVERAGE) + #define WTF_USE_INTERPRETER 0 +#else + #define WTF_USE_INTERPRETER 1 +#endif + +/* Yet Another Regex Runtime. */ +/* YARR supports x86 & x86-64, and has been tested on Mac and Windows. */ +#if (!defined(ENABLE_YARR_JIT) && PLATFORM(X86) && PLATFORM(MAC)) \ + || (!defined(ENABLE_YARR_JIT) && PLATFORM(X86_64) && PLATFORM(MAC)) \ + /* Under development, temporarily disabled until 16Mb link range limit in assembler is fixed. */ \ + || (!defined(ENABLE_YARR_JIT) && PLATFORM_ARM_ARCH(7) && PLATFORM(IPHONE) && 0) \ + || (!defined(ENABLE_YARR_JIT) && PLATFORM(X86) && PLATFORM(WIN)) +#define ENABLE_YARR 1 +#define ENABLE_YARR_JIT 1 +#endif +/* Sanity Check */ +#if ENABLE(YARR_JIT) && !ENABLE(YARR) +#error "YARR_JIT requires YARR" +#endif + +#if ENABLE(JIT) || ENABLE(YARR_JIT) #define ENABLE_ASSEMBLER 1 #endif +/* Setting this flag prevents the assembler from using RWX memory; this may improve + security but currectly comes at a significant performance cost. */ +#if PLATFORM_ARM_ARCH(7) && PLATFORM(IPHONE) +#define ENABLE_ASSEMBLER_WX_EXCLUSIVE 1 +#else +#define ENABLE_ASSEMBLER_WX_EXCLUSIVE 0 +#endif #if !defined(ENABLE_PAN_SCROLLING) && PLATFORM(WIN_OS) #define ENABLE_PAN_SCROLLING 1 @@ -502,4 +628,15 @@ #define WTF_USE_FONT_FAST_PATH 1 #endif +/* Accelerated compositing */ +#if PLATFORM(MAC) +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) +#define WTF_USE_ACCELERATED_COMPOSITING 1 +#endif +#endif + +#if PLATFORM(IPHONE) +#define WTF_USE_ACCELERATED_COMPOSITING 1 +#endif + #endif /* WTF_Platform_h */ diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/PtrAndFlags.h b/src/3rdparty/webkit/JavaScriptCore/wtf/PtrAndFlags.h new file mode 100644 index 0000000..477e893 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/PtrAndFlags.h @@ -0,0 +1,53 @@ +/* + * 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 PtrAndFlags_h +#define PtrAndFlags_h + +#include <wtf/Assertions.h> + +namespace WTF { + template<class T, typename FlagEnum> class PtrAndFlags { + public: + PtrAndFlags() : m_ptrAndFlags(0) {} + + bool isFlagSet(FlagEnum flagNumber) const { ASSERT(flagNumber < 2); return m_ptrAndFlags & (1 << flagNumber); } + void setFlag(FlagEnum flagNumber) { ASSERT(flagNumber < 2); m_ptrAndFlags |= (1 << flagNumber);} + void clearFlag(FlagEnum flagNumber) { ASSERT(flagNumber < 2); m_ptrAndFlags &= ~(1 << flagNumber);} + T* get() const { return reinterpret_cast<T*>(m_ptrAndFlags & ~3); } + void set(T* ptr) { ASSERT(!(reinterpret_cast<intptr_t>(ptr) & 3)); m_ptrAndFlags = reinterpret_cast<intptr_t>(ptr) | (m_ptrAndFlags & 3);} + private: + intptr_t m_ptrAndFlags; + }; +} // namespace WTF + +using WTF::PtrAndFlags; + +#endif // PtrAndFlags_h diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/RandomNumber.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/RandomNumber.cpp index e569227..c94d5a4 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/RandomNumber.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/RandomNumber.cpp @@ -36,6 +36,16 @@ namespace WTF { +double weakRandomNumber() +{ +#if COMPILER(MSVC) && defined(_CRT_RAND_S) + // rand_s is incredibly slow on windows so we fall back on rand for Math.random + return (rand() + (rand() / (RAND_MAX + 1.0))) / (RAND_MAX + 1.0); +#else + return randomNumber(); +#endif +} + double randomNumber() { #if !ENABLE(JSC_MULTIPLE_THREADS) @@ -46,42 +56,39 @@ double randomNumber() } #endif - uint32_t part1; - uint32_t part2; - uint64_t fullRandom; #if COMPILER(MSVC) && defined(_CRT_RAND_S) - rand_s(&part1); - rand_s(&part2); - fullRandom = part1; - fullRandom <<= 32; - fullRandom |= part2; + uint32_t bits; + rand_s(&bits); + return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0); #elif PLATFORM(DARWIN) - part1 = arc4random(); - part2 = arc4random(); - fullRandom = part1; - fullRandom <<= 32; - fullRandom |= part2; + uint32_t bits = arc4random(); + return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0); #elif PLATFORM(UNIX) - part1 = random() & (RAND_MAX - 1); - part2 = random() & (RAND_MAX - 1); + uint32_t part1 = random() & (RAND_MAX - 1); + uint32_t part2 = random() & (RAND_MAX - 1); // random only provides 31 bits - fullRandom = part1; + uint64_t fullRandom = part1; fullRandom <<= 31; fullRandom |= part2; + + // Mask off the low 53bits + fullRandom &= (1LL << 53) - 1; + return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53); #else - part1 = rand() & (RAND_MAX - 1); - part2 = rand() & (RAND_MAX - 1); + uint32_t part1 = rand() & (RAND_MAX - 1); + uint32_t part2 = rand() & (RAND_MAX - 1); // rand only provides 31 bits, and the low order bits of that aren't very random // so we take the high 26 bits of part 1, and the high 27 bits of part2. part1 >>= 5; // drop the low 5 bits part2 >>= 4; // drop the low 4 bits - fullRandom = part1; + uint64_t fullRandom = part1; fullRandom <<= 27; fullRandom |= part2; -#endif + // Mask off the low 53bits fullRandom &= (1LL << 53) - 1; return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53); +#endif } } diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/RandomNumber.h b/src/3rdparty/webkit/JavaScriptCore/wtf/RandomNumber.h index 3540344..fe1687c 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/RandomNumber.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/RandomNumber.h @@ -28,9 +28,15 @@ namespace WTF { - // Returns a pseudo-random number in the range [0, 1) + // Returns a pseudo-random number in the range [0, 1), attempts to be + // cryptographically secure if possible on the target platform double randomNumber(); + // Returns a pseudo-random number in the range [0, 1), attempts to + // produce a reasonable "random" number fast. + // We only need this because rand_s is so slow on windows. + double weakRandomNumber(); + } #endif diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/RandomNumberSeed.h b/src/3rdparty/webkit/JavaScriptCore/wtf/RandomNumberSeed.h index c7af3d6..32291dd 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/RandomNumberSeed.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/RandomNumberSeed.h @@ -38,7 +38,7 @@ #include <unistd.h> #endif -#if PLATFORM(WIN_CE) +#if PLATFORM(WINCE) #include <ce_time.h> #endif @@ -61,6 +61,15 @@ inline void initializeRandomNumberGenerator() #endif } +inline void initializeWeakRandomNumberGenerator() +{ +#if COMPILER(MSVC) && defined(_CRT_RAND_S) + // We need to initialise windows rand() explicitly for Math.random + unsigned seed = 0; + rand_s(&seed); + srand(seed); +#endif +} } #endif diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/RefCounted.h b/src/3rdparty/webkit/JavaScriptCore/wtf/RefCounted.h index ac8e167..c174145 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/RefCounted.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/RefCounted.h @@ -49,15 +49,17 @@ public: } protected: - RefCountedBase(int initialRefCount) - : m_refCount(initialRefCount) + RefCountedBase() + : m_refCount(1) #ifndef NDEBUG , m_deletionHasBegun(false) #endif { } - ~RefCountedBase() {} + ~RefCountedBase() + { + } // Returns whether the pointer should be freed or not. bool derefBase() @@ -75,7 +77,23 @@ protected: return false; } -protected: + // Helper for generating JIT code. Please do not use for non-JIT purposes. + int* addressOfCount() + { + return &m_refCount; + } + +#ifndef NDEBUG + bool deletionHasBegun() const + { + return m_deletionHasBegun; + } +#endif + +private: + template<class T> + friend class CrossThreadRefCounted; + int m_refCount; #ifndef NDEBUG bool m_deletionHasBegun; @@ -85,11 +103,6 @@ protected: template<class T> class RefCounted : public RefCountedBase { public: - RefCounted(int initialRefCount = 1) - : RefCountedBase(initialRefCount) - { - } - void deref() { if (derefBase()) @@ -97,7 +110,9 @@ public: } protected: - ~RefCounted() {} + ~RefCounted() + { + } }; } // namespace WTF diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/RefPtr.h b/src/3rdparty/webkit/JavaScriptCore/wtf/RefPtr.h index 929e745..74cd0ea 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/RefPtr.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/RefPtr.h @@ -23,6 +23,7 @@ #include <algorithm> #include "AlwaysInline.h" +#include "FastAllocBase.h" namespace WTF { @@ -32,7 +33,7 @@ namespace WTF { enum HashTableDeletedValueType { HashTableDeletedValue }; - template <typename T> class RefPtr { + template <typename T> class RefPtr : public FastAllocBase { public: RefPtr() : m_ptr(0) { } RefPtr(T* ptr) : m_ptr(ptr) { if (ptr) ptr->ref(); } diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/RetainPtr.h b/src/3rdparty/webkit/JavaScriptCore/wtf/RetainPtr.h index a66a127..77f25e0 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/RetainPtr.h +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/JavaScriptCore/wtf/SegmentedVector.h b/src/3rdparty/webkit/JavaScriptCore/wtf/SegmentedVector.h new file mode 100644 index 0000000..065c19c --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/SegmentedVector.h @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2008 Apple 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: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 SegmentedVector_h +#define SegmentedVector_h + +#include <wtf/Vector.h> + +namespace WTF { + + // An iterator for SegmentedVector. It supports only the pre ++ operator + template <typename T, size_t SegmentSize> class SegmentedVector; + template <typename T, size_t SegmentSize> class SegmentedVectorIterator { + private: + friend class SegmentedVector<T, SegmentSize>; + public: + typedef SegmentedVectorIterator<T, SegmentSize> Iterator; + + ~SegmentedVectorIterator() { } + + T& operator*() const { return m_vector.m_segments.at(m_segment)->at(m_index); } + T* operator->() const { return &m_vector.m_segments.at(m_segment)->at(m_index); } + + // Only prefix ++ operator supported + Iterator& operator++() + { + ASSERT(m_index != SegmentSize); + ++m_index; + if (m_index >= m_vector.m_segments.at(m_segment)->size()) { + if (m_segment + 1 < m_vector.m_segments.size()) { + ASSERT(m_vector.m_segments.at(m_segment)->size() > 0); + ++m_segment; + m_index = 0; + } else { + // Points to the "end" symbol + m_segment = 0; + m_index = SegmentSize; + } + } + return *this; + } + + bool operator==(const Iterator& other) const + { + return (m_index == other.m_index && m_segment = other.m_segment && &m_vector == &other.m_vector); + } + + bool operator!=(const Iterator& other) const + { + return (m_index != other.m_index || m_segment != other.m_segment || &m_vector != &other.m_vector); + } + + SegmentedVectorIterator& operator=(const SegmentedVectorIterator<T, SegmentSize>& other) + { + m_vector = other.m_vector; + m_segment = other.m_segment; + m_index = other.m_index; + return *this; + } + + private: + SegmentedVectorIterator(SegmentedVector<T, SegmentSize>& vector, size_t segment, size_t index) + : m_vector(vector) + , m_segment(segment) + , m_index(index) + { + } + + SegmentedVector<T, SegmentSize>& m_vector; + size_t m_segment; + size_t m_index; + }; + + // SegmentedVector is just like Vector, but it doesn't move the values + // stored in its buffer when it grows. Therefore, it is safe to keep + // pointers into a SegmentedVector. + template <typename T, size_t SegmentSize> class SegmentedVector { + friend class SegmentedVectorIterator<T, SegmentSize>; + public: + typedef SegmentedVectorIterator<T, SegmentSize> Iterator; + + SegmentedVector() + : m_size(0) + { + m_segments.append(&m_inlineSegment); + } + + ~SegmentedVector() + { + deleteAllSegments(); + } + + size_t size() const { return m_size; } + + T& at(size_t index) + { + if (index < SegmentSize) + return m_inlineSegment[index]; + return segmentFor(index)->at(subscriptFor(index)); + } + + T& operator[](size_t index) + { + return at(index); + } + + T& last() + { + return at(size() - 1); + } + + template <typename U> void append(const U& value) + { + ++m_size; + + if (m_size <= SegmentSize) { + m_inlineSegment.uncheckedAppend(value); + return; + } + + if (!segmentExistsFor(m_size - 1)) + m_segments.append(new Segment); + segmentFor(m_size - 1)->uncheckedAppend(value); + } + + T& alloc() + { + append<T>(T()); + return last(); + } + + void removeLast() + { + if (m_size <= SegmentSize) + m_inlineSegment.removeLast(); + else + segmentFor(m_size - 1)->removeLast(); + --m_size; + } + + void grow(size_t size) + { + ASSERT(size > m_size); + ensureSegmentsFor(size); + m_size = size; + } + + void clear() + { + deleteAllSegments(); + m_segments.resize(1); + m_inlineSegment.clear(); + m_size = 0; + } + + Iterator begin() + { + return Iterator(*this, 0, m_size ? 0 : SegmentSize); + } + + Iterator end() + { + return Iterator(*this, 0, SegmentSize); + } + + private: + typedef Vector<T, SegmentSize> Segment; + + void deleteAllSegments() + { + // Skip the first segment, because it's our inline segment, which was + // not created by new. + for (size_t i = 1; i < m_segments.size(); i++) + delete m_segments[i]; + } + + bool segmentExistsFor(size_t index) + { + return index / SegmentSize < m_segments.size(); + } + + Segment* segmentFor(size_t index) + { + return m_segments[index / SegmentSize]; + } + + size_t subscriptFor(size_t index) + { + return index % SegmentSize; + } + + void ensureSegmentsFor(size_t size) + { + size_t segmentCount = m_size / SegmentSize; + if (m_size % SegmentSize) + ++segmentCount; + segmentCount = std::max<size_t>(segmentCount, 1); // We always have at least our inline segment. + + size_t neededSegmentCount = size / SegmentSize; + if (size % SegmentSize) + ++neededSegmentCount; + + // Fill up to N - 1 segments. + size_t end = neededSegmentCount - 1; + for (size_t i = segmentCount - 1; i < end; ++i) + ensureSegment(i, SegmentSize); + + // Grow segment N to accomodate the remainder. + ensureSegment(end, subscriptFor(size - 1) + 1); + } + + void ensureSegment(size_t segmentIndex, size_t size) + { + ASSERT(segmentIndex <= m_segments.size()); + if (segmentIndex == m_segments.size()) + m_segments.append(new Segment); + m_segments[segmentIndex]->grow(size); + } + + size_t m_size; + Segment m_inlineSegment; + Vector<Segment*, 32> m_segments; + }; + +} // namespace WTF + +#endif // SegmentedVector_h diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/StdLibExtras.h b/src/3rdparty/webkit/JavaScriptCore/wtf/StdLibExtras.h index ddc5a58..afc5e8a 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/StdLibExtras.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/StdLibExtras.h @@ -23,7 +23,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifndef WTF_StdLibExtras_h +#define WTF_StdLibExtras_h + #include <wtf/Platform.h> +#include <wtf/Assertions.h> // Use these to declare and define a static local variable (static T;) so that // it is leaked so that its destructors are not called at exit. Using this @@ -36,3 +40,24 @@ #define DEFINE_STATIC_LOCAL(type, name, arguments) \ static type& name = *new type arguments #endif + +namespace WTF { + + /* + * C++'s idea of a reinterpret_cast lacks sufficient cojones. + */ + template<typename TO, typename FROM> + TO bitwise_cast(FROM from) + { + COMPILE_ASSERT(sizeof(TO) == sizeof(FROM), WTF_bitwise_cast_sizeof_casted_types_is_equal); + union { + FROM from; + TO to; + } u; + u.from = from; + return u.to; + } + +} // namespace WTF + +#endif diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/StringExtras.h b/src/3rdparty/webkit/JavaScriptCore/wtf/StringExtras.h index 881b066..1c23390 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/StringExtras.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/StringExtras.h @@ -29,6 +29,10 @@ #include <stdarg.h> #include <stdio.h> +#if HAVE(STRINGS_H) +#include <strings.h> +#endif + #if COMPILER(MSVC) inline int snprintf(char* buffer, size_t count, const char* format, ...) @@ -41,7 +45,7 @@ inline int snprintf(char* buffer, size_t count, const char* format, ...) return result; } -#if COMPILER(MSVC7) || PLATFORM(WIN_CE) +#if COMPILER(MSVC7) || PLATFORM(WINCE) inline int vsnprintf(char* buffer, size_t count, const char* format, va_list args) { @@ -50,7 +54,7 @@ inline int vsnprintf(char* buffer, size_t count, const char* format, va_list arg #endif -#if PLATFORM(WIN_CE) +#if PLATFORM(WINCE) inline int strnicmp(const char* string1, const char* string2, size_t count) { diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/TCPageMap.h b/src/3rdparty/webkit/JavaScriptCore/wtf/TCPageMap.h index 21a87e4..3f56c24 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/TCPageMap.h +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/JavaScriptCore/wtf/TCSystemAlloc.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/TCSystemAlloc.cpp index 9c147b2..478ce63 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/TCSystemAlloc.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/TCSystemAlloc.cpp @@ -381,11 +381,24 @@ 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_FREE) || HAVE(MADV_DONTNEED) + void TCMalloc_SystemRelease(void* start, size_t length) { - UNUSED_PARAM(start); - UNUSED_PARAM(length); -#if HAVE(MADV_DONTNEED) + // MADV_FREE clears the modified bit on pages, which allows + // them to be discarded immediately. +#if HAVE(MADV_FREE) + const int advice = MADV_FREE; +#else + const int advice = MADV_DONTNEED; +#endif if (FLAGS_malloc_devmem_start) { // It's not safe to use MADV_DONTNEED if we've been mapping // /dev/mem for heap memory @@ -412,26 +425,45 @@ void TCMalloc_SystemRelease(void* start, size_t length) // Note -- ignoring most return codes, because if this fails it // doesn't matter... while (madvise(reinterpret_cast<char*>(new_start), new_end - new_start, - MADV_DONTNEED) == -1 && + advice) == -1 && 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 } -#if HAVE(VIRTUALALLOC) +#else + +// Platforms that don't support returning memory use an empty inline version of TCMalloc_SystemRelease +// declared in TCSystemAlloc.h + +#endif + +#if HAVE(MADV_FREE_REUSE) + void TCMalloc_SystemCommit(void* start, size_t length) { - UNUSED_PARAM(start); - UNUSED_PARAM(length); + while (madvise(start, length, MADV_FREE_REUSE) == -1 && errno == EAGAIN) { } } + +#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/src/3rdparty/webkit/JavaScriptCore/wtf/TCSystemAlloc.h b/src/3rdparty/webkit/JavaScriptCore/wtf/TCSystemAlloc.h index 0caf718..8e3a01a 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/TCSystemAlloc.h +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadSpecific.h b/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadSpecific.h index 7603802..b07a9a2 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadSpecific.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadSpecific.h @@ -45,13 +45,15 @@ #if USE(PTHREADS) #include <pthread.h> +#elif PLATFORM(QT) +#include <QThreadStorage> #elif PLATFORM(WIN_OS) #include <windows.h> #endif namespace WTF { -#if !USE(PTHREADS) && PLATFORM(WIN_OS) +#if !USE(PTHREADS) && !PLATFORM(QT) && PLATFORM(WIN_OS) // ThreadSpecificThreadExit should be called each time when a thread is detached. // This is done automatically for threads created with WTF::createThread. void ThreadSpecificThreadExit(); @@ -66,7 +68,7 @@ public: ~ThreadSpecific(); private: -#if !USE(PTHREADS) && PLATFORM(WIN_OS) +#if !USE(PTHREADS) && !PLATFORM(QT) && PLATFORM(WIN_OS) friend void ThreadSpecificThreadExit(); #endif @@ -74,7 +76,7 @@ private: void set(T*); void static destroy(void* ptr); -#if USE(PTHREADS) || PLATFORM(WIN_OS) +#if USE(PTHREADS) || PLATFORM(QT) || PLATFORM(WIN_OS) struct Data : Noncopyable { Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {} @@ -88,6 +90,8 @@ private: #if USE(PTHREADS) pthread_key_t m_key; +#elif PLATFORM(QT) + QThreadStorage<Data*> m_key; #elif PLATFORM(WIN_OS) int m_index; #endif @@ -122,6 +126,37 @@ inline void ThreadSpecific<T>::set(T* ptr) pthread_setspecific(m_key, new Data(ptr, this)); } +#elif PLATFORM(QT) + +template<typename T> +inline ThreadSpecific<T>::ThreadSpecific() +{ +} + +template<typename T> +inline ThreadSpecific<T>::~ThreadSpecific() +{ + Data* data = static_cast<Data*>(m_key.localData()); + if (data) + data->destructor(data); +} + +template<typename T> +inline T* ThreadSpecific<T>::get() +{ + Data* data = static_cast<Data*>(m_key.localData()); + return data ? data->value : 0; +} + +template<typename T> +inline void ThreadSpecific<T>::set(T* ptr) +{ + ASSERT(!get()); + Data* data = new Data(ptr, this); + data->destructor = &ThreadSpecific<T>::destroy; + m_key.setLocalData(data); +} + #elif PLATFORM(WIN_OS) // The maximum number of TLS keys that can be created. For simplification, we assume that: @@ -129,8 +164,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 +175,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 +201,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 @@ -189,8 +224,10 @@ inline void ThreadSpecific<T>::destroy(void* ptr) #if USE(PTHREADS) pthread_setspecific(data->owner->m_key, 0); +#elif PLATFORM(QT) + data->owner->m_key.setLocalData(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/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadSpecificWin.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadSpecificWin.cpp index 1a3febb..f2c0cad 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadSpecificWin.cpp +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/JavaScriptCore/wtf/Threading.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/Threading.cpp index 0179dcc..bd25ee7 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/Threading.cpp +++ b/src/3rdparty/webkit/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); @@ -72,6 +86,8 @@ ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* // This function is deprecated but needs to be kept around for backward // compatibility. Use the 3-argument version of createThread above. +ThreadIdentifier createThread(ThreadFunction entryPoint, void* data); + ThreadIdentifier createThread(ThreadFunction entryPoint, void* data) { return createThread(entryPoint, data, 0); diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/Threading.h b/src/3rdparty/webkit/JavaScriptCore/wtf/Threading.h index 156013d..b12f41f 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/Threading.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/Threading.h @@ -59,7 +59,7 @@ #ifndef Threading_h #define Threading_h -#if PLATFORM(WIN_CE) +#if PLATFORM(WINCE) #include <windows.h> #endif @@ -67,7 +67,7 @@ #include <wtf/Locker.h> #include <wtf/Noncopyable.h> -#if PLATFORM(WIN_OS) && !PLATFORM(WIN_CE) +#if PLATFORM(WIN_OS) && !PLATFORM(WINCE) #include <windows.h> #elif PLATFORM(DARWIN) #include <libkern/OSAtomic.h> @@ -108,10 +108,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**); @@ -119,28 +126,36 @@ void detachThread(ThreadIdentifier); #if USE(PTHREADS) typedef pthread_mutex_t PlatformMutex; +typedef pthread_rwlock_t PlatformReadWriteLock; typedef pthread_cond_t PlatformCondition; #elif PLATFORM(GTK) typedef GOwnPtr<GMutex> PlatformMutex; +typedef void* PlatformReadWriteLock; // FIXME: Implement. typedef GOwnPtr<GCond> PlatformCondition; #elif PLATFORM(QT) typedef QT_PREPEND_NAMESPACE(QMutex)* PlatformMutex; +typedef void* PlatformReadWriteLock; // FIXME: Implement. typedef QT_PREPEND_NAMESPACE(QWaitCondition)* PlatformCondition; #elif PLATFORM(WIN_OS) struct PlatformMutex { CRITICAL_SECTION m_internalMutex; size_t m_recursionCount; }; +typedef void* PlatformReadWriteLock; // FIXME: Implement. struct PlatformCondition { - size_t m_timedOut; - size_t m_blocked; - size_t m_waitingForRemoval; - HANDLE m_gate; - HANDLE m_queue; - HANDLE m_mutex; + size_t m_waitersGone; + size_t m_waitersBlocked; + size_t m_waitersToUnblock; + HANDLE m_blockLock; + HANDLE m_blockQueue; + HANDLE m_unblockLock; + + bool timedWait(PlatformMutex&, DWORD durationMilliseconds); + void signal(bool unblockAll); }; #else typedef void* PlatformMutex; +typedef void* PlatformReadWriteLock; typedef void* PlatformCondition; #endif @@ -161,14 +176,32 @@ private: typedef Locker<Mutex> MutexLocker; +class ReadWriteLock : Noncopyable { +public: + ReadWriteLock(); + ~ReadWriteLock(); + + void readLock(); + bool tryReadLock(); + + void writeLock(); + bool tryWriteLock(); + + void unlock(); + +private: + PlatformReadWriteLock m_readWriteLock; +}; + class ThreadCondition : Noncopyable { public: ThreadCondition(); ~ThreadCondition(); void wait(Mutex& mutex); - // Returns true if the condition was signaled before the timeout, false if the timeout was reached - bool timedWait(Mutex&, double interval); + // Returns true if the condition was signaled before absoluteTime, false if the absoluteTime was reached or is in the past. + // The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the same time zone as WTF::currentTime(). + bool timedWait(Mutex&, double absoluteTime); void signal(); void broadcast(); @@ -179,7 +212,7 @@ private: #if PLATFORM(WIN_OS) #define WTF_USE_LOCKFREE_THREADSAFESHARED 1 -#if COMPILER(MINGW) || COMPILER(MSVC7) || PLATFORM(WIN_CE) +#if COMPILER(MINGW) || COMPILER(MSVC7) || PLATFORM(WINCE) inline void atomicIncrement(int* addend) { InterlockedIncrement(reinterpret_cast<long*>(addend)); } inline int atomicDecrement(int* addend) { return InterlockedDecrement(reinterpret_cast<long*>(addend)); } #else @@ -201,9 +234,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) { } @@ -218,20 +251,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; @@ -245,13 +264,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/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadingGtk.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadingGtk.cpp deleted file mode 100644 index 777d55b..0000000 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadingGtk.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of Apple Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 "Threading.h" - -#if !USE(PTHREADS) - -#include "HashMap.h" -#include "MainThread.h" -#include "RandomNumberSeed.h" - -#include <glib.h> - -namespace WTF { - -static Mutex* atomicallyInitializedStaticMutex; - -static ThreadIdentifier mainThreadIdentifier; - -static Mutex& threadMapMutex() -{ - static Mutex mutex; - return mutex; -} - -void initializeThreading() -{ - if (!g_thread_supported()) - g_thread_init(NULL); - ASSERT(g_thread_supported()); - - if (!atomicallyInitializedStaticMutex) { - atomicallyInitializedStaticMutex = new Mutex; - threadMapMutex(); - initializeRandomNumberGenerator(); - mainThreadIdentifier = currentThread(); - initializeMainThread(); - } -} - -void lockAtomicallyInitializedStaticMutex() -{ - ASSERT(atomicallyInitializedStaticMutex); - atomicallyInitializedStaticMutex->lock(); -} - -void unlockAtomicallyInitializedStaticMutex() -{ - atomicallyInitializedStaticMutex->unlock(); -} - -static HashMap<ThreadIdentifier, GThread*>& threadMap() -{ - static HashMap<ThreadIdentifier, GThread*> map; - return map; -} - -static ThreadIdentifier identifierByGthreadHandle(GThread*& thread) -{ - MutexLocker locker(threadMapMutex()); - - HashMap<ThreadIdentifier, GThread*>::iterator i = threadMap().begin(); - for (; i != threadMap().end(); ++i) { - if (i->second == thread) - return i->first; - } - - return 0; -} - -static ThreadIdentifier establishIdentifierForThread(GThread*& thread) -{ - ASSERT(!identifierByGthreadHandle(thread)); - - MutexLocker locker(threadMapMutex()); - - static ThreadIdentifier identifierCount = 1; - - threadMap().add(identifierCount, thread); - - return identifierCount++; -} - -static GThread* threadForIdentifier(ThreadIdentifier id) -{ - MutexLocker locker(threadMapMutex()); - - return threadMap().get(id); -} - -static void clearThreadForIdentifier(ThreadIdentifier id) -{ - MutexLocker locker(threadMapMutex()); - - ASSERT(threadMap().contains(id)); - - threadMap().remove(id); -} - -ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*) -{ - GThread* thread; - if (!(thread = g_thread_create(entryPoint, data, TRUE, 0))) { - LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint, data); - return 0; - } - - ThreadIdentifier threadID = establishIdentifierForThread(thread); - return threadID; -} - -int waitForThreadCompletion(ThreadIdentifier threadID, void** result) -{ - ASSERT(threadID); - - GThread* thread = threadForIdentifier(threadID); - - void* joinResult = g_thread_join(thread); - if (result) - *result = joinResult; - - clearThreadForIdentifier(threadID); - return 0; -} - -void detachThread(ThreadIdentifier) -{ -} - -ThreadIdentifier currentThread() -{ - GThread* currentThread = g_thread_self(); - if (ThreadIdentifier id = identifierByGthreadHandle(currentThread)) - return id; - return establishIdentifierForThread(currentThread); -} - -bool isMainThread() -{ - return currentThread() == mainThreadIdentifier; -} - -Mutex::Mutex() - : m_mutex(g_mutex_new()) -{ -} - -Mutex::~Mutex() -{ -} - -void Mutex::lock() -{ - g_mutex_lock(m_mutex.get()); -} - -bool Mutex::tryLock() -{ - return g_mutex_trylock(m_mutex.get()); -} - -void Mutex::unlock() -{ - g_mutex_unlock(m_mutex.get()); -} - -ThreadCondition::ThreadCondition() - : m_condition(g_cond_new()) -{ -} - -ThreadCondition::~ThreadCondition() -{ -} - -void ThreadCondition::wait(Mutex& mutex) -{ - g_cond_wait(m_condition.get(), mutex.impl().get()); -} - -bool ThreadCondition::timedWait(Mutex& mutex, double interval) -{ - if (interval < 0.0) { - wait(mutex); - return true; - } - - int intervalSeconds = static_cast<int>(interval); - int intervalMicroseconds = static_cast<int>((interval - intervalSeconds) * 1000000.0); - - GTimeVal targetTime; - g_get_current_time(&targetTime); - - targetTime.tv_sec += intervalSeconds; - targetTime.tv_usec += intervalMicroseconds; - if (targetTime.tv_usec > 1000000) { - targetTime.tv_usec -= 1000000; - targetTime.tv_sec++; - } - - return g_cond_timed_wait(m_condition.get(), mutex.impl().get(), &targetTime); -} - -void ThreadCondition::signal() -{ - g_cond_signal(m_condition.get()); -} - -void ThreadCondition::broadcast() -{ - g_cond_broadcast(m_condition.get()); -} - - -} - -#endif // !USE(PTHREADS) diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadingNone.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadingNone.cpp index 832cd0c..46f23d2 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadingNone.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadingNone.cpp @@ -33,10 +33,11 @@ namespace WTF { void initializeThreading() { } -ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char*) { return 0; } +ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char*) { return ThreadIdentifier(); } +void setThreadNameInternal(const char*) { } int waitForThreadCompletion(ThreadIdentifier, void**) { return 0; } void detachThread(ThreadIdentifier) { } -ThreadIdentifier currentThread() { return 0; } +ThreadIdentifier currentThread() { return ThreadIdentifier(); } bool isMainThread() { return true; } Mutex::Mutex() { } @@ -47,8 +48,8 @@ void Mutex::unlock() { } ThreadCondition::ThreadCondition() { } ThreadCondition::~ThreadCondition() { } -void ThreadCondition::wait(Mutex& mutex) { } -bool ThreadCondition::timedWait(Mutex& mutex, double interval) { return false; } +void ThreadCondition::wait(Mutex&) { } +bool ThreadCondition::timedWait(Mutex&, double) { return false; } void ThreadCondition::signal() { } void ThreadCondition::broadcast() { } diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadingPthreads.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadingPthreads.cpp index f111fcf..d0e6df8 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadingPthreads.cpp +++ b/src/3rdparty/webkit/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,27 +26,33 @@ * (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> +#if PLATFORM(ANDROID) +#include "jni_utility.h" +#endif + namespace WTF { 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 @@ -62,7 +68,7 @@ void initializeThreading() atomicallyInitializedStaticMutex = new Mutex; threadMapMutex(); initializeRandomNumberGenerator(); -#if !PLATFORM(DARWIN) +#if !PLATFORM(DARWIN) || PLATFORM(CHROMIUM) mainThreadIdentifier = currentThread(); #endif initializeMainThread(); @@ -108,14 +114,14 @@ static ThreadIdentifier establishIdentifierForPthreadHandle(pthread_t& pthreadHa static ThreadIdentifier identifierCount = 1; threadMap().add(identifierCount, pthreadHandle); - + return identifierCount++; } static pthread_t pthreadHandleForIdentifier(ThreadIdentifier id) { MutexLocker locker(threadMapMutex()); - + return threadMap().get(id); } @@ -124,31 +130,76 @@ static void clearPthreadHandleForIdentifier(ThreadIdentifier id) MutexLocker locker(threadMapMutex()); ASSERT(threadMap().contains(id)); - + threadMap().remove(id); } +#if PLATFORM(ANDROID) +// On the Android platform, threads must be registered with the VM before they run. +struct ThreadData { + ThreadFunction entryPoint; + void* arg; +}; + +static void* runThreadWithRegistration(void* arg) +{ + ThreadData* data = static_cast<ThreadData*>(arg); + JavaVM* vm = JSC::Bindings::getJavaVM(); + JNIEnv* env; + void* ret = 0; + if (vm->AttachCurrentThread(&env, 0) == JNI_OK) { + ret = data->entryPoint(data->arg); + vm->DetachCurrentThread(); + } + delete data; + return ret; +} + +ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*) +{ + pthread_t threadHandle; + ThreadData* threadData = new ThreadData(); + threadData->entryPoint = entryPoint; + threadData->arg = data; + + if (pthread_create(&threadHandle, 0, runThreadWithRegistration, static_cast<void*>(threadData))) { + LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data); + return 0; + } + return establishIdentifierForPthreadHandle(threadHandle); +} +#else 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; } return establishIdentifierForPthreadHandle(threadHandle); } +#endif + +void setThreadNameInternal(const char* threadName) +{ +#if PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !PLATFORM(IPHONE) + pthread_setname_np(threadName); +#else + UNUSED_PARAM(threadName); +#endif +} int waitForThreadCompletion(ThreadIdentifier threadID, void** result) { ASSERT(threadID); - + pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID); - + int joinResult = pthread_join(pthreadHandle, result); if (joinResult == EDEADLK) LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID); - + clearPthreadHandleForIdentifier(threadID); return joinResult; } @@ -156,11 +207,11 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result) void detachThread(ThreadIdentifier threadID) { ASSERT(threadID); - + pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID); - + pthread_detach(pthreadHandle); - + clearPthreadHandleForIdentifier(threadID); } @@ -174,7 +225,7 @@ ThreadIdentifier currentThread() bool isMainThread() { -#if PLATFORM(DARWIN) +#if PLATFORM(DARWIN) && !PLATFORM(CHROMIUM) return pthread_main_np(); #else return currentThread() == mainThreadIdentifier; @@ -193,27 +244,82 @@ 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() { int result = pthread_mutex_trylock(&m_mutex); - + 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); +} + + +ReadWriteLock::ReadWriteLock() +{ + pthread_rwlock_init(&m_readWriteLock, NULL); +} + +ReadWriteLock::~ReadWriteLock() +{ + pthread_rwlock_destroy(&m_readWriteLock); +} + +void ReadWriteLock::readLock() +{ + int result = pthread_rwlock_rdlock(&m_readWriteLock); + ASSERT_UNUSED(result, !result); +} + +bool ReadWriteLock::tryReadLock() +{ + int result = pthread_rwlock_tryrdlock(&m_readWriteLock); + + if (result == 0) + return true; + if (result == EBUSY || result == EAGAIN) + return false; + + ASSERT_NOT_REACHED(); + return false; +} + +void ReadWriteLock::writeLock() +{ + int result = pthread_rwlock_wrlock(&m_readWriteLock); + ASSERT_UNUSED(result, !result); +} + +bool ReadWriteLock::tryWriteLock() +{ + int result = pthread_rwlock_trywrlock(&m_readWriteLock); + + if (result == 0) + return true; + if (result == EBUSY || result == EAGAIN) + return false; + + ASSERT_NOT_REACHED(); + return false; +} + +void ReadWriteLock::unlock() +{ + int result = pthread_rwlock_unlock(&m_readWriteLock); + ASSERT_UNUSED(result, !result); } ThreadCondition::ThreadCondition() @@ -228,48 +334,42 @@ 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 secondsToWait) +bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime) { - if (secondsToWait < 0.0) { + if (absoluteTime < currentTime()) + return false; + + if (absoluteTime > INT_MAX) { wait(mutex); return true; } - int intervalSeconds = static_cast<int>(secondsToWait); - int intervalMicroseconds = static_cast<int>((secondsToWait - intervalSeconds) * 1000000.0); - - // Current time comes in sec/microsec - timeval currentTime; - gettimeofday(¤tTime, NULL); + int timeSeconds = static_cast<int>(absoluteTime); + int timeNanoseconds = static_cast<int>((absoluteTime - timeSeconds) * 1E9); - // Target time comes in sec/nanosec timespec targetTime; - targetTime.tv_sec = currentTime.tv_sec + intervalSeconds; - targetTime.tv_nsec = (currentTime.tv_usec + intervalMicroseconds) * 1000; - if (targetTime.tv_nsec > 1000000000) { - targetTime.tv_nsec -= 1000000000; - targetTime.tv_sec++; - } + targetTime.tv_sec = timeSeconds; + targetTime.tv_nsec = timeNanoseconds; return pthread_cond_timedwait(&m_condition, &mutex.impl(), &targetTime) == 0; } 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 #endif // USE(PTHREADS) diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadingWin.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadingWin.cpp index 3626a37..ea18656 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadingWin.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadingWin.cpp @@ -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 @@ -24,40 +25,61 @@ * 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. + */ + +/* + * There are numerous academic and practical works on how to implement pthread_cond_wait/pthread_cond_signal/pthread_cond_broadcast + * functions on Win32. Here is one example: http://www.cs.wustl.edu/~schmidt/win32-cv-1.html which is widely credited as a 'starting point' + * of modern attempts. There are several more or less proven implementations, one in Boost C++ library (http://www.boost.org) and another + * in pthreads-win32 (http://sourceware.org/pthreads-win32/). + * + * The number of articles and discussions is the evidence of significant difficulties in implementing these primitives correctly. + * The brief search of revisions, ChangeLog entries, discussions in comp.programming.threads and other places clearly documents + * numerous pitfalls and performance problems the authors had to overcome to arrive to the suitable implementations. + * Optimally, WebKit would use one of those supported/tested libraries directly. To roll out our own implementation is impractical, + * if even for the lack of sufficient testing. However, a faithful reproduction of the code from one of the popular supported + * libraries seems to be a good compromise. + * + * The early Boost implementation (http://www.boxbackup.org/trac/browser/box/nick/win/lib/win32/boost_1_32_0/libs/thread/src/condition.cpp?rev=30) + * is identical to pthreads-win32 (http://sourceware.org/cgi-bin/cvsweb.cgi/pthreads/pthread_cond_wait.c?rev=1.10&content-type=text/x-cvsweb-markup&cvsroot=pthreads-win32). + * Current Boost uses yet another (although seemingly equivalent) algorithm which came from their 'thread rewrite' effort. * - * ============================================================================= - * Note: The implementation of condition variables under the Windows - * plaform was based on that of the excellent BOOST C++ library. It - * has been rewritten to fit in with the WebKit architecture and to - * use its coding conventions. - * ============================================================================= + * This file includes timedWait/signal/broadcast implementations translated to WebKit coding style from the latest algorithm by + * Alexander Terekhov and Louis Thomas, as captured here: http://sourceware.org/cgi-bin/cvsweb.cgi/pthreads/pthread_cond_wait.c?rev=1.10&content-type=text/x-cvsweb-markup&cvsroot=pthreads-win32 + * It replaces the implementation of their previous algorithm, also documented in the same source above. + * The naming and comments are left very close to original to enable easy cross-check. * - * The Boost license is virtually identical to the Apple variation at the - * top of this file, but is included here for completeness: + * The corresponding Pthreads-win32 License is included below, and CONTRIBUTORS file which it refers to is added to + * source directory (as CONTRIBUTORS.pthreads-win32). + */ + +/* + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors * - * Boost Software License - Version 1.0 - August 17th, 2003 + * Contact Email: rpj@callisto.canberra.edu.au * - * Permission is hereby granted, free of charge, to any person or organization - * obtaining a copy of the software and accompanying documentation covered by - * this license (the "Software") to use, reproduce, display, distribute, - * execute, and transmit the Software, and to prepare derivative works of the - * Software, and to permit third-parties to whom the Software is furnished to - * do so, all subject to the following: + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html * - * The copyright notices in the Software and this entire statement, including - * the above license grant, this restriction and the following disclaimer, - * must be included in all copies of the Software, in whole or in part, and - * all derivative works of the Software, unless such copies or derivative - * works are solely in the form of machine-executable object code generated by - * a source language processor. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT - * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE - * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include "config.h" @@ -69,13 +91,14 @@ #endif #include <process.h> #include <windows.h> +#include <wtf/CurrentTime.h> #include <wtf/HashMap.h> #include <wtf/MathExtras.h> #include <wtf/RandomNumberSeed.h> 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) @@ -87,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 { @@ -134,7 +153,7 @@ void initializeThreading() initializeRandomNumberGenerator(); initializeMainThread(); mainThreadIdentifier = currentThread(); - setThreadName(mainThreadIdentifier, "Main Thread"); + setThreadNameInternal("Main Thread"); } } @@ -197,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); @@ -214,11 +230,11 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result) if (!threadHandle) LOG_ERROR("ThreadIdentifier %u did not correspond to an active thread when trying to quit", threadID); - DWORD joinResult = ::WaitForSingleObject(threadHandle, INFINITE); + DWORD joinResult = WaitForSingleObject(threadHandle, INFINITE); if (joinResult == WAIT_FAILED) LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID); - ::CloseHandle(threadHandle); + CloseHandle(threadHandle); clearThreadHandleForIdentifier(threadID); return joinResult; @@ -227,16 +243,16 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result) void detachThread(ThreadIdentifier threadID) { ASSERT(threadID); - + HANDLE threadHandle = threadHandleForIdentifier(threadID); if (threadHandle) - ::CloseHandle(threadHandle); + CloseHandle(threadHandle); clearThreadHandleForIdentifier(threadID); } ThreadIdentifier currentThread() { - return static_cast<ThreadIdentifier>(::GetCurrentThreadId()); + return static_cast<ThreadIdentifier>(GetCurrentThreadId()); } bool isMainThread() @@ -247,17 +263,17 @@ bool isMainThread() Mutex::Mutex() { m_mutex.m_recursionCount = 0; - ::InitializeCriticalSection(&m_mutex.m_internalMutex); + InitializeCriticalSection(&m_mutex.m_internalMutex); } Mutex::~Mutex() { - ::DeleteCriticalSection(&m_mutex.m_internalMutex); + DeleteCriticalSection(&m_mutex.m_internalMutex); } void Mutex::lock() { - ::EnterCriticalSection(&m_mutex.m_internalMutex); + EnterCriticalSection(&m_mutex.m_internalMutex); ++m_mutex.m_recursionCount; } @@ -269,14 +285,14 @@ bool Mutex::tryLock() // treats this as a successful case, it changes the behavior of several // tests in WebKit that check to see if the current thread already // owned this mutex (see e.g., IconDatabase::getOrCreateIconRecord) - DWORD result = ::TryEnterCriticalSection(&m_mutex.m_internalMutex); + DWORD result = TryEnterCriticalSection(&m_mutex.m_internalMutex); if (result != 0) { // We got the lock // If this thread already had the lock, we must unlock and // return false so that we mimic the behavior of POSIX's // pthread_mutex_trylock: if (m_mutex.m_recursionCount > 0) { - ::LeaveCriticalSection(&m_mutex.m_internalMutex); + LeaveCriticalSection(&m_mutex.m_internalMutex); return false; } @@ -290,183 +306,168 @@ bool Mutex::tryLock() void Mutex::unlock() { --m_mutex.m_recursionCount; - ::LeaveCriticalSection(&m_mutex.m_internalMutex); -} - -static const long MaxSemaphoreCount = static_cast<long>(~0UL >> 1); - -ThreadCondition::ThreadCondition() -{ - m_condition.m_timedOut = 0; - m_condition.m_blocked = 0; - m_condition.m_waitingForRemoval = 0; - m_condition.m_gate = ::CreateSemaphore(0, 1, 1, 0); - m_condition.m_queue = ::CreateSemaphore(0, 0, MaxSemaphoreCount, 0); - m_condition.m_mutex = ::CreateMutex(0, 0, 0); - - if (!m_condition.m_gate || !m_condition.m_queue || !m_condition.m_mutex) { - if (m_condition.m_gate) - ::CloseHandle(m_condition.m_gate); - if (m_condition.m_queue) - ::CloseHandle(m_condition.m_queue); - if (m_condition.m_mutex) - ::CloseHandle(m_condition.m_mutex); - } + LeaveCriticalSection(&m_mutex.m_internalMutex); } -ThreadCondition::~ThreadCondition() -{ - ::CloseHandle(m_condition.m_gate); - ::CloseHandle(m_condition.m_queue); - ::CloseHandle(m_condition.m_mutex); -} - -void ThreadCondition::wait(Mutex& mutex) +bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMilliseconds) { - PlatformMutex& cs = mutex.impl(); - // Enter the wait state. - DWORD res = ::WaitForSingleObject(m_condition.m_gate, INFINITE); + DWORD res = WaitForSingleObject(m_blockLock, INFINITE); ASSERT(res == WAIT_OBJECT_0); - ++m_condition.m_blocked; - res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); + ++m_waitersBlocked; + res = ReleaseSemaphore(m_blockLock, 1, 0); ASSERT(res); - ::LeaveCriticalSection(&cs.m_internalMutex); + LeaveCriticalSection(&mutex.m_internalMutex); - res = ::WaitForSingleObject(m_condition.m_queue, INFINITE); - ASSERT(res == WAIT_OBJECT_0); + // Main wait - use timeout. + bool timedOut = (WaitForSingleObject(m_blockQueue, durationMilliseconds) == WAIT_TIMEOUT); - res = ::WaitForSingleObject(m_condition.m_mutex, INFINITE); + res = WaitForSingleObject(m_unblockLock, INFINITE); ASSERT(res == WAIT_OBJECT_0); - size_t wasWaiting = m_condition.m_waitingForRemoval; - size_t wasTimedOut = m_condition.m_timedOut; - if (wasWaiting != 0) { - if (--m_condition.m_waitingForRemoval == 0) { - if (m_condition.m_blocked != 0) { - res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); // open m_gate - ASSERT(res); - wasWaiting = 0; - } - else if (m_condition.m_timedOut != 0) - m_condition.m_timedOut = 0; - } - } else if (++m_condition.m_timedOut == ((std::numeric_limits<unsigned>::max)() / 2)) { - // timeout occured, normalize the m_condition.m_timedOut count + + int signalsLeft = m_waitersToUnblock; + + if (m_waitersToUnblock) + --m_waitersToUnblock; + else if (++m_waitersGone == (INT_MAX / 2)) { // timeout/canceled or spurious semaphore + // timeout or spurious wakeup occured, normalize the m_waitersGone count // this may occur if many calls to wait with a timeout are made and // no call to notify_* is made - res = ::WaitForSingleObject(m_condition.m_gate, INFINITE); + res = WaitForSingleObject(m_blockLock, INFINITE); ASSERT(res == WAIT_OBJECT_0); - m_condition.m_blocked -= m_condition.m_timedOut; - res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); + m_waitersBlocked -= m_waitersGone; + res = ReleaseSemaphore(m_blockLock, 1, 0); ASSERT(res); - m_condition.m_timedOut = 0; + m_waitersGone = 0; } - res = ::ReleaseMutex(m_condition.m_mutex); + + res = ReleaseMutex(m_unblockLock); ASSERT(res); - if (wasWaiting == 1) { - for (/**/ ; wasTimedOut; --wasTimedOut) { - // better now than spurious later - res = ::WaitForSingleObject(m_condition.m_queue, INFINITE); - ASSERT(res == WAIT_OBJECT_0); - } - res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); + if (signalsLeft == 1) { + res = ReleaseSemaphore(m_blockLock, 1, 0); // Open the gate. ASSERT(res); } - ::EnterCriticalSection (&cs.m_internalMutex); -} + EnterCriticalSection (&mutex.m_internalMutex); -bool ThreadCondition::timedWait(Mutex& mutex, double interval) -{ - // Empty for now - ASSERT(false); - return false; + return !timedOut; } -void ThreadCondition::signal() +void PlatformCondition::signal(bool unblockAll) { - unsigned signals = 0; + unsigned signalsToIssue = 0; - DWORD res = ::WaitForSingleObject(m_condition.m_mutex, INFINITE); + DWORD res = WaitForSingleObject(m_unblockLock, INFINITE); ASSERT(res == WAIT_OBJECT_0); - if (m_condition.m_waitingForRemoval != 0) { // the m_gate is already closed - if (m_condition.m_blocked == 0) { - res = ::ReleaseMutex(m_condition.m_mutex); + if (m_waitersToUnblock) { // the gate is already closed + if (!m_waitersBlocked) { // no-op + res = ReleaseMutex(m_unblockLock); ASSERT(res); return; } - ++m_condition.m_waitingForRemoval; - --m_condition.m_blocked; - - signals = 1; - } else { - res = ::WaitForSingleObject(m_condition.m_gate, INFINITE); + if (unblockAll) { + signalsToIssue = m_waitersBlocked; + m_waitersToUnblock += m_waitersBlocked; + m_waitersBlocked = 0; + } else { + signalsToIssue = 1; + ++m_waitersToUnblock; + --m_waitersBlocked; + } + } else if (m_waitersBlocked > m_waitersGone) { + res = WaitForSingleObject(m_blockLock, INFINITE); // Close the gate. ASSERT(res == WAIT_OBJECT_0); - if (m_condition.m_blocked > m_condition.m_timedOut) { - if (m_condition.m_timedOut != 0) { - m_condition.m_blocked -= m_condition.m_timedOut; - m_condition.m_timedOut = 0; - } - signals = m_condition.m_waitingForRemoval = 1; - --m_condition.m_blocked; + if (m_waitersGone != 0) { + m_waitersBlocked -= m_waitersGone; + m_waitersGone = 0; + } + if (unblockAll) { + signalsToIssue = m_waitersBlocked; + m_waitersToUnblock = m_waitersBlocked; + m_waitersBlocked = 0; } else { - res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); - ASSERT(res); + signalsToIssue = 1; + m_waitersToUnblock = 1; + --m_waitersBlocked; } + } else { // No-op. + res = ReleaseMutex(m_unblockLock); + ASSERT(res); + return; } - res =::ReleaseMutex(m_condition.m_mutex); + res = ReleaseMutex(m_unblockLock); ASSERT(res); - if (signals) { - res = ::ReleaseSemaphore(m_condition.m_queue, signals, 0); + if (signalsToIssue) { + res = ReleaseSemaphore(m_blockQueue, signalsToIssue, 0); ASSERT(res); } } -void ThreadCondition::broadcast() +static const long MaxSemaphoreCount = static_cast<long>(~0UL >> 1); + +ThreadCondition::ThreadCondition() { - unsigned signals = 0; + m_condition.m_waitersGone = 0; + m_condition.m_waitersBlocked = 0; + m_condition.m_waitersToUnblock = 0; + m_condition.m_blockLock = CreateSemaphore(0, 1, 1, 0); + m_condition.m_blockQueue = CreateSemaphore(0, 0, MaxSemaphoreCount, 0); + m_condition.m_unblockLock = CreateMutex(0, 0, 0); + + if (!m_condition.m_blockLock || !m_condition.m_blockQueue || !m_condition.m_unblockLock) { + if (m_condition.m_blockLock) + CloseHandle(m_condition.m_blockLock); + if (m_condition.m_blockQueue) + CloseHandle(m_condition.m_blockQueue); + if (m_condition.m_unblockLock) + CloseHandle(m_condition.m_unblockLock); + } +} - DWORD res = ::WaitForSingleObject(m_condition.m_mutex, INFINITE); - ASSERT(res == WAIT_OBJECT_0); +ThreadCondition::~ThreadCondition() +{ + CloseHandle(m_condition.m_blockLock); + CloseHandle(m_condition.m_blockQueue); + CloseHandle(m_condition.m_unblockLock); +} - if (m_condition.m_waitingForRemoval != 0) { // the m_gate is already closed - if (m_condition.m_blocked == 0) { - res = ::ReleaseMutex(m_condition.m_mutex); - ASSERT(res); - return; - } +void ThreadCondition::wait(Mutex& mutex) +{ + m_condition.timedWait(mutex.impl(), INFINITE); +} - m_condition.m_waitingForRemoval += (signals = m_condition.m_blocked); - m_condition.m_blocked = 0; - } else { - res = ::WaitForSingleObject(m_condition.m_gate, INFINITE); - ASSERT(res == WAIT_OBJECT_0); - if (m_condition.m_blocked > m_condition.m_timedOut) { - if (m_condition.m_timedOut != 0) { - m_condition.m_blocked -= m_condition.m_timedOut; - m_condition.m_timedOut = 0; - } - signals = m_condition.m_waitingForRemoval = m_condition.m_blocked; - m_condition.m_blocked = 0; - } else { - res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); - ASSERT(res); - } - } +bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime) +{ + double currentTime = WTF::currentTime(); - res = ::ReleaseMutex(m_condition.m_mutex); - ASSERT(res); + // Time is in the past - return immediately. + if (absoluteTime < currentTime) + return false; - if (signals) { - res = ::ReleaseSemaphore(m_condition.m_queue, signals, 0); - ASSERT(res); + // 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)); +} + +void ThreadCondition::signal() +{ + m_condition.signal(false); // Unblock only 1 thread. +} + +void ThreadCondition::broadcast() +{ + m_condition.signal(true); // Unblock all threads. } } // namespace WTF diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/TypeTraits.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/TypeTraits.cpp new file mode 100644 index 0000000..36fc6c6 --- /dev/null +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/JavaScriptCore/wtf/TypeTraits.h b/src/3rdparty/webkit/JavaScriptCore/wtf/TypeTraits.h new file mode 100644 index 0000000..6ce6a3e --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/TypeTraits.h @@ -0,0 +1,339 @@ + /* + * 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" + +#if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && (_MSC_VER >= 1600)) +#include <type_traits> +#endif + +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; + }; + +#if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && (_MSC_VER >= 1600)) + + // GCC's libstdc++ 20070724 and later supports C++ TR1 type_traits in the std namespace. + // VC10 (VS2010) and later support C++ TR1 type_traits in the std::tr1 namespace. + template<typename T> struct HasTrivialConstructor : public std::tr1::has_trivial_constructor<T> { }; + template<typename T> struct HasTrivialDestructor : public std::tr1::has_trivial_destructor<T> { }; + +#else + + // This compiler doesn't provide type traits, so we provide basic HasTrivialConstructor + // and HasTrivialDestructor definitions. The definitions here include most built-in + // scalar types but do not include POD structs and classes. For the intended purposes of + // type_traits this results correct but potentially less efficient code. + template <typename T, T v> + struct IntegralConstant { + static const T value = v; + typedef T value_type; + typedef IntegralConstant<T, v> type; + }; + + typedef IntegralConstant<bool, true> true_type; + typedef IntegralConstant<bool, false> false_type; + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + // VC8 (VS2005) and later have built-in compiler support for HasTrivialConstructor / HasTrivialDestructor, + // but for some unexplained reason it doesn't work on built-in types. + template <typename T> struct HasTrivialConstructor : public IntegralConstant<bool, __has_trivial_constructor(T)>{ }; + template <typename T> struct HasTrivialDestructor : public IntegralConstant<bool, __has_trivial_destructor(T)>{ }; +#else + template <typename T> struct HasTrivialConstructor : public false_type{ }; + template <typename T> struct HasTrivialDestructor : public false_type{ }; +#endif + + template <typename T> struct HasTrivialConstructor<T*> : public true_type{ }; + template <typename T> struct HasTrivialDestructor<T*> : public true_type{ }; + + template <> struct HasTrivialConstructor<float> : public true_type{ }; + template <> struct HasTrivialConstructor<const float> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile float> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile float> : public true_type{ }; + + template <> struct HasTrivialConstructor<double> : public true_type{ }; + template <> struct HasTrivialConstructor<const double> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile double> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile double> : public true_type{ }; + + template <> struct HasTrivialConstructor<long double> : public true_type{ }; + template <> struct HasTrivialConstructor<const long double> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile long double> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile long double> : public true_type{ }; + + template <> struct HasTrivialConstructor<unsigned char> : public true_type{ }; + template <> struct HasTrivialConstructor<const unsigned char> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile unsigned char> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile unsigned char> : public true_type{ }; + + template <> struct HasTrivialConstructor<unsigned short> : public true_type{ }; + template <> struct HasTrivialConstructor<const unsigned short> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile unsigned short> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile unsigned short> : public true_type{ }; + + template <> struct HasTrivialConstructor<unsigned int> : public true_type{ }; + template <> struct HasTrivialConstructor<const unsigned int> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile unsigned int> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile unsigned int> : public true_type{ }; + + template <> struct HasTrivialConstructor<unsigned long> : public true_type{ }; + template <> struct HasTrivialConstructor<const unsigned long> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile unsigned long> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile unsigned long> : public true_type{ }; + + template <> struct HasTrivialConstructor<unsigned long long> : public true_type{ }; + template <> struct HasTrivialConstructor<const unsigned long long> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile unsigned long long> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile unsigned long long> : public true_type{ }; + + template <> struct HasTrivialConstructor<signed char> : public true_type{ }; + template <> struct HasTrivialConstructor<const signed char> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile signed char> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile signed char> : public true_type{ }; + + template <> struct HasTrivialConstructor<signed short> : public true_type{ }; + template <> struct HasTrivialConstructor<const signed short> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile signed short> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile signed short> : public true_type{ }; + + template <> struct HasTrivialConstructor<signed int> : public true_type{ }; + template <> struct HasTrivialConstructor<const signed int> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile signed int> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile signed int> : public true_type{ }; + + template <> struct HasTrivialConstructor<signed long> : public true_type{ }; + template <> struct HasTrivialConstructor<const signed long> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile signed long> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile signed long> : public true_type{ }; + + template <> struct HasTrivialConstructor<signed long long> : public true_type{ }; + template <> struct HasTrivialConstructor<const signed long long> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile signed long long> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile signed long long> : public true_type{ }; + + template <> struct HasTrivialConstructor<bool> : public true_type{ }; + template <> struct HasTrivialConstructor<const bool> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile bool> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile bool> : public true_type{ }; + + template <> struct HasTrivialConstructor<char> : public true_type{ }; + template <> struct HasTrivialConstructor<const char> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile char> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile char> : public true_type{ }; + + #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) + template <> struct HasTrivialConstructor<wchar_t> : public true_type{ }; + template <> struct HasTrivialConstructor<const wchar_t> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile wchar_t> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile wchar_t> : public true_type{ }; + #endif + + template <> struct HasTrivialDestructor<float> : public true_type{ }; + template <> struct HasTrivialDestructor<const float> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile float> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile float> : public true_type{ }; + + template <> struct HasTrivialDestructor<double> : public true_type{ }; + template <> struct HasTrivialDestructor<const double> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile double> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile double> : public true_type{ }; + + template <> struct HasTrivialDestructor<long double> : public true_type{ }; + template <> struct HasTrivialDestructor<const long double> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile long double> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile long double> : public true_type{ }; + + template <> struct HasTrivialDestructor<unsigned char> : public true_type{ }; + template <> struct HasTrivialDestructor<const unsigned char> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile unsigned char> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile unsigned char> : public true_type{ }; + + template <> struct HasTrivialDestructor<unsigned short> : public true_type{ }; + template <> struct HasTrivialDestructor<const unsigned short> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile unsigned short> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile unsigned short> : public true_type{ }; + + template <> struct HasTrivialDestructor<unsigned int> : public true_type{ }; + template <> struct HasTrivialDestructor<const unsigned int> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile unsigned int> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile unsigned int> : public true_type{ }; + + template <> struct HasTrivialDestructor<unsigned long> : public true_type{ }; + template <> struct HasTrivialDestructor<const unsigned long> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile unsigned long> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile unsigned long> : public true_type{ }; + + template <> struct HasTrivialDestructor<unsigned long long> : public true_type{ }; + template <> struct HasTrivialDestructor<const unsigned long long> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile unsigned long long> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile unsigned long long> : public true_type{ }; + + template <> struct HasTrivialDestructor<signed char> : public true_type{ }; + template <> struct HasTrivialDestructor<const signed char> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile signed char> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile signed char> : public true_type{ }; + + template <> struct HasTrivialDestructor<signed short> : public true_type{ }; + template <> struct HasTrivialDestructor<const signed short> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile signed short> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile signed short> : public true_type{ }; + + template <> struct HasTrivialDestructor<signed int> : public true_type{ }; + template <> struct HasTrivialDestructor<const signed int> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile signed int> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile signed int> : public true_type{ }; + + template <> struct HasTrivialDestructor<signed long> : public true_type{ }; + template <> struct HasTrivialDestructor<const signed long> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile signed long> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile signed long> : public true_type{ }; + + template <> struct HasTrivialDestructor<signed long long> : public true_type{ }; + template <> struct HasTrivialDestructor<const signed long long> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile signed long long> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile signed long long> : public true_type{ }; + + template <> struct HasTrivialDestructor<bool> : public true_type{ }; + template <> struct HasTrivialDestructor<const bool> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile bool> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile bool> : public true_type{ }; + + template <> struct HasTrivialDestructor<char> : public true_type{ }; + template <> struct HasTrivialDestructor<const char> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile char> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile char> : public true_type{ }; + + #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) + template <> struct HasTrivialDestructor<wchar_t> : public true_type{ }; + template <> struct HasTrivialDestructor<const wchar_t> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile wchar_t> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile wchar_t> : public true_type{ }; + #endif + +#endif // __GLIBCXX__, etc. + +} // namespace WTF + +#endif // TypeTraits_h diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/VMTags.h b/src/3rdparty/webkit/JavaScriptCore/wtf/VMTags.h new file mode 100644 index 0000000..519f518 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/VMTags.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 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 + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 VMTags_h +#define VMTags_h + +#include <wtf/Platform.h> + +// On Mac OS X, the VM subsystem allows tagging memory requested from mmap and vm_map +// in order to aid tools that inspect system memory use. +#if PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER) + +#include <mach/vm_statistics.h> + +#if defined(VM_MEMORY_JAVASCRIPT_CORE) && defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) +#define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_CORE) +#define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) +#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) +#else +#define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(63) +#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY VM_MAKE_TAG(64) +#define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(65) +#endif // defined(VM_MEMORY_JAVASCRIPT_CORE) && defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) + +#else // PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER) + +#define VM_TAG_FOR_COLLECTOR_MEMORY -1 +#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY -1 +#define VM_TAG_FOR_REGISTERFILE_MEMORY -1 + +#endif // PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER) + +#endif // VMTags_h diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/Vector.h b/src/3rdparty/webkit/JavaScriptCore/wtf/Vector.h index 880b45d..c378fd0 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/Vector.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/Vector.h @@ -21,16 +21,17 @@ #ifndef WTF_Vector_h #define WTF_Vector_h -#include "Assertions.h" -#include "FastMalloc.h" +#include "FastAllocBase.h" #include "Noncopyable.h" #include "NotFound.h" #include "VectorTraits.h" #include <limits> -#include <stdlib.h> -#include <string.h> #include <utility> +#if PLATFORM(QT) +#include <QDataStream> +#endif + namespace WTF { using std::min; @@ -377,7 +378,8 @@ namespace WTF { VectorBuffer(size_t capacity) : Base(inlineBuffer(), inlineCapacity) { - allocateBuffer(capacity); + if (capacity > inlineCapacity) + Base::allocateBuffer(capacity); } ~VectorBuffer() @@ -389,6 +391,10 @@ namespace WTF { { if (newCapacity > inlineCapacity) Base::allocateBuffer(newCapacity); + else { + m_buffer = inlineBuffer(); + m_capacity = inlineCapacity; + } } void deallocateBuffer(T* bufferToDeallocate) @@ -428,7 +434,7 @@ namespace WTF { }; template<typename T, size_t inlineCapacity = 0> - class Vector { + class Vector : public FastAllocBase { private: typedef VectorBuffer<T, inlineCapacity> Buffer; typedef VectorTypeOperations<T> TypeOperations; @@ -503,6 +509,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()); } @@ -560,6 +567,32 @@ namespace WTF { Buffer m_buffer; }; +#if PLATFORM(QT) + template<typename T> + QDataStream& operator<<(QDataStream& stream, const Vector<T>& data) + { + stream << qint64(data.size()); + foreach (const T& i, data) + stream << i; + return stream; + } + + template<typename T> + QDataStream& operator>>(QDataStream& stream, Vector<T>& data) + { + data.clear(); + qint64 count; + T item; + stream >> count; + data.reserveCapacity(count); + for (qint64 i = 0; i < count; ++i) { + stream >> item; + data.append(item); + } + return stream; + } +#endif + template<typename T, size_t inlineCapacity> Vector<T, inlineCapacity>::Vector(const Vector& other) : m_size(other.size()) @@ -686,7 +719,7 @@ namespace WTF { } template<typename T, size_t inlineCapacity> - void Vector<T, inlineCapacity>::resize(size_t size) + inline void Vector<T, inlineCapacity>::resize(size_t size) { if (size <= m_size) TypeOperations::destruct(begin() + size, end()); @@ -733,6 +766,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()) @@ -766,6 +808,8 @@ namespace WTF { if (!begin()) return; } + if (newSize < m_size) + CRASH(); T* dest = end(); for (size_t i = 0; i < dataSize; ++i) new (&dest[i]) T(data[i]); @@ -773,7 +817,7 @@ namespace WTF { } template<typename T, size_t inlineCapacity> template<typename U> - inline void Vector<T, inlineCapacity>::append(const U& val) + ALWAYS_INLINE void Vector<T, inlineCapacity>::append(const U& val) { const U* ptr = &val; if (size() == capacity()) { @@ -827,6 +871,8 @@ namespace WTF { if (!begin()) return; } + if (newSize < m_size) + CRASH(); T* spot = begin() + position; TypeOperations::moveOverlapping(spot, end(), spot + dataSize); for (size_t i = 0; i < dataSize; ++i) diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/VectorTraits.h b/src/3rdparty/webkit/JavaScriptCore/wtf/VectorTraits.h index 6efe36c..7974b9a 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/VectorTraits.h +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/JavaScriptCore/wtf/dtoa.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/dtoa.cpp index adbb115..9509388 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/dtoa.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/dtoa.cpp @@ -150,6 +150,8 @@ #include <wtf/FastMalloc.h> #include <wtf/Threading.h> +#include <stdio.h> + #if COMPILER(MSVC) #pragma warning(disable: 4244) #pragma warning(disable: 4245) @@ -189,13 +191,13 @@ typedef union { double d; uint32_t L[2]; } U; #endif #else #ifdef IEEE_8087 -#define word0(x) ((U*)&x)->L[1] -#define word1(x) ((U*)&x)->L[0] +#define word0(x) (x)->L[1] +#define word1(x) (x)->L[0] #else -#define word0(x) ((U*)&x)->L[0] -#define word1(x) ((U*)&x)->L[1] +#define word0(x) (x)->L[0] +#define word1(x) (x)->L[1] #endif -#define dval(x) ((U*)&x)->d +#define dval(x) (x)->d #endif /* The following definition of Storeinc is appropriate for MIPS processors. @@ -275,32 +277,29 @@ typedef union { double d; uint32_t L[2]; } U; #define Kmax 15 -struct Bigint { - struct Bigint* next; - int k, maxwds, sign, wds; - uint32_t x[1]; -}; - -static Bigint* Balloc(int k) -{ - int x = 1 << k; - Bigint* rv = (Bigint*)fastMalloc(sizeof(Bigint) + (x - 1)*sizeof(uint32_t)); - rv->k = k; - rv->maxwds = x; - rv->next = 0; - rv->sign = rv->wds = 0; - - return rv; -} - -static void Bfree(Bigint* v) -{ - fastFree(v); -} +struct BigInt { + BigInt() : sign(0), wds(0) { } + BigInt(const BigInt& other) : sign(other.sign), wds(other.wds) + { + for (int i = 0; i < 64; ++i) + x[i] = other.x[i]; + } -#define Bcopy(x, y) memcpy((char*)&x->sign, (char*)&y->sign, y->wds * sizeof(int32_t) + 2 * sizeof(int)) + BigInt& operator=(const BigInt& other) + { + sign = other.sign; + wds = other.wds; + for (int i = 0; i < 64; ++i) + x[i] = other.x[i]; + return *this; + } + + int sign; + int wds; + uint32_t x[64]; +}; -static Bigint* multadd(Bigint* b, int m, int a) /* multiply by m and add a */ +static void multadd(BigInt& b, int m, int a) /* multiply by m and add a */ { #ifdef USE_LONG_LONG unsigned long long carry; @@ -308,8 +307,8 @@ static Bigint* multadd(Bigint* b, int m, int a) /* multiply by m and add a */ uint32_t carry; #endif - int wds = b->wds; - uint32_t* x = b->x; + int wds = b.wds; + uint32_t* x = b.x; int i = 0; carry = a; do { @@ -333,19 +332,12 @@ static Bigint* multadd(Bigint* b, int m, int a) /* multiply by m and add a */ } while (++i < wds); if (carry) { - if (wds >= b->maxwds) { - Bigint* b1 = Balloc(b->k + 1); - Bcopy(b1, b); - Bfree(b); - b = b1; - } - b->x[wds++] = (uint32_t)carry; - b->wds = wds; + b.x[wds++] = (uint32_t)carry; + b.wds = wds; } - return b; } -static Bigint* s2b(const char* s, int nd0, int nd, uint32_t y9) +static void s2b(BigInt& b, const char* s, int nd0, int nd, uint32_t y9) { int k; int32_t y; @@ -353,27 +345,26 @@ static Bigint* s2b(const char* s, int nd0, int nd, uint32_t y9) for (k = 0, y = 1; x > y; y <<= 1, k++) { } #ifdef Pack_32 - Bigint* b = Balloc(k); - b->x[0] = y9; - b->wds = 1; + b.sign = 0; + b.x[0] = y9; + b.wds = 1; #else - Bigint* b = Balloc(k + 1); - b->x[0] = y9 & 0xffff; - b->wds = (b->x[1] = y9 >> 16) ? 2 : 1; + b.sign = 0; + b.x[0] = y9 & 0xffff; + b.wds = (b->x[1] = y9 >> 16) ? 2 : 1; #endif int i = 9; if (9 < nd0) { s += 9; do { - b = multadd(b, 10, *s++ - '0'); + multadd(b, 10, *s++ - '0'); } while (++i < nd0); s++; } else s += 10; for (; i < nd; i++) - b = multadd(b, 10, *s++ - '0'); - return b; + multadd(b, 10, *s++ - '0'); } static int hi0bits(uint32_t x) @@ -446,21 +437,21 @@ static int lo0bits (uint32_t* y) return k; } -static Bigint* i2b(int i) +static void i2b(BigInt& b, int i) { - Bigint* b; - - b = Balloc(1); - b->x[0] = i; - b->wds = 1; - return b; + b.sign = 0; + b.x[0] = i; + b.wds = 1; } -static Bigint* mult(Bigint* a, Bigint* b) +static void mult(BigInt& aRef, const BigInt& bRef) { - Bigint* c; - int k, wa, wb, wc; - uint32_t *x, *xa, *xae, *xb, *xbe, *xc, *xc0; + const BigInt* a = &aRef; + const BigInt* b = &bRef; + BigInt c; + int wa, wb, wc; + const uint32_t *x = 0, *xa, *xb, *xae, *xbe; + uint32_t *xc, *xc0; uint32_t y; #ifdef USE_LONG_LONG unsigned long long carry, z; @@ -469,24 +460,22 @@ static Bigint* mult(Bigint* a, Bigint* b) #endif if (a->wds < b->wds) { - c = a; + const BigInt* tmp = a; a = b; - b = c; + b = tmp; } - k = a->k; + wa = a->wds; wb = b->wds; wc = wa + wb; - if (wc > a->maxwds) - k++; - c = Balloc(k); - for (x = c->x, xa = x + wc; x < xa; x++) - *x = 0; + + for (xc = c.x, xa = xc + wc; xc < xa; xc++) + *xc = 0; xa = a->x; xae = xa + wa; xb = b->x; xbe = xb + wb; - xc0 = c->x; + xc0 = c.x; #ifdef USE_LONG_LONG for (; xb < xbe; xc0++) { if ((y = *xb++)) { @@ -548,33 +537,43 @@ static Bigint* mult(Bigint* a, Bigint* b) } #endif #endif - for (xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) { } - c->wds = wc; - return c; + for (xc0 = c.x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) { } + c.wds = wc; + aRef = c; } -static Bigint* p5s; +struct P5Node { + BigInt val; + P5Node* next; +}; + +static P5Node* p5s; static int p5s_count; -static Bigint* pow5mult(Bigint* b, int k) +static ALWAYS_INLINE void pow5mult(BigInt& b, int k) { static int p05[3] = { 5, 25, 125 }; if (int i = k & 3) - b = multadd(b, p05[i - 1], 0); + multadd(b, p05[i - 1], 0); if (!(k >>= 2)) - return b; + return; #if ENABLE(JSC_MULTIPLE_THREADS) s_dtoaP5Mutex->lock(); #endif - Bigint* p5 = p5s; + P5Node* p5 = p5s; + if (!p5) { /* first time */ - p5 = p5s = i2b(625); + p5 = new P5Node; + i2b(p5->val, 625); + p5->next = 0; + p5s = p5; p5s_count = 1; } + int p5s_count_local = p5s_count; #if ENABLE(JSC_MULTIPLE_THREADS) s_dtoaP5Mutex->unlock(); @@ -582,11 +581,9 @@ static Bigint* pow5mult(Bigint* b, int k) int p5s_used = 0; for (;;) { - if (k & 1) { - Bigint* b1 = mult(b, p5); - Bfree(b); - b = b1; - } + if (k & 1) + mult(b, p5->val); + if (!(k >>= 1)) break; @@ -596,7 +593,10 @@ static Bigint* pow5mult(Bigint* b, int k) #endif if (p5s_used == p5s_count) { ASSERT(!p5->next); - p5->next = mult(p5, p5); + p5->next = new P5Node; + p5->next->next = 0; + p5->next->val = p5->val; + mult(p5->next->val, p5->next->val); ++p5s_count; } @@ -607,30 +607,21 @@ static Bigint* pow5mult(Bigint* b, int k) } p5 = p5->next; } - - return b; } -static Bigint* lshift(Bigint* b, int k) +static ALWAYS_INLINE void lshift(BigInt& b, int k) { - Bigint* result = b; - #ifdef Pack_32 int n = k >> 5; #else int n = k >> 4; #endif - int k1 = b->k; - int n1 = n + b->wds + 1; - for (int i = b->maxwds; n1 > i; i <<= 1) - k1++; - if (b->k < k1) - result = Balloc(k1); + int n1 = n + b.wds + 1; - const uint32_t* srcStart = b->x; - uint32_t* dstStart = result->x; - const uint32_t* src = srcStart + b->wds - 1; + const uint32_t* srcStart = b.x; + uint32_t* dstStart = b.x; + const uint32_t* src = srcStart + b.wds - 1; uint32_t* dst = dstStart + n1 - 1; #ifdef Pack_32 if (k &= 0x1f) { @@ -642,7 +633,7 @@ static Bigint* lshift(Bigint* b, int k) } *dst = hiSubword; ASSERT(dst == dstStart + n); - result->wds = b->wds + n + (result->x[n1 - 1] != 0); + b.wds = b.wds + n + (b.x[n1 - 1] != 0); } #else if (k &= 0xf) { @@ -661,30 +652,26 @@ static Bigint* lshift(Bigint* b, int k) do { *--dst = *src--; } while (src >= srcStart); - result->wds = b->wds + n; + b.wds = b.wds + n; } for (dst = dstStart + n; dst != dstStart; ) *--dst = 0; - - if (result != b) - Bfree(b); - return result; } -static int cmp(Bigint* a, Bigint* b) +static int cmp(const BigInt& a, const BigInt& b) { - uint32_t *xa, *xa0, *xb, *xb0; + const uint32_t *xa, *xa0, *xb, *xb0; int i, j; - i = a->wds; - j = b->wds; - ASSERT(i <= 1 || a->x[i - 1]); - ASSERT(j <= 1 || b->x[j - 1]); + i = a.wds; + j = b.wds; + ASSERT(i <= 1 || a.x[i - 1]); + ASSERT(j <= 1 || b.x[j - 1]); if (i -= j) return i; - xa0 = a->x; + xa0 = a.x; xa = xa0 + j; - xb0 = b->x; + xb0 = b.x; xb = xb0 + j; for (;;) { if (*--xa != *--xb) @@ -695,35 +682,37 @@ static int cmp(Bigint* a, Bigint* b) return 0; } -static Bigint* diff(Bigint* a, Bigint* b) +static ALWAYS_INLINE void diff(BigInt& c, const BigInt& aRef, const BigInt& bRef) { - Bigint* c; + const BigInt* a = &aRef; + const BigInt* b = &bRef; int i, wa, wb; - uint32_t *xa, *xae, *xb, *xbe, *xc; + uint32_t *xc; - i = cmp(a,b); + i = cmp(*a, *b); if (!i) { - c = Balloc(0); - c->wds = 1; - c->x[0] = 0; - return c; + c.sign = 0; + c.wds = 1; + c.x[0] = 0; + return; } if (i < 0) { - c = a; + const BigInt* tmp = a; a = b; - b = c; + b = tmp; i = 1; } else i = 0; - c = Balloc(a->k); - c->sign = i; + + c.wds = 0; + c.sign = i; wa = a->wds; - xa = a->x; - xae = xa + wa; + const uint32_t* xa = a->x; + const uint32_t* xae = xa + wa; wb = b->wds; - xb = b->x; - xbe = xb + wb; - xc = c->x; + const uint32_t* xb = b->x; + const uint32_t* xbe = xb + wb; + xc = c.x; #ifdef USE_LONG_LONG unsigned long long borrow = 0; do { @@ -768,14 +757,13 @@ static Bigint* diff(Bigint* a, Bigint* b) #endif while (!*--xc) wa--; - c->wds = wa; - return c; + c.wds = wa; } -static double ulp(double x) +static double ulp(U *x) { register int32_t L; - double a; + U u; L = (word0(x) & Exp_mask) - (P - 1) * Exp_msk1; #ifndef Avoid_Underflow @@ -783,57 +771,57 @@ static double ulp(double x) if (L > 0) { #endif #endif - word0(a) = L; - word1(a) = 0; + word0(&u) = L; + word1(&u) = 0; #ifndef Avoid_Underflow #ifndef Sudden_Underflow } else { L = -L >> Exp_shift; if (L < Exp_shift) { - word0(a) = 0x80000 >> L; - word1(a) = 0; + word0(&u) = 0x80000 >> L; + word1(&u) = 0; } else { - word0(a) = 0; + word0(&u) = 0; L -= Exp_shift; - word1(a) = L >= 31 ? 1 : 1 << 31 - L; + word1(&u) = L >= 31 ? 1 : 1 << 31 - L; } } #endif #endif - return dval(a); + return dval(&u); } -static double b2d(Bigint* a, int* e) +static double b2d(const BigInt& a, int* e) { - uint32_t* xa; - uint32_t* xa0; + const uint32_t* xa; + const uint32_t* xa0; uint32_t w; uint32_t y; uint32_t z; int k; - double d; + U d; -#define d0 word0(d) -#define d1 word1(d) +#define d0 word0(&d) +#define d1 word1(&d) - xa0 = a->x; - xa = xa0 + a->wds; + xa0 = a.x; + xa = xa0 + a.wds; y = *--xa; ASSERT(y); k = hi0bits(y); *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; @@ -857,12 +845,11 @@ static double b2d(Bigint* a, int* e) ret_d: #undef d0 #undef d1 - return dval(d); + return dval(&d); } -static Bigint* d2b(double d, int* e, int* bits) +static ALWAYS_INLINE void d2b(BigInt& b, U* d, int* e, int* bits) { - Bigint* b; int de, k; uint32_t *x, y, z; #ifndef Sudden_Underflow @@ -871,12 +858,13 @@ static Bigint* d2b(double d, int* e, int* bits) #define d0 word0(d) #define d1 word1(d) + b.sign = 0; #ifdef Pack_32 - b = Balloc(1); + b.wds = 1; #else - b = Balloc(2); + b.wds = 2; #endif - x = b->x; + x = b.x; z = d0 & Frac_mask; d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ @@ -889,21 +877,21 @@ 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; #ifndef Sudden_Underflow i = #endif - b->wds = (x[1] = z) ? 2 : 1; + b.wds = (x[1] = z) ? 2 : 1; } else { k = lo0bits(&z); x[0] = z; #ifndef Sudden_Underflow i = #endif - b->wds = 1; + b.wds = 1; k += 32; } #else @@ -958,30 +946,29 @@ static Bigint* d2b(double d, int* e, int* bits) #endif } #endif - return b; } #undef d0 #undef d1 -static double ratio(Bigint* a, Bigint* b) +static double ratio(const BigInt& a, const BigInt& b) { - double da, db; + U da, db; int k, ka, kb; - dval(da) = b2d(a, &ka); - dval(db) = b2d(b, &kb); + dval(&da) = b2d(a, &ka); + dval(&db) = b2d(b, &kb); #ifdef Pack_32 - k = ka - kb + 32 * (a->wds - b->wds); + k = ka - kb + 32 * (a.wds - b.wds); #else - k = ka - kb + 16 * (a->wds - b->wds); + k = ka - kb + 16 * (a.wds - b.wds); #endif if (k > 0) - word0(da) += k * Exp_msk1; + word0(&da) += k * Exp_msk1; else { k = -k; - word0(db) += k * Exp_msk1; + word0(&db) += k * Exp_msk1; } - return dval(da) / dval(db); + return dval(&da) / dval(&db); } static const double tens[] = { @@ -1031,7 +1018,7 @@ static int match(const char** sp, const char* t) } #ifndef No_Hex_NaN -static void hexnan(double* rvp, const char** sp) +static void hexnan(U* rvp, const char** sp) { uint32_t c, x[2]; const char* s; @@ -1070,8 +1057,8 @@ static void hexnan(double* rvp, const char** sp) x[1] = (x[1] << 4) | c; } if ((x[0] &= 0xfffff) || x[1]) { - word0(*rvp) = Exp_mask | x[0]; - word1(*rvp) = x[1]; + word0(rvp) = Exp_mask | x[0]; + word1(rvp) = x[1]; } } #endif /*No_Hex_NaN*/ @@ -1085,16 +1072,17 @@ double strtod(const char* s00, char** se) int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; const char *s, *s0, *s1; - double aadj, aadj1, adj, rv, rv0; + double aadj, aadj1; + U aadj2, adj, rv, rv0; int32_t L; uint32_t y, z; - Bigint *bb = NULL, *bb1 = NULL, *bd = NULL, *bd0 = NULL, *bs = NULL, *delta = NULL; + BigInt bb, bb1, bd, bd0, bs, delta; #ifdef SET_INEXACT int inexact, oldinexact; #endif sign = nz0 = nz = 0; - dval(rv) = 0.; + dval(&rv) = 0; for (s = s00; ; s++) switch (*s) { case '-': @@ -1209,16 +1197,16 @@ dig_done: --s; if (!match(&s,"inity")) ++s; - word0(rv) = 0x7ff00000; - word1(rv) = 0; + word0(&rv) = 0x7ff00000; + word1(&rv) = 0; goto ret; } break; case 'n': case 'N': if (match(&s, "an")) { - word0(rv) = NAN_WORD0; - word1(rv) = NAN_WORD1; + word0(&rv) = NAN_WORD0; + word1(&rv) = NAN_WORD1; #ifndef No_Hex_NaN if (*s == '(') /*)*/ hexnan(&rv, &s); @@ -1243,21 +1231,20 @@ ret0: if (!nd0) nd0 = nd; k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; - dval(rv) = y; + dval(&rv) = y; if (k > 9) { #ifdef SET_INEXACT if (k > DBL_DIG) oldinexact = get_inexact(); #endif - dval(rv) = tens[k - 9] * dval(rv) + z; + dval(&rv) = tens[k - 9] * dval(&rv) + z; } - bd0 = 0; if (nd <= DBL_DIG && Flt_Rounds == 1) { if (!e) goto ret; if (e > 0) { if (e <= Ten_pmax) { - /* rv = */ rounded_product(dval(rv), tens[e]); + /* rv = */ rounded_product(dval(&rv), tens[e]); goto ret; } i = DBL_DIG - nd; @@ -1266,14 +1253,14 @@ ret0: * this for larger i values. */ e -= i; - dval(rv) *= tens[i]; - /* rv = */ rounded_product(dval(rv), tens[e]); + dval(&rv) *= tens[i]; + /* rv = */ rounded_product(dval(&rv), tens[e]); goto ret; } } #ifndef Inaccurate_Divide else if (e >= -Ten_pmax) { - /* rv = */ rounded_quotient(dval(rv), tens[-e]); + /* rv = */ rounded_quotient(dval(&rv), tens[-e]); goto ret; } #endif @@ -1293,7 +1280,7 @@ ret0: if (e1 > 0) { if ((i = e1 & 15)) - dval(rv) *= tens[i]; + dval(&rv) *= tens[i]; if (e1 &= ~15) { if (e1 > DBL_MAX_10_EXP) { ovfl: @@ -1301,38 +1288,36 @@ ovfl: errno = ERANGE; #endif /* Can't trust HUGE_VAL */ - word0(rv) = Exp_mask; - word1(rv) = 0; + word0(&rv) = Exp_mask; + word1(&rv) = 0; #ifdef SET_INEXACT /* set overflow bit */ - dval(rv0) = 1e300; - dval(rv0) *= dval(rv0); + dval(&rv0) = 1e300; + dval(&rv0) *= dval(&rv0); #endif - if (bd0) - goto retfree; goto ret; } e1 >>= 4; for (j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) - dval(rv) *= bigtens[j]; + dval(&rv) *= bigtens[j]; /* The last multiplication could overflow. */ - word0(rv) -= P * Exp_msk1; - dval(rv) *= bigtens[j]; - if ((z = word0(rv) & Exp_mask) > Exp_msk1 * (DBL_MAX_EXP + Bias - P)) + word0(&rv) -= P * Exp_msk1; + dval(&rv) *= bigtens[j]; + if ((z = word0(&rv) & Exp_mask) > Exp_msk1 * (DBL_MAX_EXP + Bias - P)) goto ovfl; if (z > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P)) { /* set to largest number */ /* (Can't trust DBL_MAX) */ - word0(rv) = Big0; - word1(rv) = Big1; + word0(&rv) = Big0; + word1(&rv) = Big1; } else - word0(rv) += P * Exp_msk1; + word0(&rv) += P * Exp_msk1; } } else if (e1 < 0) { e1 = -e1; if ((i = e1 & 15)) - dval(rv) /= tens[i]; + dval(&rv) /= tens[i]; if (e1 >>= 4) { if (e1 >= 1 << n_bigtens) goto undfl; @@ -1341,42 +1326,40 @@ ovfl: scale = 2 * P; for (j = 0; e1 > 0; j++, e1 >>= 1) if (e1 & 1) - dval(rv) *= tinytens[j]; - if (scale && (j = (2 * P) + 1 - ((word0(rv) & Exp_mask) >> Exp_shift)) > 0) { + dval(&rv) *= tinytens[j]; + if (scale && (j = (2 * P) + 1 - ((word0(&rv) & Exp_mask) >> Exp_shift)) > 0) { /* scaled rv is denormal; zap j low bits */ if (j >= 32) { - word1(rv) = 0; + word1(&rv) = 0; if (j >= 53) - word0(rv) = (P + 2) * Exp_msk1; + word0(&rv) = (P + 2) * Exp_msk1; else - word0(rv) &= 0xffffffff << j - 32; + word0(&rv) &= 0xffffffff << (j - 32); } else - word1(rv) &= 0xffffffff << j; + word1(&rv) &= 0xffffffff << j; } #else for (j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) - dval(rv) *= tinytens[j]; + dval(&rv) *= tinytens[j]; /* The last multiplication could underflow. */ - dval(rv0) = dval(rv); - dval(rv) *= tinytens[j]; - if (!dval(rv)) { - dval(rv) = 2. * dval(rv0); - dval(rv) *= tinytens[j]; + dval(&rv0) = dval(&rv); + dval(&rv) *= tinytens[j]; + if (!dval(&rv)) { + dval(&rv) = 2. * dval(&rv0); + dval(&rv) *= tinytens[j]; #endif - if (!dval(rv)) { + if (!dval(&rv)) { undfl: - dval(rv) = 0.; + dval(&rv) = 0.; #ifndef NO_ERRNO errno = ERANGE; #endif - if (bd0) - goto retfree; goto ret; } #ifndef Avoid_Underflow - word0(rv) = Tiny0; - word1(rv) = Tiny1; + word0(&rv) = Tiny0; + word1(&rv) = Tiny1; /* The refinement below will clean * this approximation up. */ @@ -1389,13 +1372,12 @@ undfl: /* Put digits into bd: true value = bd * 10^e */ - bd0 = s2b(s0, nd0, nd, y); + s2b(bd0, s0, nd0, nd, y); for (;;) { - bd = Balloc(bd0->k); - Bcopy(bd, bd0); - bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */ - bs = i2b(1); + bd = bd0; + d2b(bb, &rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ + i2b(bs, 1); if (e >= 0) { bb2 = bb5 = 0; @@ -1442,33 +1424,31 @@ undfl: bs2 -= i; } if (bb5 > 0) { - bs = pow5mult(bs, bb5); - bb1 = mult(bs, bb); - Bfree(bb); - bb = bb1; + pow5mult(bs, bb5); + mult(bb, bs); } if (bb2 > 0) - bb = lshift(bb, bb2); + lshift(bb, bb2); if (bd5 > 0) - bd = pow5mult(bd, bd5); + pow5mult(bd, bd5); if (bd2 > 0) - bd = lshift(bd, bd2); + lshift(bd, bd2); if (bs2 > 0) - bs = lshift(bs, bs2); - delta = diff(bb, bd); - dsign = delta->sign; - delta->sign = 0; + lshift(bs, bs2); + diff(delta, bb, bd); + dsign = delta.sign; + delta.sign = 0; i = cmp(delta, bs); if (i < 0) { /* Error is less than half an ulp -- check for * special case of mantissa a power of two. */ - if (dsign || word1(rv) || word0(rv) & Bndry_mask + if (dsign || word1(&rv) || word0(&rv) & Bndry_mask #ifdef Avoid_Underflow - || (word0(rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1 + || (word0(&rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1 #else - || (word0(rv) & Exp_mask) <= Exp_msk1 + || (word0(&rv) & Exp_mask) <= Exp_msk1 #endif ) { #ifdef SET_INEXACT @@ -1477,14 +1457,14 @@ undfl: #endif break; } - if (!delta->x[0] && delta->wds <= 1) { + if (!delta.x[0] && delta.wds <= 1) { /* exact result */ #ifdef SET_INEXACT inexact = 0; #endif break; } - delta = lshift(delta,Log2P); + lshift(delta, Log2P); if (cmp(delta, bs) > 0) goto drop_down; break; @@ -1492,26 +1472,26 @@ undfl: if (i == 0) { /* exactly half-way between */ if (dsign) { - if ((word0(rv) & Bndry_mask1) == Bndry_mask1 - && word1(rv) == ( + if ((word0(&rv) & Bndry_mask1) == Bndry_mask1 + && word1(&rv) == ( #ifdef Avoid_Underflow - (scale && (y = word0(rv) & Exp_mask) <= 2 * P * Exp_msk1) + (scale && (y = word0(&rv) & Exp_mask) <= 2 * P * Exp_msk1) ? (0xffffffff & (0xffffffff << (2 * P + 1 - (y >> Exp_shift)))) : #endif 0xffffffff)) { /*boundary case -- increment exponent*/ - word0(rv) = (word0(rv) & Exp_mask) + Exp_msk1; - word1(rv) = 0; + word0(&rv) = (word0(&rv) & Exp_mask) + Exp_msk1; + word1(&rv) = 0; #ifdef Avoid_Underflow dsign = 0; #endif break; } - } else if (!(word0(rv) & Bndry_mask) && !word1(rv)) { + } else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) { drop_down: /* boundary case -- decrement exponent */ #ifdef Sudden_Underflow /*{{*/ - L = word0(rv) & Exp_mask; + L = word0(&rv) & Exp_mask; #ifdef Avoid_Underflow if (L <= (scale ? (2 * P + 1) * Exp_msk1 : Exp_msk1)) #else @@ -1522,7 +1502,7 @@ drop_down: #else /*Sudden_Underflow}{*/ #ifdef Avoid_Underflow if (scale) { - L = word0(rv) & Exp_mask; + L = word0(&rv) & Exp_mask; if (L <= (2 * P + 1) * Exp_msk1) { if (L > (P + 2) * Exp_msk1) /* round even ==> */ @@ -1533,20 +1513,20 @@ drop_down: } } #endif /*Avoid_Underflow*/ - L = (word0(rv) & Exp_mask) - Exp_msk1; + L = (word0(&rv) & Exp_mask) - Exp_msk1; #endif /*Sudden_Underflow}}*/ - word0(rv) = L | Bndry_mask1; - word1(rv) = 0xffffffff; + word0(&rv) = L | Bndry_mask1; + word1(&rv) = 0xffffffff; break; } - if (!(word1(rv) & LSB)) + if (!(word1(&rv) & LSB)) break; if (dsign) - dval(rv) += ulp(dval(rv)); + dval(&rv) += ulp(&rv); else { - dval(rv) -= ulp(dval(rv)); + dval(&rv) -= ulp(&rv); #ifndef Sudden_Underflow - if (!dval(rv)) + if (!dval(&rv)) goto undfl; #endif } @@ -1558,9 +1538,9 @@ drop_down: if ((aadj = ratio(delta, bs)) <= 2.) { if (dsign) aadj = aadj1 = 1.; - else if (word1(rv) || word0(rv) & Bndry_mask) { + else if (word1(&rv) || word0(&rv) & Bndry_mask) { #ifndef Sudden_Underflow - if (word1(rv) == Tiny1 && !word0(rv)) + if (word1(&rv) == Tiny1 && !word0(&rv)) goto undfl; #endif aadj = 1.; @@ -1592,23 +1572,23 @@ drop_down: aadj1 += 0.5; #endif /*Check_FLT_ROUNDS*/ } - y = word0(rv) & Exp_mask; + y = word0(&rv) & Exp_mask; /* Check for overflow */ if (y == Exp_msk1 * (DBL_MAX_EXP + Bias - 1)) { - dval(rv0) = dval(rv); - word0(rv) -= P * Exp_msk1; - adj = aadj1 * ulp(dval(rv)); - dval(rv) += adj; - if ((word0(rv) & Exp_mask) >= Exp_msk1 * (DBL_MAX_EXP + Bias - P)) { - if (word0(rv0) == Big0 && word1(rv0) == Big1) + dval(&rv0) = dval(&rv); + word0(&rv) -= P * Exp_msk1; + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; + if ((word0(&rv) & Exp_mask) >= Exp_msk1 * (DBL_MAX_EXP + Bias - P)) { + if (word0(&rv0) == Big0 && word1(&rv0) == Big1) goto ovfl; - word0(rv) = Big0; - word1(rv) = Big1; + word0(&rv) = Big0; + word1(&rv) = Big1; goto cont; } else - word0(rv) += P * Exp_msk1; + word0(&rv) += P * Exp_msk1; } else { #ifdef Avoid_Underflow if (scale && y <= 2 * P * Exp_msk1) { @@ -1618,30 +1598,32 @@ drop_down: aadj = z; aadj1 = dsign ? aadj : -aadj; } - word0(aadj1) += (2 * P + 1) * Exp_msk1 - y; + dval(&aadj2) = aadj1; + word0(&aadj2) += (2 * P + 1) * Exp_msk1 - y; + aadj1 = dval(&aadj2); } - adj = aadj1 * ulp(dval(rv)); - dval(rv) += adj; + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; #else #ifdef Sudden_Underflow - if ((word0(rv) & Exp_mask) <= P * Exp_msk1) { - dval(rv0) = dval(rv); - word0(rv) += P * Exp_msk1; - adj = aadj1 * ulp(dval(rv)); - dval(rv) += adj; - if ((word0(rv) & Exp_mask) <= P * Exp_msk1) + if ((word0(&rv) & Exp_mask) <= P * Exp_msk1) { + dval(&rv0) = dval(&rv); + word0(&rv) += P * Exp_msk1; + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; + if ((word0(&rv) & Exp_mask) <= P * Exp_msk1) { - if (word0(rv0) == Tiny0 && word1(rv0) == Tiny1) + if (word0(&rv0) == Tiny0 && word1(&rv0) == Tiny1) goto undfl; - word0(rv) = Tiny0; - word1(rv) = Tiny1; + word0(&rv) = Tiny0; + word1(&rv) = Tiny1; goto cont; } else - word0(rv) -= P * Exp_msk1; + word0(&rv) -= P * Exp_msk1; } else { - adj = aadj1 * ulp(dval(rv)); - dval(rv) += adj; + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; } #else /*Sudden_Underflow*/ /* Compute adj so that the IEEE rounding rules will @@ -1656,12 +1638,12 @@ drop_down: if (!dsign) aadj1 = -aadj1; } - adj = aadj1 * ulp(dval(rv)); - dval(rv) += adj; + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow*/ } - z = word0(rv) & Exp_mask; + z = word0(&rv) & Exp_mask; #ifndef SET_INEXACT #ifdef Avoid_Underflow if (!scale) @@ -1671,7 +1653,7 @@ drop_down: L = (int32_t)aadj; aadj -= L; /* The tolerances below are conservative. */ - if (dsign || word1(rv) || word0(rv) & Bndry_mask) { + if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) { if (aadj < .4999999 || aadj > .5000001) break; } else if (aadj < .4999999 / FLT_RADIX) @@ -1679,53 +1661,44 @@ drop_down: } #endif cont: - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(delta); + ; } #ifdef SET_INEXACT if (inexact) { if (!oldinexact) { - word0(rv0) = Exp_1 + (70 << Exp_shift); - word1(rv0) = 0; - dval(rv0) += 1.; + word0(&rv0) = Exp_1 + (70 << Exp_shift); + word1(&rv0) = 0; + dval(&rv0) += 1.; } } else if (!oldinexact) clear_inexact(); #endif #ifdef Avoid_Underflow if (scale) { - word0(rv0) = Exp_1 - 2 * P * Exp_msk1; - word1(rv0) = 0; - dval(rv) *= dval(rv0); + word0(&rv0) = Exp_1 - 2 * P * Exp_msk1; + word1(&rv0) = 0; + dval(&rv) *= dval(&rv0); #ifndef NO_ERRNO /* try to avoid the bug of testing an 8087 register value */ - if (word0(rv) == 0 && word1(rv) == 0) + if (word0(&rv) == 0 && word1(&rv) == 0) errno = ERANGE; #endif } #endif /* Avoid_Underflow */ #ifdef SET_INEXACT - if (inexact && !(word0(rv) & Exp_mask)) { + if (inexact && !(word0(&rv) & Exp_mask)) { /* set underflow bit */ - dval(rv0) = 1e-300; - dval(rv0) *= dval(rv0); + dval(&rv0) = 1e-300; + dval(&rv0) *= dval(&rv0); } #endif -retfree: - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(bd0); - Bfree(delta); ret: if (se) - *se = (char*)s; - return sign ? -dval(rv) : dval(rv); + *se = const_cast<char*>(s); + return sign ? -dval(&rv) : dval(&rv); } -static int quorem(Bigint* b, Bigint* S) +static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S) { int n; uint32_t *bx, *bxe, q, *sx, *sxe; @@ -1738,13 +1711,13 @@ static int quorem(Bigint* b, Bigint* S) #endif #endif - n = S->wds; - ASSERT_WITH_MESSAGE(b->wds <= n, "oversize b in quorem"); - if (b->wds < n) + n = S.wds; + ASSERT_WITH_MESSAGE(b.wds <= n, "oversize b in quorem"); + if (b.wds < n) return 0; - sx = S->x; + sx = S.x; sxe = sx + --n; - bx = b->x; + bx = b.x; bxe = bx + n; q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ ASSERT_WITH_MESSAGE(q <= 9, "oversized quotient in quorem"); @@ -1779,18 +1752,18 @@ static int quorem(Bigint* b, Bigint* S) #endif } while (sx <= sxe); if (!*bxe) { - bx = b->x; + bx = b.x; while (--bxe > bx && !*bxe) --n; - b->wds = n; + b.wds = n; } } if (cmp(b, S) >= 0) { q++; borrow = 0; carry = 0; - bx = b->x; - sx = S->x; + bx = b.x; + sx = S.x; do { #ifdef USE_LONG_LONG ys = *sx++ + carry; @@ -1818,68 +1791,17 @@ static int quorem(Bigint* b, Bigint* S) #endif #endif } while (sx <= sxe); - bx = b->x; + bx = b.x; bxe = bx + n; if (!*bxe) { while (--bxe > bx && !*bxe) --n; - b->wds = n; + b.wds = n; } } return q; } -#if !ENABLE(JSC_MULTIPLE_THREADS) -static char* dtoa_result; -#endif - -static char* rv_alloc(int i) -{ - int k; - - int j = sizeof(uint32_t); - for (k = 0; - sizeof(Bigint) - sizeof(uint32_t) - sizeof(int) + j <= (unsigned)i; - j <<= 1) - k++; - int* r = (int*)Balloc(k); - *r = k; - return -#if !ENABLE(JSC_MULTIPLE_THREADS) - dtoa_result = -#endif - (char*)(r + 1); -} - -static char* nrv_alloc(const char* s, char** rve, int n) -{ - char* rv = rv_alloc(n); - char* t = rv; - - while ((*t = *s++)) - t++; - if (rve) - *rve = t; - return rv; -} - -/* freedtoa(s) must be used to free values s returned by dtoa - * when MULTIPLE_THREADS is #defined. It should be used in all cases, - * but for consistency with earlier versions of dtoa, it is optional - * when MULTIPLE_THREADS is not defined. - */ - -void freedtoa(char* s) -{ - Bigint* b = (Bigint*)((int*)s - 1); - b->maxwds = 1 << (b->k = *(int*)b); - Bfree(b); -#if !ENABLE(JSC_MULTIPLE_THREADS) - if (s == dtoa_result) - dtoa_result = 0; -#endif -} - /* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. * * Inspired by "How to Print Floating-Point Numbers Accurately" by @@ -1914,7 +1836,7 @@ void freedtoa(char* s) * calculation. */ -char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) +void dtoa(char* result, double dd, int ndigits, int* decpt, int* sign, char** rve) { /* Arguments ndigits, decpt, sign are similar to those @@ -1933,38 +1855,37 @@ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) int denorm; uint32_t x; #endif - Bigint *b, *b1, *delta, *mlo = NULL, *mhi, *S; - double d2, ds, eps; + BigInt b, b1, delta, mlo, mhi, S; + U d2, eps, u; + double ds; char *s, *s0; #ifdef SET_INEXACT int inexact, oldinexact; #endif -#if !ENABLE(JSC_MULTIPLE_THREADS) - if (dtoa_result) { - freedtoa(dtoa_result); - dtoa_result = 0; - } -#endif - - if (word0(d) & Sign_bit) { + u.d = dd; + if (word0(&u) & Sign_bit) { /* set sign for everything, including 0's and NaNs */ *sign = 1; - word0(d) &= ~Sign_bit; /* clear sign bit */ + word0(&u) &= ~Sign_bit; /* clear sign bit */ } else *sign = 0; - if ((word0(d) & Exp_mask) == Exp_mask) + if ((word0(&u) & Exp_mask) == Exp_mask) { /* Infinity or NaN */ *decpt = 9999; - if (!word1(d) && !(word0(d) & 0xfffff)) - return nrv_alloc("Infinity", rve, 8); - return nrv_alloc("NaN", rve, 3); + if (!word1(&u) && !(word0(&u) & 0xfffff)) + strcpy(result, "Infinity"); + else + strcpy(result, "NaN"); + return; } - if (!dval(d)) { + if (!dval(&u)) { *decpt = 1; - return nrv_alloc("0", rve, 1); + result[0] = '0'; + result[1] = '\0'; + return; } #ifdef SET_INEXACT @@ -1972,15 +1893,15 @@ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) inexact = 1; #endif - b = d2b(dval(d), &be, &bbits); + d2b(b, &u, &be, &bbits); #ifdef Sudden_Underflow - i = (int)(word0(d) >> Exp_shift1 & (Exp_mask >> Exp_shift1)); + i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask >> Exp_shift1)); #else - if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask >> Exp_shift1)))) { + if ((i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask >> Exp_shift1)))) { #endif - dval(d2) = dval(d); - word0(d2) &= Frac_mask1; - word0(d2) |= Exp_11; + dval(&d2) = dval(&u); + word0(&d2) &= Frac_mask1; + word0(&d2) |= Exp_11; /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 * log10(x) = log(x) / log(10) @@ -2011,21 +1932,21 @@ 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; - dval(d2) = x; - word0(d2) -= 31 * Exp_msk1; /* adjust exponent */ + x = (i > 32) ? (word0(&u) << (64 - i)) | (word1(&u) >> (i - 32)) + : word1(&u) << (32 - i); + dval(&d2) = x; + word0(&d2) -= 31 * Exp_msk1; /* adjust exponent */ i -= (Bias + (P - 1) - 1) + 1; denorm = 1; } #endif - ds = (dval(d2) - 1.5) * 0.289529654602168 + 0.1760912590558 + (i * 0.301029995663981); + ds = (dval(&d2) - 1.5) * 0.289529654602168 + 0.1760912590558 + (i * 0.301029995663981); k = (int)ds; if (ds < 0. && ds != k) k--; /* want k = floor(ds) */ k_check = 1; if (k >= 0 && k <= Ten_pmax) { - if (dval(d) < tens[k]) + if (dval(&u) < tens[k]) k--; k_check = 0; } @@ -2059,14 +1980,14 @@ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) ilim = ilim1 = -1; i = 18; ndigits = 0; - s = s0 = rv_alloc(i); + s = s0 = result; if (ilim >= 0 && ilim <= Quick_max && try_quick) { /* Try to get by with floating-point arithmetic. */ i = 0; - dval(d2) = dval(d); + dval(&d2) = dval(&u); k0 = k; ilim0 = ilim; ieps = 2; /* conservative */ @@ -2076,7 +1997,7 @@ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) if (j & Bletch) { /* prevent overflows */ j &= Bletch - 1; - dval(d) /= bigtens[n_bigtens - 1]; + dval(&u) /= bigtens[n_bigtens - 1]; ieps++; } for (; j; j >>= 1, i++) { @@ -2085,32 +2006,32 @@ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) ds *= bigtens[i]; } } - dval(d) /= ds; + dval(&u) /= ds; } else if ((j1 = -k)) { - dval(d) *= tens[j1 & 0xf]; + dval(&u) *= tens[j1 & 0xf]; for (j = j1 >> 4; j; j >>= 1, i++) { if (j & 1) { ieps++; - dval(d) *= bigtens[i]; + dval(&u) *= bigtens[i]; } } } - if (k_check && dval(d) < 1. && ilim > 0) { + if (k_check && dval(&u) < 1. && ilim > 0) { if (ilim1 <= 0) goto fast_failed; ilim = ilim1; k--; - dval(d) *= 10.; + dval(&u) *= 10.; ieps++; } - dval(eps) = (ieps * dval(d)) + 7.; - word0(eps) -= (P - 1) * Exp_msk1; + dval(&eps) = (ieps * dval(&u)) + 7.; + word0(&eps) -= (P - 1) * Exp_msk1; if (ilim == 0) { - S = mhi = 0; - dval(d) -= 5.; - if (dval(d) > dval(eps)) + S = mhi = BigInt(); + dval(&u) -= 5.; + if (dval(&u) > dval(&eps)) goto one_digit; - if (dval(d) < -dval(eps)) + if (dval(&u) < -dval(&eps)) goto no_digits; goto fast_failed; } @@ -2119,36 +2040,36 @@ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) /* Use Steele & White method of only * generating digits needed. */ - dval(eps) = (0.5 / tens[ilim - 1]) - dval(eps); + dval(&eps) = (0.5 / tens[ilim - 1]) - dval(&eps); for (i = 0;;) { - L = (long int)dval(d); - dval(d) -= L; + L = (long int)dval(&u); + dval(&u) -= L; *s++ = '0' + (int)L; - if (dval(d) < dval(eps)) - goto ret1; - if (1. - dval(d) < dval(eps)) + if (dval(&u) < dval(&eps)) + goto ret; + if (1. - dval(&u) < dval(&eps)) goto bump_up; if (++i >= ilim) break; - dval(eps) *= 10.; - dval(d) *= 10.; + dval(&eps) *= 10.; + dval(&u) *= 10.; } } else { #endif /* Generate ilim digits, then fix them up. */ - dval(eps) *= tens[ilim - 1]; - for (i = 1;; i++, dval(d) *= 10.) { - L = (int32_t)(dval(d)); - if (!(dval(d) -= L)) + dval(&eps) *= tens[ilim - 1]; + for (i = 1;; i++, dval(&u) *= 10.) { + L = (int32_t)(dval(&u)); + if (!(dval(&u) -= L)) ilim = i; *s++ = '0' + (int)L; if (i == ilim) { - if (dval(d) > 0.5 + dval(eps)) + if (dval(&u) > 0.5 + dval(&eps)) goto bump_up; - else if (dval(d) < 0.5 - dval(eps)) { + else if (dval(&u) < 0.5 - dval(&eps)) { while (*--s == '0') { } s++; - goto ret1; + goto ret; } break; } @@ -2158,7 +2079,7 @@ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) #endif fast_failed: s = s0; - dval(d) = dval(d2); + dval(&u) = dval(&d2); k = k0; ilim = ilim0; } @@ -2169,31 +2090,31 @@ fast_failed: /* Yes. */ ds = tens[k]; if (ndigits < 0 && ilim <= 0) { - S = mhi = 0; - if (ilim < 0 || dval(d) <= 5 * ds) + S = mhi = BigInt(); + if (ilim < 0 || dval(&u) <= 5 * ds) goto no_digits; goto one_digit; } - for (i = 1;; i++, dval(d) *= 10.) { - L = (int32_t)(dval(d) / ds); - dval(d) -= L * ds; + for (i = 1;; i++, dval(&u) *= 10.) { + L = (int32_t)(dval(&u) / ds); + dval(&u) -= L * ds; #ifdef Check_FLT_ROUNDS /* If FLT_ROUNDS == 2, L will usually be high by 1 */ - if (dval(d) < 0) { + if (dval(&u) < 0) { L--; - dval(d) += ds; + dval(&u) += ds; } #endif *s++ = '0' + (int)L; - if (!dval(d)) { + if (!dval(&u)) { #ifdef SET_INEXACT inexact = 0; #endif break; } if (i == ilim) { - dval(d) += dval(d); - if (dval(d) > ds || dval(d) == ds && L & 1) { + dval(&u) += dval(&u); + if (dval(&u) > ds || (dval(&u) == ds && (L & 1))) { bump_up: while (*--s == '9') if (s == s0) { @@ -2206,12 +2127,12 @@ bump_up: break; } } - goto ret1; + goto ret; } m2 = b2; m5 = b5; - mhi = mlo = 0; + mhi = mlo = BigInt(); if (leftright) { i = #ifndef Sudden_Underflow @@ -2220,7 +2141,7 @@ bump_up: 1 + P - bbits; b2 += i; s2 += i; - mhi = i2b(1); + i2b(mhi, 1); } if (m2 > 0 && s2 > 0) { i = m2 < s2 ? m2 : s2; @@ -2231,26 +2152,24 @@ bump_up: if (b5 > 0) { if (leftright) { if (m5 > 0) { - mhi = pow5mult(mhi, m5); - b1 = mult(mhi, b); - Bfree(b); - b = b1; + pow5mult(mhi, m5); + mult(b, mhi); } if ((j = b5 - m5)) - b = pow5mult(b, j); + pow5mult(b, j); } else - b = pow5mult(b, b5); + pow5mult(b, b5); } - S = i2b(1); + i2b(S, 1); if (s5 > 0) - S = pow5mult(S, s5); + pow5mult(S, s5); /* Check for special case that d is a normalized power of 2. */ spec_case = 0; - if (!word1(d) && !(word0(d) & Bndry_mask) + if (!word1(&u) && !(word0(&u) & Bndry_mask) #ifndef Sudden_Underflow - && word0(d) & (Exp_mask & ~Exp_msk1) + && word0(&u) & (Exp_mask & ~Exp_msk1) #endif ) { /* The special case */ @@ -2267,10 +2186,10 @@ bump_up: * can do shifts and ors to compute the numerator for q. */ #ifdef Pack_32 - if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds - 1]) : 1) + s2) & 0x1f)) + if ((i = ((s5 ? 32 - hi0bits(S.x[S.wds - 1]) : 1) + s2) & 0x1f)) i = 32 - i; #else - if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds - 1]) : 1) + s2) & 0xf)) + if ((i = ((s5 ? 32 - hi0bits(S.x[S.wds - 1]) : 1) + s2) & 0xf)) i = 16 - i; #endif if (i > 4) { @@ -2285,22 +2204,22 @@ bump_up: s2 += i; } if (b2 > 0) - b = lshift(b, b2); + lshift(b, b2); if (s2 > 0) - S = lshift(S, s2); + lshift(S, s2); if (k_check) { if (cmp(b,S) < 0) { k--; - b = multadd(b, 10, 0); /* we botched the k estimate */ + multadd(b, 10, 0); /* we botched the k estimate */ if (leftright) - mhi = multadd(mhi, 10, 0); + multadd(mhi, 10, 0); ilim = ilim1; } } if (leftright) { if (m2 > 0) - mhi = lshift(mhi, m2); + lshift(mhi, m2); /* Compute mlo -- check for special case * that d is a normalized power of 2. @@ -2308,9 +2227,8 @@ bump_up: mlo = mhi; if (spec_case) { - mhi = Balloc(mhi->k); - Bcopy(mhi, mlo); - mhi = lshift(mhi, Log2P); + mhi = mlo; + lshift(mhi, Log2P); } for (i = 1;;i++) { @@ -2319,10 +2237,9 @@ bump_up: * that will round to d? */ j = cmp(b, mlo); - delta = diff(S, mhi); - j1 = delta->sign ? 1 : cmp(b, delta); - Bfree(delta); - if (j1 == 0 && !(word1(d) & 1)) { + diff(delta, S, mhi); + j1 = delta.sign ? 1 : cmp(b, delta); + if (j1 == 0 && !(word1(&u) & 1)) { if (dig == '9') goto round_9_up; if (j > 0) @@ -2334,17 +2251,17 @@ bump_up: *s++ = dig; goto ret; } - if (j < 0 || j == 0 && !(word1(d) & 1)) { - if (!b->x[0] && b->wds <= 1) { + if (j < 0 || (j == 0 && !(word1(&u) & 1))) { + if (!b.x[0] && b.wds <= 1) { #ifdef SET_INEXACT inexact = 0; #endif goto accept_dig; } if (j1 > 0) { - b = lshift(b, 1); + 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: @@ -2363,18 +2280,14 @@ round_9_up: *s++ = dig; if (i == ilim) break; - b = multadd(b, 10, 0); - if (mlo == mhi) - mlo = mhi = multadd(mhi, 10, 0); - else { - mlo = multadd(mlo, 10, 0); - mhi = multadd(mhi, 10, 0); - } + multadd(b, 10, 0); + multadd(mlo, 10, 0); + multadd(mhi, 10, 0); } } else for (i = 1;; i++) { *s++ = dig = quorem(b,S) + '0'; - if (!b->x[0] && b->wds <= 1) { + if (!b.x[0] && b.wds <= 1) { #ifdef SET_INEXACT inexact = 0; #endif @@ -2382,14 +2295,14 @@ round_9_up: } if (i >= ilim) break; - b = multadd(b, 10, 0); + multadd(b, 10, 0); } /* Round off last digit */ - b = lshift(b, 1); + 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) { @@ -2411,29 +2324,20 @@ one_digit: k++; goto ret; ret: - Bfree(S); - if (mhi) { - if (mlo && mlo != mhi) - Bfree(mlo); - Bfree(mhi); - } -ret1: #ifdef SET_INEXACT if (inexact) { if (!oldinexact) { - word0(d) = Exp_1 + (70 << Exp_shift); - word1(d) = 0; - dval(d) += 1.; + word0(&u) = Exp_1 + (70 << Exp_shift); + word1(&u) = 0; + dval(&u) += 1.; } } else if (!oldinexact) clear_inexact(); #endif - Bfree(b); *s = 0; *decpt = k + 1; if (rve) *rve = s; - return s0; } } // namespace WTF diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/dtoa.h b/src/3rdparty/webkit/JavaScriptCore/wtf/dtoa.h index ed858c0..cbec7c7 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/dtoa.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/dtoa.h @@ -30,8 +30,7 @@ namespace WTF { extern WTF::Mutex* s_dtoaP5Mutex; double strtod(const char* s00, char** se); - char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve); - void freedtoa(char* s); + void dtoa(char* result, double d, int ndigits, int* decpt, int* sign, char** rve); } // namespace WTF diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/qt/MainThreadQt.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/qt/MainThreadQt.cpp index 1914600..7b2d0f2 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/qt/MainThreadQt.cpp +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadingQt.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/qt/ThreadingQt.cpp index 1a40d52..1fdd2bb 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/ThreadingQt.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/qt/ThreadingQt.cpp @@ -29,6 +29,7 @@ #include "config.h" #include "Threading.h" +#include "CurrentTime.h" #include "HashMap.h" #include "MainThread.h" #include "RandomNumberSeed.h" @@ -161,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); @@ -233,15 +238,22 @@ void ThreadCondition::wait(Mutex& mutex) m_condition->wait(mutex.impl()); } -bool ThreadCondition::timedWait(Mutex& mutex, double secondsToWait) +bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime) { - if (secondsToWait < 0.0) { + double currentTime = WTF::currentTime(); + + // Time is in the past - return immediately. + if (absoluteTime < currentTime) + return false; + + // 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; } - unsigned long millisecondsToWait = static_cast<unsigned long>(secondsToWait * 1000.0); - return m_condition->wait(mutex.impl(), millisecondsToWait); + double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0; + return m_condition->wait(mutex.impl(), static_cast<unsigned long>(intervalMilliseconds)); } void ThreadCondition::signal() diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/Unicode.h b/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/Unicode.h index 5b849e4..f86a9b7 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/Unicode.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/Unicode.h @@ -28,10 +28,12 @@ #include "qt4/UnicodeQt4.h" #elif USE(ICU_UNICODE) #include <wtf/unicode/icu/UnicodeIcu.h> +#elif USE(GLIB_UNICODE) +#include <wtf/unicode/glib/UnicodeGLib.h> #else #error "Unknown Unicode implementation" #endif -COMPILE_ASSERT(sizeof(UChar) == 2, UCharIsTwoBytes) +COMPILE_ASSERT(sizeof(UChar) == 2, UCharIsTwoBytes); #endif // WTF_UNICODE_H diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp new file mode 100644 index 0000000..a779b36 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2008 Jürg Billeter <j@bitron.ch> + * Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.com> + * + * 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 "UnicodeGLib.h" + +namespace WTF { +namespace Unicode { + +UChar32 foldCase(UChar32 ch) +{ + GOwnPtr<GError> gerror; + + GOwnPtr<char> utf8char; + utf8char.set(g_ucs4_to_utf8(reinterpret_cast<gunichar*>(&ch), 1, 0, 0, &gerror.outPtr())); + if (gerror) + return ch; + + GOwnPtr<char> utf8caseFolded; + utf8caseFolded.set(g_utf8_casefold(utf8char.get(), -1)); + + GOwnPtr<gunichar> ucs4Result; + ucs4Result.set(g_utf8_to_ucs4_fast(utf8caseFolded.get(), -1, 0)); + + return *ucs4Result; +} + +int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) +{ + *error = false; + GOwnPtr<GError> gerror; + + GOwnPtr<char> utf8src; + utf8src.set(g_utf16_to_utf8(src, srcLength, 0, 0, &gerror.outPtr())); + if (gerror) { + *error = true; + return -1; + } + + GOwnPtr<char> utf8result; + utf8result.set(g_utf8_casefold(utf8src.get(), -1)); + + long utf16resultLength = -1; + GOwnPtr<UChar> utf16result; + utf16result.set(g_utf8_to_utf16(utf8result.get(), -1, 0, &utf16resultLength, &gerror.outPtr())); + if (gerror) { + *error = true; + return -1; + } + + if (utf16resultLength > resultLength) { + *error = true; + return utf16resultLength; + } + memcpy(result, utf16result.get(), utf16resultLength * sizeof(UChar)); + + return utf16resultLength; +} + +int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) +{ + *error = false; + GOwnPtr<GError> gerror; + + GOwnPtr<char> utf8src; + utf8src.set(g_utf16_to_utf8(src, srcLength, 0, 0, &gerror.outPtr())); + if (gerror) { + *error = true; + return -1; + } + + GOwnPtr<char> utf8result; + utf8result.set(g_utf8_strdown(utf8src.get(), -1)); + + long utf16resultLength = -1; + GOwnPtr<UChar> utf16result; + utf16result.set(g_utf8_to_utf16(utf8result.get(), -1, 0, &utf16resultLength, &gerror.outPtr())); + if (gerror) { + *error = true; + return -1; + } + + if (utf16resultLength > resultLength) { + *error = true; + return utf16resultLength; + } + memcpy(result, utf16result.get(), utf16resultLength * sizeof(UChar)); + + return utf16resultLength; +} + +int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) +{ + *error = false; + GOwnPtr<GError> gerror; + + GOwnPtr<char> utf8src; + utf8src.set(g_utf16_to_utf8(src, srcLength, 0, 0, &gerror.outPtr())); + if (gerror) { + *error = true; + return -1; + } + + GOwnPtr<char> utf8result; + utf8result.set(g_utf8_strup(utf8src.get(), -1)); + + long utf16resultLength = -1; + GOwnPtr<UChar> utf16result; + utf16result.set(g_utf8_to_utf16(utf8result.get(), -1, 0, &utf16resultLength, &gerror.outPtr())); + if (gerror) { + *error = true; + return -1; + } + + if (utf16resultLength > resultLength) { + *error = true; + return utf16resultLength; + } + memcpy(result, utf16result.get(), utf16resultLength * sizeof(UChar)); + + return utf16resultLength; +} + +Direction direction(UChar32 c) +{ + PangoBidiType type = pango_bidi_type_for_unichar(c); + switch (type) { + case PANGO_BIDI_TYPE_L: + return LeftToRight; + case PANGO_BIDI_TYPE_R: + return RightToLeft; + case PANGO_BIDI_TYPE_AL: + return RightToLeftArabic; + case PANGO_BIDI_TYPE_LRE: + return LeftToRightEmbedding; + case PANGO_BIDI_TYPE_RLE: + return RightToLeftEmbedding; + case PANGO_BIDI_TYPE_LRO: + return LeftToRightOverride; + case PANGO_BIDI_TYPE_RLO: + return RightToLeftOverride; + case PANGO_BIDI_TYPE_PDF: + return PopDirectionalFormat; + case PANGO_BIDI_TYPE_EN: + return EuropeanNumber; + case PANGO_BIDI_TYPE_AN: + return ArabicNumber; + case PANGO_BIDI_TYPE_ES: + return EuropeanNumberSeparator; + case PANGO_BIDI_TYPE_ET: + return EuropeanNumberTerminator; + case PANGO_BIDI_TYPE_CS: + return CommonNumberSeparator; + case PANGO_BIDI_TYPE_NSM: + return NonSpacingMark; + case PANGO_BIDI_TYPE_BN: + return BoundaryNeutral; + case PANGO_BIDI_TYPE_B: + return BlockSeparator; + case PANGO_BIDI_TYPE_S: + return SegmentSeparator; + case PANGO_BIDI_TYPE_WS: + return WhiteSpaceNeutral; + default: + return OtherNeutral; + } +} + +int umemcasecmp(const UChar* a, const UChar* b, int len) +{ + GOwnPtr<char> utf8a; + GOwnPtr<char> utf8b; + + utf8a.set(g_utf16_to_utf8(a, len, 0, 0, 0)); + utf8b.set(g_utf16_to_utf8(b, len, 0, 0, 0)); + + GOwnPtr<char> foldedA; + GOwnPtr<char> foldedB; + + foldedA.set(g_utf8_casefold(utf8a.get(), -1)); + foldedB.set(g_utf8_casefold(utf8b.get(), -1)); + + // FIXME: umemcasecmp needs to mimic u_memcasecmp of icu + // from the ICU docs: + // "Compare two strings case-insensitively using full case folding. + // his is equivalent to u_strcmp(u_strFoldCase(s1, n, options), u_strFoldCase(s2, n, options))." + // + // So it looks like we don't need the full g_utf8_collate here, + // but really a bitwise comparison of casefolded unicode chars (not utf-8 bytes). + // As there is no direct equivalent to this icu function in GLib, for now + // we'll use g_utf8_collate(): + + return g_utf8_collate(foldedA.get(), foldedB.get()); +} + +} +} diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h b/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h new file mode 100644 index 0000000..c03d3ec --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2006 George Staikos <staikos@kde.org> + * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> + * Copyright (C) 2007 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2008 Jürg Billeter <j@bitron.ch> + * Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.com> + * + * 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 UnicodeGLib_h +#define UnicodeGLib_h + +#include "UnicodeMacrosFromICU.h" +#include <wtf/GOwnPtr.h> + +#include <glib.h> +#include <pango/pango.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +typedef uint16_t UChar; +typedef int32_t UChar32; + +namespace WTF { +namespace Unicode { + +enum Direction { + LeftToRight, + RightToLeft, + EuropeanNumber, + EuropeanNumberSeparator, + EuropeanNumberTerminator, + ArabicNumber, + CommonNumberSeparator, + BlockSeparator, + SegmentSeparator, + WhiteSpaceNeutral, + OtherNeutral, + LeftToRightEmbedding, + LeftToRightOverride, + RightToLeftArabic, + RightToLeftEmbedding, + RightToLeftOverride, + PopDirectionalFormat, + NonSpacingMark, + BoundaryNeutral +}; + +enum DecompositionType { + DecompositionNone, + DecompositionCanonical, + DecompositionCompat, + DecompositionCircle, + DecompositionFinal, + DecompositionFont, + DecompositionFraction, + DecompositionInitial, + DecompositionIsolated, + DecompositionMedial, + DecompositionNarrow, + DecompositionNoBreak, + DecompositionSmall, + DecompositionSquare, + DecompositionSub, + DecompositionSuper, + DecompositionVertical, + DecompositionWide, +}; + +enum CharCategory { + NoCategory = 0, + Other_NotAssigned = U_MASK(G_UNICODE_UNASSIGNED), + Letter_Uppercase = U_MASK(G_UNICODE_UPPERCASE_LETTER), + Letter_Lowercase = U_MASK(G_UNICODE_LOWERCASE_LETTER), + Letter_Titlecase = U_MASK(G_UNICODE_TITLECASE_LETTER), + Letter_Modifier = U_MASK(G_UNICODE_MODIFIER_LETTER), + Letter_Other = U_MASK(G_UNICODE_OTHER_LETTER), + + Mark_NonSpacing = U_MASK(G_UNICODE_NON_SPACING_MARK), + Mark_Enclosing = U_MASK(G_UNICODE_ENCLOSING_MARK), + Mark_SpacingCombining = U_MASK(G_UNICODE_COMBINING_MARK), + + Number_DecimalDigit = U_MASK(G_UNICODE_DECIMAL_NUMBER), + Number_Letter = U_MASK(G_UNICODE_LETTER_NUMBER), + Number_Other = U_MASK(G_UNICODE_OTHER_NUMBER), + + Separator_Space = U_MASK(G_UNICODE_SPACE_SEPARATOR), + Separator_Line = U_MASK(G_UNICODE_LINE_SEPARATOR), + Separator_Paragraph = U_MASK(G_UNICODE_PARAGRAPH_SEPARATOR), + + Other_Control = U_MASK(G_UNICODE_CONTROL), + Other_Format = U_MASK(G_UNICODE_FORMAT), + Other_PrivateUse = U_MASK(G_UNICODE_PRIVATE_USE), + Other_Surrogate = U_MASK(G_UNICODE_SURROGATE), + + Punctuation_Dash = U_MASK(G_UNICODE_DASH_PUNCTUATION), + Punctuation_Open = U_MASK(G_UNICODE_OPEN_PUNCTUATION), + Punctuation_Close = U_MASK(G_UNICODE_CLOSE_PUNCTUATION), + Punctuation_Connector = U_MASK(G_UNICODE_CONNECT_PUNCTUATION), + Punctuation_Other = U_MASK(G_UNICODE_OTHER_PUNCTUATION), + + Symbol_Math = U_MASK(G_UNICODE_MATH_SYMBOL), + Symbol_Currency = U_MASK(G_UNICODE_CURRENCY_SYMBOL), + Symbol_Modifier = U_MASK(G_UNICODE_MODIFIER_SYMBOL), + Symbol_Other = U_MASK(G_UNICODE_OTHER_SYMBOL), + + Punctuation_InitialQuote = U_MASK(G_UNICODE_INITIAL_PUNCTUATION), + Punctuation_FinalQuote = U_MASK(G_UNICODE_FINAL_PUNCTUATION) +}; + +UChar32 foldCase(UChar32); + +int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error); + +int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error); + +inline UChar32 toLower(UChar32 c) +{ + return g_unichar_tolower(c); +} + +inline UChar32 toUpper(UChar32 c) +{ + return g_unichar_toupper(c); +} + +int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error); + +inline UChar32 toTitleCase(UChar32 c) +{ + return g_unichar_totitle(c); +} + +inline bool isArabicChar(UChar32 c) +{ + return c >= 0x0600 && c <= 0x06FF; +} + +inline bool isFormatChar(UChar32 c) +{ + return g_unichar_type(c) == G_UNICODE_FORMAT; +} + +inline bool isSeparatorSpace(UChar32 c) +{ + return g_unichar_type(c) == G_UNICODE_SPACE_SEPARATOR; +} + +inline bool isPrintableChar(UChar32 c) +{ + return g_unichar_isprint(c); +} + +inline bool isDigit(UChar32 c) +{ + return g_unichar_isdigit(c); +} + +inline bool isPunct(UChar32 c) +{ + return g_unichar_ispunct(c); +} + +inline bool hasLineBreakingPropertyComplexContext(UChar32 c) +{ + // FIXME + return false; +} + +inline bool hasLineBreakingPropertyComplexContextOrIdeographic(UChar32 c) +{ + // FIXME + return false; +} + +inline UChar32 mirroredChar(UChar32 c) +{ + gunichar mirror = 0; + g_unichar_get_mirror_char(c, &mirror); + return mirror; +} + +inline CharCategory category(UChar32 c) +{ + if (c > 0xffff) + return NoCategory; + + return (CharCategory) U_MASK(g_unichar_type(c)); +} + +Direction direction(UChar32); + +inline bool isLower(UChar32 c) +{ + return g_unichar_islower(c); +} + +inline int digitValue(UChar32 c) +{ + return g_unichar_digit_value(c); +} + +inline uint8_t combiningClass(UChar32 c) +{ + // FIXME + // return g_unichar_combining_class(c); + return 0; +} + +inline DecompositionType decompositionType(UChar32 c) +{ + // FIXME + return DecompositionNone; +} + +int umemcasecmp(const UChar*, const UChar*, int len); + +} +} + +#endif + diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/glib/UnicodeMacrosFromICU.h b/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/glib/UnicodeMacrosFromICU.h new file mode 100644 index 0000000..5d3eca6 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/glib/UnicodeMacrosFromICU.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2006 George Staikos <staikos@kde.org> + * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> + * Copyright (C) 2007 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2008 Jürg Billeter <j@bitron.ch> + * Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.com> + * + * 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 UnicodeMacrosFromICU_h +#define UnicodeMacrosFromICU_h + +// some defines from ICU + +#define U16_IS_LEAD(c) (((c)&0xfffffc00)==0xd800) +#define U16_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00) +#define U16_SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000) +#define U16_GET_SUPPLEMENTARY(lead, trail) \ + (((UChar32)(lead)<<10UL)+(UChar32)(trail)-U16_SURROGATE_OFFSET) + +#define U16_LEAD(supplementary) (UChar)(((supplementary)>>10)+0xd7c0) +#define U16_TRAIL(supplementary) (UChar)(((supplementary)&0x3ff)|0xdc00) + +#define U_IS_SURROGATE(c) (((c)&0xfffff800)==0xd800) +#define U16_IS_SINGLE(c) !U_IS_SURROGATE(c) +#define U16_IS_SURROGATE(c) U_IS_SURROGATE(c) +#define U16_IS_SURROGATE_LEAD(c) (((c)&0x400)==0) + +#define U16_PREV(s, start, i, c) { \ + (c)=(s)[--(i)]; \ + if(U16_IS_TRAIL(c)) { \ + uint16_t __c2; \ + if((i)>(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \ + --(i); \ + (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \ + } \ + } \ +} + +#define U16_NEXT(s, i, length, c) { \ + (c)=(s)[(i)++]; \ + if(U16_IS_LEAD(c)) { \ + uint16_t __c2; \ + if((i)<(length) && U16_IS_TRAIL(__c2=(s)[(i)])) { \ + ++(i); \ + (c)=U16_GET_SUPPLEMENTARY((c), __c2); \ + } \ + } \ +} + +#define U_MASK(x) ((uint32_t)1<<(x)) + +#endif + diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h b/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h index 608aea6..35c6fbf 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h @@ -179,6 +179,17 @@ 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 bool hasLineBreakingPropertyComplexContextOrIdeographic(UChar32 c) +{ + int32_t prop = u_getIntPropertyValue(c, UCHAR_LINE_BREAK); + return prop == U_LB_COMPLEX_CONTEXT || prop == U_LB_IDEOGRAPHIC; +} + inline UChar32 mirroredChar(UChar32 c) { return u_charMirror(c); diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h b/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h index d7d78ce..1531694 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h @@ -92,6 +92,17 @@ typedef uint32_t UChar32; } \ } +#define U16_PREV(s, start, i, c) { \ + (c)=(s)[--(i)]; \ + if(U16_IS_TRAIL(c)) { \ + uint16_t __c2; \ + if((i)>(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \ + --(i); \ + (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \ + } \ + } \ +} + #define U_MASK(x) ((uint32_t)1<<(x)) namespace WTF { @@ -352,6 +363,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); |