Commit 1a9f113f authored by mjs's avatar mjs

- completed Darin's mostly-fix for 3037795 - Resource use

	increases when accessing very high index value in array

	The two missing pieces were handling sparse properties when
	shrinking the array, and when sorting. Thse are now both taken
	care of.

        * kjs/array_instance.h:
        * kjs/array_object.cpp:
        (ArrayInstanceImp::put):
        (ArrayInstanceImp::deleteProperty):
        (ArrayInstanceImp::resizeStorage):
        (ArrayInstanceImp::setLength):
        (ArrayInstanceImp::sort):
        (ArrayInstanceImp::pushUndefinedObjectsToEnd):
        * kjs/identifier.h:
        * kjs/object.h:
        * kjs/property_map.cpp:
        * kjs/property_map.h:
        * kjs/reference_list.cpp:
        (ReferenceList::append):
        (ReferenceList::length):
        * kjs/reference_list.h:
        * kjs/ustring.cpp:
        (UString::toUInt32):
        * kjs/ustring.h:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@2846 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 5a7a3882
2002-11-23 Maciej Stachowiak <mjs@apple.com>
- completed Darin's mostly-fix for 3037795 - Resource use
increases when accessing very high index value in array
The two missing pieces were handling sparse properties when
shrinking the array, and when sorting. Thse are now both taken
care of.
* kjs/array_instance.h:
* kjs/array_object.cpp:
(ArrayInstanceImp::put):
(ArrayInstanceImp::deleteProperty):
(ArrayInstanceImp::resizeStorage):
(ArrayInstanceImp::setLength):
(ArrayInstanceImp::sort):
(ArrayInstanceImp::pushUndefinedObjectsToEnd):
* kjs/identifier.h:
* kjs/object.h:
* kjs/property_map.cpp:
* kjs/property_map.h:
* kjs/reference_list.cpp:
(ReferenceList::append):
(ReferenceList::length):
* kjs/reference_list.h:
* kjs/ustring.cpp:
(UString::toUInt32):
* kjs/ustring.h:
2002-11-23 Maciej Stachowiak <mjs@apple.com>
Numerous collector changes for a net gain of 3% on JS ibench:
......
2002-11-23 Maciej Stachowiak <mjs@apple.com>
- completed Darin's mostly-fix for 3037795 - Resource use
increases when accessing very high index value in array
The two missing pieces were handling sparse properties when
shrinking the array, and when sorting. Thse are now both taken
care of.
* kjs/array_instance.h:
* kjs/array_object.cpp:
(ArrayInstanceImp::put):
(ArrayInstanceImp::deleteProperty):
(ArrayInstanceImp::resizeStorage):
(ArrayInstanceImp::setLength):
(ArrayInstanceImp::sort):
(ArrayInstanceImp::pushUndefinedObjectsToEnd):
* kjs/identifier.h:
* kjs/object.h:
* kjs/property_map.cpp:
* kjs/property_map.h:
* kjs/reference_list.cpp:
(ReferenceList::append):
(ReferenceList::length):
* kjs/reference_list.h:
* kjs/ustring.cpp:
(UString::toUInt32):
* kjs/ustring.h:
2002-11-23 Maciej Stachowiak <mjs@apple.com>
Numerous collector changes for a net gain of 3% on JS ibench:
......
2002-11-23 Maciej Stachowiak <mjs@apple.com>
- completed Darin's mostly-fix for 3037795 - Resource use
increases when accessing very high index value in array
The two missing pieces were handling sparse properties when
shrinking the array, and when sorting. Thse are now both taken
care of.
* kjs/array_instance.h:
* kjs/array_object.cpp:
(ArrayInstanceImp::put):
(ArrayInstanceImp::deleteProperty):
(ArrayInstanceImp::resizeStorage):
(ArrayInstanceImp::setLength):
(ArrayInstanceImp::sort):
(ArrayInstanceImp::pushUndefinedObjectsToEnd):
* kjs/identifier.h:
* kjs/object.h:
* kjs/property_map.cpp:
* kjs/property_map.h:
* kjs/reference_list.cpp:
(ReferenceList::append):
(ReferenceList::length):
* kjs/reference_list.h:
* kjs/ustring.cpp:
(UString::toUInt32):
* kjs/ustring.h:
2002-11-23 Maciej Stachowiak <mjs@apple.com>
Numerous collector changes for a net gain of 3% on JS ibench:
......
......@@ -52,10 +52,12 @@ namespace KJS {
void sort(ExecState *exec, Object &compareFunction);
private:
void setLength(unsigned newLength);
void setLength(unsigned newLength, ExecState *exec);
unsigned pushUndefinedObjectsToEnd();
unsigned pushUndefinedObjectsToEnd(ExecState *exec);
void resizeStorage(unsigned);
unsigned length;
unsigned storageLength;
unsigned capacity;
......
......@@ -104,7 +104,7 @@ Value ArrayInstanceImp::get(ExecState *exec, unsigned index) const
void ArrayInstanceImp::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr)
{
if (propertyName == lengthPropertyName) {
setLength(value.toUInt32(exec));
setLength(value.toUInt32(exec), exec);
return;
}
......@@ -112,7 +112,7 @@ void ArrayInstanceImp::put(ExecState *exec, const Identifier &propertyName, cons
unsigned index = propertyName.toULong(&ok);
if (ok) {
if (length <= index)
setLength(index + 1);
setLength(index + 1, exec);
if (index < storageLength) {
storage[index] = value.imp();
return;
......@@ -125,7 +125,7 @@ void ArrayInstanceImp::put(ExecState *exec, const Identifier &propertyName, cons
void ArrayInstanceImp::put(ExecState *exec, unsigned index, const Value &value, int attr)
{
if (length <= index)
setLength(index + 1);
setLength(index + 1, exec);
if (index < storageLength) {
storage[index] = value.imp();
return;
......@@ -171,7 +171,7 @@ bool ArrayInstanceImp::deleteProperty(ExecState *exec, const Identifier &propert
return false;
bool ok;
unsigned index = propertyName.toULong(&ok);
uint32_t index = propertyName.toUInt32(&ok);
if (ok) {
if (index >= length)
return true;
......@@ -196,9 +196,8 @@ bool ArrayInstanceImp::deleteProperty(ExecState *exec, unsigned index)
return ObjectImp::deleteProperty(exec, Identifier::from(index));
}
void ArrayInstanceImp::setLength(unsigned newLength)
void ArrayInstanceImp::resizeStorage(unsigned newLength)
{
if (newLength <= sparseArrayCutoff || newLength == length + 1) {
if (newLength < storageLength) {
memset(storage + newLength, 0, sizeof(ValueImp *) * (storageLength - newLength));
}
......@@ -209,10 +208,28 @@ void ArrayInstanceImp::setLength(unsigned newLength)
capacity = newCapacity;
}
storageLength = newLength;
}
void ArrayInstanceImp::setLength(unsigned newLength, ExecState *exec)
{
if (newLength <= MAX(sparseArrayCutoff,storageLength) || newLength == length + 1) {
resizeStorage(newLength);
}
if (newLength < length) {
ReferenceList sparseProperties;
_prop.addSparseArrayPropertiesToReferenceList(sparseProperties, Object(this));
ReferenceListIterator it = sparseProperties.begin();
while (it != sparseProperties.end()) {
Reference ref = it++;
bool ok;
if (ref.getPropertyName(exec).toULong(&ok) > newLength) {
ref.deleteValue(exec);
}
}
}
// FIXME: Need to remove items from the property map when making a sparse
// list shorter.
length = newLength;
}
......@@ -238,7 +255,7 @@ static int compareByStringForQSort(const void *a, const void *b)
void ArrayInstanceImp::sort(ExecState *exec)
{
int lengthNotIncludingUndefined = pushUndefinedObjectsToEnd();
int lengthNotIncludingUndefined = pushUndefinedObjectsToEnd(exec);
execForCompareByStringForQSort = exec;
qsort(storage, lengthNotIncludingUndefined, sizeof(ValueImp *), compareByStringForQSort);
......@@ -276,7 +293,7 @@ static int compareWithCompareFunctionForQSort(const void *a, const void *b)
void ArrayInstanceImp::sort(ExecState *exec, Object &compareFunction)
{
int lengthNotIncludingUndefined = pushUndefinedObjectsToEnd();
int lengthNotIncludingUndefined = pushUndefinedObjectsToEnd(exec);
CompareWithCompareFunctionArguments args(exec, compareFunction.imp());
compareWithCompareFunctionArguments = &args;
......@@ -284,7 +301,7 @@ void ArrayInstanceImp::sort(ExecState *exec, Object &compareFunction)
compareWithCompareFunctionArguments = 0;
}
unsigned ArrayInstanceImp::pushUndefinedObjectsToEnd()
unsigned ArrayInstanceImp::pushUndefinedObjectsToEnd(ExecState *exec)
{
ValueImp *undefined = UndefinedImp::staticUndefined;
......@@ -299,9 +316,23 @@ unsigned ArrayInstanceImp::pushUndefinedObjectsToEnd()
}
}
// FIXME: Get sparse items down here.
ReferenceList sparseProperties;
_prop.addSparseArrayPropertiesToReferenceList(sparseProperties, Object(this));
unsigned newLength = o + sparseProperties.length();
if (newLength > storageLength) {
resizeStorage(newLength);
}
ReferenceListIterator it = sparseProperties.begin();
while (it != sparseProperties.end()) {
Reference ref = it++;
storage[o] = ref.getValue(exec).imp();
ObjectImp::deleteProperty(exec, ref.getPropertyName(exec));
o++;
}
if (o != storageLength)
if (newLength != storageLength)
memset(storage + o, 0, sizeof(ValueImp *) * (storageLength - o));
return o;
......
......@@ -49,6 +49,7 @@ namespace KJS {
bool isEmpty() const { return _ustring.isEmpty(); }
unsigned long toULong(bool *ok) const { return _ustring.toULong(ok); }
uint32_t toUInt32(bool *ok) const { return _ustring.toUInt32(ok); }
double toDouble() const { return _ustring.toDouble(); }
static Identifier null;
......
......@@ -597,9 +597,10 @@ namespace KJS {
void saveProperties(SavedProperties &p) const { _prop.save(p); }
void restoreProperties(const SavedProperties &p) { _prop.restore(p); }
protected:
PropertyMap _prop;
private:
const HashEntry* findPropertyHashEntry( const Identifier& propertyName ) const;
PropertyMap _prop;
ValueImp *_proto;
ValueImp *_internalValue;
NoRefScopeChain _scope;
......
......@@ -369,6 +369,36 @@ void PropertyMap::addEnumerablesToReferenceList(ReferenceList &list, const Objec
}
}
void PropertyMap::addSparseArrayPropertiesToReferenceList(ReferenceList &list, const Object &base) const
{
#if USE_SINGLE_ENTRY
UString::Rep *key = _singleEntry.key;
if (key) {
UString k(key);
bool fitsInUInt32;
k.toUInt32(&fitsInUInt32);
if (fitsInUInt32) {
list.append(Reference(base, Identifier(key)));
}
}
#endif
if (!_table) {
return;
}
for (int i = 0; i != _table->size; ++i) {
UString::Rep *key = _table->entries[i].key;
if (key) {
UString k(key);
bool fitsInUInt32;
k.toUInt32(&fitsInUInt32);
if (fitsInUInt32) {
list.append(Reference(base, Identifier(key)));
}
}
}
}
void PropertyMap::save(SavedProperties &p) const
{
int count = 0;
......
......@@ -71,6 +71,7 @@ namespace KJS {
void mark() const;
void addEnumerablesToReferenceList(ReferenceList &, const Object &) const;
void addSparseArrayPropertiesToReferenceList(ReferenceList &, const Object &) const;
void save(SavedProperties &) const;
void restore(const SavedProperties &p);
......
......@@ -41,6 +41,7 @@ namespace KJS {
ReferenceListHeadNode(const Reference &ref) : ReferenceListNode(ref), refcount(1) {}
int refcount;
int length;
};
}
......@@ -92,6 +93,12 @@ void ReferenceList::append(const Reference& ref)
tail->next = new ReferenceListNode(ref);
tail = tail->next;
}
head->length++;
}
int ReferenceList::length()
{
return head ? head->length : 0;
}
ReferenceList::~ReferenceList()
......
......@@ -53,7 +53,8 @@ namespace KJS {
~ReferenceList();
void append(const Reference& val);
int length();
ReferenceListIterator begin() const;
ReferenceListIterator end() const;
......
......@@ -551,6 +551,22 @@ unsigned long UString::toULong(bool *ok) const
return static_cast<unsigned long>(d);
}
uint32_t UString::toUInt32(bool *ok) const
{
double d = toDouble();
bool b = true;
if (isNaN(d) || d != static_cast<uint32_t>(d)) {
b = false;
d = 0;
}
if (ok)
*ok = b;
return static_cast<uint32_t>(d);
}
int UString::find(const UString &f, int pos) const
{
int sz = size();
......
......@@ -32,6 +32,8 @@ typedef unsigned long ulong;
#endif
#endif
#include <stdint.h>
/**
* @internal
*/
......@@ -383,6 +385,9 @@ namespace KJS {
* according to the success.
*/
unsigned long toULong(bool *ok = 0L) const;
uint32_t toUInt32(bool *ok = 0L) const;
/**
* @return Position of first occurence of f starting at position pos.
* -1 if the search was not successful.
......
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