Skip to content
Permalink
Browse files
2010-03-05 Oliver Hunt <oliver@apple.com>
        Reviewed by Gavin Barraclough.

        JSC should cache int to Identifier conversion as it does for ordinary strings
        https://bugs.webkit.org/show_bug.cgi?id=35814

        Make the NumericStrings cache cache unsigned ints in addition to signed.
        We keep them separate from the int cache as it both simplifies code, and
        also because the unsigned path is exclusive to property access and therefore
        seems to have different usage patterns.

        The primary trigger for the unsigned to Identifier propertyName conversion
        is the construction of array-like objects out of normal objects.  Given these
        tend to be relative small numbers, and the array-like behaviour lends itself
        to sequential values this patch also adds a non-colliding cache for all small
        numbers.

        * JavaScriptCore.exp:
        * runtime/Identifier.cpp:
        (JSC::Identifier::from):
        * runtime/Identifier.h:
        * runtime/NumericStrings.h:
        (JSC::NumericStrings::add):
        (JSC::NumericStrings::lookup):
        (JSC::NumericStrings::lookupSmallString):

Canonical link: https://commits.webkit.org/46896@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@55599 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
ojhunt committed Mar 5, 2010
1 parent 40116db commit 1b30b234b354796d799c67068894ef174222a231
Showing 5 changed files with 71 additions and 3 deletions.
@@ -1,3 +1,30 @@
2010-03-05 Oliver Hunt <oliver@apple.com>

Reviewed by Gavin Barraclough.

JSC should cache int to Identifier conversion as it does for ordinary strings
https://bugs.webkit.org/show_bug.cgi?id=35814

Make the NumericStrings cache cache unsigned ints in addition to signed.
We keep them separate from the int cache as it both simplifies code, and
also because the unsigned path is exclusive to property access and therefore
seems to have different usage patterns.

The primary trigger for the unsigned to Identifier propertyName conversion
is the construction of array-like objects out of normal objects. Given these
tend to be relative small numbers, and the array-like behaviour lends itself
to sequential values this patch also adds a non-colliding cache for all small
numbers.

* JavaScriptCore.exp:
* runtime/Identifier.cpp:
(JSC::Identifier::from):
* runtime/Identifier.h:
* runtime/NumericStrings.h:
(JSC::NumericStrings::add):
(JSC::NumericStrings::lookup):
(JSC::NumericStrings::lookupSmallString):

2010-03-03 Oliver Hunt <oliver@apple.com>

Reviewed by Gavin Barraclough.
@@ -95,6 +95,8 @@ __ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPNS_11UStringImplE
__ZN3JSC10Identifier24checkSameIdentifierTableEPNS_12JSGlobalDataEPNS_11UStringImplE
__ZN3JSC10Identifier24checkSameIdentifierTableEPNS_9ExecStateEPNS_11UStringImplE
__ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
__ZN3JSC10Identifier4fromEPNS_9ExecStateEi
__ZN3JSC10Identifier4fromEPNS_9ExecStateEj
__ZN3JSC10Identifier5equalEPKNS_11UStringImplEPKc
__ZN3JSC10JSFunctionC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE
__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeE
@@ -22,6 +22,7 @@
#include "Identifier.h"

#include "CallFrame.h"
#include "NumericStrings.h"
#include <new> // for placement new
#include <string.h> // for strlen
#include <wtf/Assertions.h>
@@ -236,6 +237,21 @@ void Identifier::remove(UString::Rep* r)
{
currentIdentifierTable()->remove(r);
}

Identifier Identifier::from(ExecState* exec, unsigned value)
{
return Identifier(exec, exec->globalData().numericStrings.add(value));
}

Identifier Identifier::from(ExecState* exec, int value)
{
return Identifier(exec, exec->globalData().numericStrings.add(value));
}

Identifier Identifier::from(ExecState* exec, double value)
{
return Identifier(exec, exec->globalData().numericStrings.add(value));
}

#ifndef NDEBUG

@@ -54,9 +54,9 @@ namespace JSC {

const char* ascii() const { return _ustring.ascii(); }

static Identifier from(ExecState* exec, unsigned y) { return Identifier(exec, UString::from(y)); }
static Identifier from(ExecState* exec, int y) { return Identifier(exec, UString::from(y)); }
static Identifier from(ExecState* exec, double y) { return Identifier(exec, UString::from(y)); }
static Identifier from(ExecState* exec, unsigned y);
static Identifier from(ExecState* exec, int y);
static Identifier from(ExecState* exec, double y);

bool isNull() const { return _ustring.isNull(); }
bool isEmpty() const { return _ustring.isEmpty(); }
@@ -45,6 +45,8 @@ namespace JSC {

UString add(int i)
{
if (static_cast<unsigned>(i) < cacheSize)
return lookupSmallString(static_cast<unsigned>(i));
CacheEntry<int>& entry = lookup(i);
if (i == entry.key && !entry.value.isNull())
return entry.value;
@@ -53,6 +55,17 @@ namespace JSC {
return entry.value;
}

UString add(unsigned i)
{
if (i < cacheSize)
return lookupSmallString(static_cast<unsigned>(i));
CacheEntry<unsigned>& entry = lookup(i);
if (i == entry.key && !entry.value.isNull())
return entry.value;
entry.key = i;
entry.value = UString::from(i);
return entry.value;
}
private:
static const size_t cacheSize = 64;

@@ -64,9 +77,19 @@ namespace JSC {

CacheEntry<double>& lookup(double d) { return doubleCache[WTF::FloatHash<double>::hash(d) & (cacheSize - 1)]; }
CacheEntry<int>& lookup(int i) { return intCache[WTF::IntHash<int>::hash(i) & (cacheSize - 1)]; }
CacheEntry<unsigned>& lookup(unsigned i) { return unsignedCache[WTF::IntHash<unsigned>::hash(i) & (cacheSize - 1)]; }
const UString& lookupSmallString(unsigned i)
{
ASSERT(i < cacheSize);
if (smallIntCache[i].isNull())
smallIntCache[i] = UString::from(i);
return smallIntCache[i];
}

CacheEntry<double> doubleCache[cacheSize];
CacheEntry<int> intCache[cacheSize];
CacheEntry<unsigned> unsignedCache[cacheSize];
UString smallIntCache[cacheSize];
};

} // namespace JSC

0 comments on commit 1b30b23

Please sign in to comment.