Ignore:
Timestamp:
Jan 5, 2018, 2:02:31 PM (7 years ago)
Author:
[email protected]
Message:

TypedArrays and Wasm should use index masking.
https://bugs.webkit.org/show_bug.cgi?id=181313

Reviewed by Michael Saboff.

Source/JavaScriptCore:

We should have index masking for our TypedArray code in the
DFG/FTL and for Wasm when doing bounds checking. Index masking for
Wasm is added to the WasmBoundsCheckValue. Since we don't CSE any
WasmBoundsCheckValues we don't need to worry about combining a
bounds check for a load and a store. I went with fusing the
pointer masking in the WasmBoundsCheckValue since it should reduce
additional compiler overhead.

  • b3/B3LowerToAir.cpp:
  • b3/B3Validate.cpp:
  • b3/B3WasmBoundsCheckValue.cpp:

(JSC::B3::WasmBoundsCheckValue::WasmBoundsCheckValue):
(JSC::B3::WasmBoundsCheckValue::dumpMeta const):

  • b3/B3WasmBoundsCheckValue.h:

(JSC::B3::WasmBoundsCheckValue::pinnedIndexingMask const):

  • b3/air/AirCustom.h:

(JSC::B3::Air::WasmBoundsCheckCustom::generate):

  • b3/testb3.cpp:

(JSC::B3::testWasmBoundsCheck):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::emitAllocateRawObject):
(JSC::DFG::SpeculativeJIT::loadFromIntTypedArray):
(JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray):
(JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray):
(JSC::DFG::SpeculativeJIT::compileNewTypedArrayWithSize):

  • dfg/DFGSpeculativeJIT.h:
  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileAtomicsReadModifyWrite):
(JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):
(JSC::FTL::DFG::LowerDFGToB3::compileNewTypedArray):
(JSC::FTL::DFG::LowerDFGToB3::pointerIntoTypedArray):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emitIntTypedArrayGetByVal):

  • runtime/Butterfly.h:

(JSC::Butterfly::computeIndexingMask const):
(JSC::Butterfly::computeIndexingMaskForVectorLength): Deleted.

  • runtime/JSArrayBufferView.cpp:

(JSC::JSArrayBufferView::JSArrayBufferView):

  • wasm/WasmB3IRGenerator.cpp:

(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::B3IRGenerator::restoreWebAssemblyGlobalState):
(JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer):
(JSC::Wasm::B3IRGenerator::load):
(JSC::Wasm::B3IRGenerator::store):
(JSC::Wasm::B3IRGenerator::addCallIndirect):

  • wasm/WasmBinding.cpp:

(JSC::Wasm::wasmToWasm):

  • wasm/WasmMemory.cpp:

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

  • wasm/WasmMemory.h:

(JSC::Wasm::Memory::offsetOfIndexingMask):

  • wasm/WasmMemoryInformation.cpp:

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

  • wasm/WasmMemoryInformation.h:

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

  • wasm/js/JSToWasm.cpp:

(JSC::Wasm::createJSToWasmWrapper):

Source/WTF:

  • wtf/MathExtras.h:

(WTF::computeIndexingMask):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/b3/testb3.cpp

    r225778 r226461  
    1586615866}
    1586715867
    15868 void testWasmBoundsCheck(unsigned offset)
     15868enum class UseIndexingMaskGPR { No, Yes };
     15869void testWasmBoundsCheck(unsigned offset, UseIndexingMaskGPR useIndexingMask)
    1586915870{
    1587015871    Procedure proc;
    1587115872    GPRReg pinned = GPRInfo::argumentGPR1;
     15873    GPRReg indexingMask = InvalidGPRReg;
    1587215874    proc.pinRegister(pinned);
     15875
     15876    if (useIndexingMask == UseIndexingMaskGPR::Yes) {
     15877        indexingMask = GPRInfo::argumentGPR2;
     15878        proc.pinRegister(indexingMask);
     15879    }
    1587315880
    1587415881    proc.setWasmBoundsCheckGenerator([=] (CCallHelpers& jit, GPRReg pinnedGPR) {
     
    1588615893    if (pointerType() != Int32)
    1588715894        left = root->appendNew<Value>(proc, Trunc, Origin(), left);
    15888     root->appendNew<WasmBoundsCheckValue>(proc, Origin(), pinned, left, offset);
     15895    root->appendNew<WasmBoundsCheckValue>(proc, Origin(), pinned, indexingMask, left, offset);
    1588915896    Value* result = root->appendNew<Const32Value>(proc, Origin(), 0x42);
    1589015897    root->appendNewControlValue(proc, Return, Origin(), result);
    1589115898
    1589215899    auto code = compileProc(proc);
    15893     CHECK_EQ(invoke<int32_t>(*code, 1, 2 + offset), 0x42);
    15894     CHECK_EQ(invoke<int32_t>(*code, 3, 2 + offset), 42);
    15895     CHECK_EQ(invoke<int32_t>(*code, 2, 2 + offset), 42);
     15900    uint32_t bound = 2 + offset;
     15901    uint32_t mask = WTF::computeIndexingMask(bound);
     15902    auto computeResult = [&] (uint32_t input) {
     15903        return input + offset < bound ? 0x42 : 42;
     15904    };
     15905
     15906    CHECK_EQ(invoke<int32_t>(*code, 1, bound, mask), computeResult(1));
     15907    CHECK_EQ(invoke<int32_t>(*code, 3, bound, mask), computeResult(3));
     15908    CHECK_EQ(invoke<int32_t>(*code, 2, bound, mask), computeResult(2));
    1589615909}
    1589715910
     
    1774617759    RUN(testDepend64());
    1774717760
    17748     RUN(testWasmBoundsCheck(0));
    17749     RUN(testWasmBoundsCheck(100));
    17750     RUN(testWasmBoundsCheck(10000));
    17751     RUN(testWasmBoundsCheck(std::numeric_limits<unsigned>::max() - 5));
     17761    RUN(testWasmBoundsCheck(0, UseIndexingMaskGPR::No));
     17762    RUN(testWasmBoundsCheck(100, UseIndexingMaskGPR::No));
     17763    RUN(testWasmBoundsCheck(10000, UseIndexingMaskGPR::No));
     17764    RUN(testWasmBoundsCheck(std::numeric_limits<unsigned>::max() - 5, UseIndexingMaskGPR::No));
     17765    RUN(testWasmBoundsCheck(0, UseIndexingMaskGPR::Yes));
     17766    RUN(testWasmBoundsCheck(100, UseIndexingMaskGPR::Yes));
     17767    RUN(testWasmBoundsCheck(10000, UseIndexingMaskGPR::Yes));
     17768    RUN(testWasmBoundsCheck(std::numeric_limits<unsigned>::max() - 5, UseIndexingMaskGPR::Yes));
     17769
    1775217770    RUN(testWasmAddress());
    1775317771   
Note: See TracChangeset for help on using the changeset viewer.