johnson 1.2.0 → 2.0.0.pre0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (782) hide show
  1. data/CHANGELOG.rdoc +8 -0
  2. data/Manifest.txt +762 -48
  3. data/README.rdoc +2 -1
  4. data/Rakefile +90 -18
  5. data/ext/spidermonkey/conversions.c +9 -2
  6. data/ext/spidermonkey/ruby_land_proxy.c +1 -1
  7. data/ext/spidermonkey/runtime.h +1 -1
  8. data/ext/tracemonkey/context.cc +125 -0
  9. data/ext/tracemonkey/context.h +19 -0
  10. data/ext/tracemonkey/conversions.cc +365 -0
  11. data/ext/tracemonkey/conversions.h +32 -0
  12. data/ext/tracemonkey/debugger.cc +234 -0
  13. data/ext/tracemonkey/debugger.h +10 -0
  14. data/ext/tracemonkey/extconf.rb +37 -0
  15. data/ext/tracemonkey/extensions.cc +37 -0
  16. data/ext/tracemonkey/extensions.h +12 -0
  17. data/ext/tracemonkey/global.cc +40 -0
  18. data/ext/tracemonkey/global.h +11 -0
  19. data/ext/tracemonkey/idhash.cc +16 -0
  20. data/ext/tracemonkey/idhash.h +8 -0
  21. data/ext/tracemonkey/immutable_node.cc +1199 -0
  22. data/ext/tracemonkey/immutable_node.cc.erb +559 -0
  23. data/ext/tracemonkey/immutable_node.h +22 -0
  24. data/ext/tracemonkey/jroot.h +215 -0
  25. data/ext/tracemonkey/js_land_proxy.cc +620 -0
  26. data/ext/tracemonkey/js_land_proxy.h +20 -0
  27. data/ext/tracemonkey/ruby_land_proxy.cc +618 -0
  28. data/ext/tracemonkey/ruby_land_proxy.h +38 -0
  29. data/ext/tracemonkey/runtime.cc +454 -0
  30. data/ext/tracemonkey/runtime.h +27 -0
  31. data/ext/tracemonkey/split_global.cc +392 -0
  32. data/ext/tracemonkey/split_global.h +11 -0
  33. data/ext/tracemonkey/tracemonkey.cc +23 -0
  34. data/ext/tracemonkey/tracemonkey.h +32 -0
  35. data/lib/johnson.rb +12 -4
  36. data/lib/johnson/error.rb +5 -0
  37. data/lib/johnson/js/prelude.js +16 -1
  38. data/lib/johnson/parser.rb +2 -1
  39. data/lib/johnson/runtime.rb +87 -26
  40. data/lib/johnson/spidermonkey/runtime.rb +7 -16
  41. data/lib/johnson/tracemonkey.rb +13 -0
  42. data/lib/johnson/tracemonkey/context.rb +10 -0
  43. data/lib/johnson/tracemonkey/debugger.rb +67 -0
  44. data/lib/johnson/tracemonkey/immutable_node.rb +282 -0
  45. data/lib/johnson/tracemonkey/js_land_proxy.rb +64 -0
  46. data/lib/johnson/tracemonkey/mutable_tree_visitor.rb +242 -0
  47. data/lib/johnson/tracemonkey/ruby_land_proxy.rb +17 -0
  48. data/lib/johnson/tracemonkey/runtime.rb +80 -0
  49. data/test/{johnson_test.rb → generic/johnson_test.rb} +1 -1
  50. data/test/{parser_test.rb → generic/parser_test.rb} +1 -1
  51. data/test/helper.rb +23 -4
  52. data/test/johnson/{browser_test.rb → generic/browser_test.rb} +1 -1
  53. data/test/johnson/{conversions → generic/conversions}/array_test.rb +1 -1
  54. data/test/johnson/{conversions → generic/conversions}/boolean_test.rb +1 -1
  55. data/test/johnson/{conversions → generic/conversions}/callable_test.rb +1 -1
  56. data/test/johnson/{conversions → generic/conversions}/file_test.rb +1 -1
  57. data/test/johnson/generic/conversions/helper.rb +1 -0
  58. data/test/johnson/{conversions → generic/conversions}/nil_test.rb +1 -1
  59. data/test/johnson/{conversions → generic/conversions}/number_test.rb +1 -1
  60. data/test/johnson/{conversions → generic/conversions}/regexp_test.rb +1 -1
  61. data/test/johnson/{conversions → generic/conversions}/string_test.rb +1 -1
  62. data/test/johnson/{conversions → generic/conversions}/struct_test.rb +1 -1
  63. data/test/johnson/{conversions → generic/conversions}/symbol_test.rb +1 -1
  64. data/test/johnson/{conversions → generic/conversions}/thread_test.rb +1 -1
  65. data/test/johnson/{custom_conversions_test.rb → generic/custom_conversions_test.rb} +1 -1
  66. data/test/johnson/generic/default_test.rb +12 -0
  67. data/test/johnson/{error_test.rb → generic/error_test.rb} +1 -1
  68. data/test/johnson/{extensions_test.rb → generic/extensions_test.rb} +1 -1
  69. data/test/johnson/generic/helper.rb +1 -0
  70. data/test/johnson/{nodes → generic/nodes}/array_literal_test.rb +1 -1
  71. data/test/johnson/{nodes → generic/nodes}/array_node_test.rb +1 -1
  72. data/test/johnson/{nodes → generic/nodes}/binary_node_test.rb +1 -1
  73. data/test/johnson/{nodes → generic/nodes}/bracket_access_test.rb +1 -1
  74. data/test/johnson/{nodes → generic/nodes}/delete_test.rb +1 -1
  75. data/test/johnson/{nodes → generic/nodes}/do_while_test.rb +1 -1
  76. data/test/johnson/{nodes → generic/nodes}/dot_accessor_test.rb +1 -1
  77. data/test/johnson/generic/nodes/export_test.rb +11 -0
  78. data/test/johnson/{nodes → generic/nodes}/for_test.rb +1 -1
  79. data/test/johnson/{nodes → generic/nodes}/function_test.rb +1 -1
  80. data/test/johnson/generic/nodes/helper.rb +1 -0
  81. data/test/johnson/{nodes → generic/nodes}/if_test.rb +16 -6
  82. data/test/johnson/generic/nodes/import_test.rb +15 -0
  83. data/test/johnson/{nodes → generic/nodes}/label_test.rb +1 -1
  84. data/test/johnson/{nodes → generic/nodes}/let_test.rb +1 -1
  85. data/test/johnson/{nodes → generic/nodes}/object_literal_test.rb +1 -1
  86. data/test/johnson/{nodes → generic/nodes}/return_test.rb +1 -1
  87. data/test/johnson/{nodes → generic/nodes}/semi_test.rb +1 -1
  88. data/test/johnson/{nodes → generic/nodes}/switch_test.rb +1 -1
  89. data/test/johnson/{nodes → generic/nodes}/ternary_test.rb +1 -1
  90. data/test/johnson/{nodes → generic/nodes}/throw_test.rb +1 -1
  91. data/test/johnson/{nodes → generic/nodes}/try_node_test.rb +36 -6
  92. data/test/johnson/{nodes → generic/nodes}/typeof_test.rb +1 -1
  93. data/test/johnson/{nodes → generic/nodes}/unary_node_test.rb +1 -1
  94. data/test/johnson/{nodes → generic/nodes}/void_test.rb +1 -1
  95. data/test/johnson/{nodes → generic/nodes}/while_test.rb +1 -1
  96. data/test/johnson/{nodes → generic/nodes}/with_test.rb +1 -1
  97. data/test/johnson/{prelude_test.rb → generic/prelude_test.rb} +1 -1
  98. data/test/johnson/{runtime_test.rb → generic/runtime_test.rb} +3 -6
  99. data/test/johnson/generic/version_test.rb +13 -0
  100. data/test/johnson/{visitors → generic/visitors}/dot_visitor_test.rb +1 -1
  101. data/test/johnson/{visitors → generic/visitors}/enumerating_visitor_test.rb +1 -1
  102. data/test/johnson/generic/visitors/helper.rb +1 -0
  103. data/test/johnson/spidermonkey/js_land_proxy_test.rb +1 -5
  104. data/test/johnson/spidermonkey/ruby_land_proxy_test.rb +11 -7
  105. data/test/johnson/tracemonkey/context_test.rb +21 -0
  106. data/test/johnson/tracemonkey/immutable_node_test.rb +34 -0
  107. data/test/johnson/tracemonkey/js_land_proxy_test.rb +273 -0
  108. data/test/johnson/tracemonkey/ruby_land_proxy_test.rb +274 -0
  109. data/test/johnson/tracemonkey/runtime_test.rb +41 -0
  110. data/test/johnson/tracemonkey/split_global_test.rb +32 -0
  111. data/vendor/spidermonkey/js.pkg +2 -0
  112. data/vendor/tracemonkey/Makefile.in +668 -0
  113. data/vendor/tracemonkey/Makefile.ref +483 -0
  114. data/vendor/tracemonkey/README.html +54 -0
  115. data/vendor/tracemonkey/SpiderMonkey.rsp +11 -0
  116. data/vendor/tracemonkey/Y.js +19 -0
  117. data/vendor/tracemonkey/aclocal.m4 +9 -0
  118. data/vendor/tracemonkey/bench.sh +5 -0
  119. data/vendor/tracemonkey/build/autoconf/acoutput-fast.pl +202 -0
  120. data/vendor/tracemonkey/build/autoconf/altoptions.m4 +154 -0
  121. data/vendor/tracemonkey/build/autoconf/config.guess +1537 -0
  122. data/vendor/tracemonkey/build/autoconf/config.sub +1595 -0
  123. data/vendor/tracemonkey/build/autoconf/install-sh +119 -0
  124. data/vendor/tracemonkey/build/autoconf/make-makefile +315 -0
  125. data/vendor/tracemonkey/build/autoconf/match-dir.sh +101 -0
  126. data/vendor/tracemonkey/build/autoconf/moznbytetype.m4 +136 -0
  127. data/vendor/tracemonkey/build/autoconf/nspr.m4 +82 -0
  128. data/vendor/tracemonkey/build/autoconf/pkg.m4 +59 -0
  129. data/vendor/tracemonkey/build/autoconf/update-makefile.sh +118 -0
  130. data/vendor/tracemonkey/build/cygwin-wrapper +75 -0
  131. data/vendor/tracemonkey/build/hcc +111 -0
  132. data/vendor/tracemonkey/build/hcpp +155 -0
  133. data/vendor/tracemonkey/build/unix/mddepend.pl +165 -0
  134. data/vendor/tracemonkey/build/unix/uniq.pl +63 -0
  135. data/vendor/tracemonkey/build/win32/pgomerge.py +40 -0
  136. data/vendor/tracemonkey/builtins.tbl +91 -0
  137. data/vendor/tracemonkey/call.js +13 -0
  138. data/vendor/tracemonkey/config.mk +206 -0
  139. data/vendor/tracemonkey/config/Makefile.in +106 -0
  140. data/vendor/tracemonkey/config/Moz/Milestone.pm +232 -0
  141. data/vendor/tracemonkey/config/autoconf.mk.in +362 -0
  142. data/vendor/tracemonkey/config/check-sync-dirs.py +103 -0
  143. data/vendor/tracemonkey/config/check-sync-exceptions +7 -0
  144. data/vendor/tracemonkey/config/config.mk +881 -0
  145. data/vendor/tracemonkey/config/fastcwd.pl +66 -0
  146. data/vendor/tracemonkey/config/gcc_hidden.h +2 -0
  147. data/vendor/tracemonkey/config/insure.mk +53 -0
  148. data/vendor/tracemonkey/config/make-system-wrappers.pl +59 -0
  149. data/vendor/tracemonkey/config/milestone.pl +112 -0
  150. data/vendor/tracemonkey/config/milestone.txt +13 -0
  151. data/vendor/tracemonkey/config/mkdepend/Makefile.in +84 -0
  152. data/vendor/tracemonkey/config/mkdepend/cppsetup.c +233 -0
  153. data/vendor/tracemonkey/config/mkdepend/def.h +184 -0
  154. data/vendor/tracemonkey/config/mkdepend/ifparser.c +551 -0
  155. data/vendor/tracemonkey/config/mkdepend/ifparser.h +83 -0
  156. data/vendor/tracemonkey/config/mkdepend/imakemdep.h +733 -0
  157. data/vendor/tracemonkey/config/mkdepend/include.c +337 -0
  158. data/vendor/tracemonkey/config/mkdepend/main.c +860 -0
  159. data/vendor/tracemonkey/config/mkdepend/mkdepend.man +382 -0
  160. data/vendor/tracemonkey/config/mkdepend/parse.c +686 -0
  161. data/vendor/tracemonkey/config/mkdepend/pr.c +124 -0
  162. data/vendor/tracemonkey/config/nfspwd.pl +50 -0
  163. data/vendor/tracemonkey/config/nsinstall.c +481 -0
  164. data/vendor/tracemonkey/config/nsinstall.py +155 -0
  165. data/vendor/tracemonkey/config/pathsub.c +247 -0
  166. data/vendor/tracemonkey/config/pathsub.h +74 -0
  167. data/vendor/tracemonkey/config/preprocessor.pl +671 -0
  168. data/vendor/tracemonkey/config/revdepth-nt.pl +48 -0
  169. data/vendor/tracemonkey/config/revdepth.pl +51 -0
  170. data/vendor/tracemonkey/config/rules.mk +2310 -0
  171. data/vendor/tracemonkey/config/static-checking-config.mk +21 -0
  172. data/vendor/tracemonkey/config/static-checking.js +92 -0
  173. data/vendor/tracemonkey/config/string-format.js +61 -0
  174. data/vendor/tracemonkey/config/system-headers +1035 -0
  175. data/vendor/tracemonkey/config/version.mk +85 -0
  176. data/vendor/tracemonkey/config/version_win.pl +442 -0
  177. data/vendor/tracemonkey/configure +14183 -0
  178. data/vendor/tracemonkey/configure.in +5363 -0
  179. data/vendor/tracemonkey/correct.sh +23 -0
  180. data/vendor/tracemonkey/correct/check-3d-morph.js +55 -0
  181. data/vendor/tracemonkey/correct/check-3d-raytrace.js +445 -0
  182. data/vendor/tracemonkey/correct/check-access-binary-trees.js +52 -0
  183. data/vendor/tracemonkey/correct/check-access-fannkuch.js +66 -0
  184. data/vendor/tracemonkey/correct/check-access-nbody.js +171 -0
  185. data/vendor/tracemonkey/correct/check-access-nsieve.js +40 -0
  186. data/vendor/tracemonkey/correct/check-bitops-3bit-bits-in-byte.js +35 -0
  187. data/vendor/tracemonkey/correct/check-bitops-bits-in-byte.js +24 -0
  188. data/vendor/tracemonkey/correct/check-bitops-bitwise-and.js +29 -0
  189. data/vendor/tracemonkey/correct/check-bitops-nsieve-bits.js +40 -0
  190. data/vendor/tracemonkey/correct/check-controlflow-recursive.js +27 -0
  191. data/vendor/tracemonkey/correct/check-date-format-tofte.js +302 -0
  192. data/vendor/tracemonkey/correct/check-date-format-xparb.js +421 -0
  193. data/vendor/tracemonkey/correct/check-mont.js +119 -0
  194. data/vendor/tracemonkey/dtoa.c +3335 -0
  195. data/vendor/tracemonkey/editline/Makefile.in +55 -0
  196. data/vendor/tracemonkey/editline/Makefile.ref +143 -0
  197. data/vendor/tracemonkey/editline/README +83 -0
  198. data/vendor/tracemonkey/editline/editline.3 +175 -0
  199. data/vendor/tracemonkey/editline/editline.c +1371 -0
  200. data/vendor/tracemonkey/editline/editline.h +135 -0
  201. data/vendor/tracemonkey/editline/sysunix.c +182 -0
  202. data/vendor/tracemonkey/editline/unix.h +82 -0
  203. data/vendor/tracemonkey/if.js +13 -0
  204. data/vendor/tracemonkey/imacro_asm.js.in +396 -0
  205. data/vendor/tracemonkey/imacros.c.out +1034 -0
  206. data/vendor/tracemonkey/imacros.jsasm +770 -0
  207. data/vendor/tracemonkey/javascript-trace.d +73 -0
  208. data/vendor/tracemonkey/jitstats.tbl +55 -0
  209. data/vendor/tracemonkey/js-config.h.in +82 -0
  210. data/vendor/tracemonkey/js-config.in +111 -0
  211. data/vendor/tracemonkey/js.mdp +0 -0
  212. data/vendor/tracemonkey/js.msg +312 -0
  213. data/vendor/tracemonkey/js3240.rc +79 -0
  214. data/vendor/tracemonkey/jsOS240.def +654 -0
  215. data/vendor/tracemonkey/jsapi.cpp +6005 -0
  216. data/vendor/tracemonkey/jsapi.h +2727 -0
  217. data/vendor/tracemonkey/jsarena.cpp +450 -0
  218. data/vendor/tracemonkey/jsarena.h +318 -0
  219. data/vendor/tracemonkey/jsarray.cpp +3664 -0
  220. data/vendor/tracemonkey/jsarray.h +238 -0
  221. data/vendor/tracemonkey/jsatom.cpp +1244 -0
  222. data/vendor/tracemonkey/jsatom.h +493 -0
  223. data/vendor/tracemonkey/jsbit.h +249 -0
  224. data/vendor/tracemonkey/jsbool.cpp +184 -0
  225. data/vendor/tracemonkey/jsbool.h +88 -0
  226. data/vendor/tracemonkey/jsbuiltins.cpp +415 -0
  227. data/vendor/tracemonkey/jsbuiltins.h +456 -0
  228. data/vendor/tracemonkey/jsclist.h +139 -0
  229. data/vendor/tracemonkey/jscntxt.cpp +1816 -0
  230. data/vendor/tracemonkey/jscntxt.h +1541 -0
  231. data/vendor/tracemonkey/jscompat.h +57 -0
  232. data/vendor/tracemonkey/jsconfig.mk +181 -0
  233. data/vendor/tracemonkey/jscpucfg.cpp +194 -0
  234. data/vendor/tracemonkey/jscpucfg.h +91 -0
  235. data/vendor/tracemonkey/jsdate.cpp +2465 -0
  236. data/vendor/tracemonkey/jsdate.h +129 -0
  237. data/vendor/tracemonkey/jsdbgapi.cpp +2017 -0
  238. data/vendor/tracemonkey/jsdbgapi.h +500 -0
  239. data/vendor/tracemonkey/jsdhash.cpp +876 -0
  240. data/vendor/tracemonkey/jsdhash.h +588 -0
  241. data/vendor/tracemonkey/jsdtoa.cpp +572 -0
  242. data/vendor/tracemonkey/jsdtoa.h +131 -0
  243. data/vendor/tracemonkey/jsdtracef.c +318 -0
  244. data/vendor/tracemonkey/jsdtracef.h +81 -0
  245. data/vendor/tracemonkey/jsemit.cpp +7292 -0
  246. data/vendor/tracemonkey/jsemit.h +802 -0
  247. data/vendor/tracemonkey/jsexn.cpp +1337 -0
  248. data/vendor/tracemonkey/jsexn.h +96 -0
  249. data/vendor/tracemonkey/jsfile.cpp +2747 -0
  250. data/vendor/tracemonkey/jsfile.h +56 -0
  251. data/vendor/tracemonkey/jsfile.msg +90 -0
  252. data/vendor/tracemonkey/jsfun.cpp +3089 -0
  253. data/vendor/tracemonkey/jsfun.h +366 -0
  254. data/vendor/tracemonkey/jsgc.cpp +3816 -0
  255. data/vendor/tracemonkey/jsgc.h +429 -0
  256. data/vendor/tracemonkey/jshash.cpp +477 -0
  257. data/vendor/tracemonkey/jshash.h +151 -0
  258. data/vendor/tracemonkey/jsify.pl +483 -0
  259. data/vendor/tracemonkey/jsinterp.cpp +7441 -0
  260. data/vendor/tracemonkey/jsinterp.h +666 -0
  261. data/vendor/tracemonkey/jsinvoke.cpp +42 -0
  262. data/vendor/tracemonkey/jsiter.cpp +1040 -0
  263. data/vendor/tracemonkey/jsiter.h +140 -0
  264. data/vendor/tracemonkey/jskeyword.tbl +124 -0
  265. data/vendor/tracemonkey/jskwgen.cpp +460 -0
  266. data/vendor/tracemonkey/jslibmath.h +69 -0
  267. data/vendor/tracemonkey/jslock.cpp +1512 -0
  268. data/vendor/tracemonkey/jslock.h +325 -0
  269. data/vendor/tracemonkey/jslocko.asm +60 -0
  270. data/vendor/tracemonkey/jslog2.cpp +111 -0
  271. data/vendor/tracemonkey/jslong.h +167 -0
  272. data/vendor/tracemonkey/jsmath.cpp +806 -0
  273. data/vendor/tracemonkey/jsmath.h +63 -0
  274. data/vendor/tracemonkey/jsnum.cpp +1374 -0
  275. data/vendor/tracemonkey/jsnum.h +280 -0
  276. data/vendor/tracemonkey/jsobj.cpp +6165 -0
  277. data/vendor/tracemonkey/jsobj.h +870 -0
  278. data/vendor/tracemonkey/json.cpp +1338 -0
  279. data/vendor/tracemonkey/json.h +108 -0
  280. data/vendor/tracemonkey/jsopcode.cpp +5484 -0
  281. data/vendor/tracemonkey/jsopcode.h +434 -0
  282. data/vendor/tracemonkey/jsopcode.tbl +591 -0
  283. data/vendor/tracemonkey/jsoplengen.cpp +121 -0
  284. data/vendor/tracemonkey/jsotypes.h +202 -0
  285. data/vendor/tracemonkey/jsparse.cpp +9257 -0
  286. data/vendor/tracemonkey/jsparse.h +900 -0
  287. data/vendor/tracemonkey/jsprf.cpp +1262 -0
  288. data/vendor/tracemonkey/jsprf.h +150 -0
  289. data/vendor/tracemonkey/jsproto.tbl +117 -0
  290. data/vendor/tracemonkey/jsprvtd.h +366 -0
  291. data/vendor/tracemonkey/jspubtd.h +585 -0
  292. data/vendor/tracemonkey/jsregexp.cpp +5051 -0
  293. data/vendor/tracemonkey/jsregexp.h +199 -0
  294. data/vendor/tracemonkey/jsreops.tbl +145 -0
  295. data/vendor/tracemonkey/jsscan.cpp +2040 -0
  296. data/vendor/tracemonkey/jsscan.h +467 -0
  297. data/vendor/tracemonkey/jsscope.cpp +1966 -0
  298. data/vendor/tracemonkey/jsscope.h +487 -0
  299. data/vendor/tracemonkey/jsscript.cpp +1932 -0
  300. data/vendor/tracemonkey/jsscript.h +345 -0
  301. data/vendor/tracemonkey/jsshell.msg +54 -0
  302. data/vendor/tracemonkey/jsstack.js +167 -0
  303. data/vendor/tracemonkey/jsstaticcheck.h +69 -0
  304. data/vendor/tracemonkey/jsstddef.h +87 -0
  305. data/vendor/tracemonkey/jsstdint.h +96 -0
  306. data/vendor/tracemonkey/jsstr.cpp +5277 -0
  307. data/vendor/tracemonkey/jsstr.h +702 -0
  308. data/vendor/tracemonkey/jstracer.cpp +10991 -0
  309. data/vendor/tracemonkey/jstracer.h +794 -0
  310. data/vendor/tracemonkey/jstypes.h +481 -0
  311. data/vendor/tracemonkey/jsutil.cpp +361 -0
  312. data/vendor/tracemonkey/jsutil.h +178 -0
  313. data/vendor/tracemonkey/jsversion.h +243 -0
  314. data/vendor/tracemonkey/jswince.asm +44 -0
  315. data/vendor/tracemonkey/jsxdrapi.cpp +800 -0
  316. data/vendor/tracemonkey/jsxdrapi.h +220 -0
  317. data/vendor/tracemonkey/jsxml.cpp +8327 -0
  318. data/vendor/tracemonkey/jsxml.h +305 -0
  319. data/vendor/tracemonkey/liveconnect/LiveConnect.dsp +157 -0
  320. data/vendor/tracemonkey/liveconnect/LiveConnectShell.dsp +120 -0
  321. data/vendor/tracemonkey/liveconnect/LiveConnectShell.dsw +44 -0
  322. data/vendor/tracemonkey/liveconnect/Makefile.in +105 -0
  323. data/vendor/tracemonkey/liveconnect/Makefile.ref +169 -0
  324. data/vendor/tracemonkey/liveconnect/README.html +712 -0
  325. data/vendor/tracemonkey/liveconnect/_jni/netscape_javascript_JSException.h +14 -0
  326. data/vendor/tracemonkey/liveconnect/_jni/netscape_javascript_JSObject.h +155 -0
  327. data/vendor/tracemonkey/liveconnect/classes/Makefile.in +89 -0
  328. data/vendor/tracemonkey/liveconnect/classes/Makefile.ref +57 -0
  329. data/vendor/tracemonkey/liveconnect/classes/netscape/Makefile.ref +47 -0
  330. data/vendor/tracemonkey/liveconnect/classes/netscape/javascript/JSException.java +140 -0
  331. data/vendor/tracemonkey/liveconnect/classes/netscape/javascript/JSObject.java +183 -0
  332. data/vendor/tracemonkey/liveconnect/classes/netscape/javascript/JSProxy.java +58 -0
  333. data/vendor/tracemonkey/liveconnect/classes/netscape/javascript/JSRunnable.java +70 -0
  334. data/vendor/tracemonkey/liveconnect/classes/netscape/javascript/JSUtil.java +59 -0
  335. data/vendor/tracemonkey/liveconnect/classes/netscape/javascript/Makefile.ref +53 -0
  336. data/vendor/tracemonkey/liveconnect/config/AIX4.1.mk +45 -0
  337. data/vendor/tracemonkey/liveconnect/config/AIX4.2.mk +45 -0
  338. data/vendor/tracemonkey/liveconnect/config/AIX4.3.mk +50 -0
  339. data/vendor/tracemonkey/liveconnect/config/HP-UXB.10.10.mk +43 -0
  340. data/vendor/tracemonkey/liveconnect/config/HP-UXB.10.20.mk +43 -0
  341. data/vendor/tracemonkey/liveconnect/config/HP-UXB.11.00.mk +43 -0
  342. data/vendor/tracemonkey/liveconnect/config/IRIX6.2.mk +43 -0
  343. data/vendor/tracemonkey/liveconnect/config/IRIX6.3.mk +43 -0
  344. data/vendor/tracemonkey/liveconnect/config/IRIX6.5.mk +43 -0
  345. data/vendor/tracemonkey/liveconnect/config/Linux_All.mk +73 -0
  346. data/vendor/tracemonkey/liveconnect/config/OSF1V4.0.mk +65 -0
  347. data/vendor/tracemonkey/liveconnect/config/OSF1V5.0.mk +62 -0
  348. data/vendor/tracemonkey/liveconnect/config/SunOS5.5.1.mk +55 -0
  349. data/vendor/tracemonkey/liveconnect/config/SunOS5.6.mk +39 -0
  350. data/vendor/tracemonkey/liveconnect/config/SunOS5.7.mk +39 -0
  351. data/vendor/tracemonkey/liveconnect/config/SunOS5.8.mk +39 -0
  352. data/vendor/tracemonkey/liveconnect/config/WINNT4.0.mk +53 -0
  353. data/vendor/tracemonkey/liveconnect/jsj.c +886 -0
  354. data/vendor/tracemonkey/liveconnect/jsj.msg +98 -0
  355. data/vendor/tracemonkey/liveconnect/jsj_JSObject.c +1377 -0
  356. data/vendor/tracemonkey/liveconnect/jsj_JavaArray.c +474 -0
  357. data/vendor/tracemonkey/liveconnect/jsj_JavaClass.c +737 -0
  358. data/vendor/tracemonkey/liveconnect/jsj_JavaMember.c +191 -0
  359. data/vendor/tracemonkey/liveconnect/jsj_JavaObject.c +1079 -0
  360. data/vendor/tracemonkey/liveconnect/jsj_JavaPackage.c +569 -0
  361. data/vendor/tracemonkey/liveconnect/jsj_array.c +207 -0
  362. data/vendor/tracemonkey/liveconnect/jsj_class.c +770 -0
  363. data/vendor/tracemonkey/liveconnect/jsj_convert.c +902 -0
  364. data/vendor/tracemonkey/liveconnect/jsj_field.c +421 -0
  365. data/vendor/tracemonkey/liveconnect/jsj_hash.c +488 -0
  366. data/vendor/tracemonkey/liveconnect/jsj_hash.h +161 -0
  367. data/vendor/tracemonkey/liveconnect/jsj_method.c +1825 -0
  368. data/vendor/tracemonkey/liveconnect/jsj_nodl.c +1 -0
  369. data/vendor/tracemonkey/liveconnect/jsj_private.h +677 -0
  370. data/vendor/tracemonkey/liveconnect/jsj_simpleapi.c +219 -0
  371. data/vendor/tracemonkey/liveconnect/jsj_utils.c +513 -0
  372. data/vendor/tracemonkey/liveconnect/jsjava.h +316 -0
  373. data/vendor/tracemonkey/liveconnect/netscape_javascript_JSObject.h +155 -0
  374. data/vendor/tracemonkey/liveconnect/nsCLiveconnect.cpp +785 -0
  375. data/vendor/tracemonkey/liveconnect/nsCLiveconnect.h +197 -0
  376. data/vendor/tracemonkey/liveconnect/nsCLiveconnectFactory.cpp +118 -0
  377. data/vendor/tracemonkey/liveconnect/nsCLiveconnectFactory.h +76 -0
  378. data/vendor/tracemonkey/liveconnect/nsILiveconnect.h +197 -0
  379. data/vendor/tracemonkey/liveconnect/nsISecureLiveconnect.h +94 -0
  380. data/vendor/tracemonkey/liveconnect/nsISecurityContext.h +136 -0
  381. data/vendor/tracemonkey/lock_SunOS.s +119 -0
  382. data/vendor/tracemonkey/mandelbrot-results.js +3 -0
  383. data/vendor/tracemonkey/math-partial-sums.js +32 -0
  384. data/vendor/tracemonkey/math-trace-tests.js +507 -0
  385. data/vendor/tracemonkey/md5.js +289 -0
  386. data/vendor/tracemonkey/nanojit/Assembler.cpp +1984 -0
  387. data/vendor/tracemonkey/nanojit/Assembler.h +375 -0
  388. data/vendor/tracemonkey/nanojit/Fragmento.cpp +651 -0
  389. data/vendor/tracemonkey/nanojit/Fragmento.h +237 -0
  390. data/vendor/tracemonkey/nanojit/LIR.cpp +2314 -0
  391. data/vendor/tracemonkey/nanojit/LIR.h +879 -0
  392. data/vendor/tracemonkey/nanojit/LIRopcode.tbl +252 -0
  393. data/vendor/tracemonkey/nanojit/Native.h +127 -0
  394. data/vendor/tracemonkey/nanojit/NativeARM.cpp +1742 -0
  395. data/vendor/tracemonkey/nanojit/NativeARM.h +844 -0
  396. data/vendor/tracemonkey/nanojit/NativeSparc.cpp +1130 -0
  397. data/vendor/tracemonkey/nanojit/NativeSparc.h +948 -0
  398. data/vendor/tracemonkey/nanojit/NativeThumb.cpp +1322 -0
  399. data/vendor/tracemonkey/nanojit/NativeThumb.h +525 -0
  400. data/vendor/tracemonkey/nanojit/Nativei386.cpp +1748 -0
  401. data/vendor/tracemonkey/nanojit/Nativei386.h +857 -0
  402. data/vendor/tracemonkey/nanojit/RegAlloc.cpp +183 -0
  403. data/vendor/tracemonkey/nanojit/RegAlloc.h +95 -0
  404. data/vendor/tracemonkey/nanojit/TraceTreeDrawer.cpp +306 -0
  405. data/vendor/tracemonkey/nanojit/TraceTreeDrawer.h +88 -0
  406. data/vendor/tracemonkey/nanojit/avmplus.cpp +56 -0
  407. data/vendor/tracemonkey/nanojit/avmplus.h +1016 -0
  408. data/vendor/tracemonkey/nanojit/nanojit.h +253 -0
  409. data/vendor/tracemonkey/perfect.js +39 -0
  410. data/vendor/tracemonkey/plify_jsdhash.sed +35 -0
  411. data/vendor/tracemonkey/prmjtime.cpp +869 -0
  412. data/vendor/tracemonkey/prmjtime.h +103 -0
  413. data/vendor/tracemonkey/ref-config/AIX4.1.mk +65 -0
  414. data/vendor/tracemonkey/ref-config/AIX4.2.mk +64 -0
  415. data/vendor/tracemonkey/ref-config/AIX4.3.mk +65 -0
  416. data/vendor/tracemonkey/ref-config/Darwin.mk +85 -0
  417. data/vendor/tracemonkey/ref-config/Darwin1.3.mk +81 -0
  418. data/vendor/tracemonkey/ref-config/Darwin1.4.mk +41 -0
  419. data/vendor/tracemonkey/ref-config/Darwin5.2.mk +81 -0
  420. data/vendor/tracemonkey/ref-config/Darwin5.3.mk +81 -0
  421. data/vendor/tracemonkey/ref-config/Darwin64.mk +72 -0
  422. data/vendor/tracemonkey/ref-config/HP-UXB.10.10.mk +77 -0
  423. data/vendor/tracemonkey/ref-config/HP-UXB.10.20.mk +77 -0
  424. data/vendor/tracemonkey/ref-config/HP-UXB.11.00.mk +80 -0
  425. data/vendor/tracemonkey/ref-config/IRIX.mk +87 -0
  426. data/vendor/tracemonkey/ref-config/IRIX5.3.mk +44 -0
  427. data/vendor/tracemonkey/ref-config/IRIX6.1.mk +44 -0
  428. data/vendor/tracemonkey/ref-config/IRIX6.2.mk +44 -0
  429. data/vendor/tracemonkey/ref-config/IRIX6.3.mk +44 -0
  430. data/vendor/tracemonkey/ref-config/IRIX6.5.mk +44 -0
  431. data/vendor/tracemonkey/ref-config/Linux_All.mk +105 -0
  432. data/vendor/tracemonkey/ref-config/Mac_OS10.0.mk +82 -0
  433. data/vendor/tracemonkey/ref-config/OSF1V4.0.mk +72 -0
  434. data/vendor/tracemonkey/ref-config/OSF1V5.0.mk +69 -0
  435. data/vendor/tracemonkey/ref-config/SunOS4.1.4.mk +101 -0
  436. data/vendor/tracemonkey/ref-config/SunOS5.10.mk +50 -0
  437. data/vendor/tracemonkey/ref-config/SunOS5.3.mk +91 -0
  438. data/vendor/tracemonkey/ref-config/SunOS5.4.mk +92 -0
  439. data/vendor/tracemonkey/ref-config/SunOS5.5.1.mk +44 -0
  440. data/vendor/tracemonkey/ref-config/SunOS5.5.mk +87 -0
  441. data/vendor/tracemonkey/ref-config/SunOS5.6.mk +89 -0
  442. data/vendor/tracemonkey/ref-config/SunOS5.7.mk +44 -0
  443. data/vendor/tracemonkey/ref-config/SunOS5.8.mk +44 -0
  444. data/vendor/tracemonkey/ref-config/SunOS5.9.mk +44 -0
  445. data/vendor/tracemonkey/ref-config/WINNT4.0.mk +118 -0
  446. data/vendor/tracemonkey/ref-config/WINNT5.0.mk +118 -0
  447. data/vendor/tracemonkey/ref-config/WINNT5.1.mk +118 -0
  448. data/vendor/tracemonkey/ref-config/WINNT5.2.mk +118 -0
  449. data/vendor/tracemonkey/ref-config/WINNT6.0.mk +118 -0
  450. data/vendor/tracemonkey/ref-config/dgux.mk +64 -0
  451. data/vendor/tracemonkey/resource.h +15 -0
  452. data/vendor/tracemonkey/rules.mk +206 -0
  453. data/vendor/tracemonkey/shell/Makefile.in +72 -0
  454. data/vendor/tracemonkey/shell/js.cpp +4719 -0
  455. data/vendor/tracemonkey/t/3d-cube.js +337 -0
  456. data/vendor/tracemonkey/t/3d-morph.js +54 -0
  457. data/vendor/tracemonkey/t/3d-raytrace.js +441 -0
  458. data/vendor/tracemonkey/t/access-binary-trees.js +50 -0
  459. data/vendor/tracemonkey/t/access-fannkuch.js +66 -0
  460. data/vendor/tracemonkey/t/access-nbody.js +169 -0
  461. data/vendor/tracemonkey/t/access-nsieve.js +38 -0
  462. data/vendor/tracemonkey/t/bitops-3bit-bits-in-byte.js +32 -0
  463. data/vendor/tracemonkey/t/bitops-bits-in-byte.js +21 -0
  464. data/vendor/tracemonkey/t/bitops-bitwise-and.js +28 -0
  465. data/vendor/tracemonkey/t/bitops-nsieve-bits.js +32 -0
  466. data/vendor/tracemonkey/t/controlflow-recursive.js +25 -0
  467. data/vendor/tracemonkey/t/crypto-aes.js +422 -0
  468. data/vendor/tracemonkey/t/crypto-md5.js +286 -0
  469. data/vendor/tracemonkey/t/crypto-sha1.js +224 -0
  470. data/vendor/tracemonkey/t/date-format-tofte.js +299 -0
  471. data/vendor/tracemonkey/t/date-format-xparb.js +417 -0
  472. data/vendor/tracemonkey/t/math-cordic.js +95 -0
  473. data/vendor/tracemonkey/t/math-partial-sums.js +33 -0
  474. data/vendor/tracemonkey/t/math-spectral-norm.js +51 -0
  475. data/vendor/tracemonkey/t/regexp-dna.js +1712 -0
  476. data/vendor/tracemonkey/t/string-base64.js +135 -0
  477. data/vendor/tracemonkey/t/string-fasta.js +85 -0
  478. data/vendor/tracemonkey/t/string-tagcloud.js +265 -0
  479. data/vendor/tracemonkey/t/string-unpack-code.js +68 -0
  480. data/vendor/tracemonkey/t/string-validate-input.js +89 -0
  481. data/vendor/tracemonkey/time.sh +13 -0
  482. data/vendor/tracemonkey/trace-test.js +5564 -0
  483. data/vendor/tracemonkey/v8/base.js +187 -0
  484. data/vendor/tracemonkey/v8/crypto.js +1689 -0
  485. data/vendor/tracemonkey/v8/deltablue.js +880 -0
  486. data/vendor/tracemonkey/v8/earley-boyer.js +4682 -0
  487. data/vendor/tracemonkey/v8/raytrace.js +3418 -0
  488. data/vendor/tracemonkey/v8/richards.js +539 -0
  489. data/vendor/tracemonkey/v8/run-crypto.js +44 -0
  490. data/vendor/tracemonkey/v8/run-deltablue.js +44 -0
  491. data/vendor/tracemonkey/v8/run-earley-boyer.js +44 -0
  492. data/vendor/tracemonkey/v8/run-raytrace.js +44 -0
  493. data/vendor/tracemonkey/v8/run-richards.js +44 -0
  494. data/vendor/tracemonkey/v8/run.js +49 -0
  495. data/vendor/tracemonkey/vprof/readme.txt +93 -0
  496. data/vendor/tracemonkey/vprof/vprof.cpp +360 -0
  497. data/vendor/tracemonkey/vprof/vprof.h +245 -0
  498. data/vendor/tracemonkey/xpconnect/Makefile.in +67 -0
  499. data/vendor/tracemonkey/xpconnect/crashtests/117307-1.html +20 -0
  500. data/vendor/tracemonkey/xpconnect/crashtests/193710.html +11 -0
  501. data/vendor/tracemonkey/xpconnect/crashtests/290162-1.html +5 -0
  502. data/vendor/tracemonkey/xpconnect/crashtests/326615-1.html +16 -0
  503. data/vendor/tracemonkey/xpconnect/crashtests/328553-1.html +13 -0
  504. data/vendor/tracemonkey/xpconnect/crashtests/346258-1.html +12 -0
  505. data/vendor/tracemonkey/xpconnect/crashtests/346512-1-frame1.xhtml +16 -0
  506. data/vendor/tracemonkey/xpconnect/crashtests/346512-1-frame2.xhtml +15 -0
  507. data/vendor/tracemonkey/xpconnect/crashtests/346512-1.xhtml +30 -0
  508. data/vendor/tracemonkey/xpconnect/crashtests/382133-1.html +3 -0
  509. data/vendor/tracemonkey/xpconnect/crashtests/386680-1.html +22 -0
  510. data/vendor/tracemonkey/xpconnect/crashtests/394810-1.html +4 -0
  511. data/vendor/tracemonkey/xpconnect/crashtests/400349-1.html +20 -0
  512. data/vendor/tracemonkey/xpconnect/crashtests/403356-1.html +13 -0
  513. data/vendor/tracemonkey/xpconnect/crashtests/418139-1.svg +22 -0
  514. data/vendor/tracemonkey/xpconnect/crashtests/420513-1.html +11 -0
  515. data/vendor/tracemonkey/xpconnect/crashtests/453935-1.html +37 -0
  516. data/vendor/tracemonkey/xpconnect/crashtests/462926.html +12 -0
  517. data/vendor/tracemonkey/xpconnect/crashtests/468552-1.html +18 -0
  518. data/vendor/tracemonkey/xpconnect/crashtests/471366-1.html +12 -0
  519. data/vendor/tracemonkey/xpconnect/crashtests/475185-1.html +13 -0
  520. data/vendor/tracemonkey/xpconnect/crashtests/475291-1.html +14 -0
  521. data/vendor/tracemonkey/xpconnect/crashtests/503286-1.html +23 -0
  522. data/vendor/tracemonkey/xpconnect/crashtests/crashtests.list +21 -0
  523. data/vendor/tracemonkey/xpconnect/idl/Makefile.in +78 -0
  524. data/vendor/tracemonkey/xpconnect/idl/XPCIDispatch.idl +51 -0
  525. data/vendor/tracemonkey/xpconnect/idl/mozIJSSubScriptLoader.idl +64 -0
  526. data/vendor/tracemonkey/xpconnect/idl/nsIActiveXSecurityPolicy.idl +67 -0
  527. data/vendor/tracemonkey/xpconnect/idl/nsIDispatchSupport.idl +119 -0
  528. data/vendor/tracemonkey/xpconnect/idl/nsIJSContextStack.idl +85 -0
  529. data/vendor/tracemonkey/xpconnect/idl/nsIJSRuntimeService.idl +51 -0
  530. data/vendor/tracemonkey/xpconnect/idl/nsIScriptError.idl +102 -0
  531. data/vendor/tracemonkey/xpconnect/idl/nsIScriptableInterfaces.idl +67 -0
  532. data/vendor/tracemonkey/xpconnect/idl/nsIXPCScriptNotify.idl +66 -0
  533. data/vendor/tracemonkey/xpconnect/idl/nsIXPCScriptable.idl +183 -0
  534. data/vendor/tracemonkey/xpconnect/idl/nsIXPCSecurityManager.idl +114 -0
  535. data/vendor/tracemonkey/xpconnect/idl/nsIXPConnect.idl +819 -0
  536. data/vendor/tracemonkey/xpconnect/idl/xpcIJSModuleLoader.idl +95 -0
  537. data/vendor/tracemonkey/xpconnect/idl/xpcIJSWeakReference.idl +49 -0
  538. data/vendor/tracemonkey/xpconnect/idl/xpccomponents.idl +254 -0
  539. data/vendor/tracemonkey/xpconnect/idl/xpcexception.idl +66 -0
  540. data/vendor/tracemonkey/xpconnect/idl/xpcjsid.idl +83 -0
  541. data/vendor/tracemonkey/xpconnect/loader/ISO8601DateUtils.jsm +176 -0
  542. data/vendor/tracemonkey/xpconnect/loader/Makefile.in +63 -0
  543. data/vendor/tracemonkey/xpconnect/loader/XPCOMUtils.jsm +267 -0
  544. data/vendor/tracemonkey/xpconnect/loader/mozJSComponentLoader.cpp +1717 -0
  545. data/vendor/tracemonkey/xpconnect/loader/mozJSComponentLoader.h +172 -0
  546. data/vendor/tracemonkey/xpconnect/loader/mozJSLoaderConstructors.h +101 -0
  547. data/vendor/tracemonkey/xpconnect/loader/mozJSSubScriptLoader.cpp +360 -0
  548. data/vendor/tracemonkey/xpconnect/loader/mozJSSubScriptLoader.h +66 -0
  549. data/vendor/tracemonkey/xpconnect/public/Makefile.in +54 -0
  550. data/vendor/tracemonkey/xpconnect/public/nsAXPCNativeCallContext.h +89 -0
  551. data/vendor/tracemonkey/xpconnect/public/nsAutoJSValHolder.h +168 -0
  552. data/vendor/tracemonkey/xpconnect/public/xpc_map_end.h +327 -0
  553. data/vendor/tracemonkey/xpconnect/sample/Makefile.in +71 -0
  554. data/vendor/tracemonkey/xpconnect/sample/README +39 -0
  555. data/vendor/tracemonkey/xpconnect/sample/xpcsample1.cpp +337 -0
  556. data/vendor/tracemonkey/xpconnect/sample/xpcsample1.idl +82 -0
  557. data/vendor/tracemonkey/xpconnect/sample/xpcsample1.js +21 -0
  558. data/vendor/tracemonkey/xpconnect/shell/Makefile.in +106 -0
  559. data/vendor/tracemonkey/xpconnect/shell/jsshell.msg +50 -0
  560. data/vendor/tracemonkey/xpconnect/shell/xpcshell.cpp +1817 -0
  561. data/vendor/tracemonkey/xpconnect/shell/xpcshellMacUtils.h +43 -0
  562. data/vendor/tracemonkey/xpconnect/shell/xpcshellMacUtils.mm +54 -0
  563. data/vendor/tracemonkey/xpconnect/src/Makefile.in +228 -0
  564. data/vendor/tracemonkey/xpconnect/src/README +3 -0
  565. data/vendor/tracemonkey/xpconnect/src/XPCCrossOriginWrapper.cpp +1186 -0
  566. data/vendor/tracemonkey/xpconnect/src/XPCDispConvert.cpp +593 -0
  567. data/vendor/tracemonkey/xpconnect/src/XPCDispInlines.h +667 -0
  568. data/vendor/tracemonkey/xpconnect/src/XPCDispInterface.cpp +383 -0
  569. data/vendor/tracemonkey/xpconnect/src/XPCDispObject.cpp +516 -0
  570. data/vendor/tracemonkey/xpconnect/src/XPCDispParamPropJSClass.cpp +223 -0
  571. data/vendor/tracemonkey/xpconnect/src/XPCDispParams.cpp +103 -0
  572. data/vendor/tracemonkey/xpconnect/src/XPCDispPrivate.h +1401 -0
  573. data/vendor/tracemonkey/xpconnect/src/XPCDispTearOff.cpp +547 -0
  574. data/vendor/tracemonkey/xpconnect/src/XPCDispTypeInfo.cpp +471 -0
  575. data/vendor/tracemonkey/xpconnect/src/XPCIDispatchClassInfo.cpp +139 -0
  576. data/vendor/tracemonkey/xpconnect/src/XPCIDispatchExtension.cpp +362 -0
  577. data/vendor/tracemonkey/xpconnect/src/XPCNativeWrapper.cpp +1350 -0
  578. data/vendor/tracemonkey/xpconnect/src/XPCNativeWrapper.h +88 -0
  579. data/vendor/tracemonkey/xpconnect/src/XPCSafeJSObjectWrapper.cpp +1148 -0
  580. data/vendor/tracemonkey/xpconnect/src/XPCSystemOnlyWrapper.cpp +718 -0
  581. data/vendor/tracemonkey/xpconnect/src/XPCWrapper.cpp +850 -0
  582. data/vendor/tracemonkey/xpconnect/src/XPCWrapper.h +394 -0
  583. data/vendor/tracemonkey/xpconnect/src/dom_quickstubs.qsconf +568 -0
  584. data/vendor/tracemonkey/xpconnect/src/nsDispatchSupport.cpp +348 -0
  585. data/vendor/tracemonkey/xpconnect/src/nsScriptError.cpp +201 -0
  586. data/vendor/tracemonkey/xpconnect/src/nsXPConnect.cpp +2609 -0
  587. data/vendor/tracemonkey/xpconnect/src/qsgen.py +1487 -0
  588. data/vendor/tracemonkey/xpconnect/src/xpc.msg +217 -0
  589. data/vendor/tracemonkey/xpconnect/src/xpcJSWeakReference.cpp +148 -0
  590. data/vendor/tracemonkey/xpconnect/src/xpcJSWeakReference.h +56 -0
  591. data/vendor/tracemonkey/xpconnect/src/xpccallcontext.cpp +579 -0
  592. data/vendor/tracemonkey/xpconnect/src/xpccomponents.cpp +4144 -0
  593. data/vendor/tracemonkey/xpconnect/src/xpccontext.cpp +115 -0
  594. data/vendor/tracemonkey/xpconnect/src/xpcconvert.cpp +2298 -0
  595. data/vendor/tracemonkey/xpconnect/src/xpcdebug.cpp +481 -0
  596. data/vendor/tracemonkey/xpconnect/src/xpcexception.cpp +502 -0
  597. data/vendor/tracemonkey/xpconnect/src/xpcforwards.h +114 -0
  598. data/vendor/tracemonkey/xpconnect/src/xpcinlines.h +772 -0
  599. data/vendor/tracemonkey/xpconnect/src/xpcjsid.cpp +1025 -0
  600. data/vendor/tracemonkey/xpconnect/src/xpcjsruntime.cpp +1342 -0
  601. data/vendor/tracemonkey/xpconnect/src/xpclog.cpp +128 -0
  602. data/vendor/tracemonkey/xpconnect/src/xpclog.h +101 -0
  603. data/vendor/tracemonkey/xpconnect/src/xpcmaps.cpp +761 -0
  604. data/vendor/tracemonkey/xpconnect/src/xpcmaps.h +713 -0
  605. data/vendor/tracemonkey/xpconnect/src/xpcmodule.cpp +136 -0
  606. data/vendor/tracemonkey/xpconnect/src/xpcprivate.h +4138 -0
  607. data/vendor/tracemonkey/xpconnect/src/xpcquickstubs.cpp +1128 -0
  608. data/vendor/tracemonkey/xpconnect/src/xpcquickstubs.h +480 -0
  609. data/vendor/tracemonkey/xpconnect/src/xpcruntimesvc.cpp +179 -0
  610. data/vendor/tracemonkey/xpconnect/src/xpcstack.cpp +342 -0
  611. data/vendor/tracemonkey/xpconnect/src/xpcstring.cpp +139 -0
  612. data/vendor/tracemonkey/xpconnect/src/xpcthreadcontext.cpp +599 -0
  613. data/vendor/tracemonkey/xpconnect/src/xpcthrower.cpp +399 -0
  614. data/vendor/tracemonkey/xpconnect/src/xpcvariant.cpp +850 -0
  615. data/vendor/tracemonkey/xpconnect/src/xpcwrappedjs.cpp +670 -0
  616. data/vendor/tracemonkey/xpconnect/src/xpcwrappedjsclass.cpp +2015 -0
  617. data/vendor/tracemonkey/xpconnect/src/xpcwrappednative.cpp +3482 -0
  618. data/vendor/tracemonkey/xpconnect/src/xpcwrappednativeinfo.cpp +945 -0
  619. data/vendor/tracemonkey/xpconnect/src/xpcwrappednativejsops.cpp +2003 -0
  620. data/vendor/tracemonkey/xpconnect/src/xpcwrappednativeproto.cpp +302 -0
  621. data/vendor/tracemonkey/xpconnect/src/xpcwrappednativescope.cpp +991 -0
  622. data/vendor/tracemonkey/xpconnect/tests/Makefile.in +75 -0
  623. data/vendor/tracemonkey/xpconnect/tests/TestXPC.cpp +785 -0
  624. data/vendor/tracemonkey/xpconnect/tests/chrome/Makefile.in +51 -0
  625. data/vendor/tracemonkey/xpconnect/tests/chrome/test_bug500931.xul +43 -0
  626. data/vendor/tracemonkey/xpconnect/tests/components/Makefile.in +85 -0
  627. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_array.cpp +388 -0
  628. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_attributes.cpp +305 -0
  629. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_calljs.cpp +135 -0
  630. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_child.cpp +225 -0
  631. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_const.cpp +76 -0
  632. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_domstring.cpp +118 -0
  633. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_echo.cpp +616 -0
  634. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_in.cpp +204 -0
  635. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_inout.cpp +171 -0
  636. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_module.cpp +77 -0
  637. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_multiple.cpp +554 -0
  638. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_noisy.cpp +154 -0
  639. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_out.cpp +335 -0
  640. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_overloaded.cpp +250 -0
  641. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_private.h +192 -0
  642. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_string.cpp +185 -0
  643. data/vendor/tracemonkey/xpconnect/tests/components/xpctest_variant.cpp +355 -0
  644. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/StdAfx.cpp +12 -0
  645. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/StdAfx.h +28 -0
  646. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/XPCDispUtilities.h +28 -0
  647. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/XPCIDispatchTest.cpp +86 -0
  648. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/XPCIDispatchTest.def +9 -0
  649. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/XPCIDispatchTest.dsp +318 -0
  650. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/XPCIDispatchTest.dsw +29 -0
  651. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/XPCIDispatchTest.idl +454 -0
  652. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/XPCIDispatchTest.rc +145 -0
  653. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispSimple.cpp +44 -0
  654. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispSimple.h +56 -0
  655. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispSimple.rgs +23 -0
  656. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestArrays.cpp +221 -0
  657. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestArrays.h +53 -0
  658. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestArrays.rgs +23 -0
  659. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestMethods.cpp +699 -0
  660. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestMethods.h +138 -0
  661. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestMethods.rgs +23 -0
  662. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestNoIDispatch.cpp +23 -0
  663. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestNoIDispatch.h +41 -0
  664. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestNoIDispatch.rgs +23 -0
  665. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestProperties.cpp +256 -0
  666. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestProperties.h +88 -0
  667. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestProperties.rgs +23 -0
  668. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOff.cpp +23 -0
  669. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOff.h +43 -0
  670. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOff.rgs +23 -0
  671. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOn.cpp +29 -0
  672. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOn.h +45 -0
  673. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestScriptOn.rgs +23 -0
  674. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestWrappedJS.cpp +177 -0
  675. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestWrappedJS.h +50 -0
  676. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/nsXPCDispTestWrappedJS.rgs +23 -0
  677. data/vendor/tracemonkey/xpconnect/tests/idispatch/COM/resource.h +36 -0
  678. data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/WrappedCOM/Arrays/XPCIDispatchArrayTests.js +54 -0
  679. data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/WrappedCOM/Attributes/XPCIDispatchAttributeTests.js +150 -0
  680. data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/WrappedCOM/General/XPCIDispatchInstantiations.js +122 -0
  681. data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/WrappedCOM/General/XPCStress.js +58 -0
  682. data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/WrappedCOM/Methods/XPCIDispatchMethodTests.js +376 -0
  683. data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/WrappedCOM/shell.js +377 -0
  684. data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/WrappedJS/General/XPCIDispatchTestWrappedJS.js +76 -0
  685. data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/WrappedJS/shell.js +377 -0
  686. data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/exectests.cmd +1 -0
  687. data/vendor/tracemonkey/xpconnect/tests/idispatch/Tests/jsDriver.pl +1288 -0
  688. data/vendor/tracemonkey/xpconnect/tests/idl/Makefile.in +61 -0
  689. data/vendor/tracemonkey/xpconnect/tests/idl/xpctest.idl +312 -0
  690. data/vendor/tracemonkey/xpconnect/tests/idl/xpctest2.idl +51 -0
  691. data/vendor/tracemonkey/xpconnect/tests/idl/xpctest_attributes.idl +67 -0
  692. data/vendor/tracemonkey/xpconnect/tests/idl/xpctest_calljs.idl +59 -0
  693. data/vendor/tracemonkey/xpconnect/tests/idl/xpctest_const.idl +61 -0
  694. data/vendor/tracemonkey/xpconnect/tests/idl/xpctest_domstring.idl +59 -0
  695. data/vendor/tracemonkey/xpconnect/tests/idl/xpctest_in.idl +88 -0
  696. data/vendor/tracemonkey/xpconnect/tests/idl/xpctest_inout.idl +86 -0
  697. data/vendor/tracemonkey/xpconnect/tests/idl/xpctest_multiple.idl +77 -0
  698. data/vendor/tracemonkey/xpconnect/tests/idl/xpctest_out.idl +142 -0
  699. data/vendor/tracemonkey/xpconnect/tests/js/checkid.js +82 -0
  700. data/vendor/tracemonkey/xpconnect/tests/js/evaluate.js +311 -0
  701. data/vendor/tracemonkey/xpconnect/tests/js/exceptions-2.js +153 -0
  702. data/vendor/tracemonkey/xpconnect/tests/js/exceptions-3.js +194 -0
  703. data/vendor/tracemonkey/xpconnect/tests/js/exceptions-4.js +297 -0
  704. data/vendor/tracemonkey/xpconnect/tests/js/exceptions-5.js +343 -0
  705. data/vendor/tracemonkey/xpconnect/tests/js/exceptions.js +230 -0
  706. data/vendor/tracemonkey/xpconnect/tests/js/javascript.js +96 -0
  707. data/vendor/tracemonkey/xpconnect/tests/js/multiple-2.js +151 -0
  708. data/vendor/tracemonkey/xpconnect/tests/js/multiple-3.js +148 -0
  709. data/vendor/tracemonkey/xpconnect/tests/js/multiple-4.js +152 -0
  710. data/vendor/tracemonkey/xpconnect/tests/js/multiple.js +137 -0
  711. data/vendor/tracemonkey/xpconnect/tests/js/notscriptable.js +104 -0
  712. data/vendor/tracemonkey/xpconnect/tests/js/old/simpletest.js +36 -0
  713. data/vendor/tracemonkey/xpconnect/tests/js/old/speed.js +60 -0
  714. data/vendor/tracemonkey/xpconnect/tests/js/old/testxpc.js +464 -0
  715. data/vendor/tracemonkey/xpconnect/tests/js/old/threads.js +74 -0
  716. data/vendor/tracemonkey/xpconnect/tests/js/old/try.js +27 -0
  717. data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_array.js +308 -0
  718. data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_callcontext.js +68 -0
  719. data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_echo.js +636 -0
  720. data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_enum_and_sort.js +28 -0
  721. data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_enum_constants.js +15 -0
  722. data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_enum_create.js +200 -0
  723. data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_exceptions.js +167 -0
  724. data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_ids.js +135 -0
  725. data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_observer.js +36 -0
  726. data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_overloaded.js +14 -0
  727. data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_primitives.js +141 -0
  728. data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_propertybag.js +36 -0
  729. data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_variant.js +339 -0
  730. data/vendor/tracemonkey/xpconnect/tests/js/old/xpctest_variant_array.js +30 -0
  731. data/vendor/tracemonkey/xpconnect/tests/js/readonlyattributes.js +74 -0
  732. data/vendor/tracemonkey/xpconnect/tests/js/readwriteattributes.js +101 -0
  733. data/vendor/tracemonkey/xpconnect/tests/js/scriptable.js +120 -0
  734. data/vendor/tracemonkey/xpconnect/tests/js/testin.js +203 -0
  735. data/vendor/tracemonkey/xpconnect/tests/js/xpcfun.js +234 -0
  736. data/vendor/tracemonkey/xpconnect/tests/js/xpctest_primitives.js +200 -0
  737. data/vendor/tracemonkey/xpconnect/tests/mochitest/Makefile.in +66 -0
  738. data/vendor/tracemonkey/xpconnect/tests/mochitest/bug500931_helper.html +7 -0
  739. data/vendor/tracemonkey/xpconnect/tests/mochitest/inner.html +7 -0
  740. data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug361111.xul +29 -0
  741. data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug384632.html +32 -0
  742. data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug390488.html +65 -0
  743. data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug393269.html +46 -0
  744. data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug396851.html +43 -0
  745. data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug428021.html +41 -0
  746. data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug446584.html +49 -0
  747. data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug448587.html +31 -0
  748. data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug462428.html +42 -0
  749. data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug478438.html +66 -0
  750. data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug484107.html +100 -0
  751. data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug484459.html +36 -0
  752. data/vendor/tracemonkey/xpconnect/tests/mochitest/test_bug500691.html +28 -0
  753. data/vendor/tracemonkey/xpconnect/tests/mochitest/test_wrappers.html +116 -0
  754. data/vendor/tracemonkey/xpconnect/tests/unit/bogus_element_type.jsm +1 -0
  755. data/vendor/tracemonkey/xpconnect/tests/unit/bogus_exports_type.jsm +1 -0
  756. data/vendor/tracemonkey/xpconnect/tests/unit/bug451678_subscript.js +2 -0
  757. data/vendor/tracemonkey/xpconnect/tests/unit/component_import.js +144 -0
  758. data/vendor/tracemonkey/xpconnect/tests/unit/recursive_importA.jsm +44 -0
  759. data/vendor/tracemonkey/xpconnect/tests/unit/recursive_importB.jsm +45 -0
  760. data/vendor/tracemonkey/xpconnect/tests/unit/syntax_error.jsm +1 -0
  761. data/vendor/tracemonkey/xpconnect/tests/unit/test_bogus_files.js +88 -0
  762. data/vendor/tracemonkey/xpconnect/tests/unit/test_bug408412.js +51 -0
  763. data/vendor/tracemonkey/xpconnect/tests/unit/test_bug451678.js +52 -0
  764. data/vendor/tracemonkey/xpconnect/tests/unit/test_bug_442086.js +68 -0
  765. data/vendor/tracemonkey/xpconnect/tests/unit/test_import.js +127 -0
  766. data/vendor/tracemonkey/xpconnect/tests/unit/test_js_weak_references.js +63 -0
  767. data/vendor/tracemonkey/xpconnect/tests/unit/test_recursive_import.js +62 -0
  768. data/vendor/tracemonkey/xpconnect/tools/Makefile.in +49 -0
  769. data/vendor/tracemonkey/xpconnect/tools/idl/Makefile.in +53 -0
  770. data/vendor/tracemonkey/xpconnect/tools/idl/nsIXPCToolsCompiler.idl +60 -0
  771. data/vendor/tracemonkey/xpconnect/tools/idl/nsIXPCToolsProfiler.idl +57 -0
  772. data/vendor/tracemonkey/xpconnect/tools/js/CompileJSFiles.js +28 -0
  773. data/vendor/tracemonkey/xpconnect/tools/js/ListJSFiles.js +18 -0
  774. data/vendor/tracemonkey/xpconnect/tools/src/Makefile.in +76 -0
  775. data/vendor/tracemonkey/xpconnect/tools/src/nsXPCToolsCompiler.cpp +161 -0
  776. data/vendor/tracemonkey/xpconnect/tools/src/nsXPCToolsModule.cpp +65 -0
  777. data/vendor/tracemonkey/xpconnect/tools/src/nsXPCToolsProfiler.cpp +370 -0
  778. data/vendor/tracemonkey/xpconnect/tools/src/xpctools_private.h +236 -0
  779. metadata +782 -107
  780. data/test/johnson/nodes/export_test.rb +0 -9
  781. data/test/johnson/nodes/import_test.rb +0 -13
  782. data/test/johnson/version_test.rb +0 -13
@@ -0,0 +1,1966 @@
1
+ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
+ * vim: set ts=8 sw=4 et tw=78:
3
+ *
4
+ * ***** BEGIN LICENSE BLOCK *****
5
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6
+ *
7
+ * The contents of this file are subject to the Mozilla Public License Version
8
+ * 1.1 (the "License"); you may not use this file except in compliance with
9
+ * the License. You may obtain a copy of the License at
10
+ * http://www.mozilla.org/MPL/
11
+ *
12
+ * Software distributed under the License is distributed on an "AS IS" basis,
13
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14
+ * for the specific language governing rights and limitations under the
15
+ * License.
16
+ *
17
+ * The Original Code is Mozilla Communicator client code, released
18
+ * March 31, 1998.
19
+ *
20
+ * The Initial Developer of the Original Code is
21
+ * Netscape Communications Corporation.
22
+ * Portions created by the Initial Developer are Copyright (C) 1998
23
+ * the Initial Developer. All Rights Reserved.
24
+ *
25
+ * Contributor(s):
26
+ *
27
+ * Alternatively, the contents of this file may be used under the terms of
28
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
29
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30
+ * in which case the provisions of the GPL or the LGPL are applicable instead
31
+ * of those above. If you wish to allow use of your version of this file only
32
+ * under the terms of either the GPL or the LGPL, and not to allow others to
33
+ * use your version of this file under the terms of the MPL, indicate your
34
+ * decision by deleting the provisions above and replace them with the notice
35
+ * and other provisions required by the GPL or the LGPL. If you do not delete
36
+ * the provisions above, a recipient may use your version of this file under
37
+ * the terms of any one of the MPL, the GPL or the LGPL.
38
+ *
39
+ * ***** END LICENSE BLOCK ***** */
40
+
41
+ /*
42
+ * JS symbol tables.
43
+ */
44
+ #include "jsstddef.h"
45
+ #include <stdlib.h>
46
+ #include <string.h>
47
+ #include "jstypes.h"
48
+ #include "jsarena.h"
49
+ #include "jsbit.h"
50
+ #include "jsclist.h"
51
+ #include "jsdhash.h"
52
+ #include "jsutil.h" /* Added by JSIFY */
53
+ #include "jsapi.h"
54
+ #include "jsatom.h"
55
+ #include "jscntxt.h"
56
+ #include "jsdbgapi.h"
57
+ #include "jslock.h"
58
+ #include "jsnum.h"
59
+ #include "jsscope.h"
60
+ #include "jsstr.h"
61
+ #include "jsarray.h"
62
+
63
+ JSScope *
64
+ js_GetMutableScope(JSContext *cx, JSObject *obj)
65
+ {
66
+ JSScope *scope, *newscope;
67
+ JSClass *clasp;
68
+ uint32 freeslot;
69
+
70
+ scope = OBJ_SCOPE(obj);
71
+ JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope));
72
+ if (scope->object == obj)
73
+ return scope;
74
+
75
+ /*
76
+ * Compile-time block objects each have their own scope, created at
77
+ * birth, and runtime clone of a block objects are never mutated.
78
+ */
79
+ JS_ASSERT(STOBJ_GET_CLASS(obj) != &js_BlockClass);
80
+ newscope = js_NewScope(cx, scope->map.ops, LOCKED_OBJ_GET_CLASS(obj), obj);
81
+ if (!newscope)
82
+ return NULL;
83
+ JS_LOCK_SCOPE(cx, newscope);
84
+ obj->map = &newscope->map;
85
+
86
+ JS_ASSERT(newscope->freeslot == JSSLOT_FREE(STOBJ_GET_CLASS(obj)));
87
+ clasp = STOBJ_GET_CLASS(obj);
88
+ if (clasp->reserveSlots) {
89
+ freeslot = JSSLOT_FREE(clasp) + clasp->reserveSlots(cx, obj);
90
+ if (freeslot > STOBJ_NSLOTS(obj))
91
+ freeslot = STOBJ_NSLOTS(obj);
92
+ if (newscope->freeslot < freeslot)
93
+ newscope->freeslot = freeslot;
94
+ }
95
+ JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope);
96
+ js_DropScope(cx, scope, obj);
97
+ return newscope;
98
+ }
99
+
100
+ /*
101
+ * JSScope uses multiplicative hashing, _a la_ jsdhash.[ch], but specialized
102
+ * to minimize footprint. But if a scope has fewer than SCOPE_HASH_THRESHOLD
103
+ * entries, we use linear search and avoid allocating scope->table.
104
+ */
105
+ #define SCOPE_HASH_THRESHOLD 6
106
+ #define MIN_SCOPE_SIZE_LOG2 4
107
+ #define MIN_SCOPE_SIZE JS_BIT(MIN_SCOPE_SIZE_LOG2)
108
+ #define SCOPE_TABLE_NBYTES(n) ((n) * sizeof(JSScopeProperty *))
109
+
110
+ static void
111
+ InitMinimalScope(JSContext *cx, JSScope *scope)
112
+ {
113
+ js_LeaveTraceIfGlobalObject(cx, scope->object);
114
+ scope->shape = 0;
115
+ scope->hashShift = JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2;
116
+ scope->entryCount = scope->removedCount = 0;
117
+ scope->table = NULL;
118
+ scope->lastProp = NULL;
119
+ }
120
+
121
+ static JSBool
122
+ CreateScopeTable(JSContext *cx, JSScope *scope, JSBool report)
123
+ {
124
+ int sizeLog2;
125
+ JSScopeProperty *sprop, **spp;
126
+
127
+ JS_ASSERT(!scope->table);
128
+ JS_ASSERT(scope->lastProp);
129
+
130
+ if (scope->entryCount > SCOPE_HASH_THRESHOLD) {
131
+ /*
132
+ * Either we're creating a table for a large scope that was populated
133
+ * via property cache hit logic under JSOP_INITPROP, JSOP_SETNAME, or
134
+ * JSOP_SETPROP; or else calloc failed at least once already. In any
135
+ * event, let's try to grow, overallocating to hold at least twice the
136
+ * current population.
137
+ */
138
+ sizeLog2 = JS_CeilingLog2(2 * scope->entryCount);
139
+ scope->hashShift = JS_DHASH_BITS - sizeLog2;
140
+ } else {
141
+ JS_ASSERT(scope->hashShift == JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2);
142
+ sizeLog2 = MIN_SCOPE_SIZE_LOG2;
143
+ }
144
+
145
+ scope->table = (JSScopeProperty **)
146
+ calloc(JS_BIT(sizeLog2), sizeof(JSScopeProperty *));
147
+ if (!scope->table) {
148
+ if (report)
149
+ JS_ReportOutOfMemory(cx);
150
+ return JS_FALSE;
151
+ }
152
+ js_UpdateMallocCounter(cx, JS_BIT(sizeLog2) * sizeof(JSScopeProperty *));
153
+
154
+ scope->hashShift = JS_DHASH_BITS - sizeLog2;
155
+ for (sprop = scope->lastProp; sprop; sprop = sprop->parent) {
156
+ spp = js_SearchScope(scope, sprop->id, JS_TRUE);
157
+ SPROP_STORE_PRESERVING_COLLISION(spp, sprop);
158
+ }
159
+ return JS_TRUE;
160
+ }
161
+
162
+ JSScope *
163
+ js_NewScope(JSContext *cx, JSObjectOps *ops, JSClass *clasp, JSObject *obj)
164
+ {
165
+ JS_ASSERT(OPS_IS_NATIVE(ops));
166
+ JS_ASSERT(obj);
167
+
168
+ JSScope *scope = (JSScope *) JS_malloc(cx, sizeof(JSScope));
169
+ if (!scope)
170
+ return NULL;
171
+
172
+ scope->map.ops = ops;
173
+ scope->object = obj;
174
+ scope->nrefs = 1;
175
+ scope->freeslot = JSSLOT_FREE(clasp);
176
+ scope->flags = 0;
177
+ InitMinimalScope(cx, scope);
178
+
179
+ #ifdef JS_THREADSAFE
180
+ js_InitTitle(cx, &scope->title);
181
+ #endif
182
+ JS_RUNTIME_METER(cx->runtime, liveScopes);
183
+ JS_RUNTIME_METER(cx->runtime, totalScopes);
184
+ return scope;
185
+ }
186
+
187
+ #if defined DEBUG || defined JS_DUMP_PROPTREE_STATS
188
+ # include "jsprf.h"
189
+ # define LIVE_SCOPE_METER(cx,expr) JS_LOCK_RUNTIME_VOID(cx->runtime,expr)
190
+ #else
191
+ # define LIVE_SCOPE_METER(cx,expr) /* nothing */
192
+ #endif
193
+
194
+ void
195
+ js_DestroyScope(JSContext *cx, JSScope *scope)
196
+ {
197
+ #ifdef JS_THREADSAFE
198
+ js_FinishTitle(cx, &scope->title);
199
+ #endif
200
+ if (scope->table)
201
+ JS_free(cx, scope->table);
202
+
203
+ LIVE_SCOPE_METER(cx, cx->runtime->liveScopeProps -= scope->entryCount);
204
+ JS_RUNTIME_UNMETER(cx->runtime, liveScopes);
205
+ JS_free(cx, scope);
206
+ }
207
+
208
+ void
209
+ js_HoldScope(JSScope *scope)
210
+ {
211
+ JS_ASSERT(scope->nrefs >= 0);
212
+ JS_ATOMIC_INCREMENT(&scope->nrefs);
213
+ }
214
+
215
+ JSBool
216
+ js_DropScope(JSContext *cx, JSScope *scope, JSObject *obj)
217
+ {
218
+ JS_ASSERT(scope->nrefs > 0);
219
+ JS_ATOMIC_DECREMENT(&scope->nrefs);
220
+
221
+ if (scope->nrefs == 0) {
222
+ js_DestroyScope(cx, scope);
223
+ return false;
224
+ }
225
+ if (scope->object == obj)
226
+ scope->object = NULL;
227
+ return true;
228
+ }
229
+
230
+ #ifdef JS_DUMP_PROPTREE_STATS
231
+ typedef struct JSScopeStats {
232
+ jsrefcount searches;
233
+ jsrefcount hits;
234
+ jsrefcount misses;
235
+ jsrefcount hashes;
236
+ jsrefcount steps;
237
+ jsrefcount stepHits;
238
+ jsrefcount stepMisses;
239
+ jsrefcount adds;
240
+ jsrefcount redundantAdds;
241
+ jsrefcount addFailures;
242
+ jsrefcount changeFailures;
243
+ jsrefcount compresses;
244
+ jsrefcount grows;
245
+ jsrefcount removes;
246
+ jsrefcount removeFrees;
247
+ jsrefcount uselessRemoves;
248
+ jsrefcount shrinks;
249
+ } JSScopeStats;
250
+
251
+ JS_FRIEND_DATA(JSScopeStats) js_scope_stats = {0};
252
+
253
+ # define METER(x) JS_ATOMIC_INCREMENT(&js_scope_stats.x)
254
+ #else
255
+ # define METER(x) /* nothing */
256
+ #endif
257
+
258
+ JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4);
259
+ JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD);
260
+
261
+ #if JS_BYTES_PER_WORD == 4
262
+ # define HASH_ID(id) ((JSHashNumber)(id))
263
+ #elif JS_BYTES_PER_WORD == 8
264
+ # define HASH_ID(id) ((JSHashNumber)(id) ^ (JSHashNumber)((id) >> 32))
265
+ #else
266
+ # error "Unsupported configuration"
267
+ #endif
268
+
269
+ /*
270
+ * Double hashing needs the second hash code to be relatively prime to table
271
+ * size, so we simply make hash2 odd. The inputs to multiplicative hash are
272
+ * the golden ratio, expressed as a fixed-point 32 bit fraction, and the id
273
+ * itself.
274
+ */
275
+ #define SCOPE_HASH0(id) (HASH_ID(id) * JS_GOLDEN_RATIO)
276
+ #define SCOPE_HASH1(hash0,shift) ((hash0) >> (shift))
277
+ #define SCOPE_HASH2(hash0,log2,shift) ((((hash0) << (log2)) >> (shift)) | 1)
278
+
279
+ JS_FRIEND_API(JSScopeProperty **)
280
+ js_SearchScope(JSScope *scope, jsid id, JSBool adding)
281
+ {
282
+ JSHashNumber hash0, hash1, hash2;
283
+ int hashShift, sizeLog2;
284
+ JSScopeProperty *stored, *sprop, **spp, **firstRemoved;
285
+ uint32 sizeMask;
286
+
287
+ METER(searches);
288
+ if (!scope->table) {
289
+ /* Not enough properties to justify hashing: search from lastProp. */
290
+ JS_ASSERT(!SCOPE_HAD_MIDDLE_DELETE(scope));
291
+ for (spp = &scope->lastProp; (sprop = *spp); spp = &sprop->parent) {
292
+ if (sprop->id == id) {
293
+ METER(hits);
294
+ return spp;
295
+ }
296
+ }
297
+ METER(misses);
298
+ return spp;
299
+ }
300
+
301
+ /* Compute the primary hash address. */
302
+ METER(hashes);
303
+ hash0 = SCOPE_HASH0(id);
304
+ hashShift = scope->hashShift;
305
+ hash1 = SCOPE_HASH1(hash0, hashShift);
306
+ spp = scope->table + hash1;
307
+
308
+ /* Miss: return space for a new entry. */
309
+ stored = *spp;
310
+ if (SPROP_IS_FREE(stored)) {
311
+ METER(misses);
312
+ return spp;
313
+ }
314
+
315
+ /* Hit: return entry. */
316
+ sprop = SPROP_CLEAR_COLLISION(stored);
317
+ if (sprop && sprop->id == id) {
318
+ METER(hits);
319
+ return spp;
320
+ }
321
+
322
+ /* Collision: double hash. */
323
+ sizeLog2 = JS_DHASH_BITS - hashShift;
324
+ hash2 = SCOPE_HASH2(hash0, sizeLog2, hashShift);
325
+ sizeMask = JS_BITMASK(sizeLog2);
326
+
327
+ /* Save the first removed entry pointer so we can recycle it if adding. */
328
+ if (SPROP_IS_REMOVED(stored)) {
329
+ firstRemoved = spp;
330
+ } else {
331
+ firstRemoved = NULL;
332
+ if (adding && !SPROP_HAD_COLLISION(stored))
333
+ SPROP_FLAG_COLLISION(spp, sprop);
334
+ }
335
+
336
+ for (;;) {
337
+ METER(steps);
338
+ hash1 -= hash2;
339
+ hash1 &= sizeMask;
340
+ spp = scope->table + hash1;
341
+
342
+ stored = *spp;
343
+ if (SPROP_IS_FREE(stored)) {
344
+ METER(stepMisses);
345
+ return (adding && firstRemoved) ? firstRemoved : spp;
346
+ }
347
+
348
+ sprop = SPROP_CLEAR_COLLISION(stored);
349
+ if (sprop && sprop->id == id) {
350
+ METER(stepHits);
351
+ return spp;
352
+ }
353
+
354
+ if (SPROP_IS_REMOVED(stored)) {
355
+ if (!firstRemoved)
356
+ firstRemoved = spp;
357
+ } else {
358
+ if (adding && !SPROP_HAD_COLLISION(stored))
359
+ SPROP_FLAG_COLLISION(spp, sprop);
360
+ }
361
+ }
362
+
363
+ /* NOTREACHED */
364
+ return NULL;
365
+ }
366
+
367
+ static JSBool
368
+ ChangeScope(JSContext *cx, JSScope *scope, int change)
369
+ {
370
+ int oldlog2, newlog2;
371
+ uint32 oldsize, newsize, nbytes;
372
+ JSScopeProperty **table, **oldtable, **spp, **oldspp, *sprop;
373
+
374
+ if (!scope->table)
375
+ return CreateScopeTable(cx, scope, JS_TRUE);
376
+
377
+ /* Grow, shrink, or compress by changing scope->table. */
378
+ oldlog2 = JS_DHASH_BITS - scope->hashShift;
379
+ newlog2 = oldlog2 + change;
380
+ oldsize = JS_BIT(oldlog2);
381
+ newsize = JS_BIT(newlog2);
382
+ nbytes = SCOPE_TABLE_NBYTES(newsize);
383
+ table = (JSScopeProperty **) calloc(nbytes, 1);
384
+ if (!table) {
385
+ JS_ReportOutOfMemory(cx);
386
+ return JS_FALSE;
387
+ }
388
+
389
+ /* Now that we have a new table allocated, update scope members. */
390
+ scope->hashShift = JS_DHASH_BITS - newlog2;
391
+ scope->removedCount = 0;
392
+ oldtable = scope->table;
393
+ scope->table = table;
394
+
395
+ /* Treat the above calloc as a JS_malloc, to match CreateScopeTable. */
396
+ cx->runtime->gcMallocBytes += nbytes;
397
+
398
+ /* Copy only live entries, leaving removed and free ones behind. */
399
+ for (oldspp = oldtable; oldsize != 0; oldspp++) {
400
+ sprop = SPROP_FETCH(oldspp);
401
+ if (sprop) {
402
+ spp = js_SearchScope(scope, sprop->id, JS_TRUE);
403
+ JS_ASSERT(SPROP_IS_FREE(*spp));
404
+ *spp = sprop;
405
+ }
406
+ oldsize--;
407
+ }
408
+
409
+ /* Finally, free the old table storage. */
410
+ JS_free(cx, oldtable);
411
+ return JS_TRUE;
412
+ }
413
+
414
+ /*
415
+ * Take care to exclude the mark bits in case we're called from the GC.
416
+ */
417
+ #define SPROP_FLAGS_NOT_MATCHED (SPROP_MARK | SPROP_FLAG_SHAPE_REGEN)
418
+
419
+ static JSDHashNumber
420
+ js_HashScopeProperty(JSDHashTable *table, const void *key)
421
+ {
422
+ const JSScopeProperty *sprop = (const JSScopeProperty *)key;
423
+ JSDHashNumber hash;
424
+ JSPropertyOp gsop;
425
+
426
+ /* Accumulate from least to most random so the low bits are most random. */
427
+ hash = 0;
428
+ gsop = sprop->getter;
429
+ if (gsop)
430
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ (jsword)gsop;
431
+ gsop = sprop->setter;
432
+ if (gsop)
433
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ (jsword)gsop;
434
+
435
+ hash = JS_ROTATE_LEFT32(hash, 4)
436
+ ^ (sprop->flags & ~SPROP_FLAGS_NOT_MATCHED);
437
+
438
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->attrs;
439
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->shortid;
440
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->slot;
441
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->id;
442
+ return hash;
443
+ }
444
+
445
+ #define SPROP_MATCH(sprop, child) \
446
+ SPROP_MATCH_PARAMS(sprop, (child)->id, (child)->getter, (child)->setter, \
447
+ (child)->slot, (child)->attrs, (child)->flags, \
448
+ (child)->shortid)
449
+
450
+ #define SPROP_MATCH_PARAMS(sprop, aid, agetter, asetter, aslot, aattrs, \
451
+ aflags, ashortid) \
452
+ ((sprop)->id == (aid) && \
453
+ SPROP_MATCH_PARAMS_AFTER_ID(sprop, agetter, asetter, aslot, aattrs, \
454
+ aflags, ashortid))
455
+
456
+ #define SPROP_MATCH_PARAMS_AFTER_ID(sprop, agetter, asetter, aslot, aattrs, \
457
+ aflags, ashortid) \
458
+ ((sprop)->getter == (agetter) && \
459
+ (sprop)->setter == (asetter) && \
460
+ (sprop)->slot == (aslot) && \
461
+ (sprop)->attrs == (aattrs) && \
462
+ (((sprop)->flags ^ (aflags)) & ~SPROP_FLAGS_NOT_MATCHED) == 0 && \
463
+ (sprop)->shortid == (ashortid))
464
+
465
+ static JSBool
466
+ js_MatchScopeProperty(JSDHashTable *table,
467
+ const JSDHashEntryHdr *hdr,
468
+ const void *key)
469
+ {
470
+ const JSPropertyTreeEntry *entry = (const JSPropertyTreeEntry *)hdr;
471
+ const JSScopeProperty *sprop = entry->child;
472
+ const JSScopeProperty *kprop = (const JSScopeProperty *)key;
473
+
474
+ return SPROP_MATCH(sprop, kprop);
475
+ }
476
+
477
+ static const JSDHashTableOps PropertyTreeHashOps = {
478
+ JS_DHashAllocTable,
479
+ JS_DHashFreeTable,
480
+ js_HashScopeProperty,
481
+ js_MatchScopeProperty,
482
+ JS_DHashMoveEntryStub,
483
+ JS_DHashClearEntryStub,
484
+ JS_DHashFinalizeStub,
485
+ NULL
486
+ };
487
+
488
+ /*
489
+ * A property tree node on rt->propertyFreeList overlays the following prefix
490
+ * struct on JSScopeProperty.
491
+ */
492
+ typedef struct FreeNode {
493
+ jsid id;
494
+ JSScopeProperty *next;
495
+ JSScopeProperty **prevp;
496
+ } FreeNode;
497
+
498
+ #define FREENODE(sprop) ((FreeNode *) (sprop))
499
+
500
+ #define FREENODE_INSERT(list, sprop) \
501
+ JS_BEGIN_MACRO \
502
+ FREENODE(sprop)->next = (list); \
503
+ FREENODE(sprop)->prevp = &(list); \
504
+ if (list) \
505
+ FREENODE(list)->prevp = &FREENODE(sprop)->next; \
506
+ (list) = (sprop); \
507
+ JS_END_MACRO
508
+
509
+ #define FREENODE_REMOVE(sprop) \
510
+ JS_BEGIN_MACRO \
511
+ *FREENODE(sprop)->prevp = FREENODE(sprop)->next; \
512
+ if (FREENODE(sprop)->next) \
513
+ FREENODE(FREENODE(sprop)->next)->prevp = FREENODE(sprop)->prevp; \
514
+ JS_END_MACRO
515
+
516
+ /* NB: Called with rt->gcLock held. */
517
+ static JSScopeProperty *
518
+ NewScopeProperty(JSRuntime *rt)
519
+ {
520
+ JSScopeProperty *sprop;
521
+
522
+ sprop = rt->propertyFreeList;
523
+ if (sprop) {
524
+ FREENODE_REMOVE(sprop);
525
+ } else {
526
+ JS_ARENA_ALLOCATE_CAST(sprop, JSScopeProperty *,
527
+ &rt->propertyArenaPool,
528
+ sizeof(JSScopeProperty));
529
+ if (!sprop)
530
+ return NULL;
531
+ }
532
+
533
+ JS_RUNTIME_METER(rt, livePropTreeNodes);
534
+ JS_RUNTIME_METER(rt, totalPropTreeNodes);
535
+ return sprop;
536
+ }
537
+
538
+ #define CHUNKY_KIDS_TAG ((jsuword)1)
539
+ #define KIDS_IS_CHUNKY(kids) ((jsuword)(kids) & CHUNKY_KIDS_TAG)
540
+ #define KIDS_TO_CHUNK(kids) ((PropTreeKidsChunk *) \
541
+ ((jsuword)(kids) & ~CHUNKY_KIDS_TAG))
542
+ #define CHUNK_TO_KIDS(chunk) ((JSScopeProperty *) \
543
+ ((jsuword)(chunk) | CHUNKY_KIDS_TAG))
544
+ #define MAX_KIDS_PER_CHUNK 10
545
+ #define CHUNK_HASH_THRESHOLD 30
546
+
547
+ typedef struct PropTreeKidsChunk PropTreeKidsChunk;
548
+
549
+ struct PropTreeKidsChunk {
550
+ JSScopeProperty *kids[MAX_KIDS_PER_CHUNK];
551
+ JSDHashTable *table;
552
+ PropTreeKidsChunk *next;
553
+ };
554
+
555
+ static PropTreeKidsChunk *
556
+ NewPropTreeKidsChunk(JSRuntime *rt)
557
+ {
558
+ PropTreeKidsChunk *chunk;
559
+
560
+ chunk = (PropTreeKidsChunk *) calloc(1, sizeof *chunk);
561
+ if (!chunk)
562
+ return NULL;
563
+ JS_ASSERT(((jsuword)chunk & CHUNKY_KIDS_TAG) == 0);
564
+ JS_RUNTIME_METER(rt, propTreeKidsChunks);
565
+ return chunk;
566
+ }
567
+
568
+ static void
569
+ DestroyPropTreeKidsChunk(JSRuntime *rt, PropTreeKidsChunk *chunk)
570
+ {
571
+ JS_RUNTIME_UNMETER(rt, propTreeKidsChunks);
572
+ if (chunk->table)
573
+ JS_DHashTableDestroy(chunk->table);
574
+ free(chunk);
575
+ }
576
+
577
+ /* NB: Called with rt->gcLock held. */
578
+ static JSBool
579
+ InsertPropertyTreeChild(JSRuntime *rt, JSScopeProperty *parent,
580
+ JSScopeProperty *child, PropTreeKidsChunk *sweptChunk)
581
+ {
582
+ JSDHashTable *table;
583
+ JSPropertyTreeEntry *entry;
584
+ JSScopeProperty **childp, *kids, *sprop;
585
+ PropTreeKidsChunk *chunk, **chunkp;
586
+ uintN i;
587
+
588
+ JS_ASSERT(!parent || child->parent != parent);
589
+
590
+ if (!parent) {
591
+ table = &rt->propertyTreeHash;
592
+ entry = (JSPropertyTreeEntry *)
593
+ JS_DHashTableOperate(table, child, JS_DHASH_ADD);
594
+ if (!entry)
595
+ return JS_FALSE;
596
+ childp = &entry->child;
597
+ sprop = *childp;
598
+ if (!sprop) {
599
+ *childp = child;
600
+ } else {
601
+ /*
602
+ * A "Duplicate child" case.
603
+ *
604
+ * We can't do away with child, as at least one live scope entry
605
+ * still points at it. What's more, that scope's lastProp chains
606
+ * through an ancestor line to reach child, and js_Enumerate and
607
+ * others count on this linkage. We must leave child out of the
608
+ * hash table, and not require it to be there when we eventually
609
+ * GC it (see RemovePropertyTreeChild, below).
610
+ *
611
+ * It is necessary to leave the duplicate child out of the hash
612
+ * table to preserve entry uniqueness. It is safe to leave the
613
+ * child out of the hash table (unlike the duplicate child cases
614
+ * below), because the child's parent link will be null, which
615
+ * can't dangle.
616
+ */
617
+ JS_ASSERT(sprop != child && SPROP_MATCH(sprop, child));
618
+ JS_RUNTIME_METER(rt, duplicatePropTreeNodes);
619
+ }
620
+ } else {
621
+ childp = &parent->kids;
622
+ kids = *childp;
623
+ if (kids) {
624
+ if (KIDS_IS_CHUNKY(kids)) {
625
+ chunk = KIDS_TO_CHUNK(kids);
626
+
627
+ table = chunk->table;
628
+ if (table) {
629
+ entry = (JSPropertyTreeEntry *)
630
+ JS_DHashTableOperate(table, child, JS_DHASH_ADD);
631
+ if (!entry)
632
+ return JS_FALSE;
633
+ if (!entry->child) {
634
+ entry->child = child;
635
+ while (chunk->next)
636
+ chunk = chunk->next;
637
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
638
+ childp = &chunk->kids[i];
639
+ sprop = *childp;
640
+ if (!sprop)
641
+ goto insert;
642
+ }
643
+ chunkp = &chunk->next;
644
+ goto new_chunk;
645
+ }
646
+ }
647
+
648
+ do {
649
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
650
+ childp = &chunk->kids[i];
651
+ sprop = *childp;
652
+ if (!sprop)
653
+ goto insert;
654
+
655
+ JS_ASSERT(sprop != child);
656
+ if (SPROP_MATCH(sprop, child)) {
657
+ /*
658
+ * Duplicate child, see comment above. In this
659
+ * case, we must let the duplicate be inserted at
660
+ * this level in the tree, so we keep iterating,
661
+ * looking for an empty slot in which to insert.
662
+ */
663
+ JS_ASSERT(sprop != child);
664
+ JS_RUNTIME_METER(rt, duplicatePropTreeNodes);
665
+ }
666
+ }
667
+ chunkp = &chunk->next;
668
+ } while ((chunk = *chunkp) != NULL);
669
+
670
+ new_chunk:
671
+ if (sweptChunk) {
672
+ chunk = sweptChunk;
673
+ } else {
674
+ chunk = NewPropTreeKidsChunk(rt);
675
+ if (!chunk)
676
+ return JS_FALSE;
677
+ }
678
+ *chunkp = chunk;
679
+ childp = &chunk->kids[0];
680
+ } else {
681
+ sprop = kids;
682
+ JS_ASSERT(sprop != child);
683
+ if (SPROP_MATCH(sprop, child)) {
684
+ /*
685
+ * Duplicate child, see comment above. Once again, we
686
+ * must let duplicates created by deletion pile up in a
687
+ * kids-chunk-list, in order to find them when sweeping
688
+ * and thereby avoid dangling parent pointers.
689
+ */
690
+ JS_RUNTIME_METER(rt, duplicatePropTreeNodes);
691
+ }
692
+ if (sweptChunk) {
693
+ chunk = sweptChunk;
694
+ } else {
695
+ chunk = NewPropTreeKidsChunk(rt);
696
+ if (!chunk)
697
+ return JS_FALSE;
698
+ }
699
+ parent->kids = CHUNK_TO_KIDS(chunk);
700
+ chunk->kids[0] = sprop;
701
+ childp = &chunk->kids[1];
702
+ }
703
+ }
704
+ insert:
705
+ *childp = child;
706
+ }
707
+
708
+ child->parent = parent;
709
+ return JS_TRUE;
710
+ }
711
+
712
+ /* NB: Called with rt->gcLock held. */
713
+ static PropTreeKidsChunk *
714
+ RemovePropertyTreeChild(JSRuntime *rt, JSScopeProperty *child)
715
+ {
716
+ PropTreeKidsChunk *freeChunk;
717
+ JSScopeProperty *parent, *kids, *kid;
718
+ JSDHashTable *table;
719
+ PropTreeKidsChunk *list, *chunk, **chunkp, *lastChunk;
720
+ uintN i, j;
721
+ JSPropertyTreeEntry *entry;
722
+
723
+ freeChunk = NULL;
724
+ parent = child->parent;
725
+ if (!parent) {
726
+ /*
727
+ * Don't remove child if it is not in rt->propertyTreeHash, but only
728
+ * matches a root child in the table that has compatible members. See
729
+ * the "Duplicate child" comments in InsertPropertyTreeChild, above.
730
+ */
731
+ table = &rt->propertyTreeHash;
732
+ } else {
733
+ kids = parent->kids;
734
+ if (KIDS_IS_CHUNKY(kids)) {
735
+ list = chunk = KIDS_TO_CHUNK(kids);
736
+ chunkp = &list;
737
+ table = chunk->table;
738
+
739
+ do {
740
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
741
+ if (chunk->kids[i] == child) {
742
+ lastChunk = chunk;
743
+ if (!lastChunk->next) {
744
+ j = i + 1;
745
+ } else {
746
+ j = 0;
747
+ do {
748
+ chunkp = &lastChunk->next;
749
+ lastChunk = *chunkp;
750
+ } while (lastChunk->next);
751
+ }
752
+ for (; j < MAX_KIDS_PER_CHUNK; j++) {
753
+ if (!lastChunk->kids[j])
754
+ break;
755
+ }
756
+ --j;
757
+ if (chunk != lastChunk || j > i)
758
+ chunk->kids[i] = lastChunk->kids[j];
759
+ lastChunk->kids[j] = NULL;
760
+ if (j == 0) {
761
+ *chunkp = NULL;
762
+ if (!list)
763
+ parent->kids = NULL;
764
+ freeChunk = lastChunk;
765
+ }
766
+ goto out;
767
+ }
768
+ }
769
+
770
+ chunkp = &chunk->next;
771
+ } while ((chunk = *chunkp) != NULL);
772
+ } else {
773
+ table = NULL;
774
+ kid = kids;
775
+ if (kid == child)
776
+ parent->kids = NULL;
777
+ }
778
+ }
779
+
780
+ out:
781
+ if (table) {
782
+ entry = (JSPropertyTreeEntry *)
783
+ JS_DHashTableOperate(table, child, JS_DHASH_LOOKUP);
784
+
785
+ if (entry->child == child)
786
+ JS_DHashTableRawRemove(table, &entry->hdr);
787
+ }
788
+ return freeChunk;
789
+ }
790
+
791
+ static JSDHashTable *
792
+ HashChunks(PropTreeKidsChunk *chunk, uintN n)
793
+ {
794
+ JSDHashTable *table;
795
+ uintN i;
796
+ JSScopeProperty *sprop;
797
+ JSPropertyTreeEntry *entry;
798
+
799
+ table = JS_NewDHashTable(&PropertyTreeHashOps, NULL,
800
+ sizeof(JSPropertyTreeEntry),
801
+ JS_DHASH_DEFAULT_CAPACITY(n + 1));
802
+ if (!table)
803
+ return NULL;
804
+ do {
805
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
806
+ sprop = chunk->kids[i];
807
+ if (!sprop)
808
+ break;
809
+ entry = (JSPropertyTreeEntry *)
810
+ JS_DHashTableOperate(table, sprop, JS_DHASH_ADD);
811
+ entry->child = sprop;
812
+ }
813
+ } while ((chunk = chunk->next) != NULL);
814
+ return table;
815
+ }
816
+
817
+ /*
818
+ * Called without cx->runtime->gcLock held. This function acquires that lock
819
+ * only when inserting a new child. Thus there may be races to find or add a
820
+ * node that result in duplicates. We expect such races to be rare!
821
+ *
822
+ * We use rt->gcLock, not rt->rtLock, to avoid nesting the former inside the
823
+ * latter in js_GenerateShape below.
824
+ */
825
+ static JSScopeProperty *
826
+ GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent,
827
+ JSScopeProperty *child)
828
+ {
829
+ JSRuntime *rt;
830
+ JSDHashTable *table;
831
+ JSPropertyTreeEntry *entry;
832
+ JSScopeProperty *sprop;
833
+ PropTreeKidsChunk *chunk;
834
+ uintN i, n;
835
+
836
+ rt = cx->runtime;
837
+ if (!parent) {
838
+ JS_LOCK_GC(rt);
839
+
840
+ table = &rt->propertyTreeHash;
841
+ entry = (JSPropertyTreeEntry *)
842
+ JS_DHashTableOperate(table, child, JS_DHASH_ADD);
843
+ if (!entry)
844
+ goto out_of_memory;
845
+
846
+ sprop = entry->child;
847
+ if (sprop)
848
+ goto out;
849
+ } else {
850
+ /*
851
+ * Because chunks are appended at the end and never deleted except by
852
+ * the GC, we can search without taking the runtime's GC lock. We may
853
+ * miss a matching sprop added by another thread, and make a duplicate
854
+ * one, but that is an unlikely, therefore small, cost. The property
855
+ * tree has extremely low fan-out below its root in popular embeddings
856
+ * with real-world workloads.
857
+ *
858
+ * Patterns such as defining closures that capture a constructor's
859
+ * environment as getters or setters on the new object that is passed
860
+ * in as |this| can significantly increase fan-out below the property
861
+ * tree root -- see bug 335700 for details.
862
+ */
863
+ entry = NULL;
864
+ sprop = parent->kids;
865
+ if (sprop) {
866
+ if (KIDS_IS_CHUNKY(sprop)) {
867
+ chunk = KIDS_TO_CHUNK(sprop);
868
+
869
+ table = chunk->table;
870
+ if (table) {
871
+ JS_LOCK_GC(rt);
872
+ entry = (JSPropertyTreeEntry *)
873
+ JS_DHashTableOperate(table, child, JS_DHASH_LOOKUP);
874
+ sprop = entry->child;
875
+ if (sprop) {
876
+ JS_UNLOCK_GC(rt);
877
+ return sprop;
878
+ }
879
+ goto locked_not_found;
880
+ }
881
+
882
+ n = 0;
883
+ do {
884
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
885
+ sprop = chunk->kids[i];
886
+ if (!sprop) {
887
+ n += i;
888
+ if (n >= CHUNK_HASH_THRESHOLD) {
889
+ chunk = KIDS_TO_CHUNK(parent->kids);
890
+ if (!chunk->table) {
891
+ table = HashChunks(chunk, n);
892
+ JS_LOCK_GC(rt);
893
+ if (!table)
894
+ goto out_of_memory;
895
+ if (chunk->table)
896
+ JS_DHashTableDestroy(table);
897
+ else
898
+ chunk->table = table;
899
+ goto locked_not_found;
900
+ }
901
+ }
902
+ goto not_found;
903
+ }
904
+
905
+ if (SPROP_MATCH(sprop, child))
906
+ return sprop;
907
+ }
908
+ n += MAX_KIDS_PER_CHUNK;
909
+ } while ((chunk = chunk->next) != NULL);
910
+ } else {
911
+ if (SPROP_MATCH(sprop, child))
912
+ return sprop;
913
+ }
914
+ }
915
+
916
+ not_found:
917
+ JS_LOCK_GC(rt);
918
+ }
919
+
920
+ locked_not_found:
921
+ sprop = NewScopeProperty(rt);
922
+ if (!sprop)
923
+ goto out_of_memory;
924
+
925
+ sprop->id = child->id;
926
+ sprop->getter = child->getter;
927
+ sprop->setter = child->setter;
928
+ sprop->slot = child->slot;
929
+ sprop->attrs = child->attrs;
930
+ sprop->flags = child->flags;
931
+ sprop->shortid = child->shortid;
932
+ sprop->parent = sprop->kids = NULL;
933
+ sprop->shape = js_GenerateShape(cx, JS_TRUE);
934
+
935
+ if (!parent) {
936
+ entry->child = sprop;
937
+ } else {
938
+ if (!InsertPropertyTreeChild(rt, parent, sprop, NULL))
939
+ goto out_of_memory;
940
+ }
941
+
942
+ out:
943
+ JS_UNLOCK_GC(rt);
944
+ return sprop;
945
+
946
+ out_of_memory:
947
+ JS_UNLOCK_GC(rt);
948
+ JS_ReportOutOfMemory(cx);
949
+ return NULL;
950
+ }
951
+
952
+ #ifdef DEBUG_notbrendan
953
+ #define CHECK_ANCESTOR_LINE(scope, sparse) \
954
+ JS_BEGIN_MACRO \
955
+ if ((scope)->table) CheckAncestorLine(scope, sparse); \
956
+ JS_END_MACRO
957
+
958
+ static void
959
+ CheckAncestorLine(JSScope *scope, JSBool sparse)
960
+ {
961
+ uint32 size;
962
+ JSScopeProperty **spp, **start, **end, *ancestorLine, *sprop, *aprop;
963
+ uint32 entryCount, ancestorCount;
964
+
965
+ ancestorLine = SCOPE_LAST_PROP(scope);
966
+ if (ancestorLine)
967
+ JS_ASSERT(SCOPE_HAS_PROPERTY(scope, ancestorLine));
968
+
969
+ entryCount = 0;
970
+ size = SCOPE_CAPACITY(scope);
971
+ start = scope->table;
972
+ for (spp = start, end = start + size; spp < end; spp++) {
973
+ sprop = SPROP_FETCH(spp);
974
+ if (sprop) {
975
+ entryCount++;
976
+ for (aprop = ancestorLine; aprop; aprop = aprop->parent) {
977
+ if (aprop == sprop)
978
+ break;
979
+ }
980
+ JS_ASSERT(aprop);
981
+ }
982
+ }
983
+ JS_ASSERT(entryCount == scope->entryCount);
984
+
985
+ ancestorCount = 0;
986
+ for (sprop = ancestorLine; sprop; sprop = sprop->parent) {
987
+ if (SCOPE_HAD_MIDDLE_DELETE(scope) &&
988
+ !SCOPE_HAS_PROPERTY(scope, sprop)) {
989
+ JS_ASSERT(sparse);
990
+ continue;
991
+ }
992
+ ancestorCount++;
993
+ }
994
+ JS_ASSERT(ancestorCount == scope->entryCount);
995
+ }
996
+ #else
997
+ #define CHECK_ANCESTOR_LINE(scope, sparse) /* nothing */
998
+ #endif
999
+
1000
+ static void
1001
+ ReportReadOnlyScope(JSContext *cx, JSScope *scope)
1002
+ {
1003
+ JSString *str;
1004
+ const char *bytes;
1005
+
1006
+ str = js_ValueToString(cx, OBJECT_TO_JSVAL(scope->object));
1007
+ if (!str)
1008
+ return;
1009
+ bytes = js_GetStringBytes(cx, str);
1010
+ if (!bytes)
1011
+ return;
1012
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_READ_ONLY, bytes);
1013
+ }
1014
+
1015
+ JSScopeProperty *
1016
+ js_AddScopeProperty(JSContext *cx, JSScope *scope, jsid id,
1017
+ JSPropertyOp getter, JSPropertyOp setter, uint32 slot,
1018
+ uintN attrs, uintN flags, intN shortid)
1019
+ {
1020
+ JSScopeProperty **spp, *sprop, *overwriting, **spvec, **spp2, child;
1021
+ uint32 size, splen, i;
1022
+ int change;
1023
+ JSTempValueRooter tvr;
1024
+
1025
+ JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope));
1026
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
1027
+
1028
+ /*
1029
+ * You can't add properties to a sealed scope. But note well that you can
1030
+ * change property attributes in a sealed scope, even though that replaces
1031
+ * a JSScopeProperty * in the scope's hash table -- but no id is added, so
1032
+ * the scope remains sealed.
1033
+ */
1034
+ if (SCOPE_IS_SEALED(scope)) {
1035
+ ReportReadOnlyScope(cx, scope);
1036
+ return NULL;
1037
+ }
1038
+
1039
+ /*
1040
+ * Normalize stub getter and setter values for faster is-stub testing in
1041
+ * the SPROP_CALL_[GS]ETTER macros.
1042
+ */
1043
+ if (getter == JS_PropertyStub)
1044
+ getter = NULL;
1045
+ if (setter == JS_PropertyStub)
1046
+ setter = NULL;
1047
+
1048
+ /*
1049
+ * Search for id in order to claim its entry, allocating a property tree
1050
+ * node if one doesn't already exist for our parameters.
1051
+ */
1052
+ spp = js_SearchScope(scope, id, JS_TRUE);
1053
+ sprop = overwriting = SPROP_FETCH(spp);
1054
+ if (!sprop) {
1055
+ /* Check whether we need to grow, if the load factor is >= .75. */
1056
+ size = SCOPE_CAPACITY(scope);
1057
+ if (scope->entryCount + scope->removedCount >= size - (size >> 2)) {
1058
+ if (scope->removedCount >= size >> 2) {
1059
+ METER(compresses);
1060
+ change = 0;
1061
+ } else {
1062
+ METER(grows);
1063
+ change = 1;
1064
+ }
1065
+ if (!ChangeScope(cx, scope, change) &&
1066
+ scope->entryCount + scope->removedCount == size - 1) {
1067
+ METER(addFailures);
1068
+ return NULL;
1069
+ }
1070
+ spp = js_SearchScope(scope, id, JS_TRUE);
1071
+ JS_ASSERT(!SPROP_FETCH(spp));
1072
+ }
1073
+ } else {
1074
+ /* Property exists: js_SearchScope must have returned a valid entry. */
1075
+ JS_ASSERT(!SPROP_IS_REMOVED(*spp));
1076
+
1077
+ /*
1078
+ * If all property members match, this is a redundant add and we can
1079
+ * return early. If the caller wants to allocate a slot, but doesn't
1080
+ * care which slot, copy sprop->slot into slot so we can match sprop,
1081
+ * if all other members match.
1082
+ */
1083
+ if (!(attrs & JSPROP_SHARED) &&
1084
+ slot == SPROP_INVALID_SLOT &&
1085
+ SPROP_HAS_VALID_SLOT(sprop, scope)) {
1086
+ slot = sprop->slot;
1087
+ }
1088
+ if (SPROP_MATCH_PARAMS_AFTER_ID(sprop, getter, setter, slot, attrs,
1089
+ flags, shortid)) {
1090
+ METER(redundantAdds);
1091
+ return sprop;
1092
+ }
1093
+
1094
+ /*
1095
+ * If we are clearing sprop to force the existing property that it
1096
+ * describes to be overwritten, then we have to unlink sprop from the
1097
+ * ancestor line at scope->lastProp, lazily if sprop is not lastProp.
1098
+ * And we must remove the entry at *spp, precisely so the lazy "middle
1099
+ * delete" fixup code further below won't find sprop in scope->table,
1100
+ * in spite of sprop being on the ancestor line.
1101
+ *
1102
+ * When we finally succeed in finding or creating a new sprop
1103
+ * and storing its pointer at *spp, we'll use the |overwriting|
1104
+ * local saved when we first looked up id to decide whether we're
1105
+ * indeed creating a new entry, or merely overwriting an existing
1106
+ * property.
1107
+ */
1108
+ if (sprop == SCOPE_LAST_PROP(scope)) {
1109
+ do {
1110
+ SCOPE_REMOVE_LAST_PROP(scope);
1111
+ if (!SCOPE_HAD_MIDDLE_DELETE(scope))
1112
+ break;
1113
+ sprop = SCOPE_LAST_PROP(scope);
1114
+ } while (sprop && !SCOPE_HAS_PROPERTY(scope, sprop));
1115
+ } else if (!SCOPE_HAD_MIDDLE_DELETE(scope)) {
1116
+ /*
1117
+ * If we have no hash table yet, we need one now. The middle
1118
+ * delete code is simple-minded that way!
1119
+ */
1120
+ if (!scope->table) {
1121
+ if (!CreateScopeTable(cx, scope, JS_TRUE))
1122
+ return NULL;
1123
+ spp = js_SearchScope(scope, id, JS_TRUE);
1124
+ sprop = overwriting = SPROP_FETCH(spp);
1125
+ }
1126
+ SCOPE_SET_MIDDLE_DELETE(scope);
1127
+ }
1128
+ js_MakeScopeShapeUnique(cx, scope);
1129
+
1130
+ /*
1131
+ * If we fail later on trying to find or create a new sprop, we will
1132
+ * goto fail_overwrite and restore *spp from |overwriting|. Note that
1133
+ * we don't bother to keep scope->removedCount in sync, because we'll
1134
+ * fix up *spp and scope->entryCount shortly, no matter how control
1135
+ * flow returns from this function.
1136
+ */
1137
+ if (scope->table)
1138
+ SPROP_STORE_PRESERVING_COLLISION(spp, NULL);
1139
+ scope->entryCount--;
1140
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
1141
+ sprop = NULL;
1142
+ }
1143
+
1144
+ if (!sprop) {
1145
+ /*
1146
+ * If properties were deleted from the middle of the list starting at
1147
+ * scope->lastProp, we may need to fork the property tree and squeeze
1148
+ * all deleted properties out of scope's ancestor line. Otherwise we
1149
+ * risk adding a node with the same id as a "middle" node, violating
1150
+ * the rule that properties along an ancestor line have distinct ids.
1151
+ */
1152
+ if (SCOPE_HAD_MIDDLE_DELETE(scope)) {
1153
+ JS_ASSERT(scope->table);
1154
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
1155
+
1156
+ /*
1157
+ * Our forking heuristic tries to balance the desire to avoid
1158
+ * over-compacting (over-forking) against the desire to
1159
+ * *periodically* fork anyways, in order to prevent paying scan
1160
+ * penalties on each insert indefinitely, on a lineage with only
1161
+ * a few old middle-deletions. So we fork if either:
1162
+ *
1163
+ * - A quick scan finds a true conflict.
1164
+ * - We are passing through a doubling-threshold in size and
1165
+ * have accumulated a nonzero count of uncompacted deletions.
1166
+ */
1167
+
1168
+ bool conflicts = false;
1169
+ uint32 count = 0;
1170
+ uint32 threshold = JS_BIT(JS_CeilingLog2(scope->entryCount));
1171
+ for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
1172
+ ++count;
1173
+ if (sprop->id == id) {
1174
+ conflicts = true;
1175
+ break;
1176
+ }
1177
+ }
1178
+
1179
+ if (conflicts || count > threshold) {
1180
+ /*
1181
+ * Enumerate live entries in scope->table using a temporary
1182
+ * vector, by walking the (possibly sparse, due to deletions)
1183
+ * ancestor line from scope->lastProp.
1184
+ */
1185
+ splen = scope->entryCount;
1186
+ JS_ASSERT(splen != 0);
1187
+ spvec = (JSScopeProperty **)
1188
+ JS_malloc(cx, SCOPE_TABLE_NBYTES(splen));
1189
+ if (!spvec)
1190
+ goto fail_overwrite;
1191
+ i = splen;
1192
+ sprop = SCOPE_LAST_PROP(scope);
1193
+ JS_ASSERT(sprop);
1194
+ do {
1195
+ /*
1196
+ * NB: test SCOPE_GET_PROPERTY, not SCOPE_HAS_PROPERTY,
1197
+ * as the latter macro insists that sprop->id maps to
1198
+ * sprop, while the former simply tests whether sprop->id
1199
+ * is bound in scope.
1200
+ */
1201
+ if (!SCOPE_GET_PROPERTY(scope, sprop->id))
1202
+ continue;
1203
+
1204
+ JS_ASSERT(sprop != overwriting);
1205
+ JS_ASSERT(i != 0);
1206
+ spvec[--i] = sprop;
1207
+ } while ((sprop = sprop->parent) != NULL);
1208
+ JS_ASSERT(i == 0);
1209
+
1210
+ /*
1211
+ * Now loop forward through spvec, forking the property tree
1212
+ * whenever we see a "parent gap" due to deletions from scope.
1213
+ * NB: sprop is null on first entry to the loop body.
1214
+ */
1215
+ do {
1216
+ if (spvec[i]->parent == sprop) {
1217
+ sprop = spvec[i];
1218
+ } else {
1219
+ sprop = GetPropertyTreeChild(cx, sprop, spvec[i]);
1220
+ if (!sprop) {
1221
+ JS_free(cx, spvec);
1222
+ goto fail_overwrite;
1223
+ }
1224
+
1225
+ spp2 = js_SearchScope(scope, sprop->id, JS_FALSE);
1226
+ JS_ASSERT(SPROP_FETCH(spp2) == spvec[i]);
1227
+ SPROP_STORE_PRESERVING_COLLISION(spp2, sprop);
1228
+ }
1229
+ } while (++i < splen);
1230
+ JS_free(cx, spvec);
1231
+
1232
+ /*
1233
+ * Now sprop points to the last property in scope, where the
1234
+ * ancestor line from sprop to the root is dense w.r.t. scope:
1235
+ * it contains no nodes not mapped by scope->table.
1236
+ */
1237
+ scope->lastProp = sprop;
1238
+ CHECK_ANCESTOR_LINE(scope, JS_FALSE);
1239
+ JS_RUNTIME_METER(cx->runtime, middleDeleteFixups);
1240
+ SCOPE_CLR_MIDDLE_DELETE(scope);
1241
+ }
1242
+ }
1243
+
1244
+ /*
1245
+ * Aliases share another property's slot, passed in the |slot| param.
1246
+ * Shared properties have no slot. Unshared properties that do not
1247
+ * alias another property's slot get one here, but may lose it due to
1248
+ * a JS_ClearScope call.
1249
+ */
1250
+ if (!(flags & SPROP_IS_ALIAS)) {
1251
+ if (attrs & JSPROP_SHARED) {
1252
+ slot = SPROP_INVALID_SLOT;
1253
+ } else {
1254
+ /*
1255
+ * We may have set slot from a nearly-matching sprop, above.
1256
+ * If so, we're overwriting that nearly-matching sprop, so we
1257
+ * can reuse its slot -- we don't need to allocate a new one.
1258
+ * Similarly, we use a specific slot if provided by the caller.
1259
+ */
1260
+ if (slot == SPROP_INVALID_SLOT &&
1261
+ !js_AllocSlot(cx, scope->object, &slot)) {
1262
+ goto fail_overwrite;
1263
+ }
1264
+ }
1265
+ }
1266
+
1267
+ /*
1268
+ * Check for a watchpoint on a deleted property; if one exists, change
1269
+ * setter to js_watch_set.
1270
+ * XXXbe this could get expensive with lots of watchpoints...
1271
+ */
1272
+ if (!JS_CLIST_IS_EMPTY(&cx->runtime->watchPointList) &&
1273
+ js_FindWatchPoint(cx->runtime, scope, id)) {
1274
+ if (overwriting)
1275
+ JS_PUSH_TEMP_ROOT_SPROP(cx, overwriting, &tvr);
1276
+ setter = js_WrapWatchedSetter(cx, id, attrs, setter);
1277
+ if (overwriting)
1278
+ JS_POP_TEMP_ROOT(cx, &tvr);
1279
+ if (!setter)
1280
+ goto fail_overwrite;
1281
+ }
1282
+
1283
+ /* Find or create a property tree node labeled by our arguments. */
1284
+ child.id = id;
1285
+ child.getter = getter;
1286
+ child.setter = setter;
1287
+ child.slot = slot;
1288
+ child.attrs = attrs;
1289
+ child.flags = flags;
1290
+ child.shortid = shortid;
1291
+ sprop = GetPropertyTreeChild(cx, scope->lastProp, &child);
1292
+ if (!sprop)
1293
+ goto fail_overwrite;
1294
+
1295
+ /*
1296
+ * The scope's shape defaults to its last property's shape, but may
1297
+ * be regenerated later as the scope diverges (from the property cache
1298
+ * point of view) from the structural type associated with sprop.
1299
+ */
1300
+ js_ExtendScopeShape(cx, scope, sprop);
1301
+
1302
+ /* Store the tree node pointer in the table entry for id. */
1303
+ if (scope->table)
1304
+ SPROP_STORE_PRESERVING_COLLISION(spp, sprop);
1305
+ scope->entryCount++;
1306
+ scope->lastProp = sprop;
1307
+ CHECK_ANCESTOR_LINE(scope, JS_FALSE);
1308
+ #ifdef DEBUG
1309
+ if (!overwriting) {
1310
+ LIVE_SCOPE_METER(cx, ++cx->runtime->liveScopeProps);
1311
+ JS_RUNTIME_METER(cx->runtime, totalScopeProps);
1312
+ }
1313
+ #endif
1314
+
1315
+ /*
1316
+ * If we reach the hashing threshold, try to allocate scope->table.
1317
+ * If we can't (a rare event, preceded by swapping to death on most
1318
+ * modern OSes), stick with linear search rather than whining about
1319
+ * this little set-back. Therefore we must test !scope->table and
1320
+ * scope->entryCount >= SCOPE_HASH_THRESHOLD, not merely whether the
1321
+ * entry count just reached the threshold.
1322
+ */
1323
+ if (!scope->table && scope->entryCount >= SCOPE_HASH_THRESHOLD)
1324
+ (void) CreateScopeTable(cx, scope, JS_FALSE);
1325
+ }
1326
+
1327
+ jsuint index;
1328
+ if (js_IdIsIndex(sprop->id, &index))
1329
+ SCOPE_SET_INDEXED_PROPERTIES(scope);
1330
+
1331
+ METER(adds);
1332
+ return sprop;
1333
+
1334
+ fail_overwrite:
1335
+ if (overwriting) {
1336
+ /*
1337
+ * We may or may not have forked overwriting out of scope's ancestor
1338
+ * line, so we must check (the alternative is to set a flag above, but
1339
+ * that hurts the common, non-error case). If we did fork overwriting
1340
+ * out, we'll add it back at scope->lastProp. This means enumeration
1341
+ * order can change due to a failure to overwrite an id.
1342
+ * XXXbe very minor incompatibility
1343
+ */
1344
+ for (sprop = SCOPE_LAST_PROP(scope); ; sprop = sprop->parent) {
1345
+ if (!sprop) {
1346
+ sprop = SCOPE_LAST_PROP(scope);
1347
+ if (overwriting->parent == sprop) {
1348
+ scope->lastProp = overwriting;
1349
+ } else {
1350
+ sprop = GetPropertyTreeChild(cx, sprop, overwriting);
1351
+ if (sprop) {
1352
+ JS_ASSERT(sprop != overwriting);
1353
+ scope->lastProp = sprop;
1354
+ }
1355
+ overwriting = sprop;
1356
+ }
1357
+ break;
1358
+ }
1359
+ if (sprop == overwriting)
1360
+ break;
1361
+ }
1362
+ if (overwriting) {
1363
+ if (scope->table)
1364
+ SPROP_STORE_PRESERVING_COLLISION(spp, overwriting);
1365
+ scope->entryCount++;
1366
+ }
1367
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
1368
+ }
1369
+ METER(addFailures);
1370
+ return NULL;
1371
+ }
1372
+
1373
+ JSScopeProperty *
1374
+ js_ChangeScopePropertyAttrs(JSContext *cx, JSScope *scope,
1375
+ JSScopeProperty *sprop, uintN attrs, uintN mask,
1376
+ JSPropertyOp getter, JSPropertyOp setter)
1377
+ {
1378
+ JSScopeProperty child, *newsprop, **spp;
1379
+
1380
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
1381
+
1382
+ /* Allow only shared (slot-less) => unshared (slot-full) transition. */
1383
+ attrs |= sprop->attrs & mask;
1384
+ JS_ASSERT(!((attrs ^ sprop->attrs) & JSPROP_SHARED) ||
1385
+ !(attrs & JSPROP_SHARED));
1386
+ if (getter == JS_PropertyStub)
1387
+ getter = NULL;
1388
+ if (setter == JS_PropertyStub)
1389
+ setter = NULL;
1390
+ if (sprop->attrs == attrs &&
1391
+ sprop->getter == getter &&
1392
+ sprop->setter == setter) {
1393
+ return sprop;
1394
+ }
1395
+
1396
+ child.id = sprop->id;
1397
+ child.getter = getter;
1398
+ child.setter = setter;
1399
+ child.slot = sprop->slot;
1400
+ child.attrs = attrs;
1401
+ child.flags = sprop->flags;
1402
+ child.shortid = sprop->shortid;
1403
+
1404
+ if (SCOPE_LAST_PROP(scope) == sprop) {
1405
+ /*
1406
+ * Optimize the case where the last property added to scope is changed
1407
+ * to have a different attrs, getter, or setter. In the last property
1408
+ * case, we need not fork the property tree. But since we do not call
1409
+ * js_AddScopeProperty, we may need to allocate a new slot directly.
1410
+ */
1411
+ if ((sprop->attrs & JSPROP_SHARED) && !(attrs & JSPROP_SHARED)) {
1412
+ JS_ASSERT(child.slot == SPROP_INVALID_SLOT);
1413
+ if (!js_AllocSlot(cx, scope->object, &child.slot))
1414
+ return NULL;
1415
+ }
1416
+
1417
+ newsprop = GetPropertyTreeChild(cx, sprop->parent, &child);
1418
+ if (newsprop) {
1419
+ spp = js_SearchScope(scope, sprop->id, JS_FALSE);
1420
+ JS_ASSERT(SPROP_FETCH(spp) == sprop);
1421
+
1422
+ if (scope->table)
1423
+ SPROP_STORE_PRESERVING_COLLISION(spp, newsprop);
1424
+ scope->lastProp = newsprop;
1425
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
1426
+ }
1427
+ } else {
1428
+ /*
1429
+ * Let js_AddScopeProperty handle this |overwriting| case, including
1430
+ * the conservation of sprop->slot (if it's valid). We must not call
1431
+ * js_RemoveScopeProperty here, it will free a valid sprop->slot and
1432
+ * js_AddScopeProperty won't re-allocate it.
1433
+ */
1434
+ newsprop = js_AddScopeProperty(cx, scope, child.id,
1435
+ child.getter, child.setter, child.slot,
1436
+ child.attrs, child.flags, child.shortid);
1437
+ }
1438
+
1439
+ if (newsprop) {
1440
+ js_LeaveTraceIfGlobalObject(cx, scope->object);
1441
+ if (scope->shape == sprop->shape)
1442
+ scope->shape = newsprop->shape;
1443
+ else
1444
+ js_MakeScopeShapeUnique(cx, scope);
1445
+ }
1446
+ #ifdef JS_DUMP_PROPTREE_STATS
1447
+ else
1448
+ METER(changeFailures);
1449
+ #endif
1450
+ return newsprop;
1451
+ }
1452
+
1453
+ JSBool
1454
+ js_RemoveScopeProperty(JSContext *cx, JSScope *scope, jsid id)
1455
+ {
1456
+ JSScopeProperty **spp, *stored, *sprop;
1457
+ uint32 size;
1458
+
1459
+ JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope));
1460
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
1461
+ if (SCOPE_IS_SEALED(scope)) {
1462
+ ReportReadOnlyScope(cx, scope);
1463
+ return JS_FALSE;
1464
+ }
1465
+ METER(removes);
1466
+
1467
+ spp = js_SearchScope(scope, id, JS_FALSE);
1468
+ stored = *spp;
1469
+ sprop = SPROP_CLEAR_COLLISION(stored);
1470
+ if (!sprop) {
1471
+ METER(uselessRemoves);
1472
+ return JS_TRUE;
1473
+ }
1474
+
1475
+ /* Convert from a list to a hash so we can handle "middle deletes". */
1476
+ if (!scope->table && sprop != scope->lastProp) {
1477
+ if (!CreateScopeTable(cx, scope, JS_TRUE))
1478
+ return JS_FALSE;
1479
+ spp = js_SearchScope(scope, id, JS_FALSE);
1480
+ stored = *spp;
1481
+ sprop = SPROP_CLEAR_COLLISION(stored);
1482
+ }
1483
+
1484
+ /* First, if sprop is unshared and not cleared, free its slot number. */
1485
+ if (SPROP_HAS_VALID_SLOT(sprop, scope)) {
1486
+ js_FreeSlot(cx, scope->object, sprop->slot);
1487
+ JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals);
1488
+ }
1489
+
1490
+ /* Next, remove id by setting its entry to a removed or free sentinel. */
1491
+ if (SPROP_HAD_COLLISION(stored)) {
1492
+ JS_ASSERT(scope->table);
1493
+ *spp = SPROP_REMOVED;
1494
+ scope->removedCount++;
1495
+ } else {
1496
+ METER(removeFrees);
1497
+ if (scope->table)
1498
+ *spp = NULL;
1499
+ }
1500
+ scope->entryCount--;
1501
+ LIVE_SCOPE_METER(cx, --cx->runtime->liveScopeProps);
1502
+
1503
+ /* Update scope->lastProp directly, or set its deferred update flag. */
1504
+ if (sprop == SCOPE_LAST_PROP(scope)) {
1505
+ do {
1506
+ SCOPE_REMOVE_LAST_PROP(scope);
1507
+ if (!SCOPE_HAD_MIDDLE_DELETE(scope))
1508
+ break;
1509
+ sprop = SCOPE_LAST_PROP(scope);
1510
+ } while (sprop && !SCOPE_HAS_PROPERTY(scope, sprop));
1511
+ if (!SCOPE_LAST_PROP(scope))
1512
+ SCOPE_CLR_MIDDLE_DELETE(scope);
1513
+ } else if (!SCOPE_HAD_MIDDLE_DELETE(scope)) {
1514
+ SCOPE_SET_MIDDLE_DELETE(scope);
1515
+ }
1516
+ js_MakeScopeShapeUnique(cx, scope);
1517
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
1518
+
1519
+ /* Last, consider shrinking scope's table if its load factor is <= .25. */
1520
+ size = SCOPE_CAPACITY(scope);
1521
+ if (size > MIN_SCOPE_SIZE && scope->entryCount <= size >> 2) {
1522
+ METER(shrinks);
1523
+ (void) ChangeScope(cx, scope, -1);
1524
+ }
1525
+
1526
+ return JS_TRUE;
1527
+ }
1528
+
1529
+ void
1530
+ js_ClearScope(JSContext *cx, JSScope *scope)
1531
+ {
1532
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
1533
+ LIVE_SCOPE_METER(cx, cx->runtime->liveScopeProps -= scope->entryCount);
1534
+
1535
+ if (scope->table)
1536
+ free(scope->table);
1537
+ SCOPE_CLR_MIDDLE_DELETE(scope);
1538
+ InitMinimalScope(cx, scope);
1539
+ JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals);
1540
+ }
1541
+
1542
+ void
1543
+ js_TraceId(JSTracer *trc, jsid id)
1544
+ {
1545
+ jsval v;
1546
+
1547
+ v = ID_TO_VALUE(id);
1548
+ JS_CALL_VALUE_TRACER(trc, v, "id");
1549
+ }
1550
+
1551
+ #ifdef DEBUG
1552
+ static void
1553
+ PrintPropertyGetterOrSetter(JSTracer *trc, char *buf, size_t bufsize)
1554
+ {
1555
+ JSScopeProperty *sprop;
1556
+ jsid id;
1557
+ size_t n;
1558
+ const char *name;
1559
+
1560
+ JS_ASSERT(trc->debugPrinter == PrintPropertyGetterOrSetter);
1561
+ sprop = (JSScopeProperty *)trc->debugPrintArg;
1562
+ id = sprop->id;
1563
+ name = trc->debugPrintIndex ? js_setter_str : js_getter_str;
1564
+
1565
+ if (JSID_IS_ATOM(id)) {
1566
+ n = js_PutEscapedString(buf, bufsize - 1,
1567
+ ATOM_TO_STRING(JSID_TO_ATOM(id)), 0);
1568
+ if (n < bufsize - 1)
1569
+ JS_snprintf(buf + n, bufsize - n, " %s", name);
1570
+ } else if (JSID_IS_INT(sprop->id)) {
1571
+ JS_snprintf(buf, bufsize, "%d %s", JSID_TO_INT(id), name);
1572
+ } else {
1573
+ JS_snprintf(buf, bufsize, "<object> %s", name);
1574
+ }
1575
+ }
1576
+ #endif
1577
+
1578
+
1579
+ void
1580
+ js_TraceScopeProperty(JSTracer *trc, JSScopeProperty *sprop)
1581
+ {
1582
+ if (IS_GC_MARKING_TRACER(trc))
1583
+ sprop->flags |= SPROP_MARK;
1584
+ TRACE_ID(trc, sprop->id);
1585
+
1586
+ #if JS_HAS_GETTER_SETTER
1587
+ if (sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
1588
+ if (sprop->attrs & JSPROP_GETTER) {
1589
+ JS_SET_TRACING_DETAILS(trc, PrintPropertyGetterOrSetter, sprop, 0);
1590
+ JS_CallTracer(trc, js_CastAsObject(sprop->getter), JSTRACE_OBJECT);
1591
+ }
1592
+ if (sprop->attrs & JSPROP_SETTER) {
1593
+ JS_SET_TRACING_DETAILS(trc, PrintPropertyGetterOrSetter, sprop, 1);
1594
+ JS_CallTracer(trc, js_CastAsObject(sprop->setter), JSTRACE_OBJECT);
1595
+ }
1596
+ }
1597
+ #endif /* JS_HAS_GETTER_SETTER */
1598
+ }
1599
+
1600
+ #ifdef JS_DUMP_PROPTREE_STATS
1601
+
1602
+ #include <stdio.h>
1603
+
1604
+ static void
1605
+ MeterKidCount(JSBasicStats *bs, uintN nkids)
1606
+ {
1607
+ JS_BASIC_STATS_ACCUM(bs, nkids);
1608
+ bs->hist[JS_MIN(nkids, 10)]++;
1609
+ }
1610
+
1611
+ static void
1612
+ MeterPropertyTree(JSBasicStats *bs, JSScopeProperty *node)
1613
+ {
1614
+ uintN i, nkids;
1615
+ JSScopeProperty *kids, *kid;
1616
+ PropTreeKidsChunk *chunk;
1617
+
1618
+ nkids = 0;
1619
+ kids = node->kids;
1620
+ if (kids) {
1621
+ if (KIDS_IS_CHUNKY(kids)) {
1622
+ for (chunk = KIDS_TO_CHUNK(kids); chunk; chunk = chunk->next) {
1623
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
1624
+ kid = chunk->kids[i];
1625
+ if (!kid)
1626
+ break;
1627
+ MeterPropertyTree(bs, kid);
1628
+ nkids++;
1629
+ }
1630
+ }
1631
+ } else {
1632
+ MeterPropertyTree(bs, kids);
1633
+ nkids = 1;
1634
+ }
1635
+ }
1636
+
1637
+ MeterKidCount(bs, nkids);
1638
+ }
1639
+
1640
+ static JSDHashOperator
1641
+ js_MeterPropertyTree(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
1642
+ void *arg)
1643
+ {
1644
+ JSPropertyTreeEntry *entry = (JSPropertyTreeEntry *)hdr;
1645
+ JSBasicStats *bs = (JSBasicStats *)arg;
1646
+
1647
+ MeterPropertyTree(bs, entry->child);
1648
+ return JS_DHASH_NEXT;
1649
+ }
1650
+
1651
+ static void
1652
+ DumpSubtree(JSContext *cx, JSScopeProperty *sprop, int level, FILE *fp)
1653
+ {
1654
+ jsval v;
1655
+ JSString *str;
1656
+ JSScopeProperty *kids, *kid;
1657
+ PropTreeKidsChunk *chunk;
1658
+ uintN i;
1659
+
1660
+ fprintf(fp, "%*sid ", level, "");
1661
+ v = ID_TO_VALUE(sprop->id);
1662
+ if (JSID_IS_INT(sprop->id)) {
1663
+ fprintf(fp, "%d", JSVAL_TO_INT(v));
1664
+ } else {
1665
+ if (JSID_IS_ATOM(sprop->id)) {
1666
+ str = JSVAL_TO_STRING(v);
1667
+ } else {
1668
+ JS_ASSERT(JSID_IS_OBJECT(sprop->id));
1669
+ str = js_ValueToString(cx, v);
1670
+ fputs("object ", fp);
1671
+ }
1672
+ if (!str)
1673
+ fputs("<error>", fp);
1674
+ else
1675
+ js_FileEscapedString(fp, str, '"');
1676
+ }
1677
+
1678
+ fprintf(fp, " g/s %p/%p slot %u attrs %x flags %x shortid %d\n",
1679
+ (void *) sprop->getter, (void *) sprop->setter, sprop->slot,
1680
+ sprop->attrs, sprop->flags, sprop->shortid);
1681
+ kids = sprop->kids;
1682
+ if (kids) {
1683
+ ++level;
1684
+ if (KIDS_IS_CHUNKY(kids)) {
1685
+ chunk = KIDS_TO_CHUNK(kids);
1686
+ do {
1687
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
1688
+ kid = chunk->kids[i];
1689
+ if (!kid)
1690
+ break;
1691
+ JS_ASSERT(kid->parent == sprop);
1692
+ DumpSubtree(cx, kid, level, fp);
1693
+ }
1694
+ } while ((chunk = chunk->next) != NULL);
1695
+ } else {
1696
+ kid = kids;
1697
+ DumpSubtree(cx, kid, level, fp);
1698
+ }
1699
+ }
1700
+ }
1701
+
1702
+ #endif /* JS_DUMP_PROPTREE_STATS */
1703
+
1704
+ void
1705
+ js_SweepScopeProperties(JSContext *cx)
1706
+ {
1707
+ JSRuntime *rt = cx->runtime;
1708
+ JSArena **ap, *a;
1709
+ JSScopeProperty *limit, *sprop, *parent, *kids, *kid;
1710
+ uintN liveCount;
1711
+ PropTreeKidsChunk *chunk, *nextChunk, *freeChunk;
1712
+ uintN i;
1713
+
1714
+ #ifdef JS_DUMP_PROPTREE_STATS
1715
+ JSBasicStats bs;
1716
+ uint32 livePropCapacity = 0, totalLiveCount = 0;
1717
+ static FILE *logfp;
1718
+ if (!logfp)
1719
+ logfp = fopen("/tmp/proptree.stats", "w");
1720
+
1721
+ JS_BASIC_STATS_INIT(&bs);
1722
+ MeterKidCount(&bs, rt->propertyTreeHash.entryCount);
1723
+ JS_DHashTableEnumerate(&rt->propertyTreeHash, js_MeterPropertyTree, &bs);
1724
+
1725
+ {
1726
+ double props, nodes, mean, sigma;
1727
+
1728
+ props = rt->liveScopePropsPreSweep;
1729
+ nodes = rt->livePropTreeNodes;
1730
+ JS_ASSERT(nodes == bs.sum);
1731
+ mean = JS_MeanAndStdDevBS(&bs, &sigma);
1732
+
1733
+ fprintf(logfp,
1734
+ "props %g nodes %g beta %g meankids %g sigma %g max %u\n",
1735
+ props, nodes, nodes / props, mean, sigma, bs.max);
1736
+ }
1737
+
1738
+ JS_DumpHistogram(&bs, logfp);
1739
+ #endif
1740
+
1741
+ ap = &rt->propertyArenaPool.first.next;
1742
+ while ((a = *ap) != NULL) {
1743
+ limit = (JSScopeProperty *) a->avail;
1744
+ liveCount = 0;
1745
+ for (sprop = (JSScopeProperty *) a->base; sprop < limit; sprop++) {
1746
+ /* If the id is null, sprop is already on the freelist. */
1747
+ if (sprop->id == JSVAL_NULL)
1748
+ continue;
1749
+
1750
+ /*
1751
+ * If the mark bit is set, sprop is alive, so clear the mark bit
1752
+ * and continue the while loop.
1753
+ *
1754
+ * Regenerate sprop->shape if it hasn't already been refreshed
1755
+ * during the mark phase, when live scopes' lastProp members are
1756
+ * followed to update both scope->shape and lastProp->shape.
1757
+ */
1758
+ if (sprop->flags & SPROP_MARK) {
1759
+ sprop->flags &= ~SPROP_MARK;
1760
+ if (sprop->flags & SPROP_FLAG_SHAPE_REGEN)
1761
+ sprop->flags &= ~SPROP_FLAG_SHAPE_REGEN;
1762
+ else
1763
+ sprop->shape = js_RegenerateShapeForGC(cx);
1764
+ liveCount++;
1765
+ continue;
1766
+ }
1767
+
1768
+ /* Ok, sprop is garbage to collect: unlink it from its parent. */
1769
+ freeChunk = RemovePropertyTreeChild(rt, sprop);
1770
+
1771
+ /*
1772
+ * Take care to reparent all sprop's kids to their grandparent.
1773
+ * InsertPropertyTreeChild can potentially fail for two reasons:
1774
+ *
1775
+ * 1. If parent is null, insertion into the root property hash
1776
+ * table may fail. We are forced to leave the kid out of the
1777
+ * table (as can already happen with duplicates) but ensure
1778
+ * that the kid's parent pointer is set to null.
1779
+ *
1780
+ * 2. If parent is non-null, allocation of a new KidsChunk can
1781
+ * fail. To prevent this from happening, we allow sprops's own
1782
+ * chunks to be reused by the grandparent, which removes the
1783
+ * need for InsertPropertyTreeChild to malloc a new KidsChunk.
1784
+ *
1785
+ * If sprop does not have chunky kids, then we rely on the
1786
+ * RemovePropertyTreeChild call above (which removed sprop from
1787
+ * its parent) either leaving one free entry, or else returning
1788
+ * the now-unused chunk to us so we can reuse it.
1789
+ *
1790
+ * We also require the grandparent to have either no kids or else
1791
+ * chunky kids. A single non-chunky kid would force a new chunk to
1792
+ * be malloced in some cases (if sprop had a single non-chunky
1793
+ * kid, or a multiple of MAX_KIDS_PER_CHUNK kids). Note that
1794
+ * RemovePropertyTreeChild never converts a single-entry chunky
1795
+ * kid back to a non-chunky kid, so we are assured of correct
1796
+ * behaviour.
1797
+ */
1798
+ kids = sprop->kids;
1799
+ if (kids) {
1800
+ sprop->kids = NULL;
1801
+ parent = sprop->parent;
1802
+
1803
+ /* Assert that grandparent has no kids or chunky kids. */
1804
+ JS_ASSERT(!parent || !parent->kids ||
1805
+ KIDS_IS_CHUNKY(parent->kids));
1806
+ if (KIDS_IS_CHUNKY(kids)) {
1807
+ chunk = KIDS_TO_CHUNK(kids);
1808
+ do {
1809
+ nextChunk = chunk->next;
1810
+ chunk->next = NULL;
1811
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
1812
+ kid = chunk->kids[i];
1813
+ if (!kid)
1814
+ break;
1815
+ JS_ASSERT(kid->parent == sprop);
1816
+
1817
+ /*
1818
+ * Clear a space in the kids array for possible
1819
+ * re-use by InsertPropertyTreeChild.
1820
+ */
1821
+ chunk->kids[i] = NULL;
1822
+ if (!InsertPropertyTreeChild(rt, parent, kid,
1823
+ chunk)) {
1824
+ /*
1825
+ * This can happen only if we failed to add an
1826
+ * entry to the root property hash table.
1827
+ */
1828
+ JS_ASSERT(!parent);
1829
+ kid->parent = NULL;
1830
+ }
1831
+ }
1832
+ if (!chunk->kids[0]) {
1833
+ /* The chunk wasn't reused, so we must free it. */
1834
+ DestroyPropTreeKidsChunk(rt, chunk);
1835
+ }
1836
+ } while ((chunk = nextChunk) != NULL);
1837
+ } else {
1838
+ kid = kids;
1839
+ if (!InsertPropertyTreeChild(rt, parent, kid, freeChunk)) {
1840
+ /*
1841
+ * This can happen only if we failed to add an entry
1842
+ * to the root property hash table.
1843
+ */
1844
+ JS_ASSERT(!parent);
1845
+ kid->parent = NULL;
1846
+ }
1847
+ }
1848
+ }
1849
+
1850
+ if (freeChunk && !freeChunk->kids[0]) {
1851
+ /* The chunk wasn't reused, so we must free it. */
1852
+ DestroyPropTreeKidsChunk(rt, freeChunk);
1853
+ }
1854
+
1855
+ /* Clear id so we know (above) that sprop is on the freelist. */
1856
+ sprop->id = JSVAL_NULL;
1857
+ FREENODE_INSERT(rt->propertyFreeList, sprop);
1858
+ JS_RUNTIME_UNMETER(rt, livePropTreeNodes);
1859
+ }
1860
+
1861
+ /* If a contains no live properties, return it to the malloc heap. */
1862
+ if (liveCount == 0) {
1863
+ for (sprop = (JSScopeProperty *) a->base; sprop < limit; sprop++)
1864
+ FREENODE_REMOVE(sprop);
1865
+ JS_ARENA_DESTROY(&rt->propertyArenaPool, a, ap);
1866
+ } else {
1867
+ #ifdef JS_DUMP_PROPTREE_STATS
1868
+ livePropCapacity += limit - (JSScopeProperty *) a->base;
1869
+ totalLiveCount += liveCount;
1870
+ #endif
1871
+ ap = &a->next;
1872
+ }
1873
+ }
1874
+
1875
+ #ifdef JS_DUMP_PROPTREE_STATS
1876
+ fprintf(logfp, "arenautil %g%%\n",
1877
+ (totalLiveCount && livePropCapacity)
1878
+ ? (totalLiveCount * 100.0) / livePropCapacity
1879
+ : 0.0);
1880
+
1881
+ #define RATE(f1, f2) (((double)js_scope_stats.f1 / js_scope_stats.f2) * 100.0)
1882
+
1883
+ fprintf(logfp, "Scope search stats:\n"
1884
+ " searches: %6u\n"
1885
+ " hits: %6u %5.2f%% of searches\n"
1886
+ " misses: %6u %5.2f%%\n"
1887
+ " hashes: %6u %5.2f%%\n"
1888
+ " steps: %6u %5.2f%% %5.2f%% of hashes\n"
1889
+ " stepHits: %6u %5.2f%% %5.2f%%\n"
1890
+ " stepMisses: %6u %5.2f%% %5.2f%%\n"
1891
+ " adds: %6u\n"
1892
+ " redundantAdds: %6u\n"
1893
+ " addFailures: %6u\n"
1894
+ " changeFailures: %6u\n"
1895
+ " compresses: %6u\n"
1896
+ " grows: %6u\n"
1897
+ " removes: %6u\n"
1898
+ " removeFrees: %6u\n"
1899
+ " uselessRemoves: %6u\n"
1900
+ " shrinks: %6u\n",
1901
+ js_scope_stats.searches,
1902
+ js_scope_stats.hits, RATE(hits, searches),
1903
+ js_scope_stats.misses, RATE(misses, searches),
1904
+ js_scope_stats.hashes, RATE(hashes, searches),
1905
+ js_scope_stats.steps, RATE(steps, searches), RATE(steps, hashes),
1906
+ js_scope_stats.stepHits,
1907
+ RATE(stepHits, searches), RATE(stepHits, hashes),
1908
+ js_scope_stats.stepMisses,
1909
+ RATE(stepMisses, searches), RATE(stepMisses, hashes),
1910
+ js_scope_stats.adds,
1911
+ js_scope_stats.redundantAdds,
1912
+ js_scope_stats.addFailures,
1913
+ js_scope_stats.changeFailures,
1914
+ js_scope_stats.compresses,
1915
+ js_scope_stats.grows,
1916
+ js_scope_stats.removes,
1917
+ js_scope_stats.removeFrees,
1918
+ js_scope_stats.uselessRemoves,
1919
+ js_scope_stats.shrinks);
1920
+
1921
+ #undef RATE
1922
+
1923
+ fflush(logfp);
1924
+ #endif
1925
+
1926
+ #ifdef DUMP_PROPERTY_TREE
1927
+ {
1928
+ FILE *dumpfp = fopen("/tmp/proptree.dump", "w");
1929
+ if (dumpfp) {
1930
+ JSPropertyTreeEntry *pte, *end;
1931
+
1932
+ pte = (JSPropertyTreeEntry *) rt->propertyTreeHash.entryStore;
1933
+ end = pte + JS_DHASH_TABLE_SIZE(&rt->propertyTreeHash);
1934
+ while (pte < end) {
1935
+ if (pte->child)
1936
+ DumpSubtree(cx, pte->child, 0, dumpfp);
1937
+ pte++;
1938
+ }
1939
+ fclose(dumpfp);
1940
+ }
1941
+ }
1942
+ #endif
1943
+ }
1944
+
1945
+ JSBool
1946
+ js_InitPropertyTree(JSRuntime *rt)
1947
+ {
1948
+ if (!JS_DHashTableInit(&rt->propertyTreeHash, &PropertyTreeHashOps, NULL,
1949
+ sizeof(JSPropertyTreeEntry), JS_DHASH_MIN_SIZE)) {
1950
+ rt->propertyTreeHash.ops = NULL;
1951
+ return JS_FALSE;
1952
+ }
1953
+ JS_INIT_ARENA_POOL(&rt->propertyArenaPool, "properties",
1954
+ 256 * sizeof(JSScopeProperty), sizeof(void *), NULL);
1955
+ return JS_TRUE;
1956
+ }
1957
+
1958
+ void
1959
+ js_FinishPropertyTree(JSRuntime *rt)
1960
+ {
1961
+ if (rt->propertyTreeHash.ops) {
1962
+ JS_DHashTableFinish(&rt->propertyTreeHash);
1963
+ rt->propertyTreeHash.ops = NULL;
1964
+ }
1965
+ JS_FinishArenaPool(&rt->propertyArenaPool);
1966
+ }