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

Last change on this file since 10218 was 9768, checked in by ggaren, 20 years ago

-rolled in patches for http://bugzilla.opendarwin.org/show_bug.cgi?id=3945
[PATCH] Safe merges of comments and other trivialities from KDE's kjs

-patch by Martijn Klingens <[email protected]>

  • kjs/array_instance.h:
  • kjs/array_object.cpp:
  • kjs/array_object.h:
  • kjs/bool_object.cpp:
  • kjs/bool_object.h:
  • kjs/collector.cpp:
  • kjs/collector.h:
  • kjs/completion.h:
  • kjs/context.h:
  • kjs/date_object.cpp:
  • kjs/date_object.h:
  • kjs/debugger.cpp:
  • kjs/debugger.h:
  • kjs/dtoa.h:
  • kjs/error_object.cpp:
  • kjs/error_object.h:
  • kjs/function.cpp:
  • kjs/function.h:
  • kjs/function_object.cpp:
  • kjs/function_object.h:
  • kjs/grammar.y:
  • kjs/identifier.cpp:
  • kjs/identifier.h:
  • kjs/internal.cpp:
  • kjs/internal.h:
  • kjs/interpreter.cpp:
  • kjs/interpreter.h:
  • kjs/interpreter_map.cpp:
  • kjs/interpreter_map.h:
  • kjs/lexer.cpp:
  • kjs/lexer.h:
  • kjs/list.cpp:
  • kjs/list.h:
  • kjs/lookup.cpp:
  • kjs/lookup.h:
  • kjs/math_object.cpp:
  • kjs/math_object.h:
  • kjs/nodes.cpp:
  • kjs/nodes.h:
  • kjs/nodes2string.cpp:
  • kjs/number_object.cpp:
  • kjs/number_object.h:
  • kjs/object.cpp:
  • kjs/object.h:
  • kjs/object_object.cpp:
  • kjs/object_object.h:
  • kjs/operations.cpp:
  • kjs/operations.h:
  • kjs/property_map.cpp:
  • kjs/property_map.h:
  • kjs/reference.cpp:
  • kjs/reference.h:
  • kjs/reference_list.cpp:
  • kjs/reference_list.h:
  • kjs/regexp.cpp:
  • kjs/regexp.h:
  • kjs/regexp_object.cpp:
  • kjs/regexp_object.h:
  • kjs/scope_chain.cpp:
  • kjs/scope_chain.h:
  • kjs/simple_number.h:
  • kjs/string_object.cpp:
  • kjs/string_object.h:
  • kjs/testkjs.cpp:
  • kjs/types.h:
  • kjs/ustring.cpp:
  • kjs/ustring.h:
  • kjs/value.cpp:
  • kjs/value.h:
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.2 KB
Line 
1/*
2 * This file is part of the KDE libraries
3 * Copyright (C) 2003 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., 51 Franklin Steet, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22// For JavaScriptCore we need to avoid having static constructors.
23// Our strategy is to declare the global objects with a different type (initialized to 0)
24// and then use placement new to initialize the global objects later. This is not completely
25// portable, and it would be good to figure out a 100% clean way that still avoids code that
26// runs at init time.
27
28#if APPLE_CHANGES
29#define AVOID_STATIC_CONSTRUCTORS 1
30#endif
31
32#if AVOID_STATIC_CONSTRUCTORS
33#define KJS_IDENTIFIER_HIDE_GLOBALS 1
34#endif
35
36#include "identifier.h"
37
38#include "fast_malloc.h"
39
40#define DUMP_STATISTICS 0
41
42namespace KJS {
43
44#if DUMP_STATISTICS
45
46static int numProbes;
47static int numCollisions;
48
49struct IdentifierStatisticsExitLogger { ~IdentifierStatisticsExitLogger(); };
50
51static IdentifierStatisticsExitLogger logger;
52
53IdentifierStatisticsExitLogger::~IdentifierStatisticsExitLogger()
54{
55 printf("\nKJS::Identifier statistics\n\n");
56 printf("%d probes\n", numProbes);
57 printf("%d collisions (%.1f%%)\n", numCollisions, 100.0 * numCollisions / numProbes);
58}
59
60#endif
61
62const int _minTableSize = 64;
63
64UString::Rep **Identifier::_table;
65int Identifier::_tableSize;
66int Identifier::_tableSizeMask;
67int Identifier::_keyCount;
68
69bool Identifier::equal(UString::Rep *r, const char *s)
70{
71 int length = r->len;
72 const UChar *d = r->data();
73 for (int i = 0; i != length; ++i)
74 if (d[i].uc != (unsigned char)s[i])
75 return false;
76 return s[length] == 0;
77}
78
79bool Identifier::equal(UString::Rep *r, const UChar *s, int length)
80{
81 if (r->len != length)
82 return false;
83 const UChar *d = r->data();
84 for (int i = 0; i != length; ++i)
85 if (d[i].uc != s[i].uc)
86 return false;
87 return true;
88}
89
90bool Identifier::equal(UString::Rep *r, UString::Rep *b)
91{
92 int length = r->len;
93 if (length != b->len)
94 return false;
95 const UChar *d = r->data();
96 const UChar *s = b->data();
97 for (int i = 0; i != length; ++i)
98 if (d[i].uc != s[i].uc)
99 return false;
100 return true;
101}
102
103UString::Rep *Identifier::add(const char *c)
104{
105 if (!c)
106 return &UString::Rep::null;
107 int length = strlen(c);
108 if (length == 0)
109 return &UString::Rep::empty;
110
111 if (!_table)
112 expand();
113
114 unsigned hash = UString::Rep::computeHash(c);
115
116 int i = hash & _tableSizeMask;
117#if DUMP_STATISTICS
118 ++numProbes;
119 numCollisions += _table[i] && !equal(_table[i], c);
120#endif
121 while (UString::Rep *key = _table[i]) {
122 if (equal(key, c))
123 return key;
124 i = (i + 1) & _tableSizeMask;
125 }
126
127 UChar *d = static_cast<UChar *>(kjs_fast_malloc(sizeof(UChar) * length));
128 for (int j = 0; j != length; j++)
129 d[j] = c[j];
130
131 UString::Rep *r = UString::Rep::create(d, length);
132 r->isIdentifier = 1;
133 r->rc = 0;
134 r->_hash = hash;
135
136 _table[i] = r;
137 ++_keyCount;
138
139 if (_keyCount * 2 >= _tableSize)
140 expand();
141
142 return r;
143}
144
145UString::Rep *Identifier::add(const UChar *s, int length)
146{
147 if (length == 0)
148 return &UString::Rep::empty;
149
150 if (!_table)
151 expand();
152
153 unsigned hash = UString::Rep::computeHash(s, length);
154
155 int i = hash & _tableSizeMask;
156#if DUMP_STATISTICS
157 ++numProbes;
158 numCollisions += _table[i] && !equal(_table[i], s, length);
159#endif
160 while (UString::Rep *key = _table[i]) {
161 if (equal(key, s, length))
162 return key;
163 i = (i + 1) & _tableSizeMask;
164 }
165
166 UChar *d = static_cast<UChar *>(kjs_fast_malloc(sizeof(UChar) * length));
167 for (int j = 0; j != length; j++)
168 d[j] = s[j];
169
170 UString::Rep *r = UString::Rep::create(d, length);
171 r->isIdentifier = 1;
172 r->rc = 0;
173 r->_hash = hash;
174
175 _table[i] = r;
176 ++_keyCount;
177
178 if (_keyCount * 2 >= _tableSize)
179 expand();
180
181 return r;
182}
183
184UString::Rep *Identifier::add(UString::Rep *r)
185{
186 if (r->isIdentifier)
187 return r;
188 if (r->len == 0)
189 return &UString::Rep::empty;
190
191 if (!_table)
192 expand();
193
194 unsigned hash = r->hash();
195
196 int i = hash & _tableSizeMask;
197#if DUMP_STATISTICS
198 ++numProbes;
199 numCollisions += _table[i] && !equal(_table[i], r);
200#endif
201 while (UString::Rep *key = _table[i]) {
202 if (equal(key, r))
203 return key;
204 i = (i + 1) & _tableSizeMask;
205 }
206
207 r->isIdentifier = 1;
208
209 _table[i] = r;
210 ++_keyCount;
211
212 if (_keyCount * 2 >= _tableSize)
213 expand();
214
215 return r;
216}
217
218inline void Identifier::insert(UString::Rep *key)
219{
220 unsigned hash = key->hash();
221
222 int i = hash & _tableSizeMask;
223#if DUMP_STATISTICS
224 ++numProbes;
225 numCollisions += _table[i] != 0;
226#endif
227 while (_table[i])
228 i = (i + 1) & _tableSizeMask;
229
230 _table[i] = key;
231}
232
233void Identifier::remove(UString::Rep *r)
234{
235 unsigned hash = r->hash();
236
237 UString::Rep *key;
238
239 int i = hash & _tableSizeMask;
240#if DUMP_STATISTICS
241 ++numProbes;
242 numCollisions += _table[i] && equal(_table[i], r);
243#endif
244 while ((key = _table[i])) {
245 if (equal(key, r))
246 break;
247 i = (i + 1) & _tableSizeMask;
248 }
249 if (!key)
250 return;
251
252 _table[i] = 0;
253 --_keyCount;
254
255 if (_keyCount * 6 < _tableSize && _tableSize > _minTableSize) {
256 shrink();
257 return;
258 }
259
260 // Reinsert all the items to the right in the same cluster.
261 while (1) {
262 i = (i + 1) & _tableSizeMask;
263 key = _table[i];
264 if (!key)
265 break;
266 _table[i] = 0;
267 insert(key);
268 }
269}
270
271void Identifier::expand()
272{
273 rehash(_tableSize == 0 ? _minTableSize : _tableSize * 2);
274}
275
276void Identifier::shrink()
277{
278 rehash(_tableSize / 2);
279}
280
281void Identifier::rehash(int newTableSize)
282{
283 int oldTableSize = _tableSize;
284 UString::Rep **oldTable = _table;
285
286 _tableSize = newTableSize;
287 _tableSizeMask = newTableSize - 1;
288 _table = (UString::Rep **)calloc(newTableSize, sizeof(UString::Rep *));
289
290 for (int i = 0; i != oldTableSize; ++i)
291 if (UString::Rep *key = oldTable[i])
292 insert(key);
293
294 free(oldTable);
295}
296
297const Identifier &Identifier::null()
298{
299 static Identifier null;
300 return null;
301}
302
303// Global constants for property name strings.
304
305#if !AVOID_STATIC_CONSTRUCTORS
306 // Define an Identifier in the normal way.
307 #define DEFINE_GLOBAL(name, string) extern const Identifier name ## PropertyName(string);
308#else
309 // Define an Identifier-sized array of pointers to avoid static initialization.
310 // Use an array of pointers instead of an array of char in case there is some alignment issue.
311 #define DEFINE_GLOBAL(name, string) \
312 void * name ## PropertyName[(sizeof(Identifier) + sizeof(void *) - 1) / sizeof(void *)];
313#endif
314
315#define CALL_DEFINE_GLOBAL(name) DEFINE_GLOBAL(name, #name)
316KJS_IDENTIFIER_EACH_GLOBAL(CALL_DEFINE_GLOBAL)
317DEFINE_GLOBAL(specialPrototype, "__proto__")
318
319void Identifier::init()
320{
321#if AVOID_STATIC_CONSTRUCTORS
322 static bool initialized;
323 if (!initialized) {
324 // Use placement new to initialize the globals.
325 #define PLACEMENT_NEW_GLOBAL(name, string) new (&name ## PropertyName) Identifier(string);
326 #define CALL_PLACEMENT_NEW_GLOBAL(name) PLACEMENT_NEW_GLOBAL(name, #name)
327 KJS_IDENTIFIER_EACH_GLOBAL(CALL_PLACEMENT_NEW_GLOBAL)
328 PLACEMENT_NEW_GLOBAL(specialPrototype, "__proto__")
329 initialized = true;
330 }
331#endif
332}
333
334} // namespace KJS
Note: See TracBrowser for help on using the repository browser.