summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore/runtime')
-rw-r--r--JavaScriptCore/runtime/Arguments.cpp16
-rw-r--r--JavaScriptCore/runtime/ArrayPrototype.cpp8
-rw-r--r--JavaScriptCore/runtime/Collector.h14
-rw-r--r--JavaScriptCore/runtime/DateConversion.cpp3
-rw-r--r--JavaScriptCore/runtime/DatePrototype.cpp2
-rw-r--r--JavaScriptCore/runtime/ExceptionHelpers.cpp1
-rw-r--r--JavaScriptCore/runtime/FunctionConstructor.cpp1
-rw-r--r--JavaScriptCore/runtime/FunctionPrototype.cpp6
-rw-r--r--JavaScriptCore/runtime/Identifier.cpp87
-rw-r--r--JavaScriptCore/runtime/Identifier.h78
-rw-r--r--JavaScriptCore/runtime/InitializeThreading.cpp5
-rw-r--r--JavaScriptCore/runtime/InternalFunction.cpp2
-rw-r--r--JavaScriptCore/runtime/JSArray.cpp18
-rw-r--r--JavaScriptCore/runtime/JSArray.h15
-rw-r--r--JavaScriptCore/runtime/JSByteArray.cpp6
-rw-r--r--JavaScriptCore/runtime/JSCell.h3
-rw-r--r--JavaScriptCore/runtime/JSFunction.cpp2
-rw-r--r--JavaScriptCore/runtime/JSGlobalData.cpp1
-rw-r--r--JavaScriptCore/runtime/JSGlobalObject.h2
-rw-r--r--JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp186
-rw-r--r--JavaScriptCore/runtime/JSGlobalObjectFunctions.h1
-rw-r--r--JavaScriptCore/runtime/JSNumberCell.cpp2
-rw-r--r--JavaScriptCore/runtime/JSONObject.cpp25
-rw-r--r--JavaScriptCore/runtime/JSStaticScopeObject.h2
-rw-r--r--JavaScriptCore/runtime/JSString.cpp41
-rw-r--r--JavaScriptCore/runtime/JSString.h68
-rw-r--r--JavaScriptCore/runtime/JSStringBuilder.h13
-rw-r--r--JavaScriptCore/runtime/JSVariableObject.cpp4
-rw-r--r--JavaScriptCore/runtime/JSVariableObject.h8
-rw-r--r--JavaScriptCore/runtime/LiteralParser.h4
-rw-r--r--JavaScriptCore/runtime/Lookup.cpp4
-rw-r--r--JavaScriptCore/runtime/Lookup.h12
-rw-r--r--JavaScriptCore/runtime/NumberPrototype.cpp28
-rw-r--r--JavaScriptCore/runtime/NumericStrings.h8
-rw-r--r--JavaScriptCore/runtime/ObjectPrototype.cpp2
-rw-r--r--JavaScriptCore/runtime/Operations.h26
-rw-r--r--JavaScriptCore/runtime/PropertyMapHashTable.h6
-rw-r--r--JavaScriptCore/runtime/PropertyNameArray.cpp8
-rw-r--r--JavaScriptCore/runtime/PropertyNameArray.h8
-rw-r--r--JavaScriptCore/runtime/RegExp.cpp20
-rw-r--r--JavaScriptCore/runtime/RegExpCache.cpp6
-rw-r--r--JavaScriptCore/runtime/RegExpCache.h2
-rw-r--r--JavaScriptCore/runtime/RegExpConstructor.cpp3
-rw-r--r--JavaScriptCore/runtime/RegExpKey.h21
-rw-r--r--JavaScriptCore/runtime/RegExpObject.cpp3
-rw-r--r--JavaScriptCore/runtime/RegExpPrototype.cpp2
-rw-r--r--JavaScriptCore/runtime/RopeImpl.cpp2
-rw-r--r--JavaScriptCore/runtime/RopeImpl.h6
-rw-r--r--JavaScriptCore/runtime/ScopeChain.cpp2
-rw-r--r--JavaScriptCore/runtime/SmallStrings.cpp12
-rw-r--r--JavaScriptCore/runtime/SmallStrings.h2
-rw-r--r--JavaScriptCore/runtime/StringBuilder.h2
-rw-r--r--JavaScriptCore/runtime/StringConcatenate.h428
-rw-r--r--JavaScriptCore/runtime/StringConstructor.cpp2
-rw-r--r--JavaScriptCore/runtime/StringObject.cpp4
-rw-r--r--JavaScriptCore/runtime/StringPrototype.cpp131
-rw-r--r--JavaScriptCore/runtime/Structure.cpp26
-rw-r--r--JavaScriptCore/runtime/Structure.h12
-rw-r--r--JavaScriptCore/runtime/StructureTransitionTable.h4
-rw-r--r--JavaScriptCore/runtime/SymbolTable.h2
-rw-r--r--JavaScriptCore/runtime/UString.cpp516
-rw-r--r--JavaScriptCore/runtime/UString.h807
-rw-r--r--JavaScriptCore/runtime/UStringImpl.h30
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(&registerAt(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(&registerAt(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