Changeset 145931 in webkit


Ignore:
Timestamp:
Mar 15, 2013 12:33:25 PM (11 years ago)
Author:
msaboff@apple.com
Message:

Add runtime check for improper register allocations in DFG
https://bugs.webkit.org/show_bug.cgi?id=112380

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

Added framework to check for register allocation within a branch source - target range. All register allocations
are saved using the offset in the code stream where the allocation occurred. Later when a jump is linked, the
currently saved register allocations are checked to make sure that they didn't occur in the range of code that was
jumped over. This protects against the case where an allocation could have spilled register contents to free up
a register and that spill only occurs on one path of a many through the code. A subsequent fill of the spilled
register may load garbage. See https://bugs.webkit.org/show_bug.cgi?id=111777 for one such bug.
This code is protected by the compile time check of #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION).
The check is only done during the processing of SpeculativeJIT::compile(Node* node) and its callees.

  • assembler/AbstractMacroAssembler.h:

(JSC::AbstractMacroAssembler::Jump::link): Invoke register allocation checks using source and target of link.
(JSC::AbstractMacroAssembler::Jump::linkTo): Invoke register allocation checks using source and target of link.
(AbstractMacroAssembler):
(RegisterAllocationOffset): New helper class to store the instruction stream offset and compare against a
jump range.
(JSC::AbstractMacroAssembler::RegisterAllocationOffset::RegisterAllocationOffset):
(JSC::AbstractMacroAssembler::RegisterAllocationOffset::check):
(JSC::AbstractMacroAssembler::addRegisterAllocationAtOffset):
(JSC::AbstractMacroAssembler::clearRegisterAllocationOffsets):
(JSC::AbstractMacroAssembler::checkRegisterAllocationAgainstBranchRange):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::allocate):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

Source/WTF:

  • wtf/Platform.h: Added new ENABLE_DFG_REGISTER_ALLOCATION_VALIDATION compilation flag to

enable generation of register allocation checking. This is on for debug builds.

Location:
trunk/Source
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r145860 r145931  
     12013-03-15  Michael Saboff  <msaboff@apple.com>
     2
     3        Add runtime check for improper register allocations in DFG
     4        https://bugs.webkit.org/show_bug.cgi?id=112380
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Added framework to check for register allocation within a branch source - target range.  All register allocations
     9        are saved using the offset in the code stream where the allocation occurred.  Later when a jump is linked, the
     10        currently saved register allocations are checked to make sure that they didn't occur in the range of code that was
     11        jumped over.  This protects against the case where an allocation could have spilled register contents to free up
     12        a register and that spill only occurs on one path of a many through the code.  A subsequent fill of the spilled
     13        register may load garbage.  See https://bugs.webkit.org/show_bug.cgi?id=111777 for one such bug.
     14        This code is protected by the compile time check of #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION).
     15        The check is only done during the processing of SpeculativeJIT::compile(Node* node) and its callees.
     16 
     17        * assembler/AbstractMacroAssembler.h:
     18        (JSC::AbstractMacroAssembler::Jump::link): Invoke register allocation checks using source and target of link.
     19        (JSC::AbstractMacroAssembler::Jump::linkTo): Invoke register allocation checks using source and target of link.
     20        (AbstractMacroAssembler):
     21        (RegisterAllocationOffset): New helper class to store the instruction stream offset and compare against a
     22        jump range.
     23        (JSC::AbstractMacroAssembler::RegisterAllocationOffset::RegisterAllocationOffset):
     24        (JSC::AbstractMacroAssembler::RegisterAllocationOffset::check):
     25        (JSC::AbstractMacroAssembler::addRegisterAllocationAtOffset):
     26        (JSC::AbstractMacroAssembler::clearRegisterAllocationOffsets):
     27        (JSC::AbstractMacroAssembler::checkRegisterAllocationAgainstBranchRange):
     28        * dfg/DFGSpeculativeJIT.h:
     29        (JSC::DFG::SpeculativeJIT::allocate):
     30        * dfg/DFGSpeculativeJIT32_64.cpp:
     31        (JSC::DFG::SpeculativeJIT::compile):
     32        * dfg/DFGSpeculativeJIT64.cpp:
     33        (JSC::DFG::SpeculativeJIT::compile):
     34
    1352013-03-14  Oliver Hunt  <oliver@apple.com>
    236
  • trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h

    r138276 r145931  
    539539        void link(AbstractMacroAssembler<AssemblerType>* masm) const
    540540        {
     541#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
     542            masm->checkRegisterAllocationAgainstBranchRange(m_label.m_offset, masm->debugOffset());
     543#endif
     544
    541545#if CPU(ARM_THUMB2)
    542546            masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition);
     
    550554        void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm) const
    551555        {
     556#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
     557            masm->checkRegisterAllocationAgainstBranchRange(label.m_label.m_offset, m_label.m_offset);
     558#endif
     559
    552560#if CPU(ARM_THUMB2)
    553561            masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition);
     
    684692    }
    685693
     694#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
     695    class RegisterAllocationOffset {
     696    public:
     697        RegisterAllocationOffset(unsigned offset)
     698            : m_offset(offset)
     699        {
     700        }
     701
     702        void check(unsigned low, unsigned high)
     703        {
     704            RELEASE_ASSERT_WITH_MESSAGE(!(low <= m_offset && m_offset <= high), "Unsafe branch over register allocation at instruction offset %u in jump offset range %u..%u", m_offset, low, high);
     705        }
     706
     707    private:
     708        unsigned m_offset;
     709    };
     710
     711    void addRegisterAllocationAtOffset(unsigned offset)
     712    {
     713        m_registerAllocationForOffsets.append(RegisterAllocationOffset(offset));
     714    }
     715
     716    void clearRegisterAllocationOffsets()
     717    {
     718        m_registerAllocationForOffsets.clear();
     719    }
     720
     721    void checkRegisterAllocationAgainstBranchRange(unsigned offset1, unsigned offset2)
     722    {
     723        if (offset1 > offset2)
     724            std::swap(offset1, offset2);
     725
     726        size_t size = m_registerAllocationForOffsets.size();
     727        for (size_t i = 0; i < size; ++i)
     728            m_registerAllocationForOffsets[i].check(offset1, offset2);
     729    }
     730#endif
     731
    686732    template<typename T, typename U>
    687733    static ptrdiff_t differenceBetween(T from, U to)
     
    715761
    716762    WeakRandom m_randomSource;
     763
     764#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
     765    Vector<RegisterAllocationOffset, 10> m_registerAllocationForOffsets;
     766#endif
    717767
    718768#if ENABLE(JIT_CONSTANT_BLINDING)
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r145329 r145931  
    174174    GPRReg allocate()
    175175    {
     176#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
     177        m_jit.addRegisterAllocationAtOffset(m_jit.debugOffset());
     178#endif
    176179        VirtualRegister spillMe;
    177180        GPRReg gpr = m_gprs.allocate(spillMe);
     
    189192    GPRReg allocate(GPRReg specific)
    190193    {
     194#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
     195        m_jit.addRegisterAllocationAtOffset(m_jit.debugOffset());
     196#endif
    191197        VirtualRegister spillMe = m_gprs.allocateSpecific(specific);
    192198        if (spillMe != InvalidVirtualRegister) {
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r145417 r145931  
    19231923{
    19241924    NodeType op = node->op();
     1925
     1926#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
     1927    m_jit.clearRegisterAllocationOffsets();
     1928#endif
    19251929
    19261930    switch (op) {
     
    49244928        break;
    49254929    }
    4926    
     4930
     4931#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
     4932    m_jit.clearRegisterAllocationOffsets();
     4933#endif
     4934
    49274935    if (!m_compileOkay)
    49284936        return;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r145150 r145931  
    18891889    NodeType op = node->op();
    18901890   
     1891#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
     1892    m_jit.clearRegisterAllocationOffsets();
     1893#endif
     1894
    18911895    switch (op) {
    18921896    case JSConstant:
     
    47744778    }
    47754779
     4780#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
     4781    m_jit.clearRegisterAllocationOffsets();
     4782#endif
     4783
    47764784    if (!m_compileOkay)
    47774785        return;
  • trunk/Source/WTF/ChangeLog

    r145766 r145931  
     12013-03-15  Michael Saboff  <msaboff@apple.com>
     2
     3        Add runtime check for improper register allocations in DFG
     4        https://bugs.webkit.org/show_bug.cgi?id=112380
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        * wtf/Platform.h: Added new ENABLE_DFG_REGISTER_ALLOCATION_VALIDATION compilation flag to
     9        enable generation of register allocation checking.  This is on for debug builds.
     10
    1112013-03-13  Jessie Berlin  <jberlin@apple.com>
    212
  • trunk/Source/WTF/wtf/Platform.h

    r145748 r145931  
    851851#endif
    852852
     853/* Enable verification that that register allocations are not made within generated control flow.
     854   Turned on for debug builds. */
     855#if !defined(ENABLE_DFG_REGISTER_ALLOCATION_VALIDATION) && ENABLE(DFG_JIT)
     856#if !defined(NDEBUG)
     857#define ENABLE_DFG_REGISTER_ALLOCATION_VALIDATION 1
     858#else
     859#define ENABLE_DFG_REGISTER_ALLOCATION_VALIDATION 0
     860#endif
     861#endif
     862
    853863/* Configure the JIT */
    854864#if CPU(X86) && COMPILER(MSVC)
Note: See TracChangeset for help on using the changeset viewer.