Commit 302759c8 authored by darin's avatar darin

- atomic identifiers; gives another 6.5% in the iBench suite

        * kjs/identifier.h: Did the real thing.
        * kjs/identifier.cpp: Ditto.

        * kjs/property_map.h: _tableSizeHashMask -> _tableSizeMask
        * kjs/property_map.cpp: The above, plus take advantage of comparing
	by pointer instead of by comparing bytes.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@2776 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 4a234d6c
2002-11-20 Darin Adler <darin@apple.com>
- atomic identifiers; gives another 6.5% in the iBench suite
* kjs/identifier.h: Did the real thing.
* kjs/identifier.cpp: Ditto.
* kjs/property_map.h: _tableSizeHashMask -> _tableSizeMask
* kjs/property_map.cpp: The above, plus take advantage of comparing
by pointer instead of by comparing bytes.
2002-11-19 Darin Adler <darin@apple.com>
- a few more globals for often-used property names
......
2002-11-20 Darin Adler <darin@apple.com>
- atomic identifiers; gives another 6.5% in the iBench suite
* kjs/identifier.h: Did the real thing.
* kjs/identifier.cpp: Ditto.
* kjs/property_map.h: _tableSizeHashMask -> _tableSizeMask
* kjs/property_map.cpp: The above, plus take advantage of comparing
by pointer instead of by comparing bytes.
2002-11-19 Darin Adler <darin@apple.com>
- a few more globals for often-used property names
......
2002-11-20 Darin Adler <darin@apple.com>
- atomic identifiers; gives another 6.5% in the iBench suite
* kjs/identifier.h: Did the real thing.
* kjs/identifier.cpp: Ditto.
* kjs/property_map.h: _tableSizeHashMask -> _tableSizeMask
* kjs/property_map.cpp: The above, plus take advantage of comparing
by pointer instead of by comparing bytes.
2002-11-19 Darin Adler <darin@apple.com>
- a few more globals for often-used property names
......
......@@ -37,61 +37,223 @@ extern const Identifier toLocaleStringPropertyName("toLocaleString");
extern const Identifier toStringPropertyName("toString");
extern const Identifier valueOfPropertyName("valueOf");
bool operator==(const Identifier &a, const char *b)
const int _minTableSize = 64;
UString::Rep **Identifier::_table;
int Identifier::_tableSize;
int Identifier::_tableSizeMask;
int Identifier::_keyCount;
bool Identifier::equal(UString::Rep *r, const char *s)
{
int length = r->len;
const UChar *d = r->dat;
for (int i = 0; i != length; ++i)
if (d[i].unicode() != (unsigned char)s[i])
return false;
return s[length] == 0;
}
bool Identifier::equal(UString::Rep *r, const UChar *s, int length)
{
if (r->len != length)
return false;
const UChar *d = r->dat;
for (int i = 0; i != length; ++i)
if (d[i].unicode() != s[i].unicode())
return false;
return true;
}
bool Identifier::equal(UString::Rep *r, UString::Rep *b)
{
return a._ustring == b;
int length = r->len;
if (length != b->len)
return false;
const UChar *d = r->dat;
const UChar *s = b->dat;
for (int i = 0; i != length; ++i)
if (d[i].unicode() != s[i].unicode())
return false;
return true;
}
UString::Rep *Identifier::add(const char *c)
{
if (!c)
return &UString::Rep::null;
int length = strlen(c);
if (length == 0)
return &UString::Rep::empty;
// Here's where we compute a hash and find it or put it in the hash table.
UChar *d = new UChar[length];
for (int i = 0; i < length; i++)
d[i] = c[i];
UString::Rep *r = new UString::Rep;
r->dat = d;
r->len = length;
r->capacity = length;
r->rc = 0;
r->_hash = 0;
return r;
if (!c)
return &UString::Rep::null;
int length = strlen(c);
if (length == 0)
return &UString::Rep::empty;
if (!_table)
expand();
unsigned hash = UString::Rep::computeHash(c);
int i = hash & _tableSizeMask;
while (UString::Rep *key = _table[i]) {
if (equal(key, c))
return key;
i = (i + 1) & _tableSizeMask;
}
UChar *d = new UChar[length];
for (int j = 0; j != length; j++)
d[j] = c[j];
UString::Rep *r = new UString::Rep;
r->dat = d;
r->len = length;
r->capacity = UString::Rep::capacityForIdentifier;
r->rc = 0;
r->_hash = hash;
_table[i] = r;
++_keyCount;
if (_keyCount * 2 >= _tableSize)
expand();
return r;
}
UString::Rep *Identifier::add(const UChar *s, int length)
{
// Here's where we compute a hash and find it or put it in the hash table.
UChar *d = new UChar[length];
for (int i = 0; i < length; i++)
d[i] = s[i];
UString::Rep *r = new UString::Rep;
r->dat = d;
r->len = length;
r->capacity = length;
r->rc = 0;
r->_hash = 0;
return r;
if (length == 0)
return &UString::Rep::empty;
if (!_table)
expand();
unsigned hash = UString::Rep::computeHash(s, length);
int i = hash & _tableSizeMask;
while (UString::Rep *key = _table[i]) {
if (equal(key, s, length))
return key;
i = (i + 1) & _tableSizeMask;
}
UChar *d = new UChar[length];
for (int j = 0; j != length; j++)
d[j] = s[j];
UString::Rep *r = new UString::Rep;
r->dat = d;
r->len = length;
r->capacity = UString::Rep::capacityForIdentifier;
r->rc = 0;
r->_hash = hash;
_table[i] = r;
++_keyCount;
if (_keyCount * 2 >= _tableSize)
expand();
return r;
}
UString::Rep *Identifier::add(UString::Rep *r)
{
if (r->capacity == UString::Rep::capacityForIdentifier)
return r;
if (r->len == 0)
return &UString::Rep::empty;
if (!_table)
expand();
unsigned hash = r->hash();
int i = hash & _tableSizeMask;
while (UString::Rep *key = _table[i]) {
if (equal(key, r))
return key;
i = (i + 1) & _tableSizeMask;
}
r->capacity = UString::Rep::capacityForIdentifier;
_table[i] = r;
++_keyCount;
if (_keyCount * 2 >= _tableSize)
expand();
return r;
}
UString::Rep *Identifier::add(const UString &s)
inline void Identifier::insert(UString::Rep *key)
{
// Here's where we compute a hash and find it or put it in the hash table.
// Don't forget to check for the case of a string that's already in the table by looking at capacity.
return s.rep;
unsigned hash = key->hash();
int i = hash & _tableSizeMask;
while (_table[i])
i = (i + 1) & _tableSizeMask;
_table[i] = key;
}
void Identifier::remove(UString::Rep *)
void Identifier::remove(UString::Rep *r)
{
// Here's where we find the string already in the hash table, and remove it.
unsigned hash = r->hash();
UString::Rep *key;
int i = hash & _tableSizeMask;
while ((key = _table[i])) {
if (equal(key, r))
break;
i = (i + 1) & _tableSizeMask;
}
if (!key)
return;
_table[i] = 0;
--_keyCount;
if (_keyCount * 3 < _tableSize && _tableSize > _minTableSize) {
shrink();
return;
}
// Reinsert all the items to the right in the same cluster.
while (1) {
i = (i + 1) & _tableSizeMask;
key = _table[i];
if (!key)
break;
_table[i] = 0;
insert(key);
}
}
void Identifier::expand()
{
rehash(_tableSize == 0 ? _minTableSize : _tableSize * 2);
}
void Identifier::shrink()
{
rehash(_tableSize / 2);
}
void Identifier::rehash(int newTableSize)
{
int oldTableSize = _tableSize;
UString::Rep **oldTable = _table;
_tableSize = newTableSize;
_tableSizeMask = newTableSize - 1;
_table = (UString::Rep **)calloc(newTableSize, sizeof(UString::Rep *));
for (int i = 0; i != oldTableSize; ++i)
if (UString::Rep *key = oldTable[i])
insert(key);
free(oldTable);
}
} // namespace KJS
......@@ -32,7 +32,7 @@ namespace KJS {
Identifier() { }
Identifier(const char *s) : _ustring(add(s)) { }
Identifier(const UChar *s, int length) : _ustring(add(s, length)) { }
explicit Identifier(const UString &s) : _ustring(add(s)) { }
explicit Identifier(const UString &s) : _ustring(add(s.rep)) { }
const UString &ustring() const { return _ustring; }
DOM::DOMString string() const;
......@@ -61,22 +61,41 @@ namespace KJS {
static void remove(UString::Rep *);
private:
UString _ustring;
static bool equal(UString::Rep *, const char *);
static bool equal(UString::Rep *, const UChar *, int length);
static bool equal(UString::Rep *, UString::Rep *);
static bool equal(const Identifier &a, const Identifier &b)
{ return a._ustring.rep == b._ustring.rep; }
static bool equal(const Identifier &a, const char *b)
{ return equal(a._ustring.rep, b); }
static UString::Rep *add(const char *);
static UString::Rep *add(const UChar *, int length);
static UString::Rep *add(const UString &);
static UString::Rep *add(UString::Rep *);
UString _ustring;
static void insert(UString::Rep *);
static void rehash(int newTableSize);
static void expand();
static void shrink();
static UString::Rep **_table;
static int _tableSize;
static int _tableSizeMask;
static int _keyCount;
};
inline bool operator==(const Identifier &a, const Identifier &b)
{
return a._ustring == b._ustring;
}
{ return Identifier::equal(a, b); }
inline bool operator!=(const Identifier &a, const Identifier &b)
{
return a._ustring != b._ustring;
}
{ return !Identifier::equal(a, b); }
inline bool operator==(const Identifier &a, const char *b)
{ return Identifier::equal(a, b); }
extern const Identifier argumentsPropertyName;
extern const Identifier calleePropertyName;
......
......@@ -35,7 +35,6 @@ PropertyMap::PropertyMap() : _tableSize(0), _table(0), _keyCount(0)
PropertyMap::~PropertyMap()
{
//printf("key count is %d\n", _keyCount);
UString::Rep *key = _singleEntry.key;
if (key)
key->deref();
......@@ -66,30 +65,14 @@ void PropertyMap::clear()
inline int PropertyMap::hash(const UString::Rep *s) const
{
return s->hash() & _tableSizeHashMask;
}
bool PropertyMap::keysMatch(const UString::Rep *a, const UString::Rep *b)
{
if (a == b)
return true;
int len = a->len;
if (len != b->len)
return false;
for (int i = 0; i != len; ++i)
if (a->dat[i].unicode() != b->dat[i].unicode())
return false;
return true;
return s->hash() & _tableSizeMask;
}
ValueImp *PropertyMap::get(const Identifier &name, int &attributes) const
{
if (!_table) {
UString::Rep *key = _singleEntry.key;
if (key && keysMatch(name._ustring.rep, key)) {
if (name._ustring.rep == key) {
attributes = _singleEntry.attributes;
return _singleEntry.value;
}
......@@ -98,11 +81,11 @@ ValueImp *PropertyMap::get(const Identifier &name, int &attributes) const
int i = hash(name._ustring.rep);
while (UString::Rep *key = _table[i].key) {
if (keysMatch(name._ustring.rep, key)) {
if (name._ustring.rep == key) {
attributes = _table[i].attributes;
return _table[i].value;
}
i = (i + 1) & _tableSizeHashMask;
i = (i + 1) & _tableSizeMask;
}
return 0;
}
......@@ -111,16 +94,16 @@ ValueImp *PropertyMap::get(const Identifier &name) const
{
if (!_table) {
UString::Rep *key = _singleEntry.key;
if (key && keysMatch(name._ustring.rep, key))
if (name._ustring.rep == key)
return _singleEntry.value;
return 0;
}
int i = hash(name._ustring.rep);
while (UString::Rep *key = _table[i].key) {
if (keysMatch(name._ustring.rep, key))
if (name._ustring.rep == key)
return _table[i].value;
i = (i + 1) & _tableSizeHashMask;
i = (i + 1) & _tableSizeMask;
}
return 0;
}
......@@ -130,7 +113,7 @@ void PropertyMap::put(const Identifier &name, ValueImp *value, int attributes)
if (!_table) {
UString::Rep *key = _singleEntry.key;
if (key) {
if (keysMatch(name._ustring.rep, key)) {
if (name._ustring.rep == key) {
_singleEntry.value = value;
return;
}
......@@ -149,13 +132,13 @@ void PropertyMap::put(const Identifier &name, ValueImp *value, int attributes)
int i = hash(name._ustring.rep);
while (UString::Rep *key = _table[i].key) {
if (keysMatch(name._ustring.rep, key)) {
if (name._ustring.rep == key) {
// Put a new value in an existing hash table entry.
_table[i].value = value;
// Attributes are intentionally not updated.
return;
}
i = (i + 1) & _tableSizeHashMask;
i = (i + 1) & _tableSizeMask;
}
// Create a new hash table entry.
......@@ -170,7 +153,7 @@ inline void PropertyMap::insert(UString::Rep *key, ValueImp *value, int attribut
{
int i = hash(key);
while (_table[i].key)
i = (i + 1) & _tableSizeHashMask;
i = (i + 1) & _tableSizeMask;
_table[i].key = key;
_table[i].value = value;
......@@ -183,7 +166,7 @@ void PropertyMap::expand()
Entry *oldTable = _table;
_tableSize = oldTableSize ? oldTableSize * 2 : 16;
_tableSizeHashMask = _tableSize - 1;
_tableSizeMask = _tableSize - 1;
_table = (Entry *)calloc(_tableSize, sizeof(Entry));
UString::Rep *key = _singleEntry.key;
......@@ -207,7 +190,7 @@ void PropertyMap::remove(const Identifier &name)
if (!_table) {
key = _singleEntry.key;
if (key && keysMatch(name._ustring.rep, key)) {
if (name._ustring.rep == key) {
key->deref();
_singleEntry.key = 0;
_keyCount = 0;
......@@ -218,9 +201,9 @@ void PropertyMap::remove(const Identifier &name)
// Find the thing to remove.
int i = hash(name._ustring.rep);
while ((key = _table[i].key)) {
if (keysMatch(name._ustring.rep, key))
if (name._ustring.rep == key)
break;
i = (i + 1) & _tableSizeHashMask;
i = (i + 1) & _tableSizeMask;
}
if (!key)
return;
......@@ -232,7 +215,7 @@ void PropertyMap::remove(const Identifier &name)
// Reinsert all the items to the right in the same cluster.
while (1) {
i = (i + 1) & _tableSizeHashMask;
i = (i + 1) & _tableSizeMask;
key = _table[i].key;
if (!key)
break;
......
......@@ -63,7 +63,7 @@ namespace KJS {
typedef PropertyMapHashTableEntry Entry;
int _tableSizeHashMask;
int _tableSizeMask;
int _tableSize;
Entry *_table;
int _keyCount;
......
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