- Revision
- 240074
- Author
- alanc...@apple.com
- Date
- 2019-01-16 15:28:00 -0800 (Wed, 16 Jan 2019)
Log Message
Cherry-pick r239882. rdar://problem/47260361
DFG combined liveness can be wrong for terminal basic blocks
https://bugs.webkit.org/show_bug.cgi?id=193304
<rdar://problem/45268632>
Reviewed by Yusuke Suzuki.
JSTests:
* stress/dfg-combined-liveness-consider-terminal-blocks-bytecode-liveness.js: Added.
Source/_javascript_Core:
If a block doesn't have any successors, it can't rely on the typical
backwards liveness propagation that CombinedLiveness was doing. The phase
first got what was live in bytecode and IR at the heads of each block. Then
for each block, it made the live at tail the union of the live at head for
each successor. For a terminal block though, this could be wrong. We could
end up saying nothing is live even though many things may be live in bytecode.
We must account for what's bytecode live at the end of the block. Consider a
block that ends with:
```
ForceOSRExit
Unreachable
```
Things may definitely be live in bytecode at the tail. However, we'll
report nothing as being alive. This probably subtly breaks many analyses,
but we have a test case of it breaking the interference analysis that
the ArgumentsEliminationPhase performs.
* dfg/DFGBasicBlock.h:
(JSC::DFG::BasicBlock::last const):
* dfg/DFGCombinedLiveness.cpp:
(JSC::DFG::addBytecodeLiveness):
(JSC::DFG::liveNodesAtHead):
(JSC::DFG::CombinedLiveness::CombinedLiveness):
* dfg/DFGCombinedLiveness.h:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239882 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Modified Paths
Added Paths
Diff
Modified: branches/safari-607-branch/JSTests/ChangeLog (240073 => 240074)
--- branches/safari-607-branch/JSTests/ChangeLog 2019-01-16 23:27:57 UTC (rev 240073)
+++ branches/safari-607-branch/JSTests/ChangeLog 2019-01-16 23:28:00 UTC (rev 240074)
@@ -1,5 +1,60 @@
2019-01-15 Alan Coon <alanc...@apple.com>
+ Cherry-pick r239882. rdar://problem/47260361
+
+ DFG combined liveness can be wrong for terminal basic blocks
+ https://bugs.webkit.org/show_bug.cgi?id=193304
+ <rdar://problem/45268632>
+
+ Reviewed by Yusuke Suzuki.
+
+ JSTests:
+
+ * stress/dfg-combined-liveness-consider-terminal-blocks-bytecode-liveness.js: Added.
+
+ Source/_javascript_Core:
+
+ If a block doesn't have any successors, it can't rely on the typical
+ backwards liveness propagation that CombinedLiveness was doing. The phase
+ first got what was live in bytecode and IR at the heads of each block. Then
+ for each block, it made the live at tail the union of the live at head for
+ each successor. For a terminal block though, this could be wrong. We could
+ end up saying nothing is live even though many things may be live in bytecode.
+ We must account for what's bytecode live at the end of the block. Consider a
+ block that ends with:
+ ```
+ ForceOSRExit
+ Unreachable
+ ```
+
+ Things may definitely be live in bytecode at the tail. However, we'll
+ report nothing as being alive. This probably subtly breaks many analyses,
+ but we have a test case of it breaking the interference analysis that
+ the ArgumentsEliminationPhase performs.
+
+ * dfg/DFGBasicBlock.h:
+ (JSC::DFG::BasicBlock::last const):
+ * dfg/DFGCombinedLiveness.cpp:
+ (JSC::DFG::addBytecodeLiveness):
+ (JSC::DFG::liveNodesAtHead):
+ (JSC::DFG::CombinedLiveness::CombinedLiveness):
+ * dfg/DFGCombinedLiveness.h:
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239882 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2019-01-11 Saam barati <sbar...@apple.com>
+
+ DFG combined liveness can be wrong for terminal basic blocks
+ https://bugs.webkit.org/show_bug.cgi?id=193304
+ <rdar://problem/45268632>
+
+ Reviewed by Yusuke Suzuki.
+
+ * stress/dfg-combined-liveness-consider-terminal-blocks-bytecode-liveness.js: Added.
+
+2019-01-15 Alan Coon <alanc...@apple.com>
+
Cherry-pick r239879. rdar://problem/47260206
[JSC] Global lexical bindings can shadow global variables if it is `configurable = true`
Added: branches/safari-607-branch/JSTests/stress/dfg-combined-liveness-consider-terminal-blocks-bytecode-liveness.js (0 => 240074)
--- branches/safari-607-branch/JSTests/stress/dfg-combined-liveness-consider-terminal-blocks-bytecode-liveness.js (rev 0)
+++ branches/safari-607-branch/JSTests/stress/dfg-combined-liveness-consider-terminal-blocks-bytecode-liveness.js 2019-01-16 23:28:00 UTC (rev 240074)
@@ -0,0 +1,19 @@
+//@ runDefault("--useConcurrentJIT=0", "--usePutStackSinking=0")
+
+function foo() {
+ var args1 = function () {
+ return arguments;
+ }();
+ var args2 = function () {
+ var result = arguments;
+ result.length = 1;
+ return result;
+ }(1);
+ for (var i = 0; i < 10000000; ++i) {
+ args1.length;
+ args2.length;
+ }
+}
+foo();
+foo();
+foo();
Modified: branches/safari-607-branch/Source/_javascript_Core/ChangeLog (240073 => 240074)
--- branches/safari-607-branch/Source/_javascript_Core/ChangeLog 2019-01-16 23:27:57 UTC (rev 240073)
+++ branches/safari-607-branch/Source/_javascript_Core/ChangeLog 2019-01-16 23:28:00 UTC (rev 240074)
@@ -1,5 +1,84 @@
2019-01-15 Alan Coon <alanc...@apple.com>
+ Cherry-pick r239882. rdar://problem/47260361
+
+ DFG combined liveness can be wrong for terminal basic blocks
+ https://bugs.webkit.org/show_bug.cgi?id=193304
+ <rdar://problem/45268632>
+
+ Reviewed by Yusuke Suzuki.
+
+ JSTests:
+
+ * stress/dfg-combined-liveness-consider-terminal-blocks-bytecode-liveness.js: Added.
+
+ Source/_javascript_Core:
+
+ If a block doesn't have any successors, it can't rely on the typical
+ backwards liveness propagation that CombinedLiveness was doing. The phase
+ first got what was live in bytecode and IR at the heads of each block. Then
+ for each block, it made the live at tail the union of the live at head for
+ each successor. For a terminal block though, this could be wrong. We could
+ end up saying nothing is live even though many things may be live in bytecode.
+ We must account for what's bytecode live at the end of the block. Consider a
+ block that ends with:
+ ```
+ ForceOSRExit
+ Unreachable
+ ```
+
+ Things may definitely be live in bytecode at the tail. However, we'll
+ report nothing as being alive. This probably subtly breaks many analyses,
+ but we have a test case of it breaking the interference analysis that
+ the ArgumentsEliminationPhase performs.
+
+ * dfg/DFGBasicBlock.h:
+ (JSC::DFG::BasicBlock::last const):
+ * dfg/DFGCombinedLiveness.cpp:
+ (JSC::DFG::addBytecodeLiveness):
+ (JSC::DFG::liveNodesAtHead):
+ (JSC::DFG::CombinedLiveness::CombinedLiveness):
+ * dfg/DFGCombinedLiveness.h:
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239882 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2019-01-11 Saam barati <sbar...@apple.com>
+
+ DFG combined liveness can be wrong for terminal basic blocks
+ https://bugs.webkit.org/show_bug.cgi?id=193304
+ <rdar://problem/45268632>
+
+ Reviewed by Yusuke Suzuki.
+
+ If a block doesn't have any successors, it can't rely on the typical
+ backwards liveness propagation that CombinedLiveness was doing. The phase
+ first got what was live in bytecode and IR at the heads of each block. Then
+ for each block, it made the live at tail the union of the live at head for
+ each successor. For a terminal block though, this could be wrong. We could
+ end up saying nothing is live even though many things may be live in bytecode.
+ We must account for what's bytecode live at the end of the block. Consider a
+ block that ends with:
+ ```
+ ForceOSRExit
+ Unreachable
+ ```
+
+ Things may definitely be live in bytecode at the tail. However, we'll
+ report nothing as being alive. This probably subtly breaks many analyses,
+ but we have a test case of it breaking the interference analysis that
+ the ArgumentsEliminationPhase performs.
+
+ * dfg/DFGBasicBlock.h:
+ (JSC::DFG::BasicBlock::last const):
+ * dfg/DFGCombinedLiveness.cpp:
+ (JSC::DFG::addBytecodeLiveness):
+ (JSC::DFG::liveNodesAtHead):
+ (JSC::DFG::CombinedLiveness::CombinedLiveness):
+ * dfg/DFGCombinedLiveness.h:
+
+2019-01-15 Alan Coon <alanc...@apple.com>
+
Cherry-pick r239879. rdar://problem/47260206
[JSC] Global lexical bindings can shadow global variables if it is `configurable = true`
Modified: branches/safari-607-branch/Source/_javascript_Core/dfg/DFGBasicBlock.h (240073 => 240074)
--- branches/safari-607-branch/Source/_javascript_Core/dfg/DFGBasicBlock.h 2019-01-16 23:27:57 UTC (rev 240073)
+++ branches/safari-607-branch/Source/_javascript_Core/dfg/DFGBasicBlock.h 2019-01-16 23:28:00 UTC (rev 240074)
@@ -64,6 +64,11 @@
}
Node*& operator[](size_t i) { return at(i); }
Node* operator[](size_t i) const { return at(i); }
+ Node* last() const
+ {
+ RELEASE_ASSERT(!!size());
+ return at(size() - 1);
+ }
// Use this to find both the index of the terminal and the terminal itself in one go. May
// return a clear NodeAndIndex if the basic block currently lacks a terminal. That may happen
Modified: branches/safari-607-branch/Source/_javascript_Core/dfg/DFGCombinedLiveness.cpp (240073 => 240074)
--- branches/safari-607-branch/Source/_javascript_Core/dfg/DFGCombinedLiveness.cpp 2019-01-16 23:27:57 UTC (rev 240073)
+++ branches/safari-607-branch/Source/_javascript_Core/dfg/DFGCombinedLiveness.cpp 2019-01-16 23:28:00 UTC (rev 240074)
@@ -35,17 +35,10 @@
namespace JSC { namespace DFG {
-NodeSet liveNodesAtHead(Graph& graph, BasicBlock* block)
+static void addBytecodeLiveness(Graph& graph, AvailabilityMap& availabilityMap, NodeSet& seen, Node* node)
{
- NodeSet seen;
- for (NodeFlowProjection node : block->ssa->liveAtHead) {
- if (node.kind() == NodeFlowProjection::Primary)
- seen.addVoid(node.node());
- }
-
- AvailabilityMap& availabilityMap = block->ssa->availabilityAtHead;
graph.forAllLiveInBytecode(
- block->at(0)->origin.forExit,
+ node->origin.forExit,
[&] (VirtualRegister reg) {
availabilityMap.closeStartingWithLocal(
reg,
@@ -56,7 +49,17 @@
return seen.add(node).isNewEntry;
});
});
-
+}
+
+NodeSet liveNodesAtHead(Graph& graph, BasicBlock* block)
+{
+ NodeSet seen;
+ for (NodeFlowProjection node : block->ssa->liveAtHead) {
+ if (node.kind() == NodeFlowProjection::Primary)
+ seen.addVoid(node.node());
+ }
+
+ addBytecodeLiveness(graph, block->ssa->availabilityAtHead, seen, block->at(0));
return seen;
}
@@ -64,9 +67,27 @@
: liveAtHead(graph)
, liveAtTail(graph)
{
- // First compute the liveAtHead for each block.
- for (BasicBlock* block : graph.blocksInNaturalOrder())
+ // First compute
+ // - The liveAtHead for each block.
+ // - The liveAtTail for blocks that won't properly propagate
+ // the information based on their empty successor list.
+ for (BasicBlock* block : graph.blocksInNaturalOrder()) {
liveAtHead[block] = liveNodesAtHead(graph, block);
+
+ // If we don't have successors, we can't rely on the propagation below. This doesn't usually
+ // do anything for terminal blocks, since the last node is usually a return, so nothing is live
+ // after it. However, we may also have the end of the basic block be:
+ //
+ // ForceOSRExit
+ // Unreachable
+ //
+ // And things may definitely be live in bytecode at that point in the program.
+ if (!block->numSuccessors()) {
+ NodeSet seen;
+ addBytecodeLiveness(graph, block->ssa->availabilityAtTail, seen, block->last());
+ liveAtTail[block] = seen;
+ }
+ }
// Now compute the liveAtTail by unifying the liveAtHead of the successors.
for (BasicBlock* block : graph.blocksInNaturalOrder()) {
Modified: branches/safari-607-branch/Source/_javascript_Core/dfg/DFGCombinedLiveness.h (240073 => 240074)
--- branches/safari-607-branch/Source/_javascript_Core/dfg/DFGCombinedLiveness.h 2019-01-16 23:27:57 UTC (rev 240073)
+++ branches/safari-607-branch/Source/_javascript_Core/dfg/DFGCombinedLiveness.h 2019-01-16 23:28:00 UTC (rev 240074)
@@ -32,7 +32,7 @@
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).
+// Returns the set of nodes live at head, both due to DFG and due to bytecode (i.e. OSR exit).
NodeSet liveNodesAtHead(Graph&, BasicBlock*);
// WARNING: This currently does not reason about the liveness of shadow values. The execution