source: webkit/trunk/JavaScriptCore/kjs/identifier.cpp@ 2779

Last change on this file since 2779 was 2776, checked in by darin, 23 years ago
  • atomic identifiers; gives another 6.5% in the iBench suite
  • kjs/identifier.h: Did the real thing.
  • kjs/identifier.cpp: Ditto.
  • kjs/property_map.h: _tableSizeHashMask -> _tableSizeMask
  • kjs/property_map.cpp: The above, plus take advantage of comparing by pointer instead of by comparing bytes.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.2 KB
Line 
1/*
2 * This file is part of the KDE libraries
3 * Copyright (C) 2002 Apple Computer, Inc
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 */
21
22#include "identifier.h"
23
24namespace KJS {
25
26Identifier Identifier::null;
27
28extern const Identifier argumentsPropertyName("arguments");
29extern const Identifier calleePropertyName("callee");
30extern const Identifier constructorPropertyName("constructor");
31extern const Identifier lengthPropertyName("length");
32extern const Identifier messagePropertyName("message");
33extern const Identifier namePropertyName("name");
34extern const Identifier prototypePropertyName("prototype");
35extern const Identifier specialPrototypePropertyName("__proto__");
36extern const Identifier toLocaleStringPropertyName("toLocaleString");
37extern const Identifier toStringPropertyName("toString");
38extern const Identifier valueOfPropertyName("valueOf");
39
40const int _minTableSize = 64;
41
42UString::Rep **Identifier::_table;
43int Identifier::_tableSize;
44int Identifier::_tableSizeMask;
45int Identifier::_keyCount;
46
47bool Identifier::equal(UString::Rep *r, const char *s)
48{
49 int length = r->len;
50 const UChar *d = r->dat;
51 for (int i = 0; i != length; ++i)
52 if (d[i].unicode() != (unsigned char)s[i])
53 return false;
54 return s[length] == 0;
55}
56
57bool Identifier::equal(UString::Rep *r, const UChar *s, int length)
58{
59 if (r->len != length)
60 return false;
61 const UChar *d = r->dat;
62 for (int i = 0; i != length; ++i)
63 if (d[i].unicode() != s[i].unicode())
64 return false;
65 return true;
66}
67
68bool Identifier::equal(UString::Rep *r, UString::Rep *b)
69{
70 int length = r->len;
71 if (length != b->len)
72 return false;
73 const UChar *d = r->dat;
74 const UChar *s = b->dat;
75 for (int i = 0; i != length; ++i)
76 if (d[i].unicode() != s[i].unicode())
77 return false;
78 return true;
79}
80
81UString::Rep *Identifier::add(const char *c)
82{
83 if (!c)
84 return &UString::Rep::null;
85 int length = strlen(c);
86 if (length == 0)
87 return &UString::Rep::empty;
88
89 if (!_table)
90 expand();
91
92 unsigned hash = UString::Rep::computeHash(c);
93
94 int i = hash & _tableSizeMask;
95 while (UString::Rep *key = _table[i]) {
96 if (equal(key, c))
97 return key;
98 i = (i + 1) & _tableSizeMask;
99 }
100
101 UChar *d = new UChar[length];
102 for (int j = 0; j != length; j++)
103 d[j] = c[j];
104
105 UString::Rep *r = new UString::Rep;
106 r->dat = d;
107 r->len = length;
108 r->capacity = UString::Rep::capacityForIdentifier;
109 r->rc = 0;
110 r->_hash = hash;
111
112 _table[i] = r;
113 ++_keyCount;
114
115 if (_keyCount * 2 >= _tableSize)
116 expand();
117
118 return r;
119}
120
121UString::Rep *Identifier::add(const UChar *s, int length)
122{
123 if (length == 0)
124 return &UString::Rep::empty;
125
126 if (!_table)
127 expand();
128
129 unsigned hash = UString::Rep::computeHash(s, length);
130
131 int i = hash & _tableSizeMask;
132 while (UString::Rep *key = _table[i]) {
133 if (equal(key, s, length))
134 return key;
135 i = (i + 1) & _tableSizeMask;
136 }
137
138 UChar *d = new UChar[length];
139 for (int j = 0; j != length; j++)
140 d[j] = s[j];
141
142 UString::Rep *r = new UString::Rep;
143 r->dat = d;
144 r->len = length;
145 r->capacity = UString::Rep::capacityForIdentifier;
146 r->rc = 0;
147 r->_hash = hash;
148
149 _table[i] = r;
150 ++_keyCount;
151
152 if (_keyCount * 2 >= _tableSize)
153 expand();
154
155 return r;
156}
157
158UString::Rep *Identifier::add(UString::Rep *r)
159{
160 if (r->capacity == UString::Rep::capacityForIdentifier)
161 return r;
162 if (r->len == 0)
163 return &UString::Rep::empty;
164
165 if (!_table)
166 expand();
167
168 unsigned hash = r->hash();
169
170 int i = hash & _tableSizeMask;
171 while (UString::Rep *key = _table[i]) {
172 if (equal(key, r))
173 return key;
174 i = (i + 1) & _tableSizeMask;
175 }
176
177 r->capacity = UString::Rep::capacityForIdentifier;
178
179 _table[i] = r;
180 ++_keyCount;
181
182 if (_keyCount * 2 >= _tableSize)
183 expand();
184
185 return r;
186}
187
188inline void Identifier::insert(UString::Rep *key)
189{
190 unsigned hash = key->hash();
191
192 int i = hash & _tableSizeMask;
193 while (_table[i])
194 i = (i + 1) & _tableSizeMask;
195
196 _table[i] = key;
197}
198
199void Identifier::remove(UString::Rep *r)
200{
201 unsigned hash = r->hash();
202
203 UString::Rep *key;
204
205 int i = hash & _tableSizeMask;
206 while ((key = _table[i])) {
207 if (equal(key, r))
208 break;
209 i = (i + 1) & _tableSizeMask;
210 }
211 if (!key)
212 return;
213
214 _table[i] = 0;
215 --_keyCount;
216
217 if (_keyCount * 3 < _tableSize && _tableSize > _minTableSize) {
218 shrink();
219 return;
220 }
221
222 // Reinsert all the items to the right in the same cluster.
223 while (1) {
224 i = (i + 1) & _tableSizeMask;
225 key = _table[i];
226 if (!key)
227 break;
228 _table[i] = 0;
229 insert(key);
230 }
231}
232
233void Identifier::expand()
234{
235 rehash(_tableSize == 0 ? _minTableSize : _tableSize * 2);
236}
237
238void Identifier::shrink()
239{
240 rehash(_tableSize / 2);
241}
242
243void Identifier::rehash(int newTableSize)
244{
245 int oldTableSize = _tableSize;
246 UString::Rep **oldTable = _table;
247
248 _tableSize = newTableSize;
249 _tableSizeMask = newTableSize - 1;
250 _table = (UString::Rep **)calloc(newTableSize, sizeof(UString::Rep *));
251
252 for (int i = 0; i != oldTableSize; ++i)
253 if (UString::Rep *key = oldTable[i])
254 insert(key);
255
256 free(oldTable);
257}
258
259} // namespace KJS
Note: See TracBrowser for help on using the repository browser.