distil 0.7.0
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.
- data/Rakefile +28 -0
- data/VERSION +1 -0
- data/bin/distil +45 -0
- data/distil.gemspec +586 -0
- data/lib/bootstrap-template.js +56 -0
- data/lib/configurable.rb +125 -0
- data/lib/file-set.rb +42 -0
- data/lib/file-types/css-file.rb +75 -0
- data/lib/file-types/html-file.rb +11 -0
- data/lib/file-types/javascript-file.rb +98 -0
- data/lib/file-types/json-file.rb +14 -0
- data/lib/file-types/nib-file.rb +9 -0
- data/lib/jsdoc.conf +18 -0
- data/lib/jsl.conf +121 -0
- data/lib/project.rb +96 -0
- data/lib/source-file.rb +181 -0
- data/lib/target.rb +96 -0
- data/lib/task.rb +239 -0
- data/lib/tasks/copy-task.rb +21 -0
- data/lib/tasks/css-task.rb +18 -0
- data/lib/tasks/javascript-task.rb +125 -0
- data/lib/tasks/multiple-output-task.rb +134 -0
- data/lib/tasks/nib-task.rb +83 -0
- data/lib/tasks/output-task.rb +73 -0
- data/lib/tasks/single-output-task.rb +83 -0
- data/lib/tasks/test-task.rb +280 -0
- data/lib/test/HtmlTestReporter.js +127 -0
- data/lib/test/Test.js +248 -0
- data/lib/test/TestReporter.js +79 -0
- data/lib/test/TestRunner.js +132 -0
- data/lib/test/browser.rb +97 -0
- data/lib/test/scriptwrapper.html +10 -0
- data/lib/test/unittest.html +127 -0
- data/vendor/Makefile +35 -0
- data/vendor/extconf.rb +3 -0
- data/vendor/jsdoc-extras/plugins/distil-plugin.js +142 -0
- data/vendor/jsdoc-extras/plugins/interface-plugin.js +36 -0
- data/vendor/jsdoc-extras/templates/coherent/allclasses.tmpl +17 -0
- data/vendor/jsdoc-extras/templates/coherent/allfiles.tmpl +53 -0
- data/vendor/jsdoc-extras/templates/coherent/class.tmpl +803 -0
- data/vendor/jsdoc-extras/templates/coherent/index.tmpl +37 -0
- data/vendor/jsdoc-extras/templates/coherent/publish.js +242 -0
- data/vendor/jsdoc-extras/templates/coherent/showdown.js +421 -0
- data/vendor/jsdoc-extras/templates/coherent/static/code-footer.html +3 -0
- data/vendor/jsdoc-extras/templates/coherent/static/code-header.html +7 -0
- data/vendor/jsdoc-extras/templates/coherent/static/default.css +297 -0
- data/vendor/jsdoc-extras/templates/coherent/static/header.html +2 -0
- data/vendor/jsdoc-extras/templates/coherent/static/index.html +19 -0
- data/vendor/jsdoc-extras/templates/coherent/symbol.tmpl +35 -0
- data/vendor/jsdoc-toolkit/README.txt +183 -0
- data/vendor/jsdoc-toolkit/app/frame/Chain.js +102 -0
- data/vendor/jsdoc-toolkit/app/frame/Dumper.js +144 -0
- data/vendor/jsdoc-toolkit/app/frame/Hash.js +84 -0
- data/vendor/jsdoc-toolkit/app/frame/Link.js +171 -0
- data/vendor/jsdoc-toolkit/app/frame/Namespace.js +10 -0
- data/vendor/jsdoc-toolkit/app/frame/Opt.js +134 -0
- data/vendor/jsdoc-toolkit/app/frame/Reflection.js +26 -0
- data/vendor/jsdoc-toolkit/app/frame/String.js +93 -0
- data/vendor/jsdoc-toolkit/app/frame/Testrun.js +129 -0
- data/vendor/jsdoc-toolkit/app/frame.js +33 -0
- data/vendor/jsdoc-toolkit/app/handlers/FOODOC.js +26 -0
- data/vendor/jsdoc-toolkit/app/handlers/XMLDOC/DomReader.js +159 -0
- data/vendor/jsdoc-toolkit/app/handlers/XMLDOC/XMLDoc.js +16 -0
- data/vendor/jsdoc-toolkit/app/handlers/XMLDOC/XMLParse.js +292 -0
- data/vendor/jsdoc-toolkit/app/handlers/XMLDOC.js +26 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/DocComment.js +204 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/DocTag.js +300 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/JsDoc.js +126 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/JsPlate.js +109 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/Lang.js +144 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/Parser.js +144 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/PluginManager.js +33 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/Symbol.js +644 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/SymbolSet.js +241 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/TextStream.js +41 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/Token.js +18 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/TokenReader.js +332 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/TokenStream.js +133 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/Util.js +32 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC/Walker.js +499 -0
- data/vendor/jsdoc-toolkit/app/lib/JSDOC.js +106 -0
- data/vendor/jsdoc-toolkit/app/main.js +129 -0
- data/vendor/jsdoc-toolkit/app/plugins/commentSrcJson.js +20 -0
- data/vendor/jsdoc-toolkit/app/plugins/frameworkPrototype.js +16 -0
- data/vendor/jsdoc-toolkit/app/plugins/functionCall.js +10 -0
- data/vendor/jsdoc-toolkit/app/plugins/publishSrcHilite.js +54 -0
- data/vendor/jsdoc-toolkit/app/plugins/symbolLink.js +10 -0
- data/vendor/jsdoc-toolkit/app/plugins/tagParamConfig.js +31 -0
- data/vendor/jsdoc-toolkit/app/plugins/tagSynonyms.js +43 -0
- data/vendor/jsdoc-toolkit/app/run.js +348 -0
- data/vendor/jsdoc-toolkit/app/t/TestDoc.js +144 -0
- data/vendor/jsdoc-toolkit/app/t/runner.js +13 -0
- data/vendor/jsdoc-toolkit/app/test/addon.js +24 -0
- data/vendor/jsdoc-toolkit/app/test/anon_inner.js +14 -0
- data/vendor/jsdoc-toolkit/app/test/augments.js +31 -0
- data/vendor/jsdoc-toolkit/app/test/augments2.js +26 -0
- data/vendor/jsdoc-toolkit/app/test/borrows.js +46 -0
- data/vendor/jsdoc-toolkit/app/test/borrows2.js +23 -0
- data/vendor/jsdoc-toolkit/app/test/config.js +22 -0
- data/vendor/jsdoc-toolkit/app/test/constructs.js +18 -0
- data/vendor/jsdoc-toolkit/app/test/encoding.js +10 -0
- data/vendor/jsdoc-toolkit/app/test/encoding_other.js +12 -0
- data/vendor/jsdoc-toolkit/app/test/event.js +54 -0
- data/vendor/jsdoc-toolkit/app/test/exports.js +14 -0
- data/vendor/jsdoc-toolkit/app/test/functions_anon.js +39 -0
- data/vendor/jsdoc-toolkit/app/test/functions_nested.js +33 -0
- data/vendor/jsdoc-toolkit/app/test/global.js +13 -0
- data/vendor/jsdoc-toolkit/app/test/globals.js +25 -0
- data/vendor/jsdoc-toolkit/app/test/ignore.js +10 -0
- data/vendor/jsdoc-toolkit/app/test/inner.js +16 -0
- data/vendor/jsdoc-toolkit/app/test/jsdoc_test.js +477 -0
- data/vendor/jsdoc-toolkit/app/test/lend.js +33 -0
- data/vendor/jsdoc-toolkit/app/test/memberof.js +19 -0
- data/vendor/jsdoc-toolkit/app/test/memberof2.js +38 -0
- data/vendor/jsdoc-toolkit/app/test/memberof3.js +33 -0
- data/vendor/jsdoc-toolkit/app/test/memberof_constructor.js +17 -0
- data/vendor/jsdoc-toolkit/app/test/module.js +17 -0
- data/vendor/jsdoc-toolkit/app/test/name.js +19 -0
- data/vendor/jsdoc-toolkit/app/test/namespace_nested.js +23 -0
- data/vendor/jsdoc-toolkit/app/test/nocode.js +13 -0
- data/vendor/jsdoc-toolkit/app/test/oblit_anon.js +20 -0
- data/vendor/jsdoc-toolkit/app/test/overview.js +20 -0
- data/vendor/jsdoc-toolkit/app/test/param_inline.js +37 -0
- data/vendor/jsdoc-toolkit/app/test/params_optional.js +8 -0
- data/vendor/jsdoc-toolkit/app/test/prototype.js +17 -0
- data/vendor/jsdoc-toolkit/app/test/prototype_nested.js +9 -0
- data/vendor/jsdoc-toolkit/app/test/prototype_oblit.js +13 -0
- data/vendor/jsdoc-toolkit/app/test/prototype_oblit_constructor.js +24 -0
- data/vendor/jsdoc-toolkit/app/test/public.js +10 -0
- data/vendor/jsdoc-toolkit/app/test/scripts/code.js +5 -0
- data/vendor/jsdoc-toolkit/app/test/scripts/notcode.txt +5 -0
- data/vendor/jsdoc-toolkit/app/test/shared.js +42 -0
- data/vendor/jsdoc-toolkit/app/test/shared2.js +2 -0
- data/vendor/jsdoc-toolkit/app/test/shortcuts.js +22 -0
- data/vendor/jsdoc-toolkit/app/test/static_this.js +13 -0
- data/vendor/jsdoc-toolkit/app/test/synonyms.js +31 -0
- data/vendor/jsdoc-toolkit/app/test/tosource.js +23 -0
- data/vendor/jsdoc-toolkit/app/test/variable_redefine.js +14 -0
- data/vendor/jsdoc-toolkit/app/test.js +342 -0
- data/vendor/jsdoc-toolkit/changes.txt +116 -0
- data/vendor/jsdoc-toolkit/conf/sample.conf +31 -0
- data/vendor/jsdoc-toolkit/java/build.xml +36 -0
- data/vendor/jsdoc-toolkit/java/build_1.4.xml +36 -0
- data/vendor/jsdoc-toolkit/java/classes/js.jar +0 -0
- data/vendor/jsdoc-toolkit/java/src/JsDebugRun.java +21 -0
- data/vendor/jsdoc-toolkit/java/src/JsRun.java +21 -0
- data/vendor/jsdoc-toolkit/jsdebug.jar +0 -0
- data/vendor/jsdoc-toolkit/jsrun.jar +0 -0
- data/vendor/jsdoc-toolkit/jsrun.sh +53 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/allclasses.tmpl +17 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/allfiles.tmpl +56 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/class.tmpl +649 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/index.tmpl +39 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/publish.js +201 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/static/code-footer.html +3 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/static/code-header.html +14 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/static/default.css +162 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/static/header.html +2 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/static/index.html +19 -0
- data/vendor/jsdoc-toolkit/templates/jsdoc/symbol.tmpl +35 -0
- data/vendor/jsl-0.3.0/src/JavaScriptLintAPI.cpp +333 -0
- data/vendor/jsl-0.3.0/src/JavaScriptLintAPI.h +86 -0
- data/vendor/jsl-0.3.0/src/Makefile.in +375 -0
- data/vendor/jsl-0.3.0/src/Makefile.ref +372 -0
- data/vendor/jsl-0.3.0/src/README.html +826 -0
- data/vendor/jsl-0.3.0/src/SpiderMonkey.rsp +12 -0
- data/vendor/jsl-0.3.0/src/_jsl_online.php +223 -0
- data/vendor/jsl-0.3.0/src/config/AIX4.1.mk +65 -0
- data/vendor/jsl-0.3.0/src/config/AIX4.2.mk +64 -0
- data/vendor/jsl-0.3.0/src/config/AIX4.3.mk +65 -0
- data/vendor/jsl-0.3.0/src/config/Darwin.mk +81 -0
- data/vendor/jsl-0.3.0/src/config/Darwin1.3.mk +81 -0
- data/vendor/jsl-0.3.0/src/config/Darwin1.4.mk +41 -0
- data/vendor/jsl-0.3.0/src/config/Darwin5.2.mk +81 -0
- data/vendor/jsl-0.3.0/src/config/Darwin5.3.mk +81 -0
- data/vendor/jsl-0.3.0/src/config/HP-UXB.10.10.mk +77 -0
- data/vendor/jsl-0.3.0/src/config/HP-UXB.10.20.mk +77 -0
- data/vendor/jsl-0.3.0/src/config/HP-UXB.11.00.mk +80 -0
- data/vendor/jsl-0.3.0/src/config/IRIX.mk +87 -0
- data/vendor/jsl-0.3.0/src/config/IRIX5.3.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/IRIX6.1.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/IRIX6.2.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/IRIX6.3.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/IRIX6.5.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/Linux_All.mk +103 -0
- data/vendor/jsl-0.3.0/src/config/Mac_OS10.0.mk +82 -0
- data/vendor/jsl-0.3.0/src/config/OSF1V4.0.mk +72 -0
- data/vendor/jsl-0.3.0/src/config/OSF1V5.0.mk +69 -0
- data/vendor/jsl-0.3.0/src/config/SunOS4.1.4.mk +101 -0
- data/vendor/jsl-0.3.0/src/config/SunOS5.3.mk +91 -0
- data/vendor/jsl-0.3.0/src/config/SunOS5.4.mk +92 -0
- data/vendor/jsl-0.3.0/src/config/SunOS5.5.1.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/SunOS5.5.mk +87 -0
- data/vendor/jsl-0.3.0/src/config/SunOS5.6.mk +89 -0
- data/vendor/jsl-0.3.0/src/config/SunOS5.7.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/SunOS5.8.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/SunOS5.9.mk +44 -0
- data/vendor/jsl-0.3.0/src/config/WINNT4.0.mk +112 -0
- data/vendor/jsl-0.3.0/src/config/WINNT5.0.mk +112 -0
- data/vendor/jsl-0.3.0/src/config/WINNT5.1.mk +112 -0
- data/vendor/jsl-0.3.0/src/config/WINNT5.2.mk +112 -0
- data/vendor/jsl-0.3.0/src/config/dgux.mk +64 -0
- data/vendor/jsl-0.3.0/src/config.mk +166 -0
- data/vendor/jsl-0.3.0/src/editline/Makefile.ref +144 -0
- data/vendor/jsl-0.3.0/src/editline/README +83 -0
- data/vendor/jsl-0.3.0/src/editline/editline.3 +175 -0
- data/vendor/jsl-0.3.0/src/editline/editline.c +1369 -0
- data/vendor/jsl-0.3.0/src/editline/editline.h +135 -0
- data/vendor/jsl-0.3.0/src/editline/sysunix.c +182 -0
- data/vendor/jsl-0.3.0/src/editline/unix.h +82 -0
- data/vendor/jsl-0.3.0/src/fdlibm/Makefile.in +127 -0
- data/vendor/jsl-0.3.0/src/fdlibm/Makefile.ref +192 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_acos.c +147 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_acosh.c +105 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_asin.c +156 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_atan2.c +165 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_atanh.c +110 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_cosh.c +133 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_exp.c +202 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_fmod.c +184 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_gamma.c +71 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_gamma_r.c +70 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_hypot.c +173 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_j0.c +524 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_j1.c +523 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_jn.c +315 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_lgamma.c +71 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_lgamma_r.c +347 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_log.c +184 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_log10.c +134 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_pow.c +386 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_rem_pio2.c +221 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_remainder.c +120 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_scalb.c +89 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_sinh.c +122 -0
- data/vendor/jsl-0.3.0/src/fdlibm/e_sqrt.c +497 -0
- data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.dsp +160 -0
- data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.h +273 -0
- data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.mak +1453 -0
- data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.mdp +0 -0
- data/vendor/jsl-0.3.0/src/fdlibm/k_cos.c +134 -0
- data/vendor/jsl-0.3.0/src/fdlibm/k_rem_pio2.c +354 -0
- data/vendor/jsl-0.3.0/src/fdlibm/k_sin.c +114 -0
- data/vendor/jsl-0.3.0/src/fdlibm/k_standard.c +785 -0
- data/vendor/jsl-0.3.0/src/fdlibm/k_tan.c +170 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_asinh.c +101 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_atan.c +175 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_cbrt.c +133 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_ceil.c +120 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_copysign.c +72 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_cos.c +118 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_erf.c +356 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_expm1.c +267 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_fabs.c +70 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_finite.c +71 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_floor.c +121 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_frexp.c +99 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_ilogb.c +85 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_isnan.c +74 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_ldexp.c +66 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_lib_version.c +73 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_log1p.c +211 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_logb.c +79 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_matherr.c +64 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_modf.c +132 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_nextafter.c +124 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_rint.c +131 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_scalbn.c +107 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_signgam.c +40 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_significand.c +68 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_sin.c +118 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_tan.c +112 -0
- data/vendor/jsl-0.3.0/src/fdlibm/s_tanh.c +122 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_acos.c +78 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_acosh.c +78 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_asin.c +80 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_atan2.c +79 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_atanh.c +81 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_cosh.c +77 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_exp.c +88 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_fmod.c +78 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_gamma.c +85 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_gamma_r.c +81 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_hypot.c +78 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_j0.c +105 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_j1.c +106 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_jn.c +128 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_lgamma.c +85 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_lgamma_r.c +81 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_log.c +78 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_log10.c +81 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_pow.c +99 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_remainder.c +77 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_scalb.c +95 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_sinh.c +77 -0
- data/vendor/jsl-0.3.0/src/fdlibm/w_sqrt.c +77 -0
- data/vendor/jsl-0.3.0/src/js.c +2447 -0
- data/vendor/jsl-0.3.0/src/js.dsp +420 -0
- data/vendor/jsl-0.3.0/src/js.mak +4025 -0
- data/vendor/jsl-0.3.0/src/js.mdp +0 -0
- data/vendor/jsl-0.3.0/src/js.msg +291 -0
- data/vendor/jsl-0.3.0/src/js.pkg +2 -0
- data/vendor/jsl-0.3.0/src/js3240.rc +79 -0
- data/vendor/jsl-0.3.0/src/jsOS240.def +654 -0
- data/vendor/jsl-0.3.0/src/jsapi.c +4405 -0
- data/vendor/jsl-0.3.0/src/jsapi.h +1856 -0
- data/vendor/jsl-0.3.0/src/jsarena.c +567 -0
- data/vendor/jsl-0.3.0/src/jsarena.h +302 -0
- data/vendor/jsl-0.3.0/src/jsarray.c +1428 -0
- data/vendor/jsl-0.3.0/src/jsarray.h +77 -0
- data/vendor/jsl-0.3.0/src/jsatom.c +927 -0
- data/vendor/jsl-0.3.0/src/jsatom.h +426 -0
- data/vendor/jsl-0.3.0/src/jsbit.h +113 -0
- data/vendor/jsl-0.3.0/src/jsbool.c +220 -0
- data/vendor/jsl-0.3.0/src/jsbool.h +62 -0
- data/vendor/jsl-0.3.0/src/jsclist.h +139 -0
- data/vendor/jsl-0.3.0/src/jscntxt.c +1036 -0
- data/vendor/jsl-0.3.0/src/jscntxt.h +608 -0
- data/vendor/jsl-0.3.0/src/jscompat.h +57 -0
- data/vendor/jsl-0.3.0/src/jsconfig.h +489 -0
- data/vendor/jsl-0.3.0/src/jsconfig.mk +181 -0
- data/vendor/jsl-0.3.0/src/jscpucfg.c +377 -0
- data/vendor/jsl-0.3.0/src/jscpucfg.h +204 -0
- data/vendor/jsl-0.3.0/src/jsdate.c +2238 -0
- data/vendor/jsl-0.3.0/src/jsdate.h +118 -0
- data/vendor/jsl-0.3.0/src/jsdbgapi.c +1260 -0
- data/vendor/jsl-0.3.0/src/jsdbgapi.h +345 -0
- data/vendor/jsl-0.3.0/src/jsdhash.c +763 -0
- data/vendor/jsl-0.3.0/src/jsdhash.h +579 -0
- data/vendor/jsl-0.3.0/src/jsdtoa.c +3135 -0
- data/vendor/jsl-0.3.0/src/jsdtoa.h +130 -0
- data/vendor/jsl-0.3.0/src/jsemit.c +4851 -0
- data/vendor/jsl-0.3.0/src/jsemit.h +576 -0
- data/vendor/jsl-0.3.0/src/jsexn.c +1084 -0
- data/vendor/jsl-0.3.0/src/jsexn.h +102 -0
- data/vendor/jsl-0.3.0/src/jsfile.c +2610 -0
- data/vendor/jsl-0.3.0/src/jsfile.h +50 -0
- data/vendor/jsl-0.3.0/src/jsfile.msg +89 -0
- data/vendor/jsl-0.3.0/src/jsfun.c +2015 -0
- data/vendor/jsl-0.3.0/src/jsfun.h +158 -0
- data/vendor/jsl-0.3.0/src/jsgc.c +1441 -0
- data/vendor/jsl-0.3.0/src/jsgc.h +230 -0
- data/vendor/jsl-0.3.0/src/jshash.c +471 -0
- data/vendor/jsl-0.3.0/src/jshash.h +152 -0
- data/vendor/jsl-0.3.0/src/jsify.pl +485 -0
- data/vendor/jsl-0.3.0/src/jsinterp.c +4797 -0
- data/vendor/jsl-0.3.0/src/jsinterp.h +302 -0
- data/vendor/jsl-0.3.0/src/jsl-test.js +28 -0
- data/vendor/jsl-0.3.0/src/jsl.c +2371 -0
- data/vendor/jsl-0.3.0/src/jsl.conf +127 -0
- data/vendor/jsl-0.3.0/src/jsl.conf.old +124 -0
- data/vendor/jsl-0.3.0/src/jsl.dsp +242 -0
- data/vendor/jsl-0.3.0/src/jsl.dsw +59 -0
- data/vendor/jsl-0.3.0/src/jslibmath.h +290 -0
- data/vendor/jsl-0.3.0/src/jslock.c +1261 -0
- data/vendor/jsl-0.3.0/src/jslock.h +289 -0
- data/vendor/jsl-0.3.0/src/jslocko.asm +59 -0
- data/vendor/jsl-0.3.0/src/jslog2.c +83 -0
- data/vendor/jsl-0.3.0/src/jslong.c +281 -0
- data/vendor/jsl-0.3.0/src/jslong.h +437 -0
- data/vendor/jsl-0.3.0/src/jsmath.c +477 -0
- data/vendor/jsl-0.3.0/src/jsmath.h +55 -0
- data/vendor/jsl-0.3.0/src/jsnum.c +1148 -0
- data/vendor/jsl-0.3.0/src/jsnum.h +257 -0
- data/vendor/jsl-0.3.0/src/jsobj.c +4066 -0
- data/vendor/jsl-0.3.0/src/jsobj.h +475 -0
- data/vendor/jsl-0.3.0/src/jsopcode.c +2730 -0
- data/vendor/jsl-0.3.0/src/jsopcode.h +275 -0
- data/vendor/jsl-0.3.0/src/jsopcode.tbl +344 -0
- data/vendor/jsl-0.3.0/src/jsosdep.h +127 -0
- data/vendor/jsl-0.3.0/src/jsotypes.h +211 -0
- data/vendor/jsl-0.3.0/src/jsparse.c +4438 -0
- data/vendor/jsl-0.3.0/src/jsparse.h +345 -0
- data/vendor/jsl-0.3.0/src/jsprf.c +1212 -0
- data/vendor/jsl-0.3.0/src/jsprf.h +148 -0
- data/vendor/jsl-0.3.0/src/jsprvtd.h +174 -0
- data/vendor/jsl-0.3.0/src/jspubtd.h +586 -0
- data/vendor/jsl-0.3.0/src/jsregexp.c +3831 -0
- data/vendor/jsl-0.3.0/src/jsregexp.h +180 -0
- data/vendor/jsl-0.3.0/src/jsscan.c +1814 -0
- data/vendor/jsl-0.3.0/src/jsscan.h +267 -0
- data/vendor/jsl-0.3.0/src/jsscope.c +1639 -0
- data/vendor/jsl-0.3.0/src/jsscope.h +389 -0
- data/vendor/jsl-0.3.0/src/jsscript.c +1284 -0
- data/vendor/jsl-0.3.0/src/jsscript.h +179 -0
- data/vendor/jsl-0.3.0/src/jsshell.msg +50 -0
- data/vendor/jsl-0.3.0/src/jsstddef.h +83 -0
- data/vendor/jsl-0.3.0/src/jsstr.c +4502 -0
- data/vendor/jsl-0.3.0/src/jsstr.h +448 -0
- data/vendor/jsl-0.3.0/src/jstypes.h +391 -0
- data/vendor/jsl-0.3.0/src/jsutil.c +157 -0
- data/vendor/jsl-0.3.0/src/jsutil.h +75 -0
- data/vendor/jsl-0.3.0/src/jsxdrapi.c +686 -0
- data/vendor/jsl-0.3.0/src/jsxdrapi.h +193 -0
- data/vendor/jsl-0.3.0/src/liveconnect/LiveConnect.dsp +157 -0
- data/vendor/jsl-0.3.0/src/liveconnect/LiveConnectShell.dsp +120 -0
- data/vendor/jsl-0.3.0/src/liveconnect/LiveConnectShell.dsw +44 -0
- data/vendor/jsl-0.3.0/src/liveconnect/Makefile.in +106 -0
- data/vendor/jsl-0.3.0/src/liveconnect/Makefile.ref +169 -0
- data/vendor/jsl-0.3.0/src/liveconnect/README.html +719 -0
- data/vendor/jsl-0.3.0/src/liveconnect/_jni/netscape_javascript_JSException.h +14 -0
- data/vendor/jsl-0.3.0/src/liveconnect/_jni/netscape_javascript_JSObject.h +155 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/Makefile.in +89 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/Makefile.ref +57 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/Makefile.ref +47 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSException.java +140 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSObject.java +183 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSProxy.java +58 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSRunnable.java +70 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSUtil.java +59 -0
- data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/Makefile.ref +53 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/AIX4.1.mk +45 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/AIX4.2.mk +45 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/AIX4.3.mk +50 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/HP-UXB.10.10.mk +43 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/HP-UXB.10.20.mk +43 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/HP-UXB.11.00.mk +43 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/IRIX6.2.mk +43 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/IRIX6.3.mk +43 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/IRIX6.5.mk +43 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/Linux_All.mk +73 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/OSF1V4.0.mk +65 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/OSF1V5.0.mk +62 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.5.1.mk +55 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.6.mk +39 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.7.mk +39 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.8.mk +39 -0
- data/vendor/jsl-0.3.0/src/liveconnect/config/WINNT4.0.mk +53 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj.c +884 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj.msg +98 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_JSObject.c +1379 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaArray.c +481 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaClass.c +749 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaMember.c +186 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaObject.c +1099 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaPackage.c +548 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_array.c +207 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_class.c +765 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_convert.c +954 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_field.c +421 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_hash.c +504 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_hash.h +161 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_method.c +1823 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_nodl.c +1 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_private.h +689 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_simpleapi.c +219 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsj_utils.c +513 -0
- data/vendor/jsl-0.3.0/src/liveconnect/jsjava.h +313 -0
- data/vendor/jsl-0.3.0/src/liveconnect/liveconnect.pkg +3 -0
- data/vendor/jsl-0.3.0/src/liveconnect/netscape_javascript_JSObject.h +155 -0
- data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnect.cpp +785 -0
- data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnect.h +197 -0
- data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnectFactory.cpp +163 -0
- data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnectFactory.h +76 -0
- data/vendor/jsl-0.3.0/src/liveconnect/nsILiveconnect.h +195 -0
- data/vendor/jsl-0.3.0/src/liveconnect/nsISecureLiveconnect.h +84 -0
- data/vendor/jsl-0.3.0/src/liveconnect/nsISecurityContext.h +135 -0
- data/vendor/jsl-0.3.0/src/liveconnect/win32.order +6 -0
- data/vendor/jsl-0.3.0/src/lock_SunOS.s +114 -0
- data/vendor/jsl-0.3.0/src/perfect.js +39 -0
- data/vendor/jsl-0.3.0/src/perlconnect/JS.def +6 -0
- data/vendor/jsl-0.3.0/src/perlconnect/JS.dsp +107 -0
- data/vendor/jsl-0.3.0/src/perlconnect/JS.pm +318 -0
- data/vendor/jsl-0.3.0/src/perlconnect/JS.xs +1050 -0
- data/vendor/jsl-0.3.0/src/perlconnect/Makefile.PL +67 -0
- data/vendor/jsl-0.3.0/src/perlconnect/Makefile.ref +152 -0
- data/vendor/jsl-0.3.0/src/perlconnect/PerlConnect.dsp +103 -0
- data/vendor/jsl-0.3.0/src/perlconnect/PerlConnect.dsw +59 -0
- data/vendor/jsl-0.3.0/src/perlconnect/PerlConnect.pm +126 -0
- data/vendor/jsl-0.3.0/src/perlconnect/PerlConnectShell.dsp +89 -0
- data/vendor/jsl-0.3.0/src/perlconnect/README.html +345 -0
- data/vendor/jsl-0.3.0/src/perlconnect/bg.jpg +0 -0
- data/vendor/jsl-0.3.0/src/perlconnect/jsperl.c +1100 -0
- data/vendor/jsl-0.3.0/src/perlconnect/jsperl.h +52 -0
- data/vendor/jsl-0.3.0/src/perlconnect/jsperlbuild.pl +81 -0
- data/vendor/jsl-0.3.0/src/perlconnect/jsperlpvt.h +57 -0
- data/vendor/jsl-0.3.0/src/perlconnect/test.js +73 -0
- data/vendor/jsl-0.3.0/src/perlconnect/test.pl +244 -0
- data/vendor/jsl-0.3.0/src/perlconnect/typemap +121 -0
- data/vendor/jsl-0.3.0/src/plify_jsdhash.sed +31 -0
- data/vendor/jsl-0.3.0/src/prmjtime.c +646 -0
- data/vendor/jsl-0.3.0/src/prmjtime.h +95 -0
- data/vendor/jsl-0.3.0/src/resource.h +15 -0
- data/vendor/jsl-0.3.0/src/rules.mk +193 -0
- data/vendor/jsl-0.3.0/src/win32.order +391 -0
- data/vendor/jsl-0.3.0/tests/conf/always_use_option_explicit.js +4 -0
- data/vendor/jsl-0.3.0/tests/conf/define.js +8 -0
- data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-1.js +7 -0
- data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-2.js +8 -0
- data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-3.js +27 -0
- data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-4.js +4 -0
- data/vendor/jsl-0.3.0/tests/conf/lambda_assign_requires_semicolon.js +24 -0
- data/vendor/jsl-0.3.0/tests/conf/legacy_control_comments.js +8 -0
- data/vendor/jsl-0.3.0/tests/control_comments/control_comments.js +33 -0
- data/vendor/jsl-0.3.0/tests/control_comments/declare.js +26 -0
- data/vendor/jsl-0.3.0/tests/control_comments/import-overflow.js +9 -0
- data/vendor/jsl-0.3.0/tests/control_comments/import.js +5 -0
- data/vendor/jsl-0.3.0/tests/control_comments/import2.js +2 -0
- data/vendor/jsl-0.3.0/tests/control_comments/invalid_fallthru.js +13 -0
- data/vendor/jsl-0.3.0/tests/control_comments/option_explicit-with.js +12 -0
- data/vendor/jsl-0.3.0/tests/control_comments/option_explicit.js +64 -0
- data/vendor/jsl-0.3.0/tests/errors/unterminated_comment.js +8 -0
- data/vendor/jsl-0.3.0/tests/html/script_tag_in_js_literal.html +14 -0
- data/vendor/jsl-0.3.0/tests/run_tests.pl +71 -0
- data/vendor/jsl-0.3.0/tests/warnings/ambiguous_else_stmt.js +21 -0
- data/vendor/jsl-0.3.0/tests/warnings/ambiguous_nested_stmt.js +66 -0
- data/vendor/jsl-0.3.0/tests/warnings/ambiguous_newline.js +261 -0
- data/vendor/jsl-0.3.0/tests/warnings/anon_no_return_value.js +26 -0
- data/vendor/jsl-0.3.0/tests/warnings/assign_to_function_call.js +16 -0
- data/vendor/jsl-0.3.0/tests/warnings/block_without_braces.js +13 -0
- data/vendor/jsl-0.3.0/tests/warnings/comma_separated_stmts.js +17 -0
- data/vendor/jsl-0.3.0/tests/warnings/comparison_type_conv.js +44 -0
- data/vendor/jsl-0.3.0/tests/warnings/default_not_at_end.js +15 -0
- data/vendor/jsl-0.3.0/tests/warnings/dup_option_explicit.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/duplicate_case_in_switch.js +62 -0
- data/vendor/jsl-0.3.0/tests/warnings/duplicate_formal.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/empty_statement.js +29 -0
- data/vendor/jsl-0.3.0/tests/warnings/equal_as_assign.js +7 -0
- data/vendor/jsl-0.3.0/tests/warnings/inc_dec_within_stmt-ignore.js +21 -0
- data/vendor/jsl-0.3.0/tests/warnings/inc_dec_within_stmt.js +63 -0
- data/vendor/jsl-0.3.0/tests/warnings/jsl_cc_not_understood.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/leading_decimal_point.js +7 -0
- data/vendor/jsl-0.3.0/tests/warnings/legacy_cc_not_understood.js +9 -0
- data/vendor/jsl-0.3.0/tests/warnings/meaningless_block.js +12 -0
- data/vendor/jsl-0.3.0/tests/warnings/misplaced_regex.js +20 -0
- data/vendor/jsl-0.3.0/tests/warnings/missing_break.js +87 -0
- data/vendor/jsl-0.3.0/tests/warnings/missing_break_for_last_case.js +19 -0
- data/vendor/jsl-0.3.0/tests/warnings/missing_default_case.js +51 -0
- data/vendor/jsl-0.3.0/tests/warnings/missing_option_explicit.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/missing_semicolon.js +19 -0
- data/vendor/jsl-0.3.0/tests/warnings/multiple_plus_minus.js +10 -0
- data/vendor/jsl-0.3.0/tests/warnings/nested_comment.js +6 -0
- data/vendor/jsl-0.3.0/tests/warnings/no_return_value.js +25 -0
- data/vendor/jsl-0.3.0/tests/warnings/octal_number.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/parseint_missing_radix.js +15 -0
- data/vendor/jsl-0.3.0/tests/warnings/partial_option_explicit.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/redeclared_var.js +10 -0
- data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/bad_backref.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/deprecated_usage.js +11 -0
- data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/invalid_backref.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/trailing_comma.js +5 -0
- data/vendor/jsl-0.3.0/tests/warnings/trailing_comma_in_array.js +8 -0
- data/vendor/jsl-0.3.0/tests/warnings/trailing_decimal_point.js +7 -0
- data/vendor/jsl-0.3.0/tests/warnings/unreachable_code.js +29 -0
- data/vendor/jsl-0.3.0/tests/warnings/use_of_label.js +19 -0
- data/vendor/jsl-0.3.0/tests/warnings/useless_assign.js +20 -0
- data/vendor/jsl-0.3.0/tests/warnings/useless_comparison.js +55 -0
- data/vendor/jsl-0.3.0/tests/warnings/useless_void.js +6 -0
- data/vendor/jsl-0.3.0/tests/warnings/var_hides_arg.js +4 -0
- data/vendor/jsl-0.3.0/tests/warnings/with_statement.js +7 -0
- data/vendor/yuicompressor-2.4.2.jar +0 -0
- metadata +605 -0
|
@@ -0,0 +1,1441 @@
|
|
|
1
|
+
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
2
|
+
*
|
|
3
|
+
* ***** BEGIN LICENSE BLOCK *****
|
|
4
|
+
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
5
|
+
*
|
|
6
|
+
* The contents of this file are subject to the Mozilla Public License Version
|
|
7
|
+
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
8
|
+
* the License. You may obtain a copy of the License at
|
|
9
|
+
* http://www.mozilla.org/MPL/
|
|
10
|
+
*
|
|
11
|
+
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
12
|
+
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
13
|
+
* for the specific language governing rights and limitations under the
|
|
14
|
+
* License.
|
|
15
|
+
*
|
|
16
|
+
* The Original Code is Mozilla Communicator client code, released
|
|
17
|
+
* March 31, 1998.
|
|
18
|
+
*
|
|
19
|
+
* The Initial Developer of the Original Code is
|
|
20
|
+
* Netscape Communications Corporation.
|
|
21
|
+
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
22
|
+
* the Initial Developer. All Rights Reserved.
|
|
23
|
+
*
|
|
24
|
+
* Contributor(s):
|
|
25
|
+
*
|
|
26
|
+
* Alternatively, the contents of this file may be used under the terms of
|
|
27
|
+
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
28
|
+
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
29
|
+
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
30
|
+
* of those above. If you wish to allow use of your version of this file only
|
|
31
|
+
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
32
|
+
* use your version of this file under the terms of the MPL, indicate your
|
|
33
|
+
* decision by deleting the provisions above and replace them with the notice
|
|
34
|
+
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
35
|
+
* the provisions above, a recipient may use your version of this file under
|
|
36
|
+
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
37
|
+
*
|
|
38
|
+
* ***** END LICENSE BLOCK ***** */
|
|
39
|
+
|
|
40
|
+
/*
|
|
41
|
+
* JS Mark-and-Sweep Garbage Collector.
|
|
42
|
+
*
|
|
43
|
+
* This GC allocates only fixed-sized things big enough to contain two words
|
|
44
|
+
* (pointers) on any host architecture. It allocates from an arena pool (see
|
|
45
|
+
* jsarena.h). It uses an ideally parallel array of flag bytes to hold the
|
|
46
|
+
* mark bit, finalizer type index, etc.
|
|
47
|
+
*
|
|
48
|
+
* XXX swizzle page to freelist for better locality of reference
|
|
49
|
+
*/
|
|
50
|
+
#include "jsstddef.h"
|
|
51
|
+
#include <stdlib.h> /* for free, called by JS_ARENA_DESTROY */
|
|
52
|
+
#include <string.h> /* for memset, called by jsarena.h macros if DEBUG */
|
|
53
|
+
#include "jstypes.h"
|
|
54
|
+
#include "jsarena.h" /* Added by JSIFY */
|
|
55
|
+
#include "jsutil.h" /* Added by JSIFY */
|
|
56
|
+
#include "jshash.h" /* Added by JSIFY */
|
|
57
|
+
#include "jsapi.h"
|
|
58
|
+
#include "jsatom.h"
|
|
59
|
+
#include "jscntxt.h"
|
|
60
|
+
#include "jsconfig.h"
|
|
61
|
+
#include "jsdbgapi.h"
|
|
62
|
+
#include "jsfun.h"
|
|
63
|
+
#include "jsgc.h"
|
|
64
|
+
#include "jsinterp.h"
|
|
65
|
+
#include "jslock.h"
|
|
66
|
+
#include "jsnum.h"
|
|
67
|
+
#include "jsobj.h"
|
|
68
|
+
#include "jsscope.h"
|
|
69
|
+
#include "jsscript.h"
|
|
70
|
+
#include "jsstr.h"
|
|
71
|
+
|
|
72
|
+
/*
|
|
73
|
+
* GC arena sizing depends on amortizing arena overhead using a large number
|
|
74
|
+
* of things per arena, and on the thing/flags ratio of 8:1 on most platforms.
|
|
75
|
+
*
|
|
76
|
+
* On 64-bit platforms, we would have half as many things per arena because
|
|
77
|
+
* pointers are twice as big, so we double the bytes for things per arena.
|
|
78
|
+
* This preserves the 1024 byte flags sub-arena size, which relates to the
|
|
79
|
+
* GC_PAGE_SIZE (see below for why).
|
|
80
|
+
*/
|
|
81
|
+
#if JS_BYTES_PER_WORD == 8
|
|
82
|
+
# define GC_THINGS_SHIFT 14 /* 16KB for things on Alpha, etc. */
|
|
83
|
+
#else
|
|
84
|
+
# define GC_THINGS_SHIFT 13 /* 8KB for things on most platforms */
|
|
85
|
+
#endif
|
|
86
|
+
#define GC_THINGS_SIZE JS_BIT(GC_THINGS_SHIFT)
|
|
87
|
+
#define GC_FLAGS_SIZE (GC_THINGS_SIZE / sizeof(JSGCThing))
|
|
88
|
+
#define GC_ARENA_SIZE (GC_THINGS_SIZE + GC_FLAGS_SIZE)
|
|
89
|
+
|
|
90
|
+
/*
|
|
91
|
+
* The private JSGCThing struct, which describes a gcFreeList element.
|
|
92
|
+
*/
|
|
93
|
+
struct JSGCThing {
|
|
94
|
+
JSGCThing *next;
|
|
95
|
+
uint8 *flagp;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/*
|
|
99
|
+
* A GC arena contains one flag byte for each thing in its heap, and supports
|
|
100
|
+
* O(1) lookup of a flag given its thing's address.
|
|
101
|
+
*
|
|
102
|
+
* To implement this, we take advantage of the thing/flags numerology: given
|
|
103
|
+
* the 8K bytes worth of GC-things, there are 1K flag bytes. We mask a thing's
|
|
104
|
+
* address with ~1023 to find a JSGCPageInfo record at the front of a mythical
|
|
105
|
+
* "GC page" within the larger 8K thing arena. That JSGCPageInfo contains a
|
|
106
|
+
* pointer to the 128 flag bytes corresponding to the things in the page, so we
|
|
107
|
+
* index into this flags array using the thing's index within its page.
|
|
108
|
+
*
|
|
109
|
+
* To align thing pages on 1024-byte boundaries, we must allocate the 9KB of
|
|
110
|
+
* flags+things arena payload, then find the first 0 mod 1024 boundary after
|
|
111
|
+
* the first payload address. That's where things start, with a JSGCPageInfo
|
|
112
|
+
* taking up the first thing-slot, as usual for 0 mod 1024 byte boundaries.
|
|
113
|
+
* The effect of this alignment trick is to split the flags into at most 2
|
|
114
|
+
* discontiguous spans, one before the things and one after (if we're really
|
|
115
|
+
* lucky, and the arena payload starts on a 0 mod 1024 byte boundary, no need
|
|
116
|
+
* to split).
|
|
117
|
+
*
|
|
118
|
+
* The overhead of this scheme for most platforms is (16+8*(8+1))/(16+9K) or
|
|
119
|
+
* .95% (assuming 16 byte JSArena header size, and 8 byte JSGCThing size).
|
|
120
|
+
*
|
|
121
|
+
* Here's some ASCII art showing an arena:
|
|
122
|
+
*
|
|
123
|
+
* split
|
|
124
|
+
* |
|
|
125
|
+
* V
|
|
126
|
+
* +--+-------+-------+-------+-------+-------+-------+-------+-------+-----+
|
|
127
|
+
* |fB| tp0 | tp1 | tp2 | tp3 | tp4 | tp5 | tp6 | tp7 | fA |
|
|
128
|
+
* +--+-------+-------+-------+-------+-------+-------+-------+-------+-----+
|
|
129
|
+
* ^ ^
|
|
130
|
+
* tI ---------+ |
|
|
131
|
+
* tJ -------------------------------------------+
|
|
132
|
+
*
|
|
133
|
+
* - fB are the "before split" flags, fA are the "after split" flags
|
|
134
|
+
* - tp0-tp7 are the 8 thing pages
|
|
135
|
+
* - thing tI points into tp1, whose flags are below the split, in fB
|
|
136
|
+
* - thing tJ points into tp5, clearly above the split
|
|
137
|
+
*
|
|
138
|
+
* In general, one of the thing pages will have some of its things' flags on
|
|
139
|
+
* the low side of the split, and the rest of its things' flags on the high
|
|
140
|
+
* side. All the other pages have flags only below or only above. Therefore
|
|
141
|
+
* we'll have to test something to decide whether the split divides flags in
|
|
142
|
+
* a given thing's page. So we store the split pointer (the pointer to tp0)
|
|
143
|
+
* in each JSGCPageInfo, along with the flags pointer for the 128 flag bytes
|
|
144
|
+
* ideally starting, for tp0 things, at the beginning of the arena's payload
|
|
145
|
+
* (at the start of fB).
|
|
146
|
+
*
|
|
147
|
+
* That is, each JSGCPageInfo's flags pointer is 128 bytes from the previous,
|
|
148
|
+
* or at the start of the arena if there is no previous page in this arena.
|
|
149
|
+
* Thus these ideal 128-byte flag pages run contiguously from the start of the
|
|
150
|
+
* arena (right over the split!), and the JSGCPageInfo flags pointers contain
|
|
151
|
+
* no discontinuities over the split created by the thing pages. So if, for a
|
|
152
|
+
* given JSGCPageInfo *pi, we find that
|
|
153
|
+
*
|
|
154
|
+
* pi->flags + ((jsuword)thing % 1024) / sizeof(JSGCThing) >= pi->split
|
|
155
|
+
*
|
|
156
|
+
* then we must add GC_THINGS_SIZE to the nominal flags pointer to jump over
|
|
157
|
+
* all the thing pages that split the flags into two discontiguous spans.
|
|
158
|
+
*
|
|
159
|
+
* (If we need to implement card-marking for an incremental GC write barrier,
|
|
160
|
+
* we can use the low byte of the pi->split pointer as the card-mark, for an
|
|
161
|
+
* extremely efficient write barrier: when mutating an object obj, just store
|
|
162
|
+
* a 1 byte at (uint8 *) ((jsuword)obj & ~1023) for little-endian platforms.
|
|
163
|
+
* When finding flags, we'll of course have to mask split with ~255, but it is
|
|
164
|
+
* guaranteed to be 1024-byte aligned, so no information is lost by overlaying
|
|
165
|
+
* the card-mark byte on split's low byte.)
|
|
166
|
+
*/
|
|
167
|
+
#define GC_PAGE_SHIFT 10
|
|
168
|
+
#define GC_PAGE_MASK ((jsuword) JS_BITMASK(GC_PAGE_SHIFT))
|
|
169
|
+
#define GC_PAGE_SIZE JS_BIT(GC_PAGE_SHIFT)
|
|
170
|
+
|
|
171
|
+
typedef struct JSGCPageInfo {
|
|
172
|
+
uint8 *split;
|
|
173
|
+
uint8 *flags;
|
|
174
|
+
} JSGCPageInfo;
|
|
175
|
+
|
|
176
|
+
#define FIRST_THING_PAGE(a) (((a)->base + GC_FLAGS_SIZE) & ~GC_PAGE_MASK)
|
|
177
|
+
|
|
178
|
+
static JSGCThing *
|
|
179
|
+
gc_new_arena(JSArenaPool *pool)
|
|
180
|
+
{
|
|
181
|
+
uint8 *flagp, *split, *pagep, *limit;
|
|
182
|
+
JSArena *a;
|
|
183
|
+
JSGCThing *thing;
|
|
184
|
+
JSGCPageInfo *pi;
|
|
185
|
+
|
|
186
|
+
/* Use JS_ArenaAllocate to grab another 9K-net-size hunk of space. */
|
|
187
|
+
flagp = (uint8 *) JS_ArenaAllocate(pool, GC_ARENA_SIZE);
|
|
188
|
+
if (!flagp)
|
|
189
|
+
return NULL;
|
|
190
|
+
a = pool->current;
|
|
191
|
+
|
|
192
|
+
/* Reset a->avail to start at the flags split, aka the first thing page. */
|
|
193
|
+
a->avail = FIRST_THING_PAGE(a);
|
|
194
|
+
split = pagep = (uint8 *) a->avail;
|
|
195
|
+
a->avail += sizeof(JSGCPageInfo);
|
|
196
|
+
thing = (JSGCThing *) a->avail;
|
|
197
|
+
a->avail += sizeof(JSGCThing);
|
|
198
|
+
|
|
199
|
+
/* Initialize the JSGCPageInfo records at the start of every thing page. */
|
|
200
|
+
limit = pagep + GC_THINGS_SIZE;
|
|
201
|
+
do {
|
|
202
|
+
pi = (JSGCPageInfo *) pagep;
|
|
203
|
+
pi->split = split;
|
|
204
|
+
pi->flags = flagp;
|
|
205
|
+
flagp += GC_PAGE_SIZE >> (GC_THINGS_SHIFT - GC_PAGE_SHIFT);
|
|
206
|
+
pagep += GC_PAGE_SIZE;
|
|
207
|
+
} while (pagep < limit);
|
|
208
|
+
return thing;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
uint8 *
|
|
212
|
+
js_GetGCThingFlags(void *thing)
|
|
213
|
+
{
|
|
214
|
+
JSGCPageInfo *pi;
|
|
215
|
+
uint8 *flagp;
|
|
216
|
+
|
|
217
|
+
pi = (JSGCPageInfo *) ((jsuword)thing & ~GC_PAGE_MASK);
|
|
218
|
+
flagp = pi->flags + ((jsuword)thing & GC_PAGE_MASK) / sizeof(JSGCThing);
|
|
219
|
+
if (flagp >= pi->split)
|
|
220
|
+
flagp += GC_THINGS_SIZE;
|
|
221
|
+
return flagp;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
JSBool
|
|
225
|
+
js_IsAboutToBeFinalized(JSContext *cx, void *thing)
|
|
226
|
+
{
|
|
227
|
+
uint8 flags = *js_GetGCThingFlags(thing);
|
|
228
|
+
|
|
229
|
+
return !(flags & (GCF_MARK | GCF_LOCKMASK | GCF_FINAL));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
typedef void (*GCFinalizeOp)(JSContext *cx, JSGCThing *thing);
|
|
233
|
+
|
|
234
|
+
static GCFinalizeOp gc_finalizers[GCX_NTYPES];
|
|
235
|
+
|
|
236
|
+
intN
|
|
237
|
+
js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
|
|
238
|
+
JSStringFinalizeOp newop)
|
|
239
|
+
{
|
|
240
|
+
uintN i;
|
|
241
|
+
|
|
242
|
+
for (i = GCX_EXTERNAL_STRING; i < GCX_NTYPES; i++) {
|
|
243
|
+
if (gc_finalizers[i] == (GCFinalizeOp) oldop) {
|
|
244
|
+
gc_finalizers[i] = (GCFinalizeOp) newop;
|
|
245
|
+
return (intN) i;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return -1;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
#ifdef JS_GCMETER
|
|
252
|
+
#define METER(x) x
|
|
253
|
+
#else
|
|
254
|
+
#define METER(x) /* nothing */
|
|
255
|
+
#endif
|
|
256
|
+
|
|
257
|
+
/* Initial size of the gcRootsHash table (SWAG, small enough to amortize). */
|
|
258
|
+
#define GC_ROOTS_SIZE 256
|
|
259
|
+
#define GC_FINALIZE_LEN 1024
|
|
260
|
+
|
|
261
|
+
JSBool
|
|
262
|
+
js_InitGC(JSRuntime *rt, uint32 maxbytes)
|
|
263
|
+
{
|
|
264
|
+
JS_ASSERT(sizeof(JSGCThing) == sizeof(JSGCPageInfo));
|
|
265
|
+
JS_ASSERT(sizeof(JSGCThing) >= sizeof(JSObject));
|
|
266
|
+
JS_ASSERT(sizeof(JSGCThing) >= sizeof(JSString));
|
|
267
|
+
JS_ASSERT(sizeof(JSGCThing) >= sizeof(jsdouble));
|
|
268
|
+
JS_ASSERT(GC_FLAGS_SIZE >= GC_PAGE_SIZE);
|
|
269
|
+
JS_ASSERT(sizeof(JSStackHeader) >= 2 * sizeof(jsval));
|
|
270
|
+
|
|
271
|
+
if (!gc_finalizers[GCX_OBJECT]) {
|
|
272
|
+
gc_finalizers[GCX_OBJECT] = (GCFinalizeOp)js_FinalizeObject;
|
|
273
|
+
gc_finalizers[GCX_STRING] = (GCFinalizeOp)js_FinalizeString;
|
|
274
|
+
#ifdef DEBUG
|
|
275
|
+
gc_finalizers[GCX_DOUBLE] = (GCFinalizeOp)js_FinalizeDouble;
|
|
276
|
+
#endif
|
|
277
|
+
gc_finalizers[GCX_MUTABLE_STRING] = (GCFinalizeOp)js_FinalizeString;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
JS_InitArenaPool(&rt->gcArenaPool, "gc-arena", GC_ARENA_SIZE,
|
|
281
|
+
sizeof(JSGCThing));
|
|
282
|
+
if (!JS_DHashTableInit(&rt->gcRootsHash, JS_DHashGetStubOps(), NULL,
|
|
283
|
+
sizeof(JSGCRootHashEntry), GC_ROOTS_SIZE)) {
|
|
284
|
+
rt->gcRootsHash.ops = NULL;
|
|
285
|
+
return JS_FALSE;
|
|
286
|
+
}
|
|
287
|
+
rt->gcLocksHash = NULL; /* create lazily */
|
|
288
|
+
rt->gcMaxBytes = maxbytes;
|
|
289
|
+
return JS_TRUE;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
#ifdef JS_GCMETER
|
|
293
|
+
void
|
|
294
|
+
js_DumpGCStats(JSRuntime *rt, FILE *fp)
|
|
295
|
+
{
|
|
296
|
+
fprintf(fp, "\nGC allocation statistics:\n");
|
|
297
|
+
fprintf(fp, " bytes currently allocated: %lu\n", rt->gcBytes);
|
|
298
|
+
fprintf(fp, " alloc attempts: %lu\n", rt->gcStats.alloc);
|
|
299
|
+
fprintf(fp, " GC freelist length: %lu\n", rt->gcStats.freelen);
|
|
300
|
+
fprintf(fp, " recycles through GC freelist: %lu\n", rt->gcStats.recycle);
|
|
301
|
+
fprintf(fp, "alloc retries after running GC: %lu\n", rt->gcStats.retry);
|
|
302
|
+
fprintf(fp, " allocation failures: %lu\n", rt->gcStats.fail);
|
|
303
|
+
fprintf(fp, " valid lock calls: %lu\n", rt->gcStats.lock);
|
|
304
|
+
fprintf(fp, " valid unlock calls: %lu\n", rt->gcStats.unlock);
|
|
305
|
+
fprintf(fp, " locks that hit stuck counts: %lu\n", rt->gcStats.stuck);
|
|
306
|
+
fprintf(fp, " unlocks that saw stuck counts: %lu\n", rt->gcStats.unstuck);
|
|
307
|
+
fprintf(fp, " mark recursion depth: %lu\n", rt->gcStats.depth);
|
|
308
|
+
fprintf(fp, " maximum mark recursion depth: %lu\n", rt->gcStats.maxdepth);
|
|
309
|
+
fprintf(fp, " maximum GC nesting level: %lu\n", rt->gcStats.maxlevel);
|
|
310
|
+
fprintf(fp, " potentially useful GC calls: %lu\n", rt->gcStats.poke);
|
|
311
|
+
fprintf(fp, " useless GC calls: %lu\n", rt->gcStats.nopoke);
|
|
312
|
+
fprintf(fp, " thing arenas freed so far: %lu\n", rt->gcStats.afree);
|
|
313
|
+
fprintf(fp, " extra stack segments scanned: %lu\n", rt->gcStats.stackseg);
|
|
314
|
+
fprintf(fp, " stack segment slots scanned: %lu\n", rt->gcStats.segslots);
|
|
315
|
+
#ifdef JS_ARENAMETER
|
|
316
|
+
JS_DumpArenaStats(fp);
|
|
317
|
+
#endif
|
|
318
|
+
}
|
|
319
|
+
#endif
|
|
320
|
+
|
|
321
|
+
#ifdef DEBUG
|
|
322
|
+
JS_STATIC_DLL_CALLBACK(JSDHashOperator)
|
|
323
|
+
js_root_printer(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 i, void *arg)
|
|
324
|
+
{
|
|
325
|
+
uint32 *leakedroots = (uint32 *)arg;
|
|
326
|
+
JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
|
|
327
|
+
|
|
328
|
+
(*leakedroots)++;
|
|
329
|
+
fprintf(stderr,
|
|
330
|
+
"JS engine warning: leaking GC root \'%s\' at %p\n",
|
|
331
|
+
rhe->name ? (char *)rhe->name : "", rhe->root);
|
|
332
|
+
|
|
333
|
+
return JS_DHASH_NEXT;
|
|
334
|
+
}
|
|
335
|
+
#endif
|
|
336
|
+
|
|
337
|
+
void
|
|
338
|
+
js_FinishGC(JSRuntime *rt)
|
|
339
|
+
{
|
|
340
|
+
#ifdef JS_ARENAMETER
|
|
341
|
+
JS_DumpArenaStats(stdout);
|
|
342
|
+
#endif
|
|
343
|
+
#ifdef JS_GCMETER
|
|
344
|
+
js_DumpGCStats(rt, stdout);
|
|
345
|
+
#endif
|
|
346
|
+
JS_FinishArenaPool(&rt->gcArenaPool);
|
|
347
|
+
JS_ArenaFinish();
|
|
348
|
+
|
|
349
|
+
if (rt->gcRootsHash.ops) {
|
|
350
|
+
#ifdef DEBUG
|
|
351
|
+
uint32 leakedroots = 0;
|
|
352
|
+
|
|
353
|
+
/* Warn (but don't assert) debug builds of any remaining roots. */
|
|
354
|
+
JS_DHashTableEnumerate(&rt->gcRootsHash, js_root_printer,
|
|
355
|
+
&leakedroots);
|
|
356
|
+
if (leakedroots > 0) {
|
|
357
|
+
if (leakedroots == 1) {
|
|
358
|
+
fprintf(stderr,
|
|
359
|
+
"JS engine warning: 1 GC root remains after destroying the JSRuntime.\n"
|
|
360
|
+
" This root may point to freed memory. Objects reachable\n"
|
|
361
|
+
" through it have not been finalized.\n");
|
|
362
|
+
} else {
|
|
363
|
+
fprintf(stderr,
|
|
364
|
+
"JS engine warning: %lu GC roots remain after destroying the JSRuntime.\n"
|
|
365
|
+
" These roots may point to freed memory. Objects reachable\n"
|
|
366
|
+
" through them have not been finalized.\n",
|
|
367
|
+
(unsigned long) leakedroots);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
#endif
|
|
371
|
+
|
|
372
|
+
JS_DHashTableFinish(&rt->gcRootsHash);
|
|
373
|
+
rt->gcRootsHash.ops = NULL;
|
|
374
|
+
}
|
|
375
|
+
if (rt->gcLocksHash) {
|
|
376
|
+
JS_DHashTableDestroy(rt->gcLocksHash);
|
|
377
|
+
rt->gcLocksHash = NULL;
|
|
378
|
+
}
|
|
379
|
+
rt->gcFreeList = NULL;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
JSBool
|
|
383
|
+
js_AddRoot(JSContext *cx, void *rp, const char *name)
|
|
384
|
+
{
|
|
385
|
+
JSBool ok = js_AddRootRT(cx->runtime, rp, name);
|
|
386
|
+
if (!ok)
|
|
387
|
+
JS_ReportOutOfMemory(cx);
|
|
388
|
+
return ok;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
JSBool
|
|
392
|
+
js_AddRootRT(JSRuntime *rt, void *rp, const char *name)
|
|
393
|
+
{
|
|
394
|
+
JSBool ok;
|
|
395
|
+
JSGCRootHashEntry *rhe;
|
|
396
|
+
|
|
397
|
+
/*
|
|
398
|
+
* Due to the long-standing, but now removed, use of rt->gcLock across the
|
|
399
|
+
* bulk of js_GC, API users have come to depend on JS_AddRoot etc. locking
|
|
400
|
+
* properly with a racing GC, without calling JS_AddRoot from a request.
|
|
401
|
+
* We have to preserve API compatibility here, now that we avoid holding
|
|
402
|
+
* rt->gcLock across the mark phase (including the root hashtable mark).
|
|
403
|
+
*
|
|
404
|
+
* If the GC is running and we're called on another thread, wait for this
|
|
405
|
+
* GC activation to finish. We can safely wait here (in the case where we
|
|
406
|
+
* are called within a request on another thread's context) without fear
|
|
407
|
+
* of deadlock because the GC doesn't set rt->gcRunning until after it has
|
|
408
|
+
* waited for all active requests to end.
|
|
409
|
+
*/
|
|
410
|
+
JS_LOCK_GC(rt);
|
|
411
|
+
#ifdef JS_THREADSAFE
|
|
412
|
+
JS_ASSERT(!rt->gcRunning || rt->gcLevel > 0);
|
|
413
|
+
if (rt->gcRunning && rt->gcThread != js_CurrentThreadId()) {
|
|
414
|
+
do {
|
|
415
|
+
JS_AWAIT_GC_DONE(rt);
|
|
416
|
+
} while (rt->gcLevel > 0);
|
|
417
|
+
}
|
|
418
|
+
#endif
|
|
419
|
+
rhe = (JSGCRootHashEntry *) JS_DHashTableOperate(&rt->gcRootsHash, rp,
|
|
420
|
+
JS_DHASH_ADD);
|
|
421
|
+
if (rhe) {
|
|
422
|
+
rhe->root = rp;
|
|
423
|
+
rhe->name = name;
|
|
424
|
+
ok = JS_TRUE;
|
|
425
|
+
} else {
|
|
426
|
+
ok = JS_FALSE;
|
|
427
|
+
}
|
|
428
|
+
JS_UNLOCK_GC(rt);
|
|
429
|
+
return ok;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
JSBool
|
|
433
|
+
js_RemoveRoot(JSRuntime *rt, void *rp)
|
|
434
|
+
{
|
|
435
|
+
/*
|
|
436
|
+
* Due to the JS_RemoveRootRT API, we may be called outside of a request.
|
|
437
|
+
* Same synchronization drill as above in js_AddRoot.
|
|
438
|
+
*/
|
|
439
|
+
JS_LOCK_GC(rt);
|
|
440
|
+
#ifdef JS_THREADSAFE
|
|
441
|
+
JS_ASSERT(!rt->gcRunning || rt->gcLevel > 0);
|
|
442
|
+
if (rt->gcRunning && rt->gcThread != js_CurrentThreadId()) {
|
|
443
|
+
do {
|
|
444
|
+
JS_AWAIT_GC_DONE(rt);
|
|
445
|
+
} while (rt->gcLevel > 0);
|
|
446
|
+
}
|
|
447
|
+
#endif
|
|
448
|
+
(void) JS_DHashTableOperate(&rt->gcRootsHash, rp, JS_DHASH_REMOVE);
|
|
449
|
+
rt->gcPoke = JS_TRUE;
|
|
450
|
+
JS_UNLOCK_GC(rt);
|
|
451
|
+
return JS_TRUE;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
void *
|
|
455
|
+
js_AllocGCThing(JSContext *cx, uintN flags)
|
|
456
|
+
{
|
|
457
|
+
JSBool tried_gc;
|
|
458
|
+
JSRuntime *rt;
|
|
459
|
+
JSGCThing *thing;
|
|
460
|
+
uint8 *flagp;
|
|
461
|
+
JSLocalRootStack *lrs;
|
|
462
|
+
|
|
463
|
+
#ifdef TOO_MUCH_GC
|
|
464
|
+
js_GC(cx, GC_KEEP_ATOMS);
|
|
465
|
+
tried_gc = JS_TRUE;
|
|
466
|
+
#else
|
|
467
|
+
tried_gc = JS_FALSE;
|
|
468
|
+
#endif
|
|
469
|
+
|
|
470
|
+
rt = cx->runtime;
|
|
471
|
+
JS_LOCK_GC(rt);
|
|
472
|
+
JS_ASSERT(!rt->gcRunning);
|
|
473
|
+
if (rt->gcRunning) {
|
|
474
|
+
METER(rt->gcStats.finalfail++);
|
|
475
|
+
JS_UNLOCK_GC(rt);
|
|
476
|
+
return NULL;
|
|
477
|
+
}
|
|
478
|
+
METER(rt->gcStats.alloc++);
|
|
479
|
+
retry:
|
|
480
|
+
thing = rt->gcFreeList;
|
|
481
|
+
if (thing) {
|
|
482
|
+
rt->gcFreeList = thing->next;
|
|
483
|
+
flagp = thing->flagp;
|
|
484
|
+
METER(rt->gcStats.freelen--);
|
|
485
|
+
METER(rt->gcStats.recycle++);
|
|
486
|
+
} else {
|
|
487
|
+
if (rt->gcBytes < rt->gcMaxBytes &&
|
|
488
|
+
(tried_gc || rt->gcMallocBytes < rt->gcMaxBytes))
|
|
489
|
+
{
|
|
490
|
+
/*
|
|
491
|
+
* Inline form of JS_ARENA_ALLOCATE adapted to truncate the current
|
|
492
|
+
* arena's limit to a GC_PAGE_SIZE boundary, and to skip over every
|
|
493
|
+
* GC_PAGE_SIZE-byte-aligned thing (which is actually not a thing,
|
|
494
|
+
* it's a JSGCPageInfo record).
|
|
495
|
+
*/
|
|
496
|
+
JSArenaPool *pool = &rt->gcArenaPool;
|
|
497
|
+
JSArena *a = pool->current;
|
|
498
|
+
size_t nb = sizeof(JSGCThing);
|
|
499
|
+
jsuword p = a->avail;
|
|
500
|
+
jsuword q = p + nb;
|
|
501
|
+
|
|
502
|
+
if (q > (a->limit & ~GC_PAGE_MASK)) {
|
|
503
|
+
thing = gc_new_arena(pool);
|
|
504
|
+
} else {
|
|
505
|
+
if ((p & GC_PAGE_MASK) == 0) {
|
|
506
|
+
/* Beware, p points to a JSGCPageInfo record! */
|
|
507
|
+
p = q;
|
|
508
|
+
q += nb;
|
|
509
|
+
JS_ArenaCountAllocation(pool, nb);
|
|
510
|
+
}
|
|
511
|
+
a->avail = q;
|
|
512
|
+
thing = (JSGCThing *)p;
|
|
513
|
+
}
|
|
514
|
+
JS_ArenaCountAllocation(pool, nb);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/*
|
|
518
|
+
* Consider doing a "last ditch" GC if thing couldn't be allocated.
|
|
519
|
+
*
|
|
520
|
+
* Keep rt->gcLock across the call into js_GC so we don't starve and
|
|
521
|
+
* lose to racing threads who deplete the heap just after js_GC has
|
|
522
|
+
* replenished it (or has synchronized with a racing GC that collected
|
|
523
|
+
* a bunch of garbage). This unfair scheduling can happen on certain
|
|
524
|
+
* operating systems. For the gory details, see Mozilla bug 162779
|
|
525
|
+
* (http://bugzilla.mozilla.org/show_bug.cgi?id=162779).
|
|
526
|
+
*/
|
|
527
|
+
if (!thing) {
|
|
528
|
+
if (!tried_gc) {
|
|
529
|
+
rt->gcPoke = JS_TRUE;
|
|
530
|
+
js_GC(cx, GC_KEEP_ATOMS | GC_ALREADY_LOCKED);
|
|
531
|
+
tried_gc = JS_TRUE;
|
|
532
|
+
METER(rt->gcStats.retry++);
|
|
533
|
+
goto retry;
|
|
534
|
+
}
|
|
535
|
+
goto fail;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/* Find the flags pointer given thing's address. */
|
|
539
|
+
flagp = js_GetGCThingFlags(thing);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
lrs = cx->localRootStack;
|
|
543
|
+
if (lrs) {
|
|
544
|
+
/*
|
|
545
|
+
* If we're in a local root scope, don't set cx->newborn[type] at all,
|
|
546
|
+
* to avoid entraining garbage from it for an unbounded amount of time
|
|
547
|
+
* on this context. A caller will leave the local root scope and pop
|
|
548
|
+
* this reference, allowing thing to be GC'd if it has no other refs.
|
|
549
|
+
* See JS_EnterLocalRootScope and related APIs.
|
|
550
|
+
*/
|
|
551
|
+
if (js_PushLocalRoot(cx, lrs, (jsval) thing) < 0)
|
|
552
|
+
goto fail;
|
|
553
|
+
} else {
|
|
554
|
+
/*
|
|
555
|
+
* No local root scope, so we're stuck with the old, fragile model of
|
|
556
|
+
* depending on a pigeon-hole newborn per type per context.
|
|
557
|
+
*/
|
|
558
|
+
cx->newborn[flags & GCF_TYPEMASK] = thing;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/* We can't fail now, so update flags and rt->gcBytes. */
|
|
562
|
+
*flagp = (uint8)flags;
|
|
563
|
+
rt->gcBytes += sizeof(JSGCThing) + sizeof(uint8);
|
|
564
|
+
|
|
565
|
+
/*
|
|
566
|
+
* Clear thing before unlocking in case a GC run is about to scan it,
|
|
567
|
+
* finding it via cx->newborn[].
|
|
568
|
+
*/
|
|
569
|
+
thing->next = NULL;
|
|
570
|
+
thing->flagp = NULL;
|
|
571
|
+
JS_UNLOCK_GC(rt);
|
|
572
|
+
return thing;
|
|
573
|
+
|
|
574
|
+
fail:
|
|
575
|
+
METER(rt->gcStats.fail++);
|
|
576
|
+
JS_UNLOCK_GC(rt);
|
|
577
|
+
JS_ReportOutOfMemory(cx);
|
|
578
|
+
return NULL;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
JSBool
|
|
582
|
+
js_LockGCThing(JSContext *cx, void *thing)
|
|
583
|
+
{
|
|
584
|
+
JSBool ok = js_LockGCThingRT(cx->runtime, thing);
|
|
585
|
+
if (!ok)
|
|
586
|
+
JS_ReportOutOfMemory(cx);
|
|
587
|
+
return ok;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
JSBool
|
|
591
|
+
js_LockGCThingRT(JSRuntime *rt, void *thing)
|
|
592
|
+
{
|
|
593
|
+
uint8 *flagp, flags, lockbits;
|
|
594
|
+
JSBool ok;
|
|
595
|
+
JSGCLockHashEntry *lhe;
|
|
596
|
+
|
|
597
|
+
if (!thing)
|
|
598
|
+
return JS_TRUE;
|
|
599
|
+
flagp = js_GetGCThingFlags(thing);
|
|
600
|
+
flags = *flagp;
|
|
601
|
+
|
|
602
|
+
ok = JS_FALSE;
|
|
603
|
+
JS_LOCK_GC(rt);
|
|
604
|
+
lockbits = (flags & GCF_LOCKMASK);
|
|
605
|
+
|
|
606
|
+
if (lockbits != GCF_LOCKMASK) {
|
|
607
|
+
if ((flags & GCF_TYPEMASK) == GCX_OBJECT) {
|
|
608
|
+
/* Objects may require "deep locking", i.e., rooting by value. */
|
|
609
|
+
if (lockbits == 0) {
|
|
610
|
+
if (!rt->gcLocksHash) {
|
|
611
|
+
rt->gcLocksHash =
|
|
612
|
+
JS_NewDHashTable(JS_DHashGetStubOps(), NULL,
|
|
613
|
+
sizeof(JSGCLockHashEntry),
|
|
614
|
+
GC_ROOTS_SIZE);
|
|
615
|
+
if (!rt->gcLocksHash)
|
|
616
|
+
goto error;
|
|
617
|
+
} else {
|
|
618
|
+
#ifdef DEBUG
|
|
619
|
+
JSDHashEntryHdr *hdr =
|
|
620
|
+
JS_DHashTableOperate(rt->gcLocksHash, thing,
|
|
621
|
+
JS_DHASH_LOOKUP);
|
|
622
|
+
JS_ASSERT(JS_DHASH_ENTRY_IS_FREE(hdr));
|
|
623
|
+
#endif
|
|
624
|
+
}
|
|
625
|
+
lhe = (JSGCLockHashEntry *)
|
|
626
|
+
JS_DHashTableOperate(rt->gcLocksHash, thing, JS_DHASH_ADD);
|
|
627
|
+
if (!lhe)
|
|
628
|
+
goto error;
|
|
629
|
+
lhe->thing = thing;
|
|
630
|
+
lhe->count = 1;
|
|
631
|
+
*flagp = (uint8)(flags + GCF_LOCK);
|
|
632
|
+
} else {
|
|
633
|
+
JS_ASSERT(lockbits == GCF_LOCK);
|
|
634
|
+
lhe = (JSGCLockHashEntry *)
|
|
635
|
+
JS_DHashTableOperate(rt->gcLocksHash, thing,
|
|
636
|
+
JS_DHASH_LOOKUP);
|
|
637
|
+
JS_ASSERT(JS_DHASH_ENTRY_IS_BUSY(&lhe->hdr));
|
|
638
|
+
if (JS_DHASH_ENTRY_IS_BUSY(&lhe->hdr)) {
|
|
639
|
+
JS_ASSERT(lhe->count >= 1);
|
|
640
|
+
lhe->count++;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
} else {
|
|
644
|
+
*flagp = (uint8)(flags + GCF_LOCK);
|
|
645
|
+
}
|
|
646
|
+
} else {
|
|
647
|
+
METER(rt->gcStats.stuck++);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
METER(rt->gcStats.lock++);
|
|
651
|
+
ok = JS_TRUE;
|
|
652
|
+
error:
|
|
653
|
+
JS_UNLOCK_GC(rt);
|
|
654
|
+
return ok;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
JSBool
|
|
658
|
+
js_UnlockGCThingRT(JSRuntime *rt, void *thing)
|
|
659
|
+
{
|
|
660
|
+
uint8 *flagp, flags, lockbits;
|
|
661
|
+
JSGCLockHashEntry *lhe;
|
|
662
|
+
|
|
663
|
+
if (!thing)
|
|
664
|
+
return JS_TRUE;
|
|
665
|
+
flagp = js_GetGCThingFlags(thing);
|
|
666
|
+
flags = *flagp;
|
|
667
|
+
|
|
668
|
+
JS_LOCK_GC(rt);
|
|
669
|
+
lockbits = (flags & GCF_LOCKMASK);
|
|
670
|
+
|
|
671
|
+
if (lockbits != GCF_LOCKMASK) {
|
|
672
|
+
if ((flags & GCF_TYPEMASK) == GCX_OBJECT) {
|
|
673
|
+
/* Defend against a call on an unlocked object. */
|
|
674
|
+
if (lockbits != 0) {
|
|
675
|
+
JS_ASSERT(lockbits == GCF_LOCK);
|
|
676
|
+
lhe = (JSGCLockHashEntry *)
|
|
677
|
+
JS_DHashTableOperate(rt->gcLocksHash, thing,
|
|
678
|
+
JS_DHASH_LOOKUP);
|
|
679
|
+
JS_ASSERT(JS_DHASH_ENTRY_IS_BUSY(&lhe->hdr));
|
|
680
|
+
if (JS_DHASH_ENTRY_IS_BUSY(&lhe->hdr) &&
|
|
681
|
+
--lhe->count == 0) {
|
|
682
|
+
(void) JS_DHashTableOperate(rt->gcLocksHash, thing,
|
|
683
|
+
JS_DHASH_REMOVE);
|
|
684
|
+
*flagp = (uint8)(flags & ~GCF_LOCKMASK);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
} else {
|
|
688
|
+
*flagp = (uint8)(flags - GCF_LOCK);
|
|
689
|
+
}
|
|
690
|
+
} else {
|
|
691
|
+
METER(rt->gcStats.unstuck++);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
rt->gcPoke = JS_TRUE;
|
|
695
|
+
METER(rt->gcStats.unlock++);
|
|
696
|
+
JS_UNLOCK_GC(rt);
|
|
697
|
+
return JS_TRUE;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
#ifdef GC_MARK_DEBUG
|
|
701
|
+
|
|
702
|
+
#include <stdio.h>
|
|
703
|
+
#include <stdlib.h>
|
|
704
|
+
#include "jsprf.h"
|
|
705
|
+
|
|
706
|
+
JS_FRIEND_DATA(FILE *) js_DumpGCHeap;
|
|
707
|
+
JS_EXPORT_DATA(void *) js_LiveThingToFind;
|
|
708
|
+
|
|
709
|
+
#ifdef HAVE_XPCONNECT
|
|
710
|
+
#include "dump_xpc.h"
|
|
711
|
+
#endif
|
|
712
|
+
|
|
713
|
+
static const char *
|
|
714
|
+
gc_object_class_name(void* thing)
|
|
715
|
+
{
|
|
716
|
+
uint8 *flagp = js_GetGCThingFlags(thing);
|
|
717
|
+
const char *className = "";
|
|
718
|
+
static char depbuf[32];
|
|
719
|
+
|
|
720
|
+
switch (*flagp & GCF_TYPEMASK) {
|
|
721
|
+
case GCX_OBJECT: {
|
|
722
|
+
JSObject *obj = (JSObject *)thing;
|
|
723
|
+
JSClass *clasp = JSVAL_TO_PRIVATE(obj->slots[JSSLOT_CLASS]);
|
|
724
|
+
className = clasp->name;
|
|
725
|
+
#ifdef HAVE_XPCONNECT
|
|
726
|
+
if (clasp->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) {
|
|
727
|
+
jsval privateValue = obj->slots[JSSLOT_PRIVATE];
|
|
728
|
+
|
|
729
|
+
JS_ASSERT(clasp->flags & JSCLASS_HAS_PRIVATE);
|
|
730
|
+
if (!JSVAL_IS_VOID(privateValue)) {
|
|
731
|
+
void *privateThing = JSVAL_TO_PRIVATE(privateValue);
|
|
732
|
+
const char *xpcClassName = GetXPCObjectClassName(privateThing);
|
|
733
|
+
|
|
734
|
+
if (xpcClassName)
|
|
735
|
+
className = xpcClassName;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
#endif
|
|
739
|
+
break;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
case GCX_STRING:
|
|
743
|
+
case GCX_MUTABLE_STRING: {
|
|
744
|
+
JSString *str = (JSString *)thing;
|
|
745
|
+
if (JSSTRING_IS_DEPENDENT(str)) {
|
|
746
|
+
JS_snprintf(depbuf, sizeof depbuf, "start:%u, length:%u",
|
|
747
|
+
JSSTRDEP_START(str), JSSTRDEP_LENGTH(str));
|
|
748
|
+
className = depbuf;
|
|
749
|
+
} else {
|
|
750
|
+
className = "string";
|
|
751
|
+
}
|
|
752
|
+
break;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
case GCX_DOUBLE:
|
|
756
|
+
className = "double";
|
|
757
|
+
break;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
return className;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
static void
|
|
764
|
+
gc_dump_thing(JSGCThing *thing, uint8 flags, GCMarkNode *prev, FILE *fp)
|
|
765
|
+
{
|
|
766
|
+
GCMarkNode *next = NULL;
|
|
767
|
+
char *path = NULL;
|
|
768
|
+
|
|
769
|
+
while (prev) {
|
|
770
|
+
next = prev;
|
|
771
|
+
prev = prev->prev;
|
|
772
|
+
}
|
|
773
|
+
while (next) {
|
|
774
|
+
path = JS_sprintf_append(path, "%s(%s).",
|
|
775
|
+
next->name,
|
|
776
|
+
gc_object_class_name(next->thing));
|
|
777
|
+
next = next->next;
|
|
778
|
+
}
|
|
779
|
+
if (!path)
|
|
780
|
+
return;
|
|
781
|
+
|
|
782
|
+
fprintf(fp, "%08lx ", (long)thing);
|
|
783
|
+
switch (flags & GCF_TYPEMASK) {
|
|
784
|
+
case GCX_OBJECT:
|
|
785
|
+
{
|
|
786
|
+
JSObject *obj = (JSObject *)thing;
|
|
787
|
+
jsval privateValue = obj->slots[JSSLOT_PRIVATE];
|
|
788
|
+
void *privateThing = JSVAL_IS_VOID(privateValue)
|
|
789
|
+
? NULL
|
|
790
|
+
: JSVAL_TO_PRIVATE(privateValue);
|
|
791
|
+
const char *className = gc_object_class_name(thing);
|
|
792
|
+
fprintf(fp, "object %8p %s", privateThing, className);
|
|
793
|
+
break;
|
|
794
|
+
}
|
|
795
|
+
case GCX_DOUBLE:
|
|
796
|
+
fprintf(fp, "double %g", *(jsdouble *)thing);
|
|
797
|
+
break;
|
|
798
|
+
default:
|
|
799
|
+
fprintf(fp, "string %s", JS_GetStringBytes((JSString *)thing));
|
|
800
|
+
break;
|
|
801
|
+
}
|
|
802
|
+
fprintf(fp, " via %s\n", path);
|
|
803
|
+
free(path);
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
#endif /* !GC_MARK_DEBUG */
|
|
807
|
+
|
|
808
|
+
static void
|
|
809
|
+
gc_mark_atom_key_thing(void *thing, void *arg)
|
|
810
|
+
{
|
|
811
|
+
JSContext *cx = (JSContext *) arg;
|
|
812
|
+
|
|
813
|
+
GC_MARK(cx, thing, "atom", NULL);
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
void
|
|
817
|
+
js_MarkAtom(JSContext *cx, JSAtom *atom, void *arg)
|
|
818
|
+
{
|
|
819
|
+
jsval key;
|
|
820
|
+
|
|
821
|
+
if (atom->flags & ATOM_MARK)
|
|
822
|
+
return;
|
|
823
|
+
atom->flags |= ATOM_MARK;
|
|
824
|
+
key = ATOM_KEY(atom);
|
|
825
|
+
if (JSVAL_IS_GCTHING(key)) {
|
|
826
|
+
#ifdef GC_MARK_DEBUG
|
|
827
|
+
char name[32];
|
|
828
|
+
|
|
829
|
+
if (JSVAL_IS_STRING(key)) {
|
|
830
|
+
JS_snprintf(name, sizeof name, "'%s'",
|
|
831
|
+
JS_GetStringBytes(JSVAL_TO_STRING(key)));
|
|
832
|
+
} else {
|
|
833
|
+
JS_snprintf(name, sizeof name, "<%x>", key);
|
|
834
|
+
}
|
|
835
|
+
#endif
|
|
836
|
+
GC_MARK(cx, JSVAL_TO_GCTHING(key), name, arg);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
void
|
|
841
|
+
js_MarkGCThing(JSContext *cx, void *thing, void *arg)
|
|
842
|
+
{
|
|
843
|
+
uint8 flags, *flagp;
|
|
844
|
+
JSRuntime *rt;
|
|
845
|
+
JSObject *obj;
|
|
846
|
+
uint32 nslots;
|
|
847
|
+
jsval v, *vp, *end;
|
|
848
|
+
JSString *str;
|
|
849
|
+
#ifdef GC_MARK_DEBUG
|
|
850
|
+
JSScope *scope;
|
|
851
|
+
JSScopeProperty *sprop;
|
|
852
|
+
#endif
|
|
853
|
+
|
|
854
|
+
if (!thing)
|
|
855
|
+
return;
|
|
856
|
+
|
|
857
|
+
flagp = js_GetGCThingFlags(thing);
|
|
858
|
+
flags = *flagp;
|
|
859
|
+
JS_ASSERT(flags != GCF_FINAL);
|
|
860
|
+
#ifdef GC_MARK_DEBUG
|
|
861
|
+
if (js_LiveThingToFind == thing)
|
|
862
|
+
gc_dump_thing(thing, flags, arg, stderr);
|
|
863
|
+
#endif
|
|
864
|
+
|
|
865
|
+
if (flags & GCF_MARK)
|
|
866
|
+
return;
|
|
867
|
+
|
|
868
|
+
*flagp |= GCF_MARK;
|
|
869
|
+
rt = cx->runtime;
|
|
870
|
+
METER(if (++rt->gcStats.depth > rt->gcStats.maxdepth)
|
|
871
|
+
rt->gcStats.maxdepth = rt->gcStats.depth);
|
|
872
|
+
|
|
873
|
+
#ifdef GC_MARK_DEBUG
|
|
874
|
+
if (js_DumpGCHeap)
|
|
875
|
+
gc_dump_thing(thing, flags, arg, js_DumpGCHeap);
|
|
876
|
+
#endif
|
|
877
|
+
|
|
878
|
+
switch (flags & GCF_TYPEMASK) {
|
|
879
|
+
case GCX_OBJECT:
|
|
880
|
+
obj = (JSObject *) thing;
|
|
881
|
+
vp = obj->slots;
|
|
882
|
+
if (!vp) {
|
|
883
|
+
/* If obj->slots is null, obj must be a newborn. */
|
|
884
|
+
JS_ASSERT(!obj->map);
|
|
885
|
+
goto out;
|
|
886
|
+
}
|
|
887
|
+
nslots = (obj->map->ops->mark)
|
|
888
|
+
? obj->map->ops->mark(cx, obj, arg)
|
|
889
|
+
: JS_MIN(obj->map->freeslot, obj->map->nslots);
|
|
890
|
+
#ifdef GC_MARK_DEBUG
|
|
891
|
+
scope = OBJ_IS_NATIVE(obj) ? OBJ_SCOPE(obj) : NULL;
|
|
892
|
+
#endif
|
|
893
|
+
for (end = vp + nslots; vp < end; vp++) {
|
|
894
|
+
v = *vp;
|
|
895
|
+
if (JSVAL_IS_GCTHING(v)) {
|
|
896
|
+
#ifdef GC_MARK_DEBUG
|
|
897
|
+
char name[32];
|
|
898
|
+
|
|
899
|
+
if (scope) {
|
|
900
|
+
uint32 slot;
|
|
901
|
+
jsval nval;
|
|
902
|
+
|
|
903
|
+
slot = vp - obj->slots;
|
|
904
|
+
for (sprop = SCOPE_LAST_PROP(scope); ;
|
|
905
|
+
sprop = sprop->parent) {
|
|
906
|
+
if (!sprop) {
|
|
907
|
+
switch (slot) {
|
|
908
|
+
case JSSLOT_PROTO:
|
|
909
|
+
strcpy(name, "__proto__");
|
|
910
|
+
break;
|
|
911
|
+
case JSSLOT_PARENT:
|
|
912
|
+
strcpy(name, "__parent__");
|
|
913
|
+
break;
|
|
914
|
+
case JSSLOT_PRIVATE:
|
|
915
|
+
strcpy(name, "__private__");
|
|
916
|
+
break;
|
|
917
|
+
default:
|
|
918
|
+
JS_snprintf(name, sizeof name,
|
|
919
|
+
"**UNKNOWN SLOT %ld**",
|
|
920
|
+
(long)slot);
|
|
921
|
+
break;
|
|
922
|
+
}
|
|
923
|
+
break;
|
|
924
|
+
}
|
|
925
|
+
if (sprop->slot == slot) {
|
|
926
|
+
nval = ID_TO_VALUE(sprop->id);
|
|
927
|
+
if (JSVAL_IS_INT(nval)) {
|
|
928
|
+
JS_snprintf(name, sizeof name, "%ld",
|
|
929
|
+
(long)JSVAL_TO_INT(nval));
|
|
930
|
+
} else if (JSVAL_IS_STRING(nval)) {
|
|
931
|
+
JS_snprintf(name, sizeof name, "%s",
|
|
932
|
+
JS_GetStringBytes(JSVAL_TO_STRING(nval)));
|
|
933
|
+
} else {
|
|
934
|
+
strcpy(name, "**FINALIZED ATOM KEY**");
|
|
935
|
+
}
|
|
936
|
+
break;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
} else {
|
|
940
|
+
strcpy(name, "**UNKNOWN OBJECT MAP ENTRY**");
|
|
941
|
+
}
|
|
942
|
+
#endif
|
|
943
|
+
GC_MARK(cx, JSVAL_TO_GCTHING(v), name, arg);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
break;
|
|
947
|
+
|
|
948
|
+
#ifdef DEBUG
|
|
949
|
+
case GCX_STRING:
|
|
950
|
+
str = (JSString *)thing;
|
|
951
|
+
JS_ASSERT(!JSSTRING_IS_DEPENDENT(str));
|
|
952
|
+
break;
|
|
953
|
+
#endif
|
|
954
|
+
|
|
955
|
+
case GCX_MUTABLE_STRING:
|
|
956
|
+
str = (JSString *)thing;
|
|
957
|
+
if (JSSTRING_IS_DEPENDENT(str))
|
|
958
|
+
GC_MARK(cx, JSSTRDEP_BASE(str), "base", arg);
|
|
959
|
+
break;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
out:
|
|
963
|
+
METER(rt->gcStats.depth--);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
JS_STATIC_DLL_CALLBACK(JSDHashOperator)
|
|
967
|
+
gc_root_marker(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num, void *arg)
|
|
968
|
+
{
|
|
969
|
+
JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
|
|
970
|
+
jsval *rp = (jsval *)rhe->root;
|
|
971
|
+
jsval v = *rp;
|
|
972
|
+
|
|
973
|
+
/* Ignore null object and scalar values. */
|
|
974
|
+
if (!JSVAL_IS_NULL(v) && JSVAL_IS_GCTHING(v)) {
|
|
975
|
+
JSContext *cx = (JSContext *)arg;
|
|
976
|
+
#ifdef DEBUG
|
|
977
|
+
JSArena *a;
|
|
978
|
+
jsuword firstpage;
|
|
979
|
+
JSBool root_points_to_gcArenaPool = JS_FALSE;
|
|
980
|
+
void *thing = JSVAL_TO_GCTHING(v);
|
|
981
|
+
|
|
982
|
+
for (a = cx->runtime->gcArenaPool.first.next; a; a = a->next) {
|
|
983
|
+
firstpage = FIRST_THING_PAGE(a);
|
|
984
|
+
if (JS_UPTRDIFF(thing, firstpage) < a->avail - firstpage) {
|
|
985
|
+
root_points_to_gcArenaPool = JS_TRUE;
|
|
986
|
+
break;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
if (!root_points_to_gcArenaPool && rhe->name) {
|
|
990
|
+
fprintf(stderr,
|
|
991
|
+
"JS API usage error: the address passed to JS_AddNamedRoot currently holds an\n"
|
|
992
|
+
"invalid jsval. This is usually caused by a missing call to JS_RemoveRoot.\n"
|
|
993
|
+
"The root's name is \"%s\".\n",
|
|
994
|
+
rhe->name);
|
|
995
|
+
}
|
|
996
|
+
JS_ASSERT(root_points_to_gcArenaPool);
|
|
997
|
+
#endif
|
|
998
|
+
|
|
999
|
+
GC_MARK(cx, JSVAL_TO_GCTHING(v), rhe->name ? rhe->name : "root", NULL);
|
|
1000
|
+
}
|
|
1001
|
+
return JS_DHASH_NEXT;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
JS_STATIC_DLL_CALLBACK(JSDHashOperator)
|
|
1005
|
+
gc_lock_marker(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num, void *arg)
|
|
1006
|
+
{
|
|
1007
|
+
JSGCLockHashEntry *lhe = (JSGCLockHashEntry *)hdr;
|
|
1008
|
+
void *thing = (void *)lhe->thing;
|
|
1009
|
+
JSContext *cx = (JSContext *)arg;
|
|
1010
|
+
|
|
1011
|
+
GC_MARK(cx, thing, "locked object", NULL);
|
|
1012
|
+
return JS_DHASH_NEXT;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
void
|
|
1016
|
+
js_ForceGC(JSContext *cx, uintN gcflags)
|
|
1017
|
+
{
|
|
1018
|
+
uintN i;
|
|
1019
|
+
|
|
1020
|
+
for (i = 0; i < GCX_NTYPES; i++)
|
|
1021
|
+
cx->newborn[i] = NULL;
|
|
1022
|
+
cx->lastAtom = NULL;
|
|
1023
|
+
cx->runtime->gcPoke = JS_TRUE;
|
|
1024
|
+
js_GC(cx, gcflags);
|
|
1025
|
+
JS_ArenaFinish();
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
#define GC_MARK_JSVALS(cx, len, vec, name) \
|
|
1029
|
+
JS_BEGIN_MACRO \
|
|
1030
|
+
jsval _v, *_vp, *_end; \
|
|
1031
|
+
\
|
|
1032
|
+
for (_vp = vec, _end = _vp + len; _vp < _end; _vp++) { \
|
|
1033
|
+
_v = *_vp; \
|
|
1034
|
+
if (JSVAL_IS_GCTHING(_v)) \
|
|
1035
|
+
GC_MARK(cx, JSVAL_TO_GCTHING(_v), name, NULL); \
|
|
1036
|
+
} \
|
|
1037
|
+
JS_END_MACRO
|
|
1038
|
+
|
|
1039
|
+
void
|
|
1040
|
+
js_GC(JSContext *cx, uintN gcflags)
|
|
1041
|
+
{
|
|
1042
|
+
JSRuntime *rt;
|
|
1043
|
+
JSContext *iter, *acx;
|
|
1044
|
+
JSStackFrame *fp, *chain;
|
|
1045
|
+
uintN i, depth, nslots, type;
|
|
1046
|
+
JSStackHeader *sh;
|
|
1047
|
+
JSArena *a, **ap;
|
|
1048
|
+
uint8 flags, *flagp, *split;
|
|
1049
|
+
JSGCThing *thing, *limit, **flp, **oflp;
|
|
1050
|
+
GCFinalizeOp finalizer;
|
|
1051
|
+
JSBool all_clear;
|
|
1052
|
+
#ifdef JS_THREADSAFE
|
|
1053
|
+
jsword currentThread;
|
|
1054
|
+
uint32 requestDebit;
|
|
1055
|
+
#endif
|
|
1056
|
+
|
|
1057
|
+
rt = cx->runtime;
|
|
1058
|
+
#ifdef JS_THREADSAFE
|
|
1059
|
+
/* Avoid deadlock. */
|
|
1060
|
+
JS_ASSERT(!JS_IS_RUNTIME_LOCKED(rt));
|
|
1061
|
+
#endif
|
|
1062
|
+
|
|
1063
|
+
/*
|
|
1064
|
+
* Don't collect garbage if the runtime isn't up, and cx is not the last
|
|
1065
|
+
* context in the runtime. The last context must force a GC, and nothing
|
|
1066
|
+
* should suppress that final collection or there may be shutdown leaks,
|
|
1067
|
+
* or runtime bloat until the next context is created.
|
|
1068
|
+
*/
|
|
1069
|
+
if (rt->state != JSRTS_UP && !(gcflags & GC_LAST_CONTEXT))
|
|
1070
|
+
return;
|
|
1071
|
+
|
|
1072
|
+
/*
|
|
1073
|
+
* Let the API user decide to defer a GC if it wants to (unless this
|
|
1074
|
+
* is the last context). Invoke the callback regardless.
|
|
1075
|
+
*/
|
|
1076
|
+
if (rt->gcCallback) {
|
|
1077
|
+
if (!rt->gcCallback(cx, JSGC_BEGIN) && !(gcflags & GC_LAST_CONTEXT))
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/* Lock out other GC allocator and collector invocations. */
|
|
1082
|
+
if (!(gcflags & GC_ALREADY_LOCKED))
|
|
1083
|
+
JS_LOCK_GC(rt);
|
|
1084
|
+
|
|
1085
|
+
/* Do nothing if no assignment has executed since the last GC. */
|
|
1086
|
+
if (!rt->gcPoke) {
|
|
1087
|
+
METER(rt->gcStats.nopoke++);
|
|
1088
|
+
if (!(gcflags & GC_ALREADY_LOCKED))
|
|
1089
|
+
JS_UNLOCK_GC(rt);
|
|
1090
|
+
return;
|
|
1091
|
+
}
|
|
1092
|
+
METER(rt->gcStats.poke++);
|
|
1093
|
+
|
|
1094
|
+
#ifdef JS_THREADSAFE
|
|
1095
|
+
/* Bump gcLevel and return rather than nest on this thread. */
|
|
1096
|
+
currentThread = js_CurrentThreadId();
|
|
1097
|
+
if (rt->gcThread == currentThread) {
|
|
1098
|
+
JS_ASSERT(rt->gcLevel > 0);
|
|
1099
|
+
rt->gcLevel++;
|
|
1100
|
+
METER(if (rt->gcLevel > rt->gcStats.maxlevel)
|
|
1101
|
+
rt->gcStats.maxlevel = rt->gcLevel);
|
|
1102
|
+
if (!(gcflags & GC_ALREADY_LOCKED))
|
|
1103
|
+
JS_UNLOCK_GC(rt);
|
|
1104
|
+
return;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
/*
|
|
1108
|
+
* If we're in one or more requests (possibly on more than one context)
|
|
1109
|
+
* running on the current thread, indicate, temporarily, that all these
|
|
1110
|
+
* requests are inactive. NB: if cx->thread is 0, then cx is not using
|
|
1111
|
+
* the request model, and does not contribute to rt->requestCount.
|
|
1112
|
+
*/
|
|
1113
|
+
requestDebit = 0;
|
|
1114
|
+
if (cx->thread) {
|
|
1115
|
+
/*
|
|
1116
|
+
* Check all contexts for any with the same thread-id. XXX should we
|
|
1117
|
+
* keep a sub-list of contexts having the same id?
|
|
1118
|
+
*/
|
|
1119
|
+
iter = NULL;
|
|
1120
|
+
while ((acx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) {
|
|
1121
|
+
if (acx->thread == cx->thread && acx->requestDepth)
|
|
1122
|
+
requestDebit++;
|
|
1123
|
+
}
|
|
1124
|
+
} else {
|
|
1125
|
+
/*
|
|
1126
|
+
* We assert, but check anyway, in case someone is misusing the API.
|
|
1127
|
+
* Avoiding the loop over all of rt's contexts is a win in the event
|
|
1128
|
+
* that the GC runs only on request-less contexts with 0 thread-ids,
|
|
1129
|
+
* in a special thread such as might be used by the UI/DOM/Layout
|
|
1130
|
+
* "mozilla" or "main" thread in Mozilla-the-browser.
|
|
1131
|
+
*/
|
|
1132
|
+
JS_ASSERT(cx->requestDepth == 0);
|
|
1133
|
+
if (cx->requestDepth)
|
|
1134
|
+
requestDebit = 1;
|
|
1135
|
+
}
|
|
1136
|
+
if (requestDebit) {
|
|
1137
|
+
JS_ASSERT(requestDebit <= rt->requestCount);
|
|
1138
|
+
rt->requestCount -= requestDebit;
|
|
1139
|
+
if (rt->requestCount == 0)
|
|
1140
|
+
JS_NOTIFY_REQUEST_DONE(rt);
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
/* If another thread is already in GC, don't attempt GC; wait instead. */
|
|
1144
|
+
if (rt->gcLevel > 0) {
|
|
1145
|
+
/* Bump gcLevel to restart the current GC, so it finds new garbage. */
|
|
1146
|
+
rt->gcLevel++;
|
|
1147
|
+
METER(if (rt->gcLevel > rt->gcStats.maxlevel)
|
|
1148
|
+
rt->gcStats.maxlevel = rt->gcLevel);
|
|
1149
|
+
|
|
1150
|
+
/* Wait for the other thread to finish, then resume our request. */
|
|
1151
|
+
while (rt->gcLevel > 0)
|
|
1152
|
+
JS_AWAIT_GC_DONE(rt);
|
|
1153
|
+
if (requestDebit)
|
|
1154
|
+
rt->requestCount += requestDebit;
|
|
1155
|
+
if (!(gcflags & GC_ALREADY_LOCKED))
|
|
1156
|
+
JS_UNLOCK_GC(rt);
|
|
1157
|
+
return;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
/* No other thread is in GC, so indicate that we're now in GC. */
|
|
1161
|
+
rt->gcLevel = 1;
|
|
1162
|
+
rt->gcThread = currentThread;
|
|
1163
|
+
|
|
1164
|
+
/* Wait for all other requests to finish. */
|
|
1165
|
+
while (rt->requestCount > 0)
|
|
1166
|
+
JS_AWAIT_REQUEST_DONE(rt);
|
|
1167
|
+
|
|
1168
|
+
#else /* !JS_THREADSAFE */
|
|
1169
|
+
|
|
1170
|
+
/* Bump gcLevel and return rather than nest; the outer gc will restart. */
|
|
1171
|
+
rt->gcLevel++;
|
|
1172
|
+
METER(if (rt->gcLevel > rt->gcStats.maxlevel)
|
|
1173
|
+
rt->gcStats.maxlevel = rt->gcLevel);
|
|
1174
|
+
if (rt->gcLevel > 1)
|
|
1175
|
+
return;
|
|
1176
|
+
|
|
1177
|
+
#endif /* !JS_THREADSAFE */
|
|
1178
|
+
|
|
1179
|
+
/*
|
|
1180
|
+
* Set rt->gcRunning here within the GC lock, and after waiting for any
|
|
1181
|
+
* active requests to end, so that new requests that try to JS_AddRoot,
|
|
1182
|
+
* JS_RemoveRoot, or JS_RemoveRootRT block in JS_BeginRequest waiting for
|
|
1183
|
+
* rt->gcLevel to drop to zero, while request-less calls to the *Root*
|
|
1184
|
+
* APIs block in js_AddRoot or js_RemoveRoot (see above in this file),
|
|
1185
|
+
* waiting for GC to finish.
|
|
1186
|
+
*/
|
|
1187
|
+
rt->gcRunning = JS_TRUE;
|
|
1188
|
+
JS_UNLOCK_GC(rt);
|
|
1189
|
+
|
|
1190
|
+
/* If a suspended compile is running on another context, keep atoms. */
|
|
1191
|
+
if (rt->gcKeepAtoms)
|
|
1192
|
+
gcflags |= GC_KEEP_ATOMS;
|
|
1193
|
+
|
|
1194
|
+
/* Reset malloc counter. */
|
|
1195
|
+
rt->gcMallocBytes = 0;
|
|
1196
|
+
|
|
1197
|
+
/* Drop atoms held by the property cache, and clear property weak links. */
|
|
1198
|
+
js_DisablePropertyCache(cx);
|
|
1199
|
+
js_FlushPropertyCache(cx);
|
|
1200
|
+
#ifdef DEBUG_brendan
|
|
1201
|
+
{ extern void js_DumpScopeMeters(JSRuntime *rt);
|
|
1202
|
+
js_DumpScopeMeters(rt);
|
|
1203
|
+
}
|
|
1204
|
+
#endif
|
|
1205
|
+
|
|
1206
|
+
restart:
|
|
1207
|
+
rt->gcNumber++;
|
|
1208
|
+
|
|
1209
|
+
/*
|
|
1210
|
+
* Mark phase.
|
|
1211
|
+
*/
|
|
1212
|
+
JS_DHashTableEnumerate(&rt->gcRootsHash, gc_root_marker, cx);
|
|
1213
|
+
if (rt->gcLocksHash)
|
|
1214
|
+
JS_DHashTableEnumerate(rt->gcLocksHash, gc_lock_marker, cx);
|
|
1215
|
+
js_MarkAtomState(&rt->atomState, gcflags, gc_mark_atom_key_thing, cx);
|
|
1216
|
+
js_MarkWatchPoints(rt);
|
|
1217
|
+
iter = NULL;
|
|
1218
|
+
while ((acx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL) {
|
|
1219
|
+
/*
|
|
1220
|
+
* Iterate frame chain and dormant chains. Temporarily tack current
|
|
1221
|
+
* frame onto the head of the dormant list to ease iteration.
|
|
1222
|
+
*
|
|
1223
|
+
* (NB: see comment on this whole "dormant" thing in js_Execute.)
|
|
1224
|
+
*/
|
|
1225
|
+
chain = acx->fp;
|
|
1226
|
+
if (chain) {
|
|
1227
|
+
JS_ASSERT(!chain->dormantNext);
|
|
1228
|
+
chain->dormantNext = acx->dormantFrameChain;
|
|
1229
|
+
} else {
|
|
1230
|
+
chain = acx->dormantFrameChain;
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
for (fp = chain; fp; fp = chain = chain->dormantNext) {
|
|
1234
|
+
do {
|
|
1235
|
+
if (fp->callobj)
|
|
1236
|
+
GC_MARK(cx, fp->callobj, "call object", NULL);
|
|
1237
|
+
if (fp->argsobj)
|
|
1238
|
+
GC_MARK(cx, fp->argsobj, "arguments object", NULL);
|
|
1239
|
+
if (fp->varobj)
|
|
1240
|
+
GC_MARK(cx, fp->varobj, "variables object", NULL);
|
|
1241
|
+
if (fp->script) {
|
|
1242
|
+
js_MarkScript(cx, fp->script, NULL);
|
|
1243
|
+
if (fp->spbase) {
|
|
1244
|
+
/*
|
|
1245
|
+
* Don't mark what has not been pushed yet, or what
|
|
1246
|
+
* has been popped already.
|
|
1247
|
+
*/
|
|
1248
|
+
depth = fp->script->depth;
|
|
1249
|
+
nslots = (JS_UPTRDIFF(fp->sp, fp->spbase)
|
|
1250
|
+
< depth * sizeof(jsval))
|
|
1251
|
+
? (uintN)(fp->sp - fp->spbase)
|
|
1252
|
+
: depth;
|
|
1253
|
+
GC_MARK_JSVALS(cx, nslots, fp->spbase, "operand");
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
GC_MARK(cx, fp->thisp, "this", NULL);
|
|
1257
|
+
if (fp->argv) {
|
|
1258
|
+
nslots = fp->argc;
|
|
1259
|
+
if (fp->fun && fp->fun->nargs > nslots)
|
|
1260
|
+
nslots = fp->fun->nargs;
|
|
1261
|
+
GC_MARK_JSVALS(cx, nslots, fp->argv, "arg");
|
|
1262
|
+
}
|
|
1263
|
+
if (JSVAL_IS_GCTHING(fp->rval))
|
|
1264
|
+
GC_MARK(cx, JSVAL_TO_GCTHING(fp->rval), "rval", NULL);
|
|
1265
|
+
if (fp->vars)
|
|
1266
|
+
GC_MARK_JSVALS(cx, fp->nvars, fp->vars, "var");
|
|
1267
|
+
GC_MARK(cx, fp->scopeChain, "scope chain", NULL);
|
|
1268
|
+
if (fp->sharpArray)
|
|
1269
|
+
GC_MARK(cx, fp->sharpArray, "sharp array", NULL);
|
|
1270
|
+
} while ((fp = fp->down) != NULL);
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
/* Cleanup temporary "dormant" linkage. */
|
|
1274
|
+
if (acx->fp)
|
|
1275
|
+
acx->fp->dormantNext = NULL;
|
|
1276
|
+
|
|
1277
|
+
/* Mark other roots-by-definition in acx. */
|
|
1278
|
+
GC_MARK(cx, acx->globalObject, "global object", NULL);
|
|
1279
|
+
GC_MARK(cx, acx->newborn[GCX_OBJECT], "newborn object", NULL);
|
|
1280
|
+
GC_MARK(cx, acx->newborn[GCX_STRING], "newborn string", NULL);
|
|
1281
|
+
GC_MARK(cx, acx->newborn[GCX_DOUBLE], "newborn double", NULL);
|
|
1282
|
+
GC_MARK(cx, acx->newborn[GCX_MUTABLE_STRING], "newborn mutable string",
|
|
1283
|
+
NULL);
|
|
1284
|
+
for (i = GCX_EXTERNAL_STRING; i < GCX_NTYPES; i++)
|
|
1285
|
+
GC_MARK(cx, acx->newborn[i], "newborn external string", NULL);
|
|
1286
|
+
if (acx->lastAtom)
|
|
1287
|
+
GC_MARK_ATOM(cx, acx->lastAtom, NULL);
|
|
1288
|
+
#if JS_HAS_EXCEPTIONS
|
|
1289
|
+
if (acx->throwing && JSVAL_IS_GCTHING(acx->exception))
|
|
1290
|
+
GC_MARK(cx, JSVAL_TO_GCTHING(acx->exception), "exception", NULL);
|
|
1291
|
+
#endif
|
|
1292
|
+
#if JS_HAS_LVALUE_RETURN
|
|
1293
|
+
if (acx->rval2set && JSVAL_IS_GCTHING(acx->rval2))
|
|
1294
|
+
GC_MARK(cx, JSVAL_TO_GCTHING(acx->rval2), "rval2", NULL);
|
|
1295
|
+
#endif
|
|
1296
|
+
|
|
1297
|
+
for (sh = acx->stackHeaders; sh; sh = sh->down) {
|
|
1298
|
+
METER(rt->gcStats.stackseg++);
|
|
1299
|
+
METER(rt->gcStats.segslots += sh->nslots);
|
|
1300
|
+
GC_MARK_JSVALS(cx, sh->nslots, JS_STACK_SEGMENT(sh), "stack");
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
if (acx->localRootStack)
|
|
1304
|
+
js_MarkLocalRoots(cx, acx->localRootStack);
|
|
1305
|
+
}
|
|
1306
|
+
#ifdef DUMP_CALL_TABLE
|
|
1307
|
+
js_DumpCallTable(cx);
|
|
1308
|
+
#endif
|
|
1309
|
+
|
|
1310
|
+
if (rt->gcCallback)
|
|
1311
|
+
(void) rt->gcCallback(cx, JSGC_MARK_END);
|
|
1312
|
+
|
|
1313
|
+
/*
|
|
1314
|
+
* Sweep phase.
|
|
1315
|
+
* Finalize as we sweep, outside of rt->gcLock, but with rt->gcRunning set
|
|
1316
|
+
* so that any attempt to allocate a GC-thing from a finalizer will fail,
|
|
1317
|
+
* rather than nest badly and leave the unmarked newborn to be swept.
|
|
1318
|
+
*/
|
|
1319
|
+
js_SweepAtomState(&rt->atomState);
|
|
1320
|
+
js_SweepScopeProperties(rt);
|
|
1321
|
+
js_SweepScriptFilenames(rt);
|
|
1322
|
+
for (a = rt->gcArenaPool.first.next; a; a = a->next) {
|
|
1323
|
+
flagp = (uint8 *) a->base;
|
|
1324
|
+
split = (uint8 *) FIRST_THING_PAGE(a);
|
|
1325
|
+
limit = (JSGCThing *) a->avail;
|
|
1326
|
+
for (thing = (JSGCThing *) split; thing < limit; thing++) {
|
|
1327
|
+
if (((jsuword)thing & GC_PAGE_MASK) == 0) {
|
|
1328
|
+
flagp++;
|
|
1329
|
+
thing++;
|
|
1330
|
+
}
|
|
1331
|
+
flags = *flagp;
|
|
1332
|
+
if (flags & GCF_MARK) {
|
|
1333
|
+
*flagp &= ~GCF_MARK;
|
|
1334
|
+
} else if (!(flags & (GCF_LOCKMASK | GCF_FINAL))) {
|
|
1335
|
+
/* Call the finalizer with GCF_FINAL ORed into flags. */
|
|
1336
|
+
type = flags & GCF_TYPEMASK;
|
|
1337
|
+
finalizer = gc_finalizers[type];
|
|
1338
|
+
if (finalizer) {
|
|
1339
|
+
*flagp = (uint8)(flags | GCF_FINAL);
|
|
1340
|
+
if (type >= GCX_EXTERNAL_STRING)
|
|
1341
|
+
js_PurgeDeflatedStringCache((JSString *)thing);
|
|
1342
|
+
finalizer(cx, thing);
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
/* Set flags to GCF_FINAL, signifying that thing is free. */
|
|
1346
|
+
*flagp = GCF_FINAL;
|
|
1347
|
+
|
|
1348
|
+
JS_ASSERT(rt->gcBytes >= sizeof(JSGCThing) + sizeof(uint8));
|
|
1349
|
+
rt->gcBytes -= sizeof(JSGCThing) + sizeof(uint8);
|
|
1350
|
+
}
|
|
1351
|
+
if (++flagp == split)
|
|
1352
|
+
flagp += GC_THINGS_SIZE;
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
/*
|
|
1357
|
+
* Free phase.
|
|
1358
|
+
* Free any unused arenas and rebuild the JSGCThing freelist.
|
|
1359
|
+
*/
|
|
1360
|
+
ap = &rt->gcArenaPool.first.next;
|
|
1361
|
+
a = *ap;
|
|
1362
|
+
if (!a)
|
|
1363
|
+
goto out;
|
|
1364
|
+
all_clear = JS_TRUE;
|
|
1365
|
+
flp = oflp = &rt->gcFreeList;
|
|
1366
|
+
*flp = NULL;
|
|
1367
|
+
METER(rt->gcStats.freelen = 0);
|
|
1368
|
+
|
|
1369
|
+
do {
|
|
1370
|
+
flagp = (uint8 *) a->base;
|
|
1371
|
+
split = (uint8 *) FIRST_THING_PAGE(a);
|
|
1372
|
+
limit = (JSGCThing *) a->avail;
|
|
1373
|
+
for (thing = (JSGCThing *) split; thing < limit; thing++) {
|
|
1374
|
+
if (((jsuword)thing & GC_PAGE_MASK) == 0) {
|
|
1375
|
+
flagp++;
|
|
1376
|
+
thing++;
|
|
1377
|
+
}
|
|
1378
|
+
if (*flagp != GCF_FINAL) {
|
|
1379
|
+
all_clear = JS_FALSE;
|
|
1380
|
+
} else {
|
|
1381
|
+
thing->flagp = flagp;
|
|
1382
|
+
*flp = thing;
|
|
1383
|
+
flp = &thing->next;
|
|
1384
|
+
METER(rt->gcStats.freelen++);
|
|
1385
|
+
}
|
|
1386
|
+
if (++flagp == split)
|
|
1387
|
+
flagp += GC_THINGS_SIZE;
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
if (all_clear) {
|
|
1391
|
+
JS_ARENA_DESTROY(&rt->gcArenaPool, a, ap);
|
|
1392
|
+
flp = oflp;
|
|
1393
|
+
METER(rt->gcStats.afree++);
|
|
1394
|
+
} else {
|
|
1395
|
+
ap = &a->next;
|
|
1396
|
+
all_clear = JS_TRUE;
|
|
1397
|
+
oflp = flp;
|
|
1398
|
+
}
|
|
1399
|
+
} while ((a = *ap) != NULL);
|
|
1400
|
+
|
|
1401
|
+
/* Terminate the new freelist. */
|
|
1402
|
+
*flp = NULL;
|
|
1403
|
+
|
|
1404
|
+
if (rt->gcCallback)
|
|
1405
|
+
(void) rt->gcCallback(cx, JSGC_FINALIZE_END);
|
|
1406
|
+
#ifdef DEBUG_brendan
|
|
1407
|
+
{ extern void DumpSrcNoteSizeHist();
|
|
1408
|
+
DumpSrcNoteSizeHist();
|
|
1409
|
+
}
|
|
1410
|
+
#endif
|
|
1411
|
+
|
|
1412
|
+
out:
|
|
1413
|
+
JS_LOCK_GC(rt);
|
|
1414
|
+
if (rt->gcLevel > 1) {
|
|
1415
|
+
rt->gcLevel = 1;
|
|
1416
|
+
JS_UNLOCK_GC(rt);
|
|
1417
|
+
goto restart;
|
|
1418
|
+
}
|
|
1419
|
+
js_EnablePropertyCache(cx);
|
|
1420
|
+
rt->gcLevel = 0;
|
|
1421
|
+
rt->gcLastBytes = rt->gcBytes;
|
|
1422
|
+
rt->gcPoke = rt->gcRunning = JS_FALSE;
|
|
1423
|
+
|
|
1424
|
+
#ifdef JS_THREADSAFE
|
|
1425
|
+
/* If we were invoked during a request, pay back the temporary debit. */
|
|
1426
|
+
if (requestDebit)
|
|
1427
|
+
rt->requestCount += requestDebit;
|
|
1428
|
+
rt->gcThread = 0;
|
|
1429
|
+
JS_NOTIFY_GC_DONE(rt);
|
|
1430
|
+
if (!(gcflags & GC_ALREADY_LOCKED))
|
|
1431
|
+
JS_UNLOCK_GC(rt);
|
|
1432
|
+
#endif
|
|
1433
|
+
|
|
1434
|
+
if (rt->gcCallback) {
|
|
1435
|
+
if (gcflags & GC_ALREADY_LOCKED)
|
|
1436
|
+
JS_UNLOCK_GC(rt);
|
|
1437
|
+
(void) rt->gcCallback(cx, JSGC_END);
|
|
1438
|
+
if (gcflags & GC_ALREADY_LOCKED)
|
|
1439
|
+
JS_LOCK_GC(rt);
|
|
1440
|
+
}
|
|
1441
|
+
}
|