Merge lp:~joe-nationnet-deactivatedaccount/seamonkey/seamonkey-beta into lp:~mozillateam/seamonkey/seamonkey-beta.head
- seamonkey-beta
- Merge into seamonkey-beta.head
Proposed by
Joe Lesko
Status: | Merged |
---|---|
Merged at revision: | 257 |
Proposed branch: | lp:~joe-nationnet-deactivatedaccount/seamonkey/seamonkey-beta |
Merge into: | lp:~mozillateam/seamonkey/seamonkey-beta.head |
Diff against target: |
2353 lines (+90/-2148) 13 files modified
debian/build/create-tarball (+1/-2) debian/changelog (+51/-0) debian/config/branch.mk (+2/-2) debian/control (+2/-1) debian/control.in (+2/-1) debian/patches/build-fix-for-no-ENABLE_YARR_JIT.patch (+0/-109) debian/patches/compile-pldhash-as-C++.patch (+0/-1970) debian/patches/fix-build-failure-without-yarr-jit.patch (+27/-0) debian/patches/only-add-ENABLE_JIT-to-CXXFLAGS-if-jit-is-enabled.patch (+0/-55) debian/patches/printf-fix.patch (+1/-1) debian/patches/series (+1/-3) debian/rules (+2/-3) debian/seamonkey.desktop.in (+1/-1) |
To merge this branch: | bzr merge lp:~joe-nationnet-deactivatedaccount/seamonkey/seamonkey-beta |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mozilla Team | Pending | ||
Review via email: mp+85248@code.launchpad.net |
Commit message
Description of the change
* New upstream release from the beta channel (SEAMONKEY_
* Updated build/create_
* Removed patch correctly-
To post a comment you must log in.
- 260. By Joe Lesko
-
* New upstream release from the release channel (SEAMONKEY_
2_6_RELEASE)
* Updated build/create_tarball with fix from Chris Coulson
* Removed patch correctly-handle- EOF.patch as it was applied upstream.
* Added patch to correct powerpc build.
- fix-build-failure- without- yarr-jit. patch
- Updated series.
* Above changes were brought over from beta revisions 266 through 271. - 261. By Joe Lesko
-
* New upstream release from the release channel (SEAMONKEY_
2_6_1_RELEASE)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/build/create-tarball' | |||
2 | --- debian/build/create-tarball 2011-09-23 14:46:57 +0000 | |||
3 | +++ debian/build/create-tarball 2011-12-16 00:06:23 +0000 | |||
4 | @@ -232,10 +232,9 @@ | |||
5 | 232 | if moz_local != None: | 232 | if moz_local != None: |
6 | 233 | args.append('--mozilla-repo=%s' % moz_local) | 233 | args.append('--mozilla-repo=%s' % moz_local) |
7 | 234 | if tag != None: | 234 | if tag != None: |
8 | 235 | args.append('--comm-rev=%s' % tag) | ||
9 | 235 | args.append('--mozilla-rev=%s' % tag) | 236 | args.append('--mozilla-rev=%s' % tag) |
10 | 236 | do_exec(args, cwd=os.path.join(os.getcwd(), DEB_TAR_SRCDIR)) | 237 | do_exec(args, cwd=os.path.join(os.getcwd(), DEB_TAR_SRCDIR)) |
11 | 237 | args = ['hg', 'update', '-r', tag] | ||
12 | 238 | do_exec(args, cwd=os.path.join(os.getcwd(), DEB_TAR_SRCDIR)) | ||
13 | 239 | 238 | ||
14 | 240 | def verify_all_locales(all_locales, blfile): | 239 | def verify_all_locales(all_locales, blfile): |
15 | 241 | # When we also use translations from Launchpad, there will be a file | 240 | # When we also use translations from Launchpad, there will be a file |
16 | 242 | 241 | ||
17 | === modified file 'debian/changelog' | |||
18 | --- debian/changelog 2011-10-11 08:49:38 +0000 | |||
19 | +++ debian/changelog 2011-12-16 00:06:23 +0000 | |||
20 | @@ -1,3 +1,54 @@ | |||
21 | 1 | seamonkey (2.6~b4-0ubuntu1) UNRELEASED; urgency=low | ||
22 | 2 | |||
23 | 3 | * New upstream release from the beta channel (SEAMONKEY_2_6b4_RELEASE) | ||
24 | 4 | |||
25 | 5 | -- Joe Lesko <joe@nationnet.com> Thu, 15 Dec 2011 17:01:19 -0700 | ||
26 | 6 | |||
27 | 7 | seamonkey (2.6~b3-0ubuntu1) UNRELEASED; urgency=low | ||
28 | 8 | |||
29 | 9 | * New upstream release from the beta channel (SEAMONKEY_2_6b3_RELEASE) | ||
30 | 10 | * Updated build/create_tarball with fix from Chris Coulson | ||
31 | 11 | * Removed patch correctly-handle-EOF.patch as it was applied upstream. | ||
32 | 12 | * Added patch to correct powerpc build. | ||
33 | 13 | - fix-build-failure-without-yarr-jit.patch | ||
34 | 14 | - Updated series. | ||
35 | 15 | |||
36 | 16 | -- Joe Lesko <joe@nationnet.com> Sun, 11 Dec 2011 00:17:27 -0700 | ||
37 | 17 | |||
38 | 18 | seamonkey (2.5~b4-0ubuntu1) UNRELEASED; urgency=low | ||
39 | 19 | |||
40 | 20 | * New upstream release from the beta channel (SEAMONKEY_2_5b4_RELEASE) | ||
41 | 21 | * Backport patch from aurora to correctly handle EOF in | ||
42 | 22 | js::TokenStream::getAtSourceMappingURL on platforms with unsigned chars | ||
43 | 23 | - add debian/patches/correctly-handle-EOF.patch | ||
44 | 24 | - update debian/patches/series | ||
45 | 25 | * Set MOZ_DISABLE_LIBJPEG if build is for karmic as well as lucid. | ||
46 | 26 | - update debian/rules | ||
47 | 27 | * Updated build/create_tarball with fix from Chris Coulson | ||
48 | 28 | |||
49 | 29 | -- Joe <joe@nationnet.com> Tue, 08 Nov 2011 11:26:27 -0700 | ||
50 | 30 | |||
51 | 31 | seamonkey (2.5~b3-0ubuntu1) UNRELEASED; urgency=low | ||
52 | 32 | |||
53 | 33 | * New upstream release from the beta channel (SEAMONKEY_2_5b3_RELEASE) | ||
54 | 34 | - Removed DEBIAN_TAG from rules | ||
55 | 35 | - Updated config/branch.mk to pull from beta channels | ||
56 | 36 | |||
57 | 37 | * Fixed patches for SEAMONKEY_2_5b3_RELEASE | ||
58 | 38 | - Removed compile-pldhash-as-C++.patch. Included in upstream | ||
59 | 39 | - Fixed printf-fix.patch with new diff | ||
60 | 40 | - Updated series | ||
61 | 41 | |||
62 | 42 | * Fixed MimeTypes in desktop. (LP #865036 ) | ||
63 | 43 | |||
64 | 44 | * Removed patches that were applied upstream | ||
65 | 45 | - build-fix-for-no-ENABLE_YARR_JIT.patch | ||
66 | 46 | - only-add-ENABLE_JIT-to-CXXFLAGS-if-jit-is-enabled.patch | ||
67 | 47 | * Fixed shlibs for libstartup-notification0. (LP #877925) | ||
68 | 48 | - Refreshed control file | ||
69 | 49 | |||
70 | 50 | -- Joe <joe@nationnet.com> Mon, 17 Oct 2011 17:07:02 -0700 | ||
71 | 51 | |||
72 | 1 | seamonkey (2.4.1-0ubuntu1) oneiric; urgency=low | 52 | seamonkey (2.4.1-0ubuntu1) oneiric; urgency=low |
73 | 2 | 53 | ||
74 | 3 | [ Joe Lesko <joe@nationnet.com> ] | 54 | [ Joe Lesko <joe@nationnet.com> ] |
75 | 4 | 55 | ||
76 | === modified file 'debian/config/branch.mk' | |||
77 | --- debian/config/branch.mk 2011-09-13 05:05:14 +0000 | |||
78 | +++ debian/config/branch.mk 2011-12-16 00:06:23 +0000 | |||
79 | @@ -4,5 +4,5 @@ | |||
80 | 4 | DISTRIB_VERSION_MAJOR = $(shell lsb_release -s -r | cut -d '.' -f 1) | 4 | DISTRIB_VERSION_MAJOR = $(shell lsb_release -s -r | cut -d '.' -f 1) |
81 | 5 | DISTRIB_VERSION_MINOR = $(shell lsb_release -s -r | cut -d '.' -f 2) | 5 | DISTRIB_VERSION_MINOR = $(shell lsb_release -s -r | cut -d '.' -f 2) |
82 | 6 | 6 | ||
85 | 7 | COMM_REPO = http://hg.mozilla.org/releases/comm-release | 7 | COMM_REPO = http://hg.mozilla.org/releases/comm-beta |
86 | 8 | L10N_REPO = http://hg.mozilla.org/releases/l10n/mozilla-release | 8 | L10N_REPO = http://hg.mozilla.org/releases/l10n/mozilla-beta |
87 | 9 | 9 | ||
88 | === modified file 'debian/control' | |||
89 | --- debian/control 2011-10-11 08:49:05 +0000 | |||
90 | +++ debian/control 2011-12-16 00:06:23 +0000 | |||
91 | @@ -43,7 +43,8 @@ | |||
92 | 43 | Package: seamonkey | 43 | Package: seamonkey |
93 | 44 | Architecture: any | 44 | Architecture: any |
94 | 45 | Depends: debianutils (>= 1.16), | 45 | Depends: debianutils (>= 1.16), |
96 | 46 | ${misc:Depends} | 46 | ${misc:Depends}, |
97 | 47 | ${shlibs:Depends} | ||
98 | 47 | Recommends: myspell-en-us | hunspell-dictionary | myspell-dictionary | 48 | Recommends: myspell-en-us | hunspell-dictionary | myspell-dictionary |
99 | 48 | Suggests: seamonkey-gnome-support (= ${binary:Version}), | 49 | Suggests: seamonkey-gnome-support (= ${binary:Version}), |
100 | 49 | latex-xft-fonts, | 50 | latex-xft-fonts, |
101 | 50 | 51 | ||
102 | === modified file 'debian/control.in' | |||
103 | --- debian/control.in 2011-10-11 08:49:05 +0000 | |||
104 | +++ debian/control.in 2011-12-16 00:06:23 +0000 | |||
105 | @@ -43,7 +43,8 @@ | |||
106 | 43 | Package: @MOZ_APP_NAME@ | 43 | Package: @MOZ_APP_NAME@ |
107 | 44 | Architecture: any | 44 | Architecture: any |
108 | 45 | Depends: debianutils (>= 1.16), | 45 | Depends: debianutils (>= 1.16), |
110 | 46 | ${misc:Depends} | 46 | ${misc:Depends}, |
111 | 47 | ${shlibs:Depends} | ||
112 | 47 | Recommends: myspell-en-us | hunspell-dictionary | myspell-dictionary | 48 | Recommends: myspell-en-us | hunspell-dictionary | myspell-dictionary |
113 | 48 | Suggests: @MOZ_APP_NAME@-gnome-support (= ${binary:Version}), | 49 | Suggests: @MOZ_APP_NAME@-gnome-support (= ${binary:Version}), |
114 | 49 | latex-xft-fonts, | 50 | latex-xft-fonts, |
115 | 50 | 51 | ||
116 | === removed file 'debian/patches/build-fix-for-no-ENABLE_YARR_JIT.patch' | |||
117 | --- debian/patches/build-fix-for-no-ENABLE_YARR_JIT.patch 2011-10-11 07:49:14 +0000 | |||
118 | +++ debian/patches/build-fix-for-no-ENABLE_YARR_JIT.patch 1970-01-01 00:00:00 +0000 | |||
119 | @@ -1,109 +0,0 @@ | |||
120 | 1 | # HG changeset patch | ||
121 | 2 | # User Andrew Paprocki <andrew@ishiboo.com> | ||
122 | 3 | # Date 1310430767 25200 | ||
123 | 4 | # Node ID 691294843828d5b4108559b27bfe342ce3b146ef | ||
124 | 5 | # Parent 9b2e6ea86756ae95f7f5b03799663e810877ecfc | ||
125 | 6 | Bug 665819: build fix for ENABLE_YARR_JIT=0, r=dmandelin | ||
126 | 7 | |||
127 | 8 | diff --git a/mozilla/js/src/jsregexpinlines.h b/mozilla/js/src/jsregexpinlines.h | ||
128 | 9 | --- a/mozilla/js/src/jsregexpinlines.h | ||
129 | 10 | +++ b/mozilla/js/src/jsregexpinlines.h | ||
130 | 11 | @@ -486,17 +486,19 @@ RegExp::compileHelper(JSContext *cx, JSL | ||
131 | 12 | return false; | ||
132 | 13 | JSC::Yarr::JSGlobalData globalData(cx->compartment->jaegerCompartment()->execAlloc()); | ||
133 | 14 | JSC::Yarr::jitCompile(yarrPattern, &globalData, codeBlock); | ||
134 | 15 | if (!codeBlock.isFallBack()) | ||
135 | 16 | return true; | ||
136 | 17 | } | ||
137 | 18 | #endif | ||
138 | 19 | |||
139 | 20 | +#if ENABLE_YARR_JIT | ||
140 | 21 | codeBlock.setFallBack(true); | ||
141 | 22 | +#endif | ||
142 | 23 | byteCode = JSC::Yarr::byteCompile(yarrPattern, cx->compartment->regExpAllocator).get(); | ||
143 | 24 | |||
144 | 25 | return true; | ||
145 | 26 | } | ||
146 | 27 | |||
147 | 28 | inline bool | ||
148 | 29 | RegExp::compile(JSContext *cx, TokenStream *ts) | ||
149 | 30 | { | ||
150 | 31 | diff --git a/mozilla/js/src/yarr/OSAllocatorPosix.cpp b/mozilla/js/src/yarr/OSAllocatorPosix.cpp | ||
151 | 32 | --- a/mozilla/js/src/yarr/OSAllocatorPosix.cpp | ||
152 | 33 | +++ b/mozilla/js/src/yarr/OSAllocatorPosix.cpp | ||
153 | 34 | @@ -24,17 +24,17 @@ | ||
154 | 35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
155 | 36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||
156 | 37 | * THE POSSIBILITY OF SUCH DAMAGE. | ||
157 | 38 | * | ||
158 | 39 | * ***** END LICENSE BLOCK ***** */ | ||
159 | 40 | |||
160 | 41 | #include "assembler/wtf/Platform.h" | ||
161 | 42 | |||
162 | 43 | -#if ENABLE_ASSEMBLER && WTF_OS_UNIX && !WTF_OS_SYMBIAN | ||
163 | 44 | +#if WTF_OS_UNIX && !WTF_OS_SYMBIAN | ||
164 | 45 | |||
165 | 46 | #include "OSAllocator.h" | ||
166 | 47 | |||
167 | 48 | #include <errno.h> | ||
168 | 49 | #include <sys/mman.h> | ||
169 | 50 | #include "wtf/Assertions.h" | ||
170 | 51 | |||
171 | 52 | namespace WTF { | ||
172 | 53 | diff --git a/mozilla/js/src/yarr/wtfbridge.h b/mozilla/js/src/yarr/wtfbridge.h | ||
173 | 54 | --- a/mozilla/js/src/yarr/wtfbridge.h | ||
174 | 55 | +++ b/mozilla/js/src/yarr/wtfbridge.h | ||
175 | 56 | @@ -45,17 +45,19 @@ | ||
176 | 57 | * definitions for use by Yarr. | ||
177 | 58 | */ | ||
178 | 59 | |||
179 | 60 | #include "jsstr.h" | ||
180 | 61 | #include "jsprvtd.h" | ||
181 | 62 | #include "jstl.h" | ||
182 | 63 | #include "vm/String.h" | ||
183 | 64 | #include "assembler/wtf/Platform.h" | ||
184 | 65 | +#if ENABLE_YARR_JIT | ||
185 | 66 | #include "assembler/jit/ExecutableAllocator.h" | ||
186 | 67 | +#endif | ||
187 | 68 | |||
188 | 69 | namespace JSC { namespace Yarr { | ||
189 | 70 | |||
190 | 71 | /* | ||
191 | 72 | * Basic type definitions. | ||
192 | 73 | */ | ||
193 | 74 | |||
194 | 75 | typedef jschar UChar; | ||
195 | 76 | @@ -256,27 +258,31 @@ class Vector<OwnPtr<T> > { | ||
196 | 77 | }; | ||
197 | 78 | |||
198 | 79 | template <typename T, size_t N> | ||
199 | 80 | inline void | ||
200 | 81 | deleteAllValues(Vector<T, N> &v) { | ||
201 | 82 | v.deleteAllValues(); | ||
202 | 83 | } | ||
203 | 84 | |||
204 | 85 | +#if ENABLE_YARR_JIT | ||
205 | 86 | + | ||
206 | 87 | /* | ||
207 | 88 | * Minimal JSGlobalData. This used by Yarr to get the allocator. | ||
208 | 89 | */ | ||
209 | 90 | class JSGlobalData { | ||
210 | 91 | public: | ||
211 | 92 | ExecutableAllocator *regexAllocator; | ||
212 | 93 | |||
213 | 94 | JSGlobalData(ExecutableAllocator *regexAllocator) | ||
214 | 95 | : regexAllocator(regexAllocator) { } | ||
215 | 96 | }; | ||
216 | 97 | |||
217 | 98 | +#endif | ||
218 | 99 | + | ||
219 | 100 | /* | ||
220 | 101 | * Sentinel value used in Yarr. | ||
221 | 102 | */ | ||
222 | 103 | const size_t notFound = size_t(-1); | ||
223 | 104 | |||
224 | 105 | /* | ||
225 | 106 | * Do-nothing version of a macro used by WTF to avoid unused | ||
226 | 107 | * parameter warnings. | ||
227 | 108 | |||
228 | 109 | |||
229 | 110 | 0 | ||
230 | === removed file 'debian/patches/compile-pldhash-as-C++.patch' | |||
231 | --- debian/patches/compile-pldhash-as-C++.patch 2011-10-11 07:49:14 +0000 | |||
232 | +++ debian/patches/compile-pldhash-as-C++.patch 1970-01-01 00:00:00 +0000 | |||
233 | @@ -1,1970 +0,0 @@ | |||
234 | 1 | # HG changeset patch | ||
235 | 2 | # User Mike Hommey <mh+mozilla@glandium.org> | ||
236 | 3 | # Date 1312873597 -7200 | ||
237 | 4 | # Node ID 3d20269baeeef329887625951d46872c15b4c861 | ||
238 | 5 | # Parent 4c3bcc010d85f1ac063e76da0329d4df3ae6dadc | ||
239 | 6 | Bug 675618 - Compile pldhash as C++. r=bsmedberg | ||
240 | 7 | |||
241 | 8 | --- a/mozilla/xpcom/build/Makefile.in | ||
242 | 9 | +++ b/mozilla/xpcom/build/Makefile.in | ||
243 | 10 | @@ -55,10 +55,6 @@ EXPORT_LIBRARY = 1 | ||
244 | 11 | GRE_MODULE = 1 | ||
245 | 12 | MOZILLA_INTERNAL_API = 1 | ||
246 | 13 | |||
247 | 14 | -CSRCS = \ | ||
248 | 15 | - $(XPCOM_GLUE_SRC_LCSRCS) \ | ||
249 | 16 | - $(NULL) | ||
250 | 17 | - | ||
251 | 18 | CPPSRCS = \ | ||
252 | 19 | $(XPCOM_GLUE_SRC_LCPPSRCS) \ | ||
253 | 20 | $(XPCOM_GLUENS_SRC_LCPPSRCS) \ | ||
254 | 21 | @@ -128,7 +124,7 @@ EXPORTS_mozilla = \ | ||
255 | 22 | # Force use of PIC | ||
256 | 23 | FORCE_USE_PIC = 1 | ||
257 | 24 | |||
258 | 25 | -GARBAGE += $(XPCOM_GLUE_SRC_LCSRCS) $(XPCOM_GLUE_SRC_LCPPSRCS) $(XPCOM_GLUENS_SRC_LCPPSRCS) $(wildcard *.$(OBJ_SUFFIX)) | ||
259 | 26 | +GARBAGE += $(XPCOM_GLUE_SRC_LCPPSRCS) $(XPCOM_GLUENS_SRC_LCPPSRCS) $(wildcard *.$(OBJ_SUFFIX)) | ||
260 | 27 | |||
261 | 28 | include $(topsrcdir)/config/config.mk | ||
262 | 29 | include $(topsrcdir)/ipc/chromium/chromium-config.mk | ||
263 | 30 | @@ -148,5 +144,5 @@ ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) | ||
264 | 31 | CXXFLAGS += $(TK_CFLAGS) | ||
265 | 32 | endif | ||
266 | 33 | |||
267 | 34 | -export:: $(XPCOM_GLUE_SRC_CSRCS) $(XPCOM_GLUE_SRC_CPPSRCS) $(XPCOM_GLUENS_SRC_CPPSRCS) | ||
268 | 35 | +export:: $(XPCOM_GLUE_SRC_CPPSRCS) $(XPCOM_GLUENS_SRC_CPPSRCS) | ||
269 | 36 | $(INSTALL) $^ . | ||
270 | 37 | --- a/mozilla/xpcom/glue/Makefile.in | ||
271 | 38 | +++ b/mozilla/xpcom/glue/Makefile.in | ||
272 | 39 | @@ -55,10 +55,6 @@ LOCAL_INCLUDES = \ | ||
273 | 40 | -I$(srcdir)/../build \ | ||
274 | 41 | $(NULL) | ||
275 | 42 | |||
276 | 43 | -CSRCS = \ | ||
277 | 44 | - $(XPCOM_GLUE_SRC_LCSRCS) \ | ||
278 | 45 | - $(NULL) | ||
279 | 46 | - | ||
280 | 47 | CPPSRCS = \ | ||
281 | 48 | $(XPCOM_GLUE_SRC_LCPPSRCS) \ | ||
282 | 49 | $(XPCOM_GLUENS_SRC_LCPPSRCS) \ | ||
283 | 50 | --- a/mozilla/xpcom/glue/nomozalloc/Makefile.in | ||
284 | 51 | +++ b/mozilla/xpcom/glue/nomozalloc/Makefile.in | ||
285 | 52 | @@ -54,10 +54,6 @@ LOCAL_INCLUDES = \ | ||
286 | 53 | -I$(srcdir)/../../build \ | ||
287 | 54 | $(NULL) | ||
288 | 55 | |||
289 | 56 | -CSRCS = \ | ||
290 | 57 | - $(XPCOM_GLUE_SRC_LCSRCS) \ | ||
291 | 58 | - $(NULL) | ||
292 | 59 | - | ||
293 | 60 | CPPSRCS = \ | ||
294 | 61 | $(XPCOM_GLUE_SRC_LCPPSRCS) \ | ||
295 | 62 | $(XPCOM_GLUENS_SRC_LCPPSRCS) \ | ||
296 | 63 | @@ -69,7 +65,7 @@ SDK_LIBRARY = | ||
297 | 64 | $(LIB_PREFIX)xpcomglue_s_nomozalloc.$(LIB_SUFFIX) \ | ||
298 | 65 | $(NULL) | ||
299 | 66 | |||
300 | 67 | -GARBAGE += $(CSRCS) $(CPPSRCS) DeadlockDetector.h SSE.h arm.h | ||
301 | 68 | +GARBAGE += $(CPPSRCS) DeadlockDetector.h SSE.h arm.h | ||
302 | 69 | |||
303 | 70 | # we don't want the shared lib, but we want to force the creation of a static lib. | ||
304 | 71 | FORCE_STATIC_LIB = 1 | ||
305 | 72 | @@ -94,7 +90,7 @@ OS_COMPILE_CFLAGS += -Zl | ||
306 | 73 | DEFINES += -D_USE_ANSI_CPP | ||
307 | 74 | endif | ||
308 | 75 | |||
309 | 76 | -export:: $(XPCOM_GLUE_SRC_CSRCS) $(XPCOM_GLUE_SRC_CPPSRCS) $(XPCOM_GLUENS_SRC_CPPSRCS) $(topsrcdir)/xpcom/glue/nsStringAPI.cpp $(topsrcdir)/xpcom/glue/GenericModule.cpp $(topsrcdir)/xpcom/glue/DeadlockDetector.h $(topsrcdir)/xpcom/glue/SSE.h $(topsrcdir)/xpcom/glue/arm.h | ||
310 | 77 | +export:: $(XPCOM_GLUE_SRC_CPPSRCS) $(XPCOM_GLUENS_SRC_CPPSRCS) $(topsrcdir)/xpcom/glue/nsStringAPI.cpp $(topsrcdir)/xpcom/glue/GenericModule.cpp $(topsrcdir)/xpcom/glue/DeadlockDetector.h $(topsrcdir)/xpcom/glue/SSE.h $(topsrcdir)/xpcom/glue/arm.h | ||
311 | 78 | $(INSTALL) $^ . | ||
312 | 79 | |||
313 | 80 | ifdef TARGET_XPCOM_ABI | ||
314 | 81 | --- a/mozilla/xpcom/glue/objs.mk | ||
315 | 82 | +++ b/mozilla/xpcom/glue/objs.mk | ||
316 | 83 | @@ -34,12 +34,6 @@ | ||
317 | 84 | # | ||
318 | 85 | # ***** END LICENSE BLOCK ***** | ||
319 | 86 | |||
320 | 87 | -XPCOM_GLUE_SRC_LCSRCS = \ | ||
321 | 88 | - pldhash.c \ | ||
322 | 89 | - $(NULL) | ||
323 | 90 | - | ||
324 | 91 | -XPCOM_GLUE_SRC_CSRCS = $(addprefix $(topsrcdir)/xpcom/glue/, $(XPCOM_GLUE_SRC_LCSRCS)) | ||
325 | 92 | - | ||
326 | 93 | XPCOM_GLUE_SRC_LCPPSRCS = \ | ||
327 | 94 | nsArrayEnumerator.cpp \ | ||
328 | 95 | nsArrayUtils.cpp \ | ||
329 | 96 | @@ -66,6 +60,7 @@ XPCOM_GLUE_SRC_LCPPSRCS = \ | ||
330 | 97 | nsCycleCollectionParticipant.cpp \ | ||
331 | 98 | nsCycleCollectorUtils.cpp \ | ||
332 | 99 | nsDeque.cpp \ | ||
333 | 100 | + pldhash.cpp \ | ||
334 | 101 | $(NULL) | ||
335 | 102 | |||
336 | 103 | XPCOM_GLUE_SRC_CPPSRCS = $(addprefix $(topsrcdir)/xpcom/glue/, $(XPCOM_GLUE_SRC_LCPPSRCS)) | ||
337 | 104 | --- a/mozilla/xpcom/glue/standalone/Makefile.in | ||
338 | 105 | +++ b/mozilla/xpcom/glue/standalone/Makefile.in | ||
339 | 106 | @@ -71,10 +71,6 @@ LINKSRC = nsGlueLinkingNull.cpp | ||
340 | 107 | $(warning TinderboxPrint:<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=298044">Error: XPCOM Glue</a>) | ||
341 | 108 | endif | ||
342 | 109 | |||
343 | 110 | -CSRCS = \ | ||
344 | 111 | - $(XPCOM_GLUE_SRC_LCSRCS) \ | ||
345 | 112 | - $(NULL) | ||
346 | 113 | - | ||
347 | 114 | CPPSRCS = \ | ||
348 | 115 | $(XPCOM_GLUE_SRC_LCPPSRCS) \ | ||
349 | 116 | nsStringAPI.cpp \ | ||
350 | 117 | @@ -104,7 +100,7 @@ USE_STATIC_LIBS = 1 | ||
351 | 118 | # Don't use STL wrappers here (i.e. wrapped <new>); they require mozalloc | ||
352 | 119 | STL_FLAGS = | ||
353 | 120 | |||
354 | 121 | -GARBAGE += $(XPCOM_GLUE_SRC_LCSRCS) $(XPCOM_GLUE_SRC_LCPPSRCS) $(wildcard *.$(OBJ_SUFFIX)) | ||
355 | 122 | +GARBAGE += $(XPCOM_GLUE_SRC_LCPPSRCS) $(wildcard *.$(OBJ_SUFFIX)) | ||
356 | 123 | |||
357 | 124 | SRCS_IN_OBJDIR = 1 | ||
358 | 125 | |||
359 | 126 | @@ -117,7 +113,7 @@ OS_COMPILE_CFLAGS += -Zl | ||
360 | 127 | DEFINES += -D_USE_ANSI_CPP | ||
361 | 128 | endif | ||
362 | 129 | |||
363 | 130 | -export:: $(XPCOM_GLUE_SRC_CSRCS) $(XPCOM_GLUE_SRC_CPPSRCS) $(topsrcdir)/xpcom/glue/nsStringAPI.cpp | ||
364 | 131 | +export:: $(XPCOM_GLUE_SRC_CPPSRCS) $(topsrcdir)/xpcom/glue/nsStringAPI.cpp | ||
365 | 132 | $(INSTALL) $^ . | ||
366 | 133 | |||
367 | 134 | GARBAGE += nsStringAPI.cpp | ||
368 | 135 | --- a/mozilla/xpcom/glue/pldhash.c | ||
369 | 136 | +++ /dev/null | ||
370 | 137 | @@ -1,915 +0,0 @@ | ||
371 | 138 | -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | ||
372 | 139 | -/* ***** BEGIN LICENSE BLOCK ***** | ||
373 | 140 | - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | ||
374 | 141 | - * | ||
375 | 142 | - * The contents of this file are subject to the Mozilla Public License Version | ||
376 | 143 | - * 1.1 (the "License"); you may not use this file except in compliance with | ||
377 | 144 | - * the License. You may obtain a copy of the License at | ||
378 | 145 | - * http://www.mozilla.org/MPL/ | ||
379 | 146 | - * | ||
380 | 147 | - * Software distributed under the License is distributed on an "AS IS" basis, | ||
381 | 148 | - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | ||
382 | 149 | - * for the specific language governing rights and limitations under the | ||
383 | 150 | - * License. | ||
384 | 151 | - * | ||
385 | 152 | - * The Original Code is Mozilla JavaScript code. | ||
386 | 153 | - * | ||
387 | 154 | - * The Initial Developer of the Original Code is | ||
388 | 155 | - * Netscape Communications Corporation. | ||
389 | 156 | - * Portions created by the Initial Developer are Copyright (C) 1999-2001 | ||
390 | 157 | - * the Initial Developer. All Rights Reserved. | ||
391 | 158 | - * | ||
392 | 159 | - * Contributor(s): | ||
393 | 160 | - * Brendan Eich <brendan@mozilla.org> (Original Author) | ||
394 | 161 | - * Chris Waterson <waterson@netscape.com> | ||
395 | 162 | - * L. David Baron <dbaron@dbaron.org>, Mozilla Corporation | ||
396 | 163 | - * | ||
397 | 164 | - * Alternatively, the contents of this file may be used under the terms of | ||
398 | 165 | - * either of the GNU General Public License Version 2 or later (the "GPL"), | ||
399 | 166 | - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | ||
400 | 167 | - * in which case the provisions of the GPL or the LGPL are applicable instead | ||
401 | 168 | - * of those above. If you wish to allow use of your version of this file only | ||
402 | 169 | - * under the terms of either the GPL or the LGPL, and not to allow others to | ||
403 | 170 | - * use your version of this file under the terms of the MPL, indicate your | ||
404 | 171 | - * decision by deleting the provisions above and replace them with the notice | ||
405 | 172 | - * and other provisions required by the GPL or the LGPL. If you do not delete | ||
406 | 173 | - * the provisions above, a recipient may use your version of this file under | ||
407 | 174 | - * the terms of any one of the MPL, the GPL or the LGPL. | ||
408 | 175 | - * | ||
409 | 176 | - * ***** END LICENSE BLOCK ***** */ | ||
410 | 177 | - | ||
411 | 178 | -/* | ||
412 | 179 | - * Double hashing implementation. | ||
413 | 180 | - * GENERATED BY js/src/plify_jsdhash.sed -- DO NOT EDIT!!! | ||
414 | 181 | - */ | ||
415 | 182 | -#include <stdio.h> | ||
416 | 183 | -#include <stdlib.h> | ||
417 | 184 | -#include <string.h> | ||
418 | 185 | -#include "prbit.h" | ||
419 | 186 | -#include "pldhash.h" | ||
420 | 187 | -#include "nsDebug.h" /* for PR_ASSERT */ | ||
421 | 188 | - | ||
422 | 189 | -#ifdef PL_DHASHMETER | ||
423 | 190 | -# if defined MOZILLA_CLIENT && defined DEBUG_XXXbrendan | ||
424 | 191 | -# include "nsTraceMalloc.h" | ||
425 | 192 | -# endif | ||
426 | 193 | -# define METER(x) x | ||
427 | 194 | -#else | ||
428 | 195 | -# define METER(x) /* nothing */ | ||
429 | 196 | -#endif | ||
430 | 197 | - | ||
431 | 198 | -/* | ||
432 | 199 | - * The following DEBUG-only code is used to assert that calls to one of | ||
433 | 200 | - * table->ops or to an enumerator do not cause re-entry into a call that | ||
434 | 201 | - * can mutate the table. The recursion level is stored in additional | ||
435 | 202 | - * space allocated at the end of the entry store to avoid changing | ||
436 | 203 | - * PLDHashTable, which could cause issues when mixing DEBUG and | ||
437 | 204 | - * non-DEBUG components. | ||
438 | 205 | - */ | ||
439 | 206 | -#ifdef DEBUG | ||
440 | 207 | - | ||
441 | 208 | -#define JSDHASH_ONELINE_ASSERT PR_ASSERT | ||
442 | 209 | -#define RECURSION_LEVEL(table_) (*(PRUint32*)(table_->entryStore + \ | ||
443 | 210 | - PL_DHASH_TABLE_SIZE(table_) * \ | ||
444 | 211 | - table_->entrySize)) | ||
445 | 212 | -/* | ||
446 | 213 | - * Most callers that assert about the recursion level don't care about | ||
447 | 214 | - * this magical value because they are asserting that mutation is | ||
448 | 215 | - * allowed (and therefore the level is 0 or 1, depending on whether they | ||
449 | 216 | - * incremented it). | ||
450 | 217 | - * | ||
451 | 218 | - * Only PL_DHashTableFinish needs to allow this special value. | ||
452 | 219 | - */ | ||
453 | 220 | -#define IMMUTABLE_RECURSION_LEVEL ((PRUint32)-1) | ||
454 | 221 | - | ||
455 | 222 | -#define RECURSION_LEVEL_SAFE_TO_FINISH(table_) \ | ||
456 | 223 | - (RECURSION_LEVEL(table_) == 0 || \ | ||
457 | 224 | - RECURSION_LEVEL(table_) == IMMUTABLE_RECURSION_LEVEL) | ||
458 | 225 | - | ||
459 | 226 | -#define ENTRY_STORE_EXTRA sizeof(PRUint32) | ||
460 | 227 | -#define INCREMENT_RECURSION_LEVEL(table_) \ | ||
461 | 228 | - PR_BEGIN_MACRO \ | ||
462 | 229 | - if (RECURSION_LEVEL(table_) != IMMUTABLE_RECURSION_LEVEL) \ | ||
463 | 230 | - ++RECURSION_LEVEL(table_); \ | ||
464 | 231 | - PR_END_MACRO | ||
465 | 232 | -#define DECREMENT_RECURSION_LEVEL(table_) \ | ||
466 | 233 | - PR_BEGIN_MACRO \ | ||
467 | 234 | - if (RECURSION_LEVEL(table_) != IMMUTABLE_RECURSION_LEVEL) { \ | ||
468 | 235 | - NS_ASSERTION(RECURSION_LEVEL(table_) > 0, "RECURSION_LEVEL(table_) > 0"); \ | ||
469 | 236 | - --RECURSION_LEVEL(table_); \ | ||
470 | 237 | - } \ | ||
471 | 238 | - PR_END_MACRO | ||
472 | 239 | - | ||
473 | 240 | -#else | ||
474 | 241 | - | ||
475 | 242 | -#define ENTRY_STORE_EXTRA 0 | ||
476 | 243 | -#define INCREMENT_RECURSION_LEVEL(table_) PR_BEGIN_MACRO PR_END_MACRO | ||
477 | 244 | -#define DECREMENT_RECURSION_LEVEL(table_) PR_BEGIN_MACRO PR_END_MACRO | ||
478 | 245 | - | ||
479 | 246 | -#endif /* defined(DEBUG) */ | ||
480 | 247 | - | ||
481 | 248 | -void * | ||
482 | 249 | -PL_DHashAllocTable(PLDHashTable *table, PRUint32 nbytes) | ||
483 | 250 | -{ | ||
484 | 251 | - return malloc(nbytes); | ||
485 | 252 | -} | ||
486 | 253 | - | ||
487 | 254 | -void | ||
488 | 255 | -PL_DHashFreeTable(PLDHashTable *table, void *ptr) | ||
489 | 256 | -{ | ||
490 | 257 | - free(ptr); | ||
491 | 258 | -} | ||
492 | 259 | - | ||
493 | 260 | -PLDHashNumber | ||
494 | 261 | -PL_DHashStringKey(PLDHashTable *table, const void *key) | ||
495 | 262 | -{ | ||
496 | 263 | - PLDHashNumber h; | ||
497 | 264 | - const unsigned char *s; | ||
498 | 265 | - | ||
499 | 266 | - h = 0; | ||
500 | 267 | - for (s = (const unsigned char *) key; *s != '\0'; s++) | ||
501 | 268 | - h = PR_ROTATE_LEFT32(h, 4) ^ *s; | ||
502 | 269 | - return h; | ||
503 | 270 | -} | ||
504 | 271 | - | ||
505 | 272 | -PLDHashNumber | ||
506 | 273 | -PL_DHashVoidPtrKeyStub(PLDHashTable *table, const void *key) | ||
507 | 274 | -{ | ||
508 | 275 | - return (PLDHashNumber)(unsigned long)key >> 2; | ||
509 | 276 | -} | ||
510 | 277 | - | ||
511 | 278 | -PRBool | ||
512 | 279 | -PL_DHashMatchEntryStub(PLDHashTable *table, | ||
513 | 280 | - const PLDHashEntryHdr *entry, | ||
514 | 281 | - const void *key) | ||
515 | 282 | -{ | ||
516 | 283 | - const PLDHashEntryStub *stub = (const PLDHashEntryStub *)entry; | ||
517 | 284 | - | ||
518 | 285 | - return stub->key == key; | ||
519 | 286 | -} | ||
520 | 287 | - | ||
521 | 288 | -PRBool | ||
522 | 289 | -PL_DHashMatchStringKey(PLDHashTable *table, | ||
523 | 290 | - const PLDHashEntryHdr *entry, | ||
524 | 291 | - const void *key) | ||
525 | 292 | -{ | ||
526 | 293 | - const PLDHashEntryStub *stub = (const PLDHashEntryStub *)entry; | ||
527 | 294 | - | ||
528 | 295 | - /* XXX tolerate null keys on account of sloppy Mozilla callers. */ | ||
529 | 296 | - return stub->key == key || | ||
530 | 297 | - (stub->key && key && | ||
531 | 298 | - strcmp((const char *) stub->key, (const char *) key) == 0); | ||
532 | 299 | -} | ||
533 | 300 | - | ||
534 | 301 | -void | ||
535 | 302 | -PL_DHashMoveEntryStub(PLDHashTable *table, | ||
536 | 303 | - const PLDHashEntryHdr *from, | ||
537 | 304 | - PLDHashEntryHdr *to) | ||
538 | 305 | -{ | ||
539 | 306 | - memcpy(to, from, table->entrySize); | ||
540 | 307 | -} | ||
541 | 308 | - | ||
542 | 309 | -void | ||
543 | 310 | -PL_DHashClearEntryStub(PLDHashTable *table, PLDHashEntryHdr *entry) | ||
544 | 311 | -{ | ||
545 | 312 | - memset(entry, 0, table->entrySize); | ||
546 | 313 | -} | ||
547 | 314 | - | ||
548 | 315 | -void | ||
549 | 316 | -PL_DHashFreeStringKey(PLDHashTable *table, PLDHashEntryHdr *entry) | ||
550 | 317 | -{ | ||
551 | 318 | - const PLDHashEntryStub *stub = (const PLDHashEntryStub *)entry; | ||
552 | 319 | - | ||
553 | 320 | - free((void *) stub->key); | ||
554 | 321 | - memset(entry, 0, table->entrySize); | ||
555 | 322 | -} | ||
556 | 323 | - | ||
557 | 324 | -void | ||
558 | 325 | -PL_DHashFinalizeStub(PLDHashTable *table) | ||
559 | 326 | -{ | ||
560 | 327 | -} | ||
561 | 328 | - | ||
562 | 329 | -static const PLDHashTableOps stub_ops = { | ||
563 | 330 | - PL_DHashAllocTable, | ||
564 | 331 | - PL_DHashFreeTable, | ||
565 | 332 | - PL_DHashVoidPtrKeyStub, | ||
566 | 333 | - PL_DHashMatchEntryStub, | ||
567 | 334 | - PL_DHashMoveEntryStub, | ||
568 | 335 | - PL_DHashClearEntryStub, | ||
569 | 336 | - PL_DHashFinalizeStub, | ||
570 | 337 | - NULL | ||
571 | 338 | -}; | ||
572 | 339 | - | ||
573 | 340 | -const PLDHashTableOps * | ||
574 | 341 | -PL_DHashGetStubOps(void) | ||
575 | 342 | -{ | ||
576 | 343 | - return &stub_ops; | ||
577 | 344 | -} | ||
578 | 345 | - | ||
579 | 346 | -PLDHashTable * | ||
580 | 347 | -PL_NewDHashTable(const PLDHashTableOps *ops, void *data, PRUint32 entrySize, | ||
581 | 348 | - PRUint32 capacity) | ||
582 | 349 | -{ | ||
583 | 350 | - PLDHashTable *table; | ||
584 | 351 | - | ||
585 | 352 | - table = (PLDHashTable *) malloc(sizeof *table); | ||
586 | 353 | - if (!table) | ||
587 | 354 | - return NULL; | ||
588 | 355 | - if (!PL_DHashTableInit(table, ops, data, entrySize, capacity)) { | ||
589 | 356 | - free(table); | ||
590 | 357 | - return NULL; | ||
591 | 358 | - } | ||
592 | 359 | - return table; | ||
593 | 360 | -} | ||
594 | 361 | - | ||
595 | 362 | -void | ||
596 | 363 | -PL_DHashTableDestroy(PLDHashTable *table) | ||
597 | 364 | -{ | ||
598 | 365 | - PL_DHashTableFinish(table); | ||
599 | 366 | - free(table); | ||
600 | 367 | -} | ||
601 | 368 | - | ||
602 | 369 | -PRBool | ||
603 | 370 | -PL_DHashTableInit(PLDHashTable *table, const PLDHashTableOps *ops, void *data, | ||
604 | 371 | - PRUint32 entrySize, PRUint32 capacity) | ||
605 | 372 | -{ | ||
606 | 373 | - int log2; | ||
607 | 374 | - PRUint32 nbytes; | ||
608 | 375 | - | ||
609 | 376 | -#ifdef DEBUG | ||
610 | 377 | - if (entrySize > 10 * sizeof(void *)) { | ||
611 | 378 | - printf_stderr( | ||
612 | 379 | - "pldhash: for the table at address %p, the given entrySize" | ||
613 | 380 | - " of %lu %s favors chaining over double hashing.\n", | ||
614 | 381 | - (void *) table, | ||
615 | 382 | - (unsigned long) entrySize, | ||
616 | 383 | - (entrySize > 16 * sizeof(void*)) ? "definitely" : "probably"); | ||
617 | 384 | - } | ||
618 | 385 | -#endif | ||
619 | 386 | - | ||
620 | 387 | - table->ops = ops; | ||
621 | 388 | - table->data = data; | ||
622 | 389 | - if (capacity < PL_DHASH_MIN_SIZE) | ||
623 | 390 | - capacity = PL_DHASH_MIN_SIZE; | ||
624 | 391 | - | ||
625 | 392 | - PR_CEILING_LOG2(log2, capacity); | ||
626 | 393 | - | ||
627 | 394 | - capacity = PR_BIT(log2); | ||
628 | 395 | - if (capacity >= PL_DHASH_SIZE_LIMIT) | ||
629 | 396 | - return PR_FALSE; | ||
630 | 397 | - table->hashShift = PL_DHASH_BITS - log2; | ||
631 | 398 | - table->maxAlphaFrac = (PRUint8)(0x100 * PL_DHASH_DEFAULT_MAX_ALPHA); | ||
632 | 399 | - table->minAlphaFrac = (PRUint8)(0x100 * PL_DHASH_DEFAULT_MIN_ALPHA); | ||
633 | 400 | - table->entrySize = entrySize; | ||
634 | 401 | - table->entryCount = table->removedCount = 0; | ||
635 | 402 | - table->generation = 0; | ||
636 | 403 | - nbytes = capacity * entrySize; | ||
637 | 404 | - | ||
638 | 405 | - table->entryStore = (char *) ops->allocTable(table, | ||
639 | 406 | - nbytes + ENTRY_STORE_EXTRA); | ||
640 | 407 | - if (!table->entryStore) | ||
641 | 408 | - return PR_FALSE; | ||
642 | 409 | - memset(table->entryStore, 0, nbytes); | ||
643 | 410 | - METER(memset(&table->stats, 0, sizeof table->stats)); | ||
644 | 411 | - | ||
645 | 412 | -#ifdef DEBUG | ||
646 | 413 | - RECURSION_LEVEL(table) = 0; | ||
647 | 414 | -#endif | ||
648 | 415 | - | ||
649 | 416 | - return PR_TRUE; | ||
650 | 417 | -} | ||
651 | 418 | - | ||
652 | 419 | -/* | ||
653 | 420 | - * Compute max and min load numbers (entry counts) from table params. | ||
654 | 421 | - */ | ||
655 | 422 | -#define MAX_LOAD(table, size) (((table)->maxAlphaFrac * (size)) >> 8) | ||
656 | 423 | -#define MIN_LOAD(table, size) (((table)->minAlphaFrac * (size)) >> 8) | ||
657 | 424 | - | ||
658 | 425 | -void | ||
659 | 426 | -PL_DHashTableSetAlphaBounds(PLDHashTable *table, | ||
660 | 427 | - float maxAlpha, | ||
661 | 428 | - float minAlpha) | ||
662 | 429 | -{ | ||
663 | 430 | - PRUint32 size; | ||
664 | 431 | - | ||
665 | 432 | - /* | ||
666 | 433 | - * Reject obviously insane bounds, rather than trying to guess what the | ||
667 | 434 | - * buggy caller intended. | ||
668 | 435 | - */ | ||
669 | 436 | - NS_ASSERTION(0.5 <= maxAlpha && maxAlpha < 1 && 0 <= minAlpha, | ||
670 | 437 | - "0.5 <= maxAlpha && maxAlpha < 1 && 0 <= minAlpha"); | ||
671 | 438 | - if (maxAlpha < 0.5 || 1 <= maxAlpha || minAlpha < 0) | ||
672 | 439 | - return; | ||
673 | 440 | - | ||
674 | 441 | - /* | ||
675 | 442 | - * Ensure that at least one entry will always be free. If maxAlpha at | ||
676 | 443 | - * minimum size leaves no entries free, reduce maxAlpha based on minimum | ||
677 | 444 | - * size and the precision limit of maxAlphaFrac's fixed point format. | ||
678 | 445 | - */ | ||
679 | 446 | - NS_ASSERTION(PL_DHASH_MIN_SIZE - (maxAlpha * PL_DHASH_MIN_SIZE) >= 1, | ||
680 | 447 | - "PL_DHASH_MIN_SIZE - (maxAlpha * PL_DHASH_MIN_SIZE) >= 1"); | ||
681 | 448 | - if (PL_DHASH_MIN_SIZE - (maxAlpha * PL_DHASH_MIN_SIZE) < 1) { | ||
682 | 449 | - maxAlpha = (float) | ||
683 | 450 | - (PL_DHASH_MIN_SIZE - PR_MAX(PL_DHASH_MIN_SIZE / 256, 1)) | ||
684 | 451 | - / PL_DHASH_MIN_SIZE; | ||
685 | 452 | - } | ||
686 | 453 | - | ||
687 | 454 | - /* | ||
688 | 455 | - * Ensure that minAlpha is strictly less than half maxAlpha. Take care | ||
689 | 456 | - * not to truncate an entry's worth of alpha when storing in minAlphaFrac | ||
690 | 457 | - * (8-bit fixed point format). | ||
691 | 458 | - */ | ||
692 | 459 | - NS_ASSERTION(minAlpha < maxAlpha / 2, | ||
693 | 460 | - "minAlpha < maxAlpha / 2"); | ||
694 | 461 | - if (minAlpha >= maxAlpha / 2) { | ||
695 | 462 | - size = PL_DHASH_TABLE_SIZE(table); | ||
696 | 463 | - minAlpha = (size * maxAlpha - PR_MAX(size / 256, 1)) / (2 * size); | ||
697 | 464 | - } | ||
698 | 465 | - | ||
699 | 466 | - table->maxAlphaFrac = (PRUint8)(maxAlpha * 256); | ||
700 | 467 | - table->minAlphaFrac = (PRUint8)(minAlpha * 256); | ||
701 | 468 | -} | ||
702 | 469 | - | ||
703 | 470 | -/* | ||
704 | 471 | - * Double hashing needs the second hash code to be relatively prime to table | ||
705 | 472 | - * size, so we simply make hash2 odd. | ||
706 | 473 | - */ | ||
707 | 474 | -#define HASH1(hash0, shift) ((hash0) >> (shift)) | ||
708 | 475 | -#define HASH2(hash0,log2,shift) ((((hash0) << (log2)) >> (shift)) | 1) | ||
709 | 476 | - | ||
710 | 477 | -/* | ||
711 | 478 | - * Reserve keyHash 0 for free entries and 1 for removed-entry sentinels. Note | ||
712 | 479 | - * that a removed-entry sentinel need be stored only if the removed entry had | ||
713 | 480 | - * a colliding entry added after it. Therefore we can use 1 as the collision | ||
714 | 481 | - * flag in addition to the removed-entry sentinel value. Multiplicative hash | ||
715 | 482 | - * uses the high order bits of keyHash, so this least-significant reservation | ||
716 | 483 | - * should not hurt the hash function's effectiveness much. | ||
717 | 484 | - * | ||
718 | 485 | - * If you change any of these magic numbers, also update PL_DHASH_ENTRY_IS_LIVE | ||
719 | 486 | - * in pldhash.h. It used to be private to pldhash.c, but then became public to | ||
720 | 487 | - * assist iterator writers who inspect table->entryStore directly. | ||
721 | 488 | - */ | ||
722 | 489 | -#define COLLISION_FLAG ((PLDHashNumber) 1) | ||
723 | 490 | -#define MARK_ENTRY_FREE(entry) ((entry)->keyHash = 0) | ||
724 | 491 | -#define MARK_ENTRY_REMOVED(entry) ((entry)->keyHash = 1) | ||
725 | 492 | -#define ENTRY_IS_REMOVED(entry) ((entry)->keyHash == 1) | ||
726 | 493 | -#define ENTRY_IS_LIVE(entry) PL_DHASH_ENTRY_IS_LIVE(entry) | ||
727 | 494 | -#define ENSURE_LIVE_KEYHASH(hash0) if (hash0 < 2) hash0 -= 2; else (void)0 | ||
728 | 495 | - | ||
729 | 496 | -/* Match an entry's keyHash against an unstored one computed from a key. */ | ||
730 | 497 | -#define MATCH_ENTRY_KEYHASH(entry,hash0) \ | ||
731 | 498 | - (((entry)->keyHash & ~COLLISION_FLAG) == (hash0)) | ||
732 | 499 | - | ||
733 | 500 | -/* Compute the address of the indexed entry in table. */ | ||
734 | 501 | -#define ADDRESS_ENTRY(table, index) \ | ||
735 | 502 | - ((PLDHashEntryHdr *)((table)->entryStore + (index) * (table)->entrySize)) | ||
736 | 503 | - | ||
737 | 504 | -void | ||
738 | 505 | -PL_DHashTableFinish(PLDHashTable *table) | ||
739 | 506 | -{ | ||
740 | 507 | - char *entryAddr, *entryLimit; | ||
741 | 508 | - PRUint32 entrySize; | ||
742 | 509 | - PLDHashEntryHdr *entry; | ||
743 | 510 | - | ||
744 | 511 | -#ifdef DEBUG_XXXbrendan | ||
745 | 512 | - static FILE *dumpfp = NULL; | ||
746 | 513 | - if (!dumpfp) dumpfp = fopen("/tmp/pldhash.bigdump", "w"); | ||
747 | 514 | - if (dumpfp) { | ||
748 | 515 | -#ifdef MOZILLA_CLIENT | ||
749 | 516 | - NS_TraceStack(1, dumpfp); | ||
750 | 517 | -#endif | ||
751 | 518 | - PL_DHashTableDumpMeter(table, NULL, dumpfp); | ||
752 | 519 | - fputc('\n', dumpfp); | ||
753 | 520 | - } | ||
754 | 521 | -#endif | ||
755 | 522 | - | ||
756 | 523 | - INCREMENT_RECURSION_LEVEL(table); | ||
757 | 524 | - | ||
758 | 525 | - /* Call finalize before clearing entries, so it can enumerate them. */ | ||
759 | 526 | - table->ops->finalize(table); | ||
760 | 527 | - | ||
761 | 528 | - /* Clear any remaining live entries. */ | ||
762 | 529 | - entryAddr = table->entryStore; | ||
763 | 530 | - entrySize = table->entrySize; | ||
764 | 531 | - entryLimit = entryAddr + PL_DHASH_TABLE_SIZE(table) * entrySize; | ||
765 | 532 | - while (entryAddr < entryLimit) { | ||
766 | 533 | - entry = (PLDHashEntryHdr *)entryAddr; | ||
767 | 534 | - if (ENTRY_IS_LIVE(entry)) { | ||
768 | 535 | - METER(table->stats.removeEnums++); | ||
769 | 536 | - table->ops->clearEntry(table, entry); | ||
770 | 537 | - } | ||
771 | 538 | - entryAddr += entrySize; | ||
772 | 539 | - } | ||
773 | 540 | - | ||
774 | 541 | - DECREMENT_RECURSION_LEVEL(table); | ||
775 | 542 | - NS_ASSERTION(RECURSION_LEVEL_SAFE_TO_FINISH(table), | ||
776 | 543 | - "RECURSION_LEVEL_SAFE_TO_FINISH(table)"); | ||
777 | 544 | - | ||
778 | 545 | - /* Free entry storage last. */ | ||
779 | 546 | - table->ops->freeTable(table, table->entryStore); | ||
780 | 547 | -} | ||
781 | 548 | - | ||
782 | 549 | -static PLDHashEntryHdr * PL_DHASH_FASTCALL | ||
783 | 550 | -SearchTable(PLDHashTable *table, const void *key, PLDHashNumber keyHash, | ||
784 | 551 | - PLDHashOperator op) | ||
785 | 552 | -{ | ||
786 | 553 | - PLDHashNumber hash1, hash2; | ||
787 | 554 | - int hashShift, sizeLog2; | ||
788 | 555 | - PLDHashEntryHdr *entry, *firstRemoved; | ||
789 | 556 | - PLDHashMatchEntry matchEntry; | ||
790 | 557 | - PRUint32 sizeMask; | ||
791 | 558 | - | ||
792 | 559 | - METER(table->stats.searches++); | ||
793 | 560 | - NS_ASSERTION(!(keyHash & COLLISION_FLAG), | ||
794 | 561 | - "!(keyHash & COLLISION_FLAG)"); | ||
795 | 562 | - | ||
796 | 563 | - /* Compute the primary hash address. */ | ||
797 | 564 | - hashShift = table->hashShift; | ||
798 | 565 | - hash1 = HASH1(keyHash, hashShift); | ||
799 | 566 | - entry = ADDRESS_ENTRY(table, hash1); | ||
800 | 567 | - | ||
801 | 568 | - /* Miss: return space for a new entry. */ | ||
802 | 569 | - if (PL_DHASH_ENTRY_IS_FREE(entry)) { | ||
803 | 570 | - METER(table->stats.misses++); | ||
804 | 571 | - return entry; | ||
805 | 572 | - } | ||
806 | 573 | - | ||
807 | 574 | - /* Hit: return entry. */ | ||
808 | 575 | - matchEntry = table->ops->matchEntry; | ||
809 | 576 | - if (MATCH_ENTRY_KEYHASH(entry, keyHash) && matchEntry(table, entry, key)) { | ||
810 | 577 | - METER(table->stats.hits++); | ||
811 | 578 | - return entry; | ||
812 | 579 | - } | ||
813 | 580 | - | ||
814 | 581 | - /* Collision: double hash. */ | ||
815 | 582 | - sizeLog2 = PL_DHASH_BITS - table->hashShift; | ||
816 | 583 | - hash2 = HASH2(keyHash, sizeLog2, hashShift); | ||
817 | 584 | - sizeMask = PR_BITMASK(sizeLog2); | ||
818 | 585 | - | ||
819 | 586 | - /* Save the first removed entry pointer so PL_DHASH_ADD can recycle it. */ | ||
820 | 587 | - firstRemoved = NULL; | ||
821 | 588 | - | ||
822 | 589 | - for (;;) { | ||
823 | 590 | - if (NS_UNLIKELY(ENTRY_IS_REMOVED(entry))) { | ||
824 | 591 | - if (!firstRemoved) | ||
825 | 592 | - firstRemoved = entry; | ||
826 | 593 | - } else { | ||
827 | 594 | - if (op == PL_DHASH_ADD) | ||
828 | 595 | - entry->keyHash |= COLLISION_FLAG; | ||
829 | 596 | - } | ||
830 | 597 | - | ||
831 | 598 | - METER(table->stats.steps++); | ||
832 | 599 | - hash1 -= hash2; | ||
833 | 600 | - hash1 &= sizeMask; | ||
834 | 601 | - | ||
835 | 602 | - entry = ADDRESS_ENTRY(table, hash1); | ||
836 | 603 | - if (PL_DHASH_ENTRY_IS_FREE(entry)) { | ||
837 | 604 | - METER(table->stats.misses++); | ||
838 | 605 | - return (firstRemoved && op == PL_DHASH_ADD) ? firstRemoved : entry; | ||
839 | 606 | - } | ||
840 | 607 | - | ||
841 | 608 | - if (MATCH_ENTRY_KEYHASH(entry, keyHash) && | ||
842 | 609 | - matchEntry(table, entry, key)) { | ||
843 | 610 | - METER(table->stats.hits++); | ||
844 | 611 | - return entry; | ||
845 | 612 | - } | ||
846 | 613 | - } | ||
847 | 614 | - | ||
848 | 615 | - /* NOTREACHED */ | ||
849 | 616 | - return NULL; | ||
850 | 617 | -} | ||
851 | 618 | - | ||
852 | 619 | -/* | ||
853 | 620 | - * This is a copy of SearchTable, used by ChangeTable, hardcoded to | ||
854 | 621 | - * 1. assume |op == PL_DHASH_ADD|, | ||
855 | 622 | - * 2. assume that |key| will never match an existing entry, and | ||
856 | 623 | - * 3. assume that no entries have been removed from the current table | ||
857 | 624 | - * structure. | ||
858 | 625 | - * Avoiding the need for |key| means we can avoid needing a way to map | ||
859 | 626 | - * entries to keys, which means callers can use complex key types more | ||
860 | 627 | - * easily. | ||
861 | 628 | - */ | ||
862 | 629 | -static PLDHashEntryHdr * PL_DHASH_FASTCALL | ||
863 | 630 | -FindFreeEntry(PLDHashTable *table, PLDHashNumber keyHash) | ||
864 | 631 | -{ | ||
865 | 632 | - PLDHashNumber hash1, hash2; | ||
866 | 633 | - int hashShift, sizeLog2; | ||
867 | 634 | - PLDHashEntryHdr *entry; | ||
868 | 635 | - PRUint32 sizeMask; | ||
869 | 636 | - | ||
870 | 637 | - METER(table->stats.searches++); | ||
871 | 638 | - NS_ASSERTION(!(keyHash & COLLISION_FLAG), | ||
872 | 639 | - "!(keyHash & COLLISION_FLAG)"); | ||
873 | 640 | - | ||
874 | 641 | - /* Compute the primary hash address. */ | ||
875 | 642 | - hashShift = table->hashShift; | ||
876 | 643 | - hash1 = HASH1(keyHash, hashShift); | ||
877 | 644 | - entry = ADDRESS_ENTRY(table, hash1); | ||
878 | 645 | - | ||
879 | 646 | - /* Miss: return space for a new entry. */ | ||
880 | 647 | - if (PL_DHASH_ENTRY_IS_FREE(entry)) { | ||
881 | 648 | - METER(table->stats.misses++); | ||
882 | 649 | - return entry; | ||
883 | 650 | - } | ||
884 | 651 | - | ||
885 | 652 | - /* Collision: double hash. */ | ||
886 | 653 | - sizeLog2 = PL_DHASH_BITS - table->hashShift; | ||
887 | 654 | - hash2 = HASH2(keyHash, sizeLog2, hashShift); | ||
888 | 655 | - sizeMask = PR_BITMASK(sizeLog2); | ||
889 | 656 | - | ||
890 | 657 | - for (;;) { | ||
891 | 658 | - NS_ASSERTION(!ENTRY_IS_REMOVED(entry), | ||
892 | 659 | - "!ENTRY_IS_REMOVED(entry)"); | ||
893 | 660 | - entry->keyHash |= COLLISION_FLAG; | ||
894 | 661 | - | ||
895 | 662 | - METER(table->stats.steps++); | ||
896 | 663 | - hash1 -= hash2; | ||
897 | 664 | - hash1 &= sizeMask; | ||
898 | 665 | - | ||
899 | 666 | - entry = ADDRESS_ENTRY(table, hash1); | ||
900 | 667 | - if (PL_DHASH_ENTRY_IS_FREE(entry)) { | ||
901 | 668 | - METER(table->stats.misses++); | ||
902 | 669 | - return entry; | ||
903 | 670 | - } | ||
904 | 671 | - } | ||
905 | 672 | - | ||
906 | 673 | - /* NOTREACHED */ | ||
907 | 674 | - return NULL; | ||
908 | 675 | -} | ||
909 | 676 | - | ||
910 | 677 | -static PRBool | ||
911 | 678 | -ChangeTable(PLDHashTable *table, int deltaLog2) | ||
912 | 679 | -{ | ||
913 | 680 | - int oldLog2, newLog2; | ||
914 | 681 | - PRUint32 oldCapacity, newCapacity; | ||
915 | 682 | - char *newEntryStore, *oldEntryStore, *oldEntryAddr; | ||
916 | 683 | - PRUint32 entrySize, i, nbytes; | ||
917 | 684 | - PLDHashEntryHdr *oldEntry, *newEntry; | ||
918 | 685 | - PLDHashMoveEntry moveEntry; | ||
919 | 686 | -#ifdef DEBUG | ||
920 | 687 | - PRUint32 recursionLevel; | ||
921 | 688 | -#endif | ||
922 | 689 | - | ||
923 | 690 | - /* Look, but don't touch, until we succeed in getting new entry store. */ | ||
924 | 691 | - oldLog2 = PL_DHASH_BITS - table->hashShift; | ||
925 | 692 | - newLog2 = oldLog2 + deltaLog2; | ||
926 | 693 | - oldCapacity = PR_BIT(oldLog2); | ||
927 | 694 | - newCapacity = PR_BIT(newLog2); | ||
928 | 695 | - if (newCapacity >= PL_DHASH_SIZE_LIMIT) | ||
929 | 696 | - return PR_FALSE; | ||
930 | 697 | - entrySize = table->entrySize; | ||
931 | 698 | - nbytes = newCapacity * entrySize; | ||
932 | 699 | - | ||
933 | 700 | - newEntryStore = (char *) table->ops->allocTable(table, | ||
934 | 701 | - nbytes + ENTRY_STORE_EXTRA); | ||
935 | 702 | - if (!newEntryStore) | ||
936 | 703 | - return PR_FALSE; | ||
937 | 704 | - | ||
938 | 705 | - /* We can't fail from here on, so update table parameters. */ | ||
939 | 706 | -#ifdef DEBUG | ||
940 | 707 | - recursionLevel = RECURSION_LEVEL(table); | ||
941 | 708 | -#endif | ||
942 | 709 | - table->hashShift = PL_DHASH_BITS - newLog2; | ||
943 | 710 | - table->removedCount = 0; | ||
944 | 711 | - table->generation++; | ||
945 | 712 | - | ||
946 | 713 | - /* Assign the new entry store to table. */ | ||
947 | 714 | - memset(newEntryStore, 0, nbytes); | ||
948 | 715 | - oldEntryAddr = oldEntryStore = table->entryStore; | ||
949 | 716 | - table->entryStore = newEntryStore; | ||
950 | 717 | - moveEntry = table->ops->moveEntry; | ||
951 | 718 | -#ifdef DEBUG | ||
952 | 719 | - RECURSION_LEVEL(table) = recursionLevel; | ||
953 | 720 | -#endif | ||
954 | 721 | - | ||
955 | 722 | - /* Copy only live entries, leaving removed ones behind. */ | ||
956 | 723 | - for (i = 0; i < oldCapacity; i++) { | ||
957 | 724 | - oldEntry = (PLDHashEntryHdr *)oldEntryAddr; | ||
958 | 725 | - if (ENTRY_IS_LIVE(oldEntry)) { | ||
959 | 726 | - oldEntry->keyHash &= ~COLLISION_FLAG; | ||
960 | 727 | - newEntry = FindFreeEntry(table, oldEntry->keyHash); | ||
961 | 728 | - NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(newEntry), | ||
962 | 729 | - "PL_DHASH_ENTRY_IS_FREE(newEntry)"); | ||
963 | 730 | - moveEntry(table, oldEntry, newEntry); | ||
964 | 731 | - newEntry->keyHash = oldEntry->keyHash; | ||
965 | 732 | - } | ||
966 | 733 | - oldEntryAddr += entrySize; | ||
967 | 734 | - } | ||
968 | 735 | - | ||
969 | 736 | - table->ops->freeTable(table, oldEntryStore); | ||
970 | 737 | - return PR_TRUE; | ||
971 | 738 | -} | ||
972 | 739 | - | ||
973 | 740 | -PLDHashEntryHdr * PL_DHASH_FASTCALL | ||
974 | 741 | -PL_DHashTableOperate(PLDHashTable *table, const void *key, PLDHashOperator op) | ||
975 | 742 | -{ | ||
976 | 743 | - PLDHashNumber keyHash; | ||
977 | 744 | - PLDHashEntryHdr *entry; | ||
978 | 745 | - PRUint32 size; | ||
979 | 746 | - int deltaLog2; | ||
980 | 747 | - | ||
981 | 748 | - NS_ASSERTION(op == PL_DHASH_LOOKUP || RECURSION_LEVEL(table) == 0, | ||
982 | 749 | - "op == PL_DHASH_LOOKUP || RECURSION_LEVEL(table) == 0"); | ||
983 | 750 | - INCREMENT_RECURSION_LEVEL(table); | ||
984 | 751 | - | ||
985 | 752 | - keyHash = table->ops->hashKey(table, key); | ||
986 | 753 | - keyHash *= PL_DHASH_GOLDEN_RATIO; | ||
987 | 754 | - | ||
988 | 755 | - /* Avoid 0 and 1 hash codes, they indicate free and removed entries. */ | ||
989 | 756 | - ENSURE_LIVE_KEYHASH(keyHash); | ||
990 | 757 | - keyHash &= ~COLLISION_FLAG; | ||
991 | 758 | - | ||
992 | 759 | - switch (op) { | ||
993 | 760 | - case PL_DHASH_LOOKUP: | ||
994 | 761 | - METER(table->stats.lookups++); | ||
995 | 762 | - entry = SearchTable(table, key, keyHash, op); | ||
996 | 763 | - break; | ||
997 | 764 | - | ||
998 | 765 | - case PL_DHASH_ADD: | ||
999 | 766 | - /* | ||
1000 | 767 | - * If alpha is >= .75, grow or compress the table. If key is already | ||
1001 | 768 | - * in the table, we may grow once more than necessary, but only if we | ||
1002 | 769 | - * are on the edge of being overloaded. | ||
1003 | 770 | - */ | ||
1004 | 771 | - size = PL_DHASH_TABLE_SIZE(table); | ||
1005 | 772 | - if (table->entryCount + table->removedCount >= MAX_LOAD(table, size)) { | ||
1006 | 773 | - /* Compress if a quarter or more of all entries are removed. */ | ||
1007 | 774 | - if (table->removedCount >= size >> 2) { | ||
1008 | 775 | - METER(table->stats.compresses++); | ||
1009 | 776 | - deltaLog2 = 0; | ||
1010 | 777 | - } else { | ||
1011 | 778 | - METER(table->stats.grows++); | ||
1012 | 779 | - deltaLog2 = 1; | ||
1013 | 780 | - } | ||
1014 | 781 | - | ||
1015 | 782 | - /* | ||
1016 | 783 | - * Grow or compress table, returning null if ChangeTable fails and | ||
1017 | 784 | - * falling through might claim the last free entry. | ||
1018 | 785 | - */ | ||
1019 | 786 | - if (!ChangeTable(table, deltaLog2) && | ||
1020 | 787 | - table->entryCount + table->removedCount == size - 1) { | ||
1021 | 788 | - METER(table->stats.addFailures++); | ||
1022 | 789 | - entry = NULL; | ||
1023 | 790 | - break; | ||
1024 | 791 | - } | ||
1025 | 792 | - } | ||
1026 | 793 | - | ||
1027 | 794 | - /* | ||
1028 | 795 | - * Look for entry after possibly growing, so we don't have to add it, | ||
1029 | 796 | - * then skip it while growing the table and re-add it after. | ||
1030 | 797 | - */ | ||
1031 | 798 | - entry = SearchTable(table, key, keyHash, op); | ||
1032 | 799 | - if (!ENTRY_IS_LIVE(entry)) { | ||
1033 | 800 | - /* Initialize the entry, indicating that it's no longer free. */ | ||
1034 | 801 | - METER(table->stats.addMisses++); | ||
1035 | 802 | - if (ENTRY_IS_REMOVED(entry)) { | ||
1036 | 803 | - METER(table->stats.addOverRemoved++); | ||
1037 | 804 | - table->removedCount--; | ||
1038 | 805 | - keyHash |= COLLISION_FLAG; | ||
1039 | 806 | - } | ||
1040 | 807 | - if (table->ops->initEntry && | ||
1041 | 808 | - !table->ops->initEntry(table, entry, key)) { | ||
1042 | 809 | - /* We haven't claimed entry yet; fail with null return. */ | ||
1043 | 810 | - memset(entry + 1, 0, table->entrySize - sizeof *entry); | ||
1044 | 811 | - entry = NULL; | ||
1045 | 812 | - break; | ||
1046 | 813 | - } | ||
1047 | 814 | - entry->keyHash = keyHash; | ||
1048 | 815 | - table->entryCount++; | ||
1049 | 816 | - } | ||
1050 | 817 | - METER(else table->stats.addHits++); | ||
1051 | 818 | - break; | ||
1052 | 819 | - | ||
1053 | 820 | - case PL_DHASH_REMOVE: | ||
1054 | 821 | - entry = SearchTable(table, key, keyHash, op); | ||
1055 | 822 | - if (ENTRY_IS_LIVE(entry)) { | ||
1056 | 823 | - /* Clear this entry and mark it as "removed". */ | ||
1057 | 824 | - METER(table->stats.removeHits++); | ||
1058 | 825 | - PL_DHashTableRawRemove(table, entry); | ||
1059 | 826 | - | ||
1060 | 827 | - /* Shrink if alpha is <= .25 and table isn't too small already. */ | ||
1061 | 828 | - size = PL_DHASH_TABLE_SIZE(table); | ||
1062 | 829 | - if (size > PL_DHASH_MIN_SIZE && | ||
1063 | 830 | - table->entryCount <= MIN_LOAD(table, size)) { | ||
1064 | 831 | - METER(table->stats.shrinks++); | ||
1065 | 832 | - (void) ChangeTable(table, -1); | ||
1066 | 833 | - } | ||
1067 | 834 | - } | ||
1068 | 835 | - METER(else table->stats.removeMisses++); | ||
1069 | 836 | - entry = NULL; | ||
1070 | 837 | - break; | ||
1071 | 838 | - | ||
1072 | 839 | - default: | ||
1073 | 840 | - NS_NOTREACHED("0"); | ||
1074 | 841 | - entry = NULL; | ||
1075 | 842 | - } | ||
1076 | 843 | - | ||
1077 | 844 | - DECREMENT_RECURSION_LEVEL(table); | ||
1078 | 845 | - | ||
1079 | 846 | - return entry; | ||
1080 | 847 | -} | ||
1081 | 848 | - | ||
1082 | 849 | -void | ||
1083 | 850 | -PL_DHashTableRawRemove(PLDHashTable *table, PLDHashEntryHdr *entry) | ||
1084 | 851 | -{ | ||
1085 | 852 | - PLDHashNumber keyHash; /* load first in case clearEntry goofs it */ | ||
1086 | 853 | - | ||
1087 | 854 | - NS_ASSERTION(RECURSION_LEVEL(table) != IMMUTABLE_RECURSION_LEVEL, | ||
1088 | 855 | - "RECURSION_LEVEL(table) != IMMUTABLE_RECURSION_LEVEL"); | ||
1089 | 856 | - | ||
1090 | 857 | - NS_ASSERTION(PL_DHASH_ENTRY_IS_LIVE(entry), | ||
1091 | 858 | - "PL_DHASH_ENTRY_IS_LIVE(entry)"); | ||
1092 | 859 | - keyHash = entry->keyHash; | ||
1093 | 860 | - table->ops->clearEntry(table, entry); | ||
1094 | 861 | - if (keyHash & COLLISION_FLAG) { | ||
1095 | 862 | - MARK_ENTRY_REMOVED(entry); | ||
1096 | 863 | - table->removedCount++; | ||
1097 | 864 | - } else { | ||
1098 | 865 | - METER(table->stats.removeFrees++); | ||
1099 | 866 | - MARK_ENTRY_FREE(entry); | ||
1100 | 867 | - } | ||
1101 | 868 | - table->entryCount--; | ||
1102 | 869 | -} | ||
1103 | 870 | - | ||
1104 | 871 | -PRUint32 | ||
1105 | 872 | -PL_DHashTableEnumerate(PLDHashTable *table, PLDHashEnumerator etor, void *arg) | ||
1106 | 873 | -{ | ||
1107 | 874 | - char *entryAddr, *entryLimit; | ||
1108 | 875 | - PRUint32 i, capacity, entrySize, ceiling; | ||
1109 | 876 | - PRBool didRemove; | ||
1110 | 877 | - PLDHashEntryHdr *entry; | ||
1111 | 878 | - PLDHashOperator op; | ||
1112 | 879 | - | ||
1113 | 880 | - INCREMENT_RECURSION_LEVEL(table); | ||
1114 | 881 | - | ||
1115 | 882 | - entryAddr = table->entryStore; | ||
1116 | 883 | - entrySize = table->entrySize; | ||
1117 | 884 | - capacity = PL_DHASH_TABLE_SIZE(table); | ||
1118 | 885 | - entryLimit = entryAddr + capacity * entrySize; | ||
1119 | 886 | - i = 0; | ||
1120 | 887 | - didRemove = PR_FALSE; | ||
1121 | 888 | - while (entryAddr < entryLimit) { | ||
1122 | 889 | - entry = (PLDHashEntryHdr *)entryAddr; | ||
1123 | 890 | - if (ENTRY_IS_LIVE(entry)) { | ||
1124 | 891 | - op = etor(table, entry, i++, arg); | ||
1125 | 892 | - if (op & PL_DHASH_REMOVE) { | ||
1126 | 893 | - METER(table->stats.removeEnums++); | ||
1127 | 894 | - PL_DHashTableRawRemove(table, entry); | ||
1128 | 895 | - didRemove = PR_TRUE; | ||
1129 | 896 | - } | ||
1130 | 897 | - if (op & PL_DHASH_STOP) | ||
1131 | 898 | - break; | ||
1132 | 899 | - } | ||
1133 | 900 | - entryAddr += entrySize; | ||
1134 | 901 | - } | ||
1135 | 902 | - | ||
1136 | 903 | - NS_ASSERTION(!didRemove || RECURSION_LEVEL(table) == 1, | ||
1137 | 904 | - "!didRemove || RECURSION_LEVEL(table) == 1"); | ||
1138 | 905 | - | ||
1139 | 906 | - /* | ||
1140 | 907 | - * Shrink or compress if a quarter or more of all entries are removed, or | ||
1141 | 908 | - * if the table is underloaded according to the configured minimum alpha, | ||
1142 | 909 | - * and is not minimal-size already. Do this only if we removed above, so | ||
1143 | 910 | - * non-removing enumerations can count on stable table->entryStore until | ||
1144 | 911 | - * the next non-lookup-Operate or removing-Enumerate. | ||
1145 | 912 | - */ | ||
1146 | 913 | - if (didRemove && | ||
1147 | 914 | - (table->removedCount >= capacity >> 2 || | ||
1148 | 915 | - (capacity > PL_DHASH_MIN_SIZE && | ||
1149 | 916 | - table->entryCount <= MIN_LOAD(table, capacity)))) { | ||
1150 | 917 | - METER(table->stats.enumShrinks++); | ||
1151 | 918 | - capacity = table->entryCount; | ||
1152 | 919 | - capacity += capacity >> 1; | ||
1153 | 920 | - if (capacity < PL_DHASH_MIN_SIZE) | ||
1154 | 921 | - capacity = PL_DHASH_MIN_SIZE; | ||
1155 | 922 | - | ||
1156 | 923 | - PR_CEILING_LOG2(ceiling, capacity); | ||
1157 | 924 | - ceiling -= PL_DHASH_BITS - table->hashShift; | ||
1158 | 925 | - | ||
1159 | 926 | - (void) ChangeTable(table, ceiling); | ||
1160 | 927 | - } | ||
1161 | 928 | - | ||
1162 | 929 | - DECREMENT_RECURSION_LEVEL(table); | ||
1163 | 930 | - | ||
1164 | 931 | - return i; | ||
1165 | 932 | -} | ||
1166 | 933 | - | ||
1167 | 934 | -#ifdef DEBUG | ||
1168 | 935 | -void | ||
1169 | 936 | -PL_DHashMarkTableImmutable(PLDHashTable *table) | ||
1170 | 937 | -{ | ||
1171 | 938 | - RECURSION_LEVEL(table) = IMMUTABLE_RECURSION_LEVEL; | ||
1172 | 939 | -} | ||
1173 | 940 | -#endif | ||
1174 | 941 | - | ||
1175 | 942 | -#ifdef PL_DHASHMETER | ||
1176 | 943 | -#include <math.h> | ||
1177 | 944 | - | ||
1178 | 945 | -void | ||
1179 | 946 | -PL_DHashTableDumpMeter(PLDHashTable *table, PLDHashEnumerator dump, FILE *fp) | ||
1180 | 947 | -{ | ||
1181 | 948 | - char *entryAddr; | ||
1182 | 949 | - PRUint32 entrySize, entryCount; | ||
1183 | 950 | - int hashShift, sizeLog2; | ||
1184 | 951 | - PRUint32 i, tableSize, sizeMask, chainLen, maxChainLen, chainCount; | ||
1185 | 952 | - PLDHashNumber hash1, hash2, saveHash1, maxChainHash1, maxChainHash2; | ||
1186 | 953 | - double sqsum, mean, variance, sigma; | ||
1187 | 954 | - PLDHashEntryHdr *entry, *probe; | ||
1188 | 955 | - | ||
1189 | 956 | - entryAddr = table->entryStore; | ||
1190 | 957 | - entrySize = table->entrySize; | ||
1191 | 958 | - hashShift = table->hashShift; | ||
1192 | 959 | - sizeLog2 = PL_DHASH_BITS - hashShift; | ||
1193 | 960 | - tableSize = PL_DHASH_TABLE_SIZE(table); | ||
1194 | 961 | - sizeMask = PR_BITMASK(sizeLog2); | ||
1195 | 962 | - chainCount = maxChainLen = 0; | ||
1196 | 963 | - hash2 = 0; | ||
1197 | 964 | - sqsum = 0; | ||
1198 | 965 | - | ||
1199 | 966 | - for (i = 0; i < tableSize; i++) { | ||
1200 | 967 | - entry = (PLDHashEntryHdr *)entryAddr; | ||
1201 | 968 | - entryAddr += entrySize; | ||
1202 | 969 | - if (!ENTRY_IS_LIVE(entry)) | ||
1203 | 970 | - continue; | ||
1204 | 971 | - hash1 = HASH1(entry->keyHash & ~COLLISION_FLAG, hashShift); | ||
1205 | 972 | - saveHash1 = hash1; | ||
1206 | 973 | - probe = ADDRESS_ENTRY(table, hash1); | ||
1207 | 974 | - chainLen = 1; | ||
1208 | 975 | - if (probe == entry) { | ||
1209 | 976 | - /* Start of a (possibly unit-length) chain. */ | ||
1210 | 977 | - chainCount++; | ||
1211 | 978 | - } else { | ||
1212 | 979 | - hash2 = HASH2(entry->keyHash & ~COLLISION_FLAG, sizeLog2, | ||
1213 | 980 | - hashShift); | ||
1214 | 981 | - do { | ||
1215 | 982 | - chainLen++; | ||
1216 | 983 | - hash1 -= hash2; | ||
1217 | 984 | - hash1 &= sizeMask; | ||
1218 | 985 | - probe = ADDRESS_ENTRY(table, hash1); | ||
1219 | 986 | - } while (probe != entry); | ||
1220 | 987 | - } | ||
1221 | 988 | - sqsum += chainLen * chainLen; | ||
1222 | 989 | - if (chainLen > maxChainLen) { | ||
1223 | 990 | - maxChainLen = chainLen; | ||
1224 | 991 | - maxChainHash1 = saveHash1; | ||
1225 | 992 | - maxChainHash2 = hash2; | ||
1226 | 993 | - } | ||
1227 | 994 | - } | ||
1228 | 995 | - | ||
1229 | 996 | - entryCount = table->entryCount; | ||
1230 | 997 | - if (entryCount && chainCount) { | ||
1231 | 998 | - mean = (double)entryCount / chainCount; | ||
1232 | 999 | - variance = chainCount * sqsum - entryCount * entryCount; | ||
1233 | 1000 | - if (variance < 0 || chainCount == 1) | ||
1234 | 1001 | - variance = 0; | ||
1235 | 1002 | - else | ||
1236 | 1003 | - variance /= chainCount * (chainCount - 1); | ||
1237 | 1004 | - sigma = sqrt(variance); | ||
1238 | 1005 | - } else { | ||
1239 | 1006 | - mean = sigma = 0; | ||
1240 | 1007 | - } | ||
1241 | 1008 | - | ||
1242 | 1009 | - fprintf(fp, "Double hashing statistics:\n"); | ||
1243 | 1010 | - fprintf(fp, " table size (in entries): %u\n", tableSize); | ||
1244 | 1011 | - fprintf(fp, " number of entries: %u\n", table->entryCount); | ||
1245 | 1012 | - fprintf(fp, " number of removed entries: %u\n", table->removedCount); | ||
1246 | 1013 | - fprintf(fp, " number of searches: %u\n", table->stats.searches); | ||
1247 | 1014 | - fprintf(fp, " number of hits: %u\n", table->stats.hits); | ||
1248 | 1015 | - fprintf(fp, " number of misses: %u\n", table->stats.misses); | ||
1249 | 1016 | - fprintf(fp, " mean steps per search: %g\n", table->stats.searches ? | ||
1250 | 1017 | - (double)table->stats.steps | ||
1251 | 1018 | - / table->stats.searches : | ||
1252 | 1019 | - 0.); | ||
1253 | 1020 | - fprintf(fp, " mean hash chain length: %g\n", mean); | ||
1254 | 1021 | - fprintf(fp, " standard deviation: %g\n", sigma); | ||
1255 | 1022 | - fprintf(fp, " maximum hash chain length: %u\n", maxChainLen); | ||
1256 | 1023 | - fprintf(fp, " number of lookups: %u\n", table->stats.lookups); | ||
1257 | 1024 | - fprintf(fp, " adds that made a new entry: %u\n", table->stats.addMisses); | ||
1258 | 1025 | - fprintf(fp, "adds that recycled removeds: %u\n", table->stats.addOverRemoved); | ||
1259 | 1026 | - fprintf(fp, " adds that found an entry: %u\n", table->stats.addHits); | ||
1260 | 1027 | - fprintf(fp, " add failures: %u\n", table->stats.addFailures); | ||
1261 | 1028 | - fprintf(fp, " useful removes: %u\n", table->stats.removeHits); | ||
1262 | 1029 | - fprintf(fp, " useless removes: %u\n", table->stats.removeMisses); | ||
1263 | 1030 | - fprintf(fp, "removes that freed an entry: %u\n", table->stats.removeFrees); | ||
1264 | 1031 | - fprintf(fp, " removes while enumerating: %u\n", table->stats.removeEnums); | ||
1265 | 1032 | - fprintf(fp, " number of grows: %u\n", table->stats.grows); | ||
1266 | 1033 | - fprintf(fp, " number of shrinks: %u\n", table->stats.shrinks); | ||
1267 | 1034 | - fprintf(fp, " number of compresses: %u\n", table->stats.compresses); | ||
1268 | 1035 | - fprintf(fp, "number of enumerate shrinks: %u\n", table->stats.enumShrinks); | ||
1269 | 1036 | - | ||
1270 | 1037 | - if (dump && maxChainLen && hash2) { | ||
1271 | 1038 | - fputs("Maximum hash chain:\n", fp); | ||
1272 | 1039 | - hash1 = maxChainHash1; | ||
1273 | 1040 | - hash2 = maxChainHash2; | ||
1274 | 1041 | - entry = ADDRESS_ENTRY(table, hash1); | ||
1275 | 1042 | - i = 0; | ||
1276 | 1043 | - do { | ||
1277 | 1044 | - if (dump(table, entry, i++, fp) != PL_DHASH_NEXT) | ||
1278 | 1045 | - break; | ||
1279 | 1046 | - hash1 -= hash2; | ||
1280 | 1047 | - hash1 &= sizeMask; | ||
1281 | 1048 | - entry = ADDRESS_ENTRY(table, hash1); | ||
1282 | 1049 | - } while (PL_DHASH_ENTRY_IS_BUSY(entry)); | ||
1283 | 1050 | - } | ||
1284 | 1051 | -} | ||
1285 | 1052 | -#endif /* PL_DHASHMETER */ | ||
1286 | 1053 | --- /dev/null | ||
1287 | 1054 | +++ b/mozilla/xpcom/glue/pldhash.cpp | ||
1288 | 1055 | @@ -0,0 +1,915 @@ | ||
1289 | 1056 | +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | ||
1290 | 1057 | +/* ***** BEGIN LICENSE BLOCK ***** | ||
1291 | 1058 | + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | ||
1292 | 1059 | + * | ||
1293 | 1060 | + * The contents of this file are subject to the Mozilla Public License Version | ||
1294 | 1061 | + * 1.1 (the "License"); you may not use this file except in compliance with | ||
1295 | 1062 | + * the License. You may obtain a copy of the License at | ||
1296 | 1063 | + * http://www.mozilla.org/MPL/ | ||
1297 | 1064 | + * | ||
1298 | 1065 | + * Software distributed under the License is distributed on an "AS IS" basis, | ||
1299 | 1066 | + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | ||
1300 | 1067 | + * for the specific language governing rights and limitations under the | ||
1301 | 1068 | + * License. | ||
1302 | 1069 | + * | ||
1303 | 1070 | + * The Original Code is Mozilla JavaScript code. | ||
1304 | 1071 | + * | ||
1305 | 1072 | + * The Initial Developer of the Original Code is | ||
1306 | 1073 | + * Netscape Communications Corporation. | ||
1307 | 1074 | + * Portions created by the Initial Developer are Copyright (C) 1999-2001 | ||
1308 | 1075 | + * the Initial Developer. All Rights Reserved. | ||
1309 | 1076 | + * | ||
1310 | 1077 | + * Contributor(s): | ||
1311 | 1078 | + * Brendan Eich <brendan@mozilla.org> (Original Author) | ||
1312 | 1079 | + * Chris Waterson <waterson@netscape.com> | ||
1313 | 1080 | + * L. David Baron <dbaron@dbaron.org>, Mozilla Corporation | ||
1314 | 1081 | + * | ||
1315 | 1082 | + * Alternatively, the contents of this file may be used under the terms of | ||
1316 | 1083 | + * either of the GNU General Public License Version 2 or later (the "GPL"), | ||
1317 | 1084 | + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | ||
1318 | 1085 | + * in which case the provisions of the GPL or the LGPL are applicable instead | ||
1319 | 1086 | + * of those above. If you wish to allow use of your version of this file only | ||
1320 | 1087 | + * under the terms of either the GPL or the LGPL, and not to allow others to | ||
1321 | 1088 | + * use your version of this file under the terms of the MPL, indicate your | ||
1322 | 1089 | + * decision by deleting the provisions above and replace them with the notice | ||
1323 | 1090 | + * and other provisions required by the GPL or the LGPL. If you do not delete | ||
1324 | 1091 | + * the provisions above, a recipient may use your version of this file under | ||
1325 | 1092 | + * the terms of any one of the MPL, the GPL or the LGPL. | ||
1326 | 1093 | + * | ||
1327 | 1094 | + * ***** END LICENSE BLOCK ***** */ | ||
1328 | 1095 | + | ||
1329 | 1096 | +/* | ||
1330 | 1097 | + * Double hashing implementation. | ||
1331 | 1098 | + * GENERATED BY js/src/plify_jsdhash.sed -- DO NOT EDIT!!! | ||
1332 | 1099 | + */ | ||
1333 | 1100 | +#include <stdio.h> | ||
1334 | 1101 | +#include <stdlib.h> | ||
1335 | 1102 | +#include <string.h> | ||
1336 | 1103 | +#include "prbit.h" | ||
1337 | 1104 | +#include "pldhash.h" | ||
1338 | 1105 | +#include "nsDebug.h" /* for PR_ASSERT */ | ||
1339 | 1106 | + | ||
1340 | 1107 | +#ifdef PL_DHASHMETER | ||
1341 | 1108 | +# if defined MOZILLA_CLIENT && defined DEBUG_XXXbrendan | ||
1342 | 1109 | +# include "nsTraceMalloc.h" | ||
1343 | 1110 | +# endif | ||
1344 | 1111 | +# define METER(x) x | ||
1345 | 1112 | +#else | ||
1346 | 1113 | +# define METER(x) /* nothing */ | ||
1347 | 1114 | +#endif | ||
1348 | 1115 | + | ||
1349 | 1116 | +/* | ||
1350 | 1117 | + * The following DEBUG-only code is used to assert that calls to one of | ||
1351 | 1118 | + * table->ops or to an enumerator do not cause re-entry into a call that | ||
1352 | 1119 | + * can mutate the table. The recursion level is stored in additional | ||
1353 | 1120 | + * space allocated at the end of the entry store to avoid changing | ||
1354 | 1121 | + * PLDHashTable, which could cause issues when mixing DEBUG and | ||
1355 | 1122 | + * non-DEBUG components. | ||
1356 | 1123 | + */ | ||
1357 | 1124 | +#ifdef DEBUG | ||
1358 | 1125 | + | ||
1359 | 1126 | +#define JSDHASH_ONELINE_ASSERT PR_ASSERT | ||
1360 | 1127 | +#define RECURSION_LEVEL(table_) (*(PRUint32*)(table_->entryStore + \ | ||
1361 | 1128 | + PL_DHASH_TABLE_SIZE(table_) * \ | ||
1362 | 1129 | + table_->entrySize)) | ||
1363 | 1130 | +/* | ||
1364 | 1131 | + * Most callers that assert about the recursion level don't care about | ||
1365 | 1132 | + * this magical value because they are asserting that mutation is | ||
1366 | 1133 | + * allowed (and therefore the level is 0 or 1, depending on whether they | ||
1367 | 1134 | + * incremented it). | ||
1368 | 1135 | + * | ||
1369 | 1136 | + * Only PL_DHashTableFinish needs to allow this special value. | ||
1370 | 1137 | + */ | ||
1371 | 1138 | +#define IMMUTABLE_RECURSION_LEVEL ((PRUint32)-1) | ||
1372 | 1139 | + | ||
1373 | 1140 | +#define RECURSION_LEVEL_SAFE_TO_FINISH(table_) \ | ||
1374 | 1141 | + (RECURSION_LEVEL(table_) == 0 || \ | ||
1375 | 1142 | + RECURSION_LEVEL(table_) == IMMUTABLE_RECURSION_LEVEL) | ||
1376 | 1143 | + | ||
1377 | 1144 | +#define ENTRY_STORE_EXTRA sizeof(PRUint32) | ||
1378 | 1145 | +#define INCREMENT_RECURSION_LEVEL(table_) \ | ||
1379 | 1146 | + PR_BEGIN_MACRO \ | ||
1380 | 1147 | + if (RECURSION_LEVEL(table_) != IMMUTABLE_RECURSION_LEVEL) \ | ||
1381 | 1148 | + ++RECURSION_LEVEL(table_); \ | ||
1382 | 1149 | + PR_END_MACRO | ||
1383 | 1150 | +#define DECREMENT_RECURSION_LEVEL(table_) \ | ||
1384 | 1151 | + PR_BEGIN_MACRO \ | ||
1385 | 1152 | + if (RECURSION_LEVEL(table_) != IMMUTABLE_RECURSION_LEVEL) { \ | ||
1386 | 1153 | + NS_ASSERTION(RECURSION_LEVEL(table_) > 0, "RECURSION_LEVEL(table_) > 0"); \ | ||
1387 | 1154 | + --RECURSION_LEVEL(table_); \ | ||
1388 | 1155 | + } \ | ||
1389 | 1156 | + PR_END_MACRO | ||
1390 | 1157 | + | ||
1391 | 1158 | +#else | ||
1392 | 1159 | + | ||
1393 | 1160 | +#define ENTRY_STORE_EXTRA 0 | ||
1394 | 1161 | +#define INCREMENT_RECURSION_LEVEL(table_) PR_BEGIN_MACRO PR_END_MACRO | ||
1395 | 1162 | +#define DECREMENT_RECURSION_LEVEL(table_) PR_BEGIN_MACRO PR_END_MACRO | ||
1396 | 1163 | + | ||
1397 | 1164 | +#endif /* defined(DEBUG) */ | ||
1398 | 1165 | + | ||
1399 | 1166 | +void * | ||
1400 | 1167 | +PL_DHashAllocTable(PLDHashTable *table, PRUint32 nbytes) | ||
1401 | 1168 | +{ | ||
1402 | 1169 | + return malloc(nbytes); | ||
1403 | 1170 | +} | ||
1404 | 1171 | + | ||
1405 | 1172 | +void | ||
1406 | 1173 | +PL_DHashFreeTable(PLDHashTable *table, void *ptr) | ||
1407 | 1174 | +{ | ||
1408 | 1175 | + free(ptr); | ||
1409 | 1176 | +} | ||
1410 | 1177 | + | ||
1411 | 1178 | +PLDHashNumber | ||
1412 | 1179 | +PL_DHashStringKey(PLDHashTable *table, const void *key) | ||
1413 | 1180 | +{ | ||
1414 | 1181 | + PLDHashNumber h; | ||
1415 | 1182 | + const unsigned char *s; | ||
1416 | 1183 | + | ||
1417 | 1184 | + h = 0; | ||
1418 | 1185 | + for (s = (const unsigned char *) key; *s != '\0'; s++) | ||
1419 | 1186 | + h = PR_ROTATE_LEFT32(h, 4) ^ *s; | ||
1420 | 1187 | + return h; | ||
1421 | 1188 | +} | ||
1422 | 1189 | + | ||
1423 | 1190 | +PLDHashNumber | ||
1424 | 1191 | +PL_DHashVoidPtrKeyStub(PLDHashTable *table, const void *key) | ||
1425 | 1192 | +{ | ||
1426 | 1193 | + return (PLDHashNumber)(unsigned long)key >> 2; | ||
1427 | 1194 | +} | ||
1428 | 1195 | + | ||
1429 | 1196 | +PRBool | ||
1430 | 1197 | +PL_DHashMatchEntryStub(PLDHashTable *table, | ||
1431 | 1198 | + const PLDHashEntryHdr *entry, | ||
1432 | 1199 | + const void *key) | ||
1433 | 1200 | +{ | ||
1434 | 1201 | + const PLDHashEntryStub *stub = (const PLDHashEntryStub *)entry; | ||
1435 | 1202 | + | ||
1436 | 1203 | + return stub->key == key; | ||
1437 | 1204 | +} | ||
1438 | 1205 | + | ||
1439 | 1206 | +PRBool | ||
1440 | 1207 | +PL_DHashMatchStringKey(PLDHashTable *table, | ||
1441 | 1208 | + const PLDHashEntryHdr *entry, | ||
1442 | 1209 | + const void *key) | ||
1443 | 1210 | +{ | ||
1444 | 1211 | + const PLDHashEntryStub *stub = (const PLDHashEntryStub *)entry; | ||
1445 | 1212 | + | ||
1446 | 1213 | + /* XXX tolerate null keys on account of sloppy Mozilla callers. */ | ||
1447 | 1214 | + return stub->key == key || | ||
1448 | 1215 | + (stub->key && key && | ||
1449 | 1216 | + strcmp((const char *) stub->key, (const char *) key) == 0); | ||
1450 | 1217 | +} | ||
1451 | 1218 | + | ||
1452 | 1219 | +void | ||
1453 | 1220 | +PL_DHashMoveEntryStub(PLDHashTable *table, | ||
1454 | 1221 | + const PLDHashEntryHdr *from, | ||
1455 | 1222 | + PLDHashEntryHdr *to) | ||
1456 | 1223 | +{ | ||
1457 | 1224 | + memcpy(to, from, table->entrySize); | ||
1458 | 1225 | +} | ||
1459 | 1226 | + | ||
1460 | 1227 | +void | ||
1461 | 1228 | +PL_DHashClearEntryStub(PLDHashTable *table, PLDHashEntryHdr *entry) | ||
1462 | 1229 | +{ | ||
1463 | 1230 | + memset(entry, 0, table->entrySize); | ||
1464 | 1231 | +} | ||
1465 | 1232 | + | ||
1466 | 1233 | +void | ||
1467 | 1234 | +PL_DHashFreeStringKey(PLDHashTable *table, PLDHashEntryHdr *entry) | ||
1468 | 1235 | +{ | ||
1469 | 1236 | + const PLDHashEntryStub *stub = (const PLDHashEntryStub *)entry; | ||
1470 | 1237 | + | ||
1471 | 1238 | + free((void *) stub->key); | ||
1472 | 1239 | + memset(entry, 0, table->entrySize); | ||
1473 | 1240 | +} | ||
1474 | 1241 | + | ||
1475 | 1242 | +void | ||
1476 | 1243 | +PL_DHashFinalizeStub(PLDHashTable *table) | ||
1477 | 1244 | +{ | ||
1478 | 1245 | +} | ||
1479 | 1246 | + | ||
1480 | 1247 | +static const PLDHashTableOps stub_ops = { | ||
1481 | 1248 | + PL_DHashAllocTable, | ||
1482 | 1249 | + PL_DHashFreeTable, | ||
1483 | 1250 | + PL_DHashVoidPtrKeyStub, | ||
1484 | 1251 | + PL_DHashMatchEntryStub, | ||
1485 | 1252 | + PL_DHashMoveEntryStub, | ||
1486 | 1253 | + PL_DHashClearEntryStub, | ||
1487 | 1254 | + PL_DHashFinalizeStub, | ||
1488 | 1255 | + NULL | ||
1489 | 1256 | +}; | ||
1490 | 1257 | + | ||
1491 | 1258 | +const PLDHashTableOps * | ||
1492 | 1259 | +PL_DHashGetStubOps(void) | ||
1493 | 1260 | +{ | ||
1494 | 1261 | + return &stub_ops; | ||
1495 | 1262 | +} | ||
1496 | 1263 | + | ||
1497 | 1264 | +PLDHashTable * | ||
1498 | 1265 | +PL_NewDHashTable(const PLDHashTableOps *ops, void *data, PRUint32 entrySize, | ||
1499 | 1266 | + PRUint32 capacity) | ||
1500 | 1267 | +{ | ||
1501 | 1268 | + PLDHashTable *table; | ||
1502 | 1269 | + | ||
1503 | 1270 | + table = (PLDHashTable *) malloc(sizeof *table); | ||
1504 | 1271 | + if (!table) | ||
1505 | 1272 | + return NULL; | ||
1506 | 1273 | + if (!PL_DHashTableInit(table, ops, data, entrySize, capacity)) { | ||
1507 | 1274 | + free(table); | ||
1508 | 1275 | + return NULL; | ||
1509 | 1276 | + } | ||
1510 | 1277 | + return table; | ||
1511 | 1278 | +} | ||
1512 | 1279 | + | ||
1513 | 1280 | +void | ||
1514 | 1281 | +PL_DHashTableDestroy(PLDHashTable *table) | ||
1515 | 1282 | +{ | ||
1516 | 1283 | + PL_DHashTableFinish(table); | ||
1517 | 1284 | + free(table); | ||
1518 | 1285 | +} | ||
1519 | 1286 | + | ||
1520 | 1287 | +PRBool | ||
1521 | 1288 | +PL_DHashTableInit(PLDHashTable *table, const PLDHashTableOps *ops, void *data, | ||
1522 | 1289 | + PRUint32 entrySize, PRUint32 capacity) | ||
1523 | 1290 | +{ | ||
1524 | 1291 | + int log2; | ||
1525 | 1292 | + PRUint32 nbytes; | ||
1526 | 1293 | + | ||
1527 | 1294 | +#ifdef DEBUG | ||
1528 | 1295 | + if (entrySize > 10 * sizeof(void *)) { | ||
1529 | 1296 | + printf_stderr( | ||
1530 | 1297 | + "pldhash: for the table at address %p, the given entrySize" | ||
1531 | 1298 | + " of %lu %s favors chaining over double hashing.\n", | ||
1532 | 1299 | + (void *) table, | ||
1533 | 1300 | + (unsigned long) entrySize, | ||
1534 | 1301 | + (entrySize > 16 * sizeof(void*)) ? "definitely" : "probably"); | ||
1535 | 1302 | + } | ||
1536 | 1303 | +#endif | ||
1537 | 1304 | + | ||
1538 | 1305 | + table->ops = ops; | ||
1539 | 1306 | + table->data = data; | ||
1540 | 1307 | + if (capacity < PL_DHASH_MIN_SIZE) | ||
1541 | 1308 | + capacity = PL_DHASH_MIN_SIZE; | ||
1542 | 1309 | + | ||
1543 | 1310 | + PR_CEILING_LOG2(log2, capacity); | ||
1544 | 1311 | + | ||
1545 | 1312 | + capacity = PR_BIT(log2); | ||
1546 | 1313 | + if (capacity >= PL_DHASH_SIZE_LIMIT) | ||
1547 | 1314 | + return PR_FALSE; | ||
1548 | 1315 | + table->hashShift = PL_DHASH_BITS - log2; | ||
1549 | 1316 | + table->maxAlphaFrac = (PRUint8)(0x100 * PL_DHASH_DEFAULT_MAX_ALPHA); | ||
1550 | 1317 | + table->minAlphaFrac = (PRUint8)(0x100 * PL_DHASH_DEFAULT_MIN_ALPHA); | ||
1551 | 1318 | + table->entrySize = entrySize; | ||
1552 | 1319 | + table->entryCount = table->removedCount = 0; | ||
1553 | 1320 | + table->generation = 0; | ||
1554 | 1321 | + nbytes = capacity * entrySize; | ||
1555 | 1322 | + | ||
1556 | 1323 | + table->entryStore = (char *) ops->allocTable(table, | ||
1557 | 1324 | + nbytes + ENTRY_STORE_EXTRA); | ||
1558 | 1325 | + if (!table->entryStore) | ||
1559 | 1326 | + return PR_FALSE; | ||
1560 | 1327 | + memset(table->entryStore, 0, nbytes); | ||
1561 | 1328 | + METER(memset(&table->stats, 0, sizeof table->stats)); | ||
1562 | 1329 | + | ||
1563 | 1330 | +#ifdef DEBUG | ||
1564 | 1331 | + RECURSION_LEVEL(table) = 0; | ||
1565 | 1332 | +#endif | ||
1566 | 1333 | + | ||
1567 | 1334 | + return PR_TRUE; | ||
1568 | 1335 | +} | ||
1569 | 1336 | + | ||
1570 | 1337 | +/* | ||
1571 | 1338 | + * Compute max and min load numbers (entry counts) from table params. | ||
1572 | 1339 | + */ | ||
1573 | 1340 | +#define MAX_LOAD(table, size) (((table)->maxAlphaFrac * (size)) >> 8) | ||
1574 | 1341 | +#define MIN_LOAD(table, size) (((table)->minAlphaFrac * (size)) >> 8) | ||
1575 | 1342 | + | ||
1576 | 1343 | +void | ||
1577 | 1344 | +PL_DHashTableSetAlphaBounds(PLDHashTable *table, | ||
1578 | 1345 | + float maxAlpha, | ||
1579 | 1346 | + float minAlpha) | ||
1580 | 1347 | +{ | ||
1581 | 1348 | + PRUint32 size; | ||
1582 | 1349 | + | ||
1583 | 1350 | + /* | ||
1584 | 1351 | + * Reject obviously insane bounds, rather than trying to guess what the | ||
1585 | 1352 | + * buggy caller intended. | ||
1586 | 1353 | + */ | ||
1587 | 1354 | + NS_ASSERTION(0.5 <= maxAlpha && maxAlpha < 1 && 0 <= minAlpha, | ||
1588 | 1355 | + "0.5 <= maxAlpha && maxAlpha < 1 && 0 <= minAlpha"); | ||
1589 | 1356 | + if (maxAlpha < 0.5 || 1 <= maxAlpha || minAlpha < 0) | ||
1590 | 1357 | + return; | ||
1591 | 1358 | + | ||
1592 | 1359 | + /* | ||
1593 | 1360 | + * Ensure that at least one entry will always be free. If maxAlpha at | ||
1594 | 1361 | + * minimum size leaves no entries free, reduce maxAlpha based on minimum | ||
1595 | 1362 | + * size and the precision limit of maxAlphaFrac's fixed point format. | ||
1596 | 1363 | + */ | ||
1597 | 1364 | + NS_ASSERTION(PL_DHASH_MIN_SIZE - (maxAlpha * PL_DHASH_MIN_SIZE) >= 1, | ||
1598 | 1365 | + "PL_DHASH_MIN_SIZE - (maxAlpha * PL_DHASH_MIN_SIZE) >= 1"); | ||
1599 | 1366 | + if (PL_DHASH_MIN_SIZE - (maxAlpha * PL_DHASH_MIN_SIZE) < 1) { | ||
1600 | 1367 | + maxAlpha = (float) | ||
1601 | 1368 | + (PL_DHASH_MIN_SIZE - PR_MAX(PL_DHASH_MIN_SIZE / 256, 1)) | ||
1602 | 1369 | + / PL_DHASH_MIN_SIZE; | ||
1603 | 1370 | + } | ||
1604 | 1371 | + | ||
1605 | 1372 | + /* | ||
1606 | 1373 | + * Ensure that minAlpha is strictly less than half maxAlpha. Take care | ||
1607 | 1374 | + * not to truncate an entry's worth of alpha when storing in minAlphaFrac | ||
1608 | 1375 | + * (8-bit fixed point format). | ||
1609 | 1376 | + */ | ||
1610 | 1377 | + NS_ASSERTION(minAlpha < maxAlpha / 2, | ||
1611 | 1378 | + "minAlpha < maxAlpha / 2"); | ||
1612 | 1379 | + if (minAlpha >= maxAlpha / 2) { | ||
1613 | 1380 | + size = PL_DHASH_TABLE_SIZE(table); | ||
1614 | 1381 | + minAlpha = (size * maxAlpha - PR_MAX(size / 256, 1)) / (2 * size); | ||
1615 | 1382 | + } | ||
1616 | 1383 | + | ||
1617 | 1384 | + table->maxAlphaFrac = (PRUint8)(maxAlpha * 256); | ||
1618 | 1385 | + table->minAlphaFrac = (PRUint8)(minAlpha * 256); | ||
1619 | 1386 | +} | ||
1620 | 1387 | + | ||
1621 | 1388 | +/* | ||
1622 | 1389 | + * Double hashing needs the second hash code to be relatively prime to table | ||
1623 | 1390 | + * size, so we simply make hash2 odd. | ||
1624 | 1391 | + */ | ||
1625 | 1392 | +#define HASH1(hash0, shift) ((hash0) >> (shift)) | ||
1626 | 1393 | +#define HASH2(hash0,log2,shift) ((((hash0) << (log2)) >> (shift)) | 1) | ||
1627 | 1394 | + | ||
1628 | 1395 | +/* | ||
1629 | 1396 | + * Reserve keyHash 0 for free entries and 1 for removed-entry sentinels. Note | ||
1630 | 1397 | + * that a removed-entry sentinel need be stored only if the removed entry had | ||
1631 | 1398 | + * a colliding entry added after it. Therefore we can use 1 as the collision | ||
1632 | 1399 | + * flag in addition to the removed-entry sentinel value. Multiplicative hash | ||
1633 | 1400 | + * uses the high order bits of keyHash, so this least-significant reservation | ||
1634 | 1401 | + * should not hurt the hash function's effectiveness much. | ||
1635 | 1402 | + * | ||
1636 | 1403 | + * If you change any of these magic numbers, also update PL_DHASH_ENTRY_IS_LIVE | ||
1637 | 1404 | + * in pldhash.h. It used to be private to pldhash.c, but then became public to | ||
1638 | 1405 | + * assist iterator writers who inspect table->entryStore directly. | ||
1639 | 1406 | + */ | ||
1640 | 1407 | +#define COLLISION_FLAG ((PLDHashNumber) 1) | ||
1641 | 1408 | +#define MARK_ENTRY_FREE(entry) ((entry)->keyHash = 0) | ||
1642 | 1409 | +#define MARK_ENTRY_REMOVED(entry) ((entry)->keyHash = 1) | ||
1643 | 1410 | +#define ENTRY_IS_REMOVED(entry) ((entry)->keyHash == 1) | ||
1644 | 1411 | +#define ENTRY_IS_LIVE(entry) PL_DHASH_ENTRY_IS_LIVE(entry) | ||
1645 | 1412 | +#define ENSURE_LIVE_KEYHASH(hash0) if (hash0 < 2) hash0 -= 2; else (void)0 | ||
1646 | 1413 | + | ||
1647 | 1414 | +/* Match an entry's keyHash against an unstored one computed from a key. */ | ||
1648 | 1415 | +#define MATCH_ENTRY_KEYHASH(entry,hash0) \ | ||
1649 | 1416 | + (((entry)->keyHash & ~COLLISION_FLAG) == (hash0)) | ||
1650 | 1417 | + | ||
1651 | 1418 | +/* Compute the address of the indexed entry in table. */ | ||
1652 | 1419 | +#define ADDRESS_ENTRY(table, index) \ | ||
1653 | 1420 | + ((PLDHashEntryHdr *)((table)->entryStore + (index) * (table)->entrySize)) | ||
1654 | 1421 | + | ||
1655 | 1422 | +void | ||
1656 | 1423 | +PL_DHashTableFinish(PLDHashTable *table) | ||
1657 | 1424 | +{ | ||
1658 | 1425 | + char *entryAddr, *entryLimit; | ||
1659 | 1426 | + PRUint32 entrySize; | ||
1660 | 1427 | + PLDHashEntryHdr *entry; | ||
1661 | 1428 | + | ||
1662 | 1429 | +#ifdef DEBUG_XXXbrendan | ||
1663 | 1430 | + static FILE *dumpfp = NULL; | ||
1664 | 1431 | + if (!dumpfp) dumpfp = fopen("/tmp/pldhash.bigdump", "w"); | ||
1665 | 1432 | + if (dumpfp) { | ||
1666 | 1433 | +#ifdef MOZILLA_CLIENT | ||
1667 | 1434 | + NS_TraceStack(1, dumpfp); | ||
1668 | 1435 | +#endif | ||
1669 | 1436 | + PL_DHashTableDumpMeter(table, NULL, dumpfp); | ||
1670 | 1437 | + fputc('\n', dumpfp); | ||
1671 | 1438 | + } | ||
1672 | 1439 | +#endif | ||
1673 | 1440 | + | ||
1674 | 1441 | + INCREMENT_RECURSION_LEVEL(table); | ||
1675 | 1442 | + | ||
1676 | 1443 | + /* Call finalize before clearing entries, so it can enumerate them. */ | ||
1677 | 1444 | + table->ops->finalize(table); | ||
1678 | 1445 | + | ||
1679 | 1446 | + /* Clear any remaining live entries. */ | ||
1680 | 1447 | + entryAddr = table->entryStore; | ||
1681 | 1448 | + entrySize = table->entrySize; | ||
1682 | 1449 | + entryLimit = entryAddr + PL_DHASH_TABLE_SIZE(table) * entrySize; | ||
1683 | 1450 | + while (entryAddr < entryLimit) { | ||
1684 | 1451 | + entry = (PLDHashEntryHdr *)entryAddr; | ||
1685 | 1452 | + if (ENTRY_IS_LIVE(entry)) { | ||
1686 | 1453 | + METER(table->stats.removeEnums++); | ||
1687 | 1454 | + table->ops->clearEntry(table, entry); | ||
1688 | 1455 | + } | ||
1689 | 1456 | + entryAddr += entrySize; | ||
1690 | 1457 | + } | ||
1691 | 1458 | + | ||
1692 | 1459 | + DECREMENT_RECURSION_LEVEL(table); | ||
1693 | 1460 | + NS_ASSERTION(RECURSION_LEVEL_SAFE_TO_FINISH(table), | ||
1694 | 1461 | + "RECURSION_LEVEL_SAFE_TO_FINISH(table)"); | ||
1695 | 1462 | + | ||
1696 | 1463 | + /* Free entry storage last. */ | ||
1697 | 1464 | + table->ops->freeTable(table, table->entryStore); | ||
1698 | 1465 | +} | ||
1699 | 1466 | + | ||
1700 | 1467 | +static PLDHashEntryHdr * PL_DHASH_FASTCALL | ||
1701 | 1468 | +SearchTable(PLDHashTable *table, const void *key, PLDHashNumber keyHash, | ||
1702 | 1469 | + PLDHashOperator op) | ||
1703 | 1470 | +{ | ||
1704 | 1471 | + PLDHashNumber hash1, hash2; | ||
1705 | 1472 | + int hashShift, sizeLog2; | ||
1706 | 1473 | + PLDHashEntryHdr *entry, *firstRemoved; | ||
1707 | 1474 | + PLDHashMatchEntry matchEntry; | ||
1708 | 1475 | + PRUint32 sizeMask; | ||
1709 | 1476 | + | ||
1710 | 1477 | + METER(table->stats.searches++); | ||
1711 | 1478 | + NS_ASSERTION(!(keyHash & COLLISION_FLAG), | ||
1712 | 1479 | + "!(keyHash & COLLISION_FLAG)"); | ||
1713 | 1480 | + | ||
1714 | 1481 | + /* Compute the primary hash address. */ | ||
1715 | 1482 | + hashShift = table->hashShift; | ||
1716 | 1483 | + hash1 = HASH1(keyHash, hashShift); | ||
1717 | 1484 | + entry = ADDRESS_ENTRY(table, hash1); | ||
1718 | 1485 | + | ||
1719 | 1486 | + /* Miss: return space for a new entry. */ | ||
1720 | 1487 | + if (PL_DHASH_ENTRY_IS_FREE(entry)) { | ||
1721 | 1488 | + METER(table->stats.misses++); | ||
1722 | 1489 | + return entry; | ||
1723 | 1490 | + } | ||
1724 | 1491 | + | ||
1725 | 1492 | + /* Hit: return entry. */ | ||
1726 | 1493 | + matchEntry = table->ops->matchEntry; | ||
1727 | 1494 | + if (MATCH_ENTRY_KEYHASH(entry, keyHash) && matchEntry(table, entry, key)) { | ||
1728 | 1495 | + METER(table->stats.hits++); | ||
1729 | 1496 | + return entry; | ||
1730 | 1497 | + } | ||
1731 | 1498 | + | ||
1732 | 1499 | + /* Collision: double hash. */ | ||
1733 | 1500 | + sizeLog2 = PL_DHASH_BITS - table->hashShift; | ||
1734 | 1501 | + hash2 = HASH2(keyHash, sizeLog2, hashShift); | ||
1735 | 1502 | + sizeMask = PR_BITMASK(sizeLog2); | ||
1736 | 1503 | + | ||
1737 | 1504 | + /* Save the first removed entry pointer so PL_DHASH_ADD can recycle it. */ | ||
1738 | 1505 | + firstRemoved = NULL; | ||
1739 | 1506 | + | ||
1740 | 1507 | + for (;;) { | ||
1741 | 1508 | + if (NS_UNLIKELY(ENTRY_IS_REMOVED(entry))) { | ||
1742 | 1509 | + if (!firstRemoved) | ||
1743 | 1510 | + firstRemoved = entry; | ||
1744 | 1511 | + } else { | ||
1745 | 1512 | + if (op == PL_DHASH_ADD) | ||
1746 | 1513 | + entry->keyHash |= COLLISION_FLAG; | ||
1747 | 1514 | + } | ||
1748 | 1515 | + | ||
1749 | 1516 | + METER(table->stats.steps++); | ||
1750 | 1517 | + hash1 -= hash2; | ||
1751 | 1518 | + hash1 &= sizeMask; | ||
1752 | 1519 | + | ||
1753 | 1520 | + entry = ADDRESS_ENTRY(table, hash1); | ||
1754 | 1521 | + if (PL_DHASH_ENTRY_IS_FREE(entry)) { | ||
1755 | 1522 | + METER(table->stats.misses++); | ||
1756 | 1523 | + return (firstRemoved && op == PL_DHASH_ADD) ? firstRemoved : entry; | ||
1757 | 1524 | + } | ||
1758 | 1525 | + | ||
1759 | 1526 | + if (MATCH_ENTRY_KEYHASH(entry, keyHash) && | ||
1760 | 1527 | + matchEntry(table, entry, key)) { | ||
1761 | 1528 | + METER(table->stats.hits++); | ||
1762 | 1529 | + return entry; | ||
1763 | 1530 | + } | ||
1764 | 1531 | + } | ||
1765 | 1532 | + | ||
1766 | 1533 | + /* NOTREACHED */ | ||
1767 | 1534 | + return NULL; | ||
1768 | 1535 | +} | ||
1769 | 1536 | + | ||
1770 | 1537 | +/* | ||
1771 | 1538 | + * This is a copy of SearchTable, used by ChangeTable, hardcoded to | ||
1772 | 1539 | + * 1. assume |op == PL_DHASH_ADD|, | ||
1773 | 1540 | + * 2. assume that |key| will never match an existing entry, and | ||
1774 | 1541 | + * 3. assume that no entries have been removed from the current table | ||
1775 | 1542 | + * structure. | ||
1776 | 1543 | + * Avoiding the need for |key| means we can avoid needing a way to map | ||
1777 | 1544 | + * entries to keys, which means callers can use complex key types more | ||
1778 | 1545 | + * easily. | ||
1779 | 1546 | + */ | ||
1780 | 1547 | +static PLDHashEntryHdr * PL_DHASH_FASTCALL | ||
1781 | 1548 | +FindFreeEntry(PLDHashTable *table, PLDHashNumber keyHash) | ||
1782 | 1549 | +{ | ||
1783 | 1550 | + PLDHashNumber hash1, hash2; | ||
1784 | 1551 | + int hashShift, sizeLog2; | ||
1785 | 1552 | + PLDHashEntryHdr *entry; | ||
1786 | 1553 | + PRUint32 sizeMask; | ||
1787 | 1554 | + | ||
1788 | 1555 | + METER(table->stats.searches++); | ||
1789 | 1556 | + NS_ASSERTION(!(keyHash & COLLISION_FLAG), | ||
1790 | 1557 | + "!(keyHash & COLLISION_FLAG)"); | ||
1791 | 1558 | + | ||
1792 | 1559 | + /* Compute the primary hash address. */ | ||
1793 | 1560 | + hashShift = table->hashShift; | ||
1794 | 1561 | + hash1 = HASH1(keyHash, hashShift); | ||
1795 | 1562 | + entry = ADDRESS_ENTRY(table, hash1); | ||
1796 | 1563 | + | ||
1797 | 1564 | + /* Miss: return space for a new entry. */ | ||
1798 | 1565 | + if (PL_DHASH_ENTRY_IS_FREE(entry)) { | ||
1799 | 1566 | + METER(table->stats.misses++); | ||
1800 | 1567 | + return entry; | ||
1801 | 1568 | + } | ||
1802 | 1569 | + | ||
1803 | 1570 | + /* Collision: double hash. */ | ||
1804 | 1571 | + sizeLog2 = PL_DHASH_BITS - table->hashShift; | ||
1805 | 1572 | + hash2 = HASH2(keyHash, sizeLog2, hashShift); | ||
1806 | 1573 | + sizeMask = PR_BITMASK(sizeLog2); | ||
1807 | 1574 | + | ||
1808 | 1575 | + for (;;) { | ||
1809 | 1576 | + NS_ASSERTION(!ENTRY_IS_REMOVED(entry), | ||
1810 | 1577 | + "!ENTRY_IS_REMOVED(entry)"); | ||
1811 | 1578 | + entry->keyHash |= COLLISION_FLAG; | ||
1812 | 1579 | + | ||
1813 | 1580 | + METER(table->stats.steps++); | ||
1814 | 1581 | + hash1 -= hash2; | ||
1815 | 1582 | + hash1 &= sizeMask; | ||
1816 | 1583 | + | ||
1817 | 1584 | + entry = ADDRESS_ENTRY(table, hash1); | ||
1818 | 1585 | + if (PL_DHASH_ENTRY_IS_FREE(entry)) { | ||
1819 | 1586 | + METER(table->stats.misses++); | ||
1820 | 1587 | + return entry; | ||
1821 | 1588 | + } | ||
1822 | 1589 | + } | ||
1823 | 1590 | + | ||
1824 | 1591 | + /* NOTREACHED */ | ||
1825 | 1592 | + return NULL; | ||
1826 | 1593 | +} | ||
1827 | 1594 | + | ||
1828 | 1595 | +static PRBool | ||
1829 | 1596 | +ChangeTable(PLDHashTable *table, int deltaLog2) | ||
1830 | 1597 | +{ | ||
1831 | 1598 | + int oldLog2, newLog2; | ||
1832 | 1599 | + PRUint32 oldCapacity, newCapacity; | ||
1833 | 1600 | + char *newEntryStore, *oldEntryStore, *oldEntryAddr; | ||
1834 | 1601 | + PRUint32 entrySize, i, nbytes; | ||
1835 | 1602 | + PLDHashEntryHdr *oldEntry, *newEntry; | ||
1836 | 1603 | + PLDHashMoveEntry moveEntry; | ||
1837 | 1604 | +#ifdef DEBUG | ||
1838 | 1605 | + PRUint32 recursionLevel; | ||
1839 | 1606 | +#endif | ||
1840 | 1607 | + | ||
1841 | 1608 | + /* Look, but don't touch, until we succeed in getting new entry store. */ | ||
1842 | 1609 | + oldLog2 = PL_DHASH_BITS - table->hashShift; | ||
1843 | 1610 | + newLog2 = oldLog2 + deltaLog2; | ||
1844 | 1611 | + oldCapacity = PR_BIT(oldLog2); | ||
1845 | 1612 | + newCapacity = PR_BIT(newLog2); | ||
1846 | 1613 | + if (newCapacity >= PL_DHASH_SIZE_LIMIT) | ||
1847 | 1614 | + return PR_FALSE; | ||
1848 | 1615 | + entrySize = table->entrySize; | ||
1849 | 1616 | + nbytes = newCapacity * entrySize; | ||
1850 | 1617 | + | ||
1851 | 1618 | + newEntryStore = (char *) table->ops->allocTable(table, | ||
1852 | 1619 | + nbytes + ENTRY_STORE_EXTRA); | ||
1853 | 1620 | + if (!newEntryStore) | ||
1854 | 1621 | + return PR_FALSE; | ||
1855 | 1622 | + | ||
1856 | 1623 | + /* We can't fail from here on, so update table parameters. */ | ||
1857 | 1624 | +#ifdef DEBUG | ||
1858 | 1625 | + recursionLevel = RECURSION_LEVEL(table); | ||
1859 | 1626 | +#endif | ||
1860 | 1627 | + table->hashShift = PL_DHASH_BITS - newLog2; | ||
1861 | 1628 | + table->removedCount = 0; | ||
1862 | 1629 | + table->generation++; | ||
1863 | 1630 | + | ||
1864 | 1631 | + /* Assign the new entry store to table. */ | ||
1865 | 1632 | + memset(newEntryStore, 0, nbytes); | ||
1866 | 1633 | + oldEntryAddr = oldEntryStore = table->entryStore; | ||
1867 | 1634 | + table->entryStore = newEntryStore; | ||
1868 | 1635 | + moveEntry = table->ops->moveEntry; | ||
1869 | 1636 | +#ifdef DEBUG | ||
1870 | 1637 | + RECURSION_LEVEL(table) = recursionLevel; | ||
1871 | 1638 | +#endif | ||
1872 | 1639 | + | ||
1873 | 1640 | + /* Copy only live entries, leaving removed ones behind. */ | ||
1874 | 1641 | + for (i = 0; i < oldCapacity; i++) { | ||
1875 | 1642 | + oldEntry = (PLDHashEntryHdr *)oldEntryAddr; | ||
1876 | 1643 | + if (ENTRY_IS_LIVE(oldEntry)) { | ||
1877 | 1644 | + oldEntry->keyHash &= ~COLLISION_FLAG; | ||
1878 | 1645 | + newEntry = FindFreeEntry(table, oldEntry->keyHash); | ||
1879 | 1646 | + NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(newEntry), | ||
1880 | 1647 | + "PL_DHASH_ENTRY_IS_FREE(newEntry)"); | ||
1881 | 1648 | + moveEntry(table, oldEntry, newEntry); | ||
1882 | 1649 | + newEntry->keyHash = oldEntry->keyHash; | ||
1883 | 1650 | + } | ||
1884 | 1651 | + oldEntryAddr += entrySize; | ||
1885 | 1652 | + } | ||
1886 | 1653 | + | ||
1887 | 1654 | + table->ops->freeTable(table, oldEntryStore); | ||
1888 | 1655 | + return PR_TRUE; | ||
1889 | 1656 | +} | ||
1890 | 1657 | + | ||
1891 | 1658 | +PLDHashEntryHdr * PL_DHASH_FASTCALL | ||
1892 | 1659 | +PL_DHashTableOperate(PLDHashTable *table, const void *key, PLDHashOperator op) | ||
1893 | 1660 | +{ | ||
1894 | 1661 | + PLDHashNumber keyHash; | ||
1895 | 1662 | + PLDHashEntryHdr *entry; | ||
1896 | 1663 | + PRUint32 size; | ||
1897 | 1664 | + int deltaLog2; | ||
1898 | 1665 | + | ||
1899 | 1666 | + NS_ASSERTION(op == PL_DHASH_LOOKUP || RECURSION_LEVEL(table) == 0, | ||
1900 | 1667 | + "op == PL_DHASH_LOOKUP || RECURSION_LEVEL(table) == 0"); | ||
1901 | 1668 | + INCREMENT_RECURSION_LEVEL(table); | ||
1902 | 1669 | + | ||
1903 | 1670 | + keyHash = table->ops->hashKey(table, key); | ||
1904 | 1671 | + keyHash *= PL_DHASH_GOLDEN_RATIO; | ||
1905 | 1672 | + | ||
1906 | 1673 | + /* Avoid 0 and 1 hash codes, they indicate free and removed entries. */ | ||
1907 | 1674 | + ENSURE_LIVE_KEYHASH(keyHash); | ||
1908 | 1675 | + keyHash &= ~COLLISION_FLAG; | ||
1909 | 1676 | + | ||
1910 | 1677 | + switch (op) { | ||
1911 | 1678 | + case PL_DHASH_LOOKUP: | ||
1912 | 1679 | + METER(table->stats.lookups++); | ||
1913 | 1680 | + entry = SearchTable(table, key, keyHash, op); | ||
1914 | 1681 | + break; | ||
1915 | 1682 | + | ||
1916 | 1683 | + case PL_DHASH_ADD: | ||
1917 | 1684 | + /* | ||
1918 | 1685 | + * If alpha is >= .75, grow or compress the table. If key is already | ||
1919 | 1686 | + * in the table, we may grow once more than necessary, but only if we | ||
1920 | 1687 | + * are on the edge of being overloaded. | ||
1921 | 1688 | + */ | ||
1922 | 1689 | + size = PL_DHASH_TABLE_SIZE(table); | ||
1923 | 1690 | + if (table->entryCount + table->removedCount >= MAX_LOAD(table, size)) { | ||
1924 | 1691 | + /* Compress if a quarter or more of all entries are removed. */ | ||
1925 | 1692 | + if (table->removedCount >= size >> 2) { | ||
1926 | 1693 | + METER(table->stats.compresses++); | ||
1927 | 1694 | + deltaLog2 = 0; | ||
1928 | 1695 | + } else { | ||
1929 | 1696 | + METER(table->stats.grows++); | ||
1930 | 1697 | + deltaLog2 = 1; | ||
1931 | 1698 | + } | ||
1932 | 1699 | + | ||
1933 | 1700 | + /* | ||
1934 | 1701 | + * Grow or compress table, returning null if ChangeTable fails and | ||
1935 | 1702 | + * falling through might claim the last free entry. | ||
1936 | 1703 | + */ | ||
1937 | 1704 | + if (!ChangeTable(table, deltaLog2) && | ||
1938 | 1705 | + table->entryCount + table->removedCount == size - 1) { | ||
1939 | 1706 | + METER(table->stats.addFailures++); | ||
1940 | 1707 | + entry = NULL; | ||
1941 | 1708 | + break; | ||
1942 | 1709 | + } | ||
1943 | 1710 | + } | ||
1944 | 1711 | + | ||
1945 | 1712 | + /* | ||
1946 | 1713 | + * Look for entry after possibly growing, so we don't have to add it, | ||
1947 | 1714 | + * then skip it while growing the table and re-add it after. | ||
1948 | 1715 | + */ | ||
1949 | 1716 | + entry = SearchTable(table, key, keyHash, op); | ||
1950 | 1717 | + if (!ENTRY_IS_LIVE(entry)) { | ||
1951 | 1718 | + /* Initialize the entry, indicating that it's no longer free. */ | ||
1952 | 1719 | + METER(table->stats.addMisses++); | ||
1953 | 1720 | + if (ENTRY_IS_REMOVED(entry)) { | ||
1954 | 1721 | + METER(table->stats.addOverRemoved++); | ||
1955 | 1722 | + table->removedCount--; | ||
1956 | 1723 | + keyHash |= COLLISION_FLAG; | ||
1957 | 1724 | + } | ||
1958 | 1725 | + if (table->ops->initEntry && | ||
1959 | 1726 | + !table->ops->initEntry(table, entry, key)) { | ||
1960 | 1727 | + /* We haven't claimed entry yet; fail with null return. */ | ||
1961 | 1728 | + memset(entry + 1, 0, table->entrySize - sizeof *entry); | ||
1962 | 1729 | + entry = NULL; | ||
1963 | 1730 | + break; | ||
1964 | 1731 | + } | ||
1965 | 1732 | + entry->keyHash = keyHash; | ||
1966 | 1733 | + table->entryCount++; | ||
1967 | 1734 | + } | ||
1968 | 1735 | + METER(else table->stats.addHits++); | ||
1969 | 1736 | + break; | ||
1970 | 1737 | + | ||
1971 | 1738 | + case PL_DHASH_REMOVE: | ||
1972 | 1739 | + entry = SearchTable(table, key, keyHash, op); | ||
1973 | 1740 | + if (ENTRY_IS_LIVE(entry)) { | ||
1974 | 1741 | + /* Clear this entry and mark it as "removed". */ | ||
1975 | 1742 | + METER(table->stats.removeHits++); | ||
1976 | 1743 | + PL_DHashTableRawRemove(table, entry); | ||
1977 | 1744 | + | ||
1978 | 1745 | + /* Shrink if alpha is <= .25 and table isn't too small already. */ | ||
1979 | 1746 | + size = PL_DHASH_TABLE_SIZE(table); | ||
1980 | 1747 | + if (size > PL_DHASH_MIN_SIZE && | ||
1981 | 1748 | + table->entryCount <= MIN_LOAD(table, size)) { | ||
1982 | 1749 | + METER(table->stats.shrinks++); | ||
1983 | 1750 | + (void) ChangeTable(table, -1); | ||
1984 | 1751 | + } | ||
1985 | 1752 | + } | ||
1986 | 1753 | + METER(else table->stats.removeMisses++); | ||
1987 | 1754 | + entry = NULL; | ||
1988 | 1755 | + break; | ||
1989 | 1756 | + | ||
1990 | 1757 | + default: | ||
1991 | 1758 | + NS_NOTREACHED("0"); | ||
1992 | 1759 | + entry = NULL; | ||
1993 | 1760 | + } | ||
1994 | 1761 | + | ||
1995 | 1762 | + DECREMENT_RECURSION_LEVEL(table); | ||
1996 | 1763 | + | ||
1997 | 1764 | + return entry; | ||
1998 | 1765 | +} | ||
1999 | 1766 | + | ||
2000 | 1767 | +void | ||
2001 | 1768 | +PL_DHashTableRawRemove(PLDHashTable *table, PLDHashEntryHdr *entry) | ||
2002 | 1769 | +{ | ||
2003 | 1770 | + PLDHashNumber keyHash; /* load first in case clearEntry goofs it */ | ||
2004 | 1771 | + | ||
2005 | 1772 | + NS_ASSERTION(RECURSION_LEVEL(table) != IMMUTABLE_RECURSION_LEVEL, | ||
2006 | 1773 | + "RECURSION_LEVEL(table) != IMMUTABLE_RECURSION_LEVEL"); | ||
2007 | 1774 | + | ||
2008 | 1775 | + NS_ASSERTION(PL_DHASH_ENTRY_IS_LIVE(entry), | ||
2009 | 1776 | + "PL_DHASH_ENTRY_IS_LIVE(entry)"); | ||
2010 | 1777 | + keyHash = entry->keyHash; | ||
2011 | 1778 | + table->ops->clearEntry(table, entry); | ||
2012 | 1779 | + if (keyHash & COLLISION_FLAG) { | ||
2013 | 1780 | + MARK_ENTRY_REMOVED(entry); | ||
2014 | 1781 | + table->removedCount++; | ||
2015 | 1782 | + } else { | ||
2016 | 1783 | + METER(table->stats.removeFrees++); | ||
2017 | 1784 | + MARK_ENTRY_FREE(entry); | ||
2018 | 1785 | + } | ||
2019 | 1786 | + table->entryCount--; | ||
2020 | 1787 | +} | ||
2021 | 1788 | + | ||
2022 | 1789 | +PRUint32 | ||
2023 | 1790 | +PL_DHashTableEnumerate(PLDHashTable *table, PLDHashEnumerator etor, void *arg) | ||
2024 | 1791 | +{ | ||
2025 | 1792 | + char *entryAddr, *entryLimit; | ||
2026 | 1793 | + PRUint32 i, capacity, entrySize, ceiling; | ||
2027 | 1794 | + PRBool didRemove; | ||
2028 | 1795 | + PLDHashEntryHdr *entry; | ||
2029 | 1796 | + PLDHashOperator op; | ||
2030 | 1797 | + | ||
2031 | 1798 | + INCREMENT_RECURSION_LEVEL(table); | ||
2032 | 1799 | + | ||
2033 | 1800 | + entryAddr = table->entryStore; | ||
2034 | 1801 | + entrySize = table->entrySize; | ||
2035 | 1802 | + capacity = PL_DHASH_TABLE_SIZE(table); | ||
2036 | 1803 | + entryLimit = entryAddr + capacity * entrySize; | ||
2037 | 1804 | + i = 0; | ||
2038 | 1805 | + didRemove = PR_FALSE; | ||
2039 | 1806 | + while (entryAddr < entryLimit) { | ||
2040 | 1807 | + entry = (PLDHashEntryHdr *)entryAddr; | ||
2041 | 1808 | + if (ENTRY_IS_LIVE(entry)) { | ||
2042 | 1809 | + op = etor(table, entry, i++, arg); | ||
2043 | 1810 | + if (op & PL_DHASH_REMOVE) { | ||
2044 | 1811 | + METER(table->stats.removeEnums++); | ||
2045 | 1812 | + PL_DHashTableRawRemove(table, entry); | ||
2046 | 1813 | + didRemove = PR_TRUE; | ||
2047 | 1814 | + } | ||
2048 | 1815 | + if (op & PL_DHASH_STOP) | ||
2049 | 1816 | + break; | ||
2050 | 1817 | + } | ||
2051 | 1818 | + entryAddr += entrySize; | ||
2052 | 1819 | + } | ||
2053 | 1820 | + | ||
2054 | 1821 | + NS_ASSERTION(!didRemove || RECURSION_LEVEL(table) == 1, | ||
2055 | 1822 | + "!didRemove || RECURSION_LEVEL(table) == 1"); | ||
2056 | 1823 | + | ||
2057 | 1824 | + /* | ||
2058 | 1825 | + * Shrink or compress if a quarter or more of all entries are removed, or | ||
2059 | 1826 | + * if the table is underloaded according to the configured minimum alpha, | ||
2060 | 1827 | + * and is not minimal-size already. Do this only if we removed above, so | ||
2061 | 1828 | + * non-removing enumerations can count on stable table->entryStore until | ||
2062 | 1829 | + * the next non-lookup-Operate or removing-Enumerate. | ||
2063 | 1830 | + */ | ||
2064 | 1831 | + if (didRemove && | ||
2065 | 1832 | + (table->removedCount >= capacity >> 2 || | ||
2066 | 1833 | + (capacity > PL_DHASH_MIN_SIZE && | ||
2067 | 1834 | + table->entryCount <= MIN_LOAD(table, capacity)))) { | ||
2068 | 1835 | + METER(table->stats.enumShrinks++); | ||
2069 | 1836 | + capacity = table->entryCount; | ||
2070 | 1837 | + capacity += capacity >> 1; | ||
2071 | 1838 | + if (capacity < PL_DHASH_MIN_SIZE) | ||
2072 | 1839 | + capacity = PL_DHASH_MIN_SIZE; | ||
2073 | 1840 | + | ||
2074 | 1841 | + PR_CEILING_LOG2(ceiling, capacity); | ||
2075 | 1842 | + ceiling -= PL_DHASH_BITS - table->hashShift; | ||
2076 | 1843 | + | ||
2077 | 1844 | + (void) ChangeTable(table, ceiling); | ||
2078 | 1845 | + } | ||
2079 | 1846 | + | ||
2080 | 1847 | + DECREMENT_RECURSION_LEVEL(table); | ||
2081 | 1848 | + | ||
2082 | 1849 | + return i; | ||
2083 | 1850 | +} | ||
2084 | 1851 | + | ||
2085 | 1852 | +#ifdef DEBUG | ||
2086 | 1853 | +void | ||
2087 | 1854 | +PL_DHashMarkTableImmutable(PLDHashTable *table) | ||
2088 | 1855 | +{ | ||
2089 | 1856 | + RECURSION_LEVEL(table) = IMMUTABLE_RECURSION_LEVEL; | ||
2090 | 1857 | +} | ||
2091 | 1858 | +#endif | ||
2092 | 1859 | + | ||
2093 | 1860 | +#ifdef PL_DHASHMETER | ||
2094 | 1861 | +#include <math.h> | ||
2095 | 1862 | + | ||
2096 | 1863 | +void | ||
2097 | 1864 | +PL_DHashTableDumpMeter(PLDHashTable *table, PLDHashEnumerator dump, FILE *fp) | ||
2098 | 1865 | +{ | ||
2099 | 1866 | + char *entryAddr; | ||
2100 | 1867 | + PRUint32 entrySize, entryCount; | ||
2101 | 1868 | + int hashShift, sizeLog2; | ||
2102 | 1869 | + PRUint32 i, tableSize, sizeMask, chainLen, maxChainLen, chainCount; | ||
2103 | 1870 | + PLDHashNumber hash1, hash2, saveHash1, maxChainHash1, maxChainHash2; | ||
2104 | 1871 | + double sqsum, mean, variance, sigma; | ||
2105 | 1872 | + PLDHashEntryHdr *entry, *probe; | ||
2106 | 1873 | + | ||
2107 | 1874 | + entryAddr = table->entryStore; | ||
2108 | 1875 | + entrySize = table->entrySize; | ||
2109 | 1876 | + hashShift = table->hashShift; | ||
2110 | 1877 | + sizeLog2 = PL_DHASH_BITS - hashShift; | ||
2111 | 1878 | + tableSize = PL_DHASH_TABLE_SIZE(table); | ||
2112 | 1879 | + sizeMask = PR_BITMASK(sizeLog2); | ||
2113 | 1880 | + chainCount = maxChainLen = 0; | ||
2114 | 1881 | + hash2 = 0; | ||
2115 | 1882 | + sqsum = 0; | ||
2116 | 1883 | + | ||
2117 | 1884 | + for (i = 0; i < tableSize; i++) { | ||
2118 | 1885 | + entry = (PLDHashEntryHdr *)entryAddr; | ||
2119 | 1886 | + entryAddr += entrySize; | ||
2120 | 1887 | + if (!ENTRY_IS_LIVE(entry)) | ||
2121 | 1888 | + continue; | ||
2122 | 1889 | + hash1 = HASH1(entry->keyHash & ~COLLISION_FLAG, hashShift); | ||
2123 | 1890 | + saveHash1 = hash1; | ||
2124 | 1891 | + probe = ADDRESS_ENTRY(table, hash1); | ||
2125 | 1892 | + chainLen = 1; | ||
2126 | 1893 | + if (probe == entry) { | ||
2127 | 1894 | + /* Start of a (possibly unit-length) chain. */ | ||
2128 | 1895 | + chainCount++; | ||
2129 | 1896 | + } else { | ||
2130 | 1897 | + hash2 = HASH2(entry->keyHash & ~COLLISION_FLAG, sizeLog2, | ||
2131 | 1898 | + hashShift); | ||
2132 | 1899 | + do { | ||
2133 | 1900 | + chainLen++; | ||
2134 | 1901 | + hash1 -= hash2; | ||
2135 | 1902 | + hash1 &= sizeMask; | ||
2136 | 1903 | + probe = ADDRESS_ENTRY(table, hash1); | ||
2137 | 1904 | + } while (probe != entry); | ||
2138 | 1905 | + } | ||
2139 | 1906 | + sqsum += chainLen * chainLen; | ||
2140 | 1907 | + if (chainLen > maxChainLen) { | ||
2141 | 1908 | + maxChainLen = chainLen; | ||
2142 | 1909 | + maxChainHash1 = saveHash1; | ||
2143 | 1910 | + maxChainHash2 = hash2; | ||
2144 | 1911 | + } | ||
2145 | 1912 | + } | ||
2146 | 1913 | + | ||
2147 | 1914 | + entryCount = table->entryCount; | ||
2148 | 1915 | + if (entryCount && chainCount) { | ||
2149 | 1916 | + mean = (double)entryCount / chainCount; | ||
2150 | 1917 | + variance = chainCount * sqsum - entryCount * entryCount; | ||
2151 | 1918 | + if (variance < 0 || chainCount == 1) | ||
2152 | 1919 | + variance = 0; | ||
2153 | 1920 | + else | ||
2154 | 1921 | + variance /= chainCount * (chainCount - 1); | ||
2155 | 1922 | + sigma = sqrt(variance); | ||
2156 | 1923 | + } else { | ||
2157 | 1924 | + mean = sigma = 0; | ||
2158 | 1925 | + } | ||
2159 | 1926 | + | ||
2160 | 1927 | + fprintf(fp, "Double hashing statistics:\n"); | ||
2161 | 1928 | + fprintf(fp, " table size (in entries): %u\n", tableSize); | ||
2162 | 1929 | + fprintf(fp, " number of entries: %u\n", table->entryCount); | ||
2163 | 1930 | + fprintf(fp, " number of removed entries: %u\n", table->removedCount); | ||
2164 | 1931 | + fprintf(fp, " number of searches: %u\n", table->stats.searches); | ||
2165 | 1932 | + fprintf(fp, " number of hits: %u\n", table->stats.hits); | ||
2166 | 1933 | + fprintf(fp, " number of misses: %u\n", table->stats.misses); | ||
2167 | 1934 | + fprintf(fp, " mean steps per search: %g\n", table->stats.searches ? | ||
2168 | 1935 | + (double)table->stats.steps | ||
2169 | 1936 | + / table->stats.searches : | ||
2170 | 1937 | + 0.); | ||
2171 | 1938 | + fprintf(fp, " mean hash chain length: %g\n", mean); | ||
2172 | 1939 | + fprintf(fp, " standard deviation: %g\n", sigma); | ||
2173 | 1940 | + fprintf(fp, " maximum hash chain length: %u\n", maxChainLen); | ||
2174 | 1941 | + fprintf(fp, " number of lookups: %u\n", table->stats.lookups); | ||
2175 | 1942 | + fprintf(fp, " adds that made a new entry: %u\n", table->stats.addMisses); | ||
2176 | 1943 | + fprintf(fp, "adds that recycled removeds: %u\n", table->stats.addOverRemoved); | ||
2177 | 1944 | + fprintf(fp, " adds that found an entry: %u\n", table->stats.addHits); | ||
2178 | 1945 | + fprintf(fp, " add failures: %u\n", table->stats.addFailures); | ||
2179 | 1946 | + fprintf(fp, " useful removes: %u\n", table->stats.removeHits); | ||
2180 | 1947 | + fprintf(fp, " useless removes: %u\n", table->stats.removeMisses); | ||
2181 | 1948 | + fprintf(fp, "removes that freed an entry: %u\n", table->stats.removeFrees); | ||
2182 | 1949 | + fprintf(fp, " removes while enumerating: %u\n", table->stats.removeEnums); | ||
2183 | 1950 | + fprintf(fp, " number of grows: %u\n", table->stats.grows); | ||
2184 | 1951 | + fprintf(fp, " number of shrinks: %u\n", table->stats.shrinks); | ||
2185 | 1952 | + fprintf(fp, " number of compresses: %u\n", table->stats.compresses); | ||
2186 | 1953 | + fprintf(fp, "number of enumerate shrinks: %u\n", table->stats.enumShrinks); | ||
2187 | 1954 | + | ||
2188 | 1955 | + if (dump && maxChainLen && hash2) { | ||
2189 | 1956 | + fputs("Maximum hash chain:\n", fp); | ||
2190 | 1957 | + hash1 = maxChainHash1; | ||
2191 | 1958 | + hash2 = maxChainHash2; | ||
2192 | 1959 | + entry = ADDRESS_ENTRY(table, hash1); | ||
2193 | 1960 | + i = 0; | ||
2194 | 1961 | + do { | ||
2195 | 1962 | + if (dump(table, entry, i++, fp) != PL_DHASH_NEXT) | ||
2196 | 1963 | + break; | ||
2197 | 1964 | + hash1 -= hash2; | ||
2198 | 1965 | + hash1 &= sizeMask; | ||
2199 | 1966 | + entry = ADDRESS_ENTRY(table, hash1); | ||
2200 | 1967 | + } while (PL_DHASH_ENTRY_IS_BUSY(entry)); | ||
2201 | 1968 | + } | ||
2202 | 1969 | +} | ||
2203 | 1970 | +#endif /* PL_DHASHMETER */ | ||
2204 | 1971 | 0 | ||
2205 | === added file 'debian/patches/fix-build-failure-without-yarr-jit.patch' | |||
2206 | --- debian/patches/fix-build-failure-without-yarr-jit.patch 1970-01-01 00:00:00 +0000 | |||
2207 | +++ debian/patches/fix-build-failure-without-yarr-jit.patch 2011-12-16 00:06:23 +0000 | |||
2208 | @@ -0,0 +1,27 @@ | |||
2209 | 1 | Subject: Fix build failure on platforms without YARR JIT | ||
2210 | 2 | Bug-Mozilla: https://bugzilla.mozilla.org/show_bug.cgi?id=703534 | ||
2211 | 3 | Origin: upstream, https://hg.mozilla.org/mozilla-central/raw-rev/15cf58eb7923 | ||
2212 | 4 | Author: Mike Hommey <mh+mozilla@glandium.org> | ||
2213 | 5 | # Rebased for Firefox 9 and Thunderbird directory structure | ||
2214 | 6 | # HG changeset patch | ||
2215 | 7 | # User Mike Hommey <mh+mozilla@glandium.org> | ||
2216 | 8 | # Date 1321613368 -3600 | ||
2217 | 9 | # Node ID 15cf58eb7923d34de7e61df80fa5f8a18a995abf | ||
2218 | 10 | # Parent aeb035da53283c56370992f254e4f79d7dd180f8 | ||
2219 | 11 | |||
2220 | 12 | --- | ||
2221 | 13 | js/src/jscompartment.cpp | 1 - | ||
2222 | 14 | 1 file changed, 1 deletion(-) | ||
2223 | 15 | |||
2224 | 16 | Index: mozilla/mozilla/js/src/jscompartment.cpp | ||
2225 | 17 | =================================================================== | ||
2226 | 18 | --- mozilla.orig/mozilla/js/src/jscompartment.cpp | ||
2227 | 19 | +++ mozilla/mozilla/js/src/jscompartment.cpp | ||
2228 | 20 | @@ -50,7 +50,6 @@ | ||
2229 | 21 | #include "jswatchpoint.h" | ||
2230 | 22 | #include "jswrapper.h" | ||
2231 | 23 | #include "assembler/wtf/Platform.h" | ||
2232 | 24 | -#include "assembler/jit/ExecutableAllocator.h" | ||
2233 | 25 | #include "yarr/BumpPointerAllocator.h" | ||
2234 | 26 | #include "methodjit/MethodJIT.h" | ||
2235 | 27 | #include "methodjit/PolyIC.h" | ||
2236 | 0 | 28 | ||
2237 | === removed file 'debian/patches/only-add-ENABLE_JIT-to-CXXFLAGS-if-jit-is-enabled.patch' | |||
2238 | --- debian/patches/only-add-ENABLE_JIT-to-CXXFLAGS-if-jit-is-enabled.patch 2011-10-11 07:49:14 +0000 | |||
2239 | +++ debian/patches/only-add-ENABLE_JIT-to-CXXFLAGS-if-jit-is-enabled.patch 1970-01-01 00:00:00 +0000 | |||
2240 | @@ -1,55 +0,0 @@ | |||
2241 | 1 | # HG changeset patch | ||
2242 | 2 | # User Mike Hommey <mh+mozilla@glandium.org> | ||
2243 | 3 | # Date 1314108801 -7200 | ||
2244 | 4 | # Node ID 5847fed3426746e8692fdf4221acbd0917237d42 | ||
2245 | 5 | # Parent 93e8590445364cc0a5710e276912aa55b8a938e4 | ||
2246 | 6 | Bug 670719 - Only add -DENABLE_JIT=1 to CXXFLAGS if any of trace/method/yarr jit is enabled. r=dmandelin | ||
2247 | 7 | |||
2248 | 8 | diff --git a/mozilla/js/src/Makefile.in b/mozilla/js/src/Makefile.in | ||
2249 | 9 | --- a/mozilla/js/src/Makefile.in | ||
2250 | 10 | +++ b/mozilla/js/src/Makefile.in | ||
2251 | 11 | @@ -433,16 +433,19 @@ CPPSRCS += \ | ||
2252 | 12 | YarrPattern.cpp \ | ||
2253 | 13 | YarrSyntaxChecker.cpp \ | ||
2254 | 14 | $(NULL) | ||
2255 | 15 | else | ||
2256 | 16 | |||
2257 | 17 | ############################################### | ||
2258 | 18 | # BEGIN include sources for the Nitro assembler | ||
2259 | 19 | # | ||
2260 | 20 | + | ||
2261 | 21 | +ENABLE_YARR_JIT = 1 | ||
2262 | 22 | + | ||
2263 | 23 | VPATH += $(srcdir)/assembler \ | ||
2264 | 24 | $(srcdir)/assembler/wtf \ | ||
2265 | 25 | $(srcdir)/assembler/jit \ | ||
2266 | 26 | $(srcdir)/assembler/assembler \ | ||
2267 | 27 | $(srcdir)/methodjit \ | ||
2268 | 28 | $(srcdir)/yarr \ | ||
2269 | 29 | $(NONE) | ||
2270 | 30 | |||
2271 | 31 | @@ -1076,17 +1079,21 @@ endif | ||
2272 | 32 | |||
2273 | 33 | ############################################### | ||
2274 | 34 | # BEGIN kludges for the Nitro assembler | ||
2275 | 35 | # | ||
2276 | 36 | |||
2277 | 37 | # Needed to "configure" it correctly. Unfortunately these | ||
2278 | 38 | # flags wind up being applied to all code in js/src, not just | ||
2279 | 39 | # the code in js/src/assembler. | ||
2280 | 40 | -CXXFLAGS += -DUSE_SYSTEM_MALLOC=1 -DENABLE_ASSEMBLER=1 -DENABLE_JIT=1 | ||
2281 | 41 | +CXXFLAGS += -DUSE_SYSTEM_MALLOC=1 -DENABLE_ASSEMBLER=1 | ||
2282 | 42 | + | ||
2283 | 43 | +ifneq (,$(ENABLE_YARR_JIT)$(ENABLE_TRACEJIT)$(ENABLE_METHODJIT)) | ||
2284 | 44 | +CXXFLAGS += -DENABLE_JIT=1 | ||
2285 | 45 | +endif | ||
2286 | 46 | |||
2287 | 47 | INCLUDES += -I$(srcdir)/assembler -I$(srcdir)/yarr | ||
2288 | 48 | |||
2289 | 49 | ifdef ENABLE_METHODJIT | ||
2290 | 50 | # Build a standalone test program that exercises the assembler | ||
2291 | 51 | # sources a bit. | ||
2292 | 52 | TESTMAIN_OBJS = \ | ||
2293 | 53 | Assertions.$(OBJ_SUFFIX) \ | ||
2294 | 54 | |||
2295 | 55 | |||
2296 | 56 | 0 | ||
2297 | === modified file 'debian/patches/printf-fix.patch' | |||
2298 | --- debian/patches/printf-fix.patch 2011-10-11 07:49:14 +0000 | |||
2299 | +++ debian/patches/printf-fix.patch 2011-12-16 00:06:23 +0000 | |||
2300 | @@ -1,6 +1,6 @@ | |||
2301 | 1 | --- a/mozilla/gfx/2d/Logging.h | 1 | --- a/mozilla/gfx/2d/Logging.h |
2302 | 2 | +++ b/mozilla/gfx/2d/Logging.h | 2 | +++ b/mozilla/gfx/2d/Logging.h |
2304 | 3 | @@ -86,7 +86,7 @@ static void OutputMessage(const std::str | 3 | @@ -87,7 +87,7 @@ |
2305 | 4 | } | 4 | } |
2306 | 5 | #else | 5 | #else |
2307 | 6 | if (aLevel >= sGfxLogLevel) { | 6 | if (aLevel >= sGfxLogLevel) { |
2308 | 7 | 7 | ||
2309 | === modified file 'debian/patches/series' | |||
2310 | --- debian/patches/series 2011-10-11 07:49:14 +0000 | |||
2311 | +++ debian/patches/series 2011-12-16 00:06:23 +0000 | |||
2312 | @@ -1,4 +1,2 @@ | |||
2313 | 1 | build-fix-for-no-ENABLE_YARR_JIT.patch | ||
2314 | 2 | compile-pldhash-as-C++.patch | ||
2315 | 3 | only-add-ENABLE_JIT-to-CXXFLAGS-if-jit-is-enabled.patch | ||
2316 | 4 | printf-fix.patch | 1 | printf-fix.patch |
2317 | 2 | fix-build-failure-without-yarr-jit.patch | ||
2318 | 5 | 3 | ||
2319 | === modified file 'debian/rules' | |||
2320 | --- debian/rules 2011-09-30 12:45:15 +0000 | |||
2321 | +++ debian/rules 2011-12-16 00:06:23 +0000 | |||
2322 | @@ -7,7 +7,6 @@ | |||
2323 | 7 | 7 | ||
2324 | 8 | MOZ_APP_BASENAME := seamonkey | 8 | MOZ_APP_BASENAME := seamonkey |
2325 | 9 | MOZ_MOZDIR := mozilla | 9 | MOZ_MOZDIR := mozilla |
2326 | 10 | DEBIAN_TAG := SEAMONKEY_2_4_1_RELEASE | ||
2327 | 11 | 10 | ||
2328 | 12 | # Various build options | 11 | # Various build options |
2329 | 13 | # tree = use in-tree libs, system = use system libs | 12 | # tree = use in-tree libs, system = use system libs |
2330 | @@ -179,8 +178,8 @@ | |||
2331 | 179 | export LDFLAGS | 178 | export LDFLAGS |
2332 | 180 | export DEB_BUILD_HARDENING=1 | 179 | export DEB_BUILD_HARDENING=1 |
2333 | 181 | 180 | ||
2336 | 182 | # Lucid has old yasm and does not compile turbo-jpeg. | 181 | # Lucid and Karmic have old yasm and does not compile turbo-jpeg. |
2337 | 183 | ifeq (1,$(shell test "$(DISTRIB_VERSION_MAJOR)$(DISTRIB_VERSION_MINOR)" -eq "1004" && echo "1")) | 182 | ifeq (1,$(shell test "$(DISTRIB_VERSION_MAJOR)$(DISTRIB_VERSION_MINOR)" -lt "1104" && echo "1")) |
2338 | 184 | MOZ_DISABLE_LIBJPEG := 1 | 183 | MOZ_DISABLE_LIBJPEG := 1 |
2339 | 185 | endif | 184 | endif |
2340 | 186 | ifeq (1,$(shell test "$(DISTRIB_VERSION_MAJOR)$(DISTRIB_VERSION_MINOR)" -ge "1010" && echo "1")) | 185 | ifeq (1,$(shell test "$(DISTRIB_VERSION_MAJOR)$(DISTRIB_VERSION_MINOR)" -ge "1010" && echo "1")) |
2341 | 187 | 186 | ||
2342 | === modified file 'debian/seamonkey.desktop.in' | |||
2343 | --- debian/seamonkey.desktop.in 2011-09-10 07:29:03 +0000 | |||
2344 | +++ debian/seamonkey.desktop.in 2011-12-16 00:06:23 +0000 | |||
2345 | @@ -108,7 +108,7 @@ | |||
2346 | 108 | Type=Application | 108 | Type=Application |
2347 | 109 | Icon=@MOZ_APP_NAME@ | 109 | Icon=@MOZ_APP_NAME@ |
2348 | 110 | Categories=Application;Network;Email; | 110 | Categories=Application;Network;Email; |
2350 | 111 | MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/vnd.mozilla.xul+xml;application/rss+xml;application/rdf+xml;x-scheme-handler/mailto; | 111 | MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/vnd.mozilla.xul+xml;application/rss+xml;application/rdf+xml;x-scheme-handler/mailto;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp; |
2351 | 112 | StartupWMClass=@MOZ_DISPLAY_NAME@ | 112 | StartupWMClass=@MOZ_DISPLAY_NAME@ |
2352 | 113 | StartupNotify=true | 113 | StartupNotify=true |
2353 | 114 | GenericName[ast]=Client de correu | 114 | GenericName[ast]=Client de correu |