diff options
Diffstat (limited to 'JavaScriptCore/runtime')
63 files changed, 1358 insertions, 1413 deletions
diff --git a/JavaScriptCore/runtime/Arguments.cpp b/JavaScriptCore/runtime/Arguments.cpp index bb30e3b..450dc7d 100644 --- a/JavaScriptCore/runtime/Arguments.cpp +++ b/JavaScriptCore/runtime/Arguments.cpp @@ -151,13 +151,13 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& sl return true; } - return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::from(i)), slot); + return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::number(i)), slot); } bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { bool isArrayIndex; - unsigned i = propertyName.toArrayIndex(&isArrayIndex); + unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) { slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]); @@ -182,7 +182,7 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNa bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { bool isArrayIndex; - unsigned i = propertyName.toArrayIndex(&isArrayIndex); + unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) { descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].jsValue(), DontEnum); @@ -209,7 +209,7 @@ void Arguments::getOwnPropertyNames(ExecState* exec, PropertyNameArray& property if (mode == IncludeDontEnumProperties) { for (unsigned i = 0; i < d->numArguments; ++i) { if (!d->deletedArguments || !d->deletedArguments[i]) - propertyNames.add(Identifier(exec, UString::from(i))); + propertyNames.add(Identifier(exec, UString::number(i))); } propertyNames.add(exec->propertyNames().callee); propertyNames.add(exec->propertyNames().length); @@ -227,13 +227,13 @@ void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& return; } - JSObject::put(exec, Identifier(exec, UString::from(i)), value, slot); + JSObject::put(exec, Identifier(exec, UString::number(i)), value, slot); } void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { bool isArrayIndex; - unsigned i = propertyName.toArrayIndex(&isArrayIndex); + unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) d->registers[d->firstParameterIndex + i] = JSValue(value); @@ -270,13 +270,13 @@ bool Arguments::deleteProperty(ExecState* exec, unsigned i) } } - return JSObject::deleteProperty(exec, Identifier(exec, UString::from(i))); + return JSObject::deleteProperty(exec, Identifier(exec, UString::number(i))); } bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName) { bool isArrayIndex; - unsigned i = propertyName.toArrayIndex(&isArrayIndex); + unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex && i < d->numArguments) { if (!d->deletedArguments) { d->deletedArguments.set(new bool[d->numArguments]); diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp index fa6eb99..e49ca28 100644 --- a/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -166,7 +166,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned totalSize = length ? length - 1 : 0; - Vector<RefPtr<UString::Rep>, 256> strBuffer(length); + Vector<RefPtr<StringImpl>, 256> strBuffer(length); for (unsigned k = 0; k < length; k++) { JSValue element; if (isRealArray && thisObj->canGetIndex(k)) @@ -178,8 +178,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) continue; UString str = element.toString(exec); - strBuffer[k] = str.rep(); - totalSize += str.size(); + strBuffer[k] = str.impl(); + totalSize += str.length(); if (!strBuffer.data()) { throwOutOfMemoryError(exec); @@ -199,7 +199,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) for (unsigned i = 0; i < length; i++) { if (i) buffer.append(','); - if (RefPtr<UString::Rep> rep = strBuffer[i]) + if (RefPtr<StringImpl> rep = strBuffer[i]) buffer.append(rep->characters(), rep->length()); } ASSERT(buffer.size() == totalSize); diff --git a/JavaScriptCore/runtime/Collector.h b/JavaScriptCore/runtime/Collector.h index 38c178b..05d5c10 100644 --- a/JavaScriptCore/runtime/Collector.h +++ b/JavaScriptCore/runtime/Collector.h @@ -130,6 +130,7 @@ namespace JSC { void registerThread(); // Only needs to be called by clients that can use the same heap from multiple threads. static bool isCellMarked(const JSCell*); + static bool checkMarkCell(const JSCell*); static void markCell(JSCell*); WeakGCHandle* addWeakGCHandle(JSCell*); @@ -226,6 +227,14 @@ namespace JSC { FixedArray<uint32_t, BITMAP_WORDS> bits; bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); } void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); } + bool getset(size_t n) + { + unsigned i = (1 << (n & 0x1F)); + uint32_t& b = bits[n >> 5]; + bool r = !!(b & i); + b |= i; + return r; + } void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); } void clearAll() { memset(bits.data(), 0, sizeof(bits)); } ALWAYS_INLINE void advanceToNextPossibleFreeCell(size_t& startCell) @@ -288,6 +297,11 @@ namespace JSC { return cellBlock(cell)->marked.get(cellOffset(cell)); } + inline bool Heap::checkMarkCell(const JSCell* cell) + { + return cellBlock(cell)->marked.getset(cellOffset(cell)); + } + inline void Heap::markCell(JSCell* cell) { cellBlock(cell)->marked.set(cellOffset(cell)); diff --git a/JavaScriptCore/runtime/DateConversion.cpp b/JavaScriptCore/runtime/DateConversion.cpp index 70dbaa0..7eb82e4 100644 --- a/JavaScriptCore/runtime/DateConversion.cpp +++ b/JavaScriptCore/runtime/DateConversion.cpp @@ -47,6 +47,7 @@ #include "UString.h" #include <wtf/DateMath.h> #include <wtf/StringExtras.h> +#include <wtf/text/CString.h> using namespace WTF; @@ -56,7 +57,7 @@ double parseDate(ExecState* exec, const UString &date) { if (date == exec->globalData().cachedDateString) return exec->globalData().cachedDateStringValue; - double value = parseDateFromNullTerminatedCharacters(exec, date.UTF8String().data()); + double value = parseDateFromNullTerminatedCharacters(exec, date.utf8().data()); exec->globalData().cachedDateString = date; exec->globalData().cachedDateStringValue = value; return value; diff --git a/JavaScriptCore/runtime/DatePrototype.cpp b/JavaScriptCore/runtime/DatePrototype.cpp index 9dec33b..249f427 100644 --- a/JavaScriptCore/runtime/DatePrototype.cpp +++ b/JavaScriptCore/runtime/DatePrototype.cpp @@ -170,7 +170,7 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMil CFRelease(locale); if (useCustomFormat) { - CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, customFormatString.data(), customFormatString.size()); + CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, customFormatString.characters(), customFormatString.length()); CFDateFormatterSetFormat(formatter, customFormatCFString); CFRelease(customFormatCFString); } diff --git a/JavaScriptCore/runtime/ExceptionHelpers.cpp b/JavaScriptCore/runtime/ExceptionHelpers.cpp index 3e0b70c..871b2d5 100644 --- a/JavaScriptCore/runtime/ExceptionHelpers.cpp +++ b/JavaScriptCore/runtime/ExceptionHelpers.cpp @@ -36,6 +36,7 @@ #include "JSNotAnObject.h" #include "Interpreter.h" #include "Nodes.h" +#include "StringConcatenate.h" namespace JSC { diff --git a/JavaScriptCore/runtime/FunctionConstructor.cpp b/JavaScriptCore/runtime/FunctionConstructor.cpp index a036eef..f72a273 100644 --- a/JavaScriptCore/runtime/FunctionConstructor.cpp +++ b/JavaScriptCore/runtime/FunctionConstructor.cpp @@ -31,6 +31,7 @@ #include "Nodes.h" #include "Parser.h" #include "StringBuilder.h" +#include "StringConcatenate.h" namespace JSC { diff --git a/JavaScriptCore/runtime/FunctionPrototype.cpp b/JavaScriptCore/runtime/FunctionPrototype.cpp index fb2f627..c740624 100644 --- a/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/JavaScriptCore/runtime/FunctionPrototype.cpp @@ -71,13 +71,13 @@ CallType FunctionPrototype::getCallData(CallData& callData) static inline void insertSemicolonIfNeeded(UString& functionBody) { ASSERT(functionBody[0] == '{'); - ASSERT(functionBody[functionBody.size() - 1] == '}'); + ASSERT(functionBody[functionBody.length() - 1] == '}'); - for (size_t i = functionBody.size() - 2; i > 0; --i) { + for (size_t i = functionBody.length() - 2; i > 0; --i) { UChar ch = functionBody[i]; if (!Lexer::isWhiteSpace(ch) && !Lexer::isLineTerminator(ch)) { if (ch != ';' && ch != '}') - functionBody = makeString(functionBody.substr(0, i + 1), ";", functionBody.substr(i + 1, functionBody.size() - (i + 1))); + functionBody = makeString(functionBody.substringSharingImpl(0, i + 1), ";", functionBody.substringSharingImpl(i + 1, functionBody.length() - (i + 1))); return; } } diff --git a/JavaScriptCore/runtime/Identifier.cpp b/JavaScriptCore/runtime/Identifier.cpp index 46772d0..d375eff 100644 --- a/JavaScriptCore/runtime/Identifier.cpp +++ b/JavaScriptCore/runtime/Identifier.cpp @@ -65,7 +65,7 @@ void deleteIdentifierTable(IdentifierTable* table) delete table; } -bool Identifier::equal(const UString::Rep* r, const char* s) +bool Identifier::equal(const StringImpl* r, const char* s) { int length = r->length(); const UChar* d = r->characters(); @@ -75,7 +75,7 @@ bool Identifier::equal(const UString::Rep* r, const char* s) return s[length] == 0; } -bool Identifier::equal(const UString::Rep* r, const UChar* s, unsigned length) +bool Identifier::equal(const StringImpl* r, const UChar* s, unsigned length) { if (r->length() != length) return false; @@ -89,19 +89,19 @@ bool Identifier::equal(const UString::Rep* r, const UChar* s, unsigned length) struct IdentifierCStringTranslator { static unsigned hash(const char* c) { - return UString::Rep::computeHash(c); + return StringImpl::computeHash(c); } - static bool equal(UString::Rep* r, const char* s) + static bool equal(StringImpl* r, const char* s) { return Identifier::equal(r, s); } - static void translate(UString::Rep*& location, const char* c, unsigned hash) + static void translate(StringImpl*& location, const char* c, unsigned hash) { size_t length = strlen(c); UChar* d; - UString::Rep* r = UString::Rep::createUninitialized(length, d).releaseRef(); + StringImpl* r = StringImpl::createUninitialized(length, d).releaseRef(); for (size_t i = 0; i != length; i++) d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend r->setHash(hash); @@ -109,12 +109,12 @@ struct IdentifierCStringTranslator { } }; -PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c) +PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const char* c) { if (!c) - return UString::null().rep(); + return 0; if (!c[0]) - return UString::Rep::empty(); + return StringImpl::empty(); if (!c[1]) return add(globalData, globalData->smallStrings.singleCharacterStringRep(static_cast<unsigned char>(c[0]))); @@ -125,18 +125,18 @@ PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c if (iter != literalIdentifierTable.end()) return iter->second; - pair<HashSet<UString::Rep*>::iterator, bool> addResult = identifierTable.add<const char*, IdentifierCStringTranslator>(c); + pair<HashSet<StringImpl*>::iterator, bool> addResult = identifierTable.add<const char*, IdentifierCStringTranslator>(c); // If the string is newly-translated, then we need to adopt it. // The boolean in the pair tells us if that is so. - RefPtr<UString::Rep> addedString = addResult.second ? adoptRef(*addResult.first) : *addResult.first; + RefPtr<StringImpl> addedString = addResult.second ? adoptRef(*addResult.first) : *addResult.first; literalIdentifierTable.add(c, addedString.get()); return addedString.release(); } -PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const char* c) +PassRefPtr<StringImpl> Identifier::add(ExecState* exec, const char* c) { return add(&exec->globalData(), c); } @@ -149,18 +149,18 @@ struct UCharBuffer { struct IdentifierUCharBufferTranslator { static unsigned hash(const UCharBuffer& buf) { - return UString::Rep::computeHash(buf.s, buf.length); + return StringImpl::computeHash(buf.s, buf.length); } - static bool equal(UString::Rep* str, const UCharBuffer& buf) + static bool equal(StringImpl* str, const UCharBuffer& buf) { return Identifier::equal(str, buf.s, buf.length); } - static void translate(UString::Rep*& location, const UCharBuffer& buf, unsigned hash) + static void translate(StringImpl*& location, const UCharBuffer& buf, unsigned hash) { UChar* d; - UString::Rep* r = UString::Rep::createUninitialized(buf.length, d).releaseRef(); + StringImpl* r = StringImpl::createUninitialized(buf.length, d).releaseRef(); for (unsigned i = 0; i != buf.length; i++) d[i] = buf.s[i]; r->setHash(hash); @@ -168,7 +168,50 @@ struct IdentifierUCharBufferTranslator { } }; -PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const UChar* s, int length) +uint32_t Identifier::toUInt32(const UString& string, bool& ok) +{ + ok = false; + + unsigned length = string.length(); + const UChar* characters = string.characters(); + + // An empty string is not a number. + if (!length) + return 0; + + // Get the first character, turning it into a digit. + uint32_t value = characters[0] - '0'; + if (value > 9) + return 0; + + // Check for leading zeros. If the first characher is 0, then the + // length of the string must be one - e.g. "042" is not equal to "42". + if (!value && length > 1) + return 0; + + while (--length) { + // Multiply value by 10, checking for overflow out of 32 bits. + if (value > 0xFFFFFFFFU / 10) + return 0; + value *= 10; + + // Get the next character, turning it into a digit. + uint32_t newValue = *(++characters) - '0'; + if (newValue > 9) + return 0; + + // Add in the old value, checking for overflow out of 32 bits. + newValue += value; + if (newValue < value) + return 0; + value = newValue; + } + + ok = true; + return value; +} + +PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const UChar* s, int length) { if (length == 1) { UChar c = s[0]; @@ -176,21 +219,21 @@ PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const UChar* return add(globalData, globalData->smallStrings.singleCharacterStringRep(c)); } if (!length) - return UString::Rep::empty(); + return StringImpl::empty(); UCharBuffer buf = {s, length}; - pair<HashSet<UString::Rep*>::iterator, bool> addResult = globalData->identifierTable->add<UCharBuffer, IdentifierUCharBufferTranslator>(buf); + pair<HashSet<StringImpl*>::iterator, bool> addResult = globalData->identifierTable->add<UCharBuffer, IdentifierUCharBufferTranslator>(buf); // If the string is newly-translated, then we need to adopt it. // The boolean in the pair tells us if that is so. return addResult.second ? adoptRef(*addResult.first) : *addResult.first; } -PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const UChar* s, int length) +PassRefPtr<StringImpl> Identifier::add(ExecState* exec, const UChar* s, int length) { return add(&exec->globalData(), s, length); } -PassRefPtr<UString::Rep> Identifier::addSlowCase(JSGlobalData* globalData, UString::Rep* r) +PassRefPtr<StringImpl> Identifier::addSlowCase(JSGlobalData* globalData, StringImpl* r) { ASSERT(!r->isIdentifier()); // The empty & null strings are static singletons, and static strings are handled @@ -208,7 +251,7 @@ PassRefPtr<UString::Rep> Identifier::addSlowCase(JSGlobalData* globalData, UStri return *globalData->identifierTable->add(r).first; } -PassRefPtr<UString::Rep> Identifier::addSlowCase(ExecState* exec, UString::Rep* r) +PassRefPtr<StringImpl> Identifier::addSlowCase(ExecState* exec, StringImpl* r) { return addSlowCase(&exec->globalData(), r); } diff --git a/JavaScriptCore/runtime/Identifier.h b/JavaScriptCore/runtime/Identifier.h index 2db0716..3a8aed7 100644 --- a/JavaScriptCore/runtime/Identifier.h +++ b/JavaScriptCore/runtime/Identifier.h @@ -24,6 +24,7 @@ #include "JSGlobalData.h" #include "ThreadSpecific.h" #include "UString.h" +#include <wtf/text/CString.h> namespace JSC { @@ -34,25 +35,23 @@ namespace JSC { public: Identifier() { } - Identifier(ExecState* exec, const char* s) : _ustring(add(exec, s)) { } // Only to be used with string literals. - Identifier(ExecState* exec, const UChar* s, int length) : _ustring(add(exec, s, length)) { } - Identifier(ExecState* exec, UString::Rep* rep) : _ustring(add(exec, rep)) { } - Identifier(ExecState* exec, const UString& s) : _ustring(add(exec, s.rep())) { } + Identifier(ExecState* exec, const char* s) : m_string(add(exec, s)) { } // Only to be used with string literals. + Identifier(ExecState* exec, const UChar* s, int length) : m_string(add(exec, s, length)) { } + Identifier(ExecState* exec, StringImpl* rep) : m_string(add(exec, rep)) { } + Identifier(ExecState* exec, const UString& s) : m_string(add(exec, s.impl())) { } - Identifier(JSGlobalData* globalData, const char* s) : _ustring(add(globalData, s)) { } // Only to be used with string literals. - Identifier(JSGlobalData* globalData, const UChar* s, int length) : _ustring(add(globalData, s, length)) { } - Identifier(JSGlobalData* globalData, UString::Rep* rep) : _ustring(add(globalData, rep)) { } - Identifier(JSGlobalData* globalData, const UString& s) : _ustring(add(globalData, s.rep())) { } + Identifier(JSGlobalData* globalData, const char* s) : m_string(add(globalData, s)) { } // Only to be used with string literals. + Identifier(JSGlobalData* globalData, const UChar* s, int length) : m_string(add(globalData, s, length)) { } + Identifier(JSGlobalData* globalData, StringImpl* rep) : m_string(add(globalData, rep)) { } + Identifier(JSGlobalData* globalData, const UString& s) : m_string(add(globalData, s.impl())) { } - // Special constructor for cases where we overwrite an object in place. - Identifier(PlacementNewAdoptType) : _ustring(PlacementNewAdopt) { } + const UString& ustring() const { return m_string; } + StringImpl* impl() const { return m_string.impl(); } - const UString& ustring() const { return _ustring; } + const UChar* characters() const { return m_string.characters(); } + int length() const { return m_string.length(); } - const UChar* data() const { return _ustring.data(); } - int size() const { return _ustring.size(); } - - const char* ascii() const { return _ustring.ascii(); } + CString ascii() const { return m_string.ascii(); } static Identifier from(ExecState* exec, unsigned y); static Identifier from(ExecState* exec, int y); @@ -60,15 +59,13 @@ namespace JSC { static Identifier from(JSGlobalData*, unsigned y); static Identifier from(JSGlobalData*, int y); static Identifier from(JSGlobalData*, double y); - - bool isNull() const { return _ustring.isNull(); } - bool isEmpty() const { return _ustring.isEmpty(); } - - uint32_t toUInt32(bool* ok) const { return _ustring.toUInt32(ok); } - uint32_t toUInt32(bool* ok, bool tolerateEmptyString) const { return _ustring.toUInt32(ok, tolerateEmptyString); }; - uint32_t toStrictUInt32(bool* ok) const { return _ustring.toStrictUInt32(ok); } - unsigned toArrayIndex(bool* ok) const { return _ustring.toArrayIndex(ok); } - double toDouble() const { return _ustring.toDouble(); } + + static uint32_t toUInt32(const UString&, bool& ok); + uint32_t toUInt32(bool& ok) const { return toUInt32(m_string, ok); } + unsigned toArrayIndex(bool& ok) const; + + bool isNull() const { return m_string.isNull(); } + bool isEmpty() const { return m_string.isEmpty(); } friend bool operator==(const Identifier&, const Identifier&); friend bool operator!=(const Identifier&, const Identifier&); @@ -76,23 +73,23 @@ namespace JSC { friend bool operator==(const Identifier&, const char*); friend bool operator!=(const Identifier&, const char*); - static bool equal(const UString::Rep*, const char*); - static bool equal(const UString::Rep*, const UChar*, unsigned length); - static bool equal(const UString::Rep* a, const UString::Rep* b) { return ::equal(a, b); } + static bool equal(const StringImpl*, const char*); + static bool equal(const StringImpl*, const UChar*, unsigned length); + static bool equal(const StringImpl* a, const StringImpl* b) { return ::equal(a, b); } - static PassRefPtr<UString::Rep> add(ExecState*, const char*); // Only to be used with string literals. - static PassRefPtr<UString::Rep> add(JSGlobalData*, const char*); // Only to be used with string literals. + static PassRefPtr<StringImpl> add(ExecState*, const char*); // Only to be used with string literals. + static PassRefPtr<StringImpl> add(JSGlobalData*, const char*); // Only to be used with string literals. private: - UString _ustring; + UString m_string; - static bool equal(const Identifier& a, const Identifier& b) { return a._ustring.rep() == b._ustring.rep(); } - static bool equal(const Identifier& a, const char* b) { return equal(a._ustring.rep(), b); } + static bool equal(const Identifier& a, const Identifier& b) { return a.m_string.impl() == b.m_string.impl(); } + static bool equal(const Identifier& a, const char* b) { return equal(a.m_string.impl(), b); } - static PassRefPtr<UString::Rep> add(ExecState*, const UChar*, int length); - static PassRefPtr<UString::Rep> add(JSGlobalData*, const UChar*, int length); + static PassRefPtr<StringImpl> add(ExecState*, const UChar*, int length); + static PassRefPtr<StringImpl> add(JSGlobalData*, const UChar*, int length); - static PassRefPtr<UString::Rep> add(ExecState* exec, UString::Rep* r) + static PassRefPtr<StringImpl> add(ExecState* exec, StringImpl* r) { #ifndef NDEBUG checkCurrentIdentifierTable(exec); @@ -101,7 +98,7 @@ namespace JSC { return r; return addSlowCase(exec, r); } - static PassRefPtr<UString::Rep> add(JSGlobalData* globalData, UString::Rep* r) + static PassRefPtr<StringImpl> add(JSGlobalData* globalData, StringImpl* r) { #ifndef NDEBUG checkCurrentIdentifierTable(globalData); @@ -111,8 +108,8 @@ namespace JSC { return addSlowCase(globalData, r); } - static PassRefPtr<UString::Rep> addSlowCase(ExecState*, UString::Rep* r); - static PassRefPtr<UString::Rep> addSlowCase(JSGlobalData*, UString::Rep* r); + static PassRefPtr<StringImpl> addSlowCase(ExecState*, StringImpl* r); + static PassRefPtr<StringImpl> addSlowCase(JSGlobalData*, StringImpl* r); static void checkCurrentIdentifierTable(ExecState*); static void checkCurrentIdentifierTable(JSGlobalData*); @@ -141,6 +138,11 @@ namespace JSC { IdentifierTable* createIdentifierTable(); void deleteIdentifierTable(IdentifierTable*); + struct IdentifierRepHash : PtrHash<RefPtr<StringImpl> > { + static unsigned hash(const RefPtr<StringImpl>& key) { return key->existingHash(); } + static unsigned hash(StringImpl* key) { return key->existingHash(); } + }; + } // namespace JSC #endif // Identifier_h diff --git a/JavaScriptCore/runtime/InitializeThreading.cpp b/JavaScriptCore/runtime/InitializeThreading.cpp index 51d43ee..33e8e68 100644 --- a/JavaScriptCore/runtime/InitializeThreading.cpp +++ b/JavaScriptCore/runtime/InitializeThreading.cpp @@ -48,9 +48,12 @@ static pthread_once_t initializeThreadingKeyOnce = PTHREAD_ONCE_INIT; static void initializeThreadingOnce() { + // StringImpl::empty() does not construct its static string in a threadsafe fashion, + // so ensure it has been initialized from here. + StringImpl::empty(); + WTF::initializeThreading(); wtfThreadData(); - initializeUString(); JSGlobalData::storeVPtrs(); #if ENABLE(JSC_MULTIPLE_THREADS) s_dtoaP5Mutex = new Mutex; diff --git a/JavaScriptCore/runtime/InternalFunction.cpp b/JavaScriptCore/runtime/InternalFunction.cpp index f774993..0a8d9de 100644 --- a/JavaScriptCore/runtime/InternalFunction.cpp +++ b/JavaScriptCore/runtime/InternalFunction.cpp @@ -61,7 +61,7 @@ const UString InternalFunction::displayName(ExecState* exec) if (displayName && isJSString(&exec->globalData(), displayName)) return asString(displayName)->tryGetValue(); - return UString::null(); + return UString(); } const UString InternalFunction::calculatedDisplayName(ExecState* exec) diff --git a/JavaScriptCore/runtime/JSArray.cpp b/JavaScriptCore/runtime/JSArray.cpp index 0db0a63..9c3570b 100644 --- a/JavaScriptCore/runtime/JSArray.cpp +++ b/JavaScriptCore/runtime/JSArray.cpp @@ -273,7 +273,7 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName } bool isArrayIndex; - unsigned i = propertyName.toArrayIndex(&isArrayIndex); + unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex) return JSArray::getOwnPropertySlot(exec, i, slot); @@ -290,7 +290,7 @@ bool JSArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& proper ArrayStorage* storage = m_storage; bool isArrayIndex; - unsigned i = propertyName.toArrayIndex(&isArrayIndex); + unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex) { if (i >= storage->m_length) return false; @@ -317,7 +317,7 @@ bool JSArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& proper void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { bool isArrayIndex; - unsigned i = propertyName.toArrayIndex(&isArrayIndex); + unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex) { put(exec, i, value); return; @@ -441,7 +441,7 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu return; } - m_storage = reinterpret_cast<ArrayStorage*>(static_cast<char*>(baseStorage) + m_indexBias * sizeof(JSValue)); + m_storage = reinterpret_cast_ptr<ArrayStorage*>(static_cast<char*>(baseStorage) + m_indexBias * sizeof(JSValue)); m_storage->m_allocBase = baseStorage; storage = m_storage; @@ -475,7 +475,7 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu bool JSArray::deleteProperty(ExecState* exec, const Identifier& propertyName) { bool isArrayIndex; - unsigned i = propertyName.toArrayIndex(&isArrayIndex); + unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex) return deleteProperty(exec, i); @@ -591,7 +591,7 @@ bool JSArray::increaseVectorLength(unsigned newLength) if (!tryFastRealloc(baseStorage, storageSize(newVectorLength + m_indexBias)).getValue(baseStorage)) return false; - storage = m_storage = reinterpret_cast<ArrayStorage*>(static_cast<char*>(baseStorage) + m_indexBias * sizeof(JSValue)); + storage = m_storage = reinterpret_cast_ptr<ArrayStorage*>(static_cast<char*>(baseStorage) + m_indexBias * sizeof(JSValue)); m_storage->m_allocBase = baseStorage; JSValue* vector = storage->m_vector; @@ -623,7 +623,7 @@ bool JSArray::increaseVectorPrefixLength(unsigned newLength) m_indexBias += newVectorLength - newLength; - m_storage = reinterpret_cast<ArrayStorage*>(static_cast<char*>(newBaseStorage) + m_indexBias * sizeof(JSValue)); + m_storage = reinterpret_cast_ptr<ArrayStorage*>(static_cast<char*>(newBaseStorage) + m_indexBias * sizeof(JSValue)); memcpy(m_storage, storage, storageSize(0)); memcpy(&m_storage->m_vector[newLength - m_vectorLength], &storage->m_vector[0], vectorLength * sizeof(JSValue)); @@ -802,7 +802,7 @@ void JSArray::shiftCount(ExecState* exec, int count) if (m_vectorLength) { char* newBaseStorage = reinterpret_cast<char*>(storage) + count * sizeof(JSValue); memmove(newBaseStorage, storage, storageSize(0)); - m_storage = reinterpret_cast<ArrayStorage*>(newBaseStorage); + m_storage = reinterpret_cast_ptr<ArrayStorage*>(newBaseStorage); m_indexBias += count; } @@ -839,7 +839,7 @@ void JSArray::unshiftCount(ExecState* exec, int count) m_indexBias -= count; char* newBaseStorage = reinterpret_cast<char*>(storage) - count * sizeof(JSValue); memmove(newBaseStorage, storage, storageSize(0)); - m_storage = reinterpret_cast<ArrayStorage*>(newBaseStorage); + m_storage = reinterpret_cast_ptr<ArrayStorage*>(newBaseStorage); m_vectorLength += count; } else if (!increaseVectorPrefixLength(m_vectorLength + count)) { throwOutOfMemoryError(exec); diff --git a/JavaScriptCore/runtime/JSArray.h b/JavaScriptCore/runtime/JSArray.h index f718d7e..9e155d8 100644 --- a/JavaScriptCore/runtime/JSArray.h +++ b/JavaScriptCore/runtime/JSArray.h @@ -236,7 +236,7 @@ namespace JSC { current.m_values++; JSCell* cell; - if (!value || !value.isCell() || Heap::isCellMarked(cell = value.asCell())) { + if (!value || !value.isCell() || Heap::checkMarkCell(cell = value.asCell())) { if (current.m_values == end) { m_markSets.removeLast(); continue; @@ -244,7 +244,6 @@ namespace JSC { goto findNextUnmarkedNullValue; } - Heap::markCell(cell); if (cell->structure()->typeInfo().type() < CompoundType) { if (current.m_values == end) { m_markSets.removeLast(); @@ -262,7 +261,17 @@ namespace JSC { markChildren(m_values.removeLast()); } } - + + // Rule from ECMA 15.2 about what an array index is. + // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1. + inline unsigned Identifier::toArrayIndex(bool& ok) const + { + unsigned i = toUInt32(ok); + if (ok && i >= 0xFFFFFFFFU) + ok = false; + return i; + } + } // namespace JSC #endif // JSArray_h diff --git a/JavaScriptCore/runtime/JSByteArray.cpp b/JavaScriptCore/runtime/JSByteArray.cpp index 803a08c..88519cf 100644 --- a/JavaScriptCore/runtime/JSByteArray.cpp +++ b/JavaScriptCore/runtime/JSByteArray.cpp @@ -60,7 +60,7 @@ PassRefPtr<Structure> JSByteArray::createStructure(JSValue prototype) bool JSByteArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { bool ok; - unsigned index = propertyName.toUInt32(&ok, false); + unsigned index = propertyName.toUInt32(ok); if (ok && canAccessIndex(index)) { slot.setValue(getIndex(exec, index)); return true; @@ -71,7 +71,7 @@ bool JSByteArray::getOwnPropertySlot(ExecState* exec, const Identifier& property bool JSByteArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { bool ok; - unsigned index = propertyName.toUInt32(&ok, false); + unsigned index = propertyName.toUInt32(ok); if (ok && canAccessIndex(index)) { descriptor.setDescriptor(getIndex(exec, index), DontDelete); return true; @@ -91,7 +91,7 @@ bool JSByteArray::getOwnPropertySlot(ExecState* exec, unsigned propertyName, Pro void JSByteArray::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { bool ok; - unsigned index = propertyName.toUInt32(&ok, false); + unsigned index = propertyName.toUInt32(ok); if (ok) { setIndex(exec, index, value); return; diff --git a/JavaScriptCore/runtime/JSCell.h b/JavaScriptCore/runtime/JSCell.h index 72f81df..2ffce8d 100644 --- a/JavaScriptCore/runtime/JSCell.h +++ b/JavaScriptCore/runtime/JSCell.h @@ -333,9 +333,8 @@ namespace JSC { { ASSERT(!m_isCheckingForDefaultMarkViolation); ASSERT(cell); - if (Heap::isCellMarked(cell)) + if (Heap::checkMarkCell(cell)) return; - Heap::markCell(cell); if (cell->structure()->typeInfo().type() >= CompoundType) m_values.append(cell); } diff --git a/JavaScriptCore/runtime/JSFunction.cpp b/JavaScriptCore/runtime/JSFunction.cpp index 49cc8fa..7eb9ba5 100644 --- a/JavaScriptCore/runtime/JSFunction.cpp +++ b/JavaScriptCore/runtime/JSFunction.cpp @@ -134,7 +134,7 @@ const UString JSFunction::displayName(ExecState* exec) if (displayName && isJSString(&exec->globalData(), displayName)) return asString(displayName)->tryGetValue(); - return UString::null(); + return UString(); } const UString JSFunction::calculatedDisplayName(ExecState* exec) diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp index abb2db2..ca8605b 100644 --- a/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/JavaScriptCore/runtime/JSGlobalData.cpp @@ -283,6 +283,7 @@ void JSGlobalData::resetDateCache() cachedUTCOffset = NaN; dstOffsetCache.reset(); cachedDateString = UString(); + cachedDateStringValue = NaN; dateInstanceCache.reset(); } diff --git a/JavaScriptCore/runtime/JSGlobalObject.h b/JavaScriptCore/runtime/JSGlobalObject.h index 115af87..e57b737 100644 --- a/JavaScriptCore/runtime/JSGlobalObject.h +++ b/JavaScriptCore/runtime/JSGlobalObject.h @@ -353,7 +353,7 @@ namespace JSC { GlobalPropertyInfo& global = globals[i]; ASSERT(global.attributes & DontDelete); SymbolTableEntry newEntry(index, global.attributes); - symbolTable().add(global.identifier.ustring().rep(), newEntry); + symbolTable().add(global.identifier.impl(), newEntry); registerAt(index) = global.value; } } diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index d88d6a9..1e20f7f 100644 --- a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -53,7 +53,7 @@ namespace JSC { static JSValue encode(ExecState* exec, const char* doNotEscape) { UString str = exec->argument(0).toString(exec); - CString cstr = str.UTF8String(true); + CString cstr = str.utf8(true); if (!cstr.data()) return throwError(exec, createURIError(exec, "String contained an illegal UTF-16 sequence.")); @@ -77,8 +77,8 @@ static JSValue decode(ExecState* exec, const char* doNotUnescape, bool strict) JSStringBuilder builder; UString str = exec->argument(0).toString(exec); int k = 0; - int len = str.size(); - const UChar* d = str.data(); + int len = str.length(); + const UChar* d = str.characters(); UChar u = 0; while (k < len) { const UChar* p = d + k; @@ -220,8 +220,8 @@ double parseIntOverflow(const UChar* s, int length, int radix) static double parseInt(const UString& s, int radix) { - int length = s.size(); - const UChar* data = s.data(); + int length = s.length(); + const UChar* data = s.characters(); int p = 0; while (p < length && isStrWhiteSpace(data[p])) @@ -265,9 +265,9 @@ static double parseInt(const UString& s, int radix) if (number >= mantissaOverflowLowerBound) { if (radix == 10) - number = WTF::strtod(s.substr(firstDigitPosition, p - firstDigitPosition).UTF8String().data(), 0); + number = WTF::strtod(s.substringSharingImpl(firstDigitPosition, p - firstDigitPosition).utf8().data(), 0); else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32) - number = parseIntOverflow(s.substr(firstDigitPosition, p - firstDigitPosition).UTF8String().data(), p - firstDigitPosition, radix); + number = parseIntOverflow(s.substringSharingImpl(firstDigitPosition, p - firstDigitPosition).utf8().data(), p - firstDigitPosition, radix); } if (!sawDigit) @@ -276,23 +276,161 @@ static double parseInt(const UString& s, int radix) return sign * number; } +static const int SizeOfInfinity = 8; + +static bool isInfinity(const UChar* data, const UChar* end) +{ + return (end - data) >= SizeOfInfinity + && data[0] == 'I' + && data[1] == 'n' + && data[2] == 'f' + && data[3] == 'i' + && data[4] == 'n' + && data[5] == 'i' + && data[6] == 't' + && data[7] == 'y'; +} + +// See ecma-262 9.3.1 +static double jsHexIntegerLiteral(const UChar*& data, const UChar* end) +{ + // Hex number. + data += 2; + const UChar* firstDigitPosition = data; + double number = 0; + while (true) { + number = number * 16 + toASCIIHexValue(*data); + ++data; + if (data == end) + break; + if (!isASCIIHexDigit(*data)) + break; + } + if (number >= mantissaOverflowLowerBound) + number = parseIntOverflow(firstDigitPosition, data - firstDigitPosition, 16); + + return number; +} + +// See ecma-262 9.3.1 +static double jsStrDecimalLiteral(const UChar*& data, const UChar* end) +{ + ASSERT(data < end); + + // Copy the sting into a null-terminated byte buffer, and call strtod. + Vector<char, 32> byteBuffer; + for (const UChar* characters = data; characters < end; ++characters) { + UChar character = *characters; + byteBuffer.append(isASCII(character) ? character : 0); + } + byteBuffer.append(0); + char* endOfNumber; + double number = WTF::strtod(byteBuffer.data(), &endOfNumber); + + // Check if strtod found a number; if so return it. + ptrdiff_t consumed = endOfNumber - byteBuffer.data(); + if (consumed) { + data += consumed; + return number; + } + + // Check for [+-]?Infinity + switch (*data) { + case 'I': + if (isInfinity(data, end)) { + data += SizeOfInfinity; + return Inf; + } + break; + + case '+': + if (isInfinity(data + 1, end)) { + data += SizeOfInfinity + 1; + return Inf; + } + break; + + case '-': + if (isInfinity(data + 1, end)) { + data += SizeOfInfinity + 1; + return -Inf; + } + break; + } + + // Not a number. + return NaN; +} + +// See ecma-262 9.3.1 +double jsToNumber(const UString& s) +{ + unsigned size = s.length(); + + if (size == 1) { + UChar c = s.characters()[0]; + if (isASCIIDigit(c)) + return c - '0'; + if (isStrWhiteSpace(c)) + return 0; + return NaN; + } + + const UChar* data = s.characters(); + const UChar* end = data + size; + + // Skip leading white space. + for (; data < end; ++data) { + if (!isStrWhiteSpace(*data)) + break; + } + + // Empty string. + if (data == end) + return 0.0; + + double number; + if (data[0] == '0' && data + 2 < end && (data[1] | 0x20) == 'x' && isASCIIHexDigit(data[2])) + number = jsHexIntegerLiteral(data, end); + else + number = jsStrDecimalLiteral(data, end); + + // Allow trailing white space. + for (; data < end; ++data) { + if (!isStrWhiteSpace(*data)) + break; + } + if (data != end) + return NaN; + + return number; +} + static double parseFloat(const UString& s) { - // Check for 0x prefix here, because toDouble allows it, but we must treat it as 0. - // Need to skip any whitespace and then one + or - sign. - int length = s.size(); - const UChar* data = s.data(); - int p = 0; - while (p < length && isStrWhiteSpace(data[p])) - ++p; + unsigned size = s.length(); - if (p < length && (data[p] == '+' || data[p] == '-')) - ++p; + if (size == 1) { + UChar c = s.characters()[0]; + if (isASCIIDigit(c)) + return c - '0'; + return NaN; + } + + const UChar* data = s.characters(); + const UChar* end = data + size; + + // Skip leading white space. + for (; data < end; ++data) { + if (!isStrWhiteSpace(*data)) + break; + } - if (length - p >= 2 && data[p] == '0' && (data[p + 1] == 'x' || data[p + 1] == 'X')) - return 0; + // Empty string. + if (data == end) + return NaN; - return s.toDouble(true /*tolerant*/, false /* NaN for empty string */); + return jsStrDecimalLiteral(data, end); } EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec) @@ -404,8 +542,8 @@ EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec) JSStringBuilder builder; UString str = exec->argument(0).toString(exec); - const UChar* c = str.data(); - for (unsigned k = 0; k < str.size(); k++, c++) { + const UChar* c = str.characters(); + for (unsigned k = 0; k < str.length(); k++, c++) { int u = c[0]; if (u > 255) { char tmp[7]; @@ -428,9 +566,9 @@ EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec) StringBuilder builder; UString str = exec->argument(0).toString(exec); int k = 0; - int len = str.size(); + int len = str.length(); while (k < len) { - const UChar* c = str.data() + k; + const UChar* c = str.characters() + k; UChar u; if (c[0] == '%' && k <= len - 6 && c[1] == 'u') { if (isASCIIHexDigit(c[2]) && isASCIIHexDigit(c[3]) && isASCIIHexDigit(c[4]) && isASCIIHexDigit(c[5])) { @@ -453,7 +591,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec) #ifndef NDEBUG EncodedJSValue JSC_HOST_CALL globalFuncJSCPrint(ExecState* exec) { - CString string = exec->argument(0).toString(exec).UTF8String(); + CString string = exec->argument(0).toString(exec).utf8(); puts(string.data()); return JSValue::encode(jsUndefined()); } diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.h b/JavaScriptCore/runtime/JSGlobalObjectFunctions.h index e634fae..6dc7343 100644 --- a/JavaScriptCore/runtime/JSGlobalObjectFunctions.h +++ b/JavaScriptCore/runtime/JSGlobalObjectFunctions.h @@ -55,6 +55,7 @@ namespace JSC { double parseIntOverflow(const char*, int length, int radix); double parseIntOverflow(const UChar*, int length, int radix); bool isStrWhiteSpace(UChar); + double jsToNumber(const UString& s); } // namespace JSC diff --git a/JavaScriptCore/runtime/JSNumberCell.cpp b/JavaScriptCore/runtime/JSNumberCell.cpp index a61c751..77388e0 100644 --- a/JavaScriptCore/runtime/JSNumberCell.cpp +++ b/JavaScriptCore/runtime/JSNumberCell.cpp @@ -54,7 +54,7 @@ double JSNumberCell::toNumber(ExecState*) const UString JSNumberCell::toString(ExecState*) const { - return UString::from(m_value); + return UString::number(m_value); } JSObject* JSNumberCell::toObject(ExecState* exec) const diff --git a/JavaScriptCore/runtime/JSONObject.cpp b/JavaScriptCore/runtime/JSONObject.cpp index ccfd43a..ba50721 100644 --- a/JavaScriptCore/runtime/JSONObject.cpp +++ b/JavaScriptCore/runtime/JSONObject.cpp @@ -35,6 +35,7 @@ #include "Lookup.h" #include "PropertyNameArray.h" #include "StringBuilder.h" +#include "StringConcatenate.h" #include <wtf/MathExtras.h> namespace JSC { @@ -163,8 +164,8 @@ static inline UString gap(ExecState* exec, JSValue space) // If the space value is a string, use it as the gap string, otherwise use no gap string. UString spaces = space.getString(exec); - if (spaces.size() > maxGapLength) { - spaces = spaces.substr(0, maxGapLength); + if (spaces.length() > maxGapLength) { + spaces = spaces.substringSharingImpl(0, maxGapLength); } return spaces; } @@ -280,14 +281,14 @@ JSValue Stringifier::stringify(JSValue value) void Stringifier::appendQuotedString(StringBuilder& builder, const UString& value) { - int length = value.size(); + int length = value.length(); // String length plus 2 for quote marks plus 8 so we can accomodate a few escaped characters. builder.reserveCapacity(builder.size() + length + 2 + 8); builder.append('"'); - const UChar* data = value.data(); + const UChar* data = value.characters(); for (int i = 0; i < length; ++i) { int start = i; while (i < length && (data[i] > 0x1F && data[i] != '"' && data[i] != '\\')) @@ -405,7 +406,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& if (!isfinite(numericValue)) builder.append("null"); else - builder.append(UString::from(numericValue)); + builder.append(UString::number(numericValue)); return StringifySucceeded; } @@ -463,17 +464,17 @@ inline bool Stringifier::willIndent() const inline void Stringifier::indent() { // Use a single shared string, m_repeatedGap, so we don't keep allocating new ones as we indent and unindent. - unsigned newSize = m_indent.size() + m_gap.size(); - if (newSize > m_repeatedGap.size()) + unsigned newSize = m_indent.length() + m_gap.length(); + if (newSize > m_repeatedGap.length()) m_repeatedGap = makeString(m_repeatedGap, m_gap); - ASSERT(newSize <= m_repeatedGap.size()); - m_indent = m_repeatedGap.substr(0, newSize); + ASSERT(newSize <= m_repeatedGap.length()); + m_indent = m_repeatedGap.substringSharingImpl(0, newSize); } inline void Stringifier::unindent() { - ASSERT(m_indent.size() >= m_gap.size()); - m_indent = m_repeatedGap.substr(0, m_indent.size() - m_gap.size()); + ASSERT(m_indent.length() >= m_gap.length()); + m_indent = m_repeatedGap.substringSharingImpl(0, m_indent.length() - m_gap.length()); } inline void Stringifier::startNewLine(StringBuilder& builder) const @@ -722,7 +723,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) } case ArrayEndVisitMember: { JSArray* array = arrayStack.last(); - JSValue filteredValue = callReviver(array, jsString(m_exec, UString::from(indexStack.last())), outValue); + JSValue filteredValue = callReviver(array, jsString(m_exec, UString::number(indexStack.last())), outValue); if (filteredValue.isUndefined()) array->deleteProperty(m_exec, indexStack.last()); else { diff --git a/JavaScriptCore/runtime/JSStaticScopeObject.h b/JavaScriptCore/runtime/JSStaticScopeObject.h index dcece9d..c0519c1 100644 --- a/JavaScriptCore/runtime/JSStaticScopeObject.h +++ b/JavaScriptCore/runtime/JSStaticScopeObject.h @@ -47,7 +47,7 @@ namespace JSC{ : JSVariableObject(exec->globalData().staticScopeStructure, new JSStaticScopeObjectData()) { d()->registerStore = value; - symbolTable().add(ident.ustring().rep(), SymbolTableEntry(-1, attributes)); + symbolTable().add(ident.impl(), SymbolTableEntry(-1, attributes)); } virtual ~JSStaticScopeObject(); virtual void markChildren(MarkStack&); diff --git a/JavaScriptCore/runtime/JSString.cpp b/JavaScriptCore/runtime/JSString.cpp index 13c5a51..bc0120f 100644 --- a/JavaScriptCore/runtime/JSString.cpp +++ b/JavaScriptCore/runtime/JSString.cpp @@ -24,6 +24,7 @@ #include "JSString.h" #include "JSGlobalObject.h" +#include "JSGlobalObjectFunctions.h" #include "JSObject.h" #include "Operations.h" #include "StringObject.h" @@ -37,7 +38,7 @@ namespace JSC { // representing the rope is likely imbalanced with more nodes down the left side // (since appending to the string is likely more common) - and as such resolving // in this fashion should minimize work queue size. (If we built the queue forwards -// we would likely have to place all of the constituent UStringImpls into the +// we would likely have to place all of the constituent StringImpls into the // Vector before performing any concatenation, but by working backwards we likely // only fill the queue with the number of substrings at any given level in a // rope-of-ropes.) @@ -47,7 +48,7 @@ void JSString::resolveRope(ExecState* exec) const // Allocate the buffer to hold the final string, position initially points to the end. UChar* buffer; - if (PassRefPtr<UStringImpl> newImpl = UStringImpl::tryCreateUninitialized(m_length, buffer)) + if (PassRefPtr<StringImpl> newImpl = StringImpl::tryCreateUninitialized(m_length, buffer)) m_value = newImpl; else { for (unsigned i = 0; i < m_fiberCount; ++i) { @@ -79,10 +80,10 @@ void JSString::resolveRope(ExecState* exec) const workQueue.append(rope->fibers()[i]); currentFiber = rope->fibers()[fiberCountMinusOne]; } else { - UStringImpl* string = static_cast<UStringImpl*>(currentFiber); + StringImpl* string = static_cast<StringImpl*>(currentFiber); unsigned length = string->length(); position -= length; - UStringImpl::copyChars(position, string->characters(), length); + StringImpl::copyChars(position, string->characters(), length); // Was this the last item in the work queue? if (workQueue.isEmpty()) { @@ -108,26 +109,26 @@ void JSString::resolveRope(ExecState* exec) const JSValue JSString::replaceCharacter(ExecState* exec, UChar character, const UString& replacement) { if (!isRope()) { - unsigned matchPosition = m_value.find(character); - if (matchPosition == UString::NotFound) + size_t matchPosition = m_value.find(character); + if (matchPosition == notFound) return JSValue(this); - return jsString(exec, m_value.substr(0, matchPosition), replacement, m_value.substr(matchPosition + 1)); + return jsString(exec, m_value.substringSharingImpl(0, matchPosition), replacement, m_value.substringSharingImpl(matchPosition + 1)); } RopeIterator end; // Count total fibers and find matching string. size_t fiberCount = 0; - UStringImpl* matchString = 0; - int matchPosition = -1; + StringImpl* matchString = 0; + size_t matchPosition = notFound; for (RopeIterator it(m_other.m_fibers.data(), m_fiberCount); it != end; ++it) { ++fiberCount; if (matchString) continue; - UStringImpl* string = *it; + StringImpl* string = *it; matchPosition = string->find(character); - if (matchPosition == -1) + if (matchPosition == notFound) continue; matchString = string; } @@ -135,21 +136,21 @@ JSValue JSString::replaceCharacter(ExecState* exec, UChar character, const UStri if (!matchString) return this; - RopeBuilder builder(replacement.size() ? fiberCount + 2 : fiberCount + 1); + RopeBuilder builder(replacement.length() ? fiberCount + 2 : fiberCount + 1); if (UNLIKELY(builder.isOutOfMemory())) return throwOutOfMemoryError(exec); for (RopeIterator it(m_other.m_fibers.data(), m_fiberCount); it != end; ++it) { - UStringImpl* string = *it; + StringImpl* string = *it; if (string != matchString) { builder.append(UString(string)); continue; } - builder.append(UString(string).substr(0, matchPosition)); - if (replacement.size()) + builder.append(UString(string).substringSharingImpl(0, matchPosition)); + if (replacement.length()) builder.append(replacement); - builder.append(UString(string).substr(matchPosition + 1)); + builder.append(UString(string).substringSharingImpl(matchPosition + 1)); matchString = 0; } @@ -165,7 +166,7 @@ JSString* JSString::getIndexSlowCase(ExecState* exec, unsigned i) if (exec->exception()) return jsString(exec, ""); ASSERT(!isRope()); - ASSERT(i < m_value.size()); + ASSERT(i < m_value.length()); return jsSingleCharacterSubstring(exec, m_value, i); } @@ -177,7 +178,7 @@ JSValue JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const bool JSString::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result) { result = this; - number = value(exec).toDouble(); + number = jsToNumber(value(exec)); return false; } @@ -188,7 +189,7 @@ bool JSString::toBoolean(ExecState*) const double JSString::toNumber(ExecState* exec) const { - return value(exec).toDouble(); + return jsToNumber(value(exec)); } UString JSString::toString(ExecState* exec) const @@ -240,7 +241,7 @@ bool JSString::getStringPropertyDescriptor(ExecState* exec, const Identifier& pr } bool isStrictUInt32; - unsigned i = propertyName.toStrictUInt32(&isStrictUInt32); + unsigned i = propertyName.toUInt32(isStrictUInt32); if (isStrictUInt32 && i < m_length) { descriptor.setDescriptor(getIndex(exec, i), DontDelete | ReadOnly); return true; diff --git a/JavaScriptCore/runtime/JSString.h b/JavaScriptCore/runtime/JSString.h index 53c144b..12ced10 100644 --- a/JavaScriptCore/runtime/JSString.h +++ b/JavaScriptCore/runtime/JSString.h @@ -87,7 +87,7 @@ namespace JSC { void append(const UString& string) { ASSERT(m_rope); - m_rope->initializeFiber(m_index, string.rep()); + m_rope->initializeFiber(m_index, string.impl()); } void append(JSString* jsString) { @@ -132,12 +132,12 @@ namespace JSC { return *this; } - UStringImpl* operator*() + StringImpl* operator*() { WorkItem& item = m_workQueue.last(); RopeImpl::Fiber fiber = item.fibers[item.i]; ASSERT(!RopeImpl::isRope(fiber)); - return static_cast<UStringImpl*>(fiber); + return static_cast<StringImpl*>(fiber); } bool operator!=(const RopeIterator& other) const @@ -186,24 +186,24 @@ namespace JSC { ALWAYS_INLINE JSString(JSGlobalData* globalData, const UString& value) : JSCell(globalData->stringStructure.get()) - , m_length(value.size()) + , m_length(value.length()) , m_value(value) , m_fiberCount(0) { ASSERT(!m_value.isNull()); - Heap::heap(this)->reportExtraMemoryCost(value.cost()); + Heap::heap(this)->reportExtraMemoryCost(value.impl()->cost()); } enum HasOtherOwnerType { HasOtherOwner }; JSString(JSGlobalData* globalData, const UString& value, HasOtherOwnerType) : JSCell(globalData->stringStructure.get()) - , m_length(value.size()) + , m_length(value.length()) , m_value(value) , m_fiberCount(0) { ASSERT(!m_value.isNull()); } - JSString(JSGlobalData* globalData, PassRefPtr<UStringImpl> value, HasOtherOwnerType) + JSString(JSGlobalData* globalData, PassRefPtr<StringImpl> value, HasOtherOwnerType) : JSCell(globalData->stringStructure.get()) , m_length(value->length()) , m_value(value) @@ -235,7 +235,7 @@ namespace JSC { // This should only be called with fiberCount <= 3. JSString(JSGlobalData* globalData, unsigned fiberCount, JSString* s1, const UString& u2) : JSCell(globalData->stringStructure.get()) - , m_length(s1->length() + u2.size()) + , m_length(s1->length() + u2.length()) , m_fiberCount(fiberCount) { ASSERT(fiberCount <= s_maxInternalRopeLength); @@ -248,7 +248,7 @@ namespace JSC { // This should only be called with fiberCount <= 3. JSString(JSGlobalData* globalData, unsigned fiberCount, const UString& u1, JSString* s2) : JSCell(globalData->stringStructure.get()) - , m_length(u1.size() + s2->length()) + , m_length(u1.length() + s2->length()) , m_fiberCount(fiberCount) { ASSERT(fiberCount <= s_maxInternalRopeLength); @@ -276,7 +276,7 @@ namespace JSC { // This constructor constructs a new string by concatenating u1 & u2. JSString(JSGlobalData* globalData, const UString& u1, const UString& u2) : JSCell(globalData->stringStructure.get()) - , m_length(u1.size() + u2.size()) + , m_length(u1.length() + u2.length()) , m_fiberCount(2) { unsigned index = 0; @@ -288,7 +288,7 @@ namespace JSC { // This constructor constructs a new string by concatenating u1, u2 & u3. JSString(JSGlobalData* globalData, const UString& u1, const UString& u2, const UString& u3) : JSCell(globalData->stringStructure.get()) - , m_length(u1.size() + u2.size() + u3.size()) + , m_length(u1.length() + u2.length() + u3.length()) , m_fiberCount(s_maxInternalRopeLength) { unsigned index = 0; @@ -300,7 +300,7 @@ namespace JSC { JSString(JSGlobalData* globalData, const UString& value, JSStringFinalizerCallback finalizer, void* context) : JSCell(globalData->stringStructure.get()) - , m_length(value.size()) + , m_length(value.length()) , m_value(value) , m_fiberCount(0) { @@ -308,7 +308,7 @@ namespace JSC { // nasty hack because we can't union non-POD types m_other.m_finalizerCallback = finalizer; m_other.m_finalizerContext = context; - Heap::heap(this)->reportExtraMemoryCost(value.cost()); + Heap::heap(this)->reportExtraMemoryCost(value.impl()->cost()); } ~JSString() @@ -359,7 +359,7 @@ namespace JSC { void appendStringInConstruct(unsigned& index, const UString& string) { - UStringImpl* impl = string.rep(); + StringImpl* impl = string.impl(); impl->ref(); m_other.m_fibers[index++] = impl; } @@ -381,15 +381,15 @@ namespace JSC { if (v.isString()) { ASSERT(asCell(v)->isString()); JSString* s = static_cast<JSString*>(asCell(v)); - ASSERT(s->size() == 1); + ASSERT(s->fiberCount() == 1); appendStringInConstruct(index, s); m_length += s->length(); } else { UString u(v.toString(exec)); - UStringImpl* impl = u.rep(); + StringImpl* impl = u.impl(); impl->ref(); m_other.m_fibers[index++] = impl; - m_length += u.size(); + m_length += u.length(); } } @@ -427,7 +427,7 @@ namespace JSC { bool isRope() const { return m_fiberCount; } UString& string() { ASSERT(!isRope()); return m_value; } - unsigned size() { return m_fiberCount ? m_fiberCount : 1; } + unsigned fiberCount() { return m_fiberCount ? m_fiberCount : 1; } friend JSValue jsString(ExecState* exec, JSString* s1, JSString* s2); friend JSValue jsString(ExecState* exec, const UString& u1, JSString* s2); @@ -470,11 +470,11 @@ namespace JSC { inline JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset) { JSGlobalData* globalData = &exec->globalData(); - ASSERT(offset < static_cast<unsigned>(s.size())); - UChar c = s.data()[offset]; + ASSERT(offset < static_cast<unsigned>(s.length())); + UChar c = s.characters()[offset]; if (c <= 0xFF) return globalData->smallStrings.singleCharacterString(globalData, c); - return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(UStringImpl::create(s.rep(), offset, 1)))); + return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(StringImpl::create(s.impl(), offset, 1)))); } inline JSString* jsNontrivialString(JSGlobalData* globalData, const char* s) @@ -487,7 +487,7 @@ namespace JSC { inline JSString* jsNontrivialString(JSGlobalData* globalData, const UString& s) { - ASSERT(s.size() > 1); + ASSERT(s.length() > 1); return fixupVPtr(globalData, new (globalData) JSString(globalData, s)); } @@ -496,17 +496,17 @@ namespace JSC { ASSERT(canGetIndex(i)); if (isRope()) return getIndexSlowCase(exec, i); - ASSERT(i < m_value.size()); + ASSERT(i < m_value.length()); return jsSingleCharacterSubstring(exec, m_value, i); } inline JSString* jsString(JSGlobalData* globalData, const UString& s) { - int size = s.size(); + int size = s.length(); if (!size) return globalData->smallStrings.emptyString(globalData); if (size == 1) { - UChar c = s.data()[0]; + UChar c = s.characters()[0]; if (c <= 0xFF) return globalData->smallStrings.singleCharacterString(globalData, c); } @@ -515,33 +515,33 @@ namespace JSC { inline JSString* jsStringWithFinalizer(ExecState* exec, const UString& s, JSStringFinalizerCallback callback, void* context) { - ASSERT(s.size() && (s.size() > 1 || s.data()[0] > 0xFF)); + ASSERT(s.length() && (s.length() > 1 || s.characters()[0] > 0xFF)); JSGlobalData* globalData = &exec->globalData(); return fixupVPtr(globalData, new (globalData) JSString(globalData, s, callback, context)); } inline JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length) { - ASSERT(offset <= static_cast<unsigned>(s.size())); - ASSERT(length <= static_cast<unsigned>(s.size())); - ASSERT(offset + length <= static_cast<unsigned>(s.size())); + ASSERT(offset <= static_cast<unsigned>(s.length())); + ASSERT(length <= static_cast<unsigned>(s.length())); + ASSERT(offset + length <= static_cast<unsigned>(s.length())); if (!length) return globalData->smallStrings.emptyString(globalData); if (length == 1) { - UChar c = s.data()[offset]; + UChar c = s.characters()[offset]; if (c <= 0xFF) return globalData->smallStrings.singleCharacterString(globalData, c); } - return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(UStringImpl::create(s.rep(), offset, length)), JSString::HasOtherOwner)); + return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(StringImpl::create(s.impl(), offset, length)), JSString::HasOtherOwner)); } inline JSString* jsOwnedString(JSGlobalData* globalData, const UString& s) { - int size = s.size(); + int size = s.length(); if (!size) return globalData->smallStrings.emptyString(globalData); if (size == 1) { - UChar c = s.data()[0]; + UChar c = s.characters()[0]; if (c <= 0xFF) return globalData->smallStrings.singleCharacterString(globalData, c); } @@ -564,7 +564,7 @@ namespace JSC { } bool isStrictUInt32; - unsigned i = propertyName.toStrictUInt32(&isStrictUInt32); + unsigned i = propertyName.toUInt32(isStrictUInt32); if (isStrictUInt32 && i < m_length) { slot.setValue(getIndex(exec, i)); return true; diff --git a/JavaScriptCore/runtime/JSStringBuilder.h b/JavaScriptCore/runtime/JSStringBuilder.h index 8f208a1..25fe685 100644 --- a/JavaScriptCore/runtime/JSStringBuilder.h +++ b/JavaScriptCore/runtime/JSStringBuilder.h @@ -28,6 +28,7 @@ #include "ExceptionHelpers.h" #include "JSString.h" +#include "StringConcatenate.h" #include "Vector.h" namespace JSC { @@ -65,7 +66,7 @@ public: void append(const UString& str) { - m_okay &= buffer.tryAppend(str.data(), str.size()); + m_okay &= buffer.tryAppend(str.characters(), str.length()); } JSValue build(ExecState* exec) @@ -86,7 +87,7 @@ protected: template<typename StringType1, typename StringType2> inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2) { - PassRefPtr<UStringImpl> result = tryMakeString(string1, string2); + PassRefPtr<StringImpl> result = tryMakeString(string1, string2); if (!result) return throwOutOfMemoryError(exec); return jsNontrivialString(exec, result); @@ -95,7 +96,7 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, Stri template<typename StringType1, typename StringType2, typename StringType3> inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3) { - PassRefPtr<UStringImpl> result = tryMakeString(string1, string2, string3); + PassRefPtr<StringImpl> result = tryMakeString(string1, string2, string3); if (!result) return throwOutOfMemoryError(exec); return jsNontrivialString(exec, result); @@ -104,7 +105,7 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, Stri template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) { - PassRefPtr<UStringImpl> result = tryMakeString(string1, string2, string3, string4); + PassRefPtr<StringImpl> result = tryMakeString(string1, string2, string3, string4); if (!result) return throwOutOfMemoryError(exec); return jsNontrivialString(exec, result); @@ -113,7 +114,7 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, Stri template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) { - PassRefPtr<UStringImpl> result = tryMakeString(string1, string2, string3, string4, string5); + PassRefPtr<StringImpl> result = tryMakeString(string1, string2, string3, string4, string5); if (!result) return throwOutOfMemoryError(exec); return jsNontrivialString(exec, result); @@ -122,7 +123,7 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, Stri template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) { - PassRefPtr<UStringImpl> result = tryMakeString(string1, string2, string3, string4, string5, string6); + PassRefPtr<StringImpl> result = tryMakeString(string1, string2, string3, string4, string5, string6); if (!result) return throwOutOfMemoryError(exec); return jsNontrivialString(exec, result); diff --git a/JavaScriptCore/runtime/JSVariableObject.cpp b/JavaScriptCore/runtime/JSVariableObject.cpp index 7365001..81d05ba 100644 --- a/JavaScriptCore/runtime/JSVariableObject.cpp +++ b/JavaScriptCore/runtime/JSVariableObject.cpp @@ -36,7 +36,7 @@ namespace JSC { bool JSVariableObject::deleteProperty(ExecState* exec, const Identifier& propertyName) { - if (symbolTable().contains(propertyName.ustring().rep())) + if (symbolTable().contains(propertyName.impl())) return false; return JSObject::deleteProperty(exec, propertyName); @@ -60,7 +60,7 @@ bool JSVariableObject::isVariableObject() const bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertyDescriptor& descriptor) { - SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep()); + SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); if (!entry.isNull()) { descriptor.setDescriptor(registerAt(entry.getIndex()).jsValue(), entry.getAttributes() | DontDelete); return true; diff --git a/JavaScriptCore/runtime/JSVariableObject.h b/JavaScriptCore/runtime/JSVariableObject.h index f2efcdf..3f2e218 100644 --- a/JavaScriptCore/runtime/JSVariableObject.h +++ b/JavaScriptCore/runtime/JSVariableObject.h @@ -103,7 +103,7 @@ namespace JSC { inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot) { - SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep()); + SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); if (!entry.isNull()) { slot.setRegisterSlot(®isterAt(entry.getIndex())); return true; @@ -113,7 +113,7 @@ namespace JSC { inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable) { - SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep()); + SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); if (!entry.isNull()) { slot.setRegisterSlot(®isterAt(entry.getIndex())); slotIsWriteable = !entry.isReadOnly(); @@ -126,7 +126,7 @@ namespace JSC { { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); - SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep()); + SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); if (entry.isNull()) return false; if (entry.isReadOnly()) @@ -139,7 +139,7 @@ namespace JSC { { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); - SymbolTable::iterator iter = symbolTable().find(propertyName.ustring().rep()); + SymbolTable::iterator iter = symbolTable().find(propertyName.impl()); if (iter == symbolTable().end()) return false; SymbolTableEntry& entry = iter->second; diff --git a/JavaScriptCore/runtime/LiteralParser.h b/JavaScriptCore/runtime/LiteralParser.h index 0f8072b..6df5d06 100644 --- a/JavaScriptCore/runtime/LiteralParser.h +++ b/JavaScriptCore/runtime/LiteralParser.h @@ -72,8 +72,8 @@ namespace JSC { Lexer(const UString& s, ParserMode mode) : m_string(s) , m_mode(mode) - , m_ptr(s.data()) - , m_end(s.data() + s.size()) + , m_ptr(s.characters()) + , m_end(s.characters() + s.length()) { } diff --git a/JavaScriptCore/runtime/Lookup.cpp b/JavaScriptCore/runtime/Lookup.cpp index 50d096c..07416af 100644 --- a/JavaScriptCore/runtime/Lookup.cpp +++ b/JavaScriptCore/runtime/Lookup.cpp @@ -34,7 +34,7 @@ void HashTable::createTable(JSGlobalData* globalData) const for (int i = 0; i < compactSize; ++i) entries[i].setKey(0); for (int i = 0; values[i].key; ++i) { - UString::Rep* identifier = Identifier::add(globalData, values[i].key).releaseRef(); + StringImpl* identifier = Identifier::add(globalData, values[i].key).releaseRef(); int hashIndex = identifier->existingHash() & compactHashSizeMask; HashEntry* entry = &entries[hashIndex]; @@ -61,7 +61,7 @@ void HashTable::deleteTable() const if (table) { int max = compactSize; for (int i = 0; i != max; ++i) { - if (UString::Rep* key = table[i].key()) + if (StringImpl* key = table[i].key()) key->deref(); } delete [] table; diff --git a/JavaScriptCore/runtime/Lookup.h b/JavaScriptCore/runtime/Lookup.h index 5a96fd3..9bc81d4 100644 --- a/JavaScriptCore/runtime/Lookup.h +++ b/JavaScriptCore/runtime/Lookup.h @@ -55,7 +55,7 @@ namespace JSC { class HashEntry : public FastAllocBase { public: - void initialize(UString::Rep* key, unsigned char attributes, intptr_t v1, intptr_t v2 + void initialize(StringImpl* key, unsigned char attributes, intptr_t v1, intptr_t v2 #if ENABLE(JIT) , ThunkGenerator generator = 0 #endif @@ -71,8 +71,8 @@ namespace JSC { m_next = 0; } - void setKey(UString::Rep* key) { m_key = key; } - UString::Rep* key() const { return m_key; } + void setKey(StringImpl* key) { m_key = key; } + StringImpl* key() const { return m_key; } unsigned char attributes() const { return m_attributes; } @@ -91,7 +91,7 @@ namespace JSC { HashEntry* next() const { return m_next; } private: - UString::Rep* m_key; + StringImpl* m_key; unsigned char m_attributes; // JSObject attributes union { @@ -159,13 +159,13 @@ namespace JSC { { ASSERT(table); - const HashEntry* entry = &table[identifier.ustring().rep()->existingHash() & compactHashSizeMask]; + const HashEntry* entry = &table[identifier.impl()->existingHash() & compactHashSizeMask]; if (!entry->key()) return 0; do { - if (entry->key() == identifier.ustring().rep()) + if (entry->key() == identifier.impl()) return entry; entry = entry->next(); } while (entry); diff --git a/JavaScriptCore/runtime/NumberPrototype.cpp b/JavaScriptCore/runtime/NumberPrototype.cpp index e338d7c..80b7ce0 100644 --- a/JavaScriptCore/runtime/NumberPrototype.cpp +++ b/JavaScriptCore/runtime/NumberPrototype.cpp @@ -179,7 +179,7 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec) const char* lastCharInString = s + sizeof(s) - 1; double x = v.uncheckedGetNumber(); if (isnan(x) || isinf(x)) - return JSValue::encode(jsString(exec, UString::from(x))); + return JSValue::encode(jsString(exec, UString::number(x))); bool isNegative = x < 0.0; if (isNegative) @@ -271,7 +271,7 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec) } if (x >= pow(10.0, 21.0)) - return JSValue::encode(jsString(exec, makeString(s, UString::from(x)))); + return JSValue::encode(jsString(exec, makeString(s, UString::number(x)))); const double tenToTheF = pow(10.0, f); double n = floor(x * tenToTheF); @@ -280,7 +280,7 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec) UString m = integerPartNoExp(n); - int k = m.size(); + int k = m.length(); if (k <= f) { StringBuilder z; for (int i = 0; i < f + 1 - k; i++) @@ -288,13 +288,13 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec) z.append(m); m = z.build(); k = f + 1; - ASSERT(k == static_cast<int>(m.size())); + ASSERT(k == static_cast<int>(m.length())); } int kMinusf = k - f; - if (kMinusf < static_cast<int>(m.size())) - return JSValue::encode(jsString(exec, makeString(s, m.substr(0, kMinusf), ".", m.substr(kMinusf)))); - return JSValue::encode(jsString(exec, makeString(s, m.substr(0, kMinusf)))); + if (kMinusf < static_cast<int>(m.length())) + return JSValue::encode(jsString(exec, makeString(s, m.substringSharingImpl(0, kMinusf), ".", m.substringSharingImpl(kMinusf)))); + return JSValue::encode(jsString(exec, makeString(s, m.substringSharingImpl(0, kMinusf)))); } static void fractionalPartToString(char* buf, int& i, const char* result, int resultLength, int fractionalDigits) @@ -345,7 +345,7 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState* exec) double x = v.uncheckedGetNumber(); if (isnan(x) || isinf(x)) - return JSValue::encode(jsString(exec, UString::from(x))); + return JSValue::encode(jsString(exec, UString::number(x))); JSValue fractionalDigitsValue = exec->argument(0); double df = fractionalDigitsValue.toInteger(exec); @@ -455,11 +455,11 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec) m = integerPartNoExp(n); if (e < -6 || e >= precision) { - if (m.size() > 1) - m = makeString(m.substr(0, 1), ".", m.substr(1)); + if (m.length() > 1) + m = makeString(m.substringSharingImpl(0, 1), ".", m.substringSharingImpl(1)); if (e >= 0) - return JSValue::encode(jsMakeNontrivialString(exec, s, m, "e+", UString::from(e))); - return JSValue::encode(jsMakeNontrivialString(exec, s, m, "e-", UString::from(-e))); + return JSValue::encode(jsMakeNontrivialString(exec, s, m, "e+", UString::number(e))); + return JSValue::encode(jsMakeNontrivialString(exec, s, m, "e-", UString::number(-e))); } } else { m = charSequence('0', precision); @@ -469,8 +469,8 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec) if (e == precision - 1) return JSValue::encode(jsString(exec, makeString(s, m))); if (e >= 0) { - if (e + 1 < static_cast<int>(m.size())) - return JSValue::encode(jsString(exec, makeString(s, m.substr(0, e + 1), ".", m.substr(e + 1)))); + if (e + 1 < static_cast<int>(m.length())) + return JSValue::encode(jsString(exec, makeString(s, m.substringSharingImpl(0, e + 1), ".", m.substringSharingImpl(e + 1)))); return JSValue::encode(jsString(exec, makeString(s, m))); } return JSValue::encode(jsMakeNontrivialString(exec, s, "0.", charSequence('0', -(e + 1)), m)); diff --git a/JavaScriptCore/runtime/NumericStrings.h b/JavaScriptCore/runtime/NumericStrings.h index 47fbbb2..d65f142 100644 --- a/JavaScriptCore/runtime/NumericStrings.h +++ b/JavaScriptCore/runtime/NumericStrings.h @@ -40,7 +40,7 @@ namespace JSC { if (d == entry.key && !entry.value.isNull()) return entry.value; entry.key = d; - entry.value = UString::from(d); + entry.value = UString::number(d); return entry.value; } @@ -52,7 +52,7 @@ namespace JSC { if (i == entry.key && !entry.value.isNull()) return entry.value; entry.key = i; - entry.value = UString::from(i); + entry.value = UString::number(i); return entry.value; } @@ -64,7 +64,7 @@ namespace JSC { if (i == entry.key && !entry.value.isNull()) return entry.value; entry.key = i; - entry.value = UString::from(i); + entry.value = UString::number(i); return entry.value; } private: @@ -83,7 +83,7 @@ namespace JSC { { ASSERT(i < cacheSize); if (smallIntCache[i].isNull()) - smallIntCache[i] = UString::from(i); + smallIntCache[i] = UString::number(i); return smallIntCache[i]; } diff --git a/JavaScriptCore/runtime/ObjectPrototype.cpp b/JavaScriptCore/runtime/ObjectPrototype.cpp index 6197f75..57a8a31 100644 --- a/JavaScriptCore/runtime/ObjectPrototype.cpp +++ b/JavaScriptCore/runtime/ObjectPrototype.cpp @@ -65,7 +65,7 @@ void ObjectPrototype::put(ExecState* exec, const Identifier& propertyName, JSVal if (m_hasNoPropertiesWithUInt32Names) { bool isUInt32; - propertyName.toStrictUInt32(&isUInt32); + propertyName.toUInt32(isUInt32); m_hasNoPropertiesWithUInt32Names = !isUInt32; } } diff --git a/JavaScriptCore/runtime/Operations.h b/JavaScriptCore/runtime/Operations.h index bd6c205..eed1f16 100644 --- a/JavaScriptCore/runtime/Operations.h +++ b/JavaScriptCore/runtime/Operations.h @@ -46,7 +46,7 @@ namespace JSC { if ((length1 + length2) < length1) return throwOutOfMemoryError(exec); - unsigned fiberCount = s1->size() + s2->size(); + unsigned fiberCount = s1->fiberCount() + s2->fiberCount(); JSGlobalData* globalData = &exec->globalData(); if (fiberCount <= JSString::s_maxInternalRopeLength) @@ -62,7 +62,7 @@ namespace JSC { ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, JSString* s2) { - unsigned length1 = u1.size(); + unsigned length1 = u1.length(); if (!length1) return s2; unsigned length2 = s2->length(); @@ -71,7 +71,7 @@ namespace JSC { if ((length1 + length2) < length1) return throwOutOfMemoryError(exec); - unsigned fiberCount = 1 + s2->size(); + unsigned fiberCount = 1 + s2->fiberCount(); JSGlobalData* globalData = &exec->globalData(); if (fiberCount <= JSString::s_maxInternalRopeLength) @@ -90,13 +90,13 @@ namespace JSC { unsigned length1 = s1->length(); if (!length1) return jsString(exec, u2); - unsigned length2 = u2.size(); + unsigned length2 = u2.length(); if (!length2) return s1; if ((length1 + length2) < length1) return throwOutOfMemoryError(exec); - unsigned fiberCount = s1->size() + 1; + unsigned fiberCount = s1->fiberCount() + 1; JSGlobalData* globalData = &exec->globalData(); if (fiberCount <= JSString::s_maxInternalRopeLength) @@ -112,10 +112,10 @@ namespace JSC { ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, const UString& u2) { - unsigned length1 = u1.size(); + unsigned length1 = u1.length(); if (!length1) return jsString(exec, u2); - unsigned length2 = u2.size(); + unsigned length2 = u2.length(); if (!length2) return jsString(exec, u1); if ((length1 + length2) < length1) @@ -127,9 +127,9 @@ namespace JSC { ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, const UString& u2, const UString& u3) { - unsigned length1 = u1.size(); - unsigned length2 = u2.size(); - unsigned length3 = u3.size(); + unsigned length1 = u1.length(); + unsigned length2 = u2.length(); + unsigned length3 = u3.length(); if (!length1) return jsString(exec, u2, u3); if (!length2) @@ -154,7 +154,7 @@ namespace JSC { for (unsigned i = 0; i < count; ++i) { JSValue v = strings[i].jsValue(); if (LIKELY(v.isString())) - fiberCount += asString(v)->size(); + fiberCount += asString(v)->fiberCount(); else ++fiberCount; } @@ -193,13 +193,13 @@ namespace JSC { { unsigned fiberCount = 0; if (LIKELY(thisValue.isString())) - fiberCount += asString(thisValue)->size(); + fiberCount += asString(thisValue)->fiberCount(); else ++fiberCount; for (unsigned i = 0; i < exec->argumentCount(); ++i) { JSValue v = exec->argument(i); if (LIKELY(v.isString())) - fiberCount += asString(v)->size(); + fiberCount += asString(v)->fiberCount(); else ++fiberCount; } diff --git a/JavaScriptCore/runtime/PropertyMapHashTable.h b/JavaScriptCore/runtime/PropertyMapHashTable.h index 44dc2b8..bd452b6 100644 --- a/JavaScriptCore/runtime/PropertyMapHashTable.h +++ b/JavaScriptCore/runtime/PropertyMapHashTable.h @@ -27,13 +27,13 @@ namespace JSC { struct PropertyMapEntry { - UString::Rep* key; + StringImpl* key; unsigned offset; unsigned attributes; JSCell* specificValue; unsigned index; - PropertyMapEntry(UString::Rep* key, unsigned attributes, JSCell* specificValue) + PropertyMapEntry(StringImpl* key, unsigned attributes, JSCell* specificValue) : key(key) , offset(0) , attributes(attributes) @@ -42,7 +42,7 @@ namespace JSC { { } - PropertyMapEntry(UString::Rep* key, unsigned offset, unsigned attributes, JSCell* specificValue, unsigned index) + PropertyMapEntry(StringImpl* key, unsigned offset, unsigned attributes, JSCell* specificValue, unsigned index) : key(key) , offset(offset) , attributes(attributes) diff --git a/JavaScriptCore/runtime/PropertyNameArray.cpp b/JavaScriptCore/runtime/PropertyNameArray.cpp index 6b24669..afb41be 100644 --- a/JavaScriptCore/runtime/PropertyNameArray.cpp +++ b/JavaScriptCore/runtime/PropertyNameArray.cpp @@ -28,20 +28,20 @@ namespace JSC { static const size_t setThreshold = 20; -void PropertyNameArray::add(UString::Rep* identifier) +void PropertyNameArray::add(StringImpl* identifier) { - ASSERT(identifier == UString::null().rep() || identifier == UString::Rep::empty() || identifier->isIdentifier()); + ASSERT(!identifier || identifier == StringImpl::empty() || identifier->isIdentifier()); size_t size = m_data->propertyNameVector().size(); if (size < setThreshold) { for (size_t i = 0; i < size; ++i) { - if (identifier == m_data->propertyNameVector()[i].ustring().rep()) + if (identifier == m_data->propertyNameVector()[i].impl()) return; } } else { if (m_set.isEmpty()) { for (size_t i = 0; i < size; ++i) - m_set.add(m_data->propertyNameVector()[i].ustring().rep()); + m_set.add(m_data->propertyNameVector()[i].impl()); } if (!m_set.add(identifier).second) return; diff --git a/JavaScriptCore/runtime/PropertyNameArray.h b/JavaScriptCore/runtime/PropertyNameArray.h index 3dbcc9d..0da930f 100644 --- a/JavaScriptCore/runtime/PropertyNameArray.h +++ b/JavaScriptCore/runtime/PropertyNameArray.h @@ -68,9 +68,9 @@ namespace JSC { JSGlobalData* globalData() { return m_globalData; } - void add(const Identifier& identifier) { add(identifier.ustring().rep()); } - void add(UString::Rep*); - void addKnownUnique(UString::Rep* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); } + void add(const Identifier& identifier) { add(identifier.impl()); } + void add(StringImpl*); + void addKnownUnique(StringImpl* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); } Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; } const Identifier& operator[](unsigned i) const { return m_data->propertyNameVector()[i]; } @@ -86,7 +86,7 @@ namespace JSC { const_iterator end() const { return m_data->propertyNameVector().end(); } private: - typedef HashSet<UString::Rep*, PtrHash<UString::Rep*> > IdentifierSet; + typedef HashSet<StringImpl*, PtrHash<StringImpl*> > IdentifierSet; RefPtr<PropertyNameArrayData> m_data; IdentifierSet m_set; diff --git a/JavaScriptCore/runtime/RegExp.cpp b/JavaScriptCore/runtime/RegExp.cpp index 59e3f35..2b844c1 100644 --- a/JavaScriptCore/runtime/RegExp.cpp +++ b/JavaScriptCore/runtime/RegExp.cpp @@ -56,11 +56,11 @@ inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern, const US // NOTE: The global flag is handled on a case-by-case basis by functions like // String::match and RegExpObject::match. if (!flags.isNull()) { - if (flags.find('g') != UString::NotFound) + if (flags.find('g') != notFound) m_flagBits |= Global; - if (flags.find('i') != UString::NotFound) + if (flags.find('i') != notFound) m_flagBits |= IgnoreCase; - if (flags.find('m') != UString::NotFound) + if (flags.find('m') != notFound) m_flagBits |= Multiline; } compile(globalData); @@ -96,7 +96,7 @@ int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector) if (ovector) ovector->resize(0); - if (static_cast<unsigned>(startOffset) > s.size() || s.isNull()) { + if (static_cast<unsigned>(startOffset) > s.length() || s.isNull()) { m_lastMatchString = UString(); m_lastMatchStart = -1; m_lastOVector.shrink(0); @@ -105,7 +105,7 @@ int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector) // Perform check to see if this match call is the same as the last match invocation // and if it is return the prior result. - if ((startOffset == m_lastMatchStart) && (s.rep() == m_lastMatchString.rep())) { + if ((startOffset == m_lastMatchStart) && (s.impl() == m_lastMatchString.impl())) { if (ovector) *ovector = m_lastOVector; @@ -136,9 +136,9 @@ int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector) offsetVector[j] = -1; #if ENABLE(YARR_JIT) - int result = Yarr::executeRegex(m_regExpJITCode, s.data(), startOffset, s.size(), offsetVector, offsetVectorSize); + int result = Yarr::executeRegex(m_regExpJITCode, s.characters(), startOffset, s.length(), offsetVector, offsetVectorSize); #else - int result = Yarr::interpretRegex(m_regExpBytecode.get(), s.data(), startOffset, s.size(), offsetVector); + int result = Yarr::interpretRegex(m_regExpBytecode.get(), s.characters(), startOffset, s.length(), offsetVector); #endif if (result < 0) { @@ -176,7 +176,7 @@ void RegExp::compile(JSGlobalData*) m_regExp = 0; JSRegExpIgnoreCaseOption ignoreCaseOption = ignoreCase() ? JSRegExpIgnoreCase : JSRegExpDoNotIgnoreCase; JSRegExpMultilineOption multilineOption = multiline() ? JSRegExpMultiline : JSRegExpSingleLine; - m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(m_pattern.data()), m_pattern.size(), ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError); + m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(m_pattern.characters()), m_pattern.length(), ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError); } int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector) @@ -186,7 +186,7 @@ int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector) if (ovector) ovector->clear(); - if (static_cast<unsigned>(startOffset) > s.size() || s.isNull()) + if (static_cast<unsigned>(startOffset) > s.length() || s.isNull()) return -1; if (m_regExp) { @@ -204,7 +204,7 @@ int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector) offsetVector = ovector->data(); } - int numMatches = jsRegExpExecute(m_regExp, reinterpret_cast<const UChar*>(s.data()), s.size(), startOffset, offsetVector, offsetVectorSize); + int numMatches = jsRegExpExecute(m_regExp, reinterpret_cast<const UChar*>(s.characters()), s.length(), startOffset, offsetVector, offsetVectorSize); if (numMatches < 0) { #ifndef NDEBUG diff --git a/JavaScriptCore/runtime/RegExpCache.cpp b/JavaScriptCore/runtime/RegExpCache.cpp index b9d250d..d101758 100644 --- a/JavaScriptCore/runtime/RegExpCache.cpp +++ b/JavaScriptCore/runtime/RegExpCache.cpp @@ -33,7 +33,7 @@ namespace JSC { PassRefPtr<RegExp> RegExpCache::lookupOrCreate(const UString& patternString, const UString& flags) { - if (patternString.size() < maxCacheablePatternLength) { + if (patternString.length() < maxCacheablePatternLength) { pair<RegExpCacheMap::iterator, bool> result = m_cacheMap.add(RegExpKey(flags, patternString), 0); if (!result.second) return result.first->second; @@ -47,7 +47,7 @@ PassRefPtr<RegExp> RegExpCache::create(const UString& patternString, const UStri { RefPtr<RegExp> regExp = RegExp::create(m_globalData, patternString, flags); - if (patternString.size() >= maxCacheablePatternLength) + if (patternString.length() >= maxCacheablePatternLength) return regExp; RegExpKey key = RegExpKey(flags, patternString); @@ -63,7 +63,7 @@ PassRefPtr<RegExp> RegExpCache::create(const UString& patternString, const UStri m_cacheMap.remove(RegExpKey(patternKeyArray[m_nextKeyToEvict].flagsValue, patternKeyArray[m_nextKeyToEvict].pattern)); patternKeyArray[m_nextKeyToEvict].flagsValue = key.flagsValue; - patternKeyArray[m_nextKeyToEvict].pattern = patternString.rep(); + patternKeyArray[m_nextKeyToEvict].pattern = patternString.impl(); return regExp; } diff --git a/JavaScriptCore/runtime/RegExpCache.h b/JavaScriptCore/runtime/RegExpCache.h index fb30a9e..e897b43 100644 --- a/JavaScriptCore/runtime/RegExpCache.h +++ b/JavaScriptCore/runtime/RegExpCache.h @@ -28,6 +28,8 @@ #include "RegExp.h" #include "RegExpKey.h" #include "UString.h" +#include <wtf/FixedArray.h> +#include <wtf/HashMap.h> #ifndef RegExpCache_h #define RegExpCache_h diff --git a/JavaScriptCore/runtime/RegExpConstructor.cpp b/JavaScriptCore/runtime/RegExpConstructor.cpp index aff83e7..214e528 100644 --- a/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -35,6 +35,7 @@ #include "RegExpPrototype.h" #include "RegExp.h" #include "RegExpCache.h" +#include "StringConcatenate.h" #include <wtf/PassOwnPtr.h> namespace JSC { @@ -185,7 +186,7 @@ JSValue RegExpConstructor::getLeftContext(ExecState* exec) const JSValue RegExpConstructor::getRightContext(ExecState* exec) const { if (!d->lastOvector().isEmpty()) - return jsSubstring(exec, d->lastInput, d->lastOvector()[1], d->lastInput.size() - d->lastOvector()[1]); + return jsSubstring(exec, d->lastInput, d->lastOvector()[1], d->lastInput.length() - d->lastOvector()[1]); return jsEmptyString(exec); } diff --git a/JavaScriptCore/runtime/RegExpKey.h b/JavaScriptCore/runtime/RegExpKey.h index 2bbdb07..cd1368d 100644 --- a/JavaScriptCore/runtime/RegExpKey.h +++ b/JavaScriptCore/runtime/RegExpKey.h @@ -26,6 +26,7 @@ */ #include "UString.h" +#include <wtf/text/StringHash.h> #ifndef RegExpKey_h #define RegExpKey_h @@ -34,7 +35,7 @@ namespace JSC { struct RegExpKey { int flagsValue; - RefPtr<UString::Rep> pattern; + RefPtr<StringImpl> pattern; RegExpKey() : flagsValue(0) @@ -48,18 +49,24 @@ struct RegExpKey { RegExpKey(int flags, const UString& pattern) : flagsValue(flags) - , pattern(pattern.rep()) + , pattern(pattern.impl()) { } - RegExpKey(int flags, const PassRefPtr<UString::Rep> pattern) + RegExpKey(int flags, const PassRefPtr<StringImpl> pattern) + : flagsValue(flags) + , pattern(pattern) + { + } + + RegExpKey(int flags, const RefPtr<StringImpl>& pattern) : flagsValue(flags) , pattern(pattern) { } RegExpKey(const UString& flags, const UString& pattern) - : pattern(pattern.rep()) + : pattern(pattern.impl()) { flagsValue = getFlagsValue(flags); } @@ -67,11 +74,11 @@ struct RegExpKey { int getFlagsValue(const UString flags) { flagsValue = 0; - if (flags.find('g') != UString::NotFound) + if (flags.find('g') != notFound) flagsValue += 4; - if (flags.find('i') != UString::NotFound) + if (flags.find('i') != notFound) flagsValue += 2; - if (flags.find('m') != UString::NotFound) + if (flags.find('m') != notFound) flagsValue += 1; return flagsValue; } diff --git a/JavaScriptCore/runtime/RegExpObject.cpp b/JavaScriptCore/runtime/RegExpObject.cpp index 0f2c1e1..4462879 100644 --- a/JavaScriptCore/runtime/RegExpObject.cpp +++ b/JavaScriptCore/runtime/RegExpObject.cpp @@ -29,6 +29,7 @@ #include "Lookup.h" #include "RegExpConstructor.h" #include "RegExpPrototype.h" +#include "StringConcatenate.h" #include <wtf/PassOwnPtr.h> namespace JSC { @@ -156,7 +157,7 @@ bool RegExpObject::match(ExecState* exec) return position >= 0; } - if (d->lastIndex < 0 || d->lastIndex > input.size()) { + if (d->lastIndex < 0 || d->lastIndex > input.length()) { d->lastIndex = 0; return false; } diff --git a/JavaScriptCore/runtime/RegExpPrototype.cpp b/JavaScriptCore/runtime/RegExpPrototype.cpp index ac215ec..d66f5d7 100644 --- a/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -120,7 +120,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec) postfix[index] = 'm'; UString source = asRegExpObject(thisValue)->get(exec, exec->propertyNames().source).toString(exec); // If source is empty, use "/(?:)/" to avoid colliding with comment syntax - return JSValue::encode(jsMakeNontrivialString(exec, "/", source.size() ? source : UString("(?:)"), postfix)); + return JSValue::encode(jsMakeNontrivialString(exec, "/", source.length() ? source : UString("(?:)"), postfix)); } } // namespace JSC diff --git a/JavaScriptCore/runtime/RopeImpl.cpp b/JavaScriptCore/runtime/RopeImpl.cpp index 25b9848..09c24a9 100644 --- a/JavaScriptCore/runtime/RopeImpl.cpp +++ b/JavaScriptCore/runtime/RopeImpl.cpp @@ -40,7 +40,7 @@ void RopeImpl::derefFibersNonRecursive(Vector<RopeImpl*, 32>& workQueue) else nextRope->deref(); } else - static_cast<UStringImpl*>(fiber)->deref(); + static_cast<StringImpl*>(fiber)->deref(); } } diff --git a/JavaScriptCore/runtime/RopeImpl.h b/JavaScriptCore/runtime/RopeImpl.h index ac2b502..dfacbf5 100644 --- a/JavaScriptCore/runtime/RopeImpl.h +++ b/JavaScriptCore/runtime/RopeImpl.h @@ -26,14 +26,14 @@ #ifndef RopeImpl_h #define RopeImpl_h -#include "UStringImpl.h" +#include <wtf/text/StringImpl.h> namespace JSC { class RopeImpl : public StringImplBase { public: // A RopeImpl is composed from a set of smaller strings called Fibers. - // Each Fiber in a rope is either UStringImpl or another RopeImpl. + // Each Fiber in a rope is either StringImpl or another RopeImpl. typedef StringImplBase* Fiber; // Creates a RopeImpl comprising of 'fiberCount' Fibers. @@ -56,7 +56,7 @@ public: if (isRope(fiber)) static_cast<RopeImpl*>(fiber)->deref(); else - static_cast<UStringImpl*>(fiber)->deref(); + static_cast<StringImpl*>(fiber)->deref(); } void initializeFiber(unsigned &index, Fiber fiber) diff --git a/JavaScriptCore/runtime/ScopeChain.cpp b/JavaScriptCore/runtime/ScopeChain.cpp index 981794b..54c5082 100644 --- a/JavaScriptCore/runtime/ScopeChain.cpp +++ b/JavaScriptCore/runtime/ScopeChain.cpp @@ -43,7 +43,7 @@ void ScopeChainNode::print() const fprintf(stderr, "----- [scope %p] -----\n", o); for (PropertyNameArray::const_iterator propIter = propertyNames.begin(); propIter != propEnd; propIter++) { Identifier name = *propIter; - fprintf(stderr, "%s, ", name.ascii()); + fprintf(stderr, "%s, ", name.ustring().utf8().data()); } fprintf(stderr, "\n"); } diff --git a/JavaScriptCore/runtime/SmallStrings.cpp b/JavaScriptCore/runtime/SmallStrings.cpp index 822303c..f358727 100644 --- a/JavaScriptCore/runtime/SmallStrings.cpp +++ b/JavaScriptCore/runtime/SmallStrings.cpp @@ -44,19 +44,19 @@ class SmallStringsStorage : public Noncopyable { public: SmallStringsStorage(); - UString::Rep* rep(unsigned char character) { return m_reps[character].get(); } + StringImpl* rep(unsigned char character) { return m_reps[character].get(); } private: - RefPtr<UString::Rep> m_reps[numCharactersToStore]; + RefPtr<StringImpl> m_reps[numCharactersToStore]; }; SmallStringsStorage::SmallStringsStorage() { UChar* characterBuffer = 0; - RefPtr<UStringImpl> baseString = UStringImpl::createUninitialized(numCharactersToStore, characterBuffer); + RefPtr<StringImpl> baseString = StringImpl::createUninitialized(numCharactersToStore, characterBuffer); for (unsigned i = 0; i < numCharactersToStore; ++i) { characterBuffer[i] = i; - m_reps[i] = UStringImpl::create(baseString, i, 1); + m_reps[i] = StringImpl::create(baseString, i, 1); } } @@ -129,10 +129,10 @@ void SmallStrings::createSingleCharacterString(JSGlobalData* globalData, unsigne if (!m_storage) m_storage = adoptPtr(new SmallStringsStorage); ASSERT(!m_singleCharacterStrings[character]); - m_singleCharacterStrings[character] = new (globalData) JSString(globalData, m_storage->rep(character), JSString::HasOtherOwner); + m_singleCharacterStrings[character] = new (globalData) JSString(globalData, PassRefPtr<StringImpl>(m_storage->rep(character)), JSString::HasOtherOwner); } -UString::Rep* SmallStrings::singleCharacterStringRep(unsigned char character) +StringImpl* SmallStrings::singleCharacterStringRep(unsigned char character) { if (!m_storage) m_storage = adoptPtr(new SmallStringsStorage); diff --git a/JavaScriptCore/runtime/SmallStrings.h b/JavaScriptCore/runtime/SmallStrings.h index b550a04..d1ebfb1 100644 --- a/JavaScriptCore/runtime/SmallStrings.h +++ b/JavaScriptCore/runtime/SmallStrings.h @@ -55,7 +55,7 @@ namespace JSC { return m_singleCharacterStrings[character]; } - UString::Rep* singleCharacterStringRep(unsigned char character); + StringImpl* singleCharacterStringRep(unsigned char character); void markChildren(MarkStack&); void clear(); diff --git a/JavaScriptCore/runtime/StringBuilder.h b/JavaScriptCore/runtime/StringBuilder.h index 59b01e0..a26b94c 100644 --- a/JavaScriptCore/runtime/StringBuilder.h +++ b/JavaScriptCore/runtime/StringBuilder.h @@ -56,7 +56,7 @@ public: void append(const UString& str) { - buffer.append(str.data(), str.size()); + buffer.append(str.characters(), str.length()); } bool isEmpty() { return buffer.isEmpty(); } diff --git a/JavaScriptCore/runtime/StringConcatenate.h b/JavaScriptCore/runtime/StringConcatenate.h new file mode 100644 index 0000000..18a52ef --- /dev/null +++ b/JavaScriptCore/runtime/StringConcatenate.h @@ -0,0 +1,428 @@ +/* + * Copyright (C) 2010 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 StringConcatenate_h +#define StringConcatenate_h + +#include "UString.h" + +namespace JSC { + +template<typename StringType> +class StringTypeAdapter { +}; + +template<> +class StringTypeAdapter<char*> { +public: + StringTypeAdapter<char*>(char* buffer) + : m_buffer((unsigned char*)buffer) + , m_length(strlen(buffer)) + { + } + + unsigned length() { return m_length; } + + void writeTo(UChar* destination) + { + for (unsigned i = 0; i < m_length; ++i) + destination[i] = m_buffer[i]; + } + +private: + const unsigned char* m_buffer; + unsigned m_length; +}; + +template<> +class StringTypeAdapter<const char*> { +public: + StringTypeAdapter<const char*>(const char* buffer) + : m_buffer((unsigned char*)buffer) + , m_length(strlen(buffer)) + { + } + + unsigned length() { return m_length; } + + void writeTo(UChar* destination) + { + for (unsigned i = 0; i < m_length; ++i) + destination[i] = m_buffer[i]; + } + +private: + const unsigned char* m_buffer; + unsigned m_length; +}; + +template<> +class StringTypeAdapter<UString> { +public: + StringTypeAdapter<UString>(UString& string) + : m_data(string.characters()) + , m_length(string.length()) + { + } + + unsigned length() { return m_length; } + + void writeTo(UChar* destination) + { + for (unsigned i = 0; i < m_length; ++i) + destination[i] = m_data[i]; + } + +private: + const UChar* m_data; + unsigned m_length; +}; + +inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow) +{ + unsigned oldTotal = total; + total = oldTotal + addend; + if (total < oldTotal) + overflow = true; +} + +template<typename StringType1, typename StringType2> +PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2) +{ + StringTypeAdapter<StringType1> adapter1(string1); + StringTypeAdapter<StringType2> adapter2(string2); + + UChar* buffer; + bool overflow = false; + unsigned length = adapter1.length(); + sumWithOverflow(length, adapter2.length(), overflow); + if (overflow) + return 0; + PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3> +PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3) +{ + StringTypeAdapter<StringType1> adapter1(string1); + StringTypeAdapter<StringType2> adapter2(string2); + StringTypeAdapter<StringType3> adapter3(string3); + + UChar* buffer = 0; + bool overflow = false; + unsigned length = adapter1.length(); + sumWithOverflow(length, adapter2.length(), overflow); + sumWithOverflow(length, adapter3.length(), overflow); + if (overflow) + return 0; + PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> +PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) +{ + StringTypeAdapter<StringType1> adapter1(string1); + StringTypeAdapter<StringType2> adapter2(string2); + StringTypeAdapter<StringType3> adapter3(string3); + StringTypeAdapter<StringType4> adapter4(string4); + + UChar* buffer; + bool overflow = false; + unsigned length = adapter1.length(); + sumWithOverflow(length, adapter2.length(), overflow); + sumWithOverflow(length, adapter3.length(), overflow); + sumWithOverflow(length, adapter4.length(), overflow); + if (overflow) + return 0; + PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> +PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) +{ + StringTypeAdapter<StringType1> adapter1(string1); + StringTypeAdapter<StringType2> adapter2(string2); + StringTypeAdapter<StringType3> adapter3(string3); + StringTypeAdapter<StringType4> adapter4(string4); + StringTypeAdapter<StringType5> adapter5(string5); + + UChar* buffer; + bool overflow = false; + unsigned length = adapter1.length(); + sumWithOverflow(length, adapter2.length(), overflow); + sumWithOverflow(length, adapter3.length(), overflow); + sumWithOverflow(length, adapter4.length(), overflow); + sumWithOverflow(length, adapter5.length(), overflow); + if (overflow) + return 0; + PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> +PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) +{ + StringTypeAdapter<StringType1> adapter1(string1); + StringTypeAdapter<StringType2> adapter2(string2); + StringTypeAdapter<StringType3> adapter3(string3); + StringTypeAdapter<StringType4> adapter4(string4); + StringTypeAdapter<StringType5> adapter5(string5); + StringTypeAdapter<StringType6> adapter6(string6); + + UChar* buffer; + bool overflow = false; + unsigned length = adapter1.length(); + sumWithOverflow(length, adapter2.length(), overflow); + sumWithOverflow(length, adapter3.length(), overflow); + sumWithOverflow(length, adapter4.length(), overflow); + sumWithOverflow(length, adapter5.length(), overflow); + sumWithOverflow(length, adapter6.length(), overflow); + if (overflow) + return 0; + PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + result += adapter5.length(); + adapter6.writeTo(result); + + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> +PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) +{ + StringTypeAdapter<StringType1> adapter1(string1); + StringTypeAdapter<StringType2> adapter2(string2); + StringTypeAdapter<StringType3> adapter3(string3); + StringTypeAdapter<StringType4> adapter4(string4); + StringTypeAdapter<StringType5> adapter5(string5); + StringTypeAdapter<StringType6> adapter6(string6); + StringTypeAdapter<StringType7> adapter7(string7); + + UChar* buffer; + bool overflow = false; + unsigned length = adapter1.length(); + sumWithOverflow(length, adapter2.length(), overflow); + sumWithOverflow(length, adapter3.length(), overflow); + sumWithOverflow(length, adapter4.length(), overflow); + sumWithOverflow(length, adapter5.length(), overflow); + sumWithOverflow(length, adapter6.length(), overflow); + sumWithOverflow(length, adapter7.length(), overflow); + if (overflow) + return 0; + PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + result += adapter5.length(); + adapter6.writeTo(result); + result += adapter6.length(); + adapter7.writeTo(result); + + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> +PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) +{ + StringTypeAdapter<StringType1> adapter1(string1); + StringTypeAdapter<StringType2> adapter2(string2); + StringTypeAdapter<StringType3> adapter3(string3); + StringTypeAdapter<StringType4> adapter4(string4); + StringTypeAdapter<StringType5> adapter5(string5); + StringTypeAdapter<StringType6> adapter6(string6); + StringTypeAdapter<StringType7> adapter7(string7); + StringTypeAdapter<StringType8> adapter8(string8); + + UChar* buffer; + bool overflow = false; + unsigned length = adapter1.length(); + sumWithOverflow(length, adapter2.length(), overflow); + sumWithOverflow(length, adapter3.length(), overflow); + sumWithOverflow(length, adapter4.length(), overflow); + sumWithOverflow(length, adapter5.length(), overflow); + sumWithOverflow(length, adapter6.length(), overflow); + sumWithOverflow(length, adapter7.length(), overflow); + sumWithOverflow(length, adapter8.length(), overflow); + if (overflow) + return 0; + PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + result += adapter5.length(); + adapter6.writeTo(result); + result += adapter6.length(); + adapter7.writeTo(result); + result += adapter7.length(); + adapter8.writeTo(result); + + return resultImpl; +} + +template<typename StringType1, typename StringType2> +UString makeString(StringType1 string1, StringType2 string2) +{ + PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3> +UString makeString(StringType1 string1, StringType2 string2, StringType3 string3) +{ + PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> +UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) +{ + PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> +UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) +{ + PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> +UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) +{ + PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> +UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) +{ + PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> +UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) +{ + PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +} // namespace JSC + +#endif diff --git a/JavaScriptCore/runtime/StringConstructor.cpp b/JavaScriptCore/runtime/StringConstructor.cpp index f02ab09..159386d 100644 --- a/JavaScriptCore/runtime/StringConstructor.cpp +++ b/JavaScriptCore/runtime/StringConstructor.cpp @@ -34,7 +34,7 @@ static NEVER_INLINE JSValue stringFromCharCodeSlowCase(ExecState* exec) { unsigned length = exec->argumentCount(); UChar* buf; - PassRefPtr<UStringImpl> impl = UStringImpl::createUninitialized(length, buf); + PassRefPtr<StringImpl> impl = StringImpl::createUninitialized(length, buf); for (unsigned i = 0; i < length; ++i) buf[i] = static_cast<UChar>(exec->argument(i).toUInt32(exec)); return jsString(exec, impl); diff --git a/JavaScriptCore/runtime/StringObject.cpp b/JavaScriptCore/runtime/StringObject.cpp index f8e0e87..dc27618 100644 --- a/JavaScriptCore/runtime/StringObject.cpp +++ b/JavaScriptCore/runtime/StringObject.cpp @@ -80,7 +80,7 @@ bool StringObject::deleteProperty(ExecState* exec, const Identifier& propertyNam if (propertyName == exec->propertyNames().length) return false; bool isStrictUInt32; - unsigned i = propertyName.toStrictUInt32(&isStrictUInt32); + unsigned i = propertyName.toUInt32(isStrictUInt32); if (isStrictUInt32 && internalValue()->canGetIndex(i)) return false; return JSObject::deleteProperty(exec, propertyName); @@ -90,7 +90,7 @@ void StringObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& prope { int size = internalValue()->length(); for (int i = 0; i < size; ++i) - propertyNames.add(Identifier(exec, UString::from(i))); + propertyNames.add(Identifier(exec, UString::number(i))); if (mode == IncludeDontEnumProperties) propertyNames.add(exec->propertyNames().length); return JSObject::getOwnPropertyNames(exec, propertyNames, mode); diff --git a/JavaScriptCore/runtime/StringPrototype.cpp b/JavaScriptCore/runtime/StringPrototype.cpp index fb6e0f3..cfbb3be 100644 --- a/JavaScriptCore/runtime/StringPrototype.cpp +++ b/JavaScriptCore/runtime/StringPrototype.cpp @@ -151,19 +151,19 @@ bool StringPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier // ------------------------------ Functions -------------------------- -static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacement, const UString& source, const int* ovector, RegExp* reg, unsigned i) +static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacement, const UString& source, const int* ovector, RegExp* reg, size_t i) { Vector<UChar> substitutedReplacement; int offset = 0; do { - if (i + 1 == replacement.size()) + if (i + 1 == replacement.length()) break; UChar ref = replacement[i + 1]; if (ref == '$') { // "$$" -> "$" ++i; - substitutedReplacement.append(replacement.data() + offset, i - offset); + substitutedReplacement.append(replacement.characters() + offset, i - offset); offset = i + 1; continue; } @@ -179,13 +179,13 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem backrefLength = ovector[0]; } else if (ref == '\'') { backrefStart = ovector[1]; - backrefLength = source.size() - backrefStart; + backrefLength = source.length() - backrefStart; } else if (reg && ref >= '0' && ref <= '9') { // 1- and 2-digit back references are allowed unsigned backrefIndex = ref - '0'; if (backrefIndex > reg->numSubpatterns()) continue; - if (replacement.size() > i + 2) { + if (replacement.length() > i + 2) { ref = replacement[i + 2]; if (ref >= '0' && ref <= '9') { backrefIndex = 10 * backrefIndex + ref - '0'; @@ -203,14 +203,14 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem continue; if (i - offset) - substitutedReplacement.append(replacement.data() + offset, i - offset); + substitutedReplacement.append(replacement.characters() + offset, i - offset); i += 1 + advance; offset = i + 1; - substitutedReplacement.append(source.data() + backrefStart, backrefLength); - } while ((i = replacement.find('$', i + 1)) != UString::NotFound); + substitutedReplacement.append(source.characters() + backrefStart, backrefLength); + } while ((i = replacement.find('$', i + 1)) != notFound); - if (replacement.size() - offset) - substitutedReplacement.append(replacement.data() + offset, replacement.size() - offset); + if (replacement.length() - offset) + substitutedReplacement.append(replacement.characters() + offset, replacement.length() - offset); substitutedReplacement.shrinkToFit(); return UString::adopt(substitutedReplacement); @@ -218,15 +218,15 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem static inline UString substituteBackreferences(const UString& replacement, const UString& source, const int* ovector, RegExp* reg) { - unsigned i = replacement.find('$', 0); - if (UNLIKELY(i != UString::NotFound)) + size_t i = replacement.find('$', 0); + if (UNLIKELY(i != notFound)) return substituteBackreferencesSlow(replacement, source, ovector, reg, i); return replacement; } static inline int localeCompare(const UString& a, const UString& b) { - return Collator::userDefault()->collate(reinterpret_cast<const ::UChar*>(a.data()), a.size(), reinterpret_cast<const ::UChar*>(b.data()), b.size()); + return Collator::userDefault()->collate(reinterpret_cast<const ::UChar*>(a.characters()), a.length(), reinterpret_cast<const ::UChar*>(b.characters()), b.length()); } struct StringRange { @@ -248,26 +248,26 @@ public: static ALWAYS_INLINE JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, JSString* sourceVal, const UString& source, const StringRange* substringRanges, int rangeCount, const UString* separators, int separatorCount) { if (rangeCount == 1 && separatorCount == 0) { - int sourceSize = source.size(); + int sourceSize = source.length(); int position = substringRanges[0].position; int length = substringRanges[0].length; if (position <= 0 && length >= sourceSize) return sourceVal; // We could call UString::substr, but this would result in redundant checks - return jsString(exec, UStringImpl::create(source.rep(), max(0, position), min(sourceSize, length))); + return jsString(exec, StringImpl::create(source.impl(), max(0, position), min(sourceSize, length))); } int totalLength = 0; for (int i = 0; i < rangeCount; i++) totalLength += substringRanges[i].length; for (int i = 0; i < separatorCount; i++) - totalLength += separators[i].size(); + totalLength += separators[i].length(); if (totalLength == 0) return jsString(exec, ""); UChar* buffer; - PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(totalLength, buffer); + PassRefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(totalLength, buffer); if (!impl) return throwOutOfMemoryError(exec); @@ -275,12 +275,12 @@ static ALWAYS_INLINE JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, J int bufferPos = 0; for (int i = 0; i < maxCount; i++) { if (i < rangeCount) { - UStringImpl::copyChars(buffer + bufferPos, source.data() + substringRanges[i].position, substringRanges[i].length); + StringImpl::copyChars(buffer + bufferPos, source.characters() + substringRanges[i].position, substringRanges[i].length); bufferPos += substringRanges[i].length; } if (i < separatorCount) { - UStringImpl::copyChars(buffer + bufferPos, separators[i].data(), separators[i].size()); - bufferPos += separators[i].size(); + StringImpl::copyChars(buffer + bufferPos, separators[i].characters(), separators[i].length()); + bufferPos += separators[i].length(); } } @@ -363,7 +363,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) // special case of empty match if (matchLen == 0) { startPosition++; - if (startPosition > source.size()) + if (startPosition > source.length()) break; } } @@ -407,7 +407,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) // special case of empty match if (matchLen == 0) { startPosition++; - if (startPosition > source.size()) + if (startPosition > source.length()) break; } } while (global); @@ -416,8 +416,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) if (!lastIndex && replacements.isEmpty()) return JSValue::encode(sourceVal); - if (static_cast<unsigned>(lastIndex) < source.size()) - sourceRanges.append(StringRange(lastIndex, source.size() - lastIndex)); + if (static_cast<unsigned>(lastIndex) < source.length()) + sourceRanges.append(StringRange(lastIndex, source.length() - lastIndex)); return JSValue::encode(jsSpliceSubstringsWithSeparators(exec, sourceVal, source, sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size())); } @@ -425,16 +425,16 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) // Not a regular expression, so treat the pattern as a string. UString patternString = pattern.toString(exec); - if (patternString.size() == 1 && callType == CallTypeNone) + if (patternString.length() == 1 && callType == CallTypeNone) return JSValue::encode(sourceVal->replaceCharacter(exec, patternString[0], replacementString)); const UString& source = sourceVal->value(exec); - unsigned matchPos = source.find(patternString); + size_t matchPos = source.find(patternString); - if (matchPos == UString::NotFound) + if (matchPos == notFound) return JSValue::encode(sourceVal); - int matchLen = patternString.size(); + int matchLen = patternString.length(); if (callType != CallTypeNone) { MarkedArgumentBuffer args; args.append(jsSubstring(exec, source, matchPos, matchLen)); @@ -446,7 +446,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) size_t matchEnd = matchPos + matchLen; int ovector[2] = { matchPos, matchEnd }; - return JSValue::encode(jsString(exec, source.substr(0, matchPos), substituteBackreferences(replacementString, source, ovector, 0), source.substr(matchEnd))); + return JSValue::encode(jsString(exec, source.substringSharingImpl(0, matchPos), substituteBackreferences(replacementString, source, ovector, 0), source.substringSharingImpl(matchEnd))); } EncodedJSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec) @@ -469,7 +469,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState* exec) if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); UString s = thisValue.toThisString(exec); - unsigned len = s.size(); + unsigned len = s.length(); JSValue a0 = exec->argument(0); if (a0.isUInt32()) { uint32_t i = a0.asUInt32(); @@ -489,12 +489,12 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState* exec) if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); UString s = thisValue.toThisString(exec); - unsigned len = s.size(); + unsigned len = s.length(); JSValue a0 = exec->argument(0); if (a0.isUInt32()) { uint32_t i = a0.asUInt32(); if (i < len) - return JSValue::encode(jsNumber(exec, s.data()[i])); + return JSValue::encode(jsNumber(exec, s.characters()[i])); return JSValue::encode(jsNaN(exec)); } double dpos = a0.toInteger(exec); @@ -523,7 +523,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec) if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); UString s = thisValue.toThisString(exec); - int len = s.size(); + int len = s.length(); JSValue a0 = exec->argument(0); JSValue a1 = exec->argument(1); @@ -542,8 +542,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec) pos = static_cast<int>(dpos); } - unsigned result = s.find(u2, pos); - if (result == UString::NotFound) + size_t result = s.find(u2, pos); + if (result == notFound) return JSValue::encode(jsNumber(exec, -1)); return JSValue::encode(jsNumber(exec, result)); } @@ -554,7 +554,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState* exec) if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); UString s = thisValue.toThisString(exec); - int len = s.size(); + int len = s.length(); JSValue a0 = exec->argument(0); JSValue a1 = exec->argument(1); @@ -571,8 +571,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState* exec) dpos = len; #endif - unsigned result = s.rfind(u2, static_cast<unsigned>(dpos)); - if (result == UString::NotFound) + size_t result = s.reverseFind(u2, static_cast<unsigned>(dpos)); + if (result == notFound) return JSValue::encode(jsNumber(exec, -1)); return JSValue::encode(jsNumber(exec, result)); } @@ -597,7 +597,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec) * If regexp is not an object whose [[Class]] property is "RegExp", it is * replaced with the result of the expression new RegExp(regexp). */ - reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), UString::null()); + reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), UString()); } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; @@ -650,7 +650,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec) * If regexp is not an object whose [[Class]] property is "RegExp", it is * replaced with the result of the expression new RegExp(regexp). */ - reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), UString::null()); + reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), UString()); } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; @@ -665,7 +665,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec) if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); UString s = thisValue.toThisString(exec); - int len = s.size(); + int len = s.length(); JSValue a0 = exec->argument(0); JSValue a1 = exec->argument(1); @@ -707,7 +707,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) return JSValue::encode(result); } unsigned pos = 0; - while (i != limit && pos < s.size()) { + while (i != limit && pos < s.length()) { Vector<int, 32> ovector; int mpos = reg->match(s, pos, &ovector); if (mpos < 0) @@ -733,21 +733,20 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) // empty separator matches empty string -> empty array return JSValue::encode(result); } - while (i != limit && p0 < s.size() - 1) + while (i != limit && p0 < s.length() - 1) result->put(exec, i++, jsSingleCharacterSubstring(exec, s, p0++)); } else { - unsigned pos; - - while (i != limit && (pos = s.find(u2, p0)) != UString::NotFound) { + size_t pos; + while (i != limit && (pos = s.find(u2, p0)) != notFound) { result->put(exec, i++, jsSubstring(exec, s, p0, pos - p0)); - p0 = pos + u2.size(); + p0 = pos + u2.length(); } } } // add remaining string if (i != limit) - result->put(exec, i++, jsSubstring(exec, s, p0, s.size() - p0)); + result->put(exec, i++, jsSubstring(exec, s, p0, s.length() - p0)); return JSValue::encode(result); } @@ -758,7 +757,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState* exec) if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); UString s = thisValue.toThisString(exec); - int len = s.size(); + int len = s.length(); JSValue a0 = exec->argument(0); JSValue a1 = exec->argument(1); @@ -783,7 +782,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec) if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); UString s = thisValue.toThisString(exec); - int len = s.size(); + int len = s.length(); JSValue a0 = exec->argument(0); JSValue a1 = exec->argument(1); @@ -819,11 +818,11 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec) JSString* sVal = thisValue.toThisJSString(exec); const UString& s = sVal->value(exec); - int sSize = s.size(); + int sSize = s.length(); if (!sSize) return JSValue::encode(sVal); - const UChar* sData = s.data(); + const UChar* sData = s.characters(); Vector<UChar> buffer(sSize); UChar ored = 0; @@ -859,11 +858,11 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec) JSString* sVal = thisValue.toThisJSString(exec); const UString& s = sVal->value(exec); - int sSize = s.size(); + int sSize = s.length(); if (!sSize) return JSValue::encode(sVal); - const UChar* sData = s.data(); + const UChar* sData = s.characters(); Vector<UChar> buffer(sSize); UChar ored = 0; @@ -984,10 +983,10 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec) uint32_t smallInteger; if (a0.getUInt32(smallInteger) && smallInteger <= 9) { - unsigned stringSize = s.size(); + unsigned stringSize = s.length(); unsigned bufferSize = 22 + stringSize; UChar* buffer; - PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(bufferSize, buffer); + PassRefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(bufferSize, buffer); if (!impl) return JSValue::encode(jsUndefined()); buffer[0] = '<'; @@ -1005,7 +1004,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec) buffer[12] = '0' + smallInteger; buffer[13] = '"'; buffer[14] = '>'; - memcpy(&buffer[15], s.data(), stringSize * sizeof(UChar)); + memcpy(&buffer[15], s.characters(), stringSize * sizeof(UChar)); buffer[15 + stringSize] = '<'; buffer[16 + stringSize] = '/'; buffer[17 + stringSize] = 'f'; @@ -1034,11 +1033,11 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec) JSValue a0 = exec->argument(0); UString linkText = a0.toString(exec); - unsigned linkTextSize = linkText.size(); - unsigned stringSize = s.size(); + unsigned linkTextSize = linkText.length(); + unsigned stringSize = s.length(); unsigned bufferSize = 15 + linkTextSize + stringSize; UChar* buffer; - PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(bufferSize, buffer); + PassRefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(bufferSize, buffer); if (!impl) return JSValue::encode(jsUndefined()); buffer[0] = '<'; @@ -1050,10 +1049,10 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec) buffer[6] = 'f'; buffer[7] = '='; buffer[8] = '"'; - memcpy(&buffer[9], linkText.data(), linkTextSize * sizeof(UChar)); + memcpy(&buffer[9], linkText.characters(), linkTextSize * sizeof(UChar)); buffer[9 + linkTextSize] = '"'; buffer[10 + linkTextSize] = '>'; - memcpy(&buffer[11 + linkTextSize], s.data(), stringSize * sizeof(UChar)); + memcpy(&buffer[11 + linkTextSize], s.characters(), stringSize * sizeof(UChar)); buffer[11 + linkTextSize + stringSize] = '<'; buffer[12 + linkTextSize + stringSize] = '/'; buffer[13 + linkTextSize + stringSize] = 'a'; @@ -1078,20 +1077,20 @@ static inline JSValue trimString(ExecState* exec, JSValue thisValue, int trimKin UString str = thisValue.toThisString(exec); unsigned left = 0; if (trimKind & TrimLeft) { - while (left < str.size() && isTrimWhitespace(str[left])) + while (left < str.length() && isTrimWhitespace(str[left])) left++; } - unsigned right = str.size(); + unsigned right = str.length(); if (trimKind & TrimRight) { while (right > left && isTrimWhitespace(str[right - 1])) right--; } // Don't gc allocate a new string if we don't have to. - if (left == 0 && right == str.size() && thisValue.isString()) + if (left == 0 && right == str.length() && thisValue.isString()) return thisValue; - return jsString(exec, str.substr(left, right - left)); + return jsString(exec, str.substringSharingImpl(left, right - left)); } EncodedJSValue JSC_HOST_CALL stringProtoFuncTrim(ExecState* exec) diff --git a/JavaScriptCore/runtime/Structure.cpp b/JavaScriptCore/runtime/Structure.cpp index 6d13f4b..d06a239 100644 --- a/JavaScriptCore/runtime/Structure.cpp +++ b/JavaScriptCore/runtime/Structure.cpp @@ -270,7 +270,7 @@ Structure::~Structure() if (m_propertyTable) { unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; for (unsigned i = 1; i <= entryCount; i++) { - if (UString::Rep* key = m_propertyTable->entries()[i].key) + if (StringImpl* key = m_propertyTable->entries()[i].key) key->deref(); } @@ -395,7 +395,7 @@ void Structure::growPropertyStorageCapacity() void Structure::despecifyDictionaryFunction(const Identifier& propertyName) { - const UString::Rep* rep = propertyName._ustring.rep(); + const StringImpl* rep = propertyName.impl(); materializePropertyMapIfNecessary(); @@ -444,7 +444,7 @@ PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Struct ASSERT(!structure->isDictionary()); ASSERT(structure->typeInfo().type() == ObjectType); - if (Structure* existingTransition = structure->transitionTableGet(make_pair(propertyName.ustring().rep(), attributes), specificValue)) { + if (Structure* existingTransition = structure->transitionTableGet(make_pair(propertyName.impl(), attributes), specificValue)) { ASSERT(existingTransition->m_offset != noOffset); offset = existingTransition->m_offset + existingTransition->m_anonymousSlotCount; ASSERT(offset >= structure->m_anonymousSlotCount); @@ -479,7 +479,7 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain; transition->m_previous = structure; - transition->m_nameInPrevious = propertyName.ustring().rep(); + transition->m_nameInPrevious = propertyName.impl(); transition->m_attributesInPrevious = attributes; transition->m_specificValueInPrevious = specificValue; transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; @@ -509,7 +509,7 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con transition->m_offset = offset - structure->m_anonymousSlotCount; ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount()); - structure->transitionTableAdd(make_pair(propertyName.ustring().rep(), attributes), transition.get(), specificValue); + structure->transitionTableAdd(make_pair(propertyName.impl(), attributes), transition.get(), specificValue); return transition.release(); } @@ -738,7 +738,7 @@ PropertyMapHashTable* Structure::copyPropertyTable() unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; for (unsigned i = 1; i <= entryCount; ++i) { - if (UString::Rep* key = newTable->entries()[i].key) + if (StringImpl* key = newTable->entries()[i].key) key->ref(); } @@ -749,7 +749,7 @@ PropertyMapHashTable* Structure::copyPropertyTable() return newTable; } -size_t Structure::get(const UString::Rep* rep, unsigned& attributes, JSCell*& specificValue) +size_t Structure::get(const StringImpl* rep, unsigned& attributes, JSCell*& specificValue) { materializePropertyMapIfNecessary(); if (!m_propertyTable) @@ -806,7 +806,7 @@ bool Structure::despecifyFunction(const Identifier& propertyName) if (!m_propertyTable) return false; - UString::Rep* rep = propertyName._ustring.rep(); + StringImpl* rep = propertyName.impl(); unsigned i = rep->existingHash(); @@ -870,7 +870,7 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel if (attributes & DontEnum) m_hasNonEnumerableProperties = true; - UString::Rep* rep = propertyName._ustring.rep(); + StringImpl* rep = propertyName.impl(); if (!m_propertyTable) createPropertyMapHashTable(); @@ -954,7 +954,7 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel return newOffset; } -bool Structure::hasTransition(UString::Rep* rep, unsigned attributes) +bool Structure::hasTransition(StringImpl* rep, unsigned attributes) { return transitionTableHasTransition(make_pair(rep, attributes)); } @@ -965,7 +965,7 @@ size_t Structure::remove(const Identifier& propertyName) checkConsistency(); - UString::Rep* rep = propertyName._ustring.rep(); + StringImpl* rep = propertyName.impl(); if (!m_propertyTable) return notFound; @@ -979,7 +979,7 @@ size_t Structure::remove(const Identifier& propertyName) unsigned i = rep->existingHash(); unsigned k = 0; unsigned entryIndex; - UString::Rep* key = 0; + StringImpl* key = 0; while (1) { entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask]; if (entryIndex == emptyEntryIndex) @@ -1241,7 +1241,7 @@ void Structure::checkConsistency() unsigned nonEmptyEntryCount = 0; for (unsigned c = 1; c <= m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; ++c) { ASSERT(m_hasNonEnumerableProperties || !(m_propertyTable->entries()[c].attributes & DontEnum)); - UString::Rep* rep = m_propertyTable->entries()[c].key; + StringImpl* rep = m_propertyTable->entries()[c].key; ASSERT(m_propertyTable->entries()[c].offset >= m_anonymousSlotCount); if (!rep) continue; diff --git a/JavaScriptCore/runtime/Structure.h b/JavaScriptCore/runtime/Structure.h index 968443a..f480051 100644 --- a/JavaScriptCore/runtime/Structure.h +++ b/JavaScriptCore/runtime/Structure.h @@ -106,20 +106,20 @@ namespace JSC { bool isUsingInlineStorage() const; size_t get(const Identifier& propertyName); - size_t get(const UString::Rep* rep, unsigned& attributes, JSCell*& specificValue); + size_t get(const StringImpl* rep, unsigned& attributes, JSCell*& specificValue); size_t get(const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue) { ASSERT(!propertyName.isNull()); - return get(propertyName.ustring().rep(), attributes, specificValue); + return get(propertyName.impl(), attributes, specificValue); } bool transitionedFor(const JSCell* specificValue) { return m_specificValueInPrevious == specificValue; } - bool hasTransition(UString::Rep*, unsigned attributes); + bool hasTransition(StringImpl*, unsigned attributes); bool hasTransition(const Identifier& propertyName, unsigned attributes) { - return hasTransition(propertyName._ustring.rep(), attributes); + return hasTransition(propertyName.impl(), attributes); } bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; } @@ -210,7 +210,7 @@ namespace JSC { mutable RefPtr<StructureChain> m_cachedPrototypeChain; RefPtr<Structure> m_previous; - RefPtr<UString::Rep> m_nameInPrevious; + RefPtr<StringImpl> m_nameInPrevious; JSCell* m_specificValueInPrevious; // 'm_isUsingSingleSlot' indicates whether we are using the single transition optimisation. @@ -254,7 +254,7 @@ namespace JSC { if (!m_propertyTable) return WTF::notFound; - UString::Rep* rep = propertyName._ustring.rep(); + StringImpl* rep = propertyName.impl(); unsigned i = rep->existingHash(); diff --git a/JavaScriptCore/runtime/StructureTransitionTable.h b/JavaScriptCore/runtime/StructureTransitionTable.h index d1dc2d9..7e9d7ff 100644 --- a/JavaScriptCore/runtime/StructureTransitionTable.h +++ b/JavaScriptCore/runtime/StructureTransitionTable.h @@ -38,7 +38,7 @@ namespace JSC { class Structure; struct StructureTransitionTableHash { - typedef std::pair<RefPtr<UString::Rep>, unsigned> Key; + typedef std::pair<RefPtr<StringImpl>, unsigned> Key; static unsigned hash(const Key& p) { return p.first->existingHash(); @@ -53,7 +53,7 @@ namespace JSC { }; struct StructureTransitionTableHashTraits { - typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits; + typedef WTF::HashTraits<RefPtr<StringImpl> > FirstTraits; typedef WTF::GenericHashTraits<unsigned> SecondTraits; typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType > TraitType; diff --git a/JavaScriptCore/runtime/SymbolTable.h b/JavaScriptCore/runtime/SymbolTable.h index 2717075..1b1636d 100644 --- a/JavaScriptCore/runtime/SymbolTable.h +++ b/JavaScriptCore/runtime/SymbolTable.h @@ -119,7 +119,7 @@ namespace JSC { static const bool needsDestruction = false; }; - typedef HashMap<RefPtr<UString::Rep>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, SymbolTableIndexHashTraits> SymbolTable; + typedef HashMap<RefPtr<StringImpl>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<StringImpl> >, SymbolTableIndexHashTraits> SymbolTable; class SharedSymbolTable : public SymbolTable, public RefCounted<SharedSymbolTable> { public: diff --git a/JavaScriptCore/runtime/UString.cpp b/JavaScriptCore/runtime/UString.cpp index c442500..ac3acfd 100644 --- a/JavaScriptCore/runtime/UString.cpp +++ b/JavaScriptCore/runtime/UString.cpp @@ -54,36 +54,40 @@ namespace JSC { extern const double NaN; extern const double Inf; -// The null string is immutable, except for refCount. -UString* UString::s_nullUString; - COMPILE_ASSERT(sizeof(UString) == sizeof(void*), UString_should_stay_small); -void initializeUString() +// Construct a string with UTF-16 data. +UString::UString(const UChar* characters, unsigned length) + : m_impl(characters ? StringImpl::create(characters, length) : 0) { - // UStringImpl::empty() does not construct its static string in a threadsafe fashion, - // so ensure it has been initialized from here. - UStringImpl::empty(); - - UString::s_nullUString = new UString; } -UString::UString(const char* c) - : m_rep(Rep::create(c)) +// Construct a string with UTF-16 data, from a null-terminated source. +UString::UString(const UChar* characters) { + if (!characters) + return; + + int length = 0; + while (characters[length] != UChar(0)) + ++length; + + m_impl = StringImpl::create(characters, length); } -UString::UString(const char* c, unsigned length) - : m_rep(Rep::create(c, length)) +// Construct a string with latin1 data. +UString::UString(const char* characters, unsigned length) + : m_impl(characters ? StringImpl::create(characters, length) : 0) { } -UString::UString(const UChar* c, unsigned length) - : m_rep(Rep::create(c, length)) +// Construct a string with latin1 data, from a null-terminated source. +UString::UString(const char* characters) + : m_impl(characters ? StringImpl::create(characters) : 0) { } -UString UString::from(int i) +UString UString::number(int i) { UChar buf[1 + sizeof(i) * 3]; UChar* end = buf + sizeof(buf) / sizeof(UChar); @@ -112,7 +116,7 @@ UString UString::from(int i) return UString(p, static_cast<unsigned>(end - p)); } -UString UString::from(long long i) +UString UString::number(long long i) { UChar buf[1 + sizeof(i) * 3]; UChar* end = buf + sizeof(buf) / sizeof(UChar); @@ -145,7 +149,7 @@ UString UString::from(long long i) return UString(p, static_cast<unsigned>(end - p)); } -UString UString::from(unsigned u) +UString UString::number(unsigned u) { UChar buf[sizeof(u) * 3]; UChar* end = buf + sizeof(buf) / sizeof(UChar); @@ -163,7 +167,7 @@ UString UString::from(unsigned u) return UString(p, static_cast<unsigned>(end - p)); } -UString UString::from(long l) +UString UString::number(long l) { UChar buf[1 + sizeof(l) * 3]; UChar* end = buf + sizeof(buf) / sizeof(UChar); @@ -192,7 +196,7 @@ UString UString::from(long l) return UString(p, end - p); } -UString UString::from(double d) +UString UString::number(double d) { DtoaBuffer buffer; unsigned length; @@ -200,359 +204,17 @@ UString UString::from(double d) return UString(buffer, length); } -char* UString::ascii() const -{ - static char* asciiBuffer = 0; - - unsigned length = size(); - unsigned neededSize = length + 1; - delete[] asciiBuffer; - asciiBuffer = new char[neededSize]; - - const UChar* p = data(); - char* q = asciiBuffer; - const UChar* limit = p + length; - while (p != limit) { - *q = static_cast<char>(p[0]); - ++p; - ++q; - } - *q = '\0'; - - return asciiBuffer; -} - -bool UString::is8Bit() const -{ - const UChar* u = data(); - const UChar* limit = u + size(); - while (u < limit) { - if (u[0] > 0xFF) - return false; - ++u; - } - - return true; -} - -UChar UString::operator[](unsigned pos) const +UString UString::substringSharingImpl(unsigned offset, unsigned length) const { - if (pos >= size()) - return '\0'; - return data()[pos]; -} - -static inline bool isInfinity(double number) -{ - return number == Inf || number == -Inf; -} - -static bool isInfinity(const UChar* data, const UChar* end) -{ - return data + 7 < end - && data[0] == 'I' - && data[1] == 'n' - && data[2] == 'f' - && data[3] == 'i' - && data[4] == 'n' - && data[5] == 'i' - && data[6] == 't' - && data[7] == 'y'; -} - -double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const -{ - unsigned size = this->size(); - - if (size == 1) { - UChar c = data()[0]; - if (isASCIIDigit(c)) - return c - '0'; - if (isStrWhiteSpace(c) && tolerateEmptyString) - return 0; - return NaN; - } - - // FIXME: If tolerateTrailingJunk is true, then we want to tolerate junk - // after the number, even if it contains invalid UTF-16 sequences. So we - // shouldn't use the UTF8String function, which returns null when it - // encounters invalid UTF-16. Further, we have no need to convert the - // non-ASCII characters to UTF-8, so the UTF8String does quite a bit of - // unnecessary work. - - // FIXME: The space skipping code below skips only ASCII spaces, but callers - // need to skip all StrWhiteSpace. The isStrWhiteSpace function does the - // right thing but requires UChar, not char, for its argument. - - const UChar* data = this->data(); - const UChar* end = data + size; - - // Skip leading white space. - for (; data < end; ++data) { - if (!isStrWhiteSpace(*data)) - break; - } - - // Empty string. - if (data == end) - return tolerateEmptyString ? 0.0 : NaN; - - double number; - - if (data[0] == '0' && data + 2 < end && (data[1] | 0x20) == 'x' && isASCIIHexDigit(data[2])) { - // Hex number. - data += 2; - const UChar* firstDigitPosition = data; - number = 0; - while (true) { - number = number * 16 + toASCIIHexValue(*data); - ++data; - if (data == end) - break; - if (!isASCIIHexDigit(*data)) - break; - } - if (number >= mantissaOverflowLowerBound) - number = parseIntOverflow(firstDigitPosition, data - firstDigitPosition, 16); - } else { - // Decimal number. - - // Put into a null-terminated byte buffer. - Vector<char, 32> byteBuffer; - for (const UChar* characters = data; characters < end; ++characters) { - UChar character = *characters; - byteBuffer.append(isASCII(character) ? character : 0); - } - byteBuffer.append(0); - - char* byteBufferEnd; - number = WTF::strtod(byteBuffer.data(), &byteBufferEnd); - const UChar* pastNumber = data + (byteBufferEnd - byteBuffer.data()); - - if ((number || pastNumber != data) && !isInfinity(number)) - data = pastNumber; - else { - // We used strtod() to do the conversion. However, strtod() handles - // infinite values slightly differently than JavaScript in that it - // converts the string "inf" with any capitalization to infinity, - // whereas the ECMA spec requires that it be converted to NaN. - - double signedInfinity = Inf; - if (data < end) { - if (*data == '+') - data++; - else if (*data == '-') { - signedInfinity = -Inf; - data++; - } - } - if (isInfinity(data, end)) { - number = signedInfinity; - data += 8; - } else if (isInfinity(number) && data < end && (*data | 0x20) != 'i') - data = pastNumber; - else - return NaN; - } - } - - // Look for trailing junk. - if (!tolerateTrailingJunk) { - // Allow trailing white space. - for (; data < end; ++data) { - if (!isStrWhiteSpace(*data)) - break; - } - if (data != end) - return NaN; - } - - return number; -} - -double UString::toDouble(bool tolerateTrailingJunk) const -{ - return toDouble(tolerateTrailingJunk, true); -} - -double UString::toDouble() const -{ - return toDouble(false, true); -} - -uint32_t UString::toUInt32(bool* ok) const -{ - double d = toDouble(); - bool b = true; - - if (d != static_cast<uint32_t>(d)) { - b = false; - d = 0; - } - - if (ok) - *ok = b; - - return static_cast<uint32_t>(d); -} - -uint32_t UString::toUInt32(bool* ok, bool tolerateEmptyString) const -{ - double d = toDouble(false, tolerateEmptyString); - bool b = true; - - if (d != static_cast<uint32_t>(d)) { - b = false; - d = 0; - } + // FIXME: We used to check against a limit of Heap::minExtraCost / sizeof(UChar). - if (ok) - *ok = b; + unsigned stringLength = this->length(); + offset = min(offset, stringLength); + length = min(length, stringLength - offset); - return static_cast<uint32_t>(d); -} - -uint32_t UString::toStrictUInt32(bool* ok) const -{ - if (ok) - *ok = false; - - // Empty string is not OK. - unsigned len = m_rep->length(); - if (len == 0) - return 0; - const UChar* p = m_rep->characters(); - unsigned short c = p[0]; - - // If the first digit is 0, only 0 itself is OK. - if (c == '0') { - if (len == 1 && ok) - *ok = true; - return 0; - } - - // Convert to UInt32, checking for overflow. - uint32_t i = 0; - while (1) { - // Process character, turning it into a digit. - if (c < '0' || c > '9') - return 0; - const unsigned d = c - '0'; - - // Multiply by 10, checking for overflow out of 32 bits. - if (i > 0xFFFFFFFFU / 10) - return 0; - i *= 10; - - // Add in the digit, checking for overflow out of 32 bits. - const unsigned max = 0xFFFFFFFFU - d; - if (i > max) - return 0; - i += d; - - // Handle end of string. - if (--len == 0) { - if (ok) - *ok = true; - return i; - } - - // Get next character. - c = *(++p); - } -} - -unsigned UString::find(const UString& f, unsigned pos) const -{ - unsigned fsz = f.size(); - - if (fsz == 1) { - UChar ch = f[0]; - const UChar* end = data() + size(); - for (const UChar* c = data() + pos; c < end; c++) { - if (*c == ch) - return static_cast<unsigned>(c - data()); - } - return NotFound; - } - - unsigned sz = size(); - if (sz < fsz) - return NotFound; - if (fsz == 0) - return pos; - const UChar* end = data() + sz - fsz; - unsigned fsizeminusone = (fsz - 1) * sizeof(UChar); - const UChar* fdata = f.data(); - unsigned short fchar = fdata[0]; - ++fdata; - for (const UChar* c = data() + pos; c <= end; c++) { - if (c[0] == fchar && !memcmp(c + 1, fdata, fsizeminusone)) - return static_cast<unsigned>(c - data()); - } - - return NotFound; -} - -unsigned UString::find(UChar ch, unsigned pos) const -{ - const UChar* end = data() + size(); - for (const UChar* c = data() + pos; c < end; c++) { - if (*c == ch) - return static_cast<unsigned>(c - data()); - } - - return NotFound; -} - -unsigned UString::rfind(const UString& f, unsigned pos) const -{ - unsigned sz = size(); - unsigned fsz = f.size(); - if (sz < fsz) - return NotFound; - if (pos > sz - fsz) - pos = sz - fsz; - if (fsz == 0) - return pos; - unsigned fsizeminusone = (fsz - 1) * sizeof(UChar); - const UChar* fdata = f.data(); - for (const UChar* c = data() + pos; c >= data(); c--) { - if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone)) - return static_cast<unsigned>(c - data()); - } - - return NotFound; -} - -unsigned UString::rfind(UChar ch, unsigned pos) const -{ - if (isEmpty()) - return NotFound; - if (pos + 1 >= size()) - pos = size() - 1; - for (const UChar* c = data() + pos; c >= data(); c--) { - if (*c == ch) - return static_cast<unsigned>(c - data()); - } - - return NotFound; -} - -UString UString::substr(unsigned pos, unsigned len) const -{ - unsigned s = size(); - - if (pos >= s) - pos = s; - unsigned limit = s - pos; - if (len > limit) - len = limit; - - if (pos == 0 && len == s) + if (!offset && length == stringLength) return *this; - - return UString(Rep::create(m_rep, pos, len)); + return UString(StringImpl::create(m_impl, offset, length)); } bool operator==(const UString& s1, const char *s2) @@ -560,8 +222,8 @@ bool operator==(const UString& s1, const char *s2) if (s2 == 0) return s1.isEmpty(); - const UChar* u = s1.data(); - const UChar* uend = u + s1.size(); + const UChar* u = s1.characters(); + const UChar* uend = u + s1.length(); while (u != uend && *s2) { if (u[0] != (unsigned char)*s2) return false; @@ -574,11 +236,11 @@ bool operator==(const UString& s1, const char *s2) bool operator<(const UString& s1, const UString& s2) { - const unsigned l1 = s1.size(); - const unsigned l2 = s2.size(); + const unsigned l1 = s1.length(); + const unsigned l2 = s2.length(); const unsigned lmin = l1 < l2 ? l1 : l2; - const UChar* c1 = s1.data(); - const UChar* c2 = s2.data(); + const UChar* c1 = s1.characters(); + const UChar* c2 = s2.characters(); unsigned l = 0; while (l < lmin && *c1 == *c2) { c1++; @@ -593,11 +255,11 @@ bool operator<(const UString& s1, const UString& s2) bool operator>(const UString& s1, const UString& s2) { - const unsigned l1 = s1.size(); - const unsigned l2 = s2.size(); + const unsigned l1 = s1.length(); + const unsigned l2 = s2.length(); const unsigned lmin = l1 < l2 ? l1 : l2; - const UChar* c1 = s1.data(); - const UChar* c2 = s2.data(); + const UChar* c1 = s1.characters(); + const UChar* c2 = s2.characters(); unsigned l = 0; while (l < lmin && *c1 == *c2) { c1++; @@ -610,20 +272,94 @@ bool operator>(const UString& s1, const UString& s2) return (l1 > l2); } -CString UString::UTF8String(bool strict) const +CString UString::ascii() const { - // Allocate a buffer big enough to hold all the characters. - const unsigned length = size(); - Vector<char, 1024> buffer(length * 3); - - // Convert to runs of 8-bit characters. - char* p = buffer.data(); - const UChar* d = reinterpret_cast<const UChar*>(&data()[0]); - ConversionResult result = convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size(), strict); - if (result != conversionOK) + // Basic Latin1 (ISO) encoding - Unicode characters 0..255 are + // preserved, characters outside of this range are converted to '?'. + + unsigned length = this->length(); + const UChar* characters = this->characters(); + + char* characterBuffer; + CString result = CString::newUninitialized(length, characterBuffer); + + for (unsigned i = 0; i < length; ++i) { + UChar ch = characters[i]; + characterBuffer[i] = ch && (ch < 0x20 || ch >= 0x7f) ? '?' : ch; + } + + return result; +} + +CString UString::latin1() const +{ + // Basic Latin1 (ISO) encoding - Unicode characters 0..255 are + // preserved, characters outside of this range are converted to '?'. + + unsigned length = this->length(); + const UChar* characters = this->characters(); + + char* characterBuffer; + CString result = CString::newUninitialized(length, characterBuffer); + + for (unsigned i = 0; i < length; ++i) { + UChar ch = characters[i]; + characterBuffer[i] = ch > 0xff ? '?' : ch; + } + + return result; +} + +// Helper to write a three-byte UTF-8 code point to the buffer, caller must check room is available. +static inline void putUTF8Triple(char*& buffer, UChar ch) +{ + ASSERT(ch >= 0x0800); + *buffer++ = static_cast<char>(((ch >> 12) & 0x0F) | 0xE0); + *buffer++ = static_cast<char>(((ch >> 6) & 0x3F) | 0x80); + *buffer++ = static_cast<char>((ch & 0x3F) | 0x80); +} + +CString UString::utf8(bool strict) const +{ + unsigned length = this->length(); + const UChar* characters = this->characters(); + + // Allocate a buffer big enough to hold all the characters + // (an individual UTF-16 UChar can only expand to 3 UTF-8 bytes). + // Optimization ideas, if we find this function is hot: + // * We could speculatively create a CStringBuffer to contain 'length' + // characters, and resize if necessary (i.e. if the buffer contains + // non-ascii characters). (Alternatively, scan the buffer first for + // ascii characters, so we know this will be sufficient). + // * We could allocate a CStringBuffer with an appropriate size to + // have a good chance of being able to write the string into the + // buffer without reallocing (say, 1.5 x length). + Vector<char, 1024> bufferVector(length * 3); + + char* buffer = bufferVector.data(); + ConversionResult result = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size(), strict); + ASSERT(result != targetExhausted); // (length * 3) should be sufficient for any conversion + + // Only produced from strict conversion. + if (result == sourceIllegal) return CString(); - return CString(buffer.data(), p - buffer.data()); + // Check for an unconverted high surrogate. + if (result == sourceExhausted) { + if (strict) + return CString(); + // This should be one unpaired high surrogate. Treat it the same + // was as an unpaired high surrogate would have been handled in + // the middle of a string with non-strict conversion - which is + // to say, simply encode it to UTF-8. + ASSERT((characters + 1) == (this->characters() + length)); + ASSERT((*characters >= 0xD800) && (*characters <= 0xDBFF)); + // There should be room left, since one UChar hasn't been converted. + ASSERT((buffer + 3) <= (buffer + bufferVector.size())); + putUTF8Triple(buffer, *characters); + } + + return CString(bufferVector.data(), buffer - bufferVector.data()); } } // namespace JSC diff --git a/JavaScriptCore/runtime/UString.h b/JavaScriptCore/runtime/UString.h index bae9265..cd73c28 100644 --- a/JavaScriptCore/runtime/UString.h +++ b/JavaScriptCore/runtime/UString.h @@ -1,678 +1,263 @@ /* - * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * This library is 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. + * 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. + * 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 UString_h #define UString_h -#include "Collector.h" -#include "UStringImpl.h" -#include <stdint.h> -#include <string.h> -#include <wtf/Assertions.h> -#include <wtf/CrossThreadRefCounted.h> -#include <wtf/OwnFastMallocPtr.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> -#include <wtf/Vector.h> -#include <wtf/text/CString.h> -#include <wtf/unicode/Unicode.h> +#include <wtf/text/StringImpl.h> namespace JSC { - using WTF::PlacementNewAdoptType; - using WTF::PlacementNewAdopt; +class UString { +public: + // Construct a null string, distinguishable from an empty string. + UString() { } - class UString { - friend class JIT; + // Construct a string with UTF-16 data. + UString(const UChar* characters, unsigned length); - public: - typedef UStringImpl Rep; - - public: - UString() {} - UString(const char*); // Constructor for null-terminated string. - UString(const char*, unsigned length); - UString(const UChar*, unsigned length); - UString(const Vector<UChar>& buffer); - - UString(const UString& s) - : m_rep(s.m_rep) - { - } - - // Special constructor for cases where we overwrite an object in place. - UString(PlacementNewAdoptType) - : m_rep(PlacementNewAdopt) - { - } - - template<size_t inlineCapacity> - static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector) - { - return Rep::adopt(vector); - } - - static UString from(int); - static UString from(long long); - static UString from(unsigned); - static UString from(long); - static UString from(double); - - // NOTE: This method should only be used for *debugging* purposes as it - // is neither Unicode safe nor free from side effects nor thread-safe. - char* ascii() const; - - /** - * Convert the string to UTF-8, assuming it is UTF-16 encoded. - * In non-strict mode, this function is tolerant of badly formed UTF-16, it - * can create UTF-8 strings that are invalid because they have characters in - * the range U+D800-U+DDFF, U+FFFE, or U+FFFF, but the UTF-8 string is - * guaranteed to be otherwise valid. - * In strict mode, error is returned as null CString. - */ - CString UTF8String(bool strict = false) const; - - const UChar* data() const - { - if (!m_rep) - return 0; - return m_rep->characters(); - } - - unsigned size() const - { - if (!m_rep) - return 0; - return m_rep->length(); - } - - bool isNull() const { return !m_rep; } - bool isEmpty() const { return !m_rep || !m_rep->length(); } - - bool is8Bit() const; - - UChar operator[](unsigned pos) const; - - double toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const; - double toDouble(bool tolerateTrailingJunk) const; - double toDouble() const; - - uint32_t toUInt32(bool* ok = 0) const; - uint32_t toUInt32(bool* ok, bool tolerateEmptyString) const; - uint32_t toStrictUInt32(bool* ok = 0) const; - - unsigned toArrayIndex(bool* ok = 0) const; + // Construct a string with UTF-16 data, from a null-terminated source. + UString(const UChar*); - static const unsigned NotFound = 0xFFFFFFFFu; - unsigned find(const UString& f, unsigned pos = 0) const; - unsigned find(UChar, unsigned pos = 0) const; - unsigned rfind(const UString& f, unsigned pos) const; - unsigned rfind(UChar, unsigned pos) const; + // Construct a string with latin1 data. + UString(const char* characters, unsigned length); - UString substr(unsigned pos = 0, unsigned len = 0xFFFFFFFF) const; + // Construct a string with latin1 data, from a null-terminated source. + UString(const char* characters); - static const UString& null() { return *s_nullUString; } + // Construct a string referencing an existing StringImpl. + UString(StringImpl* impl) : m_impl(impl) { } + UString(PassRefPtr<StringImpl> impl) : m_impl(impl) { } + UString(RefPtr<StringImpl> impl) : m_impl(impl) { } - Rep* rep() const { return m_rep.get(); } + // Inline the destructor. + ALWAYS_INLINE ~UString() { } - UString(PassRefPtr<Rep> r) - : m_rep(r) - { - } - - size_t cost() const - { - if (!m_rep) - return 0; - return m_rep->cost(); - } + void swap(UString& o) { m_impl.swap(o.m_impl); } - ALWAYS_INLINE ~UString() { } - private: - RefPtr<Rep> m_rep; + template<size_t inlineCapacity> + static UString adopt(Vector<UChar, inlineCapacity>& vector) { return StringImpl::adopt(vector); } - static UString* s_nullUString; + bool isNull() const { return !m_impl; } + bool isEmpty() const { return !m_impl || !m_impl->length(); } - friend void initializeUString(); - friend bool operator==(const UString&, const UString&); - }; + StringImpl* impl() const { return m_impl.get(); } - ALWAYS_INLINE bool operator==(const UString& s1, const UString& s2) + unsigned length() const { - UString::Rep* rep1 = s1.rep(); - UString::Rep* rep2 = s2.rep(); - unsigned size1 = 0; - unsigned size2 = 0; - - if (rep1 == rep2) // If they're the same rep, they're equal. - return true; - - if (rep1) - size1 = rep1->length(); - - if (rep2) - size2 = rep2->length(); - - if (size1 != size2) // If the lengths are not the same, we're done. - return false; - - if (!size1) - return true; - - // At this point we know - // (a) that the strings are the same length and - // (b) that they are greater than zero length. - const UChar* d1 = rep1->characters(); - const UChar* d2 = rep2->characters(); - - if (d1 == d2) // Check to see if the data pointers are the same. - return true; - - // Do quick checks for sizes 1 and 2. - switch (size1) { - case 1: - return d1[0] == d2[0]; - case 2: - return (d1[0] == d2[0]) & (d1[1] == d2[1]); - default: - return memcmp(d1, d2, size1 * sizeof(UChar)) == 0; - } - } - - - inline bool operator!=(const UString& s1, const UString& s2) - { - return !JSC::operator==(s1, s2); - } - - bool operator<(const UString& s1, const UString& s2); - bool operator>(const UString& s1, const UString& s2); - - bool operator==(const UString& s1, const char* s2); - - inline bool operator!=(const UString& s1, const char* s2) - { - return !JSC::operator==(s1, s2); - } - - inline bool operator==(const char *s1, const UString& s2) - { - return operator==(s2, s1); - } - - inline bool operator!=(const char *s1, const UString& s2) - { - return !JSC::operator==(s1, s2); - } - - inline int codePointCompare(const UString& s1, const UString& s2) - { - return codePointCompare(s1.rep(), s2.rep()); - } - - // Rule from ECMA 15.2 about what an array index is. - // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1. - inline unsigned UString::toArrayIndex(bool* ok) const - { - unsigned i = toStrictUInt32(ok); - if (ok && i >= 0xFFFFFFFFU) - *ok = false; - return i; - } - - // We'd rather not do shared substring append for small strings, since - // this runs too much risk of a tiny initial string holding down a - // huge buffer. - static const unsigned minShareSize = Heap::minExtraCost / sizeof(UChar); - - struct IdentifierRepHash : PtrHash<RefPtr<JSC::UString::Rep> > { - static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->existingHash(); } - static unsigned hash(JSC::UString::Rep* key) { return key->existingHash(); } - }; - - void initializeUString(); - - template<typename StringType> - class StringTypeAdapter { - }; - - template<> - class StringTypeAdapter<char*> { - public: - StringTypeAdapter<char*>(char* buffer) - : m_buffer((unsigned char*)buffer) - , m_length(strlen(buffer)) - { - } - - unsigned length() { return m_length; } - - void writeTo(UChar* destination) - { - for (unsigned i = 0; i < m_length; ++i) - destination[i] = m_buffer[i]; - } - - private: - const unsigned char* m_buffer; - unsigned m_length; - }; - - template<> - class StringTypeAdapter<const char*> { - public: - StringTypeAdapter<const char*>(const char* buffer) - : m_buffer((unsigned char*)buffer) - , m_length(strlen(buffer)) - { - } - - unsigned length() { return m_length; } - - void writeTo(UChar* destination) - { - for (unsigned i = 0; i < m_length; ++i) - destination[i] = m_buffer[i]; - } - - private: - const unsigned char* m_buffer; - unsigned m_length; - }; - - template<> - class StringTypeAdapter<UString> { - public: - StringTypeAdapter<UString>(UString& string) - : m_data(string.data()) - , m_length(string.size()) - { - } - - unsigned length() { return m_length; } - - void writeTo(UChar* destination) - { - for (unsigned i = 0; i < m_length; ++i) - destination[i] = m_data[i]; - } - - private: - const UChar* m_data; - unsigned m_length; - }; - - inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow) - { - unsigned oldTotal = total; - total = oldTotal + addend; - if (total < oldTotal) - overflow = true; - } - - template<typename StringType1, typename StringType2> - PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2) - { - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - - UChar* buffer; - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - if (overflow) + if (!m_impl) return 0; - PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - - return resultImpl; + return m_impl->length(); } - template<typename StringType1, typename StringType2, typename StringType3> - PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3) + const UChar* characters() const { - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - - UChar* buffer = 0; - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - if (overflow) - return 0; - PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) + if (!m_impl) return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - - return resultImpl; + return m_impl->characters(); } - template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> - PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) + CString ascii() const; + CString latin1() const; + CString utf8(bool strict = false) const; + + UChar operator[](unsigned index) const { - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - StringTypeAdapter<StringType4> adapter4(string4); - - UChar* buffer; - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - sumWithOverflow(length, adapter4.length(), overflow); - if (overflow) - return 0; - PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) + if (!m_impl || index >= m_impl->length()) return 0; + return m_impl->characters()[index]; + } - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - - return resultImpl; + static UString number(int); + static UString number(unsigned); + static UString number(long); + static UString number(long long); + static UString number(double); + + // Find a single character or string, also with match function & latin1 forms. + size_t find(UChar c, unsigned start = 0) const + { return m_impl ? m_impl->find(c, start) : notFound; } + size_t find(const UString& str, unsigned start = 0) const + { return m_impl ? m_impl->find(str.impl(), start) : notFound; } + size_t find(const char* str, unsigned start = 0) const + { return m_impl ? m_impl->find(str, start) : notFound; } + + // Find the last instance of a single character or string. + size_t reverseFind(UChar c, unsigned start = UINT_MAX) const + { return m_impl ? m_impl->reverseFind(c, start) : notFound; } + size_t reverseFind(const UString& str, unsigned start = UINT_MAX) const + { return m_impl ? m_impl->reverseFind(str.impl(), start) : notFound; } + + UString substringSharingImpl(unsigned pos, unsigned len = UINT_MAX) const; + +private: + RefPtr<StringImpl> m_impl; +}; + +ALWAYS_INLINE bool operator==(const UString& s1, const UString& s2) +{ + StringImpl* rep1 = s1.impl(); + StringImpl* rep2 = s2.impl(); + unsigned size1 = 0; + unsigned size2 = 0; + + if (rep1 == rep2) // If they're the same rep, they're equal. + return true; + + if (rep1) + size1 = rep1->length(); + + if (rep2) + size2 = rep2->length(); + + if (size1 != size2) // If the lengths are not the same, we're done. + return false; + + if (!size1) + return true; + + // At this point we know + // (a) that the strings are the same length and + // (b) that they are greater than zero length. + const UChar* d1 = rep1->characters(); + const UChar* d2 = rep2->characters(); + + if (d1 == d2) // Check to see if the data pointers are the same. + return true; + + // Do quick checks for sizes 1 and 2. + switch (size1) { + case 1: + return d1[0] == d2[0]; + case 2: + return (d1[0] == d2[0]) & (d1[1] == d2[1]); + default: + return memcmp(d1, d2, size1 * sizeof(UChar)) == 0; } +} - template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> - PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) - { - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - StringTypeAdapter<StringType4> adapter4(string4); - StringTypeAdapter<StringType5> adapter5(string5); - - UChar* buffer; - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - sumWithOverflow(length, adapter4.length(), overflow); - sumWithOverflow(length, adapter5.length(), overflow); - if (overflow) - return 0; - PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - - return resultImpl; - } +inline bool operator!=(const UString& s1, const UString& s2) +{ + return !JSC::operator==(s1, s2); +} - template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> - PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) - { - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - StringTypeAdapter<StringType4> adapter4(string4); - StringTypeAdapter<StringType5> adapter5(string5); - StringTypeAdapter<StringType6> adapter6(string6); - - UChar* buffer; - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - sumWithOverflow(length, adapter4.length(), overflow); - sumWithOverflow(length, adapter5.length(), overflow); - sumWithOverflow(length, adapter6.length(), overflow); - if (overflow) - return 0; - PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; +bool operator<(const UString& s1, const UString& s2); +bool operator>(const UString& s1, const UString& s2); - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - result += adapter5.length(); - adapter6.writeTo(result); - - return resultImpl; - } +bool operator==(const UString& s1, const char* s2); - template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> - PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) - { - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - StringTypeAdapter<StringType4> adapter4(string4); - StringTypeAdapter<StringType5> adapter5(string5); - StringTypeAdapter<StringType6> adapter6(string6); - StringTypeAdapter<StringType7> adapter7(string7); - - UChar* buffer; - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - sumWithOverflow(length, adapter4.length(), overflow); - sumWithOverflow(length, adapter5.length(), overflow); - sumWithOverflow(length, adapter6.length(), overflow); - sumWithOverflow(length, adapter7.length(), overflow); - if (overflow) - return 0; - PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; +inline bool operator!=(const UString& s1, const char* s2) +{ + return !JSC::operator==(s1, s2); +} - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - result += adapter5.length(); - adapter6.writeTo(result); - result += adapter6.length(); - adapter7.writeTo(result); - - return resultImpl; - } +inline bool operator==(const char *s1, const UString& s2) +{ + return operator==(s2, s1); +} - template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> - PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) - { - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - StringTypeAdapter<StringType4> adapter4(string4); - StringTypeAdapter<StringType5> adapter5(string5); - StringTypeAdapter<StringType6> adapter6(string6); - StringTypeAdapter<StringType7> adapter7(string7); - StringTypeAdapter<StringType8> adapter8(string8); - - UChar* buffer; - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - sumWithOverflow(length, adapter4.length(), overflow); - sumWithOverflow(length, adapter5.length(), overflow); - sumWithOverflow(length, adapter6.length(), overflow); - sumWithOverflow(length, adapter7.length(), overflow); - sumWithOverflow(length, adapter8.length(), overflow); - if (overflow) - return 0; - PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; +inline bool operator!=(const char *s1, const UString& s2) +{ + return !JSC::operator==(s1, s2); +} - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - result += adapter5.length(); - adapter6.writeTo(result); - result += adapter6.length(); - adapter7.writeTo(result); - result += adapter7.length(); - adapter8.writeTo(result); - - return resultImpl; - } +inline int codePointCompare(const UString& s1, const UString& s2) +{ + return codePointCompare(s1.impl(), s2.impl()); +} - template<typename StringType1, typename StringType2> - UString makeString(StringType1 string1, StringType2 string2) +struct UStringHash { + static unsigned hash(StringImpl* key) { return key->hash(); } + static bool equal(const StringImpl* a, const StringImpl* b) { - PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2); - if (!resultImpl) - CRASH(); - return resultImpl; - } + if (a == b) + return true; + if (!a || !b) + return false; - template<typename StringType1, typename StringType2, typename StringType3> - UString makeString(StringType1 string1, StringType2 string2, StringType3 string3) - { - PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3); - if (!resultImpl) - CRASH(); - return resultImpl; - } + unsigned aLength = a->length(); + unsigned bLength = b->length(); + if (aLength != bLength) + return false; - template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> - UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) - { - PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4); - if (!resultImpl) - CRASH(); - return resultImpl; - } + // FIXME: perhaps we should have a more abstract macro that indicates when + // going 4 bytes at a time is unsafe +#if CPU(ARM) || CPU(SH4) + const UChar* aChars = a->characters(); + const UChar* bChars = b->characters(); + for (unsigned i = 0; i != aLength; ++i) { + if (*aChars++ != *bChars++) + return false; + } + return true; +#else + /* Do it 4-bytes-at-a-time on architectures where it's safe */ + const uint32_t* aChars = reinterpret_cast<const uint32_t*>(a->characters()); + const uint32_t* bChars = reinterpret_cast<const uint32_t*>(b->characters()); + + unsigned halfLength = aLength >> 1; + for (unsigned i = 0; i != halfLength; ++i) + if (*aChars++ != *bChars++) + return false; + + if (aLength & 1 && *reinterpret_cast<const uint16_t*>(aChars) != *reinterpret_cast<const uint16_t*>(bChars)) + return false; - template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> - UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) - { - PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5); - if (!resultImpl) - CRASH(); - return resultImpl; + return true; +#endif } - template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> - UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) + static unsigned hash(const RefPtr<StringImpl>& key) { return key->hash(); } + static bool equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b) { - PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6); - if (!resultImpl) - CRASH(); - return resultImpl; + return equal(a.get(), b.get()); } - template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> - UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) + static unsigned hash(const UString& key) { return key.impl()->hash(); } + static bool equal(const UString& a, const UString& b) { - PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7); - if (!resultImpl) - CRASH(); - return resultImpl; + return equal(a.impl(), b.impl()); } - template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> - UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) - { - PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8); - if (!resultImpl) - CRASH(); - return resultImpl; - } + static const bool safeToCompareToEmptyOrDeleted = false; +}; } // namespace JSC namespace WTF { - template<typename T> struct DefaultHash; - template<typename T> struct StrHash; - - template<> struct StrHash<JSC::UString::Rep*> { - static unsigned hash(const JSC::UString::Rep* key) { return key->hash(); } - static bool equal(const JSC::UString::Rep* a, const JSC::UString::Rep* b) { return ::equal(a, b); } - static const bool safeToCompareToEmptyOrDeleted = false; - }; - - template<> struct StrHash<RefPtr<JSC::UString::Rep> > : public StrHash<JSC::UString::Rep*> { - using StrHash<JSC::UString::Rep*>::hash; - static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->hash(); } - using StrHash<JSC::UString::Rep*>::equal; - static bool equal(const RefPtr<JSC::UString::Rep>& a, const RefPtr<JSC::UString::Rep>& b) { return ::equal(a.get(), b.get()); } - static bool equal(const JSC::UString::Rep* a, const RefPtr<JSC::UString::Rep>& b) { return ::equal(a, b.get()); } - static bool equal(const RefPtr<JSC::UString::Rep>& a, const JSC::UString::Rep* b) { return ::equal(a.get(), b); } +// UStringHash is the default hash for UString +template<typename T> struct DefaultHash; +template<> struct DefaultHash<JSC::UString> { + typedef JSC::UStringHash Hash; +}; - static const bool safeToCompareToEmptyOrDeleted = false; - }; +template <> struct VectorTraits<JSC::UString> : SimpleClassVectorTraits +{ + static const bool canInitializeWithMemset = true; +}; - template <> struct VectorTraits<JSC::UString> : SimpleClassVectorTraits - { - static const bool canInitializeWithMemset = true; - }; - } // namespace WTF #endif + diff --git a/JavaScriptCore/runtime/UStringImpl.h b/JavaScriptCore/runtime/UStringImpl.h deleted file mode 100644 index 6401d3b..0000000 --- a/JavaScriptCore/runtime/UStringImpl.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 1999 Lars Knoll (knoll@kde.org) - * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef UStringImpl_h -#define UStringImpl_h - -// FIXME: Remove this redundant name! -#include <wtf/text/StringImpl.h> -namespace JSC { typedef StringImpl UStringImpl; } - -#endif |