summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/wtf
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
commit1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353 (patch)
tree4457a7306ea5acb43fe05bfe0973b1f7faf97ba2 /JavaScriptCore/wtf
parent9364f22aed35e1a1e9d07c121510f80be3ab0502 (diff)
downloadexternal_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.zip
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.gz
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.bz2
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'JavaScriptCore/wtf')
-rw-r--r--JavaScriptCore/wtf/ASCIICType.h45
-rw-r--r--JavaScriptCore/wtf/AVLTree.h958
-rw-r--r--JavaScriptCore/wtf/AlwaysInline.h22
-rw-r--r--JavaScriptCore/wtf/Assertions.cpp3
-rw-r--r--JavaScriptCore/wtf/Assertions.h11
-rw-r--r--JavaScriptCore/wtf/Deque.h600
-rw-r--r--JavaScriptCore/wtf/FastMalloc.cpp256
-rw-r--r--JavaScriptCore/wtf/FastMalloc.h29
-rw-r--r--JavaScriptCore/wtf/GOwnPtr.cpp59
-rw-r--r--JavaScriptCore/wtf/GOwnPtr.h97
-rw-r--r--JavaScriptCore/wtf/HashCountedSet.h29
-rw-r--r--JavaScriptCore/wtf/HashFunctions.h70
-rw-r--r--JavaScriptCore/wtf/HashIterators.h1
-rw-r--r--JavaScriptCore/wtf/HashMap.h133
-rw-r--r--JavaScriptCore/wtf/HashSet.h181
-rw-r--r--JavaScriptCore/wtf/HashTable.cpp4
-rw-r--r--JavaScriptCore/wtf/HashTable.h260
-rw-r--r--JavaScriptCore/wtf/HashTraits.h180
-rw-r--r--JavaScriptCore/wtf/ListHashSet.h50
-rw-r--r--JavaScriptCore/wtf/ListRefPtr.h8
-rw-r--r--JavaScriptCore/wtf/Locker.h47
-rw-r--r--JavaScriptCore/wtf/MainThread.cpp141
-rw-r--r--JavaScriptCore/wtf/MainThread.h57
-rw-r--r--JavaScriptCore/wtf/MathExtras.h37
-rw-r--r--JavaScriptCore/wtf/MessageQueue.h136
-rw-r--r--JavaScriptCore/wtf/Noncopyable.h1
-rw-r--r--JavaScriptCore/wtf/NotFound.h35
-rw-r--r--JavaScriptCore/wtf/OwnArrayPtr.h1
-rw-r--r--JavaScriptCore/wtf/OwnPtr.h1
-rw-r--r--JavaScriptCore/wtf/PassRefPtr.h1
-rw-r--r--JavaScriptCore/wtf/Platform.h202
-rw-r--r--JavaScriptCore/wtf/RefCounted.h69
-rw-r--r--JavaScriptCore/wtf/RefCountedLeakCounter.cpp100
-rw-r--r--JavaScriptCore/wtf/RefCountedLeakCounter.h48
-rw-r--r--JavaScriptCore/wtf/RefPtr.h15
-rw-r--r--JavaScriptCore/wtf/RefPtrHashMap.h130
-rw-r--r--JavaScriptCore/wtf/RetainPtr.h1
-rw-r--r--JavaScriptCore/wtf/StringExtras.h47
-rw-r--r--JavaScriptCore/wtf/TCSpinLock.h6
-rw-r--r--JavaScriptCore/wtf/TCSystemAlloc.cpp10
-rw-r--r--JavaScriptCore/wtf/TCSystemAlloc.h6
-rw-r--r--JavaScriptCore/wtf/ThreadSpecific.h134
-rw-r--r--JavaScriptCore/wtf/Threading.h284
-rw-r--r--JavaScriptCore/wtf/ThreadingGtk.cpp229
-rw-r--r--JavaScriptCore/wtf/ThreadingNone.cpp56
-rw-r--r--JavaScriptCore/wtf/ThreadingPthreads.cpp268
-rw-r--r--JavaScriptCore/wtf/ThreadingQt.cpp243
-rw-r--r--JavaScriptCore/wtf/ThreadingWin.cpp479
-rw-r--r--JavaScriptCore/wtf/UnusedParam.h3
-rw-r--r--JavaScriptCore/wtf/Vector.h195
-rw-r--r--JavaScriptCore/wtf/VectorTraits.h5
-rw-r--r--JavaScriptCore/wtf/android/MainThreadAndroid.cpp35
-rw-r--r--JavaScriptCore/wtf/gtk/MainThreadGtk.cpp49
-rw-r--r--JavaScriptCore/wtf/mac/MainThreadMac.mm57
-rw-r--r--JavaScriptCore/wtf/qt/MainThreadQt.cpp69
-rw-r--r--JavaScriptCore/wtf/unicode/Collator.h67
-rw-r--r--JavaScriptCore/wtf/unicode/CollatorDefault.cpp75
-rw-r--r--JavaScriptCore/wtf/unicode/Unicode.h1
-rw-r--r--JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp144
-rw-r--r--JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h394
-rw-r--r--JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h740
-rw-r--r--JavaScriptCore/wtf/win/MainThreadWin.cpp76
-rw-r--r--JavaScriptCore/wtf/wx/MainThreadWx.cpp38
63 files changed, 6242 insertions, 1486 deletions
diff --git a/JavaScriptCore/wtf/ASCIICType.h b/JavaScriptCore/wtf/ASCIICType.h
index 990c1ea..b1ee3dc 100644
--- a/JavaScriptCore/wtf/ASCIICType.h
+++ b/JavaScriptCore/wtf/ASCIICType.h
@@ -29,6 +29,7 @@
#ifndef WTF_ASCIICType_h
#define WTF_ASCIICType_h
+#include <wtf/Assertions.h>
#include <wtf/Platform.h>
// The behavior of many of the functions in the <ctype.h> header is dependent
@@ -50,7 +51,6 @@ namespace WTF {
#endif
inline bool isASCIIAlpha(int c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
-// ANDROID: extra parentheses around expressions to suppress warnings
inline bool isASCIIAlphanumeric(char c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
inline bool isASCIIAlphanumeric(unsigned short c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
@@ -72,6 +72,13 @@ namespace WTF {
#endif
inline bool isASCIIHexDigit(int c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); }
+ inline bool isASCIIOctalDigit(char c) { return (c >= '0') & (c <= '7'); }
+ inline bool isASCIIOctalDigit(unsigned short c) { return (c >= '0') & (c <= '7'); }
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+ inline bool isASCIIOctalDigit(wchar_t c) { return (c >= '0') & (c <= '7'); }
+#endif
+ inline bool isASCIIOctalDigit(int c) { return (c >= '0') & (c <= '7'); }
+
inline bool isASCIILower(char c) { return c >= 'a' && c <= 'z'; }
inline bool isASCIILower(unsigned short c) { return c >= 'a' && c <= 'z'; }
#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
@@ -87,19 +94,18 @@ namespace WTF {
inline bool isASCIIUpper(int c) { return c >= 'A' && c <= 'Z'; }
/*
- Statistics from a run of the PLT on the usage of isASCIISpace:
- Hex Name Count
- --- ---- -----
- ALL OTHER VALUES 689383
- x20 SPACE 294720
- x0A NEWLINE 89059
- x09 TAB 28320
- x0D CARRIAGE RETURN 0
- x0C FORMFEED 0
- x0B VERTICAL TAB 0
-
+ Statistics from a run of Apple's page load test for callers of isASCIISpace:
+
+ character count
+ --------- -----
+ non-spaces 689383
+ 20 space 294720
+ 0A \n 89059
+ 09 \t 28320
+ 0D \r 0
+ 0C \f 0
+ 0B \v 0
*/
-
inline bool isASCIISpace(char c) { return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); }
inline bool isASCIISpace(unsigned short c) { return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); }
#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
@@ -121,6 +127,19 @@ namespace WTF {
#endif
inline int toASCIIUpper(int c) { return static_cast<int>(c & ~((c >= 'a' && c <= 'z') << 5)); }
+ inline int toASCIIHexValue(char c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
+ inline int toASCIIHexValue(unsigned short c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+ inline int toASCIIHexValue(wchar_t c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
+#endif
+ inline int toASCIIHexValue(int c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
+
+ inline bool isASCIIPrintable(char c) { return c >= ' ' && c <= '~'; }
+ inline bool isASCIIPrintable(unsigned short c) { return c >= ' ' && c <= '~'; }
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+ inline bool isASCIIPrintable(wchar_t c) { return c >= ' ' && c <= '~'; }
+#endif
+ inline bool isASCIIPrintable(int c) { return c >= ' ' && c <= '~'; }
}
#endif
diff --git a/JavaScriptCore/wtf/AVLTree.h b/JavaScriptCore/wtf/AVLTree.h
new file mode 100644
index 0000000..cd1511f
--- /dev/null
+++ b/JavaScriptCore/wtf/AVLTree.h
@@ -0,0 +1,958 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Based on Abstract AVL Tree Template v1.5 by Walt Karas
+ * <http://geocities.com/wkaras/gen_cpp/avl_tree.html>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef KJS_AVL_TREE_H_
+#define KJS_AVL_TREE_H_
+
+#include "Assertions.h"
+
+namespace JSC {
+
+// Here is the reference class for BSet.
+//
+// class BSet
+// {
+// public:
+//
+// class ANY_bitref
+// {
+// public:
+// operator bool ();
+// void operator = (bool b);
+// };
+//
+// // Does not have to initialize bits.
+// BSet();
+//
+// // Must return a valid value for index when 0 <= index < maxDepth
+// ANY_bitref operator [] (unsigned index);
+//
+// // Set all bits to 1.
+// void set();
+//
+// // Set all bits to 0.
+// void reset();
+// };
+
+template<unsigned maxDepth>
+class AVLTreeDefaultBSet {
+public:
+ bool& operator[](unsigned i) { ASSERT(i < maxDepth); return m_data[i]; }
+ void set() { for (unsigned i = 0; i < maxDepth; ++i) m_data[i] = true; }
+ void reset() { for (unsigned i = 0; i < maxDepth; ++i) m_data[i] = false; }
+
+private:
+ bool m_data[maxDepth];
+};
+
+// How to determine maxDepth:
+// d Minimum number of nodes
+// 2 2
+// 3 4
+// 4 7
+// 5 12
+// 6 20
+// 7 33
+// 8 54
+// 9 88
+// 10 143
+// 11 232
+// 12 376
+// 13 609
+// 14 986
+// 15 1,596
+// 16 2,583
+// 17 4,180
+// 18 6,764
+// 19 10,945
+// 20 17,710
+// 21 28,656
+// 22 46,367
+// 23 75,024
+// 24 121,392
+// 25 196,417
+// 26 317,810
+// 27 514,228
+// 28 832,039
+// 29 1,346,268
+// 30 2,178,308
+// 31 3,524,577
+// 32 5,702,886
+// 33 9,227,464
+// 34 14,930,351
+// 35 24,157,816
+// 36 39,088,168
+// 37 63,245,985
+// 38 102,334,154
+// 39 165,580,140
+// 40 267,914,295
+// 41 433,494,436
+// 42 701,408,732
+// 43 1,134,903,169
+// 44 1,836,311,902
+// 45 2,971,215,072
+//
+// E.g., if, in a particular instantiation, the maximum number of nodes in a tree instance is 1,000,000, the maximum depth should be 28.
+// You pick 28 because MN(28) is 832,039, which is less than or equal to 1,000,000, and MN(29) is 1,346,268, which is strictly greater than 1,000,000.
+
+template <class Abstractor, unsigned maxDepth = 32, class BSet = AVLTreeDefaultBSet<maxDepth> >
+class AVLTree {
+public:
+
+ typedef typename Abstractor::key key;
+ typedef typename Abstractor::handle handle;
+ typedef typename Abstractor::size size;
+
+ enum SearchType {
+ EQUAL = 1,
+ LESS = 2,
+ GREATER = 4,
+ LESS_EQUAL = EQUAL | LESS,
+ GREATER_EQUAL = EQUAL | GREATER
+ };
+
+
+ Abstractor& abstractor() { return abs; }
+
+ inline handle insert(handle h);
+
+ inline handle search(key k, SearchType st = EQUAL);
+ inline handle search_least();
+ inline handle search_greatest();
+
+ inline handle remove(key k);
+
+ inline handle subst(handle new_node);
+
+ void purge() { abs.root = null(); }
+
+ bool is_empty() { return abs.root == null(); }
+
+ AVLTree() { abs.root = null(); }
+
+ class Iterator {
+ public:
+
+ // Initialize depth to invalid value, to indicate iterator is
+ // invalid. (Depth is zero-base.)
+ Iterator() { depth = ~0U; }
+
+ void start_iter(AVLTree &tree, key k, SearchType st = EQUAL)
+ {
+ // Mask of high bit in an int.
+ const int MASK_HIGH_BIT = (int) ~ ((~ (unsigned) 0) >> 1);
+
+ // Save the tree that we're going to iterate through in a
+ // member variable.
+ tree_ = &tree;
+
+ int cmp, target_cmp;
+ handle h = tree_->abs.root;
+ unsigned d = 0;
+
+ depth = ~0U;
+
+ if (h == null())
+ // Tree is empty.
+ return;
+
+ if (st & LESS)
+ // Key can be greater than key of starting node.
+ target_cmp = 1;
+ else if (st & GREATER)
+ // Key can be less than key of starting node.
+ target_cmp = -1;
+ else
+ // Key must be same as key of starting node.
+ target_cmp = 0;
+
+ for (;;) {
+ cmp = cmp_k_n(k, h);
+ if (cmp == 0) {
+ if (st & EQUAL) {
+ // Equal node was sought and found as starting node.
+ depth = d;
+ break;
+ }
+ cmp = -target_cmp;
+ } 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;
+ }
+ }
+
+ void start_iter_least(AVLTree &tree)
+ {
+ tree_ = &tree;
+
+ handle h = tree_->abs.root;
+
+ depth = ~0U;
+
+ branch.reset();
+
+ while (h != null()) {
+ if (depth != ~0U)
+ path_h[depth] = h;
+ depth++;
+ h = get_lt(h);
+ }
+ }
+
+ void start_iter_greatest(AVLTree &tree)
+ {
+ tree_ = &tree;
+
+ handle h = tree_->abs.root;
+
+ depth = ~0U;
+
+ branch.set();
+
+ while (h != null()) {
+ if (depth != ~0U)
+ path_h[depth] = h;
+ depth++;
+ h = get_gt(h);
+ }
+ }
+
+ handle operator*()
+ {
+ if (depth == ~0U)
+ return null();
+
+ return depth == 0 ? tree_->abs.root : path_h[depth - 1];
+ }
+
+ void operator++()
+ {
+ if (depth != ~0U) {
+ handle h = get_gt(**this);
+ if (h == null()) {
+ do {
+ if (depth == 0) {
+ depth = ~0U;
+ break;
+ }
+ depth--;
+ } while (branch[depth]);
+ } else {
+ branch[depth] = true;
+ path_h[depth++] = h;
+ for (;;) {
+ h = get_lt(h);
+ if (h == null())
+ break;
+ branch[depth] = false;
+ path_h[depth++] = h;
+ }
+ }
+ }
+ }
+
+ void operator--()
+ {
+ if (depth != ~0U) {
+ handle h = get_lt(**this);
+ if (h == null())
+ do {
+ if (depth == 0) {
+ depth = ~0U;
+ break;
+ }
+ depth--;
+ } while (!branch[depth]);
+ else {
+ branch[depth] = false;
+ path_h[depth++] = h;
+ for (;;) {
+ h = get_gt(h);
+ if (h == null())
+ break;
+ branch[depth] = true;
+ path_h[depth++] = h;
+ }
+ }
+ }
+ }
+
+ void operator++(int) { ++(*this); }
+ void operator--(int) { --(*this); }
+
+ protected:
+
+ // Tree being iterated over.
+ AVLTree *tree_;
+
+ // Records a path into the tree. If branch[n] is true, indicates
+ // take greater branch from the nth node in the path, otherwise
+ // take the less branch. branch[0] gives branch from root, and
+ // so on.
+ BSet branch;
+
+ // Zero-based depth of path into tree.
+ unsigned depth;
+
+ // Handles of nodes in path from root to current node (returned by *).
+ handle path_h[maxDepth - 1];
+
+ int cmp_k_n(key k, handle h) { return tree_->abs.compare_key_node(k, h); }
+ int cmp_n_n(handle h1, handle h2) { return tree_->abs.compare_node_node(h1, h2); }
+ handle get_lt(handle h) { return tree_->abs.get_less(h); }
+ handle get_gt(handle h) { return tree_->abs.get_greater(h); }
+ handle null() { return tree_->abs.null(); }
+ };
+
+ template<typename fwd_iter>
+ bool build(fwd_iter p, size num_nodes)
+ {
+ if (num_nodes == 0) {
+ abs.root = null();
+ return true;
+ }
+
+ // Gives path to subtree being built. If branch[N] is false, branch
+ // less from the node at depth N, if true branch greater.
+ BSet branch;
+
+ // If rem[N] is true, then for the current subtree at depth N, it's
+ // greater subtree has one more node than it's less subtree.
+ BSet rem;
+
+ // Depth of root node of current subtree.
+ unsigned depth = 0;
+
+ // Number of nodes in current subtree.
+ size num_sub = num_nodes;
+
+ // The algorithm relies on a stack of nodes whose less subtree has
+ // been built, but whose right subtree has not yet been built. The
+ // stack is implemented as linked list. The nodes are linked
+ // together by having the "greater" handle of a node set to the
+ // next node in the list. "less_parent" is the handle of the first
+ // node in the list.
+ handle less_parent = null();
+
+ // h is root of current subtree, child is one of its children.
+ handle h, child;
+
+ for (;;) {
+ while (num_sub > 2) {
+ // Subtract one for root of subtree.
+ num_sub--;
+ rem[depth] = !!(num_sub & 1);
+ branch[depth++] = false;
+ num_sub >>= 1;
+ }
+
+ if (num_sub == 2) {
+ // Build a subtree with two nodes, slanting to greater.
+ // I arbitrarily chose to always have the extra node in the
+ // greater subtree when there is an odd number of nodes to
+ // split between the two subtrees.
+
+ h = *p;
+ p++;
+ child = *p;
+ p++;
+ set_lt(child, null());
+ set_gt(child, null());
+ set_bf(child, 0);
+ set_gt(h, child);
+ set_lt(h, null());
+ set_bf(h, 1);
+ } else { // num_sub == 1
+ // Build a subtree with one node.
+
+ h = *p;
+ p++;
+ set_lt(h, null());
+ set_gt(h, null());
+ set_bf(h, 0);
+ }
+
+ while (depth) {
+ depth--;
+ if (!branch[depth])
+ // We've completed a less subtree.
+ break;
+
+ // We've completed a greater subtree, so attach it to
+ // its parent (that is less than it). We pop the parent
+ // off the stack of less parents.
+ child = h;
+ h = less_parent;
+ less_parent = get_gt(h);
+ set_gt(h, child);
+ // num_sub = 2 * (num_sub - rem[depth]) + rem[depth] + 1
+ num_sub <<= 1;
+ num_sub += 1 - rem[depth];
+ if (num_sub & (num_sub - 1))
+ // num_sub is not a power of 2
+ set_bf(h, 0);
+ else
+ // num_sub is a power of 2
+ set_bf(h, 1);
+ }
+
+ if (num_sub == num_nodes)
+ // We've completed the full tree.
+ break;
+
+ // The subtree we've completed is the less subtree of the
+ // next node in the sequence.
+
+ child = h;
+ h = *p;
+ p++;
+ set_lt(h, child);
+
+ // Put h into stack of less parents.
+ set_gt(h, less_parent);
+ less_parent = h;
+
+ // Proceed to creating greater than subtree of h.
+ branch[depth] = true;
+ num_sub += rem[depth++];
+
+ } // end for (;;)
+
+ abs.root = h;
+
+ return true;
+ }
+
+protected:
+
+ friend class Iterator;
+
+ // Create a class whose sole purpose is to take advantage of
+ // the "empty member" optimization.
+ struct abs_plus_root : public Abstractor {
+ // The handle of the root element in the AVL tree.
+ handle root;
+ };
+
+ abs_plus_root abs;
+
+
+ handle get_lt(handle h) { return abs.get_less(h); }
+ void set_lt(handle h, handle lh) { abs.set_less(h, lh); }
+
+ handle get_gt(handle h) { return abs.get_greater(h); }
+ void set_gt(handle h, handle gh) { abs.set_greater(h, gh); }
+
+ int get_bf(handle h) { return abs.get_balance_factor(h); }
+ void set_bf(handle h, int bf) { abs.set_balance_factor(h, bf); }
+
+ int cmp_k_n(key k, handle h) { return abs.compare_key_node(k, h); }
+ int cmp_n_n(handle h1, handle h2) { return abs.compare_node_node(h1, h2); }
+
+ handle null() { return abs.null(); }
+
+private:
+
+ // Balances subtree, returns handle of root node of subtree
+ // after balancing.
+ handle balance(handle bal_h)
+ {
+ handle deep_h;
+
+ // Either the "greater than" or the "less than" subtree of
+ // this node has to be 2 levels deeper (or else it wouldn't
+ // need balancing).
+
+ if (get_bf(bal_h) > 0) {
+ // "Greater than" subtree is deeper.
+
+ deep_h = get_gt(bal_h);
+
+ if (get_bf(deep_h) < 0) {
+ handle old_h = bal_h;
+ bal_h = get_lt(deep_h);
+
+ set_gt(old_h, get_lt(bal_h));
+ set_lt(deep_h, get_gt(bal_h));
+ set_lt(bal_h, old_h);
+ set_gt(bal_h, deep_h);
+
+ int bf = get_bf(bal_h);
+ if (bf != 0) {
+ if (bf > 0) {
+ set_bf(old_h, -1);
+ set_bf(deep_h, 0);
+ } else {
+ set_bf(deep_h, 1);
+ set_bf(old_h, 0);
+ }
+ set_bf(bal_h, 0);
+ } else {
+ set_bf(old_h, 0);
+ set_bf(deep_h, 0);
+ }
+ } else {
+ set_gt(bal_h, get_lt(deep_h));
+ set_lt(deep_h, bal_h);
+ if (get_bf(deep_h) == 0) {
+ set_bf(deep_h, -1);
+ set_bf(bal_h, 1);
+ } else {
+ set_bf(deep_h, 0);
+ set_bf(bal_h, 0);
+ }
+ bal_h = deep_h;
+ }
+ } else {
+ // "Less than" subtree is deeper.
+
+ deep_h = get_lt(bal_h);
+
+ if (get_bf(deep_h) > 0) {
+ handle old_h = bal_h;
+ bal_h = get_gt(deep_h);
+ set_lt(old_h, get_gt(bal_h));
+ set_gt(deep_h, get_lt(bal_h));
+ set_gt(bal_h, old_h);
+ set_lt(bal_h, deep_h);
+
+ int bf = get_bf(bal_h);
+ if (bf != 0) {
+ if (bf < 0) {
+ set_bf(old_h, 1);
+ set_bf(deep_h, 0);
+ } else {
+ set_bf(deep_h, -1);
+ set_bf(old_h, 0);
+ }
+ set_bf(bal_h, 0);
+ } else {
+ set_bf(old_h, 0);
+ set_bf(deep_h, 0);
+ }
+ } else {
+ set_lt(bal_h, get_gt(deep_h));
+ set_gt(deep_h, bal_h);
+ if (get_bf(deep_h) == 0) {
+ set_bf(deep_h, 1);
+ set_bf(bal_h, -1);
+ } else {
+ set_bf(deep_h, 0);
+ set_bf(bal_h, 0);
+ }
+ bal_h = deep_h;
+ }
+ }
+
+ return bal_h;
+ }
+
+};
+
+template <class Abstractor, unsigned maxDepth, class BSet>
+inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
+AVLTree<Abstractor, maxDepth, BSet>::insert(handle h)
+{
+ set_lt(h, null());
+ set_gt(h, null());
+ set_bf(h, 0);
+
+ if (abs.root == null())
+ abs.root = h;
+ else {
+ // Last unbalanced node encountered in search for insertion point.
+ handle unbal = null();
+ // Parent of last unbalanced node.
+ handle parent_unbal = null();
+ // Balance factor of last unbalanced node.
+ int unbal_bf;
+
+ // Zero-based depth in tree.
+ unsigned depth = 0, unbal_depth = 0;
+
+ // Records a path into the tree. If branch[n] is true, indicates
+ // take greater branch from the nth node in the path, otherwise
+ // take the less branch. branch[0] gives branch from root, and
+ // so on.
+ BSet branch;
+
+ handle hh = abs.root;
+ handle parent = null();
+ int cmp;
+
+ do {
+ if (get_bf(hh) != 0) {
+ unbal = hh;
+ parent_unbal = parent;
+ unbal_depth = depth;
+ }
+ cmp = cmp_n_n(h, hh);
+ if (cmp == 0)
+ // Duplicate key.
+ return hh;
+ parent = hh;
+ hh = cmp < 0 ? get_lt(hh) : get_gt(hh);
+ branch[depth++] = cmp > 0;
+ } while (hh != null());
+
+ // Add node to insert as leaf of tree.
+ if (cmp < 0)
+ set_lt(parent, h);
+ else
+ set_gt(parent, h);
+
+ depth = unbal_depth;
+
+ if (unbal == null())
+ hh = abs.root;
+ else {
+ cmp = branch[depth++] ? 1 : -1;
+ unbal_bf = get_bf(unbal);
+ if (cmp < 0)
+ unbal_bf--;
+ else // cmp > 0
+ unbal_bf++;
+ hh = cmp < 0 ? get_lt(unbal) : get_gt(unbal);
+ if ((unbal_bf != -2) && (unbal_bf != 2)) {
+ // No rebalancing of tree is necessary.
+ set_bf(unbal, unbal_bf);
+ unbal = null();
+ }
+ }
+
+ if (hh != null())
+ while (h != hh) {
+ cmp = branch[depth++] ? 1 : -1;
+ if (cmp < 0) {
+ set_bf(hh, -1);
+ hh = get_lt(hh);
+ } else { // cmp > 0
+ set_bf(hh, 1);
+ hh = get_gt(hh);
+ }
+ }
+
+ if (unbal != null()) {
+ unbal = balance(unbal);
+ if (parent_unbal == null())
+ abs.root = unbal;
+ else {
+ depth = unbal_depth - 1;
+ cmp = branch[depth] ? 1 : -1;
+ if (cmp < 0)
+ set_lt(parent_unbal, unbal);
+ else // cmp > 0
+ set_gt(parent_unbal, unbal);
+ }
+ }
+ }
+
+ return h;
+}
+
+template <class Abstractor, unsigned maxDepth, class BSet>
+inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
+AVLTree<Abstractor, maxDepth, BSet>::search(key k, typename AVLTree<Abstractor, maxDepth, BSet>::SearchType st)
+{
+ const int MASK_HIGH_BIT = (int) ~ ((~ (unsigned) 0) >> 1);
+
+ int cmp, target_cmp;
+ handle match_h = null();
+ handle h = abs.root;
+
+ if (st & LESS)
+ target_cmp = 1;
+ else if (st & GREATER)
+ target_cmp = -1;
+ else
+ target_cmp = 0;
+
+ while (h != null()) {
+ cmp = cmp_k_n(k, h);
+ if (cmp == 0) {
+ if (st & EQUAL) {
+ match_h = h;
+ break;
+ }
+ cmp = -target_cmp;
+ } else if (target_cmp != 0)
+ if (!((cmp ^ target_cmp) & MASK_HIGH_BIT))
+ // cmp and target_cmp are both positive or both negative.
+ match_h = h;
+ h = cmp < 0 ? get_lt(h) : get_gt(h);
+ }
+
+ return match_h;
+}
+
+template <class Abstractor, unsigned maxDepth, class BSet>
+inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
+AVLTree<Abstractor, maxDepth, BSet>::search_least()
+{
+ handle h = abs.root, parent = null();
+
+ while (h != null()) {
+ parent = h;
+ h = get_lt(h);
+ }
+
+ return parent;
+}
+
+template <class Abstractor, unsigned maxDepth, class BSet>
+inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
+AVLTree<Abstractor, maxDepth, BSet>::search_greatest()
+{
+ handle h = abs.root, parent = null();
+
+ while (h != null()) {
+ parent = h;
+ h = get_gt(h);
+ }
+
+ return parent;
+}
+
+template <class Abstractor, unsigned maxDepth, class BSet>
+inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
+AVLTree<Abstractor, maxDepth, BSet>::remove(key k)
+{
+ // Zero-based depth in tree.
+ unsigned depth = 0, rm_depth;
+
+ // Records a path into the tree. If branch[n] is true, indicates
+ // take greater branch from the nth node in the path, otherwise
+ // take the less branch. branch[0] gives branch from root, and
+ // so on.
+ BSet branch;
+
+ handle h = abs.root;
+ handle parent = null(), child;
+ int cmp, cmp_shortened_sub_with_path;
+
+ for (;;) {
+ if (h == null())
+ // No node in tree with given key.
+ return null();
+ cmp = cmp_k_n(k, h);
+ if (cmp == 0)
+ // Found node to remove.
+ break;
+ parent = h;
+ h = cmp < 0 ? get_lt(h) : get_gt(h);
+ branch[depth++] = cmp > 0;
+ cmp_shortened_sub_with_path = cmp;
+ }
+ handle rm = h;
+ handle parent_rm = parent;
+ rm_depth = depth;
+
+ // If the node to remove is not a leaf node, we need to get a
+ // leaf node, or a node with a single leaf as its child, to put
+ // in the place of the node to remove. We will get the greatest
+ // node in the less subtree (of the node to remove), or the least
+ // node in the greater subtree. We take the leaf node from the
+ // deeper subtree, if there is one.
+
+ if (get_bf(h) < 0) {
+ child = get_lt(h);
+ branch[depth] = false;
+ cmp = -1;
+ } else {
+ child = get_gt(h);
+ branch[depth] = true;
+ cmp = 1;
+ }
+ depth++;
+
+ if (child != null()) {
+ cmp = -cmp;
+ do {
+ parent = h;
+ h = child;
+ if (cmp < 0) {
+ child = get_lt(h);
+ branch[depth] = false;
+ } else {
+ child = get_gt(h);
+ branch[depth] = true;
+ }
+ depth++;
+ } while (child != null());
+
+ if (parent == rm)
+ // Only went through do loop once. Deleted node will be replaced
+ // in the tree structure by one of its immediate children.
+ cmp_shortened_sub_with_path = -cmp;
+ else
+ 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);
+ }
+
+ if (parent == null())
+ // There were only 1 or 2 nodes in this tree.
+ abs.root = child;
+ else if (cmp_shortened_sub_with_path < 0)
+ set_lt(parent, child);
+ else
+ set_gt(parent, child);
+
+ // "path" is the parent of the subtree being eliminated or reduced
+ // from a depth of 2 to 1. If "path" is the node to be removed, we
+ // set path to the node we're about to poke into the position of the
+ // node to be removed.
+ handle path = parent == rm ? h : parent;
+
+ 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_bf(h, get_bf(rm));
+ if (parent_rm == null())
+ abs.root = h;
+ else {
+ depth = rm_depth - 1;
+ if (branch[depth])
+ set_gt(parent_rm, h);
+ else
+ set_lt(parent_rm, h);
+ }
+ }
+
+ if (path != null()) {
+ // Create a temporary linked list from the parent of the path node
+ // to the root node.
+ h = abs.root;
+ parent = null();
+ depth = 0;
+ while (h != path) {
+ if (branch[depth++]) {
+ child = get_gt(h);
+ set_gt(h, parent);
+ } else {
+ child = get_lt(h);
+ set_lt(h, parent);
+ }
+ parent = h;
+ h = child;
+ }
+
+ // Climb from the path node to the root node using the linked
+ // list, restoring the tree structure and rebalancing as necessary.
+ bool reduced_depth = true;
+ int bf;
+ cmp = cmp_shortened_sub_with_path;
+ for (;;) {
+ if (reduced_depth) {
+ bf = get_bf(h);
+ if (cmp < 0)
+ bf++;
+ else // cmp > 0
+ bf--;
+ if ((bf == -2) || (bf == 2)) {
+ h = balance(h);
+ bf = get_bf(h);
+ } else
+ set_bf(h, bf);
+ reduced_depth = (bf == 0);
+ }
+ if (parent == null())
+ break;
+ child = h;
+ h = parent;
+ cmp = branch[--depth] ? 1 : -1;
+ if (cmp < 0) {
+ parent = get_lt(h);
+ set_lt(h, child);
+ } else {
+ parent = get_gt(h);
+ set_gt(h, child);
+ }
+ }
+ abs.root = h;
+ }
+
+ return rm;
+}
+
+template <class Abstractor, unsigned maxDepth, class BSet>
+inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
+AVLTree<Abstractor, maxDepth, BSet>::subst(handle new_node)
+{
+ handle h = abs.root;
+ handle parent = null();
+ int cmp, last_cmp;
+
+ /* Search for node already in tree with same key. */
+ for (;;) {
+ if (h == null())
+ /* No node in tree with same key as new node. */
+ return null();
+ cmp = cmp_n_n(new_node, h);
+ if (cmp == 0)
+ /* Found the node to substitute new one for. */
+ break;
+ last_cmp = cmp;
+ parent = h;
+ h = cmp < 0 ? get_lt(h) : get_gt(h);
+ }
+
+ /* 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_bf(new_node, get_bf(h));
+
+ if (parent == null())
+ /* New node is also new root. */
+ abs.root = new_node;
+ else {
+ /* Make parent point to new node. */
+ if (last_cmp < 0)
+ set_lt(parent, new_node);
+ else
+ set_gt(parent, new_node);
+ }
+
+ return h;
+}
+
+
+}
+
+#endif
diff --git a/JavaScriptCore/wtf/AlwaysInline.h b/JavaScriptCore/wtf/AlwaysInline.h
index 3f54815..d39b2b9 100644
--- a/JavaScriptCore/wtf/AlwaysInline.h
+++ b/JavaScriptCore/wtf/AlwaysInline.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 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
@@ -18,8 +18,10 @@
*
*/
+#include "Platform.h"
+
#ifndef ALWAYS_INLINE
-#if COMPILER(GCC) && defined(NDEBUG)
+#if COMPILER(GCC) && defined(NDEBUG) && !COMPILER(MINGW)
#define ALWAYS_INLINE inline __attribute__ ((__always_inline__))
#elif COMPILER(MSVC) && defined(NDEBUG)
#define ALWAYS_INLINE __forceinline
@@ -35,3 +37,19 @@
#define NEVER_INLINE
#endif
#endif
+
+#ifndef UNLIKELY
+#if COMPILER(GCC)
+#define UNLIKELY(x) __builtin_expect((x), 0)
+#else
+#define UNLIKELY(x) (x)
+#endif
+#endif
+
+#ifndef LIKELY
+#if COMPILER(GCC)
+#define LIKELY(x) __builtin_expect((x), 1)
+#else
+#define LIKELY(x) (x)
+#endif
+#endif
diff --git a/JavaScriptCore/wtf/Assertions.cpp b/JavaScriptCore/wtf/Assertions.cpp
index 43f3ef7..98de91c 100644
--- a/JavaScriptCore/wtf/Assertions.cpp
+++ b/JavaScriptCore/wtf/Assertions.cpp
@@ -1,4 +1,3 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved.
*
@@ -21,7 +20,7 @@
* 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.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
diff --git a/JavaScriptCore/wtf/Assertions.h b/JavaScriptCore/wtf/Assertions.h
index 74ea91c..8449563 100644
--- a/JavaScriptCore/wtf/Assertions.h
+++ b/JavaScriptCore/wtf/Assertions.h
@@ -1,4 +1,3 @@
-/* -*- mode: c++; c-basic-offset: 4 -*- */
/*
* Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved.
*
@@ -83,9 +82,9 @@
#define WTF_PRETTY_FUNCTION __FUNCTION__
#endif
-// WTF logging functions can process %@ in the format string to log a NSObject* but the printf format attribute
-// emits a warning when %@ is used in the format string. Until <rdar://problem/5195437> is resolved we can't include
-// the attribute when being used from Objective-C code in case it decides to use %@.
+/* WTF logging functions can process %@ in the format string to log a NSObject* but the printf format attribute
+ emits a warning when %@ is used in the format string. Until <rdar://problem/5195437> is resolved we can't include
+ the attribute when being used from Objective-C code in case it decides to use %@. */
#if COMPILER(GCC) && !defined(__OBJC__)
#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(printf, formatStringArgument, extraArguments)))
#else
@@ -154,7 +153,7 @@ while (0)
CRASH(); \
} \
while (0)
-#endif // COMPILER(MSVC7)
+#endif /* COMPILER(MSVC7) */
#define ASSERT_NOT_REACHED() do { \
WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \
CRASH(); \
@@ -229,4 +228,4 @@ while (0)
#define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__)
#endif
-#endif // WTF_Assertions_h
+#endif /* WTF_Assertions_h */
diff --git a/JavaScriptCore/wtf/Deque.h b/JavaScriptCore/wtf/Deque.h
index c09ef42..70c546b 100644
--- a/JavaScriptCore/wtf/Deque.h
+++ b/JavaScriptCore/wtf/Deque.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 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
@@ -25,99 +25,565 @@
* (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_Deque_h
#define WTF_Deque_h
-#include <wtf/Assertions.h>
-#include <wtf/Noncopyable.h>
+// FIXME: Could move what Vector and Deque share into a separate file.
+// Deque doesn't actually use Vector.
+
+#include "Vector.h"
namespace WTF {
+ template<typename T> class DequeIteratorBase;
+ template<typename T> class DequeIterator;
+ template<typename T> class DequeConstIterator;
+ template<typename T> class DequeReverseIterator;
+ template<typename T> class DequeConstReverseIterator;
+
template<typename T>
- class DequeNode {
+ class Deque {
public:
- DequeNode(const T& item) : m_value(item), m_next(0) { }
+ typedef DequeIterator<T> iterator;
+ typedef DequeConstIterator<T> const_iterator;
+ typedef DequeReverseIterator<T> reverse_iterator;
+ typedef DequeConstReverseIterator<T> const_reverse_iterator;
+
+ Deque();
+ Deque(const Deque<T>&);
+ Deque& operator=(const Deque<T>&);
+ ~Deque();
+
+ void swap(Deque<T>&);
+
+ size_t size() const { return m_start <= m_end ? m_end - m_start : m_end + m_buffer.capacity() - m_start; }
+ bool isEmpty() const { return m_start == m_end; }
+
+ iterator begin() { return iterator(this, m_start); }
+ iterator end() { return iterator(this, m_end); }
+ const_iterator begin() const { return const_iterator(this, m_start); }
+ const_iterator end() const { return const_iterator(this, m_end); }
+ reverse_iterator rbegin() { return reverse_iterator(this, m_end); }
+ reverse_iterator rend() { return reverse_iterator(this, m_start); }
+ const_reverse_iterator rbegin() const { return const_reverse_iterator(this, m_end); }
+ const_reverse_iterator rend() const { return const_reverse_iterator(this, m_start); }
+
+ T& first() { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; }
+ const T& first() const { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; }
+
+ template<typename U> void append(const U&);
+ template<typename U> void prepend(const U&);
+ void removeFirst();
+
+ void clear();
+
+ private:
+ friend class DequeIteratorBase<T>;
+
+ typedef VectorBuffer<T, 0> Buffer;
+ typedef VectorTypeOperations<T> TypeOperations;
+ typedef DequeIteratorBase<T> IteratorBase;
+
+ void invalidateIterators();
+ void destroyAll();
+ void checkValidity() const;
+ void checkIndexValidity(size_t) const;
+ void expandCapacityIfNeeded();
+ void expandCapacity();
+
+ size_t m_start;
+ size_t m_end;
+ Buffer m_buffer;
+#ifndef NDEBUG
+ mutable IteratorBase* m_iterators;
+#endif
+ };
+
+ template<typename T>
+ class DequeIteratorBase {
+ private:
+ typedef DequeIteratorBase<T> Base;
+
+ protected:
+ DequeIteratorBase();
+ DequeIteratorBase(const Deque<T>*, size_t);
+ DequeIteratorBase(const Base&);
+ Base& operator=(const Base&);
+ ~DequeIteratorBase();
+
+ void assign(const Base& other) { *this = other; }
+
+ void increment();
+ void decrement();
+
+ T* before() const;
+ T* after() const;
- T m_value;
- DequeNode* m_next;
+ bool isEqual(const Base&) const;
+
+ private:
+ void addToIteratorsList();
+ void checkValidity() const;
+ void checkValidity(const Base&) const;
+
+ Deque<T>* m_deque;
+ size_t m_index;
+
+ friend class Deque<T>;
+
+#ifndef NDEBUG
+ mutable DequeIteratorBase* m_next;
+ mutable DequeIteratorBase* m_previous;
+#endif
};
template<typename T>
- class Deque : Noncopyable {
+ class DequeIterator : public DequeIteratorBase<T> {
+ private:
+ typedef DequeIteratorBase<T> Base;
+ typedef DequeIterator<T> Iterator;
+
public:
- Deque()
- : m_size(0)
- , m_first(0)
- , m_last(0)
- {
+ DequeIterator(Deque<T>* deque, size_t index) : Base(deque, index) { }
+
+ DequeIterator(const Iterator& other) : Base(other) { }
+ DequeIterator& operator=(const Iterator& other) { Base::assign(other); return *this; }
+
+ T& operator*() const { return *Base::after(); }
+ T* operator->() const { return Base::after(); }
+
+ bool operator==(const Iterator& other) const { return Base::isEqual(other); }
+ bool operator!=(const Iterator& other) const { return !Base::isEqual(other); }
+
+ Iterator& operator++() { Base::increment(); return *this; }
+ // postfix ++ intentionally omitted
+ Iterator& operator--() { Base::decrement(); return *this; }
+ // postfix -- intentionally omitted
+ };
+
+ template<typename T>
+ class DequeConstIterator : public DequeIteratorBase<T> {
+ private:
+ typedef DequeIteratorBase<T> Base;
+ typedef DequeConstIterator<T> Iterator;
+ typedef DequeIterator<T> NonConstIterator;
+
+ public:
+ DequeConstIterator(const Deque<T>* deque, size_t index) : Base(deque, index) { }
+
+ DequeConstIterator(const Iterator& other) : Base(other) { }
+ DequeConstIterator(const NonConstIterator& other) : Base(other) { }
+ DequeConstIterator& operator=(const Iterator& other) { Base::assign(other); return *this; }
+ DequeConstIterator& operator=(const NonConstIterator& other) { Base::assign(other); return *this; }
+
+ const T& operator*() const { return *Base::after(); }
+ const T* operator->() const { return Base::after(); }
+
+ bool operator==(const Iterator& other) const { return Base::isEqual(other); }
+ bool operator!=(const Iterator& other) const { return !Base::isEqual(other); }
+
+ Iterator& operator++() { Base::increment(); return *this; }
+ // postfix ++ intentionally omitted
+ Iterator& operator--() { Base::decrement(); return *this; }
+ // postfix -- intentionally omitted
+ };
+
+ template<typename T>
+ class DequeReverseIterator : public DequeIteratorBase<T> {
+ private:
+ typedef DequeIteratorBase<T> Base;
+ typedef DequeReverseIterator<T> Iterator;
+
+ public:
+ DequeReverseIterator(const Deque<T>* deque, size_t index) : Base(deque, index) { }
+
+ DequeReverseIterator(const Iterator& other) : Base(other) { }
+ DequeReverseIterator& operator=(const Iterator& other) { Base::assign(other); return *this; }
+
+ T& operator*() const { return *Base::before(); }
+ T* operator->() const { return Base::before(); }
+
+ bool operator==(const Iterator& other) const { return Base::isEqual(other); }
+ bool operator!=(const Iterator& other) const { return !Base::isEqual(other); }
+
+ Iterator& operator++() { Base::decrement(); return *this; }
+ // postfix ++ intentionally omitted
+ Iterator& operator--() { Base::increment(); return *this; }
+ // postfix -- intentionally omitted
+ };
+
+ template<typename T>
+ class DequeConstReverseIterator : public DequeIteratorBase<T> {
+ private:
+ typedef DequeIteratorBase<T> Base;
+ typedef DequeConstReverseIterator<T> Iterator;
+ typedef DequeReverseIterator<T> NonConstIterator;
+
+ public:
+ DequeConstReverseIterator(const Deque<T>* deque, size_t index) : Base(deque, index) { }
+
+ DequeConstReverseIterator(const Iterator& other) : Base(other) { }
+ DequeConstReverseIterator(const NonConstIterator& other) : Base(other) { }
+ DequeConstReverseIterator& operator=(const Iterator& other) { Base::assign(other); return *this; }
+ DequeConstReverseIterator& operator=(const NonConstIterator& other) { Base::assign(other); return *this; }
+
+ const T& operator*() const { return *Base::before(); }
+ const T* operator->() const { return Base::before(); }
+
+ bool operator==(const Iterator& other) const { return Base::isEqual(other); }
+ bool operator!=(const Iterator& other) const { return !Base::isEqual(other); }
+
+ Iterator& operator++() { Base::decrement(); return *this; }
+ // postfix ++ intentionally omitted
+ Iterator& operator--() { Base::increment(); return *this; }
+ // postfix -- intentionally omitted
+ };
+
+#ifdef NDEBUG
+ template<typename T> inline void Deque<T>::checkValidity() const { }
+ template<typename T> inline void Deque<T>::checkIndexValidity(size_t) const { }
+ template<typename T> inline void Deque<T>::invalidateIterators() { }
+#else
+ template<typename T>
+ void Deque<T>::checkValidity() const
+ {
+ if (!m_buffer.capacity()) {
+ ASSERT(!m_start);
+ ASSERT(!m_end);
+ } else {
+ ASSERT(m_start < m_buffer.capacity());
+ ASSERT(m_end < m_buffer.capacity());
}
+ }
- ~Deque()
- {
- clear();
+ template<typename T>
+ void Deque<T>::checkIndexValidity(size_t index) const
+ {
+ ASSERT(index <= m_buffer.capacity());
+ if (m_start <= m_end) {
+ ASSERT(index >= m_start);
+ ASSERT(index <= m_end);
+ } else {
+ ASSERT(index >= m_start || index <= m_end);
}
+ }
- size_t size() const { return m_size; }
- bool isEmpty() const { return !size(); }
-
- void append(const T& item)
- {
- DequeNode<T>* newNode = new DequeNode<T>(item);
- if (m_last)
- m_last->m_next = newNode;
- m_last = newNode;
- if (!m_first)
- m_first = newNode;
- ++m_size;
+ template<typename T>
+ void Deque<T>::invalidateIterators()
+ {
+ IteratorBase* next;
+ for (IteratorBase* p = m_iterators; p; p = next) {
+ next = p->m_next;
+ p->m_deque = 0;
+ p->m_next = 0;
+ p->m_previous = 0;
}
+ m_iterators = 0;
+ }
+#endif
+
+ template<typename T>
+ inline Deque<T>::Deque()
+ : m_start(0)
+ , m_end(0)
+#ifndef NDEBUG
+ , m_iterators(0)
+#endif
+ {
+ checkValidity();
+ }
- void prepend(const T& item)
- {
- DequeNode<T>* newNode = new DequeNode<T>(item);
- newNode->m_next = m_first;
- m_first = newNode;
- if (!m_last)
- m_last = newNode;
- ++m_size;
+ template<typename T>
+ inline Deque<T>::Deque(const Deque<T>& other)
+ : m_start(other.m_start)
+ , m_end(other.m_end)
+ , m_buffer(other.m_buffer.capacity())
+#ifndef NDEBUG
+ , m_iterators(0)
+#endif
+ {
+ const T* otherBuffer = other.m_buffer.buffer();
+ if (m_start <= m_end)
+ TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_end, m_buffer.buffer() + m_start);
+ else {
+ TypeOperations::uninitializedCopy(otherBuffer, otherBuffer + m_end, m_buffer.buffer());
+ TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_buffer.capacity(), m_buffer.buffer() + m_start);
}
+ }
- T& first() { ASSERT(m_first); return m_first->m_value; }
- const T& first() const { ASSERT(m_first); return m_first->m_value; }
- T& last() { ASSERT(m_last); return m_last->m_value; }
- const T& last() const { ASSERT(m_last); return m_last->m_value; }
-
- void removeFirst()
- {
- ASSERT(m_first);
- if (DequeNode<T>* n = m_first) {
- m_first = m_first->m_next;
- if (n == m_last)
- m_last = 0;
-
- m_size--;
- delete n;
- }
+ template<typename T>
+ void deleteAllValues(const Deque<T>& collection)
+ {
+ typedef typename Deque<T>::const_iterator iterator;
+ iterator end = collection.end();
+ for (iterator it = collection.begin(); it != end; ++it)
+ delete *it;
+ }
+
+ template<typename T>
+ inline Deque<T>& Deque<T>::operator=(const Deque<T>& other)
+ {
+ Deque<T> copy(other);
+ swap(copy);
+ return *this;
+ }
+
+ template<typename T>
+ inline void Deque<T>::destroyAll()
+ {
+ if (m_start <= m_end)
+ TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_end);
+ else {
+ TypeOperations::destruct(m_buffer.buffer(), m_buffer.buffer() + m_end);
+ TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_buffer.capacity());
+ }
+ }
+
+ template<typename T>
+ inline Deque<T>::~Deque()
+ {
+ checkValidity();
+ invalidateIterators();
+ destroyAll();
+ }
+
+ template <typename T>
+ inline void Deque<T>::swap(Deque<T>& other)
+ {
+ checkValidity();
+ other.checkValidity();
+ invalidateIterators();
+ std::swap(m_start, other.m_start);
+ std::swap(m_end, other.m_end);
+ m_buffer.swap(other.m_buffer);
+ checkValidity();
+ other.checkValidity();
+ }
+
+ template <typename T>
+ inline void Deque<T>::clear()
+ {
+ checkValidity();
+ invalidateIterators();
+ destroyAll();
+ m_start = 0;
+ m_end = 0;
+ checkValidity();
+ }
+
+ template<typename T>
+ inline void Deque<T>::expandCapacityIfNeeded()
+ {
+ if (m_start) {
+ if (m_end + 1 != m_start)
+ return;
+ } else if (m_end) {
+ if (m_end != m_buffer.capacity() - 1)
+ return;
+ } else if (m_buffer.capacity())
+ return;
+
+ expandCapacity();
+ }
+
+ template<typename T>
+ void Deque<T>::expandCapacity()
+ {
+ checkValidity();
+ size_t oldCapacity = m_buffer.capacity();
+ size_t newCapacity = max(static_cast<size_t>(16), oldCapacity + oldCapacity / 4 + 1);
+ T* oldBuffer = m_buffer.buffer();
+ m_buffer.allocateBuffer(newCapacity);
+ if (m_start <= m_end)
+ TypeOperations::move(oldBuffer + m_start, oldBuffer + m_end, m_buffer.buffer() + m_start);
+ else {
+ TypeOperations::move(oldBuffer, oldBuffer + m_end, m_buffer.buffer());
+ size_t newStart = newCapacity - (oldCapacity - m_start);
+ TypeOperations::move(oldBuffer + m_start, oldBuffer + oldCapacity, m_buffer.buffer() + newStart);
+ m_start = newStart;
}
+ m_buffer.deallocateBuffer(oldBuffer);
+ checkValidity();
+ }
- void clear()
- {
- DequeNode<T>* n = m_first;
- m_first = 0;
- m_last = 0;
- m_size = 0;
- while (n) {
- DequeNode<T>* next = n->m_next;
- delete n;
- n = next;
+ template<typename T> template<typename U>
+ inline void Deque<T>::append(const U& value)
+ {
+ checkValidity();
+ expandCapacityIfNeeded();
+ new (&m_buffer.buffer()[m_end]) T(value);
+ if (m_end == m_buffer.capacity() - 1)
+ m_end = 0;
+ else
+ ++m_end;
+ checkValidity();
+ }
+
+ template<typename T> template<typename U>
+ inline void Deque<T>::prepend(const U& value)
+ {
+ checkValidity();
+ expandCapacityIfNeeded();
+ if (!m_start)
+ m_start = m_buffer.capacity() - 1;
+ else
+ --m_start;
+ new (&m_buffer.buffer()[m_start]) T(value);
+ checkValidity();
+ }
+
+ template<typename T>
+ inline void Deque<T>::removeFirst()
+ {
+ checkValidity();
+ invalidateIterators();
+ ASSERT(!isEmpty());
+ TypeOperations::destruct(&m_buffer.buffer()[m_start], &m_buffer.buffer()[m_start + 1]);
+ if (m_start == m_buffer.capacity() - 1)
+ m_start = 0;
+ else
+ ++m_start;
+ checkValidity();
+ }
+
+#ifdef NDEBUG
+ template<typename T> inline void DequeIteratorBase<T>::checkValidity() const { }
+ template<typename T> inline void DequeIteratorBase<T>::checkValidity(const DequeIteratorBase<T>&) const { }
+ template<typename T> inline void DequeIteratorBase<T>::addToIteratorsList() { }
+#else
+ template<typename T>
+ void DequeIteratorBase<T>::checkValidity() const
+ {
+ ASSERT(m_deque);
+ m_deque->checkIndexValidity(m_index);
+ }
+
+ template<typename T>
+ void DequeIteratorBase<T>::checkValidity(const Base& other) const
+ {
+ checkValidity();
+ other.checkValidity();
+ ASSERT(m_deque == other.m_deque);
+ }
+
+ template<typename T>
+ void DequeIteratorBase<T>::addToIteratorsList()
+ {
+ if (!m_deque)
+ m_next = 0;
+ else {
+ m_next = m_deque->m_iterators;
+ m_deque->m_iterators = this;
+ if (m_next)
+ m_next->m_previous = this;
+ }
+ m_previous = 0;
+ }
+#endif
+
+ template<typename T>
+ inline DequeIteratorBase<T>::DequeIteratorBase()
+ : m_deque(0)
+ {
+ }
+
+ template<typename T>
+ inline DequeIteratorBase<T>::DequeIteratorBase(const Deque<T>* deque, size_t index)
+ : m_deque(const_cast<Deque<T>*>(deque))
+ , m_index(index)
+ {
+ addToIteratorsList();
+ checkValidity();
+ }
+
+ template<typename T>
+ inline DequeIteratorBase<T>::DequeIteratorBase(const Base& other)
+ : m_deque(other.m_deque)
+ , m_index(other.m_index)
+ {
+ addToIteratorsList();
+ checkValidity();
+ }
+
+ template<typename T>
+ inline DequeIteratorBase<T>::~DequeIteratorBase()
+ {
+#ifndef NDEBUG
+ // Delete iterator from doubly-linked list of iterators.
+ if (!m_deque) {
+ ASSERT(!m_next);
+ ASSERT(!m_previous);
+ } else {
+ if (m_next) {
+ ASSERT(m_next->m_previous == this);
+ m_next->m_previous = m_previous;
+ }
+ if (m_previous) {
+ ASSERT(m_deque->m_iterators != this);
+ ASSERT(m_previous->m_next == this);
+ m_previous->m_next = m_next;
+ } else {
+ ASSERT(m_deque->m_iterators == this);
+ m_deque->m_iterators = m_next;
}
}
+ m_deque = 0;
+ m_next = 0;
+ m_previous = 0;
+#endif
+ }
- private:
- size_t m_size;
- DequeNode<T>* m_first;
- DequeNode<T>* m_last;
+ template<typename T>
+ inline bool DequeIteratorBase<T>::isEqual(const Base& other) const
+ {
+ checkValidity(other);
+ return m_index == other.m_index;
+ }
- };
+ template<typename T>
+ inline void DequeIteratorBase<T>::increment()
+ {
+ checkValidity();
+ ASSERT(m_index != m_deque->m_end);
+ ASSERT(m_deque->m_buffer.capacity());
+ if (m_index == m_deque->m_buffer.capacity() - 1)
+ m_index = 0;
+ else
+ ++m_index;
+ checkValidity();
+ }
+
+ template<typename T>
+ inline void DequeIteratorBase<T>::decrement()
+ {
+ checkValidity();
+ ASSERT(m_index != m_deque->m_start);
+ ASSERT(m_deque->m_buffer.capacity());
+ if (!m_index)
+ m_index = m_deque->m_buffer.capacity() - 1;
+ else
+ --m_index;
+ checkValidity();
+ }
+
+ template<typename T>
+ inline T* DequeIteratorBase<T>::after() const
+ {
+ checkValidity();
+ ASSERT(m_index != m_deque->m_end);
+ return &m_deque->m_buffer.buffer()[m_index];
+ }
+
+ template<typename T>
+ inline T* DequeIteratorBase<T>::before() const
+ {
+ checkValidity();
+ ASSERT(m_index != m_deque->m_start);
+ if (!m_index)
+ return &m_deque->m_buffer.buffer()[m_deque->m_buffer.capacity() - 1];
+ return &m_deque->m_buffer.buffer()[m_index - 1];
+ }
} // namespace WTF
diff --git a/JavaScriptCore/wtf/FastMalloc.cpp b/JavaScriptCore/wtf/FastMalloc.cpp
index 69df95e..8f7d5ef 100644
--- a/JavaScriptCore/wtf/FastMalloc.cpp
+++ b/JavaScriptCore/wtf/FastMalloc.cpp
@@ -1,5 +1,6 @@
// Copyright (c) 2005, 2007, The Android Open Source Project
// All rights reserved.
+// Copyright (C) 2005, 2006, 2007, 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
@@ -77,7 +78,7 @@
#include "FastMalloc.h"
#include "Assertions.h"
-#if USE(MULTIPLE_THREADS)
+#if ENABLE(JSC_MULTIPLE_THREADS)
#include <pthread.h>
#endif
@@ -93,10 +94,12 @@
#define FORCE_SYSTEM_MALLOC 1
#endif
+#define TCMALLOC_TRACK_DECOMMITED_SPANS (HAVE(VIRTUALALLOC))
+
#ifndef NDEBUG
namespace WTF {
-#if USE(MULTIPLE_THREADS)
+#if ENABLE(JSC_MULTIPLE_THREADS)
static pthread_key_t isForbiddenKey;
static pthread_once_t isForbiddenKeyOnce = PTHREAD_ONCE_INIT;
static void initializeIsForbiddenKey()
@@ -139,7 +142,7 @@ void fastMallocAllow()
{
staticIsForbidden = false;
}
-#endif // USE(MULTIPLE_THREADS)
+#endif // ENABLE(JSC_MULTIPLE_THREADS)
} // namespace WTF
#endif // NDEBUG
@@ -147,53 +150,111 @@ void fastMallocAllow()
#include <string.h>
namespace WTF {
-void *fastZeroedMalloc(size_t n)
+
+void* fastZeroedMalloc(size_t n)
{
- void *result = fastMalloc(n);
- if (!result)
- return 0;
+ void* result = fastMalloc(n);
memset(result, 0, n);
-#ifndef WTF_CHANGES
- MallocHook::InvokeNewHook(result, n);
-#endif
return result;
}
+void* tryFastZeroedMalloc(size_t n)
+{
+ void* result = tryFastMalloc(n);
+ if (!result)
+ return 0;
+ memset(result, 0, n);
+ return result;
}
+} // namespace WTF
+
#if FORCE_SYSTEM_MALLOC
#include <stdlib.h>
#if !PLATFORM(WIN_OS)
#include <pthread.h>
+#else
+ #include "windows.h"
#endif
namespace WTF {
-
-void *fastMalloc(size_t n)
+
+void* tryFastMalloc(size_t n)
{
ASSERT(!isForbidden());
return malloc(n);
}
-void *fastCalloc(size_t n_elements, size_t element_size)
+void* fastMalloc(size_t n)
+{
+ ASSERT(!isForbidden());
+ void* result = malloc(n);
+ if (!result)
+ abort();
+ return result;
+}
+
+void* tryFastCalloc(size_t n_elements, size_t element_size)
{
ASSERT(!isForbidden());
return calloc(n_elements, element_size);
}
+void* fastCalloc(size_t n_elements, size_t element_size)
+{
+ ASSERT(!isForbidden());
+ void* result = calloc(n_elements, element_size);
+ if (!result)
+ abort();
+ return result;
+}
+
void fastFree(void* p)
{
ASSERT(!isForbidden());
free(p);
}
-void *fastRealloc(void* p, size_t n)
+void* tryFastRealloc(void* p, size_t n)
{
ASSERT(!isForbidden());
return realloc(p, n);
}
+void* fastRealloc(void* p, size_t n)
+{
+ ASSERT(!isForbidden());
+ void* result = realloc(p, n);
+ if (!result)
+ abort();
+ 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)
+{
+ return fastMalloc(n);
+}
+
+void fastFreeExecutable(void* p)
+{
+ fastFree(p);
+}
+#endif
+
} // namespace WTF
#if PLATFORM(DARWIN)
@@ -202,7 +263,7 @@ void *fastRealloc(void* p, size_t n)
extern "C" const int jscore_fastmalloc_introspection = 0;
#endif
-#else
+#else // FORCE_SYSTEM_MALLOC
#if HAVE(STDINT_H)
#include <stdint.h>
@@ -236,6 +297,7 @@ extern "C" const int jscore_fastmalloc_introspection = 0;
#if PLATFORM(DARWIN)
#include "MallocZoneSupport.h"
+#include <wtf/HashSet.h>
#endif
#ifndef PRIuS
@@ -290,7 +352,7 @@ public:
static void log(malloc_zone_t*, void*) { }
static void forceLock(malloc_zone_t*) { }
static void forceUnlock(malloc_zone_t*) { }
- static void statistics(malloc_zone_t*, malloc_statistics_t*) { }
+ static void statistics(malloc_zone_t*, malloc_statistics_t* stats) { memset(stats, 0, sizeof(malloc_statistics_t)); }
private:
FastMallocZone(TCMalloc_PageHeap*, TCMalloc_ThreadCache**, TCMalloc_Central_FreeListPadded*);
@@ -859,9 +921,12 @@ struct Span {
Span* prev; // Used when in link list
void* objects; // Linked list of free objects
unsigned int free : 1; // Is the span free
+#ifndef NO_TCMALLOC_SAMPLES
unsigned int sample : 1; // Sampled object?
+#endif
unsigned int sizeclass : 8; // Size-class for small objects (or 0)
unsigned int refcount : 11; // Number of non-free objects
+ bool decommitted : 1;
#undef SPAN_HISTORY
#ifdef SPAN_HISTORY
@@ -872,6 +937,12 @@ struct Span {
#endif
};
+#if TCMALLOC_TRACK_DECOMMITED_SPANS
+#define ASSERT_SPAN_COMMITTED(span) ASSERT(!span->decommitted)
+#else
+#define ASSERT_SPAN_COMMITTED(span)
+#endif
+
#ifdef SPAN_HISTORY
void Event(Span* span, char op, int v = 0) {
span->history[span->nexthistory] = op;
@@ -1173,13 +1244,22 @@ inline Span* TCMalloc_PageHeap::New(Length n) {
Span* result = ll->next;
Carve(result, n, released);
+#if TCMALLOC_TRACK_DECOMMITED_SPANS
+ if (result->decommitted) {
+ TCMalloc_SystemCommit(reinterpret_cast<void*>(result->start << kPageShift), static_cast<size_t>(n << kPageShift));
+ result->decommitted = false;
+ }
+#endif
ASSERT(Check());
free_pages_ -= n;
return result;
}
Span* result = AllocLarge(n);
- if (result != NULL) return result;
+ if (result != NULL) {
+ ASSERT_SPAN_COMMITTED(result);
+ return result;
+ }
// Grow the heap and try again
if (!GrowHeap(n)) {
@@ -1226,6 +1306,12 @@ Span* TCMalloc_PageHeap::AllocLarge(Length n) {
if (best != NULL) {
Carve(best, n, from_released);
+#if TCMALLOC_TRACK_DECOMMITED_SPANS
+ if (best->decommitted) {
+ TCMalloc_SystemCommit(reinterpret_cast<void*>(best->start << kPageShift), static_cast<size_t>(n << kPageShift));
+ best->decommitted = false;
+ }
+#endif
ASSERT(Check());
free_pages_ -= n;
return best;
@@ -1250,6 +1336,15 @@ Span* TCMalloc_PageHeap::Split(Span* span, Length n) {
return leftover;
}
+#if !TCMALLOC_TRACK_DECOMMITED_SPANS
+static ALWAYS_INLINE void propagateDecommittedState(Span*, Span*) { }
+#else
+static ALWAYS_INLINE void propagateDecommittedState(Span* destination, Span* source)
+{
+ destination->decommitted = source->decommitted;
+}
+#endif
+
inline void TCMalloc_PageHeap::Carve(Span* span, Length n, bool released) {
ASSERT(n > 0);
DLL_Remove(span);
@@ -1261,6 +1356,7 @@ inline void TCMalloc_PageHeap::Carve(Span* span, Length n, bool released) {
if (extra > 0) {
Span* leftover = NewSpan(span->start + n, extra);
leftover->free = 1;
+ propagateDecommittedState(leftover, span);
Event(leftover, 'S', extra);
RecordSpan(leftover);
@@ -1274,6 +1370,16 @@ inline void TCMalloc_PageHeap::Carve(Span* span, Length n, bool released) {
}
}
+#if !TCMALLOC_TRACK_DECOMMITED_SPANS
+static ALWAYS_INLINE void mergeDecommittedStates(Span*, Span*) { }
+#else
+static ALWAYS_INLINE void mergeDecommittedStates(Span* destination, Span* other)
+{
+ if (other->decommitted)
+ destination->decommitted = true;
+}
+#endif
+
inline void TCMalloc_PageHeap::Delete(Span* span) {
ASSERT(Check());
ASSERT(!span->free);
@@ -1281,7 +1387,9 @@ inline void TCMalloc_PageHeap::Delete(Span* span) {
ASSERT(GetDescriptor(span->start) == span);
ASSERT(GetDescriptor(span->start + span->length - 1) == span);
span->sizeclass = 0;
+#ifndef NO_TCMALLOC_SAMPLES
span->sample = 0;
+#endif
// Coalesce -- we guarantee that "p" != 0, so no bounds checking
// necessary. We do not bother resetting the stale pagemap
@@ -1298,6 +1406,7 @@ inline void TCMalloc_PageHeap::Delete(Span* span) {
// Merge preceding span into this span
ASSERT(prev->start + prev->length == p);
const Length len = prev->length;
+ mergeDecommittedStates(span, prev);
DLL_Remove(prev);
DeleteSpan(prev);
span->start -= len;
@@ -1310,6 +1419,7 @@ inline void TCMalloc_PageHeap::Delete(Span* span) {
// Merge next span into this span
ASSERT(next->start == p+n);
const Length len = next->length;
+ mergeDecommittedStates(span, next);
DLL_Remove(next);
DeleteSpan(next);
span->length += len;
@@ -1350,6 +1460,9 @@ void TCMalloc_PageHeap::IncrementalScavenge(Length n) {
DLL_Remove(s);
TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift),
static_cast<size_t>(s->length << kPageShift));
+#if TCMALLOC_TRACK_DECOMMITED_SPANS
+ s->decommitted = true;
+#endif
DLL_Prepend(&slist->returned, s);
scavenge_counter_ = std::max<size_t>(64UL, std::min<size_t>(kDefaultReleaseDelay, kDefaultReleaseDelay - (free_pages_ / kDefaultReleaseDelay)));
@@ -1456,7 +1569,7 @@ bool TCMalloc_PageHeap::GrowHeap(Length n) {
if (n < ask) {
// Try growing just "n" pages
ask = n;
- ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize);;
+ ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize);
}
if (ptr == NULL) return false;
}
@@ -1717,13 +1830,18 @@ class TCMalloc_Central_FreeList {
#ifdef WTF_CHANGES
template <class Finder, class Reader>
- void enumerateFreeObjects(Finder& finder, const Reader& reader)
+ void enumerateFreeObjects(Finder& finder, const Reader& reader, TCMalloc_Central_FreeList* remoteCentralFreeList)
{
for (Span* span = &empty_; span && span != &empty_; span = (span->next ? reader(span->next) : 0))
ASSERT(!span->objects);
ASSERT(!nonempty_.objects);
- for (Span* span = reader(nonempty_.next); span && span != &nonempty_; span = (span->next ? reader(span->next) : 0)) {
+ static const ptrdiff_t nonemptyOffset = reinterpret_cast<const char*>(&nonempty_) - reinterpret_cast<const char*>(this);
+
+ Span* remoteNonempty = reinterpret_cast<Span*>(reinterpret_cast<char*>(remoteCentralFreeList) + nonemptyOffset);
+ Span* remoteSpan = nonempty_.next;
+
+ for (Span* span = reader(remoteSpan); span && remoteSpan != remoteNonempty; remoteSpan = span->next, span = (span->next ? reader(span->next) : 0)) {
for (void* nextObject = span->objects; nextObject; nextObject = *reader(reinterpret_cast<void**>(nextObject)))
finder.visit(nextObject);
}
@@ -2090,6 +2208,7 @@ void* TCMalloc_Central_FreeList::FetchFromSpans() {
Span* span = nonempty_.next;
ASSERT(span->objects != NULL);
+ ASSERT_SPAN_COMMITTED(span);
span->refcount++;
void* result = span->objects;
span->objects = *(reinterpret_cast<void**>(result));
@@ -2120,6 +2239,7 @@ ALWAYS_INLINE void TCMalloc_Central_FreeList::Populate() {
lock_.Lock();
return;
}
+ ASSERT_SPAN_COMMITTED(span);
ASSERT(span->length == npages);
// Cache sizeclass info eagerly. Locking is not necessary.
// (Instead of being eager, we could just replace any stale info
@@ -2896,11 +3016,15 @@ static inline void* CheckedMallocResult(void *result)
}
static inline void* SpanToMallocResult(Span *span) {
+ ASSERT_SPAN_COMMITTED(span);
pageheap->CacheSizeClass(span->start, 0);
return
CheckedMallocResult(reinterpret_cast<void*>(span->start << kPageShift));
}
+#ifdef WTF_CHANGES
+template <bool abortOnFailure>
+#endif
static ALWAYS_INLINE void* do_malloc(size_t size) {
void* ret = NULL;
@@ -2930,7 +3054,14 @@ static ALWAYS_INLINE void* do_malloc(size_t size) {
// size-appropriate freelist, afer replenishing it if it's empty.
ret = CheckedMallocResult(heap->Allocate(size));
}
- if (ret == NULL) errno = ENOMEM;
+ if (!ret) {
+#ifdef WTF_CHANGES
+ if (abortOnFailure) // This branch should be optimized out by the compiler.
+ abort();
+#else
+ errno = ENOMEM;
+#endif
+ }
return ret;
}
@@ -2947,7 +3078,9 @@ static ALWAYS_INLINE void do_free(void* ptr) {
pageheap->CacheSizeClass(p, cl);
}
if (cl != 0) {
+#ifndef NO_TCMALLOC_SAMPLES
ASSERT(!pageheap->GetDescriptor(p)->sample);
+#endif
TCMalloc_ThreadCache* heap = TCMalloc_ThreadCache::GetCacheIfPresent();
if (heap != NULL) {
heap->Deallocate(ptr, cl);
@@ -2960,11 +3093,13 @@ static ALWAYS_INLINE void do_free(void* ptr) {
SpinLockHolder h(&pageheap_lock);
ASSERT(reinterpret_cast<uintptr_t>(ptr) % kPageSize == 0);
ASSERT(span != NULL && span->start == p);
+#ifndef NO_TCMALLOC_SAMPLES
if (span->sample) {
DLL_Remove(span);
stacktrace_allocator.Delete(reinterpret_cast<StackTrace*>(span->objects));
span->objects = NULL;
}
+#endif
pageheap->Delete(span);
}
}
@@ -3090,6 +3225,24 @@ static inline struct mallinfo do_mallinfo() {
#ifndef WTF_CHANGES
extern "C"
+#else
+#define do_malloc do_malloc<abortOnFailure>
+
+template <bool abortOnFailure>
+void* malloc(size_t);
+
+void* fastMalloc(size_t size)
+{
+ return malloc<true>(size);
+}
+
+void* tryFastMalloc(size_t size)
+{
+ return malloc<false>(size);
+}
+
+template <bool abortOnFailure>
+ALWAYS_INLINE
#endif
void* malloc(size_t size) {
void* result = do_malloc(size);
@@ -3111,6 +3264,22 @@ void free(void* ptr) {
#ifndef WTF_CHANGES
extern "C"
+#else
+template <bool abortOnFailure>
+void* calloc(size_t, size_t);
+
+void* fastCalloc(size_t n, size_t elem_size)
+{
+ return calloc<true>(n, elem_size);
+}
+
+void* tryFastCalloc(size_t n, size_t elem_size)
+{
+ return calloc<false>(n, elem_size);
+}
+
+template <bool abortOnFailure>
+ALWAYS_INLINE
#endif
void* calloc(size_t n, size_t elem_size) {
const size_t totalBytes = n * elem_size;
@@ -3141,6 +3310,22 @@ void cfree(void* ptr) {
#ifndef WTF_CHANGES
extern "C"
+#else
+template <bool abortOnFailure>
+void* realloc(void*, size_t);
+
+void* fastRealloc(void* old_ptr, size_t new_size)
+{
+ return realloc<true>(old_ptr, new_size);
+}
+
+void* tryFastRealloc(void* old_ptr, size_t new_size)
+{
+ return realloc<false>(old_ptr, new_size);
+}
+
+template <bool abortOnFailure>
+ALWAYS_INLINE
#endif
void* realloc(void* old_ptr, size_t new_size) {
if (old_ptr == NULL) {
@@ -3200,7 +3385,19 @@ void* realloc(void* old_ptr, size_t new_size) {
}
}
-#ifndef WTF_CHANGES
+void* fastMallocExecutable(size_t n)
+{
+ return malloc<false>(n);
+}
+
+void fastFreeExecutable(void* p)
+{
+ free(p);
+}
+
+#ifdef WTF_CHANGES
+#undef do_malloc
+#else
static SpinLock set_new_handler_lock = SPINLOCK_INITIALIZER;
@@ -3412,7 +3609,6 @@ void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride;
#endif
#if defined(WTF_CHANGES) && PLATFORM(DARWIN)
-#include <wtf/HashSet.h>
class FreeObjectFinder {
const RemoteMemoryReader& m_reader;
@@ -3431,10 +3627,10 @@ public:
threadCache->enumerateFreeObjects(*this, m_reader);
}
- void findFreeObjects(TCMalloc_Central_FreeListPadded* centralFreeList, size_t numSizes)
+ void findFreeObjects(TCMalloc_Central_FreeListPadded* centralFreeList, size_t numSizes, TCMalloc_Central_FreeListPadded* remoteCentralFreeList)
{
for (unsigned i = 0; i < numSizes; i++)
- centralFreeList[i].enumerateFreeObjects(*this, m_reader);
+ centralFreeList[i].enumerateFreeObjects(*this, m_reader, remoteCentralFreeList + i);
}
};
@@ -3548,7 +3744,7 @@ kern_return_t FastMallocZone::enumerate(task_t task, void* context, unsigned typ
FreeObjectFinder finder(memoryReader);
finder.findFreeObjects(threadHeaps);
- finder.findFreeObjects(centralCaches, kNumClasses);
+ finder.findFreeObjects(centralCaches, kNumClasses, mzone->m_centralCaches);
TCMalloc_PageHeap::PageMap* pageMap = &pageHeap->pagemap_;
PageMapFreeObjectFinder pageMapFinder(memoryReader, finder);
@@ -3625,8 +3821,14 @@ void FastMallocZone::init()
#endif
+void releaseFastMallocFreeMemory()
+{
+ SpinLockHolder h(&pageheap_lock);
+ pageheap->ReleaseFreePages();
+}
+
#if WTF_CHANGES
} // namespace WTF
#endif
-#endif // USE_SYSTEM_MALLOC
+#endif // FORCE_SYSTEM_MALLOC
diff --git a/JavaScriptCore/wtf/FastMalloc.h b/JavaScriptCore/wtf/FastMalloc.h
index 27720e0..fb2762c 100644
--- a/JavaScriptCore/wtf/FastMalloc.h
+++ b/JavaScriptCore/wtf/FastMalloc.h
@@ -1,7 +1,5 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * This file is part of the KDE libraries
- * Copyright (C) 2005 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
@@ -29,23 +27,40 @@
namespace WTF {
- void *fastMalloc(size_t n);
- void *fastZeroedMalloc(size_t n);
- void *fastCalloc(size_t n_elements, size_t element_size);
+ // These functions call abort() if an allocation fails.
+ void* fastMalloc(size_t n);
+ void* fastZeroedMalloc(size_t n);
+ void* fastCalloc(size_t n_elements, size_t element_size);
+ void* fastRealloc(void* p, size_t n);
+
+ // These functions return NULL if an allocation fails.
+ void* tryFastMalloc(size_t n);
+ void* tryFastZeroedMalloc(size_t n);
+ void* tryFastCalloc(size_t n_elements, size_t element_size);
+ void* tryFastRealloc(void* p, size_t n);
+
void fastFree(void* p);
- void *fastRealloc(void* p, size_t n);
+
+ void* fastMallocExecutable(size_t n);
+ void fastFreeExecutable(void* p);
#ifndef NDEBUG
void fastMallocForbid();
void fastMallocAllow();
#endif
+ void releaseFastMallocFreeMemory();
+
} // namespace WTF
using WTF::fastMalloc;
using WTF::fastZeroedMalloc;
using WTF::fastCalloc;
using WTF::fastRealloc;
+using WTF::tryFastMalloc;
+using WTF::tryFastZeroedMalloc;
+using WTF::tryFastCalloc;
+using WTF::tryFastRealloc;
using WTF::fastFree;
#ifndef NDEBUG
diff --git a/JavaScriptCore/wtf/GOwnPtr.cpp b/JavaScriptCore/wtf/GOwnPtr.cpp
new file mode 100644
index 0000000..58869f4
--- /dev/null
+++ b/JavaScriptCore/wtf/GOwnPtr.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2008 Collabora Ltd.
+ *
+ * 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.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "GOwnPtr.h"
+
+namespace WTF {
+
+template <> void freeOwnedGPtr<GError>(GError* ptr)
+{
+ if (ptr)
+ g_error_free(ptr);
+}
+
+template <> void freeOwnedGPtr<GList>(GList* ptr)
+{
+ g_list_free(ptr);
+}
+
+template <> void freeOwnedGPtr<GCond>(GCond* ptr)
+{
+ if (ptr)
+ g_cond_free(ptr);
+}
+
+template <> void freeOwnedGPtr<GMutex>(GMutex* ptr)
+{
+ if (ptr)
+ g_mutex_free(ptr);
+}
+
+template <> void freeOwnedGPtr<GPatternSpec>(GPatternSpec* ptr)
+{
+ if (ptr)
+ g_pattern_spec_free(ptr);
+}
+
+template <> void freeOwnedGPtr<GDir>(GDir* ptr)
+{
+ if (ptr)
+ g_dir_close(ptr);
+}
+
+} // namespace WTF
diff --git a/JavaScriptCore/wtf/GOwnPtr.h b/JavaScriptCore/wtf/GOwnPtr.h
new file mode 100644
index 0000000..bbb793a
--- /dev/null
+++ b/JavaScriptCore/wtf/GOwnPtr.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Collabora Ltd.
+ *
+ * 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 GOwnPtr_h
+#define GOwnPtr_h
+
+#include <algorithm>
+#include <glib.h>
+#include <wtf/Assertions.h>
+#include <wtf/Noncopyable.h>
+
+namespace WTF {
+ template <typename T> inline void freeOwnedGPtr(T* ptr) { g_free(reinterpret_cast<void*>(ptr)); }
+ template<> void freeOwnedGPtr<GError>(GError*);
+ template<> void freeOwnedGPtr<GList>(GList*);
+ template<> void freeOwnedGPtr<GCond>(GCond*);
+ template<> void freeOwnedGPtr<GMutex>(GMutex*);
+ template<> void freeOwnedGPtr<GPatternSpec>(GPatternSpec*);
+ template<> void freeOwnedGPtr<GDir>(GDir*);
+
+ template <typename T> class GOwnPtr : Noncopyable {
+ public:
+ explicit GOwnPtr(T* ptr = 0) : m_ptr(ptr) { }
+ ~GOwnPtr() { freeOwnedGPtr(m_ptr); }
+
+ T* get() const { return m_ptr; }
+ T* release() { T* ptr = m_ptr; m_ptr = 0; return ptr; }
+ T*& outPtr() { ASSERT(!m_ptr); return m_ptr; }
+
+ void set(T* ptr) { ASSERT(!ptr || m_ptr != ptr); freeOwnedGPtr(m_ptr); m_ptr = ptr; }
+ void clear() { freeOwnedGPtr(m_ptr); m_ptr = 0; }
+
+ T& operator*() const { ASSERT(m_ptr); return *m_ptr; }
+ T* operator->() const { ASSERT(m_ptr); return m_ptr; }
+
+ bool operator!() const { return !m_ptr; }
+
+ // This conversion operator allows implicit conversion to bool but not to other integer types.
+ typedef T* GOwnPtr::*UnspecifiedBoolType;
+ operator UnspecifiedBoolType() const { return m_ptr ? &GOwnPtr::m_ptr : 0; }
+
+ void swap(GOwnPtr& o) { std::swap(m_ptr, o.m_ptr); }
+
+ private:
+ T* m_ptr;
+ };
+
+ template <typename T> inline void swap(GOwnPtr<T>& a, GOwnPtr<T>& b) { a.swap(b); }
+
+ template <typename T, typename U> inline bool operator==(const GOwnPtr<T>& a, U* b)
+ {
+ return a.get() == b;
+ }
+
+ template <typename T, typename U> inline bool operator==(T* a, const GOwnPtr<U>& b)
+ {
+ return a == b.get();
+ }
+
+ template <typename T, typename U> inline bool operator!=(const GOwnPtr<T>& a, U* b)
+ {
+ return a.get() != b;
+ }
+
+ template <typename T, typename U> inline bool operator!=(T* a, const GOwnPtr<U>& b)
+ {
+ return a != b.get();
+ }
+
+ template <typename T> inline typename GOwnPtr<T>::PtrType getPtr(const GOwnPtr<T>& p)
+ {
+ return p.get();
+ }
+
+} // namespace WTF
+
+using WTF::GOwnPtr;
+
+#endif // GOwnPtr_h
diff --git a/JavaScriptCore/wtf/HashCountedSet.h b/JavaScriptCore/wtf/HashCountedSet.h
index 202577a..8095a2b 100644
--- a/JavaScriptCore/wtf/HashCountedSet.h
+++ b/JavaScriptCore/wtf/HashCountedSet.h
@@ -1,4 +1,3 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* This file is part of the KDE libraries
* Copyright (C) 2005 Apple Computer, Inc.
@@ -25,6 +24,7 @@
#include "Assertions.h"
#include "HashMap.h"
+#include "Vector.h"
namespace WTF {
@@ -170,6 +170,33 @@ namespace WTF {
{
m_impl.clear();
}
+
+ template<typename Value, typename HashFunctions, typename Traits, typename VectorType>
+ inline void copyToVector(const HashCountedSet<Value, HashFunctions, Traits>& collection, VectorType& vector)
+ {
+ typedef typename HashCountedSet<Value, HashFunctions, Traits>::const_iterator iterator;
+
+ vector.resize(collection.size());
+
+ iterator it = collection.begin();
+ iterator end = collection.end();
+ for (unsigned i = 0; it != end; ++it, ++i)
+ vector[i] = *it;
+ }
+
+ template<typename Value, typename HashFunctions, typename Traits>
+ inline void copyToVector(const HashCountedSet<Value, HashFunctions, Traits>& collection, Vector<Value>& vector)
+ {
+ typedef typename HashCountedSet<Value, HashFunctions, Traits>::const_iterator iterator;
+
+ vector.resize(collection.size());
+
+ iterator it = collection.begin();
+ iterator end = collection.end();
+ for (unsigned i = 0; it != end; ++it, ++i)
+ vector[i] = (*it).first;
+ }
+
} // namespace khtml
diff --git a/JavaScriptCore/wtf/HashFunctions.h b/JavaScriptCore/wtf/HashFunctions.h
index bf85dc0..2c66a2d 100644
--- a/JavaScriptCore/wtf/HashFunctions.h
+++ b/JavaScriptCore/wtf/HashFunctions.h
@@ -1,7 +1,5 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * This file is part of the KDE libraries
- * Copyright (C) 2005, 2006 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
@@ -37,6 +35,32 @@ namespace WTF {
// integer hash function
// Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
+ inline unsigned intHash(uint8_t key8)
+ {
+ unsigned key = key8;
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return key;
+ }
+
+ // Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
+ inline unsigned intHash(uint16_t key16)
+ {
+ unsigned key = key16;
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return key;
+ }
+
+ // Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
inline unsigned intHash(uint32_t key)
{
key += ~(key << 15);
@@ -69,7 +93,15 @@ namespace WTF {
};
template<typename T> struct FloatHash {
- static unsigned hash(T key) { return intHash(*reinterpret_cast<typename IntTypes<sizeof(T)>::UnsignedType*>(&key)); }
+ static unsigned hash(T key)
+ {
+ union {
+ T key;
+ typename IntTypes<sizeof(T)>::UnsignedType bits;
+ } u;
+ u.key = key;
+ return intHash(u.bits);
+ }
static bool equal(T a, T b) { return a == b; }
static const bool safeToCompareToEmptyOrDeleted = true;
};
@@ -91,18 +123,36 @@ namespace WTF {
static bool equal(T a, T b) { return a == b; }
static const bool safeToCompareToEmptyOrDeleted = true;
};
- template<typename P> struct PtrHash<RefPtr<P> > {
- static unsigned hash(const RefPtr<P>& key) { return PtrHash<P*>::hash(key.get()); }
+ template<typename P> struct PtrHash<RefPtr<P> > : PtrHash<P*> {
+ using PtrHash<P*>::hash;
+ static unsigned hash(const RefPtr<P>& key) { return hash(key.get()); }
+ using PtrHash<P*>::equal;
static bool equal(const RefPtr<P>& a, const RefPtr<P>& b) { return a == b; }
- static const bool safeToCompareToEmptyOrDeleted = true;
+ static bool equal(P* a, const RefPtr<P>& b) { return a == b; }
+ static bool equal(const RefPtr<P>& a, P* b) { return a == b; }
};
// default hash function for each type
template<typename T> struct DefaultHash;
+ template<typename T, typename U> struct PairHash {
+ static unsigned hash(const std::pair<T, U>& p)
+ {
+ return intHash((static_cast<uint64_t>(DefaultHash<T>::Hash::hash(p.first)) << 32 | DefaultHash<U>::Hash::hash(p.second)));
+ }
+ static bool equal(const std::pair<T, U>& a, const std::pair<T, U>& b)
+ {
+ return DefaultHash<T>::Hash::equal(a.first, b.first) && DefaultHash<U>::Hash::equal(a.second, b.second);
+ }
+ static const bool safeToCompareToEmptyOrDeleted = DefaultHash<T>::Hash::safeToCompareToEmptyOrDeleted
+ && DefaultHash<U>::Hash::safeToCompareToEmptyOrDeleted;
+ };
+
// make IntHash the default hash function for many integer types
+ template<> struct DefaultHash<short> { typedef IntHash<unsigned> Hash; };
+ template<> struct DefaultHash<unsigned short> { typedef IntHash<unsigned> Hash; };
template<> struct DefaultHash<int> { typedef IntHash<unsigned> Hash; };
template<> struct DefaultHash<unsigned> { typedef IntHash<unsigned> Hash; };
template<> struct DefaultHash<long> { typedef IntHash<unsigned long> Hash; };
@@ -110,6 +160,10 @@ namespace WTF {
template<> struct DefaultHash<long long> { typedef IntHash<unsigned long long> Hash; };
template<> struct DefaultHash<unsigned long long> { typedef IntHash<unsigned long long> Hash; };
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+ template<> struct DefaultHash<wchar_t> { typedef IntHash<wchar_t> Hash; };
+#endif
+
template<> struct DefaultHash<float> { typedef FloatHash<float> Hash; };
template<> struct DefaultHash<double> { typedef FloatHash<double> Hash; };
@@ -118,6 +172,8 @@ namespace WTF {
template<typename P> struct DefaultHash<P*> { typedef PtrHash<P*> Hash; };
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; };
+
} // namespace WTF
using WTF::DefaultHash;
diff --git a/JavaScriptCore/wtf/HashIterators.h b/JavaScriptCore/wtf/HashIterators.h
index c449112..682c83b 100644
--- a/JavaScriptCore/wtf/HashIterators.h
+++ b/JavaScriptCore/wtf/HashIterators.h
@@ -1,4 +1,3 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
*
diff --git a/JavaScriptCore/wtf/HashMap.h b/JavaScriptCore/wtf/HashMap.h
index 66d49d7..c5b75ff 100644
--- a/JavaScriptCore/wtf/HashMap.h
+++ b/JavaScriptCore/wtf/HashMap.h
@@ -1,6 +1,5 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * 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
@@ -34,7 +33,7 @@ namespace WTF {
private:
typedef KeyTraitsArg KeyTraits;
typedef MappedTraitsArg MappedTraits;
- typedef PairBaseHashTraits<KeyTraits, MappedTraits> ValueTraits;
+ typedef PairHashTraits<KeyTraits, MappedTraits> ValueTraits;
public:
typedef typename KeyTraits::TraitType KeyType;
@@ -44,28 +43,13 @@ namespace WTF {
private:
typedef HashArg HashFunctions;
- typedef typename HashKeyStorageTraits<HashFunctions, KeyTraits>::Hash StorageHashFunctions;
-
- typedef typename HashKeyStorageTraits<HashFunctions, KeyTraits>::Traits KeyStorageTraits;
- typedef typename MappedTraits::StorageTraits MappedStorageTraits;
- typedef PairHashTraits<KeyStorageTraits, MappedStorageTraits> ValueStorageTraits;
-
- typedef typename KeyStorageTraits::TraitType KeyStorageType;
- typedef typename MappedStorageTraits::TraitType MappedStorageType;
- typedef typename ValueStorageTraits::TraitType ValueStorageType;
-
- typedef HashTable<KeyStorageType, ValueStorageType, PairFirstExtractor<ValueStorageType>,
- StorageHashFunctions, ValueStorageTraits, KeyStorageTraits> HashTableType;
+ typedef HashTable<KeyType, ValueType, PairFirstExtractor<ValueType>,
+ HashFunctions, ValueTraits, KeyTraits> HashTableType;
public:
typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
- HashMap();
- HashMap(const HashMap&);
- HashMap& operator=(const HashMap&);
- ~HashMap();
-
void swap(HashMap&);
int size() const;
@@ -101,8 +85,6 @@ namespace WTF {
private:
pair<iterator, bool> inlineAdd(const KeyType&, const MappedType&);
- void refAll();
- void derefAll();
HashTableType m_impl;
};
@@ -111,98 +93,27 @@ namespace WTF {
static const typename PairType::first_type& extract(const PairType& p) { return p.first; }
};
- template<bool canReplaceDeletedKey, typename ValueType, typename ValueTraits, typename ValueStorageTraits, typename HashFunctions>
- struct HashMapTranslator;
-
- template<typename ValueType, typename ValueTraits, typename ValueStorageTraits, typename HashFunctions>
- struct HashMapTranslator<true, ValueType, ValueTraits, ValueStorageTraits, HashFunctions> {
+ template<typename ValueType, typename ValueTraits, typename HashFunctions>
+ struct HashMapTranslator {
typedef typename ValueType::first_type KeyType;
typedef typename ValueType::second_type MappedType;
- typedef typename ValueStorageTraits::TraitType ValueStorageType;
- typedef typename ValueStorageTraits::FirstTraits KeyStorageTraits;
- typedef typename KeyStorageTraits::TraitType KeyStorageType;
- typedef typename ValueStorageTraits::SecondTraits MappedStorageTraits;
- typedef typename MappedStorageTraits::TraitType MappedStorageType;
- typedef typename ValueTraits::FirstTraits KeyTraits;
- typedef typename ValueTraits::SecondTraits MappedTraits;
-
- static unsigned hash(const KeyType& key) { return HashFunctions::hash(key); }
- static bool equal(const KeyStorageType& a, const KeyType& b) { return HashFunctions::equal(*(KeyType*)&a, b); }
- static void translate(ValueStorageType& location, const KeyType& key, const MappedType& mapped)
- {
- Assigner<KeyTraits::needsRef, KeyType, KeyStorageType, KeyTraits>::assign(key, location.first);
- Assigner<MappedTraits::needsRef, MappedType, MappedStorageType, MappedTraits>::assign(mapped, location.second);
- }
- };
- template<typename ValueType, typename ValueTraits, typename ValueStorageTraits, typename HashFunctions>
- struct HashMapTranslator<false, ValueType, ValueTraits, ValueStorageTraits, HashFunctions> {
- typedef typename ValueType::first_type KeyType;
- typedef typename ValueType::second_type MappedType;
- typedef typename ValueStorageTraits::TraitType ValueStorageType;
- typedef typename ValueStorageTraits::FirstTraits KeyStorageTraits;
- typedef typename KeyStorageTraits::TraitType KeyStorageType;
- typedef typename ValueStorageTraits::SecondTraits MappedStorageTraits;
- typedef typename MappedStorageTraits::TraitType MappedStorageType;
- typedef typename ValueTraits::FirstTraits KeyTraits;
- typedef typename ValueTraits::SecondTraits MappedTraits;
-
static unsigned hash(const KeyType& key) { return HashFunctions::hash(key); }
- static bool equal(const KeyStorageType& a, const KeyType& b) { return HashFunctions::equal(*(KeyType*)&a, b); }
- static void translate(ValueStorageType& location, const KeyType& key, const MappedType& mapped)
+ static bool equal(const KeyType& a, const KeyType& b) { return HashFunctions::equal(a, b); }
+ static void translate(ValueType& location, const KeyType& key, const MappedType& mapped)
{
- if (location.first == KeyStorageTraits::deletedValue())
- location.first = KeyStorageTraits::emptyValue();
- Assigner<KeyTraits::needsRef, KeyType, KeyStorageType, KeyTraits>::assign(key, location.first);
- Assigner<MappedTraits::needsRef, MappedType, MappedStorageType, MappedTraits>::assign(mapped, location.second);
+ location.first = key;
+ location.second = mapped;
}
};
template<typename T, typename U, typename V, typename W, typename X>
- inline void HashMap<T, U, V, W, X>::refAll()
- {
- HashTableRefCounter<HashTableType, ValueTraits>::refAll(m_impl);
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
- inline void HashMap<T, U, V, W, X>::derefAll()
- {
- HashTableRefCounter<HashTableType, ValueTraits>::derefAll(m_impl);
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
- inline HashMap<T, U, V, W, X>::HashMap()
- {
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
- inline HashMap<T, U, V, W, X>::HashMap(const HashMap& other)
- : m_impl(other.m_impl)
- {
- refAll();
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
- inline HashMap<T, U, V, W, X>& HashMap<T, U, V, W, X>::operator=(const HashMap& other)
- {
- HashMap tmp(other);
- swap(tmp);
- return *this;
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
inline void HashMap<T, U, V, W, X>::swap(HashMap& other)
{
m_impl.swap(other.m_impl);
}
template<typename T, typename U, typename V, typename W, typename X>
- inline HashMap<T, U, V, W, X>::~HashMap()
- {
- derefAll();
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
inline int HashMap<T, U, V, W, X>::size() const
{
return m_impl.size();
@@ -247,27 +158,26 @@ namespace WTF {
template<typename T, typename U, typename V, typename W, typename X>
inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::find(const KeyType& key)
{
- return m_impl.find(*(const KeyStorageType*)&key);
+ return m_impl.find(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::find(const KeyType& key) const
{
- return m_impl.find(*(const KeyStorageType*)&key);
+ return m_impl.find(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline bool HashMap<T, U, V, W, X>::contains(const KeyType& key) const
{
- return m_impl.contains(*(const KeyStorageType*)&key);
+ return m_impl.contains(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline pair<typename HashMap<T, U, V, W, X>::iterator, bool>
HashMap<T, U, V, W, X>::inlineAdd(const KeyType& key, const MappedType& mapped)
{
- const bool canReplaceDeletedKey = !KeyTraits::needsDestruction || KeyStorageTraits::needsDestruction;
- typedef HashMapTranslator<canReplaceDeletedKey, ValueType, ValueTraits, ValueStorageTraits, HashFunctions> TranslatorType;
+ typedef HashMapTranslator<ValueType, ValueTraits, HashFunctions> TranslatorType;
return m_impl.template add<KeyType, MappedType, TranslatorType>(key, mapped);
}
@@ -276,9 +186,10 @@ namespace WTF {
HashMap<T, U, V, W, X>::set(const KeyType& key, const MappedType& mapped)
{
pair<iterator, bool> result = inlineAdd(key, mapped);
- if (!result.second)
+ if (!result.second) {
// add call above didn't change anything, so set the mapped value
result.first->second = mapped;
+ }
return result;
}
@@ -293,12 +204,10 @@ namespace WTF {
typename HashMap<T, U, V, W, MappedTraits>::MappedType
HashMap<T, U, V, W, MappedTraits>::get(const KeyType& key) const
{
- if (m_impl.isEmpty())
- return MappedTraits::emptyValue();
- ValueStorageType* entry = const_cast<HashTableType&>(m_impl).lookup(*(const KeyStorageType*)&key);
+ ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
if (!entry)
return MappedTraits::emptyValue();
- return ((ValueType *)entry)->second;
+ return entry->second;
}
template<typename T, typename U, typename V, typename W, typename X>
@@ -307,7 +216,6 @@ namespace WTF {
if (it.m_impl == m_impl.end())
return;
m_impl.checkTableConsistency();
- RefCounter<ValueTraits, ValueStorageTraits>::deref(*it.m_impl);
m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
}
@@ -320,7 +228,6 @@ namespace WTF {
template<typename T, typename U, typename V, typename W, typename X>
inline void HashMap<T, U, V, W, X>::clear()
{
- derefAll();
m_impl.clear();
}
@@ -368,7 +275,7 @@ namespace WTF {
typedef typename HashTableType::const_iterator iterator;
iterator end = collection.end();
for (iterator it = collection.begin(); it != end; ++it)
- delete *(MappedType*)&it->second;
+ delete it->second;
}
template<typename T, typename U, typename V, typename W, typename X>
@@ -383,7 +290,7 @@ namespace WTF {
typedef typename HashTableType::const_iterator iterator;
iterator end = collection.end();
for (iterator it = collection.begin(); it != end; ++it)
- delete *(KeyType*)&it->first;
+ delete it->first;
}
template<typename T, typename U, typename V, typename W, typename X>
diff --git a/JavaScriptCore/wtf/HashSet.h b/JavaScriptCore/wtf/HashSet.h
index f690956..da99f2c 100644
--- a/JavaScriptCore/wtf/HashSet.h
+++ b/JavaScriptCore/wtf/HashSet.h
@@ -1,6 +1,5 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * 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
@@ -26,36 +25,29 @@
namespace WTF {
- template<typename T> struct IdentityExtractor;
-
template<typename Value, typename HashFunctions, typename Traits> class HashSet;
template<typename Value, typename HashFunctions, typename Traits>
void deleteAllValues(const HashSet<Value, HashFunctions, Traits>&);
+ template<typename T> struct IdentityExtractor;
+
template<typename ValueArg, typename HashArg = typename DefaultHash<ValueArg>::Hash,
typename TraitsArg = HashTraits<ValueArg> > class HashSet {
private:
typedef HashArg HashFunctions;
typedef TraitsArg ValueTraits;
- typedef typename HashKeyStorageTraits<HashFunctions, ValueTraits>::Hash StorageHashFunctions;
-
- typedef typename HashKeyStorageTraits<HashFunctions, ValueTraits>::Traits StorageTraits;
- typedef typename StorageTraits::TraitType StorageType;
+ public:
+ typedef typename ValueTraits::TraitType ValueType;
- typedef HashTable<StorageType, StorageType, IdentityExtractor<StorageType>,
- StorageHashFunctions, StorageTraits, StorageTraits> HashTableType;
+ private:
+ typedef HashTable<ValueType, ValueType, IdentityExtractor<ValueType>,
+ HashFunctions, ValueTraits, ValueTraits> HashTableType;
public:
- typedef typename ValueTraits::TraitType ValueType;
typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
- HashSet();
- HashSet(const HashSet&);
- HashSet& operator=(const HashSet&);
- ~HashSet();
-
void swap(HashSet&);
int size() const;
@@ -71,13 +63,22 @@ namespace WTF {
const_iterator find(const ValueType&) const;
bool contains(const ValueType&) const;
- // the return value is a pair of an interator to the new value's location,
- // and a bool that is true if an new entry was added
+ // An alternate version of find() that finds the object by hashing and comparing
+ // with some other type, to avoid the cost of type conversion. HashTranslator
+ // must have the following function members:
+ // static unsigned hash(const T&);
+ // static bool equal(const ValueType&, const T&);
+ template<typename T, typename HashTranslator> iterator find(const T&);
+ template<typename T, typename HashTranslator> const_iterator find(const T&) const;
+ template<typename T, typename HashTranslator> bool contains(const T&) const;
+
+ // The return value is a pair of an interator to the new value's location,
+ // and a bool that is true if an new entry was added.
pair<iterator, bool> add(const ValueType&);
- // a special version of add() that finds the object by hashing and comparing
+ // An alternate version of add() that finds the object by hashing and comparing
// with some other type, to avoid the cost of type conversion if the object is already
- // in the table. HashTranslator should have the following methods:
+ // in the table. HashTranslator must have the following methods:
// static unsigned hash(const T&);
// static bool equal(const ValueType&, const T&);
// static translate(ValueType&, const T&, unsigned hashCode);
@@ -88,9 +89,6 @@ namespace WTF {
void clear();
private:
- void refAll();
- void derefAll();
-
friend void deleteAllValues<>(const HashSet&);
HashTableType m_impl;
@@ -100,92 +98,16 @@ namespace WTF {
static const T& extract(const T& t) { return t; }
};
- template<bool canReplaceDeletedValue, typename ValueType, typename ValueTraits, typename StorageTraits, typename HashFunctions>
- struct HashSetTranslator;
-
- template<typename ValueType, typename ValueTraits, typename StorageTraits, typename HashFunctions>
- struct HashSetTranslator<true, ValueType, ValueTraits, StorageTraits, HashFunctions> {
- typedef typename StorageTraits::TraitType StorageType;
- static unsigned hash(const ValueType& key) { return HashFunctions::hash(key); }
- static bool equal(const StorageType& a, const ValueType& b) { return HashFunctions::equal(*(const ValueType*)&a, b); }
- static void translate(StorageType& location, const ValueType& key, const ValueType&)
- {
- Assigner<ValueTraits::needsRef, ValueType, StorageType, ValueTraits>::assign(key, location);
- }
- };
-
- template<typename ValueType, typename ValueTraits, typename StorageTraits, typename HashFunctions>
- struct HashSetTranslator<false, ValueType, ValueTraits, StorageTraits, HashFunctions> {
- typedef typename StorageTraits::TraitType StorageType;
- static unsigned hash(const ValueType& key) { return HashFunctions::hash(key); }
- static bool equal(const StorageType& a, const ValueType& b) { return HashFunctions::equal(*(const ValueType*)&a, b); }
- static void translate(StorageType& location, const ValueType& key, const ValueType&)
- {
- if (location == StorageTraits::deletedValue())
- location = StorageTraits::emptyValue();
- Assigner<ValueTraits::needsRef, ValueType, StorageType, ValueTraits>::assign(key, location);
- }
- };
-
- template<bool canReplaceDeletedValue, typename ValueType, typename StorageTraits, typename T, typename Translator>
- struct HashSetTranslatorAdapter;
-
- template<typename ValueType, typename StorageTraits, typename T, typename Translator>
- struct HashSetTranslatorAdapter<true, ValueType, StorageTraits, T, Translator> {
- typedef typename StorageTraits::TraitType StorageType;
+ template<typename ValueType, typename ValueTraits, typename T, typename Translator>
+ struct HashSetTranslatorAdapter {
static unsigned hash(const T& key) { return Translator::hash(key); }
- static bool equal(const StorageType& a, const T& b) { return Translator::equal(*(const ValueType*)&a, b); }
- static void translate(StorageType& location, const T& key, const T&, unsigned hashCode)
+ static bool equal(const ValueType& a, const T& b) { return Translator::equal(a, b); }
+ static void translate(ValueType& location, const T& key, const T&, unsigned hashCode)
{
- Translator::translate(*(ValueType*)&location, key, hashCode);
+ Translator::translate(location, key, hashCode);
}
};
- template<typename ValueType, typename StorageTraits, typename T, typename Translator>
- struct HashSetTranslatorAdapter<false, ValueType, StorageTraits, T, Translator> {
- typedef typename StorageTraits::TraitType StorageType;
- static unsigned hash(const T& key) { return Translator::hash(key); }
- static bool equal(const StorageType& a, const T& b) { return Translator::equal(*(const ValueType*)&a, b); }
- static void translate(StorageType& location, const T& key, const T&, unsigned hashCode)
- {
- if (location == StorageTraits::deletedValue())
- location = StorageTraits::emptyValue();
- Translator::translate(*(ValueType*)&location, key, hashCode);
- }
- };
-
- template<typename T, typename U, typename V>
- inline void HashSet<T, U, V>::refAll()
- {
- HashTableRefCounter<HashTableType, ValueTraits>::refAll(m_impl);
- }
-
- template<typename T, typename U, typename V>
- inline void HashSet<T, U, V>::derefAll()
- {
- HashTableRefCounter<HashTableType, ValueTraits>::derefAll(m_impl);
- }
-
- template<typename T, typename U, typename V>
- inline HashSet<T, U, V>::HashSet()
- {
- }
-
- template<typename T, typename U, typename V>
- inline HashSet<T, U, V>::HashSet(const HashSet& other)
- : m_impl(other.m_impl)
- {
- refAll();
- }
-
- template<typename T, typename U, typename V>
- inline HashSet<T, U, V>& HashSet<T, U, V>::operator=(const HashSet& other)
- {
- HashSet tmp(other);
- swap(tmp);
- return *this;
- }
-
template<typename T, typename U, typename V>
inline void HashSet<T, U, V>::swap(HashSet& other)
{
@@ -193,12 +115,6 @@ namespace WTF {
}
template<typename T, typename U, typename V>
- inline HashSet<T, U, V>::~HashSet()
- {
- derefAll();
- }
-
- template<typename T, typename U, typename V>
inline int HashSet<T, U, V>::size() const
{
return m_impl.size();
@@ -243,27 +159,51 @@ namespace WTF {
template<typename T, typename U, typename V>
inline typename HashSet<T, U, V>::iterator HashSet<T, U, V>::find(const ValueType& value)
{
- return m_impl.find(*(const StorageType*)&value);
+ return m_impl.find(value);
}
template<typename T, typename U, typename V>
inline typename HashSet<T, U, V>::const_iterator HashSet<T, U, V>::find(const ValueType& value) const
{
- return m_impl.find(*(const StorageType*)&value);
+ return m_impl.find(value);
}
template<typename T, typename U, typename V>
inline bool HashSet<T, U, V>::contains(const ValueType& value) const
{
- return m_impl.contains(*(const StorageType*)&value);
+ return m_impl.contains(value);
+ }
+
+ template<typename Value, typename HashFunctions, typename Traits>
+ template<typename T, typename Translator>
+ typename HashSet<Value, HashFunctions, Traits>::iterator
+ inline HashSet<Value, HashFunctions, Traits>::find(const T& value)
+ {
+ typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, Translator> Adapter;
+ return m_impl.template find<T, Adapter>(value);
+ }
+
+ template<typename Value, typename HashFunctions, typename Traits>
+ template<typename T, typename Translator>
+ typename HashSet<Value, HashFunctions, Traits>::const_iterator
+ inline HashSet<Value, HashFunctions, Traits>::find(const T& value) const
+ {
+ typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, Translator> Adapter;
+ return m_impl.template find<T, Adapter>(value);
+ }
+
+ template<typename Value, typename HashFunctions, typename Traits>
+ template<typename T, typename Translator>
+ inline bool HashSet<Value, HashFunctions, Traits>::contains(const T& value) const
+ {
+ typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, Translator> Adapter;
+ return m_impl.template contains<T, Adapter>(value);
}
template<typename T, typename U, typename V>
- pair<typename HashSet<T, U, V>::iterator, bool> HashSet<T, U, V>::add(const ValueType &value)
+ pair<typename HashSet<T, U, V>::iterator, bool> HashSet<T, U, V>::add(const ValueType& value)
{
- const bool canReplaceDeletedValue = !ValueTraits::needsDestruction || StorageTraits::needsDestruction;
- typedef HashSetTranslator<canReplaceDeletedValue, ValueType, ValueTraits, StorageTraits, HashFunctions> Translator;
- return m_impl.template add<ValueType, ValueType, Translator>(value, value);
+ return m_impl.add(value);
}
template<typename Value, typename HashFunctions, typename Traits>
@@ -271,8 +211,7 @@ namespace WTF {
pair<typename HashSet<Value, HashFunctions, Traits>::iterator, bool>
HashSet<Value, HashFunctions, Traits>::add(const T& value)
{
- const bool canReplaceDeletedValue = !ValueTraits::needsDestruction || StorageTraits::needsDestruction;
- typedef HashSetTranslatorAdapter<canReplaceDeletedValue, ValueType, StorageTraits, T, Translator> Adapter;
+ typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, Translator> Adapter;
return m_impl.template addPassingHashCode<T, T, Adapter>(value, value);
}
@@ -282,7 +221,6 @@ namespace WTF {
if (it.m_impl == m_impl.end())
return;
m_impl.checkTableConsistency();
- RefCounter<ValueTraits, StorageTraits>::deref(*it.m_impl);
m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
}
@@ -295,7 +233,6 @@ namespace WTF {
template<typename T, typename U, typename V>
inline void HashSet<T, U, V>::clear()
{
- derefAll();
m_impl.clear();
}
@@ -305,7 +242,7 @@ namespace WTF {
typedef typename HashTableType::const_iterator iterator;
iterator end = collection.end();
for (iterator it = collection.begin(); it != end; ++it)
- delete *(ValueType*)&*it;
+ delete *it;
}
template<typename T, typename U, typename V>
diff --git a/JavaScriptCore/wtf/HashTable.cpp b/JavaScriptCore/wtf/HashTable.cpp
index ba45aee..f1f2a4f 100644
--- a/JavaScriptCore/wtf/HashTable.cpp
+++ b/JavaScriptCore/wtf/HashTable.cpp
@@ -1,7 +1,5 @@
/*
- This file is part of the KDE libraries
-
- Copyright (C) 2005 Apple Computer
+ Copyright (C) 2005 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/HashTable.h b/JavaScriptCore/wtf/HashTable.h
index 3b87490..4c7790a 100644
--- a/JavaScriptCore/wtf/HashTable.h
+++ b/JavaScriptCore/wtf/HashTable.h
@@ -1,7 +1,5 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * 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
@@ -63,25 +61,26 @@ namespace WTF {
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
class HashTableConstIterator;
-#if CHECK_HASHTABLE_ITERATORS
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
void addIterator(const HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*,
HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*);
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
void removeIterator(HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*);
-#else
+
+#if !CHECK_HASHTABLE_ITERATORS
+
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
inline void addIterator(const HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*,
HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*) { }
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
inline void removeIterator(HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*) { }
+
#endif
typedef enum { HashItemKnownGood } HashItemKnownGoodTag;
-
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
class HashTableConstIterator {
private:
@@ -325,10 +324,11 @@ namespace WTF {
void clear();
static bool isEmptyBucket(const ValueType& value) { return Extractor::extract(value) == KeyTraits::emptyValue(); }
- static bool isDeletedBucket(const ValueType& value) { return Extractor::extract(value) == KeyTraits::deletedValue(); }
+ static bool isDeletedBucket(const ValueType& value) { return KeyTraits::isDeletedValue(Extractor::extract(value)); }
static bool isEmptyOrDeletedBucket(const ValueType& value) { return isEmptyBucket(value) || isDeletedBucket(value); }
ValueType* lookup(const Key& key) { return lookup<Key, IdentityTranslatorType>(key); }
+ template<typename T, typename HashTranslator> ValueType* lookup(const T&);
#if CHECK_HASHTABLE_CONSISTENCY
void checkTableConsistency() const;
@@ -343,11 +343,12 @@ namespace WTF {
typedef pair<ValueType*, bool> LookupType;
typedef pair<LookupType, unsigned> FullLookupType;
- template<typename T, typename HashTranslator> ValueType* lookup(const T&);
LookupType lookupForWriting(const Key& key) { return lookupForWriting<Key, IdentityTranslatorType>(key); };
template<typename T, typename HashTranslator> FullLookupType fullLookupForWriting(const T&);
template<typename T, typename HashTranslator> LookupType lookupForWriting(const T&);
+ template<typename T, typename HashTranslator> void checkKey(const T&);
+
void removeAndInvalidateWithoutEntryConsistencyCheck(ValueType*);
void removeAndInvalidate(ValueType*);
void remove(ValueType*);
@@ -362,7 +363,7 @@ namespace WTF {
void reinsert(ValueType&);
static void initializeBucket(ValueType& bucket) { new (&bucket) ValueType(Traits::emptyValue()); }
- static void deleteBucket(ValueType& bucket) { assignDeleted<ValueType, Traits>(bucket); }
+ static void deleteBucket(ValueType& bucket) { bucket.~ValueType(); Traits::constructDeletedValue(bucket); }
FullLookupType makeLookupResult(ValueType* position, bool found, unsigned hash)
{ return FullLookupType(LookupType(position, found), hash); }
@@ -423,24 +424,47 @@ namespace WTF {
return key;
}
+#if ASSERT_DISABLED
+
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
template<typename T, typename HashTranslator>
- inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::lookup(const T& key)
+ inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkKey(const T&)
{
- ASSERT(m_table);
-#if !ASSERT_DISABLED
- if (HashFunctions::safeToCompareToEmptyOrDeleted) {
- ASSERT(!HashTranslator::equal(KeyTraits::emptyValue(), key));
- ASSERT(!HashTranslator::equal(KeyTraits::deletedValue(), key));
- }
+ }
+
+#else
+
+ template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
+ template<typename T, typename HashTranslator>
+ void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkKey(const T& key)
+ {
+ if (!HashFunctions::safeToCompareToEmptyOrDeleted)
+ return;
+ ASSERT(!HashTranslator::equal(KeyTraits::emptyValue(), key));
+ ValueType deletedValue = Traits::emptyValue();
+ deletedValue.~ValueType();
+ Traits::constructDeletedValue(deletedValue);
+ ASSERT(!HashTranslator::equal(Extractor::extract(deletedValue), key));
+ new (&deletedValue) ValueType(Traits::emptyValue());
+ }
+
#endif
+ template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
+ template<typename T, typename HashTranslator>
+ inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::lookup(const T& key)
+ {
+ checkKey<T, HashTranslator>(key);
+
int k = 0;
int sizeMask = m_tableSizeMask;
ValueType* table = m_table;
unsigned h = HashTranslator::hash(key);
int i = h & sizeMask;
+ if (!table)
+ return 0;
+
#if DUMP_HASHTABLE_STATS
++HashTableStats::numAccesses;
int probeCount = 0;
@@ -478,12 +502,7 @@ namespace WTF {
inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::lookupForWriting(const T& key)
{
ASSERT(m_table);
-#if !ASSERT_DISABLED
- if (HashFunctions::safeToCompareToEmptyOrDeleted) {
- ASSERT(!HashTranslator::equal(KeyTraits::emptyValue(), key));
- ASSERT(!HashTranslator::equal(KeyTraits::deletedValue(), key));
- }
-#endif
+ checkKey<T, HashTranslator>(key);
int k = 0;
ValueType* table = m_table;
@@ -535,12 +554,7 @@ namespace WTF {
inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::fullLookupForWriting(const T& key)
{
ASSERT(m_table);
-#if !ASSERT_DISABLED
- if (HashFunctions::safeToCompareToEmptyOrDeleted) {
- ASSERT(!HashTranslator::equal(KeyTraits::emptyValue(), key));
- ASSERT(!HashTranslator::equal(KeyTraits::deletedValue(), key));
- }
-#endif
+ checkKey<T, HashTranslator>(key);
int k = 0;
ValueType* table = m_table;
@@ -591,12 +605,7 @@ namespace WTF {
template<typename T, typename Extra, typename HashTranslator>
inline pair<typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::iterator, bool> HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::add(const T& key, const Extra& extra)
{
-#if !ASSERT_DISABLED
- if (HashFunctions::safeToCompareToEmptyOrDeleted) {
- ASSERT(!HashTranslator::equal(KeyTraits::emptyValue(), key));
- ASSERT(!HashTranslator::equal(KeyTraits::deletedValue(), key));
- }
-#endif
+ checkKey<T, HashTranslator>(key);
invalidateIterators();
@@ -652,6 +661,7 @@ namespace WTF {
}
if (deletedEntry) {
+ initializeBucket(*deletedEntry);
entry = deletedEntry;
--m_deletedCount;
}
@@ -661,12 +671,14 @@ namespace WTF {
++m_keyCount;
if (shouldExpand()) {
- // FIXME: this makes an extra copy on expand. Probably not that bad since
+ // FIXME: This makes an extra copy on expand. Probably not that bad since
// expand is rare, but would be better to have a version of expand that can
- // follow a pivot entry and return the new position
+ // follow a pivot entry and return the new position.
KeyType enteredKey = Extractor::extract(*entry);
expand();
- return std::make_pair(find(enteredKey), true);
+ pair<iterator, bool> p = std::make_pair(find(enteredKey), true);
+ ASSERT(p.first != end());
+ return p;
}
checkTableConsistency();
@@ -678,6 +690,8 @@ namespace WTF {
template<typename T, typename Extra, typename HashTranslator>
inline pair<typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::iterator, bool> HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::addPassingHashCode(const T& key, const Extra& extra)
{
+ checkKey<T, HashTranslator>(key);
+
invalidateIterators();
if (!m_table)
@@ -687,25 +701,29 @@ namespace WTF {
FullLookupType lookupResult = fullLookupForWriting<T, HashTranslator>(key);
- ValueType *entry = lookupResult.first.first;
+ ValueType* entry = lookupResult.first.first;
bool found = lookupResult.first.second;
unsigned h = lookupResult.second;
if (found)
return std::make_pair(makeKnownGoodIterator(entry), false);
- if (isDeletedBucket(*entry))
+ if (isDeletedBucket(*entry)) {
+ initializeBucket(*entry);
--m_deletedCount;
+ }
HashTranslator::translate(*entry, key, extra, h);
++m_keyCount;
if (shouldExpand()) {
- // FIXME: this makes an extra copy on expand. Probably not that bad since
+ // FIXME: This makes an extra copy on expand. Probably not that bad since
// expand is rare, but would be better to have a version of expand that can
- // follow a pivot entry and return the new position
+ // follow a pivot entry and return the new position.
KeyType enteredKey = Extractor::extract(*entry);
expand();
- return std::make_pair(find(enteredKey), true);
+ pair<iterator, bool> p = std::make_pair(find(enteredKey), true);
+ ASSERT(p.first != end());
+ return p;
}
checkTableConsistency();
@@ -723,7 +741,7 @@ namespace WTF {
++HashTableStats::numReinserts;
#endif
- Mover<ValueType, Traits::needsDestruction>::move(entry, *(lookupForWriting(Extractor::extract(entry)).first));
+ Mover<ValueType, Traits::needsDestruction>::move(entry, *lookupForWriting(Extractor::extract(entry)).first);
}
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
@@ -747,7 +765,7 @@ namespace WTF {
if (!m_table)
return end();
- ValueType* entry = const_cast<HashTable *>(this)->lookup<T, HashTranslator>(key);
+ ValueType* entry = const_cast<HashTable*>(this)->lookup<T, HashTranslator>(key);
if (!entry)
return end();
@@ -761,7 +779,7 @@ namespace WTF {
if (!m_table)
return false;
- return const_cast<HashTable *>(this)->lookup<T, HashTranslator>(key);
+ return const_cast<HashTable*>(this)->lookup<T, HashTranslator>(key);
}
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
@@ -821,12 +839,12 @@ namespace WTF {
}
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
- Value *HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::allocateTable(int size)
+ Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::allocateTable(int size)
{
// would use a template member function with explicit specializations here, but
// gcc doesn't appear to support that
if (Traits::emptyValueIsZero)
- return static_cast<ValueType *>(fastZeroedMalloc(size * sizeof(ValueType)));
+ return static_cast<ValueType*>(fastZeroedMalloc(size * sizeof(ValueType)));
ValueType* result = static_cast<ValueType*>(fastMalloc(size * sizeof(ValueType)));
for (int i = 0; i < size; i++)
initializeBucket(result[i]);
@@ -834,11 +852,14 @@ namespace WTF {
}
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
- void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::deallocateTable(ValueType *table, int size)
+ void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::deallocateTable(ValueType* table, int size)
{
- if (Traits::needsDestruction)
- for (int i = 0; i < size; ++i)
- table[i].~ValueType();
+ if (Traits::needsDestruction) {
+ for (int i = 0; i < size; ++i) {
+ if (!isDeletedBucket(table[i]))
+ table[i].~ValueType();
+ }
+ }
fastFree(table);
}
@@ -862,7 +883,7 @@ namespace WTF {
checkTableConsistencyExceptSize();
int oldTableSize = m_tableSize;
- ValueType *oldTable = m_table;
+ ValueType* oldTable = m_table;
#if DUMP_HASHTABLE_STATS
if (oldTableSize != 0)
@@ -919,7 +940,7 @@ namespace WTF {
invalidateIterators();
other.invalidateIterators();
- ValueType *tmp_table = m_table;
+ ValueType* tmp_table = m_table;
m_table = other.m_table;
other.m_table = tmp_table;
@@ -967,7 +988,7 @@ namespace WTF {
int count = 0;
int deletedCount = 0;
for (int j = 0; j < m_tableSize; ++j) {
- ValueType *entry = m_table + j;
+ ValueType* entry = m_table + j;
if (isEmptyBucket(*entry))
continue;
@@ -1115,137 +1136,6 @@ namespace WTF {
return a.m_impl != b.m_impl;
}
- // reference count manager
-
- template<typename ValueTraits, typename ValueStorageTraits> struct NeedsRef {
- static const bool value = ValueTraits::needsRef && !ValueStorageTraits::needsRef;
- };
- template<typename FirstTraits, typename SecondTraits, typename ValueStorageTraits>
- struct NeedsRef<PairBaseHashTraits<FirstTraits, SecondTraits>, ValueStorageTraits> {
- typedef typename ValueStorageTraits::FirstTraits FirstStorageTraits;
- typedef typename ValueStorageTraits::SecondTraits SecondStorageTraits;
- static const bool firstNeedsRef = NeedsRef<FirstTraits, FirstStorageTraits>::value;
- static const bool secondNeedsRef = NeedsRef<SecondTraits, SecondStorageTraits>::value;
- static const bool value = firstNeedsRef || secondNeedsRef;
- };
-
- template<bool needsRef, typename ValueTraits, typename ValueStorageTraits> struct RefCounterBase;
-
- template<typename ValueTraits, typename ValueStorageTraits>
- struct RefCounterBase<false, ValueTraits, ValueStorageTraits> {
- typedef typename ValueStorageTraits::TraitType ValueStorageType;
- static void ref(const ValueStorageType&) { }
- static void deref(const ValueStorageType&) { }
- };
-
- template<typename ValueTraits, typename ValueStorageTraits>
- struct RefCounterBase<true, ValueTraits, ValueStorageTraits> {
- typedef typename ValueStorageTraits::TraitType ValueStorageType;
- static void ref(const ValueStorageType& v) { ValueTraits::ref(v); }
- static void deref(const ValueStorageType& v) { ValueTraits::deref(v); }
- };
-
- template<typename ValueTraits, typename ValueStorageTraits> struct RefCounter {
- typedef typename ValueTraits::TraitType ValueType;
- typedef typename ValueStorageTraits::TraitType ValueStorageType;
- static const bool needsRef = NeedsRef<ValueTraits, ValueStorageTraits>::value;
- typedef RefCounterBase<needsRef, ValueTraits, ValueStorageTraits> Base;
- static void ref(const ValueStorageType& v) { Base::ref(v); }
- static void deref(const ValueStorageType& v) { Base::deref(v); }
- };
-
- template<typename FirstTraits, typename SecondTraits, typename ValueStorageTraits>
- struct RefCounter<PairBaseHashTraits<FirstTraits, SecondTraits>, ValueStorageTraits> {
- typedef typename FirstTraits::TraitType FirstType;
- typedef typename SecondTraits::TraitType SecondType;
- typedef typename ValueStorageTraits::FirstTraits FirstStorageTraits;
- typedef typename ValueStorageTraits::SecondTraits SecondStorageTraits;
- typedef typename ValueStorageTraits::TraitType ValueStorageType;
- static const bool firstNeedsRef = NeedsRef<FirstTraits, FirstStorageTraits>::value;
- static const bool secondNeedsRef = NeedsRef<SecondTraits, SecondStorageTraits>::value;
- typedef RefCounterBase<firstNeedsRef, FirstTraits, FirstStorageTraits> FirstBase;
- typedef RefCounterBase<secondNeedsRef, SecondTraits, SecondStorageTraits> SecondBase;
- static void ref(const ValueStorageType& v) {
- FirstBase::ref(v.first);
- SecondBase::ref(v.second);
- }
- static void deref(const ValueStorageType& v) {
- FirstBase::deref(v.first);
- SecondBase::deref(v.second);
- }
- };
-
- template<bool needsRef, typename HashTableType, typename ValueTraits> struct HashTableRefCounterBase;
-
- template<typename HashTableType, typename ValueTraits>
- struct HashTableRefCounterBase<false, HashTableType, ValueTraits>
- {
- static void refAll(HashTableType&) { }
- static void derefAll(HashTableType&) { }
- };
-
- template<typename HashTableType, typename ValueTraits>
- struct HashTableRefCounterBase<true, HashTableType, ValueTraits>
- {
- typedef typename HashTableType::iterator iterator;
- typedef RefCounter<ValueTraits, typename HashTableType::ValueTraits> ValueRefCounter;
- static void refAll(HashTableType&);
- static void derefAll(HashTableType&);
- };
-
- template<typename HashTableType, typename ValueTraits>
- void HashTableRefCounterBase<true, HashTableType, ValueTraits>::refAll(HashTableType& table)
- {
- iterator end = table.end();
- for (iterator it = table.begin(); it != end; ++it)
- ValueRefCounter::ref(*it);
- }
-
- template<typename HashTableType, typename ValueTraits>
- void HashTableRefCounterBase<true, HashTableType, ValueTraits>::derefAll(HashTableType& table)
- {
- iterator end = table.end();
- for (iterator it = table.begin(); it != end; ++it)
- ValueRefCounter::deref(*it);
- }
-
- template<typename HashTableType, typename ValueTraits> struct HashTableRefCounter {
- static const bool needsRef = NeedsRef<ValueTraits, typename HashTableType::ValueTraits>::value;
- typedef HashTableRefCounterBase<needsRef, HashTableType, ValueTraits> Base;
- static void refAll(HashTableType& table) { Base::refAll(table); }
- static void derefAll(HashTableType& table) { Base::derefAll(table); }
- };
-
- // helper template for HashMap and HashSet.
- template<bool needsRef, typename FromType, typename ToType, typename FromTraits> struct Assigner;
-
- template<typename FromType, typename ToType, typename FromTraits> struct Assigner<false, FromType, ToType, FromTraits> {
- typedef union {
- FromType m_from;
- ToType m_to;
- } UnionType;
-
- static void assign(const FromType& from, ToType& to) { reinterpret_cast<UnionType*>(&to)->m_from = from; }
- };
-
- template<typename FromType, typename ToType, typename FromTraits> struct Assigner<true, FromType, ToType, FromTraits> {
- static void assign(const FromType& from, ToType& to)
- {
- ToType oldTo = to;
- memcpy(&to, &from, sizeof(FromType));
- FromTraits::ref(to);
- FromTraits::deref(oldTo);
- }
- };
-
- template<typename FromType, typename FromTraits> struct Assigner<false, FromType, FromType, FromTraits> {
- static void assign(const FromType& from, FromType& to) { to = from; }
- };
-
- template<typename FromType, typename FromTraits> struct Assigner<true, FromType, FromType, FromTraits> {
- static void assign(const FromType& from, FromType& to) { to = from; }
- };
-
} // namespace WTF
#include "HashIterators.h"
diff --git a/JavaScriptCore/wtf/HashTraits.h b/JavaScriptCore/wtf/HashTraits.h
index 5f35278..b3c0b7a 100644
--- a/JavaScriptCore/wtf/HashTraits.h
+++ b/JavaScriptCore/wtf/HashTraits.h
@@ -1,7 +1,5 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * 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
@@ -47,6 +45,10 @@ namespace WTF {
template<> struct IsInteger<long long> { static const bool value = true; };
template<> struct IsInteger<unsigned long long> { static const bool value = true; };
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+ template<> struct IsInteger<wchar_t> { static const bool value = true; };
+#endif
+
COMPILE_ASSERT(IsInteger<bool>::value, WTF_IsInteger_bool_true);
COMPILE_ASSERT(IsInteger<char>::value, WTF_IsInteger_char_true);
COMPILE_ASSERT(IsInteger<signed char>::value, WTF_IsInteger_signed_char_true);
@@ -60,6 +62,10 @@ namespace WTF {
COMPILE_ASSERT(IsInteger<long long>::value, WTF_IsInteger_long_long_true);
COMPILE_ASSERT(IsInteger<unsigned long long>::value, WTF_IsInteger_unsigned_long_long_true);
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+ COMPILE_ASSERT(IsInteger<wchar_t>::value, WTF_IsInteger_wchar_t_true);
+#endif
+
COMPILE_ASSERT(!IsInteger<char*>::value, WTF_IsInteger_char_pointer_false);
COMPILE_ASSERT(!IsInteger<const char* >::value, WTF_IsInteger_const_char_pointer_false);
COMPILE_ASSERT(!IsInteger<volatile char* >::value, WTF_IsInteger_volatile_char_pointer__false);
@@ -69,183 +75,79 @@ namespace WTF {
template<typename T> struct HashTraits;
template<bool isInteger, typename T> struct GenericHashTraitsBase;
- template<typename T> struct GenericHashTraitsBase<true, T> {
- typedef T TraitType;
- typedef HashTraits<typename IntTypes<sizeof(T)>::SignedType> StorageTraits;
- static const bool emptyValueIsZero = true;
- static const bool needsDestruction = false;
- };
+
template<typename T> struct GenericHashTraitsBase<false, T> {
- typedef T TraitType;
- typedef HashTraits<T> StorageTraits;
static const bool emptyValueIsZero = false;
static const bool needsDestruction = true;
};
+ // Default integer traits disallow both 0 and -1 as keys (max value instead of -1 for unsigned).
+ template<typename T> struct GenericHashTraitsBase<true, T> {
+ static const bool emptyValueIsZero = true;
+ static const bool needsDestruction = false;
+ static void constructDeletedValue(T& slot) { slot = static_cast<T>(-1); }
+ static bool isDeletedValue(T value) { return value == static_cast<T>(-1); }
+ };
+
template<typename T> struct GenericHashTraits : GenericHashTraitsBase<IsInteger<T>::value, T> {
+ typedef T TraitType;
static T emptyValue() { return T(); }
- static const bool needsRef = false;
};
template<typename T> struct HashTraits : GenericHashTraits<T> { };
- // signed integer traits may not be appropriate for all uses since they disallow 0 and -1 as keys
- template<> struct HashTraits<signed char> : GenericHashTraits<int> {
- static signed char deletedValue() { return -1; }
- };
- template<> struct HashTraits<short> : GenericHashTraits<int> {
- static short deletedValue() { return -1; }
- };
- template<> struct HashTraits<int> : GenericHashTraits<int> {
- static int deletedValue() { return -1; }
- };
- template<> struct HashTraits<unsigned int> : GenericHashTraits<unsigned int> {
- static unsigned int deletedValue() { return static_cast<unsigned int>(-1); }
- };
- template<> struct HashTraits<long> : GenericHashTraits<long> {
- static long deletedValue() { return -1; }
- };
- template<> struct HashTraits<unsigned long> : GenericHashTraits<unsigned long> {
- static unsigned long deletedValue() { return static_cast<unsigned long>(-1); }
- };
- template<> struct HashTraits<long long> : GenericHashTraits<long long> {
- static long long deletedValue() { return -1; }
- };
- template<> struct HashTraits<unsigned long long> : GenericHashTraits<unsigned long long> {
- static unsigned long long deletedValue() { return static_cast<unsigned long long>(-1); }
- };
-
- template<typename T> struct FloatHashTraits {
- typedef T TraitType;
- typedef HashTraits<T> StorageTraits;
+ template<typename T> struct FloatHashTraits : GenericHashTraits<T> {
+ static const bool needsDestruction = false;
static T emptyValue() { return std::numeric_limits<T>::infinity(); }
- static T deletedValue() { return -std::numeric_limits<T>::infinity(); }
+ static void constructDeletedValue(T& slot) { slot = -std::numeric_limits<T>::infinity(); }
+ static bool isDeletedValue(T value) { return value == -std::numeric_limits<T>::infinity(); }
+ };
+
+ template<> struct HashTraits<float> : FloatHashTraits<float> { };
+ template<> struct HashTraits<double> : FloatHashTraits<double> { };
+
+ // Default unsigned traits disallow both 0 and max as keys -- use these traits to allow zero and disallow max - 1.
+ template<typename T> struct UnsignedWithZeroKeyHashTraits : GenericHashTraits<T> {
static const bool emptyValueIsZero = false;
static const bool needsDestruction = false;
- static const bool needsRef = false;
- };
- template<> struct HashTraits<float> : FloatHashTraits<float> {
- };
- template<> struct HashTraits<double> : FloatHashTraits<double> {
+ static T emptyValue() { return std::numeric_limits<T>::max(); }
+ static void constructDeletedValue(T& slot) { slot = std::numeric_limits<T>::max() - 1; }
+ static bool isDeletedValue(T value) { return value == std::numeric_limits<T>::max() - 1; }
};
template<typename P> struct HashTraits<P*> : GenericHashTraits<P*> {
- typedef HashTraits<typename IntTypes<sizeof(P*)>::SignedType> StorageTraits;
static const bool emptyValueIsZero = true;
static const bool needsDestruction = false;
- static P* deletedValue() { return reinterpret_cast<P*>(-1); }
+ static void constructDeletedValue(P*& slot) { slot = reinterpret_cast<P*>(-1); }
+ static bool isDeletedValue(P* value) { return value == reinterpret_cast<P*>(-1); }
};
template<typename P> struct HashTraits<RefPtr<P> > : GenericHashTraits<RefPtr<P> > {
- typedef HashTraits<typename IntTypes<sizeof(P*)>::SignedType> StorageTraits;
- typedef typename StorageTraits::TraitType StorageType;
static const bool emptyValueIsZero = true;
- static const bool needsRef = true;
-
- typedef union {
- P* m_p;
- StorageType m_s;
- } UnionType;
-
- static void ref(const StorageType& s)
- {
- if (const P* p = reinterpret_cast<const UnionType*>(&s)->m_p)
- const_cast<P*>(p)->ref();
- }
- static void deref(const StorageType& s)
- {
- if (const P* p = reinterpret_cast<const UnionType*>(&s)->m_p)
- const_cast<P*>(p)->deref();
- }
- };
-
- // template to set deleted values
-
- template<typename Traits> struct DeletedValueAssigner {
- static void assignDeletedValue(typename Traits::TraitType& location) { location = Traits::deletedValue(); }
+ static void constructDeletedValue(RefPtr<P>& slot) { new (&slot) RefPtr<P>(HashTableDeletedValue); }
+ static bool isDeletedValue(const RefPtr<P>& value) { return value.isHashTableDeletedValue(); }
};
- template<typename T, typename Traits> inline void assignDeleted(T& location)
- {
- DeletedValueAssigner<Traits>::assignDeletedValue(location);
- }
-
// special traits for pairs, helpful for their use in HashMap implementation
- template<typename FirstTraits, typename SecondTraits> struct PairHashTraits;
-
template<typename FirstTraitsArg, typename SecondTraitsArg>
- struct PairBaseHashTraits : GenericHashTraits<pair<typename FirstTraitsArg::TraitType, typename SecondTraitsArg::TraitType> > {
+ struct PairHashTraits : GenericHashTraits<pair<typename FirstTraitsArg::TraitType, typename SecondTraitsArg::TraitType> > {
typedef FirstTraitsArg FirstTraits;
typedef SecondTraitsArg SecondTraits;
typedef pair<typename FirstTraits::TraitType, typename SecondTraits::TraitType> TraitType;
- typedef PairHashTraits<typename FirstTraits::StorageTraits, typename SecondTraits::StorageTraits> StorageTraits;
-
static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
-
- static TraitType emptyValue()
- {
- return make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue());
- }
- };
-
- template<typename FirstTraits, typename SecondTraits>
- struct PairHashTraits : PairBaseHashTraits<FirstTraits, SecondTraits> {
- typedef pair<typename FirstTraits::TraitType, typename SecondTraits::TraitType> TraitType;
+ static TraitType emptyValue() { return make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
- static TraitType deletedValue()
- {
- return TraitType(FirstTraits::deletedValue(), SecondTraits::emptyValue());
- }
-
- static void assignDeletedValue(TraitType& location)
- {
- assignDeleted<typename FirstTraits::TraitType, FirstTraits>(location.first);
- location.second = SecondTraits::emptyValue();
- }
+ static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); }
+ static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
};
template<typename First, typename Second>
struct HashTraits<pair<First, Second> > : public PairHashTraits<HashTraits<First>, HashTraits<Second> > { };
- template<typename FirstTraits, typename SecondTraits>
- struct DeletedValueAssigner<PairHashTraits<FirstTraits, SecondTraits> >
- {
- static void assignDeletedValue(pair<typename FirstTraits::TraitType, typename SecondTraits::TraitType>& location)
- {
- PairHashTraits<FirstTraits, SecondTraits>::assignDeletedValue(location);
- }
- };
-
- template<typename First, typename Second>
- struct DeletedValueAssigner<HashTraits<pair<First, Second> > >
- {
- static void assignDeletedValue(pair<First, Second>& location)
- {
- HashTraits<pair<First, Second> >::assignDeletedValue(location);
- }
- };
-
- // hash functions and traits that are equivalent (for code sharing)
-
- template<typename HashArg, typename TraitsArg> struct HashKeyStorageTraits {
- typedef HashArg Hash;
- typedef TraitsArg Traits;
- };
- template<typename P> struct HashKeyStorageTraits<PtrHash<P*>, HashTraits<P*> > {
- typedef typename IntTypes<sizeof(P*)>::SignedType IntType;
- typedef IntHash<IntType> Hash;
- typedef HashTraits<IntType> Traits;
- };
- template<typename P> struct HashKeyStorageTraits<PtrHash<RefPtr<P> >, HashTraits<RefPtr<P> > > {
- typedef typename IntTypes<sizeof(P*)>::SignedType IntType;
- typedef IntHash<IntType> Hash;
- typedef HashTraits<IntType> Traits;
- };
-
} // namespace WTF
using WTF::HashTraits;
diff --git a/JavaScriptCore/wtf/ListHashSet.h b/JavaScriptCore/wtf/ListHashSet.h
index 3172943..2f75c33 100644
--- a/JavaScriptCore/wtf/ListHashSet.h
+++ b/JavaScriptCore/wtf/ListHashSet.h
@@ -1,6 +1,5 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * 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
@@ -34,7 +33,7 @@ namespace WTF {
// order - iterating it will always give back values in the order
// in which they are added.
- // In theory it would be possible to add prepend, insertAfter, insertBefore,
+ // In theory it would be possible to add prepend, insertAfter
// and an append that moves the element to the end even if already present,
// but unclear yet if these are needed.
@@ -91,10 +90,13 @@ namespace WTF {
const_iterator find(const ValueType&) const;
bool contains(const ValueType&) const;
- // the return value is a pair of an interator to the new value's location,
+ // the return value is a pair of an iterator to the new value's location,
// and a bool that is true if an new entry was added
pair<iterator, bool> add(const ValueType&);
+ pair<iterator, bool> insertBefore(const ValueType& beforeValue, const ValueType& newValue);
+ pair<iterator, bool> insertBefore(iterator it, const ValueType&);
+
void remove(const ValueType&);
void remove(iterator);
void clear();
@@ -102,6 +104,7 @@ namespace WTF {
private:
void unlinkAndDelete(Node*);
void appendNode(Node*);
+ void insertNodeBefore(Node* beforeNode, Node* newNode);
void deleteAllNodes();
iterator makeIterator(Node*);
const_iterator makeConstIterator(Node*) const;
@@ -309,7 +312,10 @@ namespace WTF {
const_iterator& operator--()
{
ASSERT(m_position != m_set->m_head);
- m_position = m_position->m_prev;
+ if (!m_position)
+ m_position = m_set->m_tail;
+ else
+ m_position = m_position->m_prev;
return *this;
}
@@ -381,7 +387,6 @@ namespace WTF {
std::swap(m_head, other.m_head);
std::swap(m_tail, other.m_tail);
m_allocator.swap(other.m_allocator);
- return *this;
}
template<typename T, typename U>
@@ -470,6 +475,23 @@ namespace WTF {
}
template<typename T, typename U>
+ pair<typename ListHashSet<T, U>::iterator, bool> ListHashSet<T, U>::insertBefore(iterator it, const ValueType& newValue)
+ {
+ typedef ListHashSetTranslator<ValueType, HashFunctions> Translator;
+ pair<typename ImplType::iterator, bool> result = m_impl.template add<ValueType, NodeAllocator*, Translator>(newValue, m_allocator.get());
+ if (result.second)
+ insertNodeBefore(it.node(), *result.first);
+ return std::make_pair(makeIterator(*result.first), result.second);
+
+ }
+
+ template<typename T, typename U>
+ pair<typename ListHashSet<T, U>::iterator, bool> ListHashSet<T, U>::insertBefore(const ValueType& beforeValue, const ValueType& newValue)
+ {
+ return insertBefore(find(beforeValue), newValue);
+ }
+
+ template<typename T, typename U>
inline void ListHashSet<T, U>::remove(iterator it)
{
if (it == end())
@@ -533,6 +555,22 @@ namespace WTF {
}
template<typename T, typename U>
+ void ListHashSet<T, U>::insertNodeBefore(Node* beforeNode, Node* newNode)
+ {
+ if (!beforeNode)
+ return appendNode(newNode);
+
+ newNode->m_next = beforeNode;
+ newNode->m_prev = beforeNode->m_prev;
+ if (beforeNode->m_prev)
+ beforeNode->m_prev->m_next = newNode;
+ beforeNode->m_prev = newNode;
+
+ if (!newNode->m_prev)
+ m_head = newNode;
+ }
+
+ template<typename T, typename U>
void ListHashSet<T, U>::deleteAllNodes()
{
if (!m_head)
diff --git a/JavaScriptCore/wtf/ListRefPtr.h b/JavaScriptCore/wtf/ListRefPtr.h
index 0f807b0..9f9a354 100644
--- a/JavaScriptCore/wtf/ListRefPtr.h
+++ b/JavaScriptCore/wtf/ListRefPtr.h
@@ -1,6 +1,5 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2005, 2006 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
@@ -36,9 +35,10 @@ namespace WTF {
// see comment in PassRefPtr.h for why this takes const reference
template <typename U> ListRefPtr(const PassRefPtr<U>& o) : RefPtr<T>(o) {}
- ~ListRefPtr() {
+ ~ListRefPtr()
+ {
RefPtr<T> reaper = this->release();
- while (reaper && reaper->refcount() == 1)
+ while (reaper && reaper->hasOneRef())
reaper = reaper->releaseNext(); // implicitly protects reaper->next, then derefs reaper
}
diff --git a/JavaScriptCore/wtf/Locker.h b/JavaScriptCore/wtf/Locker.h
new file mode 100644
index 0000000..9feec1f
--- /dev/null
+++ b/JavaScriptCore/wtf/Locker.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef Locker_h
+#define Locker_h
+
+#include <wtf/Noncopyable.h>
+
+namespace WTF {
+
+template <typename T> class Locker : Noncopyable {
+public:
+ Locker(T& lockable) : m_lockable(lockable) { m_lockable.lock(); }
+ ~Locker() { m_lockable.unlock(); }
+private:
+ T& m_lockable;
+};
+
+}
+
+using WTF::Locker;
+
+#endif
diff --git a/JavaScriptCore/wtf/MainThread.cpp b/JavaScriptCore/wtf/MainThread.cpp
new file mode 100644
index 0000000..6fe3021
--- /dev/null
+++ b/JavaScriptCore/wtf/MainThread.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MainThread.h"
+
+#include "Threading.h"
+#include "Vector.h"
+
+namespace WTF {
+
+struct FunctionWithContext {
+ MainThreadFunction* function;
+ void* context;
+ ThreadCondition* syncFlag;
+
+ FunctionWithContext(MainThreadFunction* function = 0, void* context = 0, ThreadCondition* syncFlag = 0)
+ : function(function)
+ , context(context)
+ , syncFlag(syncFlag)
+ {
+ }
+};
+
+typedef Vector<FunctionWithContext> FunctionQueue;
+
+static bool callbacksPaused; // This global varialble is only accessed from main thread.
+
+Mutex& mainThreadFunctionQueueMutex()
+{
+ static Mutex staticMutex;
+ return staticMutex;
+}
+
+static FunctionQueue& functionQueue()
+{
+ static FunctionQueue staticFunctionQueue;
+ return staticFunctionQueue;
+}
+
+#if !PLATFORM(WIN)
+void initializeMainThread()
+{
+ mainThreadFunctionQueueMutex();
+}
+#endif
+
+void dispatchFunctionsFromMainThread()
+{
+ ASSERT(isMainThread());
+
+ if (callbacksPaused)
+ return;
+
+ FunctionQueue queueCopy;
+ {
+ MutexLocker locker(mainThreadFunctionQueueMutex());
+ queueCopy.swap(functionQueue());
+ }
+
+ for (unsigned i = 0; i < queueCopy.size(); ++i) {
+ FunctionWithContext& invocation = queueCopy[i];
+ invocation.function(invocation.context);
+ if (invocation.syncFlag)
+ invocation.syncFlag->signal();
+ }
+}
+
+void callOnMainThread(MainThreadFunction* function, void* context)
+{
+ ASSERT(function);
+
+ {
+ MutexLocker locker(mainThreadFunctionQueueMutex());
+ functionQueue().append(FunctionWithContext(function, context));
+ }
+
+ scheduleDispatchFunctionsOnMainThread();
+}
+
+void callOnMainThreadAndWait(MainThreadFunction* function, void* context)
+{
+ ASSERT(function);
+
+ if (isMainThread()) {
+ function(context);
+ return;
+ }
+
+ ThreadCondition syncFlag;
+ Mutex conditionMutex;
+
+ {
+ MutexLocker locker(mainThreadFunctionQueueMutex());
+ functionQueue().append(FunctionWithContext(function, context, &syncFlag));
+ conditionMutex.lock();
+ }
+
+ scheduleDispatchFunctionsOnMainThread();
+ syncFlag.wait(conditionMutex);
+}
+
+void setMainThreadCallbacksPaused(bool paused)
+{
+ ASSERT(isMainThread());
+
+ if (callbacksPaused == paused)
+ return;
+
+ callbacksPaused = paused;
+
+ if (!callbacksPaused)
+ scheduleDispatchFunctionsOnMainThread();
+}
+
+} // namespace WTF
diff --git a/JavaScriptCore/wtf/MainThread.h b/JavaScriptCore/wtf/MainThread.h
new file mode 100644
index 0000000..953b986
--- /dev/null
+++ b/JavaScriptCore/wtf/MainThread.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MainThread_h
+#define MainThread_h
+
+namespace WTF {
+
+class Mutex;
+
+typedef void MainThreadFunction(void*);
+
+void callOnMainThread(MainThreadFunction*, void* context);
+void callOnMainThreadAndWait(MainThreadFunction*, void* context);
+
+void setMainThreadCallbacksPaused(bool paused);
+
+// Must be called from the main thread (Darwin is an exception to this rule).
+void initializeMainThread();
+
+// These functions are internal to the callOnMainThread implementation.
+void dispatchFunctionsFromMainThread();
+void scheduleDispatchFunctionsOnMainThread();
+Mutex& mainThreadFunctionQueueMutex();
+
+} // namespace WTF
+
+using WTF::callOnMainThread;
+using WTF::setMainThreadCallbacksPaused;
+
+#endif // MainThread_h
diff --git a/JavaScriptCore/wtf/MathExtras.h b/JavaScriptCore/wtf/MathExtras.h
index 75991f0..cfe5468 100644
--- a/JavaScriptCore/wtf/MathExtras.h
+++ b/JavaScriptCore/wtf/MathExtras.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 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
@@ -30,10 +30,15 @@
#include <stdlib.h>
#include <time.h>
-#if PLATFORM(SOLARIS) && COMPILER(GCC)
+#if PLATFORM(SOLARIS)
#include <ieeefp.h>
#endif
+#if PLATFORM(OPENBSD)
+#include <sys/types.h>
+#include <machine/ieee.h>
+#endif
+
#if COMPILER(MSVC)
#include <xmath.h>
@@ -61,7 +66,16 @@ const double piOverFourDouble = M_PI_4;
const float piOverFourFloat = static_cast<float>(M_PI_4);
#endif
-#if PLATFORM(SOLARIS) && COMPILER(GCC)
+#if PLATFORM(DARWIN)
+
+// Work around a bug in the Mac OS X libc where ceil(-0.1) return +0.
+inline double wtf_ceil(double x) { return copysign(ceil(x), x); }
+
+#define ceil(x) wtf_ceil(x)
+
+#endif
+
+#if PLATFORM(SOLARIS)
#ifndef isfinite
inline bool isfinite(double x) { return finite(x) && !isnand(x); }
@@ -75,6 +89,17 @@ inline bool signbit(double x) { return x < 0.0; } // FIXME: Wrong for negative 0
#endif
+#if PLATFORM(OPENBSD)
+
+#ifndef isfinite
+inline bool isfinite(double x) { return finite(x); }
+#endif
+#ifndef signbit
+inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x; return p->dbl_sign; }
+#endif
+
+#endif
+
#if COMPILER(MSVC)
inline bool isinf(double num) { return !_finite(num) && !_isnan(num); }
@@ -95,9 +120,9 @@ inline int isfinite(double x) { return _finite(x); }
// Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN instead of specific values.
inline double wtf_atan2(double x, double y)
{
- static double posInf = std::numeric_limits<double>::infinity();
- static double negInf = -std::numeric_limits<double>::infinity();
- static double nan = std::numeric_limits<double>::quiet_NaN();
+ double posInf = std::numeric_limits<double>::infinity();
+ double negInf = -std::numeric_limits<double>::infinity();
+ double nan = std::numeric_limits<double>::quiet_NaN();
double result = nan;
diff --git a/JavaScriptCore/wtf/MessageQueue.h b/JavaScriptCore/wtf/MessageQueue.h
new file mode 100644
index 0000000..481211d
--- /dev/null
+++ b/JavaScriptCore/wtf/MessageQueue.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MessageQueue_h
+#define MessageQueue_h
+
+#include <wtf/Assertions.h>
+#include <wtf/Deque.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Threading.h>
+
+namespace WTF {
+
+ template<typename DataType>
+ class MessageQueue : Noncopyable {
+ public:
+ MessageQueue() : m_killed(false) {}
+
+ void append(const DataType&);
+ void prepend(const DataType&);
+ bool waitForMessage(DataType&);
+ void kill();
+
+ bool tryGetMessage(DataType&);
+ bool killed() const;
+
+ // The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time.
+ bool isEmpty();
+
+ private:
+ mutable Mutex m_mutex;
+ ThreadCondition m_condition;
+ Deque<DataType> m_queue;
+ bool m_killed;
+ };
+
+ template<typename DataType>
+ inline void MessageQueue<DataType>::append(const DataType& message)
+ {
+ MutexLocker lock(m_mutex);
+ m_queue.append(message);
+ m_condition.signal();
+ }
+
+ template<typename DataType>
+ inline void MessageQueue<DataType>::prepend(const DataType& message)
+ {
+ MutexLocker lock(m_mutex);
+ m_queue.prepend(message);
+ m_condition.signal();
+ }
+
+ template<typename DataType>
+ inline bool MessageQueue<DataType>::waitForMessage(DataType& result)
+ {
+ MutexLocker lock(m_mutex);
+
+ while (!m_killed && m_queue.isEmpty())
+ m_condition.wait(m_mutex);
+
+ if (m_killed)
+ return false;
+
+ ASSERT(!m_queue.isEmpty());
+ result = m_queue.first();
+ m_queue.removeFirst();
+ return true;
+ }
+
+ template<typename DataType>
+ inline bool MessageQueue<DataType>::tryGetMessage(DataType& result)
+ {
+ MutexLocker lock(m_mutex);
+ if (m_killed)
+ return false;
+ if (m_queue.isEmpty())
+ return false;
+
+ result = m_queue.first();
+ m_queue.removeFirst();
+ return true;
+ }
+
+ template<typename DataType>
+ inline bool MessageQueue<DataType>::isEmpty()
+ {
+ MutexLocker lock(m_mutex);
+ if (m_killed)
+ return true;
+ return m_queue.isEmpty();
+ }
+
+ template<typename DataType>
+ inline void MessageQueue<DataType>::kill()
+ {
+ MutexLocker lock(m_mutex);
+ m_killed = true;
+ m_condition.broadcast();
+ }
+
+ template<typename DataType>
+ inline bool MessageQueue<DataType>::killed() const
+ {
+ MutexLocker lock(m_mutex);
+ return m_killed;
+ }
+}
+
+using WTF::MessageQueue;
+
+#endif // MessageQueue_h
diff --git a/JavaScriptCore/wtf/Noncopyable.h b/JavaScriptCore/wtf/Noncopyable.h
index 358b0a7..f241c7c 100644
--- a/JavaScriptCore/wtf/Noncopyable.h
+++ b/JavaScriptCore/wtf/Noncopyable.h
@@ -1,4 +1,3 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006 Apple Computer, Inc.
*
diff --git a/JavaScriptCore/wtf/NotFound.h b/JavaScriptCore/wtf/NotFound.h
new file mode 100644
index 0000000..f0bb866
--- /dev/null
+++ b/JavaScriptCore/wtf/NotFound.h
@@ -0,0 +1,35 @@
+/*
+ * 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 NotFound_h
+#define NotFound_h
+
+namespace WTF {
+
+ const size_t notFound = static_cast<size_t>(-1);
+
+} // namespace WTF
+
+#endif // NotFound_h
diff --git a/JavaScriptCore/wtf/OwnArrayPtr.h b/JavaScriptCore/wtf/OwnArrayPtr.h
index 2b6c7dc..344f813 100644
--- a/JavaScriptCore/wtf/OwnArrayPtr.h
+++ b/JavaScriptCore/wtf/OwnArrayPtr.h
@@ -1,4 +1,3 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006 Apple Computer, Inc.
*
diff --git a/JavaScriptCore/wtf/OwnPtr.h b/JavaScriptCore/wtf/OwnPtr.h
index b46969d..969950f 100644
--- a/JavaScriptCore/wtf/OwnPtr.h
+++ b/JavaScriptCore/wtf/OwnPtr.h
@@ -1,4 +1,3 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
*
diff --git a/JavaScriptCore/wtf/PassRefPtr.h b/JavaScriptCore/wtf/PassRefPtr.h
index 25b9906..ca8f2cb 100644
--- a/JavaScriptCore/wtf/PassRefPtr.h
+++ b/JavaScriptCore/wtf/PassRefPtr.h
@@ -1,4 +1,3 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
*
diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h
index 655361b..80a7bf1 100644
--- a/JavaScriptCore/wtf/Platform.h
+++ b/JavaScriptCore/wtf/Platform.h
@@ -1,4 +1,3 @@
-/* -*- mode: c++; c-basic-offset: 4 -*- */
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
@@ -21,7 +20,7 @@
* 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.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef WTF_Platform_h
@@ -50,6 +49,14 @@
#define WTF_PLATFORM_WIN_OS 1
#endif
+/* PLATFORM(WIN_CE) */
+/* Operating system level dependencies for Windows CE that should be used */
+/* regardless of operating environment */
+/* Note that for this platform PLATFORM(WIN_OS) is also defined. */
+#if defined(_WIN32_WCE)
+#define WTF_PLATFORM_WIN_CE 1
+#endif
+
/* PLATFORM(FREEBSD) */
/* Operating system level dependencies for FreeBSD-like systems that */
/* should be used regardless of operating environment */
@@ -57,6 +64,13 @@
#define WTF_PLATFORM_FREEBSD 1
#endif
+/* PLATFORM(OPENBSD) */
+/* Operating system level dependencies for OpenBSD systems that */
+/* should be used regardless of operating environment */
+#ifdef __OpenBSD__
+#define WTF_PLATFORM_OPENBSD 1
+#endif
+
/* PLATFORM(SOLARIS) */
/* Operating system level dependencies for Solaris that should be used */
/* regardless of operating environment */
@@ -79,11 +93,14 @@
/* Operating environments */
+/* PLATFORM(CHROMIUM) */
/* PLATFORM(QT) */
/* PLATFORM(GTK) */
/* PLATFORM(MAC) */
/* PLATFORM(WIN) */
-#if defined(BUILDING_QT__)
+#if defined(BUILDING_CHROMIUM__)
+#define WTF_PLATFORM_CHROMIUM 1
+#elif defined(BUILDING_QT__)
#define WTF_PLATFORM_QT 1
/* PLATFORM(KDE) */
@@ -103,15 +120,21 @@
/* Graphics engines */
-/* PLATFORM(CG) */
-/* PLATFORM(CAIRO) */
+/* PLATFORM(CG) and PLATFORM(CI) */
#if PLATFORM(MAC)
#define WTF_PLATFORM_CG 1
#define WTF_PLATFORM_CI 1
-#elif !PLATFORM(QT) && !PLATFORM(WX)
-#define WTF_PLATFORM_CAIRO 1
#endif
+/* PLATFORM(SKIA) */
+#if PLATFORM(CHROMIUM)
+#define WTF_PLATFORM_SKIA 1
+#endif
+
+/* Makes PLATFORM(WIN) default to PLATFORM(CAIRO) */
+#if !PLATFORM(MAC) && !PLATFORM(QT) && !PLATFORM(WX)
+#define WTF_PLATFORM_CAIRO 1
+#endif
#ifdef __S60__
// we are cross-compiling, it is not really windows
@@ -123,6 +146,8 @@
#endif
#ifdef ANDROID
+#define WTF_PLATFORM_ANDROID 1
+#define WTF_PLATFORM_LINUX 1
//due to pthread code in collector.cpp, we need PLATFORM(DARWIN)
//#undef WTF_PLATFORM_DARWIN
#undef WTF_PLATFORM_MAC
@@ -131,11 +156,17 @@
#undef WTF_PLATFORM_CG
#undef WTF_PLATFORM_CI
#undef WTF_PLATFORM_CAIRO
+#define WTF_USE_PTHREADS 1
#define WTF_PLATFORM_SGL 1
#define WTF_PLATFORM_UNIX 1
#define USE_SYSTEM_MALLOC 1
+#define ENABLE_MAC_JAVA_BRIDGE 1
+#define LOG_DISABLED 1
+// Prevents Webkit from drawing the caret in textfields and textareas
+// This prevents unnecessary invals.
+#define ENABLE_TEXT_CARET 0
#endif // ANDROID
/* CPU */
@@ -159,13 +190,14 @@
#define WTF_PLATFORM_BIG_ENDIAN 1
#endif
+/* PLATFORM(ARM) */
#if defined(arm) \
|| defined(__arm__)
#define WTF_PLATFORM_ARM 1
#if defined(__ARMEB__)
#define WTF_PLATFORM_BIG_ENDIAN 1
-#elif !defined(__ARM_EABI__) && !defined(__ARMEB__)
-#if !defined(ANDROID) || !defined(__VFP_FP__)
+#elif !defined(__ARM_EABI__) && !defined(__ARMEB__) && !defined(__VFP_FP__)
+#if !defined(ANDROID)
#define WTF_PLATFORM_MIDDLE_ENDIAN 1
#endif
#endif
@@ -190,6 +222,12 @@
#define WTF_PLATFORM_X86_64 1
#endif
+/* PLATFORM(SPARC64) */
+#if defined(__sparc64__)
+#define WTF_PLATFORM_SPARC64 1
+#define WTF_PLATFORM_BIG_ENDIAN 1
+#endif
+
/* Compiler */
/* COMPILER(MSVC) */
@@ -205,6 +243,11 @@
#define WTF_COMPILER_GCC 1
#endif
+/* COMPILER(MINGW) */
+#if defined(MINGW) || defined(__MINGW32__)
+#define WTF_COMPILER_MINGW 1
+#endif
+
/* COMPILER(BORLAND) */
/* not really fully supported - is this relevant any more? */
#if defined(__BORLANDC__)
@@ -217,16 +260,17 @@
#define WTF_COMPILER_CYGWIN 1
#endif
-/* multiple threads only supported on Mac for now */
-#if PLATFORM(MAC) || PLATFORM(WIN)
-#define WTF_USE_MULTIPLE_THREADS 1
+#if (PLATFORM(MAC) || PLATFORM(WIN)) && !defined(ENABLE_JSC_MULTIPLE_THREADS)
+#define ENABLE_JSC_MULTIPLE_THREADS 1
#endif
-/* for Unicode, KDE uses Qt, everything else uses ICU */
+/* for Unicode, KDE uses Qt */
#if PLATFORM(KDE) || PLATFORM(QT)
#define WTF_USE_QT4_UNICODE 1
#elif PLATFORM(SYMBIAN)
#define WTF_USE_SYMBIAN_UNICODE 1
+#elif PLATFORM(GTK)
+/* The GTK+ Unicode backend is configurable */
#else
#define WTF_USE_ICU_UNICODE 1
#endif
@@ -234,6 +278,16 @@
#if PLATFORM(MAC)
#define WTF_PLATFORM_CF 1
#define WTF_USE_PTHREADS 1
+#if !defined(ENABLE_MAC_JAVA_BRIDGE)
+#define ENABLE_MAC_JAVA_BRIDGE 1
+#endif
+#if !defined(ENABLE_DASHBOARD_SUPPORT)
+#define ENABLE_DASHBOARD_SUPPORT 1
+#endif
+#define HAVE_READLINE 1
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+#define HAVE_DTRACE 1
+#endif
#endif
#if PLATFORM(WIN)
@@ -245,10 +299,52 @@
#define WTF_USE_PTHREADS 1
#endif
-#if PLATFORM(QT)
-#define USE_SYSTEM_MALLOC 1
+#if PLATFORM(GTK)
+#if HAVE(PTHREAD_H)
+#define WTF_USE_PTHREADS 1
+#endif
+#endif
+
+#if PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(CHROMIUM)
+#define HAVE_ACCESSIBILITY 1
+#endif
+
+#if COMPILER(GCC)
+#define HAVE_COMPUTED_GOTO 1
+#endif
+
+#if PLATFORM(DARWIN)
+
+#define HAVE_ERRNO_H 1
+#define HAVE_MMAP 1
+#define HAVE_MERGESORT 1
+#define HAVE_SBRK 1
+#define HAVE_STRINGS_H 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYS_TIME_H 1
+#define HAVE_SYS_TIMEB_H 1
+
+#elif PLATFORM(WIN_OS)
+
+#define HAVE_FLOAT_H 1
+#define HAVE_SYS_TIMEB_H 1
+#define HAVE_VIRTUALALLOC 1
+
+#else
+
+/* FIXME: is this actually used or do other platforms generate their own config.h? */
+
+#define HAVE_ERRNO_H 1
+#define HAVE_MMAP 1
+#define HAVE_SBRK 1
+#define HAVE_STRINGS_H 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYS_TIME_H 1
+
#endif
+/* ENABLE macro defaults */
+
#if !defined(ENABLE_ICONDATABASE)
#define ENABLE_ICONDATABASE 1
#endif
@@ -257,8 +353,84 @@
#define ENABLE_DATABASE 1
#endif
+#if !defined(ENABLE_JAVASCRIPT_DEBUGGER)
+#define ENABLE_JAVASCRIPT_DEBUGGER 1
+#endif
+
#if !defined(ENABLE_FTPDIR)
#define ENABLE_FTPDIR 1
#endif
+#if !defined(ENABLE_DASHBOARD_SUPPORT)
+#define ENABLE_DASHBOARD_SUPPORT 0
+#endif
+
+#if !defined(ENABLE_MAC_JAVA_BRIDGE)
+#define ENABLE_MAC_JAVA_BRIDGE 0
+#endif
+
+#if !defined(ENABLE_NETSCAPE_PLUGIN_API)
+#define ENABLE_NETSCAPE_PLUGIN_API 1
+#endif
+
+#if !defined(ENABLE_OPCODE_STATS)
+#define ENABLE_OPCODE_STATS 0
+#endif
+
+#if !defined(ENABLE_CODEBLOCK_SAMPLING)
+#define ENABLE_CODEBLOCK_SAMPLING 0
+#endif
+
+#if ENABLE(CODEBLOCK_SAMPLING) && !defined(ENABLE_OPCODE_SAMPLING)
+#define ENABLE_OPCODE_SAMPLING 1
+#endif
+
+#if !defined(ENABLE_OPCODE_SAMPLING)
+#define ENABLE_OPCODE_SAMPLING 0
+#endif
+
+#if !defined(ENABLE_GEOLOCATION)
+#define ENABLE_GEOLOCATION 0
+#endif
+
+#if !defined(ENABLE_TEXT_CARET)
+#define ENABLE_TEXT_CARET 1
+#endif
+
+// ANDROID addition: allow web archive to be disabled
+#if !defined(ENABLE_ARCHIVE)
+#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
+#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))
+#define ENABLE_WREC 1
+#endif
+
+#if ENABLE(CTI) || ENABLE(WREC)
+#define ENABLE_MASM 1
+#endif
+
+#if !defined(ENABLE_PAN_SCROLLING) && (PLATFORM(WIN) || PLATFORM(CHROMIUM) || (PLATFORM(WX) && PLATFORM(WIN_OS)))
+#define ENABLE_PAN_SCROLLING 1
+#endif
+
+/* Use the QtXmlStreamReader implementation for XMLTokenizer */
+#if PLATFORM(QT)
+#if !ENABLE(XSLT)
+#define WTF_USE_QXMLSTREAM 1
+#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
+#endif
+
#endif /* WTF_Platform_h */
diff --git a/JavaScriptCore/wtf/RefCounted.h b/JavaScriptCore/wtf/RefCounted.h
index dc93b11..2dd5b2a 100644
--- a/JavaScriptCore/wtf/RefCounted.h
+++ b/JavaScriptCore/wtf/RefCounted.h
@@ -26,9 +26,30 @@
namespace WTF {
-template<class T> class RefCounted : Noncopyable {
+// This base class holds the non-template methods and attributes.
+// The RefCounted class inherits from it reducing the template bloat
+// generated by the compiler (technique called template hoisting).
+class RefCountedBase : Noncopyable {
public:
- RefCounted(int initialRefCount = 0)
+ void ref()
+ {
+ ASSERT(!m_deletionHasBegun);
+ ++m_refCount;
+ }
+
+ bool hasOneRef() const
+ {
+ ASSERT(!m_deletionHasBegun);
+ return m_refCount == 1;
+ }
+
+ int refCount() const
+ {
+ return m_refCount;
+ }
+
+protected:
+ RefCountedBase(int initialRefCount)
: m_refCount(initialRefCount)
#ifndef NDEBUG
, m_deletionHasBegun(false)
@@ -36,13 +57,10 @@ public:
{
}
- void ref()
- {
- ASSERT(!m_deletionHasBegun);
- ++m_refCount;
- }
+ ~RefCountedBase() {}
- void deref()
+ // Returns whether the pointer should be freed or not.
+ bool derefBase()
{
ASSERT(!m_deletionHasBegun);
ASSERT(m_refCount > 0);
@@ -50,20 +68,11 @@ public:
#ifndef NDEBUG
m_deletionHasBegun = true;
#endif
- delete static_cast<T*>(this);
- } else
- --m_refCount;
- }
+ return true;
+ }
- bool hasOneRef()
- {
- ASSERT(!m_deletionHasBegun);
- return m_refCount == 1;
- }
-
- int refCount() const
- {
- return m_refCount;
+ --m_refCount;
+ return false;
}
private:
@@ -73,6 +82,24 @@ private:
#endif
};
+
+template<class T> class RefCounted : public RefCountedBase {
+public:
+ RefCounted(int initialRefCount = 1)
+ : RefCountedBase(initialRefCount)
+ {
+ }
+
+ void deref()
+ {
+ if (derefBase())
+ delete static_cast<T*>(this);
+ }
+
+protected:
+ ~RefCounted() {}
+};
+
} // namespace WTF
using WTF::RefCounted;
diff --git a/JavaScriptCore/wtf/RefCountedLeakCounter.cpp b/JavaScriptCore/wtf/RefCountedLeakCounter.cpp
new file mode 100644
index 0000000..80922d3
--- /dev/null
+++ b/JavaScriptCore/wtf/RefCountedLeakCounter.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 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.
+ *
+ */
+
+#include "config.h"
+#include "RefCountedLeakCounter.h"
+
+#include <wtf/HashCountedSet.h>
+
+namespace WTF {
+
+#ifdef NDEBUG
+
+void RefCountedLeakCounter::suppressMessages(const char*) { }
+void RefCountedLeakCounter::cancelMessageSuppression(const char*) { }
+
+RefCountedLeakCounter::RefCountedLeakCounter(const char*) { }
+RefCountedLeakCounter::~RefCountedLeakCounter() { }
+
+void RefCountedLeakCounter::increment() { }
+void RefCountedLeakCounter::decrement() { }
+
+#else
+
+#define LOG_CHANNEL_PREFIX Log
+static WTFLogChannel LogRefCountedLeaks = { 0x00000000, "", WTFLogChannelOn };
+
+typedef HashCountedSet<const char*, PtrHash<const char*> > ReasonSet;
+static ReasonSet* leakMessageSuppressionReasons;
+
+void RefCountedLeakCounter::suppressMessages(const char* reason)
+{
+ if (!leakMessageSuppressionReasons)
+ leakMessageSuppressionReasons = new ReasonSet;
+ leakMessageSuppressionReasons->add(reason);
+}
+
+void RefCountedLeakCounter::cancelMessageSuppression(const char* reason)
+{
+ ASSERT(leakMessageSuppressionReasons);
+ ASSERT(leakMessageSuppressionReasons->contains(reason));
+ leakMessageSuppressionReasons->remove(reason);
+}
+
+RefCountedLeakCounter::RefCountedLeakCounter(const char* description)
+ : m_description(description)
+{
+}
+
+RefCountedLeakCounter::~RefCountedLeakCounter()
+{
+ static bool loggedSuppressionReason;
+ if (m_count) {
+ if (!leakMessageSuppressionReasons || leakMessageSuppressionReasons->isEmpty())
+ LOG(RefCountedLeaks, "LEAK: %u %s", m_count, m_description);
+ else if (!loggedSuppressionReason) {
+ // This logs only one reason. Later we could change it so we log all the reasons.
+ LOG(RefCountedLeaks, "No leak checking done: %s", leakMessageSuppressionReasons->begin()->first);
+ loggedSuppressionReason = true;
+ }
+ }
+}
+
+void RefCountedLeakCounter::increment()
+{
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ atomicIncrement(&m_count);
+#else
+ ++m_count;
+#endif
+}
+
+void RefCountedLeakCounter::decrement()
+{
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ atomicDecrement(&m_count);
+#else
+ --m_count;
+#endif
+}
+
+#endif
+
+} // namespace WTF
diff --git a/JavaScriptCore/wtf/RefCountedLeakCounter.h b/JavaScriptCore/wtf/RefCountedLeakCounter.h
new file mode 100644
index 0000000..57cc283
--- /dev/null
+++ b/JavaScriptCore/wtf/RefCountedLeakCounter.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 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 RefCountedLeakCounter_h
+#define RefCountedLeakCounter_h
+
+#include "Assertions.h"
+#include "Threading.h"
+
+namespace WTF {
+
+ struct RefCountedLeakCounter {
+ static void suppressMessages(const char*);
+ static void cancelMessageSuppression(const char*);
+
+ explicit RefCountedLeakCounter(const char* description);
+ ~RefCountedLeakCounter();
+
+ void increment();
+ void decrement();
+
+#ifndef NDEBUG
+ private:
+ volatile int m_count;
+ const char* m_description;
+#endif
+ };
+
+} // namespace WTF
+
+#endif
diff --git a/JavaScriptCore/wtf/RefPtr.h b/JavaScriptCore/wtf/RefPtr.h
index d43a071..78bd257 100644
--- a/JavaScriptCore/wtf/RefPtr.h
+++ b/JavaScriptCore/wtf/RefPtr.h
@@ -1,6 +1,5 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * 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
@@ -31,9 +30,11 @@ namespace WTF {
template <typename T> class PassRefPtr;
+ enum HashTableDeletedValueType { HashTableDeletedValue };
+
template <typename T> class RefPtr {
public:
- RefPtr() : m_ptr(0) {}
+ RefPtr() : m_ptr(0) { }
RefPtr(T* ptr) : m_ptr(ptr) { if (ptr) ptr->ref(); }
RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { if (T* ptr = m_ptr) ptr->ref(); }
// see comment in PassRefPtr.h for why this takes const reference
@@ -42,6 +43,10 @@ namespace WTF {
// Special constructor for cases where we overwrite an object in place.
RefPtr(PlacementNewAdoptType) { }
+ // Hash table deleted values, which are only constructed and never copied or destroyed.
+ RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
+ bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
+
~RefPtr() { if (T* ptr = m_ptr) ptr->deref(); }
template <typename U> RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { if (T* ptr = m_ptr) ptr->ref(); }
@@ -52,7 +57,7 @@ namespace WTF {
PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; }
T& operator*() const { return *m_ptr; }
- ALWAYS_INLINE T *operator->() const { return m_ptr; }
+ ALWAYS_INLINE T* operator->() const { return m_ptr; }
bool operator!() const { return !m_ptr; }
@@ -69,6 +74,8 @@ namespace WTF {
void swap(RefPtr&);
private:
+ static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
+
T* m_ptr;
};
diff --git a/JavaScriptCore/wtf/RefPtrHashMap.h b/JavaScriptCore/wtf/RefPtrHashMap.h
index 0515a24..1cbebb4 100644
--- a/JavaScriptCore/wtf/RefPtrHashMap.h
+++ b/JavaScriptCore/wtf/RefPtrHashMap.h
@@ -1,6 +1,5 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * 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
@@ -24,14 +23,30 @@ namespace WTF {
// This specialization is a direct copy of HashMap, with overloaded functions
// to allow for lookup by pointer instead of RefPtr, avoiding ref-count churn.
- // FIXME: Is there a better way to do this that doesn't just copy HashMap?
+ // FIXME: Find a better way that doesn't require an entire copy of the HashMap template.
+ template<typename RawKeyType, typename ValueType, typename ValueTraits, typename HashFunctions>
+ struct RefPtrHashMapRawKeyTranslator {
+ typedef typename ValueType::first_type KeyType;
+ typedef typename ValueType::second_type MappedType;
+ typedef typename ValueTraits::FirstTraits KeyTraits;
+ typedef typename ValueTraits::SecondTraits MappedTraits;
+
+ static unsigned hash(RawKeyType key) { return HashFunctions::hash(key); }
+ static bool equal(const KeyType& a, RawKeyType b) { return HashFunctions::equal(a, b); }
+ static void translate(ValueType& location, RawKeyType key, const MappedType& mapped)
+ {
+ location.first = key;
+ location.second = mapped;
+ }
+ };
+
template<typename T, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
class HashMap<RefPtr<T>, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> {
private:
typedef KeyTraitsArg KeyTraits;
typedef MappedTraitsArg MappedTraits;
- typedef PairBaseHashTraits<KeyTraits, MappedTraits> ValueTraits;
+ typedef PairHashTraits<KeyTraits, MappedTraits> ValueTraits;
public:
typedef typename KeyTraits::TraitType KeyType;
@@ -42,28 +57,16 @@ namespace WTF {
private:
typedef HashArg HashFunctions;
- typedef typename HashKeyStorageTraits<HashFunctions, KeyTraits>::Hash StorageHashFunctions;
-
- typedef typename HashKeyStorageTraits<HashFunctions, KeyTraits>::Traits KeyStorageTraits;
- typedef typename MappedTraits::StorageTraits MappedStorageTraits;
- typedef PairHashTraits<KeyStorageTraits, MappedStorageTraits> ValueStorageTraits;
+ typedef HashTable<KeyType, ValueType, PairFirstExtractor<ValueType>,
+ HashFunctions, ValueTraits, KeyTraits> HashTableType;
- typedef typename KeyStorageTraits::TraitType KeyStorageType;
- typedef typename MappedStorageTraits::TraitType MappedStorageType;
- typedef typename ValueStorageTraits::TraitType ValueStorageType;
-
- typedef HashTable<KeyStorageType, ValueStorageType, PairFirstExtractor<ValueStorageType>,
- StorageHashFunctions, ValueStorageTraits, KeyStorageTraits> HashTableType;
+ typedef RefPtrHashMapRawKeyTranslator<RawKeyType, ValueType, ValueTraits, HashFunctions>
+ RawKeyTranslator;
public:
typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
- HashMap();
- HashMap(const HashMap&);
- HashMap& operator=(const HashMap&);
- ~HashMap();
-
void swap(HashMap&);
int size() const;
@@ -84,6 +87,7 @@ namespace WTF {
bool contains(RawKeyType) const;
MappedType get(const KeyType&) const;
MappedType get(RawKeyType) const;
+ MappedType inlineGet(RawKeyType) const;
// replaces value but not key if key is already present
// return value is a pair of the iterator to the key location,
@@ -108,57 +112,17 @@ namespace WTF {
private:
pair<iterator, bool> inlineAdd(const KeyType&, const MappedType&);
pair<iterator, bool> inlineAdd(RawKeyType, const MappedType&);
- void refAll();
- void derefAll();
HashTableType m_impl;
};
template<typename T, typename U, typename V, typename W, typename X>
- inline void HashMap<RefPtr<T>, U, V, W, X>::refAll()
- {
- HashTableRefCounter<HashTableType, ValueTraits>::refAll(m_impl);
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
- inline void HashMap<RefPtr<T>, U, V, W, X>::derefAll()
- {
- HashTableRefCounter<HashTableType, ValueTraits>::derefAll(m_impl);
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
- inline HashMap<RefPtr<T>, U, V, W, X>::HashMap()
- {
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
- inline HashMap<RefPtr<T>, U, V, W, X>::HashMap(const HashMap& other)
- : m_impl(other.m_impl)
- {
- refAll();
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
- inline HashMap<RefPtr<T>, U, V, W, X>& HashMap<RefPtr<T>, U, V, W, X>::operator=(const HashMap& other)
- {
- HashMap tmp(other);
- swap(tmp);
- return *this;
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
inline void HashMap<RefPtr<T>, U, V, W, X>::swap(HashMap& other)
{
m_impl.swap(other.m_impl);
}
template<typename T, typename U, typename V, typename W, typename X>
- inline HashMap<RefPtr<T>, U, V, W, X>::~HashMap()
- {
- derefAll();
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
inline int HashMap<RefPtr<T>, U, V, W, X>::size() const
{
return m_impl.size();
@@ -203,45 +167,44 @@ namespace WTF {
template<typename T, typename U, typename V, typename W, typename X>
inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::find(const KeyType& key)
{
- return m_impl.find(*(const KeyStorageType*)&key);
+ return m_impl.find(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::find(RawKeyType key)
{
- return m_impl.find(*(const KeyStorageType*)&key);
+ return m_impl.template find<RawKeyType, RawKeyTranslator>(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::find(const KeyType& key) const
{
- return m_impl.find(*(const KeyStorageType*)&key);
+ return m_impl.find(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::find(RawKeyType key) const
{
- return m_impl.find(*(const KeyStorageType*)&key);
+ return m_impl.template find<RawKeyType, RawKeyTranslator>(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline bool HashMap<RefPtr<T>, U, V, W, X>::contains(const KeyType& key) const
{
- return m_impl.contains(*(const KeyStorageType*)&key);
+ return m_impl.contains(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline bool HashMap<RefPtr<T>, U, V, W, X>::contains(RawKeyType key) const
{
- return m_impl.contains(*(const KeyStorageType*)&key);
+ return m_impl.template contains<RawKeyType, RawKeyTranslator>(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
HashMap<RefPtr<T>, U, V, W, X>::inlineAdd(const KeyType& key, const MappedType& mapped)
{
- const bool canReplaceDeletedKey = !KeyTraits::needsDestruction || KeyStorageTraits::needsDestruction;
- typedef HashMapTranslator<canReplaceDeletedKey, ValueType, ValueTraits, ValueStorageTraits, HashFunctions> TranslatorType;
+ typedef HashMapTranslator<ValueType, ValueTraits, HashFunctions> TranslatorType;
return m_impl.template add<KeyType, MappedType, TranslatorType>(key, mapped);
}
@@ -249,7 +212,7 @@ namespace WTF {
inline pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
HashMap<RefPtr<T>, U, V, W, X>::inlineAdd(RawKeyType key, const MappedType& mapped)
{
- return inlineAdd(*(const KeyType*)&key, mapped);
+ return m_impl.template add<RawKeyType, MappedType, RawKeyTranslator>(key, mapped);
}
template<typename T, typename U, typename V, typename W, typename X>
@@ -257,9 +220,10 @@ namespace WTF {
HashMap<RefPtr<T>, U, V, W, X>::set(const KeyType& key, const MappedType& mapped)
{
pair<iterator, bool> result = inlineAdd(key, mapped);
- if (!result.second)
+ if (!result.second) {
// add call above didn't change anything, so set the mapped value
result.first->second = mapped;
+ }
return result;
}
@@ -268,9 +232,10 @@ namespace WTF {
HashMap<RefPtr<T>, U, V, W, X>::set(RawKeyType key, const MappedType& mapped)
{
pair<iterator, bool> result = inlineAdd(key, mapped);
- if (!result.second)
+ if (!result.second) {
// add call above didn't change anything, so set the mapped value
result.first->second = mapped;
+ }
return result;
}
@@ -292,24 +257,27 @@ namespace WTF {
typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
HashMap<RefPtr<T>, U, V, W, MappedTraits>::get(const KeyType& key) const
{
- if (m_impl.isEmpty())
- return MappedTraits::emptyValue();
- ValueStorageType* entry = const_cast<HashTableType&>(m_impl).lookup(*(const KeyStorageType*)&key);
+ ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
if (!entry)
return MappedTraits::emptyValue();
- return ((ValueType *)entry)->second;
+ return entry->second;
}
template<typename T, typename U, typename V, typename W, typename MappedTraits>
typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
- HashMap<RefPtr<T>, U, V, W, MappedTraits>::get(RawKeyType key) const
+ inline HashMap<RefPtr<T>, U, V, W, MappedTraits>::inlineGet(RawKeyType key) const
{
- if (m_impl.isEmpty())
- return MappedTraits::emptyValue();
- ValueStorageType* entry = const_cast<HashTableType&>(m_impl).lookup(*(const KeyStorageType*)&key);
+ ValueType* entry = const_cast<HashTableType&>(m_impl).template lookup<RawKeyType, RawKeyTranslator>(key);
if (!entry)
return MappedTraits::emptyValue();
- return ((ValueType *)entry)->second;
+ return entry->second;
+ }
+
+ template<typename T, typename U, typename V, typename W, typename MappedTraits>
+ typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
+ HashMap<RefPtr<T>, U, V, W, MappedTraits>::get(RawKeyType key) const
+ {
+ return inlineGet(key);
}
template<typename T, typename U, typename V, typename W, typename X>
@@ -318,7 +286,6 @@ namespace WTF {
if (it.m_impl == m_impl.end())
return;
m_impl.checkTableConsistency();
- RefCounter<ValueTraits, ValueStorageTraits>::deref(*it.m_impl);
m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
}
@@ -337,7 +304,6 @@ namespace WTF {
template<typename T, typename U, typename V, typename W, typename X>
inline void HashMap<RefPtr<T>, U, V, W, X>::clear()
{
- derefAll();
m_impl.clear();
}
diff --git a/JavaScriptCore/wtf/RetainPtr.h b/JavaScriptCore/wtf/RetainPtr.h
index 71260eb..2d73603 100644
--- a/JavaScriptCore/wtf/RetainPtr.h
+++ b/JavaScriptCore/wtf/RetainPtr.h
@@ -1,4 +1,3 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* This file is part of the KDE libraries
* Copyright (C) 2005, 2006 Apple Computer, Inc.
diff --git a/JavaScriptCore/wtf/StringExtras.h b/JavaScriptCore/wtf/StringExtras.h
index ca1c20c..881b066 100644
--- a/JavaScriptCore/wtf/StringExtras.h
+++ b/JavaScriptCore/wtf/StringExtras.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,27 +26,58 @@
#ifndef WTF_StringExtras_h
#define WTF_StringExtras_h
-#include <stdio.h>
#include <stdarg.h>
+#include <stdio.h>
#if COMPILER(MSVC)
-inline int snprintf(char *str, size_t size, const char* format, ...)
+inline int snprintf(char* buffer, size_t count, const char* format, ...)
{
int result;
va_list args;
va_start(args, format);
- result = _vsnprintf(str, size, format, args);
+ result = _vsnprintf(buffer, count, format, args);
va_end(args);
return result;
}
-#if COMPILER(MSVC7)
-// MSVC8 and above define this function
-#define vsnprintf snprintf
+#if COMPILER(MSVC7) || PLATFORM(WIN_CE)
+
+inline int vsnprintf(char* buffer, size_t count, const char* format, va_list args)
+{
+ return _vsnprintf(buffer, count, format, args);
+}
+
#endif
-inline int strncasecmp(const char* s1, const char* s2, size_t len) { return strnicmp(s1, s2, len); }
+#if PLATFORM(WIN_CE)
+
+inline int strnicmp(const char* string1, const char* string2, size_t count)
+{
+ return _strnicmp(string1, string2, count);
+}
+
+inline int stricmp(const char* string1, const char* string2)
+{
+ return _stricmp(string1, string2);
+}
+
+inline char* strdup(const char* strSource)
+{
+ return _strdup(strSource);
+}
+
+#endif
+
+inline int strncasecmp(const char* s1, const char* s2, size_t len)
+{
+ return strnicmp(s1, s2, len);
+}
+
+inline int strcasecmp(const char* s1, const char* s2)
+{
+ return stricmp(s1, s2);
+}
#endif
diff --git a/JavaScriptCore/wtf/TCSpinLock.h b/JavaScriptCore/wtf/TCSpinLock.h
index 2bfd090..3c6ac11 100644
--- a/JavaScriptCore/wtf/TCSpinLock.h
+++ b/JavaScriptCore/wtf/TCSpinLock.h
@@ -48,7 +48,7 @@
#endif
#include <stdlib.h> /* for abort() */
-#if COMPILER(MSVC)
+#if PLATFORM(WIN_OS)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
@@ -104,7 +104,7 @@ struct TCMalloc_SpinLock {
("isync\n\t"
"eieio\n\t"
"stw %1, %0"
-#if PLATFORM(DARWIN)
+#if PLATFORM(DARWIN) || PLATFORM(PPC)
: "=o" (lockword_)
#else
: "=m" (lockword_)
@@ -179,7 +179,7 @@ static void TCMalloc_SlowLock(volatile unsigned int* lockword) {
// from taking 30 seconds to 16 seconds.
// Sleep for a few milliseconds
-#if COMPILER(MSVC)
+#if PLATFORM(WIN_OS)
Sleep(2);
#else
struct timespec tm;
diff --git a/JavaScriptCore/wtf/TCSystemAlloc.cpp b/JavaScriptCore/wtf/TCSystemAlloc.cpp
index 73f9341..bd6eb33 100644
--- a/JavaScriptCore/wtf/TCSystemAlloc.cpp
+++ b/JavaScriptCore/wtf/TCSystemAlloc.cpp
@@ -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_READWRITE);
+ PAGE_EXECUTE_READWRITE);
if (result == NULL) {
VirtualAlloc_failure = true;
@@ -428,3 +428,11 @@ void TCMalloc_SystemRelease(void* start, size_t length)
return;
#endif
}
+
+#if HAVE(VIRTUALALLOC)
+void TCMalloc_SystemCommit(void* start, size_t length)
+{
+ UNUSED_PARAM(start);
+ UNUSED_PARAM(length);
+}
+#endif
diff --git a/JavaScriptCore/wtf/TCSystemAlloc.h b/JavaScriptCore/wtf/TCSystemAlloc.h
index d9d4a2b..d82e860 100644
--- a/JavaScriptCore/wtf/TCSystemAlloc.h
+++ b/JavaScriptCore/wtf/TCSystemAlloc.h
@@ -62,4 +62,10 @@ extern void* TCMalloc_SystemAlloc(size_t bytes, size_t *actual_bytes,
// be released, partial pages will not.)
extern void TCMalloc_SystemRelease(void* start, size_t length);
+#if HAVE(VIRTUALALLOC)
+extern void TCMalloc_SystemCommit(void* start, size_t length);
+#else
+inline void TCMalloc_SystemCommit(void*, size_t) { }
+#endif
+
#endif /* TCMALLOC_SYSTEM_ALLOC_H__ */
diff --git a/JavaScriptCore/wtf/ThreadSpecific.h b/JavaScriptCore/wtf/ThreadSpecific.h
new file mode 100644
index 0000000..87709a1
--- /dev/null
+++ b/JavaScriptCore/wtf/ThreadSpecific.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef 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.
+#include <pthread.h>
+#endif
+
+namespace WTF {
+
+template<typename T> class ThreadSpecific : Noncopyable {
+public:
+ ThreadSpecific();
+ T* operator->();
+ operator T*();
+ T& operator*();
+ ~ThreadSpecific();
+
+private:
+ T* get();
+ void set(T*);
+ void static destroy(void* ptr);
+
+#if USE(PTHREADS) || PLATFORM(WIN)
+ struct Data : Noncopyable {
+ Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {}
+
+ T* value;
+ ThreadSpecific<T>* owner;
+ };
+
+ pthread_key_t m_key;
+#endif
+};
+
+#if USE(PTHREADS) || PLATFORM(WIN)
+template<typename T>
+inline ThreadSpecific<T>::ThreadSpecific()
+{
+ int error = pthread_key_create(&m_key, destroy);
+ if (error)
+ CRASH();
+}
+
+template<typename T>
+inline ThreadSpecific<T>::~ThreadSpecific()
+{
+ pthread_key_delete(m_key); // Does not invoke destructor functions.
+}
+
+template<typename T>
+inline T* ThreadSpecific<T>::get()
+{
+ Data* data = static_cast<Data*>(pthread_getspecific(m_key));
+ return data ? data->value : 0;
+}
+
+template<typename T>
+inline void ThreadSpecific<T>::set(T* ptr)
+{
+ ASSERT(!get());
+ pthread_setspecific(m_key, new Data(ptr, this));
+}
+
+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;
+}
+
+#else
+#error ThreadSpecific is not implemented for this platform.
+#endif
+
+template<typename T>
+inline ThreadSpecific<T>::operator T*()
+{
+ T* ptr = static_cast<T*>(get());
+ if (!ptr) {
+ ptr = new T();
+ set(ptr);
+ }
+ return ptr;
+}
+
+template<typename T>
+inline T* ThreadSpecific<T>::operator->()
+{
+ return operator T*();
+}
+
+template<typename T>
+inline T& ThreadSpecific<T>::operator*()
+{
+ return *operator T*();
+}
+
+}
+
+#endif
diff --git a/JavaScriptCore/wtf/Threading.h b/JavaScriptCore/wtf/Threading.h
new file mode 100644
index 0000000..b464da3
--- /dev/null
+++ b/JavaScriptCore/wtf/Threading.h
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Note: The implementations of InterlockedIncrement and InterlockedDecrement are based
+ * on atomic_increment and atomic_exchange_and_add from the Boost C++ Library. The license
+ * is virtually identical to the Apple license above but is included here for completeness.
+ *
+ * Boost Software License - Version 1.0 - August 17th, 2003
+ *
+ * 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 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.
+ *
+ * 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.
+ */
+
+#ifndef Threading_h
+#define Threading_h
+
+#include <wtf/Assertions.h>
+#include <wtf/Locker.h>
+#include <wtf/Noncopyable.h>
+
+#if PLATFORM(WIN_OS)
+#include <windows.h>
+#elif PLATFORM(DARWIN)
+#include <libkern/OSAtomic.h>
+#elif defined ANDROID
+#include "cutils/atomic.h"
+#elif COMPILER(GCC)
+#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2))
+#include <ext/atomicity.h>
+#else
+#include <bits/atomicity.h>
+#endif
+#endif
+
+#if USE(PTHREADS)
+#include <pthread.h>
+#elif PLATFORM(GTK)
+#include <wtf/GOwnPtr.h>
+typedef struct _GMutex GMutex;
+typedef struct _GCond GCond;
+#endif
+
+#if PLATFORM(QT)
+#include <qglobal.h>
+QT_BEGIN_NAMESPACE
+class QMutex;
+class QWaitCondition;
+QT_END_NAMESPACE
+#endif
+
+#include <stdint.h>
+
+// For portability, we do not use thread-safe statics natively supported by some compilers (e.g. gcc).
+#define AtomicallyInitializedStatic(T, name) \
+ WTF::lockAtomicallyInitializedStaticMutex(); \
+ static T name; \
+ WTF::unlockAtomicallyInitializedStaticMutex();
+
+namespace WTF {
+
+typedef uint32_t ThreadIdentifier;
+typedef void* (*ThreadFunction)(void* argument);
+
+// Returns 0 if thread creation failed
+ThreadIdentifier createThread(ThreadFunction, void*, const char* threadName);
+
+ThreadIdentifier currentThread();
+bool isMainThread();
+int waitForThreadCompletion(ThreadIdentifier, void**);
+void detachThread(ThreadIdentifier);
+
+#if USE(PTHREADS)
+typedef pthread_mutex_t PlatformMutex;
+typedef pthread_cond_t PlatformCondition;
+#elif PLATFORM(GTK)
+typedef GOwnPtr<GMutex> PlatformMutex;
+typedef GOwnPtr<GCond> PlatformCondition;
+#elif PLATFORM(QT)
+typedef QT_PREPEND_NAMESPACE(QMutex)* PlatformMutex;
+typedef QT_PREPEND_NAMESPACE(QWaitCondition)* PlatformCondition;
+#elif PLATFORM(WIN_OS)
+struct PlatformMutex {
+ CRITICAL_SECTION m_internalMutex;
+ 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;
+};
+#else
+typedef void* PlatformMutex;
+typedef void* PlatformCondition;
+#endif
+
+class Mutex : Noncopyable {
+public:
+ Mutex();
+ ~Mutex();
+
+ void lock();
+ bool tryLock();
+ void unlock();
+
+public:
+ PlatformMutex& impl() { return m_mutex; }
+private:
+ PlatformMutex m_mutex;
+};
+
+typedef Locker<Mutex> MutexLocker;
+
+class ThreadCondition : Noncopyable {
+public:
+ ThreadCondition();
+ ~ThreadCondition();
+
+ void wait(Mutex& mutex);
+ // Returns true if the condition was signaled before the timeout, false if the timeout was reached
+ bool timedWait(Mutex&, double interval);
+ void signal();
+ void broadcast();
+
+private:
+ PlatformCondition m_condition;
+};
+
+#if PLATFORM(WIN_OS)
+#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
+
+#if COMPILER(MINGW) || COMPILER(MSVC7)
+inline void atomicIncrement(int* addend) { InterlockedIncrement(reinterpret_cast<long*>(addend)); }
+inline int atomicDecrement(int* addend) { return InterlockedDecrement(reinterpret_cast<long*>(addend)); }
+#else
+inline void atomicIncrement(int volatile* addend) { InterlockedIncrement(reinterpret_cast<long volatile*>(addend)); }
+inline int atomicDecrement(int volatile* addend) { return InterlockedDecrement(reinterpret_cast<long volatile*>(addend)); }
+#endif
+
+#elif PLATFORM(DARWIN)
+#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
+
+inline void atomicIncrement(int volatile* addend) { OSAtomicIncrement32Barrier(const_cast<int*>(addend)); }
+inline int atomicDecrement(int volatile* addend) { return OSAtomicDecrement32Barrier(const_cast<int*>(addend)); }
+
+#elif defined ANDROID
+
+inline void atomicIncrement(int volatile* addend) { android_atomic_inc(addend); }
+inline int atomicDecrement(int volatile* addend) { return android_atomic_dec(addend); }
+
+#elif COMPILER(GCC)
+#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
+
+inline void atomicIncrement(int volatile* addend) { __gnu_cxx::__atomic_add(addend, 1); }
+inline int atomicDecrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, -1) - 1; }
+
+#endif
+
+template<class T> class ThreadSafeShared : Noncopyable {
+public:
+ ThreadSafeShared(int initialRefCount = 1)
+ : m_refCount(initialRefCount)
+ {
+ }
+
+ void ref()
+ {
+#if USE(LOCKFREE_THREADSAFESHARED)
+ atomicIncrement(&m_refCount);
+#else
+ MutexLocker locker(m_mutex);
+ ++m_refCount;
+#endif
+ }
+
+ void deref()
+ {
+#if USE(LOCKFREE_THREADSAFESHARED)
+ if (atomicDecrement(&m_refCount) <= 0)
+#else
+ {
+ MutexLocker locker(m_mutex);
+ --m_refCount;
+ }
+ if (m_refCount <= 0)
+#endif
+ delete static_cast<T*>(this);
+ }
+
+ bool hasOneRef()
+ {
+ return refCount() == 1;
+ }
+
+ int refCount() const
+ {
+#if !USE(LOCKFREE_THREADSAFESHARED)
+ MutexLocker locker(m_mutex);
+#endif
+ return static_cast<int const volatile &>(m_refCount);
+ }
+
+private:
+ int m_refCount;
+#if !USE(LOCKFREE_THREADSAFESHARED)
+ mutable Mutex m_mutex;
+#endif
+};
+
+// This function must be called from the main thread. It is safe to call it repeatedly.
+// Darwin is an exception to this rule: it is OK to call it from any thread, the only requirement is that the calls are not reentrant.
+void initializeThreading();
+
+#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
+
+using WTF::Mutex;
+using WTF::MutexLocker;
+using WTF::ThreadCondition;
+using WTF::ThreadIdentifier;
+using WTF::ThreadSafeShared;
+
+using WTF::createThread;
+using WTF::currentThread;
+using WTF::isMainThread;
+using WTF::detachThread;
+using WTF::waitForThreadCompletion;
+
+#endif // Threading_h
diff --git a/JavaScriptCore/wtf/ThreadingGtk.cpp b/JavaScriptCore/wtf/ThreadingGtk.cpp
new file mode 100644
index 0000000..53fd1fe
--- /dev/null
+++ b/JavaScriptCore/wtf/ThreadingGtk.cpp
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Threading.h"
+
+#if !USE(PTHREADS)
+
+#include "HashMap.h"
+#include "MainThread.h"
+#include "MathExtras.h"
+
+#include <glib.h>
+
+namespace WTF {
+
+Mutex* atomicallyInitializedStaticMutex;
+
+static ThreadIdentifier mainThreadIdentifier;
+
+static Mutex& threadMapMutex()
+{
+ static Mutex mutex;
+ return mutex;
+}
+
+void initializeThreading()
+{
+ if (!g_thread_supported())
+ g_thread_init(NULL);
+ ASSERT(g_thread_supported());
+
+ if (!atomicallyInitializedStaticMutex) {
+ atomicallyInitializedStaticMutex = new Mutex;
+ threadMapMutex();
+ wtf_random_init();
+ mainThreadIdentifier = currentThread();
+ initializeMainThread();
+ }
+}
+
+static HashMap<ThreadIdentifier, GThread*>& threadMap()
+{
+ static HashMap<ThreadIdentifier, GThread*> map;
+ return map;
+}
+
+static ThreadIdentifier establishIdentifierForThread(GThread*& thread)
+{
+ MutexLocker locker(threadMapMutex());
+
+ static ThreadIdentifier identifierCount = 1;
+
+ threadMap().add(identifierCount, thread);
+
+ return identifierCount++;
+}
+
+static ThreadIdentifier identifierByGthreadHandle(GThread*& thread)
+{
+ MutexLocker locker(threadMapMutex());
+
+ HashMap<ThreadIdentifier, GThread*>::iterator i = threadMap().begin();
+ for (; i != threadMap().end(); ++i) {
+ if (i->second == thread)
+ return i->first;
+ }
+
+ return 0;
+}
+
+static GThread* threadForIdentifier(ThreadIdentifier id)
+{
+ MutexLocker locker(threadMapMutex());
+
+ return threadMap().get(id);
+}
+
+static void clearThreadForIdentifier(ThreadIdentifier id)
+{
+ MutexLocker locker(threadMapMutex());
+
+ ASSERT(threadMap().contains(id));
+
+ threadMap().remove(id);
+}
+
+ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char*)
+{
+ GThread* thread;
+ if (!(thread = g_thread_create(entryPoint, data, TRUE, 0))) {
+ LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint, data);
+ return 0;
+ }
+
+ ThreadIdentifier threadID = establishIdentifierForThread(thread);
+ return threadID;
+}
+
+int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
+{
+ ASSERT(threadID);
+
+ GThread* thread = threadForIdentifier(threadID);
+
+ *result = g_thread_join(thread);
+
+ clearThreadForIdentifier(threadID);
+ return 0;
+}
+
+void detachThread(ThreadIdentifier)
+{
+}
+
+ThreadIdentifier currentThread()
+{
+ GThread* currentThread = g_thread_self();
+ if (ThreadIdentifier id = identifierByGthreadHandle(currentThread))
+ return id;
+ return establishIdentifierForThread(currentThread);
+}
+
+bool isMainThread()
+{
+ return currentThread() == mainThreadIdentifier;
+}
+
+Mutex::Mutex()
+ : m_mutex(g_mutex_new())
+{
+}
+
+Mutex::~Mutex()
+{
+}
+
+void Mutex::lock()
+{
+ g_mutex_lock(m_mutex.get());
+}
+
+bool Mutex::tryLock()
+{
+ return g_mutex_trylock(m_mutex.get());
+}
+
+void Mutex::unlock()
+{
+ g_mutex_unlock(m_mutex.get());
+}
+
+ThreadCondition::ThreadCondition()
+ : m_condition(g_cond_new())
+{
+}
+
+ThreadCondition::~ThreadCondition()
+{
+}
+
+void ThreadCondition::wait(Mutex& mutex)
+{
+ g_cond_wait(m_condition.get(), mutex.impl().get());
+}
+
+bool ThreadCondition::timedWait(Mutex& mutex, double interval)
+{
+ if (interval < 0.0) {
+ wait(mutex);
+ return true;
+ }
+
+ int intervalSeconds = static_cast<int>(interval);
+ int intervalMicroseconds = static_cast<int>((interval - intervalSeconds) * 1000000.0);
+
+ GTimeVal targetTime;
+ g_get_current_time(&targetTime);
+
+ targetTime.tv_sec += intervalSeconds;
+ targetTime.tv_usec += intervalMicroseconds;
+ if (targetTime.tv_usec > 1000000) {
+ targetTime.tv_usec -= 1000000;
+ targetTime.tv_sec++;
+ }
+
+ return g_cond_timed_wait(m_condition.get(), mutex.impl().get(), &targetTime);
+}
+
+void ThreadCondition::signal()
+{
+ g_cond_signal(m_condition.get());
+}
+
+void ThreadCondition::broadcast()
+{
+ g_cond_broadcast(m_condition.get());
+}
+
+
+}
+
+#endif // !USE(PTHREADS)
diff --git a/JavaScriptCore/wtf/ThreadingNone.cpp b/JavaScriptCore/wtf/ThreadingNone.cpp
new file mode 100644
index 0000000..c17b3b2
--- /dev/null
+++ b/JavaScriptCore/wtf/ThreadingNone.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "config.h"
+#include "Threading.h"
+
+namespace WTF {
+
+Mutex* atomicallyInitializedStaticMutex;
+
+void initializeThreading() {}
+ThreadIdentifier createThread(ThreadFunction, void*, const char*) { return 0; }
+int waitForThreadCompletion(ThreadIdentifier, void**) { return 0; }
+void detachThread(ThreadIdentifier) { }
+ThreadIdentifier currentThread() { return 0; }
+bool isMainThread() { return false; }
+
+Mutex::Mutex() {}
+Mutex::~Mutex() {}
+void Mutex::lock() {}
+bool Mutex::tryLock() { return false; }
+void Mutex::unlock() {};
+
+ThreadCondition::ThreadCondition() {}
+ThreadCondition::~ThreadCondition() {}
+void ThreadCondition::wait(Mutex& mutex) {}
+bool ThreadCondition::timedWait(Mutex& mutex, double interval) { return false; }
+void ThreadCondition::signal() {}
+void ThreadCondition::broadcast() {}
+
+} // namespace WebCore
diff --git a/JavaScriptCore/wtf/ThreadingPthreads.cpp b/JavaScriptCore/wtf/ThreadingPthreads.cpp
new file mode 100644
index 0000000..d17a03d
--- /dev/null
+++ b/JavaScriptCore/wtf/ThreadingPthreads.cpp
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "config.h"
+#include "Threading.h"
+
+#if USE(PTHREADS)
+
+#include "HashMap.h"
+#include "MainThread.h"
+#include "MathExtras.h"
+
+#include <errno.h>
+#include <sys/time.h>
+
+namespace WTF {
+
+Mutex* atomicallyInitializedStaticMutex;
+
+#if !PLATFORM(DARWIN)
+static ThreadIdentifier mainThreadIdentifier; // The thread that was the first to call initializeThreading(), which must be the main thread.
+#endif
+
+static Mutex& threadMapMutex()
+{
+ static Mutex mutex;
+ return mutex;
+}
+
+void initializeThreading()
+{
+ if (!atomicallyInitializedStaticMutex) {
+ atomicallyInitializedStaticMutex = new Mutex;
+ threadMapMutex();
+ wtf_random_init();
+#if !PLATFORM(DARWIN)
+ mainThreadIdentifier = currentThread();
+#endif
+ initializeMainThread();
+ }
+}
+
+static HashMap<ThreadIdentifier, pthread_t>& threadMap()
+{
+ static HashMap<ThreadIdentifier, pthread_t> map;
+ return map;
+}
+
+static ThreadIdentifier establishIdentifierForPthreadHandle(pthread_t& pthreadHandle)
+{
+ MutexLocker locker(threadMapMutex());
+
+ static ThreadIdentifier identifierCount = 1;
+
+ threadMap().add(identifierCount, pthreadHandle);
+
+ return identifierCount++;
+}
+
+static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle)
+{
+ MutexLocker locker(threadMapMutex());
+
+ HashMap<ThreadIdentifier, pthread_t>::iterator i = threadMap().begin();
+ for (; i != threadMap().end(); ++i) {
+ if (pthread_equal(i->second, pthreadHandle))
+ return i->first;
+ }
+
+ return 0;
+}
+
+static pthread_t pthreadHandleForIdentifier(ThreadIdentifier id)
+{
+ MutexLocker locker(threadMapMutex());
+
+ return threadMap().get(id);
+}
+
+static void clearPthreadHandleForIdentifier(ThreadIdentifier id)
+{
+ MutexLocker locker(threadMapMutex());
+
+ ASSERT(threadMap().contains(id));
+
+ threadMap().remove(id);
+}
+
+ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char*)
+{
+ pthread_t threadHandle;
+ if (pthread_create(&threadHandle, NULL, entryPoint, data)) {
+ LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
+ return 0;
+ }
+
+ ThreadIdentifier threadID = establishIdentifierForPthreadHandle(threadHandle);
+ return threadID;
+}
+
+#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);
+
+ pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
+
+ int joinResult = pthread_join(pthreadHandle, result);
+ if (joinResult == EDEADLK)
+ LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);
+
+ clearPthreadHandleForIdentifier(threadID);
+ return joinResult;
+}
+
+void detachThread(ThreadIdentifier threadID)
+{
+ ASSERT(threadID);
+
+ pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
+
+ pthread_detach(pthreadHandle);
+
+ clearPthreadHandleForIdentifier(threadID);
+}
+
+ThreadIdentifier currentThread()
+{
+ pthread_t currentThread = pthread_self();
+ if (ThreadIdentifier id = identifierByPthreadHandle(currentThread))
+ return id;
+ return establishIdentifierForPthreadHandle(currentThread);
+}
+
+bool isMainThread()
+{
+#if PLATFORM(DARWIN)
+ return pthread_main_np();
+#else
+ return currentThread() == mainThreadIdentifier;
+#endif
+}
+
+Mutex::Mutex()
+{
+ pthread_mutex_init(&m_mutex, NULL);
+}
+
+Mutex::~Mutex()
+{
+ pthread_mutex_destroy(&m_mutex);
+}
+
+void Mutex::lock()
+{
+ if (pthread_mutex_lock(&m_mutex) != 0)
+ ASSERT(false);
+}
+
+bool Mutex::tryLock()
+{
+ int result = pthread_mutex_trylock(&m_mutex);
+
+ if (result == 0)
+ return true;
+ else if (result == EBUSY)
+ return false;
+
+ ASSERT(false);
+ return false;
+}
+
+void Mutex::unlock()
+{
+ if (pthread_mutex_unlock(&m_mutex) != 0)
+ ASSERT(false);
+}
+
+ThreadCondition::ThreadCondition()
+{
+ pthread_cond_init(&m_condition, NULL);
+}
+
+ThreadCondition::~ThreadCondition()
+{
+ pthread_cond_destroy(&m_condition);
+}
+
+void ThreadCondition::wait(Mutex& mutex)
+{
+ if (pthread_cond_wait(&m_condition, &mutex.impl()) != 0)
+ ASSERT(false);
+}
+
+bool ThreadCondition::timedWait(Mutex& mutex, double secondsToWait)
+{
+ if (secondsToWait < 0.0) {
+ wait(mutex);
+ return true;
+ }
+
+ int intervalSeconds = static_cast<int>(secondsToWait);
+ int intervalMicroseconds = static_cast<int>((secondsToWait - intervalSeconds) * 1000000.0);
+
+ // Current time comes in sec/microsec
+ timeval currentTime;
+ gettimeofday(&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++;
+ }
+
+ return pthread_cond_timedwait(&m_condition, &mutex.impl(), &targetTime) == 0;
+}
+
+void ThreadCondition::signal()
+{
+ if (pthread_cond_signal(&m_condition) != 0)
+ ASSERT(false);
+}
+
+void ThreadCondition::broadcast()
+{
+ if (pthread_cond_broadcast(&m_condition) != 0)
+ ASSERT(false);
+}
+
+} // namespace WTF
+
+#endif // USE(PTHREADS)
diff --git a/JavaScriptCore/wtf/ThreadingQt.cpp b/JavaScriptCore/wtf/ThreadingQt.cpp
new file mode 100644
index 0000000..b24f241
--- /dev/null
+++ b/JavaScriptCore/wtf/ThreadingQt.cpp
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "config.h"
+#include "Threading.h"
+
+#include "HashMap.h"
+#include "MainThread.h"
+#include "MathExtras.h"
+
+#include <QCoreApplication>
+#include <QMutex>
+#include <QThread>
+#include <QWaitCondition>
+
+namespace WTF {
+
+class ThreadPrivate : public QThread {
+public:
+ ThreadPrivate(ThreadFunction entryPoint, void* data);
+ void run();
+ void* getReturnValue() { return m_returnValue; }
+private:
+ void* m_data;
+ ThreadFunction m_entryPoint;
+ void* m_returnValue;
+};
+
+ThreadPrivate::ThreadPrivate(ThreadFunction entryPoint, void* data)
+ : m_data(data)
+ , m_entryPoint(entryPoint)
+ , m_returnValue(0)
+{
+}
+
+void ThreadPrivate::run()
+{
+ m_returnValue = m_entryPoint(m_data);
+}
+
+
+Mutex* atomicallyInitializedStaticMutex;
+
+static ThreadIdentifier mainThreadIdentifier;
+
+static Mutex& threadMapMutex()
+{
+ static Mutex mutex;
+ return mutex;
+}
+
+static HashMap<ThreadIdentifier, QThread*>& threadMap()
+{
+ static HashMap<ThreadIdentifier, QThread*> map;
+ return map;
+}
+
+static ThreadIdentifier establishIdentifierForThread(QThread*& thread)
+{
+ MutexLocker locker(threadMapMutex());
+
+ static ThreadIdentifier identifierCount = 1;
+
+ threadMap().add(identifierCount, thread);
+
+ return identifierCount++;
+}
+
+static void clearThreadForIdentifier(ThreadIdentifier id)
+{
+ MutexLocker locker(threadMapMutex());
+
+ ASSERT(threadMap().contains(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());
+
+ return threadMap().get(id);
+}
+
+void initializeThreading()
+{
+ if(!atomicallyInitializedStaticMutex) {
+ atomicallyInitializedStaticMutex = new Mutex;
+ threadMapMutex();
+ wtf_random_init();
+ QThread* mainThread = QCoreApplication::instance()->thread();
+ mainThreadIdentifier = identifierByQthreadHandle(mainThread);
+ if (!mainThreadIdentifier)
+ mainThreadIdentifier = establishIdentifierForThread(mainThread);
+ initializeMainThread();
+ }
+}
+
+ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char*)
+{
+ ThreadPrivate* thread = new ThreadPrivate(entryPoint, data);
+ if (!thread) {
+ LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint, data);
+ return 0;
+ }
+ thread->start();
+
+ QThread* threadRef = static_cast<QThread*>(thread);
+
+ return establishIdentifierForThread(threadRef);
+}
+
+int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
+{
+ ASSERT(threadID);
+
+ QThread* thread = threadForIdentifier(threadID);
+
+ bool res = thread->wait();
+
+ clearThreadForIdentifier(threadID);
+ *result = static_cast<ThreadPrivate*>(thread)->getReturnValue();
+
+ return !res;
+}
+
+void detachThread(ThreadIdentifier)
+{
+}
+
+ThreadIdentifier currentThread()
+{
+ QThread* currentThread = QThread::currentThread();
+ if (ThreadIdentifier id = identifierByQthreadHandle(currentThread))
+ return id;
+ return establishIdentifierForThread(currentThread);
+}
+
+bool isMainThread()
+{
+ return currentThread() == mainThreadIdentifier;
+}
+
+Mutex::Mutex()
+ : m_mutex(new QMutex())
+{
+}
+
+Mutex::~Mutex()
+{
+ delete m_mutex;
+}
+
+void Mutex::lock()
+{
+ m_mutex->lock();
+}
+
+bool Mutex::tryLock()
+{
+ return m_mutex->tryLock();
+}
+
+void Mutex::unlock()
+{
+ m_mutex->unlock();
+}
+
+ThreadCondition::ThreadCondition()
+ : m_condition(new QWaitCondition())
+{
+}
+
+ThreadCondition::~ThreadCondition()
+{
+ delete m_condition;
+}
+
+void ThreadCondition::wait(Mutex& mutex)
+{
+ m_condition->wait(mutex.impl());
+}
+
+bool ThreadCondition::timedWait(Mutex& mutex, double secondsToWait)
+{
+ if (secondsToWait < 0.0) {
+ wait(mutex);
+ return true;
+ }
+
+ unsigned long millisecondsToWait = static_cast<unsigned long>(secondsToWait * 1000.0);
+ return m_condition->wait(mutex.impl(), millisecondsToWait);
+}
+
+void ThreadCondition::signal()
+{
+ m_condition->wakeOne();
+}
+
+void ThreadCondition::broadcast()
+{
+ m_condition->wakeAll();
+}
+
+} // namespace WebCore
diff --git a/JavaScriptCore/wtf/ThreadingWin.cpp b/JavaScriptCore/wtf/ThreadingWin.cpp
new file mode 100644
index 0000000..00ad149
--- /dev/null
+++ b/JavaScriptCore/wtf/ThreadingWin.cpp
@@ -0,0 +1,479 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * =============================================================================
+ * 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.
+ * =============================================================================
+ *
+ * The Boost license is virtually identical to the Apple variation at the
+ * top of this file, but is included here for completeness:
+ *
+ * Boost Software License - Version 1.0 - August 17th, 2003
+ *
+ * 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 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.
+ *
+ * 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.
+ */
+
+#include "config.h"
+#include "Threading.h"
+
+#include "MainThread.h"
+#include <process.h>
+#include <windows.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
+
+namespace WTF {
+
+// MS_VC_EXCEPTION, THREADNAME_INFO, and setThreadName all come from <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>.
+static const DWORD MS_VC_EXCEPTION = 0x406D1388;
+
+#pragma pack(push, 8)
+typedef struct tagTHREADNAME_INFO {
+ DWORD dwType; // must be 0x1000
+ LPCSTR szName; // pointer to name (in user addr space)
+ DWORD dwThreadID; // thread ID (-1=caller thread)
+ DWORD dwFlags; // reserved for future use, must be zero
+} THREADNAME_INFO;
+#pragma pack(pop)
+
+static void setThreadName(DWORD dwThreadID, LPCSTR szThreadName)
+{
+ // Visual Studio has a 31-character limit on thread names. Longer names will
+ // be truncated silently, but we'd like callers to know about the limit.
+ ASSERT_ARG(szThreadName, strlen(szThreadName) <= 31);
+
+ THREADNAME_INFO info;
+ info.dwType = 0x1000;
+ info.szName = szThreadName;
+ info.dwThreadID = dwThreadID;
+ info.dwFlags = 0;
+
+ __try {
+ RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), reinterpret_cast<ULONG_PTR*>(&info));
+ } __except (EXCEPTION_CONTINUE_EXECUTION) {
+ }
+}
+
+static Mutex* atomicallyInitializedStaticMutex;
+
+void lockAtomicallyInitializedStaticMutex()
+{
+ atomicallyInitializedStaticMutex->lock();
+}
+
+void unlockAtomicallyInitializedStaticMutex()
+{
+ atomicallyInitializedStaticMutex->unlock();
+}
+
+static ThreadIdentifier mainThreadIdentifier;
+
+static Mutex& threadMapMutex()
+{
+ static Mutex mutex;
+ return mutex;
+}
+
+void initializeThreading()
+{
+ if (!atomicallyInitializedStaticMutex) {
+ atomicallyInitializedStaticMutex = new Mutex;
+ threadMapMutex();
+ wtf_random_init();
+ initializeMainThread();
+ mainThreadIdentifier = currentThread();
+ setThreadName(mainThreadIdentifier, "Main Thread");
+ }
+}
+
+static HashMap<DWORD, HANDLE>& threadMap()
+{
+ static HashMap<DWORD, HANDLE> map;
+ return map;
+}
+
+static void storeThreadHandleByIdentifier(DWORD threadID, HANDLE threadHandle)
+{
+ MutexLocker locker(threadMapMutex());
+ threadMap().add(threadID, threadHandle);
+}
+
+static HANDLE threadHandleForIdentifier(ThreadIdentifier id)
+{
+ MutexLocker locker(threadMapMutex());
+ return threadMap().get(id);
+}
+
+static void clearThreadHandleForIdentifier(ThreadIdentifier id)
+{
+ MutexLocker locker(threadMapMutex());
+ ASSERT(threadMap().contains(id));
+ threadMap().remove(id);
+}
+
+struct ThreadFunctionInvocation {
+ ThreadFunctionInvocation(ThreadFunction function, void* data) : function(function), data(data) {}
+
+ ThreadFunction function;
+ void* data;
+};
+
+static unsigned __stdcall wtfThreadEntryPoint(void* param)
+{
+ ThreadFunctionInvocation invocation = *static_cast<ThreadFunctionInvocation*>(param);
+ delete static_cast<ThreadFunctionInvocation*>(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);
+#endif
+
+ return reinterpret_cast<unsigned>(result);
+}
+
+ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* threadName)
+{
+ unsigned threadIdentifier = 0;
+ ThreadIdentifier threadID = 0;
+ ThreadFunctionInvocation* invocation = new ThreadFunctionInvocation(entryPoint, data);
+ HANDLE threadHandle = reinterpret_cast<HANDLE>(_beginthreadex(0, 0, wtfThreadEntryPoint, invocation, 0, &threadIdentifier));
+ if (!threadHandle) {
+ LOG_ERROR("Failed to create thread at entry point %p with data %p: %ld", entryPoint, data, errno);
+ return 0;
+ }
+
+ if (threadName)
+ setThreadName(threadIdentifier, threadName);
+
+ threadID = static_cast<ThreadIdentifier>(threadIdentifier);
+ storeThreadHandleByIdentifier(threadIdentifier, threadHandle);
+
+ 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);
+
+ HANDLE threadHandle = threadHandleForIdentifier(threadID);
+ if (!threadHandle)
+ LOG_ERROR("ThreadIdentifier %u did not correspond to an active thread when trying to quit", threadID);
+
+ DWORD joinResult = ::WaitForSingleObject(threadHandle, INFINITE);
+ if (joinResult == WAIT_FAILED)
+ LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);
+
+ ::CloseHandle(threadHandle);
+ clearThreadHandleForIdentifier(threadID);
+
+ return joinResult;
+}
+
+void detachThread(ThreadIdentifier threadID)
+{
+ ASSERT(threadID);
+
+ HANDLE threadHandle = threadHandleForIdentifier(threadID);
+ if (threadHandle)
+ ::CloseHandle(threadHandle);
+ clearThreadHandleForIdentifier(threadID);
+}
+
+ThreadIdentifier currentThread()
+{
+ return static_cast<ThreadIdentifier>(::GetCurrentThreadId());
+}
+
+bool isMainThread()
+{
+ return currentThread() == mainThreadIdentifier;
+}
+
+Mutex::Mutex()
+{
+ m_mutex.m_recursionCount = 0;
+ ::InitializeCriticalSection(&m_mutex.m_internalMutex);
+}
+
+Mutex::~Mutex()
+{
+ ::DeleteCriticalSection(&m_mutex.m_internalMutex);
+}
+
+void Mutex::lock()
+{
+ ::EnterCriticalSection(&m_mutex.m_internalMutex);
+ ++m_mutex.m_recursionCount;
+}
+
+bool Mutex::tryLock()
+{
+ // This method is modeled after the behavior of pthread_mutex_trylock,
+ // which will return an error if the lock is already owned by the
+ // current thread. Since the primitive Win32 'TryEnterCriticalSection'
+ // 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);
+
+ 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);
+ return false;
+ }
+
+ ++m_mutex.m_recursionCount;
+ return true;
+ }
+
+ return false;
+}
+
+void Mutex::unlock()
+{
+ --m_mutex.m_recursionCount;
+ ::LeaveCriticalSection(&m_mutex.m_internalMutex);
+}
+
+static const long MaxSemaphoreCount = static_cast<long>(~0UL >> 1);
+
+ThreadCondition::ThreadCondition()
+{
+ m_condition.m_timedOut = 0;
+ m_condition.m_blocked = 0;
+ m_condition.m_waitingForRemoval = 0;
+ m_condition.m_gate = ::CreateSemaphore(0, 1, 1, 0);
+ m_condition.m_queue = ::CreateSemaphore(0, 0, MaxSemaphoreCount, 0);
+ m_condition.m_mutex = ::CreateMutex(0, 0, 0);
+
+ if (!m_condition.m_gate || !m_condition.m_queue || !m_condition.m_mutex) {
+ if (m_condition.m_gate)
+ ::CloseHandle(m_condition.m_gate);
+ if (m_condition.m_queue)
+ ::CloseHandle(m_condition.m_queue);
+ if (m_condition.m_mutex)
+ ::CloseHandle(m_condition.m_mutex);
+ }
+}
+
+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);
+ ASSERT(res == WAIT_OBJECT_0);
+ ++m_condition.m_blocked;
+ res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0);
+ ASSERT(res);
+
+ ::LeaveCriticalSection(&cs.m_internalMutex);
+
+ res = ::WaitForSingleObject(m_condition.m_queue, INFINITE);
+ ASSERT(res == WAIT_OBJECT_0);
+
+ res = ::WaitForSingleObject(m_condition.m_mutex, 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
+ // 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);
+ ASSERT(res == WAIT_OBJECT_0);
+ m_condition.m_blocked -= m_condition.m_timedOut;
+ res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0);
+ ASSERT(res);
+ m_condition.m_timedOut = 0;
+ }
+ res = ::ReleaseMutex(m_condition.m_mutex);
+ 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);
+ ASSERT(res);
+ }
+
+ ::EnterCriticalSection (&cs.m_internalMutex);
+}
+
+bool ThreadCondition::timedWait(Mutex& mutex, double interval)
+{
+ // Empty for now
+ ASSERT(false);
+ return false;
+}
+
+void ThreadCondition::signal()
+{
+ unsigned signals = 0;
+
+ DWORD res = ::WaitForSingleObject(m_condition.m_mutex, 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);
+ ASSERT(res);
+ return;
+ }
+
+ ++m_condition.m_waitingForRemoval;
+ --m_condition.m_blocked;
+
+ signals = 1;
+ } 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 = 1;
+ --m_condition.m_blocked;
+ } else {
+ res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0);
+ ASSERT(res);
+ }
+ }
+
+ res =::ReleaseMutex(m_condition.m_mutex);
+ ASSERT(res);
+
+ if (signals) {
+ res = ::ReleaseSemaphore(m_condition.m_queue, signals, 0);
+ ASSERT(res);
+ }
+}
+
+void ThreadCondition::broadcast()
+{
+ unsigned signals = 0;
+
+ DWORD res = ::WaitForSingleObject(m_condition.m_mutex, 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);
+ ASSERT(res);
+ return;
+ }
+
+ 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);
+ }
+ }
+
+ res = ::ReleaseMutex(m_condition.m_mutex);
+ ASSERT(res);
+
+ if (signals) {
+ res = ::ReleaseSemaphore(m_condition.m_queue, signals, 0);
+ ASSERT(res);
+ }
+}
+
+} // namespace WTF
diff --git a/JavaScriptCore/wtf/UnusedParam.h b/JavaScriptCore/wtf/UnusedParam.h
index a599110..996f5c8 100644
--- a/JavaScriptCore/wtf/UnusedParam.h
+++ b/JavaScriptCore/wtf/UnusedParam.h
@@ -1,4 +1,3 @@
-/* -*- mode: c++; c-basic-offset: 4 -*- */
/*
* Copyright (C) 2006 Apple Computer, Inc.
*
@@ -27,4 +26,4 @@
#define UNUSED_PARAM(x) (void)x
-#endif // WTF_UnusedParam_h
+#endif /* WTF_UnusedParam_h */
diff --git a/JavaScriptCore/wtf/Vector.h b/JavaScriptCore/wtf/Vector.h
index 8fd412c..c0bc132 100644
--- a/JavaScriptCore/wtf/Vector.h
+++ b/JavaScriptCore/wtf/Vector.h
@@ -1,4 +1,3 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
*
@@ -24,6 +23,8 @@
#include "Assertions.h"
#include "FastMalloc.h"
+#include "Noncopyable.h"
+#include "NotFound.h"
#include "VectorTraits.h"
#include <limits>
#include <stdlib.h>
@@ -34,7 +35,33 @@ namespace WTF {
using std::min;
using std::max;
-
+
+ // WTF_ALIGN_OF / WTF_ALIGNED
+ #if COMPILER(GCC) || COMPILER(MINGW)
+ #define WTF_ALIGN_OF(type) __alignof__(type)
+ #define WTF_ALIGNED(variable_type, variable, n) variable_type variable __attribute__((__aligned__(n)))
+ #elif COMPILER(MSVC)
+ #define WTF_ALIGN_OF(type) __alignof(type)
+ #define WTF_ALIGNED(variable_type, variable, n) __declspec(align(n)) variable_type variable
+ #else
+ #error WTF_ALIGN macros need alignment control.
+ #endif
+
+ #if COMPILER(GCC) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303)
+ typedef char __attribute__((__may_alias__)) AlignedBufferChar;
+ #else
+ typedef char AlignedBufferChar;
+ #endif
+
+ template <size_t size, size_t alignment> struct AlignedBuffer;
+ template <size_t size> struct AlignedBuffer<size, 1> { AlignedBufferChar buffer[size]; };
+ template <size_t size> struct AlignedBuffer<size, 2> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 2); };
+ template <size_t size> struct AlignedBuffer<size, 4> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 4); };
+ template <size_t size> struct AlignedBuffer<size, 8> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 8); };
+ template <size_t size> struct AlignedBuffer<size, 16> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 16); };
+ template <size_t size> struct AlignedBuffer<size, 32> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 32); };
+ template <size_t size> struct AlignedBuffer<size, 64> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 64); };
+
template <bool needsDestruction, typename T>
class VectorDestructor;
@@ -240,11 +267,10 @@ namespace WTF {
};
template<typename T>
- class VectorBufferBase {
+ class VectorBufferBase : Noncopyable {
public:
void allocateBuffer(size_t newCapacity)
{
- ASSERT(newCapacity >= m_capacity);
m_capacity = newCapacity;
if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
CRASH();
@@ -253,11 +279,14 @@ namespace WTF {
void deallocateBuffer(T* bufferToDeallocate)
{
+ if (m_buffer == bufferToDeallocate)
+ m_buffer = 0;
fastFree(bufferToDeallocate);
}
T* buffer() { return m_buffer; }
const T* buffer() const { return m_buffer; }
+ T** bufferSlot() { return &m_buffer; }
size_t capacity() const { return m_capacity; }
T* releaseBuffer()
@@ -322,6 +351,7 @@ namespace WTF {
using Base::deallocateBuffer;
using Base::buffer;
+ using Base::bufferSlot;
using Base::capacity;
using Base::releaseBuffer;
@@ -343,8 +373,7 @@ namespace WTF {
VectorBuffer(size_t capacity)
: Base(inlineBuffer(), inlineCapacity)
{
- if (capacity > inlineCapacity)
- allocateBuffer(capacity);
+ allocateBuffer(capacity);
}
~VectorBuffer()
@@ -352,7 +381,11 @@ namespace WTF {
deallocateBuffer(buffer());
}
- using Base::allocateBuffer;
+ void allocateBuffer(size_t newCapacity)
+ {
+ if (newCapacity > inlineCapacity)
+ Base::allocateBuffer(newCapacity);
+ }
void deallocateBuffer(T* bufferToDeallocate)
{
@@ -362,6 +395,7 @@ namespace WTF {
}
using Base::buffer;
+ using Base::bufferSlot;
using Base::capacity;
T* releaseBuffer()
@@ -376,16 +410,15 @@ namespace WTF {
using Base::m_capacity;
static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
- T* inlineBuffer() { return reinterpret_cast<T*>(&m_inlineBuffer); }
+ T* inlineBuffer() { return reinterpret_cast<T*>(m_inlineBuffer.buffer); }
- // FIXME: Nothing guarantees this buffer is appropriately aligned to hold objects of type T.
- char m_inlineBuffer[m_inlineBufferSize];
+ AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer;
};
template<typename T, size_t inlineCapacity = 0>
class Vector {
private:
- typedef VectorBuffer<T, inlineCapacity> Impl;
+ typedef VectorBuffer<T, inlineCapacity> Buffer;
typedef VectorTypeOperations<T> TypeOperations;
public:
@@ -401,9 +434,10 @@ namespace WTF {
explicit Vector(size_t size)
: m_size(size)
- , m_impl(size)
+ , m_buffer(size)
{
- TypeOperations::initialize(begin(), end());
+ if (begin())
+ TypeOperations::initialize(begin(), end());
}
~Vector()
@@ -420,25 +454,26 @@ namespace WTF {
Vector& operator=(const Vector<T, otherCapacity>&);
size_t size() const { return m_size; }
- size_t capacity() const { return m_impl.capacity(); }
+ size_t capacity() const { return m_buffer.capacity(); }
bool isEmpty() const { return !size(); }
T& at(size_t i)
{
ASSERT(i < size());
- return m_impl.buffer()[i];
+ return m_buffer.buffer()[i];
}
const T& at(size_t i) const
{
ASSERT(i < size());
- return m_impl.buffer()[i];
+ return m_buffer.buffer()[i];
}
T& operator[](size_t i) { return at(i); }
const T& operator[](size_t i) const { return at(i); }
- T* data() { return m_impl.buffer(); }
- const T* data() const { return m_impl.buffer(); }
+ T* data() { return m_buffer.buffer(); }
+ const T* data() const { return m_buffer.buffer(); }
+ T** dataSlot() { return m_buffer.bufferSlot(); }
iterator begin() { return data(); }
iterator end() { return begin() + m_size; }
@@ -450,17 +485,20 @@ namespace WTF {
T& last() { return at(size() - 1); }
const T& last() const { return at(size() - 1); }
+ template<typename U> size_t find(const U&) const;
+
void shrink(size_t size);
void grow(size_t size);
void resize(size_t size);
void reserveCapacity(size_t newCapacity);
+ void shrinkCapacity(size_t newCapacity);
void clear() { if (m_size) shrink(0); }
template<typename U> void append(const U*, size_t);
template<typename U> void append(const U&);
template<typename U> void uncheckedAppend(const U& val);
- template<typename U, size_t c> void append(const Vector<U, c>&);
+ template<size_t otherCapacity> void append(const Vector<T, otherCapacity>&);
template<typename U> void insert(size_t position, const U*, size_t);
template<typename U> void insert(size_t position, const U&);
@@ -471,6 +509,7 @@ namespace WTF {
template<typename U, size_t c> void prepend(const Vector<U, c>&);
void remove(size_t position);
+ void remove(size_t position, size_t length);
void removeLast()
{
@@ -480,9 +519,10 @@ namespace WTF {
Vector(size_t size, const T& val)
: m_size(size)
- , m_impl(size)
+ , m_buffer(size)
{
- TypeOperations::uninitializedFill(begin(), end(), val);
+ if (begin())
+ TypeOperations::uninitializedFill(begin(), end(), val);
}
void fill(const T&, size_t);
@@ -495,7 +535,7 @@ namespace WTF {
void swap(Vector<T, inlineCapacity>& other)
{
std::swap(m_size, other.m_size);
- m_impl.swap(other.m_impl);
+ m_buffer.swap(other.m_buffer);
}
private:
@@ -504,24 +544,26 @@ namespace WTF {
template<typename U> U* expandCapacity(size_t newMinCapacity, U*);
size_t m_size;
- Impl m_impl;
+ Buffer m_buffer;
};
template<typename T, size_t inlineCapacity>
Vector<T, inlineCapacity>::Vector(const Vector& other)
: m_size(other.size())
- , m_impl(other.capacity())
+ , m_buffer(other.capacity())
{
- TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
+ if (begin())
+ TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
}
template<typename T, size_t inlineCapacity>
template<size_t otherCapacity>
Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other)
: m_size(other.size())
- , m_impl(other.capacity())
+ , m_buffer(other.capacity())
{
- TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
+ if (begin())
+ TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
}
template<typename T, size_t inlineCapacity>
@@ -535,6 +577,8 @@ namespace WTF {
else if (other.size() > capacity()) {
clear();
reserveCapacity(other.size());
+ if (!begin())
+ return *this;
}
std::copy(other.begin(), other.begin() + size(), begin());
@@ -556,6 +600,8 @@ namespace WTF {
else if (other.size() > capacity()) {
clear();
reserveCapacity(other.size());
+ if (!begin())
+ return *this;
}
std::copy(other.begin(), other.begin() + size(), begin());
@@ -566,6 +612,17 @@ namespace WTF {
}
template<typename T, size_t inlineCapacity>
+ template<typename U>
+ size_t Vector<T, inlineCapacity>::find(const U& value) const
+ {
+ for (size_t i = 0; i < size(); ++i) {
+ if (at(i) == value)
+ return i;
+ }
+ return notFound;
+ }
+
+ template<typename T, size_t inlineCapacity>
void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize)
{
if (size() > newSize)
@@ -573,6 +630,8 @@ namespace WTF {
else if (newSize > capacity()) {
clear();
reserveCapacity(newSize);
+ if (!begin())
+ return;
}
std::fill(begin(), end(), val);
@@ -621,7 +680,8 @@ namespace WTF {
else {
if (size > capacity())
expandCapacity(size);
- TypeOperations::initialize(end(), begin() + size);
+ if (begin())
+ TypeOperations::initialize(end(), begin() + size);
}
m_size = size;
@@ -641,7 +701,8 @@ namespace WTF {
ASSERT(size >= m_size);
if (size > capacity())
expandCapacity(size);
- TypeOperations::initialize(end(), begin() + size);
+ if (begin())
+ TypeOperations::initialize(end(), begin() + size);
m_size = size;
}
@@ -652,9 +713,29 @@ namespace WTF {
return;
T* oldBuffer = begin();
T* oldEnd = end();
- m_impl.allocateBuffer(newCapacity);
- TypeOperations::move(oldBuffer, oldEnd, begin());
- m_impl.deallocateBuffer(oldBuffer);
+ m_buffer.allocateBuffer(newCapacity);
+ if (begin())
+ TypeOperations::move(oldBuffer, oldEnd, begin());
+ m_buffer.deallocateBuffer(oldBuffer);
+ }
+
+ template<typename T, size_t inlineCapacity>
+ void Vector<T, inlineCapacity>::shrinkCapacity(size_t newCapacity)
+ {
+ if (newCapacity >= capacity())
+ return;
+
+ resize(min(m_size, newCapacity));
+
+ T* oldBuffer = begin();
+ if (newCapacity > 0) {
+ T* oldEnd = end();
+ m_buffer.allocateBuffer(newCapacity);
+ if (begin() != oldBuffer)
+ TypeOperations::move(oldBuffer, oldEnd, begin());
+ }
+
+ m_buffer.deallocateBuffer(oldBuffer);
}
// Templatizing these is better than just letting the conversion happen implicitly,
@@ -665,8 +746,11 @@ namespace WTF {
void Vector<T, inlineCapacity>::append(const U* data, size_t dataSize)
{
size_t newSize = m_size + dataSize;
- if (newSize > capacity())
+ if (newSize > capacity()) {
data = expandCapacity(newSize, data);
+ if (!begin())
+ return;
+ }
T* dest = end();
for (size_t i = 0; i < dataSize; ++i)
new (&dest[i]) T(data[i]);
@@ -677,16 +761,19 @@ namespace WTF {
inline void Vector<T, inlineCapacity>::append(const U& val)
{
const U* ptr = &val;
- if (size() == capacity())
+ if (size() == capacity()) {
ptr = expandCapacity(size() + 1, ptr);
+ if (!begin())
+ return;
+ }
+#if COMPILER(MSVC7)
// FIXME: MSVC7 generates compilation errors when trying to assign
// a pointer to a Vector of its base class (i.e. can't downcast). So far
// I've been unable to determine any logical reason for this, so I can
- // only assume it is a bug with the compiler. Casting is very bad
- // however because it subverts implicit conversions, so a better
- // solution is direly needed.
-#if COMPILER(MSVC7)
+ // only assume it is a bug with the compiler. Casting is a bad solution,
+ // however, because it subverts implicit conversions, so a better
+ // one is needed.
new (end()) T(static_cast<T>(*ptr));
#else
new (end()) T(*ptr);
@@ -706,8 +793,11 @@ namespace WTF {
++m_size;
}
- template<typename T, size_t inlineCapacity> template<typename U, size_t c>
- inline void Vector<T, inlineCapacity>::append(const Vector<U, c>& val)
+ // This method should not be called append, a better name would be appendElements.
+ // It could also be eliminated entirely, and call sites could just use
+ // appendRange(val.begin(), val.end()).
+ template<typename T, size_t inlineCapacity> template<size_t otherCapacity>
+ inline void Vector<T, inlineCapacity>::append(const Vector<T, otherCapacity>& val)
{
append(val.begin(), val.size());
}
@@ -717,8 +807,11 @@ namespace WTF {
{
ASSERT(position <= size());
size_t newSize = m_size + dataSize;
- if (newSize > capacity())
+ if (newSize > capacity()) {
data = expandCapacity(newSize, data);
+ if (!begin())
+ return;
+ }
T* spot = begin() + position;
TypeOperations::moveOverlapping(spot, end(), spot + dataSize);
for (size_t i = 0; i < dataSize; ++i)
@@ -731,8 +824,11 @@ namespace WTF {
{
ASSERT(position <= size());
const U* data = &val;
- if (size() == capacity())
+ if (size() == capacity()) {
data = expandCapacity(size() + 1, data);
+ if (!begin())
+ return;
+ }
T* spot = begin() + position;
TypeOperations::moveOverlapping(spot, end(), spot + 1);
new (spot) T(*data);
@@ -774,9 +870,21 @@ namespace WTF {
}
template<typename T, size_t inlineCapacity>
+ inline void Vector<T, inlineCapacity>::remove(size_t position, size_t length)
+ {
+ ASSERT(position < size());
+ ASSERT(position + length < size());
+ T* beginSpot = begin() + position;
+ T* endSpot = beginSpot + length;
+ TypeOperations::destruct(beginSpot, endSpot);
+ TypeOperations::moveOverlapping(endSpot, end(), beginSpot);
+ m_size -= length;
+ }
+
+ template<typename T, size_t inlineCapacity>
inline T* Vector<T, inlineCapacity>::releaseBuffer()
{
- T* buffer = m_impl.releaseBuffer();
+ T* buffer = m_buffer.releaseBuffer();
if (inlineCapacity && !buffer && m_size) {
// If the vector had some data, but no buffer to release,
// that means it was using the inline buffer. In that case,
@@ -785,7 +893,6 @@ namespace WTF {
buffer = static_cast<T*>(fastMalloc(bytes));
memcpy(buffer, data(), bytes);
}
- ASSERT(buffer);
m_size = 0;
return buffer;
}
diff --git a/JavaScriptCore/wtf/VectorTraits.h b/JavaScriptCore/wtf/VectorTraits.h
index c62a0bf..71aaec8 100644
--- a/JavaScriptCore/wtf/VectorTraits.h
+++ b/JavaScriptCore/wtf/VectorTraits.h
@@ -1,4 +1,3 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* This file is part of the KDE libraries
* Copyright (C) 2006 Apple Computer, Inc.
@@ -25,6 +24,7 @@
#include "RefPtr.h"
#include <utility>
+#include <memory>
using std::pair;
@@ -94,6 +94,9 @@ namespace WTF {
template<typename P>
struct VectorTraits<RefPtr<P> > : SimpleClassVectorTraits { };
+ template<typename P>
+ struct VectorTraits<std::auto_ptr<P> > : SimpleClassVectorTraits { };
+
template<typename First, typename Second>
struct VectorTraits<pair<First, Second> >
{
diff --git a/JavaScriptCore/wtf/android/MainThreadAndroid.cpp b/JavaScriptCore/wtf/android/MainThreadAndroid.cpp
new file mode 100644
index 0000000..a6d8eb6
--- /dev/null
+++ b/JavaScriptCore/wtf/android/MainThreadAndroid.cpp
@@ -0,0 +1,35 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "config.h"
+#include "MainThread.h"
+#include "jni/JavaSharedClient.h"
+
+namespace WTF {
+
+// Callback in the main thread.
+static void timeoutFired(void *)
+{
+ dispatchFunctionsFromMainThread();
+}
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+ WebCore::JavaSharedClient::EnqueueFunctionPtr(timeoutFired, NULL);
+}
+
+}
diff --git a/JavaScriptCore/wtf/gtk/MainThreadGtk.cpp b/JavaScriptCore/wtf/gtk/MainThreadGtk.cpp
new file mode 100644
index 0000000..a6e061f
--- /dev/null
+++ b/JavaScriptCore/wtf/gtk/MainThreadGtk.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MainThread.h"
+
+#include <glib.h>
+
+namespace WTF {
+
+static gboolean timeoutFired(gpointer)
+{
+ dispatchFunctionsFromMainThread();
+ return FALSE;
+}
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+ g_timeout_add(0, timeoutFired, 0);
+}
+
+
+}
diff --git a/JavaScriptCore/wtf/mac/MainThreadMac.mm b/JavaScriptCore/wtf/mac/MainThreadMac.mm
new file mode 100644
index 0000000..b04ef0e
--- /dev/null
+++ b/JavaScriptCore/wtf/mac/MainThreadMac.mm
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "MainThread.h"
+
+#import <Foundation/NSThread.h>
+
+@interface WTFMainThreadCaller : NSObject {
+}
+- (void)call;
+@end
+
+@implementation WTFMainThreadCaller
+
+- (void)call
+{
+ WTF::dispatchFunctionsFromMainThread();
+}
+
+@end // implementation WTFMainThreadCaller
+
+namespace WTF {
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+ WTFMainThreadCaller *caller = [[WTFMainThreadCaller alloc] init];
+ [caller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO];
+ [caller release];
+}
+
+} // namespace WTF
diff --git a/JavaScriptCore/wtf/qt/MainThreadQt.cpp b/JavaScriptCore/wtf/qt/MainThreadQt.cpp
new file mode 100644
index 0000000..1914600
--- /dev/null
+++ b/JavaScriptCore/wtf/qt/MainThreadQt.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2007 Staikos Computing Services Inc.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MainThread.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QCoreApplication>
+
+
+namespace WTF {
+
+class MainThreadInvoker : public QObject {
+ Q_OBJECT
+public:
+ MainThreadInvoker();
+
+private Q_SLOTS:
+ void dispatch();
+};
+
+MainThreadInvoker::MainThreadInvoker()
+{
+ moveToThread(QCoreApplication::instance()->thread());
+}
+
+void MainThreadInvoker::dispatch()
+{
+ dispatchFunctionsFromMainThread();
+}
+
+Q_GLOBAL_STATIC(MainThreadInvoker, webkit_main_thread_invoker)
+
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+ QMetaObject::invokeMethod(webkit_main_thread_invoker(), "dispatch", Qt::QueuedConnection);
+}
+
+}
+
+#include "MainThreadQt.moc"
diff --git a/JavaScriptCore/wtf/unicode/Collator.h b/JavaScriptCore/wtf/unicode/Collator.h
new file mode 100644
index 0000000..f04779d
--- /dev/null
+++ b/JavaScriptCore/wtf/unicode/Collator.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WTF_Collator_h
+#define WTF_Collator_h
+
+#include <memory>
+#include <wtf/Noncopyable.h>
+#include <wtf/unicode/Unicode.h>
+
+#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION
+struct UCollator;
+#endif
+
+namespace WTF {
+
+ class Collator : Noncopyable {
+ public:
+ enum Result { Equal = 0, Greater = 1, Less = -1 };
+
+ Collator(const char* locale); // Parsing is lenient; e.g. language identifiers (such as "en-US") are accepted, too.
+ ~Collator();
+ void setOrderLowerFirst(bool);
+
+ static std::auto_ptr<Collator> userDefault();
+
+ Result collate(const ::UChar*, size_t, const ::UChar*, size_t) const;
+
+ private:
+#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION
+ void createCollator() const;
+ void releaseCollator();
+ mutable UCollator* m_collator;
+#endif
+ char* m_locale;
+ bool m_lowerFirst;
+ };
+}
+
+using WTF::Collator;
+
+#endif
diff --git a/JavaScriptCore/wtf/unicode/CollatorDefault.cpp b/JavaScriptCore/wtf/unicode/CollatorDefault.cpp
new file mode 100644
index 0000000..eddbe53
--- /dev/null
+++ b/JavaScriptCore/wtf/unicode/CollatorDefault.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Collator.h"
+
+#if !USE(ICU_UNICODE) || UCONFIG_NO_COLLATION
+
+namespace WTF {
+
+Collator::Collator(const char*)
+{
+}
+
+Collator::~Collator()
+{
+}
+
+void Collator::setOrderLowerFirst(bool)
+{
+}
+
+std::auto_ptr<Collator> Collator::userDefault()
+{
+ return std::auto_ptr<Collator>(new Collator(0));
+}
+
+// A default implementation for platforms that lack Unicode-aware collation.
+Collator::Result Collator::collate(const UChar* lhs, size_t lhsLength, const UChar* rhs, size_t rhsLength) const
+{
+ int lmin = lhsLength < rhsLength ? lhsLength : rhsLength;
+ int l = 0;
+ while (l < lmin && *lhs == *rhs) {
+ lhs++;
+ rhs++;
+ l++;
+ }
+
+ if (l < lmin)
+ return (*lhs > *rhs) ? Greater : Less;
+
+ if (lhsLength == rhsLength)
+ return Equal;
+
+ return (lhsLength > rhsLength) ? Greater : Less;
+}
+
+}
+
+#endif
diff --git a/JavaScriptCore/wtf/unicode/Unicode.h b/JavaScriptCore/wtf/unicode/Unicode.h
index f890afc..9cd3555 100644
--- a/JavaScriptCore/wtf/unicode/Unicode.h
+++ b/JavaScriptCore/wtf/unicode/Unicode.h
@@ -1,4 +1,3 @@
-// -*- c-basic-offset: 2 -*-
/*
* This file is part of the KDE libraries
* Copyright (C) 2006 George Staikos <staikos@kde.org>
diff --git a/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp b/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp
new file mode 100644
index 0000000..a8bcc81
--- /dev/null
+++ b/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Collator.h"
+
+#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION
+
+#include "Assertions.h"
+#include "Threading.h"
+#include <unicode/ucol.h>
+#include <string.h>
+
+#if PLATFORM(DARWIN)
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+namespace WTF {
+
+static UCollator* cachedCollator;
+static Mutex& cachedCollatorMutex()
+{
+ AtomicallyInitializedStatic(Mutex, mutex);
+ return mutex;
+}
+
+Collator::Collator(const char* locale)
+ : m_collator(0)
+ , m_locale(locale ? strdup(locale) : 0)
+ , m_lowerFirst(false)
+{
+}
+
+std::auto_ptr<Collator> Collator::userDefault()
+{
+#if PLATFORM(DARWIN) && PLATFORM(CF)
+ // Mac OS X doesn't set UNIX locale to match user-selected one, so ICU default doesn't work.
+ CFStringRef collationOrder = (CFStringRef)CFPreferencesCopyValue(CFSTR("AppleCollationOrder"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
+ char buf[256];
+ if (collationOrder) {
+ CFStringGetCString(collationOrder, buf, sizeof(buf), kCFStringEncodingASCII);
+ CFRelease(collationOrder);
+ return std::auto_ptr<Collator>(new Collator(buf));
+ } else
+ return std::auto_ptr<Collator>(new Collator(""));
+#else
+ return std::auto_ptr<Collator>(new Collator(0));
+#endif
+}
+
+Collator::~Collator()
+{
+ releaseCollator();
+ free(m_locale);
+}
+
+void Collator::setOrderLowerFirst(bool lowerFirst)
+{
+ m_lowerFirst = lowerFirst;
+}
+
+Collator::Result Collator::collate(const UChar* lhs, size_t lhsLength, const UChar* rhs, size_t rhsLength) const
+{
+ if (!m_collator)
+ createCollator();
+
+ return static_cast<Result>(ucol_strcoll(m_collator, lhs, lhsLength, rhs, rhsLength));
+}
+
+void Collator::createCollator() const
+{
+ ASSERT(!m_collator);
+ UErrorCode status = U_ZERO_ERROR;
+
+ {
+ Locker<Mutex> lock(cachedCollatorMutex());
+ if (cachedCollator) {
+ const char* cachedCollatorLocale = ucol_getLocaleByType(cachedCollator, ULOC_REQUESTED_LOCALE, &status);
+ ASSERT(U_SUCCESS(status));
+ ASSERT(cachedCollatorLocale);
+
+ UColAttributeValue cachedCollatorLowerFirst = ucol_getAttribute(cachedCollator, UCOL_CASE_FIRST, &status);
+ ASSERT(U_SUCCESS(status));
+
+ // FIXME: default locale is never matched, because ucol_getLocaleByType returns the actual one used, not 0.
+ if (m_locale && 0 == strcmp(cachedCollatorLocale, m_locale)
+ && ((UCOL_LOWER_FIRST == cachedCollatorLowerFirst && m_lowerFirst) || (UCOL_UPPER_FIRST == cachedCollatorLowerFirst && !m_lowerFirst))) {
+ m_collator = cachedCollator;
+ cachedCollator = 0;
+ return;
+ }
+ }
+ }
+
+ m_collator = ucol_open(m_locale, &status);
+ if (U_FAILURE(status)) {
+ status = U_ZERO_ERROR;
+ m_collator = ucol_open("", &status); // Fallback to Unicode Collation Algorithm.
+ }
+ ASSERT(U_SUCCESS(status));
+
+ ucol_setAttribute(m_collator, UCOL_CASE_FIRST, m_lowerFirst ? UCOL_LOWER_FIRST : UCOL_UPPER_FIRST, &status);
+ ASSERT(U_SUCCESS(status));
+}
+
+void Collator::releaseCollator()
+{
+ {
+ Locker<Mutex> lock(cachedCollatorMutex());
+ if (cachedCollator)
+ ucol_close(cachedCollator);
+ cachedCollator = m_collator;
+ m_collator = 0;
+ }
+}
+
+}
+
+#endif
diff --git a/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h b/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h
index cc9ab8c..7cdc55c 100644
--- a/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h
+++ b/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h
@@ -1,9 +1,7 @@
-// -*- c-basic-offset: 2 -*-
/*
- * This file is part of the KDE libraries
* Copyright (C) 2006 George Staikos <staikos@kde.org>
* Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
- * Copyright (C) 2007 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2007 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
@@ -25,215 +23,197 @@
#ifndef KJS_UNICODE_ICU_H
#define KJS_UNICODE_ICU_H
+#include <stdlib.h>
#include <unicode/uchar.h>
#include <unicode/ustring.h>
#include <unicode/utf16.h>
-#include <stdlib.h>
-
namespace WTF {
- namespace Unicode {
-
- enum Direction {
- LeftToRight = U_LEFT_TO_RIGHT,
- RightToLeft = U_RIGHT_TO_LEFT,
- EuropeanNumber = U_EUROPEAN_NUMBER,
- EuropeanNumberSeparator = U_EUROPEAN_NUMBER_SEPARATOR,
- EuropeanNumberTerminator = U_EUROPEAN_NUMBER_TERMINATOR,
- ArabicNumber = U_ARABIC_NUMBER,
- CommonNumberSeparator = U_COMMON_NUMBER_SEPARATOR,
- BlockSeparator = U_BLOCK_SEPARATOR,
- SegmentSeparator = U_SEGMENT_SEPARATOR,
- WhiteSpaceNeutral = U_WHITE_SPACE_NEUTRAL,
- OtherNeutral = U_OTHER_NEUTRAL,
- LeftToRightEmbedding = U_LEFT_TO_RIGHT_EMBEDDING,
- LeftToRightOverride = U_LEFT_TO_RIGHT_OVERRIDE,
- RightToLeftArabic = U_RIGHT_TO_LEFT_ARABIC,
- RightToLeftEmbedding = U_RIGHT_TO_LEFT_EMBEDDING,
- RightToLeftOverride = U_RIGHT_TO_LEFT_OVERRIDE,
- PopDirectionalFormat = U_POP_DIRECTIONAL_FORMAT,
- NonSpacingMark = U_DIR_NON_SPACING_MARK,
- BoundaryNeutral = U_BOUNDARY_NEUTRAL
- };
-
- enum DecompositionType {
- DecompositionNone = U_DT_NONE,
- DecompositionCanonical = U_DT_CANONICAL,
- DecompositionCompat = U_DT_COMPAT,
- DecompositionCircle = U_DT_CIRCLE,
- DecompositionFinal = U_DT_FINAL,
- DecompositionFont = U_DT_FONT,
- DecompositionFraction = U_DT_FRACTION,
- DecompositionInitial = U_DT_INITIAL,
- DecompositionIsolated = U_DT_ISOLATED,
- DecompositionMedial = U_DT_MEDIAL,
- DecompositionNarrow = U_DT_NARROW,
- DecompositionNoBreak = U_DT_NOBREAK,
- DecompositionSmall = U_DT_SMALL,
- DecompositionSquare = U_DT_SQUARE,
- DecompositionSub = U_DT_SUB,
- DecompositionSuper = U_DT_SUPER,
- DecompositionVertical = U_DT_VERTICAL,
- DecompositionWide = U_DT_WIDE,
- };
-
- enum CharCategory {
- NoCategory = 0,
- Other_NotAssigned = U_MASK(U_GENERAL_OTHER_TYPES),
- Letter_Uppercase = U_MASK(U_UPPERCASE_LETTER),
- Letter_Lowercase = U_MASK(U_LOWERCASE_LETTER),
- Letter_Titlecase = U_MASK(U_TITLECASE_LETTER),
- Letter_Modifier = U_MASK(U_MODIFIER_LETTER),
- Letter_Other = U_MASK(U_OTHER_LETTER),
-
- Mark_NonSpacing = U_MASK(U_NON_SPACING_MARK),
- Mark_Enclosing = U_MASK(U_ENCLOSING_MARK),
- Mark_SpacingCombining = U_MASK(U_COMBINING_SPACING_MARK),
-
- Number_DecimalDigit = U_MASK(U_DECIMAL_DIGIT_NUMBER),
- Number_Letter = U_MASK(U_LETTER_NUMBER),
- Number_Other = U_MASK(U_OTHER_NUMBER),
-
- Separator_Space = U_MASK(U_SPACE_SEPARATOR),
- Separator_Line = U_MASK(U_LINE_SEPARATOR),
- Separator_Paragraph = U_MASK(U_PARAGRAPH_SEPARATOR),
-
- Other_Control = U_MASK(U_CONTROL_CHAR),
- Other_Format = U_MASK(U_FORMAT_CHAR),
- Other_PrivateUse = U_MASK(U_PRIVATE_USE_CHAR),
- Other_Surrogate = U_MASK(U_SURROGATE),
-
- Punctuation_Dash = U_MASK(U_DASH_PUNCTUATION),
- Punctuation_Open = U_MASK(U_START_PUNCTUATION),
- Punctuation_Close = U_MASK(U_END_PUNCTUATION),
- Punctuation_Connector = U_MASK(U_CONNECTOR_PUNCTUATION),
- Punctuation_Other = U_MASK(U_OTHER_PUNCTUATION),
-
- Symbol_Math = U_MASK(U_MATH_SYMBOL),
- Symbol_Currency = U_MASK(U_CURRENCY_SYMBOL),
- Symbol_Modifier = U_MASK(U_MODIFIER_SYMBOL),
- Symbol_Other = U_MASK(U_OTHER_SYMBOL),
-
- Punctuation_InitialQuote = U_MASK(U_INITIAL_PUNCTUATION),
- Punctuation_FinalQuote = U_MASK(U_FINAL_PUNCTUATION)
- };
-
- inline UChar32 foldCase(UChar32 c)
- {
- return u_foldCase(c, U_FOLD_CASE_DEFAULT);
- }
-
- inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- UErrorCode status = U_ZERO_ERROR;
- int realLength = u_strFoldCase(result, resultLength, src, srcLength, U_FOLD_CASE_DEFAULT, &status);
- *error = !U_SUCCESS(status);
- return realLength;
- }
-
- inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- UErrorCode status = U_ZERO_ERROR;
- int realLength = u_strToLower(result, resultLength, src, srcLength, "", &status);
- *error = !!U_FAILURE(status);
- return realLength;
- }
-
- inline UChar32 toLower(UChar32 c)
- {
- return u_tolower(c);
- }
-
- inline UChar32 toUpper(UChar32 c)
- {
- return u_toupper(c);
- }
-
- inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- UErrorCode status = U_ZERO_ERROR;
- int realLength = u_strToUpper(result, resultLength, src, srcLength, "", &status);
- *error = !!U_FAILURE(status);
- return realLength;
- }
-
- inline UChar32 toTitleCase(UChar32 c)
- {
- return u_totitle(c);
- }
-
- inline bool isArabicChar(UChar32 c)
- {
- return ublock_getCode(c) == UBLOCK_ARABIC;
- }
-
- inline bool isFormatChar(UChar32 c)
- {
- return u_charType(c) == U_FORMAT_CHAR;
- }
-
- inline bool isSeparatorSpace(UChar32 c)
- {
- return u_charType(c) == U_SPACE_SEPARATOR;
- }
-
- inline bool isPrintableChar(UChar32 c)
- {
- return !!u_isprint(c);
- }
-
- inline bool isDigit(UChar32 c)
- {
- return !!u_isdigit(c);
- }
-
- inline bool isPunct(UChar32 c)
- {
- return !!u_ispunct(c);
- }
-
- inline UChar32 mirroredChar(UChar32 c)
- {
- return u_charMirror(c);
- }
-
- inline CharCategory category(UChar32 c)
- {
- return static_cast<CharCategory>(U_GET_GC_MASK(c));
- }
-
- inline Direction direction(UChar32 c)
- {
- return static_cast<Direction>(u_charDirection(c));
- }
-
- inline bool isLower(UChar32 c)
- {
- return !!u_islower(c);
- }
-
- inline int digitValue(UChar32 c)
- {
- return u_charDigitValue(c);
- }
-
- inline uint8_t combiningClass(UChar32 c)
- {
- return u_getCombiningClass(c);
- }
-
- inline DecompositionType decompositionType(UChar32 c)
- {
- return static_cast<DecompositionType>(u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE));
- }
-
- inline int umemcasecmp(const UChar* a, const UChar* b, int len)
- {
- return u_memcasecmp(a, b, len, U_FOLD_CASE_DEFAULT);
- }
-
- }
+namespace Unicode {
+
+enum Direction {
+ LeftToRight = U_LEFT_TO_RIGHT,
+ RightToLeft = U_RIGHT_TO_LEFT,
+ EuropeanNumber = U_EUROPEAN_NUMBER,
+ EuropeanNumberSeparator = U_EUROPEAN_NUMBER_SEPARATOR,
+ EuropeanNumberTerminator = U_EUROPEAN_NUMBER_TERMINATOR,
+ ArabicNumber = U_ARABIC_NUMBER,
+ CommonNumberSeparator = U_COMMON_NUMBER_SEPARATOR,
+ BlockSeparator = U_BLOCK_SEPARATOR,
+ SegmentSeparator = U_SEGMENT_SEPARATOR,
+ WhiteSpaceNeutral = U_WHITE_SPACE_NEUTRAL,
+ OtherNeutral = U_OTHER_NEUTRAL,
+ LeftToRightEmbedding = U_LEFT_TO_RIGHT_EMBEDDING,
+ LeftToRightOverride = U_LEFT_TO_RIGHT_OVERRIDE,
+ RightToLeftArabic = U_RIGHT_TO_LEFT_ARABIC,
+ RightToLeftEmbedding = U_RIGHT_TO_LEFT_EMBEDDING,
+ RightToLeftOverride = U_RIGHT_TO_LEFT_OVERRIDE,
+ PopDirectionalFormat = U_POP_DIRECTIONAL_FORMAT,
+ NonSpacingMark = U_DIR_NON_SPACING_MARK,
+ BoundaryNeutral = U_BOUNDARY_NEUTRAL
+};
+
+enum DecompositionType {
+ DecompositionNone = U_DT_NONE,
+ DecompositionCanonical = U_DT_CANONICAL,
+ DecompositionCompat = U_DT_COMPAT,
+ DecompositionCircle = U_DT_CIRCLE,
+ DecompositionFinal = U_DT_FINAL,
+ DecompositionFont = U_DT_FONT,
+ DecompositionFraction = U_DT_FRACTION,
+ DecompositionInitial = U_DT_INITIAL,
+ DecompositionIsolated = U_DT_ISOLATED,
+ DecompositionMedial = U_DT_MEDIAL,
+ DecompositionNarrow = U_DT_NARROW,
+ DecompositionNoBreak = U_DT_NOBREAK,
+ DecompositionSmall = U_DT_SMALL,
+ DecompositionSquare = U_DT_SQUARE,
+ DecompositionSub = U_DT_SUB,
+ DecompositionSuper = U_DT_SUPER,
+ DecompositionVertical = U_DT_VERTICAL,
+ DecompositionWide = U_DT_WIDE,
+};
+
+enum CharCategory {
+ NoCategory = 0,
+ Other_NotAssigned = U_MASK(U_GENERAL_OTHER_TYPES),
+ Letter_Uppercase = U_MASK(U_UPPERCASE_LETTER),
+ Letter_Lowercase = U_MASK(U_LOWERCASE_LETTER),
+ Letter_Titlecase = U_MASK(U_TITLECASE_LETTER),
+ Letter_Modifier = U_MASK(U_MODIFIER_LETTER),
+ Letter_Other = U_MASK(U_OTHER_LETTER),
+
+ Mark_NonSpacing = U_MASK(U_NON_SPACING_MARK),
+ Mark_Enclosing = U_MASK(U_ENCLOSING_MARK),
+ Mark_SpacingCombining = U_MASK(U_COMBINING_SPACING_MARK),
+
+ Number_DecimalDigit = U_MASK(U_DECIMAL_DIGIT_NUMBER),
+ Number_Letter = U_MASK(U_LETTER_NUMBER),
+ Number_Other = U_MASK(U_OTHER_NUMBER),
+
+ Separator_Space = U_MASK(U_SPACE_SEPARATOR),
+ Separator_Line = U_MASK(U_LINE_SEPARATOR),
+ Separator_Paragraph = U_MASK(U_PARAGRAPH_SEPARATOR),
+
+ Other_Control = U_MASK(U_CONTROL_CHAR),
+ Other_Format = U_MASK(U_FORMAT_CHAR),
+ Other_PrivateUse = U_MASK(U_PRIVATE_USE_CHAR),
+ Other_Surrogate = U_MASK(U_SURROGATE),
+
+ Punctuation_Dash = U_MASK(U_DASH_PUNCTUATION),
+ Punctuation_Open = U_MASK(U_START_PUNCTUATION),
+ Punctuation_Close = U_MASK(U_END_PUNCTUATION),
+ Punctuation_Connector = U_MASK(U_CONNECTOR_PUNCTUATION),
+ Punctuation_Other = U_MASK(U_OTHER_PUNCTUATION),
+
+ Symbol_Math = U_MASK(U_MATH_SYMBOL),
+ Symbol_Currency = U_MASK(U_CURRENCY_SYMBOL),
+ Symbol_Modifier = U_MASK(U_MODIFIER_SYMBOL),
+ Symbol_Other = U_MASK(U_OTHER_SYMBOL),
+
+ Punctuation_InitialQuote = U_MASK(U_INITIAL_PUNCTUATION),
+ Punctuation_FinalQuote = U_MASK(U_FINAL_PUNCTUATION)
+};
+
+inline UChar32 foldCase(UChar32 c)
+{
+ return u_foldCase(c, U_FOLD_CASE_DEFAULT);
+}
+
+inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int realLength = u_strFoldCase(result, resultLength, src, srcLength, U_FOLD_CASE_DEFAULT, &status);
+ *error = !U_SUCCESS(status);
+ return realLength;
+}
+
+inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int realLength = u_strToLower(result, resultLength, src, srcLength, "", &status);
+ *error = !!U_FAILURE(status);
+ return realLength;
+}
+
+inline UChar32 toLower(UChar32 c)
+{
+ return u_tolower(c);
+}
+
+inline UChar32 toUpper(UChar32 c)
+{
+ return u_toupper(c);
+}
+
+inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int realLength = u_strToUpper(result, resultLength, src, srcLength, "", &status);
+ *error = !!U_FAILURE(status);
+ return realLength;
+}
+
+inline UChar32 toTitleCase(UChar32 c)
+{
+ return u_totitle(c);
+}
+
+inline bool isArabicChar(UChar32 c)
+{
+ return ublock_getCode(c) == UBLOCK_ARABIC;
+}
+
+inline bool isSeparatorSpace(UChar32 c)
+{
+ return u_charType(c) == U_SPACE_SEPARATOR;
}
+inline bool isPrintableChar(UChar32 c)
+{
+ return !!u_isprint(c);
+}
+
+inline bool isPunct(UChar32 c)
+{
+ return !!u_ispunct(c);
+}
+
+inline UChar32 mirroredChar(UChar32 c)
+{
+ return u_charMirror(c);
+}
+
+inline CharCategory category(UChar32 c)
+{
+ return static_cast<CharCategory>(U_GET_GC_MASK(c));
+}
+
+inline Direction direction(UChar32 c)
+{
+ return static_cast<Direction>(u_charDirection(c));
+}
+
+inline bool isLower(UChar32 c)
+{
+ return !!u_islower(c);
+}
+
+inline uint8_t combiningClass(UChar32 c)
+{
+ return u_getCombiningClass(c);
+}
+
+inline DecompositionType decompositionType(UChar32 c)
+{
+ return static_cast<DecompositionType>(u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE));
+}
+
+inline int umemcasecmp(const UChar* a, const UChar* b, int len)
+{
+ return u_memcasecmp(a, b, len, U_FOLD_CASE_DEFAULT);
+}
+
+} }
+
#endif
-// vim: ts=2 sw=2 et
diff --git a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h
index 0fbd869..d285a8f 100644
--- a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h
+++ b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h
@@ -1,5 +1,4 @@
/*
- * This file is part of the KDE libraries
* Copyright (C) 2006 George Staikos <staikos@kde.org>
* Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
*
@@ -31,6 +30,7 @@
#include <stdint.h>
#if QT_VERSION >= 0x040300
+QT_BEGIN_NAMESPACE
namespace QUnicodeTables {
struct Properties {
ushort category : 8;
@@ -53,6 +53,7 @@ namespace QUnicodeTables {
Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4);
Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2);
}
+QT_END_NAMESPACE
#endif
// ugly hack to make UChar compatible with JSChar in API/JSStringRef.h
@@ -93,455 +94,432 @@ typedef uint32_t UChar32;
#define U_MASK(x) ((uint32_t)1<<(x))
namespace WTF {
- namespace Unicode {
-
- enum Direction {
- LeftToRight = QChar::DirL,
- RightToLeft = QChar::DirR,
- EuropeanNumber = QChar::DirEN,
- EuropeanNumberSeparator = QChar::DirES,
- EuropeanNumberTerminator = QChar::DirET,
- ArabicNumber = QChar::DirAN,
- CommonNumberSeparator = QChar::DirCS,
- BlockSeparator = QChar::DirB,
- SegmentSeparator = QChar::DirS,
- WhiteSpaceNeutral = QChar::DirWS,
- OtherNeutral = QChar::DirON,
- LeftToRightEmbedding = QChar::DirLRE,
- LeftToRightOverride = QChar::DirLRO,
- RightToLeftArabic = QChar::DirAL,
- RightToLeftEmbedding = QChar::DirRLE,
- RightToLeftOverride = QChar::DirRLO,
- PopDirectionalFormat = QChar::DirPDF,
- NonSpacingMark = QChar::DirNSM,
- BoundaryNeutral = QChar::DirBN
- };
-
- enum DecompositionType {
- DecompositionNone = QChar::NoDecomposition,
- DecompositionCanonical = QChar::Canonical,
- DecompositionCompat = QChar::Compat,
- DecompositionCircle = QChar::Circle,
- DecompositionFinal = QChar::Final,
- DecompositionFont = QChar::Font,
- DecompositionFraction = QChar::Fraction,
- DecompositionInitial = QChar::Initial,
- DecompositionIsolated = QChar::Isolated,
- DecompositionMedial = QChar::Medial,
- DecompositionNarrow = QChar::Narrow,
- DecompositionNoBreak = QChar::NoBreak,
- DecompositionSmall = QChar::Small,
- DecompositionSquare = QChar::Square,
- DecompositionSub = QChar::Sub,
- DecompositionSuper = QChar::Super,
- DecompositionVertical = QChar::Vertical,
- DecompositionWide = QChar::Wide
- };
-
- enum CharCategory {
- NoCategory = 0,
- Mark_NonSpacing = U_MASK(QChar::Mark_NonSpacing),
- Mark_SpacingCombining = U_MASK(QChar::Mark_SpacingCombining),
- Mark_Enclosing = U_MASK(QChar::Mark_Enclosing),
- Number_DecimalDigit = U_MASK(QChar::Number_DecimalDigit),
- Number_Letter = U_MASK(QChar::Number_Letter),
- Number_Other = U_MASK(QChar::Number_Other),
- Separator_Space = U_MASK(QChar::Separator_Space),
- Separator_Line = U_MASK(QChar::Separator_Line),
- Separator_Paragraph = U_MASK(QChar::Separator_Paragraph),
- Other_Control = U_MASK(QChar::Other_Control),
- Other_Format = U_MASK(QChar::Other_Format),
- Other_Surrogate = U_MASK(QChar::Other_Surrogate),
- Other_PrivateUse = U_MASK(QChar::Other_PrivateUse),
- Other_NotAssigned = U_MASK(QChar::Other_NotAssigned),
- Letter_Uppercase = U_MASK(QChar::Letter_Uppercase),
- Letter_Lowercase = U_MASK(QChar::Letter_Lowercase),
- Letter_Titlecase = U_MASK(QChar::Letter_Titlecase),
- Letter_Modifier = U_MASK(QChar::Letter_Modifier),
- Letter_Other = U_MASK(QChar::Letter_Other),
- Punctuation_Connector = U_MASK(QChar::Punctuation_Connector),
- Punctuation_Dash = U_MASK(QChar::Punctuation_Dash),
- Punctuation_Open = U_MASK(QChar::Punctuation_Open),
- Punctuation_Close = U_MASK(QChar::Punctuation_Close),
- Punctuation_InitialQuote = U_MASK(QChar::Punctuation_InitialQuote),
- Punctuation_FinalQuote = U_MASK(QChar::Punctuation_FinalQuote),
- Punctuation_Other = U_MASK(QChar::Punctuation_Other),
- 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),
- };
+namespace Unicode {
+
+enum Direction {
+ LeftToRight = QChar::DirL,
+ RightToLeft = QChar::DirR,
+ EuropeanNumber = QChar::DirEN,
+ EuropeanNumberSeparator = QChar::DirES,
+ EuropeanNumberTerminator = QChar::DirET,
+ ArabicNumber = QChar::DirAN,
+ CommonNumberSeparator = QChar::DirCS,
+ BlockSeparator = QChar::DirB,
+ SegmentSeparator = QChar::DirS,
+ WhiteSpaceNeutral = QChar::DirWS,
+ OtherNeutral = QChar::DirON,
+ LeftToRightEmbedding = QChar::DirLRE,
+ LeftToRightOverride = QChar::DirLRO,
+ RightToLeftArabic = QChar::DirAL,
+ RightToLeftEmbedding = QChar::DirRLE,
+ RightToLeftOverride = QChar::DirRLO,
+ PopDirectionalFormat = QChar::DirPDF,
+ NonSpacingMark = QChar::DirNSM,
+ BoundaryNeutral = QChar::DirBN
+};
+
+enum DecompositionType {
+ DecompositionNone = QChar::NoDecomposition,
+ DecompositionCanonical = QChar::Canonical,
+ DecompositionCompat = QChar::Compat,
+ DecompositionCircle = QChar::Circle,
+ DecompositionFinal = QChar::Final,
+ DecompositionFont = QChar::Font,
+ DecompositionFraction = QChar::Fraction,
+ DecompositionInitial = QChar::Initial,
+ DecompositionIsolated = QChar::Isolated,
+ DecompositionMedial = QChar::Medial,
+ DecompositionNarrow = QChar::Narrow,
+ DecompositionNoBreak = QChar::NoBreak,
+ DecompositionSmall = QChar::Small,
+ DecompositionSquare = QChar::Square,
+ DecompositionSub = QChar::Sub,
+ DecompositionSuper = QChar::Super,
+ DecompositionVertical = QChar::Vertical,
+ DecompositionWide = QChar::Wide
+};
+
+enum CharCategory {
+ NoCategory = 0,
+ Mark_NonSpacing = U_MASK(QChar::Mark_NonSpacing),
+ Mark_SpacingCombining = U_MASK(QChar::Mark_SpacingCombining),
+ Mark_Enclosing = U_MASK(QChar::Mark_Enclosing),
+ Number_DecimalDigit = U_MASK(QChar::Number_DecimalDigit),
+ Number_Letter = U_MASK(QChar::Number_Letter),
+ Number_Other = U_MASK(QChar::Number_Other),
+ Separator_Space = U_MASK(QChar::Separator_Space),
+ Separator_Line = U_MASK(QChar::Separator_Line),
+ Separator_Paragraph = U_MASK(QChar::Separator_Paragraph),
+ Other_Control = U_MASK(QChar::Other_Control),
+ Other_Format = U_MASK(QChar::Other_Format),
+ Other_Surrogate = U_MASK(QChar::Other_Surrogate),
+ Other_PrivateUse = U_MASK(QChar::Other_PrivateUse),
+ Other_NotAssigned = U_MASK(QChar::Other_NotAssigned),
+ Letter_Uppercase = U_MASK(QChar::Letter_Uppercase),
+ Letter_Lowercase = U_MASK(QChar::Letter_Lowercase),
+ Letter_Titlecase = U_MASK(QChar::Letter_Titlecase),
+ Letter_Modifier = U_MASK(QChar::Letter_Modifier),
+ Letter_Other = U_MASK(QChar::Letter_Other),
+ Punctuation_Connector = U_MASK(QChar::Punctuation_Connector),
+ Punctuation_Dash = U_MASK(QChar::Punctuation_Dash),
+ Punctuation_Open = U_MASK(QChar::Punctuation_Open),
+ Punctuation_Close = U_MASK(QChar::Punctuation_Close),
+ Punctuation_InitialQuote = U_MASK(QChar::Punctuation_InitialQuote),
+ Punctuation_FinalQuote = U_MASK(QChar::Punctuation_FinalQuote),
+ Punctuation_Other = U_MASK(QChar::Punctuation_Other),
+ 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),
+};
#if QT_VERSION >= 0x040300
- // FIXME: handle surrogates correctly in all methods
- inline UChar32 toLower(UChar32 ch)
- {
- return QChar::toLower(ch);
- }
+// FIXME: handle surrogates correctly in all methods
- inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- const UChar *e = src + srcLength;
- const UChar *s = src;
- UChar *r = result;
- UChar *re = result + resultLength;
-
- // this avoids one out of bounds check in the loop
- if (QChar(*s).isLowSurrogate())
- *r++ = *s++;
-
- int needed = 0;
- while (s < e && r < re) {
- uint c = *s;
- if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate())
- c = QChar::surrogateToUcs4(*(s - 1), c);
- const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c);
- if (prop->lowerCaseSpecial) {
- QString qstring;
- if (c < 0x10000) {
- qstring += QChar(c);
- } else {
- qstring += QChar(*(s-1));
- qstring += QChar(*s);
- }
- qstring = qstring.toLower();
- for (int i = 0; i < qstring.length(); ++i) {
- if (r == re) {
- needed += qstring.length() - i;
- break;
- }
- *r = qstring.at(i).unicode();
- ++r;
- }
+inline UChar32 toLower(UChar32 ch)
+{
+ return QChar::toLower(ch);
+}
+
+inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ const UChar *e = src + srcLength;
+ const UChar *s = src;
+ UChar *r = result;
+ uint rindex = 0;
+
+ // this avoids one out of bounds check in the loop
+ if (s < e && QChar(*s).isLowSurrogate()) {
+ if (r)
+ r[rindex] = *s++;
+ ++rindex;
+ }
+
+ int needed = 0;
+ while (s < e && (rindex < uint(resultLength) || !r)) {
+ uint c = *s;
+ if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate())
+ c = QChar::surrogateToUcs4(*(s - 1), c);
+ const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c);
+ if (prop->lowerCaseSpecial) {
+ QString qstring;
+ if (c < 0x10000) {
+ qstring += QChar(c);
} else {
- *r = *s + prop->lowerCaseDiff;
- ++r;
+ qstring += QChar(*(s-1));
+ qstring += QChar(*s);
}
- ++s;
+ qstring = qstring.toLower();
+ for (int i = 0; i < qstring.length(); ++i) {
+ if (rindex >= uint(resultLength)) {
+ needed += qstring.length() - i;
+ break;
+ }
+ if (r)
+ r[rindex] = qstring.at(i).unicode();
+ ++rindex;
+ }
+ } else {
+ if (r)
+ r[rindex] = *s + prop->lowerCaseDiff;
+ ++rindex;
}
- if (s < e)
- needed += e - s;
- *error = (needed != 0);
- if (r < re)
- *r = 0;
- return (r - result) + needed;
- }
+ ++s;
+ }
+ if (s < e)
+ needed += e - s;
+ *error = (needed != 0);
+ if (rindex < uint(resultLength))
+ r[rindex] = 0;
+ return rindex + needed;
+}
- inline UChar32 toUpper(UChar32 ch)
- {
- return QChar::toUpper(ch);
- }
+inline UChar32 toUpper(UChar32 ch)
+{
+ return QChar::toUpper(ch);
+}
- inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- const UChar *e = src + srcLength;
- const UChar *s = src;
- UChar *r = result;
- UChar *re = result + resultLength;
-
- // this avoids one out of bounds check in the loop
- if (QChar(*s).isLowSurrogate())
- *r++ = *s++;
-
- int needed = 0;
- while (s < e && r < re) {
- uint c = *s;
- if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate())
- c = QChar::surrogateToUcs4(*(s - 1), c);
- const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c);
- if (prop->upperCaseSpecial) {
- QString qstring;
- if (c < 0x10000) {
- qstring += QChar(c);
- } else {
- qstring += QChar(*(s-1));
- qstring += QChar(*s);
- }
- qstring = qstring.toUpper();
- for (int i = 0; i < qstring.length(); ++i) {
- if (r == re) {
- needed += qstring.length() - i;
- break;
- }
- *r = qstring.at(i).unicode();
- ++r;
- }
+inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ const UChar *e = src + srcLength;
+ const UChar *s = src;
+ UChar *r = result;
+ int rindex = 0;
+
+ // this avoids one out of bounds check in the loop
+ if (s < e && QChar(*s).isLowSurrogate()) {
+ if (r)
+ r[rindex] = *s++;
+ ++rindex;
+ }
+
+ int needed = 0;
+ while (s < e && (rindex < resultLength || !r)) {
+ uint c = *s;
+ if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate())
+ c = QChar::surrogateToUcs4(*(s - 1), c);
+ const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c);
+ if (prop->upperCaseSpecial) {
+ QString qstring;
+ if (c < 0x10000) {
+ qstring += QChar(c);
} else {
- *r = *s + prop->upperCaseDiff;
- ++r;
+ qstring += QChar(*(s-1));
+ qstring += QChar(*s);
+ }
+ qstring = qstring.toUpper();
+ for (int i = 0; i < qstring.length(); ++i) {
+ if (rindex >= resultLength) {
+ needed += qstring.length() - i;
+ break;
+ }
+ if (r)
+ r[rindex] = qstring.at(i).unicode();
+ ++rindex;
}
- ++s;
+ } else {
+ if (r)
+ r[rindex] = *s + prop->upperCaseDiff;
+ ++rindex;
}
- if (s < e)
- needed += e - s;
- *error = (needed != 0);
- if (r < re)
- *r = 0;
- return (r - result) + needed;
- }
+ ++s;
+ }
+ if (s < e)
+ needed += e - s;
+ *error = (needed != 0);
+ if (rindex < resultLength)
+ r[rindex] = 0;
+ return rindex + needed;
+}
- inline int toTitleCase(UChar32 c)
- {
- return QChar::toTitleCase(c);
- }
+inline int toTitleCase(UChar32 c)
+{
+ return QChar::toTitleCase(c);
+}
- inline UChar32 foldCase(UChar32 c)
- {
- return QChar::toCaseFolded(c);
- }
+inline UChar32 foldCase(UChar32 c)
+{
+ return QChar::toCaseFolded(c);
+}
- inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- // FIXME: handle special casing. Easiest with some low level API in Qt
- *error = false;
- if (resultLength < srcLength) {
+inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ // FIXME: handle special casing. Easiest with some low level API in Qt
+ *error = false;
+ if (resultLength < srcLength) {
*error = true;
return srcLength;
- }
- for (int i = 0; i < srcLength; ++i)
- result[i] = QChar::toCaseFolded(src[i]);
- return srcLength;
- }
-
- inline bool isFormatChar(UChar32 c)
- {
- return QChar::category(c) == QChar::Other_Format;
- }
-
- inline bool isArabicChar(UChar32 c)
- {
- return c >= 0x0600 && c <= 0x06FF;
- }
-
- inline bool isPrintableChar(UChar32 c)
- {
- const uint test = U_MASK(QChar::Other_Control) |
- U_MASK(QChar::Other_NotAssigned);
- return !(U_MASK(QChar::category(c)) & test);
}
+ for (int i = 0; i < srcLength; ++i)
+ result[i] = QChar::toCaseFolded(ushort(src[i]));
+ return srcLength;
+}
- inline bool isSeparatorSpace(UChar32 c)
- {
- return QChar::category(c) == QChar::Separator_Space;
- }
+inline bool isArabicChar(UChar32 c)
+{
+ return c >= 0x0600 && c <= 0x06FF;
+}
- inline bool isPunct(UChar32 c)
- {
- const uint test = U_MASK(QChar::Punctuation_Connector) |
- U_MASK(QChar::Punctuation_Dash) |
- U_MASK(QChar::Punctuation_Open) |
- U_MASK(QChar::Punctuation_Close) |
- U_MASK(QChar::Punctuation_InitialQuote) |
- U_MASK(QChar::Punctuation_FinalQuote) |
- U_MASK(QChar::Punctuation_Other);
- return U_MASK(QChar::category(c)) & test;
- }
+inline bool isPrintableChar(UChar32 c)
+{
+ const uint test = U_MASK(QChar::Other_Control) |
+ U_MASK(QChar::Other_NotAssigned);
+ return !(U_MASK(QChar::category(c)) & test);
+}
- inline bool isDigit(UChar32 c)
- {
- return QChar::category(c) == QChar::Number_DecimalDigit;
- }
+inline bool isSeparatorSpace(UChar32 c)
+{
+ return QChar::category(c) == QChar::Separator_Space;
+}
- inline bool isLower(UChar32 c)
- {
- return QChar::category(c) == QChar::Letter_Lowercase;
- }
+inline bool isPunct(UChar32 c)
+{
+ const uint test = U_MASK(QChar::Punctuation_Connector) |
+ U_MASK(QChar::Punctuation_Dash) |
+ U_MASK(QChar::Punctuation_Open) |
+ U_MASK(QChar::Punctuation_Close) |
+ U_MASK(QChar::Punctuation_InitialQuote) |
+ U_MASK(QChar::Punctuation_FinalQuote) |
+ U_MASK(QChar::Punctuation_Other);
+ return U_MASK(QChar::category(c)) & test;
+}
- inline int digitValue(UChar32 c)
- {
- return QChar::digitValue(c);
- }
+inline bool isLower(UChar32 c)
+{
+ return QChar::category(c) == QChar::Letter_Lowercase;
+}
- inline UChar32 mirroredChar(UChar32 c)
- {
- return QChar::mirroredChar(c);
- }
+inline UChar32 mirroredChar(UChar32 c)
+{
+ return QChar::mirroredChar(c);
+}
- inline uint8_t combiningClass(UChar32 c)
- {
- return QChar::combiningClass(c);
- }
+inline uint8_t combiningClass(UChar32 c)
+{
+ return QChar::combiningClass(c);
+}
- inline DecompositionType decompositionType(UChar32 c)
- {
- return (DecompositionType)QChar::decompositionTag(c);
- }
+inline DecompositionType decompositionType(UChar32 c)
+{
+ return (DecompositionType)QChar::decompositionTag(c);
+}
- inline int umemcasecmp(const UChar* a, const UChar* b, int len)
- {
- // handle surrogates correctly
- for (int i = 0; i < len; ++i) {
- uint c1 = QChar::toCaseFolded(a[i]);
- uint c2 = QChar::toCaseFolded(b[i]);
- if (c1 != c2)
- return c1 - c2;
- }
- return 0;
+inline int umemcasecmp(const UChar* a, const UChar* b, int len)
+{
+ // handle surrogates correctly
+ for (int i = 0; i < len; ++i) {
+ uint c1 = QChar::toCaseFolded(ushort(a[i]));
+ uint c2 = QChar::toCaseFolded(ushort(b[i]));
+ if (c1 != c2)
+ return c1 - c2;
}
+ return 0;
+}
- inline Direction direction(UChar32 c)
- {
- return (Direction)QChar::direction(c);
- }
+inline Direction direction(UChar32 c)
+{
+ return (Direction)QChar::direction(c);
+}
- inline CharCategory category(UChar32 c)
- {
- return (CharCategory) U_MASK(QChar::category(c));
- }
+inline CharCategory category(UChar32 c)
+{
+ return (CharCategory) U_MASK(QChar::category(c));
+}
#else
- inline UChar32 toLower(UChar32 ch)
- {
- if (ch > 0xffff)
+inline UChar32 toLower(UChar32 ch)
+{
+ if (ch > 0xffff)
return ch;
- return QChar((unsigned short)ch).toLower().unicode();
- }
+ return QChar((unsigned short)ch).toLower().unicode();
+}
- inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- *error = false;
- if (resultLength < srcLength) {
- *error = true;
- return srcLength;
- }
- for (int i = 0; i < srcLength; ++i)
- result[i] = QChar(src[i]).toLower().unicode();
- return srcLength;
- }
+inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ *error = false;
+ if (resultLength < srcLength) {
+ *error = true;
+ return srcLength;
+ }
+ for (int i = 0; i < srcLength; ++i)
+ result[i] = QChar(src[i]).toLower().unicode();
+ return srcLength;
+}
- inline UChar32 toUpper(UChar32 ch)
- {
- if (ch > 0xffff)
+inline UChar32 toUpper(UChar32 ch)
+{
+ if (ch > 0xffff)
return ch;
- return QChar((unsigned short)ch).toUpper().unicode();
- }
+ return QChar((unsigned short)ch).toUpper().unicode();
+}
- inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- *error = false;
- if (resultLength < srcLength) {
+inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ *error = false;
+ if (resultLength < srcLength) {
*error = true;
return srcLength;
- }
- for (int i = 0; i < srcLength; ++i)
- result[i] = QChar(src[i]).toUpper().unicode();
- return srcLength;
}
+ for (int i = 0; i < srcLength; ++i)
+ result[i] = QChar(src[i]).toUpper().unicode();
+ return srcLength;
+}
- inline int toTitleCase(UChar32 c)
- {
- if (c > 0xffff)
+inline int toTitleCase(UChar32 c)
+{
+ if (c > 0xffff)
return c;
- return QChar((unsigned short)c).toUpper().unicode();
- }
+ return QChar((unsigned short)c).toUpper().unicode();
+}
- inline UChar32 foldCase(UChar32 c)
- {
- if (c > 0xffff)
+inline UChar32 foldCase(UChar32 c)
+{
+ if (c > 0xffff)
return c;
- return QChar((unsigned short)c).toLower().unicode();
- }
-
- inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- return toLower(result, resultLength, src, srcLength, error);
- }
-
- inline bool isFormatChar(UChar32 c)
- {
- return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Other_Format;
- }
-
- inline bool isPrintableChar(UChar32 c)
- {
- return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isPrint();
- }
+ return QChar((unsigned short)c).toLower().unicode();
+}
- inline bool isArabicChar(UChar32 c)
- {
- return c >= 0x0600 && c <= 0x06FF;
- }
+inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ return toLower(result, resultLength, src, srcLength, error);
+}
- inline bool isSeparatorSpace(UChar32 c)
- {
- return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Separator_Space;
- }
+inline bool isPrintableChar(UChar32 c)
+{
+ return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isPrint();
+}
- inline bool isPunct(UChar32 c)
- {
- return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isPunct();
- }
+inline bool isArabicChar(UChar32 c)
+{
+ return c >= 0x0600 && c <= 0x06FF;
+}
- inline bool isDigit(UChar32 c)
- {
- return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isDigit();
- }
+inline bool isSeparatorSpace(UChar32 c)
+{
+ return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Separator_Space;
+}
- inline bool isLower(UChar32 c)
- {
- return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Letter_Lowercase;
- }
+inline bool isPunct(UChar32 c)
+{
+ return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isPunct();
+}
- inline int digitValue(UChar32 c)
- {
- if (c > 0xffff)
- return 0;
- return QChar(c).digitValue();
- }
+inline bool isLower(UChar32 c)
+{
+ return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Letter_Lowercase;
+}
- inline UChar32 mirroredChar(UChar32 c)
- {
- if (c > 0xffff)
+inline UChar32 mirroredChar(UChar32 c)
+{
+ if (c > 0xffff)
return c;
- return QChar(c).mirroredChar().unicode();
- }
+ return QChar(c).mirroredChar().unicode();
+}
- inline uint8_t combiningClass(UChar32 c)
- {
- if (c > 0xffff)
+inline uint8_t combiningClass(UChar32 c)
+{
+ if (c > 0xffff)
return 0;
- return QChar((unsigned short)c).combiningClass();
- }
+ return QChar((unsigned short)c).combiningClass();
+}
- inline DecompositionType decompositionType(UChar32 c)
- {
- if (c > 0xffff)
+inline DecompositionType decompositionType(UChar32 c)
+{
+ if (c > 0xffff)
return DecompositionNone;
- return (DecompositionType)QChar(c).decompositionTag();
- }
+ return (DecompositionType)QChar(c).decompositionTag();
+}
- inline int umemcasecmp(const UChar* a, const UChar* b, int len)
- {
- for (int i = 0; i < len; ++i) {
+inline int umemcasecmp(const UChar* a, const UChar* b, int len)
+{
+ for (int i = 0; i < len; ++i) {
QChar c1 = QChar(a[i]).toLower();
QChar c2 = QChar(b[i]).toLower();
if (c1 != c2)
- return c1.unicode() - c2.unicode();
- }
- return 0;
+ return c1.unicode() - c2.unicode();
}
+ return 0;
+}
- inline Direction direction(UChar32 c)
- {
- if (c > 0xffff)
+inline Direction direction(UChar32 c)
+{
+ if (c > 0xffff)
return LeftToRight;
- return (Direction)QChar(c).direction();
- }
+ return (Direction)QChar(c).direction();
+}
- inline CharCategory category(UChar32 c)
- {
- if (c > 0xffff)
+inline CharCategory category(UChar32 c)
+{
+ if (c > 0xffff)
return NoCategory;
- return (CharCategory) U_MASK(QChar(c).category());
- }
+ return (CharCategory) U_MASK(QChar(c).category());
+}
#endif
- }
-}
+} }
#endif
-// vim: ts=2 sw=2 et
diff --git a/JavaScriptCore/wtf/win/MainThreadWin.cpp b/JavaScriptCore/wtf/win/MainThreadWin.cpp
new file mode 100644
index 0000000..9f05d22
--- /dev/null
+++ b/JavaScriptCore/wtf/win/MainThreadWin.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MainThread.h"
+
+#include "Assertions.h"
+#include "Threading.h"
+#include <windows.h>
+
+namespace WTF {
+
+static HWND threadingWindowHandle;
+static UINT threadingFiredMessage;
+const LPCWSTR kThreadingWindowClassName = L"ThreadingWindowClass";
+
+LRESULT CALLBACK ThreadingWindowWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (message == threadingFiredMessage)
+ dispatchFunctionsFromMainThread();
+ else
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ return 0;
+}
+
+void initializeMainThread()
+{
+ if (threadingWindowHandle)
+ return;
+
+ mainThreadFunctionQueueMutex();
+
+ WNDCLASSEX wcex;
+ memset(&wcex, 0, sizeof(WNDCLASSEX));
+ wcex.cbSize = sizeof(WNDCLASSEX);
+ wcex.lpfnWndProc = ThreadingWindowWndProc;
+ wcex.lpszClassName = kThreadingWindowClassName;
+ RegisterClassEx(&wcex);
+
+ threadingWindowHandle = CreateWindow(kThreadingWindowClassName, 0, 0,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, 0, 0, 0);
+ threadingFiredMessage = RegisterWindowMessage(L"com.apple.WebKit.MainThreadFired");
+}
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+ ASSERT(threadingWindowHandle);
+ PostMessage(threadingWindowHandle, threadingFiredMessage, 0, 0);
+}
+
+} // namespace WebCore
diff --git a/JavaScriptCore/wtf/wx/MainThreadWx.cpp b/JavaScriptCore/wtf/wx/MainThreadWx.cpp
new file mode 100644
index 0000000..3166331
--- /dev/null
+++ b/JavaScriptCore/wtf/wx/MainThreadWx.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 Kevin Ollivier
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MainThread.h"
+
+namespace WTF {
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+}
+
+}