jbarnette-johnson 1.0.0.200806240111 → 1.0.0.200807291507

Sign up to get free protection for your applications and to get access to all the features.
Files changed (269) hide show
  1. data/MANIFEST +1 -0
  2. data/Rakefile +3 -10
  3. data/bin/johnson +2 -1
  4. data/ext/spidermonkey/context.c +3 -4
  5. data/ext/spidermonkey/context.h +1 -1
  6. data/ext/spidermonkey/conversions.c +39 -33
  7. data/ext/spidermonkey/debugger.c +5 -5
  8. data/ext/spidermonkey/immutable_node.c.erb +11 -11
  9. data/ext/spidermonkey/jroot.h +4 -4
  10. data/ext/spidermonkey/js_land_proxy.c +9 -8
  11. data/ext/spidermonkey/ruby_land_proxy.c +5 -4
  12. data/ext/spidermonkey/runtime.c +1 -1
  13. data/johnson.gemspec +36 -0
  14. data/lib/hoe.rb +0 -7
  15. data/lib/johnson/cli/options.rb +10 -4
  16. data/lib/johnson/spidermonkey/runtime.rb +2 -2
  17. data/lib/johnson/version.rb +4 -2
  18. data/lib/johnson.rb +1 -0
  19. data/test/johnson/runtime_test.rb +11 -0
  20. data/test/johnson/spidermonkey/ruby_land_proxy_test.rb +6 -0
  21. data/vendor/spidermonkey/.cvsignore +9 -0
  22. data/vendor/spidermonkey/Makefile.in +462 -0
  23. data/vendor/spidermonkey/Makefile.ref +364 -0
  24. data/vendor/spidermonkey/README.html +820 -0
  25. data/vendor/spidermonkey/SpiderMonkey.rsp +12 -0
  26. data/vendor/spidermonkey/Y.js +19 -0
  27. data/vendor/spidermonkey/build.mk +43 -0
  28. data/vendor/spidermonkey/config/AIX4.1.mk +65 -0
  29. data/vendor/spidermonkey/config/AIX4.2.mk +64 -0
  30. data/vendor/spidermonkey/config/AIX4.3.mk +65 -0
  31. data/vendor/spidermonkey/config/Darwin.mk +83 -0
  32. data/vendor/spidermonkey/config/Darwin1.3.mk +81 -0
  33. data/vendor/spidermonkey/config/Darwin1.4.mk +41 -0
  34. data/vendor/spidermonkey/config/Darwin5.2.mk +81 -0
  35. data/vendor/spidermonkey/config/Darwin5.3.mk +81 -0
  36. data/vendor/spidermonkey/config/HP-UXB.10.10.mk +77 -0
  37. data/vendor/spidermonkey/config/HP-UXB.10.20.mk +77 -0
  38. data/vendor/spidermonkey/config/HP-UXB.11.00.mk +80 -0
  39. data/vendor/spidermonkey/config/IRIX.mk +87 -0
  40. data/vendor/spidermonkey/config/IRIX5.3.mk +44 -0
  41. data/vendor/spidermonkey/config/IRIX6.1.mk +44 -0
  42. data/vendor/spidermonkey/config/IRIX6.2.mk +44 -0
  43. data/vendor/spidermonkey/config/IRIX6.3.mk +44 -0
  44. data/vendor/spidermonkey/config/IRIX6.5.mk +44 -0
  45. data/vendor/spidermonkey/config/Linux_All.mk +103 -0
  46. data/vendor/spidermonkey/config/Mac_OS10.0.mk +82 -0
  47. data/vendor/spidermonkey/config/OSF1V4.0.mk +72 -0
  48. data/vendor/spidermonkey/config/OSF1V5.0.mk +69 -0
  49. data/vendor/spidermonkey/config/SunOS4.1.4.mk +101 -0
  50. data/vendor/spidermonkey/config/SunOS5.10.mk +50 -0
  51. data/vendor/spidermonkey/config/SunOS5.3.mk +91 -0
  52. data/vendor/spidermonkey/config/SunOS5.4.mk +92 -0
  53. data/vendor/spidermonkey/config/SunOS5.5.1.mk +44 -0
  54. data/vendor/spidermonkey/config/SunOS5.5.mk +87 -0
  55. data/vendor/spidermonkey/config/SunOS5.6.mk +89 -0
  56. data/vendor/spidermonkey/config/SunOS5.7.mk +44 -0
  57. data/vendor/spidermonkey/config/SunOS5.8.mk +44 -0
  58. data/vendor/spidermonkey/config/SunOS5.9.mk +44 -0
  59. data/vendor/spidermonkey/config/WINNT4.0.mk +117 -0
  60. data/vendor/spidermonkey/config/WINNT5.0.mk +117 -0
  61. data/vendor/spidermonkey/config/WINNT5.1.mk +117 -0
  62. data/vendor/spidermonkey/config/WINNT5.2.mk +117 -0
  63. data/vendor/spidermonkey/config/WINNT6.0.mk +117 -0
  64. data/vendor/spidermonkey/config/dgux.mk +64 -0
  65. data/vendor/spidermonkey/config.mk +192 -0
  66. data/vendor/spidermonkey/editline/Makefile.ref +144 -0
  67. data/vendor/spidermonkey/editline/README +83 -0
  68. data/vendor/spidermonkey/editline/editline.3 +175 -0
  69. data/vendor/spidermonkey/editline/editline.c +1369 -0
  70. data/vendor/spidermonkey/editline/editline.h +135 -0
  71. data/vendor/spidermonkey/editline/sysunix.c +182 -0
  72. data/vendor/spidermonkey/editline/unix.h +82 -0
  73. data/vendor/spidermonkey/fdlibm/.cvsignore +7 -0
  74. data/vendor/spidermonkey/fdlibm/Makefile.in +127 -0
  75. data/vendor/spidermonkey/fdlibm/Makefile.ref +192 -0
  76. data/vendor/spidermonkey/fdlibm/e_acos.c +147 -0
  77. data/vendor/spidermonkey/fdlibm/e_acosh.c +105 -0
  78. data/vendor/spidermonkey/fdlibm/e_asin.c +156 -0
  79. data/vendor/spidermonkey/fdlibm/e_atan2.c +165 -0
  80. data/vendor/spidermonkey/fdlibm/e_atanh.c +110 -0
  81. data/vendor/spidermonkey/fdlibm/e_cosh.c +133 -0
  82. data/vendor/spidermonkey/fdlibm/e_exp.c +202 -0
  83. data/vendor/spidermonkey/fdlibm/e_fmod.c +184 -0
  84. data/vendor/spidermonkey/fdlibm/e_gamma.c +71 -0
  85. data/vendor/spidermonkey/fdlibm/e_gamma_r.c +70 -0
  86. data/vendor/spidermonkey/fdlibm/e_hypot.c +173 -0
  87. data/vendor/spidermonkey/fdlibm/e_j0.c +524 -0
  88. data/vendor/spidermonkey/fdlibm/e_j1.c +523 -0
  89. data/vendor/spidermonkey/fdlibm/e_jn.c +315 -0
  90. data/vendor/spidermonkey/fdlibm/e_lgamma.c +71 -0
  91. data/vendor/spidermonkey/fdlibm/e_lgamma_r.c +347 -0
  92. data/vendor/spidermonkey/fdlibm/e_log.c +184 -0
  93. data/vendor/spidermonkey/fdlibm/e_log10.c +134 -0
  94. data/vendor/spidermonkey/fdlibm/e_pow.c +386 -0
  95. data/vendor/spidermonkey/fdlibm/e_rem_pio2.c +222 -0
  96. data/vendor/spidermonkey/fdlibm/e_remainder.c +120 -0
  97. data/vendor/spidermonkey/fdlibm/e_scalb.c +89 -0
  98. data/vendor/spidermonkey/fdlibm/e_sinh.c +122 -0
  99. data/vendor/spidermonkey/fdlibm/e_sqrt.c +497 -0
  100. data/vendor/spidermonkey/fdlibm/fdlibm.h +273 -0
  101. data/vendor/spidermonkey/fdlibm/fdlibm.mak +1453 -0
  102. data/vendor/spidermonkey/fdlibm/fdlibm.mdp +0 -0
  103. data/vendor/spidermonkey/fdlibm/k_cos.c +135 -0
  104. data/vendor/spidermonkey/fdlibm/k_rem_pio2.c +354 -0
  105. data/vendor/spidermonkey/fdlibm/k_sin.c +114 -0
  106. data/vendor/spidermonkey/fdlibm/k_standard.c +785 -0
  107. data/vendor/spidermonkey/fdlibm/k_tan.c +170 -0
  108. data/vendor/spidermonkey/fdlibm/s_asinh.c +101 -0
  109. data/vendor/spidermonkey/fdlibm/s_atan.c +175 -0
  110. data/vendor/spidermonkey/fdlibm/s_cbrt.c +133 -0
  111. data/vendor/spidermonkey/fdlibm/s_ceil.c +120 -0
  112. data/vendor/spidermonkey/fdlibm/s_copysign.c +72 -0
  113. data/vendor/spidermonkey/fdlibm/s_cos.c +118 -0
  114. data/vendor/spidermonkey/fdlibm/s_erf.c +356 -0
  115. data/vendor/spidermonkey/fdlibm/s_expm1.c +267 -0
  116. data/vendor/spidermonkey/fdlibm/s_fabs.c +70 -0
  117. data/vendor/spidermonkey/fdlibm/s_finite.c +71 -0
  118. data/vendor/spidermonkey/fdlibm/s_floor.c +121 -0
  119. data/vendor/spidermonkey/fdlibm/s_frexp.c +99 -0
  120. data/vendor/spidermonkey/fdlibm/s_ilogb.c +85 -0
  121. data/vendor/spidermonkey/fdlibm/s_isnan.c +74 -0
  122. data/vendor/spidermonkey/fdlibm/s_ldexp.c +66 -0
  123. data/vendor/spidermonkey/fdlibm/s_lib_version.c +73 -0
  124. data/vendor/spidermonkey/fdlibm/s_log1p.c +211 -0
  125. data/vendor/spidermonkey/fdlibm/s_logb.c +79 -0
  126. data/vendor/spidermonkey/fdlibm/s_matherr.c +64 -0
  127. data/vendor/spidermonkey/fdlibm/s_modf.c +132 -0
  128. data/vendor/spidermonkey/fdlibm/s_nextafter.c +124 -0
  129. data/vendor/spidermonkey/fdlibm/s_rint.c +131 -0
  130. data/vendor/spidermonkey/fdlibm/s_scalbn.c +107 -0
  131. data/vendor/spidermonkey/fdlibm/s_signgam.c +40 -0
  132. data/vendor/spidermonkey/fdlibm/s_significand.c +68 -0
  133. data/vendor/spidermonkey/fdlibm/s_sin.c +118 -0
  134. data/vendor/spidermonkey/fdlibm/s_tan.c +112 -0
  135. data/vendor/spidermonkey/fdlibm/s_tanh.c +122 -0
  136. data/vendor/spidermonkey/fdlibm/w_acos.c +78 -0
  137. data/vendor/spidermonkey/fdlibm/w_acosh.c +78 -0
  138. data/vendor/spidermonkey/fdlibm/w_asin.c +80 -0
  139. data/vendor/spidermonkey/fdlibm/w_atan2.c +79 -0
  140. data/vendor/spidermonkey/fdlibm/w_atanh.c +81 -0
  141. data/vendor/spidermonkey/fdlibm/w_cosh.c +77 -0
  142. data/vendor/spidermonkey/fdlibm/w_exp.c +88 -0
  143. data/vendor/spidermonkey/fdlibm/w_fmod.c +78 -0
  144. data/vendor/spidermonkey/fdlibm/w_gamma.c +85 -0
  145. data/vendor/spidermonkey/fdlibm/w_gamma_r.c +81 -0
  146. data/vendor/spidermonkey/fdlibm/w_hypot.c +78 -0
  147. data/vendor/spidermonkey/fdlibm/w_j0.c +105 -0
  148. data/vendor/spidermonkey/fdlibm/w_j1.c +106 -0
  149. data/vendor/spidermonkey/fdlibm/w_jn.c +128 -0
  150. data/vendor/spidermonkey/fdlibm/w_lgamma.c +85 -0
  151. data/vendor/spidermonkey/fdlibm/w_lgamma_r.c +81 -0
  152. data/vendor/spidermonkey/fdlibm/w_log.c +78 -0
  153. data/vendor/spidermonkey/fdlibm/w_log10.c +81 -0
  154. data/vendor/spidermonkey/fdlibm/w_pow.c +99 -0
  155. data/vendor/spidermonkey/fdlibm/w_remainder.c +77 -0
  156. data/vendor/spidermonkey/fdlibm/w_scalb.c +95 -0
  157. data/vendor/spidermonkey/fdlibm/w_sinh.c +77 -0
  158. data/vendor/spidermonkey/fdlibm/w_sqrt.c +77 -0
  159. data/vendor/spidermonkey/javascript-trace.d +73 -0
  160. data/vendor/spidermonkey/js.c +3951 -0
  161. data/vendor/spidermonkey/js.mak +4438 -0
  162. data/vendor/spidermonkey/js.mdp +0 -0
  163. data/vendor/spidermonkey/js.msg +307 -0
  164. data/vendor/spidermonkey/js.pkg +2 -0
  165. data/vendor/spidermonkey/js3240.rc +79 -0
  166. data/vendor/spidermonkey/jsOS240.def +654 -0
  167. data/vendor/spidermonkey/jsapi.c +5836 -0
  168. data/vendor/spidermonkey/jsapi.h +2624 -0
  169. data/vendor/spidermonkey/jsarena.c +450 -0
  170. data/vendor/spidermonkey/jsarena.h +318 -0
  171. data/vendor/spidermonkey/jsarray.c +2988 -0
  172. data/vendor/spidermonkey/jsarray.h +124 -0
  173. data/vendor/spidermonkey/jsatom.c +1045 -0
  174. data/vendor/spidermonkey/jsatom.h +442 -0
  175. data/vendor/spidermonkey/jsbit.h +253 -0
  176. data/vendor/spidermonkey/jsbool.c +176 -0
  177. data/vendor/spidermonkey/jsbool.h +73 -0
  178. data/vendor/spidermonkey/jsclist.h +139 -0
  179. data/vendor/spidermonkey/jscntxt.c +1348 -0
  180. data/vendor/spidermonkey/jscntxt.h +1120 -0
  181. data/vendor/spidermonkey/jscompat.h +57 -0
  182. data/vendor/spidermonkey/jsconfig.h +248 -0
  183. data/vendor/spidermonkey/jsconfig.mk +181 -0
  184. data/vendor/spidermonkey/jscpucfg.c +383 -0
  185. data/vendor/spidermonkey/jscpucfg.h +212 -0
  186. data/vendor/spidermonkey/jsdate.c +2398 -0
  187. data/vendor/spidermonkey/jsdate.h +124 -0
  188. data/vendor/spidermonkey/jsdbgapi.c +1799 -0
  189. data/vendor/spidermonkey/jsdbgapi.h +464 -0
  190. data/vendor/spidermonkey/jsdhash.c +868 -0
  191. data/vendor/spidermonkey/jsdhash.h +592 -0
  192. data/vendor/spidermonkey/jsdtoa.c +3167 -0
  193. data/vendor/spidermonkey/jsdtoa.h +130 -0
  194. data/vendor/spidermonkey/jsdtracef.c +317 -0
  195. data/vendor/spidermonkey/jsdtracef.h +77 -0
  196. data/vendor/spidermonkey/jsemit.c +6909 -0
  197. data/vendor/spidermonkey/jsemit.h +741 -0
  198. data/vendor/spidermonkey/jsexn.c +1371 -0
  199. data/vendor/spidermonkey/jsexn.h +96 -0
  200. data/vendor/spidermonkey/jsfile.c +2736 -0
  201. data/vendor/spidermonkey/jsfile.h +56 -0
  202. data/vendor/spidermonkey/jsfile.msg +90 -0
  203. data/vendor/spidermonkey/jsfun.c +2634 -0
  204. data/vendor/spidermonkey/jsfun.h +254 -0
  205. data/vendor/spidermonkey/jsgc.c +3554 -0
  206. data/vendor/spidermonkey/jsgc.h +403 -0
  207. data/vendor/spidermonkey/jshash.c +476 -0
  208. data/vendor/spidermonkey/jshash.h +151 -0
  209. data/vendor/spidermonkey/jsify.pl +485 -0
  210. data/vendor/spidermonkey/jsinterp.c +6981 -0
  211. data/vendor/spidermonkey/jsinterp.h +521 -0
  212. data/vendor/spidermonkey/jsinvoke.c +43 -0
  213. data/vendor/spidermonkey/jsiter.c +1067 -0
  214. data/vendor/spidermonkey/jsiter.h +122 -0
  215. data/vendor/spidermonkey/jskeyword.tbl +124 -0
  216. data/vendor/spidermonkey/jskwgen.c +460 -0
  217. data/vendor/spidermonkey/jslibmath.h +266 -0
  218. data/vendor/spidermonkey/jslock.c +1309 -0
  219. data/vendor/spidermonkey/jslock.h +313 -0
  220. data/vendor/spidermonkey/jslocko.asm +60 -0
  221. data/vendor/spidermonkey/jslog2.c +94 -0
  222. data/vendor/spidermonkey/jslong.c +264 -0
  223. data/vendor/spidermonkey/jslong.h +412 -0
  224. data/vendor/spidermonkey/jsmath.c +568 -0
  225. data/vendor/spidermonkey/jsmath.h +57 -0
  226. data/vendor/spidermonkey/jsnum.c +1228 -0
  227. data/vendor/spidermonkey/jsnum.h +283 -0
  228. data/vendor/spidermonkey/jsobj.c +5266 -0
  229. data/vendor/spidermonkey/jsobj.h +709 -0
  230. data/vendor/spidermonkey/jsopcode.c +5245 -0
  231. data/vendor/spidermonkey/jsopcode.h +394 -0
  232. data/vendor/spidermonkey/jsopcode.tbl +523 -0
  233. data/vendor/spidermonkey/jsotypes.h +202 -0
  234. data/vendor/spidermonkey/jsparse.c +6680 -0
  235. data/vendor/spidermonkey/jsparse.h +511 -0
  236. data/vendor/spidermonkey/jsprf.c +1262 -0
  237. data/vendor/spidermonkey/jsprf.h +150 -0
  238. data/vendor/spidermonkey/jsproto.tbl +128 -0
  239. data/vendor/spidermonkey/jsprvtd.h +267 -0
  240. data/vendor/spidermonkey/jspubtd.h +744 -0
  241. data/vendor/spidermonkey/jsregexp.c +4352 -0
  242. data/vendor/spidermonkey/jsregexp.h +183 -0
  243. data/vendor/spidermonkey/jsreops.tbl +145 -0
  244. data/vendor/spidermonkey/jsscan.c +2003 -0
  245. data/vendor/spidermonkey/jsscan.h +387 -0
  246. data/vendor/spidermonkey/jsscope.c +1948 -0
  247. data/vendor/spidermonkey/jsscope.h +418 -0
  248. data/vendor/spidermonkey/jsscript.c +1832 -0
  249. data/vendor/spidermonkey/jsscript.h +287 -0
  250. data/vendor/spidermonkey/jsshell.msg +50 -0
  251. data/vendor/spidermonkey/jsstddef.h +83 -0
  252. data/vendor/spidermonkey/jsstr.c +5004 -0
  253. data/vendor/spidermonkey/jsstr.h +641 -0
  254. data/vendor/spidermonkey/jstypes.h +475 -0
  255. data/vendor/spidermonkey/jsutil.c +345 -0
  256. data/vendor/spidermonkey/jsutil.h +157 -0
  257. data/vendor/spidermonkey/jsxdrapi.c +800 -0
  258. data/vendor/spidermonkey/jsxdrapi.h +218 -0
  259. data/vendor/spidermonkey/jsxml.c +8471 -0
  260. data/vendor/spidermonkey/jsxml.h +349 -0
  261. data/vendor/spidermonkey/lock_SunOS.s +119 -0
  262. data/vendor/spidermonkey/perfect.js +39 -0
  263. data/vendor/spidermonkey/plify_jsdhash.sed +36 -0
  264. data/vendor/spidermonkey/prmjtime.c +846 -0
  265. data/vendor/spidermonkey/prmjtime.h +103 -0
  266. data/vendor/spidermonkey/resource.h +15 -0
  267. data/vendor/spidermonkey/rules.mk +197 -0
  268. data/vendor/spidermonkey/win32.order +384 -0
  269. metadata +4 -3
@@ -0,0 +1,403 @@
1
+ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
+ *
3
+ * ***** BEGIN LICENSE BLOCK *****
4
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
+ *
6
+ * The contents of this file are subject to the Mozilla Public License Version
7
+ * 1.1 (the "License"); you may not use this file except in compliance with
8
+ * the License. You may obtain a copy of the License at
9
+ * http://www.mozilla.org/MPL/
10
+ *
11
+ * Software distributed under the License is distributed on an "AS IS" basis,
12
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
+ * for the specific language governing rights and limitations under the
14
+ * License.
15
+ *
16
+ * The Original Code is Mozilla Communicator client code, released
17
+ * March 31, 1998.
18
+ *
19
+ * The Initial Developer of the Original Code is
20
+ * Netscape Communications Corporation.
21
+ * Portions created by the Initial Developer are Copyright (C) 1998
22
+ * the Initial Developer. All Rights Reserved.
23
+ *
24
+ * Contributor(s):
25
+ *
26
+ * Alternatively, the contents of this file may be used under the terms of
27
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
28
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29
+ * in which case the provisions of the GPL or the LGPL are applicable instead
30
+ * of those above. If you wish to allow use of your version of this file only
31
+ * under the terms of either the GPL or the LGPL, and not to allow others to
32
+ * use your version of this file under the terms of the MPL, indicate your
33
+ * decision by deleting the provisions above and replace them with the notice
34
+ * and other provisions required by the GPL or the LGPL. If you do not delete
35
+ * the provisions above, a recipient may use your version of this file under
36
+ * the terms of any one of the MPL, the GPL or the LGPL.
37
+ *
38
+ * ***** END LICENSE BLOCK ***** */
39
+
40
+ #ifndef jsgc_h___
41
+ #define jsgc_h___
42
+ /*
43
+ * JS Garbage Collector.
44
+ */
45
+ #include "jsprvtd.h"
46
+ #include "jspubtd.h"
47
+ #include "jsdhash.h"
48
+ #include "jsbit.h"
49
+ #include "jsutil.h"
50
+
51
+ JS_BEGIN_EXTERN_C
52
+
53
+ JS_STATIC_ASSERT(JSTRACE_STRING == 2);
54
+
55
+ #define JSTRACE_NAMESPACE 3
56
+ #define JSTRACE_QNAME 4
57
+ #define JSTRACE_XML 5
58
+
59
+ /*
60
+ * One past the maximum trace kind.
61
+ */
62
+ #define JSTRACE_LIMIT 6
63
+
64
+ /*
65
+ * We use the trace kinds as the types for all GC things except external
66
+ * strings.
67
+ */
68
+ #define GCX_OBJECT JSTRACE_OBJECT /* JSObject */
69
+ #define GCX_DOUBLE JSTRACE_DOUBLE /* jsdouble */
70
+ #define GCX_STRING JSTRACE_STRING /* JSString */
71
+ #define GCX_NAMESPACE JSTRACE_NAMESPACE /* JSXMLNamespace */
72
+ #define GCX_QNAME JSTRACE_QNAME /* JSXMLQName */
73
+ #define GCX_XML JSTRACE_XML /* JSXML */
74
+ #define GCX_EXTERNAL_STRING JSTRACE_LIMIT /* JSString with external
75
+ chars */
76
+ /*
77
+ * The number of defined GC types.
78
+ */
79
+ #define GCX_NTYPES (GCX_EXTERNAL_STRING + 8)
80
+
81
+ /*
82
+ * The maximum limit for the number of GC types.
83
+ */
84
+ #define GCX_LIMIT_LOG2 4 /* type index bits */
85
+ #define GCX_LIMIT JS_BIT(GCX_LIMIT_LOG2)
86
+
87
+ JS_STATIC_ASSERT(GCX_NTYPES <= GCX_LIMIT);
88
+
89
+ /* GC flag definitions, must fit in 8 bits (type index goes in the low bits). */
90
+ #define GCF_TYPEMASK JS_BITMASK(GCX_LIMIT_LOG2)
91
+ #define GCF_MARK JS_BIT(GCX_LIMIT_LOG2)
92
+ #define GCF_FINAL JS_BIT(GCX_LIMIT_LOG2 + 1)
93
+ #define GCF_LOCKSHIFT (GCX_LIMIT_LOG2 + 2) /* lock bit shift */
94
+ #define GCF_LOCK JS_BIT(GCF_LOCKSHIFT) /* lock request bit in API */
95
+
96
+ /*
97
+ * Get the type of the external string or -1 if the string was not created
98
+ * with JS_NewExternalString.
99
+ */
100
+ extern intN
101
+ js_GetExternalStringGCType(JSString *str);
102
+
103
+ extern JS_FRIEND_API(uint32)
104
+ js_GetGCThingTraceKind(void *thing);
105
+
106
+ /*
107
+ * The sole purpose of the function is to preserve public API compatibility
108
+ * in JS_GetStringBytes which takes only single JSString* argument.
109
+ */
110
+ JSRuntime*
111
+ js_GetGCStringRuntime(JSString *str);
112
+
113
+ #if 1
114
+ /*
115
+ * Since we're forcing a GC from JS_GC anyway, don't bother wasting cycles
116
+ * loading oldval. XXX remove implied force, fix jsinterp.c's "second arg
117
+ * ignored", etc.
118
+ */
119
+ #define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JS_TRUE)
120
+ #else
121
+ #define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JSVAL_IS_GCTHING(oldval))
122
+ #endif
123
+
124
+ /*
125
+ * Write barrier macro monitoring property update from oldval to newval in
126
+ * scope->object.
127
+ *
128
+ * Since oldval is used only for the branded scope case, and the oldval actual
129
+ * argument expression is typically not used otherwise by callers, performance
130
+ * benefits if oldval is *not* evaluated into a callsite temporary variable,
131
+ * and instead passed to GC_WRITE_BARRIER for conditional evaluation (we rely
132
+ * on modern compilers to do a good CSE job). Yay, C macros.
133
+ */
134
+ #define GC_WRITE_BARRIER(cx,scope,oldval,newval) \
135
+ JS_BEGIN_MACRO \
136
+ if (SCOPE_IS_BRANDED(scope) && \
137
+ (oldval) != (newval) && \
138
+ (VALUE_IS_FUNCTION(cx,oldval) || VALUE_IS_FUNCTION(cx,newval))) { \
139
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope); \
140
+ } \
141
+ GC_POKE(cx, oldval); \
142
+ JS_END_MACRO
143
+
144
+ extern JSBool
145
+ js_InitGC(JSRuntime *rt, uint32 maxbytes);
146
+
147
+ extern void
148
+ js_FinishGC(JSRuntime *rt);
149
+
150
+ extern intN
151
+ js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
152
+ JSStringFinalizeOp newop);
153
+
154
+ extern JSBool
155
+ js_AddRoot(JSContext *cx, void *rp, const char *name);
156
+
157
+ extern JSBool
158
+ js_AddRootRT(JSRuntime *rt, void *rp, const char *name);
159
+
160
+ extern JSBool
161
+ js_RemoveRoot(JSRuntime *rt, void *rp);
162
+
163
+ #ifdef DEBUG
164
+ extern void
165
+ js_DumpNamedRoots(JSRuntime *rt,
166
+ void (*dump)(const char *name, void *rp, void *data),
167
+ void *data);
168
+ #endif
169
+
170
+ extern uint32
171
+ js_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data);
172
+
173
+ /* Table of pointers with count valid members. */
174
+ typedef struct JSPtrTable {
175
+ size_t count;
176
+ void **array;
177
+ } JSPtrTable;
178
+
179
+ extern JSBool
180
+ js_RegisterCloseableIterator(JSContext *cx, JSObject *obj);
181
+
182
+ /*
183
+ * The private JSGCThing struct, which describes a gcFreeList element.
184
+ */
185
+ struct JSGCThing {
186
+ JSGCThing *next;
187
+ uint8 *flagp;
188
+ };
189
+
190
+ #define GC_NBYTES_MAX (10 * sizeof(JSGCThing))
191
+ #define GC_NUM_FREELISTS (GC_NBYTES_MAX / sizeof(JSGCThing))
192
+ #define GC_FREELIST_NBYTES(i) (((i) + 1) * sizeof(JSGCThing))
193
+ #define GC_FREELIST_INDEX(n) (((n) / sizeof(JSGCThing)) - 1)
194
+
195
+ /*
196
+ * Allocates a new GC thing of the given size. After a successful allocation
197
+ * the caller must fully initialize the thing before calling any function that
198
+ * can potentially trigger GC. This will ensure that GC tracing never sees junk
199
+ * values stored in the partially initialized thing.
200
+ */
201
+ extern void *
202
+ js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes);
203
+
204
+ /*
205
+ * Allocate a new double jsval and store the result in *vp. vp must be a root.
206
+ * The function does not copy the result into any weak root.
207
+ */
208
+ extern JSBool
209
+ js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp);
210
+
211
+ /*
212
+ * Return a pointer to a new GC-allocated and weakly-rooted jsdouble number,
213
+ * or null when the allocation fails.
214
+ */
215
+ extern jsdouble *
216
+ js_NewWeaklyRootedDouble(JSContext *cx, jsdouble d);
217
+
218
+ extern JSBool
219
+ js_LockGCThingRT(JSRuntime *rt, void *thing);
220
+
221
+ extern JSBool
222
+ js_UnlockGCThingRT(JSRuntime *rt, void *thing);
223
+
224
+ extern JSBool
225
+ js_IsAboutToBeFinalized(JSContext *cx, void *thing);
226
+
227
+ /*
228
+ * Macro to test if a traversal is the marking phase of GC to avoid exposing
229
+ * ScriptFilenameEntry to traversal implementations.
230
+ */
231
+ #define IS_GC_MARKING_TRACER(trc) ((trc)->callback == NULL)
232
+
233
+ #if JS_HAS_XML_SUPPORT
234
+ # define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_XML)
235
+ #else
236
+ # define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_STRING)
237
+ #endif
238
+
239
+ /*
240
+ * JS_IS_VALID_TRACE_KIND assumes that JSTRACE_STRING is the last non-xml
241
+ * trace kind when JS_HAS_XML_SUPPORT is false.
242
+ */
243
+ JS_STATIC_ASSERT(JSTRACE_STRING + 1 == JSTRACE_NAMESPACE);
244
+
245
+ /*
246
+ * Trace jsval when JSVAL_IS_OBJECT(v) can be an arbitrary GC thing casted as
247
+ * JSVAL_OBJECT and js_GetGCThingTraceKind has to be used to find the real
248
+ * type behind v.
249
+ */
250
+ extern void
251
+ js_CallValueTracerIfGCThing(JSTracer *trc, jsval v);
252
+
253
+ extern void
254
+ js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp);
255
+
256
+ extern void
257
+ js_TraceRuntime(JSTracer *trc, JSBool allAtoms);
258
+
259
+ extern JS_FRIEND_API(void)
260
+ js_TraceContext(JSTracer *trc, JSContext *acx);
261
+
262
+ /*
263
+ * Kinds of js_GC invocation.
264
+ */
265
+ typedef enum JSGCInvocationKind {
266
+ /* Normal invocation. */
267
+ GC_NORMAL = 0,
268
+
269
+ /*
270
+ * Called from js_DestroyContext for last JSContext in a JSRuntime, when
271
+ * it is imperative that rt->gcPoke gets cleared early in js_GC.
272
+ */
273
+ GC_LAST_CONTEXT = 1,
274
+
275
+ /*
276
+ * Flag bit telling js_GC that the caller has already acquired rt->gcLock.
277
+ * Currently, this flag is set for the invocation kinds that also preserve
278
+ * atoms and weak roots, so we don't need another bit for GC_KEEP_ATOMS.
279
+ */
280
+ GC_LOCK_HELD = 0x10,
281
+ GC_KEEP_ATOMS = GC_LOCK_HELD,
282
+
283
+ /*
284
+ * Called from js_SetProtoOrParent with a request to set an object's proto
285
+ * or parent slot inserted on rt->setSlotRequests.
286
+ */
287
+ GC_SET_SLOT_REQUEST = GC_LOCK_HELD | 1,
288
+
289
+ /*
290
+ * Called from js_NewGCThing as a last-ditch GC attempt. See comments
291
+ * in jsgc.c just before js_GC's definition for details.
292
+ */
293
+ GC_LAST_DITCH = GC_LOCK_HELD | 2
294
+ } JSGCInvocationKind;
295
+
296
+ extern void
297
+ js_GC(JSContext *cx, JSGCInvocationKind gckind);
298
+
299
+ /* Call this after succesful malloc of memory for GC-related things. */
300
+ extern void
301
+ js_UpdateMallocCounter(JSContext *cx, size_t nbytes);
302
+
303
+ typedef struct JSGCArenaInfo JSGCArenaInfo;
304
+ typedef struct JSGCArenaList JSGCArenaList;
305
+ typedef struct JSGCChunkInfo JSGCChunkInfo;
306
+
307
+ struct JSGCArenaList {
308
+ JSGCArenaInfo *last; /* last allocated GC arena */
309
+ uint16 lastCount; /* number of allocated things in the last
310
+ arena */
311
+ uint16 thingSize; /* size of things to allocate on this list
312
+ */
313
+ JSGCThing *freeList; /* list of free GC things */
314
+ };
315
+
316
+ typedef union JSGCDoubleCell JSGCDoubleCell;
317
+
318
+ union JSGCDoubleCell {
319
+ double number;
320
+ JSGCDoubleCell *link;
321
+ };
322
+
323
+ JS_STATIC_ASSERT(sizeof(JSGCDoubleCell) == sizeof(double));
324
+
325
+ typedef struct JSGCDoubleArenaList {
326
+ JSGCArenaInfo *first; /* first allocated GC arena */
327
+ jsbitmap *nextDoubleFlags; /* bitmask with flags to check for free
328
+ things */
329
+ } JSGCDoubleArenaList;
330
+
331
+ struct JSWeakRoots {
332
+ /* Most recently created things by type, members of the GC's root set. */
333
+ void *newborn[GCX_NTYPES];
334
+
335
+ /* Atom root for the last-looked-up atom on this context. */
336
+ jsval lastAtom;
337
+
338
+ /* Root for the result of the most recent js_InternalInvoke call. */
339
+ jsval lastInternalResult;
340
+ };
341
+
342
+ JS_STATIC_ASSERT(JSVAL_NULL == 0);
343
+ #define JS_CLEAR_WEAK_ROOTS(wr) (memset((wr), 0, sizeof(JSWeakRoots)))
344
+
345
+ #ifdef DEBUG_notme
346
+ #define JS_GCMETER 1
347
+ #endif
348
+
349
+ #ifdef JS_GCMETER
350
+
351
+ typedef struct JSGCArenaStats {
352
+ uint32 alloc; /* allocation attempts */
353
+ uint32 localalloc; /* allocations from local lists */
354
+ uint32 retry; /* allocation retries after running the GC */
355
+ uint32 fail; /* allocation failures */
356
+ uint32 nthings; /* live GC things */
357
+ uint32 maxthings; /* maximum of live GC cells */
358
+ double totalthings; /* live GC things the GC scanned so far */
359
+ uint32 narenas; /* number of arena in list before the GC */
360
+ uint32 newarenas; /* new arenas allocated before the last GC */
361
+ uint32 livearenas; /* number of live arenas after the last GC */
362
+ uint32 maxarenas; /* maximum of allocated arenas */
363
+ uint32 totalarenas; /* total number of arenas with live things that
364
+ GC scanned so far */
365
+ } JSGCArenaStats;
366
+
367
+ typedef struct JSGCStats {
368
+ uint32 finalfail; /* finalizer calls allocator failures */
369
+ uint32 lockborn; /* things born locked */
370
+ uint32 lock; /* valid lock calls */
371
+ uint32 unlock; /* valid unlock calls */
372
+ uint32 depth; /* mark tail recursion depth */
373
+ uint32 maxdepth; /* maximum mark tail recursion depth */
374
+ uint32 cdepth; /* mark recursion depth of C functions */
375
+ uint32 maxcdepth; /* maximum mark recursion depth of C functions */
376
+ uint32 untraced; /* number of times tracing of GC thing's children were
377
+ delayed due to a low C stack */
378
+ #ifdef DEBUG
379
+ uint32 maxuntraced;/* maximum number of things with children to trace
380
+ later */
381
+ #endif
382
+ uint32 maxlevel; /* maximum GC nesting (indirect recursion) level */
383
+ uint32 poke; /* number of potentially useful GC calls */
384
+ uint32 afree; /* thing arenas freed so far */
385
+ uint32 stackseg; /* total extraordinary stack segments scanned */
386
+ uint32 segslots; /* total stack segment jsval slots scanned */
387
+ uint32 nclose; /* number of objects with close hooks */
388
+ uint32 maxnclose; /* max number of objects with close hooks */
389
+ uint32 closelater; /* number of close hooks scheduled to run */
390
+ uint32 maxcloselater; /* max number of close hooks scheduled to run */
391
+
392
+ JSGCArenaStats arenaStats[GC_NUM_FREELISTS];
393
+ JSGCArenaStats doubleArenaStats;
394
+ } JSGCStats;
395
+
396
+ extern JS_FRIEND_API(void)
397
+ js_DumpGCStats(JSRuntime *rt, FILE *fp);
398
+
399
+ #endif /* JS_GCMETER */
400
+
401
+ JS_END_EXTERN_C
402
+
403
+ #endif /* jsgc_h___ */
@@ -0,0 +1,476 @@
1
+ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
+ *
3
+ * ***** BEGIN LICENSE BLOCK *****
4
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
+ *
6
+ * The contents of this file are subject to the Mozilla Public License Version
7
+ * 1.1 (the "License"); you may not use this file except in compliance with
8
+ * the License. You may obtain a copy of the License at
9
+ * http://www.mozilla.org/MPL/
10
+ *
11
+ * Software distributed under the License is distributed on an "AS IS" basis,
12
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
+ * for the specific language governing rights and limitations under the
14
+ * License.
15
+ *
16
+ * The Original Code is Mozilla Communicator client code, released
17
+ * March 31, 1998.
18
+ *
19
+ * The Initial Developer of the Original Code is
20
+ * Netscape Communications Corporation.
21
+ * Portions created by the Initial Developer are Copyright (C) 1998
22
+ * the Initial Developer. All Rights Reserved.
23
+ *
24
+ * Contributor(s):
25
+ *
26
+ * Alternatively, the contents of this file may be used under the terms of
27
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
28
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29
+ * in which case the provisions of the GPL or the LGPL are applicable instead
30
+ * of those above. If you wish to allow use of your version of this file only
31
+ * under the terms of either the GPL or the LGPL, and not to allow others to
32
+ * use your version of this file under the terms of the MPL, indicate your
33
+ * decision by deleting the provisions above and replace them with the notice
34
+ * and other provisions required by the GPL or the LGPL. If you do not delete
35
+ * the provisions above, a recipient may use your version of this file under
36
+ * the terms of any one of the MPL, the GPL or the LGPL.
37
+ *
38
+ * ***** END LICENSE BLOCK ***** */
39
+
40
+ /*
41
+ * PR hash table package.
42
+ */
43
+ #include "jsstddef.h"
44
+ #include <stdlib.h>
45
+ #include <string.h>
46
+ #include "jstypes.h"
47
+ #include "jsbit.h"
48
+ #include "jsutil.h" /* Added by JSIFY */
49
+ #include "jshash.h" /* Added by JSIFY */
50
+
51
+ /* Compute the number of buckets in ht */
52
+ #define NBUCKETS(ht) JS_BIT(JS_HASH_BITS - (ht)->shift)
53
+
54
+ /* The smallest table has 16 buckets */
55
+ #define MINBUCKETSLOG2 4
56
+ #define MINBUCKETS JS_BIT(MINBUCKETSLOG2)
57
+
58
+ /* Compute the maximum entries given n buckets that we will tolerate, ~90% */
59
+ #define OVERLOADED(n) ((n) - ((n) >> 3))
60
+
61
+ /* Compute the number of entries below which we shrink the table by half */
62
+ #define UNDERLOADED(n) (((n) > MINBUCKETS) ? ((n) >> 2) : 0)
63
+
64
+ /*
65
+ ** Stubs for default hash allocator ops.
66
+ */
67
+ static void *
68
+ DefaultAllocTable(void *pool, size_t size)
69
+ {
70
+ return malloc(size);
71
+ }
72
+
73
+ static void
74
+ DefaultFreeTable(void *pool, void *item)
75
+ {
76
+ free(item);
77
+ }
78
+
79
+ static JSHashEntry *
80
+ DefaultAllocEntry(void *pool, const void *key)
81
+ {
82
+ return (JSHashEntry*) malloc(sizeof(JSHashEntry));
83
+ }
84
+
85
+ static void
86
+ DefaultFreeEntry(void *pool, JSHashEntry *he, uintN flag)
87
+ {
88
+ if (flag == HT_FREE_ENTRY)
89
+ free(he);
90
+ }
91
+
92
+ static JSHashAllocOps defaultHashAllocOps = {
93
+ DefaultAllocTable, DefaultFreeTable,
94
+ DefaultAllocEntry, DefaultFreeEntry
95
+ };
96
+
97
+ JS_PUBLIC_API(JSHashTable *)
98
+ JS_NewHashTable(uint32 n, JSHashFunction keyHash,
99
+ JSHashComparator keyCompare, JSHashComparator valueCompare,
100
+ JSHashAllocOps *allocOps, void *allocPriv)
101
+ {
102
+ JSHashTable *ht;
103
+ size_t nb;
104
+
105
+ if (n <= MINBUCKETS) {
106
+ n = MINBUCKETSLOG2;
107
+ } else {
108
+ n = JS_CeilingLog2(n);
109
+ if ((int32)n < 0)
110
+ return NULL;
111
+ }
112
+
113
+ if (!allocOps) allocOps = &defaultHashAllocOps;
114
+
115
+ ht = (JSHashTable*) allocOps->allocTable(allocPriv, sizeof *ht);
116
+ if (!ht)
117
+ return NULL;
118
+ memset(ht, 0, sizeof *ht);
119
+ ht->shift = JS_HASH_BITS - n;
120
+ n = JS_BIT(n);
121
+ nb = n * sizeof(JSHashEntry *);
122
+ ht->buckets = (JSHashEntry**) allocOps->allocTable(allocPriv, nb);
123
+ if (!ht->buckets) {
124
+ allocOps->freeTable(allocPriv, ht);
125
+ return NULL;
126
+ }
127
+ memset(ht->buckets, 0, nb);
128
+
129
+ ht->keyHash = keyHash;
130
+ ht->keyCompare = keyCompare;
131
+ ht->valueCompare = valueCompare;
132
+ ht->allocOps = allocOps;
133
+ ht->allocPriv = allocPriv;
134
+ return ht;
135
+ }
136
+
137
+ JS_PUBLIC_API(void)
138
+ JS_HashTableDestroy(JSHashTable *ht)
139
+ {
140
+ uint32 i, n;
141
+ JSHashEntry *he, **hep;
142
+ JSHashAllocOps *allocOps = ht->allocOps;
143
+ void *allocPriv = ht->allocPriv;
144
+
145
+ n = NBUCKETS(ht);
146
+ for (i = 0; i < n; i++) {
147
+ hep = &ht->buckets[i];
148
+ while ((he = *hep) != NULL) {
149
+ *hep = he->next;
150
+ allocOps->freeEntry(allocPriv, he, HT_FREE_ENTRY);
151
+ }
152
+ }
153
+ #ifdef DEBUG
154
+ memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]);
155
+ #endif
156
+ allocOps->freeTable(allocPriv, ht->buckets);
157
+ #ifdef DEBUG
158
+ memset(ht, 0xDB, sizeof *ht);
159
+ #endif
160
+ allocOps->freeTable(allocPriv, ht);
161
+ }
162
+
163
+ /*
164
+ * Multiplicative hash, from Knuth 6.4.
165
+ */
166
+ #define BUCKET_HEAD(ht, keyHash) \
167
+ (&(ht)->buckets[((keyHash) * JS_GOLDEN_RATIO) >> (ht)->shift])
168
+
169
+ JS_PUBLIC_API(JSHashEntry **)
170
+ JS_HashTableRawLookup(JSHashTable *ht, JSHashNumber keyHash, const void *key)
171
+ {
172
+ JSHashEntry *he, **hep, **hep0;
173
+
174
+ #ifdef JS_HASHMETER
175
+ ht->nlookups++;
176
+ #endif
177
+ hep = hep0 = BUCKET_HEAD(ht, keyHash);
178
+ while ((he = *hep) != NULL) {
179
+ if (he->keyHash == keyHash && ht->keyCompare(key, he->key)) {
180
+ /* Move to front of chain if not already there */
181
+ if (hep != hep0) {
182
+ *hep = he->next;
183
+ he->next = *hep0;
184
+ *hep0 = he;
185
+ }
186
+ return hep0;
187
+ }
188
+ hep = &he->next;
189
+ #ifdef JS_HASHMETER
190
+ ht->nsteps++;
191
+ #endif
192
+ }
193
+ return hep;
194
+ }
195
+
196
+ static JSBool
197
+ Resize(JSHashTable *ht, uint32 newshift)
198
+ {
199
+ size_t nb, nentries, i;
200
+ JSHashEntry **oldbuckets, *he, *next, **hep;
201
+ #ifdef DEBUG
202
+ size_t nold = NBUCKETS(ht);
203
+ #endif
204
+
205
+ JS_ASSERT(newshift < JS_HASH_BITS);
206
+
207
+ nb = (size_t)1 << (JS_HASH_BITS - newshift);
208
+
209
+ /* Integer overflow protection. */
210
+ if (nb > (size_t)-1 / sizeof(JSHashEntry*))
211
+ return JS_FALSE;
212
+ nb *= sizeof(JSHashEntry*);
213
+
214
+ oldbuckets = ht->buckets;
215
+ ht->buckets = (JSHashEntry**)ht->allocOps->allocTable(ht->allocPriv, nb);
216
+ if (!ht->buckets) {
217
+ ht->buckets = oldbuckets;
218
+ return JS_FALSE;
219
+ }
220
+ memset(ht->buckets, 0, nb);
221
+
222
+ ht->shift = newshift;
223
+ nentries = ht->nentries;
224
+
225
+ for (i = 0; nentries != 0; i++) {
226
+ for (he = oldbuckets[i]; he; he = next) {
227
+ JS_ASSERT(nentries != 0);
228
+ --nentries;
229
+ next = he->next;
230
+ hep = BUCKET_HEAD(ht, he->keyHash);
231
+
232
+ /*
233
+ * Since he comes from the old table, it must be unique and we
234
+ * simply add it to the head of bucket chain without chain lookup.
235
+ */
236
+ he->next = *hep;
237
+ *hep = he;
238
+ }
239
+ }
240
+ #ifdef DEBUG
241
+ memset(oldbuckets, 0xDB, nold * sizeof oldbuckets[0]);
242
+ #endif
243
+ ht->allocOps->freeTable(ht->allocPriv, oldbuckets);
244
+ return JS_TRUE;
245
+ }
246
+
247
+ JS_PUBLIC_API(JSHashEntry *)
248
+ JS_HashTableRawAdd(JSHashTable *ht, JSHashEntry **hep,
249
+ JSHashNumber keyHash, const void *key, void *value)
250
+ {
251
+ uint32 n;
252
+ JSHashEntry *he;
253
+
254
+ /* Grow the table if it is overloaded */
255
+ n = NBUCKETS(ht);
256
+ if (ht->nentries >= OVERLOADED(n)) {
257
+ if (!Resize(ht, ht->shift - 1))
258
+ return NULL;
259
+ #ifdef JS_HASHMETER
260
+ ht->ngrows++;
261
+ #endif
262
+ hep = JS_HashTableRawLookup(ht, keyHash, key);
263
+ }
264
+
265
+ /* Make a new key value entry */
266
+ he = ht->allocOps->allocEntry(ht->allocPriv, key);
267
+ if (!he)
268
+ return NULL;
269
+ he->keyHash = keyHash;
270
+ he->key = key;
271
+ he->value = value;
272
+ he->next = *hep;
273
+ *hep = he;
274
+ ht->nentries++;
275
+ return he;
276
+ }
277
+
278
+ JS_PUBLIC_API(JSHashEntry *)
279
+ JS_HashTableAdd(JSHashTable *ht, const void *key, void *value)
280
+ {
281
+ JSHashNumber keyHash;
282
+ JSHashEntry *he, **hep;
283
+
284
+ keyHash = ht->keyHash(key);
285
+ hep = JS_HashTableRawLookup(ht, keyHash, key);
286
+ if ((he = *hep) != NULL) {
287
+ /* Hit; see if values match */
288
+ if (ht->valueCompare(he->value, value)) {
289
+ /* key,value pair is already present in table */
290
+ return he;
291
+ }
292
+ if (he->value)
293
+ ht->allocOps->freeEntry(ht->allocPriv, he, HT_FREE_VALUE);
294
+ he->value = value;
295
+ return he;
296
+ }
297
+ return JS_HashTableRawAdd(ht, hep, keyHash, key, value);
298
+ }
299
+
300
+ JS_PUBLIC_API(void)
301
+ JS_HashTableRawRemove(JSHashTable *ht, JSHashEntry **hep, JSHashEntry *he)
302
+ {
303
+ uint32 n;
304
+
305
+ *hep = he->next;
306
+ ht->allocOps->freeEntry(ht->allocPriv, he, HT_FREE_ENTRY);
307
+
308
+ /* Shrink table if it's underloaded */
309
+ n = NBUCKETS(ht);
310
+ if (--ht->nentries < UNDERLOADED(n)) {
311
+ Resize(ht, ht->shift + 1);
312
+ #ifdef JS_HASHMETER
313
+ ht->nshrinks++;
314
+ #endif
315
+ }
316
+ }
317
+
318
+ JS_PUBLIC_API(JSBool)
319
+ JS_HashTableRemove(JSHashTable *ht, const void *key)
320
+ {
321
+ JSHashNumber keyHash;
322
+ JSHashEntry *he, **hep;
323
+
324
+ keyHash = ht->keyHash(key);
325
+ hep = JS_HashTableRawLookup(ht, keyHash, key);
326
+ if ((he = *hep) == NULL)
327
+ return JS_FALSE;
328
+
329
+ /* Hit; remove element */
330
+ JS_HashTableRawRemove(ht, hep, he);
331
+ return JS_TRUE;
332
+ }
333
+
334
+ JS_PUBLIC_API(void *)
335
+ JS_HashTableLookup(JSHashTable *ht, const void *key)
336
+ {
337
+ JSHashNumber keyHash;
338
+ JSHashEntry *he, **hep;
339
+
340
+ keyHash = ht->keyHash(key);
341
+ hep = JS_HashTableRawLookup(ht, keyHash, key);
342
+ if ((he = *hep) != NULL) {
343
+ return he->value;
344
+ }
345
+ return NULL;
346
+ }
347
+
348
+ /*
349
+ ** Iterate over the entries in the hash table calling func for each
350
+ ** entry found. Stop if "f" says to (return value & JS_ENUMERATE_STOP).
351
+ ** Return a count of the number of elements scanned.
352
+ */
353
+ JS_PUBLIC_API(int)
354
+ JS_HashTableEnumerateEntries(JSHashTable *ht, JSHashEnumerator f, void *arg)
355
+ {
356
+ JSHashEntry *he, **hep, **bucket;
357
+ uint32 nlimit, n, nbuckets, newlog2;
358
+ int rv;
359
+
360
+ nlimit = ht->nentries;
361
+ n = 0;
362
+ for (bucket = ht->buckets; n != nlimit; ++bucket) {
363
+ hep = bucket;
364
+ while ((he = *hep) != NULL) {
365
+ JS_ASSERT(n < nlimit);
366
+ rv = f(he, n, arg);
367
+ n++;
368
+ if (rv & HT_ENUMERATE_REMOVE) {
369
+ *hep = he->next;
370
+ ht->allocOps->freeEntry(ht->allocPriv, he, HT_FREE_ENTRY);
371
+ --ht->nentries;
372
+ } else {
373
+ hep = &he->next;
374
+ }
375
+ if (rv & HT_ENUMERATE_STOP) {
376
+ goto out;
377
+ }
378
+ }
379
+ }
380
+
381
+ out:
382
+ /* Shrink table if removal of entries made it underloaded */
383
+ if (ht->nentries != nlimit) {
384
+ JS_ASSERT(ht->nentries < nlimit);
385
+ nbuckets = NBUCKETS(ht);
386
+ if (MINBUCKETS < nbuckets && ht->nentries < UNDERLOADED(nbuckets)) {
387
+ newlog2 = JS_CeilingLog2(ht->nentries);
388
+ if (newlog2 < MINBUCKETSLOG2)
389
+ newlog2 = MINBUCKETSLOG2;
390
+
391
+ /* Check that we really shrink the table. */
392
+ JS_ASSERT(JS_HASH_BITS - ht->shift > newlog2);
393
+ Resize(ht, JS_HASH_BITS - newlog2);
394
+ }
395
+ }
396
+ return (int)n;
397
+ }
398
+
399
+ #ifdef JS_HASHMETER
400
+ #include <stdio.h>
401
+
402
+ JS_PUBLIC_API(void)
403
+ JS_HashTableDumpMeter(JSHashTable *ht, JSHashEnumerator dump, FILE *fp)
404
+ {
405
+ double sqsum, mean, sigma;
406
+ uint32 nchains, nbuckets;
407
+ uint32 i, n, maxChain, maxChainLen;
408
+ JSHashEntry *he;
409
+
410
+ sqsum = 0;
411
+ nchains = 0;
412
+ maxChain = maxChainLen = 0;
413
+ nbuckets = NBUCKETS(ht);
414
+ for (i = 0; i < nbuckets; i++) {
415
+ he = ht->buckets[i];
416
+ if (!he)
417
+ continue;
418
+ nchains++;
419
+ for (n = 0; he; he = he->next)
420
+ n++;
421
+ sqsum += n * n;
422
+ if (n > maxChainLen) {
423
+ maxChainLen = n;
424
+ maxChain = i;
425
+ }
426
+ }
427
+
428
+ mean = JS_MeanAndStdDev(nchains, ht->nentries, sqsum, &sigma);
429
+
430
+ fprintf(fp, "\nHash table statistics:\n");
431
+ fprintf(fp, " number of lookups: %u\n", ht->nlookups);
432
+ fprintf(fp, " number of entries: %u\n", ht->nentries);
433
+ fprintf(fp, " number of grows: %u\n", ht->ngrows);
434
+ fprintf(fp, " number of shrinks: %u\n", ht->nshrinks);
435
+ fprintf(fp, " mean steps per hash: %g\n", (double)ht->nsteps
436
+ / ht->nlookups);
437
+ fprintf(fp, "mean hash chain length: %g\n", mean);
438
+ fprintf(fp, " standard deviation: %g\n", sigma);
439
+ fprintf(fp, " max hash chain length: %u\n", maxChainLen);
440
+ fprintf(fp, " max hash chain: [%u]\n", maxChain);
441
+
442
+ for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++)
443
+ if (dump(he, i, fp) != HT_ENUMERATE_NEXT)
444
+ break;
445
+ }
446
+ #endif /* JS_HASHMETER */
447
+
448
+ JS_PUBLIC_API(int)
449
+ JS_HashTableDump(JSHashTable *ht, JSHashEnumerator dump, FILE *fp)
450
+ {
451
+ int count;
452
+
453
+ count = JS_HashTableEnumerateEntries(ht, dump, fp);
454
+ #ifdef JS_HASHMETER
455
+ JS_HashTableDumpMeter(ht, dump, fp);
456
+ #endif
457
+ return count;
458
+ }
459
+
460
+ JS_PUBLIC_API(JSHashNumber)
461
+ JS_HashString(const void *key)
462
+ {
463
+ JSHashNumber h;
464
+ const unsigned char *s;
465
+
466
+ h = 0;
467
+ for (s = (const unsigned char *)key; *s; s++)
468
+ h = JS_ROTATE_LEFT32(h, 4) ^ *s;
469
+ return h;
470
+ }
471
+
472
+ JS_PUBLIC_API(int)
473
+ JS_CompareValues(const void *v1, const void *v2)
474
+ {
475
+ return v1 == v2;
476
+ }