CINXE.COM
Hacking Tips — Firefox Source Docs documentation
<!doctype html> <html class="writer-html5" lang="en" data-content_root="../"> <head> <base href="https://firefox-source-docs.mozilla.org/js/hacking_tips.html"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Hacking Tips — Firefox Source Docs documentation</title> <link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=fa44fd50"> <link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=19f00094"> <link rel="stylesheet" type="text/css" href="../_static/graphviz.css?v=fd3f3429"> <link rel="stylesheet" type="text/css" href="../_static/copybutton.css?v=76b2166b"> <link rel="stylesheet" type="text/css" href="../_static/custom_theme.css?v=a7d3e023"> <link rel="stylesheet" type="text/css" href="../_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css?v=0a3b3ea7"> <link rel="shortcut icon" href="../_static/firefox.ico"><!--[if lt IE 9]> <script src="../_static/js/html5shiv.min.js"></script> <![endif]--> <script src="../_static/jquery.js?v=5d32c60e"></script> <script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script> <script src="../_static/documentation_options.js?v=5929fcd5"></script> <script src="../_static/doctools.js?v=9a2dae69"></script> <script src="../_static/sphinx_highlight.js?v=dc90522c"></script> <script src="../_static/clipboard.min.js?v=a7894cd8"></script> <script src="../_static/copybutton.js?v=30646c52"></script> <script src="../_static/design-tabs.js?v=36754332"></script> <script src="../_static/js/theme.js"></script> <link rel="index" title="Index" href="../genindex.html"> <link rel="search" title="Search" href="../search.html"> <link rel="next" title="Debugger API" href="Debugger/index.html"> <link rel="prev" title="Running Automated JavaScript Tests" href="test.html"> <meta http-equiv="X-Translated-By" content="Google"> <meta http-equiv="X-Translated-To" content="tr"> <script type="text/javascript" src="https://www.gstatic.com/_/translate_http/_/js/k=translate_http.tr.en_GB.omlEigW4xY8.O/am=DgY/d=1/rs=AN8SPfpjsL9kUWY0h-sp7Ilu7hZWGwEmeg/m=corsproxy" data-sourceurl="https://firefox-source-docs.mozilla.org/js/hacking_tips.html"></script> <link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" rel="stylesheet"> <script type="text/javascript" src="https://www.gstatic.com/_/translate_http/_/js/k=translate_http.tr.en_GB.omlEigW4xY8.O/am=DgY/d=1/exm=corsproxy/ed=1/rs=AN8SPfpjsL9kUWY0h-sp7Ilu7hZWGwEmeg/m=phishing_protection" data-phishing-protection-enabled="false" data-forms-warning-enabled="true" data-source-url="https://firefox-source-docs.mozilla.org/js/hacking_tips.html"></script> <meta name="robots" content="none"> </head> <body class="wy-body-for-nav"> <script type="text/javascript" src="https://www.gstatic.com/_/translate_http/_/js/k=translate_http.tr.en_GB.omlEigW4xY8.O/am=DgY/d=1/exm=corsproxy,phishing_protection/ed=1/rs=AN8SPfpjsL9kUWY0h-sp7Ilu7hZWGwEmeg/m=navigationui" data-environment="prod" data-proxy-url="https://firefox--source--docs-mozilla-org.translate.goog" data-proxy-full-url="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB" data-source-url="https://firefox-source-docs.mozilla.org/js/hacking_tips.html" data-source-language="pl" data-target-language="tr" data-display-language="en-GB" data-detected-source-language="" data-is-source-untranslated="false" data-source-untranslated-url="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://firefox-source-docs.mozilla.org/js/hacking_tips.html&anno=2" data-client="tr"></script> <div class="wy-grid-for-nav"> <nav data-toggle="wy-nav-shift" class="wy-nav-side"> <div class="wy-side-scroll"> <div class="wy-side-nav-search"><a href="https://firefox--source--docs-mozilla-org.translate.goog/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB" class="icon icon-home"> Firefox Source Docs <img src="../_static/firefox-wordmark.svg" class="logo" alt="Logo"> </a><!-- -- This code is governed by the BSD license ----> <div> <h3>Quick search</h3> <script> (function () { var cx = "dd12886298f75dbef"; var gcse = document.createElement("script"); gcse.async = true; gcse.src = "https://cse.google.com/cse.js?cx=" + cx; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(gcse, s); })(); </script><gcse:search></gcse:search> </div> </div> <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu"> <p class="caption" role="heading"><span class="caption-text">Overview</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/glossary/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">A Glossary of Common Terms</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/overview/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">A Quick Guide to Mozilla Applications</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Getting Started</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/setup/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Getting Set Up To Work On The Firefox Codebase</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Working On Firefox</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/contributing/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Working on Firefox</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/bug-mgmt/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Bug Handling</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Firefox User Guide</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/devtools-user/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Firefox DevTools User Docs</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Source Code Documentation</span></p> <ul class="current"> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/mots/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Governance</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/browser/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Firefox Front-end</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/dom/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">DOM</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/editor/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Editor</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/layout/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Style system (CSS) & Layout</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/gfx/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Graphics</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Processes, Threads and IPC</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/devtools/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Firefox DevTools Contributor Docs</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/toolkit/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Toolkit</a></li> <li class="toctree-l1 current"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">SpiderMonkey</a> <ul class="current"> <li class="toctree-l2"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/build.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Building and testing SpiderMonkey</a></li> <li class="toctree-l2"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/test.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Running Automated JavaScript Tests</a></li> <li class="toctree-l2 current"><a class="current reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#">Hacking Tips</a> <ul> <li class="toctree-l3"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#tools">Tools</a></li> <li class="toctree-l3"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#debugging-tips">Debugging Tips</a> <ul> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#getting-help-from-js-shell">Getting help (from JS shell)</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#getting-the-bytecode-of-a-function-from-js-shell">Getting the bytecode of a function (from JS shell)</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#getting-the-bytecode-of-a-function-from-gdb">Getting the bytecode of a function (from gdb)</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#printing-the-js-stack-from-gdb">Printing the JS stack (from gdb)</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#setting-a-breakpoint-in-the-generated-code-from-gdb-x86-x86-64-arm">Setting a breakpoint in the generated code (from gdb, x86 / x86-64, arm)</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#printing-ion-generated-assembly-code-from-gdb">Printing Ion generated assembly code (from gdb)</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#printing-asm-js-wasm-generated-assembly-code-from-gdb">Printing asm.js/wasm generated assembly code (from gdb)</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#finding-the-script-of-ion-generated-assembly-from-gdb">Finding the script of Ion generated assembly (from gdb)</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#viewing-the-mirgraph-of-ion-odin-compilations-from-gdb">Viewing the MIRGraph of Ion/Odin compilations (from gdb)</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#finding-the-code-that-generated-a-jit-instruction-from-rr">Finding the code that generated a JIT instruction (from rr)</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#break-on-valgrind-errors">Break on valgrind errors</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#adding-spew-for-compilations-bailouts-invalidations-from-gdb">Adding spew for Compilations & Bailouts & Invalidations (from gdb)</a></li> </ul></li> <li class="toctree-l3"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#id1">Hacking tips</a> <ul> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#using-the-gecko-profiler-browser-xpcshell">Using the Gecko Profiler (browser / xpcshell)</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#using-callgrind-js-shell">Using callgrind (JS shell)</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#using-ionmonkey-spew-js-shell">Using IonMonkey spew (JS shell)</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#using-the-arm-simulator">Using the ARM simulator</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#using-rr-on-a-test">Using rr on a test</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#hack-replacing-one-instruction">[Hack] Replacing one instruction</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#hack-spewing-all-compiled-code">[Hack] Spewing all compiled code</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#benchmarking-with-sub-milliseconds-js-shell">Benchmarking with sub-milliseconds (JS shell)</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#benchmarking-with-sub-milliseconds-browser">Benchmarking with sub-milliseconds (browser)</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#dumping-the-javascript-heap">Dumping the JavaScript heap</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#inspecting-mir-objects-within-a-debugger">Inspecting MIR objects within a debugger</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#how-to-debug-oomtest-failures">How to debug oomTest() failures</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#debugging-gc-marking-rooting">Debugging GC marking/rooting</a></li> </ul></li> </ul></li> <li class="toctree-l2"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/Debugger/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Debugger API</a></li> <li class="toctree-l2"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/SavedFrame/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">SavedFrame</a></li> <li class="toctree-l2"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/feature_checklist.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">JavaScript Language Feature Checklist</a></li> <li class="toctree-l2"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/bytecode_checklist.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">So You Want to Add a Bytecode Op</a></li> <li class="toctree-l2"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#components-of-spidermonkey">Components of SpiderMonkey</a></li> </ul></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/mobile/android/geckoview/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">GeckoView</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/mobile/android/fenix/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Fenix</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/mobile/android/focus-android/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Focus for Android</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/dom/bindings/webidl/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">WebIDL</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/modules/libpref/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">libpref</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/networking/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Networking</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/remote/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Remote Protocols</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/services/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Services</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/uriloader/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">File Handling</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/widget/cocoa/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Firefox on macOS</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/widget/windows/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Firefox on Windows</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/toolkit/components/ml/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Firefox AI Platform</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/accessible/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Accessibility</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/code-quality/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Code quality</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/writing-rust-code/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Writing Rust Code</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/rust-components/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Rust Components</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/tools/profiler/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Gecko Profiler</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/performance/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Performance</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/storage/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Database bindings (SQLite, KV, …)</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/xpcom/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">XPCOM</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/nspr/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">NSPR</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/security/nss/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Network Security Services (NSS)</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/content-security/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Web Security Checks in Gecko</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">The Firefox Build System</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/mach/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Mach</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/tools/try/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Pushing to Try</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/build/buildsystem/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Build System</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/taskcluster/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Firefox CI and Taskgraph</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/tools/moztreedocs/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Managing Documentation</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/mozbuild/vendor/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Vendoring Third Party Components</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Testing & Test Infrastructure</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/automated-testing/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Automated Testing</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/treeherder-try/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Understanding Treeherder Results</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/sheriffed-intermittents/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Sheriffed intermittent failures</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/tests-for-new-config/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Turning on Firefox tests for a new configuration</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/intermittent/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Avoiding intermittent tests</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/testing-policy/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Testing Policy</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/ci-configs/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Configuration Changes</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/browser-chrome/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Browser chrome mochitests</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/chrome-tests/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Chrome Tests</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/marionette/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Marionette</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/geckodriver/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">geckodriver</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/test-verification/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Test Verification</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/webrender/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">WebRender Tests</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/mochitest-plain/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Mochitest</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/xpcshell/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">XPCShell tests</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/tps/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">TPS</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/web-platform/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">web-platform-tests</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/gtest/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">GTest</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/tools/fuzzing/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Fuzzing</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/tools/sanitizer/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Sanitizer</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/perfdocs/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Performance Testing</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/tools/code-coverage/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Code coverage</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing-rust-code/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Testing & Debugging Rust Code</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Releases & Updates</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/update-infrastructure/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Mozilla Update Infrastructure</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/update-infrastructure/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#watershed-updates">Watershed Updates</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/update-infrastructure/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#desupport-updates">Desupport Updates</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Localization & Internationalization</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/intl/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Internationalization</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/l10n/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Localization</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Firefox and Python</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/mozbase/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">mozbase</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/python/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Using third-party Python packages</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Metrics Collected in Firefox</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/metrics/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Metrics</a></li> </ul> </div> </div> </nav> <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"> <nav class="wy-nav-top" aria-label="Mobile navigation menu"><i data-toggle="wy-nav-top" class="fa fa-bars"></i> <a href="https://firefox--source--docs-mozilla-org.translate.goog/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">Firefox Source Docs</a> </nav> <div class="wy-nav-content"> <div class="rst-content"><!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this file, - You can obtain one at http://mozilla.org/MPL/2.0/. --> <div role="navigation" aria-label="Page navigation"> <ul class="wy-breadcrumbs"> <li><a href="https://firefox--source--docs-mozilla-org.translate.goog/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB" class="icon icon-home" aria-label="Home"></a></li> <li class="breadcrumb-item"><a href="https://firefox--source--docs-mozilla-org.translate.goog/js/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">SpiderMonkey</a></li> <li class="breadcrumb-item active">Hacking Tips</li> <li class="wy-breadcrumbs-aside"><a href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://bugzilla.mozilla.org/enter_bug.cgi?product%3DDeveloper%2BInfrastructure%26component%3DFirefox%2BSource%2BDocs%253A%2BContent%26short_desc%3DDocumentation%2Bissue%2Bon%2Bjs/hacking_tips%26comment%3DURL%2B%3D%2Bhttps://firefox-source-docs.mozilla.org/js/hacking_tips.html%26bug_file_loc%3Dhttps://firefox-source-docs.mozilla.org/js/hacking_tips.html" rel="nofollow">Report an issue</a> / <a href="https://firefox--source--docs-mozilla-org.translate.goog/_sources/js/hacking_tips.md.txt?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB" rel="nofollow"> View page source</a></li> </ul> <hr> </div> <div role="main" class="document" itemscope itemtype="http://schema.org/Article"> <div itemprop="articleBody"> <section id="hacking-tips"> <h1>Hacking Tips<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#hacking-tips" title="Link to this heading">¶</a></h1> <p><strong>These tips were archived from <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://mdn-archive.mossop.dev/en-US/docs/Mozilla/Projects/SpiderMonkey/Hacking_Tips">MDN</a></strong>: This may be out of date!</p> <p>This is archived here because it captures valuable documentation that even if potentially out of date, provides inspiration.</p> <hr class="docutils"> <p>This page lists a few tips to help you investigate issues related to SpiderMonkey. All tips listed here are dealing with the JavaScript shell obtained at the end of the <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/build.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB"><span class="std std-doc">build documentation of SpiderMonkey</span></a>. It is separated in 2 parts, one section related to debugging and another section related to drafting optimizations. Many of these tips only apply to debug builds of the JS shell; they will not function in a release build.</p> <section id="tools"> <h2>Tools<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#tools" title="Link to this heading">¶</a></h2> <p>Here are some debugging tools above and beyond your standard debugger that might help you:</p> <ul class="simple"> <li><p><a class="reference external" href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://rr-project.org/">rr</a> is a record-and-replay deterministic debugger for Linux</p></li> <li><p><a class="reference external" href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://pernos.co/">Pernosco</a> takes an rr recording and adds omniscient debugging tools to help you</p> <ul> <li><p>It is a paid service with a free trial</p></li> <li><p>Mozilla has a license for internal developers; you can contact Matthew Gaudet <a class="reference external" href="mailto:mgaudet%40mozilla.com?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB">mgaudet<span>@</span>mozilla<span>.</span>com</a> for details</p></li> </ul></li> </ul> </section> <section id="debugging-tips"> <h2>Debugging Tips<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#debugging-tips" title="Link to this heading">¶</a></h2> <section id="getting-help-from-js-shell"> <h3>Getting help (from JS shell)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#getting-help-from-js-shell" title="Link to this heading">¶</a></h3> <p>Use the <strong>help</strong> function to get the list of all primitive functions of the shell with their description. Note that some functions have been moved under an ‘os’ object, and <strong>help(os)</strong> will give brief help on just the members of that “namespace”.</p> <p>You can also use <strong>help(/Regex/)</strong> to get help for members of the global namespace that match the given regular expression.</p> </section> <section id="getting-the-bytecode-of-a-function-from-js-shell"> <h3>Getting the bytecode of a function (from JS shell)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#getting-the-bytecode-of-a-function-from-js-shell" title="Link to this heading">¶</a></h3> <p>The shell has a small function named <strong>dis</strong> to dump the bytecode of a function with its source notes. Without arguments, it will dump the bytecode of its caller.</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span><span class="n">js</span><span class="o">></span> <span class="n">function</span> <span class="n">f</span> <span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> <span class="p">}</span> <span class="n">js</span><span class="o">></span> <span class="n">dis</span><span class="p">(</span><span class="n">f</span><span class="p">);</span> <span class="n">flags</span><span class="p">:</span> <span class="n">loc</span> <span class="n">op</span> <span class="o">-----</span> <span class="o">--</span> <span class="n">main</span><span class="p">:</span> <span class="mi">00000</span><span class="p">:</span> <span class="n">one</span> <span class="mi">00001</span><span class="p">:</span> <span class="k">return</span> <span class="mi">00002</span><span class="p">:</span> <span class="n">stop</span> <span class="n">Source</span> <span class="n">notes</span><span class="p">:</span> <span class="n">ofs</span> <span class="n">line</span> <span class="n">pc</span> <span class="n">delta</span> <span class="n">desc</span> <span class="n">args</span> <span class="o">----</span> <span class="o">----</span> <span class="o">-----</span> <span class="o">------</span> <span class="o">--------</span> <span class="o">------</span> <span class="mi">0</span><span class="p">:</span> <span class="mi">1</span> <span class="mi">0</span> <span class="p">[</span> <span class="mi">0</span><span class="p">]</span> <span class="n">newline</span> <span class="mi">1</span><span class="p">:</span> <span class="mi">2</span> <span class="mi">0</span> <span class="p">[</span> <span class="mi">0</span><span class="p">]</span> <span class="n">colspan</span> <span class="mi">2</span> <span class="mi">3</span><span class="p">:</span> <span class="mi">2</span> <span class="mi">2</span> <span class="p">[</span> <span class="mi">2</span><span class="p">]</span> <span class="n">colspan</span> <span class="mi">9</span> </pre> </div> </div> </section> <section id="getting-the-bytecode-of-a-function-from-gdb"> <h3>Getting the bytecode of a function (from gdb)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#getting-the-bytecode-of-a-function-from-gdb" title="Link to this heading">¶</a></h3> <p>In <em>jsopcode.cpp</em>, a function named <strong>js::DisassembleAtPC</strong> can print the bytecode of a script. Some variants of this function, such as <strong>js::DumpScript</strong> etc., are convenient for debugging.</p> </section> <section id="printing-the-js-stack-from-gdb"> <h3>Printing the JS stack (from gdb)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#printing-the-js-stack-from-gdb" title="Link to this heading">¶</a></h3> <p>In <em>jsobj.cpp</em>, a function named <strong>js::DumpBacktrace</strong> prints a backtrace à la gdb for the JS stack. The backtrace contains in the following order, the stack depth, the interpreter frame pointer (see <em>js/src/vm/Stack.h</em>, <strong>StackFrame</strong> class) or (nil) if compiled with IonMonkey, the file and line number of the call location and under parentheses, the <strong>JSScript</strong> pointer and the <strong>jsbytecode</strong> pointer (pc) executed.</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span>$ gdb --args js […] (gdb) b js::ReportOverRecursed (gdb) r js> function f(i) { if (i % 2) f(i + 1); else f(i + 3); } js> f(0) Breakpoint 1, js::ReportOverRecursed (maybecx=0xfdca70) at /home/nicolas/mozilla/ionmonkey/js/src/jscntxt.cpp:495 495 if (maybecx) (gdb) call js::DumpBacktrace(maybecx) #0 (nil) typein:2 (0x7fffef1231c0 @ 0) #1 (nil) typein:2 (0x7fffef1231c0 @ 24) #2 (nil) typein:3 (0x7fffef1231c0 @ 47) #3 (nil) typein:2 (0x7fffef1231c0 @ 24) #4 (nil) typein:3 (0x7fffef1231c0 @ 47) […] #25157 0x7fffefbbc250 typein:2 (0x7fffef1231c0 @ 24) #25158 0x7fffefbbc1c8 typein:3 (0x7fffef1231c0 @ 47) #25159 0x7fffefbbc140 typein:2 (0x7fffef1231c0 @ 24) #25160 0x7fffefbbc0b8 typein:3 (0x7fffef1231c0 @ 47) #25161 0x7fffefbbc030 typein:5 (0x7fffef123280 @ 9) </pre> </div> </div> <p>Note, you can do the exact same exercise above using <code class="docutils literal notranslate"><span class="pre">lldb</span></code> (necessary on OSX after Apple removed <code class="docutils literal notranslate"><span class="pre">gdb</span></code>) by running <code class="docutils literal notranslate"><span class="pre">lldb</span> <span class="pre">-f</span> <span class="pre">js</span></code> then following the remaining steps.</p> <p>Since SpiderMonkey 48, we have a gdb unwinder. This unwinder is able to read the frames created by the JIT, and to display the frames which are after these JIT frames.</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span>$ gdb --args out/dist/bin/js ./foo.js […] SpiderMonkey unwinder is disabled by default, to enable it type: enable unwinder .* SpiderMonkey (gdb) b js::math_cos (gdb) run […] #0 js::math_cos (cx=0x14f2640, argc=1, vp=0x7fffffff6a88) at js/src/jsmath.cpp:338 338 CallArgs args = CallArgsFromVp(argc, vp); (gdb) enable unwinder .* SpiderMonkey (gdb) backtrace 10 #0 0x0000000000f89979 in js::math_cos(JSContext*, unsigned int, JS::Value*) (cx=0x14f2640, argc=1, vp=0x7fffffff6a88) at js/src/jsmath.cpp:338 #1 0x0000000000ca9c6e in js::CallJSNative(JSContext*, bool (*)(JSContext*, unsigned int, JS::Value*), JS::CallArgs const&) (cx=0x14f2640, native=0xf89960 , args=...) at js/src/jscntxtinlines.h:235 #2 0x0000000000c87625 in js::Invoke(JSContext*, JS::CallArgs const&, js::MaybeConstruct) (cx=0x14f2640, args=..., construct=js::NO_CONSTRUCT) at js/src/vm/Interpreter.cpp:476 #3 0x000000000069bdcf in js::jit::DoCallFallback(JSContext*, js::jit::BaselineFrame*, js::jit::ICCall_Fallback*, uint32_t, JS::Value*, JS::MutableHandleValue) (cx=0x14f2640, frame=0x7fffffff6ad8, stub_=0x1798838, argc=1, vp=0x7fffffff6a88, res=JSVAL_VOID) at js/src/jit/BaselineIC.cpp:6113 #4 0x00007ffff7f41395 in </pre> </div> </div> <p>Note, when you enable the unwinder, the current version of gdb (7.10.1) does not flush the backtrace. Therefore, the JIT frames do not appear until you settle on the next breakpoint. To work-around this issue you can use the recording feature of <code class="docutils literal notranslate"><span class="pre">gdb</span></code>, to step one instruction, and settle back to where you came from with the following set of <code class="docutils literal notranslate"><span class="pre">gdb</span></code> commands:</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span><span class="p">(</span><span class="n">gdb</span><span class="p">)</span> <span class="n">record</span> <span class="n">full</span> <span class="p">(</span><span class="n">gdb</span><span class="p">)</span> <span class="n">si</span> <span class="p">(</span><span class="n">gdb</span><span class="p">)</span> <span class="n">record</span> <span class="n">goto</span> <span class="mi">0</span> <span class="p">(</span><span class="n">gdb</span><span class="p">)</span> <span class="n">record</span> <span class="n">stop</span> </pre> </div> </div> <p>If you have a core file, you can use the gdb unwinder the same way, or do everything from the command line as follows:</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span>$ gdb -ex 'enable unwinder .* SpiderMonkey' -ex 'bt 0' -ex 'thread apply all backtrace' -ex 'quit' out/dist/bin/js corefile </pre> </div> </div> <p>The gdb unwinder is supposed to be loaded by <code class="docutils literal notranslate"><span class="pre">dist/bin/js-gdb.py</span></code> and load python scripts which are located in <code class="docutils literal notranslate"><span class="pre">js/src/gdb/mozilla</span></code> under gdb. If gdb does not load the unwinder by default, you can force it to, by using the <code class="docutils literal notranslate"><span class="pre">source</span></code> command with the <code class="docutils literal notranslate"><span class="pre">js-gdb.py</span></code> file.</p> </section> <section id="setting-a-breakpoint-in-the-generated-code-from-gdb-x86-x86-64-arm"> <h3>Setting a breakpoint in the generated code (from gdb, x86 / x86-64, arm)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#setting-a-breakpoint-in-the-generated-code-from-gdb-x86-x86-64-arm" title="Link to this heading">¶</a></h3> <p>To set a breakpoint in the generated code of a specific JSScript compiled with IonMonkey, set a breakpoint on the instruction you are interested in. If you have no precise idea which function you are looking at, you can set a breakpoint on the <strong>js::ion::CodeGenerator::visitStart</strong> function. Optionally, a condition on the <strong>ins->id()</strong> of the LIR instruction can be added to select precisely the instruction you are looking for. Once the breakpoint is on the <strong>CodeGenerator</strong> function of the LIR instruction, add a command to generate a static breakpoint in the generated code.</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span>$ gdb --args js […] (gdb) b js::ion::CodeGenerator::visitStart (gdb) command >call masm.breakpoint() >continue >end (gdb) r js> function f(a, b) { return a + b; } js> for (var i = 0; i < 100000; i++) f(i, i + 1); Breakpoint 1, js::ion::CodeGenerator::visitStart (this=0x101ed20, lir=0x10234e0) at /home/nicolas/mozilla/ionmonkey/js/src/ion/CodeGenerator.cpp:609 609 } Program received signal SIGTRAP, Trace/breakpoint trap. 0x00007ffff7fb165a in ?? () (gdb) </pre> </div> </div> <p>Once you hit the generated breakpoint, you can replace it by a gdb breakpoint to make it conditional. The procedure is to first replace the generated breakpoint by a nop instruction, and to set a breakpoint at the address of the nop.</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span>(gdb) x /5i $pc - 1 0x7ffff7fb1659: int3 => 0x7ffff7fb165a: mov 0x28(%rsp),%rax 0x7ffff7fb165f: mov %eax,%ecx 0x7ffff7fb1661: mov 0x30(%rsp),%rdx 0x7ffff7fb1666: mov %edx,%ebx (gdb) # replace the int3 by a nop (gdb) set *(unsigned char *) ($pc - 1) = 0x90 (gdb) x /1i $pc - 1 0x7ffff7fb1659: nop (gdb) # set a breakpoint at the previous location (gdb) b *0x7ffff7fb1659 Breakpoint 2 at 0x7ffff7fb1659 </pre> </div> </div> </section> <section id="printing-ion-generated-assembly-code-from-gdb"> <h3>Printing Ion generated assembly code (from gdb)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#printing-ion-generated-assembly-code-from-gdb" title="Link to this heading">¶</a></h3> <p>If you want to look at the assembly code generated by IonMonkey, you can follow this procedure:</p> <ol class="arabic simple"> <li><p>Place a breakpoint at CodeGenerator.cpp on the CodeGenerator::link method.</p></li> <li><p>Step next a few times, so that the “code” variable gets generated</p></li> <li><p>Print code->code_, which is the address of the code</p></li> <li><p>Disassemble code read at this address (using x/Ni address, where N is the number of instructions you would like to see)</p></li> </ol> <p>Here is an example. It might be simpler to use the CodeGenerator::link lineno instead of the full qualified name to put the breakpoint. Let’s say that the line number of this function is 4780, for instance:</p> <div class="highlight-none notranslate"> <div class="highlight"> <pre><span></span>(gdb) b CodeGenerator.cpp:4780 Breakpoint 1 at 0x84cade0: file /home/code/mozilla-central/js/src/ion/CodeGenerator.cpp, line 4780. (gdb) r Starting program: /home/code/mozilla-central/js/src/32-release/js -f /home/code/jaeger.js [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [New Thread 0xf7903b40 (LWP 12563)] [New Thread 0xf6bdeb40 (LWP 12564)] Run#0 Breakpoint 1, js::ion::CodeGenerator::link (this=0x86badf8) at /home/code/mozilla-central/js/src/ion/CodeGenerator.cpp:4780 4780 { (gdb) n 4781 JSContext *cx = GetIonContext()->cx; (gdb) n 4783 Linker linker(masm); (gdb) n 4784 IonCode *code = linker.newCode(cx, JSC::ION*CODE); (gdb) n 4785 if (!code) (gdb) p code->code* $1 = (uint8_t \*) 0xf7fd25a8 "\201", <incomplete sequence \354\200> (gdb) x/2i 0xf7fd25a8 0xf7fd25a8: sub $0x80,%esp 0xf7fd25ae: mov 0x94(%esp),%ecx </pre> </div> </div> <p>On arm, the compiled JS code will always be ARM machine code, whereas SpiderMonkey itself is frequently Thumb2. Since there isn’t debug info for the JIT’d code, you will need to tell gdb that you are looking at ARM code:</p> <div class="highlight-none notranslate"> <div class="highlight"> <pre><span></span>(gdb) set arm force-mode arm </pre> </div> </div> <p>Or you can wrap the x command in your own command:</p> <div class="highlight-none notranslate"> <div class="highlight"> <pre><span></span>def xi set arm force-mode arm eval "x/%di %d", $arg0, $arg1 set arm force-mode auto end </pre> </div> </div> </section> <section id="printing-asm-js-wasm-generated-assembly-code-from-gdb"> <h3>Printing asm.js/wasm generated assembly code (from gdb)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#printing-asm-js-wasm-generated-assembly-code-from-gdb" title="Link to this heading">¶</a></h3> <ul class="simple"> <li><p>Set a breakpoint on <code class="docutils literal notranslate"><span class="pre">js::wasm::Instance::callExport</span></code> (defined in <code class="docutils literal notranslate"><span class="pre">WasmInstance.cpp</span></code> as of November 18th 2016). This will trigger for <em>any</em> asm.js/wasm call, so you should find a way to set this breakpoint for the only generated codes you want to look at.</p></li> <li><p>Run the program.</p></li> <li><p>Do <code class="docutils literal notranslate"><span class="pre">next</span></code> in gdb until you reach the definition of the <code class="docutils literal notranslate"><span class="pre">funcPtr</span></code>:</p></li> </ul> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span>// Call the per-exported-function trampoline created by GenerateEntry. auto funcPtr = JS*DATA_TO_FUNC_PTR(ExportFuncPtr, codeBase() + func.entryOffset()); if (!CALL_GENERATED_2(funcPtr, exportArgs.begin(), &tlsData*)) return false; </pre> </div> </div> <ul class="simple"> <li><p>After it’s set, <code class="docutils literal notranslate"><span class="pre">x/64i</span> <span class="pre">funcPtr</span></code> will show you the trampoline code. There should be a call to an address at some point; that’s what we’re targeting. Copy that address.</p></li> </ul> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span> 0x7ffff7ff6000: push %r15 0x7ffff7ff6002: push %r14 0x7ffff7ff6004: push %r13 0x7ffff7ff6006: push %r12 0x7ffff7ff6008: push %rbp 0x7ffff7ff6009: push %rbx 0x7ffff7ff600a: movabs $0xea4f80,%r10 0x7ffff7ff6014: mov 0x178(%r10),%r10 0x7ffff7ff601b: mov %rsp,0x40(%r10) 0x7ffff7ff601f: mov (%rsi),%r15 0x7ffff7ff6022: mov %rdi,%r10 0x7ffff7ff6025: push %r10 0x7ffff7ff6027: test $0xf,%spl 0x7ffff7ff602b: je 0x7ffff7ff6032 0x7ffff7ff6031: int3 0x7ffff7ff6032: callq 0x7ffff7ff5000 <------ right here </pre> </div> </div> <ul class="simple"> <li><p><code class="docutils literal notranslate"><span class="pre">x/64i</span> <span class="pre">address</span></code> (in this case: <code class="docutils literal notranslate"><span class="pre">x/64i</span> <span class="pre">0x7ffff7ff6032</span></code>).</p></li> <li><p>If you want to put a breakpoint at the function’s entry, you can do: <code class="docutils literal notranslate"><span class="pre">b</span> <span class="pre">*address</span></code> (for instance here, <code class="docutils literal notranslate"><span class="pre">b*</span> <span class="pre">0x7ffff7ff6032</span></code>). Then you can display the instructions around pc with <code class="docutils literal notranslate"><span class="pre">x/20i</span> <span class="pre">$pc,</span></code> and execute instruction by instruction with <code class="docutils literal notranslate"><span class="pre">stepi</span></code>.</p></li> </ul> </section> <section id="finding-the-script-of-ion-generated-assembly-from-gdb"> <h3>Finding the script of Ion generated assembly (from gdb)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#finding-the-script-of-ion-generated-assembly-from-gdb" title="Link to this heading">¶</a></h3> <p>When facing a bug in which you are in the middle of IonMonkey generated code, the first thing to note is that gdb’s backtrace is not reliable, because the generated code does not keep a frame pointer. To figure it out, you have to read the stack to infer the IonMonkey frame.</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span>(gdb) x /64a $sp […] 0x7fffffff9838: 0x7ffff7fad2da 0x141 0x7fffffff9848: 0x7fffef134d40 0x2 […] (gdb) p (*(JSFunction**) 0x7fffffff9848)->u.i.script_->lineno $1 = 1 (gdb) p (*(JSFunction**) 0x7fffffff9848)->u.i.script_->filename $2 = 0xff92d1 "typein" </pre> </div> </div> <p>The stack is ordered as defined in js/src/ion/IonFrames-x86-shared.h. It is composed of the return address, a descriptor (a small value), the JSFunction (if it is even) or a JSScript (if it is odd; remove it to dereference the pointer) and the frame ends with the number of actual arguments (a small value too). If you want to know at which LIR the code is failing at, the <strong>js::ion::CodeGenerator::generateBody</strong> function can be instrumented to dump the LIR <strong>id</strong> before each instruction.</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span>for (; iter != current->end(); iter++) { IonSpew(IonSpew_Codegen, "instruction %s", iter->opName()); […] masm.store16(Imm32(iter->id()), Address(StackPointer, -8)); // added if (!iter->accept(this)) return false; </pre> </div> </div> <p><code class="docutils literal notranslate"><span class="pre">This</span> <span class="pre">modification</span> <span class="pre">will</span> <span class="pre">add</span> <span class="pre">an</span> <span class="pre">instruction</span> <span class="pre">which</span> <span class="pre">abuses</span> <span class="pre">the</span> <span class="pre">stack</span> <span class="pre">pointer</span></code> to store an immediate value (the LIR id) to a location which would never be generated by any sane compiler. Thus when dumping the assembly under gdb, this kind of instructions would be easily noticeable.</p> </section> <section id="viewing-the-mirgraph-of-ion-odin-compilations-from-gdb"> <h3>Viewing the MIRGraph of Ion/Odin compilations (from gdb)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#viewing-the-mirgraph-of-ion-odin-compilations-from-gdb" title="Link to this heading">¶</a></h3> <p>With gdb instrumentation, we can call <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://github.com/sstangl/iongraph">iongraph</a> program within gdb when the execution is stopped. This instrumentation adds an <strong><code class="docutils literal notranslate"><span class="pre">iongraph</span></code></strong> command when provided with an instance of a <strong><code class="docutils literal notranslate"><span class="pre">MIRGenerator*</span></code></strong>, will call <code class="docutils literal notranslate"><span class="pre">iongraph</span></code>, <code class="docutils literal notranslate"><span class="pre">graphviz</span></code> and your preferred png viewer to display the MIR graph at the precise time of the execution. To find <strong><code class="docutils literal notranslate"><span class="pre">MIRGenetator*</span></code></strong> instances, it is best to look up into the stack for <code class="docutils literal notranslate"><span class="pre">OptimizeMIR</span></code>, or <code class="docutils literal notranslate"><span class="pre">CodeGenerator::generateBody</span></code>. <strong><code class="docutils literal notranslate"><span class="pre">OptimizeMIR</span></code></strong> function has a <strong><code class="docutils literal notranslate"><span class="pre">mir</span></code></strong> argument, and the <strong><code class="docutils literal notranslate"><span class="pre">CodeGenerator::generateBody</span></code></strong> function has a member <strong><code class="docutils literal notranslate"><span class="pre">this->gen</span></code></strong>.</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span>(gdb) bt #0 0x00000000007eaad4 in js::InlineList<js::jit::MBasicBlock>::begin() const (this=0x33dbbc0) at …/js/src/jit/InlineList.h:280 #1 0x00000000007cb845 in js::jit::MIRGraph::begin() (this=0x33dbbc0) at …/js/src/jit/MIRGraph.h:787 #2 0x0000000000837d25 in js::jit::BuildPhiReverseMapping(js::jit::MIRGraph&) (graph=...) at …/js/src/jit/IonAnalysis.cpp:2436 #3 0x000000000083317f in js::jit::OptimizeMIR(js::jit::MIRGenerator*) (mir=0x33dbdf0) at …/js/src/jit/Ion.cpp:1570 … (gdb) frame 3 #3 0x000000000083317f in js::jit::OptimizeMIR(js::jit::MIRGenerator*) (mir=0x33dbdf0) at …/js/src/jit/Ion.cpp:1570 (gdb) iongraph mir function 0 (asm.js compilation): success; 1 passes. /* open your png viewer with the result of iongraph */ </pre> </div> </div> <p>This gdb instrumentation is supposed to work with debug builds, or with optimized builds compiled with <code class="docutils literal notranslate"><span class="pre">--enable-jitspew</span></code> configure flag. External programs such as <code class="docutils literal notranslate"><span class="pre">iongraph</span></code>, <code class="docutils literal notranslate"><span class="pre">dot</span></code>, and your png viewer are searched for in the <code class="docutils literal notranslate"><span class="pre">PATH</span></code>; otherwise custom one can either be configured with environment variables (<code class="docutils literal notranslate"><span class="pre">GDB_IONGRAPH</span></code>, <code class="docutils literal notranslate"><span class="pre">GDB_DOT</span></code>, <code class="docutils literal notranslate"><span class="pre">GDB_PNGVIEWER</span></code>) before starting gdb, or with gdb parameters (<code class="docutils literal notranslate"><span class="pre">set</span> <span class="pre">iongraph-bin</span> <span class="pre"><path></span></code>, <code class="docutils literal notranslate"><span class="pre">set</span> <span class="pre">dot-bin</span> <span class="pre"><path></span></code>, <code class="docutils literal notranslate"><span class="pre">set</span> <span class="pre">pngviewer-bin</span> <span class="pre"><path></span></code>) within gdb.</p> <p>Enabling GDB instrumentation may require launching a JS shell executable that shares a directory with a file name “js-gdb.py”. If js/src/js does not provide the “iongraph” command, try js/src/shell/js. GDB may complain that ~/.gdbinit requires modification to authorize user scripts, and if so will print out directions.</p> </section> <section id="finding-the-code-that-generated-a-jit-instruction-from-rr"> <h3>Finding the code that generated a JIT instruction (from rr)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#finding-the-code-that-generated-a-jit-instruction-from-rr" title="Link to this heading">¶</a></h3> <p>If you are looking at a JIT instruction and need to know what code generated it, you can use <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://searchfox.org/mozilla-central/source/js/src/gdb/mozilla/jitsrc.py">jitsrc.py</a>. This script adds a <code class="docutils literal notranslate"><span class="pre">jitsrc</span></code> command to rr that will trace backwards from the JIT instruction to the code that generated it.</p> <p>To use the <code class="docutils literal notranslate"><span class="pre">jitsrc</span></code> command, add the following line to your .gdbinit file, or run it manually:</p> <div class="highlight-none notranslate"> <div class="highlight"> <pre><span></span>source js/src/gdb/mozilla/jitsrc.py </pre> </div> </div> <p>And you use the command like this: <code class="docutils literal notranslate"><span class="pre">jitsrc</span> <span class="pre"><address</span> <span class="pre">of</span> <span class="pre">JIT</span> <span class="pre">instruction></span></code>.</p> <p>Running the command will leave the application at the point of execution where that JIT instruction was originally emitted. For example, the backtrace might contain a frame at <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://searchfox.org/mozilla-central/rev/ddde3bbcafabe0fc8a36c660b3b673507d3e3874/js/src/jit/x64/MacroAssembler-x64.h%23575">js::jit::MacroAssemblerX64::loadPtr</a>.</p> <p>The way this works is by setting a watchpoint on the JIT instruction and <code class="docutils literal notranslate"><span class="pre">reverse-continue</span></code>ing the program execution to reach the point when that memory address was assigned to. JIT instruction memory can be copied or moved, so the <code class="docutils literal notranslate"><span class="pre">jitsrc</span></code> command automates updating the watchpoint across the copy/move to continue back to the original source of the JIT instruction.</p> </section> <section id="break-on-valgrind-errors"> <h3>Break on valgrind errors<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#break-on-valgrind-errors" title="Link to this heading">¶</a></h3> <p>Sometimes, a bug can be reproduced under valgrind but with great difficulty under gdb. One way to investigate is to let valgrind start gdb for you; the other way documented here is to let valgrind act as a gdb server which can be manipulated from the gdb remote.</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span>$ valgrind --smc-check=all-non-file </pre> </div> </div> <p>This command will tell you how to start gdb as a remote. Be aware that functions which are usually dumping some output will do it in the shell where valgrind is started and not in the shell where gdb is started. Thus functions such as <strong>js::DumpBacktrace</strong>, when called from gdb, will print their output in the shell containing valgrind.</p> </section> <section id="adding-spew-for-compilations-bailouts-invalidations-from-gdb"> <h3>Adding spew for Compilations & Bailouts & Invalidations (from gdb)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#adding-spew-for-compilations-bailouts-invalidations-from-gdb" title="Link to this heading">¶</a></h3> <p>If you are in rr, and forgot to record with the spew enabled with IONFLAGS or because this is an optimized build, then you can add similar spew with extra breakpoints within gdb. gdb has the ability to set breakpoints with commands, but a simpler / friendlier version is to use <strong>dprintf</strong>, with a location, and followed by printf-like arguments.</p> <div class="highlight-none notranslate"> <div class="highlight"> <pre><span></span>(gdb) dprintf js::jit::IonBuilder::IonBuilder, "Compiling %s:%d:%d-%d\n", info->script*->scriptSource()->filename*.mTuple.mFirstA, info->script*->lineno*, info->script*->sourceStart*, info->script*->sourceEnd* Dprintf 1 at 0x7fb4f6a104eb: file /home/nicolas/mozilla/contrib-push/js/src/jit/IonBuilder.cpp, line 159. (gdb) cond 1 inliningDepth == 0 (gdb) dprintf js::jit::BailoutIonToBaseline, "Bailout from %s:%d:%d-%d\n", iter.script()->scriptSource()->filename*.mTuple.mFirstA, iter.script()->lineno*, iter.script()->sourceStart*, iter.script()->sourceEnd* Dprintf 2 at 0x7fb4f6fe43dc: js::jit::BailoutIonToBaseline. (2 locations) (gdb) dprintf Ion.cpp:3196, "Invalidate %s:%d:%d-%d\n", co->script*->scriptSource()->filename*.mTuple.mFirstA, co->script*->lineno*, co->script*->sourceStart*, co->script*->sourceEnd* Dprintf 3 at 0x7fb4f6a0b62a: file /home/nicolas/mozilla/contrib-push/js/src/jit/Ion.cpp, line 3196. `(gdb) continue` Compiling self-hosted:650:20470-21501 Bailout from self-hosted:20:403-500 Invalidate self-hosted:20:403-500 </pre> </div> </div> <p>Note: the line 3196, listed above, corresponds to the location of the <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://searchfox.org/mozilla-central/rev/655f49c541108e3d0a232aa7173fbcb9af88d80b/js/src/jit/Ion.cpp%232475">Jit spew inside jit::Invalidate function</a>.</p> </section> </section> <section id="id1"> <h2>Hacking tips<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#id1" title="Link to this heading">¶</a></h2> <section id="using-the-gecko-profiler-browser-xpcshell"> <h3>Using the Gecko Profiler (browser / xpcshell)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#using-the-gecko-profiler-browser-xpcshell" title="Link to this heading">¶</a></h3> <p>See the section dedicated to <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/tools/profiler/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB"><span class="std std-doc">profiling with the Gecko Profiler</span></a>. This method of profiling has the advantage of mixing the JavaScript stack with the C++ stack, which is useful for analyzing library function issues.</p> <p>One tip is to start looking at a script with an inverted JS stack to locate the most expensive JS function, then to focus on the frame of this JS function, and to remove the inverted stack and look at C++ part of this function to determine from where the cost is coming from.</p> <p>These archived <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://mdn-archive.mossop.dev/en-US/docs/Performance/Profiling_with_the_Built-in_Profiler" title="/en-US/docs/Performance/Profiling_with_the_Built-in_Profiler">tips on using the Gecko Profiler</a> and <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://mdn-archive.mossop.dev/en-US/docs/Mozilla/Performance/Gecko_Profiler_FAQ" title="Gecko Profiler FAQ">FAQ</a> might also be useful as inspiration, but are old enough that they are probably not accurate any more.</p> </section> <section id="using-callgrind-js-shell"> <h3>Using callgrind (JS shell)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#using-callgrind-js-shell" title="Link to this heading">¶</a></h3> <p>Because SpiderMonkey just-in-time compilers rewrite the executed program, valgrind should be informed from the command line by adding <strong>–smc-check=all-non-file</strong>.</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span>$ valgrind --tool=callgrind --callgrind-out-file=bench.clg \ --smc-check=all-non-file </pre> </div> </div> <p>The output file can then be used with <strong>kcachegrind</strong>, which provides a graphical view of the call graph.</p> </section> <section id="using-ionmonkey-spew-js-shell"> <h3>Using IonMonkey spew (JS shell)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#using-ionmonkey-spew-js-shell" title="Link to this heading">¶</a></h3> <p>IonMonkey spew is extremely verbose (not as much as the INFER spew), but you can filter it to focus on the list of compiled scripts or channels, IonMonkey spew channels can be selected with the IONFLAGS environment variable, and compilation spew can be filtered with IONFILTER.</p> <p>IONFLAGS contains the names of <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://searchfox.org/mozilla-central/source/js/src/jit/JitSpewer.cpp%23338">each channel separated by commas</a>. The <strong>logs</strong> channel produces one file (<em>/tmp/ion.json</em>), made to be used with <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://github.com/sstangl/iongraph">iongraph</a> (made by Sean Stangl). This tool will show the MIR & LIR steps done by IonMonkey during the compilation. To use <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://github.com/sstangl/iongraph">iongraph</a>, you must install <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://www.graphviz.org/download/" title="graphviz downloads">Graphviz</a>.</p> <p>Compilation logs and spew can be filtered with the IONFILTER environment variable which contains locations as output by other spew channels. Multiple locations can be specified using comma as a separator.</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span>$ IONFILTER=pdfjs.js:16934 IONFLAGS=logs,scripts,osi,bailouts ./js --ion-offthread-compile=off ./run.js 2>&1 | less </pre> </div> </div> <p>The <strong>bailouts</strong> channel is likely to be the first thing you should focus on, because this means that something does not stay in IonMonkey and fallback to the interpreter. This channel outputs locations (as returned by the <strong>id()</strong> function of both instructions) of the latest MIR and the latest LIR phases. These locations should correspond to phases of the <strong>logs</strong> and a filter can be used to remove uninteresting functions.</p> </section> <section id="using-the-arm-simulator"> <h3>Using the ARM simulator<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#using-the-arm-simulator" title="Link to this heading">¶</a></h3> <p>The ARM simulator can be used to test the ARM JIT backend on x86/x64 hardware. An ARM simulator build is an x86 shell (or browser) with the ARM JIT backend. Instead of entering JIT code, it runs it in a simulator (interpreter) for ARM code. To use the simulator, compile an x86 shell (32-bit, x64 doesn’t work as we use a different Value format there), and pass –enable-arm-simulator to configure. For instance, on a 64-bit Linux host you can use the following configure command to get an ARM simulator build:</p> <div class="highlight-shell notranslate"> <div class="highlight"> <pre><span></span><span class="nv">AR</span><span class="o">=</span>ar<span class="w"> </span><span class="nv">CC</span><span class="o">=</span><span class="s2">"gcc -m32"</span><span class="w"> </span><span class="nv">CXX</span><span class="o">=</span><span class="s2">"g++ -m32"</span><span class="w"> </span>../configure<span class="w"> </span>--target<span class="o">=</span>i686-pc-linux --enable-debug<span class="w"> </span>--disable-optimize<span class="w"> </span>--enable-threadsafe<span class="w"> </span>--enable-simulator<span class="o">=</span>arm </pre> </div> </div> <p>Or on OS X:</p> <div class="highlight-shell notranslate"> <div class="highlight"> <pre><span></span>$<span class="w"> </span><span class="nv">AR</span><span class="o">=</span>ar<span class="w"> </span><span class="nv">CC</span><span class="o">=</span><span class="s2">"clang -m32"</span><span class="w"> </span><span class="nv">CXX</span><span class="o">=</span><span class="s2">"clang++ -m32"</span><span class="w"> </span>../configure<span class="w"> </span>--target<span class="o">=</span>i686-apple-darwin10.0.0<span class="w"> </span>--enable-debug<span class="w"> </span>--disable-optimize<span class="w"> </span>--enable-threadsafe<span class="w"> </span>--enable-arm-simulator </pre> </div> </div> <p>An <strong>–enable-debug –enable-optimize</strong> build is recommended if you want to run jit-tests or jstests.</p> <section id="use-the-vixl-debugger-in-the-simulator-arm64"> <h4>Use the VIXL Debugger in the simulator (arm64)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#use-the-vixl-debugger-in-the-simulator-arm64" title="Link to this heading">¶</a></h4> <p>Set a breakpoint (see the section above about setting a breakpoint in generated code) and run with the environment variable <code class="docutils literal notranslate"><span class="pre">USE_DEBUGGER=1</span></code>. This will then drop you into a simple debugger provided with VIXL, the ARM simulator technology used for arm64 simulation.</p> </section> <section id="use-the-simulator-debugger-for-arm32"> <h4>Use the Simulator Debugger for arm32<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#use-the-simulator-debugger-for-arm32" title="Link to this heading">¶</a></h4> <p>The same instructions for arm64 in the preceding section apply, but the environment variable differs: Use <code class="docutils literal notranslate"><span class="pre">ARM_SIM_DEBUGGER=1</span></code>.</p> </section> <section id="building-the-browser-with-the-arm-simulator"> <h4>Building the browser with the ARM simulator<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#building-the-browser-with-the-arm-simulator" title="Link to this heading">¶</a></h4> <p>You can also build the entire browser with the ARM simulator backend, for instance to reproduce browser-only JS failures on ARM. Make sure to build a browser for x86 (32-bits) and add this option to your mozconfig file:</p> <p>ac_add_options –enable-arm-simulator</p> <p>If you are under an Ubuntu or Debian 64-bits distribution and you want to build a 32-bits browser, it might be hard to find the relevant 32-bits dependencies. You can use <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://github.com/padenot/fx-32-on-64.sh">padenot’s scripts</a> which will magically setup a chrooted 32-bits environment and do All The Things (c) for you (you just need to modify the mozconfig file).</p> </section> </section> <section id="using-rr-on-a-test"> <h3>Using rr on a test<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#using-rr-on-a-test" title="Link to this heading">¶</a></h3> <p>Get the command line for your test run using -s:</p> <p>./jit_test.py -s $JS_SHELL saved-stacks/async.js</p> <p>Insert ‘rr’ before the shell invocation:</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span>rr $JS_SHELL -f $JS_SRC/jit-test/lib/prolog.js --js-cache $JS_SRC/jit-test/.js-cache -e "const platform='linux2'; const libdir='$JS_SRC/jit-test/lib/'; const scriptdir='$JS_SRC/jit-test/tests/saved-stacks/'" -f $JS_SRC/jit-test/tests/saved-stacks/async.js </pre> </div> </div> <p>(note that the above is an example; simply setting JS_SHELL and JS_SRC will not work). Or if this is an intermittent, run it in a loop capturing an rr log for every one until it fails:</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span>n=1; while rr ...same.as.above...; do echo passed $n; n=$(( $n + 1 )); done </pre> </div> </div> <p>Wait until it hits a failure. Now you can run <code class="docutils literal notranslate"><span class="pre">rr</span> <span class="pre">replay</span></code> to replay that last (failed) run under gdb.</p> <section id="rr-with-reftest"> <h4>rr with reftest<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#rr-with-reftest" title="Link to this heading">¶</a></h4> <p>To break on the write of a differing pixel:</p> <ol class="arabic simple"> <li><p>Find the X/Y of a pixel that differs</p></li> <li><p>Use <code class="docutils literal notranslate"><span class="pre">run</span> <span class="pre">Z</span></code> where Z is the mark in the log for TEST-START. For example in ‘[rr 28496 607198]REFTEST TEST-START | file:///home/bgirard/mozilla-central/tree/image/test/reftest/bmp/bmpsuite/b/wrapper.html?badpalettesize.bmp’, Z would be 607198.</p></li> <li><p><code class="docutils literal notranslate"><span class="pre">break</span> <span class="pre">'mozilla::dom::CanvasRenderingContext2D::DrawWindow(nsGlobalWindow&,</span> <span class="pre">double,</span> <span class="pre">double,</span> <span class="pre">double,</span> <span class="pre">double,</span> <span class="pre">nsAString_internal</span> <span class="pre">const&,</span> <span class="pre">unsigned</span> <span class="pre">int,</span> <span class="pre">mozilla::ErrorResult&)'</span></code></p></li> <li><p><code class="docutils literal notranslate"><span class="pre">cont</span></code></p></li> <li><p><code class="docutils literal notranslate"><span class="pre">break</span> <span class="pre">'PresShell::RenderDocument(nsRect</span> <span class="pre">const&,</span> <span class="pre">unsigned</span> <span class="pre">int,</span> <span class="pre">unsigned</span> <span class="pre">int,</span> <span class="pre">gfxContext\*)'</span></code></p></li> <li><p><code class="docutils literal notranslate"><span class="pre">set</span> <span class="pre">print</span> <span class="pre">object</span> <span class="pre">on</span></code></p></li> <li><p><code class="docutils literal notranslate"><span class="pre">set</span> <span class="pre">$x</span> <span class="pre">=</span> <span class="pre"><YOUR</span> <span class="pre">X</span> <span class="pre">VALUE></span></code></p></li> <li><p><code class="docutils literal notranslate"><span class="pre">set</span> <span class="pre">$y</span> <span class="pre">=</span> <span class="pre"><YOUR</span> <span class="pre">Y</span> <span class="pre">VALUE></span></code></p></li> <li><p><code class="docutils literal notranslate"><span class="pre">print</span> <span class="pre">&((cairo_image_surface_t*)aThebesContext->mDT.mRawPtr->mSurface).data[$y</span> <span class="pre">*</span> <span class="pre">((cairo_image_surface_t*)aThebesContext->mDT.mRawPtr->mSurface).stride</span> <span class="pre">+</span> <span class="pre">$x</span> <span class="pre">*</span> <span class="pre">((cairo_image_surface_t\*)aThebesContext->mDT.mRawPtr->mSurface).depth</span> <span class="pre">/</span> <span class="pre">8]</span></code></p></li> <li><p><code class="docutils literal notranslate"><span class="pre">watch</span> <span class="pre">*(char*)<ADDRESS</span> <span class="pre">OF</span> <span class="pre">PREVIOUS</span> <span class="pre">COMMAND></span></code> (NOTE: If you set a watch on the previous expression gdb will watch the expression and run out of watchpoints)</p></li> </ol> </section> <section id="rr-with-emacs"> <h4>rr with emacs<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#rr-with-emacs" title="Link to this heading">¶</a></h4> <p>Within emacs, do <code class="docutils literal notranslate"><span class="pre">M-x</span> <span class="pre">gud-gdb</span></code> and replace the command line with <code class="docutils literal notranslate"><span class="pre">rr</span> <span class="pre">replay</span></code>. When gdb comes up, enter</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span><span class="nb">set</span> <span class="n">annot</span> <span class="mi">1</span> </pre> </div> </div> <p>to get it to emit file location information so that emacs will pop up the corresponding source. Note that if you <code class="docutils literal notranslate"><span class="pre">reverse-continue</span></code> over a SIGSEGV and you’re using the standard .gdbinit that sets a catchpoint for that signal, you’ll get an additional stop at the catchpoint. Just <code class="docutils literal notranslate"><span class="pre">reverse-continue</span></code> again to continue to your breakpoints or whatever.</p> </section> </section> <section id="hack-replacing-one-instruction"> <h3>[Hack] Replacing one instruction<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#hack-replacing-one-instruction" title="Link to this heading">¶</a></h3> <p>To replace one specific instruction, you can customize the instruction’s visit function using the JSScript <strong>filename</strong> in <strong>lineno</strong> fields, as well as the <strong>id()</strong> of the LIR / MIR instructions. The JSScript can be obtained from <strong>info().script()</strong>.</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span>bool CodeGeneratorX86Shared::visitGuardShape(LGuardShape *guard) { if (info().script()->lineno == 16934 && guard->id() == 522) { [… another impl only for this one …] return true; } [… old impl …] </pre> </div> </div> </section> <section id="hack-spewing-all-compiled-code"> <h3>[Hack] Spewing all compiled code<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#hack-spewing-all-compiled-code" title="Link to this heading">¶</a></h3> <p>I usually just add this to the appropriate <code class="docutils literal notranslate"><span class="pre">executableCopy()</span></code> function.</p> <div class="highlight-none notranslate"> <div class="highlight"> <pre><span></span>if (getenv("INST_DUMP")) { char buf[4096]; sprintf(buf, "gdb /proc/%d/exe %d -batch -ex 'set pagination off' -ex 'set arm force-mode arm' -ex 'x/%di %p' -ex 'set arm force-mode auto'", getpid(), getpid(), m_buffer.size() / 4, buffer); system(buf); } </pre> </div> </div> <p>If you aren’t running on arm, you should omit the <code class="docutils literal notranslate"><span class="pre">-ex</span> <span class="pre">'set</span> <span class="pre">arm</span> <span class="pre">force-mode</span> <span class="pre">arm'</span></code> and <code class="docutils literal notranslate"><span class="pre">-ex</span> <span class="pre">'set</span> <span class="pre">arm</span> <span class="pre">force-mode</span> <span class="pre">auto'</span></code>. And you should change the size()/4 to be something more appropriate for your architecture.</p> </section> <section id="benchmarking-with-sub-milliseconds-js-shell"> <h3>Benchmarking with sub-milliseconds (JS shell)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#benchmarking-with-sub-milliseconds-js-shell" title="Link to this heading">¶</a></h3> <p>In the shell, we have 2 simple ways to benchmark a script. We can either use the <strong>-b</strong> shell option (<strong>–print-timing</strong>) which will evaluate a script given on the command line without any need to instrument the benchmark and print an extra line showing the run-time of the script. The other way is to wrap the section that you want to measure with the <strong>dateNow()</strong> function call, which returns the number of milliseconds, with a decimal part for sub-milliseconds.</p> <div class="highlight-js notranslate"> <div class="highlight"> <pre><span></span><span class="nx">js</span><span class="o">></span><span class="w"> </span><span class="nx">dateNow</span><span class="p">()</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">dateNow</span><span class="p">()</span> <span class="o">-</span><span class="mf">0.0009765625</span> </pre> </div> </div> <p>Since <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://bugzilla.mozilla.org/show_bug.cgi?id%3D1439788">Firefox 61</a>, the shell also has <strong>performance.now()</strong> available.</p> </section> <section id="benchmarking-with-sub-milliseconds-browser"> <h3>Benchmarking with sub-milliseconds (browser)<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#benchmarking-with-sub-milliseconds-browser" title="Link to this heading">¶</a></h3> <p>Similar to how you can use <strong>dateNow()</strong> in the JS shell, you can use <strong>performance.now()</strong> in the JavaScript code of a page.</p> </section> <section id="dumping-the-javascript-heap"> <h3>Dumping the JavaScript heap<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#dumping-the-javascript-heap" title="Link to this heading">¶</a></h3> <p>From the shell, you can call the <code class="docutils literal notranslate"><span class="pre">dumpHeap</span></code> function to dump out all GC things (reachable and unreachable) that are present in the heap. By default, the function writes to stdout, but a filename can be specified as an argument.</p> <p>Example output might look as follows:</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span><span class="mh">0x1234abcd</span> <span class="n">B</span> <span class="k">global</span> <span class="nb">object</span> </pre> </div> </div> <p>The output is textual. The first section of the file contains a list of roots, one per line. Each root has the form “0xabcd1234 <color> <description>”, where <color> is the color of the given GC thing (B for black, G for gray, W for white) and <description> is a string. The list of roots ends with a line containing “==========”.</p> <p>After the roots come a series of zones. A zone starts with several “comment lines” that start with hashes. The first comment declares the zone. It is followed by lines listing each compartment within the zone. After all the compartments come arenas, which is where the GC things are actually stored. Each arena is followed by all the GC things in the arena. A GC thing starts with a line giving its address, its color, and the thing kind (object, function, whatever). After this comes a list of addresses that the GC thing points to, each one starting with “>”.</p> <p>It’s also possible to dump the JavaScript heap from C++ code (or from gdb) using the <code class="docutils literal notranslate"><span class="pre">js::DumpHeap</span></code> function. It is part of jsfriendapi.h and it is available in release builds.</p> </section> <section id="inspecting-mir-objects-within-a-debugger"> <h3>Inspecting MIR objects within a debugger<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#inspecting-mir-objects-within-a-debugger" title="Link to this heading">¶</a></h3> <p>For MIRGraph, MBasicBlock, and MDefinition and its subclasses (MInstruction, MConstant, etc.), call the dump member function.</p> <div class="highlight-none notranslate"> <div class="highlight"> <pre><span></span>(gdb) call graph->dump() (gdb) call block->dump() (gdb) call def->dump() </pre> </div> </div> </section> <section id="how-to-debug-oomtest-failures"> <h3>How to debug oomTest() failures<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#how-to-debug-oomtest-failures" title="Link to this heading">¶</a></h3> <p>The oomTest() function executes a piece of code many times, simulating an OOM failure at each successive allocation it makes. It’s designed to highlight incorrect OOM handling, which may show up as a crash or assertion failure at some later point.</p> <p>When debugging such a crash, the most useful thing is to locate the last simulated allocation failure, as that is usually what has caused the subsequent crash.</p> <p>My workflow for doing this is as follows:</p> <ol class="arabic simple"> <li><p>Build a version of the engine with <code class="docutils literal notranslate"><span class="pre">--enable-debug</span></code> and <code class="docutils literal notranslate"><span class="pre">--enable-oom-breakpoint</span></code> configure flags.</p></li> <li><p>Set the environment variable <code class="docutils literal notranslate"><span class="pre">OOM_VERBOSE=1</span></code> and reproduce the failure. This will print an allocation count at each simulated failure. Note the count of the last allocation.</p></li> <li><p>Run the engine under a debugger and set a breakpoint on the function <code class="docutils literal notranslate"><span class="pre">js_failedAllocBreakpoint</span></code>.</p></li> <li><p>Run the program and <code class="docutils literal notranslate"><span class="pre">continue</span></code> the necessary number of times until you reach the final allocation.</p> <ul class="simple"> <li><p>e.g. in lldb, if the allocation failure number shown is 1500, run <code class="docutils literal notranslate"><span class="pre">continue</span> <span class="pre">-i</span> <span class="pre">1498</span></code> (subtracted 2 because we’ve already hit it once and don’t want to skip the last). Drop “-i” for gdb.</p></li> </ul></li> <li><p>Dump a backtrace. This should show you the point at which the OOM is incorrectly handled, which will be a few frames up from the breakpoint.</p></li> </ol> <p>Note: if you are on linux, it may be simpler to use rr.</p> <p>Some guidelines for handling OOM that lead to failures when they are not followed:</p> <ol class="arabic simple"> <li><p>Check for allocation failure!</p> <ul class="simple"> <li><p>Fallible allocations should always must be checked and handled, at a minimum by returning a status indicating failure to the caller.</p></li> </ul></li> <li><p>Report OOM to the context if you have one</p> <ul class="simple"> <li><p>If a function has a <code class="docutils literal notranslate"><span class="pre">JSContext*</span></code> argument, usually it should call <code class="docutils literal notranslate"><span class="pre">js::ReportOutOfMemory(cx)</span></code> on allocation failure to report this to the context.</p></li> </ul></li> <li><p>Sometimes it’s OK to ignore OOM</p> <ul class="simple"> <li><p>For example if you are performing a speculative optimisation you might abandon it and continue anyway. In this case, you may have to call cx->recoverFromOutOfMemory() if something further down the stack has already reported the failure.</p></li> </ul></li> </ol> </section> <section id="debugging-gc-marking-rooting"> <h3>Debugging GC marking/rooting<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/js/hacking_tips.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB#debugging-gc-marking-rooting" title="Link to this heading">¶</a></h3> <p>The <strong>js::debug</strong> namespace contains some functions that are useful for watching mark bits for an individual JSObject* (or any Cell*). <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://searchfox.org/mozilla-central/rev/dc5027f02e5ea1d6b56cfbd10f4d3a0830762115/js/src/gc/Heap.h%23817-835">js/src/gc/Heap.h</a> contains a comment describing an example usage. Reproduced here:</p> <div class="highlight-none notranslate"> <div class="highlight"> <pre><span></span>// Sample usage from gdb: // // (gdb) p $word = js::debug::GetMarkWordAddress(obj) // $1 = (uintptr_t *) 0x7fa56d5fe360 // (gdb) p/x $mask = js::debug::GetMarkMask(obj, js::gc::GRAY) // $2 = 0x200000000 // (gdb) watch *$word // Hardware watchpoint 7: *$word // (gdb) cond 7 *$word & $mask // (gdb) cont // // Note that this is *not* a watchpoint on a single bit. It is a watchpoint on // the whole word, which will trigger whenever the word changes and the // selected bit is set after the change. // // So if the bit changing is the desired one, this is exactly what you want. // But if a different bit changes (either set or cleared), you may still stop // execution if the $mask bit happened to already be set. gdb does not expose // enough information to restrict the watchpoint to just a single bit. </pre> </div> </div> <p>Most of the time, you will want <strong>js::gc::BLACK</strong> (or you can just use 0) for the 2nd param to <strong>js::debug::GetMarkMask</strong>.</p> </section> </section> </section> </div> </div> <footer> <div class="rst-footer-buttons" role="navigation" aria-label="Footer"><a href="https://firefox--source--docs-mozilla-org.translate.goog/js/test.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB" class="btn btn-neutral float-left" title="Running Automated JavaScript Tests" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a> <a href="https://firefox--source--docs-mozilla-org.translate.goog/js/Debugger/index.html?_x_tr_sl=pl&_x_tr_tl=tr&_x_tr_hl=en-GB" class="btn btn-neutral float-right" title="Debugger API" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a> </div> <hr> <div role="contentinfo"> <p></p> </div> Built with <a href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://www.sphinx-doc.org/">Sphinx</a> using a <a href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://github.com/readthedocs/sphinx_rtd_theme">theme</a> provided by <a href="https://translate.google.com/website?sl=pl&tl=tr&hl=en-GB&u=https://readthedocs.org">Read the Docs</a>. </footer> </div> </div> </section> </div> <script> jQuery(function () { SphinxRtdTheme.Navigation.enable(true); }); </script> <script>function gtElInit() {var lib = new google.translate.TranslateService();lib.translatePage('pl', 'tr', function () {});}</script> <script src="https://translate.google.com/translate_a/element.js?cb=gtElInit&hl=en-GB&client=wt" type="text/javascript"></script> </body> </html>