29 Memory Model

memory consistency model, 즉 memory model은 SharedArrayBuffer로 backed된 TypedArray instances에 accessing하여, 그리고 Atomics object의 methods를 통해 발생하는 Shared Data Block events의 possible orderings를 specifies합니다. program에 data races(아래에 defined됨)가 없을 때, events의 ordering은 sequentially consistent하게, 즉 각 agent의 actions가 interleaving된 것처럼 나타납니다. program에 data races가 있을 때, shared memory operations는 sequentially inconsistent하게 나타날 수 있습니다. 예를 들어, programs는 causality-violating behaviour 및 기타 astonishments를 보일 수 있습니다. 이러한 astonishments는 compiler transforms 및 CPUs의 design(예: out-of-order execution 및 speculation)에서 발생합니다. memory model은 program이 sequentially consistent behaviour를 보이는 precise conditions와 data races에서 read될 수 있는 possible values 둘 다를 정의합니다. 즉, undefined behaviour는 없습니다.

memory model은 SharedArrayBuffer에 대한 abstract operations 또는 evaluation 중 Atomics object의 methods에 의해 introduced되는 Memory events에 대한 relational constraints로 defined됩니다.

Note

이 section은 SharedArrayBuffers에 대한 abstract operations가 introduced하는 Memory events에 관한 axiomatic model을 제공합니다. 이 model은 이 specification의 나머지와 달리 algorithmically expressible하지 않다는 점을 강조할 필요가 있습니다. abstract operations에 의한 events의 nondeterministic introduction은 ECMAScript evaluation의 operational semantics와 memory model의 axiomatic semantics 사이의 interface입니다. 이러한 events의 semantics는 evaluation의 모든 events graphs를 considering하여 defined됩니다. 이것들은 Static Semantics도 Runtime Semantics도 아닙니다. demonstrated algorithmic implementation은 없고, 대신 particular event graph가 allowed 또는 disallowed되는지를 determine하는 constraints의 set이 있습니다.

29.1 Memory Model Fundamentals

Shared memory accesses(reads와 writes)는 아래에 defined된 atomic accesses와 data accesses라는 두 groups로 divided됩니다. Atomic accesses는 sequentially consistent합니다. 즉, agent cluster의 모든 agents가 agreed upon하는 events의 strict total ordering이 있습니다. Non-atomic accesses에는 모든 agents가 agreed upon하는 strict total ordering이 없습니다. 즉, unordered입니다.

Note 1

release-acquire와 같이 sequentially consistent보다 약하고 unordered보다 강한 orderings는 supported되지 않습니다.

Shared Data Block eventReadSharedMemory, WriteSharedMemory, 또는 ReadModifyWriteSharedMemory Record 중 하나입니다. read event는 ReadSharedMemory 또는 ReadModifyWriteSharedMemory입니다. write event는 WriteSharedMemory 또는 ReadModifyWriteSharedMemory입니다.

Table 97: ReadSharedMemory Event Fields
Field Name Value Meaning
[[Order]] seq-cst 또는 unordered memory model이 event에 대해 guarantee하는 weakest ordering.
[[NoTear]] Boolean 이 event가 이 event와 equal memory range를 가진 multiple write events로부터 read하는 것이 allowed되는지 여부.
[[Block]] Shared Data Block event가 operate하는 block.
[[ByteIndex]] non-negative integer [[Block]]에서 read의 byte address.
[[ElementSize]] non-negative integer read의 size.
Table 98: WriteSharedMemory Event Fields
Field Name Value Meaning
[[Order]] seq-cst, unordered, 또는 init memory model이 event에 대해 guarantee하는 weakest ordering.
[[NoTear]] Boolean 이 event가 이 event와 equal memory range를 가진 multiple read events에 의해 read되는 것이 allowed되는지 여부.
[[Block]] Shared Data Block event가 operate하는 block.
[[ByteIndex]] non-negative integer [[Block]]에서 write의 byte address.
[[ElementSize]] non-negative integer write의 size.
[[Payload]] byte valuesList 다른 events가 read할 byte valuesList.
Table 99: ReadModifyWriteSharedMemory Event Fields
Field Name Value Meaning
[[Order]] seq-cst Read-modify-write events는 항상 sequentially consistent합니다.
[[NoTear]] true Read-modify-write events는 tear될 수 없습니다.
[[Block]] Shared Data Block event가 operate하는 block.
[[ByteIndex]] non-negative integer [[Block]]에서 read-modify-write의 byte address.
[[ElementSize]] non-negative integer read-modify-write의 size.
[[Payload]] byte valuesList [[ModifyOp]]에 passed될 byte valuesList.
[[ModifyOp]] read-modify-write modification function read byte valuesList[[Payload]]로부터 modified byte valuesList를 반환하는 Abstract Closure.

Shared Data Block events는 abstract operations 또는 Atomics object의 methods에 의해 candidate execution Agent Events Records에 introduced됩니다. 일부 operations는 또한 fields가 없고 other events의 permitted orderings를 직접 constrain하기 위해서만 존재하는 Synchronize events를 introduce합니다. 그리고 마지막으로 host-specific events가 있습니다. Memory event는 Shared Data Block event, Synchronize event, 또는 그러한 host-specific event 중 하나입니다.

Shared Data Block event ememory rangee.[[ByteIndex]](inclusive)에서 e.[[ByteIndex]] + e.[[ElementSize]](exclusive)까지 interval의 all integers의 Set으로 둔다. 두 events가 같은 [[Block]], [[ByteIndex]], 및 [[ElementSize]]를 가질 때 두 events의 memory ranges는 equal입니다. 두 events가 같은 [[Block]]을 가지고, ranges가 equal이 아니며, 그 intersection이 non-empty일 때 두 events의 memory ranges는 overlapping합니다. 두 events가 같은 [[Block]]을 가지지 않거나 그 ranges가 equal도 overlapping도 아닐 때 두 events의 memory ranges는 disjoint입니다.

Note 2

accounted for되어야 하는 host-specific synchronizing events의 examples는 다음과 같습니다: 한 agent에서 다른 agent로 SharedArrayBuffer를 sending하는 것(예: browser에서 postMessage), agents를 starting 및 stopping하는 것, 그리고 shared memory 이외의 channels를 통해 agent cluster 내에서 communicating하는 것. particular execution execution에 대해, 이러한 events는 hosthost-synchronizes-with strict partial order를 통해 제공합니다. 또한 hostsis-agent-order-before Relation에 participate하기 위해 host-specific synchronizing events를 execution.[[EventList]]에 add할 수 있습니다.

Events는 아래에 defined된 relations에 의해 candidate executions 내에서 ordered됩니다.

29.2 Agent Events Records

Agent Events Record는 다음 fields를 가진 Record입니다.

Table 100: Agent Events Record Fields
Field Name Value Meaning
[[AgentSignifier]] agent signifier evaluation이 이 ordering을 result한 agent.
[[EventList]] Memory eventsList Events는 evaluation 중 list에 appended됩니다.
[[AgentSynchronizesWith]] Synchronize events의 pairs의 List operational semantics에 의해 introduced된 Synchronize relationships.

29.3 Chosen Value Records

Chosen Value Record는 다음 fields를 가진 Record입니다.

Table 101: Chosen Value Record Fields
Field Name Value Meaning
[[Event]] Shared Data Block event 이 chosen value에 대해 introduced된 ReadSharedMemory 또는 ReadModifyWriteSharedMemory event.
[[ChosenValue]] byte valuesList evaluation 중 nondeterministically chosen된 bytes.

29.4 Candidate Executions

agent cluster의 evaluation의 candidate execution은 다음 fields를 가진 Record입니다.

Table 102: Candidate Execution Record Fields
Field Name Value Meaning
[[EventsRecords]] Agent Events RecordsList agent를 evaluation 중 appended된 Memory eventsLists에 maps합니다.
[[ChosenValues]] Chosen Value RecordsList ReadSharedMemory 또는 ReadModifyWriteSharedMemory events를 evaluation 중 chosen된 byte valuesList에 maps합니다.

empty candidate execution은 fields가 empty Lists인 candidate execution Record입니다.

29.5 Memory Model의 Abstract Operations

29.5.1 EventSet ( execution )

The abstract operation EventSet takes argument execution (a candidate execution) and returns a Set of Memory events. It performs the following steps when called:

  1. events를 empty Set으로 둔다.
  2. execution.[[EventsRecords]]의 각 Agent Events Record eventsRecord에 대해, 다음을 수행한다.
    1. eventsRecord.[[EventList]]의 각 Memory event event에 대해, 다음을 수행한다.
      1. eventevents에 Add한다.
  3. events를 반환한다.

29.5.2 SharedDataBlockEventSet ( execution )

The abstract operation SharedDataBlockEventSet takes argument execution (a candidate execution) and returns a Set of Shared Data Block events. It performs the following steps when called:

  1. events를 empty Set으로 둔다.
  2. EventSet(execution)의 각 Memory event event에 대해, 다음을 수행한다.
    1. eventShared Data Block event이면, eventevents에 add한다.
  3. events를 반환한다.

29.5.3 HostEventSet ( execution )

The abstract operation HostEventSet takes argument execution (a candidate execution) and returns a Set of Memory events. It performs the following steps when called:

  1. EventSet(execution)의 elements 중 SharedDataBlockEventSet(execution)에 있지 않은 모든 elements를 포함하는 new Set을 반환한다.

29.5.4 ComposeWriteEventBytes ( execution, byteIndex, writes )

The abstract operation ComposeWriteEventBytes takes arguments execution (a candidate execution), byteIndex (a non-negative integer), and writes (a List of either WriteSharedMemory or ReadModifyWriteSharedMemory events) and returns a List of byte values. It performs the following steps when called:

  1. byteLocationbyteIndex로 둔다.
  2. bytesRead를 new empty List로 둔다.
  3. writes의 각 element writeEvent에 대해, 다음을 수행한다.
    1. Assert: writeEvent는 its memory range 안에 byteLocation을 가진다.
    2. payloadIndexbyteLocation - writeEvent.[[ByteIndex]]로 둔다.
    3. writeEventWriteSharedMemory event이면, 다음을 수행한다.
      1. bytewriteEvent.[[Payload]][payloadIndex]로 둔다.
    4. Else,
      1. Assert: writeEventReadModifyWriteSharedMemory event이다.
      2. bytesValueOfReadEvent(execution, writeEvent)로 둔다.
      3. bytesModifiedwriteEvent.[[ModifyOp]](bytes, writeEvent.[[Payload]])로 둔다.
      4. bytebytesModified[payloadIndex]로 둔다.
    5. bytebytesRead에 Append한다.
    6. byteLocationbyteLocation + 1로 설정한다.
  4. bytesRead를 반환한다.
Note 1

read-modify-write modification [[ModifyOp]]ReadModifyWriteSharedMemory events를 introduce하는 Atomics object의 function properties에 의해 given됩니다.

Note 2

이 abstract operation은 write eventsListbyte valuesList로 composes합니다. 이는 ReadSharedMemoryReadModifyWriteSharedMemory events의 event semantics에서 사용됩니다.

29.5.5 ValueOfReadEvent ( execution, readEvent )

The abstract operation ValueOfReadEvent takes arguments execution (a candidate execution) and readEvent (a ReadSharedMemory or ReadModifyWriteSharedMemory event) and returns a List of byte values. It performs the following steps when called:

  1. writesexecution 안의 reads-bytes-from(readEvent)으로 둔다.
  2. Assert: writesreadEvent.[[ElementSize]]와 같은 length를 가진 WriteSharedMemory 또는 ReadModifyWriteSharedMemory events의 List이다.
  3. ComposeWriteEventBytes(execution, readEvent.[[ByteIndex]], writes)를 반환한다.

29.6 Candidate Executions의 Relations

다음 relations와 mathematical functions는 particular candidate execution에 대해 parameterized되고 its Memory events를 order합니다.

29.6.1 is-agent-order-before

candidate execution execution에 대해, 그 is-agent-order-before Relation은 다음을 satisfies하는 Memory events에 대한 least Relation입니다.

  • 이벤트 eventAeventB에 대해, execution.[[EventsRecords]] 안에 어떤 Agent Events Record eventsRecord가 있어서 eventsRecord.[[EventList]]eventAeventB를 모두 포함하고, eventAeventsRecord.[[EventList]]List 순서에서 eventB보다 앞에 있으면, eventAexecution에서 eventB보다 is-agent-order-before이다.
Note

agent는 evaluation 중 per-agent strict total order로 events를 introduce합니다. 이것은 그러한 strict total orders의 union입니다.

29.6.2 reads-bytes-from

candidate execution execution에 대해, 그 reads-bytes-from function은 SharedDataBlockEventSet(execution)의 Memory eventsSharedDataBlockEventSet(execution) 안의 events의 Lists에 mapping하는 mathematical function이며 다음 conditions를 satisfies합니다.

candidate execution은 항상 reads-bytes-from function을 admits합니다.

29.6.3 reads-from

candidate execution execution에 대해, 그 reads-from Relation은 다음을 satisfies하는 Memory events에 대한 least Relation입니다.

  • events readEventwriteEvent에 대해, SharedDataBlockEventSet(execution)이 readEventwriteEvent 둘 다를 contain하고 execution 안의 reads-bytes-from(readEvent)이 writeEvent를 contain하면, readEventexecution에서 writeEvent로부터 reads-from합니다.

29.6.4 host-synchronizes-with

candidate execution execution에 대해, 그 host-synchronizes-with Relation은 적어도 다음을 satisfies하는 host-specific Memory events에 대한 host-provided strict partial order입니다.

  • eventAexecution에서 eventB와 host-synchronizes-with이면, HostEventSet(execution)은 eventAeventB를 contain합니다.
  • execution에서 host-synchronizes-with와 is-agent-order-before의 union에는 cycle이 없습니다.
Note 1

candidate execution execution 안의 두 host-specific events eventAeventB에 대해, eventAexecution에서 eventB와 host-synchronizes-with이면 eventAexecution에서 eventB보다 happens-before임을 implies합니다.

Note 2

Relationhost가 HTML workers 사이의 postMessage와 같은 additional synchronization mechanisms를 제공할 수 있게 합니다.

29.6.5 synchronizes-with

candidate execution execution에 대해, 그 synchronizes-with Relation은 다음을 satisfies하는 Memory events에 대한 least Relation입니다.

  • events readEventwriteEvent에 대해, readEventexecution에서 writeEvent로부터 reads-from하고, readEvent.[[Order]]seq-cst이고, writeEvent.[[Order]]seq-cst이고, readEventwriteEvent가 equal memory ranges를 가지면, writeEventexecution에서 readEvent와 synchronizes-with합니다.
  • execution.[[EventsRecords]]의 각 element eventsRecord에 대해, 다음은 true입니다.
    • events eventAeventB에 대해, eventsRecord.[[AgentSynchronizesWith]]가 (eventA, eventB)를 contain하면, eventAexecution에서 eventB와 synchronizes-with합니다.
  • 이벤트 eventAeventB에 대해, execution에서 eventAeventBhost-synchronizes-with이면, execution에서 eventAeventB와 synchronizes-with이다.
Note 1

memory model literature의 convention으로 인해, candidate execution execution에서 read eventswrite events와 synchronizes-with하는 대신 write eventsread events와 synchronizes-with합니다.

Note 2

candidate execution execution에서 init events는 이 Relation에 participate하지 않고 대신 happens-before에 의해 directly constrained됩니다.

Note 3

candidate execution execution에서 reads-from에 의해 related된 모든 seq-cst events가 synchronizes-with에 의해 related되는 것은 아닙니다. equal memory ranges도 가지는 events만 synchronizes-with에 의해 related됩니다.

Note 4

candidate execution execution 안의 Shared Data Block events readEventwriteEvent에 대해, writeEventreadEvent와 synchronizes-with하면, readEventwriteEvent 이외의 other writes로부터 reads-from할 수 있습니다.

29.6.6 happens-before

candidate execution execution에 대해, 그 happens-before Relation은 다음을 satisfies하는 Memory events에 대한 least Relation입니다.

  • events eventAeventB에 대해, 다음 conditions 중 any가 true이면 eventAexecution에서 eventB보다 happens-before입니다.

    • eventAexecution에서 eventB보다 is-agent-order-before이다.
    • eventAexecution에서 eventBsynchronizes-with한다.
    • SharedDataBlockEventSet(execution)이 eventAeventB 둘 다를 contain하고, eventA.[[Order]]init이며, eventAeventB가 overlapping memory ranges를 가진다.
    • eventAexecution에서 eventC보다 happens-before이고 eventCeventB보다 happens-before인 event eventC가 있다.
Note

happens-before는 agent-order의 superset이므로, candidate execution은 ECMAScript의 single-thread evaluation semantics와 consistent합니다.

29.7 Valid Executions의 Properties

29.7.1 Valid Chosen Reads

candidate execution execution은 다음 algorithm이 true를 반환하면 valid chosen reads를 가집니다.

  1. SharedDataBlockEventSet(execution)의 각 ReadSharedMemory 또는 ReadModifyWriteSharedMemory event readEvent에 대해, 다음을 수행한다.
    1. chosenValueRecord[[Event]] field가 readEventexecution.[[ChosenValues]]의 element로 둔다.
    2. chosenValuechosenValueRecord.[[ChosenValue]]로 둔다.
    3. readValueValueOfReadEvent(execution, readEvent)로 둔다.
    4. chosenLengthchosenValue 안의 elements의 number로 둔다.
    5. readLengthreadValue 안의 elements의 number로 둔다.
    6. chosenLengthreadLength이면, 다음을 수행한다.
      1. false를 반환한다.
    7. 0(inclusive)에서 chosenLength(exclusive)까지의 interval 안의 some integer i에 대해 chosenValue[i] ≠ readValue[i]이면, 다음을 수행한다.
      1. false를 반환한다.
  2. true를 반환한다.

29.7.2 Coherent Reads

candidate execution execution은 다음 algorithm이 true를 반환하면 coherent reads를 가집니다.

  1. SharedDataBlockEventSet(execution)의 각 ReadSharedMemory 또는 ReadModifyWriteSharedMemory event readEvent에 대해, 다음을 수행한다.
    1. writesexecution 안의 reads-bytes-from(readEvent)으로 둔다.
    2. byteLocationreadEvent.[[ByteIndex]]로 둔다.
    3. writes의 각 element writeEvent에 대해, 다음을 수행한다.
      1. readEventexecution에서 writeEvent보다 happens-before이면, 다음을 수행한다.
        1. false를 반환한다.
      2. byteLocation을 its memory range 안에 가지는 WriteSharedMemory 또는 ReadModifyWriteSharedMemory event value가 존재하고, writeEventexecution에서 value보다 happens-before이며 valueexecution에서 readEvent보다 happens-before이면, 다음을 수행한다.
        1. false를 반환한다.
      3. byteLocationbyteLocation + 1로 설정한다.
  2. true를 반환한다.

29.7.3 Tear Free Reads

candidate execution execution은 다음 algorithm이 true를 반환하면 tear free reads를 가집니다.

  1. SharedDataBlockEventSet(execution)의 각 ReadSharedMemory 또는 ReadModifyWriteSharedMemory event readEvent에 대해, 다음을 수행한다.
    1. readEvent.[[NoTear]]true이면, 다음을 수행한다.
      1. Assert: readEvent.[[ByteIndex]]readEvent.[[ElementSize]]로 나눈 remainder는 0이다.
      2. readEventexecution에서 writeEvent로부터 reads-from하고 writeEvent.[[NoTear]]true인 각 Memory event writeEvent에 대해, 다음을 수행한다.
        1. readEventwriteEvent가 equal memory ranges를 가지고, valuewriteEvent가 equal memory ranges를 가지고, value.[[NoTear]]true이고, writeEventvalue가 같은 Shared Data Block event가 아니며, readEventexecution에서 value로부터 reads-from하는 Memory event value가 존재하면, 다음을 수행한다.
          1. false를 반환한다.
  2. true를 반환한다.
Note

Shared Data Block event[[NoTear]] field는 integer TypedArray에 accessing하여 introduced된 경우 true이고, floating point TypedArray 또는 DataView에 accessing하여 introduced된 경우 false입니다.

직관적으로, 이 requirement는 memory rangeinteger TypedArray를 통해 aligned fashion으로 accessed될 때, 그 range에 대한 single write event가 equal ranges를 가진 other write eventsdata race에서 “win”해야 한다는 뜻입니다. 더 정확히는, 이 requirement는 aligned read event가 equal ranges를 모두 가진 multiple different write events의 bytes로 composed된 value를 read할 수 없다는 뜻입니다. 그러나 aligned read event가 overlapping ranges를 가진 multiple write events로부터 read하는 것은 가능합니다.

29.7.4 Sequentially Consistent Atomics

candidate execution execution에 대해, is-memory-order-beforeEventSet(execution) 안의 모든 Memory eventsstrict total order이며 다음을 satisfies합니다.

candidate execution이 is-memory-order-before Relation을 admits하면 sequentially consistent atomics를 가집니다.

Note 3

is-memory-order-before가 EventSet(execution) 안의 모든 events를 포함하지만, execution에서 happens-before 또는 synchronizes-with에 의해 constrained되지 않는 것들은 order 안의 anywhere에서 occur하는 것이 allowed됩니다.

29.7.5 Valid Executions

candidate execution execution은 다음 모두가 true이면 valid execution(또는 simply execution)입니다.

모든 programs는 적어도 하나의 valid execution을 가집니다.

29.8 Races

execution executionSharedDataBlockEventSet(execution)에 contained된 events eventAeventB에 대해, 다음 algorithm이 true를 반환하면 eventAeventBrace 안에 있습니다.

  1. eventAeventB가 같은 Shared Data Block event가 아니면, 다음을 수행한다.
    1. eventAexecution에서 eventB보다 happens-before이고 eventBexecution에서 eventA보다 happens-before라는 것이 둘 다 true인 경우가 아니면, 다음을 수행한다.
      1. eventAWriteSharedMemory 또는 ReadModifyWriteSharedMemory event 중 하나이고, eventBWriteSharedMemory 또는 ReadModifyWriteSharedMemory event 중 하나이며, eventAeventB가 disjoint memory ranges를 가지지 않으면, 다음을 수행한다.
        1. true를 반환한다.
      2. eventAexecution에서 eventB로부터 reads-from하거나 eventBexecution에서 eventA로부터 reads-from하면, 다음을 수행한다.
        1. true를 반환한다.
  2. false를 반환한다.

29.9 Data Races

execution executionSharedDataBlockEventSet(execution)에 contained된 events eventAeventB에 대해, 다음 algorithm이 true를 반환하면 eventAeventBdata race 안에 있습니다.

  1. eventAeventBexecution에서 race 안에 있으면, 다음을 수행한다.
    1. eventA.[[Order]]seq-cst가 아니거나 eventB.[[Order]]seq-cst가 아니면, 다음을 수행한다.
      1. true를 반환한다.
    2. eventAeventB가 overlapping memory ranges를 가지면, 다음을 수행한다.
      1. true를 반환한다.
  2. false를 반환한다.

29.10 Data Race Freedom

execution executionSharedDataBlockEventSet(execution) 안에 data race 안에 있는 두 events가 없으면 data race free입니다.

program은 all its executions가 data race free이면 data race free입니다.

memory model은 data race free programs에 대해 all events의 sequential consistency를 guarantee합니다.

29.11 Shared Memory Guidelines

Note 1

다음은 shared memory로 작업하는 ECMAScript programmers를 위한 guidelines입니다.

programs는 data race free로 유지하는 것을 recommend합니다. 즉, 같은 memory location에 concurrent non-atomic operations가 존재할 수 없도록 만듭니다. Data race free programs는 각 agent의 evaluation semantics 안의 각 step이 서로 interleaved되는 interleaving semantics를 가집니다. data race free programs에 대해서는 memory model의 details를 이해할 필요가 없습니다. details는 ECMAScript를 더 잘 작성하는 데 도움이 되는 intuition을 build할 가능성이 낮습니다.

더 일반적으로, program이 data race free가 아니더라도 atomic operations가 any data races에 involved되지 않고 race하는 operations가 모두 같은 access size를 가지는 한 predictable behaviour를 가질 수 있습니다. atomics가 races에 involved되지 않도록 arrange하는 simplest way는 atomic 및 non-atomic operations에 different memory cells가 사용되도록 ensure하고, different sizes의 atomic accesses가 동시에 같은 cells에 access하는 데 사용되지 않도록 하는 것입니다. Effectively, program은 shared memory를 가능한 한 strongly typed로 treat해야 합니다. 여전히 race하는 non-atomic accesses의 ordering과 timing에 depend할 수는 없지만, memory가 strongly typed로 treated되면 racing accesses는 “tear”되지 않습니다(bits of their values will not be mixed).

Note 2

다음은 shared memory를 사용하는 programs에 대한 compiler transformations를 작성하는 ECMAScript implementers를 위한 guidelines입니다.

multi-agent setting에서 각 agent의 performance가 single-agent setting에서와 as good as it would be 되도록, single-agent setting에서 valid한 대부분의 program transformations를 multi-agent setting에서도 allow하는 것이 desirable합니다. 이러한 transformations는 often judge하기 어렵습니다. 우리는 normative로 taken되도록 intended된(즉 memory model에 의해 implied되거나 memory model이 implies하는 것보다 stronger인) program transformations에 관한 몇 가지 rules를 outline하지만, 이는 exhaustive하지 않을 가능성이 큽니다. 이러한 rules는 is-agent-order-before Relation을 구성하는 Memory events의 introductions에 precede하는 program transformations에 apply되도록 intended됩니다.

agent-order slice를 single agent에 pertaining하는 is-agent-order-before Relation의 subset으로 둔다.

read eventpossible read values를 모든 valid executions 전반에서 그 event에 대한 ValueOfReadEvent의 모든 values의 set으로 둔다.

shared memory가 없는 경우 valid한 agent-order slice의 any transformation은 shared memory가 있는 경우에도 valid하며, 다음 exceptions가 있습니다.

  • Atomics are carved in stone: Program transformations는 [[Order]]seq-cst인 any Shared Data Block eventsis-agent-order-before Relation에서 removed되게 하거나, 서로에 대해 reordered되게 하거나, [[Order]]unordered인 events에 대해 agent-order slice 안에서 reordered되게 해서는 안 됩니다.

    (In practice, reorderings에 대한 prohibition은 compiler가 inter-agent program analysis가 없는 경우 어차피 보통 assume해야 하는 것처럼, every seq-cst operation이 synchronization이고 final is-memory-order-before Relation에 included된다고 assume하도록 force합니다. 또한 memory-order에 대한 callee의 effects가 unknown인 every call이 seq-cst operations를 contain할 수 있다고 compiler가 assume하도록 force합니다.)

  • Reads must be stable: Any given shared memory read는 execution 안에서 single value만 observe해야 합니다.

    (예를 들어, program에서 semantically single read인 것이 multiple times executed되면, program은 subsequently read된 values 중 하나만 observe하도록 allowed됩니다. rematerialization으로 known된 transformation은 이 rule을 violate할 수 있습니다.)

  • Writes must be stable: shared memory에 대한 모든 observable writes는 execution 안의 program semantics로부터 follow해야 합니다.

    (예를 들어, transformation은 larger location에 대한 read-modify-write operations를 사용해 smaller datum을 write하거나, program이 write할 수 없었던 value를 memory에 write하거나, read한 location이 read 후 다른 agent에 의해 overwritten될 수 있었다면 그 just-read value를 그 location에 다시 write하는 것과 같은 certain observable writes를 introduce해서는 안 됩니다.)

  • Possible read values must be non-empty: Program transformations는 shared memory read의 possible read values가 empty가 되도록 할 수 없습니다.

    (Counterintuitively, 이 rule은 effect적으로 writes에 대한 transformations를 restrict합니다. 왜냐하면 writes는 read events에 의해 read되는 한에서 memory model 안에서 force를 가지기 때문입니다. 예를 들어, writes는 두 seq-cst operations 사이에서 moved 및 coalesced되고 sometimes reordered될 수 있지만, transformation은 location을 updates하는 모든 write를 remove해서는 안 됩니다; some write는 preserved되어야 합니다.)

valid로 remain하는 transformations의 examples는 다음과 같습니다: 같은 location으로부터 multiple non-atomic reads를 merging하는 것, non-atomic reads를 reordering하는 것, speculative non-atomic reads를 introducing하는 것, 같은 location에 대한 multiple non-atomic writes를 merging하는 것, different locations에 대한 non-atomic writes를 reordering하는 것, 그리고 termination에 영향을 미치더라도 non-atomic reads를 loops 밖으로 hoisting하는 것. 일반적으로 aliased TypedArrays는 locations가 different임을 prove하기 어렵게 만든다는 점에 유의하십시오.

Note 3

다음은 shared memory accesses에 대한 machine code를 generating하는 ECMAScript implementers를 위한 guidelines입니다.

ARM 또는 Power의 memory models보다 no weaker인 memory models를 가진 architectures에서는, non-atomic stores와 loads가 target architecture의 bare stores와 loads로 compiled될 수 있습니다. Atomic stores와 loads는 sequential consistency를 guarantee하는 instructions로 compiled down될 수 있습니다. such instructions가 없으면, bare store 또는 load의 양쪽에 barriers를 placing하는 것과 같은 memory barriers가 employed되어야 합니다. Read-modify-write operations는 x86의 LOCK-prefixed instructions, ARM의 load-exclusive/store-exclusive instructions, Power의 load-link/store-conditional instructions와 같은 target architecture의 read-modify-write instructions로 compiled될 수 있습니다.

Specifically, memory model은 다음과 같은 code generation을 allow하도록 intended됩니다.

  • program 안의 every atomic operation은 necessary하다고 assumed됩니다.
  • Atomic operations는 서로 또는 non-atomic operations와 never rearranged됩니다.
  • Functions는 항상 atomic operations를 perform한다고 assumed됩니다.
  • Atomic operations는 larger data에 대한 read-modify-write operations로 implemented되지 않고, platform이 appropriate size의 atomic operations를 가지지 않는 경우 non-lock-free atomics로 implemented됩니다. (우리는 already every platform이 every interesting size의 normal memory access operations를 가진다고 assume합니다.)

Naive code generation은 다음 patterns를 사용합니다:

  • Regular loads와 stores는 single load 및 store instructions로 compile됩니다.
  • Lock-free atomic loads와 stores는 full(sequentially consistent) fence, regular load 또는 store, 그리고 full fence로 compile됩니다.
  • Lock-free atomic read-modify-write accesses는 full fence, atomic read-modify-write instruction sequence, 그리고 full fence로 compile됩니다.
  • Non-lock-free atomics는 spinlock acquire, full fence, 일련의 non-atomic load 및 store instructions, full fence, 그리고 spinlock release로 compile됩니다.

그 mapping은 memory range에 대한 atomic operation이 non-atomic write 또는 different size의 atomic operation과 race하지 않는 한 correct합니다. 그러나 그것이 all we need입니다: memory model은 race에 involved된 atomic operations를 effect적으로 non-atomic status로 demotes합니다. 반면 naive mapping은 꽤 strong합니다: 이는 atomic operations가 sequentially consistent fences로 사용되는 것을 allow하지만, memory model은 실제로 이를 guarantee하지 않습니다.

those basic patterns에 대한 local improvements도 memory model의 constraints에 subject하여 allowed됩니다. 예를 들어:

  • redundant fences를 remove하는 obvious platform-dependent improvements가 있습니다. 예를 들어, x86에서는 lock-free atomic loads와 stores 주변의 fences를 store 뒤에 following하는 fence를 제외하고 항상 omitted할 수 있으며, lock-free read-modify-write instructions에는 fence가 필요하지 않습니다. 이것들은 모두 LOCK-prefixed instructions를 사용하기 때문입니다. many platforms에는 several strengths의 fences가 있고, certain contexts에서는 sequential consistency를 destroying하지 않고 weaker fences가 사용될 수 있습니다.
  • 대부분의 modern platforms는 ECMAScript atomics가 required하는 모든 data sizes에 대해 lock-free atomics를 support합니다. Non-lock-free atomics가 needed되면, atomic operation의 body를 surrounding하는 fences는 보통 lock 및 unlock steps에 folded될 수 있습니다. non-lock-free atomics에 대한 simplest solution은 SharedArrayBuffer마다 single lock word를 가지는 것입니다.
  • 또한 더 complicated platform-dependent local improvements가 있으며, 이는 some code analysis를 require합니다. 예를 들어, two back-to-back fences는 often single fence와 같은 effect를 가지므로, code가 two atomic operations in sequence에 대해 generated되면 single fence만 them 사이를 separate하면 됩니다. x86에서는 atomic stores를 separating하는 single fence조차 omitted될 수 있습니다. store 뒤에 following하는 fence는 store를 subsequent load와 separate하는 데만 needed되기 때문입니다.