| <!DOCTYPE html> | |
| <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang=""> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta name="generator" content="pandoc" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> | |
| <title>HotSpot Coding Style</title> | |
| <style> | |
| code{white-space: pre-wrap;} | |
| span.smallcaps{font-variant: small-caps;} | |
| div.columns{display: flex; gap: min(4vw, 1.5em);} | |
| div.column{flex: auto; overflow-x: auto;} | |
| div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} | |
| ul.task-list{list-style: none;} | |
| ul.task-list li input[type="checkbox"] { | |
| width: 0.8em; | |
| margin: 0 0.8em 0.2em -1.6em; | |
| vertical-align: middle; | |
| } | |
| .display.math{display: block; text-align: center; margin: 0.5rem auto;} | |
| </style> | |
| <link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css" /> | |
| <!--[if lt IE 9]> | |
| <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script> | |
| <![endif]--> | |
| </head> | |
| <body> | |
| <header id="title-block-header"> | |
| <h1 class="title">HotSpot Coding Style</h1> | |
| </header> | |
| <nav id="TOC" role="doc-toc"> | |
| <ul> | |
| <li><a href="#introduction" id="toc-introduction">Introduction</a> | |
| <ul> | |
| <li><a href="#changing-this-document" | |
| id="toc-changing-this-document">Changing this Document</a></li> | |
| <li><a href="#why-care-about-style" id="toc-why-care-about-style">Why | |
| Care About Style?</a></li> | |
| <li><a href="#counterexamples" | |
| id="toc-counterexamples">Counterexamples</a></li> | |
| </ul></li> | |
| <li><a href="#structure-and-formatting" | |
| id="toc-structure-and-formatting">Structure and Formatting</a> | |
| <ul> | |
| <li><a href="#factoring-and-class-design" | |
| id="toc-factoring-and-class-design">Factoring and Class Design</a></li> | |
| <li><a href="#source-files" id="toc-source-files">Source Files</a></li> | |
| <li><a href="#jtreg-tests" id="toc-jtreg-tests">JTReg Tests</a></li> | |
| <li><a href="#naming" id="toc-naming">Naming</a></li> | |
| <li><a href="#commenting" id="toc-commenting">Commenting</a></li> | |
| <li><a href="#macros" id="toc-macros">Macros</a></li> | |
| <li><a href="#whitespace" id="toc-whitespace">Whitespace</a></li> | |
| <li><a href="#miscellaneous" | |
| id="toc-miscellaneous">Miscellaneous</a></li> | |
| </ul></li> | |
| <li><a href="#use-of-c-features" id="toc-use-of-c-features">Use of C++ | |
| Features</a> | |
| <ul> | |
| <li><a href="#error-handling" id="toc-error-handling">Error | |
| Handling</a></li> | |
| <li><a href="#rtti-runtime-type-information" | |
| id="toc-rtti-runtime-type-information">RTTI (Runtime Type | |
| Information)</a></li> | |
| <li><a href="#memory-allocation" id="toc-memory-allocation">Memory | |
| Allocation</a></li> | |
| <li><a href="#class-inheritance" id="toc-class-inheritance">Class | |
| Inheritance</a></li> | |
| <li><a href="#namespaces" id="toc-namespaces">Namespaces</a></li> | |
| <li><a href="#c-standard-library" id="toc-c-standard-library">C++ | |
| Standard Library</a></li> | |
| <li><a href="#type-deduction" id="toc-type-deduction">Type | |
| Deduction</a></li> | |
| <li><a href="#expression-sfinae" id="toc-expression-sfinae">Expression | |
| SFINAE</a></li> | |
| <li><a href="#enum" id="toc-enum">enum</a></li> | |
| <li><a href="#alignas" id="toc-alignas">alignas</a></li> | |
| <li><a href="#thread_local" id="toc-thread_local">thread_local</a></li> | |
| <li><a href="#nullptr" id="toc-nullptr">nullptr</a></li> | |
| <li><a href="#atomic" id="toc-atomic"><atomic></a></li> | |
| <li><a href="#uniform-initialization" | |
| id="toc-uniform-initialization">Uniform Initialization</a></li> | |
| <li><a href="#local-function-objects" | |
| id="toc-local-function-objects">Local Function Objects</a></li> | |
| <li><a href="#inheriting-constructors" | |
| id="toc-inheriting-constructors">Inheriting constructors</a></li> | |
| <li><a href="#attributes" id="toc-attributes">Attributes</a></li> | |
| <li><a href="#additional-permitted-features" | |
| id="toc-additional-permitted-features">Additional Permitted | |
| Features</a></li> | |
| <li><a href="#excluded-features" id="toc-excluded-features">Excluded | |
| Features</a></li> | |
| <li><a href="#undecided-features" id="toc-undecided-features">Undecided | |
| Features</a></li> | |
| </ul></li> | |
| </ul> | |
| </nav> | |
| <h2 id="introduction">Introduction</h2> | |
| <p>This is a collection of rules, guidelines, and suggestions for | |
| writing HotSpot code. Following these will help new code fit in with | |
| existing HotSpot code, making it easier to read and maintain. Failure to | |
| follow these guidelines may lead to discussion during code reviews, if | |
| not outright rejection of a change.</p> | |
| <h3 id="changing-this-document">Changing this Document</h3> | |
| <p>Proposed changes should be discussed on the <a | |
| href="mailto:hotspot-dev@openjdk.org">HotSpot Developers</a> mailing | |
| list. Changes are likely to be cautious and incremental, since HotSpot | |
| coders have been using these guidelines for years.</p> | |
| <p>Substantive changes are approved by <a | |
| href="https://www.rfc-editor.org/rfc/rfc7282.html">rough consensus</a> | |
| of the <a href="https://openjdk.org/census#hotspot">HotSpot Group</a> | |
| Members. The Group Lead determines whether consensus has been | |
| reached.</p> | |
| <p>Editorial changes (changes that only affect the description of | |
| HotSpot style, not its substance) do not require the full consensus | |
| gathering process. The normal HotSpot pull request process may be used | |
| for editorial changes, with the additional requirement that the | |
| requisite reviewers are also HotSpot Group Members.</p> | |
| <h3 id="why-care-about-style">Why Care About Style?</h3> | |
| <p>Some programmers seem to have lexers and even C preprocessors | |
| installed directly behind their eyeballs. The rest of us require code | |
| that is not only functionally correct but also easy to read. More than | |
| that, since there is no one style for easy-to-read code, and since a | |
| mashup of many styles is just as confusing as no style at all, it is | |
| important for coders to be conscious of the many implicit stylistic | |
| choices that historically have gone into the HotSpot code base.</p> | |
| <p>Some of these guidelines are driven by the cross-platform | |
| requirements for HotSpot. Shared code must work on a variety of | |
| platforms, and may encounter deficiencies in some. Using platform | |
| conditionalization in shared code is usually avoided, while shared code | |
| is strongly preferred to multiple platform-dependent implementations, so | |
| some language features may be recommended against.</p> | |
| <p>Some of the guidelines here are relatively arbitrary choices among | |
| equally plausible alternatives. The purpose of stating and enforcing | |
| these rules is largely to provide a consistent look to the code. That | |
| consistency makes the code more readable by avoiding non-functional | |
| distractions from the interesting functionality.</p> | |
| <p>When changing pre-existing code, it is reasonable to adjust it to | |
| match these conventions. Exception: If the pre-existing code clearly | |
| conforms locally to its own peculiar conventions, it is not worth | |
| reformatting the whole thing. Also consider separating changes that make | |
| extensive stylistic updates from those which make functional | |
| changes.</p> | |
| <h3 id="counterexamples">Counterexamples</h3> | |
| <p>Many of the guidelines mentioned here have (sometimes widespread) | |
| counterexamples in the HotSpot code base. Finding a counterexample is | |
| not sufficient justification for new code to follow the counterexample | |
| as a precedent, since readers of your code will rightfully expect your | |
| code to follow the greater bulk of precedents documented here.</p> | |
| <p>Occasionally a guideline mentioned here may be just out of synch with | |
| the actual HotSpot code base. If you find that a guideline is | |
| consistently contradicted by a large number of counterexamples, please | |
| bring it up for discussion and possible change. The architectural rule, | |
| of course, is "When in Rome do as the Romans". Sometimes in the suburbs | |
| of Rome the rules are a little different; these differences can be | |
| pointed out here.</p> | |
| <h2 id="structure-and-formatting">Structure and Formatting</h2> | |
| <h3 id="factoring-and-class-design">Factoring and Class Design</h3> | |
| <ul> | |
| <li><p>Group related code together, so readers can concentrate on one | |
| section of one file.</p></li> | |
| <li><p>Classes are the primary code structuring mechanism. Place related | |
| functionality in a class, or a set of related classes. Use of either | |
| namespaces or public non-member functions is rare in HotSpot code. | |
| Static non-member functions are not uncommon.</p></li> | |
| <li><p>If a class <code>FooBar</code> is going to be used in more than | |
| one place, put it a file named fooBar.hpp and fooBar.cpp. If the class | |
| is a sidekick to a more important class <code>BazBat</code>, it can go | |
| in bazBat.hpp.</p></li> | |
| <li><p>Put a member function <code>FooBar::bang</code> into the same | |
| file that defined <code>FooBar</code>, or its associated <em>.inline.hpp | |
| or </em>.cpp file.</p></li> | |
| <li><p>Use public accessor functions for member variables accessed | |
| outside the class.</p></li> | |
| <li><p>Assign names to constant literals and use the names | |
| instead.</p></li> | |
| <li><p>Keep functions small, a screenful at most. Split out chunks of | |
| logic into file-local classes or static functions if needed.</p></li> | |
| <li><p>Factor away nonessential complexity into local inline helper | |
| functions and helper classes.</p></li> | |
| <li><p>Think clearly about internal invariants that apply to each class, | |
| and document them in the form of asserts within member | |
| functions.</p></li> | |
| <li><p>Make simple, self-evident contracts for member functions. If you | |
| cannot communicate a simple contract, redesign the class.</p></li> | |
| <li><p>Implement classes as if expecting rough usage by clients. Check | |
| for incorrect usage of a class using <code>assert(...)</code>, | |
| <code>guarantee(...)</code>, <code>ShouldNotReachHere()</code> and | |
| comments wherever needed. Performance is almost never a reason to omit | |
| asserts.</p></li> | |
| <li><p>When possible, design as if for reusability. This forces a clear | |
| design of the class's externals, and clean hiding of its | |
| internals.</p></li> | |
| <li><p>Initialize all variables and data structures to a known state. If | |
| a class has a constructor, initialize it there.</p></li> | |
| <li><p>Do no optimization before its time. Prove the need to | |
| optimize.</p></li> | |
| <li><p>When you must defactor to optimize, preserve as much structure as | |
| possible. If you must hand-inline some name, label the local copy with | |
| the original name.</p></li> | |
| <li><p>If you need to use a hidden detail (e.g., a structure offset), | |
| name it (as a constant or function) in the class that owns it.</p></li> | |
| <li><p>Don't use the Copy and Paste keys to replicate more than a couple | |
| lines of code. Name what you must repeat.</p></li> | |
| <li><p>If a class needs a member function to change a user-visible | |
| attribute, the change should be done with a "setter" accessor matched to | |
| the simple "getter".</p></li> | |
| </ul> | |
| <h3 id="source-files">Source Files</h3> | |
| <ul> | |
| <li><p>All source files must have a globally unique basename. The build | |
| system depends on this uniqueness.</p></li> | |
| <li><p>Keep the include lines within a section alphabetically sorted by | |
| their lowercase value. If an include must be out of order for | |
| correctness, suffix with it a comment such as | |
| <code>// do not reorder</code>. Source code processing tools can also | |
| use this hint.</p></li> | |
| <li><p>Put conditional inclusions (<code>#if ...</code>) at the end of | |
| the section of HotSpot include lines. This also applies to | |
| macro-expanded includes of platform dependent files.</p></li> | |
| <li><p>Put system includes in a section after the HotSpot include lines | |
| with a blank line separating the two sections.</p></li> | |
| <li><p>Do not put non-trivial function implementations in .hpp files. If | |
| the implementation depends on other .hpp files, put it in a .cpp or a | |
| .inline.hpp file.</p></li> | |
| <li><p>.inline.hpp files should only be included in .cpp or .inline.hpp | |
| files.</p></li> | |
| <li><p>All .inline.hpp files should include their corresponding .hpp | |
| file as the first include line with a blank line separating it from the | |
| rest of the include lines. Declarations needed by other files should be | |
| put in the .hpp file, and not in the .inline.hpp file. This rule exists | |
| to resolve problems with circular dependencies between .inline.hpp | |
| files.</p></li> | |
| <li><p>Do not include a .hpp file if the corresponding .inline.hpp file | |
| is included.</p></li> | |
| <li><p>Use include guards for .hpp and .inline.hpp files. The name of | |
| the defined guard should be derived from the full search path of the | |
| file relative to the hotspot source directory. The guard should be all | |
| upper case with all paths separators and periods replaced by | |
| underscores.</p></li> | |
| <li><p>Some build configurations use precompiled headers to speed up the | |
| build times. The precompiled headers are included in the precompiled.hpp | |
| file. Note that precompiled.hpp is just a build time optimization, so | |
| don't rely on it to resolve include problems.</p></li> | |
| </ul> | |
| <h3 id="jtreg-tests">JTReg Tests</h3> | |
| <ul> | |
| <li><p>JTReg tests should have meaningful names.</p></li> | |
| <li><p>JTReg tests associated with specific bugs should be tagged with | |
| the <code>@bug</code> keyword in the test description.</p></li> | |
| <li><p>JTReg tests should be organized by component or feature under | |
| <code>test/</code>, in a directory hierarchy that generally follows that | |
| of the <code>src/</code> directory. There may be additional | |
| subdirectories to further categorize tests by feature. This structure | |
| makes it easy to run a collection of tests associated with a specific | |
| feature by specifying the associated directory as the source of the | |
| tests to run.</p> | |
| <ul> | |
| <li>Some (older) tests use the associated bug number in the directory | |
| name, the test name, or both. That naming style should no longer be | |
| used, with existing tests using that style being candidates for | |
| migration.</li> | |
| </ul></li> | |
| </ul> | |
| <h3 id="naming">Naming</h3> | |
| <ul> | |
| <li><p>The length of a name may be correlated to the size of its scope. | |
| In particular, short names (even single letter names) may be fine in a | |
| small scope, but are usually inappropriate for larger scopes.</p></li> | |
| <li><p>Prefer whole words rather than abbreviations, unless the | |
| abbreviation is more widely used than the long form in the code's | |
| domain.</p></li> | |
| <li><p>Choose names consistently. Do not introduce spurious variations. | |
| Abbreviate corresponding terms to a consistent length.</p></li> | |
| <li><p>Global names must be unique, to avoid <a | |
| href="https://en.cppreference.com/w/cpp/language/definition" | |
| title="One Definition Rule">One Definition Rule</a> (ODR) violations. A | |
| common prefixing scheme for related global names is often used. (This is | |
| instead of using namespaces, which are mostly avoided in | |
| HotSpot.)</p></li> | |
| <li><p>Don't give two names to the semantically same thing. But use | |
| different names for semantically different things, even if they are | |
| representationally the same. (So use meaningful <code>typedef</code> or | |
| template alias names where appropriate.)</p></li> | |
| <li><p>When choosing names, avoid categorical nouns like "variable", | |
| "field", "parameter", "value", and verbs like "compute", "get". | |
| (<code>storeValue(int param)</code> is bad.)</p></li> | |
| <li><p>Type names and global names should use mixed-case with the first | |
| letter of each word capitalized (<code>FooBar</code>).</p></li> | |
| <li><p>Embedded abbreviations in otherwise mixed-case names are usually | |
| capitalized entirely rather than being treated as a single word with | |
| only the initial letter capitalized, e.g. "HTML" rather than | |
| "Html".</p></li> | |
| <li><p>Function and local variable names use lowercase with words | |
| separated by a single underscore (<code>foo_bar</code>).</p></li> | |
| <li><p>Class data member names have a leading underscore, and use | |
| lowercase with words separated by a single underscore | |
| (<code>_foo_bar</code>).</p></li> | |
| <li><p>Constant names may be upper-case or mixed-case, according to | |
| historical necessity. (Note: There are many examples of constants with | |
| lowercase names.)</p></li> | |
| <li><p>Constant names should follow an existing pattern, and must have a | |
| distinct appearance from other names in related APIs.</p></li> | |
| <li><p>Class and type names should be noun phrases. Consider an "er" | |
| suffix for a class that represents an action.</p></li> | |
| <li><p>Function names should be verb phrases that reflect changes of | |
| state known to a class's user, or else noun phrases if they cause no | |
| change of state visible to the class's user.</p></li> | |
| <li><p>Getter accessor names are noun phrases, with no | |
| "<code>get_</code>" noise word. Boolean getters can also begin with | |
| "<code>is_</code>" or "<code>has_</code>". Member function for reading | |
| data members usually have the same name as the data member, exclusive of | |
| the leading underscore.</p></li> | |
| <li><p>Setter accessor names prepend "<code>set_</code>" to the getter | |
| name.</p></li> | |
| <li><p>Other member function names are verb phrases, as if commands to | |
| the receiver.</p></li> | |
| <li><p>Avoid leading underscores (as "<code>_oop</code>") except in | |
| cases required above. (Names with leading underscores can cause | |
| portability problems.)</p></li> | |
| </ul> | |
| <h3 id="commenting">Commenting</h3> | |
| <ul> | |
| <li><p>Clearly comment subtle fixes.</p></li> | |
| <li><p>Clearly comment tricky classes and functions.</p></li> | |
| <li><p>If you have to choose between commenting code and writing wiki | |
| content, comment the code. Link from the wiki to the source file if it | |
| makes sense.</p></li> | |
| <li><p>As a general rule don't add bug numbers to comments (they would | |
| soon overwhelm the code). But if the bug report contains significant | |
| information that can't reasonably be added as a comment, then refer to | |
| the bug report.</p></li> | |
| <li><p>Personal names are discouraged in the source code, which is a | |
| team product.</p></li> | |
| </ul> | |
| <h3 id="macros">Macros</h3> | |
| <ul> | |
| <li><p>You can almost always use an inline function or class instead of | |
| a macro. Use a macro only when you really need it.</p></li> | |
| <li><p>Templates may be preferable to multi-line macros. (There may be | |
| subtle performance effects with templates on some platforms; revert to | |
| macros if absolutely necessary.)</p></li> | |
| <li><p><code>#ifdef</code>s should not be used to introduce | |
| platform-specific code into shared code (except for <code>_LP64</code>). | |
| They must be used to manage header files, in the pattern found at the | |
| top of every source file. They should be used mainly for major build | |
| features, including <code>PRODUCT</code>, <code>ASSERT</code>, | |
| <code>_LP64</code>, <code>INCLUDE_SERIALGC</code>, | |
| <code>COMPILER1</code>, etc.</p></li> | |
| <li><p>For build features such as <code>PRODUCT</code>, use | |
| <code>#ifdef PRODUCT</code> for multiple-line inclusions or | |
| exclusions.</p></li> | |
| <li><p>For short inclusions or exclusions based on build features, use | |
| macros like <code>PRODUCT_ONLY</code> and <code>NOT_PRODUCT</code>. But | |
| avoid using them with multiple-line arguments, since debuggers do not | |
| handle that well.</p></li> | |
| <li><p>Use <code>CATCH</code>, <code>THROW</code>, etc. for | |
| HotSpot-specific exception processing.</p></li> | |
| </ul> | |
| <h3 id="whitespace">Whitespace</h3> | |
| <ul> | |
| <li><p>In general, don't change whitespace unless it improves | |
| readability or consistency. Gratuitous whitespace changes will make | |
| integrations and backports more difficult.</p></li> | |
| <li><p>Use <a | |
| href="https://en.wikipedia.org/wiki/Indentation_style#Variant:_1TBS_(OTBS)">One-True-Brace-Style</a>. | |
| The opening brace for a function or class is normally at the end of the | |
| line; it is sometimes moved to the beginning of the next line for | |
| emphasis. Substatements are enclosed in braces, even if there is only a | |
| single statement. Extremely simple one-line statements may drop braces | |
| around a substatement.</p></li> | |
| <li><p>Indentation levels are two columns.</p></li> | |
| <li><p>There is no hard line length limit. That said, bear in mind that | |
| excessively long lines can cause difficulties. Some people like to have | |
| multiple side-by-side windows in their editors, and long lines may force | |
| them to choose among unpleasant options. They can use wide windows, | |
| reducing the number that can fit across the screen, and wasting a lot of | |
| screen real estate because most lines are not that long. Alternatively, | |
| they can have more windows across the screen, with long lines wrapping | |
| (or worse, requiring scrolling to see in their entirety), which is | |
| harder to read. Similar issues exist for side-by-side code | |
| reviews.</p></li> | |
| <li><p>Tabs are not allowed in code. Set your editor accordingly.<br> | |
| (Emacs: <code>(setq-default indent-tabs-mode nil)</code>.)</p></li> | |
| <li><p>Use good taste to break lines and align corresponding tokens on | |
| adjacent lines.</p></li> | |
| <li><p>Use spaces around operators, especially comparisons and | |
| assignments. (Relaxable for boolean expressions and high-precedence | |
| operators in classic math-style formulas.)</p></li> | |
| <li><p>Put spaces on both sides of control flow keywords | |
| <code>if</code>, <code>else</code>, <code>for</code>, | |
| <code>switch</code>, etc. Don't add spaces around the associated | |
| <em>control</em> expressions. Examples:</p> | |
| <pre><code>while (test_foo(args...)) { // Yes | |
| while(test_foo(args...)) { // No, missing space after while | |
| while ( test_foo(args...) ) { // No, excess spaces around control</code></pre></li> | |
| <li><p>Use extra parentheses in expressions whenever operator precedence | |
| seems doubtful. Always use parentheses in shift/mask expressions | |
| (<code><<</code>, <code>&</code>, <code>|</code>). Don't add | |
| whitespace immediately inside parentheses.</p></li> | |
| <li><p>Use more spaces and blank lines between larger constructs, such | |
| as classes or function definitions.</p></li> | |
| <li><p>If the surrounding code has any sort of vertical organization, | |
| adjust new lines horizontally to be consistent with that organization. | |
| (E.g., trailing backslashes on long macro definitions often | |
| align.)</p></li> | |
| </ul> | |
| <h3 id="miscellaneous">Miscellaneous</h3> | |
| <ul> | |
| <li><p>Use the <a href="https://en.cppreference.com/w/cpp/language/raii" | |
| title="Resource Acquisition Is Initialization">Resource Acquisition Is | |
| Initialization</a> (RAII) design pattern to manage bracketed critical | |
| sections. See class <code>ResourceMark</code> for an example.</p></li> | |
| <li><p>Avoid implicit conversions to <code>bool</code>.</p> | |
| <ul> | |
| <li>Use <code>bool</code> for boolean values.</li> | |
| <li>Do not use ints or pointers as (implicit) booleans with | |
| <code>&&</code>, <code>||</code>, <code>if</code>, | |
| <code>while</code>. Instead, compare explicitly, i.e. | |
| <code>if (x != 0)</code> or <code>if (ptr != nullptr)</code>, etc.</li> | |
| <li>Do not use declarations in <em>condition</em> forms, i.e. don't use | |
| <code>if (T v = value) { ... }</code>.</li> | |
| </ul></li> | |
| <li><p>Use functions from globalDefinitions.hpp and related files when | |
| performing bitwise operations on integers. Do not code directly as C | |
| operators, unless they are extremely simple. (Examples: | |
| <code>align_up</code>, <code>is_power_of_2</code>, | |
| <code>exact_log2</code>.)</p></li> | |
| <li><p>Use arrays with abstractions supporting range checks.</p></li> | |
| <li><p>Always enumerate all cases in a switch statement or provide a | |
| default case. It is ok to have an empty default with comment.</p></li> | |
| </ul> | |
| <h2 id="use-of-c-features">Use of C++ Features</h2> | |
| <p>HotSpot was originally written in a subset of the C++98/03 language. | |
| More recently, support for C++14 is provided, though again, HotSpot only | |
| uses a subset. (Backports to JDK versions lacking support for more | |
| recent Standards must of course stick with the original C++98/03 | |
| subset.)</p> | |
| <p>This section describes that subset. Features from the C++98/03 | |
| language may be used unless explicitly excluded here. Features from | |
| C++11 and C++14 may be explicitly permitted or explicitly excluded, and | |
| discussed accordingly here. There is a third category, undecided | |
| features, about which HotSpot developers have not yet reached a | |
| consensus, or perhaps have not discussed at all. Use of these features | |
| is also excluded.</p> | |
| <p>(The use of some features may not be immediately obvious and may slip | |
| in anyway, since the compiler will accept them. The code review process | |
| is the main defense against this.)</p> | |
| <p>Some features are discussed in their own subsection, typically to | |
| provide more extensive discussion or rationale for limitations. Features | |
| that don't have their own subsection are listed in omnibus feature | |
| sections for permitted, excluded, and undecided features.</p> | |
| <p>Lists of new features for C++11 and C++14, along with links to their | |
| descriptions, can be found in the online documentation for some of the | |
| compilers and libraries. The C++14 Standard is the definitive | |
| description.</p> | |
| <ul> | |
| <li><a href="https://gcc.gnu.org/projects/cxx-status.html">C++ Standards | |
| Support in GCC</a></li> | |
| <li><a href="https://clang.llvm.org/cxx_status.html">C++ Support in | |
| Clang</a></li> | |
| <li><a | |
| href="https://docs.microsoft.com/en-us/cpp/visual-cpp-language-conformance">Visual | |
| C++ Language Conformance</a></li> | |
| <li><a | |
| href="https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html">libstdc++ | |
| Status</a></li> | |
| <li><a href="https://libcxx.llvm.org/cxx1y_status.html">libc++ | |
| Status</a></li> | |
| </ul> | |
| <p>As a rule of thumb, permitting features which simplify writing code | |
| and, especially, reading code, is encouraged.</p> | |
| <p>Similar discussions for some other projects:</p> | |
| <ul> | |
| <li><p><a | |
| href="https://google.github.io/styleguide/cppguide.html">Google C++ | |
| Style Guide</a> — Currently (2020) targeting C++17.</p></li> | |
| <li><p><a | |
| href="https://chromium.googlesource.com/chromium/src/+/main/styleguide/c++/c++-features.md">C++11 | |
| and C++14 use in Chromium</a> — Categorizes features as allowed, banned, | |
| or to be discussed.</p></li> | |
| <li><p><a href="https://llvm.org/docs/CodingStandards.html">llvm Coding | |
| Standards</a> — Currently (2020) targeting C++14.</p></li> | |
| <li><p><a | |
| href="https://firefox-source-docs.mozilla.org/code-quality/coding-style/using_cxx_in_firefox_code.html">Using | |
| C++ in Mozilla code</a> — C++17 support is required for recent versions | |
| (2020).</p></li> | |
| </ul> | |
| <h3 id="error-handling">Error Handling</h3> | |
| <p>Do not use exceptions. Exceptions are disabled by the build | |
| configuration for some platforms.</p> | |
| <p>Rationale: There is significant concern over the performance cost of | |
| exceptions and their usage model and implications for maintainable code. | |
| That's not just a matter of history that has been fixed; there remain | |
| questions and problems even today (2019). See, for example, <a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0709r0.pdf">Zero | |
| cost deterministic exceptions</a>. Because of this, HotSpot has always | |
| used a build configuration that disables exceptions where that is | |
| available. As a result, HotSpot code uses error handling mechanisms such | |
| as two-phase construction, factory functions, returning error codes, and | |
| immediate termination. Even if the cost of exceptions were not a | |
| concern, the existing body of code was not written with exception safety | |
| in mind. Making HotSpot exception safe would be a very large | |
| undertaking.</p> | |
| <p>In addition to the usual alternatives to exceptions, HotSpot provides | |
| its own exception mechanism. This is based on a set of macros defined in | |
| utilities/exceptions.hpp.</p> | |
| <h3 id="rtti-runtime-type-information">RTTI (Runtime Type | |
| Information)</h3> | |
| <p>Do not use <a | |
| href="https://en.wikipedia.org/wiki/Run-time_type_information" | |
| title="Runtime Type Information">Runtime Type Information</a> (RTTI). <a | |
| href="https://en.wikipedia.org/wiki/Run-time_type_information" | |
| title="Runtime Type Information">RTTI</a> is disabled by the build | |
| configuration for some platforms. Among other things, this means | |
| <code>dynamic_cast</code> cannot be used.</p> | |
| <p>Rationale: Other than to implement exceptions (which HotSpot doesn't | |
| use), most potential uses of <a | |
| href="https://en.wikipedia.org/wiki/Run-time_type_information" | |
| title="Runtime Type Information">RTTI</a> are better done via virtual | |
| functions. Some of the remainder can be replaced by bespoke mechanisms. | |
| The cost of the additional runtime data structures needed to support <a | |
| href="https://en.wikipedia.org/wiki/Run-time_type_information" | |
| title="Runtime Type Information">RTTI</a> are deemed not worthwhile, | |
| given the alternatives.</p> | |
| <h3 id="memory-allocation">Memory Allocation</h3> | |
| <p>Do not use the standard global allocation and deallocation functions | |
| (operator new and related functions). Use of these functions by HotSpot | |
| code is disabled for some platforms.</p> | |
| <p>Rationale: HotSpot often uses "resource" or "arena" allocation. Even | |
| where heap allocation is used, the standard global functions are avoided | |
| in favor of wrappers around malloc and free that support the VM's Native | |
| Memory Tracking (NMT) feature. Typically, uses of the global operator | |
| new are inadvertent and therefore often associated with memory | |
| leaks.</p> | |
| <p>Native memory allocation failures are often treated as | |
| non-recoverable. The place where "out of memory" is (first) detected may | |
| be an innocent bystander, unrelated to the actual culprit.</p> | |
| <h3 id="class-inheritance">Class Inheritance</h3> | |
| <p>Use public single inheritance.</p> | |
| <p>Prefer composition rather than non-public inheritance.</p> | |
| <p>Restrict inheritance to the "is-a" case; use composition rather than | |
| non-is-a related inheritance.</p> | |
| <p>Avoid multiple inheritance. Never use virtual inheritance.</p> | |
| <h3 id="namespaces">Namespaces</h3> | |
| <p>Avoid using namespaces. HotSpot code normally uses "all static" | |
| classes rather than namespaces for grouping. An "all static" class is | |
| not instantiable, has only static members, and is normally derived | |
| (possibly indirectly) from the helper class <code>AllStatic</code>.</p> | |
| <p>Benefits of using such classes include:</p> | |
| <ul> | |
| <li><p>Provides access control for members, which is unavailable with | |
| namespaces.</p></li> | |
| <li><p>Avoids <a href="https://en.cppreference.com/w/cpp/language/adl" | |
| title="Argument Dependent Lookup">Argument Dependent Lookup</a> | |
| (ADL).</p></li> | |
| <li><p>Closed for additional members. Namespaces allow names to be added | |
| in multiple contexts, making it harder to see the complete API.</p></li> | |
| </ul> | |
| <p>Namespaces should be used only in cases where one of those "benefits" | |
| is actually a hindrance.</p> | |
| <p>In particular, don't use anonymous namespaces. They seem like they | |
| should be useful, and indeed have some real benefits for naming and | |
| generated code size on some platforms. Unfortunately, debuggers don't | |
| seem to like them at all.</p> | |
| <p><a | |
| href="https://groups.google.com/forum/#!topic/mozilla.dev.platform/KsaG3lEEaRM" | |
| class="uri">https://groups.google.com/forum/#!topic/mozilla.dev.platform/KsaG3lEEaRM</a><br> | |
| Suggests Visual Studio debugger might not be able to refer to anonymous | |
| namespace symbols, so can't set breakpoints in them. Though the | |
| discussion seems to go back and forth on that.</p> | |
| <p><a | |
| href="https://firefox-source-docs.mozilla.org/code-quality/coding-style/coding_style_cpp.html" | |
| class="uri">https://firefox-source-docs.mozilla.org/code-quality/coding-style/coding_style_cpp.html</a><br> | |
| Search for "Anonymous namespaces" Suggests preferring "static" to | |
| anonymous namespaces where applicable, because of poor debugger support | |
| for anonymous namespaces.</p> | |
| <p><a href="https://sourceware.org/bugzilla/show_bug.cgi?id=16874" | |
| class="uri">https://sourceware.org/bugzilla/show_bug.cgi?id=16874</a><br> | |
| Bug for similar gdb problems.</p> | |
| <h3 id="c-standard-library">C++ Standard Library</h3> | |
| <p>Avoid using the C++ Standard Library.</p> | |
| <p>Historically, HotSpot has mostly avoided use of the Standard | |
| Library.</p> | |
| <p>(It used to be impossible to use most of it in shared code, because | |
| the build configuration for Solaris with Solaris Studio made all but a | |
| couple of pieces inaccessible. Support for header-only parts was added | |
| in mid-2017. Support for Solaris was removed in 2020.)</p> | |
| <p>Some reasons for this include</p> | |
| <ul> | |
| <li><p>Exceptions. Perhaps the largest core issue with adopting the use | |
| of Standard Library facilities is exceptions. HotSpot does not use | |
| exceptions and, for platforms which allow doing so, builds with them | |
| turned off. Many Standard Library facilities implicitly or explicitly | |
| use exceptions.</p></li> | |
| <li><p><code>assert</code>. An issue that is quickly encountered is the | |
| <code>assert</code> macro name collision (<a | |
| href="https://bugs.openjdk.org/browse/JDK-8007770">JDK-8007770</a>). | |
| Some mechanism for addressing this would be needed before much of the | |
| Standard Library could be used. (Not all Standard Library | |
| implementations use assert in header files, but some do.)</p></li> | |
| <li><p>Memory allocation. HotSpot requires explicit control over where | |
| allocations occur. The C++98/03 <code>std::allocator</code> class is too | |
| limited to support our usage. (Changes in more recent Standards may | |
| remove this limitation.)</p></li> | |
| <li><p>Implementation vagaries. Bugs, or simply different implementation | |
| choices, can lead to different behaviors among the various Standard | |
| Libraries we need to deal with.</p></li> | |
| <li><p>Inconsistent naming conventions. HotSpot and the C++ Standard use | |
| different naming conventions. The coexistence of those different | |
| conventions might appear jarring and reduce readability.</p></li> | |
| </ul> | |
| <p>There are a few exceptions to this rule.</p> | |
| <ul> | |
| <li><code>#include <new></code> to use placement <code>new</code>, | |
| <code>std::nothrow</code>, and <code>std::nothrow_t</code>.</li> | |
| <li><code>#include <limits></code> to use | |
| <code>std::numeric_limits</code>.</li> | |
| <li><code>#include <type_traits></code> with some restrictions, | |
| listed below.</li> | |
| <li><code>#include <cstddef></code> to use | |
| <code>std::nullptr_t</code> and <code>std::max_align_t</code>.</li> | |
| </ul> | |
| <p>Certain restrictions apply to the declarations provided by | |
| <code><type_traits></code>.</p> | |
| <ul> | |
| <li>The <code>alignof</code> operator should be used rather than | |
| <code>std::alignment_of<></code>.</li> | |
| </ul> | |
| <p>TODO: Rather than directly #including (permitted) Standard Library | |
| headers, use a convention of #including wrapper headers (in some | |
| location like hotspot/shared/stdcpp). This provides a single place for | |
| dealing with issues we might have for any given header, esp. | |
| platform-specific issues.</p> | |
| <h3 id="type-deduction">Type Deduction</h3> | |
| <p>Use type deduction only if it makes the code clearer or safer. Do not | |
| use it merely to avoid the inconvenience of writing an explicit type, | |
| unless that type is itself difficult to write. An example of the latter | |
| is a function template return type that depends on template parameters | |
| in a non-trivial way.</p> | |
| <p>There are several contexts where types are deduced.</p> | |
| <ul> | |
| <li><p>Function argument deduction. This is always permitted, and indeed | |
| encouraged. It is nearly always better to allow the type of a function | |
| template argument to be deduced rather than explicitly | |
| specified.</p></li> | |
| <li><p><code>auto</code> variable declarations (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1984.pdf">n1984</a>)<br> | |
| For local variables, this can be used to make the code clearer by | |
| eliminating type information that is obvious or irrelevant. Excessive | |
| use can make code much harder to understand.</p></li> | |
| <li><p>Function return type deduction (<a | |
| href="https://isocpp.org/files/papers/N3638.html">n3638</a>)<br> Only | |
| use if the function body has a very small number of <code>return</code> | |
| statements, and generally relatively little other code.</p></li> | |
| <li><p>Also see <a href="#lambdaexpressions">lambda | |
| expressions</a>.</p></li> | |
| </ul> | |
| <h3 id="expression-sfinae">Expression SFINAE</h3> | |
| <p><a href="https://en.cppreference.com/w/cpp/language/sfinae" | |
| title="Substitution Failure Is Not An Error">Substitution Failure Is Not | |
| An Error</a> (SFINAE) is a template metaprogramming technique that makes | |
| use of template parameter substitution failures to make compile-time | |
| decisions.</p> | |
| <p>C++11 relaxed the rules for what constitutes a hard-error when | |
| attempting to substitute template parameters with template arguments, | |
| making most deduction errors be substitution errors; see (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html">n2634</a>). | |
| This makes <a href="https://en.cppreference.com/w/cpp/language/sfinae" | |
| title="Substitution Failure Is Not An Error">SFINAE</a> more powerful | |
| and easier to use. However, the implementation complexity for this | |
| change is significant, and this seems to be a place where obscure | |
| corner-case bugs in various compilers can be found. So while this | |
| feature can (and indeed should) be used (and would be difficult to | |
| avoid), caution should be used when pushing to extremes.</p> | |
| <p>Here are a few closely related example bugs:<br> <a | |
| href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95468" | |
| class="uri">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95468</a><br> | |
| <a | |
| href="https://developercommunity.visualstudio.com/content/problem/396562/sizeof-deduced-type-is-sometimes-not-a-constant-ex.html" | |
| class="uri">https://developercommunity.visualstudio.com/content/problem/396562/sizeof-deduced-type-is-sometimes-not-a-constant-ex.html</a></p> | |
| <h3 id="enum">enum</h3> | |
| <p>Where appropriate, <em>scoped-enums</em> should be used. (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf">n2347</a>)</p> | |
| <p>Use of <em>unscoped-enums</em> is permitted, though ordinary | |
| constants may be preferable when the automatic initializer feature isn't | |
| used.</p> | |
| <p>The underlying type (the <em>enum-base</em>) of an unscoped enum type | |
| should always be specified explicitly. When unspecified, the underlying | |
| type is dependent on the range of the enumerator values and the | |
| platform.</p> | |
| <p>The underlying type of a <em>scoped-enum</em> should also be | |
| specified explicitly if conversions may be applied to values of that | |
| type.</p> | |
| <p>Due to bugs in certain (very old) compilers, there is widespread use | |
| of enums and avoidance of in-class initialization of static integral | |
| constant members. Compilers having such bugs are no longer supported. | |
| Except where an enum is semantically appropriate, new code should use | |
| integral constants.</p> | |
| <h3 id="alignas">alignas</h3> | |
| <p><em>Alignment-specifiers</em> (<code>alignas</code> <a | |
| href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf">n2341</a>) | |
| are permitted, with restrictions.</p> | |
| <p><em>Alignment-specifiers</em> are permitted when the requested | |
| alignment is a <em>fundamental alignment</em> (not greater than | |
| <code>alignof(std::max_align_t)</code> <a | |
| href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf">C++14 | |
| 3.11/2</a>).</p> | |
| <p><em>Alignment-specifiers</em> with an <em>extended alignment</em> | |
| (greater than <code>alignof(std::max_align_t)</code> <a | |
| href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf">C++14 | |
| 3.11/3</a>) may only be used to align variables with static or automatic | |
| storage duration (<a | |
| href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf">C++14 | |
| 3.7.1, 3.7.3</a>). As a consequence, <em>over-aligned types</em> are | |
| forbidden; this may change if HotSpot updates to using C++17 or later | |
| (<a | |
| href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0035r4.html">p0035r4</a>).</p> | |
| <p>Large <em>extended alignments</em> should be avoided, particularly | |
| for stack allocated objects. What is a large value may depend on the | |
| platform and configuration. There may also be hard limits for some | |
| platforms.</p> | |
| <p>An <em>alignment-specifier</em> must always be applied to a | |
| definition (<a | |
| href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf">C++14 | |
| 10.6.2/6</a>). (C++ allows an <em>alignment-specifier</em> to optionally | |
| also be applied to a declaration, so long as the definition has | |
| equivalent alignment. There isn't any known benefit from duplicating the | |
| alignment in a non-definition declaration, so such duplication should be | |
| avoided in HotSpot code.)</p> | |
| <p>Enumerations are forbidden from having <em>alignment-specifiers</em>. | |
| Aligned enumerations were originally permitted but insufficiently | |
| specified, and were later (C++20) removed (<a | |
| href="https://cplusplus.github.io/CWG/issues/2354.html">CWG 2354</a>). | |
| Permitting such usage in HotSpot now would just cause problems in the | |
| future.</p> | |
| <p><em>Alignment-specifiers</em> are forbidden in <code>typedef</code> | |
| and <em>alias-declarations</em>. This may work or may have worked in | |
| some versions of some compilers, but was later (C++14) explicitly | |
| disallowed (<a | |
| href="https://cplusplus.github.io/CWG/issues/1437.html">CWG | |
| 1437</a>).</p> | |
| <p>The HotSpot macro <code>ATTRIBUTE_ALIGNED</code> provides similar | |
| capabilities for platforms that define it. This macro predates the use | |
| by HotSpot of C++ versions providing <code>alignas</code>. New code | |
| should use <code>alignas</code>.</p> | |
| <h3 id="thread_local">thread_local</h3> | |
| <p>Avoid use of <code>thread_local</code> (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2659.htm">n2659</a>); | |
| and instead, use the HotSpot macro <code>THREAD_LOCAL</code>, for which | |
| the initializer must be a constant expression. When | |
| <code>thread_local</code> must be used, use the Hotspot macro | |
| <code>APPROVED_CPP_THREAD_LOCAL</code> to indicate that the use has been | |
| given appropriate consideration.</p> | |
| <p>As was discussed in the review for <a | |
| href="https://mail.openjdk.org/pipermail/hotspot-dev/2019-September/039487.html">JDK-8230877</a>, | |
| <code>thread_local</code> allows dynamic initialization and destruction | |
| semantics. However, that support requires a run-time penalty for | |
| references to non-function-local <code>thread_local</code> variables | |
| defined in a different translation unit, even if they don't need dynamic | |
| initialization. Dynamic initialization and destruction of non-local | |
| <code>thread_local</code> variables also has the same ordering problems | |
| as for ordinary non-local variables. So we avoid use of | |
| <code>thread_local</code> in general, limiting its use to only those | |
| cases where dynamic initialization or destruction are essential. See <a | |
| href="https://bugs.openjdk.org/browse/JDK-8282469">JDK-8282469</a> for | |
| further discussion.</p> | |
| <h3 id="nullptr">nullptr</h3> | |
| <p>Use <code>nullptr</code> (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf">n2431</a>) | |
| rather than <code>NULL</code>. See the paper for reasons to avoid | |
| <code>NULL</code>.</p> | |
| <p>Don't use (constant expression or literal) 0 for pointers. Note that | |
| C++14 removed non-literal 0 constants from <em>null pointer | |
| constants</em>, though some compilers continue to treat them as such. | |
| For historical reasons there may be lingering uses of 0 as a | |
| pointer.</p> | |
| <h3 id="atomic"><atomic></h3> | |
| <p>Do not use facilities provided by the <code><atomic></code> | |
| header (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html">n2427</a>), | |
| (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2752.htm">n2752</a>); | |
| instead, use the HotSpot <code>Atomic</code> class and related | |
| facilities.</p> | |
| <p>Atomic operations in HotSpot code must have semantics which are | |
| consistent with those provided by the JDK's compilers for Java. There | |
| are platform-specific implementation choices that a C++ compiler might | |
| make or change that are outside the scope of the C++ Standard, and might | |
| differ from what the Java compilers implement.</p> | |
| <p>In addition, HotSpot <code>Atomic</code> has a concept of | |
| "conservative" memory ordering, which may differ from (may be stronger | |
| than) sequentially consistent. There are algorithms in HotSpot that are | |
| believed to rely on that ordering.</p> | |
| <h3 id="uniform-initialization">Uniform Initialization</h3> | |
| <p>The use of <em>uniform initialization</em> (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2672.htm">n2672</a>), | |
| also known as <em>brace initialization</em>, is permitted.</p> | |
| <p>Some relevant sections from cppreference.com:</p> | |
| <ul> | |
| <li><a | |
| href="https://en.cppreference.com/w/cpp/language/initialization">initialization</a></li> | |
| <li><a | |
| href="https://en.cppreference.com/w/cpp/language/value_initialization">value | |
| initialization</a></li> | |
| <li><a | |
| href="https://en.cppreference.com/w/cpp/language/direct_initialization">direct | |
| initialization</a></li> | |
| <li><a | |
| href="https://en.cppreference.com/w/cpp/language/list_initialization">list | |
| initialization</a></li> | |
| <li><a | |
| href="https://en.cppreference.com/w/cpp/language/aggregate_initialization">aggregate | |
| initialization</a></li> | |
| </ul> | |
| <p>Although related, the use of <code>std::initializer_list</code> | |
| remains forbidden, as part of the avoidance of the C++ Standard Library | |
| in HotSpot code.</p> | |
| <h3 id="local-function-objects">Local Function Objects</h3> | |
| <ul> | |
| <li>Local function objects, including lambda expressions, may be | |
| used.</li> | |
| <li>Lambda expressions must only be used as a downward value.</li> | |
| <li>Prefer <code>[&]</code> as the capture list of a lambda | |
| expression.</li> | |
| <li>Return type deduction for lambda expressions is permitted, and | |
| indeed encouraged.</li> | |
| <li>An empty parameter list for a lambda expression may be elided.</li> | |
| <li>A lambda expression must not be <code>mutable</code>.</li> | |
| <li>Generic lambda expressions are permitted.</li> | |
| <li>Lambda expressions should be relatively simple.</li> | |
| <li>Anonymous lambda expressions should not overly clutter the enclosing | |
| expression.</li> | |
| <li>An anonymous lambda expression must not be directly invoked.</li> | |
| <li>Bind expressions are forbidden.</li> | |
| </ul> | |
| <p>Single-use function objects can be defined locally within a function, | |
| directly at the point of use. This is an alternative to having a | |
| function or function object class defined at class or namespace | |
| scope.</p> | |
| <p>This usage was somewhat limited by C++03, which does not permit such | |
| a class to be used as a template parameter. That restriction was removed | |
| by C++11 (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm">n2657</a>). | |
| Use of this feature is permitted.</p> | |
| <p>Many HotSpot protocols involve "function-like" objects that involve | |
| some named member function rather than a call operator. For example, a | |
| function that performs some action on all threads might be written | |
| as</p> | |
| <pre><code>void do_something() { | |
| struct DoSomething : public ThreadClosure { | |
| virtual void do_thread(Thread* t) { | |
| ... do something with t ... | |
| } | |
| } closure; | |
| Threads::threads_do(&closure); | |
| }</code></pre> | |
| <p>HotSpot code has historically usually placed the DoSomething class at | |
| namespace (or sometimes class) scope. This separates the function's code | |
| from its use, often to the detriment of readability. It requires giving | |
| the class a globally unique name (if at namespace scope). It also loses | |
| the information that the class is intended for use in exactly one place, | |
| and does not have any subclasses. (However, the latter can now be | |
| indicated by declaring it <code>final</code>.) Often, for simplicity, a | |
| local class will skip things like access control and accessor functions, | |
| giving the enclosing function direct access to the implementation and | |
| eliminating some boilerplate that might be provided if the class is in | |
| some outer (more accessible) scope. On the other hand, if there is a lot | |
| of surrounding code in the function body or the local class is of | |
| significant size, defining it locally can increase clutter and reduce | |
| readability.</p> | |
| <p><a name="lambdaexpressions"></a> C++11 added <em>lambda | |
| expressions</em> as a new way to write a function object. Simple lambda | |
| expressions can be significantly more concise than a function object, | |
| eliminating a lot of boiler-plate. On the other hand, a complex lambda | |
| expression may not provide much, if any, readability benefit compared to | |
| an ordinary function object. Also, while a lambda can encapsulate a call | |
| to a "function-like" object, it cannot be used in place of such.</p> | |
| <p>A common use for local functions is as one-use <a | |
| href="https://en.cppreference.com/w/cpp/language/raii" | |
| title="Resource Acquisition Is Initialization">RAII</a> objects. The | |
| amount of boilerplate for a function object class (local or not) makes | |
| such usage somewhat clumsy and verbose. But with the help of a small | |
| amount of supporting utility code, lambdas work particularly well for | |
| this use case.</p> | |
| <p>Another use for local functions is <a | |
| href="https://en.wikipedia.org/wiki/Partial_application" | |
| title="Partial Application">partial application</a>. Again here, lambdas | |
| are typically much simpler and less verbose than function object | |
| classes.</p> | |
| <p>Because of these benefits, lambda expressions are permitted in | |
| HotSpot code, with some restrictions and usage guidance. An anonymous | |
| lambda is one which is passed directly as an argument. A named lambda is | |
| the value of a variable, which is its name.</p> | |
| <p>Lambda expressions should only be passed downward. In particular, a | |
| lambda should not be returned from a function or stored in a global | |
| variable, whether directly or as the value of a member of some other | |
| object. Lambda capture is syntactically subtle (by design), and | |
| propagating a lambda in such ways can easily pass references to captured | |
| values to places where they are no longer valid. In particular, members | |
| of the enclosing <code>this</code> object are effectively captured by | |
| reference, even if the default capture is by-value. For such uses-cases | |
| a function object class should be used to make the desired value | |
| capturing and propagation explicit.</p> | |
| <p>Limiting the capture list to <code>[&]</code> (implicitly capture | |
| by reference) is a simplifying restriction that still provides good | |
| support for HotSpot usage, while reducing the cases a reader must | |
| recognize and understand.</p> | |
| <ul> | |
| <li><p>Many common lambda uses require reference capture. Not permitting | |
| it would substantially reduce the utility of lambdas.</p></li> | |
| <li><p>Referential transparency. Implicit reference capture makes | |
| variable references in the lambda body have the same meaning they would | |
| have in the enclosing code. There isn't a semantic barrier across which | |
| the meaning of a variable changes.</p></li> | |
| <li><p>Explicit reference capture introduces significant clutter, | |
| especially when lambda expressions are relatively small and simple, as | |
| they should be in HotSpot code.</p></li> | |
| <li><p>There are a number of reasons why by-value capture might be used, | |
| but for the most part they don't apply to HotSpot code, given other | |
| usage restrictions.</p> | |
| <ul> | |
| <li><p>A primary use-case for by-value capture is to support escaping | |
| uses, where values captured by-reference might become invalid. That | |
| use-case doesn't apply if only downward lambdas are used.</p></li> | |
| <li><p>By-value capture can also make a lambda-local copy for mutation, | |
| which requires making the lambda <code>mutable</code>; see | |
| below.</p></li> | |
| <li><p>By-value capture might be viewed as an optimization, avoiding any | |
| overhead for reference capture of cheap to copy values. But the compiler | |
| can often eliminate any such overhead.</p></li> | |
| <li><p>By-value capture by a non-<code>mutable</code> lambda makes the | |
| captured values const, preventing any modification by the lambda and | |
| making the captured value unaffected by modifications to the outer | |
| variable. But this only applies to captured auto variables, not member | |
| variables, and is inconsistent with referential transparency.</p></li> | |
| </ul></li> | |
| <li><p>Non-capturing lambdas (with an empty capture list - | |
| <code>[]</code>) have limited utility. There are cases where no captures | |
| are required (pure functions, for example), but if the function is small | |
| and simple then that's obvious anyway.</p></li> | |
| <li><p>Capture initializers (a C++14 feature - <a | |
| href="https://isocpp.org/files/papers/N3649.html">N3649</a>) are not | |
| permitted. Capture initializers inherently increase the complexity of | |
| the capture list, and provide little benefit over an additional in-scope | |
| local variable.</p></li> | |
| </ul> | |
| <p>The use of <code>mutable</code> lambda expressions is forbidden | |
| because there don't seem to be many, if any, good use-cases for them in | |
| HotSpot. A lambda expression needs to be mutable in order to modify a | |
| by-value captured value. But with only downward lambdas, such usage | |
| seems likely to be rare and complicated. It is better to use a function | |
| object class in any such cases that arise, rather than requiring all | |
| HotSpot developers to understand this relatively obscure feature.</p> | |
| <p>While it is possible to directly invoke an anonymous lambda | |
| expression, that feature should not be used, as such a form can be | |
| confusing to readers. Instead, name the lambda and call it by name.</p> | |
| <p>Some reasons to prefer a named lambda instead of an anonymous lambda | |
| are</p> | |
| <ul> | |
| <li><p>The body contains non-trivial control flow or declarations or | |
| other nested constructs.</p></li> | |
| <li><p>Its role in an argument list is hard to guess without examining | |
| the function declaration. Give it a name that indicates its | |
| purpose.</p></li> | |
| <li><p>It has an unusual capture list.</p></li> | |
| <li><p>It has a complex explicit return type or parameter | |
| types.</p></li> | |
| </ul> | |
| <p>Lambda expressions, and particularly anonymous lambda expressions, | |
| should be simple and compact. One-liners are good. Anonymous lambdas | |
| should usually be limited to a couple lines of body code. More complex | |
| lambdas should be named. A named lambda should not clutter the enclosing | |
| function and make it long and complex; do continue to break up large | |
| functions via the use of separate helper functions.</p> | |
| <p>An anonymous lambda expression should either be a one-liner in a | |
| one-line expression, or isolated in its own set of lines. Don't place | |
| part of a lambda expression on the same line as other arguments to a | |
| function. The body of a multi-line lambda argument should be indented | |
| from the start of the capture list, as if that were the start of an | |
| ordinary function definition. The body of a multi-line named lambda | |
| should be indented one step from the variable's indentation.</p> | |
| <p>Some examples:</p> | |
| <ol type="1"> | |
| <li><p><code>foo([&] { ++counter; });</code></p></li> | |
| <li><p><code>foo(x, [&] { ++counter; });</code></p></li> | |
| <li><p><code>foo([&] { if (predicate) ++counter; });</code></p></li> | |
| <li><p><code>foo([&] { auto tmp = process(x); tmp.f(); return tmp.g(); })</code></p></li> | |
| <li><p>Separate one-line lambda from other arguments:</p> | |
| <pre><code>foo(c.begin(), c.end(), | |
| [&] (const X& x) { do_something(x); return x.value(); });</code></pre></li> | |
| <li><p>Indentation for multi-line lambda:</p> | |
| <pre><code>c.do_entries([&] (const X& x) { | |
| do_something(x, a); | |
| do_something1(x, b); | |
| do_something2(x, c); | |
| });</code></pre></li> | |
| <li><p>Separate multi-line lambda from other arguments:</p> | |
| <pre><code>foo(c.begin(), c.end(), | |
| [&] (const X& x) { | |
| do_something(x, a); | |
| do_something1(x, b); | |
| do_something2(x, c); | |
| });</code></pre></li> | |
| <li><p>Multi-line named lambda:</p> | |
| <pre><code>auto do_entry = [&] (const X& x) { | |
| do_something(x, a); | |
| do_something1(x, b); | |
| do_something2(x, c); | |
| };</code></pre></li> | |
| </ol> | |
| <p>Item 4, and especially items 6 and 7, are pushing the simplicity | |
| limits for anonymous lambdas. Item 6 might be better written using a | |
| named lambda:</p> | |
| <pre><code>c.do_entries(do_entry);</code></pre> | |
| <p>Note that C++11 also added <em>bind expressions</em> as a way to | |
| write a function object for partial application, using | |
| <code>std::bind</code> and related facilities from the Standard Library. | |
| <code>std::bind</code> generalizes and replaces some of the binders from | |
| C++03. Bind expressions are not permitted in HotSpot code. They don't | |
| provide enough benefit over lambdas or local function classes in the | |
| cases where bind expressions are applicable to warrant the introduction | |
| of yet another mechanism in this space into HotSpot code.</p> | |
| <p>References:</p> | |
| <ul> | |
| <li>Local and unnamed types as template parameters (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm">n2657</a>)</li> | |
| <li>New wording for C++0x lambdas (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2927.pdf">n2927</a>)</li> | |
| <li>Generalized lambda capture (init-capture) (<a | |
| href="https://isocpp.org/files/papers/N3648.html">N3648</a>)</li> | |
| <li>Generic (polymorphic) lambda expressions (<a | |
| href="https://isocpp.org/files/papers/N3649.html">N3649</a>)</li> | |
| </ul> | |
| <p>References from C++17</p> | |
| <ul> | |
| <li>Wording for constexpr lambda (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0170r1.pdf">p0170r1</a>)</li> | |
| <li>Lambda capture of *this by Value (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0018r3.html">p0018r3</a>)</li> | |
| </ul> | |
| <p>References from C++20</p> | |
| <ul> | |
| <li>Allow lambda capture [=, this] (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0409r2.html">p0409r2</a>)</li> | |
| <li>Familiar template syntax for generic lambdas (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0428r2.pdf">p0428r2</a>)</li> | |
| <li>Simplifying implicit lambda capture (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0588r1.html">p0588r1</a>)</li> | |
| <li>Default constructible and assignable stateless lambdas (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0624r2.pdf">p0624r2</a>)</li> | |
| <li>Lambdas in unevaluated contexts (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0315r4.pdf">p0315r4</a>)</li> | |
| <li>Allow pack expansion in lambda init-capture (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0780r2.html">p0780r2</a>) | |
| (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2095r0.html">p2095r0</a>)</li> | |
| <li>Deprecate implicit capture of this via [=] (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0806r2.html">p0806r2</a>)</li> | |
| </ul> | |
| <p>References from C++23</p> | |
| <ul> | |
| <li>Make () more optional for lambdas (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1102r2.html">p1102r2</a>)</li> | |
| </ul> | |
| <h3 id="inheriting-constructors">Inheriting constructors</h3> | |
| <p>Do not use <em>inheriting constructors</em> (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2540.htm">n2540</a>).</p> | |
| <p>C++11 provides simple syntax allowing a class to inherit the | |
| constructors of a base class. Unfortunately there are a number of | |
| problems with the original specification, and C++17 contains significant | |
| revisions (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0136r1.html" | |
| title="p0136r1">p0136r1</a> opens with a list of 8 Core Issues). Since | |
| HotSpot doesn't support use of C++17, use of inherited constructors | |
| could run into those problems. Such uses might also change behavior in a | |
| future HotSpot update to use C++17 or later, potentially in subtle ways | |
| that could lead to hard to diagnose problems. Because of this, HotSpot | |
| code must not use inherited constructors.</p> | |
| <p>Note that gcc7 provides the <code>-fnew-inheriting-ctors</code> | |
| option to use the <a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0136r1.html" | |
| title="p0136r1">p0136r1</a> semantics. This is enabled by default when | |
| using C++17 or later. It is also enabled by default for | |
| <code>fabi-version=11</code> (introduced by gcc7) or higher when using | |
| C++11/14, as the change is considered a Defect Report that applies to | |
| those versions. Earlier versions of gcc don't have that option, and | |
| other supported compilers may not have anything similar.</p> | |
| <h3 id="attributes">Attributes</h3> | |
| <p>The use of some attributes (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf">n2761</a>) | |
| (listed below) is permitted. (Note that some of the attributes defined | |
| in that paper didn't make it into the final specification.)</p> | |
| <p>Attributes are syntactically permitted in a broad set of locations, | |
| but specific attributes are only permitted in a subset of those | |
| locations. In some cases an attribute that appertains to a given element | |
| may be placed in any of several locations with the same meaning. In | |
| those cases HotSpot has a preferred location.</p> | |
| <ul> | |
| <li>An attribute that appertains to a function is placed at the | |
| beginning of the function's declaration, rather than between the | |
| function name and the parameter list.</li> | |
| </ul> | |
| <p>Only the following attributes are permitted:</p> | |
| <ul> | |
| <li><code>[[noreturn]]</code></li> | |
| </ul> | |
| <p>The following attributes are expressly forbidden:</p> | |
| <ul> | |
| <li><code>[[carries_dependency]]</code> - Related to | |
| <code>memory_order_consume</code>.</li> | |
| <li><code>[[deprecated]]</code> - Not relevant in HotSpot code.</li> | |
| </ul> | |
| <h3 id="additional-permitted-features">Additional Permitted | |
| Features</h3> | |
| <ul> | |
| <li><p><code>alignof</code> (<a | |
| href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf">n2341</a>)</p></li> | |
| <li><p><code>constexpr</code> (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf">n2235</a>) | |
| (<a | |
| href="https://isocpp.org/files/papers/N3652.html">n3652</a>)</p></li> | |
| <li><p>Sized deallocation (<a | |
| href="https://isocpp.org/files/papers/n3778.html">n3778</a>)</p></li> | |
| <li><p>Variadic templates (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf">n2242</a>) | |
| (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf">n2555</a>)</p></li> | |
| <li><p>Static assertions (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.html">n1720</a>)</p></li> | |
| <li><p><code>decltype</code> (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf">n2343</a>) | |
| (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf">n3276</a>)</p></li> | |
| <li><p>Right angle brackets (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html">n1757</a>)</p></li> | |
| <li><p>Default template arguments for function templates (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#226">CWG | |
| D226</a>)</p></li> | |
| <li><p>Template aliases (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf">n2258</a>)</p></li> | |
| <li><p>Delegating constructors (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf">n1986</a>)</p></li> | |
| <li><p>Explicit conversion operators (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf">n2437</a>)</p></li> | |
| <li><p>Standard Layout Types (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm">n2342</a>)</p></li> | |
| <li><p>Defaulted and deleted functions (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">n2346</a>)</p></li> | |
| <li><p>Dynamic initialization and destruction with concurrency (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm">n2660</a>)</p></li> | |
| <li><p><code>final</code> virtual specifiers for classes and virtual | |
| functions (<a | |
| href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2928.htm">n2928</a>), | |
| (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3206.htm">n3206</a>), | |
| (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm">n3272</a>)</p></li> | |
| <li><p><code>override</code> virtual specifiers for virtual functions | |
| (<a | |
| href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2928.htm">n2928</a>), | |
| (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3206.htm">n3206</a>), | |
| (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm">n3272</a>)</p></li> | |
| <li><p>Range-based <code>for</code> loops (<a | |
| href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2930.html">n2930</a>) | |
| (<a | |
| href="https://en.cppreference.com/w/cpp/language/range-for">range-for</a>)</p></li> | |
| <li><p>Unrestricted Unions (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf">n2544</a>)</p></li> | |
| </ul> | |
| <h3 id="excluded-features">Excluded Features</h3> | |
| <ul> | |
| <li><p>New string and character literals</p> | |
| <ul> | |
| <li>New character types (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2249.html">n2249</a>)</li> | |
| <li>Unicode string literals (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm">n2442</a>)</li> | |
| <li>Raw string literals (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm">n2442</a>)</li> | |
| <li>Universal character name literals (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2170.html">n2170</a>)</li> | |
| </ul> | |
| <p>HotSpot doesn't need any of the new character and string literal | |
| types.</p></li> | |
| <li><p>User-defined literals (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2765.pdf">n2765</a>) | |
| — User-defined literals should not be added casually, but only through a | |
| proposal to add a specific UDL.</p></li> | |
| <li><p>Inline namespaces (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2535.htm">n2535</a>) | |
| — HotSpot makes very limited use of namespaces.</p></li> | |
| <li><p><code>using namespace</code> directives. In particular, don't use | |
| <code>using namespace std;</code> to avoid needing to qualify Standard | |
| Library names.</p></li> | |
| <li><p>Propagating exceptions (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2179.html">n2179</a>) | |
| — HotSpot does not permit the use of exceptions, so this feature isn't | |
| useful.</p></li> | |
| <li><p>Avoid non-local variables with non-constexpr initialization. In | |
| particular, avoid variables with types requiring non-trivial | |
| initialization or destruction. Initialization order problems can be | |
| difficult to deal with and lead to surprises, as can destruction | |
| ordering. HotSpot doesn't generally try to cleanup on exit, and running | |
| destructors at exit can also lead to problems.</p></li> | |
| <li><p>Avoid most operator overloading, preferring named functions. When | |
| operator overloading is used, ensure the semantics conform to the normal | |
| expected behavior of the operation.</p></li> | |
| <li><p>Avoid most implicit conversion constructors and (implicit or | |
| explicit) conversion operators. (Note that conversion to | |
| <code>bool</code> isn't needed in HotSpot code because of the "no | |
| implicit boolean" guideline.)</p></li> | |
| <li><p>Avoid <code>goto</code> statements.</p></li> | |
| </ul> | |
| <h3 id="undecided-features">Undecided Features</h3> | |
| <p>This list is incomplete; it serves to explicitly call out some | |
| features that have not yet been discussed.</p> | |
| <ul> | |
| <li><p>Trailing return type syntax for functions (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2541.htm">n2541</a>)</p></li> | |
| <li><p>Variable templates (<a | |
| href="https://isocpp.org/files/papers/N3651.pdf">n3651</a>)</p></li> | |
| <li><p>Member initializers and aggregates (<a | |
| href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3653.html">n3653</a>)</p></li> | |
| <li><p>Rvalue references and move semantics</p></li> | |
| </ul> | |
| </body> | |
| </html> |