summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2016-08-25 19:20:41 +0300
committerKonstantin Tokarev <annulen@yandex.ru>2017-02-02 12:30:55 +0000
commit6882a04fb36642862b11efe514251d32070c3d65 (patch)
treeb7959826000b061fd5ccc7512035c7478742f7b0 /Source/JavaScriptCore/dfg/DFGCFAPhase.cpp
parentab6df191029eeeb0b0f16f127d553265659f739e (diff)
downloadqtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGCFAPhase.cpp')
-rw-r--r--Source/JavaScriptCore/dfg/DFGCFAPhase.cpp157
1 files changed, 111 insertions, 46 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp b/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp
index 599a7918a..016e7d7f7 100644
--- a/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2013-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
@@ -28,10 +28,13 @@
#if ENABLE(DFG_JIT)
-#include "DFGAbstractState.h"
+#include "DFGAbstractInterpreterInlines.h"
#include "DFGGraph.h"
+#include "DFGInPlaceAbstractState.h"
#include "DFGPhase.h"
-#include "Operations.h"
+#include "DFGSafeToExecute.h"
+#include "OperandsInlines.h"
+#include "JSCInlines.h"
namespace JSC { namespace DFG {
@@ -40,18 +43,23 @@ public:
CFAPhase(Graph& graph)
: Phase(graph, "control flow analysis")
, m_state(graph)
+ , m_interpreter(graph, m_state)
+ , m_verbose(Options::verboseCFA())
{
}
bool run()
{
- ASSERT(m_graph.m_form == ThreadedCPS);
+ ASSERT(m_graph.m_form == ThreadedCPS || m_graph.m_form == SSA);
ASSERT(m_graph.m_unificationState == GloballyUnified);
ASSERT(m_graph.m_refCountState == EverythingIsLive);
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
m_count = 0;
-#endif
+
+ if (m_verbose && !shouldDumpGraphAtEachPhase(m_graph.m_plan.mode)) {
+ dataLog("Graph before CFA:\n");
+ m_graph.dump();
+ }
// This implements a pseudo-worklist-based forward CFA, except that the visit order
// of blocks is the bytecode program order (which is nearly topological), and
@@ -64,77 +72,134 @@ public:
// after all predecessors have been visited. Only loops will cause this analysis to
// revisit blocks, and the amount of revisiting is proportional to loop depth.
- AbstractState::initialize(m_graph);
+ m_state.initialize();
do {
m_changed = false;
performForwardCFA();
} while (m_changed);
+ if (m_graph.m_form != SSA) {
+ ASSERT(!m_changed);
+
+ // Widen the abstract values at the block that serves as the must-handle OSR entry.
+ for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+ BasicBlock* block = m_graph.block(blockIndex);
+ if (!block)
+ continue;
+
+ if (!block->isOSRTarget)
+ continue;
+ if (block->bytecodeBegin != m_graph.m_plan.osrEntryBytecodeIndex)
+ continue;
+
+ bool changed = false;
+ for (size_t i = m_graph.m_plan.mustHandleValues.size(); i--;) {
+ int operand = m_graph.m_plan.mustHandleValues.operandForIndex(i);
+ JSValue value = m_graph.m_plan.mustHandleValues[i];
+ Node* node = block->variablesAtHead.operand(operand);
+ if (!node)
+ continue;
+
+ AbstractValue& target = block->valuesAtHead.operand(operand);
+ changed |= target.mergeOSREntryValue(m_graph, value);
+ target.fixTypeForRepresentation(
+ m_graph, resultFor(node->variableAccessData()->flushFormat()));
+ }
+
+ if (changed || !block->cfaHasVisited) {
+ m_changed = true;
+ block->cfaShouldRevisit = true;
+ }
+ }
+
+ // Propagate any of the changes we just introduced.
+ while (m_changed) {
+ m_changed = false;
+ performForwardCFA();
+ }
+
+ // Make sure we record the intersection of all proofs that we ever allowed the
+ // compiler to rely upon.
+ for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+ BasicBlock* block = m_graph.block(blockIndex);
+ if (!block)
+ continue;
+
+ block->intersectionOfCFAHasVisited &= block->cfaHasVisited;
+ for (unsigned i = block->intersectionOfPastValuesAtHead.size(); i--;)
+ block->intersectionOfPastValuesAtHead[i].filter(block->valuesAtHead[i]);
+ }
+ }
+
return true;
}
private:
- void performBlockCFA(BlockIndex blockIndex)
+ void performBlockCFA(BasicBlock* block)
{
- BasicBlock* block = m_graph.m_blocks[blockIndex].get();
if (!block)
return;
if (!block->cfaShouldRevisit)
return;
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLogF(" Block #%u (bc#%u):\n", blockIndex, block->bytecodeBegin);
-#endif
+ if (m_verbose)
+ dataLog(" Block ", *block, ":\n");
m_state.beginBasicBlock(block);
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLogF(" head vars: ");
- dumpOperands(block->valuesAtHead, WTF::dataFile());
- dataLogF("\n");
-#endif
+ if (m_verbose) {
+ dataLog(" head vars: ", block->valuesAtHead, "\n");
+ if (m_graph.m_form == SSA)
+ dataLog(" head regs: ", mapDump(block->ssa->valuesAtHead), "\n");
+ }
for (unsigned i = 0; i < block->size(); ++i) {
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- Node* node = block->at(i);
- dataLogF(" %s @%u: ", Graph::opName(node->op()), node->index());
- m_state.dump(WTF::dataFile());
- dataLogF("\n");
-#endif
- if (!m_state.execute(i)) {
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLogF(" Expect OSR exit.\n");
-#endif
+ if (m_verbose) {
+ Node* node = block->at(i);
+ dataLogF(" %s @%u: ", Graph::opName(node->op()), node->index());
+
+ if (!safeToExecute(m_state, m_graph, node))
+ dataLog("(UNSAFE) ");
+
+ dataLog(m_state.variables(), " ", m_interpreter);
+
+ dataLogF("\n");
+ }
+ if (!m_interpreter.execute(i)) {
+ if (m_verbose)
+ dataLogF(" Expect OSR exit.\n");
break;
}
}
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLogF(" tail regs: ");
- m_state.dump(WTF::dataFile());
- dataLogF("\n");
-#endif
- m_changed |= m_state.endBasicBlock(AbstractState::MergeToSuccessors);
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLogF(" tail vars: ");
- dumpOperands(block->valuesAtTail, WTF::dataFile());
- dataLogF("\n");
-#endif
+ if (m_verbose) {
+ dataLogF(" tail regs: ");
+ m_interpreter.dump(WTF::dataFile());
+ dataLogF("\n");
+ }
+ m_changed |= m_state.endBasicBlock();
+
+ if (m_verbose) {
+ dataLog(" tail vars: ", block->valuesAtTail, "\n");
+ if (m_graph.m_form == SSA)
+ dataLog(" head regs: ", mapDump(block->ssa->valuesAtTail), "\n");
+ }
}
void performForwardCFA()
{
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLogF("CFA [%u]\n", ++m_count);
-#endif
+ ++m_count;
+ if (m_verbose)
+ dataLogF("CFA [%u]\n", ++m_count);
- for (BlockIndex block = 0; block < m_graph.m_blocks.size(); ++block)
- performBlockCFA(block);
+ for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
+ performBlockCFA(m_graph.block(blockIndex));
}
private:
- AbstractState m_state;
+ InPlaceAbstractState m_state;
+ AbstractInterpreter<InPlaceAbstractState> m_interpreter;
+
+ bool m_verbose;
bool m_changed;
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
unsigned m_count;
-#endif
};
bool performCFA(Graph& graph)