<!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>P1609R3: 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) and (display:contents) {
		/* 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;
    }

    del { background: #fcc; color: #000; text-decoration: line-through; }
    ins { background: #cfc; color: #000; }
    blockquote .highlight:not(.idl) { background: initial; margin: initial; padding: 0.5em }
    blockquote ul { background: inherit; }
    blockquote code.highlight:not(.idl) { padding: initial; }
    blockquote c-[a] { color: inherit; } /* Keyword.Declaration */
    blockquote c-[b] { color: inherit; } /* Keyword.Type */
    blockquote c-[c] { color: inherit; } /* Comment */
    blockquote c-[d] { color: inherit; } /* Comment.Multiline */
    blockquote c-[e] { color: inherit; } /* Name.Attribute */
    blockquote c-[f] { color: inherit; } /* Name.Tag */
    blockquote c-[g] { color: inherit; } /* Name.Variable */
    blockquote c-[k] { color: inherit; } /* Keyword */
    blockquote c-[l] { color: inherit; } /* Literal */
    blockquote c-[m] { color: inherit; } /* Literal.Number */
    blockquote c-[n] { color: inherit; } /* Name */
    blockquote c-[o] { color: inherit; } /* Operator */
    blockquote c-[p] { color: inherit; } /* Punctuation */
    blockquote c-[s] { color: inherit; } /* Literal.String */
    blockquote c-[t] { color: inherit; } /* Literal.String.Single */
    blockquote c-[u] { color: inherit; } /* Literal.String.Double */
    blockquote c-[cp] { color: inherit; } /* Comment.Preproc */
    blockquote c-[c1] { color: inherit; } /* Comment.Single */
    blockquote c-[cs] { color: inherit; } /* Comment.Special */
    blockquote c-[kc] { color: inherit; } /* Keyword.Constant */
    blockquote c-[kn] { color: inherit; } /* Keyword.Namespace */
    blockquote c-[kp] { color: inherit; } /* Keyword.Pseudo */
    blockquote c-[kr] { color: inherit; } /* Keyword.Reserved */
    blockquote c-[ld] { color: inherit; } /* Literal.Date */
    blockquote c-[nc] { color: inherit; } /* Name.Class */
    blockquote c-[no] { color: inherit; } /* Name.Constant */
    blockquote c-[nd] { color: inherit; } /* Name.Decorator */
    blockquote c-[ni] { color: inherit; } /* Name.Entity */
    blockquote c-[ne] { color: inherit; } /* Name.Exception */
    blockquote c-[nf] { color: inherit; } /* Name.Function */
    blockquote c-[nl] { color: inherit; } /* Name.Label */
    blockquote c-[nn] { color: inherit; } /* Name.Namespace */
    blockquote c-[py] { color: inherit; } /* Name.Property */
    blockquote c-[ow] { color: inherit; } /* Operator.Word */
    blockquote c-[mb] { color: inherit; } /* Literal.Number.Bin */
    blockquote c-[mf] { color: inherit; } /* Literal.Number.Float */
    blockquote c-[mh] { color: inherit; } /* Literal.Number.Hex */
    blockquote c-[mi] { color: inherit; } /* Literal.Number.Integer */
    blockquote c-[mo] { color: inherit; } /* Literal.Number.Oct */
    blockquote c-[sb] { color: inherit; } /* Literal.String.Backtick */
    blockquote c-[sc] { color: inherit; } /* Literal.String.Char */
    blockquote c-[sd] { color: inherit; } /* Literal.String.Doc */
    blockquote c-[se] { color: inherit; } /* Literal.String.Escape */
    blockquote c-[sh] { color: inherit; } /* Literal.String.Heredoc */
    blockquote c-[si] { color: inherit; } /* Literal.String.Interpol */
    blockquote c-[sx] { color: inherit; } /* Literal.String.Other */
    blockquote c-[sr] { color: inherit; } /* Literal.String.Regex */
    blockquote c-[ss] { color: inherit; } /* Literal.String.Symbol */
    blockquote c-[vc] { color: inherit; } /* Name.Variable.Class */
    blockquote c-[vg] { color: inherit; } /* Name.Variable.Global */
    blockquote c-[vi] { color: inherit; } /* Name.Variable.Instance */
    blockquote c-[il] { color: inherit; } /* Literal.Number.Integer.Long */
  </style>
  <meta content="Bikeshed version 2dbd5e1f0bb11704a5d90167ddaef9475f9c26b3" name="generator">
  <link href="http://wg21.link/p1609" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
  <meta content="8ee36464b2961b0c833410b0c4c3a0ed10647845" 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">P1609R3<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="2020-01-13">2020-01-13</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>Issue Tracking:
     <dd><a href="#issues-index">Inline In Spec</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>SG7, 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="#prop2"><span class="secno">4</span> <span class="content">Proposal</span></a>
     <ol class="toc">
      <li><a href="#hdr"><span class="secno">4.1</span> <span class="content">Header &lt;dynamic_instantiation></span></a>
      <li><a href="#diag"><span class="secno">4.2</span> <span class="content">Class diagnostic</span></a>
      <li><a href="#dfti"><span class="secno">4.3</span> <span class="content">dynamic_function_template_instantiation Operator</span></a>
      <li><a href="#dta"><span class="secno">4.4</span> <span class="content">dynamic_template_argument Operator</span></a>
      <li><a href="#attr1"><span class="secno">4.5</span> <span class="content">for_dynamic_instantiation Attribute</span></a>
     </ol>
    <li><a href="#ex2"><span class="secno">5</span> <span class="content">Examples</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>
    <li><a href="#issues-index"><span class="secno"></span> <span class="content">Issues Index</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 are 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 some kind of effective 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>r3: Updated based on feedback from the Belfast meeting.</p>
    <li data-md>
     <p>r2: Updated based on feedback from the Cologne meeting.</p>
    <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>. The interface proposed in this version of the paper is available in branch "cxxjit-ni-9.0". 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="prop2"><span class="secno">4. </span><span class="content">Proposal</span><a class="self-link" href="#prop2"></a></h2>
   <p>After the evening-session discussion in Cologne, and review by EWGI, what follows is an updated proposal for the interface for this functionality. This is not intended to be formal wording, but is intended to be detailed enough to prompt a detailed discussion.</p>
   <h3 class="heading settled" data-level="4.1" id="hdr"><span class="secno">4.1. </span><span class="content">Header &lt;dynamic_instantiation></span><a class="self-link" href="#hdr"></a></h3>
<pre class="highlight"><c- cp>#include</c-> &lt;source_location> // see 17.8.1
<c- cp>#include</c-> &lt;string>          // see 21.3.1

<c- k>namespace</c-> <c- n>std</c-> <c- p>{</c->
  <c- k>struct</c-> <c- n>diagnostic</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p class="issue" id="issue-70d64c7a"><a class="self-link" href="#issue-70d64c7a"></a> How should we indicate when we know that the feature won’t be available (feature macro, constexpr function, both, something else)?</p>
   <h3 class="heading settled" data-level="4.2" id="diag"><span class="secno">4.2. </span><span class="content">Class diagnostic</span><a class="self-link" href="#diag"></a></h3>
<pre class="highlight"><c- k>namespace</c-> <c- n>std</c-> <c- p>{</c->

  <c- k>struct</c-> <c- n>diagnostic</c-> <c- p>{</c->
    <c- k>const</c-> <c- n>std</c-><c- o>::</c-><c- n>string</c-> <c- o>&amp;</c-><c- n>message</c-><c- p>()</c-> <c- k>const</c-><c- p>;</c->
    <c- k>const</c-> <c- n>std</c-><c- o>::</c-><c- n>source_location</c-> <c- o>&amp;</c-><c- n>location</c-><c- p>()</c-> <c- k>const</c-><c- p>;</c->
  <c- p>};</c->
<c- p>}</c->
</pre>
   <p>The type </p>
<pre class="highlight"><c- n>diagnotsic</c-></pre>
    meets the Cpp17CopyConstructible, Cpp17CopyAssignable, and Cpp17Destructible requirements (16.5.3.1). Lvalues of type source_location are swappable (16.5.3.2).
   <p></p>
   <p>The class diagnostic represents a single compiler diagnostic associated with an evaluation of the dynamic_function_template_instantiation operator. These diagnostics might be errors, indicating that the requested instantiation is ill-formed or that the implementation is otherwise unable to create the requested instantiation, or might represent other information the implementation provides about a well-formed instantiation. The content of the message is implementation defined.</p>
   <h3 class="heading settled" data-level="4.3" id="dfti"><span class="secno">4.3. </span><span class="content">dynamic_function_template_instantiation Operator</span><a class="self-link" href="#dfti"></a></h3>
<pre class="highlight"><c- n>postfix</c-><c- o>-</c-><c- nl>expression</c-><c- p>:</c->
  <c- c1>// add the following...</c->
  <c- n>dynamic_function_template_instantiation</c-> <c- o>&lt;</c-> <c- n>id</c-><c- o>-</c-><c- n>expression</c-> <c- o>></c-> <c- p>(</c-> <c- n>expression</c-><c- o>-</c-><c- n>list_opt</c-> <c- p>)</c->
</pre>
   <p>dynamic_function_template_instantiation operator takes an id-expression. This id-expression must name a non-overloaded function template, and that function template must have a unambiguous function type that is not dependent on any of its template parameters.</p>
   <p>[ <em>Note</em>:</p>
   <p>Implementations are encouraged to warn users if the id-expression refers to a function-template without the for_dynamic_insantiation attribute.</p>
   <p>-- <em>end note</em> ]</p>
   <p>The result of a dynamic_function_template_instantiation-expression is an lvalue of an unspecified class type meeting the Cpp17MoveConstructible, Cpp17MoveAssignable, and Cpp17Destructible requirements (16.5.3.1).</p>
   <p>The evaluation of the operator shall be an ODR use of the function template identified by </p>
<pre class="highlight"><c- n>id</c-><c- o>-</c-><c- n>expression</c-> <c- o>&lt;</c-> <c- k>template</c-><c- o>-</c-><c- n>argument</c-><c- o>-</c-><c- n>list</c-> <c- o>></c-> </pre>
    where the template-argument list is composed from the operator’s expression list. The expressions in this list are treated as non-type template parameters except those expressions with the type of some dynamic_template_argument-operator evaluation. In the latter case, the template argument is that represented by the expression.
   <p></p>
   <p>The dynamic instantiation may not succeed. The class type of the result shall be implicitly convertable to bool, and if the dynamic instantiation did not succeed, the value of this conversation shall be false.</p>
   <p>The class type shall have a function-call operator of the same type as the named function template, and if the instantiation succeeds, invoking that operator will invoke the dynamically-instantiated function template. If the instantiation does not succeed, and the function-call operator is invoked, the behavior is undefined.</p>
   <p>[ <em>Note</em>:</p>
   <p>Invoking the function-call operator is intended to be an operation akin in expense to an indirect function call. Type checking and other related operations should be performed during evaluation of the dynamic_function_template_instantiation operator.</p>
   <p>-- <em>end note</em> ]</p>
   <p>The class type shall have two const member functions, one named errors, and one named warnings, and these shall return a reference to an iterable collection of std::diagnostic objects.</p>
   <p class="issue" id="issue-ad88896e"><a class="self-link" href="#issue-ad88896e"></a> Can the syntax be extended in some way to relax the restriction on overloaded function templates? Maybe allowing an optional parenthesized type list after the id-expression?</p>
   <p class="issue" id="issue-581b5564"><a class="self-link" href="#issue-581b5564"></a> What should we say about the statefulness of the instantiation process? For example, does the result of friend injection persist across different evaluations of the operator?</p>
   <p class="issue" id="issue-e4ea07b5"><a class="self-link" href="#issue-e4ea07b5"></a> How might we provide additional information to the implementation to direct the compilation (e.g., compiler-optimization flags or some equivalent)?</p>
   <p class="issue" id="issue-413c1947"><a class="self-link" href="#issue-413c1947"></a> How can we provide the ability to save/restore the compilation state of particular instantiations (e.g., into / out of a stream)?</p>
   <p>Variables that are ODR used, transitively, only by a dynamically-instantiated template, even if such a variable would otherwise have static storage duration, may be destroyed at any point after all relevant result objects of the dynamic_function_template_instantiation operators have been destroyed.</p>
   <p>[ <em>Note</em>:</p>
   <p>This is intended to allow an implementation to reclaim resources associated with global variables with inline linkage and other related code and data associated with the dynamic instantiations.</p>
   <p>-- <em>end note</em> ]</p>
   <h3 class="heading settled" data-level="4.4" id="dta"><span class="secno">4.4. </span><span class="content">dynamic_template_argument Operator</span><a class="self-link" href="#dta"></a></h3>
<pre class="highlight"><c- n>postfix</c-><c- o>-</c-><c- nl>expression</c-><c- p>:</c->
  <c- c1>// add the following...</c->
  <c- n>dynamic_template_argument</c-> <c- o>&lt;</c-> <c- k>template</c-><c- o>-</c-><c- n>argument</c-> <c- p>...</c-><c- n>_opt</c-> <c- o>></c->
</pre>
   <p>The result of a dynamic_template_argument-expression is an lvalue of an unspecified class type meeting the Cpp17CopyConstructible, Cpp17CopyAssignable, and Cpp17Destructible requirements (16.5.3.1). Unlike otherwise, a template argument that is an expression need not be a constant expression. The template argument is evaluated.</p>
   <p>[ <em>Note</em>:</p>
   <p>In the aforementioned implementation of this proposal, the operators are named __clang_dynamic_function_template_instantiation and __clang_dynamic_template_argument.</p>
   <p>-- <em>end note</em> ]</p>
   <p>If the header &lt;dynamic_instantiation> is not included prior to any use of the dynamic_function_template_instantiation operator or the dynamic_template_argument operator, the program is ill-formed.</p>
   <p>[ <em>Note</em>:</p>
   <p>This is intended to allow implementations to provide additional definitions in the header that are associated with uses of those operators.</p>
   <p>-- <em>end note</em> ]</p>
   <p>[ <em>Note</em>:</p>
   <p>In the aforementioned implementation of this proposal, this header is not required (an internal header is automatically included with the -fjit flag is provided).</p>
   <p>-- <em>end note</em> ]</p>
   <p class="issue" id="issue-80d0562f"><a class="self-link" href="#issue-80d0562f"></a> Should we make the result types of the operators named types provided by the header file? This may be necessary, at least in some cases, to be useful on interfaces.</p>
   <p class="issue" id="issue-1ddf0852"><a class="self-link" href="#issue-1ddf0852"></a> Should dynamic_template_argument and typeid be unified in some way?</p>
   <p>When the template argument is an id-expression naming a template, the result type shall have a member function named compose that takes a variable number of arguments. If the argument has the result type of some dynamic_template_argument operator, then it is used directly. Otherwise, the dynamic_template_argument operator is implicitly applied to each argument. The result of compose shall be the same as applying dynamic_template_argument to the type formed by combining the id-expression, as a template name, with the template-argument list corresponding to the expressions provided.</p>
   <p>[ <em>Note</em>:</p>
   <p>There is no mechanism provided here to detect errors from ill-formed combinations formed using the compose member function. This operation is intended to be inexpensive and all error checking deferred until use for some instantiation.</p>
   <p>-- <em>end note</em> ]</p>
   <h3 class="heading settled" data-level="4.5" id="attr1"><span class="secno">4.5. </span><span class="content">for_dynamic_instantiation Attribute</span><a class="self-link" href="#attr1"></a></h3>
   <p>The attribute-token for_dynamic_instantiation specifies that a function template is intended for use with the dynamic_function_template_instantiation operator. It shall appear at most once in each attribute list and no attribute-argument-clause shall be present. The attribute may be applied to the declarator-id in a function-template declaration.</p>
   <p>If a function-template declaration with the for_dynamic_instantiation has a function type that is dependent on any of its template parameters, the program is ill-formed. Function-template declarations with the for_dynamic_instantiation attribute shall be non-overloadable (12.2).</p>
   <p>[ <em>Note</em>:</p>
   <p>In the aforementioned implementation of this proposal, the attribute is named clang::for_dynamic_instantiation.</p>
   <p>-- <em>end note</em> ]</p>
   <p>First, we need some way to represent templates to enable runtime instantiation without referring to types using strings. We need, essentially, some runtime representation of a dependent template id, where the dependence can now be a runtime dependence.</p>
   <h2 class="heading settled" data-level="5" id="ex2"><span class="secno">5. </span><span class="content">Examples</span><a class="self-link" href="#ex2"></a></h2>
   <p>Thus, we can do the following:</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>I</c-><c- o>></c->
<c- b>void</c-> <c- n>foo</c-><c- p>(</c-><c- b>int</c-> <c- n>a</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, I = "</c-> <c- o>&lt;&lt;</c-> <c- n>I</c-> <c- o>&lt;&lt;</c-> <c- s>"</c-><c- se>\n</c-><c- s>"</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- p>...</c->

<c- k>template</c-> <c- o>&lt;</c-><c- b>int</c-> <c- n>J</c-><c- o>></c->
<c- k>struct</c-> <c- n>A</c-> <c- p>{</c-> <c- p>};</c->

<c- p>...</c->

<c- k>auto</c-> <c- n>A_tid</c-> <c- o>=</c-> <c- n>dynamic_template_argument</c-><c- o>&lt;</c-><c- n>A</c-><c- o>></c-><c- p>;</c->

<c- p>...</c->

<c- k>auto</c-> <c- n>A5</c-> <c- o>=</c-> <c- n>A_tid</c-><c- p>.</c-><c- n>compose</c-><c- p>(</c-><c- mi>5</c-><c- p>);</c->

<c- p>...</c->

<c- b>int</c-> <c- n>i</c-> <c- o>=</c-> <c- p>...,</c-> <c- n>j</c-> <c- o>=</c-> <c- p>...;</c->
<c- k>auto</c-> <c- n>foo_TI</c-> <c- o>=</c-> <c- n>dynamic_function_template_instantiation</c-><c- o>&lt;</c-><c- n>foo</c-><c- o>></c-><c- p>(</c-><c- n>A5</c-><c- p>,</c-> <c- n>i</c-><c- p>);</c->

<c- k>for</c-> <c- p>(</c-><c- k>auto</c-> <c- o>&amp;</c-><c- nl>W</c-> <c- p>:</c-> <c- n>foo_TI</c-><c- p>.</c-><c- n>warnings</c-><c- p>())</c-> <c- p>{</c->
  <c- n>std</c-><c- o>::</c-><c- n>cerr</c-> <c- o>&lt;&lt;</c-> <c- s>"warning: "</c-> <c- o>&lt;&lt;</c-> <c- n>W</c-><c- p>.</c-><c- n>message</c-><c- p>()</c-> <c- o>&lt;&lt;</c-> <c- s>" @ "</c-> <c- o>&lt;&lt;</c-> <c- o>&lt;&lt;</c-> <c- n>W</c-><c- p>.</c-><c- n>location</c-><c- p>().</c-><c- n>file_name</c-><c- p>()</c-> <c- o>&lt;&lt;</c-> <c- s>":"</c->
            <c- o>&lt;&lt;</c-> <c- n>W</c-><c- p>.</c-><c- n>location</c-><c- p>().</c-><c- n>line</c-><c- p>()</c-> <c- o>&lt;&lt;</c-> <c- s>":"</c-> <c- o>&lt;&lt;</c-> <c- n>W</c-><c- p>.</c-><c- n>location</c-><c- p>().</c-><c- n>column</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- k>if</c-> <c- p>(</c-><c- n>foo_TI</c-><c- p>)</c-> <c- p>{</c->
  <c- n>foo_TI</c-><c- p>(</c-><c- n>j</c-><c- p>);</c->
<c- p>}</c-> <c- k>else</c-> <c- p>{</c->
  <c- n>std</c-><c- o>::</c-><c- n>cerr</c-> <c- o>&lt;&lt;</c-> <c- s>"compilation failed!</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->

  <c- k>for</c-> <c- p>(</c-><c- k>auto</c-> <c- o>&amp;</c-><c- nl>W</c-> <c- p>:</c-> <c- n>foo_TI</c-><c- p>.</c-><c- n>errors</c-><c- p>())</c-> <c- p>{</c->
    <c- n>std</c-><c- o>::</c-><c- n>cerr</c-> <c- o>&lt;&lt;</c-> <c- s>"error: "</c-> <c- o>&lt;&lt;</c-> <c- n>W</c-><c- p>.</c-><c- n>message</c-><c- p>()</c-> <c- o>&lt;&lt;</c-> <c- s>" @ "</c-> <c- o>&lt;&lt;</c-> <c- n>W</c-><c- p>.</c-><c- n>location</c-><c- p>().</c-><c- n>file_name</c-><c- p>()</c-> <c- o>&lt;&lt;</c-> <c- s>":"</c->
              <c- o>&lt;&lt;</c-> <c- n>W</c-><c- p>.</c-><c- n>location</c-><c- p>().</c-><c- n>line</c-><c- p>()</c-> <c- o>&lt;&lt;</c-> <c- s>":"</c-> <c- o>&lt;&lt;</c-> <c- n>W</c-><c- p>.</c-><c- n>location</c-><c- p>().</c-><c- n>column</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- 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 templates used by the proposed operators, 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 class="note" role="note"><span>Note:</span> This section uses the interface from a previous revision of the paper...</p>
   <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>
  <h2 class="no-num no-ref heading settled" id="issues-index"><span class="content">Issues Index</span><a class="self-link" href="#issues-index"></a></h2>
  <div style="counter-reset:issue">
   <div class="issue"> How should we indicate when we know that the feature won’t be available (feature macro, constexpr function, both, something else)?<a href="#issue-70d64c7a"> ↵ </a></div>
   <div class="issue"> Can the syntax be extended in some way to relax the restriction on overloaded function templates? Maybe allowing an optional parenthesized type list after the id-expression?<a href="#issue-ad88896e"> ↵ </a></div>
   <div class="issue"> What should we say about the statefulness of the instantiation process? For example, does the result of friend injection persist across different evaluations of the operator?<a href="#issue-581b5564"> ↵ </a></div>
   <div class="issue"> How might we provide additional information to the implementation to direct the compilation (e.g., compiler-optimization flags or some equivalent)?<a href="#issue-e4ea07b5"> ↵ </a></div>
   <div class="issue"> How can we provide the ability to save/restore the compilation state of particular instantiations (e.g., into / out of a stream)?<a href="#issue-413c1947"> ↵ </a></div>
   <div class="issue"> Should we make the result types of the operators named types provided by the header file? This may be necessary, at least in some cases, to be useful on interfaces.<a href="#issue-80d0562f"> ↵ </a></div>
   <div class="issue"> Should dynamic_template_argument and typeid be unified in some way?<a href="#issue-1ddf0852"> ↵ </a></div>
  </div>