diff options
Diffstat (limited to 'Source/JavaScriptCore/wtf')
36 files changed, 1357 insertions, 239 deletions
diff --git a/Source/JavaScriptCore/wtf/Assertions.cpp b/Source/JavaScriptCore/wtf/Assertions.cpp index cdde180..3c4fc77 100644 --- a/Source/JavaScriptCore/wtf/Assertions.cpp +++ b/Source/JavaScriptCore/wtf/Assertions.cpp @@ -225,12 +225,12 @@ void WTFReportBacktrace() // Assume c++ & try to demangle the name. char* demangledName = abi::__cxa_demangle(mangledName, 0, 0, 0); if (demangledName) { - fprintf(stderr, " -> %s\n", demangledName); + fprintf(stderr, "%-3d %s\n", i, demangledName); free(demangledName); } else - fprintf(stderr, " -> %s\n", mangledName); + fprintf(stderr, "%-3d %s\n", i, mangledName); } else - fprintf(stderr, " -> %p\n", pointer); + fprintf(stderr, "%-3d %p\n", i, pointer); } #endif } diff --git a/Source/JavaScriptCore/wtf/Bitmap.h b/Source/JavaScriptCore/wtf/Bitmap.h index b046b61..9ee7f4a 100644 --- a/Source/JavaScriptCore/wtf/Bitmap.h +++ b/Source/JavaScriptCore/wtf/Bitmap.h @@ -40,6 +40,7 @@ public: size_t nextPossiblyUnset(size_t) const; void clear(size_t); void clearAll(); + int64_t findRunOfZeros(size_t) const; size_t count(size_t = 0) const; size_t isEmpty() const; size_t isFull() const; @@ -107,6 +108,26 @@ inline size_t Bitmap<size>::nextPossiblyUnset(size_t start) const } template<size_t size> +inline int64_t Bitmap<size>::findRunOfZeros(size_t runLength) const +{ + if (!runLength) + runLength = 1; + + for (size_t i = 0; i <= (size - runLength) ; i++) { + bool found = true; + for (size_t j = i; j <= (i + runLength - 1) ; j++) { + if (get(j)) { + found = false; + break; + } + } + if (found) + return i; + } + return -1; +} + +template<size_t size> inline size_t Bitmap<size>::count(size_t start) const { size_t result = 0; diff --git a/Source/JavaScriptCore/wtf/BlockStack.h b/Source/JavaScriptCore/wtf/BlockStack.h new file mode 100644 index 0000000..a4d7425 --- /dev/null +++ b/Source/JavaScriptCore/wtf/BlockStack.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2011 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. 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 INC. 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 BlockStack_h +#define BlockStack_h + +#include <wtf/Assertions.h> +#include <wtf/Vector.h> + +namespace WTF { + +template <typename T> class BlockStack { +public: + static const size_t blockSize = 4096; + static const size_t blockLength = blockSize / sizeof(T); + + BlockStack(); + ~BlockStack(); + + T* grow(); + void shrink(T*); + + const Vector<T*>& blocks(); + +private: + Vector<T*> m_blocks; + T* m_spareBlock; // Used to avoid thrash at block boundaries. +}; + +template <typename T> BlockStack<T>::BlockStack() + : m_spareBlock(0) +{ +} + +template <typename T> BlockStack<T>::~BlockStack() +{ + if (m_spareBlock) + free(m_spareBlock); + for (size_t i = 0; i < m_blocks.size(); ++i) + free(m_blocks[i]); +} + +template <typename T> inline const Vector<T*>& BlockStack<T>::blocks() +{ + return m_blocks; +} + +template <typename T> T* BlockStack<T>::grow() +{ + T* block = m_spareBlock ? m_spareBlock : static_cast<T*>(malloc(blockSize)); + m_spareBlock = 0; + + m_blocks.append(block); + return block; +} + +template <typename T> void BlockStack<T>::shrink(T* newEnd) +{ + ASSERT(newEnd != m_blocks.last() + blockLength); + m_spareBlock = m_blocks.last(); + m_blocks.removeLast(); + + while (m_blocks.last() + blockLength != newEnd) { + free(m_blocks.last()); + m_blocks.removeLast(); + } +} + +} + +using WTF::BlockStack; + +#endif diff --git a/Source/JavaScriptCore/wtf/CMakeLists.txt b/Source/JavaScriptCore/wtf/CMakeLists.txt index f85bf02..c27b2e5 100644 --- a/Source/JavaScriptCore/wtf/CMakeLists.txt +++ b/Source/JavaScriptCore/wtf/CMakeLists.txt @@ -16,6 +16,7 @@ SET(WTF_HEADERS Decoder.h Deque.h DisallowCType.h + DoublyLinkedList.h Encoder.h FastAllocBase.h FastMalloc.h @@ -64,6 +65,7 @@ SET(WTF_HEADERS RefPtrHashMap.h RetainPtr.h SegmentedVector.h + SHA1.h StackBounds.h StaticConstructors.h StdLibExtras.h @@ -115,6 +117,7 @@ SET(WTF_SOURCES OSRandomSource.cpp RandomNumber.cpp RefCountedLeakCounter.cpp + SHA1.cpp StackBounds.cpp StringExtras.cpp Threading.cpp diff --git a/Source/JavaScriptCore/wtf/CurrentTime.cpp b/Source/JavaScriptCore/wtf/CurrentTime.cpp index 56724cb..4205227 100644 --- a/Source/JavaScriptCore/wtf/CurrentTime.cpp +++ b/Source/JavaScriptCore/wtf/CurrentTime.cpp @@ -35,7 +35,7 @@ #if OS(WINDOWS) -// Windows is first since we want to use hires timers, despite PLATFORM(CF) +// Windows is first since we want to use hires timers, despite USE(CF) // being defined. // If defined, WIN32_LEAN_AND_MEAN disables timeBeginPeriod/timeEndPeriod. #undef WIN32_LEAN_AND_MEAN diff --git a/Source/JavaScriptCore/wtf/DateMath.cpp b/Source/JavaScriptCore/wtf/DateMath.cpp index 8873352..062cc1b 100644 --- a/Source/JavaScriptCore/wtf/DateMath.cpp +++ b/Source/JavaScriptCore/wtf/DateMath.cpp @@ -76,6 +76,9 @@ #include "ASCIICType.h" #include "CurrentTime.h" #include "MathExtras.h" +#if USE(JSC) +#include "ScopeChain.h" +#endif #include "StdLibExtras.h" #include "StringExtras.h" @@ -920,6 +923,14 @@ static double parseDateFromNullTerminatedCharacters(const char* dateString, bool } } } + + // The year may be after the time but before the time zone. + if (year <= 0) { + if (!parseLong(dateString, &newPosStr, 10, &year)) + year = 0; + dateString = newPosStr; + skipSpacesAndComments(dateString); + } // Don't fail if the time zone is missing. // Some websites omit the time zone (4275206). diff --git a/Source/JavaScriptCore/wtf/Deque.h b/Source/JavaScriptCore/wtf/Deque.h index 1b16afc..8ae46e9 100644 --- a/Source/JavaScriptCore/wtf/Deque.h +++ b/Source/JavaScriptCore/wtf/Deque.h @@ -37,27 +37,27 @@ 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, size_t inlineCapacity> class DequeIteratorBase; + template<typename T, size_t inlineCapacity> class DequeIterator; + template<typename T, size_t inlineCapacity> class DequeConstIterator; + template<typename T, size_t inlineCapacity> class DequeReverseIterator; + template<typename T, size_t inlineCapacity> class DequeConstReverseIterator; - template<typename T> + template<typename T, size_t inlineCapacity = 0> class Deque { WTF_MAKE_FAST_ALLOCATED; public: - typedef DequeIterator<T> iterator; - typedef DequeConstIterator<T> const_iterator; - typedef DequeReverseIterator<T> reverse_iterator; - typedef DequeConstReverseIterator<T> const_reverse_iterator; + typedef DequeIterator<T, inlineCapacity> iterator; + typedef DequeConstIterator<T, inlineCapacity> const_iterator; + typedef DequeReverseIterator<T, inlineCapacity> reverse_iterator; + typedef DequeConstReverseIterator<T, inlineCapacity> const_reverse_iterator; Deque(); - Deque(const Deque<T>&); - Deque& operator=(const Deque<T>&); + Deque(const Deque<T, inlineCapacity>&); + Deque& operator=(const Deque<T, inlineCapacity>&); ~Deque(); - void swap(Deque<T>&); + void swap(Deque<T, inlineCapacity>&); 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; } @@ -87,11 +87,11 @@ namespace WTF { iterator findIf(Predicate&); private: - friend class DequeIteratorBase<T>; + friend class DequeIteratorBase<T, inlineCapacity>; - typedef VectorBuffer<T, 0> Buffer; + typedef VectorBuffer<T, inlineCapacity> Buffer; typedef VectorTypeOperations<T> TypeOperations; - typedef DequeIteratorBase<T> IteratorBase; + typedef DequeIteratorBase<T, inlineCapacity> IteratorBase; void remove(size_t position); void invalidateIterators(); @@ -109,14 +109,14 @@ namespace WTF { #endif }; - template<typename T> + template<typename T, size_t inlineCapacity = 0> class DequeIteratorBase { private: - typedef DequeIteratorBase<T> Base; + typedef DequeIteratorBase<T, inlineCapacity> Base; protected: DequeIteratorBase(); - DequeIteratorBase(const Deque<T>*, size_t); + DequeIteratorBase(const Deque<T, inlineCapacity>*, size_t); DequeIteratorBase(const Base&); Base& operator=(const Base&); ~DequeIteratorBase(); @@ -137,10 +137,10 @@ namespace WTF { void checkValidity() const; void checkValidity(const Base&) const; - Deque<T>* m_deque; + Deque<T, inlineCapacity>* m_deque; size_t m_index; - friend class Deque<T>; + friend class Deque<T, inlineCapacity>; #ifndef NDEBUG mutable DequeIteratorBase* m_next; @@ -148,14 +148,14 @@ namespace WTF { #endif }; - template<typename T> - class DequeIterator : public DequeIteratorBase<T> { + template<typename T, size_t inlineCapacity = 0> + class DequeIterator : public DequeIteratorBase<T, inlineCapacity> { private: - typedef DequeIteratorBase<T> Base; - typedef DequeIterator<T> Iterator; + typedef DequeIteratorBase<T, inlineCapacity> Base; + typedef DequeIterator<T, inlineCapacity> Iterator; public: - DequeIterator(Deque<T>* deque, size_t index) : Base(deque, index) { } + DequeIterator(Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { } DequeIterator(const Iterator& other) : Base(other) { } DequeIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } @@ -172,15 +172,15 @@ namespace WTF { // postfix -- intentionally omitted }; - template<typename T> - class DequeConstIterator : public DequeIteratorBase<T> { + template<typename T, size_t inlineCapacity = 0> + class DequeConstIterator : public DequeIteratorBase<T, inlineCapacity> { private: - typedef DequeIteratorBase<T> Base; - typedef DequeConstIterator<T> Iterator; - typedef DequeIterator<T> NonConstIterator; + typedef DequeIteratorBase<T, inlineCapacity> Base; + typedef DequeConstIterator<T, inlineCapacity> Iterator; + typedef DequeIterator<T, inlineCapacity> NonConstIterator; public: - DequeConstIterator(const Deque<T>* deque, size_t index) : Base(deque, index) { } + DequeConstIterator(const Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { } DequeConstIterator(const Iterator& other) : Base(other) { } DequeConstIterator(const NonConstIterator& other) : Base(other) { } @@ -199,14 +199,14 @@ namespace WTF { // postfix -- intentionally omitted }; - template<typename T> - class DequeReverseIterator : public DequeIteratorBase<T> { + template<typename T, size_t inlineCapacity = 0> + class DequeReverseIterator : public DequeIteratorBase<T, inlineCapacity> { private: - typedef DequeIteratorBase<T> Base; - typedef DequeReverseIterator<T> Iterator; + typedef DequeIteratorBase<T, inlineCapacity> Base; + typedef DequeReverseIterator<T, inlineCapacity> Iterator; public: - DequeReverseIterator(const Deque<T>* deque, size_t index) : Base(deque, index) { } + DequeReverseIterator(const Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { } DequeReverseIterator(const Iterator& other) : Base(other) { } DequeReverseIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } @@ -223,15 +223,15 @@ namespace WTF { // postfix -- intentionally omitted }; - template<typename T> - class DequeConstReverseIterator : public DequeIteratorBase<T> { + template<typename T, size_t inlineCapacity = 0> + class DequeConstReverseIterator : public DequeIteratorBase<T, inlineCapacity> { private: - typedef DequeIteratorBase<T> Base; - typedef DequeConstReverseIterator<T> Iterator; - typedef DequeReverseIterator<T> NonConstIterator; + typedef DequeIteratorBase<T, inlineCapacity> Base; + typedef DequeConstReverseIterator<T, inlineCapacity> Iterator; + typedef DequeReverseIterator<T, inlineCapacity> NonConstIterator; public: - DequeConstReverseIterator(const Deque<T>* deque, size_t index) : Base(deque, index) { } + DequeConstReverseIterator(const Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { } DequeConstReverseIterator(const Iterator& other) : Base(other) { } DequeConstReverseIterator(const NonConstIterator& other) : Base(other) { } @@ -251,13 +251,17 @@ namespace WTF { }; #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() { } + template<typename T, size_t inlineCapacity> inline void Deque<T, inlineCapacity>::checkValidity() const { } + template<typename T, size_t inlineCapacity> inline void Deque<T, inlineCapacity>::checkIndexValidity(size_t) const { } + template<typename T, size_t inlineCapacity> inline void Deque<T, inlineCapacity>::invalidateIterators() { } #else - template<typename T> - void Deque<T>::checkValidity() const + template<typename T, size_t inlineCapacity> + void Deque<T, inlineCapacity>::checkValidity() const { + // In this implementation a capacity of 1 would confuse append() and + // other places that assume the index after capacity - 1 is 0. + ASSERT(m_buffer.capacity() != 1); + if (!m_buffer.capacity()) { ASSERT(!m_start); ASSERT(!m_end); @@ -267,8 +271,8 @@ namespace WTF { } } - template<typename T> - void Deque<T>::checkIndexValidity(size_t index) const + template<typename T, size_t inlineCapacity> + void Deque<T, inlineCapacity>::checkIndexValidity(size_t index) const { ASSERT(index <= m_buffer.capacity()); if (m_start <= m_end) { @@ -279,8 +283,8 @@ namespace WTF { } } - template<typename T> - void Deque<T>::invalidateIterators() + template<typename T, size_t inlineCapacity> + void Deque<T, inlineCapacity>::invalidateIterators() { IteratorBase* next; for (IteratorBase* p = m_iterators; p; p = next) { @@ -293,8 +297,8 @@ namespace WTF { } #endif - template<typename T> - inline Deque<T>::Deque() + template<typename T, size_t inlineCapacity> + inline Deque<T, inlineCapacity>::Deque() : m_start(0) , m_end(0) #ifndef NDEBUG @@ -304,8 +308,8 @@ namespace WTF { checkValidity(); } - template<typename T> - inline Deque<T>::Deque(const Deque<T>& other) + template<typename T, size_t inlineCapacity> + inline Deque<T, inlineCapacity>::Deque(const Deque<T, inlineCapacity>& other) : m_start(other.m_start) , m_end(other.m_end) , m_buffer(other.m_buffer.capacity()) @@ -322,25 +326,27 @@ namespace WTF { } } - template<typename T> - void deleteAllValues(const Deque<T>& collection) + template<typename T, size_t inlineCapacity> + void deleteAllValues(const Deque<T, inlineCapacity>& collection) { - typedef typename Deque<T>::const_iterator iterator; + typedef typename Deque<T, inlineCapacity>::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) + template<typename T, size_t inlineCapacity> + inline Deque<T, inlineCapacity>& Deque<T, inlineCapacity>::operator=(const Deque<T, inlineCapacity>& other) { + // FIXME: This is inefficient if we're using an inline buffer and T is + // expensive to copy since it will copy the buffer twice instead of once. Deque<T> copy(other); swap(copy); return *this; } - template<typename T> - inline void Deque<T>::destroyAll() + template<typename T, size_t inlineCapacity> + inline void Deque<T, inlineCapacity>::destroyAll() { if (m_start <= m_end) TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_end); @@ -350,16 +356,16 @@ namespace WTF { } } - template<typename T> - inline Deque<T>::~Deque() + template<typename T, size_t inlineCapacity> + inline Deque<T, inlineCapacity>::~Deque() { checkValidity(); invalidateIterators(); destroyAll(); } - template<typename T> - inline void Deque<T>::swap(Deque<T>& other) + template<typename T, size_t inlineCapacity> + inline void Deque<T, inlineCapacity>::swap(Deque<T, inlineCapacity>& other) { checkValidity(); other.checkValidity(); @@ -371,8 +377,8 @@ namespace WTF { other.checkValidity(); } - template<typename T> - inline void Deque<T>::clear() + template<typename T, size_t inlineCapacity> + inline void Deque<T, inlineCapacity>::clear() { checkValidity(); invalidateIterators(); @@ -382,9 +388,9 @@ namespace WTF { checkValidity(); } - template<typename T> + template<typename T, size_t inlineCapacity> template<typename Predicate> - inline DequeIterator<T> Deque<T>::findIf(Predicate& predicate) + inline DequeIterator<T, inlineCapacity> Deque<T, inlineCapacity>::findIf(Predicate& predicate) { iterator end_iterator = end(); for (iterator it = begin(); it != end_iterator; ++it) { @@ -394,8 +400,8 @@ namespace WTF { return end_iterator; } - template<typename T> - inline void Deque<T>::expandCapacityIfNeeded() + template<typename T, size_t inlineCapacity> + inline void Deque<T, inlineCapacity>::expandCapacityIfNeeded() { if (m_start) { if (m_end + 1 != m_start) @@ -409,8 +415,8 @@ namespace WTF { expandCapacity(); } - template<typename T> - void Deque<T>::expandCapacity() + template<typename T, size_t inlineCapacity> + void Deque<T, inlineCapacity>::expandCapacity() { checkValidity(); size_t oldCapacity = m_buffer.capacity(); @@ -429,16 +435,16 @@ namespace WTF { checkValidity(); } - template<typename T> - inline T Deque<T>::takeFirst() + template<typename T, size_t inlineCapacity> + inline T Deque<T, inlineCapacity>::takeFirst() { T oldFirst = first(); removeFirst(); return oldFirst; } - template<typename T> template<typename U> - inline void Deque<T>::append(const U& value) + template<typename T, size_t inlineCapacity> template<typename U> + inline void Deque<T, inlineCapacity>::append(const U& value) { checkValidity(); expandCapacityIfNeeded(); @@ -450,8 +456,8 @@ namespace WTF { checkValidity(); } - template<typename T> template<typename U> - inline void Deque<T>::prepend(const U& value) + template<typename T, size_t inlineCapacity> template<typename U> + inline void Deque<T, inlineCapacity>::prepend(const U& value) { checkValidity(); expandCapacityIfNeeded(); @@ -463,8 +469,8 @@ namespace WTF { checkValidity(); } - template<typename T> - inline void Deque<T>::removeFirst() + template<typename T, size_t inlineCapacity> + inline void Deque<T, inlineCapacity>::removeFirst() { checkValidity(); invalidateIterators(); @@ -477,22 +483,22 @@ namespace WTF { checkValidity(); } - template<typename T> - inline void Deque<T>::remove(iterator& it) + template<typename T, size_t inlineCapacity> + inline void Deque<T, inlineCapacity>::remove(iterator& it) { it.checkValidity(); remove(it.m_index); } - template<typename T> - inline void Deque<T>::remove(const_iterator& it) + template<typename T, size_t inlineCapacity> + inline void Deque<T, inlineCapacity>::remove(const_iterator& it) { it.checkValidity(); remove(it.m_index); } - template<typename T> - inline void Deque<T>::remove(size_t position) + template<typename T, size_t inlineCapacity> + inline void Deque<T, inlineCapacity>::remove(size_t position) { if (position == m_end) return; @@ -515,28 +521,28 @@ namespace WTF { } #ifdef NDEBUG - template<typename T> inline void DequeIteratorBase<T>::checkValidity() const { } - template<typename T> inline void DequeIteratorBase<T>::checkValidity(const DequeIteratorBase<T>&) const { } - template<typename T> inline void DequeIteratorBase<T>::addToIteratorsList() { } - template<typename T> inline void DequeIteratorBase<T>::removeFromIteratorsList() { } + template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::checkValidity() const { } + template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::checkValidity(const DequeIteratorBase<T, inlineCapacity>&) const { } + template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::addToIteratorsList() { } + template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::removeFromIteratorsList() { } #else - template<typename T> - void DequeIteratorBase<T>::checkValidity() const + template<typename T, size_t inlineCapacity> + void DequeIteratorBase<T, inlineCapacity>::checkValidity() const { ASSERT(m_deque); m_deque->checkIndexValidity(m_index); } - template<typename T> - void DequeIteratorBase<T>::checkValidity(const Base& other) const + template<typename T, size_t inlineCapacity> + void DequeIteratorBase<T, inlineCapacity>::checkValidity(const Base& other) const { checkValidity(); other.checkValidity(); ASSERT(m_deque == other.m_deque); } - template<typename T> - void DequeIteratorBase<T>::addToIteratorsList() + template<typename T, size_t inlineCapacity> + void DequeIteratorBase<T, inlineCapacity>::addToIteratorsList() { if (!m_deque) m_next = 0; @@ -549,8 +555,8 @@ namespace WTF { m_previous = 0; } - template<typename T> - void DequeIteratorBase<T>::removeFromIteratorsList() + template<typename T, size_t inlineCapacity> + void DequeIteratorBase<T, inlineCapacity>::removeFromIteratorsList() { if (!m_deque) { ASSERT(!m_next); @@ -574,23 +580,23 @@ namespace WTF { } #endif - template<typename T> - inline DequeIteratorBase<T>::DequeIteratorBase() + template<typename T, size_t inlineCapacity> + inline DequeIteratorBase<T, inlineCapacity>::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)) + template<typename T, size_t inlineCapacity> + inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase(const Deque<T, inlineCapacity>* deque, size_t index) + : m_deque(const_cast<Deque<T, inlineCapacity>*>(deque)) , m_index(index) { addToIteratorsList(); checkValidity(); } - template<typename T> - inline DequeIteratorBase<T>::DequeIteratorBase(const Base& other) + template<typename T, size_t inlineCapacity> + inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase(const Base& other) : m_deque(other.m_deque) , m_index(other.m_index) { @@ -598,8 +604,8 @@ namespace WTF { checkValidity(); } - template<typename T> - inline DequeIteratorBase<T>& DequeIteratorBase<T>::operator=(const Base& other) + template<typename T, size_t inlineCapacity> + inline DequeIteratorBase<T, inlineCapacity>& DequeIteratorBase<T, inlineCapacity>::operator=(const Base& other) { checkValidity(); other.checkValidity(); @@ -612,8 +618,8 @@ namespace WTF { return *this; } - template<typename T> - inline DequeIteratorBase<T>::~DequeIteratorBase() + template<typename T, size_t inlineCapacity> + inline DequeIteratorBase<T, inlineCapacity>::~DequeIteratorBase() { #ifndef NDEBUG removeFromIteratorsList(); @@ -621,15 +627,15 @@ namespace WTF { #endif } - template<typename T> - inline bool DequeIteratorBase<T>::isEqual(const Base& other) const + template<typename T, size_t inlineCapacity> + inline bool DequeIteratorBase<T, inlineCapacity>::isEqual(const Base& other) const { checkValidity(other); return m_index == other.m_index; } - template<typename T> - inline void DequeIteratorBase<T>::increment() + template<typename T, size_t inlineCapacity> + inline void DequeIteratorBase<T, inlineCapacity>::increment() { checkValidity(); ASSERT(m_index != m_deque->m_end); @@ -641,8 +647,8 @@ namespace WTF { checkValidity(); } - template<typename T> - inline void DequeIteratorBase<T>::decrement() + template<typename T, size_t inlineCapacity> + inline void DequeIteratorBase<T, inlineCapacity>::decrement() { checkValidity(); ASSERT(m_index != m_deque->m_start); @@ -654,16 +660,16 @@ namespace WTF { checkValidity(); } - template<typename T> - inline T* DequeIteratorBase<T>::after() const + template<typename T, size_t inlineCapacity> + inline T* DequeIteratorBase<T, inlineCapacity>::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 + template<typename T, size_t inlineCapacity> + inline T* DequeIteratorBase<T, inlineCapacity>::before() const { checkValidity(); ASSERT(m_index != m_deque->m_start); diff --git a/Source/JavaScriptCore/wtf/DoublyLinkedList.h b/Source/JavaScriptCore/wtf/DoublyLinkedList.h new file mode 100644 index 0000000..9351263 --- /dev/null +++ b/Source/JavaScriptCore/wtf/DoublyLinkedList.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2011 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. 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 INC. 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 DoublyLinkedList_h +#define DoublyLinkedList_h + +namespace WTF { + +template <typename Node> class DoublyLinkedList { +public: + DoublyLinkedList(); + + bool isEmpty(); + + Node* head(); + + void append(Node*); + void remove(Node*); + +private: + Node* m_head; + Node* m_tail; +}; + +template <typename Node> inline DoublyLinkedList<Node>::DoublyLinkedList() + : m_head(0) + , m_tail(0) +{ +} + +template <typename Node> inline bool DoublyLinkedList<Node>::isEmpty() +{ + return !m_head; +} + +template <typename Node> inline Node* DoublyLinkedList<Node>::head() +{ + return m_head; +} + +template <typename Node> inline void DoublyLinkedList<Node>::append(Node* node) +{ + if (!m_tail) { + ASSERT(!m_head); + m_head = node; + m_tail = node; + node->setPrev(0); + node->setNext(0); + return; + } + + ASSERT(m_head); + m_tail->setNext(node); + node->setPrev(m_tail); + node->setNext(0); + m_tail = node; +} + +template <typename Node> inline void DoublyLinkedList<Node>::remove(Node* node) +{ + if (node->prev()) { + ASSERT(node != m_head); + node->prev()->setNext(node->next()); + } else { + ASSERT(node == m_head); + m_head = node->next(); + } + + if (node->next()) { + ASSERT(node != m_tail); + node->next()->setPrev(node->prev()); + } else { + ASSERT(node == m_tail); + m_tail = node->prev(); + } +} + +} // namespace WTF + +using WTF::DoublyLinkedList; + +#endif diff --git a/Source/JavaScriptCore/wtf/ListHashSet.h b/Source/JavaScriptCore/wtf/ListHashSet.h index e916ef2..b0d0e43 100644 --- a/Source/JavaScriptCore/wtf/ListHashSet.h +++ b/Source/JavaScriptCore/wtf/ListHashSet.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2011, Benjamin Poulain <ikipou@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -90,10 +91,24 @@ namespace WTF { const_iterator begin() const; const_iterator end() const; + ValueType& first(); + const ValueType& first() const; + + ValueType& last(); + const ValueType& last() const; + void removeLast(); + iterator find(const ValueType&); const_iterator find(const ValueType&) const; bool contains(const ValueType&) const; + // An alternate version of find() that finds the object by hashing and comparing + // with some other type, to avoid the cost of type conversion. + // The HashTranslator interface is defined in HashSet. + 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 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&); @@ -442,6 +457,42 @@ namespace WTF { } template<typename T, size_t inlineCapacity, typename U> + inline T& ListHashSet<T, inlineCapacity, U>::first() + { + ASSERT(!isEmpty()); + return m_head->m_value; + } + + template<typename T, size_t inlineCapacity, typename U> + inline const T& ListHashSet<T, inlineCapacity, U>::first() const + { + ASSERT(!isEmpty()); + return m_head->m_value; + } + + template<typename T, size_t inlineCapacity, typename U> + inline T& ListHashSet<T, inlineCapacity, U>::last() + { + ASSERT(!isEmpty()); + return m_tail->m_value; + } + + template<typename T, size_t inlineCapacity, typename U> + inline const T& ListHashSet<T, inlineCapacity, U>::last() const + { + ASSERT(!isEmpty()); + return m_tail->m_value; + } + + template<typename T, size_t inlineCapacity, typename U> + inline void ListHashSet<T, inlineCapacity, U>::removeLast() + { + ASSERT(!isEmpty()); + m_impl.remove(m_tail); + unlinkAndDelete(m_tail); + } + + template<typename T, size_t inlineCapacity, typename U> inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::find(const ValueType& value) { typedef ListHashSetTranslator<ValueType, inlineCapacity, HashFunctions> Translator; @@ -461,6 +512,45 @@ namespace WTF { return makeConstIterator(*it); } + template<typename ValueType, size_t inlineCapacity, typename T, typename Translator> + struct ListHashSetTranslatorAdapter { + private: + typedef ListHashSetNode<ValueType, inlineCapacity> Node; + public: + static unsigned hash(const T& key) { return Translator::hash(key); } + static bool equal(Node* const& a, const T& b) { return Translator::equal(a->m_value, b); } + }; + + template<typename ValueType, size_t inlineCapacity, typename U> + template<typename T, typename HashTranslator> + inline typename ListHashSet<ValueType, inlineCapacity, U>::iterator ListHashSet<ValueType, inlineCapacity, U>::find(const T& value) + { + typedef ListHashSetTranslatorAdapter<ValueType, inlineCapacity, T, HashTranslator> Adapter; + ImplTypeConstIterator it = m_impl.template find<T, Adapter>(value); + if (it == m_impl.end()) + return end(); + return makeIterator(*it); + } + + template<typename ValueType, size_t inlineCapacity, typename U> + template<typename T, typename HashTranslator> + inline typename ListHashSet<ValueType, inlineCapacity, U>::const_iterator ListHashSet<ValueType, inlineCapacity, U>::find(const T& value) const + { + typedef ListHashSetTranslatorAdapter<ValueType, inlineCapacity, T, HashTranslator> Adapter; + ImplTypeConstIterator it = m_impl.template find<T, Adapter>(value); + if (it == m_impl.end()) + return end(); + return makeConstIterator(*it); + } + + template<typename ValueType, size_t inlineCapacity, typename U> + template<typename T, typename HashTranslator> + inline bool ListHashSet<ValueType, inlineCapacity, U>::contains(const T& value) const + { + typedef ListHashSetTranslatorAdapter<ValueType, inlineCapacity, T, HashTranslator> Adapter; + return m_impl.template contains<T, Adapter>(value); + } + template<typename T, size_t inlineCapacity, typename U> inline bool ListHashSet<T, inlineCapacity, U>::contains(const ValueType& value) const { diff --git a/Source/JavaScriptCore/wtf/MD5.cpp b/Source/JavaScriptCore/wtf/MD5.cpp index c926a7b..07bbadd 100644 --- a/Source/JavaScriptCore/wtf/MD5.cpp +++ b/Source/JavaScriptCore/wtf/MD5.cpp @@ -203,6 +203,7 @@ static void MD5Transform(uint32_t buf[4], const uint32_t in[16]) MD5::MD5() { + // FIXME: Move unit tests somewhere outside the constructor. See bug 55853. testMD5(); m_buf[0] = 0x67452301; m_buf[1] = 0xefcdab89; diff --git a/Source/JavaScriptCore/wtf/OSAllocator.h b/Source/JavaScriptCore/wtf/OSAllocator.h index 577a6b8..3fd4cef 100644 --- a/Source/JavaScriptCore/wtf/OSAllocator.h +++ b/Source/JavaScriptCore/wtf/OSAllocator.h @@ -77,9 +77,10 @@ inline void* OSAllocator::reserveAndCommit(size_t reserveSize, size_t commitSize inline void OSAllocator::decommitAndRelease(void* releaseBase, size_t releaseSize, void* decommitBase, size_t decommitSize) { ASSERT(decommitBase >= releaseBase && (static_cast<char*>(decommitBase) + decommitSize) <= (static_cast<char*>(releaseBase) + releaseSize)); -#if OS(WINCE) +#if OS(WINCE) || OS(SYMBIAN) // On most platforms we can actually skip this final decommit; releasing the VM will // implicitly decommit any physical memory in the region. This is not true on WINCE. + // On Symbian, this makes implementation simpler and better aligned with the RChunk API decommit(decommitBase, decommitSize); #else UNUSED_PARAM(decommitBase); diff --git a/Source/JavaScriptCore/wtf/OSAllocatorSymbian.cpp b/Source/JavaScriptCore/wtf/OSAllocatorSymbian.cpp index e746fde..c63e609 100644 --- a/Source/JavaScriptCore/wtf/OSAllocatorSymbian.cpp +++ b/Source/JavaScriptCore/wtf/OSAllocatorSymbian.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,31 +27,176 @@ #include "config.h" #include "OSAllocator.h" -#include <wtf/FastMalloc.h> +#include "PageAllocatorSymbian.h" namespace WTF { -void* OSAllocator::reserveUncommitted(size_t bytes, Usage, bool, bool) +// Array to store code chunks used by JIT engine(s) +static RPointerArray<SymbianChunk> codeChunksContainer; + +// The singleton data allocator (non code) +static PageAllocatorSymbian dataAllocator; + +_LIT(KErrorStringInternalConsistency, "OSAllocator:ConsistencyError"); +_LIT(KErrorStringChunkCreation, "OSAllocator:ChunkInitError"); +_LIT(KErrorStringPageSize, "OSAllocator:WrongPageSize"); + +// Makes a new code chunk for a JIT engine with everything in committed state +static void* allocateCodeChunk(size_t bytes) +{ + RChunk c; + TInt error = c.CreateLocalCode(bytes, bytes); + __ASSERT_ALWAYS(error == KErrNone, User::Panic(KErrorStringChunkCreation, error)); + + codeChunksContainer.Append(new SymbianChunk(c.Handle())); + return static_cast<void*>(c.Base()); +} + +// Frees the _entire_ code chunk in which this address resides. +static bool deallocateCodeChunk(void* address) +{ + bool found = false; + for (int i = 0; i < codeChunksContainer.Count(); i++) { + SymbianChunk* p = codeChunksContainer[i]; + if (p && p->contains(address)) { + codeChunksContainer.Remove(i); + delete p; + found = true; + } + } + return found; +} + +// Return the (singleton) object that manages all non-code VM operations +static PageAllocatorSymbian* dataAllocatorInstance() { - return fastMalloc(bytes); + return &dataAllocator; } -void* OSAllocator::reserveAndCommit(size_t bytes, Usage, bool, bool) +// Reserve memory and return the base address of the region +void* OSAllocator::reserveUncommitted(size_t reservationSize, Usage usage, bool , bool executable) { - return fastMalloc(bytes); + void* base = 0; + if (executable) + base = allocateCodeChunk(reservationSize); + else + base = dataAllocatorInstance()->reserve(reservationSize); + return base; } -void OSAllocator::commit(void*, size_t, bool, bool) +// Inverse operation of reserveUncommitted() +void OSAllocator::releaseDecommitted(void* parkedBase, size_t bytes) { + if (dataAllocatorInstance()->contains(parkedBase)) + dataAllocatorInstance()->release(parkedBase, bytes); + + // NOOP for code chunks (JIT) because we released them in decommit() } -void OSAllocator::decommit(void*, size_t) +// Commit what was previously reserved via reserveUncommitted() +void OSAllocator::commit(void* address, size_t bytes, bool, bool executable) { + // For code chunks, we commit (early) in reserveUncommitted(), so NOOP + // For data regions, do real work + if (!executable) + dataAllocatorInstance()->commit(address, bytes); +} + +void OSAllocator::decommit(void* address, size_t bytes) +{ + if (dataAllocatorInstance()->contains(address)) + dataAllocatorInstance()->decommit(address, bytes); + else + deallocateCodeChunk(address); // for code chunk, decommit AND release +} + +void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable) +{ + void* base = reserveUncommitted(bytes, usage, writable, executable); + commit(base, bytes, writable, executable); + return base; +} + + +// The PageAllocatorSymbian class helps map OSAllocator calls for reserve/commit/decommit +// to a single large Symbian chunk. Only works with multiples of page size, and as a corollary +// all addresses accepted or returned by it are also page-sized aligned. +// Design notes: +// - We initialize a chunk up-front with a large reservation size +// - The entire reservation reserve is logically divided into pageSized blocks (4K on Symbian) +// - The map maintains 1 bit for each of the 4K-sized region in our address space +// - OSAllocator::reserveUncommitted() requests lead to 1 or more bits being set in map +// to indicate internally reserved state. The VM address corresponding to the first bit is returned. +// - OSAllocator::commit() actually calls RChunk.commit() and commits *all or part* of the region +// reserved via reserveUncommitted() previously. +// - OSAllocator::decommit() calls RChunk.decommit() +// - OSAllocator::releaseDecommitted() unparks all the bits in the map, but trusts that a previously +// call to decommit() would have returned the memory to the OS +PageAllocatorSymbian::PageAllocatorSymbian() +{ + __ASSERT_ALWAYS(m_pageSize == WTF::pageSize(), User::Panic(KErrorStringPageSize, m_pageSize)); + + RChunk chunk; + TInt error = chunk.CreateDisconnectedLocal(0, 0, TInt(largeReservationSize)); + __ASSERT_ALWAYS(error == KErrNone, User::Panic(KErrorStringChunkCreation, error)); + + m_chunk = new SymbianChunk(chunk.Handle()); // takes ownership of chunk +} + +PageAllocatorSymbian::~PageAllocatorSymbian() +{ + delete m_chunk; +} + +// Reserves a region internally in the bitmap +void* PageAllocatorSymbian::reserve(size_t bytes) +{ + // Find first available region + const size_t nPages = bytes / m_pageSize; + const int64_t startIdx = m_map.findRunOfZeros(nPages); + + // Pseudo OOM + if (startIdx < 0) + return 0; + + for (size_t i = startIdx; i < startIdx + nPages ; i++) + m_map.set(i); + + return static_cast<void*>( m_chunk->m_base + (TUint)(m_pageSize * startIdx) ); +} + +// Reverses the effects of a reserve() call +void PageAllocatorSymbian::release(void* address, size_t bytes) +{ + const size_t startIdx = (static_cast<char*>(address) - m_chunk->m_base) / m_pageSize; + const size_t nPages = bytes / m_pageSize; + for (size_t i = startIdx; i < startIdx + nPages ; i++) + m_map.clear(i); +} + +// Actually commit memory from the OS, after a previous call to reserve() +bool PageAllocatorSymbian::commit(void* address, size_t bytes) +{ + // sanity check that bits were previously set + const size_t idx = (static_cast<char*>(address) - m_chunk->m_base) / m_pageSize; + const size_t nPages = bytes / m_pageSize; + __ASSERT_ALWAYS(m_map.get(idx), User::Panic(KErrorStringInternalConsistency, idx)); + __ASSERT_ALWAYS(m_map.get(idx+nPages-1), User::Panic(KErrorStringInternalConsistency, idx+nPages-1)); + + TInt error = m_chunk->Commit(static_cast<char*>(address) - m_chunk->m_base, bytes); + return (error == KErrNone); +} + +// Inverse operation of commit(), a release() should follow later +bool PageAllocatorSymbian::decommit(void* address, size_t bytes) +{ + TInt error = m_chunk->Decommit(static_cast<char*>(address) - m_chunk->m_base, bytes); + return (error == KErrNone); } -void OSAllocator::releaseDecommitted(void* address, size_t) +bool PageAllocatorSymbian::contains(const void* address) const { - fastFree(address); + return m_chunk->contains(address); } } // namespace WTF diff --git a/Source/JavaScriptCore/wtf/OSRandomSource.cpp b/Source/JavaScriptCore/wtf/OSRandomSource.cpp index 0c1416a..7d86f6f 100644 --- a/Source/JavaScriptCore/wtf/OSRandomSource.cpp +++ b/Source/JavaScriptCore/wtf/OSRandomSource.cpp @@ -29,6 +29,10 @@ #include <stdint.h> #include <stdlib.h> +#if OS(SYMBIAN) +#include <e32math.h> +#endif + #if OS(UNIX) #include <fcntl.h> #include <unistd.h> @@ -44,7 +48,19 @@ namespace WTF { #if USE(OS_RANDOMNESS) void cryptographicallyRandomValuesFromOS(unsigned char* buffer, size_t length) { -#if OS(UNIX) +#if OS(SYMBIAN) + TInt random; + while (length > sizeof(random)) { + random = Math::Random(); + memcpy(buffer, &random, sizeof(random)); + length -= sizeof(random); + buffer += sizeof(random); + } + if (length > 0) { + random = Math::Random(); + memcpy(buffer, &random, length); + } +#elif OS(UNIX) int fd = open("/dev/urandom", O_RDONLY, 0); if (fd < 0) CRASH(); // We need /dev/urandom for this API to work... diff --git a/Source/JavaScriptCore/wtf/OwnArrayPtr.h b/Source/JavaScriptCore/wtf/OwnArrayPtr.h index 6b7c8da..2828698 100644 --- a/Source/JavaScriptCore/wtf/OwnArrayPtr.h +++ b/Source/JavaScriptCore/wtf/OwnArrayPtr.h @@ -111,6 +111,16 @@ template<typename T> inline typename OwnArrayPtr<T>::PtrType OwnArrayPtr<T>::lea return ptr; } +#ifdef LOOSE_OWN_ARRAY_PTR +template<typename T> inline void OwnArrayPtr<T>::set(PtrType ptr) +{ + ASSERT(!ptr || m_ptr != ptr); + PtrType oldPtr = m_ptr; + m_ptr = ptr; + deleteOwnedArrayPtr(oldPtr); +} +#endif + template<typename T> inline OwnArrayPtr<T>& OwnArrayPtr<T>::operator=(const PassOwnArrayPtr<T>& o) { PtrType ptr = m_ptr; diff --git a/Source/JavaScriptCore/wtf/PageAllocatorSymbian.h b/Source/JavaScriptCore/wtf/PageAllocatorSymbian.h new file mode 100644 index 0000000..48a8464 --- /dev/null +++ b/Source/JavaScriptCore/wtf/PageAllocatorSymbian.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) + * + * 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 PageAllocatorSymbian_h +#define PageAllocatorSymbian_h + +#include <e32std.h> +#include <wtf/BitMap.h> + +namespace WTF { + +size_t pageSize(); + +// Convenience wrapper around an RChunk +class SymbianChunk : public RChunk { + +public: + SymbianChunk(TInt handle) + { + SetHandle(handle); + // prevent kernel calls by caching these + m_base = reinterpret_cast<char*>(Base()); + m_maxSize = MaxSize(); + } + + ~SymbianChunk() + { + Decommit(0, m_maxSize); + Close(); + } + + // checks if address is in chunk's virtual address space + bool contains(const void* address) const + { + return (static_cast<const char*>(address) >= m_base && static_cast<const char*>(address) < (m_base + m_maxSize)); + } + + char* m_base; + size_t m_maxSize; + +}; + +// Size of the large up-front reservation +#if defined(__WINS__) +// Emulator has limited virtual address space +const size_t largeReservationSize = 96*1024*1024; +#else +// HW has plenty of virtual addresses +const size_t largeReservationSize = 256*1024*1024; +#endif + +class PageAllocatorSymbian { + +public: + PageAllocatorSymbian(); + ~PageAllocatorSymbian(); + + void* reserve(size_t); + void release(void*, size_t); + bool commit(void*, size_t); + bool decommit(void*, size_t); + + bool contains(const void*) const; + +private: + static const size_t m_pageSize = 4096; + SymbianChunk* m_chunk; + Bitmap<largeReservationSize / m_pageSize> m_map; + +}; + +} // namespace WTF + +#endif // PageAllocatorSymbian_h + diff --git a/Source/JavaScriptCore/wtf/PassOwnArrayPtr.h b/Source/JavaScriptCore/wtf/PassOwnArrayPtr.h index e1aa61e..3f30924 100644 --- a/Source/JavaScriptCore/wtf/PassOwnArrayPtr.h +++ b/Source/JavaScriptCore/wtf/PassOwnArrayPtr.h @@ -30,9 +30,6 @@ #include "NullPtr.h" #include "TypeTraits.h" -// Remove this once we make all WebKit code compatible with stricter rules about PassOwnArrayPtr. -#define LOOSE_PASS_OWN_ARRAY_PTR - namespace WTF { template<typename T> class OwnArrayPtr; @@ -46,6 +43,10 @@ public: PassOwnArrayPtr() : m_ptr(0) { } +#if !defined(LOOSE_PASS_OWN_PTR) || !HAVE(NULLPTR) + PassOwnArrayPtr(std::nullptr_t) : m_ptr(0) { } +#endif + // It somewhat breaks the type system to allow transfer of ownership out of // a const PassOwnArrayPtr. However, it makes it much easier to work with PassOwnArrayPtr // temporaries, and we don't have a need to use real const PassOwnArrayPtrs anyway. diff --git a/Source/JavaScriptCore/wtf/Platform.h b/Source/JavaScriptCore/wtf/Platform.h index 98eee7f..593bb42 100644 --- a/Source/JavaScriptCore/wtf/Platform.h +++ b/Source/JavaScriptCore/wtf/Platform.h @@ -349,7 +349,9 @@ #endif /* ARM */ - +#if CPU(ARM) || CPU(MIPS) +#define WTF_CPU_NEEDS_ALIGNED_ACCESS 1 +#endif /* ==== OS() - underlying operating system; only to be used for mandated low-level services like virtual memory, not to choose a GUI toolkit ==== */ @@ -399,7 +401,7 @@ #endif /* OS(FREEBSD) - FreeBSD */ -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__DragonFly__) #define WTF_OS_FREEBSD 1 #endif @@ -532,29 +534,25 @@ #if PLATFORM(MAC) || PLATFORM(IOS) #define WTF_PLATFORM_CG 1 #endif -#if PLATFORM(MAC) && !PLATFORM(IOS) -#define WTF_PLATFORM_CI 1 -#endif #if PLATFORM(MAC) || PLATFORM(IOS) || (PLATFORM(WIN) && PLATFORM(CG)) #define WTF_PLATFORM_CA 1 #endif -/* PLATFORM(SKIA) for Win/Linux, CG/CI for Mac */ +/* USE(SKIA) for Win/Linux, CG for Mac */ #if PLATFORM(CHROMIUM) #if OS(DARWIN) #define WTF_PLATFORM_CG 1 -#define WTF_PLATFORM_CI 1 #define WTF_USE_ATSUI 1 #define WTF_USE_CORE_TEXT 1 #define WTF_USE_ICCJPEG 1 #else -#define WTF_PLATFORM_SKIA 1 +#define WTF_USE_SKIA 1 #define WTF_USE_CHROMIUM_NET 1 #endif #endif #if PLATFORM(BREWMP) -#define WTF_PLATFORM_SKIA 1 +#define WTF_USE_SKIA 1 #endif #if PLATFORM(GTK) @@ -567,7 +565,7 @@ #define WTF_USE_MERSENNE_TWISTER_19937 1 #endif -#if (PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(WIN) || (PLATFORM(QT) && OS(DARWIN) && !ENABLE(SINGLE_THREADED))) && !defined(ENABLE_JSC_MULTIPLE_THREADS) +#if (PLATFORM(GTK) || PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(WIN) || (PLATFORM(QT) && OS(DARWIN) && !ENABLE(SINGLE_THREADED))) && !defined(ENABLE_JSC_MULTIPLE_THREADS) #define ENABLE_JSC_MULTIPLE_THREADS 1 #endif @@ -600,6 +598,10 @@ #define WTF_USE_ICU_UNICODE 1 #endif +#if !PLATFORM(CHROMIUM) /* Chromium controls this macro with a gyp define */ +#define WTF_USE_BUILTIN_UTF8_CODEC 1 +#endif + #if PLATFORM(MAC) && !PLATFORM(IOS) #if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_TIGER) && CPU(X86_64) #define WTF_USE_PLUGIN_HOST_PROCESS 1 @@ -615,7 +617,7 @@ #if !defined(ENABLE_DASHBOARD_SUPPORT) #define ENABLE_DASHBOARD_SUPPORT 1 #endif -#define WTF_PLATFORM_CF 1 +#define WTF_USE_CF 1 #define WTF_USE_PTHREADS 1 #define HAVE_PTHREAD_RWLOCK 1 #define HAVE_READLINE 1 @@ -634,7 +636,7 @@ #endif #if PLATFORM(CHROMIUM) && OS(DARWIN) -#define WTF_PLATFORM_CF 1 +#define WTF_USE_CF 1 #define WTF_USE_PTHREADS 1 #define HAVE_PTHREAD_RWLOCK 1 #define WTF_USE_CARBON_SECURE_INPUT_MODE 1 @@ -645,7 +647,7 @@ #endif #if PLATFORM(QT) && OS(DARWIN) -#define WTF_PLATFORM_CF 1 +#define WTF_USE_CF 1 #endif #if OS(DARWIN) && !defined(BUILDING_ON_TIGER) && !PLATFORM(GTK) && !PLATFORM(QT) @@ -655,6 +657,7 @@ #if PLATFORM(IOS) #define ENABLE_CONTEXT_MENUS 0 #define ENABLE_DRAG_SUPPORT 0 +#define ENABLE_DATA_TRANSFER_ITEMS 0 #define ENABLE_FTPDIR 1 #define ENABLE_GEOLOCATION 1 #define ENABLE_ICONDATABASE 0 @@ -664,7 +667,7 @@ #define ENABLE_ORIENTATION_EVENTS 1 #define ENABLE_REPAINT_THROTTLING 1 #define HAVE_READLINE 1 -#define WTF_PLATFORM_CF 1 +#define WTF_USE_CF 1 #define WTF_USE_PTHREADS 1 #define HAVE_PTHREAD_RWLOCK 1 #define ENABLE_WEB_ARCHIVE 1 @@ -688,10 +691,19 @@ #endif #if PLATFORM(WIN) && !OS(WINCE) -#define WTF_PLATFORM_CF 1 +#define WTF_USE_CF 1 #define WTF_USE_PTHREADS 0 #endif +#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !defined(WIN_CAIRO) +#define WTF_USE_CFNETWORK 1 +#endif + +#if USE(CFNETWORK) || PLATFORM(MAC) +#define WTF_USE_CFURLCACHE 1 +#define WTF_USE_CFURLSTORAGESESSIONS 1 +#endif + #if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !PLATFORM(QT) #define ENABLE_WEB_ARCHIVE 1 #endif @@ -700,7 +712,7 @@ #define ENABLE_ASSEMBLER 1 #define ENABLE_GLOBAL_FASTMALLOC_NEW 0 #if OS(DARWIN) -#define WTF_PLATFORM_CF 1 +#define WTF_USE_CF 1 #ifndef BUILDING_ON_TIGER #define WTF_USE_CORE_TEXT 1 #define ENABLE_WEB_ARCHIVE 1 @@ -891,6 +903,10 @@ #define ENABLE_DRAG_SUPPORT 1 #endif +#if !defined(ENABLE_DATA_TRANSFER_ITEMS) +#define ENABLE_DATA_TRANSFER_ITEMS 0 +#endif + #if !defined(ENABLE_DASHBOARD_SUPPORT) #define ENABLE_DASHBOARD_SUPPORT 0 #endif diff --git a/Source/JavaScriptCore/wtf/RandomNumber.cpp b/Source/JavaScriptCore/wtf/RandomNumber.cpp index 1574324..5b06243 100644 --- a/Source/JavaScriptCore/wtf/RandomNumber.cpp +++ b/Source/JavaScriptCore/wtf/RandomNumber.cpp @@ -27,6 +27,7 @@ #include "config.h" #include "RandomNumber.h" +#include "CryptographicallyRandomNumber.h" #include "RandomNumberSeed.h" #include <limits> @@ -52,6 +53,14 @@ namespace WTF { double randomNumber() { +#if USE(OS_RANDOMNESS) + uint32_t bits = cryptographicallyRandomNumber(); + return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0); +#else + // Without OS_RANDOMNESS, we fall back to other random number generators + // that might not be cryptographically secure. Ideally, most ports would + // define USE(OS_RANDOMNESS). + #if !ENABLE(JSC_MULTIPLE_THREADS) static bool s_initialized = false; if (!s_initialized) { @@ -59,46 +68,16 @@ double randomNumber() s_initialized = true; } #endif - -#if COMPILER(MSVC) && defined(_CRT_RAND_S) - uint32_t bits; - rand_s(&bits); - return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0); -#elif OS(DARWIN) - uint32_t bits = arc4random(); - return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0); -#elif OS(UNIX) - uint32_t part1 = random() & (RAND_MAX - 1); - uint32_t part2 = random() & (RAND_MAX - 1); - // random only provides 31 bits - uint64_t fullRandom = part1; - fullRandom <<= 31; - fullRandom |= part2; - // Mask off the low 53bits - fullRandom &= (1LL << 53) - 1; - return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53); -#elif USE(MERSENNE_TWISTER_19937) +#if USE(MERSENNE_TWISTER_19937) return genrand_res53(); -#elif OS(WINDOWS) - uint32_t part1 = rand() & (RAND_MAX - 1); - uint32_t part2 = rand() & (RAND_MAX - 1); - uint32_t part3 = rand() & (RAND_MAX - 1); - uint32_t part4 = rand() & (RAND_MAX - 1); - // rand only provides 15 bits on Win32 - uint64_t fullRandom = part1; - fullRandom <<= 15; - fullRandom |= part2; - fullRandom <<= 15; - fullRandom |= part3; - fullRandom <<= 15; - fullRandom |= part4; - - // Mask off the low 53bits - fullRandom &= (1LL << 53) - 1; - return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53); #elif PLATFORM(BREWMP) uint32_t bits; + // Is this a cryptographically strong source of random numbers? If so, we + // should move this into OSRandomSource. + // http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp851.pdf + // is slightly unclear on this point, although it seems to imply that it is + // secure. RefPtr<ISource> randomSource = createRefPtrInstance<ISource>(AEECLSID_RANDOM); ISOURCE_Read(randomSource.get(), reinterpret_cast<char*>(&bits), 4); @@ -118,6 +97,7 @@ double randomNumber() fullRandom &= (1LL << 53) - 1; return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53); #endif +#endif } } diff --git a/Source/JavaScriptCore/wtf/RetainPtr.h b/Source/JavaScriptCore/wtf/RetainPtr.h index fa7c163..3a11589 100644 --- a/Source/JavaScriptCore/wtf/RetainPtr.h +++ b/Source/JavaScriptCore/wtf/RetainPtr.h @@ -25,7 +25,10 @@ #include "NullPtr.h" #include "TypeTraits.h" #include <algorithm> + +#if USE(CF) #include <CoreFoundation/CoreFoundation.h> +#endif #ifdef __OBJC__ #import <Foundation/Foundation.h> diff --git a/Source/JavaScriptCore/wtf/SHA1.cpp b/Source/JavaScriptCore/wtf/SHA1.cpp new file mode 100644 index 0000000..e76f6ac --- /dev/null +++ b/Source/JavaScriptCore/wtf/SHA1.cpp @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// A straightforward SHA-1 implementation based on RFC 3174. +// http://www.ietf.org/rfc/rfc3174.txt +// The names of functions and variables (such as "a", "b", and "f") follow notations in RFC 3174. + +#include "config.h" +#include "SHA1.h" + +#include "Assertions.h" +#ifndef NDEBUG +#include "StringExtras.h" +#include "text/CString.h" +#endif + +namespace WTF { + +#ifdef NDEBUG +static inline void testSHA1() { } +#else +static bool isTestSHA1Done; + +static void expectSHA1(CString input, int repeat, CString expected) +{ + SHA1 sha1; + for (int i = 0; i < repeat; ++i) + sha1.addBytes(reinterpret_cast<const uint8_t*>(input.data()), input.length()); + Vector<uint8_t, 20> digest; + sha1.computeHash(digest); + char* buffer = 0; + CString actual = CString::newUninitialized(40, buffer); + for (size_t i = 0; i < 20; ++i) { + snprintf(buffer, 3, "%02X", digest.at(i)); + buffer += 2; + } + ASSERT_WITH_MESSAGE(actual == expected, "input: %s, repeat: %d, actual: %s, expected: %s", input.data(), repeat, actual.data(), expected.data()); +} + +static void testSHA1() +{ + if (isTestSHA1Done) + return; + isTestSHA1Done = true; + + // Examples taken from sample code in RFC 3174. + expectSHA1("abc", 1, "A9993E364706816ABA3E25717850C26C9CD0D89D"); + expectSHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1, "84983E441C3BD26EBAAE4AA1F95129E5E54670F1"); + expectSHA1("a", 1000000, "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F"); + expectSHA1("0123456701234567012345670123456701234567012345670123456701234567", 10, "DEA356A2CDDD90C7A7ECEDC5EBB563934F460452"); +} +#endif + +static inline uint32_t f(int t, uint32_t b, uint32_t c, uint32_t d) +{ + ASSERT(t >= 0 && t < 80); + if (t < 20) + return (b & c) | ((~b) & d); + if (t < 40) + return b ^ c ^ d; + if (t < 60) + return (b & c) | (b & d) | (c & d); + return b ^ c ^ d; +} + +static inline uint32_t k(int t) +{ + ASSERT(t >= 0 && t < 80); + if (t < 20) + return 0x5a827999; + if (t < 40) + return 0x6ed9eba1; + if (t < 60) + return 0x8f1bbcdc; + return 0xca62c1d6; +} + +static inline uint32_t rotateLeft(int n, uint32_t x) +{ + ASSERT(n >= 0 && n < 32); + return (x << n) | (x >> (32 - n)); +} + +SHA1::SHA1() +{ + // FIXME: Move unit tests somewhere outside the constructor. See bug 55853. + testSHA1(); + reset(); +} + +void SHA1::addBytes(const uint8_t* input, size_t length) +{ + while (length--) { + ASSERT(m_cursor < 64); + m_buffer[m_cursor++] = *input++; + ++m_totalBytes; + if (m_cursor == 64) + processBlock(); + } +} + +void SHA1::computeHash(Vector<uint8_t, 20>& digest) +{ + finalize(); + + digest.clear(); + digest.resize(20); + for (size_t i = 0; i < 5; ++i) { + // Treat hashValue as a big-endian value. + uint32_t hashValue = m_hash[i]; + for (int j = 0; j < 4; ++j) { + digest[4 * i + (3 - j)] = hashValue & 0xFF; + hashValue >>= 8; + } + } + + reset(); +} + +void SHA1::finalize() +{ + ASSERT(m_cursor < 64); + m_buffer[m_cursor++] = 0x80; + if (m_cursor > 56) { + // Pad out to next block. + while (m_cursor < 64) + m_buffer[m_cursor++] = 0x00; + processBlock(); + } + + for (size_t i = m_cursor; i < 56; ++i) + m_buffer[i] = 0x00; + + // Write the length as a big-endian 64-bit value. + uint64_t bits = m_totalBytes * 8; + for (int i = 0; i < 8; ++i) { + m_buffer[56 + (7 - i)] = bits & 0xFF; + bits >>= 8; + } + m_cursor = 64; + processBlock(); +} + +void SHA1::processBlock() +{ + ASSERT(m_cursor == 64); + + uint32_t w[80] = { 0 }; + for (int t = 0; t < 16; ++t) + w[t] = (m_buffer[t * 4] << 24) | (m_buffer[t * 4 + 1] << 16) | (m_buffer[t * 4 + 2] << 8) | m_buffer[t * 4 + 3]; + for (int t = 16; t < 80; ++t) + w[t] = rotateLeft(1, w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]); + + uint32_t a = m_hash[0]; + uint32_t b = m_hash[1]; + uint32_t c = m_hash[2]; + uint32_t d = m_hash[3]; + uint32_t e = m_hash[4]; + + for (int t = 0; t < 80; ++t) { + uint32_t temp = rotateLeft(5, a) + f(t, b, c, d) + e + w[t] + k(t); + e = d; + d = c; + c = rotateLeft(30, b); + b = a; + a = temp; + } + + m_hash[0] += a; + m_hash[1] += b; + m_hash[2] += c; + m_hash[3] += d; + m_hash[4] += e; + + m_cursor = 0; +} + +void SHA1::reset() +{ + m_cursor = 0; + m_totalBytes = 0; + m_hash[0] = 0x67452301; + m_hash[1] = 0xefcdab89; + m_hash[2] = 0x98badcfe; + m_hash[3] = 0x10325476; + m_hash[4] = 0xc3d2e1f0; + + // Clear the buffer after use in case it's sensitive. + memset(m_buffer, 0, sizeof(m_buffer)); +} + +} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/SHA1.h b/Source/JavaScriptCore/wtf/SHA1.h new file mode 100644 index 0000000..dad6dc8 --- /dev/null +++ b/Source/JavaScriptCore/wtf/SHA1.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WTF_SHA1_h +#define WTF_SHA1_h + +#include <wtf/Vector.h> + +namespace WTF { + +class SHA1 { +public: + SHA1(); + + void addBytes(const Vector<uint8_t>& input) + { + addBytes(input.data(), input.size()); + } + void addBytes(const uint8_t* input, size_t length); + + // computeHash has a side effect of resetting the state of the object. + void computeHash(Vector<uint8_t, 20>&); + +private: + void finalize(); + void processBlock(); + void reset(); + + uint8_t m_buffer[64]; + size_t m_cursor; // Number of bytes filled in m_buffer (0-64). + uint64_t m_totalBytes; // Number of bytes added so far. + uint32_t m_hash[5]; +}; + +} // namespace WTF + +using WTF::SHA1; + +#endif // WTF_SHA1_h diff --git a/Source/JavaScriptCore/wtf/SentinelLinkedList.h b/Source/JavaScriptCore/wtf/SentinelLinkedList.h new file mode 100644 index 0000000..610d2d2 --- /dev/null +++ b/Source/JavaScriptCore/wtf/SentinelLinkedList.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2011 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. 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 INC. 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. + */ + +// A SentinelLinkedList is a linked list with dummy head and tail sentinels, +// which allow for branch-less insertion and removal, and removal without a +// pointer to the list. +// +// Requires: Node is a concrete class with: +// Node(SentinelTag); +// void setPrev(Node*); +// Node* prev(); +// void setNext(Node*); +// Node* next(); + +#ifndef SentinelLinkedList_h +#define SentinelLinkedList_h + +namespace WTF { + +enum SentinelTag { Sentinel }; + +template <typename Node> class SentinelLinkedList { +public: + typedef Node* iterator; + + SentinelLinkedList(); + + void push(Node*); + static void remove(Node*); + + iterator begin(); + iterator end(); + +private: + Node m_headSentinel; + Node m_tailSentinel; +}; + +template <typename Node> inline SentinelLinkedList<Node>::SentinelLinkedList() + : m_headSentinel(Sentinel) + , m_tailSentinel(Sentinel) +{ + m_headSentinel.setNext(&m_tailSentinel); + m_headSentinel.setPrev(0); + + m_tailSentinel.setPrev(&m_headSentinel); + m_tailSentinel.setNext(0); +} + +template <typename Node> inline typename SentinelLinkedList<Node>::iterator SentinelLinkedList<Node>::begin() +{ + return m_headSentinel.next(); +} + +template <typename Node> inline typename SentinelLinkedList<Node>::iterator SentinelLinkedList<Node>::end() +{ + return &m_tailSentinel; +} + +template <typename Node> inline void SentinelLinkedList<Node>::push(Node* node) +{ + ASSERT(node); + Node* prev = &m_headSentinel; + Node* next = m_headSentinel.next(); + + node->setPrev(prev); + node->setNext(next); + + prev->setNext(node); + next->setPrev(node); +} + +template <typename Node> inline void SentinelLinkedList<Node>::remove(Node* node) +{ + Node* prev = node->prev(); + Node* next = node->next(); + + prev->setNext(next); + next->setPrev(prev); +} + +} + +using WTF::SentinelLinkedList; + +#endif + diff --git a/Source/JavaScriptCore/wtf/SinglyLinkedList.h b/Source/JavaScriptCore/wtf/SinglyLinkedList.h new file mode 100644 index 0000000..c00bf36 --- /dev/null +++ b/Source/JavaScriptCore/wtf/SinglyLinkedList.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2011 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. 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 INC. 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 SinglyLinkedList_h +#define SinglyLinkedList_h + +namespace WTF { + +template <typename Node> class SinglyLinkedList { +public: + SinglyLinkedList(); + + bool isEmpty(); + + void push(Node*); + Node* pop(); + +private: + Node* m_head; +}; + +template <typename Node> inline SinglyLinkedList<Node>::SinglyLinkedList() + : m_head(0) +{ +} + +template <typename Node> inline bool SinglyLinkedList<Node>::isEmpty() +{ + return !m_head; +} + +template <typename Node> inline void SinglyLinkedList<Node>::push(Node* node) +{ + ASSERT(node); + node->setNext(m_head); + m_head = node; +} + +template <typename Node> inline Node* SinglyLinkedList<Node>::pop() +{ + Node* tmp = m_head; + m_head = m_head->next(); + return tmp; +} + +} + +using WTF::SinglyLinkedList; + +#endif diff --git a/Source/JavaScriptCore/wtf/ThreadingWin.cpp b/Source/JavaScriptCore/wtf/ThreadingWin.cpp index 4ca290f..c452205 100644 --- a/Source/JavaScriptCore/wtf/ThreadingWin.cpp +++ b/Source/JavaScriptCore/wtf/ThreadingWin.cpp @@ -332,6 +332,7 @@ bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMillisecon res = ReleaseSemaphore(m_blockLock, 1, 0); ASSERT(res); + --mutex.m_recursionCount; LeaveCriticalSection(&mutex.m_internalMutex); // Main wait - use timeout. @@ -365,6 +366,7 @@ bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMillisecon } EnterCriticalSection (&mutex.m_internalMutex); + ++mutex.m_recursionCount; return !timedOut; } diff --git a/Source/JavaScriptCore/wtf/Vector.h b/Source/JavaScriptCore/wtf/Vector.h index 6d8dd4c..2fb4114 100644 --- a/Source/JavaScriptCore/wtf/Vector.h +++ b/Source/JavaScriptCore/wtf/Vector.h @@ -282,6 +282,7 @@ namespace WTF { public: void allocateBuffer(size_t newCapacity) { + ASSERT(newCapacity); m_capacity = newCapacity; if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T)) CRASH(); @@ -290,6 +291,7 @@ namespace WTF { bool tryAllocateBuffer(size_t newCapacity) { + ASSERT(newCapacity); if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T)) return false; @@ -360,7 +362,10 @@ namespace WTF { VectorBuffer(size_t capacity) { - allocateBuffer(capacity); + // Calling malloc(0) might take a lock and may actually do an + // allocation on some systems (e.g. Brew). + if (capacity) + allocateBuffer(capacity); } ~VectorBuffer() @@ -392,6 +397,7 @@ namespace WTF { template<typename T, size_t inlineCapacity> class VectorBuffer : private VectorBufferBase<T> { + WTF_MAKE_NONCOPYABLE(VectorBuffer); private: typedef VectorBufferBase<T> Base; public: @@ -414,6 +420,7 @@ namespace WTF { void allocateBuffer(size_t newCapacity) { + // FIXME: This should ASSERT(!m_buffer) to catch misuse/leaks. if (newCapacity > inlineCapacity) Base::allocateBuffer(newCapacity); else { diff --git a/Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp b/Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp index 8dcfb9e..7c51ee1 100644 --- a/Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp +++ b/Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp @@ -61,11 +61,6 @@ template <> void freeOwnedGPtr<GDir>(GDir* ptr) g_dir_close(ptr); } -template <> void freeOwnedGPtr<GFile>(GFile* ptr) -{ - if (ptr) - g_object_unref(ptr); -} } // namespace WTF #endif // ENABLE(GLIB_SUPPORT) diff --git a/Source/JavaScriptCore/wtf/gobject/GOwnPtr.h b/Source/JavaScriptCore/wtf/gobject/GOwnPtr.h index 4136f28..8c7e837 100644 --- a/Source/JavaScriptCore/wtf/gobject/GOwnPtr.h +++ b/Source/JavaScriptCore/wtf/gobject/GOwnPtr.h @@ -39,7 +39,6 @@ template<> void freeOwnedGPtr<GCond>(GCond*); template<> void freeOwnedGPtr<GMutex>(GMutex*); template<> void freeOwnedGPtr<GPatternSpec>(GPatternSpec*); template<> void freeOwnedGPtr<GDir>(GDir*); -template<> void freeOwnedGPtr<GFile>(GFile*); template <typename T> class GOwnPtr { WTF_MAKE_NONCOPYABLE(GOwnPtr); diff --git a/Source/JavaScriptCore/wtf/text/AtomicString.h b/Source/JavaScriptCore/wtf/text/AtomicString.h index ab5b366..45a71e7 100644 --- a/Source/JavaScriptCore/wtf/text/AtomicString.h +++ b/Source/JavaScriptCore/wtf/text/AtomicString.h @@ -95,7 +95,7 @@ public: static void remove(StringImpl*); -#if PLATFORM(CF) +#if USE(CF) AtomicString(CFStringRef s) : m_string(add(String(s).impl())) { } CFStringRef createCFString() const { return m_string.createCFString(); } #endif diff --git a/Source/JavaScriptCore/wtf/text/StringImpl.cpp b/Source/JavaScriptCore/wtf/text/StringImpl.cpp index c83ec42..9afd1d2 100644 --- a/Source/JavaScriptCore/wtf/text/StringImpl.cpp +++ b/Source/JavaScriptCore/wtf/text/StringImpl.cpp @@ -458,14 +458,14 @@ intptr_t StringImpl::toIntPtr(bool* ok) return charactersToIntPtr(m_data, m_length, ok); } -double StringImpl::toDouble(bool* ok) +double StringImpl::toDouble(bool* ok, bool* didReadNumber) { - return charactersToDouble(m_data, m_length, ok); + return charactersToDouble(m_data, m_length, ok, didReadNumber); } -float StringImpl::toFloat(bool* ok) +float StringImpl::toFloat(bool* ok, bool* didReadNumber) { - return charactersToFloat(m_data, m_length, ok); + return charactersToFloat(m_data, m_length, ok, didReadNumber); } static bool equal(const UChar* a, const char* b, int length) @@ -1005,15 +1005,23 @@ bool equalIgnoringNullity(StringImpl* a, StringImpl* b) return false; } -WTF::Unicode::Direction StringImpl::defaultWritingDirection() +WTF::Unicode::Direction StringImpl::defaultWritingDirection(bool* hasStrongDirectionality) { for (unsigned i = 0; i < m_length; ++i) { WTF::Unicode::Direction charDirection = WTF::Unicode::direction(m_data[i]); - if (charDirection == WTF::Unicode::LeftToRight) + if (charDirection == WTF::Unicode::LeftToRight) { + if (hasStrongDirectionality) + *hasStrongDirectionality = true; return WTF::Unicode::LeftToRight; - if (charDirection == WTF::Unicode::RightToLeft || charDirection == WTF::Unicode::RightToLeftArabic) + } + if (charDirection == WTF::Unicode::RightToLeft || charDirection == WTF::Unicode::RightToLeftArabic) { + if (hasStrongDirectionality) + *hasStrongDirectionality = true; return WTF::Unicode::RightToLeft; + } } + if (hasStrongDirectionality) + *hasStrongDirectionality = false; return WTF::Unicode::LeftToRight; } diff --git a/Source/JavaScriptCore/wtf/text/StringImpl.h b/Source/JavaScriptCore/wtf/text/StringImpl.h index 25411e1..a08427b 100644 --- a/Source/JavaScriptCore/wtf/text/StringImpl.h +++ b/Source/JavaScriptCore/wtf/text/StringImpl.h @@ -34,7 +34,7 @@ #include <wtf/text/StringImplBase.h> #include <wtf/unicode/Unicode.h> -#if PLATFORM(CF) +#if USE(CF) typedef const struct __CFString * CFStringRef; #endif @@ -281,8 +281,8 @@ public: uint64_t toUInt64(bool* ok = 0); // ignores trailing garbage intptr_t toIntPtr(bool* ok = 0); // ignores trailing garbage - double toDouble(bool* ok = 0); - float toFloat(bool* ok = 0); + double toDouble(bool* ok = 0, bool* didReadNumber = 0); + float toFloat(bool* ok = 0, bool* didReadNumber = 0); PassRefPtr<StringImpl> lower(); PassRefPtr<StringImpl> upper(); @@ -316,9 +316,9 @@ public: PassRefPtr<StringImpl> replace(StringImpl*, StringImpl*); PassRefPtr<StringImpl> replace(unsigned index, unsigned len, StringImpl*); - WTF::Unicode::Direction defaultWritingDirection(); + WTF::Unicode::Direction defaultWritingDirection(bool* hasStrongDirectionality = 0); -#if PLATFORM(CF) +#if USE(CF) CFStringRef createCFString(); #endif #ifdef __OBJC__ diff --git a/Source/JavaScriptCore/wtf/text/TextPosition.h b/Source/JavaScriptCore/wtf/text/TextPosition.h index 9f426ea..bb3ffa4 100644 --- a/Source/JavaScriptCore/wtf/text/TextPosition.h +++ b/Source/JavaScriptCore/wtf/text/TextPosition.h @@ -89,7 +89,7 @@ public: ZeroBasedNumber() {} int zeroBasedInt() const { return m_value; } - + int convertAsOneBasedInt() const { return m_value + 1; } OneBasedNumber convertToOneBased() const; bool operator==(ZeroBasedNumber other) { return m_value == other.m_value; } diff --git a/Source/JavaScriptCore/wtf/text/WTFString.cpp b/Source/JavaScriptCore/wtf/text/WTFString.cpp index b9b4e74..d862f96 100644 --- a/Source/JavaScriptCore/wtf/text/WTFString.cpp +++ b/Source/JavaScriptCore/wtf/text/WTFString.cpp @@ -561,24 +561,28 @@ intptr_t String::toIntPtr(bool* ok) const return m_impl->toIntPtr(ok); } -double String::toDouble(bool* ok) const +double String::toDouble(bool* ok, bool* didReadNumber) const { if (!m_impl) { if (ok) *ok = false; + if (didReadNumber) + *didReadNumber = false; return 0.0; } - return m_impl->toDouble(ok); + return m_impl->toDouble(ok, didReadNumber); } -float String::toFloat(bool* ok) const +float String::toFloat(bool* ok, bool* didReadNumber) const { if (!m_impl) { if (ok) *ok = false; + if (didReadNumber) + *didReadNumber = false; return 0.0f; } - return m_impl->toFloat(ok); + return m_impl->toFloat(ok, didReadNumber); } String String::threadsafeCopy() const @@ -937,11 +941,13 @@ intptr_t charactersToIntPtr(const UChar* data, size_t length, bool* ok) return toIntegralType<intptr_t>(data, lengthOfCharactersAsInteger(data, length), ok, 10); } -double charactersToDouble(const UChar* data, size_t length, bool* ok) +double charactersToDouble(const UChar* data, size_t length, bool* ok, bool* didReadNumber) { if (!length) { if (ok) *ok = false; + if (didReadNumber) + *didReadNumber = false; return 0.0; } @@ -949,17 +955,20 @@ double charactersToDouble(const UChar* data, size_t length, bool* ok) for (unsigned i = 0; i < length; ++i) bytes[i] = data[i] < 0x7F ? data[i] : '?'; bytes[length] = '\0'; + char* start = bytes.data(); char* end; - double val = WTF::strtod(bytes.data(), &end); + double val = WTF::strtod(start, &end); if (ok) *ok = (end == 0 || *end == '\0'); + if (didReadNumber) + *didReadNumber = end - start; return val; } -float charactersToFloat(const UChar* data, size_t length, bool* ok) +float charactersToFloat(const UChar* data, size_t length, bool* ok, bool* didReadNumber) { // FIXME: This will return ok even when the string fits into a double but not a float. - return static_cast<float>(charactersToDouble(data, length, ok)); + return static_cast<float>(charactersToDouble(data, length, ok, didReadNumber)); } } // namespace WTF diff --git a/Source/JavaScriptCore/wtf/text/WTFString.h b/Source/JavaScriptCore/wtf/text/WTFString.h index 0aee2ef..713a6c3 100644 --- a/Source/JavaScriptCore/wtf/text/WTFString.h +++ b/Source/JavaScriptCore/wtf/text/WTFString.h @@ -31,7 +31,7 @@ #include <objc/objc.h> #endif -#if PLATFORM(CF) +#if USE(CF) typedef const struct __CFString * CFStringRef; #endif @@ -79,8 +79,8 @@ int64_t charactersToInt64(const UChar*, size_t, bool* ok = 0); // ignores traili uint64_t charactersToUInt64(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage intptr_t charactersToIntPtr(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage -double charactersToDouble(const UChar*, size_t, bool* ok = 0); -float charactersToFloat(const UChar*, size_t, bool* ok = 0); +double charactersToDouble(const UChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); +float charactersToFloat(const UChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); template<bool isSpecialCharacter(UChar)> bool isAllSpecialCharacters(const UChar*, size_t); @@ -92,6 +92,11 @@ public: // Construct a string with UTF-16 data. String(const UChar* characters, unsigned length); + // Construct a string by copying the contents of a vector. To avoid + // copying, consider using String::adopt instead. + template<size_t inlineCapacity> + explicit String(const Vector<UChar, inlineCapacity>&); + // Construct a string with UTF-16 data, from a null-terminated source. String(const UChar*); @@ -264,8 +269,8 @@ public: int64_t toInt64(bool* ok = 0) const; uint64_t toUInt64(bool* ok = 0) const; intptr_t toIntPtr(bool* ok = 0) const; - double toDouble(bool* ok = 0) const; - float toFloat(bool* ok = 0) const; + double toDouble(bool* ok = 0, bool* didReadNumber = 0) const; + float toFloat(bool* ok = 0, bool* didReadNumber = 0) const; bool percentage(int& percentage) const; @@ -284,7 +289,7 @@ public: operator UnspecifiedBoolTypeA() const; operator UnspecifiedBoolTypeB() const; -#if PLATFORM(CF) +#if USE(CF) String(CFStringRef); CFStringRef createCFString() const; #endif @@ -326,7 +331,14 @@ public: static String fromUTF8WithLatin1Fallback(const char*, size_t); // Determines the writing direction using the Unicode Bidi Algorithm rules P2 and P3. - WTF::Unicode::Direction defaultWritingDirection() const { return m_impl ? m_impl->defaultWritingDirection() : WTF::Unicode::LeftToRight; } + WTF::Unicode::Direction defaultWritingDirection(bool* hasStrongDirectionality = 0) const + { + if (m_impl) + return m_impl->defaultWritingDirection(hasStrongDirectionality); + if (hasStrongDirectionality) + *hasStrongDirectionality = false; + return WTF::Unicode::LeftToRight; + } bool containsOnlyASCII() const { return charactersAreAllASCII(characters(), length()); } bool containsOnlyLatin1() const { return charactersAreAllLatin1(characters(), length()); } @@ -378,6 +390,12 @@ inline void swap(String& a, String& b) { a.swap(b); } // Definitions of string operations +template<size_t inlineCapacity> +String::String(const Vector<UChar, inlineCapacity>& vector) + : m_impl(vector.size() ? StringImpl::create(vector.data(), vector.size()) : 0) +{ +} + #ifdef __OBJC__ // This is for situations in WebKit where the long standing behavior has been // "nil if empty", so we try to maintain longstanding behavior for the sake of diff --git a/Source/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp b/Source/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp index 805b114..ca27ba2 100644 --- a/Source/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp +++ b/Source/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp @@ -59,7 +59,7 @@ Collator::Collator(const char* locale) PassOwnPtr<Collator> Collator::userDefault() { -#if OS(DARWIN) && PLATFORM(CF) +#if OS(DARWIN) && USE(CF) // Mac OS X doesn't set UNIX locale to match user-selected one, so ICU default doesn't work. #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !OS(IOS) RetainPtr<CFLocaleRef> currentLocale(AdoptCF, CFLocaleCopyCurrent()); diff --git a/Source/JavaScriptCore/wtf/wtf.pri b/Source/JavaScriptCore/wtf/wtf.pri index 3be3b5f..5f15eb0 100644 --- a/Source/JavaScriptCore/wtf/wtf.pri +++ b/Source/JavaScriptCore/wtf/wtf.pri @@ -23,6 +23,7 @@ SOURCES += \ wtf/PageBlock.cpp \ wtf/RandomNumber.cpp \ wtf/RefCountedLeakCounter.cpp \ + wtf/SHA1.cpp \ wtf/StackBounds.cpp \ wtf/TCSystemAlloc.cpp \ wtf/ThreadingNone.cpp \ diff --git a/Source/JavaScriptCore/wtf/wx/StringWx.cpp b/Source/JavaScriptCore/wtf/wx/StringWx.cpp index fe0fd89..d5f6c57 100644 --- a/Source/JavaScriptCore/wtf/wx/StringWx.cpp +++ b/Source/JavaScriptCore/wtf/wx/StringWx.cpp @@ -25,12 +25,15 @@ #include "config.h" -#include <wtf/text/CString.h> -#include <wtf/text/WTFString.h> - +// The wx headers must come first in this case, because the wtf/text headers +// import windows.h, and we need to allow the wx headers to set its configuration +// first. #include <wx/defs.h> #include <wx/string.h> +#include <wtf/text/CString.h> +#include <wtf/text/WTFString.h> + namespace WTF { String::String(const wxString& wxstr) @@ -39,9 +42,10 @@ String::String(const wxString& wxstr) #error "This code only works in Unicode build of wxWidgets" #endif -#if SIZEOF_WCHAR_T == U_SIZEOF_UCHAR +#if SIZEOF_WCHAR_T == 2 - m_impl = StringImpl::create(wxstr.wc_str(), wxstr.length()); + const UChar* str = wxstr.wc_str(); + const size_t len = wxstr.length(); #else // SIZEOF_WCHAR_T == 4 @@ -58,13 +62,18 @@ String::String(const wxString& wxstr) #endif size_t wideLength = wxstr.length(); - UChar* data; wxMBConvUTF16 conv; - unsigned utf16Length = conv.FromWChar(0, 0, wideString, wideLength); - m_impl = StringImpl::createUninitialized(utf16Length, data); - conv.FromWChar((char*)data, utf16Length, wideString, wideLength); -#endif // SIZEOF_WCHAR_T == 4 + const size_t utf16bufLen = conv.FromWChar(0, 0, wideString, wideLength); + wxCharBuffer utf16buf(utf16bufLen); + + const UChar* str = (const UChar*)utf16buf.data(); + size_t len = conv.FromWChar(utf16buf.data(), utf16bufLen, wideString, wideLength) / 2; + +#endif // SIZEOF_WCHAR_T == 2 + + m_impl = StringImpl::create(str, len); + } String::operator wxString() const |