Skip to content
This repository has been archived by the owner on Jan 25, 2022. It is now read-only.

Discussion: Implications of shared memory for DOM/browser APIs #38

Open
lars-t-hansen opened this issue Oct 13, 2015 · 16 comments
Open

Comments

@lars-t-hansen
Copy link
Collaborator

In an aside in Issue #1, @jfbastien writes:

"How does SAB affect the web API surface area? Most APIs weren't designed to be called from multiple threads, and have led to exploits in the past e.g. (pwn2own 2015)[https://code.google.com/p/chromium/issues/detail?id=468936]."

It's probably open to discussion exactly what that question means, whether it pertains to confusing shared and unshared memory and thus exposing oneself to TOCTOTOU bugs, or if it pertains to thread-safety of DOM APIs in general.

For the former issue, Firefox has not really had to confront it because there has been a separate type hierarchy for shared views (SharedInt32Array, etc), thus there has been no space for confusion internally in the browser - everyone has had to opt in to shared memory, and that code can be reviewed carefully when that happens. There's some experimental code for WebGL that is about to land. Going forward, Firefox will implement the specification and get rid of the shared views. Internally in DOM, memory will be represented as a fat pointer that does not allow shared memory to be used accidentally in order to prevent this problem, but it's early days still for that.

For the latter issue, this seems like a problem for any API accessible from a worker as well as from the main thread, so is not really specific to SAB.

(More comments / thoughts are welcome.)

@jfbastien
Copy link
Contributor

FWIW our plans will involve heavy use of tsan.

@binji
Copy link

binji commented Dec 8, 2015

I recently grepped through Blink's IDL files for ArrayBufferView (and BufferSource) to find WebAPIs that may be affected. Here's what I found:

FontFace (http://dev.w3.org/csswg/css-font-loading/#fontface-interface)
./Source/core/css/FontFace.idl:44: Constructor(DOMString family, (DOMString or ArrayBuffer or ArrayBufferView) source, optional FontFaceDescriptors descriptors),

FileAPI (https://w3c.github.io/FileAPI)
./Source/core/fileapi/Blob.idl:36: Constructor(sequence<(ArrayBuffer or ArrayBufferView or Blob or DOMString)> blobParts, optional BlobPropertyBag options),
./Source/core/fileapi/File.idl:31: Constructor(sequence<(Blob or DOMString or ArrayBufferView or ArrayBuffer)> fileBits, DOMString fileName, optional FilePropertyBag options),

WebUSB (http://reillyeon.github.io/webusb/#idl-def-usbintransferresult)
./Source/modules/webusb/USBDevice.idl:44: [CallWith=ScriptState] Promise<USBOutTransferResult> controlTransferOut(USBControlTransferParameters setup, optional BufferSource data);
./Source/modules/webusb/USBDevice.idl:47: [CallWith=ScriptState] Promise<USBOutTransferResult> transferOut(octet endpointNumber, BufferSource data);

MediaSource (https://w3c.github.io/media-source/#sourcebuffer)
./Source/modules/mediasource/SourceBuffer.idl:64: [RaisesException] void appendBuffer(ArrayBufferView data);

WebSocket (https://html.spec.whatwg.org/multipage/comms.html#the-websocket-interface)
./Source/modules/websockets/WebSocket.idl:69: [RaisesException] void send(ArrayBufferView data);

WebCrypto (http://www.w3.org/TR/WebCryptoAPI)
./Source/modules/crypto/Crypto.idl:33: [RaisesException, MeasureAs=CryptoGetRandomValues] ArrayBufferView getRandomValues(ArrayBufferView array);
./Source/modules/crypto/SubtleCrypto.idl:47: [CallWith=ScriptState, MeasureAs=SubtleCryptoImportKey] Promise importKey(KeyFormat format, (ArrayBuffer or ArrayBufferView or Dictionary) keyData, AlgorithmIdentifier algorithm, boolean extractable, sequence<KeyUsage> keyUsages);
./Source/modules/crypto/SubtleCrypto.idl:41: [CallWith=ScriptState, MeasureAs=SubtleCryptoEncrypt] Promise encrypt(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource data);
./Source/modules/crypto/SubtleCrypto.idl:42: [CallWith=ScriptState, MeasureAs=SubtleCryptoDecrypt] Promise decrypt(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource data);
./Source/modules/crypto/SubtleCrypto.idl:43: [CallWith=ScriptState, MeasureAs=SubtleCryptoSign] Promise sign(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource data);
./Source/modules/crypto/SubtleCrypto.idl:44: [CallWith=ScriptState, ImplementedAs=verifySignature, MeasureAs=SubtleCryptoVerify] Promise verify(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource signature, BufferSource data);
./Source/modules/crypto/SubtleCrypto.idl:45: [CallWith=ScriptState, MeasureAs=SubtleCryptoDigest] Promise digest(AlgorithmIdentifier algorithm, BufferSource data);
./Source/modules/crypto/SubtleCrypto.idl:52: [CallWith=ScriptState, MeasureAs=SubtleCryptoUnwrapKey] Promise unwrapKey(KeyFormat format, BufferSource wrappedKey, CryptoKey unwrappingKey, AlgorithmIdentifier unwrapAlgorithm, AlgorithmIdentifier unwrappedKeyAlgorithm, boolean extractable, sequence<KeyUsage> keyUsages);

WebGL (http://www.khronos.org/registry/webgl/specs/latest/1.0/)
./Source/modules/webgl/WebGLRenderingContextBase.idl:490: void bufferData(GLenum target, ArrayBufferView data, GLenum usage);
./Source/modules/webgl/WebGLRenderingContextBase.idl:492: void bufferSubData(GLenum target, GLintptr offset, [FlexibleArrayBufferView] ArrayBufferView data);
./Source/modules/webgl/WebGLRenderingContextBase.idl:504: GLsizei width, GLsizei height, GLint border, ArrayBufferView? data);
./Source/modules/webgl/WebGLRenderingContextBase.idl:506: GLsizei width, GLsizei height, GLenum format, ArrayBufferView? data);
./Source/modules/webgl/WebGLRenderingContextBase.idl:599: void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView? pixels);
./Source/modules/webgl/WebGLRenderingContextBase.idl:621: GLenum format, GLenum type, ArrayBufferView? pixels);
./Source/modules/webgl/WebGLRenderingContextBase.idl:641: GLenum format, GLenum type, ArrayBufferView? pixels);
./Source/modules/webgl/WebGLRenderingContextBase.idl:659: void uniform1fv(WebGLUniformLocation? location, [FlexibleArrayBufferView] Float32Array v);
./Source/modules/webgl/WebGLRenderingContextBase.idl:662: void uniform1iv(WebGLUniformLocation? location, [FlexibleArrayBufferView] Int32Array v);
./Source/modules/webgl/WebGLRenderingContextBase.idl:665: void uniform2fv(WebGLUniformLocation? location, [FlexibleArrayBufferView] Float32Array v);
./Source/modules/webgl/WebGLRenderingContextBase.idl:668: void uniform2iv(WebGLUniformLocation? location, [FlexibleArrayBufferView] Int32Array v);
./Source/modules/webgl/WebGLRenderingContextBase.idl:671: void uniform3fv(WebGLUniformLocation? location, [FlexibleArrayBufferView] Float32Array v);
./Source/modules/webgl/WebGLRenderingContextBase.idl:674: void uniform3iv(WebGLUniformLocation? location, [FlexibleArrayBufferView] Int32Array v);
./Source/modules/webgl/WebGLRenderingContextBase.idl:677: void uniform4fv(WebGLUniformLocation? location, [FlexibleArrayBufferView] Float32Array v);
./Source/modules/webgl/WebGLRenderingContextBase.idl:680: void uniform4iv(WebGLUniformLocation? location, [FlexibleArrayBufferView] Int32Array v);
./Source/modules/webgl/WebGL2RenderingContextBase.idl:323: void texImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels);
./Source/modules/webgl/WebGL2RenderingContextBase.idl:324: void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, ArrayBufferView? pixels);
./Source/modules/webgl/WebGL2RenderingContextBase.idl:330: void compressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, ArrayBufferView data);
./Source/modules/webgl/WebGL2RenderingContextBase.idl:331: void compressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, ArrayBufferView data);
./Source/modules/webgl/WebGL2RenderingContextBase.idl:341: void uniform1uiv(WebGLUniformLocation? location, [FlexibleArrayBufferView] Uint32Array v);
./Source/modules/webgl/WebGL2RenderingContextBase.idl:343: void uniform2uiv(WebGLUniformLocation? location, [FlexibleArrayBufferView] Uint32Array v);
./Source/modules/webgl/WebGL2RenderingContextBase.idl:345: void uniform3uiv(WebGLUniformLocation? location, [FlexibleArrayBufferView] Uint32Array v);
./Source/modules/webgl/WebGL2RenderingContextBase.idl:347: void uniform4uiv(WebGLUniformLocation? location, [FlexibleArrayBufferView] Uint32Array v);

WebAudio (http://www.w3.org/TR/webaudio/)
./Source/modules/webaudio/AudioContext.idl:60: [RaisesException, MeasureAs=AudioContextDecodeAudioData] void decodeAudioData(ArrayBuffer audioData, AudioBufferCallback successCallback, optional AudioBufferCallback errorCallback);

WebBluetooth (https://webbluetoothchrome.github.io/web-bluetooth)
./Source/modules/bluetooth/BluetoothGATTCharacteristic.idl:23: [CallWith=ScriptState] Promise<void> writeValue(BufferSource value);

PushMessaging (http://w3c.github.io/push-api)
./Source/modules/push_messaging/PushEventInit.idl:8:typedef (ArrayBuffer or ArrayBufferView or USVString) PushMessageDataInit;

WebNFC (https://w3c.github.io/web-nfc/#the-nfc-interface)
./Source/modules/nfc/NFC.idl:7:typedef (DOMString or ArrayBuffer or NFCMessage) NFCPushMessage;

EncryptedMedia (https://w3c.github.io/encrypted-media/#mediaencryptedevent)
./Source/modules/encryptedmedia/MediaKeys.idl:38: [CallWith=ScriptState] Promise<void> setServerCertificate(BufferSource serverCertificate);
./Source/modules/encryptedmedia/MediaKeySession.idl:38: [CallWith=ScriptState] Promise<void> generateRequest(DOMString initDataType, BufferSource initData);
./Source/modules/encryptedmedia/MediaKeySession.idl:42: [CallWith=ScriptState] Promise<void> update(BufferSource response);
./Source/modules/encryptedmedia/MediaKeyStatusMap.idl:21: readonly maplike <BufferSource, MediaKeyStatus>;

Beacon (http://w3c.github.io/beacon/)
./Source/modules/beacon/NavigatorBeacon.idl:8: [CallWith=ExecutionContext, MeasureAs=SendBeacon, RaisesException] boolean sendBeacon(DOMString url, optional (ArrayBufferView or Blob or DOMString or FormData)? data = null);

WebRTC (http://w3c.github.io/webrtc-pc/)
./Source/modules/mediastream/RTCDataChannel.idl:52: [RaisesException] void send(ArrayBufferView data);

Presentation API (https://w3c.github.io/presentation-api)
./Source/modules/presentation/PresentationConnection.idl:29: [RaisesException, MeasureAs=PresentationConnectionSend, LegacyInterfaceTypeChecking] void send(ArrayBufferView data);

Fetch (http://fetch.spec.whatwg.org)
./Source/modules/fetch/Response.idl:10:typedef (Blob or ArrayBuffer or ArrayBufferView or FormData or USVString) BodyInit;

Encoding (https://encoding.spec.whatwg.org/#interface-textdecoder)
./Source/modules/encoding/TextDecoder.idl:41: [RaisesException, MeasureAs=TextDecoderDecode] DOMString decode(optional BufferSource input, optional TextDecodeOptions options);

XmlHttpRequest (https://xhr.spec.whatwg.org/#interface-xmlhttprequest)
./Source/core/xmlhttprequest/XMLHttpRequest.idl:69: [RaisesException] void send(optional (ArrayBuffer or ArrayBufferView or Blob or Document or DOMString or FormData)? body = null);

@lars-t-hansen
Copy link
Collaborator Author

That mirrors my experience in Firefox, more or less. I just landed the changes to Firefox to get rid of the SharedTypedArrays and had to deal with all the DOM and browser APIs that use TypedArray to make sure they did not accidentally opt in to using shared memory. (https://bugzil.la/1176214) As I wrote earlier, we handled this on the high level with a fat pointer that explicitly represents sharedness, and on the lower level by requiring that pointer to be unwrapped specially if the memory is shared. (At this time, only a small number of WebGL/Canvas APIs opt in to shared memory in Firefox.)

@binji
Copy link

binji commented Dec 16, 2015

I started a discussion on blink-dev about this: https://groups.google.com/a/chromium.org/d/topic/blink-dev/EsX3S43nm-0/discussion

They suggested we talk to the WebIDL editors about a mechanism for allowing/preventing SAB views from being used.

The comment here suggests that in addition to annotating which methods copy/reference ArrayBuffer contents, there could be annotation specifying which methods accept SAB views: https://groups.google.com/a/chromium.org/d/msg/blink-dev/EsX3S43nm-0/AAgH8_JWBAAJ.

@lars-t-hansen
Copy link
Collaborator Author

Thanks for starting that. I've received similar advice privately, that it would be best if the WebIDL APIs could opt-in to shared memory (https://bugzil.la/1231687). Mostly this was about improving error messages; for safety reasons we'd want to keep the fat pointers internally in the Firefox C++ code in any case.

@lars-t-hansen
Copy link
Collaborator Author

@erights
Copy link

erights commented Mar 23, 2016

@lars-t-hansen I don't understand how any of this protects the JavaScript programmer in general. The FF fat pointers are at the C++ level and the w3 bug is webidl specific, and therefore web specific. Aside from the narrow scope of these solutions, they seem like the right kind of thing. How do we generally prevent the kind of confusion that these prevent in those specific cases?

@lars-t-hansen
Copy link
Collaborator Author

@erights, not sure what you are thinking about when you ask about protecting the JS programmer. This particular bug probably pertains only to how we integrate the shared memory work into a specific embedding (the browser) in a safe way, ie, what we talk about here probably will not end up in ES, but will perhaps inform the discussion within TC39.

It's very desirable to opt-in to shared memory in any host API, of course.

I suppose there could be a broader discussion whether we should do anything generic within ES to distinguish between shared and non-shared memory for host functions. Host functions can extract the buffer from any TypedArray argument and check whether it is shared memory (this is what the webidl fix amounts to). Do we need anything more than that? Can we?

Or were you thinking of something else?

kisg pushed a commit to paul99/webkit-mips that referenced this issue Nov 1, 2016
https://bugs.webkit.org/show_bug.cgi?id=163986

Reviewed by Keith Miller.
JSTests:

        
This adds our own test for the various corner cases of SharedArrayBuffer. This test is meant to
check all of the things that don't require concurrency.

* stress/SharedArrayBuffer.js: Added.
(checkAtomics):
(shouldFail):
(Symbol):
(runAtomic):

Source/JavaScriptCore:

        
This implements https://tc39.github.io/ecmascript_sharedmem/shmem.html.
        
There is now a new SharedArrayBuffer type. In the JS runtime, which includes typed array
types, the SharedArrayBuffer is a drop-in replacement for ArrayBuffer, even though they are
distinct types (new SharedArrayBuffer() instanceof ArrayBuffer == false and vice versa). The
DOM will not recognize SharedArrayBuffer, or any typed array that wraps it, to ensure safety.
This matches what other browsers intend to do, see
tc39/proposal-ecmascript-sharedmem#38. API is provided for the DOM to opt
into SharedArrayBuffer. One notable place is postMessage, which will share the
SharedArrayBuffer's underlying data storage with other workers. This creates a pool of shared
memory that the workers can use to talk to each other.
        
There is also an Atomics object in global scope, which exposes sequentially consistent atomic
operations: add, and, compareExchange, exchange, load, or, store, sub, and xor. Additionally
it exposes a Atomics.isLockFree utility, which takes a byte amount and returns true or false.
Also there is Atomics.wake/wait, which neatly map to ParkingLot.
        
Accesses to typed arrays that wrap SharedArrayBuffer are optimized by JSC the same way as
always. I believe that DFG and B3 already obey the following memory model, which I believe is
a bit weaker than Cambridge and a bit stronger than what is being proposed for
SharedArrayBuffer. To predict a program's behavior under the B3 memory model, imagine the
space of all possible programs that would result from running an optimizer that adversarially
follows B3's transformation rules. B3 transformations are correct if the newly created
program is equivalent to the old one, assuming that any opaque effect in IR (like the reads
and writes of a patchpoint/call/fence) could perform any load/store that satisfies the
B3::Effects summary. Opaque effects are a way of describing an infinite set of programs: any
program that only does the effects summarized in B3::Effects belongs to the set. For example,
this prevents motion of operations across fences since fences are summarized as opaque
effects that could read or write memory. This rule alone is not enough, because it leaves the
door open for turning an atomic operation (like a load) into a non-atomic one (like a load
followed by a store of the same value back to the same location or multiple loads). This is
not an optimization that either our compiler or the CPU would want to do. One way to think of
what exactly is forbidden is that B3 transformations that mess with memory accesses can only
reorder them or remove them. This means that for any execution of the untransformed program,
the corresponding execution of the transformed program (i.e. with the same input arguments
and the same programs filled in for the opaque effects) must have the same loads and stores,
with some removed and some reordered. This is a fairly simple mental model that B3 and DFG
already follow and it's based on existing abstractions for the infinite set of programs
inside an opaque effect (DFG's AbstractHeaps and B3's Effects).
        
This patch makes all atomics operations intrinsic, but the DFG doesn't know about any of them
yet. That's covered by bug 164108.
        
This ought to be perf-neutral, but I am still running tests to confirm this. I'm also still
writing new tests to cover all of the Atomics functionality and the behavior of SAB objects.

* API/JSTypedArray.cpp:
(JSObjectGetTypedArrayBytesPtr):
(JSObjectGetTypedArrayBuffer):
(JSObjectMakeArrayBufferWithBytesNoCopy):
* API/tests/CompareAndSwapTest.cpp:
(Bitmap::concurrentTestAndSet):
* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGDesiredWatchpoints.cpp:
(JSC::DFG::ArrayBufferViewWatchpointAdaptor::add):
* heap/Heap.cpp:
(JSC::Heap::reportExtraMemoryVisited):
(JSC::Heap::reportExternalMemoryVisited):
* jsc.cpp:
(functionTransferArrayBuffer):
* runtime/ArrayBuffer.cpp:
(JSC::SharedArrayBufferContents::SharedArrayBufferContents):
(JSC::SharedArrayBufferContents::~SharedArrayBufferContents):
(JSC::ArrayBufferContents::ArrayBufferContents):
(JSC::ArrayBufferContents::operator=):
(JSC::ArrayBufferContents::~ArrayBufferContents):
(JSC::ArrayBufferContents::clear):
(JSC::ArrayBufferContents::destroy):
(JSC::ArrayBufferContents::reset):
(JSC::ArrayBufferContents::tryAllocate):
(JSC::ArrayBufferContents::makeShared):
(JSC::ArrayBufferContents::transferTo):
(JSC::ArrayBufferContents::copyTo):
(JSC::ArrayBufferContents::shareWith):
(JSC::ArrayBuffer::create):
(JSC::ArrayBuffer::createAdopted):
(JSC::ArrayBuffer::createFromBytes):
(JSC::ArrayBuffer::tryCreate):
(JSC::ArrayBuffer::createUninitialized):
(JSC::ArrayBuffer::tryCreateUninitialized):
(JSC::ArrayBuffer::createInternal):
(JSC::ArrayBuffer::ArrayBuffer):
(JSC::ArrayBuffer::slice):
(JSC::ArrayBuffer::sliceImpl):
(JSC::ArrayBuffer::makeShared):
(JSC::ArrayBuffer::setSharingMode):
(JSC::ArrayBuffer::transferTo):
(JSC::ArrayBuffer::transfer): Deleted.
* runtime/ArrayBuffer.h:
(JSC::arrayBufferSharingModeName):
(JSC::SharedArrayBufferContents::data):
(JSC::ArrayBufferContents::data):
(JSC::ArrayBufferContents::sizeInBytes):
(JSC::ArrayBufferContents::isShared):
(JSC::ArrayBuffer::sharingMode):
(JSC::ArrayBuffer::isShared):
(JSC::ArrayBuffer::gcSizeEstimateInBytes):
(JSC::arrayBufferDestructorNull): Deleted.
(JSC::arrayBufferDestructorDefault): Deleted.
(JSC::ArrayBufferContents::ArrayBufferContents): Deleted.
(JSC::ArrayBufferContents::transfer): Deleted.
(JSC::ArrayBufferContents::copyTo): Deleted.
(JSC::ArrayBuffer::create): Deleted.
(JSC::ArrayBuffer::createAdopted): Deleted.
(JSC::ArrayBuffer::createFromBytes): Deleted.
(JSC::ArrayBuffer::tryCreate): Deleted.
(JSC::ArrayBuffer::createUninitialized): Deleted.
(JSC::ArrayBuffer::tryCreateUninitialized): Deleted.
(JSC::ArrayBuffer::createInternal): Deleted.
(JSC::ArrayBuffer::ArrayBuffer): Deleted.
(JSC::ArrayBuffer::slice): Deleted.
(JSC::ArrayBuffer::sliceImpl): Deleted.
(JSC::ArrayBufferContents::tryAllocate): Deleted.
(JSC::ArrayBufferContents::~ArrayBufferContents): Deleted.
* runtime/ArrayBufferSharingMode.h: Added.
* runtime/ArrayBufferView.h:
(JSC::ArrayBufferView::possiblySharedBuffer):
(JSC::ArrayBufferView::unsharedBuffer):
(JSC::ArrayBufferView::isShared):
(JSC::ArrayBufferView::buffer): Deleted.
* runtime/AtomicsObject.cpp: Added.
(JSC::AtomicsObject::AtomicsObject):
(JSC::AtomicsObject::create):
(JSC::AtomicsObject::createStructure):
(JSC::AtomicsObject::finishCreation):
(JSC::atomicsFuncAdd):
(JSC::atomicsFuncAnd):
(JSC::atomicsFuncCompareExchange):
(JSC::atomicsFuncExchange):
(JSC::atomicsFuncIsLockFree):
(JSC::atomicsFuncLoad):
(JSC::atomicsFuncOr):
(JSC::atomicsFuncStore):
(JSC::atomicsFuncSub):
(JSC::atomicsFuncWait):
(JSC::atomicsFuncWake):
(JSC::atomicsFuncXor):
* runtime/AtomicsObject.h: Added.
* runtime/CommonIdentifiers.h:
* runtime/DataView.cpp:
(JSC::DataView::wrap):
* runtime/GenericTypedArrayViewInlines.h:
(JSC::GenericTypedArrayView<Adaptor>::subarray):
* runtime/Intrinsic.h:
* runtime/JSArrayBuffer.cpp:
(JSC::JSArrayBuffer::finishCreation):
(JSC::JSArrayBuffer::isShared):
(JSC::JSArrayBuffer::sharingMode):
* runtime/JSArrayBuffer.h:
(JSC::toPossiblySharedArrayBuffer):
(JSC::toUnsharedArrayBuffer):
(JSC::JSArrayBuffer::toWrapped):
(JSC::toArrayBuffer): Deleted.
* runtime/JSArrayBufferConstructor.cpp:
(JSC::JSArrayBufferConstructor::JSArrayBufferConstructor):
(JSC::JSArrayBufferConstructor::finishCreation):
(JSC::JSArrayBufferConstructor::create):
(JSC::constructArrayBuffer):
* runtime/JSArrayBufferConstructor.h:
(JSC::JSArrayBufferConstructor::sharingMode):
* runtime/JSArrayBufferPrototype.cpp:
(JSC::arrayBufferProtoFuncSlice):
(JSC::JSArrayBufferPrototype::JSArrayBufferPrototype):
(JSC::JSArrayBufferPrototype::finishCreation):
(JSC::JSArrayBufferPrototype::create):
* runtime/JSArrayBufferPrototype.h:
* runtime/JSArrayBufferView.cpp:
(JSC::JSArrayBufferView::finishCreation):
(JSC::JSArrayBufferView::visitChildren):
(JSC::JSArrayBufferView::unsharedBuffer):
(JSC::JSArrayBufferView::unsharedJSBuffer):
(JSC::JSArrayBufferView::possiblySharedJSBuffer):
(JSC::JSArrayBufferView::neuter):
(JSC::JSArrayBufferView::toWrapped): Deleted.
* runtime/JSArrayBufferView.h:
(JSC::JSArrayBufferView::jsBuffer): Deleted.
* runtime/JSArrayBufferViewInlines.h:
(JSC::JSArrayBufferView::isShared):
(JSC::JSArrayBufferView::possiblySharedBuffer):
(JSC::JSArrayBufferView::possiblySharedImpl):
(JSC::JSArrayBufferView::unsharedImpl):
(JSC::JSArrayBufferView::byteOffset):
(JSC::JSArrayBufferView::toWrapped):
(JSC::JSArrayBufferView::buffer): Deleted.
(JSC::JSArrayBufferView::impl): Deleted.
(JSC::JSArrayBufferView::neuter): Deleted.
* runtime/JSDataView.cpp:
(JSC::JSDataView::possiblySharedTypedImpl):
(JSC::JSDataView::unsharedTypedImpl):
(JSC::JSDataView::getTypedArrayImpl):
(JSC::JSDataView::typedImpl): Deleted.
* runtime/JSDataView.h:
(JSC::JSDataView::possiblySharedBuffer):
(JSC::JSDataView::unsharedBuffer):
(JSC::JSDataView::buffer): Deleted.
* runtime/JSDataViewPrototype.cpp:
(JSC::dataViewProtoGetterBuffer):
* runtime/JSGenericTypedArrayView.h:
(JSC::toPossiblySharedNativeTypedView):
(JSC::toUnsharedNativeTypedView):
(JSC::JSGenericTypedArrayView<Adaptor>::toWrapped):
(JSC::JSGenericTypedArrayView::typedImpl): Deleted.
(JSC::toNativeTypedView): Deleted.
* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::JSGenericTypedArrayView<Adaptor>::create):
(JSC::JSGenericTypedArrayView<Adaptor>::possiblySharedTypedImpl):
(JSC::JSGenericTypedArrayView<Adaptor>::unsharedTypedImpl):
(JSC::JSGenericTypedArrayView<Adaptor>::getTypedArrayImpl):
* runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
(JSC::genericTypedArrayViewProtoGetterFuncBuffer):
(JSC::genericTypedArrayViewPrivateFuncSubarrayCreate):
* runtime/JSGlobalObject.cpp:
(JSC::createAtomicsProperty):
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::arrayBufferPrototype):
(JSC::JSGlobalObject::arrayBufferStructure):
* runtime/MathObject.cpp:
* runtime/RuntimeFlags.h:
* runtime/SimpleTypedArrayController.cpp:
(JSC::SimpleTypedArrayController::toJS):
* runtime/TypedArrayType.h:
(JSC::typedArrayTypeForType):

Source/WebCore:


New tests added in the LayoutTests/workers/sab directory.
        
This teaches WebCore that a typed array could be shared or not. By default, WebCore will
reject shared typed arrays as if they were not typed arrays. This ensures that we don't get
race conditions in code that can't handle it.
        
If you postMessage a SharedArrayBuffer or something that wraps it, you will send the shared
memory to the other worker.

* Modules/encryptedmedia/CDMSessionClearKey.cpp:
(WebCore::CDMSessionClearKey::cachedKeyForKeyID):
* Modules/fetch/FetchBody.cpp:
(WebCore::FetchBody::extract):
* Modules/mediastream/RTCDataChannel.cpp:
(WebCore::RTCDataChannel::send):
* Modules/webaudio/AudioBuffer.cpp:
(WebCore::AudioBuffer::getChannelData):
* Modules/websockets/WebSocket.cpp:
(WebCore::WebSocket::send):
* bindings/js/JSBlobCustom.cpp:
(WebCore::constructJSBlob):
* bindings/js/JSCryptoAlgorithmDictionary.cpp:
(WebCore::createRsaKeyGenParams):
* bindings/js/JSCryptoCustom.cpp:
(WebCore::JSCrypto::getRandomValues):
* bindings/js/JSCryptoOperationData.cpp:
(WebCore::cryptoOperationDataFromJSValue):
* bindings/js/JSDOMBinding.h:
(WebCore::toJS):
(WebCore::toPossiblySharedArrayBufferView):
(WebCore::toUnsharedArrayBufferView):
(WebCore::toPossiblySharedInt8Array):
(WebCore::toPossiblySharedInt16Array):
(WebCore::toPossiblySharedInt32Array):
(WebCore::toPossiblySharedUint8Array):
(WebCore::toPossiblySharedUint8ClampedArray):
(WebCore::toPossiblySharedUint16Array):
(WebCore::toPossiblySharedUint32Array):
(WebCore::toPossiblySharedFloat32Array):
(WebCore::toPossiblySharedFloat64Array):
(WebCore::toUnsharedInt8Array):
(WebCore::toUnsharedInt16Array):
(WebCore::toUnsharedInt32Array):
(WebCore::toUnsharedUint8Array):
(WebCore::toUnsharedUint8ClampedArray):
(WebCore::toUnsharedUint16Array):
(WebCore::toUnsharedUint32Array):
(WebCore::toUnsharedFloat32Array):
(WebCore::toUnsharedFloat64Array):
(WebCore::toArrayBufferView): Deleted.
(WebCore::toInt8Array): Deleted.
(WebCore::toInt16Array): Deleted.
(WebCore::toInt32Array): Deleted.
(WebCore::toUint8Array): Deleted.
(WebCore::toUint8ClampedArray): Deleted.
(WebCore::toUint16Array): Deleted.
(WebCore::toUint32Array): Deleted.
(WebCore::toFloat32Array): Deleted.
(WebCore::toFloat64Array): Deleted.
* bindings/js/JSDataCueCustom.cpp:
(WebCore::constructJSDataCue):
* bindings/js/JSDictionary.cpp:
(WebCore::JSDictionary::convertValue):
* bindings/js/JSFileCustom.cpp:
(WebCore::constructJSFile):
* bindings/js/JSMessagePortCustom.cpp:
(WebCore::extractTransferables):
* bindings/js/JSWebGLRenderingContextBaseCustom.cpp:
(WebCore::dataFunctionf):
(WebCore::dataFunctioni):
(WebCore::dataFunctionMatrix):
* bindings/js/JSXMLHttpRequestCustom.cpp:
(WebCore::JSXMLHttpRequest::send):
* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::dumpArrayBufferView):
(WebCore::CloneSerializer::dumpIfTerminal):
(WebCore::CloneDeserializer::readArrayBufferView):
(WebCore::CloneDeserializer::readTerminal):
(WebCore::SerializedScriptValue::transferArrayBuffers):
* bindings/js/StructuredClone.cpp:
(WebCore::structuredCloneArrayBuffer):
(WebCore::structuredCloneArrayBufferView):
* bindings/scripts/CodeGeneratorJS.pm:
(JSValueToNative):
* css/FontFace.cpp:
(WebCore::FontFace::create):
* html/canvas/WebGL2RenderingContext.cpp:
(WebCore::WebGL2RenderingContext::bufferData):
(WebCore::WebGL2RenderingContext::bufferSubData):
* platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp:
(WebCore::MediaPlayerPrivateAVFoundation::extractKeyURIKeyIDAndCertificateFromInitData):

Source/WebKit/mac:

        
Support the RuntimeFlag.

* WebView/WebPreferencesPrivate.h:

Source/WebKit/win:


Support the RuntimeFlag.

* Interfaces/IWebPreferencesPrivate.idl:

Source/WebKit2:

        
Adds some small things we need for SharedArrayBuffer.

* UIProcess/API/C/WKPreferencesRefPrivate.h:
* UIProcess/API/Cocoa/WKPreferencesPrivate.h:
* WebProcess/InjectedBundle/InjectedBundle.cpp:
(WebKit::InjectedBundle::createWebDataFromUint8Array):

Source/WTF:

        
Adds some small things we need for SharedArrayBuffer.
        
* wtf/Atomics.h:
(WTF::Atomic::compareExchangeWeakRelaxed):
(WTF::Atomic::exchangeAdd):
(WTF::Atomic::exchangeAnd):
(WTF::Atomic::exchangeOr):
(WTF::Atomic::exchangeSub):
(WTF::Atomic::exchangeXor):
(WTF::atomicLoad):
(WTF::atomicStore):
(WTF::atomicCompareExchangeWeak):
(WTF::atomicCompareExchangeWeakRelaxed):
(WTF::atomicCompareExchangeStrong):
(WTF::atomicExchangeAdd):
(WTF::atomicExchangeAnd):
(WTF::atomicExchangeOr):
(WTF::atomicExchangeSub):
(WTF::atomicExchangeXor):
(WTF::atomicExchange):
(WTF::Atomic::exchangeAndAdd): Deleted.
(WTF::weakCompareAndSwap): Deleted.
We need to be able to do atomics operations on naked pointers. We also need to be able to do
all of the things that std::atomic does. This adds those things and renames
weakCompareAndSwap to atomicCompareExchangeWeakRelaxed so that we're using consistent
terminology.
        
* wtf/Bitmap.h:
(WTF::WordType>::concurrentTestAndSet): Renamed weakCompareAndSwap.
(WTF::WordType>::concurrentTestAndClear): Renamed weakCompareAndSwap.
* wtf/FastBitVector.h:
(WTF::FastBitVector::atomicSetAndCheck): Renamed weakCompareAndSwap.
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
Added unparkCount(), which lets you unpark some bounded number of threads and returns the
number of threads unparked. This is just a modest extension of unparkAll(). unparkAll() now
just calls unparkCount(ptr, UINT_MAX).

Tools:

        
Use the right kind of typed array API.

* DumpRenderTree/TestRunner.cpp:
(setAudioResultCallback):

LayoutTests:

        
Adding tests. This is a work in progress.

* workers/sab: Added.
* workers/sab/simple-worker-1.js: Added.
(onmessage):
* workers/sab/simple-worker-2.js: Added.
(onmessage):
* workers/sab/simple.html: Added.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@208209 268f45cc-cd09-0410-ab3c-d52691b4dbfc
@lars-t-hansen
Copy link
Collaborator Author

There's what probably amounts to a consensus position for the WebIDL syntax here: https://www.w3.org/Bugs/Public/show_bug.cgi?id=29388#c2

The DOM companion spec (https://tc39.github.io/ecmascript_sharedmem/dom_shmem.html) should probably be updated to this syntax. Before I do that I am going to be investigating its utility and performance in Firefox, https://bugzil.la/1231687.

@binji
Copy link

binji commented Nov 8, 2016

Thanks for reviving this, Lars. I have a similar CL from a while back where I was exploring the same thing in Blink: https://codereview.chromium.org/1526183004/.

@lars-t-hansen
Copy link
Collaborator Author

WebGL 2.0 bindings are also becoming an issue, but after some disussion with @juj I don't think there's anything difficult going on here, just work. Below are the APIs he's requested be included. I think what we're proposing for WebIDL (see my comment above) will cover these reasonably well.

Some of these also seem to be present in 1.0.2 and are listed in @binji's comment above.

void bufferData(GLenum target, ArrayBufferView srcData, GLenum usage, GLuint srcOffset, optional GLuint length = 0);
void bufferSubData(GLenum target, GLintptr dstByteOffset, ArrayBufferView srcData, GLuint srcOffset, optional GLuint length = 0);
void getBufferSubData(GLenum target, GLintptr srcByteOffset, ArrayBufferView dstData, optional GLuint dstOffset = 0, optional GLuint length = 0);
void texImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView srcData, GLuint srcOffset);
void texImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, ArrayBufferView? srcData);
void texImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, ArrayBufferView srcData, GLuint srcOffset);
void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView srcData, GLuint srcOffset);
void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, ArrayBufferView? srcData, optional GLuint srcOffset = 0);
void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, ArrayBufferView srcData, optional GLuint srcOffset = 0, optional GLuint srcLengthOverride = 0);
void compressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, ArrayBufferView srcData, optional GLuint srcOffset = 0, optional GLuint srcLengthOverride = 0);
void compressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, ArrayBufferView srcData, optional GLuint srcOffset = 0, optional GLuint srcLengthOverride = 0);
void compressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, ArrayBufferView srcData, optional GLuint srcOffset = 0, optional GLuint srcLengthOverride = 0);
void uniform{1,2,3,4}fv(WebGLUniformLocation? location, Float32List data, optional GLuint srcOffset = 0, optional GLuint srcLength = 0);
void uniform{1,2,3,4}iv(WebGLUniformLocation? location, Int32List data, optional GLuint srcOffset = 0, optional GLuint srcLength = 0);
void uniform{1,2,3,4}uiv(WebGLUniformLocation? location, Uint32List data, optional GLuint srcOffset = 0, optional GLuint srcLength = 0);
void uniformMatrix{2,3x2,4x2,2x3,3,4x3,2x4,3x4,4}fv(WebGLUniformLocation? location, GLboolean transpose, Float32List data, optional GLuint srcOffset = 0, optional GLuint srcLength = 0);
void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView dstData, GLuint dstOffset);
void clearBufferfv(GLenum buffer, GLint drawbuffer, Float32List values, optional GLuint srcOffset = 0);
void clearBufferiv(GLenum buffer, GLint drawbuffer, Int32List values, optional GLuint srcOffset = 0);
void clearBufferuiv(GLenum buffer, GLint drawbuffer, Uint32List values, optional GLuint srcOffset = 0);

@lars-t-hansen
Copy link
Collaborator Author

@domenic, @binji -- some discussion with Boris Zbarsky (WebIDL editor) in https://bugzil.la/1231687, re what the appropriate solution is in WebIDL. If you have opinions this is a good time to voice them.

@binji
Copy link

binji commented Dec 3, 2016

So it sounds like his suggestion is to duplicate all ArrayBuffer, TypedArray, etc. types differentiating them by whether the callee will copy or reference. Seems a bit strange to me that the type is specifying what the function will do with the value, rather than what the value is, but perhaps that is common elsewhere in WebIDL?

Also: I'm a little concerned that we'll have a mismatch between the actual types (e.g. Int8Array w/ backing SharedArrayBuffer) vs the WebIDL types (e.g. MaybeSharedInt8Array). In some ways I suppose it could be viewed as a union type, but it also has additional semantics.

Either way, I don't think it will be a problem for Blink's IDL generator.

@domenic
Copy link
Member

domenic commented Dec 3, 2016

Seems a bit strange to me that the type is specifying what the function will do with the value, rather than what the value is, but perhaps that is common elsewhere in WebIDL?

Nah, that's not the case in Web IDL. There types serve several purposes, one of the most important of which is saying what happens when they are passed as arguments. Cf. USVString or ByteString.

Also: I'm a little concerned that we'll have a mismatch between the actual types

Yes, I am also a bit concerned there; see my paragraph at the bottom of https://bugzilla.mozilla.org/show_bug.cgi?id=1231687#c16

@annevk
Copy link
Member

annevk commented Apr 16, 2017

@domenic maybe you should update this issue with the revised plans for [AllowShared]? I guess the plan still is to only use that extended attribute in WebGL?

@annevk
Copy link
Member

annevk commented Apr 16, 2017

Maybe this is just a duplicate of #168 at this point.

ryanhaddad pushed a commit to WebKit/WebKit that referenced this issue Dec 22, 2020
https://bugs.webkit.org/show_bug.cgi?id=163986

Reviewed by Keith Miller.
JSTests:


This adds our own test for the various corner cases of SharedArrayBuffer. This test is meant to
check all of the things that don't require concurrency.

* stress/SharedArrayBuffer.js: Added.
(checkAtomics):
(shouldFail):
(Symbol):
(runAtomic):

Source/JavaScriptCore:


This implements https://tc39.github.io/ecmascript_sharedmem/shmem.html.

There is now a new SharedArrayBuffer type. In the JS runtime, which includes typed array
types, the SharedArrayBuffer is a drop-in replacement for ArrayBuffer, even though they are
distinct types (new SharedArrayBuffer() instanceof ArrayBuffer == false and vice versa). The
DOM will not recognize SharedArrayBuffer, or any typed array that wraps it, to ensure safety.
This matches what other browsers intend to do, see
tc39/proposal-ecmascript-sharedmem#38. API is provided for the DOM to opt
into SharedArrayBuffer. One notable place is postMessage, which will share the
SharedArrayBuffer's underlying data storage with other workers. This creates a pool of shared
memory that the workers can use to talk to each other.

There is also an Atomics object in global scope, which exposes sequentially consistent atomic
operations: add, and, compareExchange, exchange, load, or, store, sub, and xor. Additionally
it exposes a Atomics.isLockFree utility, which takes a byte amount and returns true or false.
Also there is Atomics.wake/wait, which neatly map to ParkingLot.

Accesses to typed arrays that wrap SharedArrayBuffer are optimized by JSC the same way as
always. I believe that DFG and B3 already obey the following memory model, which I believe is
a bit weaker than Cambridge and a bit stronger than what is being proposed for
SharedArrayBuffer. To predict a program's behavior under the B3 memory model, imagine the
space of all possible programs that would result from running an optimizer that adversarially
follows B3's transformation rules. B3 transformations are correct if the newly created
program is equivalent to the old one, assuming that any opaque effect in IR (like the reads
and writes of a patchpoint/call/fence) could perform any load/store that satisfies the
B3::Effects summary. Opaque effects are a way of describing an infinite set of programs: any
program that only does the effects summarized in B3::Effects belongs to the set. For example,
this prevents motion of operations across fences since fences are summarized as opaque
effects that could read or write memory. This rule alone is not enough, because it leaves the
door open for turning an atomic operation (like a load) into a non-atomic one (like a load
followed by a store of the same value back to the same location or multiple loads). This is
not an optimization that either our compiler or the CPU would want to do. One way to think of
what exactly is forbidden is that B3 transformations that mess with memory accesses can only
reorder them or remove them. This means that for any execution of the untransformed program,
the corresponding execution of the transformed program (i.e. with the same input arguments
and the same programs filled in for the opaque effects) must have the same loads and stores,
with some removed and some reordered. This is a fairly simple mental model that B3 and DFG
already follow and it's based on existing abstractions for the infinite set of programs
inside an opaque effect (DFG's AbstractHeaps and B3's Effects).

This patch makes all atomics operations intrinsic, but the DFG doesn't know about any of them
yet. That's covered by bug 164108.

This ought to be perf-neutral, but I am still running tests to confirm this. I'm also still
writing new tests to cover all of the Atomics functionality and the behavior of SAB objects.

* API/JSTypedArray.cpp:
(JSObjectGetTypedArrayBytesPtr):
(JSObjectGetTypedArrayBuffer):
(JSObjectMakeArrayBufferWithBytesNoCopy):
* API/tests/CompareAndSwapTest.cpp:
(Bitmap::concurrentTestAndSet):
* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGDesiredWatchpoints.cpp:
(JSC::DFG::ArrayBufferViewWatchpointAdaptor::add):
* heap/Heap.cpp:
(JSC::Heap::reportExtraMemoryVisited):
(JSC::Heap::reportExternalMemoryVisited):
* jsc.cpp:
(functionTransferArrayBuffer):
* runtime/ArrayBuffer.cpp:
(JSC::SharedArrayBufferContents::SharedArrayBufferContents):
(JSC::SharedArrayBufferContents::~SharedArrayBufferContents):
(JSC::ArrayBufferContents::ArrayBufferContents):
(JSC::ArrayBufferContents::operator=):
(JSC::ArrayBufferContents::~ArrayBufferContents):
(JSC::ArrayBufferContents::clear):
(JSC::ArrayBufferContents::destroy):
(JSC::ArrayBufferContents::reset):
(JSC::ArrayBufferContents::tryAllocate):
(JSC::ArrayBufferContents::makeShared):
(JSC::ArrayBufferContents::transferTo):
(JSC::ArrayBufferContents::copyTo):
(JSC::ArrayBufferContents::shareWith):
(JSC::ArrayBuffer::create):
(JSC::ArrayBuffer::createAdopted):
(JSC::ArrayBuffer::createFromBytes):
(JSC::ArrayBuffer::tryCreate):
(JSC::ArrayBuffer::createUninitialized):
(JSC::ArrayBuffer::tryCreateUninitialized):
(JSC::ArrayBuffer::createInternal):
(JSC::ArrayBuffer::ArrayBuffer):
(JSC::ArrayBuffer::slice):
(JSC::ArrayBuffer::sliceImpl):
(JSC::ArrayBuffer::makeShared):
(JSC::ArrayBuffer::setSharingMode):
(JSC::ArrayBuffer::transferTo):
(JSC::ArrayBuffer::transfer): Deleted.
* runtime/ArrayBuffer.h:
(JSC::arrayBufferSharingModeName):
(JSC::SharedArrayBufferContents::data):
(JSC::ArrayBufferContents::data):
(JSC::ArrayBufferContents::sizeInBytes):
(JSC::ArrayBufferContents::isShared):
(JSC::ArrayBuffer::sharingMode):
(JSC::ArrayBuffer::isShared):
(JSC::ArrayBuffer::gcSizeEstimateInBytes):
(JSC::arrayBufferDestructorNull): Deleted.
(JSC::arrayBufferDestructorDefault): Deleted.
(JSC::ArrayBufferContents::ArrayBufferContents): Deleted.
(JSC::ArrayBufferContents::transfer): Deleted.
(JSC::ArrayBufferContents::copyTo): Deleted.
(JSC::ArrayBuffer::create): Deleted.
(JSC::ArrayBuffer::createAdopted): Deleted.
(JSC::ArrayBuffer::createFromBytes): Deleted.
(JSC::ArrayBuffer::tryCreate): Deleted.
(JSC::ArrayBuffer::createUninitialized): Deleted.
(JSC::ArrayBuffer::tryCreateUninitialized): Deleted.
(JSC::ArrayBuffer::createInternal): Deleted.
(JSC::ArrayBuffer::ArrayBuffer): Deleted.
(JSC::ArrayBuffer::slice): Deleted.
(JSC::ArrayBuffer::sliceImpl): Deleted.
(JSC::ArrayBufferContents::tryAllocate): Deleted.
(JSC::ArrayBufferContents::~ArrayBufferContents): Deleted.
* runtime/ArrayBufferSharingMode.h: Added.
* runtime/ArrayBufferView.h:
(JSC::ArrayBufferView::possiblySharedBuffer):
(JSC::ArrayBufferView::unsharedBuffer):
(JSC::ArrayBufferView::isShared):
(JSC::ArrayBufferView::buffer): Deleted.
* runtime/AtomicsObject.cpp: Added.
(JSC::AtomicsObject::AtomicsObject):
(JSC::AtomicsObject::create):
(JSC::AtomicsObject::createStructure):
(JSC::AtomicsObject::finishCreation):
(JSC::atomicsFuncAdd):
(JSC::atomicsFuncAnd):
(JSC::atomicsFuncCompareExchange):
(JSC::atomicsFuncExchange):
(JSC::atomicsFuncIsLockFree):
(JSC::atomicsFuncLoad):
(JSC::atomicsFuncOr):
(JSC::atomicsFuncStore):
(JSC::atomicsFuncSub):
(JSC::atomicsFuncWait):
(JSC::atomicsFuncWake):
(JSC::atomicsFuncXor):
* runtime/AtomicsObject.h: Added.
* runtime/CommonIdentifiers.h:
* runtime/DataView.cpp:
(JSC::DataView::wrap):
* runtime/GenericTypedArrayViewInlines.h:
(JSC::GenericTypedArrayView<Adaptor>::subarray):
* runtime/Intrinsic.h:
* runtime/JSArrayBuffer.cpp:
(JSC::JSArrayBuffer::finishCreation):
(JSC::JSArrayBuffer::isShared):
(JSC::JSArrayBuffer::sharingMode):
* runtime/JSArrayBuffer.h:
(JSC::toPossiblySharedArrayBuffer):
(JSC::toUnsharedArrayBuffer):
(JSC::JSArrayBuffer::toWrapped):
(JSC::toArrayBuffer): Deleted.
* runtime/JSArrayBufferConstructor.cpp:
(JSC::JSArrayBufferConstructor::JSArrayBufferConstructor):
(JSC::JSArrayBufferConstructor::finishCreation):
(JSC::JSArrayBufferConstructor::create):
(JSC::constructArrayBuffer):
* runtime/JSArrayBufferConstructor.h:
(JSC::JSArrayBufferConstructor::sharingMode):
* runtime/JSArrayBufferPrototype.cpp:
(JSC::arrayBufferProtoFuncSlice):
(JSC::JSArrayBufferPrototype::JSArrayBufferPrototype):
(JSC::JSArrayBufferPrototype::finishCreation):
(JSC::JSArrayBufferPrototype::create):
* runtime/JSArrayBufferPrototype.h:
* runtime/JSArrayBufferView.cpp:
(JSC::JSArrayBufferView::finishCreation):
(JSC::JSArrayBufferView::visitChildren):
(JSC::JSArrayBufferView::unsharedBuffer):
(JSC::JSArrayBufferView::unsharedJSBuffer):
(JSC::JSArrayBufferView::possiblySharedJSBuffer):
(JSC::JSArrayBufferView::neuter):
(JSC::JSArrayBufferView::toWrapped): Deleted.
* runtime/JSArrayBufferView.h:
(JSC::JSArrayBufferView::jsBuffer): Deleted.
* runtime/JSArrayBufferViewInlines.h:
(JSC::JSArrayBufferView::isShared):
(JSC::JSArrayBufferView::possiblySharedBuffer):
(JSC::JSArrayBufferView::possiblySharedImpl):
(JSC::JSArrayBufferView::unsharedImpl):
(JSC::JSArrayBufferView::byteOffset):
(JSC::JSArrayBufferView::toWrapped):
(JSC::JSArrayBufferView::buffer): Deleted.
(JSC::JSArrayBufferView::impl): Deleted.
(JSC::JSArrayBufferView::neuter): Deleted.
* runtime/JSDataView.cpp:
(JSC::JSDataView::possiblySharedTypedImpl):
(JSC::JSDataView::unsharedTypedImpl):
(JSC::JSDataView::getTypedArrayImpl):
(JSC::JSDataView::typedImpl): Deleted.
* runtime/JSDataView.h:
(JSC::JSDataView::possiblySharedBuffer):
(JSC::JSDataView::unsharedBuffer):
(JSC::JSDataView::buffer): Deleted.
* runtime/JSDataViewPrototype.cpp:
(JSC::dataViewProtoGetterBuffer):
* runtime/JSGenericTypedArrayView.h:
(JSC::toPossiblySharedNativeTypedView):
(JSC::toUnsharedNativeTypedView):
(JSC::JSGenericTypedArrayView<Adaptor>::toWrapped):
(JSC::JSGenericTypedArrayView::typedImpl): Deleted.
(JSC::toNativeTypedView): Deleted.
* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::JSGenericTypedArrayView<Adaptor>::create):
(JSC::JSGenericTypedArrayView<Adaptor>::possiblySharedTypedImpl):
(JSC::JSGenericTypedArrayView<Adaptor>::unsharedTypedImpl):
(JSC::JSGenericTypedArrayView<Adaptor>::getTypedArrayImpl):
* runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
(JSC::genericTypedArrayViewProtoGetterFuncBuffer):
(JSC::genericTypedArrayViewPrivateFuncSubarrayCreate):
* runtime/JSGlobalObject.cpp:
(JSC::createAtomicsProperty):
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::arrayBufferPrototype):
(JSC::JSGlobalObject::arrayBufferStructure):
* runtime/MathObject.cpp:
* runtime/RuntimeFlags.h:
* runtime/SimpleTypedArrayController.cpp:
(JSC::SimpleTypedArrayController::toJS):
* runtime/TypedArrayType.h:
(JSC::typedArrayTypeForType):

Source/WebCore:


New tests added in the LayoutTests/workers/sab directory.

This teaches WebCore that a typed array could be shared or not. By default, WebCore will
reject shared typed arrays as if they were not typed arrays. This ensures that we don't get
race conditions in code that can't handle it.

If you postMessage a SharedArrayBuffer or something that wraps it, you will send the shared
memory to the other worker.

* Modules/encryptedmedia/CDMSessionClearKey.cpp:
(WebCore::CDMSessionClearKey::cachedKeyForKeyID):
* Modules/fetch/FetchBody.cpp:
(WebCore::FetchBody::extract):
* Modules/mediastream/RTCDataChannel.cpp:
(WebCore::RTCDataChannel::send):
* Modules/webaudio/AudioBuffer.cpp:
(WebCore::AudioBuffer::getChannelData):
* Modules/websockets/WebSocket.cpp:
(WebCore::WebSocket::send):
* bindings/js/JSBlobCustom.cpp:
(WebCore::constructJSBlob):
* bindings/js/JSCryptoAlgorithmDictionary.cpp:
(WebCore::createRsaKeyGenParams):
* bindings/js/JSCryptoCustom.cpp:
(WebCore::JSCrypto::getRandomValues):
* bindings/js/JSCryptoOperationData.cpp:
(WebCore::cryptoOperationDataFromJSValue):
* bindings/js/JSDOMBinding.h:
(WebCore::toJS):
(WebCore::toPossiblySharedArrayBufferView):
(WebCore::toUnsharedArrayBufferView):
(WebCore::toPossiblySharedInt8Array):
(WebCore::toPossiblySharedInt16Array):
(WebCore::toPossiblySharedInt32Array):
(WebCore::toPossiblySharedUint8Array):
(WebCore::toPossiblySharedUint8ClampedArray):
(WebCore::toPossiblySharedUint16Array):
(WebCore::toPossiblySharedUint32Array):
(WebCore::toPossiblySharedFloat32Array):
(WebCore::toPossiblySharedFloat64Array):
(WebCore::toUnsharedInt8Array):
(WebCore::toUnsharedInt16Array):
(WebCore::toUnsharedInt32Array):
(WebCore::toUnsharedUint8Array):
(WebCore::toUnsharedUint8ClampedArray):
(WebCore::toUnsharedUint16Array):
(WebCore::toUnsharedUint32Array):
(WebCore::toUnsharedFloat32Array):
(WebCore::toUnsharedFloat64Array):
(WebCore::toArrayBufferView): Deleted.
(WebCore::toInt8Array): Deleted.
(WebCore::toInt16Array): Deleted.
(WebCore::toInt32Array): Deleted.
(WebCore::toUint8Array): Deleted.
(WebCore::toUint8ClampedArray): Deleted.
(WebCore::toUint16Array): Deleted.
(WebCore::toUint32Array): Deleted.
(WebCore::toFloat32Array): Deleted.
(WebCore::toFloat64Array): Deleted.
* bindings/js/JSDataCueCustom.cpp:
(WebCore::constructJSDataCue):
* bindings/js/JSDictionary.cpp:
(WebCore::JSDictionary::convertValue):
* bindings/js/JSFileCustom.cpp:
(WebCore::constructJSFile):
* bindings/js/JSMessagePortCustom.cpp:
(WebCore::extractTransferables):
* bindings/js/JSWebGLRenderingContextBaseCustom.cpp:
(WebCore::dataFunctionf):
(WebCore::dataFunctioni):
(WebCore::dataFunctionMatrix):
* bindings/js/JSXMLHttpRequestCustom.cpp:
(WebCore::JSXMLHttpRequest::send):
* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::dumpArrayBufferView):
(WebCore::CloneSerializer::dumpIfTerminal):
(WebCore::CloneDeserializer::readArrayBufferView):
(WebCore::CloneDeserializer::readTerminal):
(WebCore::SerializedScriptValue::transferArrayBuffers):
* bindings/js/StructuredClone.cpp:
(WebCore::structuredCloneArrayBuffer):
(WebCore::structuredCloneArrayBufferView):
* bindings/scripts/CodeGeneratorJS.pm:
(JSValueToNative):
* css/FontFace.cpp:
(WebCore::FontFace::create):
* html/canvas/WebGL2RenderingContext.cpp:
(WebCore::WebGL2RenderingContext::bufferData):
(WebCore::WebGL2RenderingContext::bufferSubData):
* platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp:
(WebCore::MediaPlayerPrivateAVFoundation::extractKeyURIKeyIDAndCertificateFromInitData):

Source/WebKit/mac:


Support the RuntimeFlag.

* WebView/WebPreferencesPrivate.h:

Source/WebKit/win:


Support the RuntimeFlag.

* Interfaces/IWebPreferencesPrivate.idl:

Source/WebKit2:


Adds some small things we need for SharedArrayBuffer.

* UIProcess/API/C/WKPreferencesRefPrivate.h:
* UIProcess/API/Cocoa/WKPreferencesPrivate.h:
* WebProcess/InjectedBundle/InjectedBundle.cpp:
(WebKit::InjectedBundle::createWebDataFromUint8Array):

Source/WTF:


Adds some small things we need for SharedArrayBuffer.

* wtf/Atomics.h:
(WTF::Atomic::compareExchangeWeakRelaxed):
(WTF::Atomic::exchangeAdd):
(WTF::Atomic::exchangeAnd):
(WTF::Atomic::exchangeOr):
(WTF::Atomic::exchangeSub):
(WTF::Atomic::exchangeXor):
(WTF::atomicLoad):
(WTF::atomicStore):
(WTF::atomicCompareExchangeWeak):
(WTF::atomicCompareExchangeWeakRelaxed):
(WTF::atomicCompareExchangeStrong):
(WTF::atomicExchangeAdd):
(WTF::atomicExchangeAnd):
(WTF::atomicExchangeOr):
(WTF::atomicExchangeSub):
(WTF::atomicExchangeXor):
(WTF::atomicExchange):
(WTF::Atomic::exchangeAndAdd): Deleted.
(WTF::weakCompareAndSwap): Deleted.
We need to be able to do atomics operations on naked pointers. We also need to be able to do
all of the things that std::atomic does. This adds those things and renames
weakCompareAndSwap to atomicCompareExchangeWeakRelaxed so that we're using consistent
terminology.

* wtf/Bitmap.h:
(WTF::WordType>::concurrentTestAndSet): Renamed weakCompareAndSwap.
(WTF::WordType>::concurrentTestAndClear): Renamed weakCompareAndSwap.
* wtf/FastBitVector.h:
(WTF::FastBitVector::atomicSetAndCheck): Renamed weakCompareAndSwap.
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
Added unparkCount(), which lets you unpark some bounded number of threads and returns the
number of threads unparked. This is just a modest extension of unparkAll(). unparkAll() now
just calls unparkCount(ptr, UINT_MAX).

Tools:


Use the right kind of typed array API.

* DumpRenderTree/TestRunner.cpp:
(setAudioResultCallback):

LayoutTests:


Adding tests. This is a work in progress.

* workers/sab: Added.
* workers/sab/simple-worker-1.js: Added.
(onmessage):
* workers/sab/simple-worker-2.js: Added.
(onmessage):
* workers/sab/simple.html: Added.



Canonical link: https://commits.webkit.org/181984@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208209 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants