void treatRootBlock(BasicBlock* block, InsertionSet& insertionSet)
    {
        Operands<VariableAccessData*> initialAccessData(block->variablesAtTail.numberOfArguments(), block->variablesAtTail.numberOfLocals(), nullptr);
        Operands<Node*> initialAccessNodes(block->variablesAtTail.numberOfArguments(), block->variablesAtTail.numberOfLocals(), nullptr);
        for (unsigned i = 0; i < block->size(); i++) {
            Node* node = block->at(i);
            if (!node->hasVariableAccessData(m_graph))
                continue;

            VirtualRegister operand = node->local();
            if (initialAccessData.operand(operand))
                continue;

            DFG_ASSERT(m_graph, node, node->op() != SetLocal); // We should have inserted a Flush before this!
            initialAccessData.operand(operand) = node->variableAccessData();
            initialAccessNodes.operand(operand) = node;
        }

        // We want every Flush to be able to reach backwards to
        // a SetLocal. Doing this in the root block achieves this goal.
        NodeOrigin origin = block->at(0)->origin;
        Node* undefined = insertionSet.insertConstant(0, origin, jsUndefined());

        for (unsigned i = 0; i < block->variablesAtTail.numberOfLocals(); i++) {
            VirtualRegister operand = virtualRegisterForLocal(i);
            VariableAccessData* accessData;
            DFG_ASSERT(m_graph, nullptr, initialAccessNodes.operand(operand)->op() == Flush); // We should have inserted a Flush before any SetLocal/SetArgument for the local that we are analyzing now.
            accessData = initialAccessData.operand(operand);
            DFG_ASSERT(m_graph, nullptr, accessData);
            insertionSet.insertNode(0, SpecNone, 
                SetLocal, origin, OpInfo(accessData), Edge(undefined));
        }
    }
Beispiel #2
0
/**
 * Print insertions in BED format.
 * Note, as per the BED-standard (http://genome.ucsc.edu/FAQ/FAQformat)
 *   -The coordinates should be 0-based
 *   -The chromEnd field should not include the actual feature
 *   -The name will be the inserted sequence
 *   -The score will be the number of supporing counts, which is capped at 1,000
 * By (my) convention, the chromStart will be the last genome postion
 * before hte insertio.
 * 
 * <chrom>\t<left>\t<left>\t<inserted sequence>\t<read count>\n
 * @param insertions_out The output file
 * @param insertions Maps from insertions to number of supporting reads
 * @param ref_sequences The table of reference sequences 
 */
void print_insertions(FILE* insertions_out, const InsertionSet& insertions, RefSequenceTable& ref_sequences){
	fprintf(insertions_out, "track name=insertions description=\"TopHat insertions\"\n");
	for(InsertionSet::const_iterator i = insertions.begin(); i != insertions.end(); ++i){
		int counts = i->second;
		if(counts > 1000){
			counts = 1000;
		}
		fprintf(insertions_out, "%s\t%d\t%d\t%s\t%d\n",
			ref_sequences.get_name(i->first.refid),
			i->first.left,
			i->first.left,
			(i->first.sequence).c_str(),
			counts);
	}
}
Beispiel #3
0
/**
 * Add insertions from an alignment to an InsertionSet.
 * This will look for insertion in the alignment specified by bh. If the 
 * insertion is already in insertions, it will updated the count. Otherwise,
 * it will add the insertion to the set and initialize the count to 1.
 * @param bh The bowtie hit to be used to specify alignment infromation.
 * @param insertions The InsertionSet that will be updated with the insertion information from teh alignment.
 */
void insertions_from_alignment(const BowtieHit& bh, InsertionSet& insertions){

	vector<Insertion> new_insertions;
	insertions_from_spliced_hit(bh, new_insertions);

	for(size_t i = 0; i < new_insertions.size(); ++i){
		Insertion insertion = new_insertions[i];
		InsertionSet::iterator itr = insertions.find(insertion);
		if (itr != insertions.end()){
			itr->second += 1;
		}
		else{
			assert(insertion.refid != VMAXINT32);
			insertions[insertion] = 1;
		}
	}
	return;
}
    void treatRegularBlock(BasicBlock* block, InsertionSet& insertionSet)
    {
        Operands<VariableAccessData*> currentBlockAccessData(block->variablesAtTail.numberOfArguments(), block->variablesAtTail.numberOfLocals(), nullptr);
        // Insert a Flush before every SetLocal to properly pattern the graph such that 
        // any range between SetLocal and Flush has access to the local on the stack.
        {
            for (unsigned i = 0; i < block->size(); i++) {
                Node* node = block->at(i);
                bool isPrimordialSetArgument = node->op() == SetArgument && node->local().isArgument() && node == m_graph.m_arguments[node->local().toArgument()];
                if (node->op() == SetLocal || (node->op() == SetArgument && !isPrimordialSetArgument)) {
                    VirtualRegister operand = node->local();
                    VariableAccessData* flushAccessData = currentBlockAccessData.operand(operand);
                    if (!flushAccessData)
                        flushAccessData = newVariableAccessData(operand);

                    insertionSet.insertNode(i, SpecNone, 
                        Flush, node->origin, OpInfo(flushAccessData));
                }

                if (node->hasVariableAccessData(m_graph))
                    currentBlockAccessData.operand(node->local()) = node->variableAccessData();
            }
        }

        // Flush everything at the end of the block.
        {
            NodeOrigin origin = block->at(block->size() - 1)->origin;
            auto insertFlushAtEnd = [&] (VirtualRegister operand) {
                VariableAccessData* accessData = currentBlockAccessData.operand(operand);
                if (!accessData)
                    accessData = newVariableAccessData(operand);

                currentBlockAccessData.operand(operand) = accessData;

                insertionSet.insertNode(block->size(), SpecNone, 
                    Flush, origin, OpInfo(accessData));
            };

            for (unsigned i = 0; i < block->variablesAtTail.numberOfLocals(); i++)
                insertFlushAtEnd(virtualRegisterForLocal(i));
            for (unsigned i = 0; i < block->variablesAtTail.numberOfArguments(); i++)
                insertFlushAtEnd(virtualRegisterForArgument(i));
        }
    }
Beispiel #5
0
    bool run()
    {
        for (unsigned i = m_graph.m_variableAccessData.size(); i--;) {
            VariableAccessData* variable = &m_graph.m_variableAccessData[i];
            if (!variable->isRoot())
                continue;
            variable->clearVotes();
        }
        
        // Identify the set of variables that are always subject to the same structure
        // checks. For now, only consider monomorphic structure checks (one structure).
        
        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
            if (!block)
                continue;
            for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
                NodeIndex nodeIndex = block->at(indexInBlock);
                Node& node = m_graph[nodeIndex];
                if (!node.shouldGenerate())
                    continue;
                switch (node.op()) {
                case CheckStructure: {
                    Node& child = m_graph[node.child1()];
                    if (child.op() != GetLocal)
                        break;
                    VariableAccessData* variable = child.variableAccessData();
                    variable->vote(VoteStructureCheck);
                    if (variable->isCaptured() || variable->structureCheckHoistingFailed())
                        break;
                    if (!isCellSpeculation(variable->prediction()))
                        break;
                    noticeStructureCheck(variable, node.structureSet());
                    break;
                }
                    
                case ForwardCheckStructure:
                case ForwardStructureTransitionWatchpoint:
                    // We currently rely on the fact that we're the only ones who would
                    // insert this node.
                    ASSERT_NOT_REACHED();
                    break;
                    
                case GetByOffset:
                case PutByOffset:
                case PutStructure:
                case StructureTransitionWatchpoint:
                case AllocatePropertyStorage:
                case ReallocatePropertyStorage:
                case GetPropertyStorage:
                case GetByVal:
                case PutByVal:
                case PutByValAlias:
                case GetArrayLength:
                case CheckArray:
                case GetIndexedPropertyStorage:
                case Phantom:
                    // Don't count these uses.
                    break;
                    
                default:
                    m_graph.vote(node, VoteOther);
                    break;
                }
            }
        }
        
        // Disable structure hoisting on variables that appear to mostly be used in
        // contexts where it doesn't make sense.
        
        for (unsigned i = m_graph.m_variableAccessData.size(); i--;) {
            VariableAccessData* variable = &m_graph.m_variableAccessData[i];
            if (!variable->isRoot())
                continue;
            if (variable->voteRatio() >= Options::structureCheckVoteRatioForHoisting())
                continue;
            HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
            if (iter == m_map.end())
                continue;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
            dataLog("Zeroing the structure to hoist for %s because the ratio is %lf.\n",
                    m_graph.nameOfVariableAccessData(variable), variable->voteRatio());
#endif
            iter->second.m_structure = 0;
        }

        // Identify the set of variables that are live across a structure clobber.
        
        Operands<VariableAccessData*> live(
            m_graph.m_blocks[0]->variablesAtTail.numberOfArguments(),
            m_graph.m_blocks[0]->variablesAtTail.numberOfLocals());
        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
            if (!block)
                continue;
            ASSERT(live.numberOfArguments() == block->variablesAtTail.numberOfArguments());
            ASSERT(live.numberOfLocals() == block->variablesAtTail.numberOfLocals());
            for (unsigned i = live.size(); i--;) {
                NodeIndex indexAtTail = block->variablesAtTail[i];
                VariableAccessData* variable;
                if (indexAtTail == NoNode)
                    variable = 0;
                else
                    variable = m_graph[indexAtTail].variableAccessData();
                live[i] = variable;
            }
            for (unsigned indexInBlock = block->size(); indexInBlock--;) {
                NodeIndex nodeIndex = block->at(indexInBlock);
                Node& node = m_graph[nodeIndex];
                if (!node.shouldGenerate())
                    continue;
                switch (node.op()) {
                case GetLocal:
                case Flush:
                    // This is a birth.
                    live.operand(node.local()) = node.variableAccessData();
                    break;
                    
                case SetLocal:
                case SetArgument:
                    ASSERT(live.operand(node.local())); // Must be live.
                    ASSERT(live.operand(node.local()) == node.variableAccessData()); // Must have the variable we expected.
                    // This is a death.
                    live.operand(node.local()) = 0;
                    break;
                    
                // Use the CFA's notion of what clobbers the world.
                case ValueAdd:
                    if (m_graph.addShouldSpeculateInteger(node))
                        break;
                    if (Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()]))
                        break;
                    clobber(live);
                    break;
                    
                case CompareLess:
                case CompareLessEq:
                case CompareGreater:
                case CompareGreaterEq:
                case CompareEq: {
                    Node& left = m_graph[node.child1()];
                    Node& right = m_graph[node.child2()];
                    if (Node::shouldSpeculateInteger(left, right))
                        break;
                    if (Node::shouldSpeculateNumber(left, right))
                        break;
                    if (node.op() == CompareEq) {
                        if ((m_graph.isConstant(node.child1().index())
                             && m_graph.valueOfJSConstant(node.child1().index()).isNull())
                            || (m_graph.isConstant(node.child2().index())
                                && m_graph.valueOfJSConstant(node.child2().index()).isNull()))
                            break;
                        
                        if (Node::shouldSpeculateFinalObject(left, right))
                            break;
                        if (Node::shouldSpeculateArray(left, right))
                            break;
                        if (left.shouldSpeculateFinalObject() && right.shouldSpeculateFinalObjectOrOther())
                            break;
                        if (right.shouldSpeculateFinalObject() && left.shouldSpeculateFinalObjectOrOther())
                            break;
                        if (left.shouldSpeculateArray() && right.shouldSpeculateArrayOrOther())
                            break;
                        if (right.shouldSpeculateArray() && left.shouldSpeculateArrayOrOther())
                            break;
                    }
                    clobber(live);
                    break;
                }
                    
                case GetByVal:
                case PutByVal:
                case PutByValAlias:
                    if (m_graph.byValIsPure(node))
                        break;
                    clobber(live);
                    break;
                    
                case GetMyArgumentsLengthSafe:
                case GetMyArgumentByValSafe:
                case GetById:
                case GetByIdFlush:
                case PutStructure:
                case PhantomPutStructure:
                case PutById:
                case PutByIdDirect:
                case Call:
                case Construct:
                case Resolve:
                case ResolveBase:
                case ResolveBaseStrictPut:
                case ResolveGlobal:
                    clobber(live);
                    break;
                    
                default:
                    ASSERT(node.op() != Phi);
                    break;
                }
            }
        }
        
        bool changed = false;

#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
        for (HashMap<VariableAccessData*, CheckData>::iterator it = m_map.begin();
             it != m_map.end(); ++it) {
            if (!it->second.m_structure) {
                dataLog("Not hoisting checks for %s because of heuristics.\n", m_graph.nameOfVariableAccessData(it->first));
                continue;
            }
            if (it->second.m_isClobbered && !it->second.m_structure->transitionWatchpointSetIsStillValid()) {
                dataLog("Not hoisting checks for %s because the structure is clobbered and has an invalid watchpoint set.\n", m_graph.nameOfVariableAccessData(it->first));
                continue;
            }
            dataLog("Hoisting checks for %s\n", m_graph.nameOfVariableAccessData(it->first));
        }
#endif // DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
        
        // Make changes:
        // 1) If a variable's live range does not span a clobber, then inject structure
        //    checks before the SetLocal.
        // 2) If a variable's live range spans a clobber but is watchpointable, then
        //    inject structure checks before the SetLocal and replace all other structure
        //    checks on that variable with structure transition watchpoints.
        
        InsertionSet<NodeIndex> insertionSet;
        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
            if (!block)
                continue;
            for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
                NodeIndex nodeIndex = block->at(indexInBlock);
                Node& node = m_graph[nodeIndex];
                // Be careful not to use 'node' after appending to the graph. In those switch
                // cases where we need to append, we first carefully extract everything we need
                // from the node, before doing any appending.
                if (!node.shouldGenerate())
                    continue;
                switch (node.op()) {
                case SetArgument: {
                    ASSERT(!blockIndex);
                    // Insert a GetLocal and a CheckStructure immediately following this
                    // SetArgument, if the variable was a candidate for structure hoisting.
                    // If the basic block previously only had the SetArgument as its
                    // variable-at-tail, then replace it with this GetLocal.
                    VariableAccessData* variable = node.variableAccessData();
                    HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
                    if (iter == m_map.end())
                        break;
                    if (!iter->second.m_structure)
                        break;
                    if (iter->second.m_isClobbered && !iter->second.m_structure->transitionWatchpointSetIsStillValid())
                        break;
                    
                    node.ref();

                    CodeOrigin codeOrigin = node.codeOrigin;
                    
                    Node getLocal(GetLocal, codeOrigin, OpInfo(variable), nodeIndex);
                    getLocal.predict(variable->prediction());
                    getLocal.ref();
                    NodeIndex getLocalIndex = m_graph.size();
                    m_graph.append(getLocal);
                    insertionSet.append(indexInBlock + 1, getLocalIndex);
                    
                    Node checkStructure(CheckStructure, codeOrigin, OpInfo(m_graph.addStructureSet(iter->second.m_structure)), getLocalIndex);
                    checkStructure.ref();
                    NodeIndex checkStructureIndex = m_graph.size();
                    m_graph.append(checkStructure);
                    insertionSet.append(indexInBlock + 1, checkStructureIndex);
                    
                    if (block->variablesAtTail.operand(variable->local()) == nodeIndex)
                        block->variablesAtTail.operand(variable->local()) = getLocalIndex;
                    
                    m_graph.substituteGetLocal(*block, indexInBlock, variable, getLocalIndex);
                    
                    changed = true;
                    break;
                }
                    
                case SetLocal: {
                    VariableAccessData* variable = node.variableAccessData();
                    HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
                    if (iter == m_map.end())
                        break;
                    if (!iter->second.m_structure)
                        break;
                    if (iter->second.m_isClobbered && !iter->second.m_structure->transitionWatchpointSetIsStillValid())
                        break;

                    // First insert a dead SetLocal to tell OSR that the child's value should
                    // be dropped into this bytecode variable if the CheckStructure decides
                    // to exit.
                    
                    CodeOrigin codeOrigin = node.codeOrigin;
                    NodeIndex child1 = node.child1().index();
                    
                    Node setLocal(SetLocal, codeOrigin, OpInfo(variable), child1);
                    NodeIndex setLocalIndex = m_graph.size();
                    m_graph.append(setLocal);
                    insertionSet.append(indexInBlock, setLocalIndex);
                    m_graph[child1].ref();
                    // Use a ForwardCheckStructure to indicate that we should exit to the
                    // next bytecode instruction rather than reexecuting the current one.
                    Node checkStructure(ForwardCheckStructure, codeOrigin, OpInfo(m_graph.addStructureSet(iter->second.m_structure)), child1);
                    checkStructure.ref();
                    NodeIndex checkStructureIndex = m_graph.size();
                    m_graph.append(checkStructure);
                    insertionSet.append(indexInBlock, checkStructureIndex);
                    changed = true;
                    break;
                }
                    
                case CheckStructure: {
                    Node& child = m_graph[node.child1()];
                    if (child.op() != GetLocal)
                        break;
                    HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(child.variableAccessData());
                    if (iter == m_map.end())
                        break;
                    if (!iter->second.m_structure)
                        break;
                    if (!iter->second.m_isClobbered) {
                        node.setOpAndDefaultFlags(Phantom);
                        ASSERT(node.refCount() == 1);
                        break;
                    }
                    if (!iter->second.m_structure->transitionWatchpointSetIsStillValid())
                        break;
                    ASSERT(iter->second.m_structure == node.structureSet().singletonStructure());
                    node.convertToStructureTransitionWatchpoint();
                    changed = true;
                    break;
                }
                    
                default:
                    break;
                }
            }
            insertionSet.execute(*block);
        }
        
        return changed;
    }
void insertInferredTypeCheck(
    InsertionSet& insertionSet, unsigned nodeIndex, NodeOrigin origin, Node* baseNode,
    const InferredType::Descriptor& type)
{
    insertionSet.graph().registerInferredType(type);

    switch (type.kind()) {
    case InferredType::Bottom:
        insertionSet.insertNode(nodeIndex, SpecNone, ForceOSRExit, origin);
        return;

    case InferredType::Boolean:
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, BooleanUse));
        return;

    case InferredType::Other:
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, OtherUse));
        return;

    case InferredType::Int32:
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, Int32Use));
        return;

    case InferredType::Number:
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, NumberUse));
        return;

    case InferredType::String:
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, StringUse));
        return;

    case InferredType::Symbol:
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, SymbolUse));
        return;

    case InferredType::ObjectWithStructure:
        insertionSet.insertNode(
            nodeIndex, SpecNone, CheckStructure, origin,
            OpInfo(insertionSet.graph().addStructureSet(type.structure())),
            Edge(baseNode, CellUse));
        return;

    case InferredType::ObjectWithStructureOrOther:
        insertionSet.insertNode(
            nodeIndex, SpecNone, CheckStructure, origin,
            OpInfo(insertionSet.graph().addStructureSet(type.structure())),
            Edge(baseNode, CellOrOtherUse));
        return;

    case InferredType::Object:
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, ObjectUse));
        return;

    case InferredType::ObjectOrOther:
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, ObjectOrOtherUse));
        return;

    case InferredType::Top:
        return;
    }

    DFG_CRASH(insertionSet.graph(), baseNode, "Bad inferred type");
}
    void handleBlockForTryCatch(BasicBlock* block, InsertionSet& insertionSet)
    {
        HandlerInfo* currentExceptionHandler = nullptr;
        FastBitVector liveAtCatchHead;
        liveAtCatchHead.resize(m_graph.block(0)->variablesAtTail.numberOfLocals());

        HandlerInfo* cachedHandlerResult;
        CodeOrigin cachedCodeOrigin;
        auto catchHandler = [&] (CodeOrigin origin) -> HandlerInfo* {
            ASSERT(origin);
            if (origin == cachedCodeOrigin)
                return cachedHandlerResult;

            unsigned bytecodeIndexToCheck = origin.bytecodeIndex;

            cachedCodeOrigin = origin;

            while (1) {
                InlineCallFrame* inlineCallFrame = origin.inlineCallFrame;
                CodeBlock* codeBlock = m_graph.baselineCodeBlockFor(inlineCallFrame);
                if (HandlerInfo* handler = codeBlock->handlerForBytecodeOffset(bytecodeIndexToCheck)) {
                    liveAtCatchHead.clearAll();

                    unsigned catchBytecodeIndex = handler->target;
                    m_graph.forAllLocalsLiveInBytecode(CodeOrigin(catchBytecodeIndex, inlineCallFrame), [&] (VirtualRegister operand) {
                        liveAtCatchHead[operand.toLocal()] = true;
                    });

                    cachedHandlerResult = handler;
                    break;
                }

                if (!inlineCallFrame) {
                    cachedHandlerResult = nullptr;
                    break;
                }

                bytecodeIndexToCheck = inlineCallFrame->directCaller.bytecodeIndex;
                origin = inlineCallFrame->directCaller;
            }

            return cachedHandlerResult;
        };

        Operands<VariableAccessData*> currentBlockAccessData(block->variablesAtTail.numberOfArguments(), block->variablesAtTail.numberOfLocals(), nullptr);
        HashSet<InlineCallFrame*> seenInlineCallFrames;

        auto flushEverything = [&] (NodeOrigin origin, unsigned index) {
            RELEASE_ASSERT(currentExceptionHandler);
            auto flush = [&] (VirtualRegister operand, bool alwaysInsert) {
                if ((operand.isLocal() && liveAtCatchHead[operand.toLocal()]) 
                    || operand.isArgument()
                    || alwaysInsert) {

                    ASSERT(isValidFlushLocation(block, index, operand));

                    VariableAccessData* accessData = currentBlockAccessData.operand(operand);
                    if (!accessData)
                        accessData = newVariableAccessData(operand);

                    currentBlockAccessData.operand(operand) = accessData;

                    insertionSet.insertNode(index, SpecNone, 
                        Flush, origin, OpInfo(accessData));
                }
            };

            for (unsigned local = 0; local < block->variablesAtTail.numberOfLocals(); local++)
                flush(virtualRegisterForLocal(local), false);
            for (InlineCallFrame* inlineCallFrame : seenInlineCallFrames)
                flush(VirtualRegister(inlineCallFrame->stackOffset + CallFrame::thisArgumentOffset()), true);
            flush(VirtualRegister(CallFrame::thisArgumentOffset()), true);

            seenInlineCallFrames.clear();
        };

        for (unsigned nodeIndex = 0; nodeIndex < block->size(); nodeIndex++) {
            Node* node = block->at(nodeIndex);

            {
                HandlerInfo* newHandler = catchHandler(node->origin.semantic);
                if (newHandler != currentExceptionHandler && currentExceptionHandler)
                    flushEverything(node->origin, nodeIndex);
                currentExceptionHandler = newHandler;
            }

            if (currentExceptionHandler && (node->op() == SetLocal || node->op() == SetArgument)) {
                InlineCallFrame* inlineCallFrame = node->origin.semantic.inlineCallFrame;
                if (inlineCallFrame)
                    seenInlineCallFrames.add(inlineCallFrame);
                VirtualRegister operand = node->local();

                int stackOffset = inlineCallFrame ? inlineCallFrame->stackOffset : 0;
                if ((operand.isLocal() && liveAtCatchHead[operand.toLocal()])
                    || operand.isArgument()
                    || (operand.offset() == stackOffset + CallFrame::thisArgumentOffset())) {

                    ASSERT(isValidFlushLocation(block, nodeIndex, operand));

                    VariableAccessData* variableAccessData = currentBlockAccessData.operand(operand);
                    if (!variableAccessData)
                        variableAccessData = newVariableAccessData(operand);

                    insertionSet.insertNode(nodeIndex, SpecNone, 
                        Flush, node->origin, OpInfo(variableAccessData));
                }
            }

            if (node->accessesStack(m_graph))
                currentBlockAccessData.operand(node->local()) = node->variableAccessData();
        }

        if (currentExceptionHandler) {
            NodeOrigin origin = block->at(block->size() - 1)->origin;
            flushEverything(origin, block->size());
        }
    }
 bool run()
 {
     bool changed = false;
     
     AbstractState state(m_graph);
     InsertionSet<NodeIndex> insertionSet;
     
     for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
         BasicBlock* block = m_graph.m_blocks[blockIndex].get();
         if (!block)
             continue;
         if (!block->cfaFoundConstants)
             continue;
         state.beginBasicBlock(block);
         for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
             if (!state.isValid())
                 break;
             state.execute(indexInBlock);
             NodeIndex nodeIndex = block->at(indexInBlock);
             Node& node = m_graph[nodeIndex];
             if (!node.shouldGenerate()
                 || m_graph.clobbersWorld(node)
                 || node.hasConstant())
                 continue;
             JSValue value = state.forNode(nodeIndex).value();
             if (!value)
                 continue;
             
             Node phantom(Phantom, node.codeOrigin);
             
             if (node.op() == GetLocal) {
                 ASSERT(m_graph[node.child1()].op() == Phi);
                 ASSERT(!m_graph[node.child1()].hasResult());
                 
                 ASSERT(block->variablesAtHead.operand(node.local()) == nodeIndex);
                 ASSERT(block->isInPhis(node.child1().index()));
                 block->variablesAtHead.operand(node.local()) = node.child1().index();
                 
                 NodeIndex tailNodeIndex = block->variablesAtTail.operand(node.local());
                 if (tailNodeIndex == nodeIndex)
                     block->variablesAtTail.operand(node.local()) = node.child1().index();
                 else {
                     ASSERT(m_graph[tailNodeIndex].op() == Flush
                            || m_graph[tailNodeIndex].op() == SetLocal);
                 }
             }
             
             phantom.children = node.children;
             phantom.ref();
             
             m_graph.convertToConstant(nodeIndex, value);
             NodeIndex phantomNodeIndex = m_graph.size();
             m_graph.append(phantom);
             insertionSet.append(indexInBlock, phantomNodeIndex);
             
             changed = true;
         }
         insertionSet.execute(*block);
         state.reset();
     }
     
     return changed;
 }