[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