void InPlaceAbstractState::beginBasicBlock(BasicBlock* basicBlock)
{
    ASSERT(!m_block);

    ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->valuesAtHead.numberOfLocals());
    ASSERT(basicBlock->variablesAtTail.numberOfLocals() == basicBlock->valuesAtTail.numberOfLocals());
    ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->variablesAtTail.numberOfLocals());

    for (size_t i = 0; i < basicBlock->size(); i++)
        forNode(basicBlock->at(i)).clear();

    m_variables = basicBlock->valuesAtHead;

    if (m_graph.m_form == SSA) {
        HashMap<Node*, AbstractValue>::iterator iter = basicBlock->ssa->valuesAtHead.begin();
        HashMap<Node*, AbstractValue>::iterator end = basicBlock->ssa->valuesAtHead.end();
        for (; iter != end; ++iter)
            forNode(iter->key) = iter->value;
    }
    basicBlock->cfaShouldRevisit = false;
    basicBlock->cfaHasVisited = true;
    m_block = basicBlock;
    m_isValid = true;
    m_foundConstants = false;
    m_branchDirection = InvalidBranchDirection;
    m_structureClobberState = basicBlock->cfaStructureClobberStateAtHead;
}
bool InPlaceAbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, Node* node)
{
    if (!node)
        return false;

    AbstractValue source;

    switch (node->op()) {
    case Phi:
    case SetArgument:
    case PhantomLocal:
    case Flush:
        // The block transfers the value from head to tail.
        source = inVariable;
        break;

    case GetLocal:
        // The block refines the value with additional speculations.
        source = forNode(node);
        break;

    case SetLocal:
        // The block sets the variable, and potentially refines it, both
        // before and after setting it.
        source = forNode(node->child1());
        if (node->variableAccessData()->flushFormat() == FlushedDouble)
            RELEASE_ASSERT(!(source.m_type & ~SpecFullDouble));
        break;

    default:
        RELEASE_ASSERT_NOT_REACHED();
        break;
    }

    if (destination == source) {
        // Abstract execution did not change the output value of the variable, for this
        // basic block, on this iteration.
        return false;
    }

    // Abstract execution reached a new conclusion about the speculations reached about
    // this variable after execution of this basic block. Update the state, and return
    // true to indicate that the fixpoint must go on!
    destination = source;
    return true;
}
Exemplo n.º 3
0
bool InPlaceAbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, Node* node)
{
    if (!node)
        return false;
        
    AbstractValue source;
    
    if (node->variableAccessData()->isCaptured()) {
        // If it's captured then we know that whatever value was stored into the variable last is the
        // one we care about. This is true even if the variable at tail is dead, which might happen if
        // the last thing we did to the variable was a GetLocal and then ended up now using the
        // GetLocal's result.
        
        source = inVariable;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
        dataLogF("          Transfering ");
        source.dump(WTF::dataFile());
        dataLogF(" from last access due to captured variable.\n");
#endif
    } else {
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
        dataLogF("          It's live, node @%u.\n", node->index());
#endif
    
        switch (node->op()) {
        case Phi:
        case SetArgument:
        case PhantomLocal:
        case Flush:
            // The block transfers the value from head to tail.
            source = inVariable;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
            dataLogF("          Transfering ");
            source.dump(WTF::dataFile());
            dataLogF(" from head to tail.\n");
#endif
            break;
            
        case GetLocal:
            // The block refines the value with additional speculations.
            source = forNode(node);
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
            dataLogF("          Refining to ");
            source.dump(WTF::dataFile());
            dataLogF("\n");
#endif
            break;
            
        case SetLocal:
            // The block sets the variable, and potentially refines it, both
            // before and after setting it.
            if (node->variableAccessData()->shouldUseDoubleFormat()) {
                // FIXME: This unnecessarily loses precision.
                source.setType(SpecDouble);
            } else
                source = forNode(node->child1());
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
            dataLogF("          Setting to ");
            source.dump(WTF::dataFile());
            dataLogF("\n");
#endif
            break;
        
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
    }
    
    if (destination == source) {
        // Abstract execution did not change the output value of the variable, for this
        // basic block, on this iteration.
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
        dataLogF("          Not changed!\n");
#endif
        return false;
    }
    
    // Abstract execution reached a new conclusion about the speculations reached about
    // this variable after execution of this basic block. Update the state, and return
    // true to indicate that the fixpoint must go on!
    destination = source;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
    dataLogF("          Changed!\n");
#endif
    return true;
}
Exemplo n.º 4
0
bool InPlaceAbstractState::endBasicBlock(MergeMode mergeMode)
{
    ASSERT(m_block);
    
    BasicBlock* block = m_block; // Save the block for successor merging.
    
    block->cfaFoundConstants = m_foundConstants;
    block->cfaDidFinish = m_isValid;
    block->cfaBranchDirection = m_branchDirection;
    
    if (!m_isValid) {
        reset();
        return false;
    }
    
    bool changed = false;
    
    if (mergeMode != DontMerge || !ASSERT_DISABLED) {
        switch (m_graph.m_form) {
        case ThreadedCPS: {
            for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument) {
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
                dataLogF("        Merging state for argument %zu.\n", argument);
#endif
                AbstractValue& destination = block->valuesAtTail.argument(argument);
                changed |= mergeStateAtTail(destination, m_variables.argument(argument), block->variablesAtTail.argument(argument));
            }
            
            for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local) {
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
                dataLogF("        Merging state for local %zu.\n", local);
#endif
                AbstractValue& destination = block->valuesAtTail.local(local);
                changed |= mergeStateAtTail(destination, m_variables.local(local), block->variablesAtTail.local(local));
            }
            break;
        }
            
        case SSA: {
            for (size_t i = 0; i < block->valuesAtTail.size(); ++i)
                changed |= block->valuesAtTail[i].merge(m_variables[i]);
            
            HashSet<Node*>::iterator iter = block->ssa->liveAtTail.begin();
            HashSet<Node*>::iterator end = block->ssa->liveAtTail.end();
            for (; iter != end; ++iter) {
                Node* node = *iter;
                changed |= block->ssa->valuesAtTail.find(node)->value.merge(forNode(node));
            }
            break;
        }
            
        default:
            RELEASE_ASSERT_NOT_REACHED();
        }
    }
    
    ASSERT(mergeMode != DontMerge || !changed);
    
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
    dataLogF("        Branch direction = %s\n", branchDirectionToString(m_branchDirection));
#endif
    
    reset();
    
    if (mergeMode != MergeToSuccessors)
        return changed;
    
    return mergeToSuccessors(block);
}
Exemplo n.º 5
0
	static MemSource forNode(const Node &node) {
		return forNode(node.physicalId());
	}