summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/wtf
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-05 14:34:32 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-05 14:34:32 -0800
commit635860845790a19bf50bbc51ba8fb66a96dde068 (patch)
treeef6ad9ff73a5b57f65249d4232a202fa77e6a140 /JavaScriptCore/wtf
parent8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2 (diff)
downloadexternal_webkit-635860845790a19bf50bbc51ba8fb66a96dde068.zip
external_webkit-635860845790a19bf50bbc51ba8fb66a96dde068.tar.gz
external_webkit-635860845790a19bf50bbc51ba8fb66a96dde068.tar.bz2
auto import from //depot/cupcake/@136594
Diffstat (limited to 'JavaScriptCore/wtf')
-rw-r--r--JavaScriptCore/wtf/ASCIICType.h7
-rw-r--r--JavaScriptCore/wtf/AVLTree.h33
-rw-r--r--JavaScriptCore/wtf/AlwaysInline.h12
-rw-r--r--JavaScriptCore/wtf/Assertions.cpp4
-rw-r--r--JavaScriptCore/wtf/Assertions.h16
-rw-r--r--JavaScriptCore/wtf/ByteArray.cpp38
-rw-r--r--JavaScriptCore/wtf/ByteArray.h81
-rw-r--r--JavaScriptCore/wtf/CONTRIBUTORS.pthreads-win32137
-rw-r--r--JavaScriptCore/wtf/CurrentTime.cpp246
-rw-r--r--JavaScriptCore/wtf/CurrentTime.h51
-rw-r--r--JavaScriptCore/wtf/FastMalloc.cpp153
-rw-r--r--JavaScriptCore/wtf/FastMalloc.h13
-rw-r--r--JavaScriptCore/wtf/HashCountedSet.h3
-rw-r--r--JavaScriptCore/wtf/HashFunctions.h3
-rw-r--r--JavaScriptCore/wtf/HashTable.cpp11
-rw-r--r--JavaScriptCore/wtf/HashTable.h35
-rw-r--r--JavaScriptCore/wtf/ListHashSet.h6
-rw-r--r--JavaScriptCore/wtf/MainThread.cpp7
-rw-r--r--JavaScriptCore/wtf/MathExtras.h56
-rw-r--r--JavaScriptCore/wtf/MessageQueue.h35
-rw-r--r--JavaScriptCore/wtf/OwnPtr.h6
-rw-r--r--JavaScriptCore/wtf/PassRefPtr.h5
-rw-r--r--JavaScriptCore/wtf/Platform.h146
-rw-r--r--JavaScriptCore/wtf/PtrAndFlags.h53
-rw-r--r--JavaScriptCore/wtf/RandomNumber.cpp94
-rw-r--r--JavaScriptCore/wtf/RandomNumber.h42
-rw-r--r--JavaScriptCore/wtf/RandomNumberSeed.h71
-rw-r--r--JavaScriptCore/wtf/RefCounted.h2
-rw-r--r--JavaScriptCore/wtf/RefPtr.h4
-rw-r--r--JavaScriptCore/wtf/RetainPtr.h3
-rw-r--r--JavaScriptCore/wtf/StdLibExtras.h63
-rw-r--r--JavaScriptCore/wtf/TCSpinLock.h9
-rw-r--r--JavaScriptCore/wtf/TCSystemAlloc.cpp22
-rw-r--r--JavaScriptCore/wtf/ThreadSpecific.h115
-rw-r--r--JavaScriptCore/wtf/ThreadSpecificWin.cpp45
-rw-r--r--JavaScriptCore/wtf/Threading.cpp83
-rw-r--r--JavaScriptCore/wtf/Threading.h35
-rw-r--r--JavaScriptCore/wtf/ThreadingGtk.cpp72
-rw-r--r--JavaScriptCore/wtf/ThreadingNone.cpp32
-rw-r--r--JavaScriptCore/wtf/ThreadingPthreads.cpp89
-rw-r--r--JavaScriptCore/wtf/ThreadingQt.cpp72
-rw-r--r--JavaScriptCore/wtf/ThreadingWin.cpp366
-rw-r--r--JavaScriptCore/wtf/Vector.h25
-rw-r--r--JavaScriptCore/wtf/VectorTraits.h3
-rw-r--r--JavaScriptCore/wtf/dtoa.cpp2439
-rw-r--r--JavaScriptCore/wtf/dtoa.h38
-rw-r--r--JavaScriptCore/wtf/unicode/Unicode.h13
-rw-r--r--JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp2
-rw-r--r--JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h8
-rw-r--r--JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h9
-rw-r--r--JavaScriptCore/wtf/win/MainThreadWin.cpp2
51 files changed, 4386 insertions, 529 deletions
diff --git a/JavaScriptCore/wtf/ASCIICType.h b/JavaScriptCore/wtf/ASCIICType.h
index b1ee3dc..0c2ca70 100644
--- a/JavaScriptCore/wtf/ASCIICType.h
+++ b/JavaScriptCore/wtf/ASCIICType.h
@@ -44,6 +44,13 @@
namespace WTF {
+ inline bool isASCII(char c) { return !(c & ~0x7F); }
+ inline bool isASCII(unsigned short c) { return !(c & ~0x7F); }
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+ inline bool isASCII(wchar_t c) { return !(c & ~0x7F); }
+#endif
+ inline bool isASCII(int c) { return !(c & ~0x7F); }
+
inline bool isASCIIAlpha(char c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
inline bool isASCIIAlpha(unsigned short c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
diff --git a/JavaScriptCore/wtf/AVLTree.h b/JavaScriptCore/wtf/AVLTree.h
index cd1511f..18db8ff 100644
--- a/JavaScriptCore/wtf/AVLTree.h
+++ b/JavaScriptCore/wtf/AVLTree.h
@@ -29,12 +29,12 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef KJS_AVL_TREE_H_
-#define KJS_AVL_TREE_H_
+#ifndef AVL_TREE_H_
+#define AVL_TREE_H_
#include "Assertions.h"
-namespace JSC {
+namespace WTF {
// Here is the reference class for BSet.
//
@@ -203,17 +203,19 @@ public:
break;
}
cmp = -target_cmp;
- } else if (target_cmp != 0)
- if (!((cmp ^ target_cmp) & MASK_HIGH_BIT))
+ } else if (target_cmp != 0) {
+ if (!((cmp ^ target_cmp) & MASK_HIGH_BIT)) {
// cmp and target_cmp are both negative or both positive.
depth = d;
- h = cmp < 0 ? get_lt(h) : get_gt(h);
- if (h == null())
- break;
- branch[d] = cmp > 0;
- path_h[d++] = h;
+ }
}
+ h = cmp < 0 ? get_lt(h) : get_gt(h);
+ if (h == null())
+ break;
+ branch[d] = cmp > 0;
+ path_h[d++] = h;
}
+ }
void start_iter_least(AVLTree &tree)
{
@@ -822,7 +824,7 @@ AVLTree<Abstractor, maxDepth, BSet>::remove(key k)
cmp_shortened_sub_with_path = cmp;
// Get the handle of the opposite child, which may not be null.
- child = cmp > 0 ? get_lt(h, false) : get_gt(h, false);
+ child = cmp > 0 ? get_lt(h) : get_gt(h);
}
if (parent == null())
@@ -841,8 +843,8 @@ AVLTree<Abstractor, maxDepth, BSet>::remove(key k)
if (h != rm) {
// Poke in the replacement for the node to be removed.
- set_lt(h, get_lt(rm, false));
- set_gt(h, get_gt(rm, false));
+ set_lt(h, get_lt(rm));
+ set_gt(h, get_gt(rm));
set_bf(h, get_bf(rm));
if (parent_rm == null())
abs.root = h;
@@ -934,8 +936,8 @@ AVLTree<Abstractor, maxDepth, BSet>::subst(handle new_node)
}
/* Copy tree housekeeping fields from node in tree to new node. */
- set_lt(new_node, get_lt(h, false));
- set_gt(new_node, get_gt(h, false));
+ set_lt(new_node, get_lt(h));
+ set_gt(new_node, get_gt(h));
set_bf(new_node, get_bf(h));
if (parent == null())
@@ -952,7 +954,6 @@ AVLTree<Abstractor, maxDepth, BSet>::subst(handle new_node)
return h;
}
-
}
#endif
diff --git a/JavaScriptCore/wtf/AlwaysInline.h b/JavaScriptCore/wtf/AlwaysInline.h
index d39b2b9..64fdd99 100644
--- a/JavaScriptCore/wtf/AlwaysInline.h
+++ b/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/JavaScriptCore/wtf/Assertions.cpp b/JavaScriptCore/wtf/Assertions.cpp
index 98de91c..6e04fe1 100644
--- a/JavaScriptCore/wtf/Assertions.cpp
+++ b/JavaScriptCore/wtf/Assertions.cpp
@@ -34,7 +34,7 @@
#include <CoreFoundation/CFString.h>
#endif
-#if COMPILER(MSVC)
+#if COMPILER(MSVC) && !PLATFORM(WIN_CE)
#ifndef WINVER
#define WINVER 0x0500
#endif
@@ -66,7 +66,7 @@ static void vprintf_stderr_common(const char* format, va_list args)
CFRelease(str);
CFRelease(cfFormat);
} else
-#elif COMPILER(MSVC)
+#elif COMPILER(MSVC) && !PLATFORM(WIN_CE)
if (IsDebuggerPresent()) {
size_t size = 1024;
diff --git a/JavaScriptCore/wtf/Assertions.h b/JavaScriptCore/wtf/Assertions.h
index 8449563..c17e501 100644
--- a/JavaScriptCore/wtf/Assertions.h
+++ b/JavaScriptCore/wtf/Assertions.h
@@ -120,11 +120,22 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann
/* CRASH -- gets us into the debugger or the crash reporter -- signals are ignored by the crash reporter so we must do better */
#ifndef CRASH
-#define CRASH() *(int *)(uintptr_t)0xbbadbeef = 0
+#define CRASH() do { \
+ *(int *)(uintptr_t)0xbbadbeef = 0; \
+ ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
+} while(false)
#endif
/* ASSERT, ASSERT_WITH_MESSAGE, ASSERT_NOT_REACHED */
+#if PLATFORM(WIN_CE)
+/* FIXME: We include this here only to avoid a conflict with the ASSERT macro. */
+#include <windows.h>
+#undef min
+#undef max
+#undef ERROR
+#endif
+
#if PLATFORM(WIN_OS)
/* FIXME: Change to use something other than ASSERT to avoid this conflict with win32. */
#undef ASSERT
@@ -135,6 +146,7 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann
#define ASSERT(assertion) ((void)0)
#define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0)
#define ASSERT_NOT_REACHED() ((void)0)
+#define ASSERT_UNUSED(variable, assertion) ((void)variable)
#else
@@ -159,6 +171,8 @@ while (0)
CRASH(); \
} while (0)
+#define ASSERT_UNUSED(variable, assertion) ASSERT(assertion)
+
#endif
/* ASSERT_ARG */
diff --git a/JavaScriptCore/wtf/ByteArray.cpp b/JavaScriptCore/wtf/ByteArray.cpp
new file mode 100644
index 0000000..526f147
--- /dev/null
+++ b/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/JavaScriptCore/wtf/ByteArray.h b/JavaScriptCore/wtf/ByteArray.h
new file mode 100644
index 0000000..865c30e
--- /dev/null
+++ b/JavaScriptCore/wtf/ByteArray.h
@@ -0,0 +1,81 @@
+/*
+ * 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)
+ : RefCountedBase(1)
+ , m_size(size)
+ {
+ }
+ size_t m_size;
+ unsigned char m_data[sizeof(size_t)];
+ };
+}
+
+#endif
diff --git a/JavaScriptCore/wtf/CONTRIBUTORS.pthreads-win32 b/JavaScriptCore/wtf/CONTRIBUTORS.pthreads-win32
new file mode 100644
index 0000000..7de0f26
--- /dev/null
+++ b/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/JavaScriptCore/wtf/CurrentTime.cpp b/JavaScriptCore/wtf/CurrentTime.cpp
new file mode 100644
index 0000000..d9ea448
--- /dev/null
+++ b/JavaScriptCore/wtf/CurrentTime.cpp
@@ -0,0 +1,246 @@
+/*
+ * 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(MAC)
+#include <CoreFoundation/CFDate.h>
+#elif PLATFORM(GTK)
+#include <glib.h>
+#elif PLATFORM(WX)
+#include <wx/datetime.h>
+#elif PLATFORM(WIN_OS)
+// If defined, WIN32_LEAN_AND_MEAN disables timeBeginPeriod/timeEndPeriod.
+#undef WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <math.h>
+#include <stdint.h>
+#include <sys/timeb.h>
+#include <sys/types.h>
+#include <time.h>
+#else // Posix systems relying on the gettimeofday()
+#include <sys/time.h>
+#endif
+
+namespace WTF {
+
+const double msPerSecond = 1000.0;
+
+#if PLATFORM(MAC)
+
+double currentTime()
+{
+ return CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970;
+}
+
+#elif PLATFORM(GTK)
+
+// Note: GTK on Windows will pick up the PLATFORM(WIN) implementation above which provides
+// better accuracy compared with Windows implementation of g_get_current_time:
+// (http://www.google.com/codesearch/p?hl=en#HHnNRjks1t0/glib-2.5.2/glib/gmain.c&q=g_get_current_time).
+// Non-Windows GTK builds could use gettimeofday() directly but for the sake of consistency lets use GTK function.
+double currentTime()
+{
+ GTimeVal now;
+ g_get_current_time(&now);
+ return static_cast<double>(now.tv_sec) + static_cast<double>(now.tv_usec / 1000000.0);
+}
+
+#elif PLATFORM(WX)
+
+double currentTime()
+{
+ wxDateTime now = wxDateTime::UNow();
+ return (double)now.GetTicks() + (double)(now.GetMillisecond() / 1000.0);
+}
+
+#elif PLATFORM(WIN_OS)
+
+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(WIN_CE)
+ 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 // PLATFORM(WIN_CE)
+ struct _timeb timebuffer;
+ _ftime(&timebuffer);
+ return timebuffer.time * msPerSecond + timebuffer.millitm;
+#endif // PLATFORM(WIN_CE)
+}
+
+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;
+}
+
+#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
+
+#if PLATFORM(ANDROID)
+
+uint32_t get_thread_msec()
+{
+#if defined(HAVE_POSIX_CLOCKS)
+ struct timespec tm;
+
+ clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm);
+ return tm.tv_sec * 1000LL + tm.tv_nsec / 1000000;
+#else
+ struct timeval now;
+ struct timezone zone;
+
+ gettimeofday(&now, &zone);
+ return now.tv_sec * 1000LL + now.tv_usec / 1000;
+#endif
+}
+
+#endif
+
+} // namespace WTF
diff --git a/JavaScriptCore/wtf/CurrentTime.h b/JavaScriptCore/wtf/CurrentTime.h
new file mode 100644
index 0000000..f70f98f
--- /dev/null
+++ b/JavaScriptCore/wtf/CurrentTime.h
@@ -0,0 +1,51 @@
+/*
+ * 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
+ // then a millisecond.
+ double currentTime();
+
+#if PLATFORM(ANDROID)
+ uint32_t get_thread_msec();
+#endif
+
+} // namespace WTF
+
+using WTF::currentTime;
+
+#endif // CurrentTime_h
+
diff --git a/JavaScriptCore/wtf/FastMalloc.cpp b/JavaScriptCore/wtf/FastMalloc.cpp
index 8f7d5ef..88c10ca 100644
--- a/JavaScriptCore/wtf/FastMalloc.cpp
+++ b/JavaScriptCore/wtf/FastMalloc.cpp
@@ -191,7 +191,7 @@ void* fastMalloc(size_t n)
ASSERT(!isForbidden());
void* result = malloc(n);
if (!result)
- abort();
+ CRASH();
return result;
}
@@ -206,7 +206,7 @@ void* fastCalloc(size_t n_elements, size_t element_size)
ASSERT(!isForbidden());
void* result = calloc(n_elements, element_size);
if (!result)
- abort();
+ CRASH();
return result;
}
@@ -227,33 +227,17 @@ void* fastRealloc(void* p, size_t n)
ASSERT(!isForbidden());
void* result = realloc(p, n);
if (!result)
- abort();
+ CRASH();
return result;
}
void releaseFastMallocFreeMemory() { }
-
-#if HAVE(VIRTUALALLOC)
-void* fastMallocExecutable(size_t n)
-{
- return VirtualAlloc(0, n, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
-}
-
-void fastFreeExecutable(void* p)
-{
- VirtualFree(p, 0, MEM_RELEASE);
-}
-#else
-void* fastMallocExecutable(size_t n)
+
+FastMallocStatistics fastMallocStatistics()
{
- return fastMalloc(n);
-}
-
-void fastFreeExecutable(void* p)
-{
- fastFree(p);
+ FastMallocStatistics statistics = { 0, 0, 0, 0 };
+ return statistics;
}
-#endif
} // namespace WTF
@@ -686,11 +670,11 @@ static void InitSizeClasses() {
// Do some sanity checking on add_amount[]/shift_amount[]/class_array[]
if (ClassIndex(0) < 0) {
MESSAGE("Invalid class index %d for size 0\n", ClassIndex(0));
- abort();
+ CRASH();
}
if (static_cast<size_t>(ClassIndex(kMaxSize)) >= sizeof(class_array)) {
MESSAGE("Invalid class index %d for kMaxSize\n", ClassIndex(kMaxSize));
- abort();
+ CRASH();
}
// Compute the size classes we want to use
@@ -742,7 +726,7 @@ static void InitSizeClasses() {
if (sc != kNumClasses) {
MESSAGE("wrong number of size classes: found %" PRIuS " instead of %d\n",
sc, int(kNumClasses));
- abort();
+ CRASH();
}
// Initialize the mapping arrays
@@ -760,25 +744,25 @@ static void InitSizeClasses() {
const size_t sc = SizeClass(size);
if (sc == 0) {
MESSAGE("Bad size class %" PRIuS " for %" PRIuS "\n", sc, size);
- abort();
+ CRASH();
}
if (sc > 1 && size <= class_to_size[sc-1]) {
MESSAGE("Allocating unnecessarily large class %" PRIuS " for %" PRIuS
"\n", sc, size);
- abort();
+ CRASH();
}
if (sc >= kNumClasses) {
MESSAGE("Bad size class %" PRIuS " for %" PRIuS "\n", sc, size);
- abort();
+ CRASH();
}
const size_t s = class_to_size[sc];
if (size > s) {
MESSAGE("Bad size %" PRIuS " for %" PRIuS " (sc = %" PRIuS ")\n", s, size, sc);
- abort();
+ CRASH();
}
if (s == 0) {
MESSAGE("Bad size %" PRIuS " for %" PRIuS " (sc = %" PRIuS ")\n", s, size, sc);
- abort();
+ CRASH();
}
}
@@ -861,7 +845,7 @@ class PageHeapAllocator {
if (free_avail_ < kAlignedSize) {
// Need more room
free_area_ = reinterpret_cast<char*>(MetaDataAlloc(kAllocIncrement));
- if (free_area_ == NULL) abort();
+ if (free_area_ == NULL) CRASH();
free_avail_ = kAllocIncrement;
}
result = free_area_;
@@ -995,7 +979,6 @@ static ALWAYS_INLINE bool DLL_IsEmpty(const Span* list) {
return list->next == list;
}
-#ifndef WTF_CHANGES
static int DLL_Length(const Span* list) {
int result = 0;
for (Span* s = list->next; s != list; s = s->next) {
@@ -1003,7 +986,6 @@ static int DLL_Length(const Span* list) {
}
return result;
}
-#endif
#if 0 /* Not needed at the moment -- causes compiler warnings if not used */
static void DLL_Print(const char* label, const Span* list) {
@@ -1055,11 +1037,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;
};
// -------------------------------------------------------------------------
@@ -1109,6 +1110,8 @@ class TCMalloc_PageHeap {
pagemap_.Ensure(p, 1);
return GetDescriptor(p);
}
+
+ size_t ReturnedBytes() const;
#endif
// Dump state to stderr
@@ -1491,6 +1494,21 @@ void TCMalloc_PageHeap::RegisterSizeClass(Span* span, size_t sc) {
pagemap_.set(span->start+i, span);
}
}
+
+#ifdef WTF_CHANGES
+size_t TCMalloc_PageHeap::ReturnedBytes() const {
+ size_t result = 0;
+ for (unsigned s = 0; s < kMaxPages; s++) {
+ const int r_length = DLL_Length(&free_[s].returned);
+ unsigned r_pages = s * r_length;
+ result += r_pages << kPageShift;
+ }
+
+ for (Span* s = large_.returned.next; s != &large_.returned; s = s->next)
+ result += s->length << kPageShift;
+ return result;
+}
+#endif
#ifndef WTF_CHANGES
static double PagesToMB(uint64_t pages) {
@@ -3023,7 +3041,7 @@ static inline void* SpanToMallocResult(Span *span) {
}
#ifdef WTF_CHANGES
-template <bool abortOnFailure>
+template <bool crashOnFailure>
#endif
static ALWAYS_INLINE void* do_malloc(size_t size) {
void* ret = NULL;
@@ -3056,8 +3074,8 @@ static ALWAYS_INLINE void* do_malloc(size_t size) {
}
if (!ret) {
#ifdef WTF_CHANGES
- if (abortOnFailure) // This branch should be optimized out by the compiler.
- abort();
+ if (crashOnFailure) // This branch should be optimized out by the compiler.
+ CRASH();
#else
errno = ENOMEM;
#endif
@@ -3226,9 +3244,9 @@ static inline struct mallinfo do_mallinfo() {
#ifndef WTF_CHANGES
extern "C"
#else
-#define do_malloc do_malloc<abortOnFailure>
+#define do_malloc do_malloc<crashOnFailure>
-template <bool abortOnFailure>
+template <bool crashOnFailure>
void* malloc(size_t);
void* fastMalloc(size_t size)
@@ -3241,7 +3259,7 @@ void* tryFastMalloc(size_t size)
return malloc<false>(size);
}
-template <bool abortOnFailure>
+template <bool crashOnFailure>
ALWAYS_INLINE
#endif
void* malloc(size_t size) {
@@ -3265,7 +3283,7 @@ void free(void* ptr) {
#ifndef WTF_CHANGES
extern "C"
#else
-template <bool abortOnFailure>
+template <bool crashOnFailure>
void* calloc(size_t, size_t);
void* fastCalloc(size_t n, size_t elem_size)
@@ -3278,7 +3296,7 @@ void* tryFastCalloc(size_t n, size_t elem_size)
return calloc<false>(n, elem_size);
}
-template <bool abortOnFailure>
+template <bool crashOnFailure>
ALWAYS_INLINE
#endif
void* calloc(size_t n, size_t elem_size) {
@@ -3298,6 +3316,8 @@ void* calloc(size_t n, size_t elem_size) {
return result;
}
+// Since cfree isn't used anywhere, we don't compile it in.
+#ifndef WTF_CHANGES
#ifndef WTF_CHANGES
extern "C"
#endif
@@ -3307,11 +3327,12 @@ void cfree(void* ptr) {
#endif
do_free(ptr);
}
+#endif
#ifndef WTF_CHANGES
extern "C"
#else
-template <bool abortOnFailure>
+template <bool crashOnFailure>
void* realloc(void*, size_t);
void* fastRealloc(void* old_ptr, size_t new_size)
@@ -3324,7 +3345,7 @@ void* tryFastRealloc(void* old_ptr, size_t new_size)
return realloc<false>(old_ptr, new_size);
}
-template <bool abortOnFailure>
+template <bool crashOnFailure>
ALWAYS_INLINE
#endif
void* realloc(void* old_ptr, size_t new_size) {
@@ -3385,16 +3406,6 @@ void* realloc(void* old_ptr, size_t new_size) {
}
}
-void* fastMallocExecutable(size_t n)
-{
- return malloc<false>(n);
-}
-
-void fastFreeExecutable(void* p)
-{
- free(p);
-}
-
#ifdef WTF_CHANGES
#undef do_malloc
#else
@@ -3821,13 +3832,41 @@ void FastMallocZone::init()
#endif
+#if WTF_CHANGES
void releaseFastMallocFreeMemory()
{
+ // Flush free pages in the current thread cache back to the page heap.
+ // Low watermark mechanism in Scavenge() prevents full return on the first pass.
+ // The second pass flushes everything.
+ if (TCMalloc_ThreadCache* threadCache = TCMalloc_ThreadCache::GetCacheIfPresent()) {
+ threadCache->Scavenge();
+ threadCache->Scavenge();
+ }
+
SpinLockHolder h(&pageheap_lock);
pageheap->ReleaseFreePages();
}
+
+FastMallocStatistics fastMallocStatistics()
+{
+ FastMallocStatistics statistics;
+ {
+ SpinLockHolder lockHolder(&pageheap_lock);
+ statistics.heapSize = static_cast<size_t>(pageheap->SystemBytes());
+ statistics.freeSizeInHeap = static_cast<size_t>(pageheap->FreeBytes());
+ statistics.returnedSize = pageheap->ReturnedBytes();
+ statistics.freeSizeInCaches = 0;
+ for (TCMalloc_ThreadCache* threadCache = thread_heaps; threadCache ; threadCache = threadCache->next_)
+ statistics.freeSizeInCaches += threadCache->Size();
+ }
+ for (unsigned cl = 0; cl < kNumClasses; ++cl) {
+ const int length = central_cache[cl].length();
+ const int tc_length = central_cache[cl].tc_length();
+ statistics.freeSizeInCaches += ByteSizeForClass(cl) * (length + tc_length);
+ }
+ return statistics;
+}
-#if WTF_CHANGES
} // namespace WTF
#endif
diff --git a/JavaScriptCore/wtf/FastMalloc.h b/JavaScriptCore/wtf/FastMalloc.h
index fb2762c..f1264ac 100644
--- a/JavaScriptCore/wtf/FastMalloc.h
+++ b/JavaScriptCore/wtf/FastMalloc.h
@@ -27,7 +27,7 @@
namespace WTF {
- // These functions call abort() if an allocation fails.
+ // These functions call CRASH() if an allocation fails.
void* fastMalloc(size_t n);
void* fastZeroedMalloc(size_t n);
void* fastCalloc(size_t n_elements, size_t element_size);
@@ -41,15 +41,20 @@ namespace WTF {
void fastFree(void* p);
- void* fastMallocExecutable(size_t n);
- void fastFreeExecutable(void* p);
-
#ifndef NDEBUG
void fastMallocForbid();
void fastMallocAllow();
#endif
void releaseFastMallocFreeMemory();
+
+ struct FastMallocStatistics {
+ size_t heapSize;
+ size_t freeSizeInHeap;
+ size_t freeSizeInCaches;
+ size_t returnedSize;
+ };
+ FastMallocStatistics fastMallocStatistics();
} // namespace WTF
diff --git a/JavaScriptCore/wtf/HashCountedSet.h b/JavaScriptCore/wtf/HashCountedSet.h
index 8095a2b..6fc0234 100644
--- a/JavaScriptCore/wtf/HashCountedSet.h
+++ b/JavaScriptCore/wtf/HashCountedSet.h
@@ -1,6 +1,5 @@
/*
- * This file is part of the KDE libraries
- * Copyright (C) 2005 Apple Computer, Inc.
+ * Copyright (C) 2005, 2006, 2008 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
diff --git a/JavaScriptCore/wtf/HashFunctions.h b/JavaScriptCore/wtf/HashFunctions.h
index 2c66a2d..13afb72 100644
--- a/JavaScriptCore/wtf/HashFunctions.h
+++ b/JavaScriptCore/wtf/HashFunctions.h
@@ -173,6 +173,9 @@ namespace WTF {
template<typename P> struct DefaultHash<RefPtr<P> > { typedef PtrHash<RefPtr<P> > Hash; };
template<typename T, typename U> struct DefaultHash<std::pair<T, U> > { typedef PairHash<T, U> Hash; };
+
+ // Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
+ static const unsigned stringHashingStartValue = 0x9e3779b9U;
} // namespace WTF
diff --git a/JavaScriptCore/wtf/HashTable.cpp b/JavaScriptCore/wtf/HashTable.cpp
index f1f2a4f..71d3f86 100644
--- a/JavaScriptCore/wtf/HashTable.cpp
+++ b/JavaScriptCore/wtf/HashTable.cpp
@@ -34,9 +34,17 @@ int HashTableStats::numReinserts;
static HashTableStats logger;
+static Mutex& hashTableStatsMutex()
+{
+ AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
+ return mutex;
+}
+
HashTableStats::~HashTableStats()
{
- printf("\nkhtml::HashTable statistics\n\n");
+ // Don't lock hashTableStatsMutex here because it can cause deadlocks at shutdown
+ // if any thread was killed while holding the mutex.
+ printf("\nWTF::HashTable statistics\n\n");
printf("%d accesses\n", numAccesses);
printf("%d total collisions, average %.2f probes per access\n", numCollisions, 1.0 * (numAccesses + numCollisions) / numAccesses);
printf("longest collision chain: %d\n", maxCollisions);
@@ -49,6 +57,7 @@ HashTableStats::~HashTableStats()
void HashTableStats::recordCollisionAtCount(int count)
{
+ MutexLocker lock(hashTableStatsMutex());
if (count > maxCollisions)
maxCollisions = count;
numCollisions++;
diff --git a/JavaScriptCore/wtf/HashTable.h b/JavaScriptCore/wtf/HashTable.h
index 4c7790a..3b283f8 100644
--- a/JavaScriptCore/wtf/HashTable.h
+++ b/JavaScriptCore/wtf/HashTable.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 David Levin <levin@chromium.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -24,6 +25,7 @@
#include "FastMalloc.h"
#include "HashTraits.h"
#include <wtf/Assertions.h>
+#include <wtf/Threading.h>
namespace WTF {
@@ -42,13 +44,19 @@ namespace WTF {
struct HashTableStats {
~HashTableStats();
+ // All of the variables are accessed in ~HashTableStats when the static struct is destroyed.
+
+ // The following variables are all atomically incremented when modified.
static int numAccesses;
- static int numCollisions;
- static int collisionGraph[4096];
- static int maxCollisions;
static int numRehashes;
static int numRemoves;
static int numReinserts;
+
+ // The following variables are only modified in the recordCollisionAtCount method within a mutex.
+ static int maxCollisions;
+ static int numCollisions;
+ static int collisionGraph[4096];
+
static void recordCollisionAtCount(int count);
};
@@ -201,6 +209,8 @@ namespace WTF {
#if CHECK_HASHTABLE_ITERATORS
public:
+ // Any modifications of the m_next or m_previous of an iterator that is in a linked list of a HashTable::m_iterator,
+ // should be guarded with m_table->m_mutex.
mutable const HashTableType* m_table;
mutable const_iterator* m_next;
mutable const_iterator* m_previous;
@@ -397,7 +407,9 @@ namespace WTF {
#if CHECK_HASHTABLE_ITERATORS
public:
+ // All access to m_iterators should be guarded with m_mutex.
mutable const_iterator* m_iterators;
+ mutable Mutex m_mutex;
#endif
};
@@ -466,7 +478,7 @@ namespace WTF {
return 0;
#if DUMP_HASHTABLE_STATS
- ++HashTableStats::numAccesses;
+ atomicIncrement(&HashTableStats::numAccesses);
int probeCount = 0;
#endif
@@ -511,7 +523,7 @@ namespace WTF {
int i = h & sizeMask;
#if DUMP_HASHTABLE_STATS
- ++HashTableStats::numAccesses;
+ atomicIncrement(&HashTableStats::numAccesses);
int probeCount = 0;
#endif
@@ -563,7 +575,7 @@ namespace WTF {
int i = h & sizeMask;
#if DUMP_HASHTABLE_STATS
- ++HashTableStats::numAccesses;
+ atomicIncrement(&HashTableStats::numAccesses);
int probeCount = 0;
#endif
@@ -623,7 +635,7 @@ namespace WTF {
int i = h & sizeMask;
#if DUMP_HASHTABLE_STATS
- ++HashTableStats::numAccesses;
+ atomicIncrement(&HashTableStats::numAccesses);
int probeCount = 0;
#endif
@@ -738,7 +750,7 @@ namespace WTF {
ASSERT(!lookupForWriting(Extractor::extract(entry)).second);
ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).first)));
#if DUMP_HASHTABLE_STATS
- ++HashTableStats::numReinserts;
+ atomicIncrement(&HashTableStats::numReinserts);
#endif
Mover<ValueType, Traits::needsDestruction>::move(entry, *lookupForWriting(Extractor::extract(entry)).first);
@@ -801,7 +813,7 @@ namespace WTF {
void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::remove(ValueType* pos)
{
#if DUMP_HASHTABLE_STATS
- ++HashTableStats::numRemoves;
+ atomicIncrement(&HashTableStats::numRemoves);
#endif
deleteBucket(*pos);
@@ -887,7 +899,7 @@ namespace WTF {
#if DUMP_HASHTABLE_STATS
if (oldTableSize != 0)
- ++HashTableStats::numRehashes;
+ atomicIncrement(&HashTableStats::numRehashes);
#endif
m_tableSize = newTableSize;
@@ -1016,6 +1028,7 @@ namespace WTF {
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::invalidateIterators()
{
+ MutexLocker lock(m_mutex);
const_iterator* next;
for (const_iterator* p = m_iterators; p; p = next) {
next = p->m_next;
@@ -1037,6 +1050,7 @@ namespace WTF {
if (!table) {
it->m_next = 0;
} else {
+ MutexLocker lock(table->m_mutex);
ASSERT(table->m_iterators != it);
it->m_next = table->m_iterators;
table->m_iterators = it;
@@ -1058,6 +1072,7 @@ namespace WTF {
ASSERT(!it->m_next);
ASSERT(!it->m_previous);
} else {
+ MutexLocker lock(it->m_table->m_mutex);
if (it->m_next) {
ASSERT(it->m_next->m_previous == it);
it->m_next->m_previous = it->m_previous;
diff --git a/JavaScriptCore/wtf/ListHashSet.h b/JavaScriptCore/wtf/ListHashSet.h
index 2f75c33..38cc998 100644
--- a/JavaScriptCore/wtf/ListHashSet.h
+++ b/JavaScriptCore/wtf/ListHashSet.h
@@ -60,6 +60,8 @@ namespace WTF {
typedef ListHashSetNodeHashFunctions<ValueArg, HashArg> NodeHash;
typedef HashTable<Node*, Node*, IdentityExtractor<Node*>, NodeHash, NodeTraits, NodeTraits> ImplType;
+ typedef HashTableIterator<Node*, Node*, IdentityExtractor<Node*>, NodeHash, NodeTraits, NodeTraits> ImplTypeIterator;
+ typedef HashTableConstIterator<Node*, Node*, IdentityExtractor<Node*>, NodeHash, NodeTraits, NodeTraits> ImplTypeConstIterator;
typedef HashArg HashFunctions;
@@ -441,7 +443,7 @@ namespace WTF {
inline typename ListHashSet<T, U>::iterator ListHashSet<T, U>::find(const ValueType& value)
{
typedef ListHashSetTranslator<ValueType, HashFunctions> Translator;
- typename ImplType::iterator it = m_impl.template find<ValueType, Translator>(value);
+ ImplTypeIterator it = m_impl.template find<ValueType, Translator>(value);
if (it == m_impl.end())
return end();
return makeIterator(*it);
@@ -451,7 +453,7 @@ namespace WTF {
inline typename ListHashSet<T, U>::const_iterator ListHashSet<T, U>::find(const ValueType& value) const
{
typedef ListHashSetTranslator<ValueType, HashFunctions> Translator;
- typename ImplType::const_iterator it = m_impl.template find<ValueType, Translator>(value);
+ ImplTypeConstIterator it = m_impl.template find<ValueType, Translator>(value);
if (it == m_impl.end())
return end();
return makeConstIterator(*it);
diff --git a/JavaScriptCore/wtf/MainThread.cpp b/JavaScriptCore/wtf/MainThread.cpp
index 6fe3021..c7a6caa 100644
--- a/JavaScriptCore/wtf/MainThread.cpp
+++ b/JavaScriptCore/wtf/MainThread.cpp
@@ -29,6 +29,7 @@
#include "config.h"
#include "MainThread.h"
+#include "StdLibExtras.h"
#include "Threading.h"
#include "Vector.h"
@@ -49,17 +50,17 @@ struct FunctionWithContext {
typedef Vector<FunctionWithContext> FunctionQueue;
-static bool callbacksPaused; // This global varialble is only accessed from main thread.
+static bool callbacksPaused; // This global variable is only accessed from main thread.
Mutex& mainThreadFunctionQueueMutex()
{
- static Mutex staticMutex;
+ DEFINE_STATIC_LOCAL(Mutex, staticMutex, ());
return staticMutex;
}
static FunctionQueue& functionQueue()
{
- static FunctionQueue staticFunctionQueue;
+ DEFINE_STATIC_LOCAL(FunctionQueue, staticFunctionQueue, ());
return staticFunctionQueue;
}
diff --git a/JavaScriptCore/wtf/MathExtras.h b/JavaScriptCore/wtf/MathExtras.h
index cfe5468..76488b4 100644
--- a/JavaScriptCore/wtf/MathExtras.h
+++ b/JavaScriptCore/wtf/MathExtras.h
@@ -28,7 +28,6 @@
#include <math.h>
#include <stdlib.h>
-#include <time.h>
#if PLATFORM(SOLARIS)
#include <ieeefp.h>
@@ -40,8 +39,11 @@
#endif
#if COMPILER(MSVC)
-
+#if PLATFORM(WIN_CE)
+#include <stdlib.h>
+#else
#include <xmath.h>
+#endif
#include <limits>
#if HAVE(FLOAT_H)
@@ -100,17 +102,22 @@ inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x
#endif
-#if COMPILER(MSVC)
+#if COMPILER(MSVC) || COMPILER(RVCT)
-inline bool isinf(double num) { return !_finite(num) && !_isnan(num); }
-inline bool isnan(double num) { return !!_isnan(num); }
inline long lround(double num) { return static_cast<long>(num > 0 ? num + 0.5 : ceil(num - 0.5)); }
inline long lroundf(float num) { return static_cast<long>(num > 0 ? num + 0.5f : ceilf(num - 0.5f)); }
inline double round(double num) { return num > 0 ? floor(num + 0.5) : ceil(num - 0.5); }
inline float roundf(float num) { return num > 0 ? floorf(num + 0.5f) : ceilf(num - 0.5f); }
-inline bool signbit(double num) { return _copysign(1.0, num) < 0; }
inline double trunc(double num) { return num > 0 ? floor(num) : ceil(num); }
+#endif
+
+#if COMPILER(MSVC)
+
+inline bool isinf(double num) { return !_finite(num) && !_isnan(num); }
+inline bool isnan(double num) { return !!_isnan(num); }
+inline bool signbit(double num) { return _copysign(1.0, num) < 0; }
+
inline double nextafter(double x, double y) { return _nextafter(x, y); }
inline float nextafterf(float x, float y) { return x > y ? x - FLT_EPSILON : x + FLT_EPSILON; }
@@ -150,45 +157,14 @@ inline double wtf_pow(double x, double y) { return y == 0 ? 1 : pow(x, y); }
#define fmod(x, y) wtf_fmod(x, y)
#define pow(x, y) wtf_pow(x, y)
-#if defined(_CRT_RAND_S)
-// Initializes the random number generator.
-inline void wtf_random_init()
-{
- // No need to initialize for rand_s.
-}
-
-// Returns a pseudo-random number in the range [0, 1).
-inline double wtf_random()
-{
- unsigned u;
- rand_s(&u);
-
- return static_cast<double>(u) / (static_cast<double>(UINT_MAX) + 1.0);
-}
-#endif // _CRT_RAND_S
-
#endif // COMPILER(MSVC)
-#if !COMPILER(MSVC) || !defined(_CRT_RAND_S)
-
-// Initializes the random number generator.
-inline void wtf_random_init()
-{
- srand(static_cast<unsigned>(time(0)));
-}
-
-// Returns a pseudo-random number in the range [0, 1).
-inline double wtf_random()
-{
- return static_cast<double>(rand()) / (static_cast<double>(RAND_MAX) + 1.0);
-}
-
-#endif // #if COMPILER(MSVC)
-
inline double deg2rad(double d) { return d * piDouble / 180.0; }
inline double rad2deg(double r) { return r * 180.0 / piDouble; }
inline double deg2grad(double d) { return d * 400.0 / 360.0; }
inline double grad2deg(double g) { return g * 360.0 / 400.0; }
+inline double turn2deg(double t) { return t * 360.0; }
+inline double deg2turn(double d) { return d / 360.0; }
inline double rad2grad(double r) { return r * 200.0 / piDouble; }
inline double grad2rad(double g) { return g * piDouble / 200.0; }
@@ -196,6 +172,8 @@ inline float deg2rad(float d) { return d * piFloat / 180.0f; }
inline float rad2deg(float r) { return r * 180.0f / piFloat; }
inline float deg2grad(float d) { return d * 400.0f / 360.0f; }
inline float grad2deg(float g) { return g * 360.0f / 400.0f; }
+inline float turn2deg(float t) { return t * 360.0f; }
+inline float deg2turn(float d) { return d / 360.0f; }
inline float rad2grad(float r) { return r * 200.0f / piFloat; }
inline float grad2rad(float g) { return g * piFloat / 200.0f; }
diff --git a/JavaScriptCore/wtf/MessageQueue.h b/JavaScriptCore/wtf/MessageQueue.h
index 481211d..19c5c10 100644
--- a/JavaScriptCore/wtf/MessageQueue.h
+++ b/JavaScriptCore/wtf/MessageQueue.h
@@ -36,6 +36,12 @@
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:
@@ -44,6 +50,7 @@ namespace WTF {
void append(const DataType&);
void prepend(const DataType&);
bool waitForMessage(DataType&);
+ MessageQueueWaitResult waitForMessageTimed(DataType&, double absoluteTime);
void kill();
bool tryGetMessage(DataType&);
@@ -79,7 +86,7 @@ namespace WTF {
inline bool MessageQueue<DataType>::waitForMessage(DataType& result)
{
MutexLocker lock(m_mutex);
-
+
while (!m_killed && m_queue.isEmpty())
m_condition.wait(m_mutex);
@@ -93,6 +100,27 @@ namespace WTF {
}
template<typename DataType>
+ inline MessageQueueWaitResult MessageQueue<DataType>::waitForMessageTimed(DataType& result, double absoluteTime)
+ {
+ MutexLocker lock(m_mutex);
+ bool timedOut = false;
+
+ while (!m_killed && !timedOut && m_queue.isEmpty())
+ timedOut = !m_condition.timedWait(m_mutex, absoluteTime);
+
+ if (m_killed)
+ return MessageQueueTerminated;
+
+ if (timedOut)
+ return MessageQueueTimeout;
+
+ ASSERT(!m_queue.isEmpty());
+ result = m_queue.first();
+ m_queue.removeFirst();
+ return MessageQueueMessageReceived;
+ }
+
+ template<typename DataType>
inline bool MessageQueue<DataType>::tryGetMessage(DataType& result)
{
MutexLocker lock(m_mutex);
@@ -132,5 +160,10 @@ 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/JavaScriptCore/wtf/OwnPtr.h b/JavaScriptCore/wtf/OwnPtr.h
index 969950f..256b55c 100644
--- a/JavaScriptCore/wtf/OwnPtr.h
+++ b/JavaScriptCore/wtf/OwnPtr.h
@@ -22,6 +22,7 @@
#define WTF_OwnPtr_h
#include <algorithm>
+#include <memory>
#include <wtf/Assertions.h>
#include <wtf/Noncopyable.h>
@@ -66,12 +67,17 @@ namespace WTF {
typedef ValueType* PtrType;
explicit OwnPtr(PtrType ptr = 0) : m_ptr(ptr) { }
+ OwnPtr(std::auto_ptr<ValueType> autoPtr) : m_ptr(autoPtr.release()) { }
~OwnPtr() { deleteOwnedPtr(m_ptr); }
PtrType get() const { return m_ptr; }
PtrType release() { PtrType ptr = m_ptr; m_ptr = 0; return ptr; }
+ // FIXME: This should be renamed to adopt.
void set(PtrType ptr) { ASSERT(!ptr || m_ptr != ptr); deleteOwnedPtr(m_ptr); m_ptr = ptr; }
+
+ void adopt(std::auto_ptr<ValueType> autoPtr) { ASSERT(!autoPtr.get() || m_ptr != autoPtr.get()); deleteOwnedPtr(m_ptr); m_ptr = autoPtr.release(); }
+
void clear() { deleteOwnedPtr(m_ptr); m_ptr = 0; }
ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; }
diff --git a/JavaScriptCore/wtf/PassRefPtr.h b/JavaScriptCore/wtf/PassRefPtr.h
index ca8f2cb..c1dc309 100644
--- a/JavaScriptCore/wtf/PassRefPtr.h
+++ b/JavaScriptCore/wtf/PassRefPtr.h
@@ -56,9 +56,12 @@ namespace WTF {
bool operator!() const { return !m_ptr; }
// This conversion operator allows implicit conversion to bool but not to other integer types.
+#if COMPILER(WINSCW)
+ operator bool() const { return m_ptr; }
+#else
typedef T* PassRefPtr::*UnspecifiedBoolType;
operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; }
-
+#endif
PassRefPtr& operator=(T*);
PassRefPtr& operator=(const PassRefPtr&);
template <typename U> PassRefPtr& operator=(const PassRefPtr<U>&);
diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h
index 80a7bf1..fea00c4 100644
--- a/JavaScriptCore/wtf/Platform.h
+++ b/JavaScriptCore/wtf/Platform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 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
@@ -78,15 +78,33 @@
#define WTF_PLATFORM_SOLARIS 1
#endif
+#if defined (__S60__) || defined (__SYMBIAN32__)
+/* we are cross-compiling, it is not really windows */
+#undef WTF_PLATFORM_WIN_OS
+#undef WTF_PLATFORM_WIN
+#undef WTF_PLATFORM_CAIRO
+#define WTF_PLATFORM_S60 1
+#define WTF_PLATFORM_SYMBIAN 1
+#endif
+
+
+/* PLATFORM(NETBSD) */
+/* Operating system level dependencies for NetBSD that should be used */
+/* regardless of operating environment */
+#if defined(__NetBSD__)
+#define WTF_PLATFORM_NETBSD 1
+#endif
+
/* PLATFORM(UNIX) */
/* Operating system level dependencies for Unix-like systems that */
/* should be used regardless of operating environment */
#if PLATFORM(DARWIN) \
|| PLATFORM(FREEBSD) \
+ || PLATFORM(S60) \
+ || PLATFORM(NETBSD) \
|| defined(unix) \
|| defined(__unix) \
|| defined(__unix__) \
- || defined (__NetBSD__) \
|| defined(_AIX)
#define WTF_PLATFORM_UNIX 1
#endif
@@ -126,25 +144,23 @@
#define WTF_PLATFORM_CI 1
#endif
-/* PLATFORM(SKIA) */
+/* PLATFORM(SKIA) for Win/Linux, CG/CI for Mac */
#if PLATFORM(CHROMIUM)
+#if PLATFORM(DARWIN)
+#define WTF_PLATFORM_CG 1
+#define WTF_PLATFORM_CI 1
+#define WTF_USE_ATSUI 1
+#else
#define WTF_PLATFORM_SKIA 1
#endif
+#endif
/* Makes PLATFORM(WIN) default to PLATFORM(CAIRO) */
-#if !PLATFORM(MAC) && !PLATFORM(QT) && !PLATFORM(WX)
+/* FIXME: This should be changed from a blacklist to a whitelist */
+#if !PLATFORM(MAC) && !PLATFORM(QT) && !PLATFORM(WX) && !PLATFORM(CHROMIUM)
#define WTF_PLATFORM_CAIRO 1
#endif
-#ifdef __S60__
-// we are cross-compiling, it is not really windows
-#undef WTF_PLATFORM_WIN_OS
-#undef WTF_PLATFORM_WIN
-#undef WTF_PLATFORM_CAIRO
-#define WTF_PLATFORM_S60 1
-#define WTF_PLATFORM_SYMBIAN 1
-#endif
-
#ifdef ANDROID
#define WTF_PLATFORM_ANDROID 1
#define WTF_PLATFORM_LINUX 1
@@ -228,6 +244,20 @@
#define WTF_PLATFORM_BIG_ENDIAN 1
#endif
+/* PLATFORM(WIN_CE) && 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)
+# include <QtGlobal>
+# undef WTF_PLATFORM_BIG_ENDIAN
+# undef WTF_PLATFORM_MIDDLE_ENDIAN
+# if Q_BYTE_ORDER == Q_BIG_EDIAN
+# define WTF_PLATFORM_BIG_ENDIAN 1
+# endif
+#endif
+
/* Compiler */
/* COMPILER(MSVC) */
@@ -260,6 +290,16 @@
#define WTF_COMPILER_CYGWIN 1
#endif
+/* COMPILER(RVCT) */
+#if defined(__CC_ARM) || defined(__ARMCC__)
+#define WTF_COMPILER_RVCT 1
+#endif
+
+/* COMPILER(WINSCW) */
+#if defined(__WINSCW__)
+#define WTF_COMPILER_WINSCW 1
+#endif
+
#if (PLATFORM(MAC) || PLATFORM(WIN)) && !defined(ENABLE_JSC_MULTIPLE_THREADS)
#define ENABLE_JSC_MULTIPLE_THREADS 1
#endif
@@ -290,6 +330,11 @@
#endif
#endif
+#if PLATFORM(CHROMIUM) && PLATFORM(DARWIN)
+#define WTF_PLATFORM_CF 1
+#define WTF_USE_PTHREADS 1
+#endif
+
#if PLATFORM(WIN)
#define WTF_USE_WININET 1
#endif
@@ -305,9 +350,11 @@
#endif
#endif
+#if !defined(HAVE_ACCESSIBILITY)
#if 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
@@ -327,9 +374,26 @@
#elif PLATFORM(WIN_OS)
#define HAVE_FLOAT_H 1
+#if PLATFORM(WIN_CE)
+#define HAVE_ERRNO_H 0
+#else
#define HAVE_SYS_TIMEB_H 1
+#endif
#define HAVE_VIRTUALALLOC 1
+#elif PLATFORM(SYMBIAN)
+
+#define HAVE_ERRNO_H 1
+#define HAVE_MMAP 0
+#define HAVE_SBRK 1
+
+#define HAVE_SYS_TIME_H 1
+#define HAVE_STRINGS_H 1
+
+#if !COMPILER(RVCT)
+#define HAVE_SYS_PARAM_H 1
+#endif
+
#else
/* FIXME: is this actually used or do other platforms generate their own config.h? */
@@ -402,24 +466,58 @@
#define ENABLE_ARCHIVE 1
#endif
-// CTI only supports x86 at the moment, and has only been tested on Mac and Windows.
-#if !defined(ENABLE_CTI) && PLATFORM(X86) && (PLATFORM(MAC) || PLATFORM(WIN))
-#define ENABLE_CTI 1
+#if !defined(WTF_USE_ALTERNATE_JSIMMEDIATE) && PLATFORM(X86_64) && PLATFORM(MAC)
+#define WTF_USE_ALTERNATE_JSIMMEDIATE 1
#endif
-// WREC only supports x86 at the moment, and has only been tested on Mac and Windows.
-#if !defined(ENABLE_WREC) && ENABLE(CTI) && PLATFORM(X86) && (PLATFORM(MAC) || PLATFORM(WIN))
+#if !defined(ENABLE_JIT)
+/* x86-64 support is under development. */
+#if PLATFORM(X86_64) && PLATFORM(MAC)
+ #define ENABLE_JIT 0
+ #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 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
+/* 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
+#endif
+ #define ENABLE_JIT_OPTIMIZE_CALL 1
+ #define ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS 1
+ #define ENABLE_JIT_OPTIMIZE_ARITHMETIC 1
+#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.
+#endif
+#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
#endif
-#if ENABLE(CTI) || ENABLE(WREC)
-#define ENABLE_MASM 1
+#if ENABLE(JIT) || ENABLE(WREC)
+#define ENABLE_ASSEMBLER 1
#endif
-#if !defined(ENABLE_PAN_SCROLLING) && (PLATFORM(WIN) || PLATFORM(CHROMIUM) || (PLATFORM(WX) && PLATFORM(WIN_OS)))
+#if !defined(ENABLE_PAN_SCROLLING) && PLATFORM(WIN_OS)
#define ENABLE_PAN_SCROLLING 1
#endif
+#if !defined(ENABLE_ACTIVEX_TYPE_CONVERSION_WMPLAYER)
+#define ENABLE_ACTIVEX_TYPE_CONVERSION_WMPLAYER 1
+#endif
+
/* Use the QtXmlStreamReader implementation for XMLTokenizer */
#if PLATFORM(QT)
#if !ENABLE(XSLT)
@@ -427,10 +525,8 @@
#endif
#endif
-// Use "fastcall" calling convention on MSVC
-#if COMPILER(MSVC)
-#define WTF_USE_FAST_CALL_CTI_ARGUMENT 1
-#define WTF_USE_CTI_ARGUMENT 1
+#if !PLATFORM(QT)
+#define WTF_USE_FONT_FAST_PATH 1
#endif
#endif /* WTF_Platform_h */
diff --git a/JavaScriptCore/wtf/PtrAndFlags.h b/JavaScriptCore/wtf/PtrAndFlags.h
new file mode 100644
index 0000000..477e893
--- /dev/null
+++ b/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/JavaScriptCore/wtf/RandomNumber.cpp b/JavaScriptCore/wtf/RandomNumber.cpp
new file mode 100644
index 0000000..c94d5a4
--- /dev/null
+++ b/JavaScriptCore/wtf/RandomNumber.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, 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 COMPUTER, 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 "RandomNumber.h"
+
+#include "RandomNumberSeed.h"
+
+#include <limits>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+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)
+ static bool s_initialized = false;
+ if (!s_initialized) {
+ initializeRandomNumberGenerator();
+ s_initialized = true;
+ }
+#endif
+
+#if COMPILER(MSVC) && defined(_CRT_RAND_S)
+ 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)
+ uint32_t bits = arc4random();
+ return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
+#elif PLATFORM(UNIX)
+ uint32_t part1 = random() & (RAND_MAX - 1);
+ uint32_t part2 = random() & (RAND_MAX - 1);
+ // random only provides 31 bits
+ 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
+ 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
+ uint64_t fullRandom = part1;
+ fullRandom <<= 27;
+ fullRandom |= part2;
+
+ // Mask off the low 53bits
+ fullRandom &= (1LL << 53) - 1;
+ return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53);
+#endif
+}
+
+}
diff --git a/JavaScriptCore/wtf/RandomNumber.h b/JavaScriptCore/wtf/RandomNumber.h
new file mode 100644
index 0000000..fe1687c
--- /dev/null
+++ b/JavaScriptCore/wtf/RandomNumber.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, 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 COMPUTER, 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_RandomNumber_h
+#define WTF_RandomNumber_h
+
+namespace WTF {
+
+ // 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/JavaScriptCore/wtf/RandomNumberSeed.h b/JavaScriptCore/wtf/RandomNumberSeed.h
new file mode 100644
index 0000000..f994fd9
--- /dev/null
+++ b/JavaScriptCore/wtf/RandomNumberSeed.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, 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 COMPUTER, 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_RandomNumberSeed_h
+#define WTF_RandomNumberSeed_h
+
+#include <stdlib.h>
+#include <time.h>
+
+#if HAVE(SYS_TIME_H)
+#include <sys/time.h>
+#endif
+
+#if PLATFORM(UNIX)
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+// Internal JavaScriptCore usage only
+namespace WTF {
+
+inline void initializeRandomNumberGenerator()
+{
+#if PLATFORM(DARWIN)
+ // On Darwin we use arc4random which initialises itself.
+#elif COMPILER(MSVC) && defined(_CRT_RAND_S)
+ // On Windows we use rand_s which intialises itself
+#elif PLATFORM(UNIX)
+ // srandomdev is not guaranteed to exist on linux so we use this poor seed, this should be improved
+ timeval time;
+ gettimeofday(&time, 0);
+ srandom(static_cast<unsigned>(time.tv_usec * getpid()));
+#else
+ srand(static_cast<unsigned>(time(0)));
+#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/JavaScriptCore/wtf/RefCounted.h b/JavaScriptCore/wtf/RefCounted.h
index 2dd5b2a..ac8e167 100644
--- a/JavaScriptCore/wtf/RefCounted.h
+++ b/JavaScriptCore/wtf/RefCounted.h
@@ -75,7 +75,7 @@ protected:
return false;
}
-private:
+protected:
int m_refCount;
#ifndef NDEBUG
bool m_deletionHasBegun;
diff --git a/JavaScriptCore/wtf/RefPtr.h b/JavaScriptCore/wtf/RefPtr.h
index 78bd257..929e745 100644
--- a/JavaScriptCore/wtf/RefPtr.h
+++ b/JavaScriptCore/wtf/RefPtr.h
@@ -62,8 +62,12 @@ namespace WTF {
bool operator!() const { return !m_ptr; }
// This conversion operator allows implicit conversion to bool but not to other integer types.
+#if COMPILER(WINSCW)
+ operator bool() const { return m_ptr; }
+#else
typedef T* RefPtr::*UnspecifiedBoolType;
operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::m_ptr : 0; }
+#endif
RefPtr& operator=(const RefPtr&);
RefPtr& operator=(T*);
diff --git a/JavaScriptCore/wtf/RetainPtr.h b/JavaScriptCore/wtf/RetainPtr.h
index 2d73603..a66a127 100644
--- a/JavaScriptCore/wtf/RetainPtr.h
+++ b/JavaScriptCore/wtf/RetainPtr.h
@@ -1,6 +1,5 @@
/*
- * This file is part of the KDE libraries
- * Copyright (C) 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2005, 2006, 2007, 2008 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
diff --git a/JavaScriptCore/wtf/StdLibExtras.h b/JavaScriptCore/wtf/StdLibExtras.h
new file mode 100644
index 0000000..14227ab
--- /dev/null
+++ b/JavaScriptCore/wtf/StdLibExtras.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ *
+ * 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_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
+// macro also allows workarounds a compiler bug present in Apple's version of GCC 4.0.1.
+#if COMPILER(GCC) && defined(__APPLE_CC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 1
+#define DEFINE_STATIC_LOCAL(type, name, arguments) \
+ static type* name##Ptr = new type arguments; \
+ type& name = *name##Ptr
+#else
+#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 in)
+ {
+ COMPILE_ASSERT(sizeof(TO) == sizeof(FROM), WTF_wtf_reinterpret_cast_sizeof_types_is_equal);
+ union {
+ FROM from;
+ TO to;
+ } u;
+ u.from = in;
+ return u.to;
+ }
+
+} // namespace WTF
+
+#endif
diff --git a/JavaScriptCore/wtf/TCSpinLock.h b/JavaScriptCore/wtf/TCSpinLock.h
index 3c6ac11..d651e31 100644
--- a/JavaScriptCore/wtf/TCSpinLock.h
+++ b/JavaScriptCore/wtf/TCSpinLock.h
@@ -46,7 +46,6 @@
#else
#include <sys/types.h>
#endif
-#include <stdlib.h> /* for abort() */
#if PLATFORM(WIN_OS)
#ifndef WIN32_LEAN_AND_MEAN
@@ -199,16 +198,16 @@ struct TCMalloc_SpinLock {
pthread_mutex_t private_lock_;
inline void Init() {
- if (pthread_mutex_init(&private_lock_, NULL) != 0) abort();
+ if (pthread_mutex_init(&private_lock_, NULL) != 0) CRASH();
}
inline void Finalize() {
- if (pthread_mutex_destroy(&private_lock_) != 0) abort();
+ if (pthread_mutex_destroy(&private_lock_) != 0) CRASH();
}
inline void Lock() {
- if (pthread_mutex_lock(&private_lock_) != 0) abort();
+ if (pthread_mutex_lock(&private_lock_) != 0) CRASH();
}
inline void Unlock() {
- if (pthread_mutex_unlock(&private_lock_) != 0) abort();
+ if (pthread_mutex_unlock(&private_lock_) != 0) CRASH();
}
};
diff --git a/JavaScriptCore/wtf/TCSystemAlloc.cpp b/JavaScriptCore/wtf/TCSystemAlloc.cpp
index bd6eb33..3a8908d 100644
--- a/JavaScriptCore/wtf/TCSystemAlloc.cpp
+++ b/JavaScriptCore/wtf/TCSystemAlloc.cpp
@@ -170,7 +170,7 @@ static void* TryMmap(size_t size, size_t *actual_size, size_t alignment) {
extra = alignment - pagesize;
}
void* result = mmap(NULL, size + extra,
- PROT_READ|PROT_WRITE,
+ PROT_READ | PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0);
if (result == reinterpret_cast<void*>(MAP_FAILED)) {
@@ -224,7 +224,7 @@ static void* TryVirtualAlloc(size_t size, size_t *actual_size, size_t alignment)
}
void* result = VirtualAlloc(NULL, size + extra,
MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,
- PAGE_EXECUTE_READWRITE);
+ PAGE_READWRITE);
if (result == NULL) {
VirtualAlloc_failure = true;
@@ -302,7 +302,7 @@ static void* TryDevMem(size_t size, size_t *actual_size, size_t alignment) {
devmem_failure = true;
return NULL;
}
- void *result = mmap(0, size + extra, PROT_WRITE|PROT_READ,
+ void *result = mmap(0, size + extra, PROT_READ | PROT_WRITE,
MAP_SHARED, physmem_fd, physmem_base);
if (result == reinterpret_cast<void*>(MAP_FAILED)) {
devmem_failure = true;
@@ -383,8 +383,6 @@ void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size, size_t alignment) {
void TCMalloc_SystemRelease(void* start, size_t length)
{
- UNUSED_PARAM(start);
- UNUSED_PARAM(length);
#if HAVE(MADV_DONTNEED)
if (FLAGS_malloc_devmem_start) {
// It's not safe to use MADV_DONTNEED if we've been mapping
@@ -421,18 +419,20 @@ void TCMalloc_SystemRelease(void* start, size_t length)
#endif
#if HAVE(MMAP)
- void *newAddress = mmap(start, length, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
- UNUSED_PARAM(newAddress);
+ 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(newAddress == start || newAddress == reinterpret_cast<void*>(MAP_FAILED));
+ ASSERT_UNUSED(newAddress, newAddress == start || newAddress == reinterpret_cast<void*>(MAP_FAILED));
return;
#endif
+
+#if !HAVE(MADV_DONTNEED) && !HAVE(MMAP)
+ UNUSED_PARAM(start);
+ UNUSED_PARAM(length);
+#endif
}
#if HAVE(VIRTUALALLOC)
-void TCMalloc_SystemCommit(void* start, size_t length)
+void TCMalloc_SystemCommit(void*, size_t)
{
- UNUSED_PARAM(start);
- UNUSED_PARAM(length);
}
#endif
diff --git a/JavaScriptCore/wtf/ThreadSpecific.h b/JavaScriptCore/wtf/ThreadSpecific.h
index 87709a1..7603802 100644
--- a/JavaScriptCore/wtf/ThreadSpecific.h
+++ b/JavaScriptCore/wtf/ThreadSpecific.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Jian Li <jianli@chromium.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,19 +27,36 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/* Thread local storage is implemented by using either pthread API or Windows
+ * native API. There is subtle semantic discrepancy for the cleanup function
+ * implementation as noted below:
+ * @ In pthread implementation, the destructor function will be called
+ * repeatedly if there is still non-NULL value associated with the function.
+ * @ In Windows native implementation, the destructor function will be called
+ * only once.
+ * This semantic discrepancy does not impose any problem because nowhere in
+ * WebKit the repeated call bahavior is utilized.
+ */
+
#ifndef WTF_ThreadSpecific_h
#define WTF_ThreadSpecific_h
#include <wtf/Noncopyable.h>
-#if USE(PTHREADS) || PLATFORM(WIN)
-// Windows currently doesn't use pthreads for basic threading, but implementing destructor functions is easier
-// with pthreads, so we use it here.
+#if USE(PTHREADS)
#include <pthread.h>
+#elif PLATFORM(WIN_OS)
+#include <windows.h>
#endif
namespace WTF {
+#if !USE(PTHREADS) && 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();
+#endif
+
template<typename T> class ThreadSpecific : Noncopyable {
public:
ThreadSpecific();
@@ -48,23 +66,34 @@ public:
~ThreadSpecific();
private:
+#if !USE(PTHREADS) && PLATFORM(WIN_OS)
+ friend void ThreadSpecificThreadExit();
+#endif
+
T* get();
void set(T*);
void static destroy(void* ptr);
-#if USE(PTHREADS) || PLATFORM(WIN)
+#if USE(PTHREADS) || PLATFORM(WIN_OS)
struct Data : Noncopyable {
Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {}
T* value;
ThreadSpecific<T>* owner;
+#if !USE(PTHREADS)
+ void (*destructor)(void*);
+#endif
};
+#endif
+#if USE(PTHREADS)
pthread_key_t m_key;
+#elif PLATFORM(WIN_OS)
+ int m_index;
#endif
};
-#if USE(PTHREADS) || PLATFORM(WIN)
+#if USE(PTHREADS)
template<typename T>
inline ThreadSpecific<T>::ThreadSpecific()
{
@@ -93,26 +122,92 @@ inline void ThreadSpecific<T>::set(T* ptr)
pthread_setspecific(m_key, new Data(ptr, this));
}
+#elif PLATFORM(WIN_OS)
+
+// The maximum number of TLS keys that can be created. For simplification, we assume that:
+// 1) Once the instance of ThreadSpecific<> is created, it will not be destructed until the program dies.
+// 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];
+
+template<typename T>
+inline ThreadSpecific<T>::ThreadSpecific()
+ : m_index(-1)
+{
+ DWORD tls_key = TlsAlloc();
+ if (tls_key == TLS_OUT_OF_INDEXES)
+ CRASH();
+
+ m_index = InterlockedIncrement(&g_tls_key_count) - 1;
+ if (m_index >= kMaxTlsKeySize)
+ CRASH();
+ g_tls_keys[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]);
+}
+
+template<typename T>
+inline T* ThreadSpecific<T>::get()
+{
+ Data* data = static_cast<Data*>(TlsGetValue(g_tls_keys[m_index]));
+ 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;
+ TlsSetValue(g_tls_keys[m_index], data);
+}
+
+#else
+#error ThreadSpecific is not implemented for this platform.
+#endif
+
template<typename T>
inline void ThreadSpecific<T>::destroy(void* ptr)
{
Data* data = static_cast<Data*>(ptr);
- pthread_setspecific(data->owner->m_key, 0);
- delete data->value;
- delete data;
-}
+#if USE(PTHREADS)
+ // We want get() to keep working while data destructor works, because it can be called indirectly by the destructor.
+ // Some pthreads implementations zero out the pointer before calling destroy(), so we temporarily reset it.
+ pthread_setspecific(data->owner->m_key, ptr);
+#endif
+
+ data->value->~T();
+ fastFree(data->value);
+
+#if USE(PTHREADS)
+ pthread_setspecific(data->owner->m_key, 0);
+#elif PLATFORM(WIN_OS)
+ TlsSetValue(g_tls_keys[data->owner->m_index], 0);
#else
#error ThreadSpecific is not implemented for this platform.
#endif
+ delete data;
+}
+
template<typename T>
inline ThreadSpecific<T>::operator T*()
{
T* ptr = static_cast<T*>(get());
if (!ptr) {
- ptr = new T();
+ // Set up thread-specific value's memory pointer before invoking constructor, in case any function it calls
+ // needs to access the value, to avoid recursion.
+ ptr = static_cast<T*>(fastMalloc(sizeof(T)));
set(ptr);
+ new (ptr) T;
}
return ptr;
}
diff --git a/JavaScriptCore/wtf/ThreadSpecificWin.cpp b/JavaScriptCore/wtf/ThreadSpecificWin.cpp
new file mode 100644
index 0000000..1a3febb
--- /dev/null
+++ b/JavaScriptCore/wtf/ThreadSpecificWin.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2009 Jian Li <jianli@chromium.org>
+ *
+ * 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 "ThreadSpecific.h"
+#include <wtf/Noncopyable.h>
+
+#if USE(PTHREADS)
+#error This file should not be compiled by ports that do not use Windows native ThreadSpecific implementation.
+#endif
+
+namespace WTF {
+
+long g_tls_key_count = 0;
+DWORD g_tls_keys[kMaxTlsKeySize];
+
+void ThreadSpecificThreadExit()
+{
+ for (long i = 0; i < g_tls_key_count; 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]));
+ if (data)
+ data->destructor(data);
+ }
+}
+
+} // namespace WTF
diff --git a/JavaScriptCore/wtf/Threading.cpp b/JavaScriptCore/wtf/Threading.cpp
new file mode 100644
index 0000000..41c9135
--- /dev/null
+++ b/JavaScriptCore/wtf/Threading.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ *
+ * 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"
+
+namespace WTF {
+
+struct NewThreadContext {
+ NewThreadContext(ThreadFunction entryPoint, void* data)
+ : entryPoint(entryPoint)
+ , data(data)
+ { }
+
+ ThreadFunction entryPoint;
+ void* data;
+
+ Mutex creationMutex;
+};
+
+static void* threadEntryPoint(void* contextData)
+{
+ NewThreadContext* context = reinterpret_cast<NewThreadContext*>(contextData);
+
+ // Block until our creating thread has completed any extra setup work
+ {
+ MutexLocker locker(context->creationMutex);
+ }
+
+ // Grab the info that we need out of the context, then deallocate it.
+ ThreadFunction entryPoint = context->entryPoint;
+ void* data = context->data;
+ delete context;
+
+ return entryPoint(data);
+}
+
+ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name)
+{
+ NewThreadContext* context = new NewThreadContext(entryPoint, data);
+
+ // Prevent the thread body from executing until we've established the thread identifier
+ MutexLocker locker(context->creationMutex);
+
+ return createThreadInternal(threadEntryPoint, context, name);
+}
+
+#if PLATFORM(MAC) || PLATFORM(WIN)
+
+// 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);
+}
+#endif
+
+} // namespace WTF
diff --git a/JavaScriptCore/wtf/Threading.h b/JavaScriptCore/wtf/Threading.h
index b464da3..1c0dab1 100644
--- a/JavaScriptCore/wtf/Threading.h
+++ b/JavaScriptCore/wtf/Threading.h
@@ -59,11 +59,15 @@
#ifndef Threading_h
#define Threading_h
+#if PLATFORM(WIN_CE)
+#include <windows.h>
+#endif
+
#include <wtf/Assertions.h>
#include <wtf/Locker.h>
#include <wtf/Noncopyable.h>
-#if PLATFORM(WIN_OS)
+#if PLATFORM(WIN_OS) && !PLATFORM(WIN_CE)
#include <windows.h>
#elif PLATFORM(DARWIN)
#include <libkern/OSAtomic.h>
@@ -108,6 +112,7 @@ typedef void* (*ThreadFunction)(void* argument);
// Returns 0 if thread creation failed
ThreadIdentifier createThread(ThreadFunction, void*, const char* threadName);
+ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char* threadName);
ThreadIdentifier currentThread();
bool isMainThread();
@@ -129,12 +134,15 @@ struct PlatformMutex {
size_t m_recursionCount;
};
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;
@@ -164,8 +172,9 @@ public:
~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();
@@ -176,7 +185,7 @@ private:
#if PLATFORM(WIN_OS)
#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
-#if COMPILER(MINGW) || COMPILER(MSVC7)
+#if COMPILER(MINGW) || COMPILER(MSVC7) || PLATFORM(WIN_CE)
inline void atomicIncrement(int* addend) { InterlockedIncrement(reinterpret_cast<long*>(addend)); }
inline int atomicDecrement(int* addend) { return InterlockedDecrement(reinterpret_cast<long*>(addend)); }
#else
@@ -258,14 +267,8 @@ private:
// 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();
-#if !PLATFORM(WIN_OS) || PLATFORM(WX)
-extern Mutex* atomicallyInitializedStaticMutex;
-inline void lockAtomicallyInitializedStaticMutex() { atomicallyInitializedStaticMutex->lock(); }
-inline void unlockAtomicallyInitializedStaticMutex() { atomicallyInitializedStaticMutex->unlock(); }
-#else
void lockAtomicallyInitializedStaticMutex();
void unlockAtomicallyInitializedStaticMutex();
-#endif
} // namespace WTF
diff --git a/JavaScriptCore/wtf/ThreadingGtk.cpp b/JavaScriptCore/wtf/ThreadingGtk.cpp
index 53fd1fe..24c34ca 100644
--- a/JavaScriptCore/wtf/ThreadingGtk.cpp
+++ b/JavaScriptCore/wtf/ThreadingGtk.cpp
@@ -32,15 +32,17 @@
#if !USE(PTHREADS)
+#include "CurrentTime.h"
#include "HashMap.h"
#include "MainThread.h"
-#include "MathExtras.h"
+#include "RandomNumberSeed.h"
#include <glib.h>
+#include <limits.h>
namespace WTF {
-Mutex* atomicallyInitializedStaticMutex;
+static Mutex* atomicallyInitializedStaticMutex;
static ThreadIdentifier mainThreadIdentifier;
@@ -59,27 +61,27 @@ void initializeThreading()
if (!atomicallyInitializedStaticMutex) {
atomicallyInitializedStaticMutex = new Mutex;
threadMapMutex();
- wtf_random_init();
+ initializeRandomNumberGenerator();
mainThreadIdentifier = currentThread();
initializeMainThread();
}
}
-static HashMap<ThreadIdentifier, GThread*>& threadMap()
+void lockAtomicallyInitializedStaticMutex()
{
- static HashMap<ThreadIdentifier, GThread*> map;
- return map;
+ ASSERT(atomicallyInitializedStaticMutex);
+ atomicallyInitializedStaticMutex->lock();
}
-static ThreadIdentifier establishIdentifierForThread(GThread*& thread)
+void unlockAtomicallyInitializedStaticMutex()
{
- MutexLocker locker(threadMapMutex());
-
- static ThreadIdentifier identifierCount = 1;
-
- threadMap().add(identifierCount, thread);
+ atomicallyInitializedStaticMutex->unlock();
+}
- return identifierCount++;
+static HashMap<ThreadIdentifier, GThread*>& threadMap()
+{
+ static HashMap<ThreadIdentifier, GThread*> map;
+ return map;
}
static ThreadIdentifier identifierByGthreadHandle(GThread*& thread)
@@ -95,6 +97,19 @@ static ThreadIdentifier identifierByGthreadHandle(GThread*& thread)
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());
@@ -111,7 +126,7 @@ static void clearThreadForIdentifier(ThreadIdentifier id)
threadMap().remove(id);
}
-ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char*)
+ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
{
GThread* thread;
if (!(thread = g_thread_create(entryPoint, data, TRUE, 0))) {
@@ -129,7 +144,9 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
GThread* thread = threadForIdentifier(threadID);
- *result = g_thread_join(thread);
+ void* joinResult = g_thread_join(thread);
+ if (result)
+ *result = joinResult;
clearThreadForIdentifier(threadID);
return 0;
@@ -190,25 +207,24 @@ void ThreadCondition::wait(Mutex& mutex)
g_cond_wait(m_condition.get(), mutex.impl().get());
}
-bool ThreadCondition::timedWait(Mutex& mutex, double interval)
+bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
{
- if (interval < 0.0) {
+ // Time is in the past - return right away.
+ if (absoluteTime < currentTime())
+ return false;
+
+ // Time is too far in the future for g_cond_timed_wait - wait forever.
+ if (absoluteTime > INT_MAX) {
wait(mutex);
return true;
}
-
- int intervalSeconds = static_cast<int>(interval);
- int intervalMicroseconds = static_cast<int>((interval - intervalSeconds) * 1000000.0);
+
+ int timeSeconds = static_cast<int>(absoluteTime);
+ int timeMicroseconds = static_cast<int>((absoluteTime - timeSeconds) * 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++;
- }
+ targetTime.tv_sec = timeSeconds;
+ targetTime.tv_usec = timeMicroseconds;
return g_cond_timed_wait(m_condition.get(), mutex.impl().get(), &targetTime);
}
diff --git a/JavaScriptCore/wtf/ThreadingNone.cpp b/JavaScriptCore/wtf/ThreadingNone.cpp
index c17b3b2..0be2a4b 100644
--- a/JavaScriptCore/wtf/ThreadingNone.cpp
+++ b/JavaScriptCore/wtf/ThreadingNone.cpp
@@ -26,31 +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"
namespace WTF {
-Mutex* atomicallyInitializedStaticMutex;
-
-void initializeThreading() {}
-ThreadIdentifier createThread(ThreadFunction, void*, const char*) { return 0; }
+void initializeThreading() { }
+ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char*) { return 0; }
int waitForThreadCompletion(ThreadIdentifier, void**) { return 0; }
void detachThread(ThreadIdentifier) { }
ThreadIdentifier currentThread() { return 0; }
-bool isMainThread() { return false; }
+bool isMainThread() { return true; }
-Mutex::Mutex() {}
-Mutex::~Mutex() {}
-void Mutex::lock() {}
+Mutex::Mutex() { }
+Mutex::~Mutex() { }
+void Mutex::lock() { }
bool Mutex::tryLock() { return false; }
-void Mutex::unlock() {};
+void Mutex::unlock() { }
+
+ThreadCondition::ThreadCondition() { }
+ThreadCondition::~ThreadCondition() { }
+void ThreadCondition::wait(Mutex& mutex) { }
+bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime) { return false; }
+void ThreadCondition::signal() { }
+void ThreadCondition::broadcast() { }
-ThreadCondition::ThreadCondition() {}
-ThreadCondition::~ThreadCondition() {}
-void ThreadCondition::wait(Mutex& mutex) {}
-bool ThreadCondition::timedWait(Mutex& mutex, double interval) { return false; }
-void ThreadCondition::signal() {}
-void ThreadCondition::broadcast() {}
+void lockAtomicallyInitializedStaticMutex() { }
+void unlockAtomicallyInitializedStaticMutex() { }
} // namespace WebCore
diff --git a/JavaScriptCore/wtf/ThreadingPthreads.cpp b/JavaScriptCore/wtf/ThreadingPthreads.cpp
index d17a03d..105e42a 100644
--- a/JavaScriptCore/wtf/ThreadingPthreads.cpp
+++ b/JavaScriptCore/wtf/ThreadingPthreads.cpp
@@ -29,18 +29,24 @@
#include "config.h"
#include "Threading.h"
+#include "StdLibExtras.h"
+
#if USE(PTHREADS)
+#include "CurrentTime.h"
#include "HashMap.h"
#include "MainThread.h"
-#include "MathExtras.h"
+#include "RandomNumberSeed.h"
#include <errno.h>
+#include <limits.h>
#include <sys/time.h>
namespace WTF {
-Mutex* atomicallyInitializedStaticMutex;
+typedef HashMap<ThreadIdentifier, pthread_t> ThreadMap;
+
+static Mutex* atomicallyInitializedStaticMutex;
#if !PLATFORM(DARWIN)
static ThreadIdentifier mainThreadIdentifier; // The thread that was the first to call initializeThreading(), which must be the main thread.
@@ -48,7 +54,7 @@ static ThreadIdentifier mainThreadIdentifier; // The thread that was the first t
static Mutex& threadMapMutex()
{
- static Mutex mutex;
+ DEFINE_STATIC_LOCAL(Mutex, mutex, ());
return mutex;
}
@@ -57,7 +63,7 @@ void initializeThreading()
if (!atomicallyInitializedStaticMutex) {
atomicallyInitializedStaticMutex = new Mutex;
threadMapMutex();
- wtf_random_init();
+ initializeRandomNumberGenerator();
#if !PLATFORM(DARWIN)
mainThreadIdentifier = currentThread();
#endif
@@ -65,28 +71,28 @@ void initializeThreading()
}
}
-static HashMap<ThreadIdentifier, pthread_t>& threadMap()
+void lockAtomicallyInitializedStaticMutex()
{
- static HashMap<ThreadIdentifier, pthread_t> map;
- return map;
+ ASSERT(atomicallyInitializedStaticMutex);
+ atomicallyInitializedStaticMutex->lock();
}
-static ThreadIdentifier establishIdentifierForPthreadHandle(pthread_t& pthreadHandle)
+void unlockAtomicallyInitializedStaticMutex()
{
- MutexLocker locker(threadMapMutex());
-
- static ThreadIdentifier identifierCount = 1;
+ atomicallyInitializedStaticMutex->unlock();
+}
- threadMap().add(identifierCount, pthreadHandle);
-
- return identifierCount++;
+static ThreadMap& threadMap()
+{
+ DEFINE_STATIC_LOCAL(ThreadMap, map, ());
+ return map;
}
static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle)
{
MutexLocker locker(threadMapMutex());
- HashMap<ThreadIdentifier, pthread_t>::iterator i = threadMap().begin();
+ ThreadMap::iterator i = threadMap().begin();
for (; i != threadMap().end(); ++i) {
if (pthread_equal(i->second, pthreadHandle))
return i->first;
@@ -95,6 +101,19 @@ static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle
return 0;
}
+static ThreadIdentifier establishIdentifierForPthreadHandle(pthread_t& pthreadHandle)
+{
+ ASSERT(!identifierByPthreadHandle(pthreadHandle));
+
+ MutexLocker locker(threadMapMutex());
+
+ static ThreadIdentifier identifierCount = 1;
+
+ threadMap().add(identifierCount, pthreadHandle);
+
+ return identifierCount++;
+}
+
static pthread_t pthreadHandleForIdentifier(ThreadIdentifier id)
{
MutexLocker locker(threadMapMutex());
@@ -111,7 +130,7 @@ static void clearPthreadHandleForIdentifier(ThreadIdentifier id)
threadMap().remove(id);
}
-ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char*)
+ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
{
pthread_t threadHandle;
if (pthread_create(&threadHandle, NULL, entryPoint, data)) {
@@ -119,19 +138,9 @@ ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char*
return 0;
}
- ThreadIdentifier threadID = establishIdentifierForPthreadHandle(threadHandle);
- return threadID;
+ return establishIdentifierForPthreadHandle(threadHandle);
}
-#if PLATFORM(MAC)
-// This function is deprecated but needs to be kept around for backward
-// compatibility. Use the 3-argument version of createThread above instead.
-ThreadIdentifier createThread(ThreadFunction entryPoint, void* data)
-{
- return createThread(entryPoint, data, 0);
-}
-#endif
-
int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
{
ASSERT(threadID);
@@ -208,7 +217,7 @@ void Mutex::unlock()
if (pthread_mutex_unlock(&m_mutex) != 0)
ASSERT(false);
}
-
+
ThreadCondition::ThreadCondition()
{
pthread_cond_init(&m_condition, NULL);
@@ -225,28 +234,22 @@ void ThreadCondition::wait(Mutex& mutex)
ASSERT(false);
}
-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);
+ int timeSeconds = static_cast<int>(absoluteTime);
+ int timeNanoseconds = static_cast<int>((absoluteTime - timeSeconds) * 1E9);
- // Current time comes in sec/microsec
- timeval currentTime;
- gettimeofday(&currentTime, NULL);
-
- // 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;
}
diff --git a/JavaScriptCore/wtf/ThreadingQt.cpp b/JavaScriptCore/wtf/ThreadingQt.cpp
index b24f241..55a479b 100644
--- a/JavaScriptCore/wtf/ThreadingQt.cpp
+++ b/JavaScriptCore/wtf/ThreadingQt.cpp
@@ -29,9 +29,10 @@
#include "config.h"
#include "Threading.h"
+#include "CurrentTime.h"
#include "HashMap.h"
#include "MainThread.h"
-#include "MathExtras.h"
+#include "RandomNumberSeed.h"
#include <QCoreApplication>
#include <QMutex>
@@ -64,7 +65,7 @@ void ThreadPrivate::run()
}
-Mutex* atomicallyInitializedStaticMutex;
+static Mutex* atomicallyInitializedStaticMutex;
static ThreadIdentifier mainThreadIdentifier;
@@ -80,8 +81,23 @@ static HashMap<ThreadIdentifier, QThread*>& threadMap()
return map;
}
+static ThreadIdentifier identifierByQthreadHandle(QThread*& thread)
+{
+ MutexLocker locker(threadMapMutex());
+
+ HashMap<ThreadIdentifier, QThread*>::iterator i = threadMap().begin();
+ for (; i != threadMap().end(); ++i) {
+ if (i->second == thread)
+ return i->first;
+ }
+
+ return 0;
+}
+
static ThreadIdentifier establishIdentifierForThread(QThread*& thread)
{
+ ASSERT(!identifierByQthreadHandle(thread));
+
MutexLocker locker(threadMapMutex());
static ThreadIdentifier identifierCount = 1;
@@ -100,19 +116,6 @@ static void clearThreadForIdentifier(ThreadIdentifier id)
threadMap().remove(id);
}
-static ThreadIdentifier identifierByQthreadHandle(QThread*& thread)
-{
- MutexLocker locker(threadMapMutex());
-
- HashMap<ThreadIdentifier, QThread*>::iterator i = threadMap().begin();
- for (; i != threadMap().end(); ++i) {
- if (i->second == thread)
- return i->first;
- }
-
- return 0;
-}
-
static QThread* threadForIdentifier(ThreadIdentifier id)
{
MutexLocker locker(threadMapMutex());
@@ -122,10 +125,10 @@ static QThread* threadForIdentifier(ThreadIdentifier id)
void initializeThreading()
{
- if(!atomicallyInitializedStaticMutex) {
+ if (!atomicallyInitializedStaticMutex) {
atomicallyInitializedStaticMutex = new Mutex;
threadMapMutex();
- wtf_random_init();
+ initializeRandomNumberGenerator();
QThread* mainThread = QCoreApplication::instance()->thread();
mainThreadIdentifier = identifierByQthreadHandle(mainThread);
if (!mainThreadIdentifier)
@@ -134,7 +137,18 @@ void initializeThreading()
}
}
-ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char*)
+void lockAtomicallyInitializedStaticMutex()
+{
+ ASSERT(atomicallyInitializedStaticMutex);
+ atomicallyInitializedStaticMutex->lock();
+}
+
+void unlockAtomicallyInitializedStaticMutex()
+{
+ atomicallyInitializedStaticMutex->unlock();
+}
+
+ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
{
ThreadPrivate* thread = new ThreadPrivate(entryPoint, data);
if (!thread) {
@@ -157,7 +171,8 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
bool res = thread->wait();
clearThreadForIdentifier(threadID);
- *result = static_cast<ThreadPrivate*>(thread)->getReturnValue();
+ if (result)
+ *result = static_cast<ThreadPrivate*>(thread)->getReturnValue();
return !res;
}
@@ -219,15 +234,20 @@ 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) {
- wait(mutex);
- return true;
- }
+ double currentTime = WTF::currentTime();
+
+ // Time is in the past - return immediately.
+ if (absoluteTime < currentTime)
+ return false;
+
+ double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0;
+ // Qt defines wait for up to ULONG_MAX milliseconds.
+ if (intervalMilliseconds >= ULONG_MAX)
+ intervalMilliseconds = ULONG_MAX;
- unsigned long millisecondsToWait = static_cast<unsigned long>(secondsToWait * 1000.0);
- return m_condition->wait(mutex.impl(), millisecondsToWait);
+ return m_condition->wait(mutex.impl(), static_cast<unsigned long>(intervalMilliseconds));
}
void ThreadCondition::signal()
diff --git a/JavaScriptCore/wtf/ThreadingWin.cpp b/JavaScriptCore/wtf/ThreadingWin.cpp
index 00ad149..399fb38 100644
--- a/JavaScriptCore/wtf/ThreadingWin.cpp
+++ b/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,56 +25,76 @@
* 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"
#include "Threading.h"
#include "MainThread.h"
+#if !USE(PTHREADS) && PLATFORM(WIN_OS)
+#include "ThreadSpecific.h"
+#endif
#include <process.h>
#include <windows.h>
+#include <wtf/CurrentTime.h>
#include <wtf/HashMap.h>
#include <wtf/MathExtras.h>
-
-#if PLATFORM(WIN) && USE(PTHREADS)
-// Currently, Apple's Windows port uses a mixture of native and pthreads functions in FastMalloc.
-// To ensure that thread-specific data is properly destroyed, we need to end each thread with pthread_exit().
-#include <pthread.h>
-#endif
+#include <wtf/RandomNumberSeed.h>
namespace WTF {
@@ -111,6 +132,7 @@ static Mutex* atomicallyInitializedStaticMutex;
void lockAtomicallyInitializedStaticMutex()
{
+ ASSERT(atomicallyInitializedStaticMutex);
atomicallyInitializedStaticMutex->lock();
}
@@ -132,7 +154,7 @@ void initializeThreading()
if (!atomicallyInitializedStaticMutex) {
atomicallyInitializedStaticMutex = new Mutex;
threadMapMutex();
- wtf_random_init();
+ initializeRandomNumberGenerator();
initializeMainThread();
mainThreadIdentifier = currentThread();
setThreadName(mainThreadIdentifier, "Main Thread");
@@ -148,6 +170,7 @@ static HashMap<DWORD, HANDLE>& threadMap()
static void storeThreadHandleByIdentifier(DWORD threadID, HANDLE threadHandle)
{
MutexLocker locker(threadMapMutex());
+ ASSERT(!threadMap().contains(threadID));
threadMap().add(threadID, threadHandle);
}
@@ -178,15 +201,15 @@ static unsigned __stdcall wtfThreadEntryPoint(void* param)
void* result = invocation.function(invocation.data);
-#if PLATFORM(WIN) && USE(PTHREADS)
- // pthreads-win32 knows how to work with threads created with Win32 or CRT functions, so it's OK to mix APIs.
- pthread_exit(result);
+#if !USE(PTHREADS) && PLATFORM(WIN_OS)
+ // Do the TLS cleanup.
+ ThreadSpecificThreadExit();
#endif
return reinterpret_cast<unsigned>(result);
}
-ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* threadName)
+ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char* threadName)
{
unsigned threadIdentifier = 0;
ThreadIdentifier threadID = 0;
@@ -206,13 +229,6 @@ ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char*
return threadID;
}
-// 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)
-{
- return createThread(entryPoint, data, 0);
-}
-
int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
{
ASSERT(threadID);
@@ -221,11 +237,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;
@@ -237,13 +253,13 @@ void detachThread(ThreadIdentifier 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()
@@ -254,17 +270,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;
}
@@ -276,14 +292,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;
}
@@ -297,183 +313,165 @@ bool Mutex::tryLock()
void Mutex::unlock()
{
--m_mutex.m_recursionCount;
- ::LeaveCriticalSection(&m_mutex.m_internalMutex);
+ LeaveCriticalSection(&m_mutex.m_internalMutex);
}
-static const long MaxSemaphoreCount = static_cast<long>(~0UL >> 1);
-
-ThreadCondition::ThreadCondition()
+bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMilliseconds)
{
- 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);
- }
-}
-
-ThreadCondition::~ThreadCondition()
-{
- ::CloseHandle(m_condition.m_gate);
- ::CloseHandle(m_condition.m_queue);
- ::CloseHandle(m_condition.m_mutex);
-}
-
-void ThreadCondition::wait(Mutex& mutex)
-{
- 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);
- }
+ double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0;
+ if (intervalMilliseconds >= INT_MAX)
+ intervalMilliseconds = INT_MAX;
+
+ 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/JavaScriptCore/wtf/Vector.h b/JavaScriptCore/wtf/Vector.h
index c0bc132..880b45d 100644
--- a/JavaScriptCore/wtf/Vector.h
+++ b/JavaScriptCore/wtf/Vector.h
@@ -37,7 +37,7 @@ namespace WTF {
using std::max;
// WTF_ALIGN_OF / WTF_ALIGNED
- #if COMPILER(GCC) || COMPILER(MINGW)
+ #if COMPILER(GCC) || COMPILER(MINGW) || COMPILER(RVCT) || COMPILER(WINSCW)
#define WTF_ALIGN_OF(type) __alignof__(type)
#define WTF_ALIGNED(variable_type, variable, n) variable_type variable __attribute__((__aligned__(n)))
#elif COMPILER(MSVC)
@@ -279,8 +279,10 @@ namespace WTF {
void deallocateBuffer(T* bufferToDeallocate)
{
- if (m_buffer == bufferToDeallocate)
+ if (m_buffer == bufferToDeallocate) {
m_buffer = 0;
+ m_capacity = 0;
+ }
fastFree(bufferToDeallocate);
}
@@ -346,6 +348,8 @@ namespace WTF {
std::swap(m_buffer, other.m_buffer);
std::swap(m_capacity, other.m_capacity);
}
+
+ void restoreInlineBufferIfNeeded() { }
using Base::allocateBuffer;
using Base::deallocateBuffer;
@@ -393,6 +397,14 @@ namespace WTF {
return;
Base::deallocateBuffer(bufferToDeallocate);
}
+
+ void restoreInlineBufferIfNeeded()
+ {
+ if (m_buffer)
+ return;
+ m_buffer = inlineBuffer();
+ m_capacity = inlineCapacity;
+ }
using Base::buffer;
using Base::bufferSlot;
@@ -442,7 +454,7 @@ namespace WTF {
~Vector()
{
- clear();
+ if (m_size) shrink(0);
}
Vector(const Vector&);
@@ -492,8 +504,9 @@ namespace WTF {
void resize(size_t size);
void reserveCapacity(size_t newCapacity);
void shrinkCapacity(size_t newCapacity);
+ void shrinkToFit() { shrinkCapacity(size()); }
- void clear() { if (m_size) shrink(0); }
+ void clear() { shrinkCapacity(0); }
template<typename U> void append(const U*, size_t);
template<typename U> void append(const U&);
@@ -725,7 +738,8 @@ namespace WTF {
if (newCapacity >= capacity())
return;
- resize(min(m_size, newCapacity));
+ if (newCapacity < size())
+ shrink(newCapacity);
T* oldBuffer = begin();
if (newCapacity > 0) {
@@ -736,6 +750,7 @@ namespace WTF {
}
m_buffer.deallocateBuffer(oldBuffer);
+ m_buffer.restoreInlineBufferIfNeeded();
}
// Templatizing these is better than just letting the conversion happen implicitly,
diff --git a/JavaScriptCore/wtf/VectorTraits.h b/JavaScriptCore/wtf/VectorTraits.h
index 71aaec8..6efe36c 100644
--- a/JavaScriptCore/wtf/VectorTraits.h
+++ b/JavaScriptCore/wtf/VectorTraits.h
@@ -1,6 +1,5 @@
/*
- * This file is part of the KDE libraries
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2007, 2008 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
diff --git a/JavaScriptCore/wtf/dtoa.cpp b/JavaScriptCore/wtf/dtoa.cpp
new file mode 100644
index 0000000..c9e8d30
--- /dev/null
+++ b/JavaScriptCore/wtf/dtoa.cpp
@@ -0,0 +1,2439 @@
+/****************************************************************
+ *
+ * The author of this software is David M. Gay.
+ *
+ * Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
+ * Copyright (C) 2002, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ ***************************************************************/
+
+/* Please send bug reports to
+ David M. Gay
+ Bell Laboratories, Room 2C-463
+ 600 Mountain Avenue
+ Murray Hill, NJ 07974-0636
+ U.S.A.
+ dmg@bell-labs.com
+ */
+
+/* On a machine with IEEE extended-precision registers, it is
+ * necessary to specify double-precision (53-bit) rounding precision
+ * before invoking strtod or dtoa. If the machine uses (the equivalent
+ * of) Intel 80x87 arithmetic, the call
+ * _control87(PC_53, MCW_PC);
+ * does this with many compilers. Whether this or another call is
+ * appropriate depends on the compiler; for this to work, it may be
+ * necessary to #include "float.h" or another system-dependent header
+ * file.
+ */
+
+/* strtod for IEEE-arithmetic machines.
+ *
+ * This strtod returns a nearest machine number to the input decimal
+ * string (or sets errno to ERANGE). With IEEE arithmetic, ties are
+ * broken by the IEEE round-even rule. Otherwise ties are broken by
+ * biased rounding (add half and chop).
+ *
+ * Inspired loosely by William D. Clinger's paper "How to Read Floating
+ * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
+ *
+ * Modifications:
+ *
+ * 1. We only require IEEE.
+ * 2. We get by with floating-point arithmetic in a case that
+ * Clinger missed -- when we're computing d * 10^n
+ * for a small integer d and the integer n is not too
+ * much larger than 22 (the maximum integer k for which
+ * we can represent 10^k exactly), we may be able to
+ * compute (d*10^k) * 10^(e-k) with just one roundoff.
+ * 3. Rather than a bit-at-a-time adjustment of the binary
+ * result in the hard case, we use floating-point
+ * arithmetic to determine the adjustment to within
+ * one bit; only in really hard cases do we need to
+ * compute a second residual.
+ * 4. Because of 3., we don't need a large table of powers of 10
+ * for ten-to-e (just some small tables, e.g. of 10^k
+ * for 0 <= k <= 22).
+ */
+
+/*
+ * #define IEEE_8087 for IEEE-arithmetic machines where the least
+ * significant byte has the lowest address.
+ * #define IEEE_MC68k for IEEE-arithmetic machines where the most
+ * significant byte has the lowest address.
+ * #define No_leftright to omit left-right logic in fast floating-point
+ * computation of dtoa.
+ * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
+ * and Honor_FLT_ROUNDS is not #defined.
+ * #define Inaccurate_Divide for IEEE-format with correctly rounded
+ * products but inaccurate quotients, e.g., for Intel i860.
+ * #define USE_LONG_LONG on machines that have a "long long"
+ * integer type (of >= 64 bits), and performance testing shows that
+ * it is faster than 32-bit fallback (which is often not the case
+ * on 32-bit machines). On such machines, you can #define Just_16
+ * to store 16 bits per 32-bit int32_t when doing high-precision integer
+ * arithmetic. Whether this speeds things up or slows things down
+ * depends on the machine and the number being converted.
+ * #define Bad_float_h if your system lacks a float.h or if it does not
+ * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
+ * FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
+ * #define INFNAN_CHECK on IEEE systems to cause strtod to check for
+ * Infinity and NaN (case insensitively). On some systems (e.g.,
+ * some HP systems), it may be necessary to #define NAN_WORD0
+ * appropriately -- to the most significant word of a quiet NaN.
+ * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
+ * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
+ * strtod also accepts (case insensitively) strings of the form
+ * NaN(x), where x is a string of hexadecimal digits and spaces;
+ * if there is only one string of hexadecimal digits, it is taken
+ * for the 52 fraction bits of the resulting NaN; if there are two
+ * or more strings of hex digits, the first is for the high 20 bits,
+ * the second and subsequent for the low 32 bits, with intervening
+ * white space ignored; but if this results in none of the 52
+ * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0
+ * and NAN_WORD1 are used instead.
+ * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that
+ * avoids underflows on inputs whose result does not underflow.
+ * If you #define NO_IEEE_Scale on a machine that uses IEEE-format
+ * floating-point numbers and flushes underflows to zero rather
+ * than implementing gradual underflow, then you must also #define
+ * Sudden_Underflow.
+ * #define YES_ALIAS to permit aliasing certain double values with
+ * arrays of ULongs. This leads to slightly better code with
+ * some compilers and was always used prior to 19990916, but it
+ * is not strictly legal and can cause trouble with aggressively
+ * optimizing compilers (e.g., gcc 2.95.1 under -O2).
+ * #define SET_INEXACT if IEEE arithmetic is being used and extra
+ * computation should be done to set the inexact flag when the
+ * result is inexact and avoid setting inexact when the result
+ * is exact. In this case, dtoa.c must be compiled in
+ * an environment, perhaps provided by #include "dtoa.c" in a
+ * suitable wrapper, that defines two functions,
+ * int get_inexact(void);
+ * void clear_inexact(void);
+ * such that get_inexact() returns a nonzero value if the
+ * inexact bit is already set, and clear_inexact() sets the
+ * inexact bit to 0. When SET_INEXACT is #defined, strtod
+ * also does extra computations to set the underflow and overflow
+ * flags when appropriate (i.e., when the result is tiny and
+ * inexact or when it is a numeric value rounded to +-infinity).
+ * #define NO_ERRNO if strtod should not assign errno = ERANGE when
+ * the result overflows to +-Infinity or underflows to 0.
+ */
+
+#include "config.h"
+#include "dtoa.h"
+
+#if HAVE(ERRNO_H)
+#include <errno.h>
+#else
+#define NO_ERRNO
+#endif
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wtf/AlwaysInline.h>
+#include <wtf/Assertions.h>
+#include <wtf/FastMalloc.h>
+#include <wtf/Threading.h>
+
+#if COMPILER(MSVC)
+#pragma warning(disable: 4244)
+#pragma warning(disable: 4245)
+#pragma warning(disable: 4554)
+#endif
+
+#if PLATFORM(BIG_ENDIAN)
+#define IEEE_MC68k
+#elif PLATFORM(MIDDLE_ENDIAN)
+#define IEEE_ARM
+#else
+#define IEEE_8087
+#endif
+
+#define INFNAN_CHECK
+
+#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(IEEE_ARM) != 1
+Exactly one of IEEE_8087, IEEE_ARM or IEEE_MC68k should be defined.
+#endif
+
+namespace WTF {
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+Mutex* s_dtoaP5Mutex;
+#endif
+
+typedef union { double d; uint32_t L[2]; } U;
+
+#ifdef YES_ALIAS
+#define dval(x) x
+#ifdef IEEE_8087
+#define word0(x) ((uint32_t*)&x)[1]
+#define word1(x) ((uint32_t*)&x)[0]
+#else
+#define word0(x) ((uint32_t*)&x)[0]
+#define word1(x) ((uint32_t*)&x)[1]
+#endif
+#else
+#ifdef IEEE_8087
+#define word0(x) ((U*)&x)->L[1]
+#define word1(x) ((U*)&x)->L[0]
+#else
+#define word0(x) ((U*)&x)->L[0]
+#define word1(x) ((U*)&x)->L[1]
+#endif
+#define dval(x) ((U*)&x)->d
+#endif
+
+/* The following definition of Storeinc is appropriate for MIPS processors.
+ * An alternative that might be better on some machines is
+ * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
+ */
+#if defined(IEEE_8087) || defined(IEEE_ARM)
+#define Storeinc(a,b,c) (((unsigned short*)a)[1] = (unsigned short)b, ((unsigned short*)a)[0] = (unsigned short)c, a++)
+#else
+#define Storeinc(a,b,c) (((unsigned short*)a)[0] = (unsigned short)b, ((unsigned short*)a)[1] = (unsigned short)c, a++)
+#endif
+
+#define Exp_shift 20
+#define Exp_shift1 20
+#define Exp_msk1 0x100000
+#define Exp_msk11 0x100000
+#define Exp_mask 0x7ff00000
+#define P 53
+#define Bias 1023
+#define Emin (-1022)
+#define Exp_1 0x3ff00000
+#define Exp_11 0x3ff00000
+#define Ebits 11
+#define Frac_mask 0xfffff
+#define Frac_mask1 0xfffff
+#define Ten_pmax 22
+#define Bletch 0x10
+#define Bndry_mask 0xfffff
+#define Bndry_mask1 0xfffff
+#define LSB 1
+#define Sign_bit 0x80000000
+#define Log2P 1
+#define Tiny0 0
+#define Tiny1 1
+#define Quick_max 14
+#define Int_max 14
+
+#if !defined(NO_IEEE_Scale)
+#undef Avoid_Underflow
+#define Avoid_Underflow
+#endif
+
+#if !defined(Flt_Rounds)
+#if defined(FLT_ROUNDS)
+#define Flt_Rounds FLT_ROUNDS
+#else
+#define Flt_Rounds 1
+#endif
+#endif /*Flt_Rounds*/
+
+
+#define rounded_product(a,b) a *= b
+#define rounded_quotient(a,b) a /= b
+
+#define Big0 (Frac_mask1 | Exp_msk1 * (DBL_MAX_EXP + Bias - 1))
+#define Big1 0xffffffff
+
+#ifndef Pack_32
+#define Pack_32
+#endif
+
+#if PLATFORM(PPC64) || PLATFORM(X86_64)
+// 64-bit emulation provided by the compiler is likely to be slower than dtoa own code on 32-bit hardware.
+#define USE_LONG_LONG
+#endif
+
+#ifndef USE_LONG_LONG
+#ifdef Just_16
+#undef Pack_32
+/* When Pack_32 is not defined, we store 16 bits per 32-bit int32_t.
+ * This makes some inner loops simpler and sometimes saves work
+ * during multiplications, but it often seems to make things slightly
+ * slower. Hence the default is now to store 32 bits per int32_t.
+ */
+#endif
+#endif
+
+#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);
+}
+
+#define Bcopy(x, y) memcpy((char*)&x->sign, (char*)&y->sign, y->wds * sizeof(int32_t) + 2 * sizeof(int))
+
+static Bigint* multadd(Bigint* b, int m, int a) /* multiply by m and add a */
+{
+#ifdef USE_LONG_LONG
+ unsigned long long carry;
+#else
+ uint32_t carry;
+#endif
+
+ int wds = b->wds;
+ uint32_t* x = b->x;
+ int i = 0;
+ carry = a;
+ do {
+#ifdef USE_LONG_LONG
+ unsigned long long y = *x * (unsigned long long)m + carry;
+ carry = y >> 32;
+ *x++ = (uint32_t)y & 0xffffffffUL;
+#else
+#ifdef Pack_32
+ uint32_t xi = *x;
+ uint32_t y = (xi & 0xffff) * m + carry;
+ uint32_t z = (xi >> 16) * m + (y >> 16);
+ carry = z >> 16;
+ *x++ = (z << 16) + (y & 0xffff);
+#else
+ uint32_t y = *x * m + carry;
+ carry = y >> 16;
+ *x++ = y & 0xffff;
+#endif
+#endif
+ } 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;
+ }
+ return b;
+}
+
+static Bigint* s2b(const char* s, int nd0, int nd, uint32_t y9)
+{
+ int k;
+ int32_t y;
+ int32_t x = (nd + 8) / 9;
+
+ for (k = 0, y = 1; x > y; y <<= 1, k++) { }
+#ifdef Pack_32
+ Bigint* b = Balloc(k);
+ 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;
+#endif
+
+ int i = 9;
+ if (9 < nd0) {
+ s += 9;
+ do {
+ b = multadd(b, 10, *s++ - '0');
+ } while (++i < nd0);
+ s++;
+ } else
+ s += 10;
+ for (; i < nd; i++)
+ b = multadd(b, 10, *s++ - '0');
+ return b;
+}
+
+static int hi0bits(uint32_t x)
+{
+ int k = 0;
+
+ if (!(x & 0xffff0000)) {
+ k = 16;
+ x <<= 16;
+ }
+ if (!(x & 0xff000000)) {
+ k += 8;
+ x <<= 8;
+ }
+ if (!(x & 0xf0000000)) {
+ k += 4;
+ x <<= 4;
+ }
+ if (!(x & 0xc0000000)) {
+ k += 2;
+ x <<= 2;
+ }
+ if (!(x & 0x80000000)) {
+ k++;
+ if (!(x & 0x40000000))
+ return 32;
+ }
+ return k;
+}
+
+static int lo0bits (uint32_t* y)
+{
+ int k;
+ uint32_t x = *y;
+
+ if (x & 7) {
+ if (x & 1)
+ return 0;
+ if (x & 2) {
+ *y = x >> 1;
+ return 1;
+ }
+ *y = x >> 2;
+ return 2;
+ }
+ k = 0;
+ if (!(x & 0xffff)) {
+ k = 16;
+ x >>= 16;
+ }
+ if (!(x & 0xff)) {
+ k += 8;
+ x >>= 8;
+ }
+ if (!(x & 0xf)) {
+ k += 4;
+ x >>= 4;
+ }
+ if (!(x & 0x3)) {
+ k += 2;
+ x >>= 2;
+ }
+ if (!(x & 1)) {
+ k++;
+ x >>= 1;
+ if (!x & 1)
+ return 32;
+ }
+ *y = x;
+ return k;
+}
+
+static Bigint* i2b(int i)
+{
+ Bigint* b;
+
+ b = Balloc(1);
+ b->x[0] = i;
+ b->wds = 1;
+ return b;
+}
+
+static Bigint* mult(Bigint* a, Bigint* b)
+{
+ Bigint* c;
+ int k, wa, wb, wc;
+ uint32_t *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
+ uint32_t y;
+#ifdef USE_LONG_LONG
+ unsigned long long carry, z;
+#else
+ uint32_t carry, z;
+#endif
+
+ if (a->wds < b->wds) {
+ c = a;
+ a = b;
+ b = c;
+ }
+ 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;
+ xa = a->x;
+ xae = xa + wa;
+ xb = b->x;
+ xbe = xb + wb;
+ xc0 = c->x;
+#ifdef USE_LONG_LONG
+ for (; xb < xbe; xc0++) {
+ if ((y = *xb++)) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = *x++ * (unsigned long long)y + *xc + carry;
+ carry = z >> 32;
+ *xc++ = (uint32_t)z & 0xffffffffUL;
+ } while (x < xae);
+ *xc = (uint32_t)carry;
+ }
+ }
+#else
+#ifdef Pack_32
+ for (; xb < xbe; xb++, xc0++) {
+ if ((y = *xb & 0xffff)) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
+ carry = z >> 16;
+ uint32_t z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
+ carry = z2 >> 16;
+ Storeinc(xc, z2, z);
+ } while (x < xae);
+ *xc = carry;
+ }
+ if ((y = *xb >> 16)) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ uint32_t z2 = *xc;
+ do {
+ z = (*x & 0xffff) * y + (*xc >> 16) + carry;
+ carry = z >> 16;
+ Storeinc(xc, z, z2);
+ z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
+ carry = z2 >> 16;
+ } while (x < xae);
+ *xc = z2;
+ }
+ }
+#else
+ for(; xb < xbe; xc0++) {
+ if ((y = *xb++)) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = *x++ * y + *xc + carry;
+ carry = z >> 16;
+ *xc++ = z & 0xffff;
+ } while (x < xae);
+ *xc = carry;
+ }
+ }
+#endif
+#endif
+ for (xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) { }
+ c->wds = wc;
+ return c;
+}
+
+static Bigint* p5s;
+static int p5s_count;
+
+static Bigint* pow5mult(Bigint* b, int k)
+{
+ static int p05[3] = { 5, 25, 125 };
+
+ if (int i = k & 3)
+ b = multadd(b, p05[i - 1], 0);
+
+ if (!(k >>= 2))
+ return b;
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ s_dtoaP5Mutex->lock();
+#endif
+ Bigint* p5 = p5s;
+ if (!p5) {
+ /* first time */
+ p5 = p5s = i2b(625);
+ p5s_count = 1;
+ }
+ int p5s_count_local = p5s_count;
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ s_dtoaP5Mutex->unlock();
+#endif
+ int p5s_used = 0;
+
+ for (;;) {
+ if (k & 1) {
+ Bigint* b1 = mult(b, p5);
+ Bfree(b);
+ b = b1;
+ }
+ if (!(k >>= 1))
+ break;
+
+ if (++p5s_used == p5s_count_local) {
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ s_dtoaP5Mutex->lock();
+#endif
+ if (p5s_used == p5s_count) {
+ ASSERT(!p5->next);
+ p5->next = mult(p5, p5);
+ ++p5s_count;
+ }
+
+ p5s_count_local = p5s_count;
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ s_dtoaP5Mutex->unlock();
+#endif
+ }
+ p5 = p5->next;
+ }
+
+ return b;
+}
+
+static Bigint* 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);
+
+ const uint32_t* srcStart = b->x;
+ uint32_t* dstStart = result->x;
+ const uint32_t* src = srcStart + b->wds - 1;
+ uint32_t* dst = dstStart + n1 - 1;
+#ifdef Pack_32
+ if (k &= 0x1f) {
+ uint32_t hiSubword = 0;
+ int s = 32 - k;
+ for (; src >= srcStart; --src) {
+ *dst-- = hiSubword | *src >> s;
+ hiSubword = *src << k;
+ }
+ *dst = hiSubword;
+ ASSERT(dst == dstStart + n);
+ result->wds = b->wds + n + (result->x[n1 - 1] != 0);
+ }
+#else
+ if (k &= 0xf) {
+ uint32_t hiSubword = 0;
+ int s = 16 - k;
+ for (; src >= srcStart; --src) {
+ *dst-- = hiSubword | *src >> s;
+ hiSubword = (*src << k) & 0xffff;
+ }
+ *dst = hiSubword;
+ ASSERT(dst == dstStart + n);
+ result->wds = b->wds + n + (result->x[n1 - 1] != 0);
+ }
+ #endif
+ else {
+ do {
+ *--dst = *src--;
+ } while (src >= srcStart);
+ result->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)
+{
+ 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]);
+ if (i -= j)
+ return i;
+ xa0 = a->x;
+ xa = xa0 + j;
+ xb0 = b->x;
+ xb = xb0 + j;
+ for (;;) {
+ if (*--xa != *--xb)
+ return *xa < *xb ? -1 : 1;
+ if (xa <= xa0)
+ break;
+ }
+ return 0;
+}
+
+static Bigint* diff(Bigint* a, Bigint* b)
+{
+ Bigint* c;
+ int i, wa, wb;
+ uint32_t *xa, *xae, *xb, *xbe, *xc;
+
+ i = cmp(a,b);
+ if (!i) {
+ c = Balloc(0);
+ c->wds = 1;
+ c->x[0] = 0;
+ return c;
+ }
+ if (i < 0) {
+ c = a;
+ a = b;
+ b = c;
+ i = 1;
+ } else
+ i = 0;
+ c = Balloc(a->k);
+ c->sign = i;
+ wa = a->wds;
+ xa = a->x;
+ xae = xa + wa;
+ wb = b->wds;
+ xb = b->x;
+ xbe = xb + wb;
+ xc = c->x;
+#ifdef USE_LONG_LONG
+ unsigned long long borrow = 0;
+ do {
+ unsigned long long y = (unsigned long long)*xa++ - *xb++ - borrow;
+ borrow = y >> 32 & (uint32_t)1;
+ *xc++ = (uint32_t)y & 0xffffffffUL;
+ } while (xb < xbe);
+ while (xa < xae) {
+ unsigned long long y = *xa++ - borrow;
+ borrow = y >> 32 & (uint32_t)1;
+ *xc++ = (uint32_t)y & 0xffffffffUL;
+ }
+#else
+ uint32_t borrow = 0;
+#ifdef Pack_32
+ do {
+ uint32_t y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ uint32_t z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(xc, z, y);
+ } while (xb < xbe);
+ while (xa < xae) {
+ uint32_t y = (*xa & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ uint32_t z = (*xa++ >> 16) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(xc, z, y);
+ }
+#else
+ do {
+ uint32_t y = *xa++ - *xb++ - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *xc++ = y & 0xffff;
+ } while (xb < xbe);
+ while (xa < xae) {
+ uint32_t y = *xa++ - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *xc++ = y & 0xffff;
+ }
+#endif
+#endif
+ while (!*--xc)
+ wa--;
+ c->wds = wa;
+ return c;
+}
+
+static double ulp(double x)
+{
+ register int32_t L;
+ double a;
+
+ L = (word0(x) & Exp_mask) - (P - 1) * Exp_msk1;
+#ifndef Avoid_Underflow
+#ifndef Sudden_Underflow
+ if (L > 0) {
+#endif
+#endif
+ word0(a) = L;
+ word1(a) = 0;
+#ifndef Avoid_Underflow
+#ifndef Sudden_Underflow
+ } else {
+ L = -L >> Exp_shift;
+ if (L < Exp_shift) {
+ word0(a) = 0x80000 >> L;
+ word1(a) = 0;
+ } else {
+ word0(a) = 0;
+ L -= Exp_shift;
+ word1(a) = L >= 31 ? 1 : 1 << 31 - L;
+ }
+ }
+#endif
+#endif
+ return dval(a);
+}
+
+static double b2d(Bigint* a, int* e)
+{
+ uint32_t* xa;
+ uint32_t* xa0;
+ uint32_t w;
+ uint32_t y;
+ uint32_t z;
+ int k;
+ double d;
+
+#define d0 word0(d)
+#define d1 word1(d)
+
+ 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;
+ w = xa > xa0 ? *--xa : 0;
+ 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;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = z << k | y >> 32 - k;
+ } else {
+ d0 = Exp_1 | y;
+ d1 = z;
+ }
+#else
+ if (k < Ebits + 16) {
+ z = xa > xa0 ? *--xa : 0;
+ d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
+ w = xa > xa0 ? *--xa : 0;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
+ goto ret_d;
+ }
+ z = xa > xa0 ? *--xa : 0;
+ w = xa > xa0 ? *--xa : 0;
+ k -= Ebits + 16;
+ d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = w << k + 16 | y << k;
+#endif
+ret_d:
+#undef d0
+#undef d1
+ return dval(d);
+}
+
+static Bigint* d2b(double d, int* e, int* bits)
+{
+ Bigint* b;
+ int de, k;
+ uint32_t *x, y, z;
+#ifndef Sudden_Underflow
+ int i;
+#endif
+#define d0 word0(d)
+#define d1 word1(d)
+
+#ifdef Pack_32
+ b = Balloc(1);
+#else
+ b = Balloc(2);
+#endif
+ x = b->x;
+
+ z = d0 & Frac_mask;
+ d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
+#ifdef Sudden_Underflow
+ de = (int)(d0 >> Exp_shift);
+#else
+ if ((de = (int)(d0 >> Exp_shift)))
+ z |= Exp_msk1;
+#endif
+#ifdef Pack_32
+ if ((y = d1)) {
+ if ((k = lo0bits(&y))) {
+ x[0] = y | z << 32 - k;
+ z >>= k;
+ } else
+ x[0] = y;
+#ifndef Sudden_Underflow
+ i =
+#endif
+ b->wds = (x[1] = z) ? 2 : 1;
+ } else {
+ k = lo0bits(&z);
+ x[0] = z;
+#ifndef Sudden_Underflow
+ i =
+#endif
+ b->wds = 1;
+ k += 32;
+ }
+#else
+ if ((y = d1)) {
+ if ((k = lo0bits(&y))) {
+ if (k >= 16) {
+ x[0] = y | z << 32 - k & 0xffff;
+ x[1] = z >> k - 16 & 0xffff;
+ x[2] = z >> k;
+ i = 2;
+ } else {
+ x[0] = y & 0xffff;
+ x[1] = y >> 16 | z << 16 - k & 0xffff;
+ x[2] = z >> k & 0xffff;
+ x[3] = z >> k + 16;
+ i = 3;
+ }
+ } else {
+ x[0] = y & 0xffff;
+ x[1] = y >> 16;
+ x[2] = z & 0xffff;
+ x[3] = z >> 16;
+ i = 3;
+ }
+ } else {
+ k = lo0bits(&z);
+ if (k >= 16) {
+ x[0] = z;
+ i = 0;
+ } else {
+ x[0] = z & 0xffff;
+ x[1] = z >> 16;
+ i = 1;
+ }
+ k += 32;
+ } while (!x[i])
+ --i;
+ b->wds = i + 1;
+#endif
+#ifndef Sudden_Underflow
+ if (de) {
+#endif
+ *e = de - Bias - (P - 1) + k;
+ *bits = P - k;
+#ifndef Sudden_Underflow
+ } else {
+ *e = de - Bias - (P - 1) + 1 + k;
+#ifdef Pack_32
+ *bits = (32 * i) - hi0bits(x[i - 1]);
+#else
+ *bits = (i + 2) * 16 - hi0bits(x[i]);
+#endif
+ }
+#endif
+ return b;
+}
+#undef d0
+#undef d1
+
+static double ratio(Bigint* a, Bigint* b)
+{
+ double da, db;
+ int k, ka, kb;
+
+ dval(da) = b2d(a, &ka);
+ dval(db) = b2d(b, &kb);
+#ifdef Pack_32
+ k = ka - kb + 32 * (a->wds - b->wds);
+#else
+ k = ka - kb + 16 * (a->wds - b->wds);
+#endif
+ if (k > 0)
+ word0(da) += k * Exp_msk1;
+ else {
+ k = -k;
+ word0(db) += k * Exp_msk1;
+ }
+ return dval(da) / dval(db);
+}
+
+static const double tens[] = {
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+ 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+ 1e20, 1e21, 1e22
+};
+
+static const double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
+static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
+#ifdef Avoid_Underflow
+ 9007199254740992. * 9007199254740992.e-256
+ /* = 2^106 * 1e-53 */
+#else
+ 1e-256
+#endif
+};
+
+/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
+/* flag unnecessarily. It leads to a song and dance at the end of strtod. */
+#define Scale_Bit 0x10
+#define n_bigtens 5
+
+#if defined(INFNAN_CHECK)
+
+#ifndef NAN_WORD0
+#define NAN_WORD0 0x7ff80000
+#endif
+
+#ifndef NAN_WORD1
+#define NAN_WORD1 0
+#endif
+
+static int match(const char** sp, const char* t)
+{
+ int c, d;
+ const char* s = *sp;
+
+ while ((d = *t++)) {
+ if ((c = *++s) >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+ if (c != d)
+ return 0;
+ }
+ *sp = s + 1;
+ return 1;
+}
+
+#ifndef No_Hex_NaN
+static void hexnan(double* rvp, const char** sp)
+{
+ uint32_t c, x[2];
+ const char* s;
+ int havedig, udx0, xshift;
+
+ x[0] = x[1] = 0;
+ havedig = xshift = 0;
+ udx0 = 1;
+ s = *sp;
+ while ((c = *(const unsigned char*)++s)) {
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'a' && c <= 'f')
+ c += 10 - 'a';
+ else if (c >= 'A' && c <= 'F')
+ c += 10 - 'A';
+ else if (c <= ' ') {
+ if (udx0 && havedig) {
+ udx0 = 0;
+ xshift = 1;
+ }
+ continue;
+ } else if (/*(*/ c == ')' && havedig) {
+ *sp = s + 1;
+ break;
+ } else
+ return; /* invalid form: don't change *sp */
+ havedig = 1;
+ if (xshift) {
+ xshift = 0;
+ x[0] = x[1];
+ x[1] = 0;
+ }
+ if (udx0)
+ x[0] = (x[0] << 4) | (x[1] >> 28);
+ x[1] = (x[1] << 4) | c;
+ }
+ if ((x[0] &= 0xfffff) || x[1]) {
+ word0(*rvp) = Exp_mask | x[0];
+ word1(*rvp) = x[1];
+ }
+}
+#endif /*No_Hex_NaN*/
+#endif /* INFNAN_CHECK */
+
+double strtod(const char* s00, char** se)
+{
+#ifdef Avoid_Underflow
+ int scale;
+#endif
+ 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;
+ int32_t L;
+ uint32_t y, z;
+ Bigint *bb = NULL, *bb1 = NULL, *bd = NULL, *bd0 = NULL, *bs = NULL, *delta = NULL;
+#ifdef SET_INEXACT
+ int inexact, oldinexact;
+#endif
+
+ sign = nz0 = nz = 0;
+ dval(rv) = 0.;
+ for (s = s00; ; s++)
+ switch (*s) {
+ case '-':
+ sign = 1;
+ /* no break */
+ case '+':
+ if (*++s)
+ goto break2;
+ /* no break */
+ case 0:
+ goto ret0;
+ case '\t':
+ case '\n':
+ case '\v':
+ case '\f':
+ case '\r':
+ case ' ':
+ continue;
+ default:
+ goto break2;
+ }
+break2:
+ if (*s == '0') {
+ nz0 = 1;
+ while (*++s == '0') { }
+ if (!*s)
+ goto ret;
+ }
+ s0 = s;
+ y = z = 0;
+ for (nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
+ if (nd < 9)
+ y = (10 * y) + c - '0';
+ else if (nd < 16)
+ z = (10 * z) + c - '0';
+ nd0 = nd;
+ if (c == '.') {
+ c = *++s;
+ if (!nd) {
+ for (; c == '0'; c = *++s)
+ nz++;
+ if (c > '0' && c <= '9') {
+ s0 = s;
+ nf += nz;
+ nz = 0;
+ goto have_dig;
+ }
+ goto dig_done;
+ }
+ for (; c >= '0' && c <= '9'; c = *++s) {
+have_dig:
+ nz++;
+ if (c -= '0') {
+ nf += nz;
+ for (i = 1; i < nz; i++)
+ if (nd++ < 9)
+ y *= 10;
+ else if (nd <= DBL_DIG + 1)
+ z *= 10;
+ if (nd++ < 9)
+ y = (10 * y) + c;
+ else if (nd <= DBL_DIG + 1)
+ z = (10 * z) + c;
+ nz = 0;
+ }
+ }
+ }
+dig_done:
+ e = 0;
+ if (c == 'e' || c == 'E') {
+ if (!nd && !nz && !nz0) {
+ goto ret0;
+ }
+ s00 = s;
+ esign = 0;
+ switch (c = *++s) {
+ case '-':
+ esign = 1;
+ case '+':
+ c = *++s;
+ }
+ if (c >= '0' && c <= '9') {
+ while (c == '0')
+ c = *++s;
+ if (c > '0' && c <= '9') {
+ L = c - '0';
+ s1 = s;
+ while ((c = *++s) >= '0' && c <= '9')
+ L = (10 * L) + c - '0';
+ if (s - s1 > 8 || L > 19999)
+ /* Avoid confusion from exponents
+ * so large that e might overflow.
+ */
+ e = 19999; /* safe for 16 bit ints */
+ else
+ e = (int)L;
+ if (esign)
+ e = -e;
+ } else
+ e = 0;
+ } else
+ s = s00;
+ }
+ if (!nd) {
+ if (!nz && !nz0) {
+#ifdef INFNAN_CHECK
+ /* Check for Nan and Infinity */
+ switch(c) {
+ case 'i':
+ case 'I':
+ if (match(&s,"nf")) {
+ --s;
+ if (!match(&s,"inity"))
+ ++s;
+ 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;
+#ifndef No_Hex_NaN
+ if (*s == '(') /*)*/
+ hexnan(&rv, &s);
+#endif
+ goto ret;
+ }
+ }
+#endif /* INFNAN_CHECK */
+ret0:
+ s = s00;
+ sign = 0;
+ }
+ goto ret;
+ }
+ e1 = e -= nf;
+
+ /* Now we have nd0 digits, starting at s0, followed by a
+ * decimal point, followed by nd-nd0 digits. The number we're
+ * after is the integer represented by those digits times
+ * 10**e */
+
+ if (!nd0)
+ nd0 = nd;
+ k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
+ 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;
+ }
+ 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]);
+ goto ret;
+ }
+ i = DBL_DIG - nd;
+ if (e <= Ten_pmax + i) {
+ /* A fancier test would sometimes let us do
+ * this for larger i values.
+ */
+ e -= i;
+ 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]);
+ goto ret;
+ }
+#endif
+ }
+ e1 += nd - k;
+
+#ifdef SET_INEXACT
+ inexact = 1;
+ if (k <= DBL_DIG)
+ oldinexact = get_inexact();
+#endif
+#ifdef Avoid_Underflow
+ scale = 0;
+#endif
+
+ /* Get starting approximation = rv * 10**e1 */
+
+ if (e1 > 0) {
+ if ((i = e1 & 15))
+ dval(rv) *= tens[i];
+ if (e1 &= ~15) {
+ if (e1 > DBL_MAX_10_EXP) {
+ovfl:
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ /* Can't trust HUGE_VAL */
+ word0(rv) = Exp_mask;
+ word1(rv) = 0;
+#ifdef SET_INEXACT
+ /* set overflow bit */
+ 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];
+ /* 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))
+ 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;
+ } else
+ word0(rv) += P * Exp_msk1;
+ }
+ } else if (e1 < 0) {
+ e1 = -e1;
+ if ((i = e1 & 15))
+ dval(rv) /= tens[i];
+ if (e1 >>= 4) {
+ if (e1 >= 1 << n_bigtens)
+ goto undfl;
+#ifdef Avoid_Underflow
+ if (e1 & Scale_Bit)
+ 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) {
+ /* scaled rv is denormal; zap j low bits */
+ if (j >= 32) {
+ word1(rv) = 0;
+ if (j >= 53)
+ word0(rv) = (P + 2) * Exp_msk1;
+ else
+ word0(rv) &= 0xffffffff << j - 32;
+ } else
+ word1(rv) &= 0xffffffff << j;
+ }
+#else
+ for (j = 0; e1 > 1; j++, e1 >>= 1)
+ if (e1 & 1)
+ 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];
+#endif
+ if (!dval(rv)) {
+undfl:
+ dval(rv) = 0.;
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ if (bd0)
+ goto retfree;
+ goto ret;
+ }
+#ifndef Avoid_Underflow
+ word0(rv) = Tiny0;
+ word1(rv) = Tiny1;
+ /* The refinement below will clean
+ * this approximation up.
+ */
+ }
+#endif
+ }
+ }
+
+ /* Now the hard part -- adjusting rv to the correct value.*/
+
+ /* Put digits into bd: true value = bd * 10^e */
+
+ bd0 = s2b(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);
+
+ if (e >= 0) {
+ bb2 = bb5 = 0;
+ bd2 = bd5 = e;
+ } else {
+ bb2 = bb5 = -e;
+ bd2 = bd5 = 0;
+ }
+ if (bbe >= 0)
+ bb2 += bbe;
+ else
+ bd2 -= bbe;
+ bs2 = bb2;
+#ifdef Avoid_Underflow
+ j = bbe - scale;
+ i = j + bbbits - 1; /* logb(rv) */
+ if (i < Emin) /* denormal */
+ j += P - Emin;
+ else
+ j = P + 1 - bbbits;
+#else /*Avoid_Underflow*/
+#ifdef Sudden_Underflow
+ j = P + 1 - bbbits;
+#else /*Sudden_Underflow*/
+ j = bbe;
+ i = j + bbbits - 1; /* logb(rv) */
+ if (i < Emin) /* denormal */
+ j += P - Emin;
+ else
+ j = P + 1 - bbbits;
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ bb2 += j;
+ bd2 += j;
+#ifdef Avoid_Underflow
+ bd2 += scale;
+#endif
+ i = bb2 < bd2 ? bb2 : bd2;
+ if (i > bs2)
+ i = bs2;
+ if (i > 0) {
+ bb2 -= i;
+ bd2 -= i;
+ bs2 -= i;
+ }
+ if (bb5 > 0) {
+ bs = pow5mult(bs, bb5);
+ bb1 = mult(bs, bb);
+ Bfree(bb);
+ bb = bb1;
+ }
+ if (bb2 > 0)
+ bb = lshift(bb, bb2);
+ if (bd5 > 0)
+ bd = pow5mult(bd, bd5);
+ if (bd2 > 0)
+ bd = lshift(bd, bd2);
+ if (bs2 > 0)
+ bs = lshift(bs, bs2);
+ delta = diff(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
+#ifdef Avoid_Underflow
+ || (word0(rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1
+#else
+ || (word0(rv) & Exp_mask) <= Exp_msk1
+#endif
+ ) {
+#ifdef SET_INEXACT
+ if (!delta->x[0] && delta->wds <= 1)
+ inexact = 0;
+#endif
+ break;
+ }
+ if (!delta->x[0] && delta->wds <= 1) {
+ /* exact result */
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ break;
+ }
+ delta = lshift(delta,Log2P);
+ if (cmp(delta, bs) > 0)
+ goto drop_down;
+ break;
+ }
+ if (i == 0) {
+ /* exactly half-way between */
+ if (dsign) {
+ if ((word0(rv) & Bndry_mask1) == Bndry_mask1
+ && word1(rv) == (
+#ifdef Avoid_Underflow
+ (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;
+#ifdef Avoid_Underflow
+ dsign = 0;
+#endif
+ break;
+ }
+ } else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
+drop_down:
+ /* boundary case -- decrement exponent */
+#ifdef Sudden_Underflow /*{{*/
+ L = word0(rv) & Exp_mask;
+#ifdef Avoid_Underflow
+ if (L <= (scale ? (2 * P + 1) * Exp_msk1 : Exp_msk1))
+#else
+ if (L <= Exp_msk1)
+#endif /*Avoid_Underflow*/
+ goto undfl;
+ L -= Exp_msk1;
+#else /*Sudden_Underflow}{*/
+#ifdef Avoid_Underflow
+ if (scale) {
+ L = word0(rv) & Exp_mask;
+ if (L <= (2 * P + 1) * Exp_msk1) {
+ if (L > (P + 2) * Exp_msk1)
+ /* round even ==> */
+ /* accept rv */
+ break;
+ /* rv = smallest denormal */
+ goto undfl;
+ }
+ }
+#endif /*Avoid_Underflow*/
+ L = (word0(rv) & Exp_mask) - Exp_msk1;
+#endif /*Sudden_Underflow}}*/
+ word0(rv) = L | Bndry_mask1;
+ word1(rv) = 0xffffffff;
+ break;
+ }
+ if (!(word1(rv) & LSB))
+ break;
+ if (dsign)
+ dval(rv) += ulp(dval(rv));
+ else {
+ dval(rv) -= ulp(dval(rv));
+#ifndef Sudden_Underflow
+ if (!dval(rv))
+ goto undfl;
+#endif
+ }
+#ifdef Avoid_Underflow
+ dsign = 1 - dsign;
+#endif
+ break;
+ }
+ if ((aadj = ratio(delta, bs)) <= 2.) {
+ if (dsign)
+ aadj = aadj1 = 1.;
+ else if (word1(rv) || word0(rv) & Bndry_mask) {
+#ifndef Sudden_Underflow
+ if (word1(rv) == Tiny1 && !word0(rv))
+ goto undfl;
+#endif
+ aadj = 1.;
+ aadj1 = -1.;
+ } else {
+ /* special case -- power of FLT_RADIX to be */
+ /* rounded down... */
+
+ if (aadj < 2. / FLT_RADIX)
+ aadj = 1. / FLT_RADIX;
+ else
+ aadj *= 0.5;
+ aadj1 = -aadj;
+ }
+ } else {
+ aadj *= 0.5;
+ aadj1 = dsign ? aadj : -aadj;
+#ifdef Check_FLT_ROUNDS
+ switch (Rounding) {
+ case 2: /* towards +infinity */
+ aadj1 -= 0.5;
+ break;
+ case 0: /* towards 0 */
+ case 3: /* towards -infinity */
+ aadj1 += 0.5;
+ }
+#else
+ if (Flt_Rounds == 0)
+ aadj1 += 0.5;
+#endif /*Check_FLT_ROUNDS*/
+ }
+ 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)
+ goto ovfl;
+ word0(rv) = Big0;
+ word1(rv) = Big1;
+ goto cont;
+ } else
+ word0(rv) += P * Exp_msk1;
+ } else {
+#ifdef Avoid_Underflow
+ if (scale && y <= 2 * P * Exp_msk1) {
+ if (aadj <= 0x7fffffff) {
+ if ((z = (uint32_t)aadj) <= 0)
+ z = 1;
+ aadj = z;
+ aadj1 = dsign ? aadj : -aadj;
+ }
+ word0(aadj1) += (2 * P + 1) * Exp_msk1 - y;
+ }
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
+#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(rv0) == Tiny0 && word1(rv0) == Tiny1)
+ goto undfl;
+ word0(rv) = Tiny0;
+ word1(rv) = Tiny1;
+ goto cont;
+ }
+ else
+ word0(rv) -= P * Exp_msk1;
+ } else {
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
+ }
+#else /*Sudden_Underflow*/
+ /* Compute adj so that the IEEE rounding rules will
+ * correctly round rv + adj in some half-way cases.
+ * If rv * ulp(rv) is denormalized (i.e.,
+ * y <= (P - 1) * Exp_msk1), we must adjust aadj to avoid
+ * trouble from bits lost to denormalization;
+ * example: 1.2e-307 .
+ */
+ if (y <= (P - 1) * Exp_msk1 && aadj > 1.) {
+ aadj1 = (double)(int)(aadj + 0.5);
+ if (!dsign)
+ aadj1 = -aadj1;
+ }
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ }
+ z = word0(rv) & Exp_mask;
+#ifndef SET_INEXACT
+#ifdef Avoid_Underflow
+ if (!scale)
+#endif
+ if (y == z) {
+ /* Can we stop now? */
+ L = (int32_t)aadj;
+ aadj -= L;
+ /* The tolerances below are conservative. */
+ if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
+ if (aadj < .4999999 || aadj > .5000001)
+ break;
+ } else if (aadj < .4999999 / FLT_RADIX)
+ break;
+ }
+#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.;
+ }
+ } 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);
+#ifndef NO_ERRNO
+ /* try to avoid the bug of testing an 8087 register value */
+ if (word0(rv) == 0 && word1(rv) == 0)
+ errno = ERANGE;
+#endif
+ }
+#endif /* Avoid_Underflow */
+#ifdef SET_INEXACT
+ if (inexact && !(word0(rv) & Exp_mask)) {
+ /* set underflow bit */
+ dval(rv0) = 1e-300;
+ dval(rv0) *= dval(rv0);
+ }
+#endif
+retfree:
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(bd0);
+ Bfree(delta);
+ret:
+ if (se)
+ *se = const_cast<char*>(s);
+ return sign ? -dval(rv) : dval(rv);
+}
+
+static int quorem(Bigint* b, Bigint* S)
+{
+ int n;
+ uint32_t *bx, *bxe, q, *sx, *sxe;
+#ifdef USE_LONG_LONG
+ unsigned long long borrow, carry, y, ys;
+#else
+ uint32_t borrow, carry, y, ys;
+#ifdef Pack_32
+ uint32_t si, z, zs;
+#endif
+#endif
+
+ n = S->wds;
+ ASSERT_WITH_MESSAGE(b->wds <= n, "oversize b in quorem");
+ if (b->wds < n)
+ return 0;
+ sx = S->x;
+ sxe = sx + --n;
+ bx = b->x;
+ bxe = bx + n;
+ q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
+ ASSERT_WITH_MESSAGE(q <= 9, "oversized quotient in quorem");
+ if (q) {
+ borrow = 0;
+ carry = 0;
+ do {
+#ifdef USE_LONG_LONG
+ ys = *sx++ * (unsigned long long)q + carry;
+ carry = ys >> 32;
+ y = *bx - (ys & 0xffffffffUL) - borrow;
+ borrow = y >> 32 & (uint32_t)1;
+ *bx++ = (uint32_t)y & 0xffffffffUL;
+#else
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) * q + carry;
+ zs = (si >> 16) * q + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*bx >> 16) - (zs & 0xffff) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(bx, z, y);
+#else
+ ys = *sx++ * q + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *bx++ = y & 0xffff;
+#endif
+#endif
+ } while (sx <= sxe);
+ if (!*bxe) {
+ bx = b->x;
+ while (--bxe > bx && !*bxe)
+ --n;
+ b->wds = n;
+ }
+ }
+ if (cmp(b, S) >= 0) {
+ q++;
+ borrow = 0;
+ carry = 0;
+ bx = b->x;
+ sx = S->x;
+ do {
+#ifdef USE_LONG_LONG
+ ys = *sx++ + carry;
+ carry = ys >> 32;
+ y = *bx - (ys & 0xffffffffUL) - borrow;
+ borrow = y >> 32 & (uint32_t)1;
+ *bx++ = (uint32_t)y & 0xffffffffUL;
+#else
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) + carry;
+ zs = (si >> 16) + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*bx >> 16) - (zs & 0xffff) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(bx, z, y);
+#else
+ ys = *sx++ + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *bx++ = y & 0xffff;
+#endif
+#endif
+ } while (sx <= sxe);
+ bx = b->x;
+ bxe = bx + n;
+ if (!*bxe) {
+ while (--bxe > bx && !*bxe)
+ --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
+ * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
+ *
+ * Modifications:
+ * 1. Rather than iterating, we use a simple numeric overestimate
+ * to determine k = floor(log10(d)). We scale relevant
+ * quantities using O(log2(k)) rather than O(k) multiplications.
+ * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
+ * try to generate digits strictly left to right. Instead, we
+ * compute with fewer bits and propagate the carry if necessary
+ * when rounding the final digit up. This is often faster.
+ * 3. Under the assumption that input will be rounded nearest,
+ * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
+ * That is, we allow equality in stopping tests when the
+ * round-nearest rule will give the same floating-point value
+ * as would satisfaction of the stopping test with strict
+ * inequality.
+ * 4. We remove common factors of powers of 2 from relevant
+ * quantities.
+ * 5. When converting floating-point integers less than 1e16,
+ * we use floating-point arithmetic rather than resorting
+ * to multiple-precision integers.
+ * 6. When asked to produce fewer than 15 digits, we first try
+ * to get by with floating-point arithmetic; we resort to
+ * multiple-precision integer arithmetic only if we cannot
+ * guarantee that the floating-point calculation has given
+ * the correctly rounded result. For k requested digits and
+ * "uniformly" distributed input, the probability is
+ * something like 10^(k-15) that we must resort to the int32_t
+ * calculation.
+ */
+
+char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve)
+{
+ /*
+ Arguments ndigits, decpt, sign are similar to those
+ of ecvt and fcvt; trailing zeros are suppressed from
+ the returned string. If not null, *rve is set to point
+ to the end of the return value. If d is +-Infinity or NaN,
+ then *decpt is set to 9999.
+
+ */
+
+ int bbits, b2, b5, be, dig, i, ieps, ilim = 0, ilim0, ilim1 = 0,
+ j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
+ spec_case, try_quick;
+ int32_t L;
+#ifndef Sudden_Underflow
+ int denorm;
+ uint32_t x;
+#endif
+ Bigint *b, *b1, *delta, *mlo = NULL, *mhi, *S;
+ double d2, ds, eps;
+ 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) {
+ /* set sign for everything, including 0's and NaNs */
+ *sign = 1;
+ word0(d) &= ~Sign_bit; /* clear sign bit */
+ } else
+ *sign = 0;
+
+ if ((word0(d) & 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 (!dval(d)) {
+ *decpt = 1;
+ return nrv_alloc("0", rve, 1);
+ }
+
+#ifdef SET_INEXACT
+ try_quick = oldinexact = get_inexact();
+ inexact = 1;
+#endif
+
+ b = d2b(dval(d), &be, &bbits);
+#ifdef Sudden_Underflow
+ i = (int)(word0(d) >> Exp_shift1 & (Exp_mask >> Exp_shift1));
+#else
+ if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask >> Exp_shift1)))) {
+#endif
+ dval(d2) = dval(d);
+ word0(d2) &= Frac_mask1;
+ word0(d2) |= Exp_11;
+
+ /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
+ * log10(x) = log(x) / log(10)
+ * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
+ * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
+ *
+ * This suggests computing an approximation k to log10(d) by
+ *
+ * k = (i - Bias)*0.301029995663981
+ * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
+ *
+ * We want k to be too large rather than too small.
+ * The error in the first-order Taylor series approximation
+ * is in our favor, so we just round up the constant enough
+ * to compensate for any error in the multiplication of
+ * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
+ * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
+ * adding 1e-13 to the constant term more than suffices.
+ * Hence we adjust the constant term to 0.1760912590558.
+ * (We could get a more accurate k by invoking log10,
+ * but this is probably not worthwhile.)
+ */
+
+ i -= Bias;
+#ifndef Sudden_Underflow
+ denorm = 0;
+ } else {
+ /* 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 */
+ i -= (Bias + (P - 1) - 1) + 1;
+ denorm = 1;
+ }
+#endif
+ 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])
+ k--;
+ k_check = 0;
+ }
+ j = bbits - i - 1;
+ if (j >= 0) {
+ b2 = 0;
+ s2 = j;
+ } else {
+ b2 = -j;
+ s2 = 0;
+ }
+ if (k >= 0) {
+ b5 = 0;
+ s5 = k;
+ s2 += k;
+ } else {
+ b2 -= k;
+ b5 = -k;
+ s5 = 0;
+ }
+
+#ifndef SET_INEXACT
+#ifdef Check_FLT_ROUNDS
+ try_quick = Rounding == 1;
+#else
+ try_quick = 1;
+#endif
+#endif /*SET_INEXACT*/
+
+ leftright = 1;
+ ilim = ilim1 = -1;
+ i = 18;
+ ndigits = 0;
+ s = s0 = rv_alloc(i);
+
+ if (ilim >= 0 && ilim <= Quick_max && try_quick) {
+
+ /* Try to get by with floating-point arithmetic. */
+
+ i = 0;
+ dval(d2) = dval(d);
+ k0 = k;
+ ilim0 = ilim;
+ ieps = 2; /* conservative */
+ if (k > 0) {
+ ds = tens[k & 0xf];
+ j = k >> 4;
+ if (j & Bletch) {
+ /* prevent overflows */
+ j &= Bletch - 1;
+ dval(d) /= bigtens[n_bigtens - 1];
+ ieps++;
+ }
+ for (; j; j >>= 1, i++) {
+ if (j & 1) {
+ ieps++;
+ ds *= bigtens[i];
+ }
+ }
+ dval(d) /= ds;
+ } else if ((j1 = -k)) {
+ dval(d) *= tens[j1 & 0xf];
+ for (j = j1 >> 4; j; j >>= 1, i++) {
+ if (j & 1) {
+ ieps++;
+ dval(d) *= bigtens[i];
+ }
+ }
+ }
+ if (k_check && dval(d) < 1. && ilim > 0) {
+ if (ilim1 <= 0)
+ goto fast_failed;
+ ilim = ilim1;
+ k--;
+ dval(d) *= 10.;
+ ieps++;
+ }
+ dval(eps) = (ieps * dval(d)) + 7.;
+ word0(eps) -= (P - 1) * Exp_msk1;
+ if (ilim == 0) {
+ S = mhi = 0;
+ dval(d) -= 5.;
+ if (dval(d) > dval(eps))
+ goto one_digit;
+ if (dval(d) < -dval(eps))
+ goto no_digits;
+ goto fast_failed;
+ }
+#ifndef No_leftright
+ if (leftright) {
+ /* Use Steele & White method of only
+ * generating digits needed.
+ */
+ dval(eps) = (0.5 / tens[ilim - 1]) - dval(eps);
+ for (i = 0;;) {
+ L = (long int)dval(d);
+ dval(d) -= L;
+ *s++ = '0' + (int)L;
+ if (dval(d) < dval(eps))
+ goto ret1;
+ if (1. - dval(d) < dval(eps))
+ goto bump_up;
+ if (++i >= ilim)
+ break;
+ dval(eps) *= 10.;
+ dval(d) *= 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))
+ ilim = i;
+ *s++ = '0' + (int)L;
+ if (i == ilim) {
+ if (dval(d) > 0.5 + dval(eps))
+ goto bump_up;
+ else if (dval(d) < 0.5 - dval(eps)) {
+ while (*--s == '0') { }
+ s++;
+ goto ret1;
+ }
+ break;
+ }
+ }
+#ifndef No_leftright
+ }
+#endif
+fast_failed:
+ s = s0;
+ dval(d) = dval(d2);
+ k = k0;
+ ilim = ilim0;
+ }
+
+ /* Do we have a "small" integer? */
+
+ if (be >= 0 && k <= Int_max) {
+ /* Yes. */
+ ds = tens[k];
+ if (ndigits < 0 && ilim <= 0) {
+ S = mhi = 0;
+ if (ilim < 0 || dval(d) <= 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;
+#ifdef Check_FLT_ROUNDS
+ /* If FLT_ROUNDS == 2, L will usually be high by 1 */
+ if (dval(d) < 0) {
+ L--;
+ dval(d) += ds;
+ }
+#endif
+ *s++ = '0' + (int)L;
+ if (!dval(d)) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ break;
+ }
+ if (i == ilim) {
+ dval(d) += dval(d);
+ if (dval(d) > ds || dval(d) == ds && L & 1) {
+bump_up:
+ while (*--s == '9')
+ if (s == s0) {
+ k++;
+ *s = '0';
+ break;
+ }
+ ++*s++;
+ }
+ break;
+ }
+ }
+ goto ret1;
+ }
+
+ m2 = b2;
+ m5 = b5;
+ mhi = mlo = 0;
+ if (leftright) {
+ i =
+#ifndef Sudden_Underflow
+ denorm ? be + (Bias + (P - 1) - 1 + 1) :
+#endif
+ 1 + P - bbits;
+ b2 += i;
+ s2 += i;
+ mhi = i2b(1);
+ }
+ if (m2 > 0 && s2 > 0) {
+ i = m2 < s2 ? m2 : s2;
+ b2 -= i;
+ m2 -= i;
+ s2 -= i;
+ }
+ if (b5 > 0) {
+ if (leftright) {
+ if (m5 > 0) {
+ mhi = pow5mult(mhi, m5);
+ b1 = mult(mhi, b);
+ Bfree(b);
+ b = b1;
+ }
+ if ((j = b5 - m5))
+ b = pow5mult(b, j);
+ } else
+ b = pow5mult(b, b5);
+ }
+ S = i2b(1);
+ if (s5 > 0)
+ S = 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)
+#ifndef Sudden_Underflow
+ && word0(d) & (Exp_mask & ~Exp_msk1)
+#endif
+ ) {
+ /* The special case */
+ b2 += Log2P;
+ s2 += Log2P;
+ spec_case = 1;
+ }
+
+ /* Arrange for convenient computation of quotients:
+ * shift left if necessary so divisor has 4 leading 0 bits.
+ *
+ * Perhaps we should just compute leading 28 bits of S once
+ * and for all and pass them and a shift to quorem, so it
+ * 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))
+ i = 32 - i;
+#else
+ if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds - 1]) : 1) + s2) & 0xf))
+ i = 16 - i;
+#endif
+ if (i > 4) {
+ i -= 4;
+ b2 += i;
+ m2 += i;
+ s2 += i;
+ } else if (i < 4) {
+ i += 28;
+ b2 += i;
+ m2 += i;
+ s2 += i;
+ }
+ if (b2 > 0)
+ b = lshift(b, b2);
+ if (s2 > 0)
+ S = lshift(S, s2);
+ if (k_check) {
+ if (cmp(b,S) < 0) {
+ k--;
+ b = multadd(b, 10, 0); /* we botched the k estimate */
+ if (leftright)
+ mhi = multadd(mhi, 10, 0);
+ ilim = ilim1;
+ }
+ }
+
+ if (leftright) {
+ if (m2 > 0)
+ mhi = lshift(mhi, m2);
+
+ /* Compute mlo -- check for special case
+ * that d is a normalized power of 2.
+ */
+
+ mlo = mhi;
+ if (spec_case) {
+ mhi = Balloc(mhi->k);
+ Bcopy(mhi, mlo);
+ mhi = lshift(mhi, Log2P);
+ }
+
+ for (i = 1;;i++) {
+ dig = quorem(b,S) + '0';
+ /* Do we yet have the shortest decimal string
+ * 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)) {
+ if (dig == '9')
+ goto round_9_up;
+ if (j > 0)
+ dig++;
+#ifdef SET_INEXACT
+ else if (!b->x[0] && b->wds <= 1)
+ inexact = 0;
+#endif
+ *s++ = dig;
+ goto ret;
+ }
+ if (j < 0 || j == 0 && !(word1(d) & 1)) {
+ if (!b->x[0] && b->wds <= 1) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ goto accept_dig;
+ }
+ if (j1 > 0) {
+ b = lshift(b, 1);
+ j1 = cmp(b, S);
+ if ((j1 > 0 || j1 == 0 && dig & 1) && dig++ == '9')
+ goto round_9_up;
+ }
+accept_dig:
+ *s++ = dig;
+ goto ret;
+ }
+ if (j1 > 0) {
+ if (dig == '9') { /* possible if i == 1 */
+round_9_up:
+ *s++ = '9';
+ goto roundoff;
+ }
+ *s++ = dig + 1;
+ goto ret;
+ }
+ *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);
+ }
+ }
+ } else
+ for (i = 1;; i++) {
+ *s++ = dig = quorem(b,S) + '0';
+ if (!b->x[0] && b->wds <= 1) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ goto ret;
+ }
+ if (i >= ilim)
+ break;
+ b = multadd(b, 10, 0);
+ }
+
+ /* Round off last digit */
+
+ b = lshift(b, 1);
+ j = cmp(b, S);
+ if (j > 0 || j == 0 && dig & 1) {
+roundoff:
+ while (*--s == '9')
+ if (s == s0) {
+ k++;
+ *s++ = '1';
+ goto ret;
+ }
+ ++*s++;
+ } else {
+ while (*--s == '0') { }
+ s++;
+ }
+ goto ret;
+no_digits:
+ k = -1 - ndigits;
+ goto ret;
+one_digit:
+ *s++ = '1';
+ 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.;
+ }
+ } else if (!oldinexact)
+ clear_inexact();
+#endif
+ Bfree(b);
+ *s = 0;
+ *decpt = k + 1;
+ if (rve)
+ *rve = s;
+ return s0;
+}
+
+} // namespace WTF
diff --git a/JavaScriptCore/wtf/dtoa.h b/JavaScriptCore/wtf/dtoa.h
new file mode 100644
index 0000000..ed858c0
--- /dev/null
+++ b/JavaScriptCore/wtf/dtoa.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2003, 2008 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
+ * 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 WTF_dtoa_h
+#define WTF_dtoa_h
+
+namespace WTF {
+ class Mutex;
+}
+
+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);
+
+} // namespace WTF
+
+#endif // WTF_dtoa_h
diff --git a/JavaScriptCore/wtf/unicode/Unicode.h b/JavaScriptCore/wtf/unicode/Unicode.h
index 9cd3555..e6e8f23 100644
--- a/JavaScriptCore/wtf/unicode/Unicode.h
+++ b/JavaScriptCore/wtf/unicode/Unicode.h
@@ -1,6 +1,6 @@
/*
- * This file is part of the KDE libraries
* Copyright (C) 2006 George Staikos <staikos@kde.org>
+ * Copyright (C) 2006, 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
@@ -19,10 +19,10 @@
*
*/
-#ifndef KJS_UNICODE_H
-#define KJS_UNICODE_H
+#ifndef WTF_UNICODE_H
+#define WTF_UNICODE_H
-#include <wtf/Platform.h>
+#include <wtf/Assertions.h>
#if USE(QT4_UNICODE)
#include "qt4/UnicodeQt4.h"
@@ -32,5 +32,6 @@
#error "Unknown Unicode implementation"
#endif
-#endif
-// vim: ts=2 sw=2 et
+COMPILE_ASSERT(sizeof(UChar) == 2, UCharIsTwoBytes);
+
+#endif // WTF_UNICODE_H
diff --git a/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp b/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp
index a8bcc81..79dec79 100644
--- a/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp
+++ b/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp
@@ -45,7 +45,7 @@ namespace WTF {
static UCollator* cachedCollator;
static Mutex& cachedCollatorMutex()
{
- AtomicallyInitializedStatic(Mutex, mutex);
+ AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
return mutex;
}
diff --git a/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h b/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h
index 7cdc55c..608aea6 100644
--- a/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h
+++ b/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2006 George Staikos <staikos@kde.org>
* Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
- * Copyright (C) 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
@@ -20,8 +20,8 @@
*
*/
-#ifndef KJS_UNICODE_ICU_H
-#define KJS_UNICODE_ICU_H
+#ifndef WTF_UNICODE_ICU_H
+#define WTF_UNICODE_ICU_H
#include <stdlib.h>
#include <unicode/uchar.h>
@@ -216,4 +216,4 @@ inline int umemcasecmp(const UChar* a, const UChar* b, int len)
} }
-#endif
+#endif // WTF_UNICODE_ICU_H
diff --git a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h
index d285a8f..d7d78ce 100644
--- a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h
+++ b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2006 George Staikos <staikos@kde.org>
* Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
+ * 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
@@ -19,8 +20,8 @@
*
*/
-#ifndef KJS_UNICODE_QT4_H
-#define KJS_UNICODE_QT4_H
+#ifndef WTF_UNICODE_QT4_H
+#define WTF_UNICODE_QT4_H
#include <QChar>
#include <QString>
@@ -170,7 +171,7 @@ enum CharCategory {
Symbol_Math = U_MASK(QChar::Symbol_Math),
Symbol_Currency = U_MASK(QChar::Symbol_Currency),
Symbol_Modifier = U_MASK(QChar::Symbol_Modifier),
- Symbol_Other = U_MASK(QChar::Symbol_Other),
+ Symbol_Other = U_MASK(QChar::Symbol_Other)
};
@@ -522,4 +523,4 @@ inline CharCategory category(UChar32 c)
} }
-#endif
+#endif // WTF_UNICODE_QT4_H
diff --git a/JavaScriptCore/wtf/win/MainThreadWin.cpp b/JavaScriptCore/wtf/win/MainThreadWin.cpp
index 9f05d22..5f0163c 100644
--- a/JavaScriptCore/wtf/win/MainThreadWin.cpp
+++ b/JavaScriptCore/wtf/win/MainThreadWin.cpp
@@ -31,7 +31,9 @@
#include "Assertions.h"
#include "Threading.h"
+#if !PLATFORM(WIN_CE)
#include <windows.h>
+#endif
namespace WTF {