Title: [226863] branches/safari-605-branch/Source/_javascript_Core
Revision
226863
Author
jmarc...@apple.com
Date
2018-01-11 22:30:35 -0800 (Thu, 11 Jan 2018)

Log Message

Cherry-pick r226655. rdar://problem/36450822

Modified Paths

Diff

Modified: branches/safari-605-branch/Source/_javascript_Core/ChangeLog (226862 => 226863)


--- branches/safari-605-branch/Source/_javascript_Core/ChangeLog	2018-01-12 05:29:01 UTC (rev 226862)
+++ branches/safari-605-branch/Source/_javascript_Core/ChangeLog	2018-01-12 06:30:35 UTC (rev 226863)
@@ -1,5 +1,44 @@
 2018-01-11  Jason Marcell  <jmarc...@apple.com>
 
+        Cherry-pick r226655. rdar://problem/36450822
+
+    2018-01-09  Saam Barati  <sbar...@apple.com>
+
+            Reduce graph size by replacing terminal nodes in blocks that have a ForceOSRExit with Unreachable
+            https://bugs.webkit.org/show_bug.cgi?id=181409
+
+            Reviewed by Keith Miller.
+
+            When I was looking at profiler data for Speedometer, I noticed that one of
+            the hottest functions in Speedometer is around 1100 bytecode operations long.
+            Only about 100 of those bytecode ops ever execute. However, we ended up
+            spending a lot of time compiling basic blocks that never executed. We often
+            plant ForceOSRExit nodes when we parse bytecodes that have a null value profile.
+            This is the case when such a node never executes.
+
+            This patch makes it so that anytime a block has a ForceOSRExit, we replace its
+            terminal node with an Unreachable node (and remove all nodes after the
+            ForceOSRExit). This will cut down on graph size when such a block dominates
+            other blocks in the CFG. This allows us to get rid of huge chunks of the CFG
+            in certain programs. When doing this transformation, we also insert
+            Flushes/PhantomLocals to ensure we can recover values that are bytecode
+            live-in to the ForceOSRExit.
+
+            Using ForceOSRExit as the signal for this is a bit of a hack. It definitely
+            does not get rid of all the CFG that it could. If we decide it's worth
+            it, we could use additional inputs into this mechanism. For example, we could
+            profile if a basic block ever executes inside the LLInt/Baseline, and
+            remove parts of the CFG based on that.
+
+            When running Speedometer with the concurrent JIT turned off, this patch
+            improves DFG/FTL compile times by around 5%.
+
+            * dfg/DFGByteCodeParser.cpp:
+            (JSC::DFG::ByteCodeParser::addToGraph):
+            (JSC::DFG::ByteCodeParser::parse):
+
+2018-01-11  Jason Marcell  <jmarc...@apple.com>
+
         Cherry-pick r226650. rdar://problem/36429150
 
     2018-01-09  Mark Lam  <mark....@apple.com>

Modified: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (226862 => 226863)


--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2018-01-12 05:29:01 UTC (rev 226862)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2018-01-12 06:30:35 UTC (rev 226863)
@@ -694,7 +694,10 @@
     
     Node* addToGraph(Node* node)
     {
+        m_hasAnyForceOSRExits |= (node->op() == ForceOSRExit);
+
         VERBOSE_LOG("        appended ", node, " ", Graph::opName(node->op()), "\n");
+
         m_currentBlock->append(node);
         if (clobbersExitState(m_graph, node))
             m_exitOK = false;
@@ -1141,6 +1144,7 @@
     
     Instruction* m_currentInstruction;
     bool m_hasDebuggerEnabled;
+    bool m_hasAnyForceOSRExits { false };
 };
 
 BasicBlock* ByteCodeParser::allocateTargetableBlock(unsigned bytecodeIndex)
@@ -6559,6 +6563,67 @@
     parseCodeBlock();
     linkBlocks(inlineStackEntry.m_unlinkedBlocks, inlineStackEntry.m_blockLinkingTargets);
 
+    if (m_hasAnyForceOSRExits) {
+        InsertionSet insertionSet(m_graph);
+        Operands<VariableAccessData*> mapping(OperandsLike, m_graph.block(0)->variablesAtHead);
+
+        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
+            mapping.fill(nullptr);
+            if (validationEnabled()) {
+                // Verify that it's correct to fill mapping with nullptr.
+                for (unsigned i = 0; i < block->variablesAtHead.size(); ++i) {
+                    Node* node = block->variablesAtHead.at(i);
+                    RELEASE_ASSERT(!node);
+                }
+            }
+
+            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
+                Node* node = block->at(nodeIndex);
+
+                if (node->hasVariableAccessData(m_graph))
+                    mapping.operand(node->local()) = node->variableAccessData();
+
+                if (node->op() == ForceOSRExit) {
+                    NodeOrigin endOrigin = node->origin.withExitOK(true);
+
+                    if (validationEnabled()) {
+                        // This verifies that we don't need to change any of the successors's predecessor
+                        // list after planting the Unreachable below. At this point in the bytecode
+                        // parser, we haven't linked up the predecessor lists yet.
+                        for (BasicBlock* successor : block->successors())
+                            RELEASE_ASSERT(successor->predecessors.isEmpty());
+                    }
+
+                    block->resize(nodeIndex + 1);
+
+                    insertionSet.insertNode(block->size(), SpecNone, ExitOK, endOrigin);
+                    m_graph.forAllLiveInBytecode(endOrigin.semantic, [&] (VirtualRegister operand) {
+                        VariableAccessData* variable = mapping.operand(operand);
+                        if (!variable)
+                            variable = newVariableAccessData(operand);
+
+                        auto op = PhantomLocal;
+                        if ((m_graph.needsScopeRegister() && operand == m_codeBlock->scopeRegister())
+                            || (operand.isArgument() && (operand != virtualRegisterForArgument(0) || m_graph.needsFlushedThis()))) {
+                            op = Flush;
+                        }
+                        insertionSet.insertNode(block->size(), SpecNone, op, endOrigin, OpInfo(variable));
+                    });
+
+                    insertionSet.insertNode(block->size(), SpecNone, Unreachable, endOrigin);
+                    insertionSet.execute(block);
+                    break;
+                }
+            }
+        }
+    } else if (validationEnabled()) {
+        // Ensure our bookkeeping for ForceOSRExit nodes is working.
+        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
+            for (Node* node : *block)
+                RELEASE_ASSERT(node->op() != ForceOSRExit);
+        }
+    }
+
     m_graph.determineReachability();
     m_graph.killUnreachableBlocks();
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to