Ignore:
Timestamp:
Nov 17, 2020, 7:46:39 PM (5 years ago)
Author:
[email protected]
Message:

[JSC] Implement WebAssembly.Memory with shared
https://bugs.webkit.org/show_bug.cgi?id=218693

Reviewed by Saam Barati.

JSTests:

  • wasm/function-tests/trap-load-shared.js: Added.

(wasmFrameCountFromError):

  • wasm/function-tests/trap-store-shared.js: Added.
  • wasm/js-api/test_memory.js:

(binaryShouldNotParse):

  • wasm/stress/shared-memory-errors.js: Added.

(assert.throws):

  • wasm/stress/shared-wasm-memory-buffer.js: Added.

LayoutTests/imported/w3c:

  • web-platform-tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/requires-success.any.worker-expected.txt:
  • web-platform-tests/wasm/jsapi/memory/constructor-shared.tentative.any-expected.txt:
  • web-platform-tests/wasm/jsapi/memory/constructor-shared.tentative.any.worker-expected.txt:
  • web-platform-tests/wasm/jsapi/memory/constructor.any-expected.txt:
  • web-platform-tests/wasm/jsapi/memory/constructor.any.worker-expected.txt:
  • web-platform-tests/wasm/jsapi/memory/grow.any-expected.txt:
  • web-platform-tests/wasm/jsapi/memory/grow.any.worker-expected.txt:
  • web-platform-tests/webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-copy-channel-expected.txt:

Source/JavaScriptCore:

This patch implements shared WebAssembly.Memory. This can be shared between workers like SharedArrayBuffer.
The most interesting thing of shared WebAssembly.Memory is that it is growable. The memory can be grown in
one thread, and immediately, it should be accessible in the other threads.

To achieve that, shared WebAssembly.Memory leverages signaling even if bounds-checking is mainly used.
If the fast memory is enabled, we just use it so that mprotect can make memory grown easily. But if fast memory
is disabled, we allocates requested VA region and perform bounds-checking with this VA. Since WebAssembly.Memory
always requires "maximum" size of memory, we can first allocate VA and map active part of memory first. And
when growing, we perform mprotect to the rest of the memory. Since this VA is not 4GB, we still need to perform
bounds-checking, but we perform bounds-checking with VA size instead of active memory size. As a result, even if
shared WebAssembly.Memory is grown, we do not need to update (1) pointer and (2) bounds-checking size.
The shared bounds-checking WebAssembly.Memory is something like below.

<================================================ maximum ============================><------------ other memory, protected by bounds-checking --...
<======= active ==========><===================== not active yet =====================>
[ if we access this, fault handler will detect it]
pointer bounds checking size

These "growable bound-checking memory" is now managed by wasm memory-manager. And fault handler is used even if fast memory is disabled.
And fault handler also accepts signals from Wasm LLInt code since both bounds-checkings + signalings are required to confine memory access even in
Wasm LLInt. This patch also renamed memory-size and size-register to bounds-checking-size and bounds-checking-size-register since this is no longer
a size of memory.

  • CMakeLists.txt:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • llint/LLIntPCRanges.h:

(JSC::LLInt::isWasmLLIntPC):

  • llint/LowLevelInterpreter.asm:
  • llint/WebAssembly.asm:
  • runtime/JSArrayBuffer.h:

(JSC::JSArrayBuffer::toWrappedAllowShared):

  • runtime/JSArrayBufferView.h:
  • runtime/JSArrayBufferViewInlines.h:

(JSC::JSArrayBufferView::toWrappedAllowShared):

  • runtime/JSGenericTypedArrayView.h:

(JSC::JSGenericTypedArrayView<Adaptor>::toWrappedAllowShared):

  • runtime/Options.cpp:

(JSC::overrideDefaults):
(JSC::Options::initialize):

  • wasm/WasmAirIRGenerator.cpp:

(JSC::Wasm::AirIRGenerator::AirIRGenerator):
(JSC::Wasm::AirIRGenerator::restoreWebAssemblyGlobalState):
(JSC::Wasm::AirIRGenerator::addCurrentMemory):
(JSC::Wasm::AirIRGenerator::emitCheckAndPreparePointer):
(JSC::Wasm::AirIRGenerator::addCall):
(JSC::Wasm::AirIRGenerator::addCallIndirect):

  • wasm/WasmB3IRGenerator.cpp:

(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::B3IRGenerator::restoreWebAssemblyGlobalState):
(JSC::Wasm::B3IRGenerator::addCurrentMemory):
(JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer):
(JSC::Wasm::B3IRGenerator::addCall):
(JSC::Wasm::B3IRGenerator::addCallIndirect):

  • wasm/WasmBinding.cpp:

(JSC::Wasm::wasmToWasm):

  • wasm/WasmFaultSignalHandler.cpp:

(JSC::Wasm::trapHandler):
(JSC::Wasm::enableFastMemory):
(JSC::Wasm::prepareFastMemory):

  • wasm/WasmInstance.h:

(JSC::Wasm::Instance::cachedMemory const):
(JSC::Wasm::Instance::cachedBoundsCheckingSize const):
(JSC::Wasm::Instance::updateCachedMemory):
(JSC::Wasm::Instance::offsetOfCachedBoundsCheckingSize):
(JSC::Wasm::Instance::cachedMemorySize const): Deleted.
(JSC::Wasm::Instance::offsetOfCachedMemorySize): Deleted.

  • wasm/WasmMemory.cpp:

(JSC::Wasm::MemoryHandle::MemoryHandle):
(JSC::Wasm::MemoryHandle::~MemoryHandle):
(JSC::Wasm::Memory::Memory):
(JSC::Wasm::Memory::create):
(JSC::Wasm::Memory::tryCreate):
(JSC::Wasm::Memory::addressIsInGrowableOrFastMemory):
(JSC::Wasm::Memory::growShared):
(JSC::Wasm::Memory::grow):
(JSC::Wasm::Memory::dump const):
(JSC::Wasm::Memory::~Memory): Deleted.
(JSC::Wasm::Memory::addressIsInActiveFastMemory): Deleted.

  • wasm/WasmMemory.h:

(JSC::Wasm::Memory::addressIsInGrowableOrFastMemory):
(JSC::Wasm::Memory::operator bool const): Deleted.
(JSC::Wasm::Memory::memory const): Deleted.
(JSC::Wasm::Memory::size const): Deleted.
(JSC::Wasm::Memory::sizeInPages const): Deleted.
(JSC::Wasm::Memory::initial const): Deleted.
(JSC::Wasm::Memory::maximum const): Deleted.
(JSC::Wasm::Memory::mode const): Deleted.
(JSC::Wasm::Memory::check): Deleted.
(JSC::Wasm::Memory::offsetOfMemory): Deleted.
(JSC::Wasm::Memory::offsetOfSize): Deleted.
(JSC::Wasm::Memory::addressIsInActiveFastMemory): Deleted.

  • wasm/WasmMemoryInformation.cpp:

(JSC::Wasm::PinnedRegisterInfo::get):
(JSC::Wasm::PinnedRegisterInfo::PinnedRegisterInfo):

  • wasm/WasmMemoryInformation.h:

(JSC::Wasm::PinnedRegisterInfo::toSave const):

  • wasm/WasmMemoryMode.cpp:

(JSC::Wasm::makeString):

  • wasm/WasmMemoryMode.h:
  • wasm/js/JSToWasm.cpp:

(JSC::Wasm::createJSToWasmWrapper):

  • wasm/js/JSWebAssemblyInstance.cpp:

(JSC::JSWebAssemblyInstance::tryCreate):

  • wasm/js/JSWebAssemblyMemory.cpp:

(JSC::JSWebAssemblyMemory::buffer):
(JSC::JSWebAssemblyMemory::growSuccessCallback):

  • wasm/js/JSWebAssemblyMemory.h:
  • wasm/js/WebAssemblyFunction.cpp:

(JSC::WebAssemblyFunction::jsCallEntrypointSlow):

  • wasm/js/WebAssemblyMemoryConstructor.cpp:

(JSC::JSC_DEFINE_HOST_FUNCTION):

  • wasm/js/WebAssemblyMemoryPrototype.cpp:

(JSC::JSC_DEFINE_HOST_FUNCTION):

  • wasm/js/WebAssemblyModuleRecord.cpp:

(JSC::WebAssemblyModuleRecord::evaluate):

Source/WebCore:

In WebCore, we need three things.

  1. Shared WebAssembly.Memory serialization/deserialization

This patch adds structure-cloning for WebAssembly.Memory to pass it to the other workers. Cloning is available
only when the WebAssembly.Memory is shared mode. And it is only available when we are using it in postMessage.
So we cannot store WebAssembly.Memory in IndexedDB.

  1. WebCoreTypedArrayController::isAtomicsWaitAllowedOnCurrentThread

Atomics.wait is usable only in Workers, and *not* usable in Service Workers. When creating VM, we pass WorkerThreadType
and make WebCoreTypedArrayController::isAtomicsWaitAllowedOnCurrentThread return appropriate value.

  1. [AllowShared] support for WPT

WPT tests for this are broken, and tests are saying "PASS" while the feature is not implemented at all.
Now, the feature is actually implemented, and WPT tests start showing that [AllowShared] annotation in IDL
is not implemented. [AllowShared] is that, usually, DOM does not accept TypedArray originated from SharedArrayBuffer.
e.g. encodeInto(..., Uint8Array) DOM IDL throws an error if Uint8Array is backed by SharedArrayBuffer.
But in the limited places, we are explicitly allowing this. This is [AllowShared] annotation.
This patch implements that so that we keep passing TextEncoder / TextDecoder tests.

  • Headers.cmake:
  • Modules/indexeddb/server/IDBSerializationContext.cpp:

(WebCore::IDBServer::IDBSerializationContext::initializeVM):

  • WebCore.xcodeproj/project.pbxproj:
  • bindings/IDLTypes.h:
  • bindings/js/CommonVM.cpp:

(WebCore::commonVMSlow):

  • bindings/js/JSDOMConvertBufferSource.h:

(WebCore::Detail::BufferSourceConverter::convert):
(WebCore::Converter<IDLArrayBuffer>::convert):
(WebCore::Converter<IDLDataView>::convert):
(WebCore::Converter<IDLInt8Array>::convert):
(WebCore::Converter<IDLInt16Array>::convert):
(WebCore::Converter<IDLInt32Array>::convert):
(WebCore::Converter<IDLUint8Array>::convert):
(WebCore::Converter<IDLUint16Array>::convert):
(WebCore::Converter<IDLUint32Array>::convert):
(WebCore::Converter<IDLUint8ClampedArray>::convert):
(WebCore::Converter<IDLFloat32Array>::convert):
(WebCore::Converter<IDLFloat64Array>::convert):
(WebCore::Converter<IDLArrayBufferView>::convert):
(WebCore::Converter<IDLAllowSharedAdaptor<T>>::convert):

  • bindings/js/JSDOMConvertUnion.h:
  • bindings/js/SerializedScriptValue.cpp:

(WebCore::CloneSerializer::serialize):
(WebCore::CloneSerializer::CloneSerializer):
(WebCore::CloneSerializer::dumpIfTerminal):
(WebCore::CloneDeserializer::deserialize):
(WebCore::CloneDeserializer::CloneDeserializer):
(WebCore::CloneDeserializer::readTerminal):
(WebCore::SerializedScriptValue::SerializedScriptValue):
(WebCore::SerializedScriptValue::computeMemoryCost const):
(WebCore::SerializedScriptValue::create):
(WebCore::SerializedScriptValue::deserialize):

  • bindings/js/SerializedScriptValue.h:
  • bindings/js/WebCoreJSClientData.cpp:

(WebCore::JSVMClientData::initNormalWorld):

  • bindings/js/WebCoreJSClientData.h:
  • bindings/js/WebCoreTypedArrayController.cpp:

(WebCore::WebCoreTypedArrayController::WebCoreTypedArrayController):
(WebCore::WebCoreTypedArrayController::isAtomicsWaitAllowedOnCurrentThread):

  • bindings/js/WebCoreTypedArrayController.h:
  • bindings/scripts/CodeGeneratorJS.pm:

(IsAnnotatedType):
(GetAnnotatedIDLType):

  • bindings/scripts/IDLAttributes.json:
  • bindings/scripts/test/JS/JSTestObj.cpp:

(WebCore::JSTestObjDOMConstructor::construct):
(WebCore::jsTestObjPrototypeFunction_encodeIntoBody):
(WebCore::JSC_DEFINE_HOST_FUNCTION):

  • bindings/scripts/test/TestObj.idl:
  • dom/TextDecoder.idl:
  • dom/TextDecoderStreamDecoder.idl:
  • dom/TextEncoder.idl:
  • workers/DedicatedWorkerGlobalScope.cpp:

(WebCore::DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope):

  • workers/WorkerGlobalScope.cpp:

(WebCore::WorkerGlobalScope::WorkerGlobalScope):

  • workers/WorkerGlobalScope.h:
  • workers/WorkerOrWorkletGlobalScope.cpp:

(WebCore::WorkerOrWorkletGlobalScope::WorkerOrWorkletGlobalScope):

  • workers/WorkerOrWorkletGlobalScope.h:
  • workers/WorkerOrWorkletScriptController.cpp:

(WebCore::WorkerOrWorkletScriptController::WorkerOrWorkletScriptController):

  • workers/WorkerOrWorkletScriptController.h:
  • workers/WorkerThreadType.h: Added.
  • workers/service/ServiceWorkerGlobalScope.cpp:

(WebCore::ServiceWorkerGlobalScope::ServiceWorkerGlobalScope):

  • worklets/WorkletGlobalScope.cpp:

(WebCore::WorkletGlobalScope::WorkletGlobalScope):

LayoutTests:

  • js/dom/resources/webassembly-memory-normal-fail-worker.js: Added.
  • js/dom/resources/webassembly-memory-shared-worker.js: Added.

(onmessage):

  • js/dom/webassembly-memory-normal-fail-expected.txt: Added.
  • js/dom/webassembly-memory-normal-fail.html: Added.
  • js/dom/webassembly-memory-shared-basic-expected.txt: Added.
  • js/dom/webassembly-memory-shared-basic.html: Added.
  • js/dom/webassembly-memory-shared-fail-expected.txt: Added.
  • js/dom/webassembly-memory-shared-fail.html: Added.
  • platform/win/TestExpectations:
  • storage/indexeddb/resources/shared-memory-structured-clone.js: Added.

(prepareDatabase):
(async startTests):
(testSharedWebAssemblyMemory):

  • storage/indexeddb/shared-memory-structured-clone-expected.txt: Added.
  • storage/indexeddb/shared-memory-structured-clone.html: Added.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/llint/LLIntPCRanges.h

    r268247 r269940  
    3636    void llintPCRangeStart();
    3737    void llintPCRangeEnd();
     38#if ENABLE(WEBASSEMBLY)
     39    void wasmLLIntPCRangeStart();
     40    void wasmLLIntPCRangeEnd();
     41#endif
    3842}
    3943
     
    4751}
    4852
     53#if ENABLE(WEBASSEMBLY)
     54ALWAYS_INLINE bool isWasmLLIntPC(void* pc)
     55{
     56    uintptr_t pcAsInt = bitwise_cast<uintptr_t>(pc);
     57    uintptr_t start = untagCodePtr<uintptr_t, CFunctionPtrTag>(wasmLLIntPCRangeStart);
     58    uintptr_t end = untagCodePtr<uintptr_t, CFunctionPtrTag>(wasmLLIntPCRangeEnd);
     59    RELEASE_ASSERT(start < end);
     60    return start <= pcAsInt && pcAsInt <= end;
     61}
     62#endif
     63
    4964#if !ENABLE(C_LOOP)
    5065static constexpr GPRReg LLIntPC = GPRInfo::regT4;
Note: See TracChangeset for help on using the changeset viewer.