Title: [98658] trunk
Revision
98658
Author
[email protected]
Date
2011-10-27 16:35:43 -0700 (Thu, 27 Oct 2011)

Log Message

If the bytecode generator emits code after the return in the first basic block,
DFG's inliner crashes
https://bugs.webkit.org/show_bug.cgi?id=71071

Source/_javascript_Core: 

Reviewed by Gavin Barraclough.
        
Removed some cruft dealing with parsing failures due to unsupported functionality
(that's never reached anymore due to it being caught in DFGCapabilities). This
allowed me to repurpose the bool return from parseBlock() to mean: true if we
should continue to parse, or false if we've already parsed all live code.

* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::ByteCodeParser):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::parseCodeBlock):

LayoutTests: 

Reviewed by Gavin Barraclough.

* fast/js/dfg-inline-early-return-expected.txt: Added.
* fast/js/dfg-inline-early-return.html: Added.
* fast/js/script-tests/dfg-inline-early-return.js: Added.
(foo):
(bar):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (98657 => 98658)


--- trunk/LayoutTests/ChangeLog	2011-10-27 23:24:59 UTC (rev 98657)
+++ trunk/LayoutTests/ChangeLog	2011-10-27 23:35:43 UTC (rev 98658)
@@ -1,3 +1,17 @@
+2011-10-27  Filip Pizlo  <[email protected]>
+
+        If the bytecode generator emits code after the return in the first basic block,
+        DFG's inliner crashes
+        https://bugs.webkit.org/show_bug.cgi?id=71071
+
+        Reviewed by Gavin Barraclough.
+
+        * fast/js/dfg-inline-early-return-expected.txt: Added.
+        * fast/js/dfg-inline-early-return.html: Added.
+        * fast/js/script-tests/dfg-inline-early-return.js: Added.
+        (foo):
+        (bar):
+
 2011-10-27  John Gregg  <[email protected]>
 
         Unreviewed, new chromium expectations for shading/anti-aliasing changes.

Added: trunk/LayoutTests/fast/js/dfg-inline-early-return-expected.txt (0 => 98658)


--- trunk/LayoutTests/fast/js/dfg-inline-early-return-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-inline-early-return-expected.txt	2011-10-27 23:35:43 UTC (rev 98658)
@@ -0,0 +1,11 @@
+This tests that an early return in the first basic block does not crash the DFG's bytecode parser whilst inlining.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS foo(42) is 42
+PASS bar(42) is 42
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/js/dfg-inline-early-return.html (0 => 98658)


--- trunk/LayoutTests/fast/js/dfg-inline-early-return.html	                        (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-inline-early-return.html	2011-10-27 23:35:43 UTC (rev 98658)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/fast/js/script-tests/dfg-inline-early-return.js (0 => 98658)


--- trunk/LayoutTests/fast/js/script-tests/dfg-inline-early-return.js	                        (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/dfg-inline-early-return.js	2011-10-27 23:35:43 UTC (rev 98658)
@@ -0,0 +1,21 @@
+description(
+"This tests that an early return in the first basic block does not crash the DFG's bytecode parser whilst inlining."
+);
+
+function foo(a) {
+    {
+        return a;
+    }
+}
+
+function bar(a) {
+    return foo(a);
+}
+
+for (var i = 0; i < 100; ++i)
+    bar(i);
+
+shouldBe("foo(42)", "42");
+shouldBe("bar(42)", "42");
+
+var successfullyParsed = true;

Modified: trunk/Source/_javascript_Core/ChangeLog (98657 => 98658)


--- trunk/Source/_javascript_Core/ChangeLog	2011-10-27 23:24:59 UTC (rev 98657)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-10-27 23:35:43 UTC (rev 98658)
@@ -1,3 +1,21 @@
+2011-10-27  Filip Pizlo  <[email protected]>
+
+        If the bytecode generator emits code after the return in the first basic block,
+        DFG's inliner crashes
+        https://bugs.webkit.org/show_bug.cgi?id=71071
+
+        Reviewed by Gavin Barraclough.
+        
+        Removed some cruft dealing with parsing failures due to unsupported functionality
+        (that's never reached anymore due to it being caught in DFGCapabilities). This
+        allowed me to repurpose the bool return from parseBlock() to mean: true if we
+        should continue to parse, or false if we've already parsed all live code.
+
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::ByteCodeParser):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        (JSC::DFG::ByteCodeParser::parseCodeBlock):
+
 2011-10-27  Joseph Pecoraro  <[email protected]>
 
         Reviewed by David Kilzer.

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (98657 => 98658)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2011-10-27 23:24:59 UTC (rev 98657)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2011-10-27 23:35:43 UTC (rev 98658)
@@ -47,7 +47,6 @@
         , m_graph(graph)
         , m_currentBlock(0)
         , m_currentIndex(0)
-        , m_parseFailed(false)
         , m_constantUndefined(UINT_MAX)
         , m_constantNull(UINT_MAX)
         , m_constantNaN(UINT_MAX)
@@ -73,7 +72,7 @@
     
 private:
     // Just parse from m_currentIndex to the end of the current CodeBlock.
-    bool parseCodeBlock();
+    void parseCodeBlock();
 
     // Helper for min and max.
     bool handleMinMax(bool usesResult, int resultOperand, NodeType op, int firstArg, int lastArg);
@@ -681,9 +680,6 @@
     // The bytecode index of the current instruction being generated.
     unsigned m_currentIndex;
 
-    // Record failures due to unimplemented functionality or regressions.
-    bool m_parseFailed;
-
     // We use these values during code generation, and to avoid the need for
     // special handling we make sure they are available as constants in the
     // CodeBlock's constant pool. These variables are initialized to
@@ -837,7 +833,7 @@
 
 #define LAST_OPCODE(name) \
     m_currentIndex += OPCODE_LENGTH(name); \
-    return !m_parseFailed
+    return shouldContinueParsing
 
 void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentInstruction, NodeType op, CodeSpecializationKind kind)
 {
@@ -1207,6 +1203,8 @@
 
 bool ByteCodeParser::parseBlock(unsigned limit)
 {
+    bool shouldContinueParsing = true;
+    
     // If we are the first basic block, introduce markers for arguments. This allows
     // us to track if a use of an argument may use the actual argument passed, as
     // opposed to using a value we set explicitly.
@@ -1240,7 +1238,7 @@
                 printf("Refusing to plant jump at limit %u because block %p is empty.\n", limit, m_currentBlock);
 #endif
             }
-            return !m_parseFailed;
+            return shouldContinueParsing;
         }
         
         // Switch on the current bytecode opcode.
@@ -2001,7 +1999,12 @@
                 if (m_inlineStackTop->m_returnValue != InvalidVirtualRegister)
                     setDirect(m_inlineStackTop->m_returnValue, get(currentInstruction[1].u.operand));
                 m_inlineStackTop->m_didReturn = true;
-                if (!m_inlineStackTop->m_unlinkedBlocks.isEmpty()) {
+                if (m_inlineStackTop->m_unlinkedBlocks.isEmpty()) {
+                    // If we're returning from the first block, then we're done parsing.
+                    ASSERT(m_inlineStackTop->m_callsiteBlockHead == m_graph.m_blocks.size() - 1);
+                    shouldContinueParsing = false;
+                    LAST_OPCODE(op_ret);
+                } else {
                     // If inlining created blocks, and we're doing a return, then we need some
                     // special linking.
                     ASSERT(m_inlineStackTop->m_unlinkedBlocks.last().m_blockIndex == m_graph.m_blocks.size() - 1);
@@ -2355,7 +2358,7 @@
     byteCodeParser->m_inlineStackTop = this;
 }
 
-bool ByteCodeParser::parseCodeBlock()
+void ByteCodeParser::parseCodeBlock()
 {
     CodeBlock* codeBlock = m_inlineStackTop->m_codeBlock;
     
@@ -2402,25 +2405,29 @@
                 }
             }
 
-            if (!parseBlock(limit))
-                return false;
+            bool shouldContinueParsing = parseBlock(limit);
+
             // We should not have gone beyond the limit.
             ASSERT(m_currentIndex <= limit);
             
             // We should have planted a terminal, or we just gave up because
             // we realized that the jump target information is imprecise, or we
-            // are at the end of an inline function.
-            ASSERT(m_currentBlock->begin == m_graph.size() || m_graph.last().isTerminal() || (m_currentIndex == codeBlock->instructions().size() && m_inlineStackTop->m_inlineCallFrame));
+            // are at the end of an inline function, or we realized that we
+            // should stop parsing because there was a return in the first
+            // basic block.
+            ASSERT(m_currentBlock->begin == m_graph.size() || m_graph.last().isTerminal() || (m_currentIndex == codeBlock->instructions().size() && m_inlineStackTop->m_inlineCallFrame) || !shouldContinueParsing);
 
             m_currentBlock->end = m_graph.size();
+            
+            if (!shouldContinueParsing)
+                return;
+            
             m_currentBlock = 0;
         } while (m_currentIndex < limit);
     }
 
     // Should have reached the end of the instructions.
     ASSERT(m_currentIndex == codeBlock->instructions().size());
-    
-    return true;
 }
 
 bool ByteCodeParser::parse()
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to