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,1639 @@
|
|
|
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 symbol tables.
|
|
42
|
+
*/
|
|
43
|
+
#include "jsstddef.h"
|
|
44
|
+
#include <stdlib.h>
|
|
45
|
+
#include <string.h>
|
|
46
|
+
#include "jstypes.h"
|
|
47
|
+
#include "jsarena.h"
|
|
48
|
+
#include "jsbit.h"
|
|
49
|
+
#include "jsclist.h"
|
|
50
|
+
#include "jsdhash.h"
|
|
51
|
+
#include "jsutil.h" /* Added by JSIFY */
|
|
52
|
+
#include "jsapi.h"
|
|
53
|
+
#include "jsatom.h"
|
|
54
|
+
#include "jscntxt.h"
|
|
55
|
+
#include "jsdbgapi.h"
|
|
56
|
+
#include "jslock.h"
|
|
57
|
+
#include "jsnum.h"
|
|
58
|
+
#include "jsscope.h"
|
|
59
|
+
#include "jsstr.h"
|
|
60
|
+
|
|
61
|
+
JSScope *
|
|
62
|
+
js_GetMutableScope(JSContext *cx, JSObject *obj)
|
|
63
|
+
{
|
|
64
|
+
JSScope *scope, *newscope;
|
|
65
|
+
|
|
66
|
+
scope = OBJ_SCOPE(obj);
|
|
67
|
+
JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope));
|
|
68
|
+
if (scope->object == obj)
|
|
69
|
+
return scope;
|
|
70
|
+
newscope = js_NewScope(cx, 0, scope->map.ops, LOCKED_OBJ_GET_CLASS(obj),
|
|
71
|
+
obj);
|
|
72
|
+
if (!newscope)
|
|
73
|
+
return NULL;
|
|
74
|
+
JS_LOCK_SCOPE(cx, newscope);
|
|
75
|
+
obj->map = js_HoldObjectMap(cx, &newscope->map);
|
|
76
|
+
scope = (JSScope *) js_DropObjectMap(cx, &scope->map, obj);
|
|
77
|
+
JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope);
|
|
78
|
+
return newscope;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/*
|
|
82
|
+
* JSScope uses multiplicative hashing, _a la_ jsdhash.[ch], but specialized
|
|
83
|
+
* to minimize footprint. But if a scope has fewer than SCOPE_HASH_THRESHOLD
|
|
84
|
+
* entries, we use linear search and avoid allocating scope->table.
|
|
85
|
+
*/
|
|
86
|
+
#define SCOPE_HASH_THRESHOLD 6
|
|
87
|
+
#define MIN_SCOPE_SIZE_LOG2 4
|
|
88
|
+
#define MIN_SCOPE_SIZE JS_BIT(MIN_SCOPE_SIZE_LOG2)
|
|
89
|
+
#define SCOPE_TABLE_NBYTES(n) ((n) * sizeof(JSScopeProperty *))
|
|
90
|
+
|
|
91
|
+
static void
|
|
92
|
+
InitMinimalScope(JSScope *scope)
|
|
93
|
+
{
|
|
94
|
+
scope->hashShift = JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2;
|
|
95
|
+
scope->entryCount = scope->removedCount = 0;
|
|
96
|
+
scope->table = NULL;
|
|
97
|
+
scope->lastProp = NULL;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
static JSBool
|
|
101
|
+
CreateScopeTable(JSScope *scope)
|
|
102
|
+
{
|
|
103
|
+
int sizeLog2;
|
|
104
|
+
JSScopeProperty *sprop, **spp;
|
|
105
|
+
|
|
106
|
+
JS_ASSERT(!scope->table);
|
|
107
|
+
JS_ASSERT(scope->lastProp);
|
|
108
|
+
|
|
109
|
+
if (scope->entryCount > SCOPE_HASH_THRESHOLD) {
|
|
110
|
+
/*
|
|
111
|
+
* Ouch: calloc failed at least once already -- let's try again,
|
|
112
|
+
* overallocating to hold at least twice the current population.
|
|
113
|
+
*/
|
|
114
|
+
sizeLog2 = JS_CeilingLog2(2 * scope->entryCount);
|
|
115
|
+
scope->hashShift = JS_DHASH_BITS - sizeLog2;
|
|
116
|
+
} else {
|
|
117
|
+
JS_ASSERT(scope->hashShift == JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2);
|
|
118
|
+
sizeLog2 = MIN_SCOPE_SIZE_LOG2;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
scope->table = (JSScopeProperty **)
|
|
122
|
+
calloc(JS_BIT(sizeLog2), sizeof(JSScopeProperty *));
|
|
123
|
+
if (!scope->table)
|
|
124
|
+
return JS_FALSE;
|
|
125
|
+
|
|
126
|
+
scope->hashShift = JS_DHASH_BITS - sizeLog2;
|
|
127
|
+
for (sprop = scope->lastProp; sprop; sprop = sprop->parent) {
|
|
128
|
+
spp = js_SearchScope(scope, sprop->id, JS_TRUE);
|
|
129
|
+
SPROP_STORE_PRESERVING_COLLISION(spp, sprop);
|
|
130
|
+
}
|
|
131
|
+
return JS_TRUE;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
JSScope *
|
|
135
|
+
js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, JSClass *clasp,
|
|
136
|
+
JSObject *obj)
|
|
137
|
+
{
|
|
138
|
+
JSScope *scope;
|
|
139
|
+
|
|
140
|
+
scope = (JSScope *) JS_malloc(cx, sizeof(JSScope));
|
|
141
|
+
if (!scope)
|
|
142
|
+
return NULL;
|
|
143
|
+
|
|
144
|
+
js_InitObjectMap(&scope->map, nrefs, ops, clasp);
|
|
145
|
+
scope->object = obj;
|
|
146
|
+
scope->flags = 0;
|
|
147
|
+
InitMinimalScope(scope);
|
|
148
|
+
|
|
149
|
+
#ifdef JS_THREADSAFE
|
|
150
|
+
scope->ownercx = cx;
|
|
151
|
+
memset(&scope->lock, 0, sizeof scope->lock);
|
|
152
|
+
|
|
153
|
+
/*
|
|
154
|
+
* Set u.link = NULL, not u.count = 0, in case the target architecture's
|
|
155
|
+
* null pointer has a non-zero integer representation.
|
|
156
|
+
*/
|
|
157
|
+
scope->u.link = NULL;
|
|
158
|
+
|
|
159
|
+
#ifdef DEBUG
|
|
160
|
+
scope->file[0] = scope->file[1] = scope->file[2] = scope->file[3] = NULL;
|
|
161
|
+
scope->line[0] = scope->line[1] = scope->line[2] = scope->line[3] = 0;
|
|
162
|
+
#endif
|
|
163
|
+
#endif
|
|
164
|
+
|
|
165
|
+
JS_RUNTIME_METER(cx->runtime, liveScopes);
|
|
166
|
+
JS_RUNTIME_METER(cx->runtime, totalScopes);
|
|
167
|
+
return scope;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
#ifdef DEBUG_SCOPE_COUNT
|
|
171
|
+
extern void
|
|
172
|
+
js_unlog_scope(JSScope *scope);
|
|
173
|
+
#endif
|
|
174
|
+
|
|
175
|
+
void
|
|
176
|
+
js_DestroyScope(JSContext *cx, JSScope *scope)
|
|
177
|
+
{
|
|
178
|
+
#ifdef DEBUG_SCOPE_COUNT
|
|
179
|
+
js_unlog_scope(scope);
|
|
180
|
+
#endif
|
|
181
|
+
|
|
182
|
+
#ifdef JS_THREADSAFE
|
|
183
|
+
/* Scope must be single-threaded at this point, so set scope->ownercx. */
|
|
184
|
+
JS_ASSERT(scope->u.count == 0);
|
|
185
|
+
scope->ownercx = cx;
|
|
186
|
+
js_FinishLock(&scope->lock);
|
|
187
|
+
#endif
|
|
188
|
+
if (scope->table)
|
|
189
|
+
JS_free(cx, scope->table);
|
|
190
|
+
|
|
191
|
+
#ifdef DEBUG
|
|
192
|
+
JS_LOCK_RUNTIME_VOID(cx->runtime,
|
|
193
|
+
cx->runtime->liveScopeProps -= scope->entryCount);
|
|
194
|
+
#endif
|
|
195
|
+
JS_RUNTIME_UNMETER(cx->runtime, liveScopes);
|
|
196
|
+
JS_free(cx, scope);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
#ifdef DUMP_SCOPE_STATS
|
|
200
|
+
typedef struct JSScopeStats {
|
|
201
|
+
jsrefcount searches;
|
|
202
|
+
jsrefcount steps;
|
|
203
|
+
jsrefcount hits;
|
|
204
|
+
jsrefcount misses;
|
|
205
|
+
jsrefcount stepHits;
|
|
206
|
+
jsrefcount stepMisses;
|
|
207
|
+
jsrefcount adds;
|
|
208
|
+
jsrefcount redundantAdds;
|
|
209
|
+
jsrefcount addFailures;
|
|
210
|
+
jsrefcount changeFailures;
|
|
211
|
+
jsrefcount compresses;
|
|
212
|
+
jsrefcount grows;
|
|
213
|
+
jsrefcount removes;
|
|
214
|
+
jsrefcount removeFrees;
|
|
215
|
+
jsrefcount uselessRemoves;
|
|
216
|
+
jsrefcount shrinks;
|
|
217
|
+
} JSScopeStats;
|
|
218
|
+
|
|
219
|
+
JS_FRIEND_DATA(JSScopeStats) js_scope_stats;
|
|
220
|
+
|
|
221
|
+
# define METER(x) JS_ATOMIC_INCREMENT(&js_scope_stats.x)
|
|
222
|
+
#else
|
|
223
|
+
# define METER(x) /* nothing */
|
|
224
|
+
#endif
|
|
225
|
+
|
|
226
|
+
/*
|
|
227
|
+
* Double hashing needs the second hash code to be relatively prime to table
|
|
228
|
+
* size, so we simply make hash2 odd. The inputs to multiplicative hash are
|
|
229
|
+
* the golden ratio, expressed as a fixed-point 32 bit fraction, and the int
|
|
230
|
+
* property index or named property's atom number (observe that most objects
|
|
231
|
+
* have either no indexed properties, or almost all indexed and a few names,
|
|
232
|
+
* so collisions between index and atom number are unlikely).
|
|
233
|
+
*/
|
|
234
|
+
#define SCOPE_HASH0(id) (HASH_ID(id) * JS_GOLDEN_RATIO)
|
|
235
|
+
#define SCOPE_HASH1(hash0,shift) ((hash0) >> (shift))
|
|
236
|
+
#define SCOPE_HASH2(hash0,log2,shift) ((((hash0) << (log2)) >> (shift)) | 1)
|
|
237
|
+
|
|
238
|
+
JS_FRIEND_API(JSScopeProperty **)
|
|
239
|
+
js_SearchScope(JSScope *scope, jsid id, JSBool adding)
|
|
240
|
+
{
|
|
241
|
+
JSHashNumber hash0, hash1, hash2;
|
|
242
|
+
int hashShift, sizeLog2;
|
|
243
|
+
JSScopeProperty *stored, *sprop, **spp, **firstRemoved;
|
|
244
|
+
uint32 sizeMask;
|
|
245
|
+
|
|
246
|
+
METER(searches);
|
|
247
|
+
if (!scope->table) {
|
|
248
|
+
/* Not enough properties to justify hashing: search from lastProp. */
|
|
249
|
+
JS_ASSERT(!SCOPE_HAD_MIDDLE_DELETE(scope));
|
|
250
|
+
for (spp = &scope->lastProp; (sprop = *spp); spp = &sprop->parent) {
|
|
251
|
+
if (sprop->id == id) {
|
|
252
|
+
METER(hits);
|
|
253
|
+
return spp;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
METER(misses);
|
|
257
|
+
return spp;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/* Compute the primary hash address. */
|
|
261
|
+
hash0 = SCOPE_HASH0(id);
|
|
262
|
+
hashShift = scope->hashShift;
|
|
263
|
+
hash1 = SCOPE_HASH1(hash0, hashShift);
|
|
264
|
+
spp = scope->table + hash1;
|
|
265
|
+
|
|
266
|
+
/* Miss: return space for a new entry. */
|
|
267
|
+
stored = *spp;
|
|
268
|
+
if (SPROP_IS_FREE(stored)) {
|
|
269
|
+
METER(misses);
|
|
270
|
+
return spp;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/* Hit: return entry. */
|
|
274
|
+
sprop = SPROP_CLEAR_COLLISION(stored);
|
|
275
|
+
if (sprop && sprop->id == id) {
|
|
276
|
+
METER(hits);
|
|
277
|
+
return spp;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/* Collision: double hash. */
|
|
281
|
+
sizeLog2 = JS_DHASH_BITS - hashShift;
|
|
282
|
+
hash2 = SCOPE_HASH2(hash0, sizeLog2, hashShift);
|
|
283
|
+
sizeMask = JS_BITMASK(sizeLog2);
|
|
284
|
+
|
|
285
|
+
/* Save the first removed entry pointer so we can recycle it if adding. */
|
|
286
|
+
if (SPROP_IS_REMOVED(stored)) {
|
|
287
|
+
firstRemoved = spp;
|
|
288
|
+
} else {
|
|
289
|
+
firstRemoved = NULL;
|
|
290
|
+
if (adding && !SPROP_HAD_COLLISION(stored))
|
|
291
|
+
SPROP_FLAG_COLLISION(spp, sprop);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
for (;;) {
|
|
295
|
+
METER(steps);
|
|
296
|
+
hash1 -= hash2;
|
|
297
|
+
hash1 &= sizeMask;
|
|
298
|
+
spp = scope->table + hash1;
|
|
299
|
+
|
|
300
|
+
stored = *spp;
|
|
301
|
+
if (SPROP_IS_FREE(stored)) {
|
|
302
|
+
METER(stepMisses);
|
|
303
|
+
return (adding && firstRemoved) ? firstRemoved : spp;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
sprop = SPROP_CLEAR_COLLISION(stored);
|
|
307
|
+
if (sprop && sprop->id == id) {
|
|
308
|
+
METER(stepHits);
|
|
309
|
+
return spp;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (SPROP_IS_REMOVED(stored)) {
|
|
313
|
+
if (!firstRemoved)
|
|
314
|
+
firstRemoved = spp;
|
|
315
|
+
} else {
|
|
316
|
+
if (adding && !SPROP_HAD_COLLISION(stored))
|
|
317
|
+
SPROP_FLAG_COLLISION(spp, sprop);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/* NOTREACHED */
|
|
322
|
+
return NULL;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
static JSBool
|
|
326
|
+
ChangeScope(JSContext *cx, JSScope *scope, int change)
|
|
327
|
+
{
|
|
328
|
+
int oldlog2, newlog2;
|
|
329
|
+
uint32 oldsize, newsize, nbytes;
|
|
330
|
+
JSScopeProperty **table, **oldtable, **spp, **oldspp, *sprop;
|
|
331
|
+
|
|
332
|
+
/* Grow, shrink, or compress by changing scope->table. */
|
|
333
|
+
oldlog2 = JS_DHASH_BITS - scope->hashShift;
|
|
334
|
+
newlog2 = oldlog2 + change;
|
|
335
|
+
oldsize = JS_BIT(oldlog2);
|
|
336
|
+
newsize = JS_BIT(newlog2);
|
|
337
|
+
nbytes = SCOPE_TABLE_NBYTES(newsize);
|
|
338
|
+
table = (JSScopeProperty **) calloc(nbytes, 1);
|
|
339
|
+
if (!table) {
|
|
340
|
+
JS_ReportOutOfMemory(cx);
|
|
341
|
+
return JS_FALSE;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/* Now that we have a new table allocated, update scope members. */
|
|
345
|
+
scope->hashShift = JS_DHASH_BITS - newlog2;
|
|
346
|
+
scope->removedCount = 0;
|
|
347
|
+
oldtable = scope->table;
|
|
348
|
+
scope->table = table;
|
|
349
|
+
|
|
350
|
+
/* Copy only live entries, leaving removed and free ones behind. */
|
|
351
|
+
for (oldspp = oldtable; oldsize != 0; oldspp++) {
|
|
352
|
+
sprop = SPROP_FETCH(oldspp);
|
|
353
|
+
if (sprop) {
|
|
354
|
+
spp = js_SearchScope(scope, sprop->id, JS_TRUE);
|
|
355
|
+
JS_ASSERT(SPROP_IS_FREE(*spp));
|
|
356
|
+
*spp = sprop;
|
|
357
|
+
}
|
|
358
|
+
oldsize--;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/* Finally, free the old table storage. */
|
|
362
|
+
JS_free(cx, oldtable);
|
|
363
|
+
return JS_TRUE;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/*
|
|
367
|
+
* Take care to exclude the mark and duplicate bits, in case we're called from
|
|
368
|
+
* the GC, or we are searching for a property that has not yet been flagged as
|
|
369
|
+
* a duplicate when making a duplicate formal parameter.
|
|
370
|
+
*/
|
|
371
|
+
#define SPROP_FLAGS_NOT_MATCHED (SPROP_MARK | SPROP_IS_DUPLICATE)
|
|
372
|
+
|
|
373
|
+
JS_STATIC_DLL_CALLBACK(JSDHashNumber)
|
|
374
|
+
js_HashScopeProperty(JSDHashTable *table, const void *key)
|
|
375
|
+
{
|
|
376
|
+
const JSScopeProperty *sprop = (const JSScopeProperty *)key;
|
|
377
|
+
JSDHashNumber hash;
|
|
378
|
+
JSPropertyOp gsop;
|
|
379
|
+
|
|
380
|
+
/* Accumulate from least to most random so the low bits are most random. */
|
|
381
|
+
hash = 0;
|
|
382
|
+
gsop = sprop->getter;
|
|
383
|
+
if (gsop)
|
|
384
|
+
hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ (jsword)gsop;
|
|
385
|
+
gsop = sprop->setter;
|
|
386
|
+
if (gsop)
|
|
387
|
+
hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ (jsword)gsop;
|
|
388
|
+
|
|
389
|
+
hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4)
|
|
390
|
+
^ (sprop->flags & ~SPROP_FLAGS_NOT_MATCHED);
|
|
391
|
+
|
|
392
|
+
hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ sprop->attrs;
|
|
393
|
+
hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ sprop->shortid;
|
|
394
|
+
hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ sprop->slot;
|
|
395
|
+
hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ sprop->id;
|
|
396
|
+
return hash;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
#define SPROP_MATCH(sprop, child) \
|
|
400
|
+
SPROP_MATCH_PARAMS(sprop, (child)->id, (child)->getter, (child)->setter, \
|
|
401
|
+
(child)->slot, (child)->attrs, (child)->flags, \
|
|
402
|
+
(child)->shortid)
|
|
403
|
+
|
|
404
|
+
#define SPROP_MATCH_PARAMS(sprop, aid, agetter, asetter, aslot, aattrs, \
|
|
405
|
+
aflags, ashortid) \
|
|
406
|
+
((sprop)->id == (aid) && \
|
|
407
|
+
SPROP_MATCH_PARAMS_AFTER_ID(sprop, agetter, asetter, aslot, aattrs, \
|
|
408
|
+
aflags, ashortid))
|
|
409
|
+
|
|
410
|
+
#define SPROP_MATCH_PARAMS_AFTER_ID(sprop, agetter, asetter, aslot, aattrs, \
|
|
411
|
+
aflags, ashortid) \
|
|
412
|
+
((sprop)->getter == (agetter) && \
|
|
413
|
+
(sprop)->setter == (asetter) && \
|
|
414
|
+
(sprop)->slot == (aslot) && \
|
|
415
|
+
(sprop)->attrs == (aattrs) && \
|
|
416
|
+
(((sprop)->flags ^ (aflags)) & ~SPROP_FLAGS_NOT_MATCHED) == 0 && \
|
|
417
|
+
(sprop)->shortid == (ashortid))
|
|
418
|
+
|
|
419
|
+
JS_STATIC_DLL_CALLBACK(JSBool)
|
|
420
|
+
js_MatchScopeProperty(JSDHashTable *table,
|
|
421
|
+
const JSDHashEntryHdr *hdr,
|
|
422
|
+
const void *key)
|
|
423
|
+
{
|
|
424
|
+
const JSPropertyTreeEntry *entry = (const JSPropertyTreeEntry *)hdr;
|
|
425
|
+
const JSScopeProperty *sprop = entry->child;
|
|
426
|
+
const JSScopeProperty *kprop = (const JSScopeProperty *)key;
|
|
427
|
+
|
|
428
|
+
return SPROP_MATCH(sprop, kprop);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
static const JSDHashTableOps PropertyTreeHashOps = {
|
|
432
|
+
JS_DHashAllocTable,
|
|
433
|
+
JS_DHashFreeTable,
|
|
434
|
+
JS_DHashGetKeyStub,
|
|
435
|
+
js_HashScopeProperty,
|
|
436
|
+
js_MatchScopeProperty,
|
|
437
|
+
JS_DHashMoveEntryStub,
|
|
438
|
+
JS_DHashClearEntryStub,
|
|
439
|
+
JS_DHashFinalizeStub,
|
|
440
|
+
NULL
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
/*
|
|
444
|
+
* A property tree node on rt->propertyFreeList overlays the following prefix
|
|
445
|
+
* struct on JSScopeProperty.
|
|
446
|
+
*/
|
|
447
|
+
typedef struct FreeNode {
|
|
448
|
+
jsid id;
|
|
449
|
+
JSScopeProperty *next;
|
|
450
|
+
JSScopeProperty **prevp;
|
|
451
|
+
} FreeNode;
|
|
452
|
+
|
|
453
|
+
#define FREENODE(sprop) ((FreeNode *) (sprop))
|
|
454
|
+
|
|
455
|
+
#define FREENODE_INSERT(list, sprop) \
|
|
456
|
+
JS_BEGIN_MACRO \
|
|
457
|
+
FREENODE(sprop)->next = (list); \
|
|
458
|
+
FREENODE(sprop)->prevp = &(list); \
|
|
459
|
+
if (list) \
|
|
460
|
+
FREENODE(list)->prevp = &FREENODE(sprop)->next; \
|
|
461
|
+
(list) = (sprop); \
|
|
462
|
+
JS_END_MACRO
|
|
463
|
+
|
|
464
|
+
#define FREENODE_REMOVE(sprop) \
|
|
465
|
+
JS_BEGIN_MACRO \
|
|
466
|
+
*FREENODE(sprop)->prevp = FREENODE(sprop)->next; \
|
|
467
|
+
if (FREENODE(sprop)->next) \
|
|
468
|
+
FREENODE(FREENODE(sprop)->next)->prevp = FREENODE(sprop)->prevp; \
|
|
469
|
+
JS_END_MACRO
|
|
470
|
+
|
|
471
|
+
/* NB: Called with the runtime lock held. */
|
|
472
|
+
static JSScopeProperty *
|
|
473
|
+
NewScopeProperty(JSRuntime *rt)
|
|
474
|
+
{
|
|
475
|
+
JSScopeProperty *sprop;
|
|
476
|
+
|
|
477
|
+
sprop = rt->propertyFreeList;
|
|
478
|
+
if (sprop) {
|
|
479
|
+
FREENODE_REMOVE(sprop);
|
|
480
|
+
} else {
|
|
481
|
+
JS_ARENA_ALLOCATE_CAST(sprop, JSScopeProperty *,
|
|
482
|
+
&rt->propertyArenaPool,
|
|
483
|
+
sizeof(JSScopeProperty));
|
|
484
|
+
if (!sprop)
|
|
485
|
+
return NULL;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
JS_RUNTIME_METER(rt, livePropTreeNodes);
|
|
489
|
+
JS_RUNTIME_METER(rt, totalPropTreeNodes);
|
|
490
|
+
return sprop;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
#define CHUNKY_KIDS_TAG ((jsuword)1)
|
|
494
|
+
#define KIDS_IS_CHUNKY(kids) ((jsuword)(kids) & CHUNKY_KIDS_TAG)
|
|
495
|
+
#define KIDS_TO_CHUNK(kids) ((PropTreeKidsChunk *) \
|
|
496
|
+
((jsuword)(kids) & ~CHUNKY_KIDS_TAG))
|
|
497
|
+
#define CHUNK_TO_KIDS(chunk) ((JSScopeProperty *) \
|
|
498
|
+
((jsuword)(chunk) | CHUNKY_KIDS_TAG))
|
|
499
|
+
#define MAX_KIDS_PER_CHUNK 10
|
|
500
|
+
|
|
501
|
+
typedef struct PropTreeKidsChunk PropTreeKidsChunk;
|
|
502
|
+
|
|
503
|
+
struct PropTreeKidsChunk {
|
|
504
|
+
JSScopeProperty *kids[MAX_KIDS_PER_CHUNK];
|
|
505
|
+
PropTreeKidsChunk *next;
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
static PropTreeKidsChunk *
|
|
509
|
+
NewPropTreeKidsChunk(JSRuntime *rt)
|
|
510
|
+
{
|
|
511
|
+
PropTreeKidsChunk *chunk;
|
|
512
|
+
|
|
513
|
+
chunk = calloc(1, sizeof *chunk);
|
|
514
|
+
if (!chunk)
|
|
515
|
+
return NULL;
|
|
516
|
+
JS_ASSERT(((jsuword)chunk & CHUNKY_KIDS_TAG) == 0);
|
|
517
|
+
JS_RUNTIME_METER(rt, propTreeKidsChunks);
|
|
518
|
+
return chunk;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
static void
|
|
522
|
+
DestroyPropTreeKidsChunk(JSRuntime *rt, PropTreeKidsChunk *chunk)
|
|
523
|
+
{
|
|
524
|
+
JS_RUNTIME_UNMETER(rt, propTreeKidsChunks);
|
|
525
|
+
free(chunk);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/* NB: Called with the runtime lock held. */
|
|
529
|
+
static JSBool
|
|
530
|
+
InsertPropertyTreeChild(JSRuntime *rt, JSScopeProperty *parent,
|
|
531
|
+
JSScopeProperty *child)
|
|
532
|
+
{
|
|
533
|
+
JSPropertyTreeEntry *entry;
|
|
534
|
+
JSScopeProperty **childp, *kids, *sprop;
|
|
535
|
+
PropTreeKidsChunk *chunk, **chunkp;
|
|
536
|
+
uintN i;
|
|
537
|
+
|
|
538
|
+
JS_ASSERT(!parent || child->parent != parent);
|
|
539
|
+
|
|
540
|
+
if (!parent) {
|
|
541
|
+
entry = (JSPropertyTreeEntry *)
|
|
542
|
+
JS_DHashTableOperate(&rt->propertyTreeHash, child, JS_DHASH_ADD);
|
|
543
|
+
if (!entry)
|
|
544
|
+
return JS_FALSE;
|
|
545
|
+
childp = &entry->child;
|
|
546
|
+
sprop = *childp;
|
|
547
|
+
if (!sprop) {
|
|
548
|
+
*childp = child;
|
|
549
|
+
} else {
|
|
550
|
+
/*
|
|
551
|
+
* A "Duplicate child" case.
|
|
552
|
+
*
|
|
553
|
+
* We can't do away with child, as at least one live scope entry
|
|
554
|
+
* still points at it. What's more, that scope's lastProp chains
|
|
555
|
+
* through an ancestor line to reach child, and js_Enumerate and
|
|
556
|
+
* others count on this linkage. We must leave child out of the
|
|
557
|
+
* hash table, and not require it to be there when we eventually
|
|
558
|
+
* GC it (see RemovePropertyTreeChild, below).
|
|
559
|
+
*
|
|
560
|
+
* It is necessary to leave the duplicate child out of the hash
|
|
561
|
+
* table to preserve entry uniqueness. It is safe to leave the
|
|
562
|
+
* child out of the hash table (unlike the duplicate child cases
|
|
563
|
+
* below), because the child's parent link will be null, which
|
|
564
|
+
* can't dangle.
|
|
565
|
+
*/
|
|
566
|
+
JS_ASSERT(sprop != child && SPROP_MATCH(sprop, child));
|
|
567
|
+
JS_RUNTIME_METER(rt, duplicatePropTreeNodes);
|
|
568
|
+
}
|
|
569
|
+
} else {
|
|
570
|
+
childp = &parent->kids;
|
|
571
|
+
kids = *childp;
|
|
572
|
+
if (kids) {
|
|
573
|
+
if (KIDS_IS_CHUNKY(kids)) {
|
|
574
|
+
chunk = KIDS_TO_CHUNK(kids);
|
|
575
|
+
do {
|
|
576
|
+
for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
|
|
577
|
+
childp = &chunk->kids[i];
|
|
578
|
+
sprop = *childp;
|
|
579
|
+
if (!sprop)
|
|
580
|
+
goto insert;
|
|
581
|
+
|
|
582
|
+
JS_ASSERT(sprop != child);
|
|
583
|
+
if (SPROP_MATCH(sprop, child)) {
|
|
584
|
+
/*
|
|
585
|
+
* Duplicate child, see comment above. In this
|
|
586
|
+
* case, we must let the duplicate be inserted at
|
|
587
|
+
* this level in the tree, so we keep iterating,
|
|
588
|
+
* looking for an empty slot in which to insert.
|
|
589
|
+
*/
|
|
590
|
+
JS_ASSERT(sprop != child);
|
|
591
|
+
JS_RUNTIME_METER(rt, duplicatePropTreeNodes);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
chunkp = &chunk->next;
|
|
595
|
+
} while ((chunk = *chunkp) != NULL);
|
|
596
|
+
|
|
597
|
+
chunk = NewPropTreeKidsChunk(rt);
|
|
598
|
+
if (!chunk)
|
|
599
|
+
return JS_FALSE;
|
|
600
|
+
*chunkp = chunk;
|
|
601
|
+
childp = &chunk->kids[0];
|
|
602
|
+
} else {
|
|
603
|
+
sprop = kids;
|
|
604
|
+
JS_ASSERT(sprop != child);
|
|
605
|
+
if (SPROP_MATCH(sprop, child)) {
|
|
606
|
+
/*
|
|
607
|
+
* Duplicate child, see comment above. Once again, we
|
|
608
|
+
* must let duplicates created by deletion pile up in a
|
|
609
|
+
* kids-chunk-list, in order to find them when sweeping
|
|
610
|
+
* and thereby avoid dangling parent pointers.
|
|
611
|
+
*/
|
|
612
|
+
JS_RUNTIME_METER(rt, duplicatePropTreeNodes);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
chunk = NewPropTreeKidsChunk(rt);
|
|
616
|
+
if (!chunk)
|
|
617
|
+
return JS_FALSE;
|
|
618
|
+
parent->kids = CHUNK_TO_KIDS(chunk);
|
|
619
|
+
chunk->kids[0] = sprop;
|
|
620
|
+
childp = &chunk->kids[1];
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
insert:
|
|
624
|
+
*childp = child;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
child->parent = parent;
|
|
628
|
+
return JS_TRUE;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/* NB: Called with the runtime lock held. */
|
|
632
|
+
static void
|
|
633
|
+
RemovePropertyTreeChild(JSRuntime *rt, JSScopeProperty *child)
|
|
634
|
+
{
|
|
635
|
+
JSPropertyTreeEntry *entry;
|
|
636
|
+
JSScopeProperty *parent, *kids, *kid;
|
|
637
|
+
PropTreeKidsChunk *list, *chunk, **chunkp, *lastChunk;
|
|
638
|
+
uintN i, j;
|
|
639
|
+
|
|
640
|
+
parent = child->parent;
|
|
641
|
+
if (!parent) {
|
|
642
|
+
/*
|
|
643
|
+
* Don't remove child if it is not in rt->propertyTreeHash, but only
|
|
644
|
+
* matches a root child in the table that has compatible members. See
|
|
645
|
+
* the "Duplicate child" comments in InsertPropertyTreeChild, above.
|
|
646
|
+
*/
|
|
647
|
+
entry = (JSPropertyTreeEntry *)
|
|
648
|
+
JS_DHashTableOperate(&rt->propertyTreeHash, child, JS_DHASH_LOOKUP);
|
|
649
|
+
|
|
650
|
+
if (entry->child == child)
|
|
651
|
+
JS_DHashTableRawRemove(&rt->propertyTreeHash, &entry->hdr);
|
|
652
|
+
} else {
|
|
653
|
+
kids = parent->kids;
|
|
654
|
+
if (KIDS_IS_CHUNKY(kids)) {
|
|
655
|
+
list = chunk = KIDS_TO_CHUNK(kids);
|
|
656
|
+
chunkp = &list;
|
|
657
|
+
|
|
658
|
+
do {
|
|
659
|
+
for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
|
|
660
|
+
if (chunk->kids[i] == child) {
|
|
661
|
+
lastChunk = chunk;
|
|
662
|
+
if (!lastChunk->next) {
|
|
663
|
+
j = i + 1;
|
|
664
|
+
} else {
|
|
665
|
+
j = 0;
|
|
666
|
+
do {
|
|
667
|
+
chunkp = &lastChunk->next;
|
|
668
|
+
lastChunk = *chunkp;
|
|
669
|
+
} while (lastChunk->next);
|
|
670
|
+
}
|
|
671
|
+
for (; j < MAX_KIDS_PER_CHUNK; j++) {
|
|
672
|
+
if (!lastChunk->kids[j])
|
|
673
|
+
break;
|
|
674
|
+
}
|
|
675
|
+
--j;
|
|
676
|
+
if (chunk != lastChunk || j > i)
|
|
677
|
+
chunk->kids[i] = lastChunk->kids[j];
|
|
678
|
+
lastChunk->kids[j] = NULL;
|
|
679
|
+
if (j == 0) {
|
|
680
|
+
*chunkp = NULL;
|
|
681
|
+
if (!list)
|
|
682
|
+
parent->kids = NULL;
|
|
683
|
+
DestroyPropTreeKidsChunk(rt, lastChunk);
|
|
684
|
+
}
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
chunkp = &chunk->next;
|
|
690
|
+
} while ((chunk = *chunkp) != NULL);
|
|
691
|
+
} else {
|
|
692
|
+
kid = kids;
|
|
693
|
+
if (kid == child)
|
|
694
|
+
parent->kids = NULL;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
/*
|
|
700
|
+
* Called *without* the runtime lock held, this function acquires that lock
|
|
701
|
+
* only when inserting a new child. Thus there may be races to find or add
|
|
702
|
+
* a node that result in duplicates. We expect such races to be rare!
|
|
703
|
+
*/
|
|
704
|
+
static JSScopeProperty *
|
|
705
|
+
GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent,
|
|
706
|
+
JSScopeProperty *child)
|
|
707
|
+
{
|
|
708
|
+
JSRuntime *rt;
|
|
709
|
+
JSPropertyTreeEntry *entry;
|
|
710
|
+
JSScopeProperty *sprop;
|
|
711
|
+
PropTreeKidsChunk *chunk;
|
|
712
|
+
uintN i;
|
|
713
|
+
|
|
714
|
+
rt = cx->runtime;
|
|
715
|
+
if (!parent) {
|
|
716
|
+
JS_LOCK_RUNTIME(rt);
|
|
717
|
+
|
|
718
|
+
entry = (JSPropertyTreeEntry *)
|
|
719
|
+
JS_DHashTableOperate(&rt->propertyTreeHash, child, JS_DHASH_ADD);
|
|
720
|
+
if (!entry)
|
|
721
|
+
goto out_of_memory;
|
|
722
|
+
|
|
723
|
+
sprop = entry->child;
|
|
724
|
+
if (sprop)
|
|
725
|
+
goto out;
|
|
726
|
+
} else {
|
|
727
|
+
/*
|
|
728
|
+
* Because chunks are appended at the end and never deleted except by
|
|
729
|
+
* the GC, we can search without taking the runtime lock. We may miss
|
|
730
|
+
* a matching sprop added by another thread, and make a duplicate one,
|
|
731
|
+
* but that is an unlikely, therefore small, cost. The property tree
|
|
732
|
+
* has extremely low fan-out below its root in popular embeddings with
|
|
733
|
+
* real-world workloads.
|
|
734
|
+
*
|
|
735
|
+
* If workload changes so as to increase fan-out significantly below
|
|
736
|
+
* the property tree root, we'll want to add another tag bit stored in
|
|
737
|
+
* parent->kids that indicates a JSDHashTable pointer.
|
|
738
|
+
*/
|
|
739
|
+
entry = NULL;
|
|
740
|
+
sprop = parent->kids;
|
|
741
|
+
if (sprop) {
|
|
742
|
+
if (KIDS_IS_CHUNKY(sprop)) {
|
|
743
|
+
chunk = KIDS_TO_CHUNK(sprop);
|
|
744
|
+
do {
|
|
745
|
+
for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
|
|
746
|
+
sprop = chunk->kids[i];
|
|
747
|
+
if (!sprop)
|
|
748
|
+
goto not_found;
|
|
749
|
+
|
|
750
|
+
if (SPROP_MATCH(sprop, child))
|
|
751
|
+
return sprop;
|
|
752
|
+
}
|
|
753
|
+
} while ((chunk = chunk->next) != NULL);
|
|
754
|
+
} else {
|
|
755
|
+
if (SPROP_MATCH(sprop, child))
|
|
756
|
+
return sprop;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
not_found:
|
|
761
|
+
JS_LOCK_RUNTIME(rt);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
sprop = NewScopeProperty(rt);
|
|
765
|
+
if (!sprop)
|
|
766
|
+
goto out_of_memory;
|
|
767
|
+
|
|
768
|
+
sprop->id = child->id;
|
|
769
|
+
sprop->getter = child->getter;
|
|
770
|
+
sprop->setter = child->setter;
|
|
771
|
+
sprop->slot = child->slot;
|
|
772
|
+
sprop->attrs = child->attrs;
|
|
773
|
+
sprop->flags = child->flags;
|
|
774
|
+
sprop->shortid = child->shortid;
|
|
775
|
+
sprop->parent = sprop->kids = NULL;
|
|
776
|
+
if (!parent) {
|
|
777
|
+
entry->child = sprop;
|
|
778
|
+
} else {
|
|
779
|
+
if (!InsertPropertyTreeChild(rt, parent, sprop))
|
|
780
|
+
goto out_of_memory;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
out:
|
|
784
|
+
JS_UNLOCK_RUNTIME(rt);
|
|
785
|
+
return sprop;
|
|
786
|
+
|
|
787
|
+
out_of_memory:
|
|
788
|
+
JS_UNLOCK_RUNTIME(rt);
|
|
789
|
+
JS_ReportOutOfMemory(cx);
|
|
790
|
+
return NULL;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
#ifdef DEBUG_notbrendan
|
|
794
|
+
#define CHECK_ANCESTOR_LINE(scope, sparse) \
|
|
795
|
+
JS_BEGIN_MACRO \
|
|
796
|
+
if ((scope)->table) CheckAncestorLine(scope, sparse); \
|
|
797
|
+
JS_END_MACRO
|
|
798
|
+
|
|
799
|
+
static void
|
|
800
|
+
CheckAncestorLine(JSScope *scope, JSBool sparse)
|
|
801
|
+
{
|
|
802
|
+
uint32 size;
|
|
803
|
+
JSScopeProperty **spp, **start, **end, *ancestorLine, *sprop, *aprop;
|
|
804
|
+
uint32 entryCount, ancestorCount;
|
|
805
|
+
|
|
806
|
+
ancestorLine = SCOPE_LAST_PROP(scope);
|
|
807
|
+
if (ancestorLine)
|
|
808
|
+
JS_ASSERT(SCOPE_HAS_PROPERTY(scope, ancestorLine));
|
|
809
|
+
|
|
810
|
+
entryCount = 0;
|
|
811
|
+
size = SCOPE_CAPACITY(scope);
|
|
812
|
+
start = scope->table;
|
|
813
|
+
for (spp = start, end = start + size; spp < end; spp++) {
|
|
814
|
+
sprop = SPROP_FETCH(spp);
|
|
815
|
+
if (sprop) {
|
|
816
|
+
entryCount++;
|
|
817
|
+
for (aprop = ancestorLine; aprop; aprop = aprop->parent) {
|
|
818
|
+
if (aprop == sprop)
|
|
819
|
+
break;
|
|
820
|
+
}
|
|
821
|
+
JS_ASSERT(aprop);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
JS_ASSERT(entryCount == scope->entryCount);
|
|
825
|
+
|
|
826
|
+
ancestorCount = 0;
|
|
827
|
+
for (sprop = ancestorLine; sprop; sprop = sprop->parent) {
|
|
828
|
+
if (SCOPE_HAD_MIDDLE_DELETE(scope) &&
|
|
829
|
+
!SCOPE_HAS_PROPERTY(scope, sprop)) {
|
|
830
|
+
JS_ASSERT(sparse || (sprop->flags & SPROP_IS_DUPLICATE));
|
|
831
|
+
continue;
|
|
832
|
+
}
|
|
833
|
+
ancestorCount++;
|
|
834
|
+
}
|
|
835
|
+
JS_ASSERT(ancestorCount == scope->entryCount);
|
|
836
|
+
}
|
|
837
|
+
#else
|
|
838
|
+
#define CHECK_ANCESTOR_LINE(scope, sparse) /* nothing */
|
|
839
|
+
#endif
|
|
840
|
+
|
|
841
|
+
static void
|
|
842
|
+
ReportReadOnlyScope(JSContext *cx, JSScope *scope)
|
|
843
|
+
{
|
|
844
|
+
JSString *str;
|
|
845
|
+
|
|
846
|
+
str = js_ValueToString(cx, OBJECT_TO_JSVAL(scope->object));
|
|
847
|
+
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_READ_ONLY,
|
|
848
|
+
str
|
|
849
|
+
? JS_GetStringBytes(str)
|
|
850
|
+
: LOCKED_OBJ_GET_CLASS(scope->object)->name);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
JSScopeProperty *
|
|
854
|
+
js_AddScopeProperty(JSContext *cx, JSScope *scope, jsid id,
|
|
855
|
+
JSPropertyOp getter, JSPropertyOp setter, uint32 slot,
|
|
856
|
+
uintN attrs, uintN flags, intN shortid)
|
|
857
|
+
{
|
|
858
|
+
JSScopeProperty **spp, *sprop, *overwriting, **spvec, **spp2, child;
|
|
859
|
+
uint32 size, splen, i;
|
|
860
|
+
int change;
|
|
861
|
+
|
|
862
|
+
JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope));
|
|
863
|
+
CHECK_ANCESTOR_LINE(scope, JS_TRUE);
|
|
864
|
+
|
|
865
|
+
/*
|
|
866
|
+
* You can't add properties to a sealed scope. But note well that you can
|
|
867
|
+
* change property attributes in a sealed scope, even though that replaces
|
|
868
|
+
* a JSScopeProperty * in the scope's hash table -- but no id is added, so
|
|
869
|
+
* the scope remains sealed.
|
|
870
|
+
*/
|
|
871
|
+
if (SCOPE_IS_SEALED(scope)) {
|
|
872
|
+
ReportReadOnlyScope(cx, scope);
|
|
873
|
+
return NULL;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
/*
|
|
877
|
+
* Normalize stub getter and setter values for faster is-stub testing in
|
|
878
|
+
* the SPROP_CALL_[GS]ETTER macros.
|
|
879
|
+
*/
|
|
880
|
+
if (getter == JS_PropertyStub)
|
|
881
|
+
getter = NULL;
|
|
882
|
+
if (setter == JS_PropertyStub)
|
|
883
|
+
setter = NULL;
|
|
884
|
+
|
|
885
|
+
/*
|
|
886
|
+
* Search for id in order to claim its entry, allocating a property tree
|
|
887
|
+
* node if one doesn't already exist for our parameters.
|
|
888
|
+
*/
|
|
889
|
+
spp = js_SearchScope(scope, id, JS_TRUE);
|
|
890
|
+
sprop = overwriting = SPROP_FETCH(spp);
|
|
891
|
+
if (!sprop) {
|
|
892
|
+
/* Check whether we need to grow, if the load factor is >= .75. */
|
|
893
|
+
size = SCOPE_CAPACITY(scope);
|
|
894
|
+
if (scope->entryCount + scope->removedCount >= size - (size >> 2)) {
|
|
895
|
+
if (scope->removedCount >= size >> 2) {
|
|
896
|
+
METER(compresses);
|
|
897
|
+
change = 0;
|
|
898
|
+
} else {
|
|
899
|
+
METER(grows);
|
|
900
|
+
change = 1;
|
|
901
|
+
}
|
|
902
|
+
if (!ChangeScope(cx, scope, change) &&
|
|
903
|
+
scope->entryCount + scope->removedCount == size - 1) {
|
|
904
|
+
METER(addFailures);
|
|
905
|
+
return NULL;
|
|
906
|
+
}
|
|
907
|
+
spp = js_SearchScope(scope, id, JS_TRUE);
|
|
908
|
+
JS_ASSERT(!SPROP_FETCH(spp));
|
|
909
|
+
}
|
|
910
|
+
} else {
|
|
911
|
+
/* Property exists: js_SearchScope must have returned a valid entry. */
|
|
912
|
+
JS_ASSERT(!SPROP_IS_REMOVED(*spp));
|
|
913
|
+
|
|
914
|
+
/*
|
|
915
|
+
* If all property members match, this is a redundant add and we can
|
|
916
|
+
* return early. If the caller wants to allocate a slot, but doesn't
|
|
917
|
+
* care which slot, copy sprop->slot into slot so we can match sprop,
|
|
918
|
+
* if all other members match.
|
|
919
|
+
*/
|
|
920
|
+
if (!(attrs & JSPROP_SHARED) &&
|
|
921
|
+
slot == SPROP_INVALID_SLOT &&
|
|
922
|
+
SPROP_HAS_VALID_SLOT(sprop, scope)) {
|
|
923
|
+
slot = sprop->slot;
|
|
924
|
+
}
|
|
925
|
+
if (SPROP_MATCH_PARAMS_AFTER_ID(sprop, getter, setter, slot, attrs,
|
|
926
|
+
flags, shortid)) {
|
|
927
|
+
METER(redundantAdds);
|
|
928
|
+
return sprop;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/*
|
|
932
|
+
* Duplicate formal parameters require us to leave the old property
|
|
933
|
+
* on the ancestor line, so the decompiler can find it, even though
|
|
934
|
+
* its entry in scope->table is overwritten to point at a new property
|
|
935
|
+
* descending from the old one. The SPROP_IS_DUPLICATE flag helps us
|
|
936
|
+
* cope with the consequent disparity between ancestor line height and
|
|
937
|
+
* scope->entryCount.
|
|
938
|
+
*/
|
|
939
|
+
if (flags & SPROP_IS_DUPLICATE) {
|
|
940
|
+
sprop->flags |= SPROP_IS_DUPLICATE;
|
|
941
|
+
} else {
|
|
942
|
+
/*
|
|
943
|
+
* If we are clearing sprop to force an existing property to be
|
|
944
|
+
* overwritten (apart from a duplicate formal parameter), we must
|
|
945
|
+
* unlink it from the ancestor line at scope->lastProp, lazily if
|
|
946
|
+
* sprop is not lastProp. And we must remove the entry at *spp,
|
|
947
|
+
* precisely so the lazy "middle delete" fixup code further below
|
|
948
|
+
* won't find sprop in scope->table, in spite of sprop being on
|
|
949
|
+
* the ancestor line.
|
|
950
|
+
*
|
|
951
|
+
* When we finally succeed in finding or creating a new sprop
|
|
952
|
+
* and storing its pointer at *spp, we'll use the |overwriting|
|
|
953
|
+
* local saved when we first looked up id to decide whether we're
|
|
954
|
+
* indeed creating a new entry, or merely overwriting an existing
|
|
955
|
+
* property.
|
|
956
|
+
*/
|
|
957
|
+
if (sprop == SCOPE_LAST_PROP(scope)) {
|
|
958
|
+
do {
|
|
959
|
+
SCOPE_REMOVE_LAST_PROP(scope);
|
|
960
|
+
if (!SCOPE_HAD_MIDDLE_DELETE(scope))
|
|
961
|
+
break;
|
|
962
|
+
sprop = SCOPE_LAST_PROP(scope);
|
|
963
|
+
} while (sprop && !SCOPE_HAS_PROPERTY(scope, sprop));
|
|
964
|
+
} else if (!SCOPE_HAD_MIDDLE_DELETE(scope)) {
|
|
965
|
+
/*
|
|
966
|
+
* If we have no hash table yet, we need one now. The middle
|
|
967
|
+
* delete code is simple-minded that way!
|
|
968
|
+
*/
|
|
969
|
+
if (!scope->table) {
|
|
970
|
+
if (!CreateScopeTable(scope)) {
|
|
971
|
+
JS_ReportOutOfMemory(cx);
|
|
972
|
+
return NULL;
|
|
973
|
+
}
|
|
974
|
+
spp = js_SearchScope(scope, id, JS_TRUE);
|
|
975
|
+
sprop = overwriting = SPROP_FETCH(spp);
|
|
976
|
+
}
|
|
977
|
+
SCOPE_SET_MIDDLE_DELETE(scope);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
/*
|
|
982
|
+
* If we fail later on trying to find or create a new sprop, we will
|
|
983
|
+
* goto fail_overwrite and restore *spp from |overwriting|. Note that
|
|
984
|
+
* we don't bother to keep scope->removedCount in sync, because we'll
|
|
985
|
+
* fix up *spp and scope->entryCount shortly, no matter how control
|
|
986
|
+
* flow returns from this function.
|
|
987
|
+
*/
|
|
988
|
+
if (scope->table)
|
|
989
|
+
SPROP_STORE_PRESERVING_COLLISION(spp, NULL);
|
|
990
|
+
scope->entryCount--;
|
|
991
|
+
CHECK_ANCESTOR_LINE(scope, JS_TRUE);
|
|
992
|
+
sprop = NULL;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
if (!sprop) {
|
|
996
|
+
/*
|
|
997
|
+
* If properties were deleted from the middle of the list starting at
|
|
998
|
+
* scope->lastProp, we may need to fork the property tree and squeeze
|
|
999
|
+
* all deleted properties out of scope's ancestor line. Otherwise we
|
|
1000
|
+
* risk adding a node with the same id as a "middle" node, violating
|
|
1001
|
+
* the rule that properties along an ancestor line have distinct ids
|
|
1002
|
+
* (unless flagged SPROP_IS_DUPLICATE).
|
|
1003
|
+
*/
|
|
1004
|
+
if (SCOPE_HAD_MIDDLE_DELETE(scope)) {
|
|
1005
|
+
JS_ASSERT(scope->table);
|
|
1006
|
+
CHECK_ANCESTOR_LINE(scope, JS_TRUE);
|
|
1007
|
+
|
|
1008
|
+
splen = scope->entryCount;
|
|
1009
|
+
if (splen == 0) {
|
|
1010
|
+
JS_ASSERT(scope->lastProp == NULL);
|
|
1011
|
+
} else {
|
|
1012
|
+
/*
|
|
1013
|
+
* Enumerate live entries in scope->table using a temporary
|
|
1014
|
+
* vector, by walking the (possibly sparse, due to deletions)
|
|
1015
|
+
* ancestor line from scope->lastProp.
|
|
1016
|
+
*/
|
|
1017
|
+
spvec = (JSScopeProperty **)
|
|
1018
|
+
JS_malloc(cx, SCOPE_TABLE_NBYTES(splen));
|
|
1019
|
+
if (!spvec)
|
|
1020
|
+
goto fail_overwrite;
|
|
1021
|
+
i = splen;
|
|
1022
|
+
sprop = SCOPE_LAST_PROP(scope);
|
|
1023
|
+
JS_ASSERT(sprop);
|
|
1024
|
+
do {
|
|
1025
|
+
/*
|
|
1026
|
+
* NB: test SCOPE_GET_PROPERTY, not SCOPE_HAS_PROPERTY --
|
|
1027
|
+
* the latter insists that sprop->id maps to sprop, while
|
|
1028
|
+
* the former simply tests whether sprop->id is bound in
|
|
1029
|
+
* scope. We must allow for duplicate formal parameters
|
|
1030
|
+
* along the ancestor line, and fork them as needed.
|
|
1031
|
+
*/
|
|
1032
|
+
if (!SCOPE_GET_PROPERTY(scope, sprop->id))
|
|
1033
|
+
continue;
|
|
1034
|
+
|
|
1035
|
+
JS_ASSERT(sprop != overwriting);
|
|
1036
|
+
if (i == 0) {
|
|
1037
|
+
/*
|
|
1038
|
+
* If our original splen estimate, scope->entryCount,
|
|
1039
|
+
* is less than the ancestor line height, there must
|
|
1040
|
+
* be duplicate formal parameters in this (function
|
|
1041
|
+
* object) scope. Count remaining ancestors in order
|
|
1042
|
+
* to realloc spvec.
|
|
1043
|
+
*/
|
|
1044
|
+
JSScopeProperty *tmp = sprop;
|
|
1045
|
+
do {
|
|
1046
|
+
if (SCOPE_GET_PROPERTY(scope, tmp->id))
|
|
1047
|
+
i++;
|
|
1048
|
+
} while ((tmp = tmp->parent) != NULL);
|
|
1049
|
+
spp2 = (JSScopeProperty **)
|
|
1050
|
+
JS_realloc(cx, spvec, SCOPE_TABLE_NBYTES(splen+i));
|
|
1051
|
+
if (!spp2) {
|
|
1052
|
+
JS_free(cx, spvec);
|
|
1053
|
+
goto fail_overwrite;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
spvec = spp2;
|
|
1057
|
+
memmove(spvec + i, spvec, SCOPE_TABLE_NBYTES(splen));
|
|
1058
|
+
splen += i;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
spvec[--i] = sprop;
|
|
1062
|
+
} while ((sprop = sprop->parent) != NULL);
|
|
1063
|
+
JS_ASSERT(i == 0);
|
|
1064
|
+
|
|
1065
|
+
/*
|
|
1066
|
+
* Now loop forward through spvec, forking the property tree
|
|
1067
|
+
* whenever we see a "parent gap" due to deletions from scope.
|
|
1068
|
+
* NB: sprop is null on first entry to the loop body.
|
|
1069
|
+
*/
|
|
1070
|
+
do {
|
|
1071
|
+
if (spvec[i]->parent == sprop) {
|
|
1072
|
+
sprop = spvec[i];
|
|
1073
|
+
} else {
|
|
1074
|
+
sprop = GetPropertyTreeChild(cx, sprop, spvec[i]);
|
|
1075
|
+
if (!sprop) {
|
|
1076
|
+
JS_free(cx, spvec);
|
|
1077
|
+
goto fail_overwrite;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
spp2 = js_SearchScope(scope, sprop->id, JS_FALSE);
|
|
1081
|
+
JS_ASSERT(SPROP_FETCH(spp2) == spvec[i]);
|
|
1082
|
+
SPROP_STORE_PRESERVING_COLLISION(spp2, sprop);
|
|
1083
|
+
}
|
|
1084
|
+
} while (++i < splen);
|
|
1085
|
+
JS_free(cx, spvec);
|
|
1086
|
+
|
|
1087
|
+
/*
|
|
1088
|
+
* Now sprop points to the last property in scope, where the
|
|
1089
|
+
* ancestor line from sprop to the root is dense w.r.t. scope:
|
|
1090
|
+
* it contains no nodes not mapped by scope->table, apart from
|
|
1091
|
+
* any stinking ECMA-mandated duplicate formal parameters.
|
|
1092
|
+
*/
|
|
1093
|
+
scope->lastProp = sprop;
|
|
1094
|
+
CHECK_ANCESTOR_LINE(scope, JS_FALSE);
|
|
1095
|
+
JS_RUNTIME_METER(cx->runtime, middleDeleteFixups);
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
SCOPE_CLR_MIDDLE_DELETE(scope);
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
/*
|
|
1102
|
+
* Aliases share another property's slot, passed in the |slot| param.
|
|
1103
|
+
* Shared properties have no slot. Unshared properties that do not
|
|
1104
|
+
* alias another property's slot get one here, but may lose it due to
|
|
1105
|
+
* a JS_ClearScope call.
|
|
1106
|
+
*/
|
|
1107
|
+
if (!(flags & SPROP_IS_ALIAS)) {
|
|
1108
|
+
if (attrs & JSPROP_SHARED) {
|
|
1109
|
+
slot = SPROP_INVALID_SLOT;
|
|
1110
|
+
} else {
|
|
1111
|
+
/*
|
|
1112
|
+
* We may have set slot from a nearly-matching sprop, above.
|
|
1113
|
+
* If so, we're overwriting that nearly-matching sprop, so we
|
|
1114
|
+
* can reuse its slot -- we don't need to allocate a new one.
|
|
1115
|
+
* Callers should therefore pass SPROP_INVALID_SLOT for all
|
|
1116
|
+
* non-alias, unshared property adds.
|
|
1117
|
+
*/
|
|
1118
|
+
if (slot != SPROP_INVALID_SLOT)
|
|
1119
|
+
JS_ASSERT(overwriting);
|
|
1120
|
+
else if (!js_AllocSlot(cx, scope->object, &slot))
|
|
1121
|
+
goto fail_overwrite;
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
/*
|
|
1126
|
+
* Check for a watchpoint on a deleted property; if one exists, change
|
|
1127
|
+
* setter to js_watch_set.
|
|
1128
|
+
* XXXbe this could get expensive with lots of watchpoints...
|
|
1129
|
+
*/
|
|
1130
|
+
if (!JS_CLIST_IS_EMPTY(&cx->runtime->watchPointList) &&
|
|
1131
|
+
js_FindWatchPoint(cx->runtime, scope, id)) {
|
|
1132
|
+
setter = js_WrapWatchedSetter(cx, id, attrs, setter);
|
|
1133
|
+
if (!setter)
|
|
1134
|
+
goto fail_overwrite;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
/* Find or create a property tree node labeled by our arguments. */
|
|
1138
|
+
child.id = id;
|
|
1139
|
+
child.getter = getter;
|
|
1140
|
+
child.setter = setter;
|
|
1141
|
+
child.slot = slot;
|
|
1142
|
+
child.attrs = attrs;
|
|
1143
|
+
child.flags = flags;
|
|
1144
|
+
child.shortid = shortid;
|
|
1145
|
+
sprop = GetPropertyTreeChild(cx, scope->lastProp, &child);
|
|
1146
|
+
if (!sprop)
|
|
1147
|
+
goto fail_overwrite;
|
|
1148
|
+
|
|
1149
|
+
/* Store the tree node pointer in the table entry for id. */
|
|
1150
|
+
if (scope->table)
|
|
1151
|
+
SPROP_STORE_PRESERVING_COLLISION(spp, sprop);
|
|
1152
|
+
scope->entryCount++;
|
|
1153
|
+
scope->lastProp = sprop;
|
|
1154
|
+
CHECK_ANCESTOR_LINE(scope, JS_FALSE);
|
|
1155
|
+
if (!overwriting) {
|
|
1156
|
+
JS_RUNTIME_METER(cx->runtime, liveScopeProps);
|
|
1157
|
+
JS_RUNTIME_METER(cx->runtime, totalScopeProps);
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
/*
|
|
1161
|
+
* If we reach the hashing threshold, try to allocate scope->table.
|
|
1162
|
+
* If we can't (a rare event, preceded by swapping to death on most
|
|
1163
|
+
* modern OSes), stick with linear search rather than whining about
|
|
1164
|
+
* this little set-back. Therefore we must test !scope->table and
|
|
1165
|
+
* scope->entryCount >= SCOPE_HASH_THRESHOLD, not merely whether the
|
|
1166
|
+
* entry count just reached the threshold.
|
|
1167
|
+
*/
|
|
1168
|
+
if (!scope->table && scope->entryCount >= SCOPE_HASH_THRESHOLD)
|
|
1169
|
+
(void) CreateScopeTable(scope);
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
METER(adds);
|
|
1173
|
+
return sprop;
|
|
1174
|
+
|
|
1175
|
+
fail_overwrite:
|
|
1176
|
+
if (overwriting) {
|
|
1177
|
+
/*
|
|
1178
|
+
* We may or may not have forked overwriting out of scope's ancestor
|
|
1179
|
+
* line, so we must check (the alternative is to set a flag above, but
|
|
1180
|
+
* that hurts the common, non-error case). If we did fork overwriting
|
|
1181
|
+
* out, we'll add it back at scope->lastProp. This means enumeration
|
|
1182
|
+
* order can change due to a failure to overwrite an id.
|
|
1183
|
+
* XXXbe very minor incompatibility
|
|
1184
|
+
*/
|
|
1185
|
+
for (sprop = SCOPE_LAST_PROP(scope); ; sprop = sprop->parent) {
|
|
1186
|
+
if (!sprop) {
|
|
1187
|
+
sprop = SCOPE_LAST_PROP(scope);
|
|
1188
|
+
if (overwriting->parent == sprop) {
|
|
1189
|
+
scope->lastProp = overwriting;
|
|
1190
|
+
} else {
|
|
1191
|
+
sprop = GetPropertyTreeChild(cx, sprop, overwriting);
|
|
1192
|
+
if (sprop) {
|
|
1193
|
+
JS_ASSERT(sprop != overwriting);
|
|
1194
|
+
scope->lastProp = sprop;
|
|
1195
|
+
}
|
|
1196
|
+
overwriting = sprop;
|
|
1197
|
+
}
|
|
1198
|
+
break;
|
|
1199
|
+
}
|
|
1200
|
+
if (sprop == overwriting)
|
|
1201
|
+
break;
|
|
1202
|
+
}
|
|
1203
|
+
if (overwriting) {
|
|
1204
|
+
if (scope->table)
|
|
1205
|
+
SPROP_STORE_PRESERVING_COLLISION(spp, overwriting);
|
|
1206
|
+
scope->entryCount++;
|
|
1207
|
+
}
|
|
1208
|
+
CHECK_ANCESTOR_LINE(scope, JS_TRUE);
|
|
1209
|
+
}
|
|
1210
|
+
METER(addFailures);
|
|
1211
|
+
return NULL;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
JSScopeProperty *
|
|
1215
|
+
js_ChangeScopePropertyAttrs(JSContext *cx, JSScope *scope,
|
|
1216
|
+
JSScopeProperty *sprop, uintN attrs, uintN mask,
|
|
1217
|
+
JSPropertyOp getter, JSPropertyOp setter)
|
|
1218
|
+
{
|
|
1219
|
+
JSScopeProperty child, *newsprop, **spp;
|
|
1220
|
+
|
|
1221
|
+
CHECK_ANCESTOR_LINE(scope, JS_TRUE);
|
|
1222
|
+
|
|
1223
|
+
/* Allow only shared (slot-less) => unshared (slot-full) transition. */
|
|
1224
|
+
attrs |= sprop->attrs & mask;
|
|
1225
|
+
JS_ASSERT(!((attrs ^ sprop->attrs) & JSPROP_SHARED) ||
|
|
1226
|
+
!(attrs & JSPROP_SHARED));
|
|
1227
|
+
if (getter == JS_PropertyStub)
|
|
1228
|
+
getter = NULL;
|
|
1229
|
+
if (setter == JS_PropertyStub)
|
|
1230
|
+
setter = NULL;
|
|
1231
|
+
if (sprop->attrs == attrs &&
|
|
1232
|
+
sprop->getter == getter &&
|
|
1233
|
+
sprop->setter == setter) {
|
|
1234
|
+
return sprop;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
child.id = sprop->id;
|
|
1238
|
+
child.getter = getter;
|
|
1239
|
+
child.setter = setter;
|
|
1240
|
+
child.slot = sprop->slot;
|
|
1241
|
+
child.attrs = attrs;
|
|
1242
|
+
child.flags = sprop->flags;
|
|
1243
|
+
child.shortid = sprop->shortid;
|
|
1244
|
+
|
|
1245
|
+
if (SCOPE_LAST_PROP(scope) == sprop) {
|
|
1246
|
+
/*
|
|
1247
|
+
* Optimize the case where the last property added to scope is changed
|
|
1248
|
+
* to have a different attrs, getter, or setter. In the last property
|
|
1249
|
+
* case, we need not fork the property tree. But since we do not call
|
|
1250
|
+
* js_AddScopeProperty, we may need to allocate a new slot directly.
|
|
1251
|
+
*/
|
|
1252
|
+
if ((sprop->attrs & JSPROP_SHARED) && !(attrs & JSPROP_SHARED)) {
|
|
1253
|
+
JS_ASSERT(child.slot == SPROP_INVALID_SLOT);
|
|
1254
|
+
if (!js_AllocSlot(cx, scope->object, &child.slot))
|
|
1255
|
+
return NULL;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
newsprop = GetPropertyTreeChild(cx, sprop->parent, &child);
|
|
1259
|
+
if (newsprop) {
|
|
1260
|
+
spp = js_SearchScope(scope, sprop->id, JS_FALSE);
|
|
1261
|
+
JS_ASSERT(SPROP_FETCH(spp) == sprop);
|
|
1262
|
+
|
|
1263
|
+
if (scope->table)
|
|
1264
|
+
SPROP_STORE_PRESERVING_COLLISION(spp, newsprop);
|
|
1265
|
+
scope->lastProp = newsprop;
|
|
1266
|
+
CHECK_ANCESTOR_LINE(scope, JS_TRUE);
|
|
1267
|
+
}
|
|
1268
|
+
} else {
|
|
1269
|
+
/*
|
|
1270
|
+
* Let js_AddScopeProperty handle this |overwriting| case, including
|
|
1271
|
+
* the conservation of sprop->slot (if it's valid). We must not call
|
|
1272
|
+
* js_RemoveScopeProperty here, it will free a valid sprop->slot and
|
|
1273
|
+
* js_AddScopeProperty won't re-allocate it.
|
|
1274
|
+
*/
|
|
1275
|
+
newsprop = js_AddScopeProperty(cx, scope, child.id,
|
|
1276
|
+
child.getter, child.setter, child.slot,
|
|
1277
|
+
child.attrs, child.flags, child.shortid);
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
#ifdef DUMP_SCOPE_STATS
|
|
1281
|
+
if (!newsprop)
|
|
1282
|
+
METER(changeFailures);
|
|
1283
|
+
#endif
|
|
1284
|
+
return newsprop;
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
JSBool
|
|
1288
|
+
js_RemoveScopeProperty(JSContext *cx, JSScope *scope, jsid id)
|
|
1289
|
+
{
|
|
1290
|
+
JSScopeProperty **spp, *stored, *sprop;
|
|
1291
|
+
uint32 size;
|
|
1292
|
+
|
|
1293
|
+
JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope));
|
|
1294
|
+
CHECK_ANCESTOR_LINE(scope, JS_TRUE);
|
|
1295
|
+
if (SCOPE_IS_SEALED(scope)) {
|
|
1296
|
+
ReportReadOnlyScope(cx, scope);
|
|
1297
|
+
return JS_FALSE;
|
|
1298
|
+
}
|
|
1299
|
+
METER(removes);
|
|
1300
|
+
|
|
1301
|
+
spp = js_SearchScope(scope, id, JS_FALSE);
|
|
1302
|
+
stored = *spp;
|
|
1303
|
+
sprop = SPROP_CLEAR_COLLISION(stored);
|
|
1304
|
+
if (!sprop) {
|
|
1305
|
+
METER(uselessRemoves);
|
|
1306
|
+
return JS_TRUE;
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
/* Convert from a list to a hash so we can handle "middle deletes". */
|
|
1310
|
+
if (!scope->table && sprop != scope->lastProp) {
|
|
1311
|
+
if (!CreateScopeTable(scope)) {
|
|
1312
|
+
JS_ReportOutOfMemory(cx);
|
|
1313
|
+
return JS_FALSE;
|
|
1314
|
+
}
|
|
1315
|
+
spp = js_SearchScope(scope, id, JS_FALSE);
|
|
1316
|
+
stored = *spp;
|
|
1317
|
+
sprop = SPROP_CLEAR_COLLISION(stored);
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
/* First, if sprop is unshared and not cleared, free its slot number. */
|
|
1321
|
+
if (SPROP_HAS_VALID_SLOT(sprop, scope))
|
|
1322
|
+
js_FreeSlot(cx, scope->object, sprop->slot);
|
|
1323
|
+
|
|
1324
|
+
/* Next, remove id by setting its entry to a removed or free sentinel. */
|
|
1325
|
+
if (SPROP_HAD_COLLISION(stored)) {
|
|
1326
|
+
JS_ASSERT(scope->table);
|
|
1327
|
+
*spp = SPROP_REMOVED;
|
|
1328
|
+
scope->removedCount++;
|
|
1329
|
+
} else {
|
|
1330
|
+
METER(removeFrees);
|
|
1331
|
+
if (scope->table)
|
|
1332
|
+
*spp = NULL;
|
|
1333
|
+
}
|
|
1334
|
+
scope->entryCount--;
|
|
1335
|
+
JS_RUNTIME_UNMETER(cx->runtime, liveScopeProps);
|
|
1336
|
+
|
|
1337
|
+
/* Update scope->lastProp directly, or set its deferred update flag. */
|
|
1338
|
+
if (sprop == SCOPE_LAST_PROP(scope)) {
|
|
1339
|
+
do {
|
|
1340
|
+
SCOPE_REMOVE_LAST_PROP(scope);
|
|
1341
|
+
if (!SCOPE_HAD_MIDDLE_DELETE(scope))
|
|
1342
|
+
break;
|
|
1343
|
+
sprop = SCOPE_LAST_PROP(scope);
|
|
1344
|
+
} while (sprop && !SCOPE_HAS_PROPERTY(scope, sprop));
|
|
1345
|
+
} else if (!SCOPE_HAD_MIDDLE_DELETE(scope)) {
|
|
1346
|
+
SCOPE_SET_MIDDLE_DELETE(scope);
|
|
1347
|
+
}
|
|
1348
|
+
CHECK_ANCESTOR_LINE(scope, JS_TRUE);
|
|
1349
|
+
|
|
1350
|
+
/* Last, consider shrinking scope's table if its load factor is <= .25. */
|
|
1351
|
+
size = SCOPE_CAPACITY(scope);
|
|
1352
|
+
if (size > MIN_SCOPE_SIZE && scope->entryCount <= size >> 2) {
|
|
1353
|
+
METER(shrinks);
|
|
1354
|
+
(void) ChangeScope(cx, scope, -1);
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
return JS_TRUE;
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
void
|
|
1361
|
+
js_ClearScope(JSContext *cx, JSScope *scope)
|
|
1362
|
+
{
|
|
1363
|
+
CHECK_ANCESTOR_LINE(scope, JS_TRUE);
|
|
1364
|
+
#ifdef DEBUG
|
|
1365
|
+
JS_LOCK_RUNTIME_VOID(cx->runtime,
|
|
1366
|
+
cx->runtime->liveScopeProps -= scope->entryCount);
|
|
1367
|
+
#endif
|
|
1368
|
+
|
|
1369
|
+
if (scope->table)
|
|
1370
|
+
free(scope->table);
|
|
1371
|
+
SCOPE_CLR_MIDDLE_DELETE(scope);
|
|
1372
|
+
InitMinimalScope(scope);
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
#ifdef DUMP_SCOPE_STATS
|
|
1376
|
+
|
|
1377
|
+
#include <stdio.h>
|
|
1378
|
+
#include <math.h>
|
|
1379
|
+
|
|
1380
|
+
uint32 js_nkids_max;
|
|
1381
|
+
uint32 js_nkids_sum;
|
|
1382
|
+
double js_nkids_sqsum;
|
|
1383
|
+
uint32 js_nkids_hist[11];
|
|
1384
|
+
|
|
1385
|
+
static void
|
|
1386
|
+
MeterKidCount(uintN nkids)
|
|
1387
|
+
{
|
|
1388
|
+
if (nkids) {
|
|
1389
|
+
js_nkids_sum += nkids;
|
|
1390
|
+
js_nkids_sqsum += (double)nkids * nkids;
|
|
1391
|
+
if (nkids > js_nkids_max)
|
|
1392
|
+
js_nkids_max = nkids;
|
|
1393
|
+
}
|
|
1394
|
+
js_nkids_hist[JS_MIN(nkids, 10)]++;
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
static void
|
|
1398
|
+
MeterPropertyTree(JSScopeProperty *node)
|
|
1399
|
+
{
|
|
1400
|
+
uintN i, nkids;
|
|
1401
|
+
JSScopeProperty *kids, *kid;
|
|
1402
|
+
PropTreeKidsChunk *chunk;
|
|
1403
|
+
|
|
1404
|
+
nkids = 0;
|
|
1405
|
+
kids = node->kids;
|
|
1406
|
+
if (kids) {
|
|
1407
|
+
if (KIDS_IS_CHUNKY(kids)) {
|
|
1408
|
+
for (chunk = KIDS_TO_CHUNK(kids); chunk; chunk = chunk->next) {
|
|
1409
|
+
for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
|
|
1410
|
+
kid = chunk->kids[i];
|
|
1411
|
+
if (!kid)
|
|
1412
|
+
break;
|
|
1413
|
+
MeterPropertyTree(kid);
|
|
1414
|
+
nkids++;
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
} else {
|
|
1418
|
+
MeterPropertyTree(kids);
|
|
1419
|
+
nkids = 1;
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
MeterKidCount(nkids);
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
JS_STATIC_DLL_CALLBACK(JSDHashOperator)
|
|
1427
|
+
js_MeterPropertyTree(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
|
|
1428
|
+
void *arg)
|
|
1429
|
+
{
|
|
1430
|
+
JSPropertyTreeEntry *entry = (JSPropertyTreeEntry *)hdr;
|
|
1431
|
+
|
|
1432
|
+
MeterPropertyTree(entry->child);
|
|
1433
|
+
return JS_DHASH_NEXT;
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
#include "jsprf.h"
|
|
1437
|
+
|
|
1438
|
+
static void
|
|
1439
|
+
DumpSubtree(JSScopeProperty *sprop, int level, FILE *fp)
|
|
1440
|
+
{
|
|
1441
|
+
char buf[10];
|
|
1442
|
+
JSScopeProperty *kids, *kid;
|
|
1443
|
+
PropTreeKidsChunk *chunk;
|
|
1444
|
+
uintN i;
|
|
1445
|
+
|
|
1446
|
+
fprintf(fp, "%*sid %s g/s %p/%p slot %lu attrs %x flags %x shortid %d\n",
|
|
1447
|
+
level, "",
|
|
1448
|
+
JSVAL_IS_INT(sprop->id)
|
|
1449
|
+
? (JS_snprintf(buf, sizeof buf, "%ld", JSVAL_TO_INT(sprop->id)),
|
|
1450
|
+
buf)
|
|
1451
|
+
: JS_GetStringBytes(ATOM_TO_STRING((JSAtom *) sprop->id)),
|
|
1452
|
+
(void *) sprop->getter, (void *) sprop->setter,
|
|
1453
|
+
(unsigned long) sprop->slot, sprop->attrs, sprop->flags,
|
|
1454
|
+
sprop->shortid);
|
|
1455
|
+
kids = sprop->kids;
|
|
1456
|
+
if (kids) {
|
|
1457
|
+
++level;
|
|
1458
|
+
if (KIDS_IS_CHUNKY(kids)) {
|
|
1459
|
+
chunk = KIDS_TO_CHUNK(kids);
|
|
1460
|
+
do {
|
|
1461
|
+
for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
|
|
1462
|
+
kid = chunk->kids[i];
|
|
1463
|
+
if (!kid)
|
|
1464
|
+
break;
|
|
1465
|
+
JS_ASSERT(kid->parent == sprop);
|
|
1466
|
+
DumpSubtree(kid, level, fp);
|
|
1467
|
+
}
|
|
1468
|
+
} while ((chunk = chunk->next) != NULL);
|
|
1469
|
+
} else {
|
|
1470
|
+
kid = kids;
|
|
1471
|
+
DumpSubtree(kid, level, fp);
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
#endif /* DUMP_SCOPE_STATS */
|
|
1477
|
+
|
|
1478
|
+
void
|
|
1479
|
+
js_SweepScopeProperties(JSRuntime *rt)
|
|
1480
|
+
{
|
|
1481
|
+
JSArena **ap, *a;
|
|
1482
|
+
JSScopeProperty *limit, *sprop, *parent, *kids, *kid;
|
|
1483
|
+
uintN liveCount;
|
|
1484
|
+
PropTreeKidsChunk *chunk, *nextChunk;
|
|
1485
|
+
uintN i;
|
|
1486
|
+
|
|
1487
|
+
#ifdef DUMP_SCOPE_STATS
|
|
1488
|
+
uint32 livePropCapacity = 0, totalLiveCount = 0;
|
|
1489
|
+
static FILE *logfp;
|
|
1490
|
+
if (!logfp)
|
|
1491
|
+
logfp = fopen("/tmp/proptree.stats", "a");
|
|
1492
|
+
|
|
1493
|
+
MeterKidCount(rt->propertyTreeHash.entryCount);
|
|
1494
|
+
JS_DHashTableEnumerate(&rt->propertyTreeHash, js_MeterPropertyTree, NULL);
|
|
1495
|
+
|
|
1496
|
+
{
|
|
1497
|
+
double mean = 0.0, var = 0.0, sigma = 0.0;
|
|
1498
|
+
double nodesum = rt->livePropTreeNodes;
|
|
1499
|
+
double kidsum = js_nkids_sum;
|
|
1500
|
+
if (nodesum > 0 && kidsum >= 0) {
|
|
1501
|
+
mean = kidsum / nodesum;
|
|
1502
|
+
var = nodesum * js_nkids_sqsum - kidsum * kidsum;
|
|
1503
|
+
if (var < 0.0 || nodesum <= 1)
|
|
1504
|
+
var = 0.0;
|
|
1505
|
+
else
|
|
1506
|
+
var /= nodesum * (nodesum - 1);
|
|
1507
|
+
|
|
1508
|
+
/* Windows says sqrt(0.0) is "-1.#J" (?!) so we must test. */
|
|
1509
|
+
sigma = (var != 0.0) ? sqrt(var) : 0.0;
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
fprintf(logfp,
|
|
1513
|
+
"props %u nodes %g beta %g meankids %g sigma %g max %u",
|
|
1514
|
+
rt->liveScopeProps, nodesum, nodesum / rt->liveScopeProps,
|
|
1515
|
+
mean, sigma, js_nkids_max);
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
fprintf(logfp, " histogram %u %u %u %u %u %u %u %u %u %u %u",
|
|
1519
|
+
js_nkids_hist[0], js_nkids_hist[1],
|
|
1520
|
+
js_nkids_hist[2], js_nkids_hist[3],
|
|
1521
|
+
js_nkids_hist[4], js_nkids_hist[5],
|
|
1522
|
+
js_nkids_hist[6], js_nkids_hist[7],
|
|
1523
|
+
js_nkids_hist[8], js_nkids_hist[9],
|
|
1524
|
+
js_nkids_hist[10]);
|
|
1525
|
+
js_nkids_sum = js_nkids_max = 0;
|
|
1526
|
+
js_nkids_sqsum = 0;
|
|
1527
|
+
memset(js_nkids_hist, 0, sizeof js_nkids_hist);
|
|
1528
|
+
#endif
|
|
1529
|
+
|
|
1530
|
+
ap = &rt->propertyArenaPool.first.next;
|
|
1531
|
+
while ((a = *ap) != NULL) {
|
|
1532
|
+
limit = (JSScopeProperty *) a->avail;
|
|
1533
|
+
liveCount = 0;
|
|
1534
|
+
for (sprop = (JSScopeProperty *) a->base; sprop < limit; sprop++) {
|
|
1535
|
+
/* If the id is null, sprop is already on the freelist. */
|
|
1536
|
+
if (sprop->id == JSVAL_NULL)
|
|
1537
|
+
continue;
|
|
1538
|
+
|
|
1539
|
+
/* If the mark bit is set, sprop is alive, so we skip it. */
|
|
1540
|
+
if (sprop->flags & SPROP_MARK) {
|
|
1541
|
+
sprop->flags &= ~SPROP_MARK;
|
|
1542
|
+
liveCount++;
|
|
1543
|
+
continue;
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
/* Ok, sprop is garbage to collect: unlink it from its parent. */
|
|
1547
|
+
RemovePropertyTreeChild(rt, sprop);
|
|
1548
|
+
|
|
1549
|
+
/* Take care to reparent all sprop's kids to their grandparent. */
|
|
1550
|
+
kids = sprop->kids;
|
|
1551
|
+
if (kids) {
|
|
1552
|
+
sprop->kids = NULL;
|
|
1553
|
+
parent = sprop->parent;
|
|
1554
|
+
if (KIDS_IS_CHUNKY(kids)) {
|
|
1555
|
+
chunk = KIDS_TO_CHUNK(kids);
|
|
1556
|
+
do {
|
|
1557
|
+
for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
|
|
1558
|
+
kid = chunk->kids[i];
|
|
1559
|
+
if (!kid)
|
|
1560
|
+
break;
|
|
1561
|
+
JS_ASSERT(kid->parent == sprop);
|
|
1562
|
+
InsertPropertyTreeChild(rt, parent, kid);
|
|
1563
|
+
}
|
|
1564
|
+
nextChunk = chunk->next;
|
|
1565
|
+
DestroyPropTreeKidsChunk(rt, chunk);
|
|
1566
|
+
} while ((chunk = nextChunk) != NULL);
|
|
1567
|
+
} else {
|
|
1568
|
+
kid = kids;
|
|
1569
|
+
InsertPropertyTreeChild(rt, parent, kid);
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
/* Clear id so we know (above) that sprop is on the freelist. */
|
|
1574
|
+
sprop->id = JSVAL_NULL;
|
|
1575
|
+
FREENODE_INSERT(rt->propertyFreeList, sprop);
|
|
1576
|
+
JS_RUNTIME_UNMETER(rt, livePropTreeNodes);
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
/* If a contains no live properties, return it to the malloc heap. */
|
|
1580
|
+
if (liveCount == 0) {
|
|
1581
|
+
for (sprop = (JSScopeProperty *) a->base; sprop < limit; sprop++)
|
|
1582
|
+
FREENODE_REMOVE(sprop);
|
|
1583
|
+
JS_ARENA_DESTROY(&rt->propertyArenaPool, a, ap);
|
|
1584
|
+
} else {
|
|
1585
|
+
#ifdef DUMP_SCOPE_STATS
|
|
1586
|
+
livePropCapacity += limit - (JSScopeProperty *) a->base;
|
|
1587
|
+
totalLiveCount += liveCount;
|
|
1588
|
+
#endif
|
|
1589
|
+
ap = &a->next;
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
#ifdef DUMP_SCOPE_STATS
|
|
1594
|
+
fprintf(logfp, " arenautil %g%%\n",
|
|
1595
|
+
(totalLiveCount * 100.0) / livePropCapacity);
|
|
1596
|
+
fflush(logfp);
|
|
1597
|
+
#endif
|
|
1598
|
+
|
|
1599
|
+
#ifdef DUMP_PROPERTY_TREE
|
|
1600
|
+
{
|
|
1601
|
+
FILE *dumpfp = fopen("/tmp/proptree.dump", "w");
|
|
1602
|
+
if (dumpfp) {
|
|
1603
|
+
JSPropertyTreeEntry *pte, *end;
|
|
1604
|
+
|
|
1605
|
+
pte = (JSPropertyTreeEntry *) rt->propertyTreeHash.entryStore;
|
|
1606
|
+
end = pte + JS_DHASH_TABLE_SIZE(&rt->propertyTreeHash);
|
|
1607
|
+
while (pte < end) {
|
|
1608
|
+
if (pte->child)
|
|
1609
|
+
DumpSubtree(pte->child, 0, dumpfp);
|
|
1610
|
+
pte++;
|
|
1611
|
+
}
|
|
1612
|
+
fclose(dumpfp);
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
#endif
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
JSBool
|
|
1619
|
+
js_InitPropertyTree(JSRuntime *rt)
|
|
1620
|
+
{
|
|
1621
|
+
if (!JS_DHashTableInit(&rt->propertyTreeHash, &PropertyTreeHashOps, NULL,
|
|
1622
|
+
sizeof(JSPropertyTreeEntry), JS_DHASH_MIN_SIZE)) {
|
|
1623
|
+
rt->propertyTreeHash.ops = NULL;
|
|
1624
|
+
return JS_FALSE;
|
|
1625
|
+
}
|
|
1626
|
+
JS_InitArenaPool(&rt->propertyArenaPool, "properties",
|
|
1627
|
+
256 * sizeof(JSScopeProperty), sizeof(void *));
|
|
1628
|
+
return JS_TRUE;
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
void
|
|
1632
|
+
js_FinishPropertyTree(JSRuntime *rt)
|
|
1633
|
+
{
|
|
1634
|
+
if (rt->propertyTreeHash.ops) {
|
|
1635
|
+
JS_DHashTableFinish(&rt->propertyTreeHash);
|
|
1636
|
+
rt->propertyTreeHash.ops = NULL;
|
|
1637
|
+
}
|
|
1638
|
+
JS_FinishArenaPool(&rt->propertyArenaPool);
|
|
1639
|
+
}
|