22 #include "identifier.h"
28 #define DUMP_STATISTICS 0
35 static int numCollisions;
37 struct IdentifierStatisticsExitLogger { ~IdentifierStatisticsExitLogger(); };
39 static IdentifierStatisticsExitLogger logger;
41 IdentifierStatisticsExitLogger::~IdentifierStatisticsExitLogger()
43 printf(
"\nKJS::Identifier statistics\n\n");
44 printf(
"%d probes\n", numProbes);
45 printf(
"%d collisions (%.1f%%)\n", numCollisions, 100.0 * numCollisions / numProbes);
50 extern const Identifier argumentsPropertyName(
"arguments");
51 extern const Identifier calleePropertyName(
"callee");
52 extern const Identifier callerPropertyName(
"caller");
53 extern const Identifier constructorPropertyName(
"constructor");
54 extern const Identifier lengthPropertyName(
"length");
55 extern const Identifier messagePropertyName(
"message");
56 extern const Identifier namePropertyName(
"name");
57 extern const Identifier prototypePropertyName(
"prototype");
58 extern const Identifier specialPrototypePropertyName(
"__proto__");
59 extern const Identifier toLocaleStringPropertyName(
"toLocaleString");
60 extern const Identifier toStringPropertyName(
"toString");
61 extern const Identifier valueOfPropertyName(
"valueOf");
63 static const int _minTableSize = 64;
65 UString::Rep **Identifier::_table;
66 int Identifier::_tableSize;
67 int Identifier::_tableSizeMask;
68 int Identifier::_keyCount;
70 bool Identifier::equal(UString::Rep *r,
const char *s)
73 const UChar *d = r->data();
74 for (
int i = 0; i != length; ++i)
75 if (d[i].uc != (
unsigned char)s[i])
77 return s[length] == 0;
80 bool Identifier::equal(UString::Rep *r,
const UChar *s,
int length)
84 const UChar *d = r->data();
85 for (
int i = 0; i != length; ++i)
86 if (d[i].uc != s[i].uc)
91 bool Identifier::equal(UString::Rep *r, UString::Rep *b)
96 const UChar *d = r->data();
97 const UChar *s = b->data();
98 for (
int i = 0; i != length; ++i)
99 if (d[i].uc != s[i].uc)
104 UString::Rep *Identifier::add(
const char *c)
107 return &UString::Rep::null;
108 int length = strlen(c);
110 return &UString::Rep::empty;
115 unsigned hash = UString::Rep::computeHash(c);
117 int i = hash & _tableSizeMask;
120 numCollisions += _table[i] && !equal(_table[i], c);
122 while (UString::Rep *key = _table[i]) {
125 i = (i + 1) & _tableSizeMask;
128 UChar *d =
new UChar[length];
129 for (
int j = 0; j != length; j++)
132 UString::Rep *r =
new UString::Rep;
135 r->capacity = UString::Rep::capacityForIdentifier;
142 if (_keyCount * 2 >= _tableSize)
148 UString::Rep *Identifier::add(
const UChar *s,
int length)
151 return &UString::Rep::empty;
156 unsigned hash = UString::Rep::computeHash(s, length);
158 int i = hash & _tableSizeMask;
161 numCollisions += _table[i] && !equal(_table[i], s, length);
163 while (UString::Rep *key = _table[i]) {
164 if (equal(key, s, length))
166 i = (i + 1) & _tableSizeMask;
169 UChar *d =
new UChar[length];
170 for (
int j = 0; j != length; j++)
173 UString::Rep *r =
new UString::Rep;
176 r->capacity = UString::Rep::capacityForIdentifier;
183 if (_keyCount * 2 >= _tableSize)
189 UString::Rep *Identifier::add(UString::Rep *r)
191 if (r->capacity == UString::Rep::capacityForIdentifier)
194 return &UString::Rep::empty;
199 unsigned hash = r->hash();
201 int i = hash & _tableSizeMask;
204 numCollisions += _table[i] && !equal(_table[i], r);
206 while (UString::Rep *key = _table[i]) {
209 i = (i + 1) & _tableSizeMask;
212 r->capacity = UString::Rep::capacityForIdentifier;
217 if (_keyCount * 2 >= _tableSize)
223 inline void Identifier::insert(UString::Rep *key)
225 unsigned hash =
key->hash();
227 int i = hash & _tableSizeMask;
230 numCollisions += _table[i] != 0;
233 i = (i + 1) & _tableSizeMask;
238 void Identifier::remove(UString::Rep *r)
240 unsigned hash = r->hash();
244 int i = hash & _tableSizeMask;
247 numCollisions += _table[i] && equal(_table[i], r);
249 while ((key = _table[i])) {
252 i = (i + 1) & _tableSizeMask;
260 if (_keyCount * 6 < _tableSize && _tableSize > _minTableSize) {
267 i = (i + 1) & _tableSizeMask;
276 void Identifier::expand()
278 rehash(_tableSize == 0 ? _minTableSize : _tableSize * 2);
281 void Identifier::shrink()
283 rehash(_tableSize / 2);
286 void Identifier::rehash(
int newTableSize)
288 int oldTableSize = _tableSize;
289 UString::Rep **oldTable = _table;
291 _tableSize = newTableSize;
292 _tableSizeMask = newTableSize - 1;
293 _table = (UString::Rep **)calloc(newTableSize,
sizeof(UString::Rep *));
295 for (
int i = 0; i != oldTableSize; ++i)
296 if (UString::Rep *key = oldTable[i])
Represents an Identifier for a Javascript object.
static const Identifier & null()
Creates an empty Identifier.