Title: [184311] trunk/Source/_javascript_Core
Revision
184311
Author
[email protected]
Date
2015-05-13 15:14:25 -0700 (Wed, 13 May 2015)

Log Message

The liveness pruning done by ObjectAllocationSinkingPhase ignores the possibility of an object's bytecode liveness being longer than its DFG liveness
https://bugs.webkit.org/show_bug.cgi?id=144945

Reviewed by Michael Saboff.
        
We were making the mistake of using DFG liveness for object allocation sinking decisions.
This is wrong. In fact we almost never want to use DFG liveness directly. The only place
where that makes sense is pruning in DFG AI.
        
So, I created a CombinedLiveness class that combines the DFG liveness with bytecode
liveness.
        
In the process of doing this, I realized that the DFGForAllKills definition of combined
liveness at block tail was not strictly right; it was using the bytecode liveness at the
block terminal instead of the union of the bytecode live-at-heads of successor blocks. So,
I changed DFGForAllKills to work in terms of CombinedLiveness.
        
This allows me to unskip the test I added in r184260. I also added a new test that tries to
trigger this bug more directly.

* CMakeLists.txt:
* _javascript_Core.vcxproj/_javascript_Core.vcxproj:
* _javascript_Core.xcodeproj/project.pbxproj:
* dfg/DFGArgumentsEliminationPhase.cpp:
* dfg/DFGCombinedLiveness.cpp: Added.
(JSC::DFG::liveNodesAtHead):
(JSC::DFG::CombinedLiveness::CombinedLiveness):
* dfg/DFGCombinedLiveness.h: Added.
(JSC::DFG::CombinedLiveness::CombinedLiveness):
* dfg/DFGForAllKills.h:
(JSC::DFG::forAllKillsInBlock):
(JSC::DFG::forAllLiveNodesAtTail): Deleted.
* dfg/DFGObjectAllocationSinkingPhase.cpp:
(JSC::DFG::ObjectAllocationSinkingPhase::performSinking):
(JSC::DFG::ObjectAllocationSinkingPhase::determineMaterializationPoints):
(JSC::DFG::ObjectAllocationSinkingPhase::placeMaterializationPoints):
(JSC::DFG::ObjectAllocationSinkingPhase::promoteSunkenFields):
* tests/stress/escape-object-in-diamond-then-exit.js: Added.
* tests/stress/sink-object-past-invalid-check-sneaky.js:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (184310 => 184311)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2015-05-13 22:07:09 UTC (rev 184310)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2015-05-13 22:14:25 UTC (rev 184311)
@@ -145,6 +145,7 @@
     dfg/DFGCleanUpPhase.cpp
     dfg/DFGClobberSet.cpp
     dfg/DFGClobberize.cpp
+    dfg/DFGCombinedLiveness.cpp
     dfg/DFGCommon.cpp
     dfg/DFGCommonData.cpp
     dfg/DFGCompilationKey.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (184310 => 184311)


--- trunk/Source/_javascript_Core/ChangeLog	2015-05-13 22:07:09 UTC (rev 184310)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-05-13 22:14:25 UTC (rev 184311)
@@ -1,3 +1,45 @@
+2015-05-13  Filip Pizlo  <[email protected]>
+
+        The liveness pruning done by ObjectAllocationSinkingPhase ignores the possibility of an object's bytecode liveness being longer than its DFG liveness
+        https://bugs.webkit.org/show_bug.cgi?id=144945
+
+        Reviewed by Michael Saboff.
+        
+        We were making the mistake of using DFG liveness for object allocation sinking decisions.
+        This is wrong. In fact we almost never want to use DFG liveness directly. The only place
+        where that makes sense is pruning in DFG AI.
+        
+        So, I created a CombinedLiveness class that combines the DFG liveness with bytecode
+        liveness.
+        
+        In the process of doing this, I realized that the DFGForAllKills definition of combined
+        liveness at block tail was not strictly right; it was using the bytecode liveness at the
+        block terminal instead of the union of the bytecode live-at-heads of successor blocks. So,
+        I changed DFGForAllKills to work in terms of CombinedLiveness.
+        
+        This allows me to unskip the test I added in r184260. I also added a new test that tries to
+        trigger this bug more directly.
+
+        * CMakeLists.txt:
+        * _javascript_Core.vcxproj/_javascript_Core.vcxproj:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * dfg/DFGArgumentsEliminationPhase.cpp:
+        * dfg/DFGCombinedLiveness.cpp: Added.
+        (JSC::DFG::liveNodesAtHead):
+        (JSC::DFG::CombinedLiveness::CombinedLiveness):
+        * dfg/DFGCombinedLiveness.h: Added.
+        (JSC::DFG::CombinedLiveness::CombinedLiveness):
+        * dfg/DFGForAllKills.h:
+        (JSC::DFG::forAllKillsInBlock):
+        (JSC::DFG::forAllLiveNodesAtTail): Deleted.
+        * dfg/DFGObjectAllocationSinkingPhase.cpp:
+        (JSC::DFG::ObjectAllocationSinkingPhase::performSinking):
+        (JSC::DFG::ObjectAllocationSinkingPhase::determineMaterializationPoints):
+        (JSC::DFG::ObjectAllocationSinkingPhase::placeMaterializationPoints):
+        (JSC::DFG::ObjectAllocationSinkingPhase::promoteSunkenFields):
+        * tests/stress/escape-object-in-diamond-then-exit.js: Added.
+        * tests/stress/sink-object-past-invalid-check-sneaky.js:
+
 2015-05-13  Ryosuke Niwa  <[email protected]>
 
         I skipped a wrong test in r184270. Fix that.

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj (184310 => 184311)


--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj	2015-05-13 22:07:09 UTC (rev 184310)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj	2015-05-13 22:14:25 UTC (rev 184311)
@@ -383,6 +383,7 @@
     <ClCompile Include="..\dfg\DFGCleanUpPhase.cpp" />
     <ClCompile Include="..\dfg\DFGClobberize.cpp" />
     <ClCompile Include="..\dfg\DFGClobberSet.cpp" />
+    <ClCompile Include="..\dfg\DFGCombinedLiveness.cpp" />
     <ClCompile Include="..\dfg\DFGCommon.cpp" />
     <ClCompile Include="..\dfg\DFGCommonData.cpp" />
     <ClCompile Include="..\dfg\DFGCompilationKey.cpp" />
@@ -1063,6 +1064,7 @@
     <ClInclude Include="..\dfg\DFGCleanUpPhase.h" />
     <ClInclude Include="..\dfg\DFGClobberize.h" />
     <ClInclude Include="..\dfg\DFGClobberSet.h" />
+    <ClInclude Include="..\dfg\DFGCombinedLiveness.h" />
     <ClInclude Include="..\dfg\DFGCommon.h" />
     <ClInclude Include="..\dfg\DFGCommonData.h" />
     <ClInclude Include="..\dfg\DFGCompilationKey.h" />

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (184310 => 184311)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-05-13 22:07:09 UTC (rev 184310)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-05-13 22:14:25 UTC (rev 184311)
@@ -82,6 +82,8 @@
 		0F0332C418B01763005F979A /* GetByIdVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0332C218B01763005F979A /* GetByIdVariant.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F0332C618B53FA9005F979A /* FTLWeight.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0332C518B53FA9005F979A /* FTLWeight.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F0332C818B546EC005F979A /* FTLWeightedTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0332C718B546EC005F979A /* FTLWeightedTarget.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		0F04396D1B03DC0B009598B7 /* DFGCombinedLiveness.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F04396B1B03DC0B009598B7 /* DFGCombinedLiveness.cpp */; };
+		0F04396E1B03DC0B009598B7 /* DFGCombinedLiveness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0776BD14FF002800102332 /* JITCompilationEffort.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */; };
@@ -1816,6 +1818,8 @@
 		0F0332C218B01763005F979A /* GetByIdVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetByIdVariant.h; sourceTree = "<group>"; };
 		0F0332C518B53FA9005F979A /* FTLWeight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLWeight.h; path = ftl/FTLWeight.h; sourceTree = "<group>"; };
 		0F0332C718B546EC005F979A /* FTLWeightedTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLWeightedTarget.h; path = ftl/FTLWeightedTarget.h; sourceTree = "<group>"; };
+		0F04396B1B03DC0B009598B7 /* DFGCombinedLiveness.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCombinedLiveness.cpp; path = dfg/DFGCombinedLiveness.cpp; sourceTree = "<group>"; };
+		0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCombinedLiveness.h; path = dfg/DFGCombinedLiveness.h; sourceTree = "<group>"; };
 		0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; };
 		0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; };
 		0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
@@ -4881,6 +4885,8 @@
 				A77A423917A0BBFD00A8DB81 /* DFGClobberize.h */,
 				A77A423A17A0BBFD00A8DB81 /* DFGClobberSet.cpp */,
 				A77A423B17A0BBFD00A8DB81 /* DFGClobberSet.h */,
+				0F04396B1B03DC0B009598B7 /* DFGCombinedLiveness.cpp */,
+				0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */,
 				0FB4B51A16B62772003F696B /* DFGCommon.cpp */,
 				0FC0977E1469EBC400CF2442 /* DFGCommon.h */,
 				0FEA0A2D170D40BF00BB722C /* DFGCommonData.cpp */,
@@ -6230,6 +6236,7 @@
 				0FC3CD0019ADA410006AC72A /* DFGBlockWorklist.h in Headers */,
 				0FE050181AA9091100D33B33 /* DirectArguments.h in Headers */,
 				FE20CE9E15F04A9500DF3430 /* LLIntCLoop.h in Headers */,
+				0F04396E1B03DC0B009598B7 /* DFGCombinedLiveness.h in Headers */,
 				0F4680CA14BBB16C00BFE272 /* LLIntCommon.h in Headers */,
 				0FBDB9AD1AB0FBC6000B57E5 /* DFGCallCreateDirectArgumentsSlowPathGenerator.h in Headers */,
 				0F4680D314BBD16700BFE272 /* LLIntData.h in Headers */,
@@ -7514,6 +7521,7 @@
 				70EC0EC61AA0D7DA00B6AAFA /* StringIteratorPrototype.cpp in Sources */,
 				A5FD0067189AFE9C00633231 /* ScriptArguments.cpp in Sources */,
 				A5FD006D189B00AA00633231 /* ScriptCallFrame.cpp in Sources */,
+				0F04396D1B03DC0B009598B7 /* DFGCombinedLiveness.cpp in Sources */,
 				A5FD006F189B00AA00633231 /* ScriptCallStack.cpp in Sources */,
 				A5FD007D189B0B4C00633231 /* ScriptCallStackFactory.cpp in Sources */,
 				A503FA25188EFFFD00110F14 /* ScriptDebugServer.cpp in Sources */,

Modified: trunk/Source/_javascript_Core/dfg/DFGArgumentsEliminationPhase.cpp (184310 => 184311)


--- trunk/Source/_javascript_Core/dfg/DFGArgumentsEliminationPhase.cpp	2015-05-13 22:07:09 UTC (rev 184310)
+++ trunk/Source/_javascript_Core/dfg/DFGArgumentsEliminationPhase.cpp	2015-05-13 22:14:25 UTC (rev 184311)
@@ -33,6 +33,7 @@
 #include "DFGBasicBlockInlines.h"
 #include "DFGBlockMapInlines.h"
 #include "DFGClobberize.h"
+#include "DFGCombinedLiveness.h"
 #include "DFGForAllKills.h"
 #include "DFGGraph.h"
 #include "DFGInsertionSet.h"
@@ -226,6 +227,7 @@
         performLivenessAnalysis(m_graph);
         performOSRAvailabilityAnalysis(m_graph);
         m_graph.initializeNodeOwners();
+        CombinedLiveness combinedLiveness(m_graph);
         
         BlockMap<Operands<bool>> clobberedByBlock(m_graph);
         for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
@@ -264,7 +266,7 @@
                 continue;
             
             forAllKillsInBlock(
-                m_graph, block,
+                m_graph, combinedLiveness, block,
                 [&] (unsigned nodeIndex, Node* candidate) {
                     if (!m_candidates.contains(candidate))
                         return;

Added: trunk/Source/_javascript_Core/dfg/DFGCombinedLiveness.cpp (0 => 184311)


--- trunk/Source/_javascript_Core/dfg/DFGCombinedLiveness.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/dfg/DFGCombinedLiveness.cpp	2015-05-13 22:14:25 UTC (rev 184311)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "DFGCombinedLiveness.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGAvailabilityMap.h"
+#include "DFGBlockMapInlines.h"
+#include "FullBytecodeLiveness.h"
+#include "JSCInlines.h"
+
+namespace JSC { namespace DFG {
+
+HashSet<Node*> liveNodesAtHead(Graph& graph, BasicBlock* block)
+{
+    HashSet<Node*> seen;
+    for (Node* node : block->ssa->liveAtHead)
+        seen.add(node);
+    
+    AvailabilityMap& availabilityMap = block->ssa->availabilityAtHead;
+    graph.forAllLocalsLiveInBytecode(
+        block->firstOrigin().forExit,
+        [&] (VirtualRegister reg) {
+            availabilityMap.closeStartingWithLocal(
+                reg,
+                [&] (Node* node) -> bool {
+                    return seen.contains(node);
+                },
+                [&] (Node* node) -> bool {
+                    return seen.add(node).isNewEntry;
+                });
+        });
+    
+    return seen;
+}
+
+CombinedLiveness::CombinedLiveness(Graph& graph)
+    : liveAtHead(graph)
+    , liveAtTail(graph)
+{
+    // First compute the liveAtHead for each block.
+    for (BasicBlock* block : graph.blocksInNaturalOrder())
+        liveAtHead[block] = liveNodesAtHead(graph, block);
+    
+    // Now compute the liveAtTail by unifying the liveAtHead of the successors.
+    for (BasicBlock* block : graph.blocksInNaturalOrder()) {
+        for (BasicBlock* successor : block->successors()) {
+            for (Node* node : liveAtHead[successor])
+                liveAtTail[block].add(node);
+        }
+    }
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+

Added: trunk/Source/_javascript_Core/dfg/DFGCombinedLiveness.h (0 => 184311)


--- trunk/Source/_javascript_Core/dfg/DFGCombinedLiveness.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/dfg/DFGCombinedLiveness.h	2015-05-13 22:14:25 UTC (rev 184311)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGCombinedLiveness_h
+#define DFGCombinedLiveness_h
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGBlockMap.h"
+#include "DFGGraph.h"
+
+namespace JSC { namespace DFG {
+
+// Returns the set of nodes live at tail, both due to due DFG and due to bytecode (i.e. OSR exit).
+HashSet<Node*> liveNodesAtHead(Graph&, BasicBlock*);
+
+struct CombinedLiveness {
+    CombinedLiveness() { }
+    
+    CombinedLiveness(Graph&);
+    
+    BlockMap<HashSet<Node*>> liveAtHead;
+    BlockMap<HashSet<Node*>> liveAtTail;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGCombinedLiveness_h
+

Modified: trunk/Source/_javascript_Core/dfg/DFGForAllKills.h (184310 => 184311)


--- trunk/Source/_javascript_Core/dfg/DFGForAllKills.h	2015-05-13 22:07:09 UTC (rev 184310)
+++ trunk/Source/_javascript_Core/dfg/DFGForAllKills.h	2015-05-13 22:14:25 UTC (rev 184311)
@@ -26,7 +26,7 @@
 #ifndef DFGForAllKills_h
 #define DFGForAllKills_h
 
-#include "BytecodeKills.h"
+#include "DFGCombinedLiveness.h"
 #include "DFGGraph.h"
 #include "DFGOSRAvailabilityAnalysisPhase.h"
 #include "FullBytecodeLiveness.h"
@@ -39,35 +39,6 @@
 // node is killed. A prerequisite to using these utilities is having liveness and OSR availability
 // computed.
 
-template<typename Functor>
-void forAllLiveNodesAtTail(Graph& graph, BasicBlock* block, const Functor& functor)
-{
-    HashSet<Node*> seen;
-    for (Node* node : block->ssa->liveAtTail) {
-        if (seen.add(node).isNewEntry)
-            functor(node);
-    }
-    
-    DFG_ASSERT(graph, block->terminal(), block->terminal()->origin.forExit.isSet());
-    
-    AvailabilityMap& availabilityMap = block->ssa->availabilityAtTail;
-    graph.forAllLocalsLiveInBytecode(
-        block->terminal()->origin.forExit,
-        [&] (VirtualRegister reg) {
-            availabilityMap.closeStartingWithLocal(
-                reg,
-                [&] (Node* node) -> bool {
-                    return seen.contains(node);
-                },
-                [&] (Node* node) -> bool {
-                    if (!seen.add(node).isNewEntry)
-                        return false;
-                    functor(node);
-                    return true;
-                });
-        });
-}
-
 // This tells you those things that die on the boundary between nodeBefore and nodeAfter. It is
 // conservative in the sense that it might resort to telling you some things that are still live at
 // nodeAfter.
@@ -192,13 +163,12 @@
 // the value is either no longer live. This pretends that nodes are dead at the end of the block, so that
 // you can use this to do per-basic-block analyses.
 template<typename Functor>
-void forAllKillsInBlock(Graph& graph, BasicBlock* block, const Functor& functor)
+void forAllKillsInBlock(
+    Graph& graph, const CombinedLiveness& combinedLiveness, BasicBlock* block,
+    const Functor& functor)
 {
-    forAllLiveNodesAtTail(
-        graph, block,
-        [&] (Node* node) {
-            functor(block->size(), node);
-        });
+    for (Node* node : combinedLiveness.liveAtTail[block])
+        functor(block->size(), node);
     
     LocalOSRAvailabilityCalculator localAvailability;
     localAvailability.beginBlock(block);

Modified: trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp (184310 => 184311)


--- trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp	2015-05-13 22:07:09 UTC (rev 184310)
+++ trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp	2015-05-13 22:14:25 UTC (rev 184311)
@@ -31,6 +31,7 @@
 #include "DFGAbstractHeap.h"
 #include "DFGBlockMapInlines.h"
 #include "DFGClobberize.h"
+#include "DFGCombinedLiveness.h"
 #include "DFGGraph.h"
 #include "DFGInsertOSRHintsForUpdate.h"
 #include "DFGInsertionSet.h"
@@ -107,6 +108,7 @@
         m_graph.computeRefCounts();
         performLivenessAnalysis(m_graph);
         performOSRAvailabilityAnalysis(m_graph);
+        m_combinedLiveness = CombinedLiveness(m_graph);
         
         CString graphBeforeSinking;
         if (Options::verboseValidationFailure() && Options::validateGraphAtEachPhase()) {
@@ -189,7 +191,7 @@
                 // So, we prune materialized-at-tail to only include things that are live.
                 Vector<Node*> toRemove;
                 for (auto pair : materialized) {
-                    if (!block->ssa->liveAtTail.contains(pair.key))
+                    if (!m_combinedLiveness.liveAtTail[block].contains(pair.key))
                         toRemove.append(pair.key);
                 }
                 for (Node* key : toRemove)
@@ -227,7 +229,7 @@
                 if (pair.value)
                     continue; // It was materialized.
                 
-                if (block->ssa->liveAtTail.contains(pair.key))
+                if (m_combinedLiveness.liveAtTail[block].contains(pair.key))
                     continue; // It might still get materialized in all of the successors.
                 
                 // We know that it died in this block and it wasn't materialized. That means that
@@ -391,7 +393,7 @@
         m_ssaCalculator.computePhis(
             [&] (SSACalculator::Variable* variable, BasicBlock* block) -> Node* {
                 Node* allocation = indexToNode[variable->index()];
-                if (!block->ssa->liveAtHead.contains(allocation))
+                if (!m_combinedLiveness.liveAtHead[block].contains(allocation))
                     return nullptr;
                 
                 Node* phiNode = m_graph.addNode(allocation->prediction(), Phi, NodeOrigin());
@@ -405,7 +407,7 @@
         for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
             HashMap<Node*, Node*> mapping;
             
-            for (Node* candidate : block->ssa->liveAtHead) {
+            for (Node* candidate : m_combinedLiveness.liveAtHead[block]) {
                 SSACalculator::Variable* variable = nodeToVariable.get(candidate);
                 if (!variable)
                     continue;
@@ -714,7 +716,7 @@
         m_ssaCalculator.computePhis(
             [&] (SSACalculator::Variable* variable, BasicBlock* block) -> Node* {
                 PromotedHeapLocation location = m_indexToLocation[variable->index()];
-                if (!block->ssa->liveAtHead.contains(location.base()))
+                if (!m_combinedLiveness.liveAtHead[block].contains(location.base()))
                     return nullptr;
                 
                 Node* phiNode = m_graph.addNode(SpecHeapTop, Phi, NodeOrigin());
@@ -1085,6 +1087,7 @@
         }
     }
     
+    CombinedLiveness m_combinedLiveness;
     SSACalculator m_ssaCalculator;
     HashSet<Node*> m_sinkCandidates;
     HashMap<Node*, Node*> m_materializationToEscapee;

Added: trunk/Source/_javascript_Core/tests/stress/escape-object-in-diamond-then-exit.js (0 => 184311)


--- trunk/Source/_javascript_Core/tests/stress/escape-object-in-diamond-then-exit.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/escape-object-in-diamond-then-exit.js	2015-05-13 22:14:25 UTC (rev 184311)
@@ -0,0 +1,40 @@
+var global = null;
+
+function foo(p, q) {
+    var o = {f:42};
+    if (p)
+        global = o;
+    var tmp = q + 1;
+    return o.f + tmp;
+}
+
+noInline(foo);
+
+var lastObject = null;
+
+function validateEscape(when) {
+    if (global === lastObject)
+        throw "Error: bad value in global " + when + ", identical to lastObject.";
+    if (global === null || !(typeof global == "object"))
+        throw "Error: bad value in global " + when + ": it's not an object.";
+    if (global.f != 42)
+        throw "Error: bad value in global " + when + ": f isn't 42, it's: " + global.f;
+    lastObject = global;
+    global = null;
+}
+
+for (var i = 0; i < 10000; ++i) {
+    var escape = !!(i & 1);
+    var result = foo(escape, 42);
+    if (result != 42 + 42 + 1)
+        throw "Error: bad result: " + result;
+    if (escape)
+        validateEscape("in loop");
+    else if (global !== null)
+        throw "Error: bad value in global: " + global;
+}
+
+var result = foo(true, 2147483647);
+if (result != 42 + 2147483647 + 1)
+    throw "Error: bad result at end: " + result;
+validateEscape("at end");

Modified: trunk/Source/_javascript_Core/tests/stress/sink-object-past-invalid-check-sneaky.js (184310 => 184311)


--- trunk/Source/_javascript_Core/tests/stress/sink-object-past-invalid-check-sneaky.js	2015-05-13 22:07:09 UTC (rev 184310)
+++ trunk/Source/_javascript_Core/tests/stress/sink-object-past-invalid-check-sneaky.js	2015-05-13 22:14:25 UTC (rev 184311)
@@ -1,6 +1,3 @@
-// https://bugs.webkit.org/show_bug.cgi?id=144945
-//@ skip
-
 function foo(p) {
     var result = 0;
     var o = {valueOf: function() { result = 1; }};
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to