<!doctype html><html lang="en">
 <head>
  <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
  <title>P1609R1: C++ Should Support Just-in-Time Compilation</title>
<style data-fill-with="stylesheet">/******************************************************************************
 *                   Style sheet for the W3C specifications                   *
 *
 * Special classes handled by this style sheet include:
 *
 * Indices
 *   - .toc for the Table of Contents (<ol class="toc">)
 *     + <span class="secno"> for the section numbers
 *   - #toc for the Table of Contents (<nav id="toc">)
 *   - ul.index for Indices (<a href="#ref">term</a><span>, in §N.M</span>)
 *   - table.index for Index Tables (e.g. for properties or elements)
 *
 * Structural Markup
 *   - table.data for general data tables
 *     -> use 'scope' attribute, <colgroup>, <thead>, and <tbody> for best results !
 *     -> use <table class='complex data'> for extra-complex tables
 *     -> use <td class='long'> for paragraph-length cell content
 *     -> use <td class='pre'> when manual line breaks/indentation would help readability
 *   - dl.switch for switch statements
 *   - ol.algorithm for algorithms (helps to visualize nesting)
 *   - .figure and .caption (HTML4) and figure and figcaption (HTML5)
 *     -> .sidefigure for right-floated figures
 *   - ins/del
 *
 * Code
 *   - pre and code
 *
 * Special Sections
 *   - .note       for informative notes             (div, p, span, aside, details)
 *   - .example    for informative examples          (div, p, pre, span)
 *   - .issue      for issues                        (div, p, span)
 *   - .assertion  for assertions                    (div, p, span)
 *   - .advisement for loud normative statements     (div, p, strong)
 *   - .annoying-warning for spec obsoletion notices (div, aside, details)
 *
 * Definition Boxes
 *   - pre.def   for WebIDL definitions
 *   - table.def for tables that define other entities (e.g. CSS properties)
 *   - dl.def    for definition lists that define other entitles (e.g. HTML elements)
 *
 * Numbering
 *   - .secno for section numbers in .toc and headings (<span class='secno'>3.2</span>)
 *   - .marker for source-inserted example/figure/issue numbers (<span class='marker'>Issue 4</span>)
 *   - ::before styled for CSS-generated issue/example/figure numbers:
 *     -> Documents wishing to use this only need to add
 *        figcaption::before,
 *        .caption::before { content: "Figure "  counter(figure) " ";  }
 *        .example::before { content: "Example " counter(example) " "; }
 *        .issue::before   { content: "Issue "   counter(issue) " ";   }
 *
 * Header Stuff (ignore, just don't conflict with these classes)
 *   - .head for the header
 *   - .copyright for the copyright
 *
 * Miscellaneous
 *   - .overlarge for things that should be as wide as possible, even if
 *     that overflows the body text area. This can be used on an item or
 *     on its container, depending on the effect desired.
 *     Note that this styling basically doesn't help at all when printing,
 *     since A4 paper isn't much wider than the max-width here.
 *     It's better to design things to fit into a narrower measure if possible.
 *   - js-added ToC jump links (see fixup.js)
 *
 ******************************************************************************/

/******************************************************************************/
/*                                   Body                                     */
/******************************************************************************/

	body {
		counter-reset: example figure issue;

		/* Layout */
		max-width: 50em;               /* limit line length to 50em for readability   */
		margin: 0 auto;                /* center text within page                     */
		padding: 1.6em 1.5em 2em 50px; /* assume 16px font size for downlevel clients */
		padding: 1.6em 1.5em 2em calc(26px + 1.5em); /* leave space for status flag     */

		/* Typography */
		line-height: 1.5;
		font-family: sans-serif;
		widows: 2;
		orphans: 2;
		word-wrap: break-word;
		overflow-wrap: break-word;
		hyphens: auto;

		/* Colors */
		color: black;
		background: white top left fixed no-repeat;
		background-size: 25px auto;
	}


/******************************************************************************/
/*                         Front Matter & Navigation                          */
/******************************************************************************/

/** Header ********************************************************************/

	div.head { margin-bottom: 1em }
	div.head hr { border-style: solid; }

	div.head h1 {
		font-weight: bold;
		margin: 0 0 .1em;
		font-size: 220%;
	}

	div.head h2 { margin-bottom: 1.5em;}

/** W3C Logo ******************************************************************/

	.head .logo {
		float: right;
		margin: 0.4rem 0 0.2rem .4rem;
	}

	.head img[src*="logos/W3C"] {
		display: block;
		border: solid #1a5e9a;
		border-width: .65rem .7rem .6rem;
		border-radius: .4rem;
		background: #1a5e9a;
		color: white;
		font-weight: bold;
	}

	.head a:hover > img[src*="logos/W3C"],
	.head a:focus > img[src*="logos/W3C"] {
		opacity: .8;
	}

	.head a:active > img[src*="logos/W3C"] {
		background: #c00;
		border-color: #c00;
	}

	/* see also additional rules in Link Styling section */

/** Copyright *****************************************************************/

	p.copyright,
	p.copyright small { font-size: small }

/** Back to Top / ToC Toggle **************************************************/

	@media print {
		#toc-nav {
			display: none;
		}
	}
	@media not print {
		#toc-nav {
			position: fixed;
			z-index: 2;
			bottom: 0; left: 0;
			margin: 0;
			min-width: 1.33em;
			border-top-right-radius: 2rem;
			box-shadow: 0 0 2px;
			font-size: 1.5em;
			color: black;
		}
		#toc-nav > a {
			display: block;
			white-space: nowrap;

			height: 1.33em;
			padding: .1em 0.3em;
			margin: 0;

			background: white;
			box-shadow: 0 0 2px;
			border: none;
			border-top-right-radius: 1.33em;
			background: white;
		}
		#toc-nav > #toc-jump {
			padding-bottom: 2em;
			margin-bottom: -1.9em;
		}

		#toc-nav > a:hover,
		#toc-nav > a:focus {
			background: #f8f8f8;
		}
		#toc-nav > a:not(:hover):not(:focus) {
			color: #707070;
		}

		/* statusbar gets in the way on keyboard focus; remove once browsers fix */
		#toc-nav > a[href="#toc"]:not(:hover):focus:last-child {
			padding-bottom: 1.5rem;
		}

		#toc-nav:not(:hover) > a:not(:focus) > span + span {
			/* Ideally this uses :focus-within on #toc-nav */
			display: none;
		}
		#toc-nav > a > span + span {
			padding-right: 0.2em;
		}

		#toc-toggle-inline {
			vertical-align: 0.05em;
			font-size: 80%;
			color: gray;
			color: hsla(203,20%,40%,.7);
			border-style: none;
			background: transparent;
			position: relative;
		}
		#toc-toggle-inline:hover:not(:active),
		#toc-toggle-inline:focus:not(:active) {
			text-shadow: 1px 1px silver;
			top: -1px;
			left: -1px;
		}

		#toc-nav :active {
			color: #C00;
		}
	}

/** ToC Sidebar ***************************************************************/

	/* Floating sidebar */
	@media screen {
		body.toc-sidebar #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			max-width: 80%;
			max-width: calc(100% - 2em - 26px);
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
		}
		body.toc-sidebar #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
		}
		body.toc-sidebar #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	/* Hide main scroller when only the ToC is visible anyway */
	@media screen and (max-width: 28em) {
		body.toc-sidebar {
			overflow: hidden;
		}
	}

	/* Sidebar with its own space */
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
		}
		body:not(.toc-inline) #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
		}

		body:not(.toc-inline) {
			padding-left: 29em;
		}
		/* See also Overflow section at the bottom */

		body:not(.toc-inline) #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) {
			margin: 0 4em;
		}
	}

/******************************************************************************/
/*                                Sectioning                                  */
/******************************************************************************/

/** Headings ******************************************************************/

	h1, h2, h3, h4, h5, h6, dt {
		page-break-after: avoid;
		page-break-inside: avoid;
		font: 100% sans-serif;   /* Reset all font styling to clear out UA styles */
		font-family: inherit;    /* Inherit the font family. */
		line-height: 1.2;        /* Keep wrapped headings compact */
		hyphens: manual;         /* Hyphenated headings look weird */
	}

	h2, h3, h4, h5, h6 {
		margin-top: 3rem;
	}

	h1, h2, h3 {
		color: #005A9C;
		background: transparent;
	}

	h1 { font-size: 170%; }
	h2 { font-size: 140%; }
	h3 { font-size: 120%; }
	h4 { font-weight: bold; }
	h5 { font-style: italic; }
	h6 { font-variant: small-caps; }
	dt { font-weight: bold; }

/** Subheadings ***************************************************************/

	h1 + h2,
	#subtitle {
		/* #subtitle is a subtitle in an H2 under the H1 */
		margin-top: 0;
	}
	h2 + h3,
	h3 + h4,
	h4 + h5,
	h5 + h6 {
		margin-top: 1.2em; /* = 1 x line-height */
	}

/** Section divider ***********************************************************/

	:not(.head) > hr {
		font-size: 1.5em;
		text-align: center;
		margin: 1em auto;
		height: auto;
		border: transparent solid 0;
		background: transparent;
	}
	:not(.head) > hr::before {
		content: "\2727\2003\2003\2727\2003\2003\2727";
	}

/******************************************************************************/
/*                            Paragraphs and Lists                            */
/******************************************************************************/

	p {
		margin: 1em 0;
	}

	dd > p:first-child,
	li > p:first-child {
		margin-top: 0;
	}

	ul, ol {
		margin-left: 0;
		padding-left: 2em;
	}

	li {
		margin: 0.25em 0 0.5em;
		padding: 0;
	}

	dl dd {
		margin: 0 0 .5em 2em;
	}

	.head dd + dd { /* compact for header */
		margin-top: -.5em;
	}

	/* Style for algorithms */
	ol.algorithm ol:not(.algorithm),
	.algorithm > ol ol:not(.algorithm) {
	 border-left: 0.5em solid #DEF;
	}

	/* Put nice boxes around each algorithm. */
	[data-algorithm]:not(.heading) {
	  padding: .5em;
	  border: thin solid #ddd; border-radius: .5em;
	  margin: .5em calc(-0.5em - 1px);
	}
	[data-algorithm]:not(.heading) > :first-child {
	  margin-top: 0;
	}
	[data-algorithm]:not(.heading) > :last-child {
	  margin-bottom: 0;
	}

	/* Style for switch/case <dl>s */
	dl.switch > dd > ol.only,
	dl.switch > dd > .only > ol {
	 margin-left: 0;
	}
	dl.switch > dd > ol.algorithm,
	dl.switch > dd > .algorithm > ol {
	 margin-left: -2em;
	}
	dl.switch {
	 padding-left: 2em;
	}
	dl.switch > dt {
	 text-indent: -1.5em;
	 margin-top: 1em;
	}
	dl.switch > dt + dt {
	 margin-top: 0;
	}
	dl.switch > dt::before {
	 content: '\21AA';
	 padding: 0 0.5em 0 0;
	 display: inline-block;
	 width: 1em;
	 text-align: right;
	 line-height: 0.5em;
	}

/** Terminology Markup ********************************************************/


/******************************************************************************/
/*                                 Inline Markup                              */
/******************************************************************************/

/** Terminology Markup ********************************************************/
	dfn   { /* Defining instance */
		font-weight: bolder;
	}
	a > i { /* Instance of term */
		font-style: normal;
	}
	dt dfn code, code.idl {
		font-size: medium;
	}
	dfn var {
		font-style: normal;
	}

/** Change Marking ************************************************************/

	del { color: red;  text-decoration: line-through; }
	ins { color: #080; text-decoration: underline;    }

/** Miscellaneous improvements to inline formatting ***************************/

	sup {
		vertical-align: super;
		font-size: 80%
	}

/******************************************************************************/
/*                                    Code                                    */
/******************************************************************************/

/** General monospace/pre rules ***********************************************/

	pre, code, samp {
		font-family: Menlo, Consolas, "DejaVu Sans Mono", Monaco, monospace;
		font-size: .9em;
		page-break-inside: avoid;
		hyphens: none;
		text-transform: none;
	}
	pre code,
	code code {
		font-size: 100%;
	}

	pre {
		margin-top: 1em;
		margin-bottom: 1em;
		overflow: auto;
	}

/** Inline Code fragments *****************************************************/

  /* Do something nice. */

/******************************************************************************/
/*                                    Links                                   */
/******************************************************************************/

/** General Hyperlinks ********************************************************/

	/* We hyperlink a lot, so make it less intrusive */
	a[href] {
		color: #034575;
		text-decoration: none;
		border-bottom: 1px solid #707070;
		/* Need a bit of extending for it to look okay */
		padding: 0 1px 0;
		margin: 0 -1px 0;
	}
	a:visited {
		border-bottom-color: #BBB;
	}

	/* Use distinguishing colors when user is interacting with the link */
	a[href]:focus,
	a[href]:hover {
		background: #f8f8f8;
		background: rgba(75%, 75%, 75%, .25);
		border-bottom-width: 3px;
		margin-bottom: -2px;
	}
	a[href]:active {
		color: #C00;
		border-color: #C00;
	}

	/* Backout above styling for W3C logo */
	.head .logo,
	.head .logo a {
		border: none;
		text-decoration: none;
		background: transparent;
	}

/******************************************************************************/
/*                                    Images                                  */
/******************************************************************************/

	img {
		border-style: none;
	}

	/* For autogen numbers, add
	   .caption::before, figcaption::before { content: "Figure " counter(figure) ". "; }
	*/

	figure, .figure, .sidefigure {
		page-break-inside: avoid;
		text-align: center;
		margin: 2.5em 0;
	}
	.figure img,    .sidefigure img,    figure img,
	.figure object, .sidefigure object, figure object {
		max-width: 100%;
		margin: auto;
	}
	.figure pre, .sidefigure pre, figure pre {
		text-align: left;
		display: table;
		margin: 1em auto;
	}
	.figure table, figure table {
		margin: auto;
	}
	@media screen and (min-width: 20em) {
		.sidefigure {
			float: right;
			width: 50%;
			margin: 0 0 0.5em 0.5em
		}
	}
	.caption, figcaption, caption {
		font-style: italic;
		font-size: 90%;
	}
	.caption::before, figcaption::before, figcaption > .marker {
		font-weight: bold;
	}
	.caption, figcaption {
		counter-increment: figure;
	}

	/* DL list is indented 2em, but figure inside it is not */
	dd > .figure, dd > figure { margin-left: -2em }

/******************************************************************************/
/*                             Colored Boxes                                  */
/******************************************************************************/

	.issue, .note, .example, .assertion, .advisement, blockquote {
		padding: .5em;
		border: .5em;
		border-left-style: solid;
		page-break-inside: avoid;
	}
	span.issue, span.note {
		padding: .1em .5em .15em;
		border-right-style: solid;
	}

	.issue,
	.note,
	.example,
	.advisement,
	.assertion,
	blockquote {
		margin: 1em auto;
	}
	.note  > p:first-child,
	.issue > p:first-child,
	blockquote > :first-child {
		margin-top: 0;
	}
	blockquote > :last-child {
		margin-bottom: 0;
	}

/** Blockquotes ***************************************************************/

	blockquote {
		border-color: silver;
	}

/** Open issue ****************************************************************/

	.issue {
		border-color: #E05252;
		background: #FBE9E9;
		counter-increment: issue;
		overflow: auto;
	}
	.issue::before, .issue > .marker {
		text-transform: uppercase;
		color: #AE1E1E;
		padding-right: 1em;
		text-transform: uppercase;
	}
	/* Add .issue::before { content: "Issue " counter(issue) " "; } for autogen numbers,
	   or use class="marker" to mark up the issue number in source. */

/** Example *******************************************************************/

	.example {
		border-color: #E0CB52;
		background: #FCFAEE;
		counter-increment: example;
		overflow: auto;
		clear: both;
	}
	.example::before, .example > .marker {
		text-transform: uppercase;
		color: #827017;
		min-width: 7.5em;
		display: block;
	}
	/* Add .example::before { content: "Example " counter(example) " "; } for autogen numbers,
	   or use class="marker" to mark up the example number in source. */

/** Non-normative Note ********************************************************/

	.note {
		border-color: #52E052;
		background: #E9FBE9;
		overflow: auto;
	}

	.note::before, .note > .marker,
	details.note > summary::before,
	details.note > summary > .marker {
		text-transform: uppercase;
		display: block;
		color: hsl(120, 70%, 30%);
	}
	/* Add .note::before { content: "Note"; } for autogen label,
	   or use class="marker" to mark up the label in source. */

	details.note > summary {
		display: block;
		color: hsl(120, 70%, 30%);
	}
	details.note[open] > summary {
		border-bottom: 1px silver solid;
	}

/** Assertion Box *************************************************************/
	/*  for assertions in algorithms */

	.assertion {
		border-color: #AAA;
		background: #EEE;
	}

/** Advisement Box ************************************************************/
	/*  for attention-grabbing normative statements */

	.advisement {
		border-color: orange;
		border-style: none solid;
		background: #FFEECC;
	}
	strong.advisement {
		display: block;
		text-align: center;
	}
	.advisement > .marker {
		color: #B35F00;
	}

/** Spec Obsoletion Notice ****************************************************/
	/* obnoxious obsoletion notice for older/abandoned specs. */

	details {
		display: block;
	}
	summary {
		font-weight: bolder;
	}

	.annoying-warning:not(details),
	details.annoying-warning:not([open]) > summary,
	details.annoying-warning[open] {
		background: #fdd;
		color: red;
		font-weight: bold;
		padding: .75em 1em;
		border: thick red;
		border-style: solid;
		border-radius: 1em;
	}
	.annoying-warning :last-child {
		margin-bottom: 0;
	}

@media not print {
	details.annoying-warning[open] {
		position: fixed;
		left: 1em;
		right: 1em;
		bottom: 1em;
		z-index: 1000;
	}
}

	details.annoying-warning:not([open]) > summary {
		text-align: center;
	}

/** Entity Definition Boxes ***************************************************/

	.def {
		padding: .5em 1em;
		background: #DEF;
		margin: 1.2em 0;
		border-left: 0.5em solid #8CCBF2;
	}

/******************************************************************************/
/*                                    Tables                                  */
/******************************************************************************/

	th, td {
		text-align: left;
		text-align: start;
	}

/** Property/Descriptor Definition Tables *************************************/

	table.def {
		/* inherits .def box styling, see above */
		width: 100%;
		border-spacing: 0;
	}

	table.def td,
	table.def th {
		padding: 0.5em;
		vertical-align: baseline;
		border-bottom: 1px solid #bbd7e9;
	}

	table.def > tbody > tr:last-child th,
	table.def > tbody > tr:last-child td {
		border-bottom: 0;
	}

	table.def th {
		font-style: italic;
		font-weight: normal;
		padding-left: 1em;
		width: 3em;
	}

	/* For when values are extra-complex and need formatting for readability */
	table td.pre {
		white-space: pre-wrap;
	}

	/* A footnote at the bottom of a def table */
	table.def           td.footnote {
		padding-top: 0.6em;
	}
	table.def           td.footnote::before {
		content: " ";
		display: block;
		height: 0.6em;
		width: 4em;
		border-top: thin solid;
	}

/** Data tables (and properly marked-up index tables) *************************/
	/*
		 <table class="data"> highlights structural relationships in a table
		 when correct markup is used (e.g. thead/tbody, th vs. td, scope attribute)

		 Use class="complex data" for particularly complicated tables --
		 (This will draw more lines: busier, but clearer.)

		 Use class="long" on table cells with paragraph-like contents
		 (This will adjust text alignment accordingly.)
		 Alternately use class="longlastcol" on tables, to have the last column assume "long".
	*/

	table {
		word-wrap: normal;
		overflow-wrap: normal;
		hyphens: manual;
	}

	table.data,
	table.index {
		margin: 1em auto;
		border-collapse: collapse;
		border: hidden;
		width: 100%;
	}
	table.data caption,
	table.index caption {
		max-width: 50em;
		margin: 0 auto 1em;
	}

	table.data td,  table.data th,
	table.index td, table.index th {
		padding: 0.5em 1em;
		border-width: 1px;
		border-color: silver;
		border-top-style: solid;
	}

	table.data thead td:empty {
		padding: 0;
		border: 0;
	}

	table.data  thead,
	table.index thead,
	table.data  tbody,
	table.index tbody {
		border-bottom: 2px solid;
	}

	table.data colgroup,
	table.index colgroup {
		border-left: 2px solid;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		border-right: 2px solid;
		border-top: 1px solid silver;
		padding-right: 1em;
	}

	table.data th[colspan],
	table.data td[colspan] {
		text-align: center;
	}

	table.complex.data th,
	table.complex.data td {
		border: 1px solid silver;
		text-align: center;
	}

	table.data.longlastcol td:last-child,
	table.data td.long {
	 vertical-align: baseline;
	 text-align: left;
	}

	table.data img {
		vertical-align: middle;
	}


/*
Alternate table alignment rules

	table.data,
	table.index {
		text-align: center;
	}

	table.data  thead th[scope="row"],
	table.index thead th[scope="row"] {
		text-align: right;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		text-align: right;
	}

Possible extra rowspan handling

	table.data  tbody th[rowspan]:not([rowspan='1']),
	table.index tbody th[rowspan]:not([rowspan='1']),
	table.data  tbody td[rowspan]:not([rowspan='1']),
	table.index tbody td[rowspan]:not([rowspan='1']) {
		border-left: 1px solid silver;
	}

	table.data  tbody th[rowspan]:first-child,
	table.index tbody th[rowspan]:first-child,
	table.data  tbody td[rowspan]:first-child,
	table.index tbody td[rowspan]:first-child{
		border-left: 0;
		border-right: 1px solid silver;
	}
*/

/******************************************************************************/
/*                                  Indices                                   */
/******************************************************************************/


/** Table of Contents *********************************************************/

	.toc a {
		/* More spacing; use padding to make it part of the click target. */
		padding-top: 0.1rem;
		/* Larger, more consistently-sized click target */
		display: block;
		/* Reverse color scheme */
		color: black;
		border-color: #3980B5;
		border-bottom-width: 3px !important;
		margin-bottom: 0px !important;
	}
	.toc a:visited {
		border-color: #054572;
	}
	.toc a:not(:focus):not(:hover) {
		/* Allow colors to cascade through from link styling */
		border-bottom-color: transparent;
	}

	.toc, .toc ol, .toc ul, .toc li {
		list-style: none; /* Numbers must be inlined into source */
		/* because generated content isn't search/selectable and markers can't do multilevel yet */
		margin:  0;
		padding: 0;
		line-height: 1.1rem; /* consistent spacing */
	}

	/* ToC not indented until third level, but font style & margins show hierarchy */
	.toc > li             { font-weight: bold;   }
	.toc > li li          { font-weight: normal; }
	.toc > li li li       { font-size:   95%;    }
	.toc > li li li li    { font-size:   90%;    }
	.toc > li li li li .secno { font-size: 85%; }
	.toc > li li li li li { font-size:   85%;    }
	.toc > li li li li li .secno { font-size: 100%; }

	/* @supports not (display:grid) { */
		.toc > li             { margin: 1.5rem 0;    }
		.toc > li li          { margin: 0.3rem 0;    }
		.toc > li li li       { margin-left: 2rem;   }

		/* Section numbers in a column of their own */
		.toc .secno {
			float: left;
			width: 4rem;
			white-space: nowrap;
		}

		.toc li {
			clear: both;
		}

		:not(li) > .toc              { margin-left:  5rem; }
		.toc .secno                  { margin-left: -5rem; }
		.toc > li li li .secno       { margin-left: -7rem; }
		.toc > li li li li .secno    { margin-left: -9rem; }
		.toc > li li li li li .secno { margin-left: -11rem; }

		/* Tighten up indentation in narrow ToCs */
		@media (max-width: 30em) {
			:not(li) > .toc              { margin-left:  4rem; }
			.toc .secno                  { margin-left: -4rem; }
			.toc > li li li              { margin-left:  1rem; }
			.toc > li li li .secno       { margin-left: -5rem; }
			.toc > li li li li .secno    { margin-left: -6rem; }
			.toc > li li li li li .secno { margin-left: -7rem; }
		}
	/* } */

	@supports (display:grid) {
		/* Use #toc over .toc to override non-@supports rules. */
		#toc {
			display: grid;
			align-content: start;
			grid-template-columns: auto 1fr;
			grid-column-gap: 1rem;
			column-gap: 1rem;
			grid-row-gap: .6rem;
			row-gap: .6rem;
		}
		#toc h2 {
			grid-column: 1 / -1;
			margin-bottom: 0;
		}
		#toc ol,
		#toc li,
		#toc a {
			display: contents;
			/* Switch <a> to subgrid when supported */
		}
		#toc span {
			margin: 0;
		}
		#toc > .toc > li > a > span {
			/* The spans of the top-level list,
			   comprising the first items of each top-level section. */
			margin-top: 1.1rem;
		}
		#toc#toc .secno { /* Ugh, need more specificity to override base.css */
			grid-column: 1;
			width: auto;
			margin-left: 0;
		}
		#toc .content {
			grid-column: 2;
			width: auto;
			margin-right: 1rem;
		}
		#toc .content:hover {
			background: rgba(75%, 75%, 75%, .25);
			border-bottom: 3px solid #054572;
			margin-bottom: -3px;
		}
		#toc li li li .content {
			margin-left: 1rem;
		}
		#toc li li li li .content {
			margin-left: 2rem;
		}
	}


/** Index *********************************************************************/

	/* Index Lists: Layout */
	ul.index       { margin-left: 0; columns: 15em; text-indent: 1em hanging; }
	ul.index li    { margin-left: 0; list-style: none; break-inside: avoid; }
	ul.index li li { margin-left: 1em }
	ul.index dl    { margin-top: 0; }
	ul.index dt    { margin: .2em 0 .2em 20px;}
	ul.index dd    { margin: .2em 0 .2em 40px;}
	/* Index Lists: Typography */
	ul.index ul,
	ul.index dl { font-size: smaller; }
	@media not print {
		ul.index li span {
			white-space: nowrap;
			color: transparent; }
		ul.index li a:hover + span,
		ul.index li a:focus + span {
			color: #707070;
		}
	}

/** Index Tables *****************************************************/
	/* See also the data table styling section, which this effectively subclasses */

	table.index {
		font-size: small;
		border-collapse: collapse;
		border-spacing: 0;
		text-align: left;
		margin: 1em 0;
	}

	table.index td,
	table.index th {
		padding: 0.4em;
	}

	table.index tr:hover td:not([rowspan]),
	table.index tr:hover th:not([rowspan]) {
		background: #f7f8f9;
	}

	/* The link in the first column in the property table (formerly a TD) */
	table.index th:first-child a {
		font-weight: bold;
	}

/******************************************************************************/
/*                                    Print                                   */
/******************************************************************************/

	@media print {
		/* Pages have their own margins. */
		html {
			margin: 0;
		}
		/* Serif for print. */
		body {
			font-family: serif;
		}
	}
	@page {
		margin: 1.5cm 1.1cm;
	}

/******************************************************************************/
/*                                    Legacy                                  */
/******************************************************************************/

	/* This rule is inherited from past style sheets. No idea what it's for. */
	.hide { display: none }



/******************************************************************************/
/*                             Overflow Control                               */
/******************************************************************************/

	.figure .caption, .sidefigure .caption, figcaption {
		/* in case figure is overlarge, limit caption to 50em */
		max-width: 50rem;
		margin-left: auto;
		margin-right: auto;
	}
	.overlarge > table {
		/* limit preferred width of table */
		max-width: 50em;
		margin-left: auto;
		margin-right: auto;
	}

	@media (min-width: 55em) {
		.overlarge {
			margin-left: calc(13px + 26.5rem - 50vw);
			margin-right: calc(13px + 26.5rem - 50vw);
			max-width: none;
		}
	}
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) .overlarge {
			/* 30.5em body padding 50em content area */
			margin-left: calc(40em - 50vw) !important;
			margin-right: calc(40em - 50vw) !important;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) .overlarge {
			/* 4em html margin 30.5em body padding 50em content area */
			margin-left: 0 !important;
			margin-right: calc(84.5em - 100vw) !important;
		}
	}

	@media not print {
		.overlarge {
			overflow-x: auto;
			/* See Lea Verou's explanation background-attachment:
			 * http://lea.verou.me/2012/04/background-attachment-local/
			 *
			background: top left  / 4em 100% linear-gradient(to right,  #ffffff, rgba(255, 255, 255, 0)) local,
			            top right / 4em 100% linear-gradient(to left, #ffffff, rgba(255, 255, 255, 0)) local,
			            top left  / 1em 100% linear-gradient(to right,  #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            top right / 1em 100% linear-gradient(to left, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            white;
			background-repeat: no-repeat;
			*/
		}
	}
</style>
<style type="text/css">
    table, th, td {
      border: 1px solid black;
      border-collapse: collapse;
      vertical-align: top;
    }
    th, td {
      border-left: none;
      border-right: none;
      padding: 0px 10px;
    }
    th {
      text-align: center;
    }
  </style>
  <meta content="Bikeshed version c03af8da7325f5ae3f9ca742161b5d270bbce12f" name="generator">
  <link href="http://wg21.link/p1609" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
  <meta content="c2d76c58c3fb4a96032208848693bcf8ff10e538" name="document-revision">
<style>/* style-md-lists */

/* This is a weird hack for me not yet following the commonmark spec
   regarding paragraph and lists. */
[data-md] > :first-child {
    margin-top: 0;
}
[data-md] > :last-child {
    margin-bottom: 0;
}</style>
<style>/* style-counters */

body {
    counter-reset: example figure issue;
}
.issue {
    counter-increment: issue;
}
.issue:not(.no-marker)::before {
    content: "Issue " counter(issue);
}

.example {
    counter-increment: example;
}
.example:not(.no-marker)::before {
    content: "Example " counter(example);
}
.invalid.example:not(.no-marker)::before,
.illegal.example:not(.no-marker)::before {
    content: "Invalid Example" counter(example);
}

figcaption {
    counter-increment: figure;
}
figcaption:not(.no-marker)::before {
    content: "Figure " counter(figure) " ";
}</style>
<style>/* style-syntax-highlighting */

.highlight:not(.idl) { background: hsl(24, 20%, 95%); }
code.highlight { padding: .1em; border-radius: .3em; }
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }
c-[a] { color: #990055 } /* Keyword.Declaration */
c-[b] { color: #990055 } /* Keyword.Type */
c-[c] { color: #708090 } /* Comment */
c-[d] { color: #708090 } /* Comment.Multiline */
c-[e] { color: #0077aa } /* Name.Attribute */
c-[f] { color: #669900 } /* Name.Tag */
c-[g] { color: #222222 } /* Name.Variable */
c-[k] { color: #990055 } /* Keyword */
c-[l] { color: #000000 } /* Literal */
c-[m] { color: #000000 } /* Literal.Number */
c-[n] { color: #0077aa } /* Name */
c-[o] { color: #999999 } /* Operator */
c-[p] { color: #999999 } /* Punctuation */
c-[s] { color: #a67f59 } /* Literal.String */
c-[t] { color: #a67f59 } /* Literal.String.Single */
c-[u] { color: #a67f59 } /* Literal.String.Double */
c-[cp] { color: #708090 } /* Comment.Preproc */
c-[c1] { color: #708090 } /* Comment.Single */
c-[cs] { color: #708090 } /* Comment.Special */
c-[kc] { color: #990055 } /* Keyword.Constant */
c-[kn] { color: #990055 } /* Keyword.Namespace */
c-[kp] { color: #990055 } /* Keyword.Pseudo */
c-[kr] { color: #990055 } /* Keyword.Reserved */
c-[ld] { color: #000000 } /* Literal.Date */
c-[nc] { color: #0077aa } /* Name.Class */
c-[no] { color: #0077aa } /* Name.Constant */
c-[nd] { color: #0077aa } /* Name.Decorator */
c-[ni] { color: #0077aa } /* Name.Entity */
c-[ne] { color: #0077aa } /* Name.Exception */
c-[nf] { color: #0077aa } /* Name.Function */
c-[nl] { color: #0077aa } /* Name.Label */
c-[nn] { color: #0077aa } /* Name.Namespace */
c-[py] { color: #0077aa } /* Name.Property */
c-[ow] { color: #999999 } /* Operator.Word */
c-[mb] { color: #000000 } /* Literal.Number.Bin */
c-[mf] { color: #000000 } /* Literal.Number.Float */
c-[mh] { color: #000000 } /* Literal.Number.Hex */
c-[mi] { color: #000000 } /* Literal.Number.Integer */
c-[mo] { color: #000000 } /* Literal.Number.Oct */
c-[sb] { color: #a67f59 } /* Literal.String.Backtick */
c-[sc] { color: #a67f59 } /* Literal.String.Char */
c-[sd] { color: #a67f59 } /* Literal.String.Doc */
c-[se] { color: #a67f59 } /* Literal.String.Escape */
c-[sh] { color: #a67f59 } /* Literal.String.Heredoc */
c-[si] { color: #a67f59 } /* Literal.String.Interpol */
c-[sx] { color: #a67f59 } /* Literal.String.Other */
c-[sr] { color: #a67f59 } /* Literal.String.Regex */
c-[ss] { color: #a67f59 } /* Literal.String.Symbol */
c-[vc] { color: #0077aa } /* Name.Variable.Class */
c-[vg] { color: #0077aa } /* Name.Variable.Global */
c-[vi] { color: #0077aa } /* Name.Variable.Instance */
c-[il] { color: #000000 } /* Literal.Number.Integer.Long */
</style>
<style>/* style-selflinks */

.heading, .issue, .note, .example, li, dt {
    position: relative;
}
a.self-link {
    position: absolute;
    top: 0;
    left: calc(-1 * (3.5rem - 26px));
    width: calc(3.5rem - 26px);
    height: 2em;
    text-align: center;
    border: none;
    transition: opacity .2s;
    opacity: .5;
}
a.self-link:hover {
    opacity: 1;
}
.heading > a.self-link {
    font-size: 83%;
}
li > a.self-link {
    left: calc(-1 * (3.5rem - 26px) - 2em);
}
dfn > a.self-link {
    top: auto;
    left: auto;
    opacity: 0;
    width: 1.5em;
    height: 1.5em;
    background: gray;
    color: white;
    font-style: normal;
    transition: opacity .2s, background-color .2s, color .2s;
}
dfn:hover > a.self-link {
    opacity: 1;
}
dfn > a.self-link:hover {
    color: black;
}

a.self-link::before            { content: "¶"; }
.heading > a.self-link::before { content: "§"; }
dfn > a.self-link::before      { content: "#"; }</style>
<style>/* style-autolinks */

.css.css, .property.property, .descriptor.descriptor {
    color: #005a9c;
    font-size: inherit;
    font-family: inherit;
}
.css::before, .property::before, .descriptor::before {
    content: "‘";
}
.css::after, .property::after, .descriptor::after {
    content: "’";
}
.property, .descriptor {
    /* Don't wrap property and descriptor names */
    white-space: nowrap;
}
.type { /* CSS value <type> */
    font-style: italic;
}
pre .property::before, pre .property::after {
    content: "";
}
[data-link-type="property"]::before,
[data-link-type="propdesc"]::before,
[data-link-type="descriptor"]::before,
[data-link-type="value"]::before,
[data-link-type="function"]::before,
[data-link-type="at-rule"]::before,
[data-link-type="selector"]::before,
[data-link-type="maybe"]::before {
    content: "‘";
}
[data-link-type="property"]::after,
[data-link-type="propdesc"]::after,
[data-link-type="descriptor"]::after,
[data-link-type="value"]::after,
[data-link-type="function"]::after,
[data-link-type="at-rule"]::after,
[data-link-type="selector"]::after,
[data-link-type="maybe"]::after {
    content: "’";
}

[data-link-type].production::before,
[data-link-type].production::after,
.prod [data-link-type]::before,
.prod [data-link-type]::after {
    content: "";
}

[data-link-type=element],
[data-link-type=element-attr] {
    font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace;
    font-size: .9em;
}
[data-link-type=element]::before { content: "<" }
[data-link-type=element]::after  { content: ">" }

[data-link-type=biblio] {
    white-space: pre;
}</style>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">P1609R1<br>C++ Should Support Just-in-Time Compilation</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Published Proposal, <time class="dt-updated" datetime="2019-06-17">2019-06-17</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="http://wg21.link/p1609">http://wg21.link/p1609</a>
     <dt>Author:
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:hfinkel@anl.gov">Hal Finkel</a> (<span class="p-org org">Argonne National Laboratory</span>)
     <dt>Audience:
     <dd>SG17
     <dt>Project:
     <dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract">
   <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
   <p>C++ has been specifically designed to support the creation of performance-sensitive systems. C++ templates have become a critical piece of this support, allowing the creation of algorithmic specializations to which the application can dispatch based on runtime conditions. However, many applications are pushing this capability to its limit, generating so many specializations using template instantiation that compile times are interfering with programmer productivity. In other cases, programmers simply must settle for suboptimal performance because the ahead-of-time generation of specializations with better performance is not practical given the size of the relevant parameter space. To address these challenges, this paper proposes to add to C++ the capability to support programmer-directed just-in-time (JIT) compilation.</p>
  </div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li><a href="#intro"><span class="secno">1</span> <span class="content">Introduction</span></a>
    <li><a href="#chlog"><span class="secno">2</span> <span class="content">Changelog</span></a>
    <li><a href="#impl"><span class="secno">3</span> <span class="content">Implementation</span></a>
    <li>
     <a href="#prop"><span class="secno">4</span> <span class="content">Proposal</span></a>
     <ol class="toc">
      <li>
       <a href="#attr"><span class="secno">4.1</span> <span class="content">Attribute</span></a>
       <ol class="toc">
        <li><a href="#ex1"><span class="secno">4.1.1</span> <span class="content">Example</span></a>
        <li><a href="#ex2"><span class="secno">4.1.2</span> <span class="content">Example</span></a>
       </ol>
      <li><a href="#restr"><span class="secno">4.2</span> <span class="content">Restrictions</span></a>
     </ol>
    <li><a href="#desq"><span class="secno">5</span> <span class="content">A Design Question</span></a>
    <li><a href="#state"><span class="secno">6</span> <span class="content">On State</span></a>
    <li><a href="#abi"><span class="secno">7</span> <span class="content">ABI and Error Handling</span></a>
    <li>
     <a href="#bench"><span class="secno">8</span> <span class="content">A Benchmark</span></a>
     <ol class="toc">
      <li><a href="#ctperf"><span class="secno">8.1</span> <span class="content">Compile Time</span></a>
      <li><a href="#rtperf"><span class="secno">8.2</span> <span class="content">Runtime Performance</span></a>
      <li><a href="#ovh"><span class="secno">8.3</span> <span class="content">Overheads</span></a>
     </ol>
    <li><a href="#others"><span class="secno">9</span> <span class="content">Other C++ JIT Approaches</span></a>
    <li><a href="#ack"><span class="secno">10</span> <span class="content">Acknowledgments</span></a>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="intro"><span class="secno">1. </span><span class="content">Introduction</span><a class="self-link" href="#intro"></a></h2>
   <p>C++ is the go-to language for programming performance-sensitive systems. In part, this is due to C++'s design philosophy of "leav[ing] no room for a lower-level language below C++ (except assembler)" (see Appendix A in p0559r0 and Bjarne’s 2007 HoPL paper). As C++ programmers, however, we are faced with a fundamental dilemma:</p>
   <ol>
    <li data-md>
     <p>A compiler can often generate more-efficient code for algorithms in which some important parameters have (compile-time) known values compared to code for the same algorithms for which those same parameters are known only during program execution. These parameters are sometimes values (e.g., the number of rows in the matrix is three) and sometimes types. Types here include both types being operated upon and types representing behavioral composition.</p>
    <li data-md>
     <p>In some cases, we can template the algorithms on these relevant parameters and instantiate the templates for a large set of the parameters likely to be relevant during program execution. The program can then dispatch to a relevant instantiation during program execution, perhaps falling back to a generic implementation. However, this can have a large compile-time cost. In fact, practical limits on compile time often limit the size of the parameter space which can be covered by instantiated templates.</p>
    <li data-md>
     <p>In other cases, the relevant parameter space is so large that a relevant set of instantiations cannot be feasibly selected. In such cases, we’re forced to settle for a generic implementation, even if the actual sets of parameters that occur during any particular program execution is not large.</p>
   </ol>
   <p>If we had the ability to instantiate templates during program execution, using parameters not known until program execution, we could provide the higher performance of fixed-parameter implementations while simultaneously providing improved compile times. This paper explores the following question: Can we naturally integrate this kind of just-in-time (JIT) compilation capability, including the ability to construct novel template instantiations during program execution, into C++?</p>
   <p>Clearly, this kind of JIT compilation capability might not be something that all C++ implementation can provide. In some cases, this is because of technical limitation of the underlying platforms (e.g., in certain kinds of embedded systems). In other cases, this is because the additional risk factors introduced by dynamic compilation are unacceptable in certain environments. Regardless, it seems natural that capabilities in this space would fall into a conditionally-supported category.</p>
   <h2 class="heading settled" data-level="2" id="chlog"><span class="secno">2. </span><span class="content">Changelog</span><a class="self-link" href="#chlog"></a></h2>
   <ul>
    <li data-md>
     <p>r1: Updated to discuss overheads in more detail, ABI considerations, and other issues raised on the reflector.</p>
   </ul>
   <h2 class="heading settled" data-level="3" id="impl"><span class="secno">3. </span><span class="content">Implementation</span><a class="self-link" href="#impl"></a></h2>
   <p>The proposal below has been implemented, and that implementation is available from the repository: <a href="https://github.com/hfinkel/llvm-project-cxxjit">github:hfinkel/llvm-project-cxxjit</a>. There is some additional documentation on the wiki associated with the repository: <a href="https://github.com/hfinkel/llvm-project-cxxjit/wiki">github:hfinkel/llvm-project-cxxjit/wiki</a>. The data presented below was generated using this implementation.</p>
   <h2 class="heading settled" data-level="4" id="prop"><span class="secno">4. </span><span class="content">Proposal</span><a class="self-link" href="#prop"></a></h2>
   <p>This proposal is designed to be minimal, and proposes a JIT capability with an interface limited to function templates. JIT compilation engines, as a practical matter, are generally designed to provide new functions (e.g., to provide a function pointer to some newly-compiled function), making this a natural fit to the underlying technology. Moreover, this allows us to elide questions regarding partial specialization.</p>
   <h3 class="heading settled" data-level="4.1" id="attr"><span class="secno">4.1. </span><span class="content">Attribute</span><a class="self-link" href="#attr"></a></h3>
   <p>Function templates can be tagged for just-in-time compilation by using the attribute:</p>
   <p><code class="highlight"><c- p>[[</c-><c- n>jit</c-><c- p>]]</c-></code></p>
   <p>[ <em>Note</em>:</p>
   <p>In the aforementioned implementation of this proposal, the attribute is named [[clang::jit]].</p>
   <p>-- <em>end note</em> ]</p>
   <p>The attributed function template provides for additional features and restrictions. Features:</p>
   <ol>
    <li data-md>
     <p>Instantiations of this function template will not be constructed at compile time, but rather calling a specialization of the template, or taking the address of a specialization of the template, will trigger the instantiation and compilation of the template during program execution. Note that this property is non-normative (i.e., not observable within the abstract machine) in some cases (e.g., when all template parameters are known at compile time and there are no observable order-of-instantiation dependenceis (see the discussion of state below)).</p>
    <li data-md>
     <p>Non-constant expressions may be provided for the non-type template parameters, and these values will be used during program execution to construct the type of the requested instantiation.</p>
   </ol>
   <h4 class="heading settled" data-level="4.1.1" id="ex1"><span class="secno">4.1.1. </span><span class="content">Example</span><a class="self-link" href="#ex1"></a></h4>
<pre class="highlight"><c- cp>#include</c-> &lt;iostream>
<c- cp>#include</c-> &lt;cstdlib>

<c- k>template</c-> <c- o>&lt;</c-><c- b>int</c-> <c- n>x</c-><c- o>></c->
<c- p>[[</c-><c- n>jit</c-><c- p>]]</c-> <c- b>void</c-> <c- n>run</c-><c- p>()</c-> <c- p>{</c->
  <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"I was compiled at runtime, x = "</c-> <c- o>&lt;&lt;</c-> <c- n>x</c-> <c- o>&lt;&lt;</c-> <c- s>"</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>}</c->

<c- b>int</c-> <c- n>main</c-><c- p>(</c-><c- b>int</c-> <c- n>argc</c-><c- p>,</c-> <c- b>char</c-> <c- o>*</c-><c- n>argv</c-><c- p>[])</c-> <c- p>{</c->
  <c- b>int</c-> <c- n>a</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>atoi</c-><c- p>(</c-><c- n>argv</c-><c- p>[</c-><c- mi>1</c-><c- p>]);</c->
  <c- n>run</c-><c- o>&lt;</c-><c- n>a</c-><c- o>></c-><c- p>();</c->
<c- p>}</c->
</pre>
   <ol start="3">
    <li data-md>
     <p>Type arguments to the template can be provided as strings. If the argument is implicitly convertible to a <code class="highlight"><c- k>const</c-> <c- b>char</c-> <c- o>*</c-></code>, then that conversion is performed, and the result is used to identify the requested type. Otherwise, if an object is provided, and that object has a member function named <code class="highlight"><c- n>c_str</c-><c- p>()</c-></code>, and the result of that function can be converted to a <code class="highlight"><c- k>const</c-> <c- b>char</c-> <c- o>*</c-></code>, then the call and conversion (if necessary) are performed in order to get a string used to identify the type. The string is parsed and analyzed to identify the type in the declaration context of the parent to the function triggering the instantiation. Whether types defined after the point in the source code that triggers the instantiation are available is not specified.</p>
   </ol>
   <h4 class="heading settled" data-level="4.1.2" id="ex2"><span class="secno">4.1.2. </span><span class="content">Example</span><a class="self-link" href="#ex2"></a></h4>
<pre class="highlight"><c- cp>#include</c-> &lt;iostream>

<c- k>struct</c-> <c- n>F</c-> <c- p>{</c->
  <c- b>int</c-> <c- n>i</c-><c- p>;</c->
  <c- b>double</c-> <c- n>d</c-><c- p>;</c->
<c- p>};</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- n>T</c-><c- p>,</c-> <c- b>int</c-> <c- n>S</c-><c- o>></c->
<c- k>struct</c-> <c- n>G</c-> <c- p>{</c->
  <c- n>T</c-> <c- n>arr</c-><c- p>[</c-><c- n>S</c-><c- p>];</c->
<c- p>};</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- n>T</c-><c- o>></c->
<c- p>[[</c-><c- n>jit</c-><c- p>]]</c-> <c- b>void</c-> <c- n>run</c-><c- p>()</c-> <c- p>{</c->
  <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"I was compiled at runtime, sizeof(T) = "</c-> <c- o>&lt;&lt;</c-> <c- k>sizeof</c-><c- p>(</c-><c- n>T</c-><c- p>)</c-> <c- o>&lt;&lt;</c-> <c- s>"</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>}</c->

<c- b>int</c-> <c- n>main</c-><c- p>(</c-><c- b>int</c-> <c- n>argc</c-><c- p>,</c-> <c- b>char</c-> <c- o>*</c-><c- n>argv</c-><c- p>[])</c-> <c- p>{</c->
  <c- n>std</c-><c- o>::</c-><c- n>string</c-> <c- n>t</c-><c- p>(</c-><c- n>argv</c-><c- p>[</c-><c- mi>1</c-><c- p>]);</c->
  <c- n>run</c-><c- o>&lt;</c-><c- n>t</c-><c- o>></c-><c- p>();</c->
<c- p>}</c->
</pre>
   <h3 class="heading settled" data-level="4.2" id="restr"><span class="secno">4.2. </span><span class="content">Restrictions</span><a class="self-link" href="#restr"></a></h3>
   <ol>
    <li data-md>
     <p>Because the body of the template is not instantiated at compile time, <code class="highlight"><c- k>decltype</c-><c- p>(</c-><c- k>auto</c-><c- p>)</c-></code> and any other type-deduction mechanisms depending on the body of the function are not available.</p>
    <li data-md>
     <p>Because the template specializations are not compiled until during program execution, they’re not available at compile time for use as non-type template arguments, etc.</p>
   </ol>
   <p>Explicit specializations of a JIT function template are not just-in-time compiled.</p>
   <p class="note" role="note"><span>Note:</span> A JIT template with a pointer/reference non-type template parameter which is provided with a runtime pointer value will generate a different instantiation for each pointer value. If the pointer provided points to a global object, no attempt is made to map that pointer value back to the name of the global object when constructing the new type.</p>
   <p class="note" role="note"><span>Note:</span> In general, pointer/reference-type non-type template arguments are not permitted to point to subobjects. This restriction still applies formally to the templates instantiated at runtime using runtime-provided pointer values. This has important optimization benefits: pointers that can be traced back to distinct underlying objects are known not to alias, and these template parameters appear to the optimizer to have this unique-object property.</p>
   <h2 class="heading settled" data-level="5" id="desq"><span class="secno">5. </span><span class="content">A Design Question</span><a class="self-link" href="#desq"></a></h2>
   <p>The proposal above reflects what has been implemented, but the use of a attribute might be suboptimal from a language-design perspective. Some points against this attribute approach:</p>
   <ol>
    <li data-md>
     <p>The template is not otherwise special, it’s the point of instantiation that’s special (and that might not compile at all without the JIT support).</p>
    <li data-md>
     <p>The uses of the template look vaguely normal, and so places where you might invoke the JIT compiler will be difficult to spot during code review.</p>
    <li data-md>
     <p>The current mechanism provides no place to get out an error or provide a fall-back execution path - except that having the runtime throw an exception might work.</p>
    <li data-md>
     <p>Should the mechanism be synchronous (as in this proposal), or asynchronous (e.g., something that returns a promise).</p>
   </ol>
   <p>Thus, it might be better to use, e.g., a keyword near the point of instantiation. Perhaps something like this:</p>
<pre class="highlight"><c- n>jit_this_template</c-> <c- n>foo</c-><c- o>&lt;</c-><c- n>argc</c-><c- o>></c-><c- p>();</c->
</pre>
   <p>or maybe:</p>
<pre class="highlight"><c- n>foo</c-> <c- n>jit_this_template</c-> <c- o>&lt;</c-><c- n>argc</c-><c- o>></c-><c- p>();</c->
</pre>
   <p>where <code class="highlight"><c- n>jit_this_template</c-></code> is a new keyword.</p>
   <p>The disadvantage of tying the JIT use to the point of instantiation instead of to the template itself, is that we need to decide that happens if the same instantiation is created both at compile time in the usual manner and also requested to be delayed until program execution. This might be okay or it might be some kind of ODR violation.</p>
   <p>A library-like syntax is also possible (suggestion by Connor Waters):</p>
<pre class="highlight"><c- n>std</c-><c- o>::</c-><c- n>jit</c-><c- o>&lt;</c-><c- n>foo</c-><c- p>,</c-> <c- n>a</c-><c- p>,</c-> <c- n>_</c-><c- p>,</c-> <c- n>b</c-><c- p>,</c-> <c- n>c</c-><c- p>,</c-> <c- n>_</c-><c- p>,</c-> <c- n>_</c-><c- o>></c-><c- p>(</c-><c- n>x</c-><c- p>,</c-> <c- n>y</c-><c- p>,</c-> <c- n>z</c-><c- p>)</c->
</pre>
   <h2 class="heading settled" data-level="6" id="state"><span class="secno">6. </span><span class="content">On State</span><a class="self-link" href="#state"></a></h2>
   <p>Because the instantiation of some templates can affect the instantiation of other templates (e.g., because friend injection can affect later overload resolution), as currently proposed, the implementation of the JIT-compilation functionality cannot be "stateless." While not clearly desirable in general, although it enables some interesting counting tricks (e.g., <a href="http://b.atch.se/posts/non-constant-constant-expressions/">Non-Constant Constant-Expressions in C++</a>), this might be particularly undesirable in the JIT-compilation context: It likely makes it more difficult for the JIT-compilation engine to discard its in-memory state even in cases where that might be otherwise advantageous (e.g., to reduce its memory footprint if resource pressure becomes an issue). It is already a non-trivial question as to whether, and under what conditions, the runtime system might be able to determine that a particular instantiation might become unused, thus enabling the freeing of associated resources.</p>
   <p>As the JIT-compilation process operates on semantically-processed inputs, and so there is no preprocessor state relevant to the JIT-compilation process. This imposes some restriction on the use of the feature: the JIT-compiled code cannot use differences in the preprocessor state (e.g., whether __AVX2__ is defined) to customize its behavior (and/or implementation strategy) based on the capabilities of the system on which the program is running. This restriction is likely undesirable, although it is not clear how best to lift the restriction.</p>
   <h2 class="heading settled" data-level="7" id="abi"><span class="secno">7. </span><span class="content">ABI and Error Handling</span><a class="self-link" href="#abi"></a></h2>
   <p>It is important that the JIT-compilation facility provide robust error handling capabilities. In this light, although observable within the abstract machine, a production-quality implementation might choose to segregate the JIT-compilation engine into a separate process. JIT compilation can fail because, in addition to compiler bugs, the compilation engine might lack some necessary resources, or the code might otherwise trigger some implementation limit. In addition, compilation might fail because an invalid type string was provided or the provided type or value triggered some semantic error (including triggering a static_assert). It might be correct to say that the latter set of conditions are simply undefined behavior, but regardless, providing some ability for the application to handle such errors at the point of instantiation seems useful. No specific mechanism is proposed in this paper, but feedback is certainly desired.</p>
   <p>This is related to questions regarding the ABI: If an application is compiled with all of the necessary metadata embedded with in to compile the JIT-attributed templates, does that metadata format and the underlying interface to the JIT-compilation engine that uses it become part of the ABI that the system must support in order to run the application? The answer to this question seems likely to be yes. In practice, this represents another reason why compilation might fail: ABI incompatibility (e.g., running an application on a system with a JIT-compilation engine incompatible with the one required by the application - one that is too old, for example). At the cost of some (perhaps significant) binary-size overhead, this issue can be avoided by linking the necessary parts of the compiler into the application itself.</p>
   <p>Also related to the question of the ABI is that of inter-compiler compatibility: If different translation units that comprise an application’s code base are compiled with different compilers, and some of these different translation units use JIT-compilation features, does this necessarily cause problems? Implementation experience is certainly needed here, but it seems likely that an appropriate system ABI could be defined that would allow this kind of combination to work. In the case where the use of different compilers implied the corresponding use of different JIT engines, and we want to ensure properties such as global uniqueness of static local variables in inline functions generated by just-in-time compilation, the system would need provide some way for each JIT engine to register with the others which symbols (functions, global variables, etc.) it had generated. It is unknown what else, if anything, might be required. This seems conceptually similar to the notification functionality that already exists in order to notify a debugger about the newly-generated (JIT-compiled) symbols.</p>
   <h2 class="heading settled" data-level="8" id="bench"><span class="secno">8. </span><span class="content">A Benchmark</span><a class="self-link" href="#bench"></a></h2>
   <p>As a benchmark to illustrate the feature, we’ll adapt a benchmark from the <a href="http://eigen.tuxfamily.org/">Eigen</a> library. Specifically, this one: https://github.com/eigenteam/eigen-git-mirror/blob/master/bench/benchmark.cpp</p>
   <p>We want to look at two aspects: Compile time and runtime performance. Eigen provides a matrix type which can either have compile-time-specific or runtime-specified sizes (i.e., the number of rows and columns).</p>
<pre class="highlight"><c- cp>#include</c-> &lt;iostream>
<c- cp>#include</c-> &lt;string>
<c- cp>#include</c-> &lt;chrono>
<c- cp>#include</c-> &lt;cstdlib>

<c- cp>#include</c-> &lt;Eigen/Core>

<c- k>using</c-> <c- k>namespace</c-> <c- n>std</c-><c- p>;</c->
<c- k>using</c-> <c- k>namespace</c-> <c- n>Eigen</c-><c- p>;</c->
</pre>
   <p>If we wish to support a variant of this benchmark supporting float, double, and long double, and supporting any size at runtime, we can adapt the code as:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- n>T</c-><c- o>></c->
<c- b>void</c-> <c- n>test_aot</c-><c- p>(</c-><c- b>int</c-> <c- n>size</c-><c- p>,</c-> <c- b>int</c-> <c- n>repeat</c-><c- p>)</c-> <c- p>{</c->
  <c- n>Matrix</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-><c- n>Dynamic</c-><c- p>,</c-><c- n>Dynamic</c-><c- o>></c-> <c- n>I</c-> <c- o>=</c-> <c- n>Matrix</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-><c- n>Dynamic</c-><c- p>,</c-><c- n>Dynamic</c-><c- o>>::</c-><c- n>Ones</c-><c- p>(</c-><c- n>size</c-><c- p>,</c-> <c- n>size</c-><c- p>);</c->
  <c- n>Matrix</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-><c- n>Dynamic</c-><c- p>,</c-><c- n>Dynamic</c-><c- o>></c-> <c- n>m</c-><c- p>(</c-><c- n>size</c-><c- p>,</c-> <c- n>size</c-><c- p>);</c->
  <c- k>for</c-><c- p>(</c-><c- b>int</c-> <c- n>i</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c-> <c- n>i</c-> <c- o>&lt;</c-> <c- n>size</c-><c- p>;</c-> <c- n>i</c-><c- o>++</c-><c- p>)</c->
  <c- k>for</c-><c- p>(</c-><c- b>int</c-> <c- n>j</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c-> <c- n>j</c-> <c- o>&lt;</c-> <c- n>size</c-><c- p>;</c-> <c- n>j</c-><c- o>++</c-><c- p>)</c-> <c- p>{</c->
    <c- n>m</c-><c- p>(</c-><c- n>i</c-><c- p>,</c-><c- n>j</c-><c- p>)</c-> <c- o>=</c-> <c- p>(</c-><c- n>i</c-><c- o>+</c-><c- n>size</c-><c- o>*</c-><c- n>j</c-><c- p>);</c->
  <c- p>}</c->

  <c- k>auto</c-> <c- n>start</c-> <c- o>=</c-> <c- n>chrono</c-><c- o>::</c-><c- n>system_clock</c-><c- o>::</c-><c- n>now</c-><c- p>();</c->

  <c- k>for</c-> <c- p>(</c-><c- b>int</c-> <c- n>r</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c-> <c- n>r</c-> <c- o>&lt;</c-> <c- n>repeat</c-><c- p>;</c-> <c- o>++</c-><c- n>r</c-><c- p>)</c-> <c- p>{</c->
    <c- n>m</c-> <c- o>=</c-> <c- n>Matrix</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-><c- n>Dynamic</c-><c- p>,</c-><c- n>Dynamic</c-><c- o>>::</c-><c- n>Ones</c-><c- p>(</c-><c- n>size</c-><c- p>,</c-> <c- n>size</c-><c- p>)</c-> <c- o>+</c-> <c- n>T</c-><c- p>(</c-><c- mf>0.00005</c-><c- p>)</c-> <c- o>*</c-> <c- p>(</c-><c- n>m</c-> <c- o>+</c-> <c- p>(</c-><c- n>m</c-><c- o>*</c-><c- n>m</c-><c- p>));</c->
  <c- p>}</c->

  <c- k>auto</c-> <c- n>end</c-> <c- o>=</c-> <c- n>chrono</c-><c- o>::</c-><c- n>system_clock</c-><c- o>::</c-><c- n>now</c-><c- p>();</c->
  <c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"AoT: "</c-> <c- o>&lt;&lt;</c-> <c- n>chrono</c-><c- o>::</c-><c- n>duration</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c-><c- p>(</c-><c- n>end</c-> <c- o>-</c-> <c- n>start</c-><c- p>).</c-><c- n>count</c-><c- p>()</c-> <c- o>&lt;&lt;</c-> <c- s>" s</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>}</c->

<c- b>void</c-> <c- n>test_aot</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>string</c-> <c- o>&amp;</c-><c- n>type</c-><c- p>,</c-> <c- b>int</c-> <c- n>size</c-><c- p>,</c-> <c- b>int</c-> <c- n>repeat</c-><c- p>)</c-> <c- p>{</c->
  <c- k>if</c-> <c- p>(</c-><c- n>type</c-> <c- o>==</c-> <c- s>"float"</c-><c- p>)</c->
    <c- n>test_aot</c-><c- o>&lt;</c-><c- b>float</c-><c- o>></c-><c- p>(</c-><c- n>size</c-><c- p>,</c-> <c- n>repeat</c-><c- p>);</c->
  <c- k>else</c-> <c- nf>if</c-> <c- p>(</c-><c- n>type</c-> <c- o>==</c-> <c- s>"double"</c-><c- p>)</c->
    <c- n>test_aot</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c-><c- p>(</c-><c- n>size</c-><c- p>,</c-> <c- n>repeat</c-><c- p>);</c->
  <c- k>else</c-> <c- nf>if</c-> <c- p>(</c-><c- n>type</c-> <c- o>==</c-> <c- s>"long double"</c-><c- p>)</c->
    <c- n>test_aot</c-><c- o>&lt;</c-><c- b>long</c-> <c- b>double</c-><c- o>></c-><c- p>(</c-><c- n>size</c-><c- p>,</c-> <c- n>repeat</c-><c- p>);</c->
  <c- k>else</c->
    <c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- n>type</c-> <c- o>&lt;&lt;</c-> <c- s>"not supported for AoT</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>To do the same thing with the JIT feature, we can write:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- n>T</c-><c- p>,</c-> <c- b>int</c-> <c- n>size</c-><c- o>></c->
<c- p>[[</c-><c- n>jit</c-><c- p>]]</c-> <c- b>void</c-> <c- n>test_jit_sz</c-><c- p>(</c-><c- b>int</c-> <c- n>repeat</c-><c- p>)</c-> <c- p>{</c->
  <c- n>Matrix</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-><c- n>size</c-><c- p>,</c-><c- n>size</c-><c- o>></c-> <c- n>I</c-> <c- o>=</c-> <c- n>Matrix</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-><c- n>size</c-><c- p>,</c-><c- n>size</c-><c- o>>::</c-><c- n>Ones</c-><c- p>();</c->
  <c- n>Matrix</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-><c- n>size</c-><c- p>,</c-><c- n>size</c-><c- o>></c-> <c- n>m</c-><c- p>;</c->
  <c- k>for</c-><c- p>(</c-><c- b>int</c-> <c- n>i</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c-> <c- n>i</c-> <c- o>&lt;</c-> <c- n>size</c-><c- p>;</c-> <c- n>i</c-><c- o>++</c-><c- p>)</c->
  <c- k>for</c-><c- p>(</c-><c- b>int</c-> <c- n>j</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c-> <c- n>j</c-> <c- o>&lt;</c-> <c- n>size</c-><c- p>;</c-> <c- n>j</c-><c- o>++</c-><c- p>)</c-> <c- p>{</c->
    <c- n>m</c-><c- p>(</c-><c- n>i</c-><c- p>,</c-><c- n>j</c-><c- p>)</c-> <c- o>=</c-> <c- p>(</c-><c- n>i</c-><c- o>+</c-><c- n>size</c-><c- o>*</c-><c- n>j</c-><c- p>);</c->
  <c- p>}</c->

  <c- k>auto</c-> <c- n>start</c-> <c- o>=</c-> <c- n>chrono</c-><c- o>::</c-><c- n>system_clock</c-><c- o>::</c-><c- n>now</c-><c- p>();</c->

  <c- k>for</c-> <c- p>(</c-><c- b>int</c-> <c- n>r</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c-> <c- n>r</c-> <c- o>&lt;</c-> <c- n>repeat</c-><c- p>;</c-> <c- o>++</c-><c- n>r</c-><c- p>)</c-> <c- p>{</c->
    <c- n>m</c-> <c- o>=</c-> <c- n>Matrix</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-><c- n>size</c-><c- p>,</c-><c- n>size</c-><c- o>>::</c-><c- n>Ones</c-><c- p>()</c-> <c- o>+</c-> <c- n>T</c-><c- p>(</c-><c- mf>0.00005</c-><c- p>)</c-> <c- o>*</c-> <c- p>(</c-><c- n>m</c-> <c- o>+</c-> <c- p>(</c-><c- n>m</c-><c- o>*</c-><c- n>m</c-><c- p>));</c->
  <c- p>}</c->

  <c- k>auto</c-> <c- n>end</c-> <c- o>=</c-> <c- n>chrono</c-><c- o>::</c-><c- n>system_clock</c-><c- o>::</c-><c- n>now</c-><c- p>();</c->
  <c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"JIT: "</c-> <c- o>&lt;&lt;</c-> <c- n>chrono</c-><c- o>::</c-><c- n>duration</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c-><c- p>(</c-><c- n>end</c-> <c- o>-</c-> <c- n>start</c-><c- p>).</c-><c- n>count</c-><c- p>()</c-> <c- o>&lt;&lt;</c-> <c- s>" s</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>}</c->

<c- b>void</c-> <c- n>test_jit</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>string</c-> <c- o>&amp;</c-><c- n>type</c-><c- p>,</c-> <c- b>int</c-> <c- n>size</c-><c- p>,</c-> <c- b>int</c-> <c- n>repeat</c-><c- p>)</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>test_jit_sz</c-><c- o>&lt;</c-><c- n>type</c-><c- p>,</c-> <c- n>size</c-><c- o>></c-><c- p>(</c-><c- n>repeat</c-><c- p>);</c->
<c- p>}</c->
</pre>
   <p>And we can use very-similar code to construct explicit instantiations at compile time, but of course, then we’re limited to support for the explicit sizes we have selected.</p>
   <h3 class="heading settled" data-level="8.1" id="ctperf"><span class="secno">8.1. </span><span class="content">Compile Time</span><a class="self-link" href="#ctperf"></a></h3>
   <p>Compiling using the implementation linked above on an Intel Xeon E5-2699 using the flags <code class="highlight"><c- o>-</c-><c- n>march</c-><c- o>=</c-><c- n>native</c-> <c- o>-</c-><c- n>ffast</c-><c- o>-</c-><c- n>math</c-> <c- o>-</c-><c- n>O3</c-></code>, and measuring compile time using "user" time from the Linux <code class="highlight"><c- n>time</c-></code> command.</p>
   <table>
    <thead>
     <tr>
      <th>
      <th>Time
      <th>Time over Base
    <tbody>
     <tr>
      <td>JIT Only
      <td>3.5s
      <td>0.92s
     <tr>
      <td>(AoT) Single Specialization (double, size = 16)
      <td>4.95s
      <td>2.37s
     <tr>
      <td>(AoT) Single Specialization (double, size = 7)
      <td>3.3s
      <td>0.72s
     <tr>
      <td>(AoT) Single Specialization (double, size = 3)
      <td>3.2s
      <td>0.62s
     <tr>
      <td>(AoT) Single Specialization (double, size = 1)
      <td>2.95s
      <td>0.37s
     <tr>
      <td>(AoT) Two Specializations (double, size = 16) and (double, 7)
      <td>5.7s
      <td>3.12s
     <tr>
      <td>Generic AoT Only (three floating-point types with dispatch)
      <td>9.7s
      <td>7.12s
     <tr>
      <td>Generic AoT Only (double only)
      <td>5.3s
      <td>2.72s
     <tr>
      <td>Nothing (just the includes and a main function)
      <td>2.58s
      <td>-
   </table>
   <p>As you can see, the time for generating each specific specialization is essentially additive, and they get more expensive as the fixed matrix sizes get longer. Generating the code for the JIT has a compile-time cost, but it’s not even as expensive as a single non-fixed-size implementation.</p>
   <h3 class="heading settled" data-level="8.2" id="rtperf"><span class="secno">8.2. </span><span class="content">Runtime Performance</span><a class="self-link" href="#rtperf"></a></h3>
   <p>For (double, size = 3); a repeat count of 40000000. Times as reported by the code (excludes JIT compilation time).</p>
   <table>
    <thead>
     <tr>
      <th>
      <th>Time
    <tbody>
     <tr>
      <td>JIT
      <td>1.0s
     <tr>
      <td>Single Specialization
      <td>1.01s
     <tr>
      <td>AoT
      <td>8.05s
   </table>
   <p>For (double, size = 7)</p>
   <table>
    <thead>
     <tr>
      <th>
      <th>Time
    <tbody>
     <tr>
      <td>JIT
      <td>8.34s
     <tr>
      <td>Single Specialization
      <td>8.45s
     <tr>
      <td>AoT
      <td>20s
   </table>
   <p>For (double, size = 16)</p>
   <table>
    <thead>
     <tr>
      <th>
      <th>Time
    <tbody>
     <tr>
      <td>JIT
      <td>35.3s
     <tr>
      <td>Single Specialization
      <td>35.1s
     <tr>
      <td>AoT
      <td>36.2s
   </table>
   <p>A few trends to notice:</p>
   <p>The JIT-generated code is <strong>significantly</strong> faster than the ahead-of-time-generated code for small matrix sizes. The advantage becomes less significant as the matrix sizes become larger. At a high level, this is easy to understand: as the matrix sizes become larger, the value to the optimizer of knowing the exact size decreases.</p>
   <p>Thus, using the JIT gives the performance advantages of using many ahead-of-time specializations, and is sometimes even better, with very low compile-time cost.</p>
   <p>For more information, see: <a href="https://arxiv.org/abs/1904.08555">arXiv:1904.08555</a>.</p>
   <h3 class="heading settled" data-level="8.3" id="ovh"><span class="secno">8.3. </span><span class="content">Overheads</span><a class="self-link" href="#ovh"></a></h3>
   <p>There is no overhead to the presence of the JIT-compilation feature in the language when it is not used (although if the feature is enabled, and that causes the compiler to link with the JIT-compilation engine, that can cause both an increase in link time and binary size if the implementation is not aggressive about pruning those dependencies). When the JIT feature is used, however, there are additional costs. Clang’s serialized AST can be large, and the current implementation makes no attempt to prune it before embedding it into each object file. For example, in this benchmark, the AoT-only executable is 135 KB in size. The executable making use of the JIT-compilation feature is 12 MB in size, and this does not include the size of the compiled Clang and LLVM libraries. If these libraries are linked to the application statically, instead of dynamically, the size of the binary increases to 75 MB (again, no attempt has yet been made to exclude unnecessary parts of the compiler in the current implementation). In the current implementation, the memory overhead of the JIT-compilation engine is approximately 127 MB, although efforts to prune the serialized AST might be able to reduce that significantly.</p>
   <p>Regarding runtime overheads, on an Intel Haswell processor, for the simplest lookup involving a single template argument, the instantiation-cache lookup takes approximately 350 cycles (approximately 140 ns). Should the cache lookup fail, but solely because some types were specified using different names, resolving the instantiation request to the previously-compiled function takes approximately 160 thousand cycles (approximately 65 us). Compiling new instantiations takes, at the very least, tens of millions of cycles (a few milliseconds). The compilation time of a new instantiation, of course, depends heavily on the amount and complexity of the code being compiled (for the example above, this is essentially the time over baseline for each (AoT) single specialization).</p>
   <h2 class="heading settled" data-level="9" id="others"><span class="secno">9. </span><span class="content">Other C++ JIT Approaches</span><a class="self-link" href="#others"></a></h2>
   <p>Combining C++ with JIT compilation is not new. See:</p>
   <ul>
    <li data-md>
     <p>Facebook’s C++ JIT <a href="https://llvm.org/devmtg/2019-04/talks.html#Talk_15">talk</a> / <a href="https://llvm.org/devmtg/2019-04/talks.html#Poster_9">poster</a></p>
    <li data-md>
     <p>CERN’s <a href="https://root.cern.ch/cling">Cling</a></p>
    <li data-md>
     <p>From the RuntimeCompiledCPlusPlus project, <a href="https://github.com/RuntimeCompiledCPlusPlus/RuntimeCompiledCPlusPlus/wiki/Alternatives">A large list</a></p>
   </ul>
   <p>An alternate method for providing an C++ JIT interface is to provide a mechanism, some kind of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>eval</c-></code>, which takes a string representing C++ code and evaluates it. Such an interface raises a number of additional questions compared to the interface proposed here, including: Should preprocessor macros be expanded inside of the string, and if so, with what preprocessor state? Do different calls to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>eval</c-></code> have any effect on each other (i.e., can one call to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>eval</c-></code> define a function called by code in another call to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>eval</c-></code>)? If so, are these state changes scoped in any way? If not, would such an interface likely be inefficient to use because it would require reprocessing large amounts of C++ code every time it is invoked? What facilities would need to be provided so that the code designed to construct the to-be-dynamically-executed C++ code could be maintainable?</p>
   <p>The flavor of JIT-compilation proposed here aims to provide this capability in keeping with the general C++ philosophy of minimal overhead and explicit programmer control. This makes it a different kind of JIT-compilation than that provided in many of JIT-compiled languages (e.g., Java or Javascript) - in these languages all of the code is JIT-compiled (or interpreted), and sophisticated multi-tiered JIT-compilation, using techniques such as OSR (on-stack replacement) and deoptimiation, is used to minimize compilation time spent on all code not measured to be hot (i.e., profiling information is not just used by the JIT-compilation engine itself, but is used to figure out what the JIT-compilaton engine should compile in the first place). This proposal focuses on providing a user-directed JIT compilation of code that the programmer already knows is worth compiling during program execution. Future extensions to this proposal might allow for providing some range of possible values/types for template instantation for use by a JIT-compilation engine capable of performing some online autotuning using that information.</p>
   <h2 class="heading settled" data-level="10" id="ack"><span class="secno">10. </span><span class="content">Acknowledgments</span><a class="self-link" href="#ack"></a></h2>
   <p>I’d like to thank David Poliakoff for a lot of testing and feedback on the implementation, and I’d like to thank the many committee members who provided me with feedback on this idea during the Kona meeting and on the reflector (including, but certainly not limited to, Herb Sutter, Chandler Carruth, Olivier Giroux, Vinod Grover, Matthias Kretz, and JF Bastien). I’d also like to thank Michał Dominiak, Nir Friedman, and Connor Waters for providing early feedback online.</p>
   <p>This research was supported by the Exascale Computing Project (17-SC-20-SC), a collaborative effort of two U.S. Department of Energy organizations (Office of Science and the National Nuclear Security Administration) responsible for the planning and preparation of a capable exascale ecosystem, including software, applications, hardware, advanced system engineering, and early testbed platforms, in support of the nation’s exascale computing imperative. Additionally, this research used resources of the Argonne Leadership Computing Facility, which is a DOE Office of Science User Facility supported under Contract DE-AC02-06CH11357.</p>
  </main>
<script>
(function() {
  "use strict";
  var collapseSidebarText = '<span aria-hidden="true">←</span> '
                          + '<span>Collapse Sidebar</span>';
  var expandSidebarText   = '<span aria-hidden="true">→</span> '
                          + '<span>Pop Out Sidebar</span>';
  var tocJumpText         = '<span aria-hidden="true">↑</span> '
                          + '<span>Jump to Table of Contents</span>';

  var sidebarMedia = window.matchMedia('screen and (min-width: 78em)');
  var autoToggle   = function(e){ toggleSidebar(e.matches) };
  if(sidebarMedia.addListener) {
    sidebarMedia.addListener(autoToggle);
  }

  function toggleSidebar(on) {
    if (on == undefined) {
      on = !document.body.classList.contains('toc-sidebar');
    }

    /* Don’t scroll to compensate for the ToC if we’re above it already. */
    var headY = 0;
    var head = document.querySelector('.head');
    if (head) {
      // terrible approx of "top of ToC"
      headY += head.offsetTop + head.offsetHeight;
    }
    var skipScroll = window.scrollY < headY;

    var toggle = document.getElementById('toc-toggle');
    var tocNav = document.getElementById('toc');
    if (on) {
      var tocHeight = tocNav.offsetHeight;
      document.body.classList.add('toc-sidebar');
      document.body.classList.remove('toc-inline');
      toggle.innerHTML = collapseSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, 0 - tocHeight);
      }
      tocNav.focus();
      sidebarMedia.addListener(autoToggle); // auto-collapse when out of room
    }
    else {
      document.body.classList.add('toc-inline');
      document.body.classList.remove('toc-sidebar');
      toggle.innerHTML = expandSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, tocNav.offsetHeight);
      }
      if (toggle.matches(':hover')) {
        /* Unfocus button when not using keyboard navigation,
           because I don’t know where else to send the focus. */
        toggle.blur();
      }
    }
  }

  function createSidebarToggle() {
    /* Create the sidebar toggle in JS; it shouldn’t exist when JS is off. */
    var toggle = document.createElement('a');
      /* This should probably be a button, but appearance isn’t standards-track.*/
    toggle.id = 'toc-toggle';
    toggle.class = 'toc-toggle';
    toggle.href = '#toc';
    toggle.innerHTML = collapseSidebarText;

    sidebarMedia.addListener(autoToggle);
    var toggler = function(e) {
      e.preventDefault();
      sidebarMedia.removeListener(autoToggle); // persist explicit off states
      toggleSidebar();
      return false;
    }
    toggle.addEventListener('click', toggler, false);


    /* Get <nav id=toc-nav>, or make it if we don’t have one. */
    var tocNav = document.getElementById('toc-nav');
    if (!tocNav) {
      tocNav = document.createElement('p');
      tocNav.id = 'toc-nav';
      /* Prepend for better keyboard navigation */
      document.body.insertBefore(tocNav, document.body.firstChild);
    }
    /* While we’re at it, make sure we have a Jump to Toc link. */
    var tocJump = document.getElementById('toc-jump');
    if (!tocJump) {
      tocJump = document.createElement('a');
      tocJump.id = 'toc-jump';
      tocJump.href = '#toc';
      tocJump.innerHTML = tocJumpText;
      tocNav.appendChild(tocJump);
    }

    tocNav.appendChild(toggle);
  }

  var toc = document.getElementById('toc');
  if (toc) {
    createSidebarToggle();
    toggleSidebar(sidebarMedia.matches);

    /* If the sidebar has been manually opened and is currently overlaying the text
       (window too small for the MQ to add the margin to body),
       then auto-close the sidebar once you click on something in there. */
    toc.addEventListener('click', function(e) {
      if(e.target.tagName.toLowerCase() == "a" && document.body.classList.contains('toc-sidebar') && !sidebarMedia.matches) {
        toggleSidebar(false);
      }
    }, false);
  }
  else {
    console.warn("Can’t find Table of Contents. Please use <nav id='toc'> around the ToC.");
  }

  /* Wrap tables in case they overflow */
  var tables = document.querySelectorAll(':not(.overlarge) > table.data, :not(.overlarge) > table.index');
  var numTables = tables.length;
  for (var i = 0; i < numTables; i++) {
    var table = tables[i];
    var wrapper = document.createElement('div');
    wrapper.className = 'overlarge';
    table.parentNode.insertBefore(wrapper, table);
    wrapper.appendChild(table);
  }

})();
</script>