mirror of
https://github.com/bendtherules/ask262.git
synced 2026-08-18 21:31:46 +00:00
544 lines
96 KiB
HTML
544 lines
96 KiB
HTML
<!DOCTYPE html><html lang="en-GB-oxendict"><head><meta name="viewport" content="width=device-width, initial-scale=1"><meta charset="utf-8"><meta property="og:image" content="https://tc39.es/ecmarkup/ecma-logo.png"><meta property="og:title" content="ECMAScript® 2026 Language Specification"><meta property="og:description" content="Introduction
|
|
This Ecma Standard defines the ECMAScript 2026 Language. It is the seventeenth edition of the ECMAScript Language Specification. ECMAScript is based on several originating technologies, the most well-known being JavaScript (Netscape) and JScript (Microsoft). The language was invent">
|
|
<link rel="icon" href="../img/favicon.ico">
|
|
<link rel="stylesheet" href="../assets/css/ecmarkup.css"><link rel="stylesheet" href="../assets/css/print.css" media="print">
|
|
|
|
<title>ECMAScript® 2026 Language Specification</title><script src="../assets/js/multipage.js?cache=Wu2V1pj2" defer=""></script><script src="../assets/js/ecmarkup.js?cache=BPFBckdu" defer=""></script><link rel="canonical" href="../#sec-memory-model"></head>
|
|
<body><div id="spec-container"><emu-clause id="sec-memory-model">
|
|
<h1><span class="secnum">29</span> Memory Model</h1>
|
|
<p>The memory consistency model, or <dfn tabindex="-1">memory model</dfn>, specifies the possible orderings of <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16906"><a href="memory-model.html#sec-memory-model-fundamentals">Shared Data Block events</a></emu-xref>, arising via accessing <emu-xref href="#typedarray" id="_ref_16907"><a href="ordinary-and-exotic-objects-behaviours.html#typedarray">TypedArray</a></emu-xref> instances backed by a SharedArrayBuffer and via methods on the Atomics object. When the program has no data races (defined below), the ordering of events appears as sequentially consistent, i.e., as an interleaving of actions from each <emu-xref href="#agent" id="_ref_16908"><a href="executable-code-and-execution-contexts.html#agent">agent</a></emu-xref>. When the program has data races, shared memory operations may appear sequentially inconsistent. For example, programs may exhibit causality-violating behaviour and other astonishments. These astonishments arise from compiler transforms and the design of CPUs (e.g., out-of-order execution and speculation). The memory model defines both the precise conditions under which a program exhibits sequentially consistent behaviour as well as the possible values read from data races. To wit, there is no undefined behaviour.</p>
|
|
<p>The memory model is defined as relational constraints on <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16909"><a href="memory-model.html#sec-memory-model-fundamentals">Memory events</a></emu-xref> introduced by <emu-xref href="#sec-algorithm-conventions-abstract-operations" id="_ref_16910"><a href="notational-conventions.html#sec-algorithm-conventions-abstract-operations">abstract operations</a></emu-xref> on SharedArrayBuffer or by methods on the Atomics object during an evaluation.</p>
|
|
<emu-note><span class="note">Note</span><div class="note-contents">
|
|
<p>This section provides an axiomatic model on <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16911"><a href="memory-model.html#sec-memory-model-fundamentals">Memory events</a></emu-xref> introduced by the <emu-xref href="#sec-algorithm-conventions-abstract-operations" id="_ref_16912"><a href="notational-conventions.html#sec-algorithm-conventions-abstract-operations">abstract operations</a></emu-xref> on SharedArrayBuffers. It bears stressing that the model is not expressible algorithmically, unlike the rest of this specification. The nondeterministic introduction of events by <emu-xref href="#sec-algorithm-conventions-abstract-operations" id="_ref_16913"><a href="notational-conventions.html#sec-algorithm-conventions-abstract-operations">abstract operations</a></emu-xref> is the interface between the operational semantics of ECMAScript evaluation and the axiomatic semantics of the memory model. The semantics of these events is defined by considering graphs of all events in an evaluation. These are neither Static Semantics nor Runtime Semantics. There is no demonstrated algorithmic implementation, but instead a set of constraints that determine if a particular event graph is allowed or disallowed.</p>
|
|
</div></emu-note>
|
|
|
|
<emu-clause id="sec-memory-model-fundamentals">
|
|
<h1><span class="secnum">29.1</span> Memory Model Fundamentals</h1>
|
|
<p>Shared memory accesses (reads and writes) are divided into two groups, atomic accesses and data accesses, defined below. Atomic accesses are sequentially consistent, i.e., there is a strict total ordering of events agreed upon by all <emu-xref href="#agent" id="_ref_16914"><a href="executable-code-and-execution-contexts.html#agent">agents</a></emu-xref> in an <emu-xref href="#sec-agent-clusters" id="_ref_16915"><a href="executable-code-and-execution-contexts.html#sec-agent-clusters">agent cluster</a></emu-xref>. Non-atomic accesses do not have a strict total ordering agreed upon by all <emu-xref href="#agent" id="_ref_16916"><a href="executable-code-and-execution-contexts.html#agent">agents</a></emu-xref>, i.e., unordered.</p>
|
|
<emu-note><span class="note">Note 1</span><div class="note-contents">
|
|
<p>No orderings weaker than sequentially consistent and stronger than unordered, such as release-acquire, are supported.</p>
|
|
</div></emu-note>
|
|
<p>A <dfn variants="Shared Data Block events" tabindex="-1">Shared Data Block event</dfn> is either a <dfn tabindex="-1">ReadSharedMemory</dfn>, <dfn tabindex="-1">WriteSharedMemory</dfn>, or <dfn tabindex="-1">ReadModifyWriteSharedMemory</dfn> <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16917"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">Record</a></emu-xref>. A <dfn variants="read events" tabindex="-1">read event</dfn> is either a ReadSharedMemory or a ReadModifyWriteSharedMemory. A <dfn variants="write events" tabindex="-1">write event</dfn> is either a WriteSharedMemory or a ReadModifyWriteSharedMemory.</p>
|
|
|
|
<emu-table id="table-readsharedmemory-fields" caption="ReadSharedMemory Event Fields"><figure><figcaption>Table 91: <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16918"><a href="memory-model.html#sec-memory-model-fundamentals">ReadSharedMemory</a></emu-xref> Event Fields</figcaption>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Field Name</th>
|
|
<th>Value</th>
|
|
<th>Meaning</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody><tr>
|
|
<td><var class="field">[[Order]]</var></td>
|
|
<td><emu-const>seq-cst</emu-const> or <emu-const>unordered</emu-const></td>
|
|
<td>The weakest ordering guaranteed by the <emu-xref href="#sec-memory-model" id="_ref_16919"><a href="memory-model.html#sec-memory-model">memory model</a></emu-xref> for the event.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[NoTear]]</var></td>
|
|
<td>a Boolean</td>
|
|
<td>Whether this event is allowed to read from multiple <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16920"><a href="memory-model.html#sec-memory-model-fundamentals">write events</a></emu-xref> with equal <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16921"><a href="memory-model.html#sec-memory-model-fundamentals">memory range</a></emu-xref> as this event.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[Block]]</var></td>
|
|
<td>a <emu-xref href="#sec-data-blocks" id="_ref_16922"><a href="ecmascript-data-types-and-values.html#sec-data-blocks">Shared Data Block</a></emu-xref></td>
|
|
<td>The block the event operates on.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[ByteIndex]]</var></td>
|
|
<td>a non-negative <emu-xref href="#integer" id="_ref_16923"><a href="notational-conventions.html#integer">integer</a></emu-xref></td>
|
|
<td>The byte address of the read in <var class="field">[[Block]]</var>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[ElementSize]]</var></td>
|
|
<td>a non-negative <emu-xref href="#integer" id="_ref_16924"><a href="notational-conventions.html#integer">integer</a></emu-xref></td>
|
|
<td>The size of the read.</td>
|
|
</tr>
|
|
</tbody></table>
|
|
</figure></emu-table>
|
|
|
|
<emu-table id="table-writesharedmemory-fields" caption="WriteSharedMemory Event Fields"><figure><figcaption>Table 92: <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16925"><a href="memory-model.html#sec-memory-model-fundamentals">WriteSharedMemory</a></emu-xref> Event Fields</figcaption>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Field Name</th>
|
|
<th>Value</th>
|
|
<th>Meaning</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody><tr>
|
|
<td><var class="field">[[Order]]</var></td>
|
|
<td><emu-const>seq-cst</emu-const>, <emu-const>unordered</emu-const>, or <emu-const>init</emu-const></td>
|
|
<td>The weakest ordering guaranteed by the <emu-xref href="#sec-memory-model" id="_ref_16926"><a href="memory-model.html#sec-memory-model">memory model</a></emu-xref> for the event.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[NoTear]]</var></td>
|
|
<td>a Boolean</td>
|
|
<td>Whether this event is allowed to be read from multiple <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16927"><a href="memory-model.html#sec-memory-model-fundamentals">read events</a></emu-xref> with equal <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16928"><a href="memory-model.html#sec-memory-model-fundamentals">memory range</a></emu-xref> as this event.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[Block]]</var></td>
|
|
<td>a <emu-xref href="#sec-data-blocks" id="_ref_16929"><a href="ecmascript-data-types-and-values.html#sec-data-blocks">Shared Data Block</a></emu-xref></td>
|
|
<td>The block the event operates on.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[ByteIndex]]</var></td>
|
|
<td>a non-negative <emu-xref href="#integer" id="_ref_16930"><a href="notational-conventions.html#integer">integer</a></emu-xref></td>
|
|
<td>The byte address of the write in <var class="field">[[Block]]</var>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[ElementSize]]</var></td>
|
|
<td>a non-negative <emu-xref href="#integer" id="_ref_16931"><a href="notational-conventions.html#integer">integer</a></emu-xref></td>
|
|
<td>The size of the write.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[Payload]]</var></td>
|
|
<td>a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16932"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of <emu-xref href="#sec-data-blocks" id="_ref_16933"><a href="ecmascript-data-types-and-values.html#sec-data-blocks">byte values</a></emu-xref></td>
|
|
<td>The <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16934"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of <emu-xref href="#sec-data-blocks" id="_ref_16935"><a href="ecmascript-data-types-and-values.html#sec-data-blocks">byte values</a></emu-xref> to be read by other events.</td>
|
|
</tr>
|
|
</tbody></table>
|
|
</figure></emu-table>
|
|
|
|
<emu-table id="table-rmwsharedmemory-fields" caption="ReadModifyWriteSharedMemory Event Fields"><figure><figcaption>Table 93: <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16936"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> Event Fields</figcaption>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Field Name</th>
|
|
<th>Value</th>
|
|
<th>Meaning</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody><tr>
|
|
<td><var class="field">[[Order]]</var></td>
|
|
<td><emu-const>seq-cst</emu-const></td>
|
|
<td>Read-modify-<emu-xref href="#sec-memory-model-fundamentals" id="_ref_16937"><a href="memory-model.html#sec-memory-model-fundamentals">write events</a></emu-xref> are always sequentially consistent.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[NoTear]]</var></td>
|
|
<td><emu-val>true</emu-val></td>
|
|
<td>Read-modify-<emu-xref href="#sec-memory-model-fundamentals" id="_ref_16938"><a href="memory-model.html#sec-memory-model-fundamentals">write events</a></emu-xref> cannot tear.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[Block]]</var></td>
|
|
<td>a <emu-xref href="#sec-data-blocks" id="_ref_16939"><a href="ecmascript-data-types-and-values.html#sec-data-blocks">Shared Data Block</a></emu-xref></td>
|
|
<td>The block the event operates on.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[ByteIndex]]</var></td>
|
|
<td>a non-negative <emu-xref href="#integer" id="_ref_16940"><a href="notational-conventions.html#integer">integer</a></emu-xref></td>
|
|
<td>The byte address of the read-modify-write in <var class="field">[[Block]]</var>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[ElementSize]]</var></td>
|
|
<td>a non-negative <emu-xref href="#integer" id="_ref_16941"><a href="notational-conventions.html#integer">integer</a></emu-xref></td>
|
|
<td>The size of the read-modify-write.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[Payload]]</var></td>
|
|
<td>a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16942"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of <emu-xref href="#sec-data-blocks" id="_ref_16943"><a href="ecmascript-data-types-and-values.html#sec-data-blocks">byte values</a></emu-xref></td>
|
|
<td>The <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16944"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of <emu-xref href="#sec-data-blocks" id="_ref_16945"><a href="ecmascript-data-types-and-values.html#sec-data-blocks">byte values</a></emu-xref> to be passed to <var class="field">[[ModifyOp]]</var>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[ModifyOp]]</var></td>
|
|
<td>a <emu-xref href="#sec-arraybuffer-notation" id="_ref_16946"><a href="structured-data.html#sec-arraybuffer-notation">read-modify-write modification function</a></emu-xref></td>
|
|
<td>An abstract closure that returns a modified <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16947"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of <emu-xref href="#sec-data-blocks" id="_ref_16948"><a href="ecmascript-data-types-and-values.html#sec-data-blocks">byte values</a></emu-xref> from a read <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16949"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of <emu-xref href="#sec-data-blocks" id="_ref_16950"><a href="ecmascript-data-types-and-values.html#sec-data-blocks">byte values</a></emu-xref> and <var class="field">[[Payload]]</var>.</td>
|
|
</tr>
|
|
</tbody></table>
|
|
</figure></emu-table>
|
|
|
|
<p>Shared Data Block events are introduced to <emu-xref href="#sec-candidate-executions" id="_ref_16951"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <emu-xref href="#sec-agent-event-records" id="_ref_16952"><a href="memory-model.html#sec-agent-event-records">Agent Events Records</a></emu-xref> by <emu-xref href="#sec-algorithm-conventions-abstract-operations" id="_ref_16953"><a href="notational-conventions.html#sec-algorithm-conventions-abstract-operations">abstract operations</a></emu-xref> or by methods on the Atomics object. Some operations also introduce <dfn variants="Synchronize,Synchronize event" tabindex="-1">Synchronize events</dfn>, which have no fields and exist purely to directly constrain the permitted orderings of other events. And finally, there are <emu-xref href="#host" id="_ref_16954"><a href="overview.html#host">host</a></emu-xref>-specific events. A <dfn variants="Memory events" tabindex="-1">Memory event</dfn> is either a Shared Data Block event, Synchronize event, or such a <emu-xref href="#host" id="_ref_16955"><a href="overview.html#host">host</a></emu-xref>-specific event.</p>
|
|
<p>Let the <dfn variants="memory ranges" tabindex="-1">memory range</dfn> of a Shared Data Block event <var>e</var> be the Set of all <emu-xref href="#integer" id="_ref_16956"><a href="notational-conventions.html#integer">integers</a></emu-xref> in the <emu-xref href="#interval" id="_ref_16957"><a href="notational-conventions.html#interval">interval</a></emu-xref> from <var>e</var>.<var class="field">[[ByteIndex]]</var> (inclusive) to <var>e</var>.<var class="field">[[ByteIndex]]</var> + <var>e</var>.<var class="field">[[ElementSize]]</var> (exclusive). Two events' memory ranges are equal when the events have the same <var class="field">[[Block]]</var>, <var class="field">[[ByteIndex]]</var>, and <var class="field">[[ElementSize]]</var>. Two events' memory ranges are overlapping when the events have the same <var class="field">[[Block]]</var>, the ranges are not equal, and their intersection is non-empty. Two events' memory ranges are disjoint when the events do not have the same <var class="field">[[Block]]</var> or their ranges are neither equal nor overlapping.</p>
|
|
<emu-note><span class="note">Note 2</span><div class="note-contents">
|
|
<p>Examples of <emu-xref href="#host" id="_ref_16958"><a href="overview.html#host">host</a></emu-xref>-specific synchronizing events that should be accounted for are: sending a SharedArrayBuffer from one <emu-xref href="#agent" id="_ref_16959"><a href="executable-code-and-execution-contexts.html#agent">agent</a></emu-xref> to another (e.g., by <code>postMessage</code> in a browser), starting and stopping <emu-xref href="#agent" id="_ref_16960"><a href="executable-code-and-execution-contexts.html#agent">agents</a></emu-xref>, and communicating within the <emu-xref href="#sec-agent-clusters" id="_ref_16961"><a href="executable-code-and-execution-contexts.html#sec-agent-clusters">agent cluster</a></emu-xref> via channels other than shared memory. For a particular execution <var>execution</var>, those events are provided by the <emu-xref href="#host" id="_ref_16962"><a href="overview.html#host">host</a></emu-xref> via the <emu-xref href="#sec-host-synchronizes-with" id="_ref_16963"><a href="memory-model.html#sec-host-synchronizes-with">host-synchronizes-with</a></emu-xref> <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_16964"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">strict partial order</a></emu-xref>. Additionally, <emu-xref href="#host" id="_ref_16965"><a href="overview.html#host">hosts</a></emu-xref> can add <emu-xref href="#host" id="_ref_16966"><a href="overview.html#host">host</a></emu-xref>-specific synchronizing events to <var>execution</var>.<var class="field">[[EventList]]</var> so as to participate in the <emu-xref href="#sec-agent-order" id="_ref_16967"><a href="memory-model.html#sec-agent-order">is-agent-order-before</a></emu-xref> <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_16968"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">Relation</a></emu-xref>.</p>
|
|
</div></emu-note>
|
|
<p>Events are ordered within <emu-xref href="#sec-candidate-executions" id="_ref_16969"><a href="memory-model.html#sec-candidate-executions">candidate executions</a></emu-xref> by the relations defined below.</p>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-agent-event-records">
|
|
<h1><span class="secnum">29.2</span> Agent Events Records</h1>
|
|
<p>An <dfn variants="Agent Events Records" tabindex="-1">Agent Events Record</dfn> is a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16970"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">Record</a></emu-xref> with the following fields.</p>
|
|
<emu-table id="table-agent-events-records" caption="Agent Events Record Fields"><figure><figcaption>Table 94: <emu-xref href="#sec-agent-event-records" id="_ref_16971"><a href="memory-model.html#sec-agent-event-records">Agent Events Record</a></emu-xref> Fields</figcaption>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Field Name</th>
|
|
<th>Value</th>
|
|
<th>Meaning</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody><tr>
|
|
<td><var class="field">[[AgentSignifier]]</var></td>
|
|
<td>an <emu-xref href="#sec-agents" id="_ref_16972"><a href="executable-code-and-execution-contexts.html#sec-agents">agent signifier</a></emu-xref></td>
|
|
<td>The <emu-xref href="#agent" id="_ref_16973"><a href="executable-code-and-execution-contexts.html#agent">agent</a></emu-xref> whose evaluation resulted in this ordering.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[EventList]]</var></td>
|
|
<td>a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16974"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16975"><a href="memory-model.html#sec-memory-model-fundamentals">Memory events</a></emu-xref></td>
|
|
<td>Events are appended to the list during evaluation.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[AgentSynchronizesWith]]</var></td>
|
|
<td>a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16976"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of pairs of <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16977"><a href="memory-model.html#sec-memory-model-fundamentals">Synchronize events</a></emu-xref></td>
|
|
<td><emu-xref href="#sec-memory-model-fundamentals" id="_ref_16978"><a href="memory-model.html#sec-memory-model-fundamentals">Synchronize</a></emu-xref> relationships introduced by the operational semantics.</td>
|
|
</tr>
|
|
</tbody></table>
|
|
</figure></emu-table>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-chosen-value-records">
|
|
<h1><span class="secnum">29.3</span> Chosen Value Records</h1>
|
|
<p>A <dfn variants="Chosen Value Records" tabindex="-1">Chosen Value Record</dfn> is a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16979"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">Record</a></emu-xref> with the following fields.</p>
|
|
<emu-table id="table-chosen-value-records" caption="Chosen Value Record Fields"><figure><figcaption>Table 95: <emu-xref href="#sec-chosen-value-records" id="_ref_16980"><a href="memory-model.html#sec-chosen-value-records">Chosen Value Record</a></emu-xref> Fields</figcaption>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Field Name</th>
|
|
<th>Value</th>
|
|
<th>Meaning</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody><tr>
|
|
<td><var class="field">[[Event]]</var></td>
|
|
<td>a <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16981"><a href="memory-model.html#sec-memory-model-fundamentals">Shared Data Block event</a></emu-xref></td>
|
|
<td>The <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16982"><a href="memory-model.html#sec-memory-model-fundamentals">ReadSharedMemory</a></emu-xref> or <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16983"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> event that was introduced for this chosen value.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[ChosenValue]]</var></td>
|
|
<td>a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16984"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of <emu-xref href="#sec-data-blocks" id="_ref_16985"><a href="ecmascript-data-types-and-values.html#sec-data-blocks">byte values</a></emu-xref></td>
|
|
<td>The bytes that were nondeterministically chosen during evaluation.</td>
|
|
</tr>
|
|
</tbody></table>
|
|
</figure></emu-table>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-candidate-executions">
|
|
<h1><span class="secnum">29.4</span> Candidate Executions</h1>
|
|
<p>A <dfn variants="candidate executions" tabindex="-1">candidate execution</dfn> of the evaluation of an <emu-xref href="#sec-agent-clusters" id="_ref_16986"><a href="executable-code-and-execution-contexts.html#sec-agent-clusters">agent cluster</a></emu-xref> is a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16987"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">Record</a></emu-xref> with the following fields.</p>
|
|
<emu-table id="table-candidate-execution-records" caption="Candidate Execution Record Fields"><figure><figcaption>Table 96: Candidate Execution <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16988"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">Record</a></emu-xref> Fields</figcaption>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Field Name</th>
|
|
<th>Value</th>
|
|
<th>Meaning</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody><tr>
|
|
<td><var class="field">[[EventsRecords]]</var></td>
|
|
<td>a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16989"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of <emu-xref href="#sec-agent-event-records" id="_ref_16990"><a href="memory-model.html#sec-agent-event-records">Agent Events Records</a></emu-xref></td>
|
|
<td>Maps an <emu-xref href="#agent" id="_ref_16991"><a href="executable-code-and-execution-contexts.html#agent">agent</a></emu-xref> to <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16992"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">Lists</a></emu-xref> of <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16993"><a href="memory-model.html#sec-memory-model-fundamentals">Memory events</a></emu-xref> appended during the evaluation.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><var class="field">[[ChosenValues]]</var></td>
|
|
<td>a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16994"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of <emu-xref href="#sec-chosen-value-records" id="_ref_16995"><a href="memory-model.html#sec-chosen-value-records">Chosen Value Records</a></emu-xref></td>
|
|
<td>Maps <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16996"><a href="memory-model.html#sec-memory-model-fundamentals">ReadSharedMemory</a></emu-xref> or <emu-xref href="#sec-memory-model-fundamentals" id="_ref_16997"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> events to the <emu-xref href="#sec-list-and-record-specification-type" id="_ref_16998"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of <emu-xref href="#sec-data-blocks" id="_ref_16999"><a href="ecmascript-data-types-and-values.html#sec-data-blocks">byte values</a></emu-xref> chosen during the evaluation.</td>
|
|
</tr>
|
|
</tbody></table>
|
|
</figure></emu-table>
|
|
|
|
<p>An <dfn variants="empty candidate executions" tabindex="-1">empty candidate execution</dfn> is a candidate execution <emu-xref href="#sec-list-and-record-specification-type" id="_ref_17000"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">Record</a></emu-xref> whose fields are empty <emu-xref href="#sec-list-and-record-specification-type" id="_ref_17001"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">Lists</a></emu-xref>.</p>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-abstract-operations-for-the-memory-model" oldids="sec-synchronizeeventset"><span id="sec-synchronizeeventset"></span>
|
|
<h1><span class="secnum">29.5</span> Abstract Operations for the Memory Model</h1>
|
|
|
|
<emu-clause id="sec-event-set" type="abstract operation" aoid="EventSet">
|
|
<h1><span class="secnum">29.5.1</span> EventSet ( <var>execution</var> )</h1>
|
|
<p>The abstract operation EventSet takes argument <var>execution</var> (a <emu-xref href="#sec-candidate-executions" id="_ref_17002"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref>) and returns a Set of <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17003"><a href="memory-model.html#sec-memory-model-fundamentals">Memory events</a></emu-xref>. It performs the following steps when called:</p>
|
|
<emu-alg><ol><li>Let <var>events</var> be an empty Set.</li><li>For each <emu-xref href="#sec-agent-event-records" id="_ref_17004"><a href="memory-model.html#sec-agent-event-records">Agent Events Record</a></emu-xref> <var>aer</var> of <var>execution</var>.<var class="field">[[EventsRecords]]</var>, do<ol><li>For each <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17005"><a href="memory-model.html#sec-memory-model-fundamentals">Memory event</a></emu-xref> <var>E</var> of <var>aer</var>.<var class="field">[[EventList]]</var>, do<ol><li>Add <var>E</var> to <var>events</var>.</li></ol></li></ol></li><li>Return <var>events</var>.</li></ol></emu-alg>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-sharedatablockeventset" type="abstract operation" aoid="SharedDataBlockEventSet">
|
|
<h1><span class="secnum">29.5.2</span> SharedDataBlockEventSet ( <var>execution</var> )</h1>
|
|
<p>The abstract operation SharedDataBlockEventSet takes argument <var>execution</var> (a <emu-xref href="#sec-candidate-executions" id="_ref_17006"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref>) and returns a Set of <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17007"><a href="memory-model.html#sec-memory-model-fundamentals">Shared Data Block events</a></emu-xref>. It performs the following steps when called:</p>
|
|
<emu-alg><ol><li>Let <var>events</var> be an empty Set.</li><li>For each <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17008"><a href="memory-model.html#sec-memory-model-fundamentals">Memory event</a></emu-xref> <var>E</var> of <emu-xref aoid="EventSet" id="_ref_17009"><a href="memory-model.html#sec-event-set">EventSet</a></emu-xref>(<var>execution</var>), do<ol><li>If <var>E</var> is a <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17010"><a href="memory-model.html#sec-memory-model-fundamentals">Shared Data Block event</a></emu-xref>, add <var>E</var> to <var>events</var>.</li></ol></li><li>Return <var>events</var>.</li></ol></emu-alg>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-hosteventset" type="abstract operation" aoid="HostEventSet">
|
|
<h1><span class="secnum">29.5.3</span> HostEventSet ( <var>execution</var> )</h1>
|
|
<p>The abstract operation HostEventSet takes argument <var>execution</var> (a <emu-xref href="#sec-candidate-executions" id="_ref_17011"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref>) and returns a Set of <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17012"><a href="memory-model.html#sec-memory-model-fundamentals">Memory events</a></emu-xref>. It performs the following steps when called:</p>
|
|
<emu-alg><ol><li>Return a new Set containing all elements of <emu-xref aoid="EventSet" id="_ref_17013"><a href="memory-model.html#sec-event-set">EventSet</a></emu-xref>(<var>execution</var>) that are not in <emu-xref aoid="SharedDataBlockEventSet" id="_ref_17014"><a href="memory-model.html#sec-sharedatablockeventset">SharedDataBlockEventSet</a></emu-xref>(<var>execution</var>).</li></ol></emu-alg>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-composewriteeventbytes" type="abstract operation" aoid="ComposeWriteEventBytes">
|
|
<h1><span class="secnum">29.5.4</span> ComposeWriteEventBytes ( <var>execution</var>, <var>byteIndex</var>, <var>Ws</var> )</h1>
|
|
<p>The abstract operation ComposeWriteEventBytes takes arguments <var>execution</var> (a <emu-xref href="#sec-candidate-executions" id="_ref_17015"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref>), <var>byteIndex</var> (a non-negative <emu-xref href="#integer" id="_ref_17016"><a href="notational-conventions.html#integer">integer</a></emu-xref>), and <var>Ws</var> (a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_17017"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of either <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17018"><a href="memory-model.html#sec-memory-model-fundamentals">WriteSharedMemory</a></emu-xref> or <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17019"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> events) and returns a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_17020"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of <emu-xref href="#sec-data-blocks" id="_ref_17021"><a href="ecmascript-data-types-and-values.html#sec-data-blocks">byte values</a></emu-xref>. It performs the following steps when called:</p>
|
|
<emu-alg><ol><li>Let <var>byteLocation</var> be <var>byteIndex</var>.</li><li>Let <var>bytesRead</var> be a new empty <emu-xref href="#sec-list-and-record-specification-type" id="_ref_17022"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref>.</li><li>For each element <var>W</var> of <var>Ws</var>, do<ol><li><emu-xref href="#assert" id="_ref_17023"><a href="notational-conventions.html#assert">Assert</a></emu-xref>: <var>W</var> has <var>byteLocation</var> in its <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17024"><a href="memory-model.html#sec-memory-model-fundamentals">memory range</a></emu-xref>.</li><li>Let <var>payloadIndex</var> be <var>byteLocation</var> - <var>W</var>.<var class="field">[[ByteIndex]]</var>.</li><li>If <var>W</var> is a <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17025"><a href="memory-model.html#sec-memory-model-fundamentals">WriteSharedMemory</a></emu-xref> event, then<ol><li>Let <var>byte</var> be <var>W</var>.<var class="field">[[Payload]]</var>[<var>payloadIndex</var>].</li></ol></li><li>Else,<ol><li><emu-xref href="#assert" id="_ref_17026"><a href="notational-conventions.html#assert">Assert</a></emu-xref>: <var>W</var> is a <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17027"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> event.</li><li>Let <var>bytes</var> be <emu-xref aoid="ValueOfReadEvent" id="_ref_17028"><a href="memory-model.html#sec-valueofreadevent">ValueOfReadEvent</a></emu-xref>(<var>execution</var>, <var>W</var>).</li><li>Let <var>bytesModified</var> be <var>W</var>.<var class="field">[[ModifyOp]]</var>(<var>bytes</var>, <var>W</var>.<var class="field">[[Payload]]</var>).</li><li>Let <var>byte</var> be <var>bytesModified</var>[<var>payloadIndex</var>].</li></ol></li><li>Append <var>byte</var> to <var>bytesRead</var>.</li><li>Set <var>byteLocation</var> to <var>byteLocation</var> + 1.</li></ol></li><li>Return <var>bytesRead</var>.</li></ol></emu-alg>
|
|
<emu-note><span class="note">Note 1</span><div class="note-contents">
|
|
<p>The read-modify-write modification <var class="field">[[ModifyOp]]</var> is given by the function properties on the Atomics object that introduce <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17029"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> events.</p>
|
|
</div></emu-note>
|
|
<emu-note><span class="note">Note 2</span><div class="note-contents">
|
|
<p>This abstract operation composes a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_17030"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17031"><a href="memory-model.html#sec-memory-model-fundamentals">write events</a></emu-xref> into a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_17032"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of <emu-xref href="#sec-data-blocks" id="_ref_17033"><a href="ecmascript-data-types-and-values.html#sec-data-blocks">byte values</a></emu-xref>. It is used in the event semantics of <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17034"><a href="memory-model.html#sec-memory-model-fundamentals">ReadSharedMemory</a></emu-xref> and <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17035"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> events.</p>
|
|
</div></emu-note>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-valueofreadevent" type="abstract operation" aoid="ValueOfReadEvent">
|
|
<h1><span class="secnum">29.5.5</span> ValueOfReadEvent ( <var>execution</var>, <var>R</var> )</h1>
|
|
<p>The abstract operation ValueOfReadEvent takes arguments <var>execution</var> (a <emu-xref href="#sec-candidate-executions" id="_ref_17036"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref>) and <var>R</var> (a <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17037"><a href="memory-model.html#sec-memory-model-fundamentals">ReadSharedMemory</a></emu-xref> or <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17038"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> event) and returns a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_17039"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of <emu-xref href="#sec-data-blocks" id="_ref_17040"><a href="ecmascript-data-types-and-values.html#sec-data-blocks">byte values</a></emu-xref>. It performs the following steps when called:</p>
|
|
<emu-alg><ol><li>Let <var>Ws</var> be <emu-xref aoid="reads-bytes-from" id="_ref_17041"><a href="memory-model.html#sec-reads-bytes-from">reads-bytes-from</a></emu-xref>(<var>R</var>) in <var>execution</var>.</li><li><emu-xref href="#assert" id="_ref_17042"><a href="notational-conventions.html#assert">Assert</a></emu-xref>: <var>Ws</var> is a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_17043"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17044"><a href="memory-model.html#sec-memory-model-fundamentals">WriteSharedMemory</a></emu-xref> or <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17045"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> events with length equal to <var>R</var>.<var class="field">[[ElementSize]]</var>.</li><li>Return <emu-xref aoid="ComposeWriteEventBytes" id="_ref_17046"><a href="memory-model.html#sec-composewriteeventbytes">ComposeWriteEventBytes</a></emu-xref>(<var>execution</var>, <var>R</var>.<var class="field">[[ByteIndex]]</var>, <var>Ws</var>).</li></ol></emu-alg>
|
|
</emu-clause>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-relations-of-candidate-executions">
|
|
<h1><span class="secnum">29.6</span> Relations of Candidate Executions</h1>
|
|
|
|
<p>The following relations and mathematical functions are parameterized over a particular <emu-xref href="#sec-candidate-executions" id="_ref_17047"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> and order its <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17048"><a href="memory-model.html#sec-memory-model-fundamentals">Memory events</a></emu-xref>.</p>
|
|
|
|
<emu-clause id="sec-agent-order">
|
|
<h1><span class="secnum">29.6.1</span> is-agent-order-before</h1>
|
|
<p>For a <emu-xref href="#sec-candidate-executions" id="_ref_17049"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <var>execution</var>, its <dfn tabindex="-1">is-agent-order-before</dfn> <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17050"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">Relation</a></emu-xref> is the <emu-xref href="#least-relation" id="_ref_17051"><a href="ecmascript-data-types-and-values.html#least-relation">least Relation</a></emu-xref> on <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17052"><a href="memory-model.html#sec-memory-model-fundamentals">Memory events</a></emu-xref> that satisfies the following.</p>
|
|
<ul>
|
|
<li>For events <var>E</var> and <var>D</var>, <var>E</var> is-agent-order-before <var>D</var> in <var>execution</var> if there is some <emu-xref href="#sec-agent-event-records" id="_ref_17053"><a href="memory-model.html#sec-agent-event-records">Agent Events Record</a></emu-xref> <var>aer</var> in <var>execution</var>.<var class="field">[[EventsRecords]]</var> such that <var>aer</var>.<var class="field">[[EventList]]</var> contains both <var>E</var> and <var>D</var> and <var>E</var> is before <var>D</var> in <emu-xref href="#sec-list-and-record-specification-type" id="_ref_17054"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> order of <var>aer</var>.<var class="field">[[EventList]]</var>.</li>
|
|
</ul>
|
|
|
|
<emu-note><span class="note">Note</span><div class="note-contents">
|
|
<p>Each <emu-xref href="#agent" id="_ref_17055"><a href="executable-code-and-execution-contexts.html#agent">agent</a></emu-xref> introduces events in a per-<emu-xref href="#agent" id="_ref_17056"><a href="executable-code-and-execution-contexts.html#agent">agent</a></emu-xref> <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17057"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">strict total order</a></emu-xref> during the evaluation. This is the union of those <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17058"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">strict total orders</a></emu-xref>.</p>
|
|
</div></emu-note>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-reads-bytes-from" aoid="reads-bytes-from">
|
|
<h1><span class="secnum">29.6.2</span> reads-bytes-from</h1>
|
|
<p>For a <emu-xref href="#sec-candidate-executions" id="_ref_17059"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <var>execution</var>, its <em>reads-bytes-from</em> function is a mathematical function mapping <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17060"><a href="memory-model.html#sec-memory-model-fundamentals">Memory events</a></emu-xref> in <emu-xref aoid="SharedDataBlockEventSet" id="_ref_17061"><a href="memory-model.html#sec-sharedatablockeventset">SharedDataBlockEventSet</a></emu-xref>(<var>execution</var>) to <emu-xref href="#sec-list-and-record-specification-type" id="_ref_17062"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">Lists</a></emu-xref> of events in <emu-xref aoid="SharedDataBlockEventSet" id="_ref_17063"><a href="memory-model.html#sec-sharedatablockeventset">SharedDataBlockEventSet</a></emu-xref>(<var>execution</var>) that satisfies the following conditions.</p>
|
|
<ul>
|
|
<li>
|
|
<p>For each <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17064"><a href="memory-model.html#sec-memory-model-fundamentals">ReadSharedMemory</a></emu-xref> or <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17065"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> event <var>R</var> in <emu-xref aoid="SharedDataBlockEventSet" id="_ref_17066"><a href="memory-model.html#sec-sharedatablockeventset">SharedDataBlockEventSet</a></emu-xref>(<var>execution</var>), reads-bytes-from(<var>R</var>) in <var>execution</var> is a <emu-xref href="#sec-list-and-record-specification-type" id="_ref_17067"><a href="ecmascript-data-types-and-values.html#sec-list-and-record-specification-type">List</a></emu-xref> of length <var>R</var>.<var class="field">[[ElementSize]]</var> whose elements are <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17068"><a href="memory-model.html#sec-memory-model-fundamentals">WriteSharedMemory</a></emu-xref> or <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17069"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> events <var>Ws</var> such that all of the following are true.</p>
|
|
<ul>
|
|
<li>Each event <var>W</var> with index <var>i</var> in <var>Ws</var> has <var>R</var>.<var class="field">[[ByteIndex]]</var> + <var>i</var> in its <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17070"><a href="memory-model.html#sec-memory-model-fundamentals">memory range</a></emu-xref>.</li>
|
|
<li><var>R</var> is not in <var>Ws</var>.</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
<p>A <emu-xref href="#sec-candidate-executions" id="_ref_17071"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> always admits a reads-bytes-from function.</p>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-reads-from">
|
|
<h1><span class="secnum">29.6.3</span> reads-from</h1>
|
|
<p>For a <emu-xref href="#sec-candidate-executions" id="_ref_17072"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <var>execution</var>, its <dfn tabindex="-1">reads-from</dfn> <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17073"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">Relation</a></emu-xref> is the <emu-xref href="#least-relation" id="_ref_17074"><a href="ecmascript-data-types-and-values.html#least-relation">least Relation</a></emu-xref> on <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17075"><a href="memory-model.html#sec-memory-model-fundamentals">Memory events</a></emu-xref> that satisfies the following.</p>
|
|
<ul>
|
|
<li>For events <var>R</var> and <var>W</var>, <var>R</var> reads-from <var>W</var> in <var>execution</var> if <emu-xref aoid="SharedDataBlockEventSet" id="_ref_17076"><a href="memory-model.html#sec-sharedatablockeventset">SharedDataBlockEventSet</a></emu-xref>(<var>execution</var>) contains both <var>R</var> and <var>W</var>, and <emu-xref aoid="reads-bytes-from" id="_ref_17077"><a href="memory-model.html#sec-reads-bytes-from">reads-bytes-from</a></emu-xref>(<var>R</var>) in <var>execution</var> contains <var>W</var>.</li>
|
|
</ul>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-host-synchronizes-with">
|
|
<h1><span class="secnum">29.6.4</span> host-synchronizes-with</h1>
|
|
<p>For a <emu-xref href="#sec-candidate-executions" id="_ref_17078"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <var>execution</var>, its <dfn tabindex="-1">host-synchronizes-with</dfn> <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17079"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">Relation</a></emu-xref> is a <emu-xref href="#host" id="_ref_17080"><a href="overview.html#host">host</a></emu-xref>-provided <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17081"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">strict partial order</a></emu-xref> on <emu-xref href="#host" id="_ref_17082"><a href="overview.html#host">host</a></emu-xref>-specific <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17083"><a href="memory-model.html#sec-memory-model-fundamentals">Memory events</a></emu-xref> that satisfies at least the following.</p>
|
|
<ul>
|
|
<li>If <var>E</var> host-synchronizes-with <var>D</var> in <var>execution</var>, <emu-xref aoid="HostEventSet" id="_ref_17084"><a href="memory-model.html#sec-hosteventset">HostEventSet</a></emu-xref>(<var>execution</var>) contains <var>E</var> and <var>D</var>.</li>
|
|
<li>There is no cycle in the union of host-synchronizes-with and <emu-xref href="#sec-agent-order" id="_ref_17085"><a href="memory-model.html#sec-agent-order">is-agent-order-before</a></emu-xref> in <var>execution</var>.</li>
|
|
</ul>
|
|
|
|
<emu-note><span class="note">Note 1</span><div class="note-contents">
|
|
<p>For two <emu-xref href="#host" id="_ref_17086"><a href="overview.html#host">host</a></emu-xref>-specific events <var>E</var> and <var>D</var> in a <emu-xref href="#sec-candidate-executions" id="_ref_17087"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <var>execution</var>, <var>E</var> host-synchronizes-with <var>D</var> in <var>execution</var> implies <var>E</var> <emu-xref href="#sec-happens-before" id="_ref_17088"><a href="memory-model.html#sec-happens-before">happens-before</a></emu-xref> <var>D</var> in <var>execution</var>.</p>
|
|
</div></emu-note>
|
|
<emu-note><span class="note">Note 2</span><div class="note-contents">
|
|
<p>This <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17089"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">Relation</a></emu-xref> allows the <emu-xref href="#host" id="_ref_17090"><a href="overview.html#host">host</a></emu-xref> to provide additional synchronization mechanisms, such as <code>postMessage</code> between HTML workers.</p>
|
|
</div></emu-note>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-synchronizes-with">
|
|
<h1><span class="secnum">29.6.5</span> synchronizes-with</h1>
|
|
<p>For a <emu-xref href="#sec-candidate-executions" id="_ref_17091"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <var>execution</var>, its <dfn tabindex="-1">synchronizes-with</dfn> <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17092"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">Relation</a></emu-xref> is the <emu-xref href="#least-relation" id="_ref_17093"><a href="ecmascript-data-types-and-values.html#least-relation">least Relation</a></emu-xref> on <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17094"><a href="memory-model.html#sec-memory-model-fundamentals">Memory events</a></emu-xref> that satisfies the following.</p>
|
|
<ul>
|
|
<li>
|
|
For events <var>R</var> and <var>W</var>, <var>W</var> synchronizes-with <var>R</var> in <var>execution</var> if <var>R</var> <emu-xref href="#sec-reads-from" id="_ref_17095"><a href="memory-model.html#sec-reads-from">reads-from</a></emu-xref> <var>W</var> in <var>execution</var>, <var>R</var>.<var class="field">[[Order]]</var> is <emu-const>seq-cst</emu-const>, <var>W</var>.<var class="field">[[Order]]</var> is <emu-const>seq-cst</emu-const>, and <var>R</var> and <var>W</var> have equal <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17096"><a href="memory-model.html#sec-memory-model-fundamentals">memory ranges</a></emu-xref>.
|
|
</li>
|
|
<li>
|
|
For each element <var>eventsRecord</var> of <var>execution</var>.<var class="field">[[EventsRecords]]</var>, the following is true.
|
|
<ul>
|
|
<li>For events <var>S</var> and <var>Sw</var>, <var>S</var> synchronizes-with <var>Sw</var> in <var>execution</var> if <var>eventsRecord</var>.<var class="field">[[AgentSynchronizesWith]]</var> contains (<var>S</var>, <var>Sw</var>).</li>
|
|
</ul>
|
|
</li>
|
|
<li>For events <var>E</var> and <var>D</var>, <var>E</var> synchronizes-with <var>D</var> in <var>execution</var> if <var>execution</var>.<var class="field">[[HostSynchronizesWith]]</var> contains (<var>E</var>, <var>D</var>).</li>
|
|
</ul>
|
|
|
|
<emu-note><span class="note">Note 1</span><div class="note-contents">
|
|
<p>Owing to convention in <emu-xref href="#sec-memory-model" id="_ref_17097"><a href="memory-model.html#sec-memory-model">memory model</a></emu-xref> literature, in a <emu-xref href="#sec-candidate-executions" id="_ref_17098"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <var>execution</var>, <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17099"><a href="memory-model.html#sec-memory-model-fundamentals">write events</a></emu-xref> synchronizes-with <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17100"><a href="memory-model.html#sec-memory-model-fundamentals">read events</a></emu-xref>, instead of <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17101"><a href="memory-model.html#sec-memory-model-fundamentals">read events</a></emu-xref> synchronizes-with <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17102"><a href="memory-model.html#sec-memory-model-fundamentals">write events</a></emu-xref>.</p>
|
|
</div></emu-note>
|
|
|
|
<emu-note><span class="note">Note 2</span><div class="note-contents">
|
|
<p>In a <emu-xref href="#sec-candidate-executions" id="_ref_17103"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <var>execution</var>, <emu-const>init</emu-const> events do not participate in this <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17104"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">Relation</a></emu-xref> and are instead constrained directly by <emu-xref href="#sec-happens-before" id="_ref_17105"><a href="memory-model.html#sec-happens-before">happens-before</a></emu-xref>.</p>
|
|
</div></emu-note>
|
|
|
|
<emu-note><span class="note">Note 3</span><div class="note-contents">
|
|
<p>In a <emu-xref href="#sec-candidate-executions" id="_ref_17106"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <var>execution</var>, not all <emu-const>seq-cst</emu-const> events related by <emu-xref href="#sec-reads-from" id="_ref_17107"><a href="memory-model.html#sec-reads-from">reads-from</a></emu-xref> are related by synchronizes-with. Only events that also have equal <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17108"><a href="memory-model.html#sec-memory-model-fundamentals">memory ranges</a></emu-xref> are related by synchronizes-with.</p>
|
|
</div></emu-note>
|
|
|
|
<emu-note><span class="note">Note 4</span><div class="note-contents">
|
|
<p>For <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17109"><a href="memory-model.html#sec-memory-model-fundamentals">Shared Data Block events</a></emu-xref> <var>R</var> and <var>W</var> in a <emu-xref href="#sec-candidate-executions" id="_ref_17110"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <var>execution</var> such that <var>W</var> synchronizes-with <var>R</var>, <var>R</var> may <emu-xref href="#sec-reads-from" id="_ref_17111"><a href="memory-model.html#sec-reads-from">reads-from</a></emu-xref> other writes than <var>W</var>.</p>
|
|
</div></emu-note>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-happens-before">
|
|
<h1><span class="secnum">29.6.6</span> happens-before</h1>
|
|
<p>For a <emu-xref href="#sec-candidate-executions" id="_ref_17112"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <var>execution</var>, its <dfn tabindex="-1">happens-before</dfn> <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17113"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">Relation</a></emu-xref> is the <emu-xref href="#least-relation" id="_ref_17114"><a href="ecmascript-data-types-and-values.html#least-relation">least Relation</a></emu-xref> on <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17115"><a href="memory-model.html#sec-memory-model-fundamentals">Memory events</a></emu-xref> that satisfies the following.</p>
|
|
|
|
<ul>
|
|
<li>
|
|
<p>For events <var>E</var> and <var>D</var>, <var>E</var> happens-before <var>D</var> in <var>execution</var> if any of the following conditions are true.</p>
|
|
<ul>
|
|
<li><var>E</var> <emu-xref href="#sec-agent-order" id="_ref_17116"><a href="memory-model.html#sec-agent-order">is-agent-order-before</a></emu-xref> <var>D</var> in <var>execution</var>.</li>
|
|
<li><var>E</var> <emu-xref href="#sec-synchronizes-with" id="_ref_17117"><a href="memory-model.html#sec-synchronizes-with">synchronizes-with</a></emu-xref> <var>D</var> in <var>execution</var>.</li>
|
|
<li><emu-xref aoid="SharedDataBlockEventSet" id="_ref_17118"><a href="memory-model.html#sec-sharedatablockeventset">SharedDataBlockEventSet</a></emu-xref>(<var>execution</var>) contains both <var>E</var> and <var>D</var>, <var>E</var>.<var class="field">[[Order]]</var> is <emu-const>init</emu-const>, and <var>E</var> and <var>D</var> have overlapping <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17119"><a href="memory-model.html#sec-memory-model-fundamentals">memory ranges</a></emu-xref>.</li>
|
|
<li>There is an event <var>F</var> such that <var>E</var> happens-before <var>F</var> and <var>F</var> happens-before <var>D</var> in <var>execution</var>.</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
|
|
<emu-note><span class="note">Note</span><div class="note-contents">
|
|
<p>Because happens-before is a superset of <emu-xref href="#agent" id="_ref_17120"><a href="executable-code-and-execution-contexts.html#agent">agent</a></emu-xref>-order, a <emu-xref href="#sec-candidate-executions" id="_ref_17121"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> is consistent with the single-thread evaluation semantics of ECMAScript.</p>
|
|
</div></emu-note>
|
|
</emu-clause>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-properties-of-valid-executions">
|
|
<h1><span class="secnum">29.7</span> Properties of Valid Executions</h1>
|
|
|
|
<emu-clause id="sec-valid-chosen-reads">
|
|
<h1><span class="secnum">29.7.1</span> Valid Chosen Reads</h1>
|
|
<p>A <emu-xref href="#sec-candidate-executions" id="_ref_17122"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <var>execution</var> has valid chosen reads if the following algorithm returns <emu-val>true</emu-val>.</p>
|
|
<emu-alg><ol><li>For each <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17123"><a href="memory-model.html#sec-memory-model-fundamentals">ReadSharedMemory</a></emu-xref> or <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17124"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> event <var>R</var> of <emu-xref aoid="SharedDataBlockEventSet" id="_ref_17125"><a href="memory-model.html#sec-sharedatablockeventset">SharedDataBlockEventSet</a></emu-xref>(<var>execution</var>), do<ol><li>Let <var>chosenValueRecord</var> be the element of <var>execution</var>.<var class="field">[[ChosenValues]]</var> whose <var class="field">[[Event]]</var> field is <var>R</var>.</li><li>Let <var>chosenValue</var> be <var>chosenValueRecord</var>.<var class="field">[[ChosenValue]]</var>.</li><li>Let <var>readValue</var> be <emu-xref aoid="ValueOfReadEvent" id="_ref_17126"><a href="memory-model.html#sec-valueofreadevent">ValueOfReadEvent</a></emu-xref>(<var>execution</var>, <var>R</var>).</li><li>Let <var>chosenLen</var> be the number of elements in <var>chosenValue</var>.</li><li>Let <var>readLen</var> be the number of elements in <var>readValue</var>.</li><li>If <var>chosenLen</var> ≠ <var>readLen</var>, then<ol><li>Return <emu-val>false</emu-val>.</li></ol></li><li>If <var>chosenValue</var>[<var>i</var>] ≠ <var>readValue</var>[<var>i</var>] for some <emu-xref href="#integer" id="_ref_17127"><a href="notational-conventions.html#integer">integer</a></emu-xref> <var>i</var> in the <emu-xref href="#interval" id="_ref_17128"><a href="notational-conventions.html#interval">interval</a></emu-xref> from 0 (inclusive) to <var>chosenLen</var> (exclusive), then<ol><li>Return <emu-val>false</emu-val>.</li></ol></li></ol></li><li>Return <emu-val>true</emu-val>.</li></ol></emu-alg>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-coherent-reads">
|
|
<h1><span class="secnum">29.7.2</span> Coherent Reads</h1>
|
|
<p>A <emu-xref href="#sec-candidate-executions" id="_ref_17129"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <var>execution</var> has coherent reads if the following algorithm returns <emu-val>true</emu-val>.</p>
|
|
<emu-alg><ol><li>For each <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17130"><a href="memory-model.html#sec-memory-model-fundamentals">ReadSharedMemory</a></emu-xref> or <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17131"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> event <var>R</var> of <emu-xref aoid="SharedDataBlockEventSet" id="_ref_17132"><a href="memory-model.html#sec-sharedatablockeventset">SharedDataBlockEventSet</a></emu-xref>(<var>execution</var>), do<ol><li>Let <var>Ws</var> be <emu-xref aoid="reads-bytes-from" id="_ref_17133"><a href="memory-model.html#sec-reads-bytes-from">reads-bytes-from</a></emu-xref>(<var>R</var>) in <var>execution</var>.</li><li>Let <var>byteLocation</var> be <var>R</var>.<var class="field">[[ByteIndex]]</var>.</li><li>For each element <var>W</var> of <var>Ws</var>, do<ol><li>If <var>R</var> <emu-xref href="#sec-happens-before" id="_ref_17134"><a href="memory-model.html#sec-happens-before">happens-before</a></emu-xref> <var>W</var> in <var>execution</var>, then<ol><li>Return <emu-val>false</emu-val>.</li></ol></li><li>If there exists a <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17135"><a href="memory-model.html#sec-memory-model-fundamentals">WriteSharedMemory</a></emu-xref> or <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17136"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> event <var>V</var> that has <var>byteLocation</var> in its <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17137"><a href="memory-model.html#sec-memory-model-fundamentals">memory range</a></emu-xref> such that <var>W</var> <emu-xref href="#sec-happens-before" id="_ref_17138"><a href="memory-model.html#sec-happens-before">happens-before</a></emu-xref> <var>V</var> in <var>execution</var> and <var>V</var> <emu-xref href="#sec-happens-before" id="_ref_17139"><a href="memory-model.html#sec-happens-before">happens-before</a></emu-xref> <var>R</var> in <var>execution</var>, then<ol><li>Return <emu-val>false</emu-val>.</li></ol></li><li>Set <var>byteLocation</var> to <var>byteLocation</var> + 1.</li></ol></li></ol></li><li>Return <emu-val>true</emu-val>.</li></ol></emu-alg>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-tear-free-aligned-reads">
|
|
<h1><span class="secnum">29.7.3</span> Tear Free Reads</h1>
|
|
<p>A <emu-xref href="#sec-candidate-executions" id="_ref_17140"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <var>execution</var> has tear free reads if the following algorithm returns <emu-val>true</emu-val>.</p>
|
|
<emu-alg><ol><li>For each <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17141"><a href="memory-model.html#sec-memory-model-fundamentals">ReadSharedMemory</a></emu-xref> or <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17142"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> event <var>R</var> of <emu-xref aoid="SharedDataBlockEventSet" id="_ref_17143"><a href="memory-model.html#sec-sharedatablockeventset">SharedDataBlockEventSet</a></emu-xref>(<var>execution</var>), do<ol><li>If <var>R</var>.<var class="field">[[NoTear]]</var> is <emu-val>true</emu-val>, then<ol><li><emu-xref href="#assert" id="_ref_17144"><a href="notational-conventions.html#assert">Assert</a></emu-xref>: The remainder of dividing <var>R</var>.<var class="field">[[ByteIndex]]</var> by <var>R</var>.<var class="field">[[ElementSize]]</var> is 0.</li><li>For each <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17145"><a href="memory-model.html#sec-memory-model-fundamentals">Memory event</a></emu-xref> <var>W</var> such that <var>R</var> <emu-xref href="#sec-reads-from" id="_ref_17146"><a href="memory-model.html#sec-reads-from">reads-from</a></emu-xref> <var>W</var> in <var>execution</var> and <var>W</var>.<var class="field">[[NoTear]]</var> is <emu-val>true</emu-val>, do<ol><li>If <var>R</var> and <var>W</var> have equal <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17147"><a href="memory-model.html#sec-memory-model-fundamentals">memory ranges</a></emu-xref> and there exists a <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17148"><a href="memory-model.html#sec-memory-model-fundamentals">Memory event</a></emu-xref> <var>V</var> such that <var>V</var> and <var>W</var> have equal <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17149"><a href="memory-model.html#sec-memory-model-fundamentals">memory ranges</a></emu-xref>, <var>V</var>.<var class="field">[[NoTear]]</var> is <emu-val>true</emu-val>, <var>W</var> and <var>V</var> are not the same <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17150"><a href="memory-model.html#sec-memory-model-fundamentals">Shared Data Block event</a></emu-xref>, and <var>R</var> <emu-xref href="#sec-reads-from" id="_ref_17151"><a href="memory-model.html#sec-reads-from">reads-from</a></emu-xref> <var>V</var> in <var>execution</var>, then<ol><li>Return <emu-val>false</emu-val>.</li></ol></li></ol></li></ol></li></ol></li><li>Return <emu-val>true</emu-val>.</li></ol></emu-alg>
|
|
|
|
<emu-note><span class="note">Note</span><div class="note-contents">
|
|
<p>A <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17152"><a href="memory-model.html#sec-memory-model-fundamentals">Shared Data Block event</a></emu-xref>'s <var class="field">[[NoTear]]</var> field is <emu-val>true</emu-val> when that event was introduced via accessing an <emu-xref href="#integer" id="_ref_17153"><a href="notational-conventions.html#integer">integer</a></emu-xref> <emu-xref href="#typedarray" id="_ref_17154"><a href="ordinary-and-exotic-objects-behaviours.html#typedarray">TypedArray</a></emu-xref>, and <emu-val>false</emu-val> when introduced via accessing a floating point <emu-xref href="#typedarray" id="_ref_17155"><a href="ordinary-and-exotic-objects-behaviours.html#typedarray">TypedArray</a></emu-xref> or DataView.</p>
|
|
<p>Intuitively, this requirement says when a <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17156"><a href="memory-model.html#sec-memory-model-fundamentals">memory range</a></emu-xref> is accessed in an aligned fashion via an <emu-xref href="#integer" id="_ref_17157"><a href="notational-conventions.html#integer">integer</a></emu-xref> <emu-xref href="#typedarray" id="_ref_17158"><a href="ordinary-and-exotic-objects-behaviours.html#typedarray">TypedArray</a></emu-xref>, a single <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17159"><a href="memory-model.html#sec-memory-model-fundamentals">write event</a></emu-xref> on that range must "win" when in a <emu-xref href="#sec-data-races" id="_ref_17160"><a href="memory-model.html#sec-data-races">data race</a></emu-xref> with other <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17161"><a href="memory-model.html#sec-memory-model-fundamentals">write events</a></emu-xref> with equal ranges. More precisely, this requirement says an aligned <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17162"><a href="memory-model.html#sec-memory-model-fundamentals">read event</a></emu-xref> cannot read a value composed of bytes from multiple, different <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17163"><a href="memory-model.html#sec-memory-model-fundamentals">write events</a></emu-xref> all with equal ranges. It is possible, however, for an aligned <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17164"><a href="memory-model.html#sec-memory-model-fundamentals">read event</a></emu-xref> to read from multiple <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17165"><a href="memory-model.html#sec-memory-model-fundamentals">write events</a></emu-xref> with overlapping ranges.</p>
|
|
</div></emu-note>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-memory-order">
|
|
<h1><span class="secnum">29.7.4</span> Sequentially Consistent Atomics</h1>
|
|
<p>For a <emu-xref href="#sec-candidate-executions" id="_ref_17166"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <var>execution</var>, <dfn tabindex="-1">is-memory-order-before</dfn> is a <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17167"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">strict total order</a></emu-xref> of all <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17168"><a href="memory-model.html#sec-memory-model-fundamentals">Memory events</a></emu-xref> in <emu-xref aoid="EventSet" id="_ref_17169"><a href="memory-model.html#sec-event-set">EventSet</a></emu-xref>(<var>execution</var>) that satisfies the following.</p>
|
|
<ul>
|
|
<li>For events <var>E</var> and <var>D</var>, <var>E</var> is-memory-order-before <var>D</var> in <var>execution</var> if <var>E</var> <emu-xref href="#sec-happens-before" id="_ref_17170"><a href="memory-model.html#sec-happens-before">happens-before</a></emu-xref> <var>D</var> in <var>execution</var>.</li>
|
|
<li>
|
|
<p>For events <var>R</var> and <var>W</var> such that <var>R</var> <emu-xref href="#sec-reads-from" id="_ref_17171"><a href="memory-model.html#sec-reads-from">reads-from</a></emu-xref> <var>W</var> in <var>execution</var>, there is no <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17172"><a href="memory-model.html#sec-memory-model-fundamentals">WriteSharedMemory</a></emu-xref> or <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17173"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> event <var>V</var> in <emu-xref aoid="SharedDataBlockEventSet" id="_ref_17174"><a href="memory-model.html#sec-sharedatablockeventset">SharedDataBlockEventSet</a></emu-xref>(<var>execution</var>) such that <var>V</var>.<var class="field">[[Order]]</var> is <emu-const>seq-cst</emu-const>, <var>W</var> is-memory-order-before <var>V</var> in <var>execution</var>, <var>V</var> is-memory-order-before <var>R</var> in <var>execution</var>, and any of the following conditions are true.</p>
|
|
<ul>
|
|
<li><var>W</var> <emu-xref href="#sec-synchronizes-with" id="_ref_17175"><a href="memory-model.html#sec-synchronizes-with">synchronizes-with</a></emu-xref> <var>R</var> in <var>execution</var>, and <var>V</var> and <var>R</var> have equal <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17176"><a href="memory-model.html#sec-memory-model-fundamentals">memory ranges</a></emu-xref>.</li>
|
|
<li><var>W</var> <emu-xref href="#sec-happens-before" id="_ref_17177"><a href="memory-model.html#sec-happens-before">happens-before</a></emu-xref> <var>R</var> and <var>V</var> <emu-xref href="#sec-happens-before" id="_ref_17178"><a href="memory-model.html#sec-happens-before">happens-before</a></emu-xref> <var>R</var> in <var>execution</var>, <var>W</var>.<var class="field">[[Order]]</var> is <emu-const>seq-cst</emu-const>, and <var>W</var> and <var>V</var> have equal <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17179"><a href="memory-model.html#sec-memory-model-fundamentals">memory ranges</a></emu-xref>.</li>
|
|
<li><var>W</var> <emu-xref href="#sec-happens-before" id="_ref_17180"><a href="memory-model.html#sec-happens-before">happens-before</a></emu-xref> <var>R</var> and <var>W</var> <emu-xref href="#sec-happens-before" id="_ref_17181"><a href="memory-model.html#sec-happens-before">happens-before</a></emu-xref> <var>V</var> in <var>execution</var>, <var>R</var>.<var class="field">[[Order]]</var> is <emu-const>seq-cst</emu-const>, and <var>V</var> and <var>R</var> have equal <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17182"><a href="memory-model.html#sec-memory-model-fundamentals">memory ranges</a></emu-xref>.</li>
|
|
</ul>
|
|
<emu-note><span class="note">Note 1</span><div class="note-contents">
|
|
<p>This clause additionally constrains <emu-const>seq-cst</emu-const> events on equal <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17183"><a href="memory-model.html#sec-memory-model-fundamentals">memory ranges</a></emu-xref>.</p>
|
|
</div></emu-note>
|
|
</li>
|
|
<li>
|
|
<p>For each <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17184"><a href="memory-model.html#sec-memory-model-fundamentals">WriteSharedMemory</a></emu-xref> or <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17185"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> event <var>W</var> in <emu-xref aoid="SharedDataBlockEventSet" id="_ref_17186"><a href="memory-model.html#sec-sharedatablockeventset">SharedDataBlockEventSet</a></emu-xref>(<var>execution</var>), if <var>W</var>.<var class="field">[[Order]]</var> is <emu-const>seq-cst</emu-const>, then it is not the case that there is an infinite number of <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17187"><a href="memory-model.html#sec-memory-model-fundamentals">ReadSharedMemory</a></emu-xref> or <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17188"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> events in <emu-xref aoid="SharedDataBlockEventSet" id="_ref_17189"><a href="memory-model.html#sec-sharedatablockeventset">SharedDataBlockEventSet</a></emu-xref>(<var>execution</var>) with equal <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17190"><a href="memory-model.html#sec-memory-model-fundamentals">memory range</a></emu-xref> that is memory-order before <var>W</var>.</p>
|
|
<emu-note><span class="note">Note 2</span><div class="note-contents">
|
|
<p>This clause together with the forward progress guarantee on <emu-xref href="#agent" id="_ref_17191"><a href="executable-code-and-execution-contexts.html#agent">agents</a></emu-xref> ensure the liveness condition that <emu-const>seq-cst</emu-const> <emu-xref href="#sec-memory-model-fundamentals" id="_ref_849"><a href="memory-model.html#sec-memory-model-fundamentals">writes</a></emu-xref> become visible to <emu-const>seq-cst</emu-const> <emu-xref href="#sec-memory-model-fundamentals" id="_ref_850"><a href="memory-model.html#sec-memory-model-fundamentals">reads</a></emu-xref> with equal <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17192"><a href="memory-model.html#sec-memory-model-fundamentals">memory range</a></emu-xref> in <emu-xref href="#finite" id="_ref_17193"><a href="ecmascript-data-types-and-values.html#finite">finite</a></emu-xref> time.</p>
|
|
</div></emu-note>
|
|
</li>
|
|
</ul>
|
|
<p>A <emu-xref href="#sec-candidate-executions" id="_ref_17194"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> has sequentially consistent atomics if it admits an is-memory-order-before <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17195"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">Relation</a></emu-xref>.</p>
|
|
|
|
<emu-note><span class="note">Note 3</span><div class="note-contents">
|
|
<p>While is-memory-order-before includes all events in <emu-xref aoid="EventSet" id="_ref_17196"><a href="memory-model.html#sec-event-set">EventSet</a></emu-xref>(<var>execution</var>), those that are not constrained by <emu-xref href="#sec-happens-before" id="_ref_17197"><a href="memory-model.html#sec-happens-before">happens-before</a></emu-xref> or <emu-xref href="#sec-synchronizes-with" id="_ref_17198"><a href="memory-model.html#sec-synchronizes-with">synchronizes-with</a></emu-xref> in <var>execution</var> are allowed to occur anywhere in the order.</p>
|
|
</div></emu-note>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-valid-executions">
|
|
<h1><span class="secnum">29.7.5</span> Valid Executions</h1>
|
|
<p>A <emu-xref href="#sec-candidate-executions" id="_ref_17199"><a href="memory-model.html#sec-candidate-executions">candidate execution</a></emu-xref> <var>execution</var> is a valid execution (or simply an execution) if all of the following are true.</p>
|
|
<ul>
|
|
<li>The <emu-xref href="#host" id="_ref_17200"><a href="overview.html#host">host</a></emu-xref> provides a <emu-xref href="#sec-host-synchronizes-with" id="_ref_17201"><a href="memory-model.html#sec-host-synchronizes-with">host-synchronizes-with</a></emu-xref> <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17202"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">Relation</a></emu-xref> for <var>execution</var>.</li>
|
|
<li><var>execution</var> admits a <emu-xref href="#sec-happens-before" id="_ref_17203"><a href="memory-model.html#sec-happens-before">happens-before</a></emu-xref> <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17204"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">Relation</a></emu-xref> that is a <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17205"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">strict partial order</a></emu-xref>.</li>
|
|
<li><var>execution</var> has valid chosen reads.</li>
|
|
<li><var>execution</var> has coherent reads.</li>
|
|
<li><var>execution</var> has tear free reads.</li>
|
|
<li><var>execution</var> has sequentially consistent atomics.</li>
|
|
</ul>
|
|
<p>All programs have at least one valid execution.</p>
|
|
</emu-clause>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-races">
|
|
<h1><span class="secnum">29.8</span> Races</h1>
|
|
<p>For an execution <var>execution</var> and events <var>E</var> and <var>D</var> that are contained in <emu-xref aoid="SharedDataBlockEventSet" id="_ref_17206"><a href="memory-model.html#sec-sharedatablockeventset">SharedDataBlockEventSet</a></emu-xref>(<var>execution</var>), <var>E</var> and <var>D</var> are in a <em>race</em> if the following algorithm returns <emu-val>true</emu-val>.</p>
|
|
<emu-alg><ol><li>If <var>E</var> and <var>D</var> are not the same <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17207"><a href="memory-model.html#sec-memory-model-fundamentals">Shared Data Block event</a></emu-xref>, then<ol><li>If it is not the case that both <var>E</var> <emu-xref href="#sec-happens-before" id="_ref_17208"><a href="memory-model.html#sec-happens-before">happens-before</a></emu-xref> <var>D</var> in <var>execution</var> and <var>D</var> <emu-xref href="#sec-happens-before" id="_ref_17209"><a href="memory-model.html#sec-happens-before">happens-before</a></emu-xref> <var>E</var> in <var>execution</var>, then<ol><li>If <var>E</var> and <var>D</var> are both <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17210"><a href="memory-model.html#sec-memory-model-fundamentals">WriteSharedMemory</a></emu-xref> or <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17211"><a href="memory-model.html#sec-memory-model-fundamentals">ReadModifyWriteSharedMemory</a></emu-xref> events and <var>E</var> and <var>D</var> do not have disjoint <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17212"><a href="memory-model.html#sec-memory-model-fundamentals">memory ranges</a></emu-xref>, then<ol><li>Return <emu-val>true</emu-val>.</li></ol></li><li>If <var>E</var> <emu-xref href="#sec-reads-from" id="_ref_17213"><a href="memory-model.html#sec-reads-from">reads-from</a></emu-xref> <var>D</var> in <var>execution</var> or <var>D</var> <emu-xref href="#sec-reads-from" id="_ref_17214"><a href="memory-model.html#sec-reads-from">reads-from</a></emu-xref> <var>E</var> in <var>execution</var>, then<ol><li>Return <emu-val>true</emu-val>.</li></ol></li></ol></li></ol></li><li>Return <emu-val>false</emu-val>.</li></ol></emu-alg>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-data-races">
|
|
<h1><span class="secnum">29.9</span> Data Races</h1>
|
|
<p>For an execution <var>execution</var> and events <var>E</var> and <var>D</var> that are contained in <emu-xref aoid="SharedDataBlockEventSet" id="_ref_17215"><a href="memory-model.html#sec-sharedatablockeventset">SharedDataBlockEventSet</a></emu-xref>(<var>execution</var>), <var>E</var> and <var>D</var> are in a <dfn tabindex="-1">data race</dfn> if the following algorithm returns <emu-val>true</emu-val>.</p>
|
|
<emu-alg><ol><li>If <var>E</var> and <var>D</var> are in a <emu-xref href="#sec-races" id="_ref_851"><a href="memory-model.html#sec-races">race</a></emu-xref> in <var>execution</var>, then<ol><li>If <var>E</var>.<var class="field">[[Order]]</var> is not <emu-const>seq-cst</emu-const> or <var>D</var>.<var class="field">[[Order]]</var> is not <emu-const>seq-cst</emu-const>, then<ol><li>Return <emu-val>true</emu-val>.</li></ol></li><li>If <var>E</var> and <var>D</var> have overlapping <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17216"><a href="memory-model.html#sec-memory-model-fundamentals">memory ranges</a></emu-xref>, then<ol><li>Return <emu-val>true</emu-val>.</li></ol></li></ol></li><li>Return <emu-val>false</emu-val>.</li></ol></emu-alg>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-data-race-freedom">
|
|
<h1><span class="secnum">29.10</span> Data Race Freedom</h1>
|
|
<p>An execution <var>execution</var> is <dfn tabindex="-1">data race free</dfn> if there are no two events in <emu-xref aoid="SharedDataBlockEventSet" id="_ref_17217"><a href="memory-model.html#sec-sharedatablockeventset">SharedDataBlockEventSet</a></emu-xref>(<var>execution</var>) that are in a <emu-xref href="#sec-data-races" id="_ref_17218"><a href="memory-model.html#sec-data-races">data race</a></emu-xref>.</p>
|
|
<p>A program is data race free if all its executions are data race free.</p>
|
|
<p>The <emu-xref href="#sec-memory-model" id="_ref_17219"><a href="memory-model.html#sec-memory-model">memory model</a></emu-xref> guarantees sequential consistency of all events for data race free programs.</p>
|
|
</emu-clause>
|
|
|
|
<emu-clause id="sec-shared-memory-guidelines">
|
|
<h1><span class="secnum">29.11</span> Shared Memory Guidelines</h1>
|
|
<emu-note><span class="note">Note 1</span><div class="note-contents">
|
|
<p>The following are guidelines for ECMAScript programmers working with shared memory.</p>
|
|
<p>We recommend programs be kept <emu-xref href="#sec-data-race-freedom" id="_ref_17220"><a href="memory-model.html#sec-data-race-freedom">data race free</a></emu-xref>, i.e., make it so that it is impossible for there to be concurrent non-atomic operations on the same memory location. <emu-xref href="#sec-data-race-freedom" id="_ref_17221"><a href="memory-model.html#sec-data-race-freedom">Data race free</a></emu-xref> programs have interleaving semantics where each step in the evaluation semantics of each <emu-xref href="#agent" id="_ref_17222"><a href="executable-code-and-execution-contexts.html#agent">agent</a></emu-xref> are interleaved with each other. For <emu-xref href="#sec-data-race-freedom" id="_ref_17223"><a href="memory-model.html#sec-data-race-freedom">data race free</a></emu-xref> programs, it is not necessary to understand the details of the <emu-xref href="#sec-memory-model" id="_ref_17224"><a href="memory-model.html#sec-memory-model">memory model</a></emu-xref>. The details are unlikely to build intuition that will help one to better write ECMAScript.</p>
|
|
<p>More generally, even if a program is not <emu-xref href="#sec-data-race-freedom" id="_ref_17225"><a href="memory-model.html#sec-data-race-freedom">data race free</a></emu-xref> it may have predictable behaviour, so long as atomic operations are not involved in any data races and the operations that race all have the same access size. The simplest way to arrange for atomics not to be involved in races is to ensure that different memory cells are used by atomic and non-atomic operations and that atomic accesses of different sizes are not used to access the same cells at the same time. Effectively, the program should treat shared memory as strongly typed as much as possible. One still cannot depend on the ordering and timing of non-atomic accesses that race, but if memory is treated as strongly typed the racing accesses will not "tear" (bits of their values will not be mixed).</p>
|
|
</div></emu-note>
|
|
|
|
<emu-note><span class="note">Note 2</span><div class="note-contents">
|
|
<p>The following are guidelines for ECMAScript implementers writing compiler transformations for programs using shared memory.</p>
|
|
<p>It is desirable to allow most program transformations that are valid in a single-<emu-xref href="#agent" id="_ref_17226"><a href="executable-code-and-execution-contexts.html#agent">agent</a></emu-xref> setting in a multi-<emu-xref href="#agent" id="_ref_17227"><a href="executable-code-and-execution-contexts.html#agent">agent</a></emu-xref> setting, to ensure that the performance of each <emu-xref href="#agent" id="_ref_17228"><a href="executable-code-and-execution-contexts.html#agent">agent</a></emu-xref> in a multi-<emu-xref href="#agent" id="_ref_17229"><a href="executable-code-and-execution-contexts.html#agent">agent</a></emu-xref> program is as good as it would be in a single-<emu-xref href="#agent" id="_ref_17230"><a href="executable-code-and-execution-contexts.html#agent">agent</a></emu-xref> setting. Frequently these transformations are hard to judge. We outline some rules about program transformations that are intended to be taken as normative (in that they are implied by the <emu-xref href="#sec-memory-model" id="_ref_17231"><a href="memory-model.html#sec-memory-model">memory model</a></emu-xref> or stronger than what the <emu-xref href="#sec-memory-model" id="_ref_17232"><a href="memory-model.html#sec-memory-model">memory model</a></emu-xref> implies) but which are likely not exhaustive. These rules are intended to apply to program transformations that precede the introductions of the <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17233"><a href="memory-model.html#sec-memory-model-fundamentals">Memory events</a></emu-xref> that make up the <emu-xref href="#sec-agent-order" id="_ref_17234"><a href="memory-model.html#sec-agent-order">is-agent-order-before</a></emu-xref> <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17235"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">Relation</a></emu-xref>.</p>
|
|
<p>Let an <dfn variants="agent-order slices" tabindex="-1">agent-order slice</dfn> be the subset of the <emu-xref href="#sec-agent-order" id="_ref_17236"><a href="memory-model.html#sec-agent-order">is-agent-order-before</a></emu-xref> <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17237"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">Relation</a></emu-xref> pertaining to a single <emu-xref href="#agent" id="_ref_17238"><a href="executable-code-and-execution-contexts.html#agent">agent</a></emu-xref>.</p>
|
|
<p>Let <dfn tabindex="-1">possible read values</dfn> of a <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17239"><a href="memory-model.html#sec-memory-model-fundamentals">read event</a></emu-xref> be the set of all values of <emu-xref aoid="ValueOfReadEvent" id="_ref_17240"><a href="memory-model.html#sec-valueofreadevent">ValueOfReadEvent</a></emu-xref> for that event across all valid executions.</p>
|
|
<p>Any transformation of an agent-order slice that is valid in the absence of shared memory is valid in the presence of shared memory, with the following exceptions.</p>
|
|
<ul>
|
|
<li>
|
|
<p><em>Atomics are carved in stone</em>: Program transformations must not cause any <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17241"><a href="memory-model.html#sec-memory-model-fundamentals">Shared Data Block events</a></emu-xref> whose <var class="field">[[Order]]</var> is <emu-const>seq-cst</emu-const> to be removed from the <emu-xref href="#sec-agent-order" id="_ref_17242"><a href="memory-model.html#sec-agent-order">is-agent-order-before</a></emu-xref> <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17243"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">Relation</a></emu-xref>, nor to be reordered with respect to each other, nor to be reordered inside an agent-order slice with respect to events whose <var class="field">[[Order]]</var> is <emu-const>unordered</emu-const>.</p>
|
|
<p>(In practice, the prohibition on reorderings forces a compiler to assume that every <emu-const>seq-cst</emu-const> operation is a synchronization and included in the final <emu-xref href="#sec-memory-order" id="_ref_17244"><a href="memory-model.html#sec-memory-order">is-memory-order-before</a></emu-xref> <emu-xref href="#sec-set-and-relation-specification-type" id="_ref_17245"><a href="ecmascript-data-types-and-values.html#sec-set-and-relation-specification-type">Relation</a></emu-xref>, which it would usually have to assume anyway in the absence of inter-<emu-xref href="#agent" id="_ref_17246"><a href="executable-code-and-execution-contexts.html#agent">agent</a></emu-xref> program analysis. It also forces the compiler to assume that every call where the callee's effects on the memory-order are unknown may contain <emu-const>seq-cst</emu-const> operations.)</p>
|
|
</li>
|
|
<li>
|
|
<p><em>Reads must be stable</em>: Any given shared memory read must only observe a single value in an execution.</p>
|
|
<p>(For example, if what is semantically a single read in the program is executed multiple times then the program is subsequently allowed to observe only one of the values read. A transformation known as rematerialization can violate this rule.)</p>
|
|
</li>
|
|
<li>
|
|
<p><em>Writes must be stable</em>: All observable writes to shared memory must follow from program semantics in an execution.</p>
|
|
<p>(For example, a transformation may not introduce certain observable writes, such as by using read-modify-write operations on a larger location to write a smaller datum, writing a value to memory that the program could not have written, or writing a just-read value back to the location it was read from, if that location could have been overwritten by another <emu-xref href="#agent" id="_ref_17247"><a href="executable-code-and-execution-contexts.html#agent">agent</a></emu-xref> after the read.)</p>
|
|
</li>
|
|
<li>
|
|
<p><em>Possible read values must be non-empty</em>: Program transformations cannot cause the possible read values of a shared memory read to become empty.</p>
|
|
<p>(Counterintuitively, this rule in effect restricts transformations on writes, because writes have force in <emu-xref href="#sec-memory-model" id="_ref_17248"><a href="memory-model.html#sec-memory-model">memory model</a></emu-xref> insofar as to be read by <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17249"><a href="memory-model.html#sec-memory-model-fundamentals">read events</a></emu-xref>. For example, writes may be moved and coalesced and sometimes reordered between two <emu-const>seq-cst</emu-const> operations, but the transformation may not remove every write that updates a location; some write must be preserved.)</p>
|
|
</li>
|
|
</ul>
|
|
<p>Examples of transformations that remain valid are: merging multiple non-atomic reads from the same location, reordering non-atomic reads, introducing speculative non-atomic reads, merging multiple non-atomic writes to the same location, reordering non-atomic writes to different locations, and hoisting non-atomic reads out of loops even if that affects termination. Note in general that aliased <emu-xref href="#typedarray" id="_ref_17250"><a href="ordinary-and-exotic-objects-behaviours.html#typedarray">TypedArrays</a></emu-xref> make it hard to prove that locations are different.</p>
|
|
</div></emu-note>
|
|
|
|
<emu-note><span class="note">Note 3</span><div class="note-contents">
|
|
<p>The following are guidelines for ECMAScript implementers generating machine code for shared memory accesses.</p>
|
|
<p>For architectures with memory models no weaker than those of ARM or Power, non-atomic stores and loads may be compiled to bare stores and loads on the target architecture. Atomic stores and loads may be compiled down to instructions that guarantee sequential consistency. If no such instructions exist, memory barriers are to be employed, such as placing barriers on both sides of a bare store or load. Read-modify-write operations may be compiled to read-modify-write instructions on the target architecture, such as <code>LOCK</code>-prefixed instructions on x86, load-exclusive/store-exclusive instructions on ARM, and load-link/store-conditional instructions on Power.</p>
|
|
<p>Specifically, the <emu-xref href="#sec-memory-model" id="_ref_17251"><a href="memory-model.html#sec-memory-model">memory model</a></emu-xref> is intended to allow code generation as follows.</p>
|
|
<ul>
|
|
<li>Every atomic operation in the program is assumed to be necessary.</li>
|
|
<li>Atomic operations are never rearranged with each other or with non-atomic operations.</li>
|
|
<li>Functions are always assumed to perform atomic operations.</li>
|
|
<li>Atomic operations are never implemented as read-modify-write operations on larger data, but as non-lock-free atomics if the platform does not have atomic operations of the appropriate size. (We already assume that every platform has normal memory access operations of every interesting size.)</li>
|
|
</ul>
|
|
<p>Naive code generation uses these patterns:</p>
|
|
<ul>
|
|
<li>Regular loads and stores compile to single load and store instructions.</li>
|
|
<li>Lock-free atomic loads and stores compile to a full (sequentially consistent) fence, a regular load or store, and a full fence.</li>
|
|
<li>Lock-free atomic read-modify-write accesses compile to a full fence, an atomic read-modify-write instruction sequence, and a full fence.</li>
|
|
<li>Non-lock-free atomics compile to a spinlock acquire, a full fence, a series of non-atomic load and store instructions, a full fence, and a spinlock release.</li>
|
|
</ul>
|
|
<p>That mapping is correct so long as an atomic operation on a <emu-xref href="#sec-memory-model-fundamentals" id="_ref_17252"><a href="memory-model.html#sec-memory-model-fundamentals">memory range</a></emu-xref> does not race with a non-atomic write or with an atomic operation of different size. However, that is all we need: the <emu-xref href="#sec-memory-model" id="_ref_17253"><a href="memory-model.html#sec-memory-model">memory model</a></emu-xref> effectively demotes the atomic operations involved in a race to non-atomic status. On the other hand, the naive mapping is quite strong: it allows atomic operations to be used as sequentially consistent fences, which the <emu-xref href="#sec-memory-model" id="_ref_17254"><a href="memory-model.html#sec-memory-model">memory model</a></emu-xref> does not actually guarantee.</p>
|
|
<p>Local improvements to those basic patterns are also allowed, subject to the constraints of the <emu-xref href="#sec-memory-model" id="_ref_17255"><a href="memory-model.html#sec-memory-model">memory model</a></emu-xref>. For example:</p>
|
|
<ul>
|
|
<li>There are obvious platform-dependent improvements that remove redundant fences. For example, on x86 the fences around lock-free atomic loads and stores can always be omitted except for the fence following a store, and no fence is needed for lock-free read-modify-write instructions, as these all use <code>LOCK</code>-prefixed instructions. On many platforms there are fences of several strengths, and weaker fences can be used in certain contexts without destroying sequential consistency.</li>
|
|
<li>Most modern platforms support lock-free atomics for all the data sizes required by ECMAScript atomics. Should non-lock-free atomics be needed, the fences surrounding the body of the atomic operation can usually be folded into the lock and unlock steps. The simplest solution for non-lock-free atomics is to have a single lock word per SharedArrayBuffer.</li>
|
|
<li>There are also more complicated platform-dependent local improvements, requiring some code analysis. For example, two back-to-back fences often have the same effect as a single fence, so if code is generated for two atomic operations in sequence, only a single fence need separate them. On x86, even a single fence separating atomic stores can be omitted, as the fence following a store is only needed to separate the store from a subsequent load.</li>
|
|
</ul>
|
|
</div></emu-note>
|
|
</emu-clause>
|
|
</emu-clause></div></body></html> |