Changeset 228966 in webkit


Ignore:
Timestamp:
Feb 23, 2018 3:16:59 PM (6 years ago)
Author:
gskachkov@gmail.com
Message:

WebAssembly: cache memory address / size on instance
https://bugs.webkit.org/show_bug.cgi?id=177305

Reviewed by JF Bastien.

JSTests:

  • wasm/function-tests/memory-reuse.js: Added.

(createWasmInstance):
(doCheckTrap):
(doMemoryGrow):
(doCheck):
(checkWasmInstancesWithSharedMemory):

Source/JavaScriptCore:

Cache memory address/size in wasm:Instance to avoid load wasm:Memory
object during access to memory and memory size property in JiT

  • wasm/WasmB3IRGenerator.cpp:

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

  • wasm/WasmBinding.cpp:

(JSC::Wasm::wasmToWasm):

  • wasm/WasmInstance.h:

(JSC::Wasm::Instance::cachedMemory const):
(JSC::Wasm::Instance::cachedMemorySize const):
(JSC::Wasm::Instance::createWeakPtr):
(JSC::Wasm::Instance::setMemory):
(JSC::Wasm::Instance::updateCachedMemory):
(JSC::Wasm::Instance::offsetOfCachedMemory):
(JSC::Wasm::Instance::offsetOfCachedMemorySize):
(JSC::Wasm::Instance::offsetOfCachedIndexingMask):
(JSC::Wasm::Instance::allocationSize):

  • wasm/WasmMemory.cpp:

(JSC::Wasm::Memory::grow):
(JSC::Wasm::Memory::registerInstance):

  • wasm/WasmMemory.h:

(JSC::Wasm::Memory::indexingMask):

  • wasm/js/JSToWasm.cpp:

(JSC::Wasm::createJSToWasmWrapper):

  • wasm/js/WebAssemblyModuleRecord.cpp:

(JSC::WebAssemblyModuleRecord::evaluate):

Location:
trunk
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r228950 r228966  
     12018-02-23  Oleksandr Skachkov  <gskachkov@gmail.com>
     2
     3        WebAssembly: cache memory address / size on instance
     4        https://bugs.webkit.org/show_bug.cgi?id=177305
     5
     6        Reviewed by JF Bastien.
     7
     8        * wasm/function-tests/memory-reuse.js: Added.
     9        (createWasmInstance):
     10        (doCheckTrap):
     11        (doMemoryGrow):
     12        (doCheck):
     13        (checkWasmInstancesWithSharedMemory):
     14
    1152018-02-23  Yusuke Suzuki  <utatane.tea@gmail.com>
    216
  • trunk/Source/JavaScriptCore/ChangeLog

    r228952 r228966  
     12018-02-23  Oleksandr Skachkov  <gskachkov@gmail.com>
     2
     3        WebAssembly: cache memory address / size on instance
     4        https://bugs.webkit.org/show_bug.cgi?id=177305
     5
     6        Reviewed by JF Bastien.
     7
     8        Cache memory address/size in wasm:Instance to avoid load wasm:Memory
     9        object during access to memory and memory size property in JiT
     10
     11        * wasm/WasmB3IRGenerator.cpp:
     12        (JSC::Wasm::B3IRGenerator::restoreWebAssemblyGlobalState):
     13        (JSC::Wasm::B3IRGenerator::addCurrentMemory):
     14        (JSC::Wasm::B3IRGenerator::addCallIndirect):
     15        * wasm/WasmBinding.cpp:
     16        (JSC::Wasm::wasmToWasm):
     17        * wasm/WasmInstance.h:
     18        (JSC::Wasm::Instance::cachedMemory const):
     19        (JSC::Wasm::Instance::cachedMemorySize const):
     20        (JSC::Wasm::Instance::createWeakPtr):
     21        (JSC::Wasm::Instance::setMemory):
     22        (JSC::Wasm::Instance::updateCachedMemory):
     23        (JSC::Wasm::Instance::offsetOfCachedMemory):
     24        (JSC::Wasm::Instance::offsetOfCachedMemorySize):
     25        (JSC::Wasm::Instance::offsetOfCachedIndexingMask):
     26        (JSC::Wasm::Instance::allocationSize):
     27        * wasm/WasmMemory.cpp:
     28        (JSC::Wasm::Memory::grow):
     29        (JSC::Wasm::Memory::registerInstance):
     30        * wasm/WasmMemory.h:
     31        (JSC::Wasm::Memory::indexingMask):
     32        * wasm/js/JSToWasm.cpp:
     33        (JSC::Wasm::createJSToWasmWrapper):
     34        * wasm/js/WebAssemblyModuleRecord.cpp:
     35        (JSC::WebAssemblyModuleRecord::evaluate):
     36
    1372018-02-23  Saam Barati  <sbarati@apple.com>
    238
  • trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp

    r226615 r228966  
    486486        patchpoint->setGenerator([pinnedRegs] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    487487            GPRReg baseMemory = pinnedRegs->baseMemoryPointer;
    488             jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfMemory()), baseMemory);
    489488            const auto& sizeRegs = pinnedRegs->sizeRegisters;
    490489            ASSERT(sizeRegs.size() >= 1);
    491490            ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
    492             jit.loadPtr(CCallHelpers::Address(baseMemory, Memory::offsetOfSize()), sizeRegs[0].sizeRegister);
    493             jit.loadPtr(CCallHelpers::Address(baseMemory, Memory::offsetOfIndexingMask()), pinnedRegs->indexingMask);
    494             jit.loadPtr(CCallHelpers::Address(baseMemory, Memory::offsetOfMemory()), baseMemory);
     491            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemorySize()), sizeRegs[0].sizeRegister);
     492            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedIndexingMask()), pinnedRegs->indexingMask);
     493            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemory()), baseMemory);
    495494            for (unsigned i = 1; i < sizeRegs.size(); ++i)
    496495                jit.add64(CCallHelpers::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
     
    605604auto B3IRGenerator::addCurrentMemory(ExpressionType& result) -> PartialResult
    606605{
    607     Value* memoryObject = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), instanceValue(), safeCast<int32_t>(Instance::offsetOfMemory()));
    608 
    609606    static_assert(sizeof(decltype(static_cast<Memory*>(nullptr)->size())) == sizeof(uint64_t), "codegen relies on this size");
    610     Value* size = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int64, origin(), memoryObject, safeCast<int32_t>(Memory::offsetOfSize()));
    611    
     607    Value* size = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int64, origin(), instanceValue(), safeCast<int32_t>(Instance::offsetOfCachedMemorySize()));
     608
    612609    constexpr uint32_t shiftValue = 16;
    613610    static_assert(PageCount::pageSize == 1ull << shiftValue, "This must hold for the code below to be correct.");
     
    13001297            jit.storePtr(baseMemory, CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedStackLimit()));
    13011298            jit.storeWasmContextInstance(newContextInstance);
    1302             jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfMemory()), baseMemory); // Memory*.
     1299            ASSERT(sizeRegs[0].sizeRegister != baseMemory);
     1300            // FIXME: We should support more than one memory size register
     1301            //   see: https://bugs.webkit.org/show_bug.cgi?id=162952
    13031302            ASSERT(sizeRegs.size() == 1);
    1304             ASSERT(sizeRegs[0].sizeRegister != baseMemory);
    13051303            ASSERT(sizeRegs[0].sizeRegister != newContextInstance);
    13061304            ASSERT(!sizeRegs[0].sizeOffset);
    1307             jit.loadPtr(CCallHelpers::Address(baseMemory, Memory::offsetOfIndexingMask()), pinnedRegs.indexingMask); // Indexing mask.
    1308             jit.loadPtr(CCallHelpers::Address(baseMemory, Memory::offsetOfSize()), sizeRegs[0].sizeRegister); // Memory size.
    1309             jit.loadPtr(CCallHelpers::Address(baseMemory, Memory::offsetOfMemory()), baseMemory); // Memory::void*.
     1305            jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedIndexingMask()), pinnedRegs.indexingMask); // Indexing mask.
     1306            jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemorySize()), sizeRegs[0].sizeRegister); // Memory size.
     1307            jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
    13101308        });
    13111309        doContextSwitch->appendNewControlValue(m_proc, Jump, origin(), continuation);
  • trunk/Source/JavaScriptCore/wasm/WasmBinding.cpp

    r226461 r228966  
    6565    // FIXME the following code assumes that all Wasm::Instance have the same pinned registers. https://bugs.webkit.org/show_bug.cgi?id=162952
    6666    // Set up the callee's baseMemory register as well as the memory size registers.
    67     jit.loadPtr(JIT::Address(baseMemory, Instance::offsetOfMemory()), baseMemory); // Wasm::Memory*.
    6867    ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
    69     jit.loadPtr(CCallHelpers::Address(baseMemory, Memory::offsetOfIndexingMask()), pinnedRegs.indexingMask); // Indexing mask.
    70     jit.loadPtr(JIT::Address(baseMemory, Wasm::Memory::offsetOfSize()), sizeRegs[0].sizeRegister); // Memory size.
    71     jit.loadPtr(JIT::Address(baseMemory, Wasm::Memory::offsetOfMemory()), baseMemory); // Wasm::Memory::void*.
     68    jit.loadPtr(JIT::Address(baseMemory, Wasm::Instance::offsetOfCachedIndexingMask()), pinnedRegs.indexingMask); // Indexing mask.
     69    jit.loadPtr(JIT::Address(baseMemory, Wasm::Instance::offsetOfCachedMemorySize()), sizeRegs[0].sizeRegister); // Memory size.
     70    jit.loadPtr(JIT::Address(baseMemory, Wasm::Instance::offsetOfCachedMemory()), baseMemory); // Wasm::Memory::void*.
    7271    for (unsigned i = 1; i < sizeRegs.size(); ++i) {
    7372        ASSERT(sizeRegs[i].sizeRegister != baseMemory);
  • trunk/Source/JavaScriptCore/wasm/WasmInstance.h

    r226920 r228966  
    6666    Memory* memory() { return m_memory.get(); }
    6767    Table* table() { return m_table.get(); }
    68    
    69     void setMemory(Ref<Memory>&& memory) { m_memory = WTFMove(memory); }
     68
     69    void* cachedMemory() const { return m_cachedMemory; }
     70    size_t cachedMemorySize() const { return m_cachedMemorySize; }
     71
     72    WeakPtr<Instance> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(*this); }
     73    void setMemory(Ref<Memory>&& memory)
     74    {
     75        m_memory = WTFMove(memory);
     76        m_memory.get()->registerInstance(this);
     77        updateCachedMemory();
     78    }
     79    void updateCachedMemory()
     80    {
     81        if (m_memory != nullptr) {
     82            m_cachedMemory = memory()->memory();
     83            m_cachedMemorySize = memory()->size();
     84            m_cachedIndexingMask = memory()->indexingMask();
     85        }
     86    }
    7087    void setTable(Ref<Table>&& table) { m_table = WTFMove(table); }
    7188
     
    7996    static ptrdiff_t offsetOfGlobals() { return OBJECT_OFFSETOF(Instance, m_globals); }
    8097    static ptrdiff_t offsetOfTable() { return OBJECT_OFFSETOF(Instance, m_table); }
     98    static ptrdiff_t offsetOfCachedMemory() { return OBJECT_OFFSETOF(Instance, m_cachedMemory); }
     99    static ptrdiff_t offsetOfCachedMemorySize() { return OBJECT_OFFSETOF(Instance, m_cachedMemorySize); }
     100    static ptrdiff_t offsetOfCachedIndexingMask() { return OBJECT_OFFSETOF(Instance, m_cachedIndexingMask); }
    81101    static ptrdiff_t offsetOfPointerToTopEntryFrame() { return OBJECT_OFFSETOF(Instance, m_pointerToTopEntryFrame); }
    82102
     
    127147        return (offsetOfTail() + sizeof(ImportFunctionInfo) * numImportFunctions).unsafeGet();
    128148    }
    129 
    130149    void* m_owner { nullptr }; // In a JS embedding, this is a JSWebAssemblyInstance*.
    131150    Context* m_context { nullptr };
     151    void* m_cachedMemory { nullptr };
     152    size_t m_cachedMemorySize { 0 };
     153    size_t m_cachedIndexingMask { 0 };
    132154    Ref<Module> m_module;
    133155    RefPtr<CodeBlock> m_codeBlock;
     
    139161    void* m_cachedStackLimit { bitwise_cast<void*>(std::numeric_limits<uintptr_t>::max()) };
    140162    StoreTopCallFrameCallback m_storeTopCallFrame;
     163    WeakPtrFactory<Instance> m_weakPtrFactory;
    141164    unsigned m_numImportFunctions { 0 };
    142165};
  • trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp

    r227951 r228966  
    2626#include "config.h"
    2727#include "WasmMemory.h"
     28#include "WasmInstance.h"
    2829
    2930#if ENABLE(WEBASSEMBLY)
     
    378379    auto success = [&] () {
    379380        m_growSuccessCallback(GrowSuccessTag, oldPageCount, newPageCount);
     381        // Update cache for instance
     382        for (auto& instance : m_instances) {
     383            if (instance.get() != nullptr)
     384                instance.get()->updateCachedMemory();
     385        }
    380386        return oldPageCount;
    381387    };
     
    438444}
    439445
     446void Memory::registerInstance(Instance* instance)
     447{
     448    size_t count = m_instances.size();
     449    for (size_t index = 0; index < count; index++) {
     450        if (m_instances.at(index).get() == nullptr) {
     451            m_instances.at(index) = instance->createWeakPtr();
     452            return;
     453        }
     454    }
     455    m_instances.append(instance->createWeakPtr());
     456}
     457
    440458void Memory::dump(PrintStream& out) const
    441459{
  • trunk/Source/JavaScriptCore/wasm/WasmMemory.h

    r226461 r228966  
    3535#include <wtf/RefCounted.h>
    3636#include <wtf/RefPtr.h>
     37#include <wtf/Vector.h>
     38#include <wtf/WeakPtr.h>
    3739
    3840namespace WTF {
     
    4345
    4446namespace Wasm {
     47
     48class Instance;
    4549
    4650class Memory : public RefCounted<Memory> {
     
    6771    void* memory() const { return m_memory; }
    6872    size_t size() const { return m_size; }
     73    size_t indexingMask() { return m_indexingMask; }
    6974    PageCount sizeInPages() const { return PageCount::fromBytes(m_size); }
    7075
     
    8186    };
    8287    Expected<PageCount, GrowFailReason> grow(PageCount);
     88    void registerInstance(Instance*);
    8389
    8490    void check() {  ASSERT(!deletionHasBegun()); }
     
    9399    Memory(PageCount initial, PageCount maximum, WTF::Function<void(NotifyPressure)>&& notifyMemoryPressure, WTF::Function<void(SyncTryToReclaim)>&& syncTryToReclaimMemory, WTF::Function<void(GrowSuccess, PageCount, PageCount)>&& growSuccessCallback);
    94100
    95     // FIXME: we cache these on the instances to avoid a load on instance->instance calls. This will require updating all the instances when grow is called. https://bugs.webkit.org/show_bug.cgi?id=177305
    96101    void* m_memory { nullptr };
    97102    size_t m_size { 0 };
     
    104109    WTF::Function<void(SyncTryToReclaim)> m_syncTryToReclaimMemory;
    105110    WTF::Function<void(GrowSuccess, PageCount, PageCount)> m_growSuccessCallback;
     111    Vector<WeakPtr<Instance>> m_instances;
    106112};
    107113
  • trunk/Source/JavaScriptCore/wasm/js/JSToWasm.cpp

    r227527 r228966  
    176176        GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
    177177
    178         if (!Context::useFastTLS())
    179             jit.loadPtr(CCallHelpers::Address(wasmContextInstanceGPR, Instance::offsetOfMemory()), baseMemory);
    180         else {
     178        if (Context::useFastTLS())
    181179            jit.loadWasmContextInstance(baseMemory);
    182             jit.loadPtr(CCallHelpers::Address(baseMemory, Instance::offsetOfMemory()), baseMemory);
    183         }
    184 
     180
     181        GPRReg currentInstanceGPR = Context::useFastTLS() ? baseMemory : wasmContextInstanceGPR;
    185182        if (mode != MemoryMode::Signaling) {
    186             jit.loadPtr(CCallHelpers::Address(baseMemory, Wasm::Memory::offsetOfIndexingMask()), pinnedRegs.indexingMask);
     183            jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedIndexingMask()), pinnedRegs.indexingMask);
    187184            const auto& sizeRegs = pinnedRegs.sizeRegisters;
    188185            ASSERT(sizeRegs.size() >= 1);
    189186            ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
    190             jit.loadPtr(CCallHelpers::Address(baseMemory, Wasm::Memory::offsetOfSize()), sizeRegs[0].sizeRegister);
     187            jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemorySize()), sizeRegs[0].sizeRegister);
    191188            for (unsigned i = 1; i < sizeRegs.size(); ++i)
    192189                jit.add64(CCallHelpers::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
    193190        }
    194191
    195         jit.loadPtr(CCallHelpers::Address(baseMemory, Wasm::Memory::offsetOfMemory()), baseMemory);
     192        jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemory()), baseMemory);
    196193    }
    197194
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp

    r226920 r228966  
    224224
    225225    const Vector<Wasm::Segment::Ptr>& data = moduleInformation.data;
    226     JSWebAssemblyMemory* jsMemory = m_instance->memory();
    227 
     226   
    228227    std::optional<JSValue> exception;
    229228
     
    251250
    252251    auto forEachSegment = [&] (auto fn) {
    253         uint8_t* memory = reinterpret_cast<uint8_t*>(jsMemory->memory().memory());
    254         uint64_t sizeInBytes = jsMemory->memory().size();
     252        uint8_t* memory = reinterpret_cast<uint8_t*>(m_instance->instance().cachedMemory());
     253        uint64_t sizeInBytes = m_instance->instance().cachedMemorySize();
    255254
    256255        for (const Wasm::Segment::Ptr& segment : data) {
Note: See TracChangeset for help on using the changeset viewer.