Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (161009 => 161010)
--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp 2013-12-23 19:51:38 UTC (rev 161009)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp 2013-12-23 20:21:28 UTC (rev 161010)
@@ -87,7 +87,8 @@
: traversalBacktrackingAction(BacktrackingAction::NoBacktracking)
, matchingBacktrackingAction(BacktrackingAction::NoBacktracking)
, backtrackingFlags(0)
- , tagName(0)
+ , tagName(nullptr)
+ , id(nullptr)
{
}
FragmentRelation relationToLeftFragment;
@@ -98,6 +99,7 @@
unsigned char backtrackingFlags;
const QualifiedName* tagName;
+ const AtomicString* id;
};
typedef JSC::MacroAssembler Assembler;
@@ -133,7 +135,9 @@
// Element properties matchers.
void generateElementMatching(Assembler::JumpList& failureCases, const SelectorFragment&);
+ void generateElementDataMatching(Assembler::JumpList& failureCases, const SelectorFragment&);
void generateElementHasTagName(Assembler::JumpList& failureCases, const QualifiedName& nameToMatch);
+ void generateElementHasId(Assembler::JumpList& failureCases, const LocalRegister& elementDataAddress, const AtomicString& idToMatch);
Assembler m_assembler;
RegisterAllocator m_registerAllocator;
@@ -142,6 +146,7 @@
FunctionType m_functionType;
Vector<SelectorFragment, 8> m_selectorFragments;
+ bool m_selectorCannotMatchAnything;
StackAllocator::StackReference m_checkingContextStackReference;
@@ -189,6 +194,7 @@
inline SelectorCodeGenerator::SelectorCodeGenerator(const CSSSelector* rootSelector)
: m_stackAllocator(m_assembler)
, m_functionType(FunctionType::SimpleSelectorChecker)
+ , m_selectorCannotMatchAnything(false)
#if CSS_SELECTOR_JIT_DEBUGGING
, m_originalSelector(rootSelector)
#endif
@@ -205,8 +211,16 @@
ASSERT(!fragment.tagName);
fragment.tagName = &(selector->tagQName());
break;
+ case CSSSelector::Id: {
+ const AtomicString& id = selector->value();
+ if (fragment.id) {
+ if (id != *fragment.id)
+ goto InconsistentSelector;
+ } else
+ fragment.id = &(selector->value());
+ break;
+ }
case CSSSelector::Unknown:
- case CSSSelector::Id:
case CSSSelector::Class:
case CSSSelector::Exact:
case CSSSelector::Set:
@@ -242,14 +256,16 @@
computeBacktrackingInformation();
return;
-
+InconsistentSelector:
+ m_functionType = FunctionType::SimpleSelectorChecker;
+ m_selectorCannotMatchAnything = true;
CannotHandleSelector:
m_selectorFragments.clear();
}
inline SelectorCompilationStatus SelectorCodeGenerator::compile(JSC::VM* vm, JSC::MacroAssemblerCodeRef& codeRef)
{
- if (m_selectorFragments.isEmpty())
+ if (m_selectorFragments.isEmpty() && !m_selectorCannotMatchAnything)
return SelectorCompilationStatus::CannotCompile;
m_registerAllocator.allocateRegister(elementAddressRegister);
@@ -284,12 +300,14 @@
m_registerAllocator.deallocateRegister(elementAddressRegister);
if (m_functionType == FunctionType::SimpleSelectorChecker) {
- // Success.
- m_assembler.move(Assembler::TrustedImm32(1), returnRegister);
- m_assembler.ret();
+ if (!m_selectorCannotMatchAnything) {
+ // Success.
+ m_assembler.move(Assembler::TrustedImm32(1), returnRegister);
+ m_assembler.ret();
+ }
// Failure.
- if (!failureCases.empty()) {
+ if (m_selectorCannotMatchAnything || !failureCases.empty()) {
failureCases.link(&m_assembler);
m_assembler.move(Assembler::TrustedImm32(0), returnRegister);
m_assembler.ret();
@@ -724,8 +742,25 @@
{
if (fragment.tagName)
generateElementHasTagName(failureCases, *(fragment.tagName));
+ generateElementDataMatching(failureCases, fragment);
}
+void SelectorCodeGenerator::generateElementDataMatching(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
+{
+ if (!fragment.id)
+ return;
+
+ // Generate:
+ // elementDataAddress = element->elementData();
+ // if (!elementDataAddress)
+ // failure!
+ LocalRegister elementDataAddress(m_registerAllocator);
+ m_assembler.loadPtr(Assembler::Address(elementAddressRegister, Element::elementDataMemoryOffset()), elementDataAddress);
+ failureCases.append(m_assembler.branchTestPtr(Assembler::Zero, elementDataAddress));
+
+ generateElementHasId(failureCases, elementDataAddress, *fragment.id);
+}
+
inline void SelectorCodeGenerator::generateElementHasTagName(Assembler::JumpList& failureCases, const QualifiedName& nameToMatch)
{
if (nameToMatch == anyQName())
@@ -752,6 +787,14 @@
}
}
+void SelectorCodeGenerator::generateElementHasId(Assembler::JumpList& failureCases, const LocalRegister& elementDataAddress, const AtomicString& idToMatch)
+{
+ // Compare the pointers of the AtomicStringImpl from idForStyleResolution with the reference idToMatch.
+ LocalRegister idToMatchRegister(m_registerAllocator);
+ m_assembler.move(Assembler::TrustedImmPtr(idToMatch.impl()), idToMatchRegister);
+ failureCases.append(m_assembler.branchPtr(Assembler::NotEqual, Assembler::Address(elementDataAddress, ElementData::idForStyleResolutionMemoryOffset()), idToMatchRegister));
+}
+
}; // namespace SelectorCompiler.
}; // namespace WebCore.
Modified: trunk/Source/WebCore/dom/Element.h (161009 => 161010)
--- trunk/Source/WebCore/dom/Element.h 2013-12-23 19:51:38 UTC (rev 161009)
+++ trunk/Source/WebCore/dom/Element.h 2013-12-23 20:21:28 UTC (rev 161010)
@@ -293,6 +293,7 @@
void stripScriptingAttributes(Vector<Attribute>&) const;
const ElementData* elementData() const { return m_elementData.get(); }
+ static ptrdiff_t elementDataMemoryOffset() { return OBJECT_OFFSETOF(Element, m_elementData); }
UniqueElementData& ensureUniqueElementData();
void synchronizeAllAttributes() const;
Modified: trunk/Source/WebCore/dom/ElementData.h (161009 => 161010)
--- trunk/Source/WebCore/dom/ElementData.h 2013-12-23 19:51:38 UTC (rev 161009)
+++ trunk/Source/WebCore/dom/ElementData.h 2013-12-23 20:21:28 UTC (rev 161010)
@@ -51,6 +51,7 @@
const SpaceSplitString& classNames() const { return m_classNames; }
const AtomicString& idForStyleResolution() const { return m_idForStyleResolution; }
+ static ptrdiff_t idForStyleResolutionMemoryOffset() { return OBJECT_OFFSETOF(ElementData, m_idForStyleResolution); }
void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyleResolution = newId; }
const StyleProperties* inlineStyle() const { return m_inlineStyle.get(); }