Commit f7fc08d7 authored by darin's avatar darin

- add a couple of list operations to avoid clearing lists so much during...

	- add a couple of list operations to avoid clearing lists so much during sorting; gives 1.5% iBench

        * kjs/types.h: Added replaceFirst/replaceLast.
        * kjs/types.cpp: (List::replaceFirst), (List::replaceLast): Added.

        * kjs/array_object.cpp: (compareWithCompareFunctionForQSort): Use replaceFirst/replaceLast.

        * kjs/property_map.cpp: Put in an ifdef so I can re-add/remove the single entry to see if
	it has outlived its usefulness. (It hasn't yet.)


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@2777 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 302759c8
2002-11-20 Darin Adler <darin@apple.com>
- add a couple of list operations to avoid clearing lists so much during sorting; gives 1.5% iBench
* kjs/types.h: Added replaceFirst/replaceLast.
* kjs/types.cpp: (List::replaceFirst), (List::replaceLast): Added.
* kjs/array_object.cpp: (compareWithCompareFunctionForQSort): Use replaceFirst/replaceLast.
* kjs/property_map.cpp: Put in an ifdef so I can re-add/remove the single entry to see if
it has outlived its usefulness. (It hasn't yet.)
2002-11-20 Darin Adler <darin@apple.com>
- atomic identifiers; gives another 6.5% in the iBench suite
......
2002-11-20 Darin Adler <darin@apple.com>
- add a couple of list operations to avoid clearing lists so much during sorting; gives 1.5% iBench
* kjs/types.h: Added replaceFirst/replaceLast.
* kjs/types.cpp: (List::replaceFirst), (List::replaceLast): Added.
* kjs/array_object.cpp: (compareWithCompareFunctionForQSort): Use replaceFirst/replaceLast.
* kjs/property_map.cpp: Put in an ifdef so I can re-add/remove the single entry to see if
it has outlived its usefulness. (It hasn't yet.)
2002-11-20 Darin Adler <darin@apple.com>
- atomic identifiers; gives another 6.5% in the iBench suite
......
2002-11-20 Darin Adler <darin@apple.com>
- add a couple of list operations to avoid clearing lists so much during sorting; gives 1.5% iBench
* kjs/types.h: Added replaceFirst/replaceLast.
* kjs/types.cpp: (List::replaceFirst), (List::replaceLast): Added.
* kjs/array_object.cpp: (compareWithCompareFunctionForQSort): Use replaceFirst/replaceLast.
* kjs/property_map.cpp: Put in an ifdef so I can re-add/remove the single entry to see if
it has outlived its usefulness. (It hasn't yet.)
2002-11-20 Darin Adler <darin@apple.com>
- atomic identifiers; gives another 6.5% in the iBench suite
......
......@@ -214,7 +214,10 @@ struct CompareWithCompareFunctionArguments {
: exec(e)
, compareFunction(cf)
, globalObject(e->interpreter()->globalObject())
{ }
{
arguments.append(Undefined());
arguments.append(Undefined());
}
ExecState *exec;
ObjectImp *compareFunction;
......@@ -228,9 +231,8 @@ static int compareWithCompareFunctionForQSort(const void *a, const void *b)
{
CompareWithCompareFunctionArguments *args = compareWithCompareFunctionArguments;
args->arguments.clear();
args->arguments.append(*(ValueImp **)a);
args->arguments.append(*(ValueImp **)b);
args->arguments.replaceFirst(*(ValueImp **)a);
args->arguments.replaceLast(*(ValueImp **)b);
return args->compareFunction->call(args->exec, args->globalObject, args->arguments)
.toInt32(args->exec);
}
......
......@@ -25,6 +25,9 @@
#include "object.h"
#include "reference_list.h"
// At the time I added this, the optimization still gave a 1.5% performance boost.
#define USE_SINGLE_ENTRY 1
namespace KJS {
// Algorithm concepts from Algorithms in C++, Sedgewick.
......@@ -35,11 +38,13 @@ PropertyMap::PropertyMap() : _tableSize(0), _table(0), _keyCount(0)
PropertyMap::~PropertyMap()
{
#if USE_SINGLE_ENTRY
UString::Rep *key = _singleEntry.key;
if (key)
key->deref();
#endif
for (int i = 0; i < _tableSize; i++) {
key = _table[i].key;
UString::Rep *key = _table[i].key;
if (key)
key->deref();
}
......@@ -48,11 +53,13 @@ PropertyMap::~PropertyMap()
void PropertyMap::clear()
{
#if USE_SINGLE_ENTRY
UString::Rep *key = _singleEntry.key;
if (key) {
key->deref();
_singleEntry.key = 0;
}
#endif
for (int i = 0; i < _tableSize; i++) {
UString::Rep *key = _table[i].key;
if (key) {
......@@ -70,18 +77,22 @@ inline int PropertyMap::hash(const UString::Rep *s) const
ValueImp *PropertyMap::get(const Identifier &name, int &attributes) const
{
UString::Rep *rep = name._ustring.rep;
if (!_table) {
#if USE_SINGLE_ENTRY
UString::Rep *key = _singleEntry.key;
if (name._ustring.rep == key) {
if (rep == key) {
attributes = _singleEntry.attributes;
return _singleEntry.value;
}
#endif
return 0;
}
int i = hash(name._ustring.rep);
int i = hash(rep);
while (UString::Rep *key = _table[i].key) {
if (name._ustring.rep == key) {
if (rep == key) {
attributes = _table[i].attributes;
return _table[i].value;
}
......@@ -92,16 +103,20 @@ ValueImp *PropertyMap::get(const Identifier &name, int &attributes) const
ValueImp *PropertyMap::get(const Identifier &name) const
{
UString::Rep *rep = name._ustring.rep;
if (!_table) {
#if USE_SINGLE_ENTRY
UString::Rep *key = _singleEntry.key;
if (name._ustring.rep == key)
if (rep == key)
return _singleEntry.value;
#endif
return 0;
}
int i = hash(name._ustring.rep);
int i = hash(rep);
while (UString::Rep *key = _table[i].key) {
if (name._ustring.rep == key)
if (rep == key)
return _table[i].value;
i = (i + 1) & _tableSizeMask;
}
......@@ -110,29 +125,33 @@ ValueImp *PropertyMap::get(const Identifier &name) const
void PropertyMap::put(const Identifier &name, ValueImp *value, int attributes)
{
UString::Rep *rep = name._ustring.rep;
#if USE_SINGLE_ENTRY
if (!_table) {
UString::Rep *key = _singleEntry.key;
if (key) {
if (name._ustring.rep == key) {
if (rep == key) {
_singleEntry.value = value;
return;
}
} else {
name._ustring.rep->ref();
_singleEntry.key = name._ustring.rep;
rep->ref();
_singleEntry.key = rep;
_singleEntry.value = value;
_singleEntry.attributes = attributes;
_keyCount = 1;
return;
}
}
#endif
if (_keyCount * 2 >= _tableSize)
expand();
int i = hash(name._ustring.rep);
int i = hash(rep);
while (UString::Rep *key = _table[i].key) {
if (name._ustring.rep == key) {
if (rep == key) {
// Put a new value in an existing hash table entry.
_table[i].value = value;
// Attributes are intentionally not updated.
......@@ -142,8 +161,8 @@ void PropertyMap::put(const Identifier &name, ValueImp *value, int attributes)
}
// Create a new hash table entry.
name._ustring.rep->ref();
_table[i].key = name._ustring.rep;
rep->ref();
_table[i].key = rep;
_table[i].value = value;
_table[i].attributes = attributes;
++_keyCount;
......@@ -169,14 +188,16 @@ void PropertyMap::expand()
_tableSizeMask = _tableSize - 1;
_table = (Entry *)calloc(_tableSize, sizeof(Entry));
#if USE_SINGLE_ENTRY
UString::Rep *key = _singleEntry.key;
if (key) {
insert(key, _singleEntry.value, _singleEntry.attributes);
_singleEntry.key = 0;
}
#endif
for (int i = 0; i != oldTableSize; ++i) {
key = oldTable[i].key;
UString::Rep *key = oldTable[i].key;
if (key)
insert(key, oldTable[i].value, oldTable[i].attributes);
}
......@@ -186,22 +207,26 @@ void PropertyMap::expand()
void PropertyMap::remove(const Identifier &name)
{
UString::Rep *rep = name._ustring.rep;
UString::Rep *key;
if (!_table) {
#if USE_SINGLE_ENTRY
key = _singleEntry.key;
if (name._ustring.rep == key) {
if (rep == key) {
key->deref();
_singleEntry.key = 0;
_keyCount = 0;
}
#endif
return;
}
// Find the thing to remove.
int i = hash(name._ustring.rep);
int i = hash(rep);
while ((key = _table[i].key)) {
if (name._ustring.rep == key)
if (rep == key)
break;
i = (i + 1) & _tableSizeMask;
}
......@@ -226,11 +251,13 @@ void PropertyMap::remove(const Identifier &name)
void PropertyMap::mark() const
{
#if USE_SINGLE_ENTRY
if (_singleEntry.key) {
ValueImp *v = _singleEntry.value;
if (!v->marked())
v->mark();
}
#endif
for (int i = 0; i != _tableSize; ++i) {
if (_table[i].key) {
ValueImp *v = _table[i].value;
......@@ -242,9 +269,11 @@ void PropertyMap::mark() const
void PropertyMap::addEnumerablesToReferenceList(ReferenceList &list, const Object &base) const
{
#if USE_SINGLE_ENTRY
UString::Rep *key = _singleEntry.key;
if (key && !(_singleEntry.attributes & DontEnum))
list.append(Reference(base, Identifier(key)));
#endif
for (int i = 0; i != _tableSize; ++i) {
UString::Rep *key = _table[i].key;
if (key && !(_table[i].attributes & DontEnum))
......
......@@ -349,3 +349,23 @@ void List::swap(List &other)
hook = other.hook;
other.hook = tmp;
}
void List::replaceFirst(ValueImp *v)
{
ListNode *n = hook->next;
if (!m_needsMarking) {
v->ref();
n->member->deref();
}
n->member = v;
}
void List::replaceLast(ValueImp *v)
{
ListNode *n = hook->prev;
if (!m_needsMarking) {
v->ref();
n->member->deref();
}
n->member = v;
}
......@@ -183,7 +183,12 @@ namespace KJS {
* function has a @ref KJS::List parameter.
*/
static const List &empty();
void mark();
void replaceFirst(ValueImp *);
void replaceLast(ValueImp *);
private:
void erase(ListNode *n);
......
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