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

Last change on this file since 30810 was 27176, checked in by mjs, 18 years ago

Reviewed by Oliver.


  • numerous HashTable performance improvements


This does not quite add up to a measurable win on SunSpider, but it allows a
follow-on > 3% improvement and probably helps WebCore too.


I made the following improvements, among others:


  • Made HashFunctions note whether it is ok to compare a real value with the equal() function to the empty or deleted value, and used this to optimize the comparisons done in hash lookup.


  • Specialized lookup so it doesn't have to do so many extra branches and build so many extra std::pairs for cases that don't need them. There are now four versions, one for read-only access, two for writing, and one folded directly into add() (these all were improvments).


  • Made HashMap::get() use lookup() directly instead of find() to avoid having to build iterators.


  • Made a special constructor for iterators that knows it points to a valid filled cell and so skips updating itself.
  • Reordered memory accesses in the various lookup functions for better codegetion


  • Made simple translators avoid passing a hash code around


  • Other minor tweaks


  • wtf/HashTable.h: (WTF::): (WTF::HashTableConstIterator::HashTableConstIterator): (WTF::HashTableIterator::HashTableIterator): (WTF::IdentityHashTranslator::translate): (WTF::HashTable::end): (WTF::HashTable::lookup): (WTF::HashTable::lookupForWriting): (WTF::HashTable::makeKnownGoodIterator): (WTF::HashTable::makeKnownGoodConstIterator): (WTF::::lookup): (WTF::::lookupForWriting): (WTF::::fullLookupForWriting): (WTF::::add): (WTF::::addPassingHashCode): (WTF::::reinsert): (WTF::::find): (WTF::::contains):
  • kjs/identifier.cpp: (WTF::):
  • wtf/HashFunctions.h: (WTF::):
  • wtf/HashMap.h: (WTF::): (WTF::::get):
  • wtf/HashSet.h: (WTF::): (WTF::::add):
  • wtf/ListHashSet.h: (WTF::ListHashSetTranslator::translate):
  • Property svn:eol-style set to native
File size: 5.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 Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22#include "config.h"
23
24#include "identifier.h"
25
26#include "JSLock.h"
27#include <new> // for placement new
28#include <string.h> // for strlen
29#include <wtf/Assertions.h>
30#include <wtf/FastMalloc.h>
31#include <wtf/HashSet.h>
32
33namespace WTF {
34
35 template<typename T> struct DefaultHash;
36 template<typename T> struct StrHash;
37
38 template<> struct StrHash<KJS::UString::Rep *> {
39 static unsigned hash(const KJS::UString::Rep *key) { return key->hash(); }
40 static bool equal(const KJS::UString::Rep *a, const KJS::UString::Rep *b) { return KJS::Identifier::equal(a, b); }
41 static const bool safeToCompareToEmptyOrDeleted = false;
42 };
43
44 template<> struct DefaultHash<KJS::UString::Rep *> {
45 typedef StrHash<KJS::UString::Rep *> Hash;
46 };
47
48}
49
50namespace KJS {
51
52typedef HashSet<UString::Rep *> IdentifierTable;
53static IdentifierTable *table;
54
55static inline IdentifierTable& identifierTable()
56{
57 ASSERT(JSLock::lockCount() > 0);
58
59 if (!table)
60 table = new IdentifierTable;
61 return *table;
62}
63
64
65bool Identifier::equal(const UString::Rep *r, const char *s)
66{
67 int length = r->len;
68 const UChar *d = r->data();
69 for (int i = 0; i != length; ++i)
70 if (d[i].uc != (unsigned char)s[i])
71 return false;
72 return s[length] == 0;
73}
74
75bool Identifier::equal(const UString::Rep *r, const UChar *s, int length)
76{
77 if (r->len != length)
78 return false;
79 const UChar *d = r->data();
80 for (int i = 0; i != length; ++i)
81 if (d[i].uc != s[i].uc)
82 return false;
83 return true;
84}
85
86bool Identifier::equal(const UString::Rep *r, const UString::Rep *b)
87{
88 int length = r->len;
89 if (length != b->len)
90 return false;
91 const UChar *d = r->data();
92 const UChar *s = b->data();
93 for (int i = 0; i != length; ++i)
94 if (d[i].uc != s[i].uc)
95 return false;
96 return true;
97}
98
99struct CStringTranslator
100{
101 static unsigned hash(const char *c)
102 {
103 return UString::Rep::computeHash(c);
104 }
105
106 static bool equal(UString::Rep *r, const char *s)
107 {
108 return Identifier::equal(r, s);
109 }
110
111 static void translate(UString::Rep*& location, const char *c, unsigned hash)
112 {
113 size_t length = strlen(c);
114 UChar *d = static_cast<UChar *>(fastMalloc(sizeof(UChar) * length));
115 for (size_t i = 0; i != length; i++)
116 d[i] = c[i];
117
118 UString::Rep *r = UString::Rep::create(d, static_cast<int>(length)).releaseRef();
119 r->isIdentifier = 1;
120 r->rc = 0;
121 r->_hash = hash;
122
123 location = r;
124 }
125};
126
127PassRefPtr<UString::Rep> Identifier::add(const char *c)
128{
129 if (!c) {
130 UString::Rep::null.hash();
131 return &UString::Rep::null;
132 }
133
134 if (!c[0]) {
135 UString::Rep::empty.hash();
136 return &UString::Rep::empty;
137 }
138
139 return *identifierTable().add<const char *, CStringTranslator>(c).first;
140}
141
142struct UCharBuffer {
143 const UChar *s;
144 unsigned int length;
145};
146
147struct UCharBufferTranslator
148{
149 static unsigned hash(const UCharBuffer& buf)
150 {
151 return UString::Rep::computeHash(buf.s, buf.length);
152 }
153
154 static bool equal(UString::Rep *str, const UCharBuffer& buf)
155 {
156 return Identifier::equal(str, buf.s, buf.length);
157 }
158
159 static void translate(UString::Rep *& location, const UCharBuffer& buf, unsigned hash)
160 {
161 UChar *d = static_cast<UChar *>(fastMalloc(sizeof(UChar) * buf.length));
162 for (unsigned i = 0; i != buf.length; i++)
163 d[i] = buf.s[i];
164
165 UString::Rep *r = UString::Rep::create(d, buf.length).releaseRef();
166 r->isIdentifier = 1;
167 r->rc = 0;
168 r->_hash = hash;
169
170 location = r;
171 }
172};
173
174PassRefPtr<UString::Rep> Identifier::add(const UChar *s, int length)
175{
176 if (!length) {
177 UString::Rep::empty.hash();
178 return &UString::Rep::empty;
179 }
180
181 UCharBuffer buf = {s, length};
182 return *identifierTable().add<UCharBuffer, UCharBufferTranslator>(buf).first;
183}
184
185PassRefPtr<UString::Rep> Identifier::addSlowCase(UString::Rep *r)
186{
187 ASSERT(!r->isIdentifier);
188
189 if (r->len == 0) {
190 UString::Rep::empty.hash();
191 return &UString::Rep::empty;
192 }
193
194 UString::Rep *result = *identifierTable().add(r).first;
195 if (result == r)
196 r->isIdentifier = true;
197 return result;
198}
199
200void Identifier::remove(UString::Rep *r)
201{
202 identifierTable().remove(r);
203}
204
205} // namespace KJS
Note: See TracBrowser for help on using the repository browser.