[SCM] WebKit Debian packaging branch, debian/unstable, updated. debian/1.1.15-1-40151-g37bb677
darin
darin at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 07:03:35 UTC 2009
The following commit has been merged in the debian/unstable branch:
commit a6cae2cce86fd79a4e6623a3e8f9e16528624c5b
Author: darin <darin at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Tue Nov 19 06:53:35 2002 +0000
- property and string improvements giving a 7% or so improvement in JavaScript iBench
* kjs/property_map.h: Rewrite to use a hash table.
* kjs/property_map.cpp: Ditto.
* kjs/string_object.h:
* kjs/string_object.cpp:
(StringInstanceImp::StringInstanceImp): Construct a string with the right value
instead of putting the string in later.
(StringInstanceImp::get): Get the length from the string, not a separate property.
(StringInstanceImp::put): Ignore attempts to set length, since we don't put it in
the property map.
(StringInstanceImp::hasProperty): Return true for length.
(StringInstanceImp::deleteProperty): Return false for length.
(StringObjectImp::construct): Call new StringInstanceImp constructor. Don't try
to set a length property.
* kjs/ustring.h: Make the rep deref know how to deallocate the rep.
* kjs/ustring.cpp:
(UString::release): Move the real work to the rep's deref, since the hash table
now uses the rep directly.
* kjs/object.h: Remove unused field.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@2749 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index b6c40df..07a7760 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,29 @@
+2002-11-18 Darin Adler <darin at apple.com>
+
+ - property and string improvements giving a 7% or so improvement in JavaScript iBench
+
+ * kjs/property_map.h: Rewrite to use a hash table.
+ * kjs/property_map.cpp: Ditto.
+
+ * kjs/string_object.h:
+ * kjs/string_object.cpp:
+ (StringInstanceImp::StringInstanceImp): Construct a string with the right value
+ instead of putting the string in later.
+ (StringInstanceImp::get): Get the length from the string, not a separate property.
+ (StringInstanceImp::put): Ignore attempts to set length, since we don't put it in
+ the property map.
+ (StringInstanceImp::hasProperty): Return true for length.
+ (StringInstanceImp::deleteProperty): Return false for length.
+ (StringObjectImp::construct): Call new StringInstanceImp constructor. Don't try
+ to set a length property.
+
+ * kjs/ustring.h: Make the rep deref know how to deallocate the rep.
+ * kjs/ustring.cpp:
+ (UString::release): Move the real work to the rep's deref, since the hash table
+ now uses the rep directly.
+
+ * kjs/object.h: Remove unused field.
+
2002-11-18 Maciej Stachowiak <mjs at apple.com>
Change List to completely avoid going through the GC
diff --git a/JavaScriptCore/ChangeLog-2002-12-03 b/JavaScriptCore/ChangeLog-2002-12-03
index b6c40df..07a7760 100644
--- a/JavaScriptCore/ChangeLog-2002-12-03
+++ b/JavaScriptCore/ChangeLog-2002-12-03
@@ -1,3 +1,29 @@
+2002-11-18 Darin Adler <darin at apple.com>
+
+ - property and string improvements giving a 7% or so improvement in JavaScript iBench
+
+ * kjs/property_map.h: Rewrite to use a hash table.
+ * kjs/property_map.cpp: Ditto.
+
+ * kjs/string_object.h:
+ * kjs/string_object.cpp:
+ (StringInstanceImp::StringInstanceImp): Construct a string with the right value
+ instead of putting the string in later.
+ (StringInstanceImp::get): Get the length from the string, not a separate property.
+ (StringInstanceImp::put): Ignore attempts to set length, since we don't put it in
+ the property map.
+ (StringInstanceImp::hasProperty): Return true for length.
+ (StringInstanceImp::deleteProperty): Return false for length.
+ (StringObjectImp::construct): Call new StringInstanceImp constructor. Don't try
+ to set a length property.
+
+ * kjs/ustring.h: Make the rep deref know how to deallocate the rep.
+ * kjs/ustring.cpp:
+ (UString::release): Move the real work to the rep's deref, since the hash table
+ now uses the rep directly.
+
+ * kjs/object.h: Remove unused field.
+
2002-11-18 Maciej Stachowiak <mjs at apple.com>
Change List to completely avoid going through the GC
diff --git a/JavaScriptCore/ChangeLog-2003-10-25 b/JavaScriptCore/ChangeLog-2003-10-25
index b6c40df..07a7760 100644
--- a/JavaScriptCore/ChangeLog-2003-10-25
+++ b/JavaScriptCore/ChangeLog-2003-10-25
@@ -1,3 +1,29 @@
+2002-11-18 Darin Adler <darin at apple.com>
+
+ - property and string improvements giving a 7% or so improvement in JavaScript iBench
+
+ * kjs/property_map.h: Rewrite to use a hash table.
+ * kjs/property_map.cpp: Ditto.
+
+ * kjs/string_object.h:
+ * kjs/string_object.cpp:
+ (StringInstanceImp::StringInstanceImp): Construct a string with the right value
+ instead of putting the string in later.
+ (StringInstanceImp::get): Get the length from the string, not a separate property.
+ (StringInstanceImp::put): Ignore attempts to set length, since we don't put it in
+ the property map.
+ (StringInstanceImp::hasProperty): Return true for length.
+ (StringInstanceImp::deleteProperty): Return false for length.
+ (StringObjectImp::construct): Call new StringInstanceImp constructor. Don't try
+ to set a length property.
+
+ * kjs/ustring.h: Make the rep deref know how to deallocate the rep.
+ * kjs/ustring.cpp:
+ (UString::release): Move the real work to the rep's deref, since the hash table
+ now uses the rep directly.
+
+ * kjs/object.h: Remove unused field.
+
2002-11-18 Maciej Stachowiak <mjs at apple.com>
Change List to completely avoid going through the GC
diff --git a/JavaScriptCore/kjs/object.h b/JavaScriptCore/kjs/object.h
index b835a5f..1f93e1e 100644
--- a/JavaScriptCore/kjs/object.h
+++ b/JavaScriptCore/kjs/object.h
@@ -43,7 +43,6 @@
namespace KJS {
- class ObjectImpPrivate;
class PropertyMap;
class HashTable;
class HashEntry;
@@ -583,7 +582,6 @@ namespace KJS {
ValueImp* getDirect(const UString& propertyName) const;
private:
const HashEntry* findPropertyHashEntry( const UString& propertyName ) const;
- ObjectImpPrivate *_od;
PropertyMap *_prop;
ValueImp *_proto;
ValueImp *_internalValue;
diff --git a/JavaScriptCore/kjs/property_map.cpp b/JavaScriptCore/kjs/property_map.cpp
index a938b39..41cf8b6 100644
--- a/JavaScriptCore/kjs/property_map.cpp
+++ b/JavaScriptCore/kjs/property_map.cpp
@@ -1,7 +1,7 @@
// -*- c-basic-offset: 2 -*-
/*
* This file is part of the KDE libraries
- * Copyright (C) 2001 Peter Kelly (pmk at post.com)
+ * Copyright (C) 2002 Darin Adler (darin at apple.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -20,593 +20,261 @@
*
*/
-
#include "property_map.h"
#include "object.h"
#include "reference_list.h"
-#include <string.h>
-#include <assert.h>
-#include <stdio.h>
-
namespace KJS {
-// ------------------------------ PropertyMapNode ------------------------------
-
- class PropertyMapNode {
- public:
- PropertyMapNode(const UString &n, ValueImp *v, int att, PropertyMapNode *p)
- : name(n), value(v), attr(att), left(0), right(0), parent(p), height(1) {}
-
- UString name;
- ValueImp *value;
- int attr;
-
- void setLeft(PropertyMapNode *newLeft);
- void setRight(PropertyMapNode *newRight);
- PropertyMapNode *findMax();
- PropertyMapNode *findMin();
-
- PropertyMapNode *next();
-
- PropertyMapNode *left;
- PropertyMapNode *right;
- PropertyMapNode *parent;
- int height;
-
- private:
- void setParent(PropertyMapNode *newParent);
- };
-
-void PropertyMapNode::setLeft(PropertyMapNode *newLeft)
-{
- if (left)
- left->setParent(0);
- left = newLeft;
- if (left)
- left->setParent(this);
-}
-
-void PropertyMapNode::setRight(PropertyMapNode *newRight)
-{
- if (right)
- right->setParent(0);
- right = newRight;
- if (right)
- right->setParent(this);
-}
-
-void PropertyMapNode::setParent(PropertyMapNode *newParent)
-{
- if (parent) {
- //assert(this == parent->left || this == parent->right);
- if (this == parent->left)
- parent->left = 0;
- else
- parent->right = 0;
- }
- parent = newParent;
-}
-
-PropertyMapNode *PropertyMapNode::findMax()
-{
- PropertyMapNode *max = this;
- while (max->right)
- max = max->right;
- return max;
-}
-
-PropertyMapNode *PropertyMapNode::findMin()
-{
- PropertyMapNode *min = this;
- while (min->left)
- min = min->left;
- return min;
-}
-
-PropertyMapNode *PropertyMapNode::next()
-{
- // find the next node, going from lowest name to highest name
-
- // We have a right node. Starting from our right node, keep going left as far as we can
- if (right) {
- PropertyMapNode *n = right;
- while (n->left)
- n = n->left;
- return n;
- }
-
- // We have no right node. Keep going up to the left, until we find a node that has a parent
- // to the right. If we find one, go to it. Otherwise, we have reached the end.
- PropertyMapNode *n = this;
- while (n->parent && n->parent->right == n) {
- // parent is to our left
- n = n->parent;
- }
- if (n->parent && n->parent->left == n) {
- // parent is to our right
- return n->parent;
- }
-
- return 0;
-}
-
-// ------------------------------ PropertyMap ----------------------------------
+// Algorithm concepts from Algorithms in C++, Sedgewick.
-int KJS::uscompare(const UString &s1, const UString &s2)
+PropertyMap::PropertyMap() : _tableSize(0), _table(0), _keyCount(0)
{
- int len1 = s1.size();
- int len2 = s2.size();
- if (len1 < len2)
- return -1;
- else if (len1 > len2)
- return 1;
- else
- return memcmp(s1.data(), s2.data(), len1*sizeof(UChar));
-}
-
-PropertyMap::PropertyMap()
-{
- root = 0;
}
PropertyMap::~PropertyMap()
{
- clear();
+ //printf("key count is %d\n", _keyCount);
+ UString::Rep *key = _singleEntry.key;
+ if (key)
+ key->deref();
+ for (int i = 0; i < _tableSize; i++) {
+ key = _table[i].key;
+ if (key)
+ key->deref();
+ }
+ free(_table);
}
-void PropertyMap::put(const UString &name, ValueImp *value, int attr)
+void PropertyMap::clear()
{
- // if not root; make the root the new node
- if (!root) {
- root = new PropertyMapNode(name, value, attr, 0);
- return;
- }
-
- // try to find the parent node
- PropertyMapNode *parent = root;
- int isLeft = false;
- while (true) {
- int cmp = uscompare(name, parent->name);
- if (cmp < 0) {
- // traverse to left node (if any)
- isLeft = true;
- if (!parent->left)
- break;
- else
- parent = parent->left;
+ UString::Rep *key = _singleEntry.key;
+ if (key) {
+ key->deref();
+ _singleEntry.key = 0;
}
- else if (cmp > 0) {
- // traverse to right node (if any)
- isLeft = false;
- if (!parent->right)
- break;
- else
- parent = parent->right;
+ for (int i = 0; i < _tableSize; i++) {
+ UString::Rep *key = _table[i].key;
+ if (key) {
+ key->deref();
+ _table[i].key = 0;
+ }
}
- else {
- // a node with this name already exists; just replace the value
- parent->value = value;
- return;
- }
- }
-
- // we found the parent
- //assert(parent);
-
- if (isLeft) {
- //assert(!parent->left);
- parent->left = new PropertyMapNode(name, value, attr, parent);
- }
- else {
- //assert(!parent->right);
- parent->right = new PropertyMapNode(name, value, attr, parent);
- }
- updateHeight(parent);
-
-
- PropertyMapNode *node = parent;
- while (node) {
- PropertyMapNode *p = node->parent;
- balance(node); // may change node
- node = p;
- }
+ _keyCount = 0;
}
-void PropertyMap::remove(const UString &name)
+int PropertyMap::hash(const UString::Rep *s) const
{
- PropertyMapNode *node = getNode(name);
- if (!node) // name not in tree
- return;
-
- PropertyMapNode *removed = remove(node);
- if (removed)
- delete node;
+ int h = 0;
+ int length = s->len;
+ int prefixLength = length < 8 ? length : 8;
+ for (int i = 0; i < prefixLength; i++)
+ h = (127 * h + s->dat[i].unicode()) & _tableSizeHashMask;
+ int suffixPosition = length < 16 ? 8 : length - 8;
+ for (int i = suffixPosition; i < length; i++)
+ h = (127 * h + s->dat[i].unicode()) & _tableSizeHashMask;
+ return h;
}
-ValueImp *PropertyMap::get(const UString &name) const
+bool PropertyMap::keysMatch(const UString::Rep *a, const UString::Rep *b)
{
- const PropertyMapNode *n = getNode(name);
- return n ? n->value : 0;
+ 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;
}
ValueImp *PropertyMap::get(const UString &name, int &attributes) const
{
- const PropertyMapNode *n = getNode(name);
- attributes = n ? n->attr : 0;
- return n ? n->value : 0;
-}
-
-void PropertyMap::clear()
-{
- clear(0);
-}
-
-void PropertyMap::mark()
-{
- PropertyMapNode *node = first();
- while (node) {
- if (!node->value->marked())
- node->value->mark();
- node = node->next();
- }
-}
-
-void PropertyMap::addEnumerablesToReferenceList(ReferenceList &list, const Object &base) const
-{
- PropertyMapNode *node = first();
- while (node) {
- if (!(node->attr & DontEnum))
- list.append(Reference(base, node->name));
- node = node->next();
- }
-}
-
-void PropertyMap::clear(PropertyMapNode *node)
-{
- if (node == 0)
- node = root;
- if (node == 0) // nothing to do
- return;
-
- if (node->left)
- clear(node->left);
- if (node->right)
- clear(node->right);
- if (node == root)
- root = 0;
- delete node;
-}
-
-void PropertyMap::dump(const PropertyMapNode *node, int indent) const
-{
- if (!node && indent > 0)
- return;
- if (!node)
- node = root;
- if (!node)
- return;
-
- assert(!node->right || node->right->parent == node);
- dump(node->right, indent+1);
- for (int i = 0; i < indent; i++) {
- printf(" ");
- }
- printf("[%d] %s\n", node->height, node->name.ascii());
- assert(!node->left || node->left->parent == node);
- dump(node->left, indent+1);
-}
-
-void PropertyMap::checkTree(const PropertyMapNode *node) const
-{
- if (!root)
- return;
- if (node == 0)
- node = root;
- if (node == root) {
- assert(!node->parent);
- }
- assert(!node->right || node->right->parent == node);
- assert(!node->left || node->left->parent == node);
- assert(node->left != node);
- assert(node->right != node);
- if (node->left && node->right)
- assert(node->left != node->right);
-
- PropertyMapNode *n = node->parent;
- while (n) {
- assert(n != node);
- n = n->parent;
- }
-
- if (node->right)
- checkTree(node->right);
- if (node->left)
- checkTree(node->left);
-}
-
-PropertyMapNode *PropertyMap::getNode(const UString &name) const
-{
- PropertyMapNode *node = root;
-
- while (true) {
- if (!node)
- return 0;
-
- int cmp = uscompare(name, node->name);
- if (cmp < 0)
- node = node->left;
- else if (cmp > 0)
- node = node->right;
- else
- return node;
- }
-}
-
-PropertyMapNode *PropertyMap::first() const
-{
- if (!root)
+ if (!_table) {
+ UString::Rep *key = _singleEntry.key;
+ if (key && keysMatch(name.rep, key)) {
+ attributes = _singleEntry.attributes;
+ return _singleEntry.value;
+ }
+ return 0;
+ }
+
+ int i = hash(name.rep);
+ while (UString::Rep *key = _table[i].key) {
+ if (keysMatch(name.rep, key)) {
+ attributes = _table[i].attributes;
+ return _table[i].value;
+ }
+ i = (i + 1) % _tableSize;
+ }
return 0;
-
- PropertyMapNode *node = root;
- while (node->left)
- node = node->left;
- return node;
}
-PropertyMapNode * PropertyMap::remove(PropertyMapNode *node)
+ValueImp *PropertyMap::get(const UString &name) const
{
- PropertyMapNode *parent = node->parent;
- //assert(!parent || (node == parent->left || node == parent->right));
- bool isLeft = (parent && node == parent->left);
-
- PropertyMapNode *replace = 0;
- if (node->left && node->right) {
- PropertyMapNode *maxLeft = node->left->findMax();
- if (maxLeft == node->left) {
- maxLeft->setRight(node->right);
- replace = maxLeft;
+ if (!_table) {
+ UString::Rep *key = _singleEntry.key;
+ if (key && keysMatch(name.rep, key))
+ return _singleEntry.value;
+ return 0;
}
- else {
- remove(maxLeft);
-
- maxLeft->setLeft(node->left);
- maxLeft->setRight(node->right);
- replace = maxLeft;
+
+ int i = hash(name.rep);
+ while (UString::Rep *key = _table[i].key) {
+ if (keysMatch(name.rep, key))
+ return _table[i].value;
+ i = (i + 1) % _tableSize;
}
- // removing maxLeft could have re-balanced the tree, so recalculate
- // parent again
- parent = node->parent;
- //assert(!parent || (node == parent->left || node == parent->right));
- isLeft = (parent && node == parent->left);
- }
- else if (node->left) {
- replace = node->left;
- }
- else if (node->right) {
- replace = node->right;
- }
- else {
- replace = 0;
- }
-
- if (parent) {
- if (isLeft)
- parent->setLeft(replace);
- else
- parent->setRight(replace);
- }
- else {
- root = replace;
- if (replace)
- replace->parent = 0;
- }
-
- if (replace)
- updateHeight(replace); // will also update parent's height
- else if (parent)
- updateHeight(parent);
- else if (root)
- updateHeight(root);
-
-
- // balance the tree
- PropertyMapNode *bal = parent;
- while (bal) {
- PropertyMapNode *p = bal->parent;
- balance(bal); // may change bal
- bal = p;
- }
-
- return node;
+ return 0;
}
-void PropertyMap::balance(PropertyMapNode* node)
+void PropertyMap::put(const UString &name, ValueImp *value, int attributes)
{
- int lheight = node->left ? node->left->height : 0;
- int rheight = node->right ? node->right->height : 0;
-
- int bal = rheight-lheight;
-
- if (bal < -1) {
- //assert(node->left);
- int llheight = node->left->left ? node->left->left->height : 0;
- int lrheight = node->left->right ? node->left->right->height : 0;
- int lbal = lrheight - llheight;
-
- if (lbal < 0) {
- rotateLL(node); // LL rotation
+ if (!_table) {
+ UString::Rep *key = _singleEntry.key;
+ if (key) {
+ if (keysMatch(name.rep, key)) {
+ _singleEntry.value = value;
+ return;
+ }
+ } else {
+ name.rep->ref();
+ _singleEntry.key = name.rep;
+ _singleEntry.value = value;
+ _singleEntry.attributes = attributes;
+ _keyCount = 1;
+ return;
+ }
}
- else {
- // lbal >= 0
- rotateLR(node);
- }
- }
- else if (bal > 1) {
- int rlheight = node->right->left ? node->right->left->height : 0;
- int rrheight = node->right->right ? node->right->right->height : 0;
- int rbal = rrheight - rlheight;
- if (rbal < 0) {
- rotateRL(node);
- }
- else {
- // rbal >= 0
- rotateRR(node); // RR rotateion
+
+ if (_keyCount >= _tableSize / 2)
+ expand();
+
+ int i = hash(name.rep);
+ while (UString::Rep *key = _table[i].key) {
+ if (keysMatch(name.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) % _tableSize;
}
- }
+
+ // Create a new hash table entry.
+ name.rep->ref();
+ _table[i].key = name.rep;
+ _table[i].value = value;
+ _table[i].attributes = attributes;
+ ++_keyCount;
}
-void PropertyMap::updateHeight(PropertyMapNode* &node)
+inline void PropertyMap::insert(UString::Rep *key, ValueImp *value, int attributes)
{
- int lheight = node->left ? node->left->height : 0;
- int rheight = node->right ? node->right->height : 0;
- if (lheight > rheight)
- node->height = lheight+1;
- else
- node->height = rheight+1;
- //assert(node->parent != node);
- if (node->parent)
- updateHeight(node->parent);
+ int i = hash(key);
+ while (_table[i].key)
+ i = (i + 1) % _tableSize;
+
+ _table[i].key = key;
+ _table[i].value = value;
+ _table[i].attributes = attributes;
}
-void PropertyMap::rotateRR(PropertyMapNode* &node)
+void PropertyMap::expand()
{
- /*
- Perform a RR ("single left") rotation, e.g.
+ int oldTableSize = _tableSize;
+ Entry *oldTable = _table;
- a b
- / \ / \
- X b --> a Z
- / \ / \
- Y Z X Y
- */
+ _tableSize = oldTableSize ? oldTableSize * 2 : 16;
+ _tableSizeHashMask = _tableSize - 1;
+ _table = (Entry *)calloc(_tableSize, sizeof(Entry));
- // Here, node is initially a, will be replaced with b
-
- PropertyMapNode *a = node;
- PropertyMapNode *b = node->right;
-
- PropertyMapNode *parent = a->parent;
- //assert(!parent || (a == parent->left || a == parent->right));
- bool isLeft = (parent && a == parent->left);
-
- // do the rotation
- a->setRight(b->left);
- b->setLeft(a);
-
- // now node is b
- node = b;
- if (parent) {
- if (isLeft)
- parent->setLeft(b);
- else
- parent->setRight(b);
- }
- else {
- // a was the root node
- root = b;
- }
+ UString::Rep *key = _singleEntry.key;
+ if (key) {
+ insert(key, _singleEntry.value, _singleEntry.attributes);
+ _singleEntry.key = 0;
+ }
+
+ for (int i = 0; i != oldTableSize; ++i) {
+ key = oldTable[i].key;
+ if (key)
+ insert(key, oldTable[i].value, oldTable[i].attributes);
+ }
- updateHeight(a);
- updateHeight(b);
+ free(oldTable);
}
-
-void PropertyMap::rotateLL(PropertyMapNode* &node)
+void PropertyMap::remove(const UString &name)
{
- /*
- Perform a LL ("single right") rotation, e.g.
-
-
- a b
- / \ / \
- b Z --> X a
- / \ / \
- X Y Y Z
- */
-
- // Here, node is initially a, will be replaced with b
-
- PropertyMapNode *a = node;
- PropertyMapNode *b = node->left;
-
- PropertyMapNode *parent = a->parent;
- //assert(!parent || (a == parent->left || a == parent->right));
- bool isLeft = (parent && a == parent->left);
-
- // do the rotation
- a->setLeft(b->right);
- b->setRight(a);
-
- // now node is b
- node = b;
- if (parent) {
- if (isLeft)
- parent->setLeft(b);
- else
- parent->setRight(b);
- }
- else {
- // a was the root node
- root = b;
- }
+ UString::Rep *key;
+
+ if (!_table) {
+ key = _singleEntry.key;
+ if (key && keysMatch(name.rep, key)) {
+ key->deref();
+ _singleEntry.key = 0;
+ _keyCount = 0;
+ }
+ return;
+ }
- updateHeight(a);
- updateHeight(b);
+ // Find the thing to remove.
+ int i = hash(name.rep);
+ while ((key = _table[i].key)) {
+ if (keysMatch(name.rep, key))
+ break;
+ i = (i + 1) % _tableSize;
+ }
+ if (!key)
+ return;
+
+ // Remove the one key.
+ key->deref();
+ _table[i].key = 0;
+ --_keyCount;
+
+ // Reinsert all the items to the right in the same cluster.
+ while (1) {
+ i = (i + 1) % _tableSize;
+ key = _table[i].key;
+ if (!key)
+ break;
+ _table[i].key = 0;
+ insert(key, _table[i].value, _table[i].attributes);
+ }
}
-void PropertyMap::rotateRL(PropertyMapNode* &node)
+void PropertyMap::mark() const
{
- /*
- Perform a RL ("double left") rotation, e.g.
-
- a a b
- / \ LL on c / \ RR on b / \
- W c --> W b --> a c
- / \ / \ / \ / \
- b Z X c W X Y Z
- / \ / \
- X Y Y Z
-
- */
-
- PropertyMapNode *a = node;
- PropertyMapNode *c = node->right;
- PropertyMapNode *b = node->right->left;
-
- rotateLL(c);
- rotateRR(b);
-
- updateHeight(a);
- updateHeight(c);
- updateHeight(b);
+ if (_singleEntry.key) {
+ ValueImp *v = _singleEntry.value;
+ if (!v->marked())
+ v->mark();
+ }
+ for (int i = 0; i != _tableSize; ++i) {
+ if (_table[i].key) {
+ ValueImp *v = _table[i].value;
+ if (!v->marked())
+ v->mark();
+ }
+ }
}
-void PropertyMap::rotateLR(PropertyMapNode* &node)
+void PropertyMap::addEnumerablesToReferenceList(ReferenceList &list, const Object &base) const
{
- /*
- Perform a LR ("double right") rotation, e.g.
-
- a a b
- / \ RR on c / \ LL on a / \
- c Z --> b Z --> c a
- / \ / \ / \ / \
- W b c Y W X Y Z
- / \ / \
- X Y W X
- */
-
- PropertyMapNode *a = node;
- PropertyMapNode *c = node->left;
- PropertyMapNode *b = node->left->right;
-
- rotateRR(c);
- rotateLL(a);
-
- updateHeight(c);
- updateHeight(a);
- updateHeight(b);
+ UString::Rep *key = _singleEntry.key;
+ if (key && !(_singleEntry.attributes & DontEnum))
+ list.append(Reference(base, key));
+ for (int i = 0; i != _tableSize; ++i) {
+ UString::Rep *key = _table[i].key;
+ if (key && !(_table[i].attributes & DontEnum))
+ list.append(Reference(base, key));
+ }
}
} // namespace KJS
diff --git a/JavaScriptCore/kjs/property_map.h b/JavaScriptCore/kjs/property_map.h
index fcbf5c8..2c275ce 100644
--- a/JavaScriptCore/kjs/property_map.h
+++ b/JavaScriptCore/kjs/property_map.h
@@ -1,7 +1,7 @@
// -*- c-basic-offset: 2 -*-
/*
* This file is part of the KDE libraries
- * Copyright (C) 2001 Peter Kelly (pmk at post.com)
+ * Copyright (C) 2002 Darin Adler (darin at apple.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -20,66 +20,56 @@
*
*/
-
#ifndef _KJS_PROPERTY_MAP_H_
#define _KJS_PROPERTY_MAP_H_
#include "ustring.h"
-#include "value.h"
namespace KJS {
- class PropertyMapNode;
- class ReferenceList;
-
- /**
- * @internal
- *
- * Provides a name/value map for storing properties based on UString keys. The
- * map is implemented using an AVL tree, which provides O(log2 n) performance
- * for insertion and deletion, and retrieval.
- *
- * For a description of AVL tree operations, see
- * http://www.cis.ksu.edu/~howell/300f99/minavl/rotations.html
- * http://www.cgc.cs.jhu.edu/~jkloss/htmls/structures/avltree.html
- */
- class PropertyMap {
- public:
- PropertyMap();
- ~PropertyMap();
-
- void put(const UString &name, ValueImp *value, int attr);
- void remove(const UString &name);
- ValueImp *get(const UString &name) const;
- ValueImp *get(const UString &name, int &attributes) const;
+ class Object;
+ class ReferenceList;
+ class ValueImp;
- void clear();
- void mark();
+ struct PropertyMapHashTableEntry
+ {
+ PropertyMapHashTableEntry() : key(0) { }
+ UString::Rep *key;
+ ValueImp *value;
+ int attributes;
+ };
- void addEnumerablesToReferenceList(ReferenceList &, const Object &) const;
-
- private:
-
- void clear(PropertyMapNode *node);
- void dump(const PropertyMapNode *node = 0, int indent = 0) const;
- void checkTree(const PropertyMapNode *node = 0) const;
-
- PropertyMapNode *getNode(const UString &name) const;
- PropertyMapNode *first() const;
-
- PropertyMapNode *remove(PropertyMapNode *node);
- void balance(PropertyMapNode* node);
- void updateHeight(PropertyMapNode* &node);
-
- void rotateRR(PropertyMapNode* &node);
- void rotateLL(PropertyMapNode* &node);
- void rotateRL(PropertyMapNode* &node);
- void rotateLR(PropertyMapNode* &node);
-
- PropertyMapNode *root;
- };
-
- int uscompare(const UString &s1, const UString &s2);
+ class PropertyMap {
+ public:
+ PropertyMap();
+ ~PropertyMap();
+
+ void clear();
+
+ void put(const UString &name, ValueImp *value, int attributes);
+ void remove(const UString &name);
+ ValueImp *get(const UString &name) const;
+ ValueImp *get(const UString &name, int &attributes) const;
+
+ void mark() const;
+ void addEnumerablesToReferenceList(ReferenceList &, const Object &) const;
+
+ private:
+ int hash(const UString::Rep *) const;
+ static bool keysMatch(const UString::Rep *, const UString::Rep *);
+ void expand();
+
+ void insert(UString::Rep *, ValueImp *value, int attributes);
+
+ typedef PropertyMapHashTableEntry Entry;
+
+ int _tableSizeHashMask;
+ int _tableSize;
+ Entry *_table;
+ int _keyCount;
+
+ Entry _singleEntry;
+ };
}; // namespace
diff --git a/JavaScriptCore/kjs/string_object.cpp b/JavaScriptCore/kjs/string_object.cpp
index 480c933..3864ba0 100644
--- a/JavaScriptCore/kjs/string_object.cpp
+++ b/JavaScriptCore/kjs/string_object.cpp
@@ -43,6 +43,40 @@ StringInstanceImp::StringInstanceImp(const Object &proto)
setInternalValue(String(""));
}
+StringInstanceImp::StringInstanceImp(const Object &proto, const UString &string)
+ : ObjectImp(proto)
+{
+ setInternalValue(String(string));
+}
+
+Value StringInstanceImp::get(ExecState *exec, const UString &propertyName) const
+{
+ if (propertyName == lengthPropertyName)
+ return Number(internalValue().toString(exec).size());
+ return ObjectImp::get(exec, propertyName);
+}
+
+void StringInstanceImp::put(ExecState *exec, const UString &propertyName, const Value &value, int attr)
+{
+ if (propertyName == lengthPropertyName)
+ return;
+ ObjectImp::put(exec, propertyName, value, attr);
+}
+
+bool StringInstanceImp::hasProperty(ExecState *exec, const UString &propertyName) const
+{
+ if (propertyName == lengthPropertyName)
+ return true;
+ return ObjectImp::hasProperty(exec, propertyName);
+}
+
+bool StringInstanceImp::deleteProperty(ExecState *exec, const UString &propertyName)
+{
+ if (propertyName == lengthPropertyName)
+ return false;
+ return ObjectImp::deleteProperty(exec, propertyName);
+}
+
// ------------------------------ StringPrototypeImp ---------------------------
const ClassInfo StringPrototypeImp::info = {"String", &StringInstanceImp::info, &stringTable, 0};
/* Source for string_object.lut.h
@@ -516,18 +550,9 @@ bool StringObjectImp::implementsConstruct() const
Object StringObjectImp::construct(ExecState *exec, const List &args)
{
Object proto = exec->interpreter()->builtinStringPrototype();
- Object obj(new StringInstanceImp(proto ));
-
- UString s;
- if (args.size() > 0)
- s = args.begin()->dispatchToString(exec);
- else
- s = UString("");
-
- obj.setInternalValue(String(s));
- obj.put(exec, lengthPropertyName, Number(s.size()), ReadOnly|DontEnum|DontDelete);
-
- return obj;
+ if (args.size() == 0)
+ return Object(new StringInstanceImp(proto));
+ return Object(new StringInstanceImp(proto, args.begin()->dispatchToString(exec)));
}
bool StringObjectImp::implementsCall() const
diff --git a/JavaScriptCore/kjs/string_object.h b/JavaScriptCore/kjs/string_object.h
index b4a8791..1989a70 100644
--- a/JavaScriptCore/kjs/string_object.h
+++ b/JavaScriptCore/kjs/string_object.h
@@ -30,6 +30,12 @@ namespace KJS {
class StringInstanceImp : public ObjectImp {
public:
StringInstanceImp(const Object &proto);
+ StringInstanceImp(const Object &proto, const UString &string);
+
+ virtual Value get(ExecState *exec, const UString &propertyName) const;
+ virtual void put(ExecState *exec, const UString &propertyName, const Value &value, int attr = None);
+ virtual bool hasProperty(ExecState *exec, const UString &propertyName) const;
+ virtual bool deleteProperty(ExecState *exec, const UString &propertyName);
virtual const ClassInfo *classInfo() const { return &info; }
static const ClassInfo info;
diff --git a/JavaScriptCore/kjs/ustring.cpp b/JavaScriptCore/kjs/ustring.cpp
index d4b4be1..10d4afb 100644
--- a/JavaScriptCore/kjs/ustring.cpp
+++ b/JavaScriptCore/kjs/ustring.cpp
@@ -591,10 +591,7 @@ void UString::detach()
void UString::release()
{
- if (!rep->deref()) {
- delete [] rep->dat;
- delete rep;
- }
+ rep->deref();
}
bool KJS::operator==(const UString& s1, const UString& s2)
@@ -664,17 +661,3 @@ int KJS::compare(const UString& s1, const UString& s2)
}
return (l1 < l2) ? 1 : -1;
}
-
-// Algorithm concept from Algorithms in C++, Sedgewick, Program 14.1.
-int KJS::hash(const UString &s, int hashTableSize)
-{
- int h = 0;
- int length = s.size();
- int prefix = length < 8 ? length : 8;
- for (int i = 0; i != prefix; i++)
- h = (127 * h + s[i].unicode()) % hashTableSize;
- int suffix = length < 16 ? 8 : length - 8;
- for (int i = suffix; i != length; i++)
- h = (127 * h + s[i].unicode()) % hashTableSize;
- return h;
-}
diff --git a/JavaScriptCore/kjs/ustring.h b/JavaScriptCore/kjs/ustring.h
index 61b98f8..e67ad88 100644
--- a/JavaScriptCore/kjs/ustring.h
+++ b/JavaScriptCore/kjs/ustring.h
@@ -143,11 +143,11 @@ namespace KJS {
/**
* @return Unicode value.
*/
- unsigned short unicode() const { return ref().unicode(); }
+ unsigned short unicode() const { return ref().uc; }
/**
* @return Lower byte.
*/
- unsigned char low() const { return ref().uc & 0xFF; }
+ unsigned char low() const { return ref().uc; }
/**
* @return Higher byte.
*/
@@ -199,6 +199,8 @@ namespace KJS {
class UString {
friend bool operator==(const UString&, const UString&);
friend class UCharReference;
+ friend class PropertyMap;
+ friend class PropertyMapHashTableEntry;
/**
* @internal
*/
@@ -210,7 +212,12 @@ namespace KJS {
inline int size() const { return len; }
inline void ref() { rc++; }
- inline int deref() { return --rc; }
+ inline void deref() {
+ if (--rc == 0) {
+ delete [] dat;
+ delete this;
+ }
+ }
UChar *dat;
int len;
@@ -402,6 +409,7 @@ namespace KJS {
static void globalClear();
#endif
private:
+ UString(Rep *r) { attach(r); }
void attach(Rep *r);
void detach();
void release();
@@ -432,7 +440,6 @@ namespace KJS {
}
int compare(const UString &, const UString &);
- int hash(const UString &, int hashTableSize);
}; // namespace
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list