Commit 25ecbabb authored by benjamin@webkit.org's avatar benjamin@webkit.org

Cache the type string of JavaScript object

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

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

Instead of creating the JSString every time, we create
lazily the strings in JSGlobalData.

This avoid the construction of the StringImpl and of the JSString,
which gives some performance improvements.

* runtime/CommonIdentifiers.h:
* runtime/JSValue.cpp:
(JSC::JSValue::toStringSlowCase):
* runtime/Operations.cpp:
(JSC::jsTypeStringForValue):
* runtime/SmallStrings.cpp:
(JSC::SmallStrings::SmallStrings):
(JSC::SmallStrings::finalizeSmallStrings):
(JSC::SmallStrings::initialize):
(JSC):
* runtime/SmallStrings.h:
(SmallStrings):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@111433 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent c7363bc1
2012-03-20 Benjamin Poulain <bpoulain@apple.com>
Cache the type string of JavaScript object
https://bugs.webkit.org/show_bug.cgi?id=81446
Reviewed by Geoffrey Garen.
Instead of creating the JSString every time, we create
lazily the strings in JSGlobalData.
This avoid the construction of the StringImpl and of the JSString,
which gives some performance improvements.
* runtime/CommonIdentifiers.h:
* runtime/JSValue.cpp:
(JSC::JSValue::toStringSlowCase):
* runtime/Operations.cpp:
(JSC::jsTypeStringForValue):
* runtime/SmallStrings.cpp:
(JSC::SmallStrings::SmallStrings):
(JSC::SmallStrings::finalizeSmallStrings):
(JSC::SmallStrings::initialize):
(JSC):
* runtime/SmallStrings.h:
(SmallStrings):
2012-03-20 Oliver Hunt <oliver@apple.com>
Allow LLINT to work even when executable allocation fails.
......@@ -72,8 +72,7 @@
macro(value) \
macro(valueOf) \
macro(writable) \
macro(displayName) \
macro(undefined)
macro(displayName)
#define JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(macro) \
macro(null) \
......
......@@ -260,19 +260,20 @@ bool JSValue::isValidCallee()
JSString* JSValue::toStringSlowCase(ExecState* exec) const
{
JSGlobalData& globalData = exec->globalData();
ASSERT(!isString());
if (isInt32())
return jsString(&exec->globalData(), exec->globalData().numericStrings.add(asInt32()));
return jsString(&globalData, globalData.numericStrings.add(asInt32()));
if (isDouble())
return jsString(&exec->globalData(), exec->globalData().numericStrings.add(asDouble()));
return jsString(&globalData, globalData.numericStrings.add(asDouble()));
if (isTrue())
return jsNontrivialString(exec, exec->propertyNames().trueKeyword.ustring());
return globalData.smallStrings.trueString(&globalData);
if (isFalse())
return jsNontrivialString(exec, exec->propertyNames().falseKeyword.ustring());
return globalData.smallStrings.falseString(&globalData);
if (isNull())
return jsNontrivialString(exec, exec->propertyNames().nullKeyword.ustring());
return globalData.smallStrings.nullString(&globalData);
if (isUndefined())
return jsNontrivialString(exec, exec->propertyNames().undefined.ustring());
return globalData.smallStrings.undefinedString(&globalData);
ASSERT(isCell());
JSValue value = asCell()->toPrimitive(exec, PreferString);
......
......@@ -58,25 +58,26 @@ NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2)
JSValue jsTypeStringForValue(CallFrame* callFrame, JSValue v)
{
JSGlobalData& globalData = callFrame->globalData();
if (v.isUndefined())
return jsNontrivialString(callFrame, "undefined");
return globalData.smallStrings.undefinedString(&globalData);
if (v.isBoolean())
return jsNontrivialString(callFrame, "boolean");
return globalData.smallStrings.booleanString(&globalData);
if (v.isNumber())
return jsNontrivialString(callFrame, "number");
return globalData.smallStrings.numberString(&globalData);
if (v.isString())
return jsNontrivialString(callFrame, "string");
return globalData.smallStrings.stringString(&globalData);
if (v.isObject()) {
// Return "undefined" for objects that should be treated
// as null when doing comparisons.
if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined())
return jsNontrivialString(callFrame, "undefined");
return globalData.smallStrings.undefinedString(&globalData);
CallData callData;
JSObject* object = asObject(v);
if (object->methodTable()->getCallData(object, callData) != CallTypeNone)
return jsNontrivialString(callFrame, "function");
return globalData.smallStrings.functionString(&globalData);
}
return jsNontrivialString(callFrame, "object");
return globalData.smallStrings.objectString(&globalData);
}
bool jsIsObjectType(JSValue v)
......
......@@ -68,10 +68,13 @@ SmallStringsStorage::SmallStringsStorage()
}
SmallStrings::SmallStrings()
: m_emptyString(0)
#define JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE(name) , m_##name(0)
JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE)
#undef JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE
{
COMPILE_ASSERT(singleCharacterStringCount == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage);
m_emptyString = 0;
for (unsigned i = 0; i < singleCharacterStringCount; ++i)
m_singleCharacterStrings[i] = 0;
}
......@@ -85,6 +88,9 @@ void SmallStrings::finalizeSmallStrings()
finalize(m_emptyString);
for (unsigned i = 0; i < singleCharacterStringCount; ++i)
finalize(m_singleCharacterStrings[i]);
#define JSC_COMMON_STRINGS_ATTRIBUTE_FINALIZE(name) finalize(m_##name);
JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_FINALIZE)
#undef JSC_COMMON_STRINGS_ATTRIBUTE_FINALIZE
}
void SmallStrings::createEmptyString(JSGlobalData* globalData)
......@@ -108,4 +114,9 @@ StringImpl* SmallStrings::singleCharacterStringRep(unsigned char character)
return m_storage->rep(character);
}
void SmallStrings::initialize(JSGlobalData* globalData, JSString*& string, const char* value) const
{
string = JSString::create(*globalData, StringImpl::create(value));
}
} // namespace JSC
......@@ -30,6 +30,17 @@
#include <wtf/FixedArray.h>
#include <wtf/OwnPtr.h>
#define JSC_COMMON_STRINGS_EACH_NAME(macro) \
macro(boolean) \
macro(false) \
macro(function) \
macro(number) \
macro(null) \
macro(object) \
macro(undefined) \
macro(string) \
macro(true)
namespace JSC {
class HeapRootVisitor;
......@@ -66,13 +77,28 @@ namespace JSC {
JSString** singleCharacterStrings() { return &m_singleCharacterStrings[0]; }
#define JSC_COMMON_STRINGS_ACCESSOR_DEFINITION(name) \
JSString* name##String(JSGlobalData* globalData) const \
{ \
if (!m_##name) \
initialize(globalData, m_##name, #name); \
return m_##name; \
}
JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ACCESSOR_DEFINITION)
#undef JSC_COMMON_STRINGS_ACCESSOR_DEFINITION
private:
static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1;
JS_EXPORT_PRIVATE void createEmptyString(JSGlobalData*);
JS_EXPORT_PRIVATE void createSingleCharacterString(JSGlobalData*, unsigned char);
void initialize(JSGlobalData* globalData, JSString*& string, const char* value) const;
JSString* m_emptyString;
#define JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION(name) mutable JSString* m_##name;
JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION)
#undef JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION
JSString* m_singleCharacterStrings[singleCharacterStringCount];
OwnPtr<SmallStringsStorage> m_storage;
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment