Title: [186419] releases/WebKitGTK/webkit-2.8/Source/WebCore
Revision
186419
Author
[email protected]
Date
2015-07-07 01:51:15 -0700 (Tue, 07 Jul 2015)

Log Message

Merge r185719 - [CSS JIT][ARMv7] The pseudo element early exit trashes r6
https://bugs.webkit.org/show_bug.cgi?id=146078

Patch by Benjamin Poulain <[email protected]> on 2015-06-18
Reviewed by Alex Christensen.

The pseudo element early failure runs before we generate the prologue.
The reason is that we can often exit immediately on function entry, before
we even touch any memory.

On ARMv7, we don't have many spare registers so the MacroAssembler
uses r6 as a scratch register and the client code is expected to save
it.

In the early failure case, we were not pushing r6 before using the MacroAssembler
and its value could be trashed.

This patch push the macro assembler registers separately from the prologue.

For restoring the registers, a new function generateFunctionEnding() encapsulate
the pop() and ret().

* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::SelectorCodeGenerator::pushMacroAssemblerRegisters):
(WebCore::SelectorCompiler::SelectorCodeGenerator::popMacroAssemblerRegisters):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generatePrologue):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateEpilogue):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorChecker):

* cssjit/StackAllocator.h:
(WebCore::StackAllocator::operator=):
We have a new case for the stack allocator: some stack changes are conditional
at compile time instead of runtime. This is easy to deal with by overriding
the stack if a path is not taken at compile time.

Modified Paths

Diff

Modified: releases/WebKitGTK/webkit-2.8/Source/WebCore/ChangeLog (186418 => 186419)


--- releases/WebKitGTK/webkit-2.8/Source/WebCore/ChangeLog	2015-07-07 08:45:57 UTC (rev 186418)
+++ releases/WebKitGTK/webkit-2.8/Source/WebCore/ChangeLog	2015-07-07 08:51:15 UTC (rev 186419)
@@ -1,3 +1,39 @@
+2015-06-18  Benjamin Poulain  <[email protected]>
+
+        [CSS JIT][ARMv7] The pseudo element early exit trashes r6
+        https://bugs.webkit.org/show_bug.cgi?id=146078
+
+        Reviewed by Alex Christensen.
+
+        The pseudo element early failure runs before we generate the prologue.
+        The reason is that we can often exit immediately on function entry, before
+        we even touch any memory.
+
+        On ARMv7, we don't have many spare registers so the MacroAssembler
+        uses r6 as a scratch register and the client code is expected to save
+        it.
+
+        In the early failure case, we were not pushing r6 before using the MacroAssembler
+        and its value could be trashed.
+
+        This patch push the macro assembler registers separately from the prologue.
+
+        For restoring the registers, a new function generateFunctionEnding() encapsulate
+        the pop() and ret().
+
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::pushMacroAssemblerRegisters):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::popMacroAssemblerRegisters):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generatePrologue):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateEpilogue):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorChecker):
+
+        * cssjit/StackAllocator.h:
+        (WebCore::StackAllocator::operator=):
+        We have a new case for the stack allocator: some stack changes are conditional
+        at compile time instead of runtime. This is easy to deal with by overriding
+        the stack if a path is not taken at compile time.
+
 2015-06-18  Joseph Pecoraro  <[email protected]>
 
         Crash under WebCore::DOMWindow::dispatchMessageEventWithOriginCheck attempting to log console message

Modified: releases/WebKitGTK/webkit-2.8/Source/WebCore/cssjit/SelectorCompiler.cpp (186418 => 186419)


--- releases/WebKitGTK/webkit-2.8/Source/WebCore/cssjit/SelectorCompiler.cpp	2015-07-07 08:45:57 UTC (rev 186418)
+++ releases/WebKitGTK/webkit-2.8/Source/WebCore/cssjit/SelectorCompiler.cpp	2015-07-07 08:51:15 UTC (rev 186419)
@@ -323,8 +323,11 @@
     Assembler::Jump modulo(JSC::MacroAssembler::ResultCondition, Assembler::RegisterID inputDividend, int divisor);
     void moduloIsZero(Assembler::JumpList& failureCases, Assembler::RegisterID inputDividend, int divisor);
 
+    void pushMacroAssemblerRegisters();
+    void popMacroAssemblerRegisters(StackAllocator&);
     bool generatePrologue();
-    void generateEpilogue();
+    void generateEpilogue(StackAllocator&);
+    StackAllocator::StackReferenceVector m_macroAssemblerRegistersStackReferences;
     StackAllocator::StackReferenceVector m_prologueStackReferences;
 
     Assembler m_assembler;
@@ -1672,6 +1675,25 @@
     }
 }
 
+inline void SelectorCodeGenerator::pushMacroAssemblerRegisters()
+{
+#if CPU(ARM_THUMB2)
+    // r6 is tempRegister in RegisterAllocator.h and addressTempRegister in MacroAssemblerARMv7.h and must be preserved by the callee.
+    Vector<JSC::MacroAssembler::RegisterID, 1> macroAssemblerRegisters({ JSC::ARMRegisters::r6 });
+    m_macroAssemblerRegistersStackReferences = m_stackAllocator.push(macroAssemblerRegisters);
+#endif
+}
+
+inline void SelectorCodeGenerator::popMacroAssemblerRegisters(StackAllocator& stackAllocator)
+{
+#if CPU(ARM_THUMB2)
+    Vector<JSC::MacroAssembler::RegisterID, 1> macroAssemblerRegisters({ JSC::ARMRegisters::r6 });
+    stackAllocator.pop(m_macroAssemblerRegistersStackReferences, macroAssemblerRegisters);
+#else
+    UNUSED_PARAM(stackAllocator);
+#endif
+}
+
 inline bool SelectorCodeGenerator::generatePrologue()
 {
 #if CPU(ARM64)
@@ -1681,10 +1703,8 @@
     m_prologueStackReferences = m_stackAllocator.push(prologueRegisters);
     return true;
 #elif CPU(ARM_THUMB2)
-    Vector<JSC::MacroAssembler::RegisterID, 2> prologueRegisters;
+    Vector<JSC::MacroAssembler::RegisterID, 1> prologueRegisters;
     prologueRegisters.append(JSC::ARMRegisters::lr);
-    // r6 is tempRegister in RegisterAllocator.h and addressTempRegister in MacroAssemblerARMv7.h and must be preserved by the callee.
-    prologueRegisters.append(JSC::ARMRegisters::r6);
     m_prologueStackReferences = m_stackAllocator.push(prologueRegisters);
     return true;
 #elif CPU(X86_64) && CSS_SELECTOR_JIT_DEBUGGING
@@ -1696,22 +1716,19 @@
     return false;
 }
 
-inline void SelectorCodeGenerator::generateEpilogue()
+inline void SelectorCodeGenerator::generateEpilogue(StackAllocator& stackAllocator)
 {
 #if CPU(ARM64)
-    Vector<JSC::MacroAssembler::RegisterID, 2> prologueRegisters;
-    prologueRegisters.append(JSC::ARM64Registers::lr);
-    prologueRegisters.append(JSC::ARM64Registers::fp);
-    m_stackAllocator.pop(m_prologueStackReferences, prologueRegisters);
+    Vector<JSC::MacroAssembler::RegisterID, 2> prologueRegisters({ JSC::ARM64Registers::lr, JSC::ARM64Registers::fp });
+    stackAllocator.pop(m_prologueStackReferences, prologueRegisters);
 #elif CPU(ARM_THUMB2)
-    Vector<JSC::MacroAssembler::RegisterID, 2> prologueRegisters;
-    prologueRegisters.append(JSC::ARMRegisters::lr);
-    prologueRegisters.append(JSC::ARMRegisters::r6);
-    m_stackAllocator.pop(m_prologueStackReferences, prologueRegisters);
+    Vector<JSC::MacroAssembler::RegisterID, 1> prologueRegister({ JSC::ARMRegisters::lr });
+    stackAllocator.pop(m_prologueStackReferences, prologueRegister);
 #elif CPU(X86_64) && CSS_SELECTOR_JIT_DEBUGGING
-    Vector<JSC::MacroAssembler::RegisterID, 1> prologueRegister;
-    prologueRegister.append(callFrameRegister);
-    m_stackAllocator.pop(m_prologueStackReferences, prologueRegister);
+    Vector<JSC::MacroAssembler::RegisterID, 1> prologueRegister({ callFrameRegister });
+    stackAllocator.pop(m_prologueStackReferences, prologueRegister);
+#else
+    UNUSED_PARAM(stackAllocator);
 #endif
 }
 
@@ -1727,6 +1744,9 @@
 
 void SelectorCodeGenerator::generateSelectorChecker()
 {
+    pushMacroAssemblerRegisters();
+    StackAllocator earlyFailureStack = m_stackAllocator;
+
     Assembler::JumpList failureOnFunctionEntry;
     // Test selector's pseudo element equals to requested PseudoId.
     if (m_selectorContext != SelectorContext::QuerySelector && m_functionType == FunctionType::SelectorCheckerWithCheckingContext) {
@@ -1753,6 +1773,7 @@
     unsigned maximumBacktrackingAllocations = 8;
     if (m_selectorFragments.stackRequirements > maximumBacktrackingAllocations) {
         m_assembler.move(Assembler::TrustedImm32(0), returnRegister);
+        popMacroAssemblerRegisters(m_stackAllocator);
         m_assembler.ret();
         return;
     }
@@ -1811,9 +1832,13 @@
 
     if (m_functionType == FunctionType::SimpleSelectorChecker) {
         if (temporaryStackBase == m_stackAllocator.stackTop() && !reservedCalleeSavedRegisters && !needsEpilogue) {
+            StackAllocator successStack = m_stackAllocator;
+            StackAllocator failureStack = m_stackAllocator;
+
             ASSERT(!m_selectorFragments.stackRequirements);
             // Success.
             m_assembler.move(Assembler::TrustedImm32(1), returnRegister);
+            popMacroAssemblerRegisters(successStack);
             m_assembler.ret();
 
             // Failure.
@@ -1821,8 +1846,12 @@
             if (!failureCases.empty()) {
                 failureCases.link(&m_assembler);
                 m_assembler.move(Assembler::TrustedImm32(0), returnRegister);
+                popMacroAssemblerRegisters(failureStack);
                 m_assembler.ret();
-            }
+            } else
+                failureStack = successStack;
+
+            m_stackAllocator.merge(WTF::move(successStack), WTF::move(failureStack));
             return;
         }
     }
@@ -1842,16 +1871,22 @@
         m_stackAllocator.popAndDiscardUpTo(temporaryStackBase);
     if (reservedCalleeSavedRegisters)
         m_stackAllocator.pop(calleeSavedRegisterStackReferences, m_registerAllocator.restoreCalleeSavedRegisters());
+
+    StackAllocator successStack = m_stackAllocator;
     if (needsEpilogue)
-        generateEpilogue();
+        generateEpilogue(successStack);
+    popMacroAssemblerRegisters(successStack);
     m_assembler.ret();
 
     // Early failure on function entry case.
     if (!failureOnFunctionEntry.empty()) {
         failureOnFunctionEntry.link(&m_assembler);
         m_assembler.move(Assembler::TrustedImm32(0), returnRegister);
+        popMacroAssemblerRegisters(earlyFailureStack);
         m_assembler.ret();
-    }
+    } else
+        earlyFailureStack = successStack;
+    m_stackAllocator.merge(WTF::move(successStack), WTF::move(earlyFailureStack));
 }
 
 void SelectorCodeGenerator::generateSelectorCheckerExcludingPseudoElements(Assembler::JumpList& failureCases, const SelectorFragmentList& selectorFragmentList)

Modified: releases/WebKitGTK/webkit-2.8/Source/WebCore/cssjit/StackAllocator.h (186418 => 186419)


--- releases/WebKitGTK/webkit-2.8/Source/WebCore/cssjit/StackAllocator.h	2015-07-07 08:45:57 UTC (rev 186418)
+++ releases/WebKitGTK/webkit-2.8/Source/WebCore/cssjit/StackAllocator.h	2015-07-07 08:51:15 UTC (rev 186419)
@@ -237,6 +237,15 @@
         return JSC::MacroAssembler::Address(JSC::MacroAssembler::stackPointerRegister, offsetToStackReference(stackReference));
     }
 
+    StackAllocator& operator=(const StackAllocator& other)
+    {
+        RELEASE_ASSERT(&m_assembler == &other.m_assembler);
+        m_offsetFromTop = other.m_offsetFromTop;
+        m_hasFunctionCallPadding = other.m_hasFunctionCallPadding;
+        return *this;
+    }
+
+
 private:
     static unsigned stackUnitInBytes()
     {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to