Ignore:
Timestamp:
May 19, 2017, 8:48:40 AM (8 years ago)
Author:
[email protected]
Message:

B3::Value::effects() says that having a fence range implies the fence bit, but on x86_64 we lower loadAcq/storeRel to load/store so the store-before-load fence bit orderings won't be honored
https://bugs.webkit.org/show_bug.cgi?id=172306

Reviewed by Michael Saboff.

This changes B3 to emit xchg and its variants for fenced stores on x86. This ensures that
fenced stores cannot be reordered around other fenced instructions. Previously, B3 emitted
normal store instructions for fenced stores. That's wrong because then you get reorderings
that are possible in TSO but impossible in SC. Fenced instructions are supposed to be SC
with respect for each other.

This is imprecise. If you really just wanted a store-release, then every X86 store does this.
But, in B3, fenced stores are ARM-style store-release, meaning that they are fenced with
respect to all other fences. If we ever did want to say that something is a store release in
the traditional sense, then we'd want MemoryValue to have a fence flag. Then, having a fence
range without the fence flag would mean the traditional store-release, which lowers to a
normal store on x86. But to my knowledge, that traditional store-release is only useful for
unlocking spinlocks. We don't use spinlocks in JSC. Adaptive locks require CAS for unlock,
and B3 CAS is plenty fast. I think it's OK to have this small imprecision of giving clients
an ARM-style store-release on x86 using xchg.

The implication of this change is that the FTL no longer violates the SAB memory model.

  • assembler/MacroAssemblerX86Common.h:

(JSC::MacroAssemblerX86Common::xchg8):
(JSC::MacroAssemblerX86Common::xchg16):
(JSC::MacroAssemblerX86Common::xchg32):
(JSC::MacroAssemblerX86Common::loadAcq8): Deleted.
(JSC::MacroAssemblerX86Common::loadAcq8SignedExtendTo32): Deleted.
(JSC::MacroAssemblerX86Common::loadAcq16): Deleted.
(JSC::MacroAssemblerX86Common::loadAcq16SignedExtendTo32): Deleted.
(JSC::MacroAssemblerX86Common::loadAcq32): Deleted.
(JSC::MacroAssemblerX86Common::storeRel8): Deleted.
(JSC::MacroAssemblerX86Common::storeRel16): Deleted.
(JSC::MacroAssemblerX86Common::storeRel32): Deleted.

  • assembler/MacroAssemblerX86_64.h:

(JSC::MacroAssemblerX86_64::xchg64):
(JSC::MacroAssemblerX86_64::loadAcq64): Deleted.
(JSC::MacroAssemblerX86_64::storeRel64): Deleted.

  • b3/B3LowerToAir.cpp:

(JSC::B3::Air::LowerToAir::ArgPromise::inst):
(JSC::B3::Air::LowerToAir::trappingInst):
(JSC::B3::Air::LowerToAir::tryAppendStoreBinOp):
(JSC::B3::Air::LowerToAir::createStore):
(JSC::B3::Air::LowerToAir::storeOpcode):
(JSC::B3::Air::LowerToAir::appendStore):
(JSC::B3::Air::LowerToAir::append):
(JSC::B3::Air::LowerToAir::appendTrapping):
(JSC::B3::Air::LowerToAir::fillStackmap):
(JSC::B3::Air::LowerToAir::lower):

  • b3/air/AirKind.cpp:

(JSC::B3::Air::Kind::dump):

  • b3/air/AirKind.h:

(JSC::B3::Air::Kind::Kind):
(JSC::B3::Air::Kind::operator==):
(JSC::B3::Air::Kind::hash):

  • b3/air/AirLowerAfterRegAlloc.cpp:

(JSC::B3::Air::lowerAfterRegAlloc):

  • b3/air/AirLowerMacros.cpp:

(JSC::B3::Air::lowerMacros):

  • b3/air/AirOpcode.opcodes:
  • b3/air/AirValidate.cpp:
  • b3/air/opcode_generator.rb:
  • b3/testb3.cpp:

(JSC::B3::correctSqrt):
(JSC::B3::testSqrtArg):
(JSC::B3::testSqrtImm):
(JSC::B3::testSqrtMem):
(JSC::B3::testSqrtArgWithUselessDoubleConversion):
(JSC::B3::testSqrtArgWithEffectfulDoubleConversion):
(JSC::B3::testStoreRelAddLoadAcq32):
(JSC::B3::testTrappingLoad):
(JSC::B3::testTrappingStore):
(JSC::B3::testTrappingLoadAddStore):
(JSC::B3::testTrappingLoadDCE):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h

    r215592 r217127  
    30143014    }
    30153015   
     3016    void xchg8(RegisterID reg, Address address)
     3017    {
     3018        m_assembler.xchgb_rm(reg, address.offset, address.base);
     3019    }
     3020   
     3021    void xchg8(RegisterID reg, BaseIndex address)
     3022    {
     3023        m_assembler.xchgb_rm(reg, address.offset, address.base, address.index, address.scale);
     3024    }
     3025   
     3026    void xchg16(RegisterID reg, Address address)
     3027    {
     3028        m_assembler.xchgw_rm(reg, address.offset, address.base);
     3029    }
     3030   
     3031    void xchg16(RegisterID reg, BaseIndex address)
     3032    {
     3033        m_assembler.xchgw_rm(reg, address.offset, address.base, address.index, address.scale);
     3034    }
     3035   
     3036    void xchg32(RegisterID reg, Address address)
     3037    {
     3038        m_assembler.xchgl_rm(reg, address.offset, address.base);
     3039    }
     3040   
     3041    void xchg32(RegisterID reg, BaseIndex address)
     3042    {
     3043        m_assembler.xchgl_rm(reg, address.offset, address.base, address.index, address.scale);
     3044    }
     3045   
    30163046    // We take memoryFence to mean acqrel. This has acqrel semantics on x86.
    30173047    void memoryFence()
     
    37373767        m_assembler.lock();
    37383768        m_assembler.xchgl_rm(reg, address.offset, address.base, address.index, address.scale);
    3739     }
    3740    
    3741     void loadAcq8(Address src, RegisterID dest)
    3742     {
    3743         load8(src, dest);
    3744     }
    3745    
    3746     void loadAcq8(BaseIndex src, RegisterID dest)
    3747     {
    3748         load8(src, dest);
    3749     }
    3750    
    3751     void loadAcq8SignedExtendTo32(Address src, RegisterID dest)
    3752     {
    3753         load8SignedExtendTo32(src, dest);
    3754     }
    3755    
    3756     void loadAcq8SignedExtendTo32(BaseIndex src, RegisterID dest)
    3757     {
    3758         load8SignedExtendTo32(src, dest);
    3759     }
    3760    
    3761     void loadAcq16(Address src, RegisterID dest)
    3762     {
    3763         load16(src, dest);
    3764     }
    3765    
    3766     void loadAcq16(BaseIndex src, RegisterID dest)
    3767     {
    3768         load16(src, dest);
    3769     }
    3770    
    3771     void loadAcq16SignedExtendTo32(Address src, RegisterID dest)
    3772     {
    3773         load16SignedExtendTo32(src, dest);
    3774     }
    3775    
    3776     void loadAcq16SignedExtendTo32(BaseIndex src, RegisterID dest)
    3777     {
    3778         load16SignedExtendTo32(src, dest);
    3779     }
    3780    
    3781     void loadAcq32(Address src, RegisterID dest)
    3782     {
    3783         load32(src, dest);
    3784     }
    3785    
    3786     void loadAcq32(BaseIndex src, RegisterID dest)
    3787     {
    3788         load32(src, dest);
    3789     }
    3790    
    3791     void storeRel8(RegisterID src, Address dest)
    3792     {
    3793         store8(src, dest);
    3794     }
    3795    
    3796     void storeRel8(RegisterID src, BaseIndex dest)
    3797     {
    3798         store8(src, dest);
    3799     }
    3800    
    3801     void storeRel8(TrustedImm32 imm, Address dest)
    3802     {
    3803         store8(imm, dest);
    3804     }
    3805    
    3806     void storeRel8(TrustedImm32 imm, BaseIndex dest)
    3807     {
    3808         store8(imm, dest);
    3809     }
    3810    
    3811     void storeRel16(RegisterID src, Address dest)
    3812     {
    3813         store16(src, dest);
    3814     }
    3815    
    3816     void storeRel16(RegisterID src, BaseIndex dest)
    3817     {
    3818         store16(src, dest);
    3819     }
    3820    
    3821     void storeRel16(TrustedImm32 imm, Address dest)
    3822     {
    3823         store16(imm, dest);
    3824     }
    3825    
    3826     void storeRel16(TrustedImm32 imm, BaseIndex dest)
    3827     {
    3828         store16(imm, dest);
    3829     }
    3830    
    3831     void storeRel32(RegisterID src, Address dest)
    3832     {
    3833         store32(src, dest);
    3834     }
    3835    
    3836     void storeRel32(RegisterID src, BaseIndex dest)
    3837     {
    3838         store32(src, dest);
    3839     }
    3840    
    3841     void storeRel32(TrustedImm32 imm, Address dest)
    3842     {
    3843         store32(imm, dest);
    3844     }
    3845    
    3846     void storeRel32(TrustedImm32 imm, BaseIndex dest)
    3847     {
    3848         store32(imm, dest);
    38493769    }
    38503770   
Note: See TracChangeset for help on using the changeset viewer.