Ignore:
Timestamp:
Nov 27, 2020, 4:02:55 PM (4 years ago)
Author:
[email protected]
Message:

[JSC] Add wasm atomics instructions
https://bugs.webkit.org/show_bug.cgi?id=218954

Reviewed by Filip Pizlo.

JSTests:

  • wasm.yaml:
  • wasm/Builder.js:

(const._importMemoryContinuation):
(export.default.Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section):

  • wasm/Builder_WebAssemblyBinary.js:

(const.putResizableLimits):
(const.emitters.Import):
(const.emitters.Memory):

  • wasm/function-tests/trap-load-shared.js:
  • wasm/function-tests/trap-store-shared.js:
  • wasm/stress/atomic-decrement.js: Added.

(i.agent.start.import.string_appeared_here.then):
(i.async error):

  • wasm/stress/atomic-increment.js: Added.

(i.agent.start.import.string_appeared_here.then):
(i.async error):

  • wasm/stress/memory-fence.js: Added.

(async try):
(catch):

  • wasm/threads-spec-tests/atomic-signed.wast.js: Added.
  • wasm/threads-spec-tests/atomic.wast.js: Added.
  • wasm/threads-spec-tests/memory.wast.js: Added.
  • wasm/threads-spec-tests/resources/atomic-signed.wast: Added.
  • wasm/wasm.json:

Source/JavaScriptCore:

This patch implements wasm threading's atomic operations[1] in X86_64 and ARM64. Currently, all ARM64 atomic operations are implemented by using LL/SC.
Later, we will use ARM64 CAS operations if possible, at least in ARM64E.

To test it easily, we also extend jsc shell's worker to support transferring shared WebAssembly.Memory so that we can use wasm atomic operations in several
workers in jsc shell.

[1]: https://github.com/WebAssembly/threads

  • assembler/MacroAssemblerX86Common.h:

(JSC::MacroAssemblerX86Common::atomicXchg8):
(JSC::MacroAssemblerX86Common::atomicXchg16):
(JSC::MacroAssemblerX86Common::atomicXchg32):

  • b3/B3Kind.h:

(JSC::B3::Kind::hasTraps const):

  • b3/B3LowerToAir.cpp:
  • b3/B3Width.h:

(JSC::B3::bytesForWidth):

  • b3/testb3_8.cpp:

(testAtomicXchg):

  • bytecode/BytecodeList.rb:
  • interpreter/Register.h:

(JSC::Register::unboxedInt64 const):
(JSC::Register::asanUnsafeUnboxedInt64 const):

  • jsc.cpp:

(Message::releaseContents):
(Message::Message):
(JSC_DEFINE_HOST_FUNCTION):

  • llint/WebAssembly.asm:
  • offlineasm/arm64.rb:
  • offlineasm/instructions.rb:
  • offlineasm/x86.rb:
  • runtime/OptionsList.h:
  • wasm/WasmAirIRGenerator.cpp:

(JSC::Wasm::AirIRGenerator::appendEffectful):
(JSC::Wasm::accessWidth):
(JSC::Wasm::sizeOfAtomicOpMemoryAccess):
(JSC::Wasm::AirIRGenerator::fixupPointerPlusOffsetForAtomicOps):
(JSC::Wasm::AirIRGenerator::sanitizeAtomicResult):
(JSC::Wasm::AirIRGenerator::appendGeneralAtomic):
(JSC::Wasm::AirIRGenerator::appendStrongCAS):
(JSC::Wasm::AirIRGenerator::emitAtomicLoadOp):
(JSC::Wasm::AirIRGenerator::atomicLoad):
(JSC::Wasm::AirIRGenerator::emitAtomicStoreOp):
(JSC::Wasm::AirIRGenerator::atomicStore):
(JSC::Wasm::AirIRGenerator::emitAtomicBinaryRMWOp):
(JSC::Wasm::AirIRGenerator::atomicBinaryRMW):
(JSC::Wasm::AirIRGenerator::emitAtomicCompareExchange):
(JSC::Wasm::AirIRGenerator::atomicCompareExchange):
(JSC::Wasm::AirIRGenerator::atomicWait):
(JSC::Wasm::AirIRGenerator::atomicNotify):
(JSC::Wasm::AirIRGenerator::atomicFence):
(JSC::Wasm::AirIRGenerator::addCall):

  • wasm/WasmB3IRGenerator.cpp:

(JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer):
(JSC::Wasm::B3IRGenerator::memoryKind):
(JSC::Wasm::accessWidth):
(JSC::Wasm::sizeOfAtomicOpMemoryAccess):
(JSC::Wasm::B3IRGenerator::sanitizeAtomicResult):
(JSC::Wasm::B3IRGenerator::fixupPointerPlusOffsetForAtomicOps):
(JSC::Wasm::B3IRGenerator::emitAtomicLoadOp):
(JSC::Wasm::B3IRGenerator::atomicLoad):
(JSC::Wasm::B3IRGenerator::emitAtomicStoreOp):
(JSC::Wasm::B3IRGenerator::atomicStore):
(JSC::Wasm::B3IRGenerator::emitAtomicBinaryRMWOp):
(JSC::Wasm::B3IRGenerator::atomicBinaryRMW):
(JSC::Wasm::B3IRGenerator::emitAtomicCompareExchange):
(JSC::Wasm::B3IRGenerator::atomicCompareExchange):
(JSC::Wasm::B3IRGenerator::atomicWait):
(JSC::Wasm::B3IRGenerator::atomicNotify):
(JSC::Wasm::B3IRGenerator::atomicFence):
(JSC::Wasm::B3IRGenerator::addCall):

  • wasm/WasmFunctionParser.h:

(JSC::Wasm::FunctionParser<Context>::atomicLoad):
(JSC::Wasm::FunctionParser<Context>::atomicStore):
(JSC::Wasm::FunctionParser<Context>::atomicBinaryRMW):
(JSC::Wasm::FunctionParser<Context>::atomicCompareExchange):
(JSC::Wasm::FunctionParser<Context>::atomicWait):
(JSC::Wasm::FunctionParser<Context>::atomicNotify):
(JSC::Wasm::FunctionParser<Context>::atomicFence):
(JSC::Wasm::FunctionParser<Context>::parseExpression):
(JSC::Wasm::FunctionParser<Context>::parseUnreachableExpression):

  • wasm/WasmLLIntGenerator.cpp:

(JSC::Wasm::LLIntGenerator::atomicLoad):
(JSC::Wasm::LLIntGenerator::atomicStore):
(JSC::Wasm::LLIntGenerator::atomicBinaryRMW):
(JSC::Wasm::LLIntGenerator::atomicCompareExchange):
(JSC::Wasm::LLIntGenerator::atomicWait):
(JSC::Wasm::LLIntGenerator::atomicNotify):
(JSC::Wasm::LLIntGenerator::atomicFence):

  • wasm/WasmMemory.h:
  • wasm/WasmMemoryInformation.cpp:

(JSC::Wasm::MemoryInformation::MemoryInformation):

  • wasm/WasmMemoryInformation.h:

(JSC::Wasm::MemoryInformation::isShared const):

  • wasm/WasmOperations.cpp:

(JSC::Wasm::wait):
(JSC::Wasm::JSC_DEFINE_JIT_OPERATION):

  • wasm/WasmOperations.h:
  • wasm/WasmSectionParser.cpp:

(JSC::Wasm::SectionParser::parseResizableLimits):
(JSC::Wasm::SectionParser::parseTableHelper):
(JSC::Wasm::SectionParser::parseMemoryHelper):

  • wasm/WasmSectionParser.h:
  • wasm/WasmSlowPaths.cpp:

(JSC::LLInt::WASM_SLOW_PATH_DECL):

  • wasm/WasmSlowPaths.h:
  • wasm/generateWasm.py:

(isAtomic):
(isAtomicLoad):
(isAtomicStore):
(isAtomicBinaryRMW):
(memoryLog2Alignment):

  • wasm/generateWasmOpsHeader.py:

(atomicMemoryLoadMacroizer):
(atomicMemoryLoadMacroizer.modifier):
(atomicMemoryStoreMacroizer):
(atomicMemoryStoreMacroizer.modifier):
(atomicBinaryRMWMacroizer):
(atomicBinaryRMWMacroizer.modifier):
(memoryLog2AlignmentGenerator):
(atomicMemoryLog2AlignmentGenerator):
(ExtAtomicOpType):

  • wasm/js/JSWebAssemblyInstance.cpp:

(JSC::JSWebAssemblyInstance::tryCreate):

  • wasm/wasm.json:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/offlineasm/x86.rb

    r269929 r270208  
    17931793        when "leap"
    17941794            $asm.puts "lea#{x86Suffix(:ptr)} #{orderOperands(operands[0].x86AddressOperand(:ptr), operands[1].x86Operand(:ptr))}"
    1795         when "memfence"
     1795        when "memfence", "fence"
    17961796            sp = RegisterID.new(nil, "sp")
    17971797            if isIntelSyntax
     
    18401840            end
    18411841            $asm.puts "mov#{x86Suffix(:ptr)} #{orderOperands(operands[0].x86Operand(:ptr), mem)}"
     1842        when "atomicxchgaddb"
     1843            $asm.puts "lock"
     1844            $asm.puts "xadd#{x86Suffix(:byte)} #{x86Operands(:byte, :byte)}"
     1845        when "atomicxchgaddh"
     1846            $asm.puts "lock"
     1847            $asm.puts "xadd#{x86Suffix(:half)} #{x86Operands(:half, :half)}"
     1848        when "atomicxchgaddi"
     1849            $asm.puts "lock"
     1850            $asm.puts "xadd#{x86Suffix(:int)} #{x86Operands(:int, :int)}"
     1851        when "atomicxchgaddq"
     1852            $asm.puts "lock"
     1853            $asm.puts "xadd#{x86Suffix(:quad)} #{x86Operands(:quad, :quad)}"
     1854        when "atomicxchgsubb"
     1855            $asm.puts "neg#{x86Suffix(:byte)} #{operands[0].x86Operand(:byte)}"
     1856            $asm.puts "lock"
     1857            $asm.puts "xadd#{x86Suffix(:byte)} #{x86Operands(:byte, :byte)}"
     1858        when "atomicxchgsubh"
     1859            $asm.puts "neg#{x86Suffix(:half)} #{operands[0].x86Operand(:half)}"
     1860            $asm.puts "lock"
     1861            $asm.puts "xadd#{x86Suffix(:half)} #{x86Operands(:half, :half)}"
     1862        when "atomicxchgsubi"
     1863            $asm.puts "neg#{x86Suffix(:int)} #{operands[0].x86Operand(:int)}"
     1864            $asm.puts "lock"
     1865            $asm.puts "xadd#{x86Suffix(:int)} #{x86Operands(:int, :int)}"
     1866        when "atomicxchgsubq"
     1867            $asm.puts "neg#{x86Suffix(:quad)} #{operands[0].x86Operand(:quad)}"
     1868            $asm.puts "lock"
     1869            $asm.puts "xadd#{x86Suffix(:quad)} #{x86Operands(:quad, :quad)}"
     1870        when "atomicxchgb"
     1871            $asm.puts "xchg#{x86Suffix(:byte)} #{x86Operands(:byte, :byte)}"
     1872        when "atomicxchgh"
     1873            $asm.puts "xchg#{x86Suffix(:half)} #{x86Operands(:half, :half)}"
     1874        when "atomicxchgi"
     1875            $asm.puts "xchg#{x86Suffix(:int)} #{x86Operands(:int, :int)}"
     1876        when "atomicxchgq"
     1877            $asm.puts "xchg#{x86Suffix(:quad)} #{x86Operands(:quad, :quad)}"
     1878        when "batomicweakcasb"
     1879            raise "first operand must be t0" unless operands[0].is_a? RegisterID and operands[0].name == 't0'
     1880            $asm.puts "lock"
     1881            $asm.puts "cmpxchg#{x86Suffix(:byte)} #{orderOperands(operands[1].x86Operand(:byte), operands[2].x86Operand(:byte))}"
     1882            $asm.puts "jne #{operands.last.asmLabel}"
     1883        when "batomicweakcash"
     1884            raise "first operand must be t0" unless operands[0].is_a? RegisterID and operands[0].name == 't0'
     1885            $asm.puts "lock"
     1886            $asm.puts "cmpxchg#{x86Suffix(:half)} #{orderOperands(operands[1].x86Operand(:half), operands[2].x86Operand(:half))}"
     1887            $asm.puts "jne #{operands.last.asmLabel}"
     1888        when "batomicweakcasi"
     1889            raise "first operand must be t0" unless operands[0].is_a? RegisterID and operands[0].name == 't0'
     1890            $asm.puts "lock"
     1891            $asm.puts "cmpxchg#{x86Suffix(:int)} #{orderOperands(operands[1].x86Operand(:int), operands[2].x86Operand(:int))}"
     1892            $asm.puts "jne #{operands.last.asmLabel}"
     1893        when "batomicweakcasq"
     1894            raise "first operand must be t0" unless operands[0].is_a? RegisterID and operands[0].name == 't0'
     1895            $asm.puts "lock"
     1896            $asm.puts "cmpxchg#{x86Suffix(:quad)} #{orderOperands(operands[1].x86Operand(:quad), operands[2].x86Operand(:quad))}"
     1897            $asm.puts "jne #{operands.last.asmLabel}"
     1898        when "atomicweakcasb"
     1899            raise "first operand must be t0" unless operands[0].is_a? RegisterID and operands[0].name == 't0'
     1900            $asm.puts "lock"
     1901            $asm.puts "cmpxchg#{x86Suffix(:byte)} #{orderOperands(operands[1].x86Operand(:byte), operands[2].x86Operand(:byte))}"
     1902        when "atomicweakcash"
     1903            raise "first operand must be t0" unless operands[0].is_a? RegisterID and operands[0].name == 't0'
     1904            $asm.puts "lock"
     1905            $asm.puts "cmpxchg#{x86Suffix(:half)} #{orderOperands(operands[1].x86Operand(:half), operands[2].x86Operand(:half))}"
     1906        when "atomicweakcasi"
     1907            raise "first operand must be t0" unless operands[0].is_a? RegisterID and operands[0].name == 't0'
     1908            $asm.puts "lock"
     1909            $asm.puts "cmpxchg#{x86Suffix(:int)} #{orderOperands(operands[1].x86Operand(:int), operands[2].x86Operand(:int))}"
     1910        when "atomicweakcasq"
     1911            raise "first operand must be t0" unless operands[0].is_a? RegisterID and operands[0].name == 't0'
     1912            $asm.puts "lock"
     1913            $asm.puts "cmpxchg#{x86Suffix(:quad)} #{orderOperands(operands[1].x86Operand(:quad), operands[2].x86Operand(:quad))}"
    18421914        else
    18431915            lowerDefault
Note: See TracChangeset for help on using the changeset viewer.