diff options
author | Konstantin Tokarev <annulen@yandex.ru> | 2016-08-25 19:20:41 +0300 |
---|---|---|
committer | Konstantin Tokarev <annulen@yandex.ru> | 2017-02-02 12:30:55 +0000 |
commit | 6882a04fb36642862b11efe514251d32070c3d65 (patch) | |
tree | b7959826000b061fd5ccc7512035c7478742f7b0 /Source/JavaScriptCore/dfg/DFGCFAPhase.cpp | |
parent | ab6df191029eeeb0b0f16f127d553265659f739e (diff) | |
download | qtwebkit-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.cpp | 157 |
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) |