Commit 762e2c65 authored by benjamin@webkit.org's avatar benjamin@webkit.org

Improve JSC use of Strings after the UString->String change

https://bugs.webkit.org/show_bug.cgi?id=95633

Patch by Benjamin Poulain <bpoulain@apple.com> on 2012-09-04
Reviewed by Geoffrey Garen.

This patch improve the use of strings in the JSC runtime.

The initialization of Identifier is left for future patches.

The improvements are the following:
-5% faster to raise one of the modified exception.
-3 times faster to execute Boolean::toString()

Most of the changes are just about using the new methods
for string literals.

With the changes, the binary on x86_64 gets 176 bytes smaller.

* API/JSCallbackObjectFunctions.h:
(JSC::::staticFunctionGetter):
(JSC::::callbackGetter):
* API/JSContextRef.cpp:
(JSContextCreateBacktrace):
* API/JSObjectRef.cpp:
(JSObjectMakeFunctionWithCallback):
* bytecode/CodeBlock.cpp:
(JSC::valueToSourceString):
(JSC::CodeBlock::nameForRegister):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::addStackTraceIfNecessary):
* runtime/ArrayConstructor.cpp:
(JSC::constructArrayWithSizeQuirk):
* runtime/ArrayPrototype.cpp:
(JSC::shift):
(JSC::unshift):
(JSC::arrayProtoFuncPop):
(JSC::arrayProtoFuncReverse):
* runtime/BooleanPrototype.cpp:
(JSC::booleanProtoFuncToString): Instead of instanciating new strings, reuse the
keywords available in SmallStrings. Avoiding the creation of the JSString and StringImpl
makes the method significantly faster.

* runtime/DateConversion.cpp:
(JSC::formatDateTime):
* runtime/DatePrototype.cpp:
(JSC::formatLocaleDate):
(JSC::formateDateInstance):
(JSC::dateProtoFuncToISOString):
Change the way we use snprintf() for clarity and performance.

Instead of allocating one extra byte to put a zero "just in case", we use the size returned
by snprintf().
To prevent any overflow from a programming mistake, we explicitely test for overflow and
return an empty string.

(JSC::dateProtoFuncToJSON):
* runtime/Error.cpp:
(JSC::createNotEnoughArgumentsError):
(JSC::throwTypeError):
(JSC::throwSyntaxError):
* runtime/Error.h:
(JSC::StrictModeTypeErrorFunction::create):
* runtime/ErrorPrototype.cpp:
(JSC::ErrorPrototype::finishCreation):
(JSC::errorProtoFuncToString):
Using a null String is correct because (8) uses jsString(), (9) tests for a length of 0.

* runtime/ExceptionHelpers.cpp:
(JSC::InterruptedExecutionError::defaultValue):
(JSC::TerminatedExecutionError::defaultValue):
(JSC::createStackOverflowError):
(JSC::createOutOfMemoryError):
* runtime/Executable.cpp:
(JSC::EvalExecutable::compileInternal):
(JSC::FunctionExecutable::paramString):
* runtime/FunctionConstructor.cpp:
(JSC::constructFunction):
(JSC::constructFunctionSkippingEvalEnabledCheck):
* runtime/FunctionPrototype.h:
(JSC::FunctionPrototype::create):
Using a null String for the name is correct because InternalFunction uses jsString()
to create the name value.

* runtime/InternalFunction.cpp:
(JSC::InternalFunction::finishCreation):
There is no need to create an empty string for a null string, jsString() handle both
cases as empty JSString.

* runtime/JSArray.cpp:
(JSC::reject):
(JSC::SparseArrayValueMap::put):
(JSC::JSArray::put):
(JSC::JSArray::putByIndexBeyondVectorLength):
(JSC::JSArray::putDirectIndexBeyondVectorLength):
(JSC::JSArray::setLength):
(JSC::JSArray::pop):
(JSC::JSArray::push):
* runtime/JSFunction.cpp:
(JSC::JSFunction::finishCreation): Same issue as InternalFunction::finishCreation.

(JSC::JSFunction::callerGetter):
(JSC::JSFunction::defineOwnProperty):
* runtime/JSGlobalData.cpp:
(JSC::enableAssembler): Use CFSTR() instead of CFStringCreateWithCString().
CFStringCreateWithCString() copy the content and may choose to decode the data.
CFSTR() is much more efficient.

* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::reset):
JSFunction uses jsString() to create the name, we can use null strings instead
of creating empty strings.

(JSC::JSGlobalObject::createThrowTypeError): ditto.
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::encode):
(JSC::decode):
(JSC::globalFuncEval):
* runtime/JSONObject.cpp:
(JSC::Stringifier::appendStringifiedValue):
(JSC::Stringifier::Holder::appendNextProperty):
(JSC::JSONProtoFuncParse):
(JSC::JSONProtoFuncStringify):
* runtime/JSObject.cpp:
(JSC::JSObject::put):
(JSC::JSObject::defaultValue):
(JSC::JSObject::hasInstance):
(JSC::JSObject::defineOwnProperty):
* runtime/JSString.cpp:
Return an empty JSString to avoid the creation of a temporary empty String.

(JSC::JSRopeString::getIndexSlowCase):
* runtime/JSString.h:
(JSC): Remove the versions of jsNontrivialString() taking a char*. All the callers
have been replaced by calls using ASCIILiteral.

* runtime/JSValue.cpp:
(JSC::JSValue::putToPrimitive):
* runtime/LiteralParser.cpp:
(JSC::::Lexer::lex):
(JSC::::Lexer::lexString):
(JSC::::Lexer::lexNumber):
(JSC::::parse):
* runtime/LiteralParser.h:
(JSC::LiteralParser::getErrorMessage):
* runtime/NumberPrototype.cpp:
(JSC::numberProtoFuncToExponential):
(JSC::numberProtoFuncToFixed):
(JSC::numberProtoFuncToPrecision):
(JSC::numberProtoFuncToString):
* runtime/ObjectConstructor.cpp:
(JSC::objectConstructorGetPrototypeOf):
(JSC::objectConstructorGetOwnPropertyDescriptor):
(JSC::objectConstructorGetOwnPropertyNames):
(JSC::objectConstructorKeys):
(JSC::toPropertyDescriptor):
(JSC::objectConstructorDefineProperty):
(JSC::objectConstructorDefineProperties):
(JSC::objectConstructorCreate):
(JSC::objectConstructorSeal):
(JSC::objectConstructorFreeze):
(JSC::objectConstructorPreventExtensions):
(JSC::objectConstructorIsSealed):
(JSC::objectConstructorIsFrozen):
(JSC::objectConstructorIsExtensible):
* runtime/ObjectPrototype.cpp:
(JSC::objectProtoFuncDefineGetter):
(JSC::objectProtoFuncDefineSetter):
(JSC::objectProtoFuncToString):
* runtime/RegExpConstructor.cpp:
(JSC::constructRegExp):
* runtime/RegExpObject.cpp:
(JSC::reject):
(JSC::regExpObjectSource):
* runtime/RegExpPrototype.cpp:
(JSC::regExpProtoFuncCompile):
* runtime/StringObject.cpp:
(JSC::StringObject::defineOwnProperty):
* runtime/StringPrototype.cpp:
(JSC::jsSpliceSubstrings):
(JSC::jsSpliceSubstringsWithSeparators):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@127505 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 163e4775
......@@ -568,7 +568,7 @@ JSValue JSCallbackObject<Parent>::staticFunctionGetter(ExecState* exec, JSValue
}
}
return throwError(exec, createReferenceError(exec, "Static function property defined with NULL callAsFunction callback."));
return throwError(exec, createReferenceError(exec, ASCIILiteral("Static function property defined with NULL callAsFunction callback.")));
}
template <class Parent>
......@@ -600,7 +600,7 @@ JSValue JSCallbackObject<Parent>::callbackGetter(ExecState* exec, JSValue slotPa
}
}
return throwError(exec, createReferenceError(exec, "hasProperty callback returned true for a property that doesn't exist."));
return throwError(exec, createReferenceError(exec, ASCIILiteral("hasProperty callback returned true for a property that doesn't exist.")));
}
} // namespace JSC
......@@ -173,9 +173,9 @@ JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize)
if (exec->callee()) {
if (asObject(exec->callee())->inherits(&InternalFunction::s_info)) {
functionName = asInternalFunction(exec->callee())->name(exec);
builder.append("#0 ");
builder.appendLiteral("#0 ");
builder.append(functionName);
builder.append("() ");
builder.appendLiteral("() ");
count++;
}
}
......
......@@ -92,7 +92,7 @@ JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name,
{
ExecState* exec = toJS(ctx);
APIEntryShim entryShim(exec);
return toRef(JSCallbackFunction::create(exec, exec->lexicalGlobalObject(), callAsFunction, name ? name->ustring() : "anonymous"));
return toRef(JSCallbackFunction::create(exec, exec->lexicalGlobalObject(), callAsFunction, name ? name->ustring() : ASCIILiteral("anonymous")));
}
JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
......
2012-09-04 Benjamin Poulain <bpoulain@apple.com>
Improve JSC use of Strings after the UString->String change
https://bugs.webkit.org/show_bug.cgi?id=95633
Reviewed by Geoffrey Garen.
This patch improve the use of strings in the JSC runtime.
The initialization of Identifier is left for future patches.
The improvements are the following:
-5% faster to raise one of the modified exception.
-3 times faster to execute Boolean::toString()
Most of the changes are just about using the new methods
for string literals.
With the changes, the binary on x86_64 gets 176 bytes smaller.
* API/JSCallbackObjectFunctions.h:
(JSC::::staticFunctionGetter):
(JSC::::callbackGetter):
* API/JSContextRef.cpp:
(JSContextCreateBacktrace):
* API/JSObjectRef.cpp:
(JSObjectMakeFunctionWithCallback):
* bytecode/CodeBlock.cpp:
(JSC::valueToSourceString):
(JSC::CodeBlock::nameForRegister):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::addStackTraceIfNecessary):
* runtime/ArrayConstructor.cpp:
(JSC::constructArrayWithSizeQuirk):
* runtime/ArrayPrototype.cpp:
(JSC::shift):
(JSC::unshift):
(JSC::arrayProtoFuncPop):
(JSC::arrayProtoFuncReverse):
* runtime/BooleanPrototype.cpp:
(JSC::booleanProtoFuncToString): Instead of instanciating new strings, reuse the
keywords available in SmallStrings. Avoiding the creation of the JSString and StringImpl
makes the method significantly faster.
* runtime/DateConversion.cpp:
(JSC::formatDateTime):
* runtime/DatePrototype.cpp:
(JSC::formatLocaleDate):
(JSC::formateDateInstance):
(JSC::dateProtoFuncToISOString):
Change the way we use snprintf() for clarity and performance.
Instead of allocating one extra byte to put a zero "just in case", we use the size returned
by snprintf().
To prevent any overflow from a programming mistake, we explicitely test for overflow and
return an empty string.
(JSC::dateProtoFuncToJSON):
* runtime/Error.cpp:
(JSC::createNotEnoughArgumentsError):
(JSC::throwTypeError):
(JSC::throwSyntaxError):
* runtime/Error.h:
(JSC::StrictModeTypeErrorFunction::create):
* runtime/ErrorPrototype.cpp:
(JSC::ErrorPrototype::finishCreation):
(JSC::errorProtoFuncToString):
Using a null String is correct because (8) uses jsString(), (9) tests for a length of 0.
* runtime/ExceptionHelpers.cpp:
(JSC::InterruptedExecutionError::defaultValue):
(JSC::TerminatedExecutionError::defaultValue):
(JSC::createStackOverflowError):
(JSC::createOutOfMemoryError):
* runtime/Executable.cpp:
(JSC::EvalExecutable::compileInternal):
(JSC::FunctionExecutable::paramString):
* runtime/FunctionConstructor.cpp:
(JSC::constructFunction):
(JSC::constructFunctionSkippingEvalEnabledCheck):
* runtime/FunctionPrototype.h:
(JSC::FunctionPrototype::create):
Using a null String for the name is correct because InternalFunction uses jsString()
to create the name value.
* runtime/InternalFunction.cpp:
(JSC::InternalFunction::finishCreation):
There is no need to create an empty string for a null string, jsString() handle both
cases as empty JSString.
* runtime/JSArray.cpp:
(JSC::reject):
(JSC::SparseArrayValueMap::put):
(JSC::JSArray::put):
(JSC::JSArray::putByIndexBeyondVectorLength):
(JSC::JSArray::putDirectIndexBeyondVectorLength):
(JSC::JSArray::setLength):
(JSC::JSArray::pop):
(JSC::JSArray::push):
* runtime/JSFunction.cpp:
(JSC::JSFunction::finishCreation): Same issue as InternalFunction::finishCreation.
(JSC::JSFunction::callerGetter):
(JSC::JSFunction::defineOwnProperty):
* runtime/JSGlobalData.cpp:
(JSC::enableAssembler): Use CFSTR() instead of CFStringCreateWithCString().
CFStringCreateWithCString() copy the content and may choose to decode the data.
CFSTR() is much more efficient.
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::reset):
JSFunction uses jsString() to create the name, we can use null strings instead
of creating empty strings.
(JSC::JSGlobalObject::createThrowTypeError): ditto.
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::encode):
(JSC::decode):
(JSC::globalFuncEval):
* runtime/JSONObject.cpp:
(JSC::Stringifier::appendStringifiedValue):
(JSC::Stringifier::Holder::appendNextProperty):
(JSC::JSONProtoFuncParse):
(JSC::JSONProtoFuncStringify):
* runtime/JSObject.cpp:
(JSC::JSObject::put):
(JSC::JSObject::defaultValue):
(JSC::JSObject::hasInstance):
(JSC::JSObject::defineOwnProperty):
* runtime/JSString.cpp:
Return an empty JSString to avoid the creation of a temporary empty String.
(JSC::JSRopeString::getIndexSlowCase):
* runtime/JSString.h:
(JSC): Remove the versions of jsNontrivialString() taking a char*. All the callers
have been replaced by calls using ASCIILiteral.
* runtime/JSValue.cpp:
(JSC::JSValue::putToPrimitive):
* runtime/LiteralParser.cpp:
(JSC::::Lexer::lex):
(JSC::::Lexer::lexString):
(JSC::::Lexer::lexNumber):
(JSC::::parse):
* runtime/LiteralParser.h:
(JSC::LiteralParser::getErrorMessage):
* runtime/NumberPrototype.cpp:
(JSC::numberProtoFuncToExponential):
(JSC::numberProtoFuncToFixed):
(JSC::numberProtoFuncToPrecision):
(JSC::numberProtoFuncToString):
* runtime/ObjectConstructor.cpp:
(JSC::objectConstructorGetPrototypeOf):
(JSC::objectConstructorGetOwnPropertyDescriptor):
(JSC::objectConstructorGetOwnPropertyNames):
(JSC::objectConstructorKeys):
(JSC::toPropertyDescriptor):
(JSC::objectConstructorDefineProperty):
(JSC::objectConstructorDefineProperties):
(JSC::objectConstructorCreate):
(JSC::objectConstructorSeal):
(JSC::objectConstructorFreeze):
(JSC::objectConstructorPreventExtensions):
(JSC::objectConstructorIsSealed):
(JSC::objectConstructorIsFrozen):
(JSC::objectConstructorIsExtensible):
* runtime/ObjectPrototype.cpp:
(JSC::objectProtoFuncDefineGetter):
(JSC::objectProtoFuncDefineSetter):
(JSC::objectProtoFuncToString):
* runtime/RegExpConstructor.cpp:
(JSC::constructRegExp):
* runtime/RegExpObject.cpp:
(JSC::reject):
(JSC::regExpObjectSource):
* runtime/RegExpPrototype.cpp:
(JSC::regExpProtoFuncCompile):
* runtime/StringObject.cpp:
(JSC::StringObject::defineOwnProperty):
* runtime/StringPrototype.cpp:
(JSC::jsSpliceSubstrings):
(JSC::jsSpliceSubstringsWithSeparators):
2012-09-04 Filip Pizlo <fpizlo@apple.com>
DFG GetByVal for JSArrays shouldn't OSR exit every time that the index is out of bound
......
......@@ -75,7 +75,7 @@ static String escapeQuotes(const String& str)
static String valueToSourceString(ExecState* exec, JSValue val)
{
if (!val)
return "0";
return ASCIILiteral("0");
if (val.isString())
return makeString("\"", escapeQuotes(val.toString(exec)->value(exec)), "\"");
......@@ -3032,14 +3032,14 @@ String CodeBlock::nameForRegister(int registerNumber)
return String(ptr->first);
}
if (needsActivation() && registerNumber == activationRegister())
return "activation";
return ASCIILiteral("activation");
if (registerNumber == thisRegister())
return "this";
return ASCIILiteral("this");
if (usesArguments()) {
if (registerNumber == argumentsRegister())
return "arguments";
return ASCIILiteral("arguments");
if (unmodifiedArgumentsRegister(argumentsRegister()) == registerNumber)
return "real arguments";
return ASCIILiteral("real arguments");
}
if (registerNumber < 0) {
int argumentPosition = -registerNumber;
......
......@@ -742,6 +742,8 @@ void Interpreter::addStackTraceIfNecessary(CallFrame* callFrame, JSObject* error
globalObject = globalData->dynamicGlobalObject;
else
globalObject = error->globalObject();
// FIXME: JSStringJoiner could be more efficient than StringBuilder here.
StringBuilder builder;
for (unsigned i = 0; i < stackTrace.size(); i++) {
builder.append(String(stackTrace[i].toString(globalObject->globalExec()).impl()));
......
......@@ -85,7 +85,7 @@ static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgLi
if (args.size() == 1 && args.at(0).isNumber()) {
uint32_t n = args.at(0).toUInt32(exec);
if (n != args.at(0).toNumber(exec))
return throwError(exec, createRangeError(exec, "Array size is not a small enough positive integer."));
return throwError(exec, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer.")));
return constructEmptyArray(exec, globalObject, n);
}
......
......@@ -205,13 +205,13 @@ static inline void shift(ExecState* exec, JSObject* thisObj, unsigned header, un
if (exec->hadException())
return;
} else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, to)) {
throwTypeError(exec, "Unable to delete property.");
throwTypeError(exec, ASCIILiteral("Unable to delete property."));
return;
}
}
for (unsigned k = length; k > length - count; --k) {
if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k - 1)) {
throwTypeError(exec, "Unable to delete property.");
throwTypeError(exec, ASCIILiteral("Unable to delete property."));
return;
}
}
......@@ -243,7 +243,7 @@ static inline void unshift(ExecState* exec, JSObject* thisObj, unsigned header,
return;
thisObj->methodTable()->putByIndex(thisObj, exec, to, value, true);
} else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, to)) {
throwTypeError(exec, "Unable to delete property.");
throwTypeError(exec, ASCIILiteral("Unable to delete property."));
return;
}
if (exec->hadException())
......@@ -491,7 +491,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec)
if (exec->hadException())
return JSValue::encode(jsUndefined());
if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, length - 1)) {
throwTypeError(exec, "Unable to delete property.");
throwTypeError(exec, ASCIILiteral("Unable to delete property."));
return JSValue::encode(jsUndefined());
}
putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1));
......@@ -553,7 +553,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)
if (exec->hadException())
return JSValue::encode(jsUndefined());
} else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k)) {
throwTypeError(exec, "Unable to delete property.");
throwTypeError(exec, ASCIILiteral("Unable to delete property."));
return JSValue::encode(jsUndefined());
}
......@@ -562,7 +562,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)
if (exec->hadException())
return JSValue::encode(jsUndefined());
} else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, lk1)) {
throwTypeError(exec, "Unable to delete property.");
throwTypeError(exec, ASCIILiteral("Unable to delete property."));
return JSValue::encode(jsUndefined());
}
}
......
......@@ -77,21 +77,22 @@ bool BooleanPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exe
EncodedJSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState* exec)
{
JSGlobalData* globalData = &exec->globalData();
JSValue thisValue = exec->hostThisValue();
if (thisValue == jsBoolean(false))
return JSValue::encode(jsNontrivialString(exec, "false"));
return JSValue::encode(globalData->smallStrings.falseString(globalData));
if (thisValue == jsBoolean(true))
return JSValue::encode(jsNontrivialString(exec, "true"));
return JSValue::encode(globalData->smallStrings.trueString(globalData));
if (!thisValue.inherits(&BooleanObject::s_info))
return throwVMTypeError(exec);
if (asBooleanObject(thisValue)->internalValue() == jsBoolean(false))
return JSValue::encode(jsNontrivialString(exec, "false"));
return JSValue::encode(globalData->smallStrings.falseString(globalData));
ASSERT(asBooleanObject(thisValue)->internalValue() == jsBoolean(true));
return JSValue::encode(jsNontrivialString(exec, "true"));
return JSValue::encode(globalData->smallStrings.trueString(globalData));
}
EncodedJSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState* exec)
......
......@@ -73,7 +73,7 @@ String formatDateTime(const GregorianDateTime& t, DateTimeFormat format, bool as
builder.append(weekdayName[(t.weekDay() + 6) % 7]);
if (asUTCVariant) {
builder.append(", ");
builder.appendLiteral(", ");
appendNumber<2>(builder, t.monthDay());
builder.append(' ');
builder.append(monthName[t.month()]);
......@@ -96,7 +96,7 @@ String formatDateTime(const GregorianDateTime& t, DateTimeFormat format, bool as
appendNumber<2>(builder, t.minute());
builder.append(':');
appendNumber<2>(builder, t.second());
builder.append(" GMT");
builder.appendLiteral(" GMT");
if (!asUTCVariant) {
int offset = abs(t.utcOffset()) / 60;
......@@ -114,7 +114,7 @@ String formatDateTime(const GregorianDateTime& t, DateTimeFormat format, bool as
strftime(timeZoneName, sizeof(timeZoneName), "%Z", &gtm);
#endif
if (timeZoneName[0]) {
builder.append(" (");
builder.appendLiteral(" (");
builder.append(timeZoneName);
builder.append(')');
}
......
......@@ -334,7 +334,7 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, doubl
{
const GregorianDateTime* gregorianDateTime = dateObject->gregorianDateTime(exec);
if (!gregorianDateTime)
return jsNontrivialString(exec, "Invalid Date");
return jsNontrivialString(exec, ASCIILiteral("Invalid Date"));
return formatLocaleDate(exec, *gregorianDateTime, format);
}
......@@ -352,7 +352,7 @@ static EncodedJSValue formateDateInstance(ExecState* exec, DateTimeFormat format
? thisDateObj->gregorianDateTimeUTC(exec)
: thisDateObj->gregorianDateTime(exec);
if (!gregorianDateTime)
return JSValue::encode(jsNontrivialString(exec, "Invalid Date"));
return JSValue::encode(jsNontrivialString(exec, String(ASCIILiteral("Invalid Date"))));
return JSValue::encode(jsNontrivialString(exec, formatDateTime(*gregorianDateTime, format, asUTCVariant)));
}
......@@ -548,24 +548,30 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec)
DateInstance* thisDateObj = asDateInstance(thisValue);
if (!isfinite(thisDateObj->internalNumber()))
return throwVMError(exec, createRangeError(exec, "Invalid Date"));
return throwVMError(exec, createRangeError(exec, ASCIILiteral("Invalid Date")));
const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
if (!gregorianDateTime)
return JSValue::encode(jsNontrivialString(exec, "Invalid Date"));
return JSValue::encode(jsNontrivialString(exec, String(ASCIILiteral("Invalid Date"))));
// Maximum amount of space we need in buffer: 7 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second) + 4 (. + 3 digits for milliseconds)
// 6 for formatting and one for null termination = 28. We add one extra character to allow us to force null termination.
char buffer[29];
char buffer[28];
// If the year is outside the bounds of 0 and 9999 inclusive we want to use the extended year format (ES 15.9.1.15.1).
int ms = static_cast<int>(fmod(thisDateObj->internalNumber(), msPerSecond));
if (ms < 0)
ms += msPerSecond;
int charactersWritten;
if (gregorianDateTime->year() > 9999 || gregorianDateTime->year() < 0)
snprintf(buffer, sizeof(buffer) - 1, "%+07d-%02d-%02dT%02d:%02d:%02d.%03dZ", gregorianDateTime->year(), gregorianDateTime->month() + 1, gregorianDateTime->monthDay(), gregorianDateTime->hour(), gregorianDateTime->minute(), gregorianDateTime->second(), ms);
charactersWritten = snprintf(buffer, sizeof(buffer), "%+07d-%02d-%02dT%02d:%02d:%02d.%03dZ", gregorianDateTime->year(), gregorianDateTime->month() + 1, gregorianDateTime->monthDay(), gregorianDateTime->hour(), gregorianDateTime->minute(), gregorianDateTime->second(), ms);
else
snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", gregorianDateTime->year(), gregorianDateTime->month() + 1, gregorianDateTime->monthDay(), gregorianDateTime->hour(), gregorianDateTime->minute(), gregorianDateTime->second(), ms);
buffer[sizeof(buffer) - 1] = 0;
return JSValue::encode(jsNontrivialString(exec, buffer));
charactersWritten = snprintf(buffer, sizeof(buffer), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", gregorianDateTime->year(), gregorianDateTime->month() + 1, gregorianDateTime->monthDay(), gregorianDateTime->hour(), gregorianDateTime->minute(), gregorianDateTime->second(), ms);
ASSERT(charactersWritten > 0 && static_cast<unsigned>(charactersWritten) < sizeof(buffer));
if (static_cast<unsigned>(charactersWritten) >= sizeof(buffer))
return JSValue::encode(jsEmptyString(exec));
return JSValue::encode(jsNontrivialString(exec, String(buffer, charactersWritten)));
}
EncodedJSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec)
......@@ -1113,13 +1119,13 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec)
CallData callData;
CallType callType = getCallData(toISOValue, callData);
if (callType == CallTypeNone)
return throwVMError(exec, createTypeError(exec, "toISOString is not a function"));
return throwVMError(exec, createTypeError(exec, ASCIILiteral("toISOString is not a function")));
JSValue result = call(exec, asObject(toISOValue), callType, callData, object, exec->emptyList());
if (exec->hadException())
return JSValue::encode(jsNull());
if (result.isObject())
return throwVMError(exec, createTypeError(exec, "toISOString did not return a primitive value"));
return throwVMError(exec, createTypeError(exec, ASCIILiteral("toISOString did not return a primitive value")));
return JSValue::encode(result);
}
......
......@@ -81,7 +81,7 @@ JSObject* createTypeError(JSGlobalObject* globalObject, const String& message)
JSObject* createNotEnoughArgumentsError(JSGlobalObject* globalObject)
{
return createTypeError(globalObject, "Not enough arguments");
return createTypeError(globalObject, ASCIILiteral("Not enough arguments"));
}
JSObject* createURIError(JSGlobalObject* globalObject, const String& message)
......@@ -169,12 +169,12 @@ JSObject* throwError(ExecState* exec, JSObject* error)
JSObject* throwTypeError(ExecState* exec)
{
return throwError(exec, createTypeError(exec, "Type error"));
return throwError(exec, createTypeError(exec, ASCIILiteral("Type error")));
}
JSObject* throwSyntaxError(ExecState* exec)
{
return throwError(exec, createSyntaxError(exec, "Syntax error"));
return throwError(exec, createSyntaxError(exec, ASCIILiteral("Syntax error")));
}
ASSERT_CLASS_FITS_IN_CELL(StrictModeTypeErrorFunction);
......
......@@ -89,7 +89,7 @@ namespace JSC {
static StrictModeTypeErrorFunction* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, const String& message)
{
StrictModeTypeErrorFunction* function = new (NotNull, allocateCell<StrictModeTypeErrorFunction>(*exec->heap())) StrictModeTypeErrorFunction(globalObject, structure, message);
function->finishCreation(exec->globalData(), "");
function->finishCreation(exec->globalData(), String());
return function;
}
......
......@@ -59,7 +59,7 @@ void ErrorPrototype::finishCreation(ExecState* exec, JSGlobalObject*)
{
Base::finishCreation(exec->globalData(), "");
ASSERT(inherits(&s_info));
putDirect(exec->globalData(), exec->propertyNames().name, jsNontrivialString(exec, "Error"), DontEnum);
putDirect(exec->globalData(), exec->propertyNames().name, jsNontrivialString(exec, String(ASCIILiteral("Error"))), DontEnum);
}
bool ErrorPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
......@@ -98,7 +98,7 @@ EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec)
// 4. If name is undefined, then let name be "Error"; else let name be ToString(name).
String nameString;
if (name.isUndefined())
nameString = "Error";
nameString = ASCIILiteral("Error");
else {
nameString = name.toString(exec)->value(exec);
if (exec->hadException())
......@@ -115,7 +115,7 @@ EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec)
// 7. If msg is undefined, then let msg be the empty String; else let msg be ToString(msg).
String messageString;
if (message.isUndefined())
messageString = "";
messageString = String();
else {
messageString = message.toString(exec)->value(exec);
if (exec->hadException())
......
......@@ -47,7 +47,7 @@ const ClassInfo InterruptedExecutionError::s_info = { "InterruptedExecutionError
JSValue InterruptedExecutionError::defaultValue(const JSObject*, ExecState* exec, PreferredPrimitiveType hint)
{
if (hint == PreferString)
return jsNontrivialString(exec, "JavaScript execution exceeded timeout.");
return jsNontrivialString(exec, String(ASCIILiteral("JavaScript execution exceeded timeout.")));
return JSValue(std::numeric_limits<double>::quiet_NaN());
}
......@@ -74,7 +74,7 @@ const ClassInfo TerminatedExecutionError::s_info = { "TerminatedExecutionError",
JSValue TerminatedExecutionError::defaultValue(const JSObject*, ExecState* exec, PreferredPrimitiveType hint)
{
if (hint == PreferString)
return jsNontrivialString(exec, "JavaScript execution terminated.");
return jsNontrivialString(exec, String(ASCIILiteral("JavaScript execution terminated.")));
return JSValue(std::numeric_limits<double>::quiet_NaN());
}
......@@ -96,12 +96,12 @@ bool isTerminatedExecutionException(JSValue value)
JSObject* createStackOverflowError(ExecState* exec)
{
return createRangeError(exec, "Maximum call stack size exceeded.");
return createRangeError(exec, ASCIILiteral("Maximum call stack size exceeded."));
}
JSObject* createStackOverflowError(JSGlobalObject* globalObject)
{
return createRangeError(globalObject, "Maximum call stack size exceeded.");
return createRangeError(globalObject, ASCIILiteral("Maximum call stack size exceeded."));
}
JSObject* createUndefinedVariableError(ExecState* exec, const Identifier& ident)
......@@ -153,7 +153,7 @@ JSObject* createErrorForInvalidGlobalAssignment(ExecState* exec, const String& p
JSObject* createOutOfMemoryError(JSGlobalObject* globalObject)
{
return createError(globalObject, "Out of memory");
return createError(globalObject, ASCIILiteral("Out of memory"));
}
JSObject* throwOutOfMemoryError(ExecState* exec)
......
......@@ -209,7 +209,7 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCo
m_evalCodeBlock = newCodeBlock.release();
} else {
if (!lexicalGlobalObject->evalEnabled())
return throwError(exec, createEvalError(exec, "Eval is disabled"));
return throwError(exec, createEvalError(exec, ASCIILiteral("Eval is disabled")));
RefPtr<EvalNode> evalNode = parse<EvalNode>(globalData, lexicalGlobalObject, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, EvalNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
if (!evalNode) {
ASSERT(exception);
......@@ -675,7 +675,7 @@ String FunctionExecutable::paramString() const
StringBuilder builder;
for (size_t pos = 0; pos < parameters.size(); ++pos) {
if (!builder.isEmpty())
builder.append(", ");
builder.appendLiteral(", ");
builder.append(parameters[pos].ustring());
}
return builder.toString();
......
......@@ -82,7 +82,7 @@ CallType FunctionConstructor::getCallData(JSCell*, CallData& callData)
JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, const Identifier& functionName, const String& sourceURL, const TextPosition& position)
{
if (!globalObject->evalEnabled())
return throwError(exec, createEvalError(exec, "Function constructor is disabled"));
return throwError(exec, createEvalError(exec, ASCIILiteral("Function constructor is disabled")));
return constructFunctionSkippingEvalEnabledCheck(exec, globalObject, args, functionName, sourceURL, position);
}
......@@ -93,20 +93,20 @@ JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState* exec, JSGlobalObj
// We also need \n before the closing } to handle // comments at the end of the last line
String program;
if (args.isEmpty())
program = "(function() { \n})";
program = ASCIILiteral("(function() { \n})");
else if (args.size() == 1)
program = makeString("(function() { ", args.at(0).toString(exec)->value(exec), "\n})");
else {
StringBuilder builder;
builder.append("(function(");
builder.appendLiteral("(function(");
builder.append(args.at(0).toString(exec)->value(exec));
for (size_t i = 1; i < args.size() - 1; i++) {
builder.append(",");
builder.append(',');
builder.append(args.at(i).toString(exec)->value(exec));
}
builder.append(") { ");
builder.appendLiteral(") { ");
builder.append(args.at(args.size() - 1).toString(exec)->value(exec));
builder.append("\n})");
builder.appendLiteral("\n})");
program = builder.toString();
}
......
......@@ -32,7 +32,7 @@ namespace JSC {
static FunctionPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
{
FunctionPrototype* prototype = new (NotNull, allocateCell<FunctionPrototype>(*exec->heap())) FunctionPrototype(globalObject, structure);
prototype->finishCreation(exec, "");
prototype->finishCreation(exec, String());
return prototype;
}
......
......@@ -44,7 +44,7 @@ void InternalFunction::finishCreation(JSGlobalData& globalData, const String& na
Base::finishCreation(globalData);
ASSERT(inherits(&s_info));
ASSERT(methodTable()->getCallData != InternalFunction::s_info.methodTable.getCallData);
putDirect(globalData, globalData.propertyNames->name, jsString(&globalData, name.isNull() ? "" : name), DontDelete | ReadOnly | DontEnum);
putDirect(globalData, globalData.propertyNames->name, jsString(&globalData, name), DontDelete | ReadOnly | DontEnum);
}
const String& InternalFunction::name(ExecState* exec)
......
......@@ -113,7 +113,7 @@ static inline bool isDenseEnoughForVector(unsigned length, unsigned numValues)
static bool reject(ExecState* exec, bool throwException, const char* message)
{
if (throwException)
throwTypeError(exec, message);
throwTypeError(exec, ASCIILiteral(message));
return false;
}
......@@ -212,14 +212,14 @@ inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i