Title: [185621] trunk/Source
Revision
185621
Author
[email protected]
Date
2015-06-16 15:29:19 -0700 (Tue, 16 Jun 2015)

Log Message

[Content Extensions] Implement branch compaction for DFA bytecode.
https://bugs.webkit.org/show_bug.cgi?id=145619

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

Source/WebCore:

This patch adds another pass to the DFABytecodeCompiler which finds where the bytecode from each node
would be if it were compiled with no branch compaction, then uses that as a worst-case value to determine
how many bytes are needed to store the relative jump distance.  Then when linking, it will fill in the
value as it already did, but with a variable size jump.  The jumps are also now signed distances relative to
where the jump is stored.

This patch is covered by existing tests, which have many jumps that are near the -128/127 byte boundary,
and the switch from 16-bit jumps to 32-bit jumps near the -65536/65535 byte boundary is analogous.

* contentextensions/ContentExtensionCompiler.cpp:
(WebCore::ContentExtensions::compileRuleList):
* contentextensions/DFABytecode.h:
(WebCore::ContentExtensions::smallestPossibleJumpSize):
(WebCore::ContentExtensions::instructionSizeWithArguments):
* contentextensions/DFABytecodeCompiler.cpp:
(WebCore::ContentExtensions::append):
(WebCore::ContentExtensions::appendZeroes):
(WebCore::ContentExtensions::setBits):
(WebCore::ContentExtensions::appendActionBytecodeSize):
(WebCore::ContentExtensions::DFABytecodeCompiler::emitAppendAction):
(WebCore::ContentExtensions::DFABytecodeCompiler::longestPossibleJump):
(WebCore::ContentExtensions::DFABytecodeCompiler::emitJump):
(WebCore::ContentExtensions::DFABytecodeCompiler::emitCheckValue):
(WebCore::ContentExtensions::DFABytecodeCompiler::emitCheckValueRange):
(WebCore::ContentExtensions::DFABytecodeCompiler::emitTerminate):
(WebCore::ContentExtensions::DFABytecodeCompiler::compileNode):
(WebCore::ContentExtensions::DFABytecodeCompiler::compiledNodeMaxBytecodeSize):
(WebCore::ContentExtensions::DFABytecodeCompiler::ranges):
(WebCore::ContentExtensions::DFABytecodeCompiler::checkForRangeMaxBytecodeSize):
(WebCore::ContentExtensions::DFABytecodeCompiler::compileCheckForRange):
(WebCore::ContentExtensions::DFABytecodeCompiler::nodeTransitionsMaxBytecodeSize):
(WebCore::ContentExtensions::DFABytecodeCompiler::compileNodeTransitions):
(WebCore::ContentExtensions::DFABytecodeCompiler::compile):
(WebCore::ContentExtensions::set32Bits): Deleted.
* contentextensions/DFABytecodeCompiler.h:
* contentextensions/DFABytecodeInterpreter.cpp:
(WebCore::ContentExtensions::getBits):
(WebCore::ContentExtensions::getInstruction):
(WebCore::ContentExtensions::jumpSizeInBytes):
(WebCore::ContentExtensions::getJumpSize):
(WebCore::ContentExtensions::getJumpDistance):
(WebCore::ContentExtensions::DFABytecodeInterpreter::interpretAppendAction):
(WebCore::ContentExtensions::DFABytecodeInterpreter::interpretTestFlagsAndAppendAction):
(WebCore::ContentExtensions::DFABytecodeInterpreter::actionsForDefaultStylesheetFromDFARoot):
(WebCore::ContentExtensions::DFABytecodeInterpreter::interpret):
* loader/ResourceLoadInfo.h:

Source/WebKit2:

* UIProcess/API/APIUserContentExtensionStore.h:
Increment version number to reflect changes to bytecode.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (185620 => 185621)


--- trunk/Source/WebCore/ChangeLog	2015-06-16 22:18:39 UTC (rev 185620)
+++ trunk/Source/WebCore/ChangeLog	2015-06-16 22:29:19 UTC (rev 185621)
@@ -1,3 +1,57 @@
+2015-06-16  Alex Christensen  <[email protected]>
+
+        [Content Extensions] Implement branch compaction for DFA bytecode.
+        https://bugs.webkit.org/show_bug.cgi?id=145619
+
+        Reviewed by Benjamin Poulain.
+
+        This patch adds another pass to the DFABytecodeCompiler which finds where the bytecode from each node
+        would be if it were compiled with no branch compaction, then uses that as a worst-case value to determine
+        how many bytes are needed to store the relative jump distance.  Then when linking, it will fill in the 
+        value as it already did, but with a variable size jump.  The jumps are also now signed distances relative to
+        where the jump is stored.
+
+        This patch is covered by existing tests, which have many jumps that are near the -128/127 byte boundary,
+        and the switch from 16-bit jumps to 32-bit jumps near the -65536/65535 byte boundary is analogous.
+
+        * contentextensions/ContentExtensionCompiler.cpp:
+        (WebCore::ContentExtensions::compileRuleList):
+        * contentextensions/DFABytecode.h:
+        (WebCore::ContentExtensions::smallestPossibleJumpSize):
+        (WebCore::ContentExtensions::instructionSizeWithArguments):
+        * contentextensions/DFABytecodeCompiler.cpp:
+        (WebCore::ContentExtensions::append):
+        (WebCore::ContentExtensions::appendZeroes):
+        (WebCore::ContentExtensions::setBits):
+        (WebCore::ContentExtensions::appendActionBytecodeSize):
+        (WebCore::ContentExtensions::DFABytecodeCompiler::emitAppendAction):
+        (WebCore::ContentExtensions::DFABytecodeCompiler::longestPossibleJump):
+        (WebCore::ContentExtensions::DFABytecodeCompiler::emitJump):
+        (WebCore::ContentExtensions::DFABytecodeCompiler::emitCheckValue):
+        (WebCore::ContentExtensions::DFABytecodeCompiler::emitCheckValueRange):
+        (WebCore::ContentExtensions::DFABytecodeCompiler::emitTerminate):
+        (WebCore::ContentExtensions::DFABytecodeCompiler::compileNode):
+        (WebCore::ContentExtensions::DFABytecodeCompiler::compiledNodeMaxBytecodeSize):
+        (WebCore::ContentExtensions::DFABytecodeCompiler::ranges):
+        (WebCore::ContentExtensions::DFABytecodeCompiler::checkForRangeMaxBytecodeSize):
+        (WebCore::ContentExtensions::DFABytecodeCompiler::compileCheckForRange):
+        (WebCore::ContentExtensions::DFABytecodeCompiler::nodeTransitionsMaxBytecodeSize):
+        (WebCore::ContentExtensions::DFABytecodeCompiler::compileNodeTransitions):
+        (WebCore::ContentExtensions::DFABytecodeCompiler::compile):
+        (WebCore::ContentExtensions::set32Bits): Deleted.
+        * contentextensions/DFABytecodeCompiler.h:
+        * contentextensions/DFABytecodeInterpreter.cpp:
+        (WebCore::ContentExtensions::getBits):
+        (WebCore::ContentExtensions::getInstruction):
+        (WebCore::ContentExtensions::jumpSizeInBytes):
+        (WebCore::ContentExtensions::getJumpSize):
+        (WebCore::ContentExtensions::getJumpDistance):
+        (WebCore::ContentExtensions::DFABytecodeInterpreter::interpretAppendAction):
+        (WebCore::ContentExtensions::DFABytecodeInterpreter::interpretTestFlagsAndAppendAction):
+        (WebCore::ContentExtensions::DFABytecodeInterpreter::actionsForDefaultStylesheetFromDFARoot):
+        (WebCore::ContentExtensions::DFABytecodeInterpreter::interpret):
+        * loader/ResourceLoadInfo.h:
+
 2015-06-16  Carlos Alberto Lopez Perez  <[email protected]>
 
         [GTK] [Wayland] Should be possible to build with support for both X11 and Wayland.

Modified: trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp (185620 => 185621)


--- trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp	2015-06-16 22:18:39 UTC (rev 185620)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp	2015-06-16 22:29:19 UTC (rev 185621)
@@ -178,6 +178,8 @@
         ASSERT(trigger.urlFilter.length());
 
         // High bits are used for flags. This should match how they are used in DFABytecodeCompiler::compileNode.
+        ASSERT(!trigger.flags || ActionFlagMask & (static_cast<uint64_t>(trigger.flags) << 32));
+        ASSERT(!(~ActionFlagMask & (static_cast<uint64_t>(trigger.flags) << 32)));
         uint64_t actionLocationAndFlags = (static_cast<uint64_t>(trigger.flags) << 32) | static_cast<uint64_t>(actionLocations[ruleIndex]);
         URLFilterParser::ParseStatus status = URLFilterParser::Ok;
         if (trigger.domains.isEmpty()) {

Modified: trunk/Source/WebCore/contentextensions/DFABytecode.h (185620 => 185621)


--- trunk/Source/WebCore/contentextensions/DFABytecode.h	2015-06-16 22:18:39 UTC (rev 185620)
+++ trunk/Source/WebCore/contentextensions/DFABytecode.h	2015-06-16 22:29:19 UTC (rev 185621)
@@ -41,46 +41,69 @@
 
     // CheckValue has two arguments:
     // The value to check (1 byte),
-    // The index to jump to if the values are equal (4 bytes).
-    CheckValueCaseInsensitive,
-    CheckValueCaseSensitive,
+    // The distance to jump if the values are equal (1-4 bytes, signed).
+    CheckValueCaseInsensitive = 0x0,
+    CheckValueCaseSensitive = 0x1,
 
     // Jump to an offset if the input value is within a certain range.
     // The lower value (1 byte).
     // The higher value (1 byte).
-    // The index to jump to if the value is in the range (4 bytes).
-    CheckValueRangeCaseInsensitive,
-    CheckValueRangeCaseSensitive,
+    // The distance to jump if the value is in the range (1-4 bytes, signed).
+    CheckValueRangeCaseInsensitive = 0x2,
+    CheckValueRangeCaseSensitive = 0x3,
 
     // AppendAction has one argument:
     // The action to append (4 bytes).
-    AppendAction,
-    AppendActionDefaultStylesheet,
-    AppendActionWithIfDomain,
+    AppendAction = 0x4,
+    AppendActionDefaultStylesheet = 0x5,
+    AppendActionWithIfDomain = 0x6,
     
     // TestFlagsAndAppendAction has two arguments:
     // The flags to check before appending (2 bytes).
     // The action to append (4 bytes).
-    TestFlagsAndAppendAction,
-    TestFlagsAndAppendActionWithIfDomain,
+    TestFlagsAndAppendAction = 0x7,
+    TestFlagsAndAppendActionWithIfDomain = 0x8,
 
     // Terminate has no arguments.
-    Terminate,
+    Terminate = 0x9,
 
     // Jump has one argument:
-    // The index to jump to unconditionally (4 bytes).
-    Jump,
+    // The distance to jump (1-4 bytes, signed).
+    Jump = 0xA,
 };
 
+// The last four bits contain the instruction type.
+const uint8_t DFABytecodeInstructionMask = 0x0F;
+const uint8_t DFABytecodeJumpSizeMask = 0xF0;
+
+// DFA bytecode starts with a 4 byte header which contains the size of this DFA.
+typedef uint32_t DFAHeader;
+
+// A DFABytecodeJumpSize is stored in the top four bits of the DFABytecodeInstructions that have a jump.
+enum DFABytecodeJumpSize {
+    Int8 = 0x10,
+    Int16 = 0x20,
+    Int32 = 0x30,
+};
+
+static inline DFABytecodeJumpSize smallestPossibleJumpSize(int32_t longestPossibleJump)
+{
+    if (longestPossibleJump <= std::numeric_limits<int8_t>::max() && longestPossibleJump >= std::numeric_limits<int8_t>::min())
+        return Int8;
+    if (longestPossibleJump <= std::numeric_limits<int16_t>::max() && longestPossibleJump >= std::numeric_limits<int16_t>::min())
+        return Int16;
+    return Int32;
+}
+    
 static inline size_t instructionSizeWithArguments(DFABytecodeInstruction instruction)
 {
     switch (instruction) {
     case DFABytecodeInstruction::CheckValueCaseSensitive:
     case DFABytecodeInstruction::CheckValueCaseInsensitive:
-        return sizeof(DFABytecodeInstruction) + sizeof(uint8_t) + sizeof(uint32_t);
     case DFABytecodeInstruction::CheckValueRangeCaseSensitive:
     case DFABytecodeInstruction::CheckValueRangeCaseInsensitive:
-        return sizeof(DFABytecodeInstruction) + sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint32_t);
+    case DFABytecodeInstruction::Jump:
+        RELEASE_ASSERT_NOT_REACHED(); // Variable instruction size.
     case DFABytecodeInstruction::AppendAction:
     case DFABytecodeInstruction::AppendActionDefaultStylesheet:
     case DFABytecodeInstruction::AppendActionWithIfDomain:
@@ -90,8 +113,6 @@
         return sizeof(DFABytecodeInstruction) + sizeof(uint16_t) + sizeof(uint32_t);
     case DFABytecodeInstruction::Terminate:
         return sizeof(DFABytecodeInstruction);
-    case DFABytecodeInstruction::Jump:
-        return sizeof(DFABytecodeInstruction) + sizeof(uint32_t);
     }
 }
     

Modified: trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.cpp (185620 => 185621)


--- trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.cpp	2015-06-16 22:18:39 UTC (rev 185620)
+++ trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.cpp	2015-06-16 22:29:19 UTC (rev 185621)
@@ -43,15 +43,40 @@
     *reinterpret_cast<IntType*>(&bytecode[bytecode.size() - sizeof(IntType)]) = value;
 }
 
-inline void set32Bits(Vector<DFABytecode>& bytecode, uint32_t index, uint32_t value)
+inline void appendZeroes(Vector<DFABytecode>& bytecode, DFABytecodeJumpSize jumpSize)
 {
-    *reinterpret_cast<uint32_t*>(&bytecode[index]) = value;
+    switch (jumpSize) {
+    case DFABytecodeJumpSize::Int8:
+        append<int8_t>(bytecode, 0); // This value will be set when linking.
+        break;
+    case DFABytecodeJumpSize::Int16:
+        append<int16_t>(bytecode, 0); // This value will be set when linking.
+        break;
+    case DFABytecodeJumpSize::Int32:
+        append<int32_t>(bytecode, 0); // This value will be set when linking.
+        break;
+    }
 }
 
+template <typename IntType>
+inline void setBits(Vector<DFABytecode>& bytecode, uint32_t index, IntType value)
+{
+    RELEASE_ASSERT(index + sizeof(IntType) <= bytecode.size());
+    ASSERT_WITH_MESSAGE(!*reinterpret_cast<IntType*>(&bytecode[index]), "Right now we should only be using setBits to overwrite values that were zero as a placeholder.");
+    *reinterpret_cast<IntType*>(&bytecode[index]) = value;
+}
+
+static unsigned appendActionBytecodeSize(uint64_t action)
+{
+    if (action & ActionFlagMask)
+        return sizeof(DFABytecodeInstruction) + sizeof(uint16_t) + sizeof(uint32_t);
+    return sizeof(DFABytecodeInstruction) + sizeof(uint32_t);
+}
+    
 void DFABytecodeCompiler::emitAppendAction(uint64_t action)
 {
     // High bits are used to store flags. See compileRuleList.
-    if (action & 0xFFFF00000000) {
+    if (action & ActionFlagMask) {
         ASSERT(!(action & DisplayNoneStyleSheetFlag));
         if (action & IfDomainFlag)
             append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::TestFlagsAndAppendActionWithIfDomain);
@@ -71,30 +96,62 @@
     }
 }
 
-void DFABytecodeCompiler::emitJump(uint32_t destinationNodeIndex)
+int32_t DFABytecodeCompiler::longestPossibleJump(uint32_t instructionLocation, uint32_t sourceNodeIndex, uint32_t destinationNodeIndex)
 {
-    append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::Jump);
-    m_linkRecords.append(std::make_pair(m_bytecode.size(), destinationNodeIndex));
-    append<uint32_t>(m_bytecode, 0); // This value will be set when linking.
+    if (m_nodeStartOffsets[destinationNodeIndex] == std::numeric_limits<uint32_t>::max()) {
+        // Jumping to a node that hasn't been compiled yet, we don't know exactly how far forward we will need to jump,
+        // so make sure we have enough room for the worst possible case, the farthest possible jump
+        // which would be the distance if there were no compacted branches between this jump and its destination.
+        ASSERT(instructionLocation >= m_nodeStartOffsets[sourceNodeIndex]);
+        ASSERT(m_maxNodeStartOffsets[destinationNodeIndex] > m_maxNodeStartOffsets[sourceNodeIndex]);
+        ASSERT(m_nodeStartOffsets[sourceNodeIndex] != std::numeric_limits<uint32_t>::max());
+        return m_maxNodeStartOffsets[destinationNodeIndex] - m_maxNodeStartOffsets[sourceNodeIndex] - (m_nodeStartOffsets[sourceNodeIndex] - instructionLocation);
+    }
+    
+    // Jumping to an already compiled node, we already know exactly where we will need to jump to.
+    ASSERT(m_nodeStartOffsets[destinationNodeIndex] <= instructionLocation);
+    return m_nodeStartOffsets[destinationNodeIndex] - instructionLocation;
 }
+    
+void DFABytecodeCompiler::emitJump(uint32_t sourceNodeIndex, uint32_t destinationNodeIndex)
+{
+    uint32_t instructionLocation = m_bytecode.size();
+    uint32_t jumpLocation = instructionLocation + sizeof(uint8_t);
+    int32_t longestPossibleJumpDistance = longestPossibleJump(instructionLocation, sourceNodeIndex, destinationNodeIndex);
+    DFABytecodeJumpSize jumpSize = smallestPossibleJumpSize(longestPossibleJumpDistance);
+    append<uint8_t>(m_bytecode, static_cast<uint8_t>(DFABytecodeInstruction::Jump) | jumpSize);
 
-void DFABytecodeCompiler::emitCheckValue(uint8_t value, uint32_t destinationNodeIndex, bool caseSensitive)
+    m_linkRecords.append(LinkRecord({jumpSize, longestPossibleJumpDistance, instructionLocation, jumpLocation, destinationNodeIndex}));
+    appendZeroes(m_bytecode, jumpSize);
+}
+
+void DFABytecodeCompiler::emitCheckValue(uint8_t value, uint32_t sourceNodeIndex, uint32_t destinationNodeIndex, bool caseSensitive)
 {
-    append<DFABytecodeInstruction>(m_bytecode, caseSensitive ? DFABytecodeInstruction::CheckValueCaseSensitive : DFABytecodeInstruction::CheckValueCaseInsensitive);
+    uint32_t instructionLocation = m_bytecode.size();
+    uint32_t jumpLocation = instructionLocation + 2 * sizeof(uint8_t);
+    int32_t longestPossibleJumpDistance = longestPossibleJump(instructionLocation, sourceNodeIndex, destinationNodeIndex);
+    DFABytecodeJumpSize jumpSize = smallestPossibleJumpSize(longestPossibleJumpDistance);
+    DFABytecodeInstruction instruction = caseSensitive ? DFABytecodeInstruction::CheckValueCaseSensitive : DFABytecodeInstruction::CheckValueCaseInsensitive;
+    append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | jumpSize);
     append<uint8_t>(m_bytecode, value);
-    m_linkRecords.append(std::make_pair(m_bytecode.size(), destinationNodeIndex));
-    append<uint32_t>(m_bytecode, 0); // This value will be set when linking.
+    m_linkRecords.append(LinkRecord({jumpSize, longestPossibleJumpDistance, instructionLocation, jumpLocation, destinationNodeIndex}));
+    appendZeroes(m_bytecode, jumpSize);
 }
 
-void DFABytecodeCompiler::emitCheckValueRange(uint8_t lowValue, uint8_t highValue, uint32_t destinationNodeIndex, bool caseSensitive)
+void DFABytecodeCompiler::emitCheckValueRange(uint8_t lowValue, uint8_t highValue, uint32_t sourceNodeIndex, uint32_t destinationNodeIndex, bool caseSensitive)
 {
     ASSERT_WITH_MESSAGE(lowValue < highValue, "The instruction semantic impose lowValue is strictly less than highValue.");
 
-    append<DFABytecodeInstruction>(m_bytecode, caseSensitive ? DFABytecodeInstruction::CheckValueRangeCaseSensitive : DFABytecodeInstruction::CheckValueRangeCaseInsensitive);
+    uint32_t instructionLocation = m_bytecode.size();
+    uint32_t jumpLocation = instructionLocation + 3 * sizeof(uint8_t);
+    int32_t longestPossibleJumpDistance = longestPossibleJump(instructionLocation, sourceNodeIndex, destinationNodeIndex);
+    DFABytecodeJumpSize jumpSize = smallestPossibleJumpSize(longestPossibleJumpDistance);
+    DFABytecodeInstruction instruction = caseSensitive ? DFABytecodeInstruction::CheckValueRangeCaseSensitive : DFABytecodeInstruction::CheckValueRangeCaseInsensitive;
+    append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | jumpSize);
     append<uint8_t>(m_bytecode, lowValue);
     append<uint8_t>(m_bytecode, highValue);
-    m_linkRecords.append(std::make_pair(m_bytecode.size(), destinationNodeIndex));
-    append<uint32_t>(m_bytecode, 0); // This value will be set when linking.
+    m_linkRecords.append(LinkRecord({jumpSize, longestPossibleJumpDistance, instructionLocation, jumpLocation, destinationNodeIndex}));
+    appendZeroes(m_bytecode, jumpSize);
 }
 
 void DFABytecodeCompiler::emitTerminate()
@@ -104,9 +161,11 @@
 
 void DFABytecodeCompiler::compileNode(uint32_t index, bool root)
 {
+    unsigned startSize = m_bytecode.size();
+    
     const DFANode& node = m_dfa.nodes[index];
     if (node.isKilled()) {
-        m_nodeStartOffsets[index] = std::numeric_limits<uint32_t>::max();
+        ASSERT(m_nodeStartOffsets[index] == std::numeric_limits<uint32_t>::max());
         return;
     }
 
@@ -122,10 +181,24 @@
     if (root)
         m_nodeStartOffsets[index] = m_bytecode.size();
     
-    compileNodeTransitions(node);
+    compileNodeTransitions(index);
+    
+    ASSERT_UNUSED(startSize, m_bytecode.size() - startSize <= compiledNodeMaxBytecodeSize(index));
 }
+    
+unsigned DFABytecodeCompiler::compiledNodeMaxBytecodeSize(uint32_t index)
+{
+    const DFANode& node = m_dfa.nodes[index];
+    if (node.isKilled())
+        return 0;
+    unsigned size = 0;
+    for (uint64_t action : node.actions(m_dfa))
+        size += appendActionBytecodeSize(action);
+    size += nodeTransitionsMaxBytecodeSize(node);
+    return size;
+}
 
-void DFABytecodeCompiler::compileNodeTransitions(const DFANode& node)
+Vector<DFABytecodeCompiler::Range> DFABytecodeCompiler::ranges(const DFANode& node)
 {
     uint32_t destinations[128];
     memset(destinations, 0xff, sizeof(destinations));
@@ -187,52 +260,119 @@
         // If a range goes to 127, there will never be values higher than it, so checking for case-insensitive ranges would always fail.
         ranges.append(Range(rangeMin, 127, destinations[rangeMin], true));
     }
-
-    for (const auto& range : ranges)
-        compileCheckForRange(range);
-    if (node.hasFallbackTransition())
-        emitJump(node.fallbackTransitionDestination(m_dfa));
-    else
-        emitTerminate();
+    return ranges;
 }
+    
+unsigned DFABytecodeCompiler::checkForRangeMaxBytecodeSize(const Range& range)
+{
+    if (range.min == range.max)
+        return sizeof(DFABytecodeInstruction::CheckValueCaseInsensitive) + sizeof(uint8_t) + sizeof(uint32_t);
+    return sizeof(DFABytecodeInstruction::CheckValueRangeCaseInsensitive) + 2 * sizeof(uint8_t) + sizeof(uint32_t);
+}
 
-void DFABytecodeCompiler::compileCheckForRange(const Range& range)
+void DFABytecodeCompiler::compileCheckForRange(uint32_t nodeIndex, const Range& range)
 {
+    unsigned startSize = m_bytecode.size();
     ASSERT_WITH_MESSAGE(range.max < 128, "The DFA engine only supports the ASCII alphabet.");
     ASSERT(range.min <= range.max);
 
     if (range.min == range.max)
-        emitCheckValue(range.min, range.destination, range.caseSensitive);
+        emitCheckValue(range.min, nodeIndex, range.destination, range.caseSensitive);
     else
-        emitCheckValueRange(range.min, range.max, range.destination, range.caseSensitive);
+        emitCheckValueRange(range.min, range.max, nodeIndex, range.destination, range.caseSensitive);
+    
+    ASSERT_UNUSED(startSize, m_bytecode.size() - startSize <= checkForRangeMaxBytecodeSize(range));
 }
 
+unsigned DFABytecodeCompiler::nodeTransitionsMaxBytecodeSize(const DFANode& node)
+{
+    unsigned size = 0;
+    for (const auto& range : ranges(node))
+        size += checkForRangeMaxBytecodeSize(range);
+    if (node.hasFallbackTransition())
+        size += sizeof(DFABytecodeInstruction::Jump) + sizeof(uint32_t);
+    else
+        size += instructionSizeWithArguments(DFABytecodeInstruction::Terminate);
+    return size;
+}
+
+void DFABytecodeCompiler::compileNodeTransitions(uint32_t nodeIndex)
+{
+    const DFANode& node = m_dfa.nodes[nodeIndex];
+    unsigned startSize = m_bytecode.size();
+    
+    for (const auto& range : ranges(node))
+        compileCheckForRange(nodeIndex, range);
+    if (node.hasFallbackTransition())
+        emitJump(nodeIndex, node.fallbackTransitionDestination(m_dfa));
+    else
+        emitTerminate();
+
+    ASSERT_UNUSED(startSize, m_bytecode.size() - startSize <= nodeTransitionsMaxBytecodeSize(node));
+}
+
 void DFABytecodeCompiler::compile()
 {
-    // DFA header.
     uint32_t startLocation = m_bytecode.size();
-    append<uint32_t>(m_bytecode, 0);
+    append<DFAHeader>(m_bytecode, 0); // This will be set when we are finished compiling this DFA.
+
     m_nodeStartOffsets.resize(m_dfa.nodes.size());
+    for (unsigned i = 0; i < m_dfa.nodes.size(); ++i)
+        m_nodeStartOffsets[i] = std::numeric_limits<uint32_t>::max();
     
+    // Populate m_maxNodeStartOffsets with a worst-case index of where the node would be with no branch compaction.
+    // Compacting the branches using 1-4 byte signed jump distances should only make nodes closer together than this.
+    ASSERT(m_maxNodeStartOffsets.isEmpty());
+    m_maxNodeStartOffsets.clear();
+    m_maxNodeStartOffsets.resize(m_dfa.nodes.size());
+    unsigned rootActionsSize = 0;
+    for (uint64_t action : m_dfa.nodes[m_dfa.root].actions(m_dfa))
+        rootActionsSize += appendActionBytecodeSize(action);
+    m_maxNodeStartOffsets[m_dfa.root] = sizeof(DFAHeader) + rootActionsSize;
+    unsigned nextIndex = sizeof(DFAHeader) + compiledNodeMaxBytecodeSize(m_dfa.root);
+    for (uint32_t i = 0; i < m_dfa.nodes.size(); i++) {
+        if (i != m_dfa.root) {
+            m_maxNodeStartOffsets[i] = nextIndex;
+            nextIndex += compiledNodeMaxBytecodeSize(i);
+        }
+    }
+    
     // Make sure the root is always at the beginning of the bytecode.
     compileNode(m_dfa.root, true);
     for (uint32_t i = 0; i < m_dfa.nodes.size(); i++) {
         if (i != m_dfa.root)
             compileNode(i, false);
     }
+    
+    ASSERT(m_maxNodeStartOffsets.size() == m_nodeStartOffsets.size());
+    for (unsigned i = 0; i < m_dfa.nodes.size(); ++i) {
+        if (m_nodeStartOffsets[i] != std::numeric_limits<uint32_t>::max())
+            ASSERT(m_maxNodeStartOffsets[i] >= m_nodeStartOffsets[i]);
+    }
 
     // Link.
     for (const auto& linkRecord : m_linkRecords) {
-        uint32_t offset = linkRecord.first;
-        ASSERT(!(*reinterpret_cast<uint32_t*>(&m_bytecode[offset])));
-
-        uint32_t target = m_nodeStartOffsets[linkRecord.second];
-        RELEASE_ASSERT(target != std::numeric_limits<uint32_t>::max());
-        set32Bits(m_bytecode, offset, m_nodeStartOffsets[linkRecord.second]);
+        uint32_t destination = m_nodeStartOffsets[linkRecord.destinationNodeIndex];
+        RELEASE_ASSERT(destination < std::numeric_limits<int32_t>::max());
+        int32_t distance = destination - linkRecord.instructionLocation;
+        ASSERT(abs(distance) <= abs(linkRecord.longestPossibleJump));
+        
+        switch (linkRecord.jumpSize) {
+        case Int8:
+            RELEASE_ASSERT(distance == static_cast<int8_t>(distance));
+            setBits<int8_t>(m_bytecode, linkRecord.jumpLocation, static_cast<int8_t>(distance));
+            break;
+        case Int16:
+            RELEASE_ASSERT(distance == static_cast<int16_t>(distance));
+            setBits<int16_t>(m_bytecode, linkRecord.jumpLocation, static_cast<int16_t>(distance));
+            break;
+        case Int32:
+            setBits<int32_t>(m_bytecode, linkRecord.jumpLocation, distance);
+            break;
+        }
     }
     
-    // Set size header.
-    set32Bits(m_bytecode, startLocation, m_bytecode.size() - startLocation);
+    setBits<DFAHeader>(m_bytecode, startLocation, m_bytecode.size() - startLocation);
 }
     
 } // namespace ContentExtensions

Modified: trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.h (185620 => 185621)


--- trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.h	2015-06-16 22:18:39 UTC (rev 185620)
+++ trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.h	2015-06-16 22:29:19 UTC (rev 185621)
@@ -62,24 +62,36 @@
         uint32_t destination;
         bool caseSensitive;
     };
-    void compileNode(uint32_t, bool root);
-    void compileNodeTransitions(const DFANode&);
-    void compileCheckForRange(const Range&);
+    Vector<Range> ranges(const DFANode&);
+    
+    unsigned compiledNodeMaxBytecodeSize(uint32_t index);
+    void compileNode(uint32_t index, bool root);
+    unsigned nodeTransitionsMaxBytecodeSize(const DFANode&);
+    void compileNodeTransitions(uint32_t nodeIndex);
+    unsigned checkForRangeMaxBytecodeSize(const Range&);
+    void compileCheckForRange(uint32_t nodeIndex, const Range&);
+    int32_t longestPossibleJump(uint32_t jumpLocation, uint32_t sourceNodeIndex, uint32_t destinationNodeIndex);
 
     void emitAppendAction(uint64_t);
-    void emitJump(uint32_t destinationNodeIndex);
-    void emitCheckValue(uint8_t value, uint32_t destinationNodeIndex, bool caseSensitive);
-    void emitCheckValueRange(uint8_t lowValue, uint8_t highValue, uint32_t destinationNodeIndex, bool caseSensitive);
+    void emitJump(uint32_t sourceNodeIndex, uint32_t destinationNodeIndex);
+    void emitCheckValue(uint8_t value, uint32_t sourceNodeIndex, uint32_t destinationNodeIndex, bool caseSensitive);
+    void emitCheckValueRange(uint8_t lowValue, uint8_t highValue, uint32_t sourceNodeIndex, uint32_t destinationNodeIndex, bool caseSensitive);
     void emitTerminate();
 
     Vector<DFABytecode>& m_bytecode;
     const DFA& m_dfa;
     
+    Vector<uint32_t> m_maxNodeStartOffsets;
     Vector<uint32_t> m_nodeStartOffsets;
     
-    // The first value is the index in the bytecode buffer where the jump is to be written.
-    // The second value is the index of the node to jump to.
-    Vector<std::pair<uint32_t, uint32_t>> m_linkRecords;
+    struct LinkRecord {
+        DFABytecodeJumpSize jumpSize;
+        int32_t longestPossibleJump;
+        uint32_t instructionLocation;
+        uint32_t jumpLocation;
+        uint32_t destinationNodeIndex;
+    };
+    Vector<LinkRecord> m_linkRecords;
 };
 
 } // namespace ContentExtensions

Modified: trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp (185620 => 185621)


--- trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp	2015-06-16 22:18:39 UTC (rev 185620)
+++ trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp	2015-06-16 22:29:19 UTC (rev 185621)
@@ -36,10 +36,10 @@
 namespace ContentExtensions {
 
 template <typename IntType>
-static inline IntType getBits(const DFABytecode* bytecode, unsigned bytecodeLength, unsigned index, Vector<bool>& pagesUsed)
+static inline IntType getBits(const DFABytecode* bytecode, uint32_t bytecodeLength, uint32_t index, Vector<bool>& pagesUsed)
 {
 #if CONTENT_EXTENSIONS_MEMORY_REPORTING
-    unsigned page = index / CONTENT_EXTENSIONS_PAGE_SIZE;
+    uint32_t page = index / CONTENT_EXTENSIONS_PAGE_SIZE;
     while (pagesUsed.size() < (bytecodeLength + CONTENT_EXTENSIONS_PAGE_SIZE - 1) / CONTENT_EXTENSIONS_PAGE_SIZE)
         pagesUsed.append(false);
     pagesUsed[page] = true;
@@ -49,23 +49,64 @@
     ASSERT_UNUSED(bytecodeLength, index + sizeof(IntType) <= bytecodeLength);
     return *reinterpret_cast<const IntType*>(&bytecode[index]);
 }
-    
-void DFABytecodeInterpreter::interpretAppendAction(unsigned& programCounter, Actions& actions, bool ifDomain)
+
+// FIXME: Get rid of pagesUsed. We don't need to keep track of the pages used.
+static inline DFABytecodeInstruction getInstruction(const DFABytecode* bytecode, uint32_t bytecodeLength, uint32_t index, Vector<bool>& pagesUsed)
 {
-    ASSERT(getBits<DFABytecodeInstruction>(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed) == DFABytecodeInstruction::AppendAction
-        || getBits<DFABytecodeInstruction>(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed) == DFABytecodeInstruction::AppendActionWithIfDomain
-        || getBits<DFABytecodeInstruction>(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed) == DFABytecodeInstruction::AppendActionDefaultStylesheet);
-    actions.add((ifDomain ? IfDomainFlag : 0) | static_cast<uint64_t>(getBits<unsigned>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode), m_pagesUsed)));
+    return static_cast<DFABytecodeInstruction>(getBits<uint8_t>(bytecode, bytecodeLength, index, pagesUsed) & DFABytecodeInstructionMask);
+}
+
+static inline size_t jumpSizeInBytes(DFABytecodeJumpSize jumpSize)
+{
+    switch (jumpSize) {
+    case Int8:
+        return sizeof(int8_t);
+    case Int16:
+        return sizeof(int16_t);
+    case Int32:
+        return sizeof(int32_t);
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+}
+
+static inline DFABytecodeJumpSize getJumpSize(const DFABytecode* bytecode, uint32_t bytecodeLength, uint32_t index, Vector<bool>& pagesUsed)
+{
+    DFABytecodeJumpSize jumpSize = static_cast<DFABytecodeJumpSize>(getBits<uint8_t>(bytecode, bytecodeLength, index, pagesUsed) & DFABytecodeJumpSizeMask);
+    ASSERT(jumpSize == DFABytecodeJumpSize::Int32 || jumpSize == DFABytecodeJumpSize::Int16 || jumpSize == DFABytecodeJumpSize::Int8);
+    return jumpSize;
+}
+
+static inline int32_t getJumpDistance(const DFABytecode* bytecode, uint32_t bytecodeLength, uint32_t index, Vector<bool>& pagesUsed, DFABytecodeJumpSize jumpSize)
+{
+    switch (jumpSize) {
+    case Int8:
+        return getBits<int8_t>(bytecode, bytecodeLength, index, pagesUsed);
+    case Int16:
+        return getBits<int16_t>(bytecode, bytecodeLength, index, pagesUsed);
+    case Int32:
+        return getBits<int32_t>(bytecode, bytecodeLength, index, pagesUsed);
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+}
+
+void DFABytecodeInterpreter::interpretAppendAction(uint32_t& programCounter, Actions& actions, bool ifDomain)
+{
+    ASSERT(getInstruction(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed) == DFABytecodeInstruction::AppendAction
+        || getInstruction(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed) == DFABytecodeInstruction::AppendActionWithIfDomain
+        || getInstruction(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed) == DFABytecodeInstruction::AppendActionDefaultStylesheet);
+    actions.add((ifDomain ? IfDomainFlag : 0) | static_cast<uint64_t>(getBits<uint32_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction), m_pagesUsed)));
     programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendAction);
     ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::AppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::AppendActionWithIfDomain));
     ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::AppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::AppendActionDefaultStylesheet));
 }
 
-void DFABytecodeInterpreter::interpretTestFlagsAndAppendAction(unsigned& programCounter, uint16_t flags, Actions& actions, bool ifDomain)
+void DFABytecodeInterpreter::interpretTestFlagsAndAppendAction(uint32_t& programCounter, uint16_t flags, Actions& actions, bool ifDomain)
 {
-    ASSERT(getBits<DFABytecodeInstruction>(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed) == DFABytecodeInstruction::TestFlagsAndAppendAction
-        || getBits<DFABytecodeInstruction>(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed) == DFABytecodeInstruction::TestFlagsAndAppendActionWithIfDomain);
-    uint16_t flagsToCheck = getBits<uint16_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode), m_pagesUsed);
+    ASSERT(getInstruction(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed) == DFABytecodeInstruction::TestFlagsAndAppendAction
+        || getInstruction(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed) == DFABytecodeInstruction::TestFlagsAndAppendActionWithIfDomain);
+    uint16_t flagsToCheck = getBits<uint16_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction), m_pagesUsed);
 
     uint16_t loadTypeFlags = flagsToCheck & LoadTypeMask;
     uint16_t ressourceTypeFlags = flagsToCheck & ResourceTypeMask;
@@ -74,7 +115,7 @@
     bool ressourceTypeMatches = ressourceTypeFlags ? (ressourceTypeFlags & flags) : true;
     
     if (loadTypeMatches && ressourceTypeMatches)
-        actions.add((ifDomain ? IfDomainFlag : 0) | static_cast<uint64_t>(getBits<unsigned>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode) + sizeof(uint16_t), m_pagesUsed)));
+        actions.add((ifDomain ? IfDomainFlag : 0) | static_cast<uint64_t>(getBits<uint32_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint16_t), m_pagesUsed)));
     programCounter += instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction);
     ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendActionWithIfDomain));
 }
@@ -84,11 +125,11 @@
     Actions actions;
 
     // DFA header.
-    unsigned dfaBytecodeLength = getBits<unsigned>(m_bytecode, m_bytecodeLength, 0, m_pagesUsed);
-    unsigned programCounter = sizeof(unsigned);
+    uint32_t dfaBytecodeLength = getBits<uint32_t>(m_bytecode, m_bytecodeLength, 0, m_pagesUsed);
+    uint32_t programCounter = sizeof(uint32_t);
 
     while (programCounter < dfaBytecodeLength) {
-        DFABytecodeInstruction instruction = static_cast<DFABytecodeInstruction>(m_bytecode[programCounter]);
+        DFABytecodeInstruction instruction = getInstruction(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed);
         if (instruction == DFABytecodeInstruction::AppendActionDefaultStylesheet)
             interpretAppendAction(programCounter, actions, false);
         else if (instruction == DFABytecodeInstruction::AppendAction)
@@ -113,18 +154,18 @@
     
     Actions actions;
     
-    unsigned programCounter = 0;
+    uint32_t programCounter = 0;
     while (programCounter < m_bytecodeLength) {
 
         // DFA header.
-        unsigned dfaStart = programCounter;
-        unsigned dfaBytecodeLength = getBits<unsigned>(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed);
-        programCounter += sizeof(unsigned);
+        uint32_t dfaStart = programCounter;
+        uint32_t dfaBytecodeLength = getBits<uint32_t>(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed);
+        programCounter += sizeof(uint32_t);
 
         // Skip the default stylesheet actions on the DFA root. These are accessed via actionsForDefaultStylesheetFromDFARoot.
         if (!dfaStart) {
             while (programCounter < dfaBytecodeLength) {
-                DFABytecodeInstruction instruction = static_cast<DFABytecodeInstruction>(m_bytecode[programCounter]);
+                DFABytecodeInstruction instruction = getInstruction(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed);
                 if (instruction == DFABytecodeInstruction::AppendActionDefaultStylesheet)
                     programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendActionDefaultStylesheet);
                 else if (instruction == DFABytecodeInstruction::AppendAction)
@@ -137,18 +178,18 @@
             if (programCounter >= m_bytecodeLength)
                 return actions;
         } else {
-            ASSERT_WITH_MESSAGE(static_cast<DFABytecodeInstruction>(m_bytecode[programCounter]) != DFABytecodeInstruction::AppendAction
-                && static_cast<DFABytecodeInstruction>(m_bytecode[programCounter]) != DFABytecodeInstruction::TestFlagsAndAppendAction, 
+            ASSERT_WITH_MESSAGE(getInstruction(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed) != DFABytecodeInstruction::AppendAction
+                && getInstruction(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed) != DFABytecodeInstruction::TestFlagsAndAppendAction,
                 "Triggers that match everything should only be in the first DFA.");
         }
         
         // Interpret the bytecode from this DFA.
         // This should always terminate if interpreting correctly compiled bytecode.
-        unsigned urlIndex = 0;
+        uint32_t urlIndex = 0;
         bool urlIndexIsAfterEndOfString = false;
         while (true) {
             ASSERT(programCounter <= m_bytecodeLength);
-            switch (static_cast<DFABytecodeInstruction>(m_bytecode[programCounter])) {
+            switch (getInstruction(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed)) {
 
             case DFABytecodeInstruction::Terminate:
                 goto nextDFA;
@@ -159,13 +200,15 @@
 
                 // Check to see if the next character in the url is the value stored with the bytecode.
                 char character = url[urlIndex];
-                if (character == getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode), m_pagesUsed)) {
-                    programCounter = dfaStart + getBits<unsigned>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode) + sizeof(uint8_t), m_pagesUsed);
+                DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed);
+                if (character == getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction), m_pagesUsed)) {
+                    uint32_t jumpLocation = programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t);
+                    programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, m_pagesUsed, jumpSize);
                     if (!character)
                         urlIndexIsAfterEndOfString = true;
                     urlIndex++; // This represents an edge in the DFA.
                 } else
-                    programCounter += instructionSizeWithArguments(DFABytecodeInstruction::CheckValueCaseSensitive);
+                    programCounter += sizeof(DFABytecodeInstruction) + sizeof(uint8_t) + jumpSizeInBytes(jumpSize);
                 break;
             }
 
@@ -175,13 +218,15 @@
 
                 // Check to see if the next character in the url is the value stored with the bytecode.
                 char character = toASCIILower(url[urlIndex]);
-                if (character == getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode), m_pagesUsed)) {
-                    programCounter = dfaStart + getBits<unsigned>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode) + sizeof(uint8_t), m_pagesUsed);
+                DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed);
+                if (character == getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction), m_pagesUsed)) {
+                    uint32_t jumpLocation = programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t);
+                    programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, m_pagesUsed, jumpSize);
                     if (!character)
                         urlIndexIsAfterEndOfString = true;
                     urlIndex++; // This represents an edge in the DFA.
                 } else
-                    programCounter += instructionSizeWithArguments(DFABytecodeInstruction::CheckValueCaseInsensitive);
+                    programCounter += sizeof(DFABytecodeInstruction) + sizeof(uint8_t) + jumpSizeInBytes(jumpSize);
                 break;
             }
                     
@@ -190,14 +235,16 @@
                     goto nextDFA;
                 
                 char character = url[urlIndex];
-                if (character >= getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode), m_pagesUsed)
-                    && character <= getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode) + sizeof(uint8_t), m_pagesUsed)) {
-                    programCounter = dfaStart + getBits<unsigned>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode) + sizeof(uint8_t) + sizeof(uint8_t), m_pagesUsed);
+                DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed);
+                if (character >= getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction), m_pagesUsed)
+                    && character <= getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t), m_pagesUsed)) {
+                    uint32_t jumpLocation = programCounter + sizeof(DFABytecodeInstruction) + 2 * sizeof(uint8_t);
+                    programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, m_pagesUsed, jumpSize);
                     if (!character)
                         urlIndexIsAfterEndOfString = true;
                     urlIndex++; // This represents an edge in the DFA.
                 } else
-                    programCounter += instructionSizeWithArguments(DFABytecodeInstruction::CheckValueRangeCaseSensitive);
+                    programCounter += sizeof(DFABytecodeInstruction) + 2 * sizeof(uint8_t) + jumpSizeInBytes(jumpSize);
                 break;
             }
 
@@ -206,24 +253,29 @@
                     goto nextDFA;
                 
                 char character = toASCIILower(url[urlIndex]);
-                if (character >= getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode), m_pagesUsed)
-                    && character <= getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode) + sizeof(uint8_t), m_pagesUsed)) {
-                    programCounter = dfaStart + getBits<unsigned>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode) + sizeof(uint8_t) + sizeof(uint8_t), m_pagesUsed);
+                DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed);
+                if (character >= getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction), m_pagesUsed)
+                    && character <= getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t), m_pagesUsed)) {
+                    uint32_t jumpLocation = programCounter + sizeof(DFABytecodeInstruction) + 2 * sizeof(uint8_t);
+                    programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, m_pagesUsed, jumpSize);
                     if (!character)
                         urlIndexIsAfterEndOfString = true;
                     urlIndex++; // This represents an edge in the DFA.
                 } else
-                    programCounter += instructionSizeWithArguments(DFABytecodeInstruction::CheckValueRangeCaseInsensitive);
+                    programCounter += sizeof(DFABytecodeInstruction) + 2 * sizeof(uint8_t) + jumpSizeInBytes(jumpSize);
                 break;
             }
 
-            case DFABytecodeInstruction::Jump:
+            case DFABytecodeInstruction::Jump: {
                 if (!url[urlIndex] || urlIndexIsAfterEndOfString)
                     goto nextDFA;
                 
-                programCounter = dfaStart + getBits<unsigned>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode), m_pagesUsed);
+                uint32_t jumpLocation = programCounter + sizeof(DFABytecodeInstruction);
+                DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed);
+                programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, m_pagesUsed, jumpSize);
                 urlIndex++; // This represents an edge in the DFA.
                 break;
+            }
                     
             case DFABytecodeInstruction::AppendAction:
                 interpretAppendAction(programCounter, actions, false);

Modified: trunk/Source/WebCore/loader/ResourceLoadInfo.h (185620 => 185621)


--- trunk/Source/WebCore/loader/ResourceLoadInfo.h	2015-06-16 22:18:39 UTC (rev 185620)
+++ trunk/Source/WebCore/loader/ResourceLoadInfo.h	2015-06-16 22:29:19 UTC (rev 185621)
@@ -60,6 +60,7 @@
 // The next bit is used to mark actions that are from a rule with an if-domain condition.
 // The next bit is used to mark actions that in the default stylesheet.
 // The values -1 and -2 are used for removed and empty values in HashTables.
+const uint64_t ActionFlagMask = 0x0000FFFF00000000;
 const uint64_t IfDomainFlag = 0x0001000000000000;
 const uint64_t DisplayNoneStyleSheetFlag = 0x0002000000000000;
 

Modified: trunk/Source/WebKit2/ChangeLog (185620 => 185621)


--- trunk/Source/WebKit2/ChangeLog	2015-06-16 22:18:39 UTC (rev 185620)
+++ trunk/Source/WebKit2/ChangeLog	2015-06-16 22:29:19 UTC (rev 185621)
@@ -1,3 +1,13 @@
+2015-06-16  Alex Christensen  <[email protected]>
+
+        [Content Extensions] Implement branch compaction for DFA bytecode.
+        https://bugs.webkit.org/show_bug.cgi?id=145619
+
+        Reviewed by Benjamin Poulain.
+
+        * UIProcess/API/APIUserContentExtensionStore.h:
+        Increment version number to reflect changes to bytecode.
+
 2015-06-16  Anders Carlsson  <[email protected]>
 
         WebResourceCacheManager is unused, get rid of it

Modified: trunk/Source/WebKit2/UIProcess/API/APIUserContentExtensionStore.h (185620 => 185621)


--- trunk/Source/WebKit2/UIProcess/API/APIUserContentExtensionStore.h	2015-06-16 22:18:39 UTC (rev 185620)
+++ trunk/Source/WebKit2/UIProcess/API/APIUserContentExtensionStore.h	2015-06-16 22:29:19 UTC (rev 185621)
@@ -51,7 +51,7 @@
     
     // This should be incremented every time a functional change is made to the bytecode, file format, etc.
     // to prevent crashing while loading old data.
-    const static uint32_t CurrentContentExtensionFileVersion = 3;
+    const static uint32_t CurrentContentExtensionFileVersion = 4;
 
     static UserContentExtensionStore& defaultStore();
     static Ref<UserContentExtensionStore> storeWithPath(const WTF::String& storePath);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to