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()
{