Commit 2dd6a841 authored by darin's avatar darin

- another string constant discovered that can be optimized

        * kjs/object.h: Add a property name constant for "__proto__".
        * kjs/object.cpp: Define it.
	(ObjectImp::get): Use it.
	(ObjectImp::hasProperty): Use it.

	- prepare to turn PropertyMap into a hash table

        * kjs/object.cpp:
	(ObjectImp::mark): Use the new PropertyMap::mark().
	(ObjectImp::put): Use the new overload of PropertyMap::get().
	(ObjectImp::deleteProperty): Use the new overload of PropertyMap::get().
	(ObjectImp::propList): Use PropertyMap::addEnumerablesToReferenceList().

        * kjs/property_map.h: Remove PropertyMapNode and make all node-related methods private.
	Add mark(), a new overload of get() that returns attributes, a clear() that takes no attributes,
	and addEnumerablesToReferenceList().
        * kjs/property_map.cpp:
	(PropertyMap::get): Added new overload.
	(PropertyMap::clear): Added new overload.
	(PropertyMap::mark): Added.
	(PropertyMap::addEnumerablesToReferenceList): Added.

        * kjs/ustring.h: Added a hash function.
        * kjs/ustring.cpp: (KJS::hash): Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@2740 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent de6825fb
2002-11-18 Darin Adler <darin@apple.com>
- another string constant discovered that can be optimized
* kjs/object.h: Add a property name constant for "__proto__".
* kjs/object.cpp: Define it.
(ObjectImp::get): Use it.
(ObjectImp::hasProperty): Use it.
- prepare to turn PropertyMap into a hash table
* kjs/object.cpp:
(ObjectImp::mark): Use the new PropertyMap::mark().
(ObjectImp::put): Use the new overload of PropertyMap::get().
(ObjectImp::deleteProperty): Use the new overload of PropertyMap::get().
(ObjectImp::propList): Use PropertyMap::addEnumerablesToReferenceList().
* kjs/property_map.h: Remove PropertyMapNode and make all node-related methods private.
Add mark(), a new overload of get() that returns attributes, a clear() that takes no attributes,
and addEnumerablesToReferenceList().
* kjs/property_map.cpp:
(PropertyMap::get): Added new overload.
(PropertyMap::clear): Added new overload.
(PropertyMap::mark): Added.
(PropertyMap::addEnumerablesToReferenceList): Added.
* kjs/ustring.h: Added a hash function.
* kjs/ustring.cpp: (KJS::hash): Added.
2002-11-18 Darin Adler <darin@apple.com>
- simplified the ExecState class, which was showing up in profiles
......
2002-11-18 Darin Adler <darin@apple.com>
- another string constant discovered that can be optimized
* kjs/object.h: Add a property name constant for "__proto__".
* kjs/object.cpp: Define it.
(ObjectImp::get): Use it.
(ObjectImp::hasProperty): Use it.
- prepare to turn PropertyMap into a hash table
* kjs/object.cpp:
(ObjectImp::mark): Use the new PropertyMap::mark().
(ObjectImp::put): Use the new overload of PropertyMap::get().
(ObjectImp::deleteProperty): Use the new overload of PropertyMap::get().
(ObjectImp::propList): Use PropertyMap::addEnumerablesToReferenceList().
* kjs/property_map.h: Remove PropertyMapNode and make all node-related methods private.
Add mark(), a new overload of get() that returns attributes, a clear() that takes no attributes,
and addEnumerablesToReferenceList().
* kjs/property_map.cpp:
(PropertyMap::get): Added new overload.
(PropertyMap::clear): Added new overload.
(PropertyMap::mark): Added.
(PropertyMap::addEnumerablesToReferenceList): Added.
* kjs/ustring.h: Added a hash function.
* kjs/ustring.cpp: (KJS::hash): Added.
2002-11-18 Darin Adler <darin@apple.com>
- simplified the ExecState class, which was showing up in profiles
......
2002-11-18 Darin Adler <darin@apple.com>
- another string constant discovered that can be optimized
* kjs/object.h: Add a property name constant for "__proto__".
* kjs/object.cpp: Define it.
(ObjectImp::get): Use it.
(ObjectImp::hasProperty): Use it.
- prepare to turn PropertyMap into a hash table
* kjs/object.cpp:
(ObjectImp::mark): Use the new PropertyMap::mark().
(ObjectImp::put): Use the new overload of PropertyMap::get().
(ObjectImp::deleteProperty): Use the new overload of PropertyMap::get().
(ObjectImp::propList): Use PropertyMap::addEnumerablesToReferenceList().
* kjs/property_map.h: Remove PropertyMapNode and make all node-related methods private.
Add mark(), a new overload of get() that returns attributes, a clear() that takes no attributes,
and addEnumerablesToReferenceList().
* kjs/property_map.cpp:
(PropertyMap::get): Added new overload.
(PropertyMap::clear): Added new overload.
(PropertyMap::mark): Added.
(PropertyMap::addEnumerablesToReferenceList): Added.
* kjs/ustring.h: Added a hash function.
* kjs/ustring.cpp: (KJS::hash): Added.
2002-11-18 Darin Adler <darin@apple.com>
- simplified the ExecState class, which was showing up in profiles
......
......@@ -44,6 +44,7 @@ namespace KJS {
extern const UString argumentsPropertyName("arguments");
extern const UString lengthPropertyName("length");
extern const UString prototypePropertyName("prototype");
extern const UString specialPrototypePropertyName("__proto__");
extern const UString toStringPropertyName("toString");
extern const UString valueOfPropertyName("valueOf");
......@@ -93,12 +94,7 @@ void ObjectImp::mark()
if (_proto && !_proto->marked())
_proto->mark();
PropertyMapNode *node = _prop->first();
while (node) {
if (!node->value->marked())
node->value->mark();
node = node->next();
}
_prop->mark();
if (_internalValue && !_internalValue->marked())
_internalValue->mark();
......@@ -151,15 +147,6 @@ UString ObjectImp::className() const
Value ObjectImp::get(ExecState *exec, const UString &propertyName) const
{
if (propertyName == "__proto__") {
Object proto = Object::dynamicCast(prototype());
// non-standard netscape extension
if (proto.isNull())
return Null();
else
return proto;
}
ValueImp *imp = getDirect(propertyName);
if ( imp )
return Value(imp);
......@@ -168,6 +155,10 @@ Value ObjectImp::get(ExecState *exec, const UString &propertyName) const
if (proto.isNull())
return Undefined();
// non-standard netscape extension
if (propertyName == specialPrototypePropertyName)
return proto;
return proto.get(exec,propertyName);
}
......@@ -204,8 +195,8 @@ void ObjectImp::put(ExecState *exec, const UString &propertyName,
return;
}
if (propertyName == "__proto__") {
// non-standard netscape extension
// non-standard netscape extension
if (propertyName == specialPrototypePropertyName) {
setPrototype(value);
return;
}
......@@ -222,9 +213,10 @@ void ObjectImp::put(ExecState *exec, unsigned propertyName,
// ECMA 8.6.2.3
bool ObjectImp::canPut(ExecState *, const UString &propertyName) const
{
PropertyMapNode *node = _prop->getNode(propertyName);
if (node)
return!(node->attr & ReadOnly);
int attributes;
ValueImp *v = _prop->get(propertyName, attributes);
if (v)
return!(attributes & ReadOnly);
// Look in the static hashtable of properties
const HashEntry* e = findPropertyHashEntry(propertyName);
......@@ -239,8 +231,6 @@ bool ObjectImp::canPut(ExecState *, const UString &propertyName) const
// ECMA 8.6.2.4
bool ObjectImp::hasProperty(ExecState *exec, const UString &propertyName) const
{
if (propertyName == "__proto__")
return true;
if (_prop->get(propertyName))
return true;
......@@ -248,6 +238,10 @@ bool ObjectImp::hasProperty(ExecState *exec, const UString &propertyName) const
if (findPropertyHashEntry(propertyName))
return true;
// non-standard netscape extension
if (propertyName == specialPrototypePropertyName)
return true;
// Look in the prototype
Object proto = Object::dynamicCast(prototype());
return !proto.isNull() && proto.hasProperty(exec,propertyName);
......@@ -261,9 +255,10 @@ bool ObjectImp::hasProperty(ExecState *exec, unsigned propertyName) const
// ECMA 8.6.2.5
bool ObjectImp::deleteProperty(ExecState */*exec*/, const UString &propertyName)
{
PropertyMapNode *node = _prop->getNode(propertyName);
if (node) {
if ((node->attr & DontDelete))
int attributes;
ValueImp *v = _prop->get(propertyName, attributes);
if (v) {
if ((attributes & DontDelete))
return false;
_prop->remove(propertyName);
return true;
......@@ -405,13 +400,7 @@ ReferenceList ObjectImp::propList(ExecState *exec, bool recursive)
if (_proto && _proto->dispatchType() == ObjectType && recursive)
list = static_cast<ObjectImp*>(_proto)->propList(exec,recursive);
PropertyMapNode *node = _prop->first();
while (node) {
if (!(node->attr & DontEnum))
list.append(Reference(Object(this), node->name));
node = node->next();
}
_prop->addEnumerablesToReferenceList(list, Object(this));
// Add properties from the static hashtable of properties
const ClassInfo *info = classInfo();
......
......@@ -708,6 +708,7 @@ namespace KJS {
extern const UString argumentsPropertyName;
extern const UString lengthPropertyName;
extern const UString prototypePropertyName;
extern const UString specialPrototypePropertyName;
extern const UString toStringPropertyName;
extern const UString valueOfPropertyName;
......
......@@ -23,14 +23,42 @@
#include "property_map.h"
#include "object.h"
#include "reference_list.h"
#include <string.h>
#include <assert.h>
#include <stdio.h>
using namespace KJS;
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)
......@@ -203,6 +231,38 @@ ValueImp *PropertyMap::get(const UString &name) const
return n ? n->value : 0;
}
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)
......@@ -548,3 +608,5 @@ void PropertyMap::rotateLR(PropertyMapNode* &node)
updateHeight(a);
updateHeight(b);
}
} // namespace KJS
......@@ -29,30 +29,8 @@
namespace KJS {
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);
};
class PropertyMapNode;
class ReferenceList;
/**
* @internal
......@@ -73,16 +51,22 @@ namespace KJS {
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;
void clear();
void mark();
void addEnumerablesToReferenceList(ReferenceList &, const Object &) const;
private:
void clear(PropertyMapNode *node = 0);
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;
private:
PropertyMapNode *remove(PropertyMapNode *node);
void balance(PropertyMapNode* node);
void updateHeight(PropertyMapNode* &node);
......
......@@ -664,3 +664,17 @@ 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;
}
......@@ -432,6 +432,7 @@ namespace KJS {
}
int compare(const UString &, const UString &);
int hash(const UString &, int hashTableSize);
}; // namespace
......
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