You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[js-api] Add support for resizable ArrayBuffers and growable SharedArrayBuffers (#208)
* Merge remote-tracking branch 'syg/spec/rab-js-api-integration' into add-RAB-support
This adds support for ResizableArrayBuffers and GrowableSharedArrayBuffers,
by adding and extending the changes in rab-js-api-integration [1]
to include cases for SharedArrayBuffer.
Also adds a TODO for the steps of the new HostGrowSharedArrayBuffer algorithm.
All this could potentially be refactored to be more concise.
[1] WebAssembly/spec#1300
* Add WIP algorithm for HostGrowSharedArrayBuffer and stylistic changes
to match the style in the spec PR adding resizable buffers.
* Fixed HostGrowSharedArrayBuffer algorithm notation, added TODOs to not forget to check these cases.
* Moved TODO item to the correct location.
1. Let |buffer| be a new {{ArrayBuffer}} with the internal slots \[[ArrayBufferData]], \[[ArrayBufferByteLength]], and \[[ArrayBufferDetachKey]].
629
+
1. Set |buffer|.\[[ArrayBufferData]] to |block|.
630
+
1. Set |buffer|.\[[ArrayBufferByteLength]] to the length of |block|.
631
+
1. Set |buffer|.\[[ArrayBufferDetachKey]] to "WebAssembly.Memory".
632
+
1. Return |buffer|.
633
+
</div>
634
+
635
+
Note: (TODO) Check whether only SharedArrayBuffers need integrity level "frozen" (see the Threads Proposal Overview).
636
+
637
+
To create a resizable memory buffer we perform the same steps as above, but also setting the buffer's maximum size.
638
+
639
+
<div algorithm>
640
+
To <dfn>create a resizable memory buffer</dfn> from a [=memory address=] |memaddr| and a |maxsize|, perform the following steps:
611
641
612
642
1. Let |block| be a [=Data Block=] which is [=identified with=] the underlying memory of |memaddr|.
643
+
1. Let |length| be the length of |block|.
644
+
1. If |maxsize| > (65536 × 65536),
645
+
1. Throw a {{RangeError}} exception.
613
646
1. If |block| is a [=Shared Data Block=],
614
-
1. Let |buffer| be a new {{SharedArrayBuffer}} whose \[[ArrayBufferData]] is |block| and \[[ArrayBufferByteLength]] is set to the length of |block|.
647
+
1. Let |buffer| be a new {{SharedArrayBuffer}} with the internal slots \[[ArrayBufferData]], \[[ArrayBufferByteLength]], and \[[ArrayBufferMaxByteLength]].
648
+
1. Set |buffer|.\[[ArrayBufferData]] to |block|.
649
+
1. Set |buffer|.\[[ArrayBufferByteLength]] to the length of |block|.
650
+
1. Set |buffer|.\[[ArrayBufferMaxByteLength]] to |maxsize|.
1. Let |buffer| be a new {{ArrayBuffer}} whose \[[ArrayBufferData]] is |block| and \[[ArrayBufferByteLength]] is set to the length of |block|.
653
+
1. Let |buffer| be a new {{ArrayBuffer}} with the internal slots \[[ArrayBufferData]], \[[ArrayBufferByteLength]], \[[ArrayBufferMaxByteLength]], and \[[ArrayBufferDetachKey]].
654
+
1. Set |buffer|.\[[ArrayBufferData]] to |block|.
655
+
1. Set |buffer|.\[[ArrayBufferByteLength]] to |length|.
656
+
1. Set |buffer|.\[[ArrayBufferMaxByteLength]] to |maxsize|.
618
657
1. Set |buffer|.\[[ArrayBufferDetachKey]] to "WebAssembly.Memory".
619
658
1. Return |buffer|.
620
659
</div>
@@ -623,7 +662,7 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each
623
662
To <dfn>initialize a memory object</dfn> |memory| from a [=memory address=] |memaddr|, perform the following steps:
624
663
1. Let |map| be the [=surrounding agent=]'s associated [=Memory object cache=].
1. Set **this**.\[[BufferObject]] to |resizableBuffer|.
777
+
1. Return |resizableBuffer|.
778
+
</div>
779
+
780
+
{{ArrayBuffer}} and {{SharedArrayBuffer}} objects returned by a {{Memory}} object must have size that is a multiple of a WebAssembly [=page size=] (the constant 65536). For this reason [=HostResizeArrayBuffer=] and [=HostGrowSharedArrayBuffer=] are redefined as follows.
781
+
782
+
<div algorithm>
783
+
The <dfn>abstract operation [=HostResizeArrayBuffer=]</dfn> takes arguments an {{ArrayBuffer}} |buffer| and |newLength|. It performs the following steps when called.
784
+
785
+
1. If |buffer|.\[[ArrayBufferDetachKey]] is "WebAssembly.Memory",
786
+
1. Let |map| be the [=surrounding agent=]'s associated [=Memory object cache=].
787
+
1. Assert: |buffer| is the \[[BufferObject]] of exactly one value in |map|.
788
+
1. [=map/iterate|For each=] |memaddr| → |mem| in |map|,
789
+
1. If [=SameValue=](mem.\[[BufferObject]], |buffer|) is true,
790
+
1. Assert: |buffer|.\[[ArrayBufferByteLength]] modulo 65536 is 0.
791
+
1. Let |lengthDelta| be |newLength| - |buffer|.\[[ArrayBufferByteLength]].
792
+
1. If |lengthDelta| < 0 or |lengthDelta| modulo 65536 is not 0,
793
+
1. Throw a {{RangeError}} exception.
794
+
1. Let |delta| be |lengthDelta| ÷ 65536.
795
+
1. [=grow the memory buffer|Grow the memory buffer=] associated with |memaddr| by |delta|.
796
+
1. Return handled.
797
+
1. Otherwise, return unhandled.
689
798
</div>
690
799
800
+
<div algorithm>
801
+
The <dfn>abstract operation [=HostGrowSharedArrayBuffer=]</dfn> takes arguments a {{SharedArrayBuffer}} |buffer| and |newLength|. It performs the following steps when called.
802
+
803
+
1. Let |map| be the [=surrounding agent=]'s associated [=Memory object cache=].
804
+
1. Assert: |buffer| is the \[[BufferObject]] of exactly one value in |map|.
805
+
1. [=map/iterate|For each=] |memaddr| → |mem| in |map|,
806
+
1. If [=SameValue=](mem.\[[BufferObject]], |buffer|) is true,
807
+
1. Assert: |buffer|.\[[ArrayBufferByteLength]] modulo 65536 is 0.
808
+
1. Let |lengthDelta| be |newLength| - |buffer|.\[[ArrayBufferByteLength]].
809
+
1. If |lengthDelta| < 0 or |lengthDelta| modulo 65536 is not 0,
810
+
1. Throw a {{RangeError}} exception.
811
+
1. Let |delta| be |lengthDelta| ÷ 65536.
812
+
1. [=grow the memory buffer|Grow the memory buffer=] associated with |memaddr| by |delta|.
813
+
1. If |newLength| < |buffer|.\[[ArrayBufferByteLength]] or |newLength| > |buffer|.\[[ArrayBufferMaxByteLength]], throw a {{RangeError}} exception.
814
+
1. Let |agentRecord| be the surrounding agent's [=Agent Record=].
815
+
1. Let |isLittleEndian| be |agentRecord|.\[[LittleEndian]] .
816
+
1. Let |event| be an implementation defined [=ReadModifyWriteSharedMemory=] event, whose \[[Order]] is "SeqCst", \[[Payload]] is [§NumericToRawBytes$](Bigint, |newLength|, |isLittleEndian|), \[[Block]] is |buffer|.\[[ArrayBufferByteLengthData]], \[[ByteIndex]] is 0, and \[[ElementSize]] is 8.
817
+
1. Let |eventsRecord| be the [=Agent Events Record|EventsRecord=] in |agentRecord|.\[[CandidateExecution]].\[[EventsRecords]] that corresponds to the surrounding agent's signifier |agentRecord|.\[[Signifier]].
818
+
1. Append |event| to |eventsRecord|.\[[EventsList]].
819
+
1. Return handled.
820
+
</div>
821
+
822
+
Note: (TODO) Check the error case of memory.grow on the Wasm side.
823
+
691
824
<div algorithm>
692
825
The getter of the <dfn attribute for="Memory">buffer</dfn> attribute of {{Memory}} perfoms the following steps:
0 commit comments