From c068fe922c50c8788bdf7e55ff037f3dbb45ad73 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Wed, 1 Jul 2026 11:22:36 +0200 Subject: [PATCH 1/6] update-docs --- .github/workflows/deploy.yml | 2 + .github/workflows/pr-build.yml | 2 + .gitignore | 4 + package.json | 5 +- src/docs/api.md | 45 -- src/docs/become-committer.md | 46 -- src/docs/benchmarks.md | 140 ----- src/docs/blink-layout-tests.md | 16 - src/docs/build-gn.md | 134 ----- src/docs/build.md | 63 --- src/docs/builtin-functions.md | 9 - src/docs/committer-responsibility.md | 42 -- src/docs/compile-arm64.md | 86 --- src/docs/contribute.md | 41 -- src/docs/cross-compile-arm.md | 170 ------ src/docs/cross-compile-ios.md | 52 -- src/docs/csa-builtins.md | 228 -------- src/docs/d8.md | 80 --- src/docs/debug-arm.md | 521 ----------------- src/docs/design-review-guidelines.md | 148 ----- src/docs/embed.md | 431 -------------- src/docs/evaluate-code-coverage.md | 35 -- src/docs/feature-launch-process.md | 83 --- src/docs/flake-bisect.md | 72 --- src/docs/gdb-jit.md | 65 --- src/docs/gdb.md | 40 -- src/docs/hidden-classes.md | 233 -------- src/docs/i18n.md | 39 -- src/docs/ide-setup.md | 95 ---- src/docs/ignition.md | 20 - src/docs/index.md | 79 --- src/docs/inspector.md | 70 --- src/docs/linux-perf.md | 167 ------ src/docs/memory-leaks.md | 53 -- src/docs/merge-patch.md | 81 --- src/docs/node-integration.md | 71 --- src/docs/official-support.md | 22 - src/docs/ports.md | 29 - src/docs/profile-chromium.md | 59 -- src/docs/profile.md | 172 ------ src/docs/rcs.md | 64 --- src/docs/release-process.md | 68 --- src/docs/respectful-code.md | 53 -- src/docs/security-bugs.md | 8 - src/docs/source-code.md | 162 ------ src/docs/stack-trace-api.md | 190 ------- src/docs/test.md | 109 ---- src/docs/torque-builtins.md | 139 ----- src/docs/torque.md | 742 ------------------------- src/docs/trace.md | 46 -- src/docs/triage-issues.md | 35 -- src/docs/turbofan.md | 47 -- src/docs/untrusted-code-mitigations.md | 36 -- src/docs/version-numbers.md | 54 -- src/docs/wasm-compilation-pipeline.md | 61 -- src/docs/wasm-shipping-checklist.md | 206 ------- src/docs/webassembly-opcode.md | 437 --------------- sync-docs.mjs | 53 ++ 58 files changed, 64 insertions(+), 6196 deletions(-) delete mode 100644 src/docs/api.md delete mode 100644 src/docs/become-committer.md delete mode 100644 src/docs/benchmarks.md delete mode 100644 src/docs/blink-layout-tests.md delete mode 100644 src/docs/build-gn.md delete mode 100644 src/docs/build.md delete mode 100644 src/docs/builtin-functions.md delete mode 100644 src/docs/committer-responsibility.md delete mode 100644 src/docs/compile-arm64.md delete mode 100644 src/docs/contribute.md delete mode 100644 src/docs/cross-compile-arm.md delete mode 100644 src/docs/cross-compile-ios.md delete mode 100644 src/docs/csa-builtins.md delete mode 100644 src/docs/d8.md delete mode 100644 src/docs/debug-arm.md delete mode 100644 src/docs/design-review-guidelines.md delete mode 100644 src/docs/embed.md delete mode 100644 src/docs/evaluate-code-coverage.md delete mode 100644 src/docs/feature-launch-process.md delete mode 100644 src/docs/flake-bisect.md delete mode 100644 src/docs/gdb-jit.md delete mode 100644 src/docs/gdb.md delete mode 100644 src/docs/hidden-classes.md delete mode 100644 src/docs/i18n.md delete mode 100644 src/docs/ide-setup.md delete mode 100644 src/docs/ignition.md delete mode 100644 src/docs/index.md delete mode 100644 src/docs/inspector.md delete mode 100644 src/docs/linux-perf.md delete mode 100644 src/docs/memory-leaks.md delete mode 100644 src/docs/merge-patch.md delete mode 100644 src/docs/node-integration.md delete mode 100644 src/docs/official-support.md delete mode 100644 src/docs/ports.md delete mode 100644 src/docs/profile-chromium.md delete mode 100644 src/docs/profile.md delete mode 100644 src/docs/rcs.md delete mode 100644 src/docs/release-process.md delete mode 100644 src/docs/respectful-code.md delete mode 100644 src/docs/security-bugs.md delete mode 100644 src/docs/source-code.md delete mode 100644 src/docs/stack-trace-api.md delete mode 100644 src/docs/test.md delete mode 100644 src/docs/torque-builtins.md delete mode 100644 src/docs/torque.md delete mode 100644 src/docs/trace.md delete mode 100644 src/docs/triage-issues.md delete mode 100644 src/docs/turbofan.md delete mode 100644 src/docs/untrusted-code-mitigations.md delete mode 100644 src/docs/version-numbers.md delete mode 100644 src/docs/wasm-compilation-pipeline.md delete mode 100644 src/docs/wasm-shipping-checklist.md delete mode 100644 src/docs/webassembly-opcode.md create mode 100644 sync-docs.mjs diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 40408daab..467985e20 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -15,6 +15,8 @@ jobs: with: node-version-file: '.nvmrc' - run: npm install + - name: Sync V8 docs + run: npm run sync-docs - run: npm run lint - run: npm run build - uses: FirebaseExtended/action-hosting-deploy@v0 diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index 4255bc23e..7b56ab666 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -17,6 +17,8 @@ jobs: with: node-version-file: '.nvmrc' - run: npm install + - name: Sync V8 docs + run: npm run sync-docs - run: npm run lint - run: npm run build - uses: FirebaseExtended/action-hosting-deploy@v0 diff --git a/.gitignore b/.gitignore index 8b70d746a..8aaf4baa9 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,7 @@ package-lock.json Desktop.ini ._* Thumbs.db +# Ignore synced docs +/src/docs/* +!/src/docs/docs.json +!/src/docs/README_V8_DEV.md diff --git a/package.json b/package.json index 6dbd936bd..de0f1ae0e 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,9 @@ "copy-js": "shx cp ./node_modules/dark-mode-toggle/dist/dark-mode-toggle.min.mjs dist/_js/dark-mode-toggle.mjs", "img-video-dimensions": "node add-image-and-video-dimensions.js", "clean": "shx rm -rf -- dist", - "build": "npm run clean && npm run css && npm run js && npm run json && npm run copy-img && npm run copy-js && npm run eleventy && npm run sw && npm run xml && npm run html", - "watch": "npm run build && npx eleventy --watch", + "sync-docs": "node sync-docs.mjs", + "build": "npm run clean && npm run sync-docs && npm run css && npm run js && npm run json && npm run copy-img && npm run copy-js && npm run eleventy && npm run sw && npm run xml && npm run html", + "watch": "npm run sync-docs && npm run build && npx eleventy --watch", "serve": "npm start", "dev": "npm start", "debug": "DEBUG=* npx eleventy", diff --git a/src/docs/api.md b/src/docs/api.md deleted file mode 100644 index cdfa291f8..000000000 --- a/src/docs/api.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: 'V8’s public API' -description: 'This document discusses the stability of V8’s public API, and how developers can make changes to it.' ---- -This document discusses the stability of V8’s public API, and how developers can make changes to it. - -## API stability - -If V8 in a Chromium canary turns out to be crashy, it gets rolled back to the V8 version of the previous canary. It is therefore important to keep V8’s API compatible from one canary version to the next. - -We continuously run a [bot](https://ci.chromium.org/p/v8/builders/luci.v8.ci/Linux%20V8%20API%20Stability) that signals API stability violations. It compiles Chromium’s HEAD with V8’s [current canary version](https://chromium.googlesource.com/v8/v8/+/refs/heads/canary). - -Failures of this bot are currently only FYI and no action is required. The blame list can be used to easily identify dependent CLs in case of a rollback. - -If you break this bot, be reminded to increase the window between a V8 change and a dependent Chromium change next time. - -## How to change V8’s public API - -V8 is used by many different embedders: Chrome, Node.js, gjstest, etc. When changing V8’s public API (basically the files under the `include/` directory) we need to ensure that the embedders can smoothly update to the new V8 version. In particular, we cannot assume that an embedder updates to the new V8 version and adjusts their code to the new API in one atomic change. - -The embedder should be able to adjust their code to the new API while still using the previous version of V8. All instructions below follow from this rule. - -- Adding new types, constants, and functions is safe with one caveat: do not add a new pure virtual function to an existing class. New virtual functions should have default implementation. -- Adding a new parameter to a function is safe if the parameter has the default value. -- Removing or renaming types, constants, functions is unsafe. Use the [`V8_DEPRECATED`](https://cs.chromium.org/chromium/src/v8/include/v8config.h?l=395&rcl=0425b20ad9a8ba38c2e0dd16e8814abb722bfdde) and [`V8_DEPRECATE_SOON`](https://cs.chromium.org/chromium/src/v8/include/v8config.h?l=403&rcl=0425b20ad9a8ba38c2e0dd16e8814abb722bfdde) macros, which causes compile-time warnings when the deprecated methods are called by the embedder. For example, let’s say we want to rename function `foo` to function `bar`. Then we need to do the following: - - Add the new function `bar` near the existing function `foo`. - - Wait until the CL rolls in Chrome. Adjust Chrome to use `bar`. - - Annotate `foo` with `V8_DEPRECATED("Use bar instead") void foo();` - - In the same CL adjust the tests that use `foo` to use `bar`. - - Write in CL motivation for the change and high-level update instructions. - - Wait until the next V8 branch. - - Remove function `foo`. - - `V8_DEPRECATE_SOON` is a softer version of `V8_DEPRECATED`. Chrome will not break with it, so step b is not need. `V8_DEPRECATE_SOON` is not sufficient for removing the function. - - You still need to annotate with `V8_DEPRECATED` and wait for the next branch before removing the function. - - `V8_DEPRECATED` can be tested using the `v8_deprecation_warnings` GN flag. - `V8_DEPRECATE_SOON` can be tested using `v8_imminent_deprecation_warnings`. - -- Changing function signatures is unsafe. Use the `V8_DEPRECATED` and `V8_DEPRECATE_SOON` macros as described above. - -We maintain a [document mentioning important API changes](https://docs.google.com/document/d/1g8JFi8T_oAE_7uAri7Njtig7fKaPDfotU6huOa1alds/edit) for each V8 version. - -There is also a regularly updated [doxygen api documentation](https://v8.dev/api). diff --git a/src/docs/become-committer.md b/src/docs/become-committer.md deleted file mode 100644 index 9e6218443..000000000 --- a/src/docs/become-committer.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: 'Becoming a committer' -description: 'How does one become a V8 committer? This document explains.' ---- -Technically, committers are people who have write access to the V8 repository. All patches need to be reviewed by at least two committers (including the author). Independently from this requirement, patches also need to be authored or reviewed by an OWNER. - -This privilege is granted with some expectation of responsibility: committers are people who care about the V8 project and want to help meet its goals. Committers are not just people who can make changes, but people who have demonstrated their ability to collaborate with the team, get the most knowledgeable people to review code, contribute high-quality code, and follow through to fix issues (in code or tests). - -A committer is a contributor to the V8 project’s success and a citizen helping the projects succeed. See [Committer’s Responsibility](/docs/committer-responsibility). - -## How do I become a committer? - -*Note to Googlers: There is a [slightly different approach for V8 team members](http://go/v8/setup_permissions.md).* - -If you haven't done so already, **you'll need to set up a Security Key on your account before you're added to the committer list.**. For more information about this requirement see [Gerrit ReAuth](https://chromium.googlesource.com/chromium/src/+/main/docs/gerrit_reauth.md). - -In a nutshell, contribute 20 non-trivial patches and get at least three different people to review them (you'll need three people to support you). Then ask someone to nominate you. You're demonstrating your: - -- commitment to the project (20 good patches requires a lot of your valuable time), -- ability to collaborate with the team, -- understanding of how the team works (policies, processes for testing and code review, etc), -- understanding of the projects' code base and coding style, and -- ability to write good code (last but certainly not least) - -A current committer nominates you by sending email to containing: - -- your first and last name -- your email address in Gerrit -- an explanation of why you should be a committer, -- embedded list of links to revisions (about top 10) containing your patches - -Two other committers need to second your nomination. If no one objects in 5 working days, you're a committer. If anyone objects or wants more information, the committers discuss and usually come to a consensus (within the 5 working days). If issues cannot be resolved, there's a vote among current committers. - -Once you get approval from the existing committers, you are granted additional review permissions. You'll also be added to the mailing list v8-committers@chromium.org. - -In the worst case, the process can drag out for two weeks. Keep writing patches! Even in the rare cases where a nomination fails, the objection is usually something easy to address like “more patches” or “not enough people are familiar with this person’s work.” - -## Maintaining committer status - -You don't really need to do much to maintain committer status: just keep being awesome and helping the V8 project! - -In the unhappy event that a committer continues to disregard good citizenship (or actively disrupts the project), we may need to revoke that person's status. The process is the same as for nominating a new committer: someone suggests the revocation with a good reason, two people second the motion, and a vote may be called if consensus cannot be reached. I hope that's simple enough, and that we never have to test it in practice. - -In addition, as a security measure, if you are inactive on Gerrit (no upload, no comment and no review) for more than a year, we may revoke your committer privileges. An email notification is sent about 7 days prior to the removal. This is not meant as a punishment, so if you wish to resume contributing after that, contact v8-committers@chromium.org to ask that it be restored, and we will normally do so. - -(This document was inspired by .) diff --git a/src/docs/benchmarks.md b/src/docs/benchmarks.md deleted file mode 100644 index a69827f5a..000000000 --- a/src/docs/benchmarks.md +++ /dev/null @@ -1,140 +0,0 @@ ---- -title: 'Running benchmarks locally' -description: 'This document explains how to run classic benchmark suites in d8.' ---- -We have a simple workflow for running the “classic” benchmarks of SunSpider, Kraken and Octane. You can run with different binaries and flag combinations, and results are averaged over multiple runs. - -## CPU - -Build the `d8` shell following the instructions at [Building with GN](/docs/build-gn). - -Before you run benchmarks, make sure you set your CPU frequency scaling governor to performance. - -```bash -sudo tools/cpu.sh fast -``` - -The commands `cpu.sh` understands are - -- `fast`, performance (alias for `fast`) -- `slow`, powersave (alias for `slow`) -- `default`, ondemand (alias for `default`) -- `dualcore` (disables all but two cores), dual (alias for `dualcore`) -- `allcores` (re-enables all available cores), all (alias for `allcores`). - -## CSuite - -`CSuite` is our simple benchmark runner: - -```bash -test/benchmarks/csuite/csuite.py - (sunspider | kraken | octane) - (baseline | compare) - - [-x ""] -``` - -First run in `baseline` mode to create the baselines, then in `compare` mode to get results. `CSuite` defaults to doing 10 runs for Octane, 100 for SunSpider, and 80 for Kraken, but you can override these for quicker results with the `-r` option. - -`CSuite` creates two subdirectories in the directory where you run from: - -1. `./_benchmark_runner_data` — this is cached output from the N runs. -1. `./_results` — it writes the results into file master here. You could save these - files with different names, and they’ll show up in compare mode. - -In compare mode, you’ll naturally use a different binary or at least different flags. - -## Example usage - -Say you’ve built two versions of `d8`, and want to see what happens to SunSpider. First, create baselines: - -```bash -$ test/benchmarks/csuite/csuite.py sunspider baseline out.gn/master/d8 -Wrote ./_results/master. -Run sunspider again with compare mode to see results. -``` - -As suggested, run again but this time in `compare` mode with a different binary: - -``` -$ test/benchmarks/csuite/csuite.py sunspider compare out.gn/x64.release/d8 - - benchmark: score | master | % | -===================================================+==========+========+ - 3d-cube-sunspider: 13.9 S 13.4 S -3.6 | - 3d-morph-sunspider: 8.6 S 8.4 S -2.3 | - 3d-raytrace-sunspider: 15.1 S 14.9 S -1.3 | - access-binary-trees-sunspider: 3.7 S 3.9 S 5.4 | - access-fannkuch-sunspider: 11.9 S 11.8 S -0.8 | - access-nbody-sunspider: 4.6 S 4.8 S 4.3 | - access-nsieve-sunspider: 8.4 S 8.1 S -3.6 | - bitops-3bit-bits-in-byte-sunspider: 2.0 | 2.0 | | - bitops-bits-in-byte-sunspider: 3.7 S 3.9 S 5.4 | - bitops-bitwise-and-sunspider: 2.7 S 2.9 S 7.4 | - bitops-nsieve-bits-sunspider: 5.3 S 5.6 S 5.7 | - controlflow-recursive-sunspider: 3.8 S 3.6 S -5.3 | - crypto-aes-sunspider: 10.9 S 9.8 S -10.1 | - crypto-md5-sunspider: 7.0 | 7.4 S 5.7 | - crypto-sha1-sunspider: 9.2 S 9.0 S -2.2 | - date-format-tofte-sunspider: 9.8 S 9.9 S 1.0 | - date-format-xparb-sunspider: 10.3 S 10.3 S | - math-cordic-sunspider: 6.1 S 6.2 S 1.6 | - math-partial-sums-sunspider: 20.2 S 20.1 S -0.5 | - math-spectral-norm-sunspider: 3.2 S 3.0 S -6.2 | - regexp-dna-sunspider: 7.6 S 7.8 S 2.6 | - string-base64-sunspider: 14.2 S 14.0 | -1.4 | - string-fasta-sunspider: 12.8 S 12.6 S -1.6 | - string-tagcloud-sunspider: 18.2 S 18.2 S | - string-unpack-code-sunspider: 20.0 | 20.1 S 0.5 | - string-validate-input-sunspider: 9.4 S 9.4 S | - SunSpider: 242.6 S 241.1 S -0.6 | ----------------------------------------------------+----------+--------+ -``` - -The output of the previous run is cached in a subdirectory created in the current directory (`_benchmark_runner_data`). The aggregate results are also cached, in directory `_results`. These directories can be deleted after you’ve run the compare step. - -Another situation is when you have the same binary, but want to see the results of different flags. Feeling rather droll, you’d like to see how Octane performs without an optimizing compiler. First the baseline: - -```bash -$ test/benchmarks/csuite/csuite.py -r 1 octane baseline out.gn/x64.release/d8 - -Normally, octane requires 10 runs to get stable results. -Wrote /usr/local/google/home/mvstanton/src/v8/_results/master. -Run octane again with compare mode to see results. -``` - -Note the warning that one run usually isn’t enough to be sure of many performance optimizations, however, our “change” should have a reproducible effect with only one run! Now let’s compare, passing the `--noopt` flag to turn off [TurboFan](/docs/turbofan): - -```bash -$ test/benchmarks/csuite/csuite.py -r 1 octane compare out.gn/x64.release/d8 \ - -x "--noopt" - -Normally, octane requires 10 runs to get stable results. - benchmark: score | master | % | -===================================================+==========+========+ - Richards: 973.0 | 26770.0 | -96.4 | - DeltaBlue: 1070.0 | 57245.0 | -98.1 | - Crypto: 923.0 | 32550.0 | -97.2 | - RayTrace: 2896.0 | 75035.0 | -96.1 | - EarleyBoyer: 4363.0 | 42779.0 | -89.8 | - RegExp: 2881.0 | 6611.0 | -56.4 | - Splay: 4241.0 | 19489.0 | -78.2 | - SplayLatency: 14094.0 | 57192.0 | -75.4 | - NavierStokes: 1308.0 | 39208.0 | -96.7 | - PdfJS: 6385.0 | 26645.0 | -76.0 | - Mandreel: 709.0 | 33166.0 | -97.9 | - MandreelLatency: 5407.0 | 97749.0 | -94.5 | - Gameboy: 5440.0 | 54336.0 | -90.0 | - CodeLoad: 25631.0 | 25282.0 | 1.4 | - Box2D: 3288.0 | 67572.0 | -95.1 | - zlib: 59154.0 | 58775.0 | 0.6 | - Typescript: 12700.0 | 23310.0 | -45.5 | - Octane: 4070.0 | 37234.0 | -89.1 | ----------------------------------------------------+----------+--------+ -``` - -Neat to see that `CodeLoad` and `zlib` were relatively unharmed. - -## Under the hood - -`CSuite` is based on two scripts in the same directory, `benchmark.py` and `compare-baseline.py`. There are more options in those scripts. For example, you can record multiple baselines and do 3-, 4-, or 5-way comparisons. `CSuite` is optimized for quick use, and sacrifices some flexibility. diff --git a/src/docs/blink-layout-tests.md b/src/docs/blink-layout-tests.md deleted file mode 100644 index e08e4823e..000000000 --- a/src/docs/blink-layout-tests.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: 'Blink web tests (a.k.a. layout tests)' -description: 'V8’s infrastructure continuously runs Blink’s web tests to prevent integration problems with Chromium. This document describes what to do in case such a test fails.' ---- -We continuously run [Blink’s web tests (formerly known as “layout tests”)](https://chromium.googlesource.com/chromium/src/+/master/docs/testing/web_tests.md) on our [integration console](https://ci.chromium.org/p/v8/g/integration/console) to prevent integration problems with Chromium. - -On test failures, the bots compare the results of V8 Tip-of-Tree with Chromium’s pinned V8 version, to only flag newly introduced V8 problems (with false positives < 5%). Blame assignment is trivial as the [Linux release](https://ci.chromium.org/p/v8/builders/luci.v8.ci/V8%20Blink%20Linux) bot tests all revisions. - -Commits with newly-introduced failures are normally reverted to unblock auto-rolling into Chromium. In case you notice you break layout tests or your commit gets reverted because of such breakage, and in case the changes are expected, follow this procedure to add updated baselines to Chromium before (re-)landing your CL: - -1. Land a Chromium change setting `[ Failure Pass ]` for the changed tests ([more](https://chromium.googlesource.com/chromium/src/+/master/docs/testing/web_test_expectations.md#updating-the-expectations-files)). -1. Land your V8 CL and wait 1-2 days until it cycles into Chromium. -1. Follow [these instructions](https://chromium.googlesource.com/chromium/src/+/master/docs/testing/web_tests.md#Rebaselining-Web-Tests) to manually generate the new baselines. Note that if you’re making changes only to Chromium, [this preferred automatic procedure](https://chromium.googlesource.com/chromium/src/+/master/docs/testing/web_test_expectations.md#how-to-rebaseline) should work for you. -1. Remove the `[ Failure Pass ]` entry from the test expectations file and commit it along with the new baselines in Chromium. - -Please associate all CLs with a `Bug: …` footer. diff --git a/src/docs/build-gn.md b/src/docs/build-gn.md deleted file mode 100644 index 8464d7d01..000000000 --- a/src/docs/build-gn.md +++ /dev/null @@ -1,134 +0,0 @@ ---- -title: 'Building V8 with GN' -description: 'This document explains how to use GN to build V8.' ---- -V8 is built with the help of [GN](https://gn.googlesource.com/gn/+/master/docs/). GN is a meta build system of sorts, as it generates build files for a number of other build systems. How you build therefore depends on what “back-end” build system and compiler you’re using. -The instructions below assume that you already have a [checkout of V8](/docs/source-code) and that you have [installed the build dependencies](/docs/build). - -More information on GN can be found in [Chromium’s documentation](https://www.chromium.org/developers/gn-build-configuration) or [GN’s own docs](https://gn.googlesource.com/gn/+/master/docs/). - -Building V8 from source involves three steps: - -1. generating build files -1. compiling -1. running tests - -There are two workflows for building V8: - -- the convenience workflow using a helper script called `gm` that nicely combines all three steps -- the raw workflow, where you run separate commands on a lower level for each step manually - -## Building V8 using `gm` (the convenience workflow) { #gm } - -`gm` is a convenience all-in-one script that generates build files, triggers the build and optionally also runs the tests. It can be found at `tools/dev/gm.py` in your V8 checkout. We recommend adding an alias to your shell configuration: - -```bash -alias gm=/path/to/v8/tools/dev/gm.py -``` - -You can then use `gm` to build V8 for known configurations, such as `x64.release`: - -```bash -gm x64.release -``` - -To run the tests right after the build, run: - -```bash -gm x64.release.check -``` - -`gm` outputs all the commands it’s executing, making it easy to track and re-execute them if necessary. - -`gm` enables building the required binaries and running specific tests with a single command: - -```bash -gm x64.debug mjsunit/foo cctest/test-bar/* -``` - -## Building V8: the raw, manual workflow { #manual } - -### Step 1: generate build files { #generate-build-files } - -There are several ways of generating the build files: - -1. The raw, manual workflow involves using `gn` directly. -1. A helper script named `v8gen` streamlines the process for common configurations. - -#### Generating build files using `gn` { #gn } - -Generate build files for the directory `out/foo` using `gn`: - -```bash -gn args out/foo -``` - -This opens an editor window for specifying the [`gn` arguments](https://gn.googlesource.com/gn/+/master/docs/reference.md). Alternatively, you can pass the arguments on the command line: - -```bash -gn gen out/foo --args='is_debug=false target_cpu="x64" v8_target_cpu="arm64"' -``` - -This generates build files for compiling V8 with the arm64 simulator in release mode. - -For an overview of all available `gn` arguments, run: - -```bash -gn args out/foo --list -``` - -#### Generate build files using `v8gen` { #v8gen } - -The V8 repository includes a `v8gen` convenience script to more easily generate build files for common configurations. We recommend adding an alias to your shell configuration: - -```bash -alias v8gen=/path/to/v8/tools/dev/v8gen.py -``` - -Call `v8gen --help` for more information. - -List available configurations (or bots from a master): - -```bash -v8gen list -``` - -```bash -v8gen list -m client.v8 -``` - -Build like a particular bot from the `client.v8` waterfall in folder `foo`: - -```bash -v8gen -b 'V8 Linux64 - debug builder' -m client.v8 foo -``` - -### Step 2: compile V8 { #compile } - -To build all of V8 (assuming `gn` generated to the `x64.release` folder), run: - -```bash -ninja -C out/x64.release -``` - -To build specific targets like `d8`, append them to the command: - -```bash -ninja -C out/x64.release d8 -``` - -### Step 3: run tests { #tests } - -You can pass the output directory to the test driver. Other relevant flags are inferred from the build: - -```bash -tools/run-tests.py --outdir out/foo -``` - -You can also test your most recently compiled build (in `out.gn`): - -```bash -tools/run-tests.py --gn -``` - -**Build issues? File a bug at [v8.dev/bug](/bug) or ask for help on .** diff --git a/src/docs/build.md b/src/docs/build.md deleted file mode 100644 index 50ae91996..000000000 --- a/src/docs/build.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: 'Building V8 from source' -description: 'This document explains how to build V8 from source.' ---- -In order to be able to build V8 from scratch on Windows/Linux/macOS for x64, please follow the following steps. - -## Getting the V8 source code - -Follow the instructions in our guide on [checking out the V8 source code](/docs/source-code). - -## Installing build dependencies - -1. For macOS: install Xcode and accept its license agreement. (If you’ve installed the command-line tools separately, [remove them first](https://bugs.chromium.org/p/chromium/issues/detail?id=729990#c1).) - -1. Make sure that you are in the V8 source directory. If you followed every step in the previous section, you’re already at the right location. - -1. Download all the build dependencies: - - ```bash - gclient sync - ``` - - For Googlers - If you see Failed to fetch file or Login required errors when running the hooks, try authenticating with Google Storage first by running: - - ```bash - gsutil.py config - ``` - - Login with your @google.com account, and enter `0` when asked for a project ID. - -1. This step is only needed on Linux. Install additional build dependencies: - - ```bash - ./build/install-build-deps.sh - ``` - -## Building V8 - -1. Make sure that you are in the V8 source directory on the `main` branch. - - ```bash - cd /path/to/v8 - ``` - -1. Pull in the latest changes and install any new build dependencies: - - ```bash - git pull && gclient sync - ``` - -1. Compile the source: - - ```bash - tools/dev/gm.py x64.release - ``` - - Or, to compile the source and immediately run the tests: - - ```bash - tools/dev/gm.py x64.release.check - ``` - - For more information on the `gm.py` helper script and the commands it triggers, see [Building with GN](/docs/build-gn). diff --git a/src/docs/builtin-functions.md b/src/docs/builtin-functions.md deleted file mode 100644 index b32df77b1..000000000 --- a/src/docs/builtin-functions.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: 'Built-in functions' -description: 'This document explains what “built-ins” are in V8.' ---- -Built-in functions in V8 come in different flavors w.r.t. implementation, depending on their functionality, performance requirements, and sometimes plain historical development. - -Some are implemented in JavaScript directly, and are compiled into executable code at runtime just like any user JavaScript. Some of them resort to so-called _runtime functions_ for part of their functionality. Runtime functions are written in C++ and called from JavaScript through a `%`-prefix. Usually, these runtime functions are limited to V8 internal JavaScript code. For debugging purposes, they can also be called from normal JavaScript code, if V8 is run with the flag `--allow-natives-syntax`. Some runtime functions are directly embedded by the compiler into generated code. For a list, see `src/runtime/runtime.h`. - -Other functions are implemented as _built-ins_, which themselves can be implemented in a number of different ways. Some are implemented directly in platform-dependent assembly. Some are implemented in _CodeStubAssembler_, a platform-independent abstraction. Yet others are directly implemented in C++. Built-ins are sometimes also used to implement pieces of glue code, not necessarily entire functions. For a list, see `src/builtins/builtins.h`. diff --git a/src/docs/committer-responsibility.md b/src/docs/committer-responsibility.md deleted file mode 100644 index 68e7b4ab8..000000000 --- a/src/docs/committer-responsibility.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: 'Responsibilities of V8 committers and reviewers' -description: 'This document lists guidelines for V8 contributors.' ---- -When you’re committing to the V8 repositories, ensure that you follow these guidelines (adapted from ): - -1. Find the right reviewer for your changes and for patches you’re asked to review. -1. Be available on IM and/or email before and after you land the change. -1. Watch the [waterfall](https://ci.chromium.org/p/v8/g/main/console) until all bots turn green after your change. -1. When landing a TBR change (To Be Reviewed), make sure to notify the people whose code you’re changing. Usually just send the review e-mail. - -In short, do the right thing for the project, not the easiest thing to get code committed, and above all: use your best judgement. - -**Don’t be afraid to ask questions. There is always someone who will immediately read messages sent to the v8-committers mailing list who can help you.** - -## Changes with multiple reviewers - -There are occasionally changes with a lot of reviewers on them, since sometimes several people might need to be in the loop for a change because of multiple areas of responsibility and expertise. - -The problem is that without some guidelines, there’s no clear responsibility given in these reviews. - -If you’re the sole reviewer on a change, you know you have to do a good job. When there are three other people, you sometimes assume that somebody else must have looked carefully at some part of the review. Sometimes all the reviewers think this and the change isn’t reviewed properly. - -In other cases, some reviewers say “LGTM” for a patch, while others are still expecting changes. The author can get confused as to the status of the review, and some patches have been checked in where at least one reviewer expected further changes before committing. - -At the same time, we want to encourage many people to participate in the review process and keep tabs on what’s going on. - -So, here are some guidelines to help clarify the process: - -1. When a patch author requests more than one reviewer, they should make clear in the review request email what they expect the responsibility of each reviewer to be. For example, you could write this in the email: - - ``` - - larry: bitmap changes - - sergey: process hacks - - everybody else: FYI - ``` - -1. In this case, you might be on the review list because you’ve asked to be in the loop for multiprocess changes, but you wouldn’t be the primary reviewer and the author and other reviewers wouldn’t be expecting you to review all the diffs in detail. -1. If you get a review that includes many other people, and the author didn’t do (1), please ask them what part you’re responsible for if you don’t want to review the whole thing in detail. -1. The author should wait for approval from everybody on the reviewer list before checking in. -1. People who are on a review without clear review responsibility (i.e. drive-by reviews) should be super responsive and not hold up the review. The patch author should feel free to ping them mercilessly if they are. -1. If you’re an “FYI” person on a review and you didn’t actually review in detail (or at all), but don’t have a problem with the patch, note this. You could say something like “rubber stamp” or “ACK” instead of “LGTM”. This way the real reviewers know not to trust that you did their work for them, but the author of the patch knows they don’t have to wait for further feedback from you. Hopefully we can still keep everybody in the loop but have clear ownership and detailed reviews. It might even speed up some changes since you can quickly “ACK” changes you don’t care about, and the author knows they don’t have to wait for feedback from you. diff --git a/src/docs/compile-arm64.md b/src/docs/compile-arm64.md deleted file mode 100644 index 57b2ecfb5..000000000 --- a/src/docs/compile-arm64.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: 'Compiling on Arm64 Linux' -description: 'Tips and tricks to build V8 natively on Arm64 Linux' ---- -If you've gone through instructions on how to [check out](/docs/source-code) and [build](/docs/build-gn) V8 on a machine that is neither x86 nor an Apple Silicon Mac, you may have ran into a bit of trouble, due to the build system downloading native binaries and then not being able to run them. However, even though using an Arm64 Linux machine to work on V8 is __not officially supported__, overcoming those hurdles is pretty straightforward. - -## Bypassing `vpython` - -`fetch v8`, `gclient sync` and other `depot_tools` commands use a wrapper for python called "vpython". If you see errors related to it, you can define the following variable to use the system's python installation instead: - -```bash -export VPYTHON_BYPASS="manually managed python not supported by chrome operations" -``` - -## Compatible `ninja` binary - -The first thing to do is to make sure we use a native binary for `ninja`, which we pick instead of the one in `depot_tools`. A simple way to do this is to tweak your PATH as follows when installing `depot_tools`: - -```bash -export PATH=$PATH:/path/to/depot_tools -``` - -This way, you'll be able to use your system's `ninja` installation, given it's likely to be available. Although if it isn't you can [build it from source](https://github.com/ninja-build/ninja#building-ninja-itself). - -## Compiling clang - -By default, V8 will want to use its own build of clang that may not run on your machine. You could tweak GN arguments in order to [use the system's clang or GCC](#system_clang_gcc), however, you may want to use the same clang as upstream, as it will be the most supported version. - -You can build it locally directly from the V8 checkout: - -```bash -./tools/clang/scripts/build.py --without-android --without-fuchsia \ - --host-cc=gcc --host-cxx=g++ \ - --gcc-toolchain=/usr \ - --use-system-cmake --disable-asserts -``` - -## Setting up GN arguments manually - -Convenience scripts may not work by default, instead you'll have to set GN arguments manually following the [manual](/docs/build-gn#gn) workflow. You can get the usual "release", "optdebug" and "debug" configurations with the following arguments: - -- `release` - -```bash -is_debug=false -``` - -- `optdebug` - -```bash -is_debug=true -v8_enable_backtrace=true -v8_enable_slow_dchecks=true -``` - -- `debug` - -```bash -is_debug=true -v8_enable_backtrace=true -v8_enable_slow_dchecks=true -v8_optimized_debug=false -``` - -## Using the system's clang or GCC { #system_clang_gcc } - -Building with GCC is only a case of disabling compiling with clang: - -```bash -is_clang=false -``` - -Note that by default, V8 will link using `lld`, which requires a recent version of GCC. You can use `use_lld=false` to switch to the gold linker, or additionally use `use_gold=false` to use `ld`. - -If you'd like to use the clang that's installed with your system, say in `/usr`, you can use the following arguments: - -```bash -clang_base_path="/usr" -clang_use_chrome_plugins=false -``` - -However, given the system's clang version may not be well supported, you're likely to deal with warnings, such as unknown compiler flags. In this case it's useful to stop treating warnings as errors with: - -```bash -treat_warnings_as_errors=false -``` diff --git a/src/docs/contribute.md b/src/docs/contribute.md deleted file mode 100644 index 7e37776ad..000000000 --- a/src/docs/contribute.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: 'Contributing to V8' -description: 'This document explains how to contribute to V8.' ---- -The information on this page explains how to contribute to V8. Be sure to read the whole thing before sending us a contribution. - -## Get the code - -See [Checking out the V8 source code](/docs/source-code). - -## Before you contribute - -### Ask on V8’s mailing list for guidance - -Before you start working on a larger V8 contribution, you should get in touch with us first through [the V8 contributor mailing list](https://groups.google.com/group/v8-dev) so we can help out and possibly guide you. Coordinating up front makes it much easier to avoid frustration later on. - -### Sign the CLA - -Before we can use your code you have to sign the [Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual), which you can do online. This is mainly because you own the copyright to your changes, even after your contribution becomes part of our codebase, so we need your permission to use and distribute your code. We also need to be sure of various other things, for instance that you’ll tell us if you know that your code infringes on other people’s patents. You don’t have to do this until after you’ve submitted your code for review and a member has approved it, but you will have to do it before we can put your code into our codebase. - -Contributions made by corporations are covered by a different agreement than the one above, the [Software Grant and Corporate Contributor License Agreement](https://cla.developers.google.com/about/google-corporate). - -Sign them online [here](https://cla.developers.google.com/). - -## Submit your code - -The source code of V8 follows the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) so you should familiarize yourself with those guidelines. Before submitting code you must pass all our [tests](/docs/test), and have to successfully run the presubmit checks: - -```bash -git cl presubmit -``` - -The presubmit script uses a linter from Google, [`cpplint.py`](https://raw.githubusercontent.com/google/styleguide/gh-pages/cpplint/cpplint.py). It is part of [`depot_tools`](https://dev.chromium.org/developers/how-tos/install-depot-tools), and it must be in your `PATH` — so if you have `depot_tools` in your `PATH`, everything should just work. - -### Upload to V8’s codereview tool - -All submissions, including submissions by project members, require review. We use the same code-review tools and process as the Chromium project. In order to submit a patch, you need to get the [`depot_tools`](https://dev.chromium.org/developers/how-tos/install-depot-tools) and follow these instructions on [requesting a review](https://chromium.googlesource.com/chromium/src/+/master/docs/contributing.md) (using your V8 workspace instead of a Chromium workspace). - -### Look out for breakage or regressions - -Once you have codereview approval, you can land your patch using the commit queue. It runs a bunch of tests and commits your patch if all tests pass. Once your change is committed, it is a good idea to watch [the console](https://ci.chromium.org/p/v8/g/main/console) until the bots turn green after your change, because the console runs a few more tests than the commit queue. diff --git a/src/docs/cross-compile-arm.md b/src/docs/cross-compile-arm.md deleted file mode 100644 index f5d0622b9..000000000 --- a/src/docs/cross-compile-arm.md +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: 'Cross-compiling and debugging for ARM/Android' -description: 'This document explains how to cross-compile V8 for ARM/Android, and how to debug it.' ---- -First, make sure you can [build with GN](/docs/build-gn). - -Then, add `android` to your `.gclient` configuration file. - -```python -target_os = ['android'] # Add this to get Android stuff checked out. -``` - -The `target_os` field is a list, so if you're also building on unix it'll look like this: - -```python -target_os = ['android', 'unix'] # Multiple target OSes. -``` - -Run `gclient sync`, and you’ll get a large checkout under `./third_party/android_tools`. - -Enable developer mode on your phone or tablet, and turn on USB debugging, via instructions [here](https://developer.android.com/studio/run/device.html). Also, get the handy [`adb`](https://developer.android.com/studio/command-line/adb.html) tool on your path. It’s in your checkout at `./third_party/android_sdk/public/platform-tools`. - -## Using `gm` - -Use [the `tools/dev/gm.py` script](/docs/build-gn#gm) to automatically build V8 tests and run them on the device. - -```bash -alias gm=/path/to/v8/tools/dev/gm.py -gm android_arm.release.check -``` - -This command pushes the binaries and tests to the `/data/local/tmp/v8` directory on the device. - -## Manual build - -Use `v8gen.py` to generate an ARM release or debug build: - -```bash -tools/dev/v8gen.py arm.release -``` - -Then run `gn args out.gn/arm.release` and make sure you have the following keys: - -```python -target_os = "android" # These lines need to be changed manually -target_cpu = "arm" # as v8gen.py assumes a simulator build. -v8_target_cpu = "arm" -is_component_build = false -``` - -The keys should be the same for debug builds. If you are building for an arm64 device like the Pixel C, which supports 32bit and 64bit binaries, the keys should look like this: - -```python -target_os = "android" # These lines need to be changed manually -target_cpu = "arm64" # as v8gen.py assumes a simulator build. -v8_target_cpu = "arm64" -is_component_build = false -``` - -Now build: - -```bash -ninja -C out.gn/arm.release d8 -``` - -Use `adb` to copy the binary and snapshot files to the phone: - -```bash -adb shell 'mkdir -p /data/local/tmp/v8/bin' -adb push out.gn/arm.release/d8 /data/local/tmp/v8/bin -adb push out.gn/arm.release/icudtl.dat /data/local/tmp/v8/bin -adb push out.gn/arm.release/snapshot_blob.bin /data/local/tmp/v8/bin -``` - -```bash -rebuffat:~/src/v8$ adb shell -bullhead:/ $ cd /data/local/tmp/v8/bin -bullhead:/data/local/tmp/v8/bin $ ls -v8 icudtl.dat snapshot_blob.bin -bullhead:/data/local/tmp/v8/bin $ ./d8 -V8 version 5.8.0 (candidate) -d8> 'w00t!' -"w00t!" -d8> -``` - -## Debugging - -### d8 - -Remote debugging `d8` on an Android device is relatively simple. First start `gdbserver` on the Android device: - -```bash -bullhead:/data/local/tmp/v8/bin $ gdbserver :5039 $D8 -``` - -Then connect to the server on your host device. - -```bash -adb forward tcp:5039 tcp:5039 -gdb $D8 -gdb> target remote :5039 -``` - -`gdb` and `gdbserver` need to be compatible with each other, if in doubt use the binaries from the [Android NDK](https://developer.android.com/ndk). Note that by default the `d8` binary is stripped (debugging info removed), `$OUT_DIR/exe.unstripped/d8` contains the unstripped binary though. - -### Logging - -By default, some of `d8`’s debugging output ends up in the Android system log, which can be dumped using [`logcat`](https://developer.android.com/studio/command-line/logcat). Unfortunately, sometimes part of a particular debugging output is split between system log and `adb`, and sometimes some part seems to be completely missing. To avoid these issues, it is recommended to add the following setting to the `gn args`: - -```python -v8_android_log_stdout = true -``` - -### Floating-point issues - -The `gn args` setting `arm_float_abi = "hard"`, which is used by the V8 Arm GC Stress bot, can result in completely nonsensical program behavior on hardware different from the one the GC stress bot is using (e.g. on Nexus 7). - -## Using Sourcery G++ Lite - -The Sourcery G++ Lite cross compiler suite is a free version of Sourcery G++ from [CodeSourcery](http://www.codesourcery.com/). There is a page for the [GNU Toolchain for ARM Processors](http://www.codesourcery.com/sgpp/lite/arm). Determine the version you need for your host/target combination. - -The following instructions use [2009q1-203 for ARM GNU/Linux](http://www.codesourcery.com/sgpp/lite/arm/portal/release858), and if using a different version please change the URLs and `TOOL_PREFIX` below accordingly. - -### Installing on host and target - -The simplest way of setting this up is to install the full Sourcery G++ Lite package on both the host and target at the same location. This will ensure that all the libraries required are available on both sides. If you want to use the default libraries on the host there is no need the install anything on the target. - -The following script installs in `/opt/codesourcery`: - -```bash -#!/bin/sh - -sudo mkdir /opt/codesourcery -cd /opt/codesourcery -sudo chown "$USERNAME" . -chmod g+ws . -umask 2 -wget http://www.codesourcery.com/sgpp/lite/arm/portal/package4571/public/arm-none-linux-gnueabi/arm-2009q1-203-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 -tar -xvf arm-2009q1-203-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 -``` - -## Profile - -- Compile a binary, push it to the device, keep a copy of it on the host: - - ```bash - adb shell cp /data/local/tmp/v8/bin/d8 /data/local/tmp/v8/bin/d8-version.under.test - cp out.gn/arm.release/d8 ./d8-version.under.test - ``` - -- Get a profiling log and copy it to the host: - - ```bash - adb push benchmarks /data/local/tmp - adb shell cd /data/local/tmp/benchmarks; ../v8/bin/d8-version.under.test run.js --prof - adb shell /data/local/tmp/v8/bin/d8-version.under.test benchmark.js --prof - adb pull /data/local/tmp/benchmarks/v8.log ./ - ``` - -- Open `v8.log` in your favorite editor and edit the first line to match the full path of the `d8-version.under.test` binary on your workstation (instead of the `/data/local/tmp/v8/bin/` path it had on the device) - -- Run the tick processor with the host’s `d8` and an appropriate `nm` binary: - - ```bash - cp out/x64.release/d8 . # only required once - cp out/x64.release/natives_blob.bin . # only required once - cp out/x64.release/snapshot_blob.bin . # only required once - tools/linux-tick-processor --nm=$(pwd)/third_party/android_ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-nm - ``` diff --git a/src/docs/cross-compile-ios.md b/src/docs/cross-compile-ios.md deleted file mode 100644 index 5b8ecc68b..000000000 --- a/src/docs/cross-compile-ios.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: 'Cross-compiling for iOS' -description: 'This document explains how to cross-compile V8 for iOS.' ---- -This page serves as a brief introduction to building V8 for iOS targets. - -## Requirements - -- A macOS (OS X) host machine with Xcode installed. -- A 64-bit target iOS device (legacy 32-bit iOS devices are unsupported). -- V8 v7.5 or newer. -- jitless is a hard requirement for iOS (as of Dec. 2020). Therefore please use the flags '--expose_gc --jitless' - -## Initial setup - -Follow [the instructions to build V8](/docs/build). - -Fetch additional tools needed for iOS cross-compilation by adding `target_os` in your `.gclient` configuration file, located in the parent directory of the `v8` source directory: - -```python -# [... other contents of .gclient such as the 'solutions' variable ...] -target_os = ['ios'] -``` - -After updating `.gclient`, run `gclient sync` to download the additional tools. - -## Manual build - -This section shows how to build a monolithic V8 version for use on either a physical iOS device or the Xcode iOS simulator. The output of this build is a `libv8_monolith.a` file that contains all V8 libraries as well as the V8 snapshot. - -Set up GN build files by running `gn args out/release-ios` and inserting the following keys: - -```python -ios_deployment_target = 10 -is_component_build = false -is_debug = false -target_cpu = "arm64" # "x64" for a simulator build. -target_os = "ios" -use_custom_libcxx = false # Use Xcode's libcxx. -v8_enable_i18n_support = false # Produces a smaller binary. -v8_monolithic = true # Enable the v8_monolith target. -v8_use_external_startup_data = false # The snaphot is included in the binary. -v8_enable_pointer_compression = false # Unsupported on iOS. -``` - -Now build: - -```bash -ninja -C out/release-ios v8_monolith -``` - -Finally, add the generated `libv8_monolith.a` file to your Xcode project as a static library. For further documentation on embedding V8 in your application, see [Getting started with embedding V8](/docs/embed). diff --git a/src/docs/csa-builtins.md b/src/docs/csa-builtins.md deleted file mode 100644 index c425f5bbb..000000000 --- a/src/docs/csa-builtins.md +++ /dev/null @@ -1,228 +0,0 @@ ---- -title: 'CodeStubAssembler builtins' -description: 'This document is intended as an introduction to writing CodeStubAssembler builtins, and is targeted towards V8 developers.' ---- -This document is intended as an introduction to writing CodeStubAssembler builtins, and is targeted towards V8 developers. - -:::note -**Note:** [Torque](/docs/torque) replaces CodeStubAssembler as the recommended way to implement new builtins. See [Torque builtins](/docs/torque-builtins) for the Torque version of this guide. -::: - -## Builtins - -In V8, builtins can be seen as chunks of code that are executable by the VM at runtime. A common use case is to implement the functions of builtin objects (such as RegExp or Promise), but builtins can also be used to provide other internal functionality (e.g. as part of the IC system). - -V8’s builtins can be implemented using a number of different methods (each with different trade-offs): - -- **Platform-dependent assembly language**: can be highly efficient, but need manual ports to all platforms and are difficult to maintain. -- **C++**: very similar in style to runtime functions and have access to V8’s powerful runtime functionality, but usually not suited to performance-sensitive areas. -- **JavaScript**: concise and readable code, access to fast intrinsics, but frequent usage of slow runtime calls, subject to unpredictable performance through type pollution, and subtle issues around (complicated and non-obvious) JS semantics. -- **CodeStubAssembler**: provides efficient low-level functionality that is very close to assembly language while remaining platform-independent and preserving readability. - -The remaining document focuses on the latter and give a brief tutorial for developing a simple CodeStubAssembler (CSA) builtin exposed to JavaScript. - -## CodeStubAssembler - -V8’s CodeStubAssembler is a custom, platform-agnostic assembler that provides low-level primitives as a thin abstraction over assembly, but also offers an extensive library of higher-level functionality. - -```cpp -// Low-level: -// Loads the pointer-sized data at addr into value. -Node* addr = /* ... */; -Node* value = Load(MachineType::IntPtr(), addr); - -// And high-level: -// Performs the JS operation ToString(object). -// ToString semantics are specified at https://tc39.es/ecma262/#sec-tostring. -Node* object = /* ... */; -Node* string = ToString(context, object); -``` - -CSA builtins run through part of the TurboFan compilation pipeline (including block scheduling and register allocation, but notably not through optimization passes) which then emits the final executable code. - -## Writing a CodeStubAssembler builtin - -In this section, we will write a simple CSA builtin that takes a single argument, and returns whether it represents the number `42`. The builtin is exposed to JS by installing it on the `Math` object (because we can). - -This example demonstrates: - -- Creating a CSA builtin with JavaScript linkage, which can be called like a JS function. -- Using CSA to implement simple logic: Smi and heap-number handling, conditionals, and calls to TFS builtins. -- Using CSA Variables. -- Installation of the CSA builtin on the `Math` object. - -In case you’d like to follow along locally, the following code is based off revision [7a8d20a7](https://chromium.googlesource.com/v8/v8/+/7a8d20a79f9d5ce6fe589477b09327f3e90bf0e0). - -## Declaring `MathIs42` - -Builtins are declared in the `BUILTIN_LIST_BASE` macro in [`src/builtins/builtins-definitions.h`](https://cs.chromium.org/chromium/src/v8/src/builtins/builtins-definitions.h?q=builtins-definitions.h+package:%5Echromium$&l=1). To create a new CSA builtin with JS linkage and one parameter named `X`: - -```cpp -#define BUILTIN_LIST_BASE(CPP, API, TFJ, TFC, TFS, TFH, ASM, DBG) \ - // […snip…] - TFJ(MathIs42, 1, kX) \ - // […snip…] -``` - -Note that `BUILTIN_LIST_BASE` takes several different macros that denote different builtin kinds (see inline documentation for more details). CSA builtins specifically are split into: - -- **TFJ**: JavaScript linkage. -- **TFS**: Stub linkage. -- **TFC**: Stub linkage builtin requiring a custom interface descriptor (e.g. if arguments are untagged or need to be passed in specific registers). -- **TFH**: Specialized stub linkage builtin used for IC handlers. - -## Defining `MathIs42` - -Builtin definitions are located in `src/builtins/builtins-*-gen.cc` files, roughly organized by topic. Since we will be writing a `Math` builtin, we’ll put our definition into [`src/builtins/builtins-math-gen.cc`](https://cs.chromium.org/chromium/src/v8/src/builtins/builtins-math-gen.cc?q=builtins-math-gen.cc+package:%5Echromium$&l=1). - -```cpp -// TF_BUILTIN is a convenience macro that creates a new subclass of the given -// assembler behind the scenes. -TF_BUILTIN(MathIs42, MathBuiltinsAssembler) { - // Load the current function context (an implicit argument for every stub) - // and the X argument. Note that we can refer to parameters by the names - // defined in the builtin declaration. - Node* const context = Parameter(Descriptor::kContext); - Node* const x = Parameter(Descriptor::kX); - - // At this point, x can be basically anything - a Smi, a HeapNumber, - // undefined, or any other arbitrary JS object. Let’s call the ToNumber - // builtin to convert x to a number we can use. - // CallBuiltin can be used to conveniently call any CSA builtin. - Node* const number = CallBuiltin(Builtins::kToNumber, context, x); - - // Create a CSA variable to store the resulting value. The type of the - // variable is kTagged since we will only be storing tagged pointers in it. - VARIABLE(var_result, MachineRepresentation::kTagged); - - // We need to define a couple of labels which will be used as jump targets. - Label if_issmi(this), if_isheapnumber(this), out(this); - - // ToNumber always returns a number. We need to distinguish between Smis - // and heap numbers - here, we check whether number is a Smi and conditionally - // jump to the corresponding labels. - Branch(TaggedIsSmi(number), &if_issmi, &if_isheapnumber); - - // Binding a label begins generating code for it. - BIND(&if_issmi); - { - // SelectBooleanConstant returns the JS true/false values depending on - // whether the passed condition is true/false. The result is bound to our - // var_result variable, and we then unconditionally jump to the out label. - var_result.Bind(SelectBooleanConstant(SmiEqual(number, SmiConstant(42)))); - Goto(&out); - } - - BIND(&if_isheapnumber); - { - // ToNumber can only return either a Smi or a heap number. Just to make sure - // we add an assertion here that verifies number is actually a heap number. - CSA_ASSERT(this, IsHeapNumber(number)); - // Heap numbers wrap a floating point value. We need to explicitly extract - // this value, perform a floating point comparison, and again bind - // var_result based on the outcome. - Node* const value = LoadHeapNumberValue(number); - Node* const is_42 = Float64Equal(value, Float64Constant(42)); - var_result.Bind(SelectBooleanConstant(is_42)); - Goto(&out); - } - - BIND(&out); - { - Node* const result = var_result.value(); - CSA_ASSERT(this, IsBoolean(result)); - Return(result); - } -} -``` - -## Attaching `Math.Is42` - -Builtin objects such as `Math` are set up mostly in [`src/bootstrapper.cc`](https://cs.chromium.org/chromium/src/v8/src/bootstrapper.cc?q=src/bootstrapper.cc+package:%5Echromium$&l=1) (with some setup occurring in `.js` files). Attaching our new builtin is simple: - -```cpp -// Existing code to set up Math, included here for clarity. -Handle math = factory->NewJSObject(cons, TENURED); -JSObject::AddProperty(global, name, math, DONT_ENUM); -// […snip…] -SimpleInstallFunction(math, "is42", Builtins::kMathIs42, 1, true); -``` - -Now that `Is42` is attached, it can be called from JS: - -```bash -$ out/debug/d8 -d8> Math.is42(42); -true -d8> Math.is42('42.0'); -true -d8> Math.is42(true); -false -d8> Math.is42({ valueOf: () => 42 }); -true -``` - -## Defining and calling a builtin with stub linkage - -CSA builtins can also be created with stub linkage (instead of JS linkage as we used above in `MathIs42`). Such builtins can be useful to extract commonly-used code into a separate code object that can be used by multiple callers, while the code is only produced once. Let’s extract the code that handles heap numbers into a separate builtin called `MathIsHeapNumber42`, and call it from `MathIs42`. - -Defining and using TFS stubs is easy; declaration are again placed in [`src/builtins/builtins-definitions.h`](https://cs.chromium.org/chromium/src/v8/src/builtins/builtins-definitions.h?q=builtins-definitions.h+package:%5Echromium$&l=1): - -```cpp -#define BUILTIN_LIST_BASE(CPP, API, TFJ, TFC, TFS, TFH, ASM, DBG) \ - // […snip…] - TFS(MathIsHeapNumber42, kX) \ - TFJ(MathIs42, 1, kX) \ - // […snip…] -``` - -Note that currently, order within `BUILTIN_LIST_BASE` does matter. Since `MathIs42` calls `MathIsHeapNumber42`, the former needs to be listed after the latter (this requirement should be lifted at some point). - -The definition is also straightforward. In [`src/builtins/builtins-math-gen.cc`](https://cs.chromium.org/chromium/src/v8/src/builtins/builtins-math-gen.cc?q=builtins-math-gen.cc+package:%5Echromium$&l=1): - -```cpp -// Defining a TFS builtin works exactly the same way as TFJ builtins. -TF_BUILTIN(MathIsHeapNumber42, MathBuiltinsAssembler) { - Node* const x = Parameter(Descriptor::kX); - CSA_ASSERT(this, IsHeapNumber(x)); - Node* const value = LoadHeapNumberValue(x); - Node* const is_42 = Float64Equal(value, Float64Constant(42)); - Return(SelectBooleanConstant(is_42)); -} -``` - -Finally, let’s call our new builtin from `MathIs42`: - -```cpp -TF_BUILTIN(MathIs42, MathBuiltinsAssembler) { - // […snip…] - BIND(&if_isheapnumber); - { - // Instead of handling heap numbers inline, we now call into our new TFS stub. - var_result.Bind(CallBuiltin(Builtins::kMathIsHeapNumber42, context, number)); - Goto(&out); - } - // […snip…] -} -``` - -Why should you care about TFS builtins at all? Why not leave the code inline (or extracted into a helper method for better readability)? - -An important reason is code space: builtins are generated at compile-time and included in the V8 snapshot, thus unconditionally taking up (significant) space in every created isolate. Extracting large chunks of commonly used code to TFS builtins can quickly lead to space savings in the 10s to 100s of KBs. - -## Testing stub-linkage builtins - -Even though our new builtin uses a non-standard (at least non-C++) calling convention, it’s possible to write test cases for it. The following code can be added to [`test/cctest/compiler/test-run-stubs.cc`](https://cs.chromium.org/chromium/src/v8/test/cctest/compiler/test-run-stubs.cc?l=1&rcl=4cab16db27808cf66ab883e7904f1891f9fd0717) to test the builtin on all platforms: - -```cpp -TEST(MathIsHeapNumber42) { - HandleAndZoneScope scope; - Isolate* isolate = scope.main_isolate(); - Heap* heap = isolate->heap(); - Zone* zone = scope.main_zone(); - - StubTester tester(isolate, zone, Builtins::kMathIs42); - Handle result1 = tester.Call(Handle(Smi::FromInt(0), isolate)); - CHECK(result1->BooleanValue()); -} -``` diff --git a/src/docs/d8.md b/src/docs/d8.md deleted file mode 100644 index 29b38eba3..000000000 --- a/src/docs/d8.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: 'Using `d8`' -description: 'd8 is V8’s own developer shell.' ---- -[`d8`](https://source.chromium.org/chromium/chromium/src/+/main:v8/src/d8/) is V8’s own developer shell. - -`d8` is useful for running some JavaScript locally or debugging changes you have made to V8. [Building V8 using GN](/docs/build-gn) for x64 outputs a `d8` binary in `out.gn/x64.optdebug/d8`. You can call `d8` with the `--help` argument for more information about usage and flags. - -## Print to the command line - -Printing output is probably going to be very important if you plan to use `d8` to run JavaScript files rather than interactively. This can be achieved using `console.log`: - -```bash -$ cat test.js -console.log('Hello world!'); - -$ out.gn/x64.optdebug/d8 test.js -Hello world! -``` - -`d8` also comes with a global `print` function that does the same thing. However, `console.log` is preferred over `print` since it works in web browsers as well. - -## Read input - -Using `read()` you can store the contents of a file into a variable. - -```js -d8> const license = read('LICENSE'); -d8> license -"This license applies to all parts of V8 that are not externally -maintained libraries. The externally maintained libraries used by V8 -are: -… (etc.)" -``` - -Use `readline()` to interactively enter text: - -```js -d8> const greeting = readline(); -Welcome -d8> greeting -"Welcome" -``` - -## Load external scripts - -`load()` runs another JavaScript file in the current context, meaning that you can then access anything declared in that file. - -```js -$ cat util.js -function greet(name) { - return 'Hello, ' + name; -} - -$ d8 -d8> load('util.js'); -d8> greet('World!'); -"Hello, World!" -``` - -## Pass flags into JavaScript - -It’s possible to make command-line arguments available to your JavaScript code at runtime with `d8`. Just pass them after `--` on the command line. You can then access them at the top-level of your script using the `arguments` object. - -```bash -out.gn/x64.optdebug/d8 -- hi -``` - -You can now access an array of the arguments using the `arguments` object: - -```js -d8> arguments[0] -"hi" -``` - -## More resources - -[Kevin Ennis’s D8 Guide](https://gist.github.com/kevincennis/0cd2138c78a07412ef21) has really good information about exploring V8 using `d8`. - -Background of the name `d8`: very early on, V8 had a “[sample shell](https://chromium.googlesource.com/v8/v8/+/master/samples/shell.cc)”, whose purpose was to demonstrate how V8 could be embedded to build a JavaScript shell. It was intentionally minimalist, and was simply called “shell”. Soon after, a “developer shell” was added with more convenience features to aid developers in their daily work, and it needed a name too. The original reason why “d8” was chosen as a name is lost to history; it caught on because “eveloper” is 8 omitted characters, so “d8 shell” makes sense as an abbreviation, and also fits in nicely with “V8” as the project name. diff --git a/src/docs/debug-arm.md b/src/docs/debug-arm.md deleted file mode 100644 index a372d9b85..000000000 --- a/src/docs/debug-arm.md +++ /dev/null @@ -1,521 +0,0 @@ ---- -title: 'Arm debugging with the simulator' -description: 'The Arm simulator and debugger can be very helpful when working with V8 code generation.' ---- -The simulator and debugger can be very helpful when working with V8 code generation. - -- It is convenient as it allows you to test code generation without access to actual hardware. -- No [cross](/docs/cross-compile-arm) or native compilation is needed. -- The simulator fully supports the debugging of generated code. - -Please note that this simulator is designed for V8 purposes. Only the features used by V8 are implemented, and you might encounter unimplemented features or instructions. In this case, feel free to implement them and submit the code! - -- [Compiling](#compiling) -- [Starting the debugger](#start_debug) -- [Debugging commands](#debug_commands) - - [printobject](#po) - - [trace](#trace) - - [break](#break) -- [Extra breakpoint features](#extra) - - [32-bit: `stop()`](#arm32_stop) - - [64-bit: `Debug()`](#arm64_debug) - -## Compiling for Arm using the simulator { #compiling } - -By default on an x86 host, compiling for Arm with [gm](/docs/build-gn#gm) will give you a simulator build: - -```bash -gm arm64.debug # For a 64-bit build or... -gm arm.debug # ... for a 32-bit build. -``` - -You may also build the `optdebug` configuration as the `debug` may be a little slow, especially if you want to run the V8 test suite. - -## Starting the debugger { #start_debug } - -You can start the debugger immediately from the command line after `n` instructions: - -```bash -out/arm64.debug/d8 --stop_sim_at # Or out/arm.debug/d8 for a 32-bit build. -``` - -Alternatively, you can generate a breakpoint instruction in the generated code: - -Natively, breakpoint instructions cause the program to halt with a `SIGTRAP` signal, allowing you to debug the issue with gdb. However, if running with a simulator, a breakpoint instruction in generated code will instead drop you into the simulator debugger. - -You can generate a breakpoint in multiple ways by using `DebugBreak()` from [Torque](/docs/torque-builtins), from the [CodeStubAssembler](/docs/csa-builtins), as a node in a [TurboFan](/docs/turbofan) pass, or directly using an assembler. - -Here we focus on debugging low-level native code, so let's look at the assembler method: - -```cpp -TurboAssembler::DebugBreak(); -``` - -Let's say we have a jitted function called `add` compiled with [TurboFan](/docs/turbofan) and we'd like to break at the start. Given a `test.js` example: - -{ #test.js } - -```js -// Our optimized function. -function add(a, b) { - return a + b; -} - -// Typical cheat code enabled by --allow-natives-syntax. -%PrepareFunctionForOptimization(add); - -// Give the optimizing compiler type feedback so it'll speculate `a` and `b` are -// numbers. -add(1, 3); - -// And force it to optimize. -%OptimizeFunctionOnNextCall(add); -add(5, 7); -``` - -To do it, we can hook into TurboFan's [code generator](https://source.chromium.org/chromium/chromium/src/+/master:v8/src/compiler/backend/code-generator.cc?q=CodeGenerator::AssembleCode) and access the assembler to insert our breakpoint: - -```cpp -void CodeGenerator::AssembleCode() { - // ... - - // Check if we're optimizing, then look-up the name of the current function and - // insert a breakpoint. - if (info->IsOptimizing()) { - AllowHandleDereference allow_handle_dereference; - if (info->shared_info()->PassesFilter("add")) { - tasm()->DebugBreak(); - } - } - - // ... -} -``` - -And let's run it: - -```simulator -$ d8 \ - # Enable '%' cheat code JS functions. - --allow-natives-syntax \ - # Disassemble our function. - --print-opt-code --print-opt-code-filter="add" --code-comments \ - # Disable spectre mitigations for readability. - --no-untrusted-code-mitigations \ - test.js ---- Raw source --- -(a, b) { - return a + b; -} - - ---- Optimized code --- -optimization_id = 0 -source_position = 12 -kind = OPTIMIZED_FUNCTION -name = add -stack_slots = 6 -compiler = turbofan -address = 0x7f0900082ba1 - -Instructions (size = 504) -0x7f0900082be0 0 d45bd600 constant pool begin (num_const = 6) -0x7f0900082be4 4 00000000 constant -0x7f0900082be8 8 00000001 constant -0x7f0900082bec c 75626544 constant -0x7f0900082bf0 10 65724267 constant -0x7f0900082bf4 14 00006b61 constant -0x7f0900082bf8 18 d45bd7e0 constant - -- Prologue: check code start register -- -0x7f0900082bfc 1c 10ffff30 adr x16, #-0x1c (addr 0x7f0900082be0) -0x7f0900082c00 20 eb02021f cmp x16, x2 -0x7f0900082c04 24 54000080 b.eq #+0x10 (addr 0x7f0900082c14) - Abort message: - Wrong value in code start register passed -0x7f0900082c08 28 d2800d01 movz x1, #0x68 - -- Inlined Trampoline to Abort -- -0x7f0900082c0c 2c 58000d70 ldr x16, pc+428 (addr 0x00007f0900082db8) ;; off heap target -0x7f0900082c10 30 d63f0200 blr x16 - -- Prologue: check for deoptimization -- - [ DecompressTaggedPointer -0x7f0900082c14 34 b85d0050 ldur w16, [x2, #-48] -0x7f0900082c18 38 8b100350 add x16, x26, x16 - ] -0x7f0900082c1c 3c b8407210 ldur w16, [x16, #7] -0x7f0900082c20 40 36000070 tbz w16, #0, #+0xc (addr 0x7f0900082c2c) - -- Inlined Trampoline to CompileLazyDeoptimizedCode -- -0x7f0900082c24 44 58000c31 ldr x17, pc+388 (addr 0x00007f0900082da8) ;; off heap target -0x7f0900082c28 48 d61f0220 br x17 - -- B0 start (construct frame) -- -(...) - ---- End code --- -# Debugger hit 0: DebugBreak -0x00007f0900082bfc 10ffff30 adr x16, #-0x1c (addr 0x7f0900082be0) -sim> -``` - -We can see we've stopped at the start of the optimized function and the simulator gave us a prompt! - -Note this is just an example and V8 changes quickly so the details may vary. But you should be able to do this anywhere where an assembler is available. - -## Debugging commands { #debug_commands } - -### Common commands - -Enter `help` in the debugger prompt to get details on available commands. These include usual gdb-like commands, such as `stepi`, `cont`, `disasm`, etc. If the Simulator is run under gdb, the `gdb` debugger command will give control to gdb. You can then use `cont` from gdb to go back to the debugger. - -### Architecture specific commands - -Each target architecture implements its own simulator and debugger, so the experience and details will vary. - -- [printobject](#po) -- [trace](#trace) -- [break](#break) - -#### `printobject $register` (alias `po`) { #po } - -Describe a JS object held in a register. - -For example, let's say this time we're running [our example](#test.js) on a 32-bit Arm simulator build. We can examine incoming arguments passed in registers: - -```simulator -$ ./out/arm.debug/d8 --allow-natives-syntax test.js -Simulator hit stop, breaking at the next instruction: - 0x26842e24 e24fc00c sub ip, pc, #12 -sim> print r1 -r1: 0x4b60ffb1 1264648113 -# The current function object is passed with r1. -sim> printobject r1 -r1: -0x4b60ffb1: [Function] in OldSpace - - map: 0x485801f9 [FastProperties] - - prototype: 0x4b6010f1 - - elements: 0x5b700661 [HOLEY_ELEMENTS] - - function prototype: - - initial_map: - - shared_info: 0x4b60fe9d - - name: 0x5b701c5d - - formal_parameter_count: 2 - - kind: NormalFunction - - context: 0x4b600c65 - - code: 0x26842de1 - - source code: (a, b) { - return a + b; -} -(...) - -# Now print the current JS context passed in r7. -sim> printobject r7 -r7: -0x449c0c65: [NativeContext] in OldSpace - - map: 0x561000b9 - - length: 261 - - scope_info: 0x34081341 - - previous: 0 - - native_context: 0x449c0c65 - 0: 0x34081341 - 1: 0 - 2: 0x449cdaf5 - 3: 0x58480c25 - 4: 0x58485499 - 5: 0x561018a1 - 6: 0x3408027d - 7: 0x449c75c1 - 8: 0x561010f9 - 9: 0x449c967d - 10: 0x449c8dbd -(...) -``` - -#### `trace` (alias `t`) { #trace } - -Enable or disable tracing executed instructions. - -When enabled, the simulator will print disassembled instructions as it is executing them. If you're running a 64-bit Arm build, the simulator is also able to trace changes to register values. - -You may also enable this from the command-line with the `--trace-sim` flag to enable tracing from the start. - -With the same [example](#test.js): - -```simulator -$ out/arm64.debug/d8 --allow-natives-syntax \ - # --debug-sim is required on 64-bit Arm to enable disassembly - # when tracing. - --debug-sim test.js -# Debugger hit 0: DebugBreak -0x00007f1e00082bfc 10ffff30 adr x16, #-0x1c (addr 0x7f1e00082be0) -sim> trace -0x00007f1e00082bfc 10ffff30 adr x16, #-0x1c (addr 0x7f1e00082be0) -Enabling disassembly, registers and memory write tracing - -# Break on the return address stored in the lr register. -sim> break lr -Set a breakpoint at 0x7f1f880abd28 -0x00007f1e00082bfc 10ffff30 adr x16, #-0x1c (addr 0x7f1e00082be0) - -# Continuing will trace the function's execution until we return, allowing -# us to make sense of what is happening. -sim> continue -# x0: 0x00007f1e00082ba1 -# x1: 0x00007f1e08250125 -# x2: 0x00007f1e00082be0 -(...) - -# We first load the 'a' and 'b' arguments from the stack and check if they -# are tagged numbers. This is indicated by the least significant bit being 0. -0x00007f1e00082c90 f9401fe2 ldr x2, [sp, #56] -# x2: 0x000000000000000a <- 0x00007f1f821f0278 -0x00007f1e00082c94 7200005f tst w2, #0x1 -# NZCV: N:0 Z:1 C:0 V:0 -0x00007f1e00082c98 54000ac1 b.ne #+0x158 (addr 0x7f1e00082df0) -0x00007f1e00082c9c f9401be3 ldr x3, [sp, #48] -# x3: 0x000000000000000e <- 0x00007f1f821f0270 -0x00007f1e00082ca0 7200007f tst w3, #0x1 -# NZCV: N:0 Z:1 C:0 V:0 -0x00007f1e00082ca4 54000a81 b.ne #+0x150 (addr 0x7f1e00082df4) - -# Then we untag and add 'a' and 'b' together. -0x00007f1e00082ca8 13017c44 asr w4, w2, #1 -# x4: 0x0000000000000005 -0x00007f1e00082cac 2b830484 adds w4, w4, w3, asr #1 -# NZCV: N:0 Z:0 C:0 V:0 -# x4: 0x000000000000000c -# That's 5 + 7 == 12, all good! - -# Then we check for overflows and tag the result again. -0x00007f1e00082cb0 54000a46 b.vs #+0x148 (addr 0x7f1e00082df8) -0x00007f1e00082cb4 2b040082 adds w2, w4, w4 -# NZCV: N:0 Z:0 C:0 V:0 -# x2: 0x0000000000000018 -0x00007f1e00082cb8 54000466 b.vs #+0x8c (addr 0x7f1e00082d44) - - -# And finally we place the result in x0. -0x00007f1e00082cbc aa0203e0 mov x0, x2 -# x0: 0x0000000000000018 -(...) - -0x00007f1e00082cec d65f03c0 ret -Hit and disabled a breakpoint at 0x7f1f880abd28. -0x00007f1f880abd28 f85e83b4 ldur x20, [fp, #-24] -sim> -``` - -#### `break $address` { #break } - -Inserts a breakpoint at the specified address. - -Note that on 32-bit Arm, you can have only one breakpoint and you'll need to disable write protection on code pages to insert it. The 64-bit Arm simulator does not have such restrictions. - -With our [example](#test.js) again: - -```simulator -$ out/arm.debug/d8 --allow-natives-syntax \ - # This is useful to know which address to break to. - --print-opt-code --print-opt-code-filter="add" \ - test.js -(...) - -Simulator hit stop, breaking at the next instruction: - 0x488c2e20 e24fc00c sub ip, pc, #12 - -# Break on a known interesting address, where we start -# loading 'a' and 'b'. -sim> break 0x488c2e9c -sim> continue - 0x488c2e9c e59b200c ldr r2, [fp, #+12] - -# We can look-ahead with 'disasm'. -sim> disasm 10 - 0x488c2e9c e59b200c ldr r2, [fp, #+12] - 0x488c2ea0 e3120001 tst r2, #1 - 0x488c2ea4 1a000037 bne +228 -> 0x488c2f88 - 0x488c2ea8 e59b3008 ldr r3, [fp, #+8] - 0x488c2eac e3130001 tst r3, #1 - 0x488c2eb0 1a000037 bne +228 -> 0x488c2f94 - 0x488c2eb4 e1a040c2 mov r4, r2, asr #1 - 0x488c2eb8 e09440c3 adds r4, r4, r3, asr #1 - 0x488c2ebc 6a000037 bvs +228 -> 0x488c2fa0 - 0x488c2ec0 e0942004 adds r2, r4, r4 - -# And try and break on the result of the first `adds` instructions. -sim> break 0x488c2ebc -setting breakpoint failed - -# Ah, we need to delete the breakpoint first. -sim> del -sim> break 0x488c2ebc -sim> cont - 0x488c2ebc 6a000037 bvs +228 -> 0x488c2fa0 - -sim> print r4 -r4: 0x0000000c 12 -# That's 5 + 7 == 12, all good! -``` - -### Generated breakpoint instuctions with a few additional features { #extra } - -Instead of `TurboAssembler::DebugBreak()`, you may use a lower-level instruction which has the same effect except with additional features. - -- [32-bit: `stop()`](#arm32_stop) -- [64-bit: `Debug()`](#arm64_debug) - -#### `stop()` (32-bit Arm) { #arm32_stop } - -```cpp -Assembler::stop(Condition cond = al, int32_t code = kDefaultStopCode); -``` - -The first argument is the condition and the second is the stop code. If a code is specified, and is less than 256, the stop is said to be “watched”, and can be disabled/enabled; a counter also keeps track of how many times the Simulator hits this code. - -Imagine we are working on this V8 C++ code: - -```cpp -__ stop(al, 123); -__ mov(r0, r0); -__ mov(r0, r0); -__ mov(r0, r0); -__ mov(r0, r0); -__ mov(r0, r0); -__ stop(al, 0x1); -__ mov(r1, r1); -__ mov(r1, r1); -__ mov(r1, r1); -__ mov(r1, r1); -__ mov(r1, r1); -``` - -Here's a sample debugging session: - -We hit the first stop. - -```simulator -Simulator hit stop 123, breaking at the next instruction: - 0xb53559e8 e1a00000 mov r0, r0 -``` - -We can see the following stop using `disasm`. - -```simulator -sim> disasm - 0xb53559e8 e1a00000 mov r0, r0 - 0xb53559ec e1a00000 mov r0, r0 - 0xb53559f0 e1a00000 mov r0, r0 - 0xb53559f4 e1a00000 mov r0, r0 - 0xb53559f8 e1a00000 mov r0, r0 - 0xb53559fc ef800001 stop 1 - 0x1 - 0xb5355a00 e1a00000 mov r1, r1 - 0xb5355a04 e1a00000 mov r1, r1 - 0xb5355a08 e1a00000 mov r1, r1 -``` - -Information can be printed for all (watched) stops which were hit at least once. - -```simulator -sim> stop info all -Stop information: -stop 123 - 0x7b: Enabled, counter = 1 -sim> cont -Simulator hit stop 1, breaking at the next instruction: - 0xb5355a04 e1a00000 mov r1, r1 -sim> stop info all -Stop information: -stop 1 - 0x1: Enabled, counter = 1 -stop 123 - 0x7b: Enabled, counter = 1 -``` - -Stops can be disabled or enabled. (Only available for watched stops.) - -```simulator -sim> stop disable 1 -sim> cont -Simulator hit stop 123, breaking at the next instruction: - 0xb5356808 e1a00000 mov r0, r0 -sim> cont -Simulator hit stop 123, breaking at the next instruction: - 0xb5356c28 e1a00000 mov r0, r0 -sim> stop info all -Stop information: -stop 1 - 0x1: Disabled, counter = 2 -stop 123 - 0x7b: Enabled, counter = 3 -sim> stop enable 1 -sim> cont -Simulator hit stop 1, breaking at the next instruction: - 0xb5356c44 e1a00000 mov r1, r1 -sim> stop disable all -sim> con -``` - -#### `Debug()` (64-bit Arm) { #arm64_debug } - -```cpp -MacroAssembler::Debug(const char* message, uint32_t code, Instr params = BREAK); -``` - -This instruction is a breakpoint by default, but is also able to enable and disable tracing as if you had done it with the [`trace`](#trace) command in the debugger. You can also give it a message and a code as an identifier. - -Imagine we are working on this V8 C++ code, taken from the native builtin that prepares the frame to call a JS function. - -```cpp -int64_t bad_frame_pointer = -1L; // Bad frame pointer, should fail if it is used. -__ Mov(x13, bad_frame_pointer); -__ Mov(x12, StackFrame::TypeToMarker(type)); -__ Mov(x11, ExternalReference::Create(IsolateAddressId::kCEntryFPAddress, - masm->isolate())); -__ Ldr(x10, MemOperand(x11)); - -__ Push(x13, x12, xzr, x10); -``` - -It might be useful to insert a breakpoint with `DebugBreak()` so we can examine the current state when we run this. But we can go further and trace this code if we use `Debug()` instead: - -```cpp -// Start tracing and log disassembly and register values. -__ Debug("start tracing", 42, TRACE_ENABLE | LOG_ALL); - -int64_t bad_frame_pointer = -1L; // Bad frame pointer, should fail if it is used. -__ Mov(x13, bad_frame_pointer); -__ Mov(x12, StackFrame::TypeToMarker(type)); -__ Mov(x11, ExternalReference::Create(IsolateAddressId::kCEntryFPAddress, - masm->isolate())); -__ Ldr(x10, MemOperand(x11)); - -__ Push(x13, x12, xzr, x10); - -// Stop tracing. -__ Debug("stop tracing", 42, TRACE_DISABLE); -``` - -It allows us to trace register values for __just__ the snippet of code we're working on: - -```simulator -$ d8 --allow-natives-syntax --debug-sim test.js -# NZCV: N:0 Z:0 C:0 V:0 -# FPCR: AHP:0 DN:0 FZ:0 RMode:0b00 (Round to Nearest) -# x0: 0x00007fbf00000000 -# x1: 0x00007fbf0804030d -# x2: 0x00007fbf082500e1 -(...) - -0x00007fc039d31cb0 9280000d movn x13, #0x0 -# x13: 0xffffffffffffffff -0x00007fc039d31cb4 d280004c movz x12, #0x2 -# x12: 0x0000000000000002 -0x00007fc039d31cb8 d2864110 movz x16, #0x3208 -# ip0: 0x0000000000003208 -0x00007fc039d31cbc 8b10034b add x11, x26, x16 -# x11: 0x00007fbf00003208 -0x00007fc039d31cc0 f940016a ldr x10, [x11] -# x10: 0x0000000000000000 <- 0x00007fbf00003208 -0x00007fc039d31cc4 a9be7fea stp x10, xzr, [sp, #-32]! -# sp: 0x00007fc033e81340 -# x10: 0x0000000000000000 -> 0x00007fc033e81340 -# xzr: 0x0000000000000000 -> 0x00007fc033e81348 -0x00007fc039d31cc8 a90137ec stp x12, x13, [sp, #16] -# x12: 0x0000000000000002 -> 0x00007fc033e81350 -# x13: 0xffffffffffffffff -> 0x00007fc033e81358 -0x00007fc039d31ccc 910063fd add fp, sp, #0x18 (24) -# fp: 0x00007fc033e81358 -0x00007fc039d31cd0 d45bd600 hlt #0xdeb0 -``` diff --git a/src/docs/design-review-guidelines.md b/src/docs/design-review-guidelines.md deleted file mode 100644 index 69ebd6b73..000000000 --- a/src/docs/design-review-guidelines.md +++ /dev/null @@ -1,148 +0,0 @@ ---- -title: 'Design review guidelines' -description: 'This document explains the V8 project’s design review guidelines.' ---- -Please make sure to follow the following guidelines when applicable. - -There are multiple drivers for the formalization of V8’s design reviews: - -1. make it clear to Individual Contributors (ICs) who the decision makers are and highlight what the path forward in the case that projects are not proceeding due to technical disagreement -1. create a forum to have straight-forward design discussions -1. ensure V8 Technical Leads (TL) are aware of all significant changes and have the opportunity to give their input on the Tech Lead (TL) layer -1. increase the involvement of all V8 contributors over the globe - -## Summary - -![V8’s Design Review Guidelines at a glance](/_img/docs/design-review-guidelines/design-review-guidelines.svg) - -Important: - -1. assume good intentions -1. be kind and civilized -1. be pragmatic - -The proposed solution is based on the following assumption/pillars: - -1. The proposed workflow puts the individual contributor (IC) in charge. They are the one who facilitate the process. -1. Their guiding TLs are tasked to help them navigate the territory and find the right LGTM providers. -1. If a feature is uncontroversial, nearly no overhead should be created. -1. If there is a lot of controversy, the feature can be 'escalated' to the V8 Eng Review Owners meeting where further steps are decided. - -## Roles - -### Individual Contributor (IC) - -LGTM: N/A -This person is the creator of the feature and the creator of the design documentation. - -### The Tech Lead (TL) of the IC - -LGTM: Must have -This person is the TL of a given project or component. Likely this is the person that is an owner of the main component your feature is going to touch. If it is not clear who the TL is, please ask the V8 Eng Review Owners via v8-eng-review-owners@googlegroups.com. TLs are responsible to add more people to the list of required LGTMs if appropriate. - -### LGTM provider - -LGTM: Must have -This is a person that is required to give LGTM. It might be an IC, or a TL(M). - -### “Random” reviewer of the document (RRotD) { #rrotd } - -LGTM: Not required -This is somebody who is simply reviewing and comment on the proposal. Their input should be considered, although their LGTM is not required. - -### V8 Eng Review Owners - -LGTM: Not required -Stuck proposals can be escalated to the V8 Eng Review Owners via . Potential use cases of such an escalation: - -- an LGTM provider is non-responsive -- no consensus on the design can be reached - -The V8 Eng Review Owners can overrule non-LGTMs or LGTMs. - -## Detailed workflow - -![V8’s Design Review Guidelines at a glance](/_img/docs/design-review-guidelines/design-review-guidelines.svg) - -1. Start: IC decides to work on a feature/gets a feature assigned to them -1. IC sends out their early design doc/explainer/one pager to a few RRotDs - 1. Prototypes are considered part of the "design doc" -1. IC adds people to the list of LGTM providers that the IC thinks should give their LGTM. The TL is a must have on the list of LGTM providers. -1. IC incorporates feedback. -1. TL adds more people to the list of LGTM providers. -1. IC sends out the early design doc/explainer/one pager to . -1. IC collects the LGTMs. TL helps them. - 1. LGTM provider reviews document, add comments and gives either an LGTM or not LGTM at the beginning of the document. If they add a not LGTM, they are obligated to list the reason(s). - 1. Optional: LGTM providers can remove themselves from the list of LGTM providers and/or suggest other LGTM providers - 1. IC and TL work to resolve the unresolved issues. - 1. If all LGTM are gathered send an email to v8-dev@googlegroups.com (e.g. by pinging the original thread) and announce implementation. -1. Optional: If IC and TL are blocked and/or want to have a broader discussion they can escalate the issue to the V8 Eng Review Owners. - 1. IC sends a mail to v8-eng-review-owners@googlegroups.com - 1. TL in CC - 1. Link to design doc in the mail - 1. Every V8 Eng Review Owners member is obligated to review the doc and optionally add themselves to the list of LGTM providers. - 1. Next steps to unblock the feature are decided. - 1. If the blocker is not resolved afterwards or new, unresolvable blockers are discovered, goto 8. -1. Optional: If "not LGTMs" are added after the feature was approved already, they should be treated like normal, unresolved issues. - 1. IC and TL work to resolve the unresolved issues. -1. End: IC proceeds with the feature. - -And always remember: - -1. assume good intentions -1. be kind and civilized -1. be pragmatic - -## FAQ - -### How to decide if the feature is worthy to have a design document? - -Some pointers when a design doc is appropriate: - -- Touches at least two components -- Needs reconciliation with non-V8 projects e.g. Debugger, Blink -- Take longer than 1 week of effort to implement -- Is a language feature -- Platform specific code will be touched -- User facing changes -- Has special security consideration or security impact is not obvious - -When in doubt, ask the TL. - -### How to decide who to add to the list of LGTM providers? - -Some pointers when people should be added to the list of LGTM providers: - -- OWNERs of the source files/directories you anticipate to touch -- Main component expert of the components you anticipate to touch -- Downstream consumers of your changes e.g. when you change an API - -### Who is “my” TL? - -Likely this is the person that is an owner of the main component your feature is going to touch. If it is not clear who the TL is, please ask the V8 Eng Review Owners via . - -### Where can I find a template for design documents? - -[Here](https://docs.google.com/document/d/1CWNKvxOYXGMHepW31hPwaFz9mOqffaXnuGqhMqcyFYo/template/preview). - -### What if something big changes? - -Make sure you still have the LGTMs e.g. by pinging the LGTM providers with a clear, reasonable deadline to veto. - -### LGTM providers don’t comment on my doc, what should I do? - -In this case you can follow this path of escalation: - -- Ping them directly via mail, Hangouts or comment/assignment in the doc and specifically ask them explicitly to add an LGTM or non-LGTM. -- Get your TL involved and ask them for help. -- Escalate to . - -### Somebody added me as an LGTM provider to a doc, what should I do? - -V8 is aiming to make decisions more transparent and escalation more straight-forward. If you think the design is good enough and should be done add an “LGTM” to the table cell next to your name. - -If you have blocking concerns or remarks, please add “Not LGTM, because \” into the table cell next to your name. Be prepared to get asked for another round of review. - -### How does this work together with the Blink Intents process? - -The V8 Design Review Guidelines complement [V8’s Blink Intent+Errata process](/docs/feature-launch-process). If you are launching a new WebAssembly or JavaScript language feature, please follow V8’s Blink Intent+Errata process and the V8 Design Review Guidelines. It likely makes sense to have all the LGTMs gathered at the point in time you would send an Intent to Implement. diff --git a/src/docs/embed.md b/src/docs/embed.md deleted file mode 100644 index 728930f35..000000000 --- a/src/docs/embed.md +++ /dev/null @@ -1,431 +0,0 @@ ---- -title: 'Getting started with embedding V8' -description: 'This document introduces some key V8 concepts and provides a “hello world” example to get you started with V8 code.' ---- -This document introduces some key V8 concepts and provides a “hello world” example to get you started with V8 code. - -## Audience - -This document is intended for C++ programmers who want to embed the V8 JavaScript engine within a C++ application. It helps you to make your own application’s C++ objects and methods available to JavaScript, and to make JavaScript objects and functions available to your C++ application. - -## Hello world - -Let’s look at a [Hello World example](https://chromium.googlesource.com/v8/v8/+/branch-heads/11.9/samples/hello-world.cc) that takes a JavaScript statement as a string argument, executes it as JavaScript code, and prints the result to standard out. - -First, some key concepts: - -- An isolate is a VM instance with its own heap. -- A local handle is a pointer to an object. All V8 objects are accessed using handles. They are necessary because of the way the V8 garbage collector works. -- A handle scope can be thought of as a container for any number of handles. When you've finished with your handles, instead of deleting each one individually you can simply delete their scope. -- A context is an execution environment that allows separate, unrelated, JavaScript code to run in a single instance of V8. You must explicitly specify the context in which you want any JavaScript code to be run. - -These concepts are discussed in greater detail in [the advanced guide](/docs/embed#advanced-guide). - -## Run the example - -Follow the steps below to run the example yourself: - -1. Download the V8 source code by following [the Git instructions](/docs/source-code#using-git). -1. The instructions for this hello world example have last been tested with V8 v13.1. You can check out this branch with `git checkout branch-heads/13.1 -b sample -t` -1. Create a build configuration using the helper script: - - ```bash - tools/dev/v8gen.py x64.release.sample - ``` - - You can inspect and manually edit the build configuration by running: - - ```bash - gn args out.gn/x64.release.sample - ``` - -1. Build the static library on a Linux 64 system: - - ```bash - ninja -C out.gn/x64.release.sample v8_monolith - ``` - -1. Compile `hello-world.cc`, linking to the static library created in the build process. For example, on 64bit Linux using the GNU compiler and LLD linker: - - ```bash - g++ -I. -Iinclude samples/hello-world.cc -o hello_world -fno-rtti -fuse-ld=lld -lv8_monolith -lv8_libbase -lv8_libplatform -ldl -Lout.gn/x64.release.sample/obj/ -pthread -std=c++20 -DV8_COMPRESS_POINTERS -DV8_ENABLE_SANDBOX - ``` - -1. For more complex code, V8 fails without an ICU data file. Copy this file to where your binary is stored: - - ```bash - cp out.gn/x64.release.sample/icudtl.dat . - ``` - -1. Run the `hello_world` executable file at the command line. e.g. On Linux, in the V8 directory, run: - - ```bash - ./hello_world - ``` - -1. It prints `Hello, World!`. Yay! - Note: as of November 2024, it might also segfault early during process startup. Investigation is pending. If you run into this and can figure out what's wrong, please comment on [issue 377222400](https://issues.chromium.org/issues/377222400), or [submit a patch](https://v8.dev/docs/contribute). - -If you are looking for an example which is in sync with the main branch, check out the file [`hello-world.cc`](https://chromium.googlesource.com/v8/v8/+/main/samples/hello-world.cc). This is a very simple example and you’ll likely want to do more than just execute scripts as strings. [The advanced guide below](#advanced-guide) contains more information for V8 embedders. - -## More example code - -The following samples are provided as part of the source code download. - -### [`process.cc`](https://github.com/v8/v8/blob/main/samples/process.cc) - -This sample provides the code necessary to extend a hypothetical HTTP request processing application — which could be part of a web server, for example — so that it is scriptable. It takes a JavaScript script as an argument, which must provide a function called `Process`. The JavaScript `Process` function can be used to, for example, collect information such as how many hits each page served by the fictional web server gets. - -### [`shell.cc`](https://github.com/v8/v8/blob/main/samples/shell.cc) - -This sample takes filenames as arguments then reads and executes their contents. Includes a command prompt at which you can enter JavaScript code snippets which are then executed. In this sample additional functions like `print` are also added to JavaScript through the use of object and function templates. - -## Advanced guide - -Now that you’re familiar with using V8 as a standalone virtual machine and with some key V8 concepts such as handles, scopes, and contexts, let’s discuss these concepts further and introduce a few other concepts that are key to embedding V8 within your own C++ application. - -The V8 API provides functions for compiling and executing scripts, accessing C++ methods and data structures, handling errors, and enabling security checks. Your application can use V8 just like any other C++ library. Your C++ code accesses V8 through the V8 API by including the header `include/v8.h`. - -### Handles and garbage collection - -A handle provides a reference to a JavaScript object’s location in the heap. The V8 garbage collector reclaims memory used by objects that can no longer again be accessed. During the garbage collection process the garbage collector often moves objects to different locations in the heap. When the garbage collector moves an object the garbage collector also updates all handles that refer to the object with the object’s new location. - -An object is considered garbage if it is inaccessible from JavaScript and there are no handles that refer to it. From time to time the garbage collector removes all objects considered to be garbage. V8’s garbage collection mechanism is key to V8’s performance. - -There are several types of handles: - -- Local handles are held on a stack and are deleted when the appropriate destructor is called. These handles’ lifetime is determined by a handle scope, which is often created at the beginning of a function call. When the handle scope is deleted, the garbage collector is free to deallocate those objects previously referenced by handles in the handle scope, provided they are no longer accessible from JavaScript or other handles. This type of handle is used in the hello world example above. - - Local handles have the class `Local`. - - **Note:** The handle stack is not part of the C++ call stack, but the handle scopes are embedded in the C++ stack. Handle scopes can only be stack-allocated, not allocated with `new`. - -- Persistent handles provide a reference to a heap-allocated JavaScript Object, just like a local handle. There are two flavors, which differ in the lifetime management of the reference they handle. Use a persistent handle when you need to keep a reference to an object for more than one function call, or when handle lifetimes do not correspond to C++ scopes. Google Chrome, for example, uses persistent handles to refer to Document Object Model (DOM) nodes. A persistent handle can be made weak, using `PersistentBase::SetWeak`, to trigger a callback from the garbage collector when the only references to an object are from weak persistent handles. - - - A `UniquePersistent` handle relies on C++ constructors and destructors to manage the lifetime of the underlying object. - - A `Persistent` can be constructed with its constructor, but must be explicitly cleared with `Persistent::Reset`. - -- There are other types of handles which are rarely used, that we will only briefly mention here: - - - `Eternal` is a persistent handle for JavaScript objects that are expected to never be deleted. It is cheaper to use because it relieves the garbage collector from determining the liveness of that object. - - Both `Persistent` and `UniquePersistent` cannot be copied, which makes them unsuitable as values with pre-C++11 standard library containers. `PersistentValueMap` and `PersistentValueVector` provide container classes for persistent values, with map and vector-like semantics. C++11 embedders do not require these, since C++11 move semantics solve the underlying problem. - -Of course, creating a local handle every time you create an object can result in a lot of handles! This is where handle scopes are very useful. You can think of a handle scope as a container that holds lots of handles. When the handle scope’s destructor is called all handles created within that scope are removed from the stack. As you would expect, this results in the objects to which the handles point being eligible for deletion from the heap by the garbage collector. - -Returning to [our very simple hello world example](#hello-world), in the following diagram you can see the handle-stack and heap-allocated objects. Note that `Context::New()` returns a `Local` handle, and we create a new `Persistent` handle based on it to demonstrate the usage of `Persistent` handles. - -![](/_img/docs/embed/local-persist-handles-review.png) - -When the destructor `HandleScope::~HandleScope` is called, the handle scope is deleted. Objects referred to by handles within the deleted handle scope are eligible for removal in the next garbage collection if there are no other references to them. The garbage collector can also remove the `source_obj`, and `script_obj` objects from the heap as they are no longer referenced by any handles or otherwise reachable from JavaScript. Since the context handle is a persistent handle, it is not removed when the handle scope is exited. The only way to remove the context handle is to explicitly call `Reset` on it. - -:::note -**Note:** Throughout this document the term “handle” refers to a local handle. When discussing a persistent handle, that term is used in full. -::: - -It is important to be aware of one common pitfall with this model: *you cannot return a local handle directly from a function that declares a handle scope*. If you do the local handle you’re trying to return will end up being deleted by the handle scope’s destructor immediately before the function returns. The proper way to return a local handle is construct an `EscapableHandleScope` instead of a `HandleScope` and to call the `Escape` method on the handle scope, passing in the handle whose value you want to return. Here’s an example of how that works in practice: - -```cpp -// This function returns a new array with three elements, x, y, and z. -Local NewPointArray(int x, int y, int z) { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - - // We will be creating temporary handles so we use a handle scope. - v8::EscapableHandleScope handle_scope(isolate); - - // Create a new empty array. - v8::Local array = v8::Array::New(isolate, 3); - - // Return an empty result if there was an error creating the array. - if (array.IsEmpty()) - return v8::Local(); - - // Fill out the values - array->Set(0, Integer::New(isolate, x)); - array->Set(1, Integer::New(isolate, y)); - array->Set(2, Integer::New(isolate, z)); - - // Return the value through Escape. - return handle_scope.Escape(array); -} -``` - -The `Escape` method copies the value of its argument into the enclosing scope, deletes all its local handles, and then gives back the new handle copy which can safely be returned. - -### Contexts - -In V8, a context is an execution environment that allows separate, unrelated, JavaScript applications to run in a single instance of V8. You must explicitly specify the context in which you want any JavaScript code to be run. - -Why is this necessary? Because JavaScript provides a set of built-in utility functions and objects that can be changed by JavaScript code. For example, if two entirely unrelated JavaScript functions both changed the global object in the same way then unexpected results are fairly likely to happen. - -In terms of CPU time and memory, it might seem an expensive operation to create a new execution context given the number of built-in objects that must be built. However, V8’s extensive caching ensures that, while the first context you create is somewhat expensive, subsequent contexts are much cheaper. This is because the first context needs to create the built-in objects and parse the built-in JavaScript code while subsequent contexts only have to create the built-in objects for their context. With the V8 snapshot feature (activated with build option `snapshot=yes`, which is the default) the time spent creating the first context will be highly optimized as a snapshot includes a serialized heap which contains already compiled code for the built-in JavaScript code. Along with garbage collection, V8’s extensive caching is also key to V8’s performance. - -When you have created a context you can enter and exit it any number of times. While you are in context A you can also enter a different context, B, which means that you replace A as the current context with B. When you exit B then A is restored as the current context. This is illustrated below: - -![](/_img/docs/embed/intro-contexts.png) - -Note that the built-in utility functions and objects of each context are kept separate. You can optionally set a security token when you create a context. See the [Security Model](#security-model) section for more information. - -The motivation for using contexts in V8 was so that each window and iframe in a browser can have its own fresh JavaScript environment. - -### Templates - -A template is a blueprint for JavaScript functions and objects in a context. You can use a template to wrap C++ functions and data structures within JavaScript objects so that they can be manipulated by JavaScript scripts. For example, Google Chrome uses templates to wrap C++ DOM nodes as JavaScript objects and to install functions in the global namespace. You can create a set of templates and then use the same ones for every new context you make. You can have as many templates as you require. However you can only have one instance of any template in any given context. - -In JavaScript there is a strong duality between functions and objects. To create a new type of object in Java or C++ you would typically define a new class. In JavaScript you create a new function instead, and create instances using the function as a constructor. The layout and functionality of a JavaScript object is closely tied to the function that constructed it. This is reflected in the way V8 templates work. There are two types of templates: - -- Function templates - - A function template is the blueprint for a single function. You create a JavaScript instance of the template by calling the template’s `GetFunction` method from within the context in which you wish to instantiate the JavaScript function. You can also associate a C++ callback with a function template which is called when the JavaScript function instance is invoked. - -- Object templates - - Each function template has an associated object template. This is used to configure objects created with this function as their constructor. You can associate two types of C++ callbacks with object templates: - - - accessor callbacks are invoked when a specific object property is accessed by a script - - interceptor callbacks are invoked when any object property is accessed by a script - - [Accessors](#accessors) and [interceptors](#interceptors) are discussed later in this document. - -The following code provides an example of creating a template for the global object and setting the built-in global functions. - -```cpp -// Create a template for the global object and set the -// built-in global functions. -v8::Local global = v8::ObjectTemplate::New(isolate); -global->Set(v8::String::NewFromUtf8(isolate, "log"), - v8::FunctionTemplate::New(isolate, LogCallback)); - -// Each processor gets its own context so different processors -// do not affect each other. -v8::Persistent context = - v8::Context::New(isolate, nullptr, global); -``` - -This example code is taken from `JsHttpProcessor::Initializer` in the `process.cc` sample. - -### Accessors - -An accessor is a C++ callback that calculates and returns a value when an object property is accessed by a JavaScript script. Accessors are configured through an object template, using the `SetAccessor` method. This method takes the name of the property with which it is associated and two callbacks to run when a script attempts to read or write the property. - -The complexity of an accessor depends upon the type of data you are manipulating: - -- [Accessing static global variables](#accessing-static-global-variables) -- [Accessing dynamic variables](#accessing-dynamic-variables) - -### Accessing static global variables - -Let’s say there are two C++ integer variables, `x` and `y` that are to be made available to JavaScript as global variables within a context. To do this, you need to call C++ accessor functions whenever a script reads or writes those variables. These accessor functions convert a C++ integer to a JavaScript integer using `Integer::New`, and convert a JavaScript integer to a C++ integer using `Int32Value`. An example is provided below: - -```cpp -void XGetter(v8::Local property, - const v8::PropertyCallbackInfo& info) { - info.GetReturnValue().Set(x); -} - -void XSetter(v8::Local property, v8::Local value, - const v8::PropertyCallbackInfo& info) { - x = value->Int32Value(); -} - -// YGetter/YSetter are so similar they are omitted for brevity - -v8::Local global_templ = v8::ObjectTemplate::New(isolate); -global_templ->SetAccessor(v8::String::NewFromUtf8(isolate, "x"), - XGetter, XSetter); -global_templ->SetAccessor(v8::String::NewFromUtf8(isolate, "y"), - YGetter, YSetter); -v8::Persistent context = - v8::Context::New(isolate, nullptr, global_templ); -``` - -Note that the object template in the code above is created at the same time as the context. The template could have been created in advance and then used for any number of contexts. - -### Accessing dynamic variables - -In the preceding example the variables were static and global. What if the data being manipulated is dynamic, as is true of the DOM tree in a browser? Let’s imagine `x` and `y` are object fields on the C++ class `Point`: - -```cpp -class Point { - public: - Point(int x, int y) : x_(x), y_(y) { } - int x_, y_; -} -``` - -To make any number of C++ `point` instances available to JavaScript we need to create one JavaScript object for each C++ `point` and make a connection between the JavaScript object and the C++ instance. This is done with external values and internal object fields. - -First create an object template for the `point` wrapper object: - -```cpp -v8::Local point_templ = v8::ObjectTemplate::New(isolate); -``` - -Each JavaScript `point` object keeps a reference to the C++ object for which it is a wrapper with an internal field. These fields are so named because they cannot be accessed from within JavaScript, they can only be accessed from C++ code. An object can have any number of internal fields, the number of internal fields is set on the object template as follows: - -```cpp -point_templ->SetInternalFieldCount(1); -``` - -Here the internal field count is set to `1` which means the object has one internal field, with an index of `0`, that points to a C++ object. - -Add the `x` and `y` accessors to the template: - -```cpp -point_templ->SetAccessor(v8::String::NewFromUtf8(isolate, "x"), - GetPointX, SetPointX); -point_templ->SetAccessor(v8::String::NewFromUtf8(isolate, "y"), - GetPointY, SetPointY); -``` - -Next, wrap a C++ point by creating a new instance of the template and then setting the internal field `0` to an external wrapper around the point `p`. - -```cpp -Point* p = ...; -v8::Local obj = point_templ->NewInstance(); -obj->SetInternalField(0, v8::External::New(isolate, p)); -``` - -The external object is simply a wrapper around a `void*`. External objects can only be used to store reference values in internal fields. JavaScript objects can not have references to C++ objects directly so the external value is used as a "bridge" to go from JavaScript into C++. In that sense external values are the opposite of handles since handles lets C++ make references to JavaScript objects. - -Here’s the definition of the `get` and `set` accessors for `x`, the `y` accessor definitions are identical except `y` replaces `x`: - -```cpp -void GetPointX(Local property, - const PropertyCallbackInfo& info) { - v8::Local self = info.Holder(); - v8::Local wrap = - v8::Local::Cast(self->GetInternalField(0)); - void* ptr = wrap->Value(); - int value = static_cast(ptr)->x_; - info.GetReturnValue().Set(value); -} - -void SetPointX(v8::Local property, v8::Local value, - const v8::PropertyCallbackInfo& info) { - v8::Local self = info.Holder(); - v8::Local wrap = - v8::Local::Cast(self->GetInternalField(0)); - void* ptr = wrap->Value(); - static_cast(ptr)->x_ = value->Int32Value(); -} -``` - -Accessors extract the reference to the `point` object that was wrapped by the JavaScript object and then read and writes the associated field. This way these generic accessors can be used on any number of wrapped point objects. - -### Interceptors - -You can also specify a callback for whenever a script accesses any object property. These are called interceptors. For efficiency, there are two types of interceptors: - -- *named property interceptors* - called when accessing properties with string names. - An example of this, in a browser environment, is `document.theFormName.elementName`. -- *indexed property interceptors* - called when accessing indexed properties. An example of this, in a browser environment, is `document.forms.elements[0]`. - -The sample `process.cc`, provided with the V8 source code, includes an example of using interceptors. In the following code snippet `SetNamedPropertyHandler` specifies the `MapGet` and `MapSet` interceptors: - -```cpp -v8::Local result = v8::ObjectTemplate::New(isolate); -result->SetNamedPropertyHandler(MapGet, MapSet); -``` - -The `MapGet` interceptor is provided below: - -```cpp -void JsHttpRequestProcessor::MapGet(v8::Local name, - const v8::PropertyCallbackInfo& info) { - // Fetch the map wrapped by this object. - map *obj = UnwrapMap(info.Holder()); - - // Convert the JavaScript string to a std::string. - string key = ObjectToString(name); - - // Look up the value if it exists using the standard STL idiom. - map::iterator iter = obj->find(key); - - // If the key is not present return an empty handle as signal. - if (iter == obj->end()) return; - - // Otherwise fetch the value and wrap it in a JavaScript string. - const string &value = (*iter).second; - info.GetReturnValue().Set(v8::String::NewFromUtf8( - value.c_str(), v8::String::kNormalString, value.length())); -} -``` - -As with accessors, the specified callbacks are invoked whenever a property is accessed. The difference between accessors and interceptors is that interceptors handle all properties, while accessors are associated with one specific property. - -### Security model - -The “same-origin policy” (first introduced with Netscape Navigator 2.0) prevents a document or script loaded from one “origin” from getting or setting properties of a document from a different “origin”. The term origin is defined here as a combination of domain name (e.g. `www.example.com`), protocol (e.g. `https`) and port. For example, `www.example.com:81` is not the same origin as `www.example.com`. All three must match for two web pages to be considered to have the same origin. Without this protection, a malicious web page could compromise the integrity of another web page. - -In V8 an “origin” is defined as a context. Access to any context other than the one from which you are calling is not allowed by default. To access a context other than the one from which you are calling, you need to use security tokens or security callbacks. A security token can be any value but is typically a symbol, a canonical string that does not exist anywhere else. You can optionally specify a security token with `SetSecurityToken` when you set up a context. If you do not specify a security token V8 will automatically generate one for the context you are creating. - -When an attempt is made to access a global variable the V8 security system first checks the security token of the global object being accessed against the security token of the code attempting to access the global object. If the tokens match access is granted. If the tokens do not match V8 performs a callback to check if access should be allowed. You can specify whether access to an object should be allowed by setting the security callback on the object, using the `SetAccessCheckCallbacks` method on object templates. The V8 security system can then fetch the security callback of the object being accessed and call it to ask if another context is allowed to access it. This callback is given the object being accessed, the name of the property being accessed, the type of access (read, write, or delete for example) and returns whether or not to allow access. - -This mechanism is implemented in Google Chrome so that if security tokens do not match, a special callback is used to allow access only to the following: `window.focus()`, `window.blur()`, `window.close()`, `window.location`, `window.open()`, `history.forward()`, `history.back()`, and `history.go()`. - -### Exceptions - -V8 throws an exception if an error occurs — for example, when a script or function attempts to read a property that does not exist, or if a function is called that is not a function. - -V8 returns an empty handle if an operation did not succeed. It is therefore important that your code checks a return value is not an empty handle before continuing execution. Check for an empty handle with the `Local` class’s public member function `IsEmpty()`. - -You can catch exceptions with `TryCatch`, for example: - -```cpp -v8::TryCatch trycatch(isolate); -v8::Local v = script->Run(); -if (v.IsEmpty()) { - v8::Local exception = trycatch.Exception(); - v8::String::Utf8Value exception_str(exception); - printf("Exception: %s\n", *exception_str); - // ... -} -``` - -If the value returned is an empty handle, and you do not have a `TryCatch` in place, your code must bail out. If you do have a `TryCatch` the exception is caught and your code is allowed to continue processing. - -### Inheritance - -JavaScript is a *class-free*, object-oriented language, and as such, it uses prototypal inheritance instead of classical inheritance. This can be puzzling to programmers trained in conventional object-oriented languages like C++ and Java. - -Class-based object-oriented languages, such as Java and C++, are founded on the concept of two distinct entities: classes and instances. JavaScript is a prototype-based language and so does not make this distinction: it simply has objects. JavaScript does not natively support the declaration of class hierarchies; however, JavaScript’s prototype mechanism simplifies the process of adding custom properties and methods to all instances of an object. In JavaScript, you can add custom properties to objects. For example: - -```js -// Create an object named `bicycle`. -function bicycle() {} -// Create an instance of `bicycle` called `roadbike`. -var roadbike = new bicycle(); -// Define a custom property, `wheels`, on `roadbike`. -roadbike.wheels = 2; -``` - -A custom property added this way only exists for that instance of the object. If we create another instance of `bicycle()`, called `mountainbike` for example, `mountainbike.wheels` would return `undefined` unless the `wheels` property is explicitly added. - -Sometimes this is exactly what is required, at other times it would be helpful to add the custom property to all instances of an object - all bicycles have wheels after all. This is where the prototype object of JavaScript is very useful. To use the prototype object, reference the keyword `prototype` on the object before adding the custom property to it as follows: - -```js -// First, create the “bicycle” object -function bicycle() {} -// Assign the wheels property to the object’s prototype -bicycle.prototype.wheels = 2; -``` - -All instances of `bicycle()` will now have the `wheels` property prebuilt into them. - -The same approach is used in V8 with templates. Each `FunctionTemplate` has a `PrototypeTemplate` method which gives a template for the function’s prototype. You can set properties, and associate C++ functions with those properties, on a `PrototypeTemplate` which will then be present on all instances of the corresponding `FunctionTemplate`. For example: - -```cpp -v8::Local biketemplate = v8::FunctionTemplate::New(isolate); -biketemplate->PrototypeTemplate().Set( - v8::String::NewFromUtf8(isolate, "wheels"), - v8::FunctionTemplate::New(isolate, MyWheelsMethodCallback)->GetFunction() -); -``` - -This causes all instances of `biketemplate` to have a `wheels` method in their prototype chain which, when called, causes the C++ function `MyWheelsMethodCallback` to be called. - -V8’s `FunctionTemplate` class provides the public member function `Inherit()` which you can call when you want a function template to inherit from another function template, as follows: - -```cpp -void Inherit(v8::Local parent); -``` diff --git a/src/docs/evaluate-code-coverage.md b/src/docs/evaluate-code-coverage.md deleted file mode 100644 index 1ab41432b..000000000 --- a/src/docs/evaluate-code-coverage.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: 'Evaluating code coverage' -description: 'This document explains what to do if you’re working on a change in V8 and you want to evaluate its code coverage.' ---- -You are working on a change. You want to evaluate code coverage for your new code. - -V8 provides two tools for doing this: local, on your machine; and build infrastructure support. - -## Local - -Relative to the root of the v8 repo, use `./tools/gcov.sh` (tested on linux). This uses gnu’s code coverage tooling and some scripting to produce an HTML report, where you can drill down coverage info per directory, file, and then down to line of code. - -The script builds V8 under a separate `out` directory, using `gcov` settings. We use a separate directory to avoid clobbering your normal build settings. This separate directory is called `cov` — it is created immediately under the repo root. `gcov.sh` then runs the test suite, and produces the report. The path to the report is provided when the script completes. - -If your change has architecture specific components, you can cumulatively collect coverage from architecture specific runs. - -```bash -./tools/gcov.sh x64 arm -``` - -This rebuilds in-place for each architecture, clobbering the binaries from the previous run, but preserving and accumulating over the coverage results. - -By default, the script collects from `Release` runs. If you want `Debug`, you may specify so: - -```bash -BUILD_TYPE=Debug ./tools/gcov.sh x64 arm arm64 -``` - -Running the script with no options will provide a summary of options as well. - -## Code coverage bot - -For each change that landed, we run a x64 coverage analysis — see the [coverage bot](https://ci.chromium.org/p/v8/builders/luci.v8.ci/V8%20Linux64%20-%20gcov%20coverage). We don't run bots for coverage for other architectures. - -To get the report for a particular run, you want to list the build steps, find the “gsutil coverage report” one (towards the end), and open the “report” under it. diff --git a/src/docs/feature-launch-process.md b/src/docs/feature-launch-process.md deleted file mode 100644 index 6967fb3f6..000000000 --- a/src/docs/feature-launch-process.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: 'Implementing and shipping JavaScript/WebAssembly language features' -description: 'This document explains the process for implementing and shipping JavaScript or WebAssembly language features in V8.' ---- -In general, V8 follows the [Blink Intent process for already-defined consensus-based standards](https://www.chromium.org/blink/launching-features/#process-existing-standard) for JavaScript and WebAssembly language features. V8-specific errata are laid out below. Please follow the Blink Intent process, unless the errata tells you otherwise. - -If you have any questions on this topic for JavaScript features, please email syg@chromium.org and v8-dev@googlegroups.com. - -For WebAssembly features, please email gdeepti@chromium.org and v8-dev@googlegroups.com. - -## Errata - -### JavaScript features usually wait until Stage 3+ { #stage3plus } - -As a rule of thumb, V8 waits to implement JavaScript feature proposals until they advance to [Stage 3 or later in TC39](https://tc39.es/process-document/). TC39 has its own consensus process, and Stage 3 or later signals explicit consensus among TC39 delegates, including all browser vendors, that a feature proposal is ready to implement. This external consensus process means Stage 3+ features do not need to send Intent emails other than Intent to Ship. - -### TAG review { #tag } - -For smaller JavaScript or WebAssembly features, a TAG review is not required, as TC39 and the Wasm CG already provide significant technical oversight. If the feature is large or cross-cutting (e.g., requires changes to other Web Platform APIs or modifications to Chromium), TAG review is recommended. - -### Both V8 and blink flags are required { #flags } - -When implementing a feature, both a V8 flag and a blink `base::Feature` are required. - -Blink features are required so that Chrome can turn off features without distributing new binaries in emergency situations. This is usually implemented in [`gin/gin_features.h`](https://source.chromium.org/chromium/chromium/src/+/main:gin/gin_features.h), [`gin/gin_features.cc`](https://source.chromium.org/chromium/chromium/src/+/main:gin/gin_features.cc), and [`gin/v8_initializer.cc`](https://source.chromium.org/chromium/chromium/src/+/main:gin/v8_initializer.cc), - -### Fuzzing is required to ship { #fuzzing } - -JavaScript and WebAssembly features must be fuzzed for a minimum period of 4 weeks, or one (1) release milestone, with all fuzz bugs fixed, before they can be shipped. - -For code-complete JavaScript features, start fuzzing by moving the feature flag to the `JAVASCRIPT_STAGED_FEATURES_BASE` macro in [`src/flags/flag-definitions.h`](https://source.chromium.org/chromium/chromium/src/+/master:v8/src/flags/flag-definitions.h). - -For WebAssembly, see the [WebAssembly shipping checklist](/docs/wasm-shipping-checklist). - -### [Chromestatus](https://chromestatus.com/) and review gates { #chromestatus } - -The blink intent process includes a series of review gates that must be approved on the feature's entry in [Chromestatus](https://chromestatus.com/) before an Intent to Ship is sent out seeking API OWNER approvals. - -These gates are tailored towards web APIs, and some gates may not be applicable to JavaScript and WebAssembly features. The following is broad guidance. The specifics differ from feature to feature; do not apply guidance blindly! - -#### Privacy - -Most JavaScript and WebAssembly features do not affect privacy. Rarely, features may add new fingerprinting vectors that reveal information about a user's operating system or hardware. - -#### Security - -While JavaScript and WebAssembly are common attack vectors in security exploits, most new features do not add additional attack surface. [Fuzzing](#fuzzing) is required, and mitigates some of the risk. - -Features that affect known popular attack vectors, such as `ArrayBuffer`s in JavaScript, and features that might enable side-channel attacks, need extra scrutiny and must be reviewed. - -#### Enterprise - -Throughout their standardization process in TC39 and the Wasm CG, JavaScript and WebAssembly features already undergo heavy backwards compatibility scrutiny. It is exceedingly rare for features to be willfuly backwards incompatible. - -For JavaScript, recently shipped features can also be disabled via `chrome://flags/#disable-javascript-harmony-shipping`. - -#### Debuggability - -JavaScript and WebAssembly features' debuggability differs significantly from feature to feature. JavaScript features that only add new built-in methods do not need additional debugger support, while WebAssembly features that add new capabilities may need significant additional debugger support. - -For more details, see the [JavaScript feature debugging checklist](https://docs.google.com/document/d/1_DBgJ9eowJJwZYtY6HdiyrizzWzwXVkG5Kt8s3TccYE/edit#heading=h.u5lyedo73aa9) and the [WebAssembly feature debugging checklist](https://goo.gle/devtools-wasm-checklist). - -When in doubt, this gate is applicable. - -#### Testing { #tests } - -Instead of WPT, Test262 tests are sufficient for JavaScript features, and WebAssembly spec tests are sufficient for WebAssembly features. - -Adding Web Platform Tests (WPT) is not required, as JavaScript and WebAssembly language features have their own interoperable test repositories that are run by multiple implementations. Feel free to add some though, if you think it is beneficial. - -For JavaScript features, explicit correctness tests in [Test262](https://github.com/tc39/test262) are required. Note that tests in the [staging directory](https://github.com/tc39/test262/blob/main/CONTRIBUTING.md#staging) suffice. - -For WebAssembly features, explicit correctness tests in the [WebAssembly Spec Test repo](https://github.com/WebAssembly/spec/tree/master/test) are required. - -For performance tests, JavaScript already underlies most existing performance benchmarks, like Speedometer. - -### Who to CC { #cc } - -**Every** “intent to `$something`” email (e.g. “intent to implement”) should CC in addition to . This way, other embedders of V8 are kept in the loop too. - -### Link to the spec repo { #spec } - -The Blink Intent process requires an explainer. Instead of writing a new doc, feel free to link to respective spec repository instead (e.g. [`import.meta`](https://github.com/tc39/proposal-import-meta)). diff --git a/src/docs/flake-bisect.md b/src/docs/flake-bisect.md deleted file mode 100644 index f7b99d0f8..000000000 --- a/src/docs/flake-bisect.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: 'Flake bisect' -description: 'This document explains how to bisect flaky tests.' ---- -Flaky tests are reported in a separate step on the bots ([example build](https://ci.chromium.org/ui/p/v8/builders/ci/V8%20Linux64%20TSAN/38630/overview)). - -Each test log provides a pre-filled command line for triggering an automated flake bisect, like: - -``` -Trigger flake bisect on command line: -bb add v8/try.triggered/v8_flako -p 'to_revision="deadbeef"' -p 'test_name="MyTest"' ... -``` - -Before triggering flake bisects for the first time, users must log in with a google.com account: - -```bash -bb auth-login -``` - -Then execute the provided command, which returns a build URL running flake bisect ([example](https://ci.chromium.org/ui/p/v8/builders/try.triggered/v8_flako/b8836020260675019825/overview)). - -If you’re in luck, bisection points you to a suspect. If not, you might want to read further… - -## Detailed description - -For technical details, see also the implementation [tracker bug](https://crbug.com/711249). The flake bisect approach has the same intentions as [findit](https://sites.google.com/chromium.org/cat/findit), but uses a different implementation. - -### How does it work? - -A bisect job has 3 phases: calibration, backwards and inwards bisection. During calibration, testing is repeated doubling the total timeout (or the number of repetitions) until enough flakes are detected in one run. Then, backwards bisection doubles the git range until a revision without flakes is found. At last, we bisect into the range of the good revision and the oldest bad one. Note, bisection doesn't produce new build products, it is purely based on builds previously created on V8's continuous infrastructure. - -### Bisection fails when… - -- No confidence can be reached during calibration. This is typical for one-in-a-million flakes or flaky behavior only visible when other tests run in parallel (e.g. memory hungry tests). -- The culprit is too old. Bisection bails out after a certain number of steps, or if older builds are not available anymore on the isolate server. -- The overall bisect job times out. In this case it might be possible to restart it with an older known bad revision. - -## Properties for customizing flake bisect - -- `extra_args`: Extra arguments passed to V8’s `run-tests.py` script. -- repetitions: Initial number of test repetitions (passed to `run-tests.py`'s `--random-seed-stress-count` option; unused if `total_timeout_sec` is used). -- `timeout_sec`: Timeout parameter passed to `run-tests.py`. -- `to_revision`: Revision known to be bad. This is where bisection will start. -- `total_timeout_sec`: Initial total timeout for one entire bisect step. During calibration, this time is doubled several times if needed. Set to 0 to disable and use the `repetitions` property instead. -- `variant`: Name of the testing variant passed to `run-tests.py`. - -## Properties you won’t need to change - -- `bisect_buildername`: Master name of the builder that produced the builds for bisection. -- `bisect_mastername`: Name of the builder that produced the builds for bisection. -- `build_config`: Build config passed to V8’s `run-tests.py` script (there the parameter name is `--mode`, example: `Release` or `Debug`). -- `isolated_name`: Name of the isolated file (e.g. `bot_default`, `mjsunit`). -- `swarming_dimensions`: Swarming dimensions classifying the type of bot the tests should run on. Passed as list of strings, each in the format `name:value`. -- `test_name`: Fully qualified test name passed to run-tests.py. E.g. `mjsunit/foobar`. - -## Tips and tricks - -### Bisecting a hanging test (e.g. dead lock) - -If a failing run times out, while a pass is running very fast, it is useful to tweak the timeout_sec parameter, so that bisection is not delayed waiting for the hanging runs to time out. E.g. if the pass is usually reached in <1 second, set the timeout to something small, e.g. 5 seconds. - -### Getting more confidence on a suspect - -In some runs, confidence is very low. E.g. calibration is satisfied if four flakes are seen in one run. During bisection, every run with one or more flakes is counted as bad. In such cases it might be useful to restart the bisect job setting to_revision to the culprit and using a higher number of repetitions or total timeout than the original job and confirm that the same conclusion is reached again. - -### Working around timeout issues - -In case the overall timeout option causes builds to hang, it’s best to estimate a fitting number of repetitions and set `total_timeout_sec` to `0`. - -### Test behavior depending on random seed - -Rarely, a code path is only triggered with a particular random seed. In this case it might be beneficial to fix it using `extra_args`, e.g. `"extra_args": ["--random-seed=123"]`. Otherwise, the stress runner uses different random seeds throughout. Note though that a particular random seed might reproduce a problem in one revision, but not in another. diff --git a/src/docs/gdb-jit.md b/src/docs/gdb-jit.md deleted file mode 100644 index 01efd4573..000000000 --- a/src/docs/gdb-jit.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: 'GDB JIT Compilation Interface integration' -description: 'GDB JIT Compilation Interface integration allows V8 to provide GDB with the symbol and debugging information for native code emitted from the V8 runtime.' ---- -GDB JIT Compilation Interface integration allows V8 to provide GDB with the symbol and debugging information for native code emitted from the V8 runtime. - -When GDB JIT Compilation Interface is disabled a typical backtrace in GDB contains frames marked with `??`. These frames correspond to dynamically generated code: - -``` -#8 0x08281674 in v8::internal::Runtime_SetProperty (args=...) at src/runtime.cc:3758 -#9 0xf5cae28e in ?? () -#10 0xf5cc3a0a in ?? () -#11 0xf5cc38f4 in ?? () -#12 0xf5cbef19 in ?? () -#13 0xf5cb09a2 in ?? () -#14 0x0809e0a5 in v8::internal::Invoke (construct=false, func=..., receiver=..., argc=0, args=0x0, - has_pending_exception=0xffffd46f) at src/execution.cc:97 -``` - -However enabling GDB JIT Compilation Interface allows GDB to produce more informative stack trace: - -``` -#6 0x082857fc in v8::internal::Runtime_SetProperty (args=...) at src/runtime.cc:3758 -#7 0xf5cae28e in ?? () -#8 0xf5cc3a0a in loop () at test.js:6 -#9 0xf5cc38f4 in test.js () at test.js:13 -#10 0xf5cbef19 in ?? () -#11 0xf5cb09a2 in ?? () -#12 0x0809e1f9 in v8::internal::Invoke (construct=false, func=..., receiver=..., argc=0, args=0x0, - has_pending_exception=0xffffd44f) at src/execution.cc:97 -``` - -Frames still unknown to GDB correspond to native code without source information. See [known limitations](#known-limitations) for more details. - -GDB JIT Compilation Interface is specified in the GDB documentation: - -## Prerequisites - -- V8 v3.0.9 or newer -- GDB 7.0 or newer -- Linux OS -- CPU with Intel-compatible architecture (ia32 or x64) - -## Enabling GDB JIT Compilation Interface - -GDB JIT Compilation Interface is currently excluded from the compilation by default and disabled in runtime. To enable it: - -1. Build V8 library with `ENABLE_GDB_JIT_INTERFACE` defined. If you are using scons to build V8 run it with `gdbjit=on`. -1. Pass `--gdbjit` flag when starting V8. - -To check that you have enabled GDB JIT integration correctly try setting a breakpoint on `__jit_debug_register_code`. This function is invoked to notify GDB about new code objects. - -## Known limitations - -- GDB side of JIT Interface currently (as of GDB 7.2) does not handle registration of code objects very effectively. Each next registration takes more time: with 500 registered objects each next registration takes more than 50ms, with 1000 registered code objects - more than 300 ms. This problem was [reported to GDB developers](https://sourceware.org/ml/gdb/2011-01/msg00002.html) but currently there is no solution available. To reduce pressure on GDB current implementation of GDB JIT integration operates in two modes: _default_ and _full_ (enabled by `--gdbjit-full` flag). In _default_ mode V8 notifies GDB only about code objects that have source information attached (this usually includes all user scripts). In _full_ - about all generated code objects (stubs, ICs, trampolines). - -- On x64 GDB is unable to properly unwind stack without `.eh_frame` section ([Issue 1053](https://bugs.chromium.org/p/v8/issues/detail?id=1053)) - -- GDB is not notified about code deserialized from the snapshot ([Issue 1054](https://bugs.chromium.org/p/v8/issues/detail?id=1054)) - -- Only Linux OS on Intel-compatible CPUs is supported. For different OSes either a different ELF-header should be generated or a completely different object format should be used. - -- Enabling GDB JIT interface disables compacting GC. This is done to reduce pressure on GDB as unregistering and registering each moved code object will incur considerable overhead. - -- GDB JIT integration provides only _approximate_ source information. It does not provide any information about local variables, function’s arguments, stack layout etc. It does not enable stepping through JavaScript code or setting breakpoint on the given line. However one can set a breakpoint on a function by its name. diff --git a/src/docs/gdb.md b/src/docs/gdb.md deleted file mode 100644 index c63bf7f7c..000000000 --- a/src/docs/gdb.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: 'Debugging builtins with GDB' -description: 'As of V8 v6.9, it’s possible to create breakpoints in GDB to debug CSA / ASM / Torque builtins.' ---- -As of V8 v6.9, it’s possible to create breakpoints in GDB (and possibly other debuggers) to debug CSA / ASM / Torque builtins. - -``` -(gdb) tb i::Isolate::Init -Temporary breakpoint 1 at 0x7ffff706742b: i::Isolate::Init. (2 locations) -(gdb) r -Thread 1 "d8" hit Temporary breakpoint 1, 0x00007ffff7c55bc0 in Isolate::Init -(gdb) br Builtins_RegExpPrototypeExec -Breakpoint 2 at 0x7ffff7ac8784 -(gdb) c -Thread 1 "d8" hit Breakpoint 2, 0x00007ffff7ac8784 in Builtins_RegExpPrototypeExec () -``` - -Note that it works well to use a temporary breakpoint (shortcut `tb` in GDB) instead of a regular breakpoint (`br`) for this, since you only need it at process start. - -Builtins are also visible in stack traces: - -``` -(gdb) bt -#0 0x00007ffff7ac8784 in Builtins_RegExpPrototypeExec () -#1 0x00007ffff78f5066 in Builtins_ArgumentsAdaptorTrampoline () -#2 0x000039751d2825b1 in ?? () -#3 0x000037ef23a0fa59 in ?? () -#4 0x0000000000000000 in ?? () -``` - -Caveats: - -- Only works with embedded builtins. -- Breakpoints can only be set at the start of the builtin. -- The initial breakpoint in `Isolate::Init` is needed prior to setting the builtin breakpoint, since GDB modifies the binary and we verify a hash of the builtins section in the binary at startup. Otherwise, V8 complains about a hash mismatch: - - ``` - # Fatal error in ../../src/isolate.cc, line 117 - # Check failed: d.Hash() == d.CreateHash() (11095509419988753467 vs. 3539781814546519144). - ``` diff --git a/src/docs/hidden-classes.md b/src/docs/hidden-classes.md deleted file mode 100644 index 1374f53b9..000000000 --- a/src/docs/hidden-classes.md +++ /dev/null @@ -1,233 +0,0 @@ ---- -title: 'Maps (Hidden Classes) in V8' -description: 'How does V8 track and optimize the perceived structure of your objects?' ---- - -Let's show how V8 builds it's hidden classes. The principal data structures are: - -- `Map`: the hidden class itself. It's the first pointer value in an object and therefore allows easy comparison to see if two objects have the same class. -- `DescriptorArray`: The full list of properties that this class has along with information about them. In some cases, the property value is even in this array. -- `TransitionArray`: An array of "edges" from this `Map` to sibling Maps. Each edge is a property name, and should be thought of as "if I were to add a property with this name to the current class, what class would I transition to?" - -Because many `Map` objects only have one transition to another one (ie, they are "transitional" maps, only used on the way to something else), V8 doesn't always create a full-blown `TransitionArray` for it. Instead it'll just link directly to this "next" `Map`. The system has to do a bit of spelunking in the `DescriptorArray` of the `Map` being pointed to in order to figure out the name attached to the transition. - -This is an extremely rich subject. It's also subject to change, though, if you understand the concepts in this article future change should be incrementally understandable. - -## Why have hidden classes? - -V8 could do without hidden classes, sure. It would treat each object as a bag of properties. However, a very useful principle would have been left laying around: the principal of intelligent design. V8 surmises that you'll only create so many **different** kinds of objects. And each kind of object will be used in what can eventually be seen to be stereotypical ways. I say "eventually be seen" because the JavaScript language is a scripting language, not a pre-compiled one. So V8 never knows what will come next. To make use of intelligent design (that is, the assumption that there is a mind behind the code coming in), V8 has to watch and wait, letting the sense of structure seep in. The hidden class mechanism is the principal means to do this. Of course, it presupposes a sophisticated listening mechanism, and these are the Inline Caches (ICs) about which much has been written. - -So, if you are convinced this is good and necessary work, follow me! - -## An example - -```javascript -function Peak(name, height, extra) { - this.name = name; - this.height = height; - if (isNaN(extra)) { - this.experience = extra; - } else { - this.prominence = extra; - } -} - -m1 = new Peak("Matterhorn", 4478, 1040); -m2 = new Peak("Wendelstein", 1838, "good"); -``` - -With this code we've already got an interesting map tree from the root map (also known as the initial map) which is attached to the function `Peak`: - -
- Hidden class example -
- -Each blue box is a map, starting with the initial map. This is the map of the object returned if somehow, we managed to run the function `Peak` without adding a single property. The follow-on maps are the ones that result by adding the properties given by the names on the edges between maps. Each map has a list of the properties associated with an object of that map. Furthermore, it describes the exact location of each property. Finally, from one of these maps, say, `Map3` which is the hidden class of the object you'll get if you passed a number for the `extra` argument in `Peak()`, you can follow a back link up all the way to the initial map. - -Let's draw it again with this extra information. The annotation (i0), (i1), means in-object field location 0, 1, etc: - -
- Hidden class example -
- -Now, if you spend time examining these maps before you've created at least 7 `Peak` objects, you'll encounter **slack tracking** which can be confusing. I have [another article](https://v8.dev/blog/slack-tracking) about that. Just create 7 more objects and it will be finished. At this point, your Peak objects will have exactly 3 in-object properties, with no possibility to add more directly in the object. Any additional properties will be offloaded to the object's property backing store. It's just an array of property values, whose index comes from the map (Well, technically, from the `DescriptorArray` attached to the map). Let's add a property to `m2` on a new line, and look again at the map tree: - -```javascript -m2.cost = "one arm, one leg"; -``` - -
- Hidden class example -
- -I snuck something in here. Notice that all of the properties are annotated with "const," which means that from V8's point of view, nobody ever changed them since the constructor, so they can be considered constants once they've been initialized. TurboFan (the optimizing compiler) loves this. Say `m2` is referenced as a constant global by a function. Then the lookup of `m2.cost` can be done at compile time, since the field is marked as constant. I'll return to this later in the article. - -Notice that property "cost" is marked as `const p0`, which means it's a constant property stored at index zero in the **properties backing store** rather than in the object directly. This is because we have no more room in the object. This information is visible in `%DebugPrint(m2)`: - -``` -d8> %DebugPrint(m2); -DebugPrint: 0x2f9488e9: [JS_OBJECT_TYPE] - - map: 0x219473fd [FastProperties] - - prototype: 0x2f94876d - - elements: 0x419421a1 [HOLEY_ELEMENTS] - - properties: 0x2f94aecd { - 0x419446f9: [String] in ReadOnlySpace: #name: 0x237125e1 - (const data field 0) - 0x23712581: [String] in OldSpace: #height: - 1838 (const data field 1) - 0x23712865: [String] in OldSpace: #experience: 0x237125f9 - (const data field 2) - 0x23714515: [String] in OldSpace: #cost: 0x23714525 - - (const data field 3) properties[0] - } - ... -{name: "Wendelstein", height: 1, experience: "good", cost: "one arm, one leg"} -d8> -``` - -You can see that we have 4 properties, all marked as const. The first 3 in the object, and the last in `properties[0]` which means the first slot of the properties backing store. We can look at that: - -``` -d8> %DebugPrintPtr(0x2f94aecd) -DebugPrint: 0x2f94aecd: [PropertyArray] - - map: 0x41942be9 - - length: 3 - - hash: 0 - 0: 0x23714525 - 1-2: 0x41942329 -``` - -The extra properties are there just in case you decide to add more all of a sudden. - -## The real structure - -There are different things we could do at this point, but since you must really like V8, having read this far, I'd like to try drawing the real data structures we use, the ones mentioned at the beginning of `Map`, `DescriptorArray`, and `TransitionArray`. Now that you have some idea of the hidden class concept being built up behind the scenes, you may as well bind your thinking more closely to the code through the right names and structures. Let me try and reproduce that last figure in V8's representation. First I'm going to draw the **DescriptorArrays**, which hold the list of properties for a given Map. These arrays can be shared -- the key to that is that the Map itself knows how many properties it is allowed to look at in the DescriptorArray. Since the properties are in the order they were added in time, these arrays can be shared by several maps. See: - -
- Hidden class example -
- -Notice that **Map1**, **Map2**, and **Map3** all point to **DescriptorArray1**. The number next to the "descriptors" field in each Map indicates how many fields over in the DescriptorArray belong to the Map. So **Map1**, which only knows about the "name" property, looks only at the first property listed in **DescriptorArray1**. Whereas **Map2** has two properties, "name" and "height." So it looks at the first and second items in **DescriptorArray1** (name and height). This kind of sharing saves a lot of space. - -Naturally, we can't share where there is a split. There is a transition from Map2 over to Map4 if the "experience" property is added, and over to Map3 if the "prominence" property is added. You can see Map4 and Map5 sharing DescriptorArray2 in the same way that DescriptorArray1 was shared among three Maps. - -The only thing missing from our "true to life" diagram is the `TransitionArray` which is still metaphorical at this point. Let's change that. I took the liberty of removing the **back pointer** lines, which cleans things up a bit. Just remember that from any Map in the tree, you can walk up the tree, too. - -
- Hidden class example -
- -The diagram rewards study. **Question: what would happen if a new property "rating" was added after "name" instead of going on to "height" and other properties?** - -**Answer**: Map1 would get a real **TransitionArray** so as to keep track of the bifurcation. If property *height* is added, we should transition to **Map2**. However, if property *rating* is added, we should go to a new map, **Map6**. This map would need a new DescriptorArray that mentions *name* and *rating*. The object has extra free slots at this point in the object (only one of three is used), so property *rating* will be given one of those slots. - -*I checked my answer with the help of `%DebugPrintPtr()`, and drew the following:* - -
- Hidden class example -
- -No need to beg me to stop, I see that this is the upper limit of such diagrams! But I think you can get a sense of how the parts move. Just imagine if after adding this ersatz property *rating*, we continued on with *height*, *experience* and *cost*. Well, we'd have to create maps **Map7**, **Map8** and **Map9**. Because we insisted on adding this property in the middle of an established chain of maps, we will duplicate much structure. I don't have the heart to make that drawing -- though if you send it to me I will add it to this document :). - -I used the handy [DreamPuf](https://dreampuf.github.io/GraphvizOnline) project to make the diagrams easily. Here is a [link](https://dreampuf.github.io/GraphvizOnline/#digraph%20G%20%7B%0A%0A%20%20node%20%5Bfontname%3DHelvetica%2C%20shape%3D%22record%22%2C%20fontcolor%3D%22white%22%2C%20style%3Dfilled%2C%20color%3D%22%233F53FF%22%5D%0A%20%20edge%20%5Bfontname%3DHelvetica%5D%0A%20%20%0A%20%20Map0%20%5Blabel%3D%22%7B%3Ch%3E%20Map0%20%7C%20%3Cd%3E%20descriptors%20(0)%20%7C%20%3Ct%3E%20transitions%20(1)%7D%22%5D%3B%0A%20%20Map1%20%5Blabel%3D%22%7B%3Ch%3E%20Map1%20%7C%20%3Cd%3E%20descriptors%20(1)%20%7C%20%3Ct%3E%20transitions%20(1)%7D%22%5D%3B%0A%20%20Map2%20%5Blabel%3D%22%7B%3Ch%3E%20Map2%20%7C%20%3Cd%3E%20descriptors%20(2)%20%7C%20%3Ct%3E%20transitions%20(2)%7D%22%5D%3B%0A%20%20Map3%20%5Blabel%3D%22%7B%3Ch%3E%20Map3%20%7C%20%3Cd%3E%20descriptors%20(3)%20%7C%20%3Ct%3E%20transitions%20(0)%7D%22%5D%0A%20%20Map4%20%5Blabel%3D%22%7B%3Ch%3E%20Map4%20%7C%20%3Cd%3E%20descriptors%20(3)%20%7C%20%3Ct%3E%20transitions%20(1)%7D%22%5D%0A%20%20Map5%20%5Blabel%3D%22%7B%3Ch%3E%20Map5%20%7C%20%3Cd%3E%20descriptors%20(4)%20%7C%20%3Ct%3E%20transitions%20(0)%7D%22%5D%0A%20%20Map6%20%5Blabel%3D%22%7B%3Ch%3E%20Map6%20%7C%20%3Cd%3E%20descriptors%20(2)%20%7C%20%3Ct%3E%20transitions%20(0)%7D%22%5D%3B%0A%20%20Map0%3At%20-%3E%20Map1%20%5Blabel%3D%22name%20(inferred)%22%5D%3B%0A%20%20%0A%20%20Map4%3At%20-%3E%20Map5%20%5Blabel%3D%22cost%20(inferred)%22%5D%3B%0A%20%20%0A%20%20%2F%2F%20Create%20the%20descriptor%20arrays%0A%20%20node%20%5Bfontname%3DHelvetica%2C%20shape%3D%22record%22%2C%20fontcolor%3D%22black%22%2C%20style%3Dfilled%2C%20color%3D%22%23FFB34D%22%5D%3B%0A%20%20%0A%20%20DA0%20%5Blabel%3D%22%7BDescriptorArray0%20%7C%20(empty)%7D%22%5D%0A%20%20Map0%3Ad%20-%3E%20DA0%3B%0A%20%20DA1%20%5Blabel%3D%22%7BDescriptorArray1%20%7C%20name%20(const%20i0)%20%7C%20height%20(const%20i1)%20%7C%20prominence%20(const%20i2)%7D%22%5D%3B%0A%20%20Map1%3Ad%20-%3E%20DA1%3B%0A%20%20Map2%3Ad%20-%3E%20DA1%3B%0A%20%20Map3%3Ad%20-%3E%20DA1%3B%0A%20%20%0A%20%20DA2%20%5Blabel%3D%22%7BDescriptorArray2%20%7C%20name%20(const%20i0)%20%7C%20height%20(const%20i1)%20%7C%20experience%20(const%20i2)%20%7C%20cost%20(const%20p0)%7D%22%5D%3B%0A%20%20Map4%3Ad%20-%3E%20DA2%3B%0A%20%20Map5%3Ad%20-%3E%20DA2%3B%0A%20%20%0A%20%20DA3%20%5Blabel%3D%22%7BDescriptorArray3%20%7C%20name%20(const%20i0)%20%7C%20rating%20(const%20i1)%7D%22%5D%3B%0A%20%20Map6%3Ad%20-%3E%20DA3%3B%0A%20%20%0A%20%20%2F%2F%20Create%20the%20transition%20arrays%0A%20%20node%20%5Bfontname%3DHelvetica%2C%20shape%3D%22record%22%2C%20fontcolor%3D%22white%22%2C%20style%3Dfilled%2C%20color%3D%22%23B3813E%22%5D%3B%0A%20%20TA0%20%5Blabel%3D%22%7BTransitionArray0%20%7C%20%3Ca%3E%20experience%20%7C%20%3Cb%3E%20prominence%7D%22%5D%3B%0A%20%20Map2%3At%20-%3E%20TA0%3B%0A%20%20TA0%3Aa%20-%3E%20Map4%3Ah%3B%0A%20%20TA0%3Ab%20-%3E%20Map3%3Ah%3B%0A%20%20%0A%20%20TA1%20%5Blabel%3D%22%7BTransitionArray1%20%7C%20%3Ca%3E%20rating%20%7C%20%3Cb%3E%20height%7D%22%5D%3B%0A%20%20Map1%3At%20-%3E%20TA1%3B%0A%20%20TA1%3Ab%20-%3E%20Map2%3B%0A%20%20TA1%3Aa%20-%3E%20Map6%3B%0A%7D) to the previous diagram. - -## TurboFan and const properties - -Thus far, all these fields are marked in the `DescriptorArray` as `const`. Let's play with this. Run the following code on a debug build: - -```javascript -// run as: -// d8 --allow-natives-syntax --no-lazy-feedback-allocation --code-comments --print-opt-code -function Peak(name, height) { - this.name = name; - this.height = height; -} - -let m1 = new Peak("Matterhorn", 4478); -m2 = new Peak("Wendelstein", 1838); - -// Make sure slack tracking finishes. -for (let i = 0; i < 7; i++) new Peak("blah", i); - -m2.cost = "one arm, one leg"; -function foo(a) { - return m2.cost; -} - -foo(3); -foo(3); -%OptimizeFunctionOnNextCall(foo); -foo(3); -``` - -You'll get a printout of optimized function `foo()`. The code is very short. You'll see at the end of the function: - -``` -... -40 mov eax,0x2a812499 ;; object: 0x2a812499 -45 mov esp,ebp -47 pop ebp -48 ret 0x8 ;; return "one arm, one leg"! -``` - -TurboFan, being a cheeky devil, just directly inserted the value of `m2.cost`. Well how do you like that! - -Of course, after that last call to `foo()` you could insert this line: - -```javascript -m2.cost = "priceless"; -``` - -What do you think will happen? One thing for sure, we can't let `foo()` stay as it is. It would return the wrong answer. Re-run the program, but add flag `--trace-deopt` so you'll be told when optimized code is removed from the system. After the printout of the optimized `foo()`, you'll see these lines: - -``` -[marking dependent code 0x5c684901 0x21e525b9 (opt #0) for deoptimization, - reason: field-const] -[deoptimize marked code in all contexts] -``` - -Wow. - -
- I like it a lot -
- -If you force re-optimization you'll get code that is not quite as good, but still benefits greatly from the Map structure we've been describing. Remember from our diagrams that property *cost* is the first property in -the properties backing store for an object. Well, it may have lost it's const designation, but we still have it's address. Basically, in an object with map **Map5**, which we'll certainly verify that global variable `m2` still has, we only have to-- - -1. load the properties backing store, and -2. read out the first array element. - -Let's see that. Add this code below the last line: - -```javascript -// Force reoptimization of foo(). -foo(3); -%OptimizeFunctionOnNextCall(foo); -foo(3); -``` - -Now have a look at the code produced: - -``` -... -40 mov ecx,0x42cc8901 ;; object: 0x42cc8901 -45 mov ecx,[ecx+0x3] ;; Load the properties backing store -48 mov eax,[ecx+0x7] ;; Get the first element. -4b mov esp,ebp -4d pop ebp -4e ret 0x8 ;; return it in register eax! -``` - -Why heck. That's exactly what we said should happen. Perhaps we are beginning to Know. - -TurboFan is also smart enough to deoptimize if variable `m2` ever changes to a different class. You can watch the latest optimized code deoptimize again with something droll like: - -```javascript -m2 = 42; // heh. -``` - -## Where to go from here - -Many options. Map migration. Dictionary mode (aka "slow mode"). Lots to explore in this area and I hope you enjoy yourself as much as I do -- thanks for reading! diff --git a/src/docs/i18n.md b/src/docs/i18n.md deleted file mode 100644 index 6cadb3efc..000000000 --- a/src/docs/i18n.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: 'i18n support' -description: 'V8 optionally implements the ECMAScript 402 specification. The API is enabled by default, but can be turned off at compile time.' ---- -V8 optionally implements [the ECMAScript 402 specification](https://tc39.es/ecma402/). The API is enabled by default, but can be turned off at compile time. - -## Prerequisites - -The i18n implementation adds a dependency on ICU. As of v7.2, V8 requires at least ICU version 63. The exact dependency is specified in [V8’s `DEPS` file](https://chromium.googlesource.com/v8/v8.git/+/master/DEPS). - -Run the following command to check out a suitable version of ICU into `third_party/icu`: - -```bash -gclient sync -``` - -See [“staying up to date”](/docs/source-code#staying-up-to-date) for more details. - -## Alternative ICU checkout - -You can check out the ICU sources at a different location and define the gyp variable `icu_gyp_path` to point at the `icu.gyp` file. - -## System ICU - -Last but not least, you can compile V8 against a version of ICU installed in your system. To do so, specify the GYP variable `use_system_icu=1`. If you also have `want_separate_host_toolset` enabled, the bundled ICU is still compiled to generate the V8 snapshot. The system ICU is only used for the target architecture. - -## Embedding V8 - -If you embed V8 in your application, but your application itself doesn’t use ICU, you need to initialize ICU before calling into V8 by executing: - -```cpp -v8::V8::InitializeICU(); -``` - -It is safe to invoke this method if ICU was not compiled in, then it does nothing. - -## Compiling without i18n support - -To build V8 without i18n support, use [`gn args`](/docs/build-gn#gn) to set `v8_enable_i18n_support = false` before compiling. diff --git a/src/docs/ide-setup.md b/src/docs/ide-setup.md deleted file mode 100644 index 3fc3a19b5..000000000 --- a/src/docs/ide-setup.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -title: 'GUI and IDE setup' -description: 'This document contains GUI and IDE-specific tips for working on the V8 code base.' ---- -The V8 source code can be browsed online with [Chromium Code Search](https://cs.chromium.org/chromium/src/v8/). - -This project’s Git repository may be accessed using many other client programs and plug-ins. See your client’s documentation for more information. - -## Visual Studio Code and clangd - -For instructions how to set up VSCode for V8, see this [document](https://docs.google.com/document/d/1BpdCFecUGuJU5wN6xFkHQJEykyVSlGN8B9o3Kz2Oes8/). This is currently (2021) the recommended setup. - -## Eclipse - -For instructions how to set up Eclipse for V8, see this [document](https://docs.google.com/document/d/1q3JkYNJhib3ni9QvNKIY_uarVxeVDiDi6teE5MbVIGQ/). Note: as of 2020, indexing V8 with Eclipse does not work well. - -## Visual Studio Code and cquery - -VSCode and cquery provide good code navigation capabilities. It offers “go to definition” as well as “find all references” for C++ symbols and works quite well. This section describes how to get a basic setup on a *nix system. - -### Install VSCode - -Install VSCode in your preferred way. The rest of this guide assumes that you can run VSCode from the command line via the command `code`. - -### Install cquery - -Clone cquery from [cquery](https://github.com/cquery-project/cquery) in a directory of your choice. We use `CQUERY_DIR="$HOME/cquery"` in this guide. - -```bash -git clone https://github.com/cquery-project/cquery "$CQUERY_DIR" -cd "$CQUERY_DIR" -git submodule update --init -mkdir build -cd build -cmake .. -DCMAKE_BUILD_TYPE=release -DCMAKE_INSTALL_PREFIX=release -DCMAKE_EXPORT_COMPILE_COMMANDS=YES -make install -j8 -``` - -If anything goes wrong, be sure to check out [cquery’s getting started guide](https://github.com/cquery-project/cquery/wiki). - -You can use `git pull && git submodule update` to update cquery at a later time (don't forget to rebuild via `cmake .. -DCMAKE_BUILD_TYPE=release -DCMAKE_INSTALL_PREFIX=release -DCMAKE_EXPORT_COMPILE_COMMANDS=YES && make install -j8`). - -### Install and configure cquery-plugin for VSCode - -Install the cquery extension from the marketplace in VSCode. Open VSCode in your V8 checkout: - -```bash -cd v8 -code . -``` - -Go to settings in VSCode, for example, via the shortcut Ctrl + ,. - -Add the following to your workspace configuration, replacing `YOURUSERNAME` and `YOURV8CHECKOUTDIR` appropriately. - -```json -"settings": { - "cquery.launch.command": "/home/YOURUSERNAME/cquery/build/release/bin/cquery", - "cquery.cacheDirectory": "/home/YOURUSERNAME/YOURV8CHECKOUTDIR/.vscode/cquery_cached_index/", - "cquery.completion.include.blacklist": [".*/.vscache/.*", "/tmp.*", "build/.*"], - […] -} -``` - -### Provide `compile_commands.json` to cquery - -The last step is to generate a compile_commands.json to cquery. This file will contain the specific compiler command lines used to build V8 to cquery. Run the following command in the V8 checkout: - -```bash -ninja -C out.gn/x64.release -t compdb cxx cc > compile_commands.json -``` - -This needs to be re-executed from time to time to teach cquery about new source files. In particular, you should always re-run the command after a `BUILD.gn` was changed. - -### Other useful settings - -The auto-closing of parenthesis in Visual Studio Code does not work that well. It can be disabled with - -```json -"editor.autoClosingBrackets": false -``` - -in the user settings. - -The following exclusion masks help avoid unwanted results when using search (Ctrl+Shift+F): - -```js -"files.exclude": { - "**/.vscode": true, // this is a default value -}, -"search.exclude": { - "**/out*": true, // this is a default value - "**/build*": true // this is a default value -}, -``` diff --git a/src/docs/ignition.md b/src/docs/ignition.md deleted file mode 100644 index a32e6cc84..000000000 --- a/src/docs/ignition.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: 'Ignition' -description: 'This document collects resources about Ignition, V8’s interpreter.' ---- -V8 features an interpreter called Ignition. Ignition is a fast low-level register-based interpreter written using the backend of [TurboFan](/docs/turbofan). The V8 blog post presents a [high-level overview](/blog/ignition-interpreter) of the Ignition interpreter. More details can be found in the following resources: - -## Talks - -- [V8: Hooking up the Ignition to the Turbofan](https://docs.google.com/presentation/d/1chhN90uB8yPaIhx_h2M3lPyxPgdPmkADqSNAoXYQiVE/edit) -- [Ignition: jump-starting an interpreter for V8](https://docs.google.com/presentation/d/1HgDDXBYqCJNasBKBDf9szap1j4q4wnSHhOYpaNy5mHU/edit#slide=id.g1357e6d1a4_0_58) -- [Ignition: an interpreter for V8](https://docs.google.com/presentation/d/1OqjVqRhtwlKeKfvMdX6HaCIu9wpZsrzqpIVIwQSuiXQ/edit) ([video](https://youtu.be/r5OWCtuKiAk)) - -## Articles - -- [Understanding V8’s bytecode](https://medium.com/dailyjs/understanding-v8s-bytecode-317d46c94775) - -## Design Docs - -- [Ignition design document](https://docs.google.com/document/d/11T2CRex9hXxoJwbYqVQ32yIPMh0uouUZLdyrtmMoL44/edit?ts=56f27d9d#heading=h.6jz9dj3bnr8t) -- [Register equivalence optimization](https://docs.google.com/document/d/1wW_VkkIwhAAgAxLYM0wvoTEkq8XykibDIikGpWH7l1I/edit?ts=570d7131#heading=h.6jz9dj3bnr8t) diff --git a/src/docs/index.md b/src/docs/index.md deleted file mode 100644 index c92adcddb..000000000 --- a/src/docs/index.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: 'Documentation' -description: 'Documentation for the V8 project.' ---- -V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++. It is used in Chrome and in Node.js, among others. - -This documentation is aimed at C++ developers who want to use V8 in their applications, as well as anyone interested in V8’s design and performance. This document introduces you to V8, while the remaining documentation shows you how to use V8 in your code and describes some of its design details, as well as providing a set of JavaScript benchmarks for measuring V8’s performance. - -## About V8 - -V8 implements ECMAScript and WebAssembly, and runs on Windows, macOS, and Linux systems that use x64, IA-32, or ARM processors. Additional systems (IBM i, AIX) and processors (MIPS, ppcle64, s390x) are externally maintained, see [ports](/docs/ports). V8 can be embedded into any C++ application. - -V8 compiles and executes JavaScript source code, handles memory allocation for objects, and garbage collects objects it no longer needs. V8’s stop-the-world, generational, accurate garbage collector is one of the keys to V8’s performance. - -JavaScript is commonly used for client-side scripting in a browser, being used to manipulate Document Object Model (DOM) objects for example. The DOM is not, however, typically provided by the JavaScript engine but instead by a browser. The same is true of V8 — Google Chrome provides the DOM. V8 does however provide all the data types, operators, objects and functions specified in the ECMA standard. - -V8 enables any C++ application to expose its own objects and functions to JavaScript code. It’s up to you to decide on the objects and functions you would like to expose to JavaScript. - -## Documentation overview - -- [Building V8 from source](/docs/build) - - [Checking out the V8 source code](/docs/source-code) - - [Building with GN](/docs/build-gn) - - [Cross-compiling and debugging for ARM/Android](/docs/cross-compile-arm) - - [Cross-compiling for iOS](/docs/cross-compile-ios) - - [GUI and IDE setup](/docs/ide-setup) - - [Compiling on Arm64](/docs/compile-arm64) -- [Contributing](/docs/contribute) - - [Respectful code](/docs/respectful-code) - - [V8’s public API and its stability](/docs/api) - - [Becoming a V8 committer](/docs/become-committer) - - [Committer’s responsibility](/docs/committer-responsibility) - - [Blink web tests (a.k.a. layout tests)](/docs/blink-layout-tests) - - [Evaluating code coverage](/docs/evaluate-code-coverage) - - [Release process](/docs/release-process) - - [Design review guidelines](/docs/design-review-guidelines) - - [Implementing and shipping JavaScript/WebAssembly language features](/docs/feature-launch-process) - - [Checklist for staging and shipping of WebAssembly features](/docs/wasm-shipping-checklist) - - [Flake bisect](/docs/flake-bisect) - - [Handling of ports](/docs/ports) - - [Official support](/docs/official-support) - - [Merging & patching](/docs/merge-patch) - - [Node.js integration build](/docs/node-integration) - - [Reporting security bugs](/docs/security-bugs) - - [Running benchmarks locally](/docs/benchmarks) - - [Testing](/docs/test) - - [Triaging issues](/docs/triage-issues) -- Debugging - - [Arm debugging with the simulator](/docs/debug-arm) - - [Cross-compiling and debugging for ARM/Android](/docs/cross-compile-arm) - - [Debugging builtins with GDB](/docs/gdb) - - [Debugging over the V8 Inspector Protocol](/docs/inspector) - - [GDB JIT Compilation Interface integration](/docs/gdb-jit) - - [Investigating memory leaks](/docs/memory-leaks) - - [Stack trace API](/docs/stack-trace-api) - - [Using D8](/docs/d8) - - [V8 Tools](https://v8.dev/tools) -- Embedding V8 - - [Guide to embedding V8](/docs/embed) - - [Version numbers](/docs/version-numbers) - - [Built-in functions](/docs/builtin-functions) - - [i18n support](/docs/i18n) - - [Untrusted code mitigations](/docs/untrusted-code-mitigations) -- Under the hood - - [Ignition](/docs/ignition) - - [TurboFan](/docs/turbofan) - - [Torque user manual](/docs/torque) - - [Writing Torque built-ins](/docs/torque-builtins) - - [Writing CSA built-ins](/docs/csa-builtins) - - [Adding a new WebAssembly opcode](/docs/webassembly-opcode) - - [Maps, aka "Hidden Classes"](/docs/hidden-classes) - - [Slack Tracking - what is it?](/blog/slack-tracking) - - [WebAssembly compilation pipeline](/docs/wasm-compilation-pipeline) -- Writing optimizable JavaScript - - [Using V8’s sample-based profiler](/docs/profile) - - [Profiling Chromium with V8](/docs/profile-chromium) - - [Using Linux `perf` with V8](/docs/linux-perf) - - [Tracing V8](/docs/trace) - - [Using Runtime Call Stats](/docs/rcs) diff --git a/src/docs/inspector.md b/src/docs/inspector.md deleted file mode 100644 index b5a05890d..000000000 --- a/src/docs/inspector.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: 'Debugging over the V8 Inspector Protocol' -description: 'This page is intended to give embedders the basic tools they need to implement debugging support in V8.' ---- -V8 provides extensive debugging functionality to both users and embedders. Users will usually interact with the V8 debugger through the [Chrome DevTools](https://developer.chrome.com/devtools) interface. Embedders (including DevTools) need to rely directly on the [Inspector Protocol](https://chromedevtools.github.io/debugger-protocol-viewer/tot/). - -This page is intended to give embedders the basic tools they need to implement debugging support in V8. - -## Connecting to the Inspector - -V8’s [command-line debug shell `d8`](/docs/d8) includes a simple inspector integration through the [`InspectorFrontend`](https://cs.chromium.org/chromium/src/v8/src/d8/d8.cc?l=2286&rcl=608c4a9c391f3b7cac68068d61f2a8996f216973) and [`InspectorClient`](https://cs.chromium.org/chromium/src/v8/src/d8/d8.cc?l=2355&rcl=608c4a9c391f3b7cac68068d61f2a8996f216973). The client sets up a communication channel for messages sent from the embedder to V8: - -```cpp -static void SendInspectorMessage( - const v8::FunctionCallbackInfo& args) { - // [...] Create a StringView that Inspector can understand. - session->dispatchProtocolMessage(message_view); -} -``` - -Meanwhile, the frontend establishes a channel for messages sent from V8 to the embedder by implementing `sendResponse` and `sendNotification`, which then forward to: - -```cpp -void Send(const v8_inspector::StringView& string) { - // [...] String transformations. - // Grab the global property called 'receive' from the current context. - Local callback_name = - v8::String::NewFromUtf8(isolate_, "receive", v8::NewStringType::kNormal) - .ToLocalChecked(); - Local context = context_.Get(isolate_); - Local callback = - context->Global()->Get(context, callback_name).ToLocalChecked(); - // And call it to pass the message on to JS. - if (callback->IsFunction()) { - // [...] - MaybeLocal result = Local::Cast(callback)->Call( - context, Undefined(isolate_), 1, args); - } -} -``` - -## Using the Inspector Protocol - -Continuing with our example, `d8` forwards inspector messages to JavaScript. The following code implements a basic, but fully functional interaction with the Inspector through `d8`: - -```js -// inspector-demo.js -// Receiver function called by d8. -function receive(message) { - print(message) -} - -const msg = JSON.stringify({ - id: 0, - method: 'Debugger.enable', -}); - -// Call the function provided by d8. -send(msg); - -// Run this file by executing 'd8 --enable-inspector inspector-demo.js'. -``` - -## Further documentation - -A more fleshed-out example of Inspector API usage is available at [`test-api.js`](https://cs.chromium.org/chromium/src/v8/test/debugger/test-api.js?type=cs&q=test-api&l=1), which implements a simple debugging API for use by V8’s test suite. - -V8 also contains an alternative Inspector integration at [`inspector-test.cc`](https://cs.chromium.org/chromium/src/v8/test/inspector/inspector-test.cc?q=inspector-te+package:%5Echromium$&l=1). - -The Chrome DevTools wiki provides [full documentation](https://chromedevtools.github.io/debugger-protocol-viewer/tot/) of all available functions. diff --git a/src/docs/linux-perf.md b/src/docs/linux-perf.md deleted file mode 100644 index ea7786c3c..000000000 --- a/src/docs/linux-perf.md +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: 'V8’s Linux `perf` integration' -description: 'This document explains how to analyze the performance of V8’s JITted code with the Linux `perf` tool.' ---- -V8 has built-in support for the Linux `perf` tool. It is enable by the `--perf-prof` command-line options. -V8 writes out performance data during execution into a file that can be used to analyze the performance of V8’s JITted code (including JS-function names) with the Linux `perf` tool. - -## Requirements - -- `linux-perf` version 5 or higher (previous version don't have jit support). (See instructions at the [end](#build-perf)) -- Build V8/Chrome with `enable_profiling=true` for better symbolized C++ code. - -## Building V8 - -To use V8’s integration with Linux perf you need to build it with the `enable_profiling = true` gn flag: - -```bash -echo 'enable_profiling = true' >> out/x64.release/args.gn -autoninja -C out/x64.release -``` - -## Profiling `d8` with [`linux-perf-d8.py`](https://source.chromium.org/search?q=linux-perf-d8.py) - -After building `d8`, you can start using linux perf: - -```bash -tools/profiling/linux-perf-d8.py out/x64.release/d8 path/to/test.js; -``` - -A more complete example: - -```bash -echo '(function f() { - var s = 0; for (var i = 0; i < 1000000000; i++) { s += i; } return s; - })();' > test.js; - -# Use custom V8 flags and a separate output dir for less clutter: -mkdir perf_results -tools/profiling/linux-perf-d8.py --perf-data-dir=perf_results \ - out/x64.release/d8 --expose-gc --allow-natives-syntax test.js; - -# Fancy UI (`-flame` is googler-only, use `-web` as a public alternative): -pprof -flame perf_results/XXX_perf.data.jitted; -# Terminal-based tool: -perf report -i perf_results/XXX_perf.data.jitted; -``` - -Check `linux-perf-d8.py --help` for more details. Note that you can use all `d8` flags after the d8 binary argument. - - -## Profiling Chrome or content_shell with [linux-perf-chrome.py](https://source.chromium.org/search?q=linux-perf-chrome.py) - -1. You can use the [linux-perf-chrome.py](https://source.chromium.org/search?q=linux-perf-chrome.py) script to profile chrome. Make sure to add the [required chrome gn flags](https://chromium.googlesource.com/chromium/src/+/master/docs/profiling.md#General-checkout-setup) to get proper C++ symbols. - -1. Once your build is ready, you can profile a website with both, full symbols for C++ and JS code. - - ```bash - mkdir perf_results; - tools/profiling/linux-perf-chrome.py out/x64.release/chrome \ - --perf-data-dir=perf_results --timeout=30 - ``` - -1. Navigate to your website and then close the browser (or wait for the `--timeout` to complete) -1. After quitting the browser `linux-perf.py` will post-process the files and show a list with a result file for each renderer process: - - ``` - chrome_renderer_1583105_3.perf.data.jitted 19.79MiB - chrome_renderer_1583105_2.perf.data.jitted 8.59MiB - chrome_renderer_1583105_4.perf.data.jitted 0.18MiB - chrome_renderer_1583105_1.perf.data.jitted 0.16MiB - ``` - -## Exploring linux-perf results - -Finally you can use the Linux `perf` tool to explore the profile of a d8 or chrome renderer process: - -```bash -perf report -i perf_results/XXX_perf.data.jitted -``` - -You can also use [pprof](https://github.com/google/pprof) to generate more visualizations: - -```bash -# Note: `-flame` is google-only, use `-web` as a public alternative: -pprof -flame perf_results/XXX_perf.data.jitted; -``` - -## Low-level linux-perf usage - -### Using linux-perf with `d8` directly - -Depending on your use-case you might want to resort to using linux-perf directly with `d8`. -This requires a two-step process, first `perf record` creates a `perf.data` file that has to be post-processed with `perf inject` to inject the JS-symbols. - -``` bash -perf record --call-graph=fp --clockid=mono --freq=max \ - --output=perf.data - out/x64.release/d8 \ - --perf-prof --interpreted-frames-native-stack \ - test.js; -perf inject --jit --input=perf.data --output=perf.data.jitted; -perf report --input=perf.data.jitted; -``` - -### V8 linux-perf Flags - -[`--perf-prof`](https://source.chromium.org/search?q=FLAG_perf_prof) is used to the V8 command-line to record performance samples in JIT code. - -[`--interpreted-frames-native-stack`](https://source.chromium.org/search?q=FLAG_interpreted_frames_native_stack) is used to create different entry points (copied versions of InterpreterEntryTrampoline) for interpreted functions so they can be distinguished by `perf` based on the address alone. Since the InterpreterEntryTrampoline has to be copied this comes at slight performance and memory regression. - - -### Using linux-perf with chrome directly - -1. You can use the same V8 flags to profile chrome itself. Follow the instructions above for the correct V8 flags and add the [required chrome gn flags](https://chromium.googlesource.com/chromium/src/+/master/docs/profiling.md#General-checkout-setup) to your chrome build. - -1. Once your build is ready, you can profile a website with both, full symbols for C++ and JS code. - - ```bash - out/x64.release/chrome \ - --user-data-dir=`mktemp -d` \ - --no-sandbox --incognito --enable-benchmarking \ - --js-flags='--perf-prof --interpreted-frames-native-stack' - ``` - -1. After starting up chrome, find the renderer process id using the Task Manager and use it to start profiling: - - ```bash - perf record -g -k mono -p $RENDERER_PID -o perf.data - ``` - -1. Navigate to your website and then continue with the next section on how to evaluate the perf output. - -1. After execution finishes, combine the static information gathered from the `perf` tool with the performance samples output by V8 for JIT code: - - ```bash - perf inject --jit --input=perf.data --output=perf.data.jitted - ``` - -1. Finally you can use the Linux `perf` [tool to explore](#Explore-linux-perf-results) - -## Build `perf` - -If you have an outdated linux kernel you can build linux-perf with jit support locally. - -- Install a new Linux kernel, and then reboot your machine: - - ```bash - sudo apt-get install linux-generic-lts-wily; - ``` - -- Install dependencies: - - ```bash - sudo apt-get install libdw-dev libunwind8-dev systemtap-sdt-dev libaudit-dev \ - libslang2-dev binutils-dev liblzma-dev; - ``` - -- Download kernel sources that include the latest `perf` tool source: - - ```bash - cd some/directory; - git clone --depth 1 git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git; - cd tip/tools/perf; - make - ``` - -In the following steps, invoke `perf` as `some/director/tip/tools/perf/perf`. diff --git a/src/docs/memory-leaks.md b/src/docs/memory-leaks.md deleted file mode 100644 index 86382a0e8..000000000 --- a/src/docs/memory-leaks.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: 'Investigating memory leaks' -description: 'This document provides guidance on investigating memory leaks in V8.' ---- -If you’re investigating a memory leak and wonder why an object is not garbage-collected, you can use `%DebugTrackRetainingPath(object)` to print the actual retaining path of the object on each GC. - -This requires `--allow-natives-syntax --track-retaining-path` run-time flags and works both in release and debug modes. More info in the CL description. - -Consider the following `test.js`: - -```js -function foo() { - const x = { bar: 'bar' }; - %DebugTrackRetainingPath(x); - return () => { return x; } -} -const closure = foo(); -gc(); -``` - -Example (use debug mode or `v8_enable_object_print = true` for much more verbose output): - -```bash -$ out/x64.release/d8 --allow-natives-syntax --track-retaining-path --expose-gc test.js -################################################# -Retaining path for 0x245c59f0c1a1: - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Distance from root 6: 0x245c59f0c1a1 - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Distance from root 5: 0x245c59f0c169 - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Distance from root 4: 0x245c59f0c219 - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Distance from root 3: 0x1fbb02e2d679 - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Distance from root 2: 0x245c59f0c139 - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Distance from root 1: 0x1fbb02e03d91 - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Root: (Isolate) -------------------------------------------------- -``` - -## Debugger support - -While in a debugger session (e.g. `gdb`/`lldb`), and assuming you passed the above flags to the process (i.e. `--allow-natives-syntax --track-retaining-path`), you may be able to `print isolate->heap()->PrintRetainingPath(HeapObject*)` on an object of interest. diff --git a/src/docs/merge-patch.md b/src/docs/merge-patch.md deleted file mode 100644 index 4dcd956b0..000000000 --- a/src/docs/merge-patch.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: 'Merging & patching' -description: 'This document explains how to merge V8 patches to a release branch.' ---- -If you have a patch to the `main` branch (e.g. an important bug fix) that needs to be merged into one of the release V8 branches (refs/branch-heads/12.5), read on. - -The following examples use a branched 12.3 version of V8. Substitute `12.3` with your version number. Read the documentation on [V8’s version numbering](/docs/version-numbers) for more information. - -An associated issue on V8’s issue tracker is **mandatory** if a patch is merged. This helps with keeping track of merges. - -## What qualifies a merge candidate? - -- The patch fixes a *severe* bug (in order of importance): - 1. security bug - 1. stability bug - 1. correctness bug - 1. performance bug -- The patch does not alter APIs. -- The patch does not change behavior present before branch cut (except if the behavior change fixes a bug). - -More information can be found on the [relevant Chromium page](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/process/merge_request.md). When in doubt, send an email to . - -## The merge process - -The merge process in the V8 tracker is driven by Attributes. Therefore please set the 'Merge-Request' on to the relevant Chrome Milestone. In case the merge is only affecting a V8 [port](https://v8.dev/docs/ports) please set the HW attribute accordingliy. E.g: - -``` -Merge-Request: 123 -HW: MIPS,LoongArch64 -``` - -once reviewed, this will be adjusted during the review to: - -``` -Merge: Approved-123 -or -Merge: Rejected-123 -``` - -After the CL landed, this will be adjusted one more time to: - -``` -Merge: Merged-123, Merged-12.3 -``` - -## How to check if a commit was already merged/reverted/has Canary coverage - -Use [chromiumdash](https://chromiumdash.appspot.com/commit/) to verify if the relevant CL has Canary coverage. - - -On top the **Releases** section should show a Canary. - -## How to create the merge CL - -### Option 1: Using [gerrit](https://chromium-review.googlesource.com/) - Recommended - - -1. Open the CL you want to back-merge. -1. Select "Cherry pick" from the extended menu (three vertical dots in the upper right corner). -1. Enter "refs/branch-heads/*XX.X*" as destination branch (replace *XX.X* by the proper branch). -1. Modify the commit message and prefix the title with "Merged: ". -1. In case of merge conflict, please also go ahead and create the CL. To resolve conflicts (if any) - either using the gerrit UI or you can easily pull the patch locally by using the "download patch" command from the menu (three vertical dots in the upper right corner). -1. Send out for review. - -### Option 2: Using the automated script - -Let’s assume you’re merging revision af3cf11 to branch 12.2 (please specify full git hashes - abbreviations are used here for simplicity). - -``` -https://source.chromium.org/chromium/chromium/src/+/main:v8/tools/release/merge_to_branch_gerrit.py --branch 12.3 -r af3cf11 -``` - - -### After landing: Observe the [branch waterfall](https://ci.chromium.org/p/v8) - -If one of the builders is not green after handling your patch, revert the merge immediately. A bot (`AutoTagBot`) takes care of the correct versioning after a 10-minute wait. - -## Patching a version used on Canary/Dev - -In case you need to patch a Canary/Dev version (which should not happen often), cc vahl@ or machenbach@ on the issue. Googlers: please check out the [internal site](http://g3doc/company/teams/v8/patching_a_version) before creating the CL. - diff --git a/src/docs/node-integration.md b/src/docs/node-integration.md deleted file mode 100644 index c5ba88f6c..000000000 --- a/src/docs/node-integration.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: 'What to do if your CL broke the Node.js integration build' -description: 'This document explains what to do if your CL broke the Node.js integration build.' ---- -[Node.js](https://github.com/nodejs/node) uses V8 stable or beta. For additional integration, the V8 team builds Node with V8's [main branch](https://chromium.googlesource.com/v8/v8/+/refs/heads/main), i.e., with a V8 version from today. We provide an integration bot for [Linux](https://ci.chromium.org/p/node-ci/builders/ci/Node-CI%20Linux64), while [Windows](https://ci.chromium.org/p/node-ci/builders/ci/Node-CI%20Win64) and [Mac](https://ci.chromium.org/p/node-ci/builders/ci/Node-CI%20Mac64) are in the works. - -If the [`node_ci_linux64_rel`](https://ci.chromium.org/p/node-ci/builders/try/node_ci_linux64_rel) bot fails on the V8 commit queue, there is either a legitimate problem with your CL (fix it) or [Node](https://github.com/v8/node/) must be modified. If the Node tests failed, search for “Not OK” in the log files. **This document describes how to reproduce the problem locally and how to make changes to [V8’s Node fork](https://github.com/v8/node/) if your V8 CL causes the build to fail.** - -## Source - -Follow the [instructions](https://chromium.googlesource.com/v8/node-ci) at the node-ci repository to check out source. - -## Test changes to V8 - -V8 is set up as a DEPS dependency of node-ci. You may want to apply changes to V8 for testing or to reproduce failures. To do so, add your main V8 checkout as remote: - -```bash -cd v8 -git remote add v8 /.git -git fetch v8 -git checkout v8/ -cd .. -``` - -Remember to run gclient hooks before compiling. - -```bash -gclient runhooks -JOBS=`nproc` make test -``` - -## Make changes to Node.js - -Node.js is also set up as a `DEPS` dependency of node-ci. You may want to apply changes to Node.js to fix breakages that V8 changes may cause. V8 tests against a [fork of Node.js](https://github.com/v8/node). You need a GitHub account to make changes to that fork. - -### Get the Node sources - -Fork [V8’s Node.js repository on GitHub](https://github.com/v8/node/) (click the fork button) unless you already did previously. - -Add your both your fork and V8’s fork as remotes to the existing checkout: - -```bash -cd node -git remote add v8 http://github.com/v8/node -git remote add git@github.com:/node.git -git fetch v8 -git checkout v8/node-ci- -export BRANCH_NAME=`date +"%Y-%m-%d"`_fix_name -git checkout -b $BRANCH_NAME -``` - -> **Note** `` is the date we sync’ed with upstream Node.js. Choose the latest date. - -Make your changes to the Node.js checkout, and commit them. Then push the changes to GitHub: - -```bash -git push $BRANCH_NAME -``` - -And create a pull request against the branch `node-ci-`. - - -Once the pull request has been merged to V8’s fork of Node.js, you need to update node-ci’s `DEPS` file, and create a CL. - -```bash -git checkout -b update-deps -gclient setdep --var=node_revision= -git add DEPS -git commit -m 'Update Node' -git cl upload -``` diff --git a/src/docs/official-support.md b/src/docs/official-support.md deleted file mode 100644 index 59f99847e..000000000 --- a/src/docs/official-support.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: 'Officially supported configurations' -description: 'This document explains which build configurations are maintained by the V8 team.' ---- -V8 supports a multitude of different build configurations across operating systems, their versions, architecture ports, build flags and so on. - -The rule of thumb: If we support it, we have a bot running on one of our [continuous integration consoles](https://ci.chromium.org/p/v8/g/main/console). - -Some nuances: - -- Breakages on the most important builders will block code submission. A tree sheriff will usually revert the culprit. -- Breakages on roughly the same [set of builders](https://chromium.googlesource.com/infra/infra/+/main/infra/services/lkgr_finder/config/v8_cfg.pyl) block our continuous roll into Chromium. -- Some architecture ports are [handled externally](/docs/ports). -- Some configurations are [experimental](https://ci.chromium.org/p/v8/g/experiments/console). Breakages are permitted and will be handled by the owners of the configuration. - -If you have a configuration that exhibits a problem, but is not covered by one of the bots above: - -- Feel free to submit a CL that fixes your problem. The team will support you with a code review. -- You can use v8-dev@googlegroups.com to discuss the problem. -- If you think we should support this configuration (maybe a hole in our test matrix?), please file a bug on the [V8 issue tracker](https://bugs.chromium.org/p/v8/issues/entry) and ask. - -However, we don’t have the bandwidth to support every possible configuration. diff --git a/src/docs/ports.md b/src/docs/ports.md deleted file mode 100644 index c5d111f94..000000000 --- a/src/docs/ports.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: 'Handling of ports' -description: 'This document describes how architecture-specific V8 ports should be handled.' ---- -This document describes how ports should be handled. - -## ARM - -For straight-forward ARM ports, do them yourself. If there are difficulties or questions, contact the ARM team in the CL by adding `v8-arm-ports@googlegroups.com` to the reviewer or CC list. For questions you can email the group ([mailto link](mailto:v8-arm-ports@googlegroups.com)). - -## MIPS (not officially supported) - -The Mips team will do the port. Contact/CC the MIPS team in the CL if needed by adding `v8-mips-ports@googlegroups.com` to the reviewer or CC list. For questions you can email the group ([mailto link](mailto:v8-mips-ports@googlegroups.com)). - -## PPC (not officially supported) - -The PPC team will do the port. Contact/CC the PPC team in the CL if needed by adding `v8-ppc-ports@googlegroups.com` to the reviewer or CC list. For questions you can email the group ([mailto link](mailto:v8-ppc-ports@googlegroups.com)). - -## s390 (not officially supported) - -The s390 team will do the port. Contact/CC the s390 team in the CL if needed by adding `v8-s390-ports@googlegroups.com` to the reviewer or CC list. For questions you can email the group ([mailto link](mailto:v8-s390-ports@googlegroups.com)). - -## RISC-V (not officially supported) - -The Risc-V team will do the port. Contact/CC the Risc-V team in the CL if needed by adding `v8-risc-v-ports@chromium.org` to the reviewer or CC list. For questions you can email the group ([mailto link](mailto:v8-risc-v-ports@chromium.org)). - -## Loong64 (not officially supported) - -The Loong64 team will do the port. Contact/CC the team in the CL if needed by adding `v8-loongarch64-ports@chromium.org` to the reviewer or CC list. For questions you can email the group ([mailto link](mailto:v8-loongarch64-ports@chromium.org)). diff --git a/src/docs/profile-chromium.md b/src/docs/profile-chromium.md deleted file mode 100644 index f37f91706..000000000 --- a/src/docs/profile-chromium.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: 'Profiling Chromium with V8' -description: 'This document explains how to use V8’s CPU and heap profilers with Chromium.' ---- -[V8’s CPU & heap profilers](/docs/profile) are trivial to use from V8’s shells, but it may appear confusing how to use them with Chromium. This page should help you with it. - -## Why is using V8’s profilers with Chromium different from using them with V8 shells? - -Chromium is a complex application, unlike V8 shells. Below is the list of Chromium features that affect profiler usage: - -- each renderer is a separate process (OK, not actually each, but let’s omit this detail), so they can’t share the same log file; -- sandbox built around renderer process prevents it from writing to a disk; -- Developer Tools configure profilers for their own purposes; -- V8’s logging code contains some optimizations to simplify logging state checks. - -## How to run Chromium to get a CPU profile? - -Here is how to run Chromium in order to get a CPU profile from the start of the process: - -```bash -./Chromium --no-sandbox --user-data-dir=`mktemp -d` --incognito --js-flags='--prof' -``` - -Please note that you wouldn’t see profiles in Developer Tools, because all the data is being logged to a file, not to Developer Tools. - -### Flags description - -`--no-sandbox` turns off the renderer sandbox so chrome can write to the log file. - -`--user-data-dir` is used to create a fresh profile, use this to avoid caches and potential side-effects from installed extensions (optional). - -`--incognito` is used to further prevent pollution of your results (optional). - -`--js-flags` contains the flags passed to V8: - -- `--logfile=%t.log` specifies a name pattern for log files. `%t` gets expanded into the current time in milliseconds, so each process gets its own log file. You can use prefixes and suffixes if you want, like this: `prefix-%t-suffix.log`. By default every isolate gets a separate log file. -- `--prof` tells V8 to write statistical profiling information into the log file. - -## Android - -Chrome on Android has a number of unique points that make it a bit more complex to profile. - -- The command line must be written via `adb` before starting Chrome on the device. As a result, quotes in the command line sometimes get lost, and it is best to separate arguments in `--js-flags` with a comma rather than trying to use whitespace and quotes. -- The path for the logfile must be specified as an absolute path to somewhere that is writable on Android’s filesystem. -- The sandboxing used for renderer processes on Android means that even with `--no-sandbox`, the renderer process still can’t write to files on the filesystem, therefore `--single-process` needs to be passed to run the renderer in the same process as the browser process. -- The `.so` is embedded in Chrome’s APK which means symbolization needs to convert from APK memory addresses to the unstripped `.so` file in the builds. - -The following commands enable profiling on Android: - -```bash -./build/android/adb_chrome_public_command_line --no-sandbox --single-process --js-flags='--logfile=/storage/emulated/0/Download/%t.log,--prof' - -adb pull /storage/emulated/0/Download/ -./src/v8/tools/linux-tick-processor --apk-embedded-library=out/Release/lib.unstripped/libchrome.so --preprocess -``` - -## Notes - -Under Windows, be sure to turn on `.MAP` file creation for `chrome.dll`, but not for `chrome.exe`. diff --git a/src/docs/profile.md b/src/docs/profile.md deleted file mode 100644 index 4e662c53f..000000000 --- a/src/docs/profile.md +++ /dev/null @@ -1,172 +0,0 @@ ---- -title: 'Using V8’s sample-based profiler' -description: 'This document explains how to use V8’s sample-based profiler.' ---- -V8 has built-in sample-based profiling. Profiling is turned off by default, but can be enabled via the `--prof` command-line option. The sampler records stacks of both JavaScript and C/C++ code. - -## Build - -Build the `d8` shell following the instructions at [Building with GN](/docs/build-gn). - -## Command line - -To start profiling, use the `--prof` option. When profiling, V8 generates a `v8.log` file which contains profiling data. - -Windows: - -```bash -build\Release\d8 --prof script.js -``` - -Other platforms (replace `ia32` with `x64` if you want to profile the `x64` build): - -```bash -out/ia32.release/d8 --prof script.js -``` - -## Process the generated output - -Log file processing is done using JS scripts running by the d8 shell. For this to work, a `d8` binary (or symlink, or `d8.exe` on Windows) must be in the root of your V8 checkout, or in the path specified by the environment variable `D8_PATH`. Note: this binary is just used to process the log, but not for the actual profiling, so it doesn’t matter which version etc. it is. - -**Make sure `d8` used for analysis was not built with `is_component_build`!** - -Windows: - -```bash -tools\windows-tick-processor.bat v8.log -``` - -Linux: - -```bash -tools/linux-tick-processor v8.log -``` - -macOS: - -```bash -tools/mac-tick-processor v8.log -``` - -## Web UI for `--prof` - -Preprocess the log with `--preprocess` (to resolve C++ symbols, etc). - -```bash -$V8_PATH/tools/linux-tick-processor --preprocess > v8.json -``` - -Open [`tools/profview/index.html`](https://v8.dev/tools/head/profview) in your browser and select the `v8.json` file there. - -## Example output - -``` -Statistical profiling result from benchmarks\v8.log, (4192 ticks, 0 unaccounted, 0 excluded). - - [Shared libraries]: - ticks total nonlib name - 9 0.2% 0.0% C:\WINDOWS\system32\ntdll.dll - 2 0.0% 0.0% C:\WINDOWS\system32\kernel32.dll - - [JavaScript]: - ticks total nonlib name - 741 17.7% 17.7% LazyCompile: am3 crypto.js:108 - 113 2.7% 2.7% LazyCompile: Scheduler.schedule richards.js:188 - 103 2.5% 2.5% LazyCompile: rewrite_nboyer earley-boyer.js:3604 - 103 2.5% 2.5% LazyCompile: TaskControlBlock.run richards.js:324 - 96 2.3% 2.3% Builtin: JSConstructCall - ... - - [C++]: - ticks total nonlib name - 94 2.2% 2.2% v8::internal::ScavengeVisitor::VisitPointers - 33 0.8% 0.8% v8::internal::SweepSpace - 32 0.8% 0.8% v8::internal::Heap::MigrateObject - 30 0.7% 0.7% v8::internal::Heap::AllocateArgumentsObject - ... - - - [GC]: - ticks total nonlib name - 458 10.9% - - [Bottom up (heavy) profile]: - Note: percentage shows a share of a particular caller in the total - amount of its parent calls. - Callers occupying less than 2.0% are not shown. - - ticks parent name - 741 17.7% LazyCompile: am3 crypto.js:108 - 449 60.6% LazyCompile: montReduce crypto.js:583 - 393 87.5% LazyCompile: montSqrTo crypto.js:603 - 212 53.9% LazyCompile: bnpExp crypto.js:621 - 212 100.0% LazyCompile: bnModPowInt crypto.js:634 - 212 100.0% LazyCompile: RSADoPublic crypto.js:1521 - 181 46.1% LazyCompile: bnModPow crypto.js:1098 - 181 100.0% LazyCompile: RSADoPrivate crypto.js:1628 - ... -``` - -## Profiling web applications - -Today’s highly optimized virtual machines can run web apps at blazing speed. But one shouldn’t rely only on them to achieve great performance: a carefully optimized algorithm or a less expensive function can often reach many-fold speed improvements on all browsers. [Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/)’ [CPU Profiler](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/reference) helps you analyze your code’s bottlenecks. But sometimes, you need to go deeper and more granular: this is where V8’s internal profiler comes in handy. - -Let’s use that profiler to examine the [Mandelbrot explorer demo](https://web.archive.org/web/20130313064141/http://ie.microsoft.com/testdrive/performance/mandelbrotexplorer/) that Microsoft [released](https://blogs.msdn.microsoft.com/ie/2012/11/13/ie10-fast-fluid-perfect-for-touch-and-available-now-for-windows-7/) together with IE10. After the demo release, V8 has fixed a bug that slowed down the computation unnecessarily (hence the poor performance of Chrome in the demo’s blog post) and further optimized the engine, implementing a faster `exp()` approximation than what the standard system libraries provide. Following these changes, **the demo ran 8× faster than previously measured** in Chrome. - -But what if you want the code to run faster on all browsers? You should first **understand what keeps your CPU busy**. Run Chrome (Windows and Linux [Canary](https://tools.google.com/dlpage/chromesxs)) with the following command line switches, which causes it to output profiler tick information (in the `v8.log` file) for the URL you specify, which in our case was a local version of the Mandelbrot demo without web workers: - -```bash -./chrome --js-flags='--prof' --no-sandbox 'http://localhost:8080/' -``` - -When preparing the test case, make sure it begins its work immediately upon load, and close Chrome when the computation is done (hit Alt+F4), so that you only have the ticks you care about in the log file. Also note that web workers aren’t yet profiled correctly with this technique. - -Then, process the `v8.log` file with the `tick-processor` script that ships with V8 (or the new practical web version): - -```bash -v8/tools/linux-tick-processor v8.log -``` - -Here’s an interesting snippet of the processed output that should catch your attention: - -``` -Statistical profiling result from null, (14306 ticks, 0 unaccounted, 0 excluded). - [Shared libraries]: - ticks total nonlib name - 6326 44.2% 0.0% /lib/x86_64-linux-gnu/libm-2.15.so - 3258 22.8% 0.0% /.../chrome/src/out/Release/lib/libv8.so - 1411 9.9% 0.0% /lib/x86_64-linux-gnu/libpthread-2.15.so - 27 0.2% 0.0% /.../chrome/src/out/Release/lib/libwebkit.so -``` - -The top section shows that V8 is spending more time inside an OS-specific system library than in its own code. Let’s look at what’s responsible for it by examining the “bottom up” output section, where you can read indented lines as “was called by” (and lines starting with a `*` mean that the function has been optimized by TurboFan): - -``` -[Bottom up (heavy) profile]: - Note: percentage shows a share of a particular caller in the total - amount of its parent calls. - Callers occupying less than 2.0% are not shown. - - ticks parent name - 6326 44.2% /lib/x86_64-linux-gnu/libm-2.15.so - 6325 100.0% LazyCompile: *exp native math.js:91 - 6314 99.8% LazyCompile: *calculateMandelbrot http://localhost:8080/Demo.js:215 -``` - -More than **44% of the total time is spent executing the `exp()` function inside a system library**! Adding some overhead for calling system libraries, that means about two thirds of the overall time are spent evaluating `Math.exp()`. - -If you look at the JavaScript code, you’ll see that `exp()` is used solely to produce a smooth grayscale palette. There are countless ways to produce a smooth grayscale palette, but let’s suppose you really really like exponential gradients. Here is where algorithmic optimization comes into play. - -You’ll notice that `exp()` is called with an argument in the range `-4 < x < 0`, so we can safely replace it with its [Taylor approximation](https://en.wikipedia.org/wiki/Taylor_series) for that range, which delivers the same smooth gradient with only a multiplication and a couple of divisions: - -``` -exp(x) ≈ 1 / ( 1 - x + x * x / 2) for -4 < x < 0 -``` - -Tweaking the algorithm this way boosts the performance by an extra 30% compared to latest Canary and 5× to the system library based `Math.exp()` on Chrome Canary. - -![](/_img/docs/profile/mandelbrot.png) - -This example shows how V8’s internal profiler can help you go deeper into understanding your code bottlenecks, and that a smarter algorithm can push performance even further. - -To find out more about how benchmark that represent today’s complex and demanding web applications, read [How V8 measures real-world performance](/blog/real-world-performance). diff --git a/src/docs/rcs.md b/src/docs/rcs.md deleted file mode 100644 index 88fd9a2e7..000000000 --- a/src/docs/rcs.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: 'Runtime Call Stats' -description: 'This document explains how to use Runtime Call Stats to get detailed V8-internal metrics.' ---- -[The DevTools Performance panel](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/) gives insights into your web app’s runtime performance by visualizing various Chrome-internal metrics. However, certain low-level V8 metrics aren’t currently exposed in DevTools. This article guides you through the most robust way of gathering detailed V8-internal metrics, known as Runtime Call Stats or RCS, through `chrome://tracing`. - -Tracing records the behavior of the entire browser, including other tabs, windows, and extensions, so it works best when done in a clean user profile, with extensions disabled, and with no other browser tabs open: - -```bash -# Start a new Chrome browser session with a clean user profile and extensions disabled -google-chrome --user-data-dir="$(mktemp -d)" --disable-extensions -``` - -Type the URL of the page you want to measure in the first tab, but do not load the page yet. - -![](/_img/rcs/01.png) - -Add a second tab and open `chrome://tracing`. Tip: you can just enter `chrome:tracing`, without the slashes. - -![](/_img/rcs/02.png) - -Click on the “Record” button to prepare recording a trace. First choose “Web developer” and then select “Edit categories”. - -![](/_img/rcs/03.png) - -Select `v8.runtime_stats` from the list. Depending on how detailed your investigation is, you may select other categories as well. - -![](/_img/rcs/04.png) - -Press “Record” and switch back to the first tab and load the page. The fastest way is to use Ctrl/+1 to directly jump to the first tab and then press Enter to accept the entered URL. - -![](/_img/rcs/05.png) - -Wait until your page has completed loading or the buffer is full, then “Stop” the recording. - -![](/_img/rcs/06.png) - -Look for a “Renderer” section that contains the web page title from the recorded tab. The easiest way to do this is by clicking “Processes”, then clicking “None” to uncheck all entries, and then selecting only the renderer you’re interested in. - -![](/_img/rcs/07.png) - -Select the trace events/slices by pressing Shift and dragging. Make sure you cover _all_ the sections, including `CrRendererMain` and any `ThreadPoolForegroundWorker`s. A table with all the selected slices appears at the bottom. - -![](/_img/rcs/08.png) - -Scroll to the top right of the table and click on the link next to “Runtime call stats table”. - -![](/_img/rcs/09.png) - -In the view that appears, scroll to the bottom to see a detailed table of where V8 spends its time. - -![](/_img/rcs/10.png) - -By flipping open a category you can further drill down into the data. - -![](/_img/rcs/11.png) - -## Command-line interface { #cli } - -Run [`d8`](/docs/d8) with `--runtime-call-stats` to get RCS metrics from the command-line: - -```bash -d8 --runtime-call-stats foo.js -``` diff --git a/src/docs/release-process.md b/src/docs/release-process.md deleted file mode 100644 index 8640ccc8e..000000000 --- a/src/docs/release-process.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: 'Release process' -description: 'This document explains the V8 release process.' ---- -The V8 release process is tightly connected to [Chrome’s](https://www.chromium.org/getting-involved/dev-channel). The V8 team is using all four Chrome release channels to push new versions to the users. - -If you want to look up what V8 version is in a Chrome release you can check [Chromiumdash](https://chromiumdash.appspot.com/releases). For each Chrome release a separate branch is created in the V8 repository to make the trace-back easier e.g. for [Chrome M121](https://chromium.googlesource.com/v8/v8/+log/refs/branch-heads/12.1). - -## Canary releases - -Every day a new Canary build is pushed to the users via [Chrome’s Canary channel](https://www.google.com/chrome/browser/canary.html?platform=win64). Normally the deliverable is the latest, stable enough version from [main](https://chromium.googlesource.com/v8/v8.git/+/refs/heads/main). - -Branches for a Canary normally look like this: - -## Dev releases - -Every week a new Dev build is pushed to the users via [Chrome’s Dev channel](https://www.google.com/chrome/browser/desktop/index.html?extra=devchannel&platform=win64). Normally the deliverable includes the latest stable enough V8 version on the Canary channel. - - -## Beta releases - -Roughly every 2 weeks a new major branch is created e.g. [for Chrome 94](https://chromium.googlesource.com/v8/v8.git/+log/branch-heads/9.4). This is happening in sync with the creation of [Chrome’s Beta channel](https://www.google.com/chrome/browser/beta.html?platform=win64). The Chrome Beta is pinned to the head of V8’s branch. After approx. 2 weeks the branch is promoted to Stable. - -Changes are only cherry-picked onto the branch in order to stabilize the version. - -Branches for a Beta normally look like this - -``` -refs/branch-heads/12.1 -``` - -They are based on a Canary branch. - -## Stable releases - -Roughly every 4 weeks a new major Stable release is done. No special branch is created as the latest Beta branch is simply promoted to Stable. This version is pushed to the users via [Chrome’s Stable channel](https://www.google.com/chrome/browser/desktop/index.html?platform=win64). - -Branches for a Stable release normally look like this: - -``` -refs/branch-heads/12.1 -``` - -They are promoted (reused) Beta branches. - -## API - -Chromiumdash is also providing an API to collect the same information: - -``` -https://chromiumdash.appspot.com/fetch_milestones (to get the V8 branch name e.g. refs/branch-heads/12.1) -https://chromiumdash.appspot.com/fetch_releases (to get the the V8 branch git hash) -``` - -The following parameter are helpful: -mstone=121 -channel=Stable,Canary,Beta,Dev -platform=Mac,Windows,Lacros,Linux,Android,Webview,etc. - -## Which version should I embed in my application? - -The tip of the same branch that Chrome’s Stable channel uses. - -We often backmerge important bug fixes to a stable branch, so if you care about stability and security and correctness, you should include those updates too — that’s why we recommend “the tip of the branch”, as opposed to an exact version. - -As soon as a new branch is promoted to Stable, we stop maintaining the previous stable branch. This happens every four weeks, so you should be prepared to update at least this often. - -**Related:** [Which V8 version should I use?](/docs/version-numbers#which-v8-version-should-i-use%3F) diff --git a/src/docs/respectful-code.md b/src/docs/respectful-code.md deleted file mode 100644 index c68bbe026..000000000 --- a/src/docs/respectful-code.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: 'Respectful code' -description: 'Inclusivity is central to V8’s culture, and our values include treating each other with dignity. As such, it’s important that everyone can contribute without facing the harmful effects of bias and discrimination.' ---- - -Inclusivity is central to V8’s culture, and our values include treating each other with dignity. As such, it’s important that everyone can contribute without facing the harmful effects of bias and discrimination. However, terms in our codebase, UIs, and documentation can perpetuate that discrimination. This document sets forth guidance which aims to address disrespectful terminology in code and documentation. - -## Policy { #policy } - -Terminology that is derogatory, hurtful, or perpetuates discrimination, either directly or indirectly, should be avoided. - -## What is in scope for this policy? { #scope } - -Anything that a contributor would read while working on V8, including: - -- Names of variables, types, functions, files, build rules, binaries, exported variables, ... -- Test data -- System output and displays -- Documentation (both inside and outside of source files) -- Commit messages - -## Principles { #principles } - -- Be respectful: derogatory language shouldn’t be necessary to describe how things work. -- Respect culturally sensitive language: some words may carry significant historical or political meanings. Please be mindful of this and use alternatives. - -## How do I know if particular terminology is OK or not? { #questions } - -Apply the principles above. If you have any questions, you can reach out to `v8-dev@googlegroups.com`. - -## What are examples of terminology to be avoided? { #examples } - -This list is NOT meant to be comprehensive. It contains a few examples that people have run into frequently. - -:::table-wrapper -| Term | Suggested alternatives | -| --------- | ------------------------------------------------------------- | -| master | primary, controller, leader, host | -| slave | replica, subordinate, secondary, follower, device, peripheral | -| whitelist | allowlist, exception list, inclusion list | -| blacklist | denylist, blocklist, exclusion list | -| insane | unexpected, catastrophic, incoherent | -| sane | expected, appropriate, sensible, valid | -| crazy | unexpected, catastrophic, incoherent | -| redline | priority line, limit, soft limit | -::: - -## What if I am interfacing with something that violates this policy? { #violations } - -This circumstance has come up a few times, particularly for code implementing specifications. In these circumstances, differing from the language in the specification may interfere with the ability to understand the implementation. For these circumstances, we suggest one of the following, in order of decreasing preference: - -1. If using alternate terminology doesn’t interfere with understanding, use alternate terminology. -1. Failing that, do not propagate the terminology beyond the layer of code that is performing the interfacing. Where necessary, use alternative terminology at the API boundaries. diff --git a/src/docs/security-bugs.md b/src/docs/security-bugs.md deleted file mode 100644 index e3449374d..000000000 --- a/src/docs/security-bugs.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: 'Reporting security bugs' -description: 'This document explains the process for reporting security issues in V8.' ---- -V8 fully uses [Chromium’s Security process](https://www.chromium.org/Home/chromium-security). In order to report a V8 security bug please follow these steps: - -1. Check [Chromium’s guidelines for security bugs](https://www.chromium.org/Home/chromium-security/reporting-security-bugs) -1. File a [new bug](https://bugs.chromium.org/p/chromium/issues/entry?template=Security%20Bug) and add the component “Blink>JavaScript”. diff --git a/src/docs/source-code.md b/src/docs/source-code.md deleted file mode 100644 index b53350ca2..000000000 --- a/src/docs/source-code.md +++ /dev/null @@ -1,162 +0,0 @@ ---- -title: 'Checking out the V8 source code' -description: 'This document explains how to check out the V8 source code locally.' ---- -This document explains how to check out the V8 source code locally. If you just want to browse the source online, use these links: - -- [browse](https://chromium.googlesource.com/v8/v8/) -- [browse bleeding edge](https://chromium.googlesource.com/v8/v8/+/master) -- [changes](https://chromium.googlesource.com/v8/v8/+log/master) - -## Using Git - -V8’s Git repository is located at , with an official mirror on GitHub: . - -Don’t just `git clone` either of these URLs! if you want to build V8 from your checkout, instead follow the instructions below to get everything set up correctly. - -## Instructions - -1. On Linux or macOS, first install Git and then [`depot_tools`](https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up). - - On Windows, follow the Chromium instructions ([for Googlers](https://goto.google.com/building-chrome-win), [for non-Googlers](https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md#Setting-up-Windows)) to install Git, Visual Studio, Debugging tools for Windows, and `depot_tools`. - -1. Update `depot_tools` by executing the following into your terminal/shell. On Windows, this has to be done in the Command Prompt (`cmd.exe`), as opposed to PowerShell or others. - - ``` - gclient - ``` - -1. For **push access**, you need to set up a `.netrc` file with your Git password: - - 1. Go to and log in with your committer account (usually an `@chromium.org` account). Note: creating a new password doesn’t automatically revoke any previously created passwords. Please make sure you use the same email as the one set for `git config user.email`. - 1. Have a look at the big, grey box containing shell commands. Paste those lines into your shell. - -1. Now, get the V8 source code, including all branches and dependencies: - - ```bash - mkdir ~/v8 - cd ~/v8 - fetch v8 - cd v8 - ``` - -After that you’re intentionally in a detached head state. - -Optionally you can specify how new branches should be tracked: - -```bash -git config branch.autosetupmerge always -git config branch.autosetuprebase always -``` - -Alternatively, you can create new local branches like this (recommended): - -```bash -git new-branch fix-bug-1234 -``` - -## Staying up-to-date - -Update your current branch with `git pull`. Note that if you’re not on a branch, `git pull` won’t work, and you’ll need to use `git fetch` instead. - -```bash -git pull -``` - -Sometimes dependencies of V8 are updated. You can synchronize those by running: - -```bash -gclient sync -``` - -## Sending code for reviewing - -```bash -git cl upload -``` - -## Committing - -You can use the CQ checkbox on codereview for committing (preferred). See also the [chromium instructions](https://chromium.googlesource.com/chromium/src/+/master/docs/infra/cq.md) for CQ flags and troubleshooting. - -If you need more trybots than the default, add the following to your commit message on Gerrit (e.g. for adding a nosnap bot): - -``` -CQ_INCLUDE_TRYBOTS=tryserver.v8:v8_linux_nosnap_rel -``` - -To land manually, update your branch: - -```bash -git pull --rebase origin -``` - -Then commit using - -```bash -git cl land -``` - -## Try jobs - -This section is only useful for V8 project members. - -### Creating a try job from codereview - -1. Upload a CL to Gerrit. - - ```bash - git cl upload - ``` - -1. Try the CL by sending a try job to the try bots like this: - - ```bash - git cl try - ``` - -1. Wait for the try bots to build and you get an email with the result. You can also check the try state at your patch on Gerrit. - -1. If applying the patch fails you either need to rebase your patch or specify the V8 revision to sync to: - -```bash -git cl try --revision=1234 -``` - -### Creating a try job from a local branch - -1. Commit some changes to a git branch in the local repo. - -1. Try the change by sending a try job to the try bots like this: - - ```bash - git cl try - ``` - -1. Wait for the try bots to build and you get an email with the result. Note: There are issues with some of the replicas at the moment. Sending try jobs from codereview is recommended. - -### Useful arguments - -The revision argument tells the try bot what revision of the code base is used for applying your local changes to. Without the revision, [V8’s LKGR revision](https://v8-status.appspot.com/lkgr) is used as the base. - -```bash -git cl try --revision=1234 -``` - -To avoid running your try job on all bots, use the `--bot` flag with a comma-separated list of builder names. Example: - -```bash -git cl try --bot=v8_mac_rel -``` - -### Viewing the try server - -```bash -git cl try-results -``` - -## Source code branches - -There are several different branches of V8; if you're unsure of which version to get, you most likely want the up-to-date stable version. Have a look at our [Release Process](/docs/release-process) for more information about the different branches used. - -You may want to follow the V8 version that Chrome is shipping on its stable (or beta) channels, see . diff --git a/src/docs/stack-trace-api.md b/src/docs/stack-trace-api.md deleted file mode 100644 index cff70dd09..000000000 --- a/src/docs/stack-trace-api.md +++ /dev/null @@ -1,190 +0,0 @@ ---- -title: 'Stack trace API' -description: 'This document outlines V8’s JavaScript stack trace API.' ---- -All internal errors thrown in V8 capture a stack trace when they are created. This stack trace can be accessed from JavaScript through the non-standard `error.stack` property. V8 also has various hooks for controlling how stack traces are collected and formatted, and for allowing custom errors to also collect stack traces. This document outlines V8’s JavaScript stack trace API. - -## Basic stack traces - -By default, almost all errors thrown by V8 have a `stack` property that holds the topmost 10 stack frames, formatted as a string. Here’s an example of a fully formatted stack trace: - -``` -ReferenceError: FAIL is not defined - at Constraint.execute (deltablue.js:525:2) - at Constraint.recalculate (deltablue.js:424:21) - at Planner.addPropagate (deltablue.js:701:6) - at Constraint.satisfy (deltablue.js:184:15) - at Planner.incrementalAdd (deltablue.js:591:21) - at Constraint.addConstraint (deltablue.js:162:10) - at Constraint.BinaryConstraint (deltablue.js:346:7) - at Constraint.EqualityConstraint (deltablue.js:515:38) - at chainTest (deltablue.js:807:6) - at deltaBlue (deltablue.js:879:2) -``` - -The stack trace is collected when the error is created and is the same regardless of where or how many times the error is thrown. We collect 10 frames because it is usually enough to be useful but not so many that it has a noticeable negative performance impact. You can control how many stack frames are collected by setting the variable - -```js -Error.stackTraceLimit -``` - -Setting it to `0` disables stack trace collection. Any finite integer value can be used as the maximum number of frames to collect. Setting it to `Infinity` means that all frames get collected. This variable only affects the current context; it has to be set explicitly for each context that needs a different value. (Note that what is known as a “context” in V8 terminology corresponds to a page or `