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; }};