Title: [183307] trunk/Source/_javascript_Core
Revision
183307
Author
[email protected]
Date
2015-04-24 22:19:07 -0700 (Fri, 24 Apr 2015)

Log Message

CRASH in operationCreateDirectArgumentsDuringExit()
https://bugs.webkit.org/show_bug.cgi?id=143962

Reviewed by Geoffrey Garen.
        
We shouldn't assume that constant-like OSR exit values are always recoverable. They are only
recoverable so long as they are live. Therefore, OSR exit should track liveness of
constants instead of assuming that they are always live.

* dfg/DFGGenerationInfo.h:
(JSC::DFG::GenerationInfo::noticeOSRBirth):
(JSC::DFG::GenerationInfo::appendBirth):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileCurrentBlock):
* dfg/DFGVariableEvent.cpp:
(JSC::DFG::VariableEvent::dump):
* dfg/DFGVariableEvent.h:
(JSC::DFG::VariableEvent::birth):
(JSC::DFG::VariableEvent::id):
(JSC::DFG::VariableEvent::dataFormat):
* dfg/DFGVariableEventStream.cpp:
(JSC::DFG::VariableEventStream::reconstruct):
* tests/stress/phantom-direct-arguments-clobber-argument-count.js: Added.
(foo):
(bar):
* tests/stress/phantom-direct-arguments-clobber-callee.js: Added.
(foo):
(bar):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (183306 => 183307)


--- trunk/Source/_javascript_Core/ChangeLog	2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-04-25 05:19:07 UTC (rev 183307)
@@ -1,3 +1,34 @@
+2015-04-24  Filip Pizlo  <[email protected]>
+
+        CRASH in operationCreateDirectArgumentsDuringExit()
+        https://bugs.webkit.org/show_bug.cgi?id=143962
+
+        Reviewed by Geoffrey Garen.
+        
+        We shouldn't assume that constant-like OSR exit values are always recoverable. They are only
+        recoverable so long as they are live. Therefore, OSR exit should track liveness of
+        constants instead of assuming that they are always live.
+
+        * dfg/DFGGenerationInfo.h:
+        (JSC::DFG::GenerationInfo::noticeOSRBirth):
+        (JSC::DFG::GenerationInfo::appendBirth):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileCurrentBlock):
+        * dfg/DFGVariableEvent.cpp:
+        (JSC::DFG::VariableEvent::dump):
+        * dfg/DFGVariableEvent.h:
+        (JSC::DFG::VariableEvent::birth):
+        (JSC::DFG::VariableEvent::id):
+        (JSC::DFG::VariableEvent::dataFormat):
+        * dfg/DFGVariableEventStream.cpp:
+        (JSC::DFG::VariableEventStream::reconstruct):
+        * tests/stress/phantom-direct-arguments-clobber-argument-count.js: Added.
+        (foo):
+        (bar):
+        * tests/stress/phantom-direct-arguments-clobber-callee.js: Added.
+        (foo):
+        (bar):
+
 2015-04-24  Benjamin Poulain  <[email protected]>
 
         [JSC] When inserting a NaN into a Int32 array, we convert it to DoubleArray then to ContiguousArray

Modified: trunk/Source/_javascript_Core/dfg/DFGGenerationInfo.h (183306 => 183307)


--- trunk/Source/_javascript_Core/dfg/DFGGenerationInfo.h	2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/_javascript_Core/dfg/DFGGenerationInfo.h	2015-04-25 05:19:07 UTC (rev 183307)
@@ -153,8 +153,6 @@
     
     void noticeOSRBirth(VariableEventStream& stream, Node* node, VirtualRegister virtualRegister)
     {
-        if (m_isConstant)
-            return;
         if (m_node != node)
             return;
         if (!alive())
@@ -164,7 +162,9 @@
         
         m_bornForOSR = true;
         
-        if (m_registerFormat != DataFormatNone)
+        if (m_isConstant)
+            appendBirth(stream);
+        else if (m_registerFormat != DataFormatNone)
             appendFill(BirthToFill, stream);
         else if (m_spillFormat != DataFormatNone)
             appendSpill(BirthToSpill, stream, virtualRegister);
@@ -379,6 +379,11 @@
     }
 
 private:
+    void appendBirth(VariableEventStream& stream)
+    {
+        stream.appendAndLog(VariableEvent::birth(MinifiedID(m_node)));
+    }
+    
     void appendFill(VariableEventKind kind, VariableEventStream& stream)
     {
         ASSERT(m_bornForOSR);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (183306 => 183307)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2015-04-25 05:19:07 UTC (rev 183307)
@@ -1428,33 +1428,29 @@
         m_codeOriginForExitTarget = m_currentNode->origin.forExit;
         m_codeOriginForExitProfile = m_currentNode->origin.semantic;
         m_lastGeneratedNode = m_currentNode->op();
-        if (!m_currentNode->shouldGenerate()) {
-            if (belongsInMinifiedGraph(m_currentNode->op()))
-                m_minifiedGraph->append(MinifiedNode::fromNode(m_currentNode));
-        } else {
-            if (verboseCompilationEnabled()) {
-                dataLogF(
-                    "SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x",
-                    (int)m_currentNode->index(),
-                    m_currentNode->origin.semantic.bytecodeIndex, m_jit.debugOffset());
-                dataLog("\n");
-            }
-            
-            compile(m_currentNode);
-
+        
+        ASSERT(m_currentNode->shouldGenerate());
+        
+        if (verboseCompilationEnabled()) {
+            dataLogF(
+                "SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x",
+                (int)m_currentNode->index(),
+                m_currentNode->origin.semantic.bytecodeIndex, m_jit.debugOffset());
+            dataLog("\n");
+        }
+        
+        compile(m_currentNode);
+        
+        if (belongsInMinifiedGraph(m_currentNode->op()))
+            m_minifiedGraph->append(MinifiedNode::fromNode(m_currentNode));
+        
 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
-            m_jit.clearRegisterAllocationOffsets();
+        m_jit.clearRegisterAllocationOffsets();
 #endif
-
-            if (!m_compileOkay) {
-                bail(DFGBailedAtEndOfNode);
-                return;
-            }
-            
-            if (belongsInMinifiedGraph(m_currentNode->op())) {
-                m_minifiedGraph->append(MinifiedNode::fromNode(m_currentNode));
-                noticeOSRBirth(m_currentNode);
-            }
+        
+        if (!m_compileOkay) {
+            bail(DFGBailedAtEndOfNode);
+            return;
         }
         
         // Make sure that the abstract state is rematerialized for the next node.

Modified: trunk/Source/_javascript_Core/dfg/DFGVariableEvent.cpp (183306 => 183307)


--- trunk/Source/_javascript_Core/dfg/DFGVariableEvent.cpp	2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/_javascript_Core/dfg/DFGVariableEvent.cpp	2015-04-25 05:19:07 UTC (rev 183307)
@@ -46,6 +46,9 @@
     case BirthToSpill:
         dumpSpillInfo("BirthToSpill", out);
         break;
+    case Birth:
+        out.print("Birth(", id(), ")");
+        break;
     case Fill:
         dumpFillInfo("Fill", out);
         break;

Modified: trunk/Source/_javascript_Core/dfg/DFGVariableEvent.h (183306 => 183307)


--- trunk/Source/_javascript_Core/dfg/DFGVariableEvent.h	2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/_javascript_Core/dfg/DFGVariableEvent.h	2015-04-25 05:19:07 UTC (rev 183307)
@@ -47,6 +47,7 @@
     // that we start to care about this node.
     BirthToFill,
     BirthToSpill,
+    Birth,
     
     // Events related to how a node is represented.
     Fill,
@@ -133,6 +134,14 @@
         return event;
     }
     
+    static VariableEvent birth(MinifiedID id)
+    {
+        VariableEvent event;
+        event.m_which.id = id.bits();
+        event.m_kind = Birth;
+        return event;
+    }
+    
     static VariableEvent spill(VariableEventKind kind, MinifiedID id, VirtualRegister virtualRegister, DataFormat format)
     {
         ASSERT(kind == BirthToSpill || kind == Spill);
@@ -179,17 +188,17 @@
     
     MinifiedID id() const
     {
-        ASSERT(m_kind == BirthToFill || m_kind == Fill
-               || m_kind == BirthToSpill || m_kind == Spill
-               || m_kind == Death || m_kind == MovHintEvent);
+        ASSERT(
+            m_kind == BirthToFill || m_kind == Fill || m_kind == BirthToSpill || m_kind == Spill
+            || m_kind == Death || m_kind == MovHintEvent || m_kind == Birth);
         return MinifiedID::fromBits(m_which.id);
     }
     
     DataFormat dataFormat() const
     {
-        ASSERT(m_kind == BirthToFill || m_kind == Fill
-               || m_kind == BirthToSpill || m_kind == Spill
-               || m_kind == SetLocalEvent);
+        ASSERT(
+            m_kind == BirthToFill || m_kind == Fill || m_kind == BirthToSpill || m_kind == Spill
+            || m_kind == SetLocalEvent);
         return static_cast<DataFormat>(m_dataFormat);
     }
     

Modified: trunk/Source/_javascript_Core/dfg/DFGVariableEventStream.cpp (183306 => 183307)


--- trunk/Source/_javascript_Core/dfg/DFGVariableEventStream.cpp	2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/_javascript_Core/dfg/DFGVariableEventStream.cpp	2015-04-25 05:19:07 UTC (rev 183307)
@@ -48,11 +48,14 @@
 
 struct MinifiedGenerationInfo {
     bool filled; // true -> in gpr/fpr/pair, false -> spilled
+    bool alive;
     VariableRepresentation u;
     DataFormat format;
     
     MinifiedGenerationInfo()
-        : format(DataFormatNone)
+        : filled(false)
+        , alive(false)
+        , format(DataFormatNone)
     {
     }
     
@@ -62,13 +65,19 @@
         case BirthToFill:
         case Fill:
             filled = true;
+            alive = true;
             break;
         case BirthToSpill:
         case Spill:
             filled = false;
+            alive = true;
             break;
+        case Birth:
+            alive = true;
+            return;
         case Death:
             format = DataFormatNone;
+            alive = false;
             return;
         default:
             return;
@@ -146,7 +155,8 @@
             // nothing to do.
             break;
         case BirthToFill:
-        case BirthToSpill: {
+        case BirthToSpill:
+        case Birth: {
             MinifiedGenerationInfo info;
             info.update(event);
             generationInfos.add(event.id(), info);
@@ -185,14 +195,14 @@
         
         ASSERT(source.kind() == HaveNode);
         MinifiedNode* node = graph.at(source.id());
-        if (tryToSetConstantRecovery(valueRecoveries[i], node))
-            continue;
-        
         MinifiedGenerationInfo info = generationInfos.get(source.id());
-        if (info.format == DataFormatNone) {
+        if (!info.alive) {
             valueRecoveries[i] = ValueRecovery::constant(jsUndefined());
             continue;
         }
+
+        if (tryToSetConstantRecovery(valueRecoveries[i], node))
+            continue;
         
         ASSERT(info.format != DataFormatNone);
         

Added: trunk/Source/_javascript_Core/tests/stress/phantom-direct-arguments-clobber-argument-count.js (0 => 183307)


--- trunk/Source/_javascript_Core/tests/stress/phantom-direct-arguments-clobber-argument-count.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/phantom-direct-arguments-clobber-argument-count.js	2015-04-25 05:19:07 UTC (rev 183307)
@@ -0,0 +1,20 @@
+function foo() {
+    return effectful42.apply(this, arguments);
+}
+
+function bar(a, b) {
+    var result = foo.apply(this, b);
+    return [a, a, a, a, a, a, a, a, result + a];
+}
+
+noInline(bar);
+
+for (var i = 0; i < 10000; ++i) {
+    var result = "" + bar(1, []);
+    if (result != "1,1,1,1,1,1,1,1,43")
+        throw "Error: bad result: " + result;
+}
+
+var result = "" + bar(2147483647, []);
+if (result != "2147483647,2147483647,2147483647,2147483647,2147483647,2147483647,2147483647,2147483647,2147483689")
+    throw "Error: bad result at end: " + result;

Added: trunk/Source/_javascript_Core/tests/stress/phantom-direct-arguments-clobber-callee.js (0 => 183307)


--- trunk/Source/_javascript_Core/tests/stress/phantom-direct-arguments-clobber-callee.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/phantom-direct-arguments-clobber-callee.js	2015-04-25 05:19:07 UTC (rev 183307)
@@ -0,0 +1,21 @@
+function foo() {
+    return function() { return effectful42.apply(this, arguments) };
+}
+noInline(foo);
+
+function bar(a) {
+    var result = foo()();
+    return [result, result, result, result, result, result, result, result, result + a];
+}
+
+noInline(bar);
+
+for (var i = 0; i < 10000; ++i) {
+    var result = "" + bar(1);
+    if (result != "42,42,42,42,42,42,42,42,43")
+        throw "Error: bad result: " + result;
+}
+
+var result = "" + bar(2147483647);
+if (result != "42,42,42,42,42,42,42,42,2147483689")
+    throw "Error: bad result at end: " + result;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to