1/* 2 * Copyright (C) 2013 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "DFGOSRAvailabilityAnalysisPhase.h" 28 29#if ENABLE(DFG_JIT) 30 31#include "DFGBasicBlockInlines.h" 32#include "DFGGraph.h" 33#include "DFGInsertionSet.h" 34#include "DFGPhase.h" 35#include "JSCInlines.h" 36 37namespace JSC { namespace DFG { 38 39class OSRAvailabilityAnalysisPhase : public Phase { 40public: 41 OSRAvailabilityAnalysisPhase(Graph& graph) 42 : Phase(graph, "OSR availability analysis") 43 { 44 } 45 46 bool run() 47 { 48 ASSERT(m_graph.m_form == SSA); 49 50 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { 51 BasicBlock* block = m_graph.block(blockIndex); 52 if (!block) 53 continue; 54 block->ssa->availabilityAtHead.fill(Availability()); 55 block->ssa->availabilityAtTail.fill(Availability()); 56 } 57 58 BasicBlock* root = m_graph.block(0); 59 for (unsigned argument = root->ssa->availabilityAtHead.numberOfArguments(); argument--;) { 60 root->ssa->availabilityAtHead.argument(argument) = 61 Availability::unavailable().withFlush( 62 FlushedAt(FlushedJSValue, virtualRegisterForArgument(argument))); 63 } 64 65 if (m_graph.m_plan.mode == FTLForOSREntryMode) { 66 for (unsigned local = m_graph.m_profiledBlock->m_numCalleeRegisters; local--;) 67 root->ssa->availabilityAtHead.local(local) = Availability::unavailable(); 68 } else { 69 for (unsigned local = root->ssa->availabilityAtHead.numberOfLocals(); local--;) 70 root->ssa->availabilityAtHead.local(local) = Availability::unavailable(); 71 } 72 73 // This could be made more efficient by processing blocks in reverse postorder. 74 Operands<Availability> availability; 75 bool changed; 76 do { 77 changed = false; 78 79 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { 80 BasicBlock* block = m_graph.block(blockIndex); 81 if (!block) 82 continue; 83 84 availability = block->ssa->availabilityAtHead; 85 86 for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { 87 Node* node = block->at(nodeIndex); 88 89 switch (node->op()) { 90 case SetLocal: { 91 VariableAccessData* variable = node->variableAccessData(); 92 availability.operand(variable->local()) = 93 Availability(node->child1().node(), variable->flushedAt()); 94 break; 95 } 96 97 case GetArgument: { 98 VariableAccessData* variable = node->variableAccessData(); 99 availability.operand(variable->local()) = 100 Availability(node, variable->flushedAt()); 101 break; 102 } 103 104 case MovHint: { 105 availability.operand(node->unlinkedLocal()) = 106 Availability(node->child1().node()); 107 break; 108 } 109 110 case ZombieHint: { 111 availability.operand(node->unlinkedLocal()) = 112 Availability::unavailable(); 113 break; 114 } 115 116 default: 117 break; 118 } 119 } 120 121 if (availability == block->ssa->availabilityAtTail) 122 continue; 123 124 block->ssa->availabilityAtTail = availability; 125 changed = true; 126 127 for (unsigned successorIndex = block->numSuccessors(); successorIndex--;) { 128 BasicBlock* successor = block->successor(successorIndex); 129 for (unsigned i = availability.size(); i--;) { 130 successor->ssa->availabilityAtHead[i] = availability[i].merge( 131 successor->ssa->availabilityAtHead[i]); 132 } 133 } 134 } 135 } while (changed); 136 137 return true; 138 } 139}; 140 141bool performOSRAvailabilityAnalysis(Graph& graph) 142{ 143 SamplingRegion samplingRegion("DFG OSR Availability Analysis Phase"); 144 return runPhase<OSRAvailabilityAnalysisPhase>(graph); 145} 146 147} } // namespace JSC::DFG 148 149#endif // ENABLE(DFG_JIT) 150 151