summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore/runtime')
-rw-r--r--JavaScriptCore/runtime/ArrayPrototype.cpp81
-rw-r--r--JavaScriptCore/runtime/Collector.cpp26
-rw-r--r--JavaScriptCore/runtime/Collector.h1
-rw-r--r--JavaScriptCore/runtime/CollectorHeapIterator.h22
-rw-r--r--JavaScriptCore/runtime/CommonIdentifiers.cpp3
-rw-r--r--JavaScriptCore/runtime/CommonIdentifiers.h1
-rw-r--r--JavaScriptCore/runtime/DateConstructor.cpp3
-rw-r--r--JavaScriptCore/runtime/DatePrototype.cpp7
-rw-r--r--JavaScriptCore/runtime/Error.cpp8
-rw-r--r--JavaScriptCore/runtime/ErrorPrototype.cpp5
-rw-r--r--JavaScriptCore/runtime/ExceptionHelpers.cpp7
-rw-r--r--JavaScriptCore/runtime/ExceptionHelpers.h1
-rw-r--r--JavaScriptCore/runtime/Executable.cpp2
-rw-r--r--JavaScriptCore/runtime/FunctionConstructor.cpp2
-rw-r--r--JavaScriptCore/runtime/FunctionPrototype.cpp7
-rw-r--r--JavaScriptCore/runtime/Identifier.cpp6
-rw-r--r--JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp26
-rw-r--r--JavaScriptCore/runtime/JSONObject.cpp2
-rw-r--r--JavaScriptCore/runtime/JSPropertyNameIterator.cpp18
-rw-r--r--JavaScriptCore/runtime/JSPropertyNameIterator.h34
-rw-r--r--JavaScriptCore/runtime/JSString.h5
-rw-r--r--JavaScriptCore/runtime/JSStringBuilder.h105
-rw-r--r--JavaScriptCore/runtime/JSValue.cpp4
-rw-r--r--JavaScriptCore/runtime/LiteralParser.cpp2
-rw-r--r--JavaScriptCore/runtime/NumberPrototype.cpp11
-rw-r--r--JavaScriptCore/runtime/ObjectPrototype.cpp3
-rw-r--r--JavaScriptCore/runtime/Operations.cpp7
-rw-r--r--JavaScriptCore/runtime/Operations.h2
-rw-r--r--JavaScriptCore/runtime/PropertyNameArray.cpp2
-rw-r--r--JavaScriptCore/runtime/RegExpPrototype.cpp3
-rw-r--r--JavaScriptCore/runtime/SmallStrings.cpp37
-rw-r--r--JavaScriptCore/runtime/SmallStrings.h1
-rw-r--r--JavaScriptCore/runtime/StringBuilder.h8
-rw-r--r--JavaScriptCore/runtime/StringPrototype.cpp118
-rw-r--r--JavaScriptCore/runtime/Structure.h8
-rw-r--r--JavaScriptCore/runtime/UString.cpp178
-rw-r--r--JavaScriptCore/runtime/UString.h129
-rw-r--r--JavaScriptCore/runtime/UStringImpl.cpp39
-rw-r--r--JavaScriptCore/runtime/UStringImpl.h18
-rw-r--r--JavaScriptCore/runtime/WeakGCPtr.h6
40 files changed, 551 insertions, 397 deletions
diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp
index ce814b2..b64abad 100644
--- a/JavaScriptCore/runtime/ArrayPrototype.cpp
+++ b/JavaScriptCore/runtime/ArrayPrototype.cpp
@@ -28,6 +28,7 @@
#include "CachedCall.h"
#include "Interpreter.h"
#include "JIT.h"
+#include "JSStringBuilder.h"
#include "ObjectPrototype.h"
#include "Lookup.h"
#include "Operations.h"
@@ -182,8 +183,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue
totalSize += str.size();
if (!strBuffer.data()) {
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
+ throwOutOfMemoryError(exec);
}
if (exec->hadException())
@@ -195,7 +195,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue
Vector<UChar> buffer;
buffer.reserveCapacity(totalSize);
if (!buffer.data())
- return throwError(exec, GeneralError, "Out of memory");
+ return throwOutOfMemoryError(exec);
for (unsigned i = 0; i < length; i++) {
if (i)
@@ -223,42 +223,28 @@ JSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, J
if (alreadyVisited)
return jsEmptyString(exec); // return an empty string, avoding infinite recursion.
- Vector<UChar, 256> strBuffer;
+ JSStringBuilder strBuffer;
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
for (unsigned k = 0; k < length; k++) {
if (k >= 1)
strBuffer.append(',');
- if (!strBuffer.data()) {
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
- break;
- }
JSValue element = thisObj->get(exec, k);
- if (element.isUndefinedOrNull())
- continue;
-
- JSObject* o = element.toObject(exec);
- JSValue conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);
- UString str;
- CallData callData;
- CallType callType = conversionFunction.getCallData(callData);
- if (callType != CallTypeNone)
- str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec);
- else
- str = element.toString(exec);
- strBuffer.append(str.data(), str.size());
-
- if (!strBuffer.data()) {
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
+ if (!element.isUndefinedOrNull()) {
+ JSObject* o = element.toObject(exec);
+ JSValue conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);
+ UString str;
+ CallData callData;
+ CallType callType = conversionFunction.getCallData(callData);
+ if (callType != CallTypeNone)
+ str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec);
+ else
+ str = element.toString(exec);
+ strBuffer.append(str);
}
-
- if (exec->hadException())
- break;
}
arrayVisitedElements.remove(thisObj);
- return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
+ return strBuffer.build(exec);
}
JSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
@@ -275,38 +261,27 @@ JSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue thi
if (alreadyVisited)
return jsEmptyString(exec); // return an empty string, avoding infinite recursion.
- Vector<UChar, 256> strBuffer;
+ JSStringBuilder strBuffer;
- UChar comma = ',';
- UString separator = args.at(0).isUndefined() ? UString(&comma, 1) : args.at(0).toString(exec);
+ UString separator;
+ if (!args.at(0).isUndefined())
+ separator = args.at(0).toString(exec);
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
for (unsigned k = 0; k < length; k++) {
- if (k >= 1)
- strBuffer.append(separator.data(), separator.size());
- if (!strBuffer.data()) {
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
- break;
+ if (k >= 1) {
+ if (separator.isNull())
+ strBuffer.append(',');
+ else
+ strBuffer.append(separator);
}
JSValue element = thisObj->get(exec, k);
- if (element.isUndefinedOrNull())
- continue;
-
- UString str = element.toString(exec);
- strBuffer.append(str.data(), str.size());
-
- if (!strBuffer.data()) {
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
- }
-
- if (exec->hadException())
- break;
+ if (!element.isUndefinedOrNull())
+ strBuffer.append(element.toString(exec));
}
arrayVisitedElements.remove(thisObj);
- return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
+ return strBuffer.build(exec);
}
JSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
diff --git a/JavaScriptCore/runtime/Collector.cpp b/JavaScriptCore/runtime/Collector.cpp
index 63139a2..2873e0b 100644
--- a/JavaScriptCore/runtime/Collector.cpp
+++ b/JavaScriptCore/runtime/Collector.cpp
@@ -1122,12 +1122,15 @@ void Heap::markRoots()
MarkedArgumentBuffer::markLists(markStack, *m_markListSet);
if (m_globalData->exception)
markStack.append(m_globalData->exception);
- m_globalData->smallStrings.markChildren(markStack);
if (m_globalData->functionCodeBlockBeingReparsed)
m_globalData->functionCodeBlockBeingReparsed->markAggregate(markStack);
if (m_globalData->firstStringifierToMark)
JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark);
+ // Mark the small strings cache last, since it will clear itself if nothing
+ // else has marked it.
+ m_globalData->smallStrings.markChildren(markStack);
+
markStack.drain();
markStack.compact();
@@ -1197,12 +1200,13 @@ static const char* typeName(JSCell* cell)
return "number";
#endif
if (cell->isGetterSetter())
- return "gettersetter";
+ return "Getter-Setter";
if (cell->isAPIValueWrapper())
- return "value wrapper";
+ return "API wrapper";
if (cell->isPropertyNameIterator())
- return "for-in iterator";
- ASSERT(cell->isObject());
+ return "For-in iterator";
+ if (!cell->isObject())
+ return "[empty cell]";
const ClassInfo* info = cell->classInfo();
return info ? info->className : "Object";
}
@@ -1218,6 +1222,18 @@ HashCountedSet<const char*>* Heap::protectedObjectTypeCounts()
return counts;
}
+HashCountedSet<const char*>* Heap::objectTypeCounts()
+{
+ HashCountedSet<const char*>* counts = new HashCountedSet<const char*>;
+
+ LiveObjectIterator it = primaryHeapBegin();
+ LiveObjectIterator heapEnd = primaryHeapEnd();
+ for ( ; it != heapEnd; ++it)
+ counts->add(typeName(*it));
+
+ return counts;
+}
+
bool Heap::isBusy()
{
return m_heap.operationInProgress != NoOperation;
diff --git a/JavaScriptCore/runtime/Collector.h b/JavaScriptCore/runtime/Collector.h
index 7f7a679..82aa8a1 100644
--- a/JavaScriptCore/runtime/Collector.h
+++ b/JavaScriptCore/runtime/Collector.h
@@ -100,6 +100,7 @@ namespace JSC {
size_t protectedObjectCount();
size_t protectedGlobalObjectCount();
HashCountedSet<const char*>* protectedObjectTypeCounts();
+ HashCountedSet<const char*>* objectTypeCounts();
void registerThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
diff --git a/JavaScriptCore/runtime/CollectorHeapIterator.h b/JavaScriptCore/runtime/CollectorHeapIterator.h
index e4f2f91..be6f3c9 100644
--- a/JavaScriptCore/runtime/CollectorHeapIterator.h
+++ b/JavaScriptCore/runtime/CollectorHeapIterator.h
@@ -38,7 +38,7 @@ namespace JSC {
protected:
CollectorHeapIterator(CollectorHeap&, size_t startBlock, size_t startCell);
- void advance(size_t cellsPerBlock);
+ void advance(size_t max);
CollectorHeap& m_heap;
size_t m_block;
@@ -80,10 +80,12 @@ namespace JSC {
return reinterpret_cast<JSCell*>(m_heap.blocks[m_block]->cells + m_cell);
}
- inline void CollectorHeapIterator::advance(size_t cellsPerBlock)
+ // Iterators advance up to the next-to-last -- and not the last -- cell in a
+ // block, since the last cell is a dummy sentinel.
+ inline void CollectorHeapIterator::advance(size_t max)
{
++m_cell;
- if (m_cell == cellsPerBlock) {
+ if (m_cell == max) {
m_cell = 0;
++m_block;
}
@@ -97,14 +99,12 @@ namespace JSC {
inline LiveObjectIterator& LiveObjectIterator::operator++()
{
- if (m_block < m_heap.nextBlock || m_cell < m_heap.nextCell) {
- advance(HeapConstants::cellsPerBlock);
+ advance(HeapConstants::cellsPerBlock - 1);
+ if (m_block < m_heap.nextBlock || (m_block == m_heap.nextBlock && m_cell < m_heap.nextCell))
return *this;
- }
- do {
- advance(HeapConstants::cellsPerBlock);
- } while (m_block < m_heap.usedBlocks && !m_heap.blocks[m_block]->marked.get(m_cell));
+ while (m_block < m_heap.usedBlocks && !m_heap.blocks[m_block]->marked.get(m_cell))
+ advance(HeapConstants::cellsPerBlock - 1);
return *this;
}
@@ -117,7 +117,7 @@ namespace JSC {
inline DeadObjectIterator& DeadObjectIterator::operator++()
{
do {
- advance(HeapConstants::cellsPerBlock);
+ advance(HeapConstants::cellsPerBlock - 1);
ASSERT(m_block > m_heap.nextBlock || (m_block == m_heap.nextBlock && m_cell >= m_heap.nextCell));
} while (m_block < m_heap.usedBlocks && m_heap.blocks[m_block]->marked.get(m_cell));
return *this;
@@ -131,7 +131,7 @@ namespace JSC {
inline ObjectIterator& ObjectIterator::operator++()
{
- advance(HeapConstants::cellsPerBlock);
+ advance(HeapConstants::cellsPerBlock - 1);
return *this;
}
diff --git a/JavaScriptCore/runtime/CommonIdentifiers.cpp b/JavaScriptCore/runtime/CommonIdentifiers.cpp
index 3837817..ed5e304 100644
--- a/JavaScriptCore/runtime/CommonIdentifiers.cpp
+++ b/JavaScriptCore/runtime/CommonIdentifiers.cpp
@@ -28,8 +28,7 @@ static const char* const nullCString = 0;
#define INITIALIZE_PROPERTY_NAME(name) , name(globalData, #name)
CommonIdentifiers::CommonIdentifiers(JSGlobalData* globalData)
- : nullIdentifier(globalData, nullCString)
- , emptyIdentifier(globalData, "")
+ : emptyIdentifier(globalData, "")
, underscoreProto(globalData, "__proto__")
, thisIdentifier(globalData, "this")
JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PROPERTY_NAME)
diff --git a/JavaScriptCore/runtime/CommonIdentifiers.h b/JavaScriptCore/runtime/CommonIdentifiers.h
index de24f4a..0a3d774 100644
--- a/JavaScriptCore/runtime/CommonIdentifiers.h
+++ b/JavaScriptCore/runtime/CommonIdentifiers.h
@@ -90,7 +90,6 @@ namespace JSC {
friend class JSGlobalData;
public:
- const Identifier nullIdentifier;
const Identifier emptyIdentifier;
const Identifier underscoreProto;
const Identifier thisIdentifier;
diff --git a/JavaScriptCore/runtime/DateConstructor.cpp b/JavaScriptCore/runtime/DateConstructor.cpp
index e9a5c29..ab95d06 100644
--- a/JavaScriptCore/runtime/DateConstructor.cpp
+++ b/JavaScriptCore/runtime/DateConstructor.cpp
@@ -28,6 +28,7 @@
#include "JSFunction.h"
#include "JSGlobalObject.h"
#include "JSString.h"
+#include "JSStringBuilder.h"
#include "ObjectPrototype.h"
#include "PrototypeFunction.h"
#include <math.h>
@@ -137,7 +138,7 @@ static JSValue JSC_HOST_CALL callDate(ExecState* exec, JSObject*, JSValue, const
DateConversionBuffer time;
formatDate(ts, date);
formatTime(ts, time);
- return jsNontrivialString(exec, makeString(date, " ", time));
+ return jsMakeNontrivialString(exec, date, " ", time);
}
CallType DateConstructor::getCallData(CallData& callData)
diff --git a/JavaScriptCore/runtime/DatePrototype.cpp b/JavaScriptCore/runtime/DatePrototype.cpp
index ca9d4ea..25b0ac4 100644
--- a/JavaScriptCore/runtime/DatePrototype.cpp
+++ b/JavaScriptCore/runtime/DatePrototype.cpp
@@ -26,6 +26,7 @@
#include "DateConversion.h"
#include "Error.h"
#include "JSString.h"
+#include "JSStringBuilder.h"
#include "ObjectPrototype.h"
#include "DateInstance.h"
@@ -427,7 +428,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec, JSObject*, JSValue
DateConversionBuffer time;
formatDate(*gregorianDateTime, date);
formatTime(*gregorianDateTime, time);
- return jsNontrivialString(exec, makeString(date, " ", time));
+ return jsMakeNontrivialString(exec, date, " ", time);
}
JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
@@ -444,7 +445,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSVal
DateConversionBuffer time;
formatDateUTCVariant(*gregorianDateTime, date);
formatTimeUTC(*gregorianDateTime, time);
- return jsNontrivialString(exec, makeString(date, " ", time));
+ return jsMakeNontrivialString(exec, date, " ", time);
}
JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
@@ -570,7 +571,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSVal
DateConversionBuffer time;
formatDateUTCVariant(*gregorianDateTime, date);
formatTimeUTC(*gregorianDateTime, time);
- return jsNontrivialString(exec, makeString(date, " ", time));
+ return jsMakeNontrivialString(exec, date, " ", time);
}
JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
diff --git a/JavaScriptCore/runtime/Error.cpp b/JavaScriptCore/runtime/Error.cpp
index ddd4bc4..69464b7 100644
--- a/JavaScriptCore/runtime/Error.cpp
+++ b/JavaScriptCore/runtime/Error.cpp
@@ -94,7 +94,7 @@ JSObject* Error::create(ExecState* exec, ErrorType type, const UString& message,
JSObject* Error::create(ExecState* exec, ErrorType type, const char* message)
{
- return create(exec, type, message, -1, -1, NULL);
+ return create(exec, type, message, -1, -1, UString());
}
JSObject* throwError(ExecState* exec, JSObject* error)
@@ -105,21 +105,21 @@ JSObject* throwError(ExecState* exec, JSObject* error)
JSObject* throwError(ExecState* exec, ErrorType type)
{
- JSObject* error = Error::create(exec, type, UString(), -1, -1, NULL);
+ JSObject* error = Error::create(exec, type, UString(), -1, -1, UString());
exec->setException(error);
return error;
}
JSObject* throwError(ExecState* exec, ErrorType type, const UString& message)
{
- JSObject* error = Error::create(exec, type, message, -1, -1, NULL);
+ JSObject* error = Error::create(exec, type, message, -1, -1, UString());
exec->setException(error);
return error;
}
JSObject* throwError(ExecState* exec, ErrorType type, const char* message)
{
- JSObject* error = Error::create(exec, type, message, -1, -1, NULL);
+ JSObject* error = Error::create(exec, type, message, -1, -1, UString());
exec->setException(error);
return error;
}
diff --git a/JavaScriptCore/runtime/ErrorPrototype.cpp b/JavaScriptCore/runtime/ErrorPrototype.cpp
index be9e4b8..eb35733 100644
--- a/JavaScriptCore/runtime/ErrorPrototype.cpp
+++ b/JavaScriptCore/runtime/ErrorPrototype.cpp
@@ -23,6 +23,7 @@
#include "JSFunction.h"
#include "JSString.h"
+#include "JSStringBuilder.h"
#include "ObjectPrototype.h"
#include "PrototypeFunction.h"
#include "UString.h"
@@ -55,11 +56,11 @@ JSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec, JSObject*, JSValue
if (!name.isUndefined()) {
if (!message.isUndefined())
- return jsNontrivialString(exec, makeString(name.toString(exec), ": ", message.toString(exec)));
+ return jsMakeNontrivialString(exec, name.toString(exec), ": ", message.toString(exec));
return jsNontrivialString(exec, name.toString(exec));
}
if (!message.isUndefined())
- return jsNontrivialString(exec, makeString("Error: ", message.toString(exec)));
+ return jsMakeNontrivialString(exec, "Error: ", message.toString(exec));
return jsNontrivialString(exec, "Error");
}
diff --git a/JavaScriptCore/runtime/ExceptionHelpers.cpp b/JavaScriptCore/runtime/ExceptionHelpers.cpp
index 9bb740e..b9c6319 100644
--- a/JavaScriptCore/runtime/ExceptionHelpers.cpp
+++ b/JavaScriptCore/runtime/ExceptionHelpers.cpp
@@ -58,7 +58,7 @@ JSValue createInterruptedExecutionException(JSGlobalData* globalData)
static JSValue createError(ExecState* exec, ErrorType e, const char* msg)
{
- return Error::create(exec, e, msg, -1, -1, 0);
+ return Error::create(exec, e, msg, -1, -1, UString());
}
JSValue createStackOverflowError(ExecState* exec)
@@ -188,4 +188,9 @@ JSObject* createNotAnObjectError(ExecState* exec, JSNotAnObjectErrorStub* error,
return exception;
}
+JSValue throwOutOfMemoryError(ExecState* exec)
+{
+ return throwError(exec, GeneralError, "Out of memory");
+}
+
} // namespace JSC
diff --git a/JavaScriptCore/runtime/ExceptionHelpers.h b/JavaScriptCore/runtime/ExceptionHelpers.h
index e739d09..b6e7373 100644
--- a/JavaScriptCore/runtime/ExceptionHelpers.h
+++ b/JavaScriptCore/runtime/ExceptionHelpers.h
@@ -51,6 +51,7 @@ namespace JSC {
JSObject* createNotAConstructorError(ExecState*, JSValue, unsigned bytecodeOffset, CodeBlock*);
JSValue createNotAFunctionError(ExecState*, JSValue, unsigned bytecodeOffset, CodeBlock*);
JSObject* createNotAnObjectError(ExecState*, JSNotAnObjectErrorStub*, unsigned bytecodeOffset, CodeBlock*);
+ JSValue throwOutOfMemoryError(ExecState*);
} // namespace JSC
diff --git a/JavaScriptCore/runtime/Executable.cpp b/JavaScriptCore/runtime/Executable.cpp
index bc18cc9..79900dc 100644
--- a/JavaScriptCore/runtime/Executable.cpp
+++ b/JavaScriptCore/runtime/Executable.cpp
@@ -272,7 +272,7 @@ UString FunctionExecutable::paramString() const
builder.append(", ");
builder.append(parameters[pos].ustring());
}
- return builder.release();
+ return builder.build();
}
};
diff --git a/JavaScriptCore/runtime/FunctionConstructor.cpp b/JavaScriptCore/runtime/FunctionConstructor.cpp
index 9d55dd1..9b0b1bb 100644
--- a/JavaScriptCore/runtime/FunctionConstructor.cpp
+++ b/JavaScriptCore/runtime/FunctionConstructor.cpp
@@ -89,7 +89,7 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi
builder.append(") { ");
builder.append(args.at(args.size() - 1).toString(exec));
builder.append("\n})");
- program = builder.release();
+ program = builder.build();
}
int errLine;
diff --git a/JavaScriptCore/runtime/FunctionPrototype.cpp b/JavaScriptCore/runtime/FunctionPrototype.cpp
index f08bd5e..3475f08 100644
--- a/JavaScriptCore/runtime/FunctionPrototype.cpp
+++ b/JavaScriptCore/runtime/FunctionPrototype.cpp
@@ -25,6 +25,7 @@
#include "JSArray.h"
#include "JSFunction.h"
#include "JSString.h"
+#include "JSStringBuilder.h"
#include "Interpreter.h"
#include "Lexer.h"
#include "PrototypeFunction.h"
@@ -38,7 +39,7 @@ static JSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*, JSObject*, JSVal
static JSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*, JSObject*, JSValue, const ArgList&);
FunctionPrototype::FunctionPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure)
- : InternalFunction(&exec->globalData(), structure, exec->propertyNames().nullIdentifier)
+ : InternalFunction(&exec->globalData(), structure, exec->propertyNames().emptyIdentifier)
{
putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum);
}
@@ -90,13 +91,13 @@ JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec, JSObject*, JSVa
FunctionExecutable* executable = function->jsExecutable();
UString sourceString = executable->source().toString();
insertSemicolonIfNeeded(sourceString);
- return jsString(exec, makeString("function ", function->name(exec), "(", executable->paramString(), ") ", sourceString));
+ return jsMakeNontrivialString(exec, "function ", function->name(exec), "(", executable->paramString(), ") ", sourceString);
}
}
if (thisValue.inherits(&InternalFunction::info)) {
InternalFunction* function = asInternalFunction(thisValue);
- return jsString(exec, makeString("function ", function->name(exec), "() {\n [native code]\n}"));
+ return jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n [native code]\n}");
}
return throwError(exec, TypeError);
diff --git a/JavaScriptCore/runtime/Identifier.cpp b/JavaScriptCore/runtime/Identifier.cpp
index 747c4ac..97929e2 100644
--- a/JavaScriptCore/runtime/Identifier.cpp
+++ b/JavaScriptCore/runtime/Identifier.cpp
@@ -123,10 +123,8 @@ struct CStringTranslator {
PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c)
{
- if (!c) {
- UString::Rep::null().hash();
- return &UString::Rep::null();
- }
+ ASSERT(c);
+
if (!c[0]) {
UString::Rep::empty().hash();
return &UString::Rep::empty();
diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
index 0bc1274..3ddac7c 100644
--- a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
+++ b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
@@ -30,11 +30,11 @@
#include "Interpreter.h"
#include "JSGlobalObject.h"
#include "JSString.h"
+#include "JSStringBuilder.h"
#include "Lexer.h"
#include "LiteralParser.h"
#include "Nodes.h"
#include "Parser.h"
-#include "StringBuilder.h"
#include "StringExtras.h"
#include "dtoa.h"
#include <stdio.h>
@@ -57,7 +57,7 @@ static JSValue encode(ExecState* exec, const ArgList& args, const char* doNotEsc
if (!cstr.c_str())
return throwError(exec, URIError, "String contained an illegal UTF-16 sequence.");
- StringBuilder builder;
+ JSStringBuilder builder;
const char* p = cstr.c_str();
for (size_t k = 0; k < cstr.size(); k++, p++) {
char c = *p;
@@ -66,15 +66,15 @@ static JSValue encode(ExecState* exec, const ArgList& args, const char* doNotEsc
else {
char tmp[4];
snprintf(tmp, 4, "%%%02X", static_cast<unsigned char>(c));
- builder.append((const char*)tmp);
+ builder.append(tmp);
}
}
- return jsString(exec, builder.release());
+ return builder.build(exec);
}
static JSValue decode(ExecState* exec, const ArgList& args, const char* doNotUnescape, bool strict)
{
- StringBuilder builder;
+ JSStringBuilder builder;
UString str = args.at(0).toString(exec);
int k = 0;
int len = str.size();
@@ -135,7 +135,7 @@ static JSValue decode(ExecState* exec, const ArgList& args, const char* doNotUne
k++;
builder.append(c);
}
- return jsString(exec, builder.release());
+ return builder.build(exec);
}
bool isStrWhiteSpace(UChar c)
@@ -378,8 +378,7 @@ JSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec, JSObject*, JSValue, cons
"0123456789"
"*+-./@_";
- StringBuilder builder;
- UString s;
+ JSStringBuilder builder;
UString str = args.at(0).toString(exec);
const UChar* c = str.data();
for (int k = 0; k < str.size(); k++, c++) {
@@ -387,18 +386,17 @@ JSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec, JSObject*, JSValue, cons
if (u > 255) {
char tmp[7];
sprintf(tmp, "%%u%04X", u);
- s = UString(tmp);
+ builder.append(tmp);
} else if (u != 0 && strchr(do_not_escape, static_cast<char>(u)))
- s = UString(c, 1);
+ builder.append(c, 1);
else {
char tmp[4];
sprintf(tmp, "%%%02X", u);
- s = UString(tmp);
+ builder.append(tmp);
}
- builder.append(s);
}
- return jsString(exec, builder.release());
+ return builder.build(exec);
}
JSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec, JSObject*, JSValue, const ArgList& args)
@@ -425,7 +423,7 @@ JSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec, JSObject*, JSValue, co
builder.append(*c);
}
- return jsString(exec, builder.release());
+ return jsString(exec, builder.build());
}
#ifndef NDEBUG
diff --git a/JavaScriptCore/runtime/JSONObject.cpp b/JavaScriptCore/runtime/JSONObject.cpp
index ce0dcff..acd9280 100644
--- a/JavaScriptCore/runtime/JSONObject.cpp
+++ b/JavaScriptCore/runtime/JSONObject.cpp
@@ -268,7 +268,7 @@ JSValue Stringifier::stringify(JSValue value)
if (m_exec->hadException())
return jsNull();
- return jsString(m_exec, result.release());
+ return jsString(m_exec, result.build());
}
void Stringifier::appendQuotedString(StringBuilder& builder, const UString& value)
diff --git a/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
index d3dcb83..a5d4da0 100644
--- a/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
+++ b/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
@@ -35,6 +35,24 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator);
+inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlots)
+ : JSCell(exec->globalData().propertyNameIteratorStructure.get())
+ , m_cachedStructure(0)
+ , m_numCacheableSlots(numCacheableSlots)
+ , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size())
+ , m_jsStrings(new JSValue[m_jsStringsSize])
+{
+ PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArrayData->propertyNameVector();
+ for (size_t i = 0; i < m_jsStringsSize; ++i)
+ m_jsStrings[i] = jsOwnedString(exec, propertyNameVector[i].ustring());
+}
+
+JSPropertyNameIterator::~JSPropertyNameIterator()
+{
+ if (m_cachedStructure)
+ m_cachedStructure->clearEnumerationCache(this);
+}
+
JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject* o)
{
ASSERT(!o->structure()->enumerationCache() ||
diff --git a/JavaScriptCore/runtime/JSPropertyNameIterator.h b/JavaScriptCore/runtime/JSPropertyNameIterator.h
index d18c2c5..3f533a0 100644
--- a/JavaScriptCore/runtime/JSPropertyNameIterator.h
+++ b/JavaScriptCore/runtime/JSPropertyNameIterator.h
@@ -49,6 +49,8 @@ namespace JSC {
{
return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren), AnonymousSlotCount);
}
+
+ virtual ~JSPropertyNameIterator();
virtual bool isPropertyNameIterator() const { return true; }
@@ -81,23 +83,21 @@ namespace JSC {
OwnArrayPtr<JSValue> m_jsStrings;
};
-inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlots)
- : JSCell(exec->globalData().propertyNameIteratorStructure.get())
- , m_cachedStructure(0)
- , m_numCacheableSlots(numCacheableSlots)
- , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size())
- , m_jsStrings(new JSValue[m_jsStringsSize])
-{
- PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArrayData->propertyNameVector();
- for (size_t i = 0; i < m_jsStringsSize; ++i)
- m_jsStrings[i] = jsOwnedString(exec, propertyNameVector[i].ustring());
-}
-
-inline void Structure::setEnumerationCache(JSPropertyNameIterator* enumerationCache)
-{
- ASSERT(!isDictionary());
- m_enumerationCache = enumerationCache;
-}
+ inline void Structure::setEnumerationCache(JSPropertyNameIterator* enumerationCache)
+ {
+ ASSERT(!isDictionary());
+ m_enumerationCache = enumerationCache;
+ }
+
+ inline void Structure::clearEnumerationCache(JSPropertyNameIterator* enumerationCache)
+ {
+ m_enumerationCache.clear(enumerationCache);
+ }
+
+ inline JSPropertyNameIterator* Structure::enumerationCache()
+ {
+ return m_enumerationCache.get();
+ }
} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSString.h b/JavaScriptCore/runtime/JSString.h
index af03025..cff8e3a 100644
--- a/JavaScriptCore/runtime/JSString.h
+++ b/JavaScriptCore/runtime/JSString.h
@@ -283,8 +283,9 @@ namespace JSC {
}
const UString tryGetValue() const
{
- if (isRope())
- UString();
+ // If this is a rope, m_value should be null -
+ // if this is not a rope, m_value should be non-null.
+ ASSERT(isRope() == m_value.isNull());
return m_value;
}
unsigned length() { return m_stringLength; }
diff --git a/JavaScriptCore/runtime/JSStringBuilder.h b/JavaScriptCore/runtime/JSStringBuilder.h
new file mode 100644
index 0000000..2b11736
--- /dev/null
+++ b/JavaScriptCore/runtime/JSStringBuilder.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSStringBuilder_h
+#define JSStringBuilder_h
+
+#include "ExceptionHelpers.h"
+#include "JSString.h"
+#include "StringBuilder.h"
+
+namespace JSC {
+
+class JSStringBuilder : public StringBuilder {
+public:
+ JSValue build(ExecState* exec)
+ {
+ buffer.shrinkToFit();
+ if (!buffer.data())
+ return throwOutOfMemoryError(exec);
+ return jsString(exec, UString::adopt(buffer));
+ }
+
+private:
+ // Make attempts to call this compile error - if you only wanted a UString,
+ // Why didn't you just use a StringBuilder?! (This may change, maybe at some
+ // point in the future we'll need to start building a string not knowing whether
+ // we'll want a UString or a JSValue - but until we have this requirement,
+ // block this).
+ UString build()
+ {
+ ASSERT_NOT_REACHED();
+ return StringBuilder::build();
+ }
+};
+
+template<typename StringType1, typename StringType2>
+inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2)
+{
+ PassRefPtr<UStringImpl> result = tryMakeString(string1, string2);
+ if (!result)
+ return throwOutOfMemoryError(exec);
+ return jsNontrivialString(exec, result);
+}
+
+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);
+ if (!result)
+ return throwOutOfMemoryError(exec);
+ return jsNontrivialString(exec, result);
+}
+
+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);
+ if (!result)
+ return throwOutOfMemoryError(exec);
+ return jsNontrivialString(exec, result);
+}
+
+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);
+ if (!result)
+ return throwOutOfMemoryError(exec);
+ return jsNontrivialString(exec, result);
+}
+
+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);
+ if (!result)
+ return throwOutOfMemoryError(exec);
+ return jsNontrivialString(exec, result);
+}
+
+}
+
+#endif
diff --git a/JavaScriptCore/runtime/JSValue.cpp b/JavaScriptCore/runtime/JSValue.cpp
index 699c1cd..502312c 100644
--- a/JavaScriptCore/runtime/JSValue.cpp
+++ b/JavaScriptCore/runtime/JSValue.cpp
@@ -174,7 +174,11 @@ uint32_t toUInt32SlowCase(double d, bool& ok)
NEVER_INLINE double nonInlineNaN()
{
+#if OS(SYMBIAN)
+ return nanval();
+#else
return std::numeric_limits<double>::quiet_NaN();
+#endif
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/LiteralParser.cpp b/JavaScriptCore/runtime/LiteralParser.cpp
index aa1e5ed..cc33bae 100644
--- a/JavaScriptCore/runtime/LiteralParser.cpp
+++ b/JavaScriptCore/runtime/LiteralParser.cpp
@@ -200,7 +200,7 @@ template <LiteralParser::ParserMode mode> inline LiteralParser::TokenType Litera
if (m_ptr >= m_end || *m_ptr != '"')
return TokError;
- token.stringToken = builder.release();
+ token.stringToken = builder.build();
token.type = TokString;
token.end = ++m_ptr;
return TokString;
diff --git a/JavaScriptCore/runtime/NumberPrototype.cpp b/JavaScriptCore/runtime/NumberPrototype.cpp
index 67210fa..fa32b86 100644
--- a/JavaScriptCore/runtime/NumberPrototype.cpp
+++ b/JavaScriptCore/runtime/NumberPrototype.cpp
@@ -25,6 +25,7 @@
#include "Error.h"
#include "JSFunction.h"
#include "JSString.h"
+#include "JSStringBuilder.h"
#include "Operations.h"
#include "PrototypeFunction.h"
#include "StringBuilder.h"
@@ -94,7 +95,7 @@ static UString integerPartNoExp(double d)
builder.append((const char*)(buf.data()));
}
- return builder.release();
+ return builder.build();
}
static UString charSequence(char c, int count)
@@ -262,7 +263,7 @@ JSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValue
for (int i = 0; i < f + 1 - k; i++)
z.append('0');
z.append(m);
- m = z.release();
+ m = z.build();
k = f + 1;
ASSERT(k == m.size());
}
@@ -432,8 +433,8 @@ JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSV
if (m.size() > 1)
m = makeString(m.substr(0, 1), ".", m.substr(1));
if (e >= 0)
- return jsNontrivialString(exec, makeString(s, m, "e+", UString::from(e)));
- return jsNontrivialString(exec, makeString(s, m, "e-", UString::from(-e)));
+ return jsMakeNontrivialString(exec, s, m, "e+", UString::from(e));
+ return jsMakeNontrivialString(exec, s, m, "e-", UString::from(-e));
}
} else {
m = charSequence('0', precision);
@@ -447,7 +448,7 @@ JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSV
return jsString(exec, makeString(s, m.substr(0, e + 1), ".", m.substr(e + 1)));
return jsString(exec, makeString(s, m));
}
- return jsNontrivialString(exec, makeString(s, "0.", charSequence('0', -(e + 1)), m));
+ return jsMakeNontrivialString(exec, s, "0.", charSequence('0', -(e + 1)), m);
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/ObjectPrototype.cpp b/JavaScriptCore/runtime/ObjectPrototype.cpp
index 3065c6d..c32a007 100644
--- a/JavaScriptCore/runtime/ObjectPrototype.cpp
+++ b/JavaScriptCore/runtime/ObjectPrototype.cpp
@@ -24,6 +24,7 @@
#include "Error.h"
#include "JSFunction.h"
#include "JSString.h"
+#include "JSStringBuilder.h"
#include "PrototypeFunction.h"
namespace JSC {
@@ -148,7 +149,7 @@ JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState* exec, JSObject*,
JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- return jsNontrivialString(exec, makeString("[object ", thisValue.toThisObject(exec)->className(), "]"));
+ return jsMakeNontrivialString(exec, "[object ", thisValue.toThisObject(exec)->className(), "]");
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/Operations.cpp b/JavaScriptCore/runtime/Operations.cpp
index 0e1887c..cf236bf 100644
--- a/JavaScriptCore/runtime/Operations.cpp
+++ b/JavaScriptCore/runtime/Operations.cpp
@@ -41,13 +41,6 @@ bool JSValue::strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2)
return strictEqualSlowCaseInline(exec, v1, v2);
}
-NEVER_INLINE JSValue throwOutOfMemoryError(ExecState* exec)
-{
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
- return error;
-}
-
NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2)
{
// exception for the Date exception in defaultValue()
diff --git a/JavaScriptCore/runtime/Operations.h b/JavaScriptCore/runtime/Operations.h
index c3aa0fa..9b27074 100644
--- a/JavaScriptCore/runtime/Operations.h
+++ b/JavaScriptCore/runtime/Operations.h
@@ -22,6 +22,7 @@
#ifndef Operations_h
#define Operations_h
+#include "ExceptionHelpers.h"
#include "Interpreter.h"
#include "JSImmediate.h"
#include "JSNumberCell.h"
@@ -29,7 +30,6 @@
namespace JSC {
- NEVER_INLINE JSValue throwOutOfMemoryError(ExecState*);
NEVER_INLINE JSValue jsAddSlowCase(CallFrame*, JSValue, JSValue);
JSValue jsTypeStringForValue(CallFrame*, JSValue);
bool jsIsObjectType(JSValue);
diff --git a/JavaScriptCore/runtime/PropertyNameArray.cpp b/JavaScriptCore/runtime/PropertyNameArray.cpp
index 5108272..4937b7c 100644
--- a/JavaScriptCore/runtime/PropertyNameArray.cpp
+++ b/JavaScriptCore/runtime/PropertyNameArray.cpp
@@ -30,7 +30,7 @@ static const size_t setThreshold = 20;
void PropertyNameArray::add(UString::Rep* identifier)
{
- ASSERT(identifier == &UString::Rep::null() || identifier == &UString::Rep::empty() || identifier->isIdentifier());
+ ASSERT(identifier == &UString::Rep::empty() || identifier->isIdentifier());
size_t size = m_data->propertyNameVector().size();
if (size < setThreshold) {
diff --git a/JavaScriptCore/runtime/RegExpPrototype.cpp b/JavaScriptCore/runtime/RegExpPrototype.cpp
index 5f9d357..dd5fe02 100644
--- a/JavaScriptCore/runtime/RegExpPrototype.cpp
+++ b/JavaScriptCore/runtime/RegExpPrototype.cpp
@@ -27,6 +27,7 @@
#include "JSFunction.h"
#include "JSObject.h"
#include "JSString.h"
+#include "JSStringBuilder.h"
#include "JSValue.h"
#include "ObjectPrototype.h"
#include "PrototypeFunction.h"
@@ -116,7 +117,7 @@ JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec, JSObject*, JSValu
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 jsNontrivialString(exec, makeString("/", source.size() ? source : UString("(?:)"), postfix));
+ return jsMakeNontrivialString(exec, "/", source.size() ? source : UString("(?:)"), postfix);
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/SmallStrings.cpp b/JavaScriptCore/runtime/SmallStrings.cpp
index ac71735..d9d4377 100644
--- a/JavaScriptCore/runtime/SmallStrings.cpp
+++ b/JavaScriptCore/runtime/SmallStrings.cpp
@@ -34,6 +34,11 @@
namespace JSC {
static const unsigned numCharactersToStore = 0x100;
+static inline bool isMarked(JSString* string)
+{
+ return string && Heap::isCellMarked(string);
+}
+
class SmallStringsStorage : public Noncopyable {
public:
SmallStringsStorage();
@@ -55,13 +60,9 @@ SmallStringsStorage::SmallStringsStorage()
}
SmallStrings::SmallStrings()
- : m_emptyString(0)
- , m_storage(0)
{
COMPILE_ASSERT(numCharactersToStore == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage);
-
- for (unsigned i = 0; i < numCharactersToStore; ++i)
- m_singleCharacterStrings[i] = 0;
+ clear();
}
SmallStrings::~SmallStrings()
@@ -70,6 +71,25 @@ SmallStrings::~SmallStrings()
void SmallStrings::markChildren(MarkStack& markStack)
{
+ /*
+ Our hypothesis is that small strings are very common. So, we cache them
+ to avoid GC churn. However, in cases where this hypothesis turns out to
+ be false -- including the degenerate case where all JavaScript execution
+ has terminated -- we don't want to waste memory.
+
+ To test our hypothesis, we check if any small string has been marked. If
+ so, it's probably reasonable to mark the rest. If not, we clear the cache.
+ */
+
+ bool isAnyStringMarked = isMarked(m_emptyString);
+ for (unsigned i = 0; i < numCharactersToStore && !isAnyStringMarked; ++i)
+ isAnyStringMarked |= isMarked(m_singleCharacterStrings[i]);
+
+ if (!isAnyStringMarked) {
+ clear();
+ return;
+ }
+
if (m_emptyString)
markStack.append(m_emptyString);
for (unsigned i = 0; i < numCharactersToStore; ++i) {
@@ -78,6 +98,13 @@ void SmallStrings::markChildren(MarkStack& markStack)
}
}
+void SmallStrings::clear()
+{
+ m_emptyString = 0;
+ for (unsigned i = 0; i < numCharactersToStore; ++i)
+ m_singleCharacterStrings[i] = 0;
+}
+
unsigned SmallStrings::count() const
{
unsigned count = 0;
diff --git a/JavaScriptCore/runtime/SmallStrings.h b/JavaScriptCore/runtime/SmallStrings.h
index efecbb0..cc11d0a 100644
--- a/JavaScriptCore/runtime/SmallStrings.h
+++ b/JavaScriptCore/runtime/SmallStrings.h
@@ -57,6 +57,7 @@ namespace JSC {
UString::Rep* singleCharacterStringRep(unsigned char character);
void markChildren(MarkStack&);
+ void clear();
unsigned count() const;
diff --git a/JavaScriptCore/runtime/StringBuilder.h b/JavaScriptCore/runtime/StringBuilder.h
index 8e18d37..27dbbd7 100644
--- a/JavaScriptCore/runtime/StringBuilder.h
+++ b/JavaScriptCore/runtime/StringBuilder.h
@@ -39,7 +39,7 @@ public:
void append(const char* str)
{
- buffer.append(str, strlen(str));
+ append(str, strlen(str));
}
void append(const char* str, size_t len)
@@ -66,13 +66,15 @@ public:
UChar operator[](size_t i) const { return buffer.at(i); }
- UString release()
+ UString build()
{
buffer.shrinkToFit();
+ if (buffer.size() && !buffer.data())
+ CRASH();
return UString::adopt(buffer);
}
-private:
+protected:
Vector<UChar, 64> buffer;
};
diff --git a/JavaScriptCore/runtime/StringPrototype.cpp b/JavaScriptCore/runtime/StringPrototype.cpp
index d002e07..8c014ec 100644
--- a/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/JavaScriptCore/runtime/StringPrototype.cpp
@@ -28,6 +28,7 @@
#include "JSGlobalObjectFunctions.h"
#include "JSArray.h"
#include "JSFunction.h"
+#include "JSStringBuilder.h"
#include "ObjectPrototype.h"
#include "Operations.h"
#include "PropertyNameArray.h"
@@ -227,6 +228,86 @@ 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());
}
+struct StringRange {
+public:
+ StringRange(int pos, int len)
+ : position(pos)
+ , length(len)
+ {
+ }
+
+ StringRange()
+ {
+ }
+
+ int position;
+ int length;
+};
+
+JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, JSString* sourceVal, const UString& source, const StringRange* substringRanges, int rangeCount, const UString* separators, int separatorCount);
+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 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)));
+ }
+
+ 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();
+
+ if (totalLength == 0)
+ return jsString(exec, "");
+
+ UChar* buffer;
+ PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(totalLength, buffer);
+ if (!impl)
+ return throwOutOfMemoryError(exec);
+
+ int maxCount = max(rangeCount, separatorCount);
+ 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);
+ bufferPos += substringRanges[i].length;
+ }
+ if (i < separatorCount) {
+ UStringImpl::copyChars(buffer + bufferPos, separators[i].data(), separators[i].size());
+ bufferPos += separators[i].size();
+ }
+ }
+
+ return jsString(exec, impl);
+}
+
+JSValue jsReplaceRange(ExecState* exec, const UString& source, int rangeStart, int rangeLength, const UString& replacement);
+JSValue jsReplaceRange(ExecState* exec, const UString& source, int rangeStart, int rangeLength, const UString& replacement)
+{
+ int replacementLength = replacement.size();
+ int totalLength = source.size() - rangeLength + replacementLength;
+ if (totalLength == 0)
+ return jsString(exec, "");
+
+ UChar* buffer;
+ PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(totalLength, buffer);
+ if (!impl)
+ return throwOutOfMemoryError(exec);
+
+ UStringImpl::copyChars(buffer, source.data(), rangeStart);
+ UStringImpl::copyChars(buffer + rangeStart, replacement.data(), replacementLength);
+ int rangeEnd = rangeStart + rangeLength;
+ UStringImpl::copyChars(buffer + rangeStart + replacementLength, source.data() + rangeEnd, source.size() - rangeEnd);
+
+ return jsString(exec, impl);
+}
+
JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
JSString* sourceVal = thisValue.toThisJSString(exec);
@@ -250,7 +331,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
int lastIndex = 0;
int startPosition = 0;
- Vector<UString::Range, 16> sourceRanges;
+ Vector<StringRange, 16> sourceRanges;
Vector<UString, 16> replacements;
// This is either a loop (if global is set) or a one-way (if not).
@@ -269,7 +350,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
if (matchIndex < 0)
break;
- sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex));
+ sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
int completeMatchStart = ovector[0];
unsigned i = 0;
@@ -311,7 +392,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
if (matchIndex < 0)
break;
- sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex));
+ sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
if (callType != CallTypeNone) {
int completeMatchStart = ovector[0];
@@ -352,10 +433,9 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
return sourceVal;
if (lastIndex < source.size())
- sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex));
+ sourceRanges.append(StringRange(lastIndex, source.size() - lastIndex));
- return jsString(exec, source.spliceSubstringsWithSeparators(sourceRanges.data(), sourceRanges.size(),
- replacements.data(), replacements.size()));
+ return jsSpliceSubstringsWithSeparators(exec, sourceVal, source, sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size());
}
// Not a regular expression, so treat the pattern as a string.
@@ -377,7 +457,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
}
int ovector[2] = { matchPos, matchPos + matchLen };
- return jsString(exec, source.replaceRange(matchPos, matchLen, substituteBackreferences(replacementString, source, ovector, 0)));
+ return jsReplaceRange(exec, source, matchPos, matchLen, substituteBackreferences(replacementString, source, ovector, 0));
}
JSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
@@ -789,62 +869,62 @@ JSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, J
JSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
- return jsNontrivialString(exec, makeString("<big>", s, "</big>"));
+ return jsMakeNontrivialString(exec, "<big>", s, "</big>");
}
JSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
- return jsNontrivialString(exec, makeString("<small>", s, "</small>"));
+ return jsMakeNontrivialString(exec, "<small>", s, "</small>");
}
JSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
- return jsNontrivialString(exec, makeString("<blink>", s, "</blink>"));
+ return jsMakeNontrivialString(exec, "<blink>", s, "</blink>");
}
JSValue JSC_HOST_CALL stringProtoFuncBold(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
- return jsNontrivialString(exec, makeString("<b>", s, "</b>"));
+ return jsMakeNontrivialString(exec, "<b>", s, "</b>");
}
JSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
- return jsString(exec, makeString("<tt>", s, "</tt>"));
+ return jsMakeNontrivialString(exec, "<tt>", s, "</tt>");
}
JSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
- return jsNontrivialString(exec, makeString("<i>", s, "</i>"));
+ return jsMakeNontrivialString(exec, "<i>", s, "</i>");
}
JSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
- return jsNontrivialString(exec, makeString("<strike>", s, "</strike>"));
+ return jsMakeNontrivialString(exec, "<strike>", s, "</strike>");
}
JSValue JSC_HOST_CALL stringProtoFuncSub(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
- return jsNontrivialString(exec, makeString("<sub>", s, "</sub>"));
+ return jsMakeNontrivialString(exec, "<sub>", s, "</sub>");
}
JSValue JSC_HOST_CALL stringProtoFuncSup(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
- return jsNontrivialString(exec, makeString("<sup>", s, "</sup>"));
+ return jsMakeNontrivialString(exec, "<sup>", s, "</sup>");
}
JSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
UString s = thisValue.toThisString(exec);
JSValue a0 = args.at(0);
- return jsNontrivialString(exec, makeString("<font color=\"", a0.toString(exec), "\">", s, "</font>"));
+ return jsMakeNontrivialString(exec, "<font color=\"", a0.toString(exec), "\">", s, "</font>");
}
JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
@@ -886,14 +966,14 @@ JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValu
return jsNontrivialString(exec, impl);
}
- return jsNontrivialString(exec, makeString("<font size=\"", a0.toString(exec), "\">", s, "</font>"));
+ return jsMakeNontrivialString(exec, "<font size=\"", a0.toString(exec), "\">", s, "</font>");
}
JSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
UString s = thisValue.toThisString(exec);
JSValue a0 = args.at(0);
- return jsNontrivialString(exec, makeString("<a name=\"", a0.toString(exec), "\">", s, "</a>"));
+ return jsMakeNontrivialString(exec, "<a name=\"", a0.toString(exec), "\">", s, "</a>");
}
JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
diff --git a/JavaScriptCore/runtime/Structure.h b/JavaScriptCore/runtime/Structure.h
index 1353a5a..95cf94c 100644
--- a/JavaScriptCore/runtime/Structure.h
+++ b/JavaScriptCore/runtime/Structure.h
@@ -36,6 +36,7 @@
#include "StructureTransitionTable.h"
#include "JSTypeInfo.h"
#include "UString.h"
+#include "WeakGCPtr.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
@@ -101,7 +102,7 @@ namespace JSC {
void growPropertyStorageCapacity();
unsigned propertyStorageCapacity() const { return m_propertyStorageCapacity; }
- unsigned propertyStorageSize() const { return m_anonymousSlotCount + (m_propertyTable ? m_propertyTable->keyCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1); }
+ unsigned propertyStorageSize() const { return m_anonymousSlotCount + (m_propertyTable ? m_propertyTable->keyCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : static_cast<unsigned>(m_offset + 1)); }
bool isUsingInlineStorage() const;
size_t get(const Identifier& propertyName);
@@ -135,7 +136,8 @@ namespace JSC {
void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; }
void setEnumerationCache(JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
- JSPropertyNameIterator* enumerationCache() { return m_enumerationCache.get(); }
+ void clearEnumerationCache(JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
+ JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h.
void getPropertyNames(PropertyNameArray&, EnumerationMode mode);
private:
@@ -199,7 +201,7 @@ namespace JSC {
StructureTransitionTable table;
- ProtectedPtr<JSPropertyNameIterator> m_enumerationCache;
+ WeakGCPtr<JSPropertyNameIterator> m_enumerationCache;
PropertyMapHashTable* m_propertyTable;
diff --git a/JavaScriptCore/runtime/UString.cpp b/JavaScriptCore/runtime/UString.cpp
index e75a05c..4a89a23 100644
--- a/JavaScriptCore/runtime/UString.cpp
+++ b/JavaScriptCore/runtime/UString.cpp
@@ -53,7 +53,7 @@ using namespace WTF::Unicode;
using namespace std;
namespace JSC {
-
+
extern const double NaN;
extern const double Inf;
@@ -146,95 +146,46 @@ bool operator==(const CString& c1, const CString& c2)
return len == c2.size() && (len == 0 || memcmp(c1.c_str(), c2.c_str(), len) == 0);
}
-// These static strings are immutable, except for rc, whose initial value is chosen to
+// These static strings are immutable, except for rc, whose initial value is chosen to
// reduce the possibility of it becoming zero due to ref/deref not being thread-safe.
static UChar sharedEmptyChar;
-UStringImpl* UStringImpl::s_null;
UStringImpl* UStringImpl::s_empty;
-UString* UString::nullUString;
+
+UString::Rep* UString::s_nullRep;
+UString* UString::s_nullUString;
void initializeUString()
{
- UStringImpl::s_null = new UStringImpl(0, 0, UStringImpl::ConstructStaticString);
UStringImpl::s_empty = new UStringImpl(&sharedEmptyChar, 0, UStringImpl::ConstructStaticString);
- UString::nullUString = new UString;
-}
-
-static PassRefPtr<UString::Rep> createRep(const char* c)
-{
- if (!c)
- return &UString::Rep::null();
-
- if (!c[0])
- return &UString::Rep::empty();
- size_t length = strlen(c);
- UChar* d;
- PassRefPtr<UStringImpl> result = UStringImpl::tryCreateUninitialized(length, d);
- if (!result)
- return &UString::Rep::null();
-
- 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
- return result;
-}
-
-static inline PassRefPtr<UString::Rep> createRep(const char* c, int length)
-{
- if (!c)
- return &UString::Rep::null();
-
- if (!length)
- return &UString::Rep::empty();
-
- UChar* d;
- PassRefPtr<UStringImpl> result = UStringImpl::tryCreateUninitialized(length, d);
- if (!result)
- return &UString::Rep::null();
-
- for (int i = 0; i < length; i++)
- d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
- return result;
+ UString::s_nullRep = new UStringImpl(0, 0, UStringImpl::ConstructStaticString);
+ UString::s_nullUString = new UString;
}
UString::UString(const char* c)
- : m_rep(createRep(c))
+ : m_rep(Rep::create(c))
{
}
UString::UString(const char* c, int length)
- : m_rep(createRep(c, length))
+ : m_rep(Rep::create(c, length))
{
}
UString::UString(const UChar* c, int length)
{
- if (length == 0)
+ if (length == 0)
m_rep = &Rep::empty();
else
m_rep = Rep::create(c, length);
}
-UString UString::createFromUTF8(const char* string)
-{
- if (!string)
- return null();
-
- size_t length = strlen(string);
- Vector<UChar, 1024> buffer(length);
- UChar* p = buffer.data();
- if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length))
- return null();
-
- return UString(buffer.data(), p - buffer.data());
-}
-
UString UString::from(int i)
{
UChar buf[1 + sizeof(i) * 3];
UChar* end = buf + sizeof(buf) / sizeof(UChar);
UChar* p = end;
-
+
if (i == 0)
*--p = '0';
else if (i == INT_MIN) {
@@ -296,7 +247,7 @@ UString UString::from(unsigned int u)
UChar buf[sizeof(u) * 3];
UChar* end = buf + sizeof(buf) / sizeof(UChar);
UChar* p = end;
-
+
if (u == 0)
*--p = '0';
else {
@@ -305,7 +256,7 @@ UString UString::from(unsigned int u)
u /= 10;
}
}
-
+
return UString(p, static_cast<int>(end - p));
}
@@ -346,71 +297,6 @@ UString UString::from(double d)
return UString(buffer, length);
}
-UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const
-{
- m_rep->checkConsistency();
-
- if (rangeCount == 1 && separatorCount == 0) {
- int thisSize = size();
- int position = substringRanges[0].position;
- int length = substringRanges[0].length;
- if (position <= 0 && length >= thisSize)
- return *this;
- return UString::Rep::create(m_rep, max(0, position), min(thisSize, 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();
-
- if (totalLength == 0)
- return "";
-
- UChar* buffer;
- PassRefPtr<Rep> rep = Rep::tryCreateUninitialized(totalLength, buffer);
- if (!rep)
- return null();
-
- int maxCount = max(rangeCount, separatorCount);
- int bufferPos = 0;
- for (int i = 0; i < maxCount; i++) {
- if (i < rangeCount) {
- UStringImpl::copyChars(buffer + bufferPos, data() + 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();
- }
- }
-
- return rep;
-}
-
-UString UString::replaceRange(int rangeStart, int rangeLength, const UString& replacement) const
-{
- m_rep->checkConsistency();
-
- int replacementLength = replacement.size();
- int totalLength = size() - rangeLength + replacementLength;
- if (totalLength == 0)
- return "";
-
- UChar* buffer;
- PassRefPtr<Rep> rep = Rep::tryCreateUninitialized(totalLength, buffer);
- if (!rep)
- return null();
-
- UStringImpl::copyChars(buffer, data(), rangeStart);
- UStringImpl::copyChars(buffer + rangeStart, replacement.data(), replacementLength);
- int rangeEnd = rangeStart + rangeLength;
- UStringImpl::copyChars(buffer + rangeStart + replacementLength, data() + rangeEnd, size() - rangeEnd);
-
- return rep;
-}
-
bool UString::getCString(CStringBuffer& buffer) const
{
int length = size();
@@ -456,30 +342,6 @@ char* UString::ascii() const
return asciiBuffer;
}
-UString& UString::operator=(const char* c)
-{
- if (!c) {
- m_rep = &Rep::null();
- return *this;
- }
-
- if (!c[0]) {
- m_rep = &Rep::empty();
- return *this;
- }
-
- int l = static_cast<int>(strlen(c));
- UChar* d = 0;
- m_rep = Rep::tryCreateUninitialized(l, d);
- if (m_rep) {
- for (int i = 0; i < l; i++)
- d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
- } else
- makeNull();
-
- return *this;
-}
-
bool UString::is8Bit() const
{
const UChar* u = data();
@@ -721,7 +583,7 @@ int UString::find(UChar ch, int pos) const
if (*c == ch)
return static_cast<int>(c - data());
}
-
+
return -1;
}
@@ -888,16 +750,4 @@ CString UString::UTF8String(bool strict) const
return CString(buffer.data(), p - buffer.data());
}
-// For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X.
-NEVER_INLINE void UString::makeNull()
-{
- m_rep = &Rep::null();
-}
-
-// For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X.
-NEVER_INLINE UString::Rep* UString::nullRep()
-{
- return &Rep::null();
-}
-
} // namespace JSC
diff --git a/JavaScriptCore/runtime/UString.h b/JavaScriptCore/runtime/UString.h
index 0c13689..7d9ec49 100644
--- a/JavaScriptCore/runtime/UString.h
+++ b/JavaScriptCore/runtime/UString.h
@@ -81,7 +81,6 @@ namespace JSC {
typedef UStringImpl Rep;
public:
- // UString constructors passed char*s assume ISO Latin-1 encoding; for UTF8 use 'createFromUTF8', below.
UString();
UString(const char*); // Constructor for null-terminated string.
UString(const char*, int length);
@@ -109,34 +108,12 @@ namespace JSC {
return Rep::adopt(vector);
}
- static UString createFromUTF8(const char*);
-
static UString from(int);
static UString from(long long);
static UString from(unsigned int);
static UString from(long);
static UString from(double);
- struct Range {
- public:
- Range(int pos, int len)
- : position(pos)
- , length(len)
- {
- }
-
- Range()
- {
- }
-
- int position;
- int length;
- };
-
- UString spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const;
-
- UString replaceRange(int rangeStart, int RangeEnd, const UString& replacement) const;
-
bool getCString(CStringBuffer&) const;
// NOTE: This method should only be used for *debugging* purposes as it
@@ -153,11 +130,9 @@ namespace JSC {
*/
CString UTF8String(bool strict = false) const;
- UString& operator=(const char*c);
-
const UChar* data() const { return m_rep->data(); }
- bool isNull() const { return m_rep == &Rep::null(); }
+ bool isNull() const { return m_rep == s_nullRep; }
bool isEmpty() const { return !m_rep->size(); }
bool is8Bit() const;
@@ -183,10 +158,9 @@ namespace JSC {
UString substr(int pos = 0, int len = -1) const;
- static const UString& null() { return *nullUString; }
+ static const UString& null() { return *s_nullUString; }
Rep* rep() const { return m_rep.get(); }
- static Rep* nullRep();
UString(PassRefPtr<Rep> r)
: m_rep(r)
@@ -197,10 +171,10 @@ namespace JSC {
size_t cost() const { return m_rep->cost(); }
private:
- void makeNull();
-
RefPtr<Rep> m_rep;
- static UString* nullUString;
+
+ JS_EXPORTDATA static Rep* s_nullRep;
+ static UString* s_nullUString;
friend void initializeUString();
friend bool operator==(const UString&, const UString&);
@@ -255,7 +229,7 @@ namespace JSC {
int compare(const UString&, const UString&);
inline UString::UString()
- : m_rep(&Rep::null())
+ : m_rep(s_nullRep)
{
}
@@ -354,7 +328,7 @@ namespace JSC {
};
template<typename StringType1, typename StringType2>
- UString makeString(StringType1 string1, StringType2 string2)
+ PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2)
{
StringTypeAdapter<StringType1> adapter1(string1);
StringTypeAdapter<StringType2> adapter2(string2);
@@ -363,7 +337,7 @@ namespace JSC {
unsigned length = adapter1.length() + adapter2.length();
PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
if (!resultImpl)
- return UString();
+ return 0;
UChar* result = buffer;
adapter1.writeTo(result);
@@ -374,7 +348,7 @@ namespace JSC {
}
template<typename StringType1, typename StringType2, typename StringType3>
- UString makeString(StringType1 string1, StringType2 string2, StringType3 string3)
+ PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3)
{
StringTypeAdapter<StringType1> adapter1(string1);
StringTypeAdapter<StringType2> adapter2(string2);
@@ -384,7 +358,7 @@ namespace JSC {
unsigned length = adapter1.length() + adapter2.length() + adapter3.length();
PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
if (!resultImpl)
- return UString();
+ return 0;
UChar* result = buffer;
adapter1.writeTo(result);
@@ -397,7 +371,7 @@ namespace JSC {
}
template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
- UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
+ PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
{
StringTypeAdapter<StringType1> adapter1(string1);
StringTypeAdapter<StringType2> adapter2(string2);
@@ -408,7 +382,7 @@ namespace JSC {
unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length();
PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
if (!resultImpl)
- return UString();
+ return 0;
UChar* result = buffer;
adapter1.writeTo(result);
@@ -423,7 +397,7 @@ namespace JSC {
}
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> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
{
StringTypeAdapter<StringType1> adapter1(string1);
StringTypeAdapter<StringType2> adapter2(string2);
@@ -435,7 +409,7 @@ namespace JSC {
unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length();
PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
if (!resultImpl)
- return UString();
+ return 0;
UChar* result = buffer;
adapter1.writeTo(result);
@@ -452,7 +426,7 @@ namespace JSC {
}
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<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
{
StringTypeAdapter<StringType1> adapter1(string1);
StringTypeAdapter<StringType2> adapter2(string2);
@@ -465,7 +439,7 @@ namespace JSC {
unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length();
PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
if (!resultImpl)
- return UString();
+ return 0;
UChar* result = buffer;
adapter1.writeTo(result);
@@ -484,7 +458,7 @@ namespace JSC {
}
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<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
{
StringTypeAdapter<StringType1> adapter1(string1);
StringTypeAdapter<StringType2> adapter2(string2);
@@ -498,7 +472,7 @@ namespace JSC {
unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length() + adapter7.length();
PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
if (!resultImpl)
- return UString();
+ return 0;
UChar* result = buffer;
adapter1.writeTo(result);
@@ -519,7 +493,7 @@ namespace JSC {
}
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> 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);
@@ -534,7 +508,7 @@ namespace JSC {
unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length() + adapter7.length() + adapter8.length();
PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
if (!resultImpl)
- return UString();
+ return 0;
UChar* result = buffer;
adapter1.writeTo(result);
@@ -556,6 +530,69 @@ namespace JSC {
return resultImpl;
}
+ template<typename StringType1, typename StringType2>
+ UString makeString(StringType1 string1, StringType2 string2)
+ {
+ PassRefPtr<UStringImpl> 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<UStringImpl> 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<UStringImpl> 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<UStringImpl> 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<UStringImpl> 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<UStringImpl> 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<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8);
+ if (!resultImpl)
+ CRASH();
+ return resultImpl;
+ }
+
} // namespace JSC
namespace WTF {
diff --git a/JavaScriptCore/runtime/UStringImpl.cpp b/JavaScriptCore/runtime/UStringImpl.cpp
index 4b0d1c9..9882007 100644
--- a/JavaScriptCore/runtime/UStringImpl.cpp
+++ b/JavaScriptCore/runtime/UStringImpl.cpp
@@ -34,7 +34,44 @@ using namespace WTF::Unicode;
using namespace std;
namespace JSC {
-
+
+PassRefPtr<UStringImpl> UStringImpl::create(const char* c)
+{
+ ASSERT(c);
+
+ if (!c[0])
+ return &UStringImpl::empty();
+
+ size_t length = strlen(c);
+ UChar* d;
+ PassRefPtr<UStringImpl> result = UStringImpl::createUninitialized(length, d);
+ 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
+ return result;
+}
+
+PassRefPtr<UStringImpl> UStringImpl::create(const char* c, int length)
+{
+ ASSERT(c);
+
+ if (!length)
+ return &UStringImpl::empty();
+
+ UChar* d;
+ PassRefPtr<UStringImpl> result = UStringImpl::createUninitialized(length, d);
+ for (int i = 0; i < length; i++)
+ d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
+ return result;
+}
+
+PassRefPtr<UStringImpl> UStringImpl::create(const UChar* buffer, int length)
+{
+ UChar* newBuffer;
+ PassRefPtr<UStringImpl> impl = createUninitialized(length, newBuffer);
+ copyChars(newBuffer, buffer, length);
+ return impl;
+}
+
SharedUChar* UStringImpl::baseSharedBuffer()
{
ASSERT((bufferOwnership() == BufferShared)
diff --git a/JavaScriptCore/runtime/UStringImpl.h b/JavaScriptCore/runtime/UStringImpl.h
index abed637..bbea0aa 100644
--- a/JavaScriptCore/runtime/UStringImpl.h
+++ b/JavaScriptCore/runtime/UStringImpl.h
@@ -87,20 +87,16 @@ public:
template<size_t inlineCapacity>
static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector)
{
- if (unsigned length = vector.size())
+ if (unsigned length = vector.size()) {
+ ASSERT(vector.data());
return adoptRef(new UStringImpl(vector.releaseBuffer(), length, BufferOwned));
+ }
return &empty();
}
- static PassRefPtr<UStringImpl> create(const UChar* buffer, int length)
- {
- UChar* newBuffer;
- if (PassRefPtr<UStringImpl> impl = tryCreateUninitialized(length, newBuffer)) {
- copyChars(newBuffer, buffer, length);
- return impl;
- }
- return &null();
- }
+ static PassRefPtr<UStringImpl> create(const char* c);
+ static PassRefPtr<UStringImpl> create(const char* c, int length);
+ static PassRefPtr<UStringImpl> create(const UChar* buffer, int length);
static PassRefPtr<UStringImpl> create(PassRefPtr<UStringImpl> rep, int offset, int length)
{
@@ -180,7 +176,6 @@ public:
static unsigned computeHash(const char* s, int length) { ASSERT(length >= 0); return WTF::stringHash(s, length); }
static unsigned computeHash(const char* s) { return WTF::stringHash(s); }
- static UStringImpl& null() { return *s_null; }
static UStringImpl& empty() { return *s_empty; }
ALWAYS_INLINE void checkConsistency() const
@@ -288,7 +283,6 @@ private:
mutable unsigned m_isIdentifier : 1;
UntypedPtrAndBitfield m_dataBuffer;
- JS_EXPORTDATA static UStringImpl* s_null;
JS_EXPORTDATA static UStringImpl* s_empty;
friend class JIT;
diff --git a/JavaScriptCore/runtime/WeakGCPtr.h b/JavaScriptCore/runtime/WeakGCPtr.h
index 8653721..3ed4645 100644
--- a/JavaScriptCore/runtime/WeakGCPtr.h
+++ b/JavaScriptCore/runtime/WeakGCPtr.h
@@ -44,7 +44,11 @@ public:
return m_ptr;
}
- void clear() { m_ptr = 0; }
+ void clear(JSCell* ptr)
+ {
+ if (ptr == m_ptr)
+ m_ptr = 0;
+ }
T& operator*() const { return *get(); }
T* operator->() const { return get(); }