mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 749358 - Inline MUse storage. r=luke
This commit is contained in:
parent
78a045cb78
commit
fcd36f671b
@ -406,6 +406,9 @@ class Vector : private AllocPolicy
|
||||
/* Clears and releases any heap-allocated storage. */
|
||||
void clearAndFree();
|
||||
|
||||
/* If true, appending |needed| elements will not call realloc(). */
|
||||
bool canAppendWithoutRealloc(size_t needed) const;
|
||||
|
||||
/*
|
||||
* Potentially fallible append operations.
|
||||
*
|
||||
@ -772,6 +775,13 @@ Vector<T,N,AP>::clearAndFree()
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T, size_t N, class AP>
|
||||
inline bool
|
||||
Vector<T,N,AP>::canAppendWithoutRealloc(size_t needed) const
|
||||
{
|
||||
return mLength + needed <= mCapacity;
|
||||
}
|
||||
|
||||
template <class T, size_t N, class AP>
|
||||
template <class U>
|
||||
JS_ALWAYS_INLINE bool
|
||||
|
@ -55,10 +55,10 @@ EdgeCaseAnalysis::AllUsesTruncate(MInstruction *m)
|
||||
int ret = 1;
|
||||
for (MUseIterator use = m->usesBegin(); use != m->usesEnd(); use++) {
|
||||
// See #809485 why this is allowed
|
||||
if (use->node()->isResumePoint())
|
||||
if (use->consumer()->isResumePoint())
|
||||
continue;
|
||||
|
||||
MDefinition *def = use->node()->toDefinition();
|
||||
MDefinition *def = use->consumer()->toDefinition();
|
||||
if (def->isTruncateToInt32())
|
||||
continue;
|
||||
if (def->isBitAnd())
|
||||
|
@ -103,11 +103,11 @@ ion::EliminateDeadResumePointOperands(MIRGenerator *mir, MIRGraph &graph)
|
||||
// Walk the uses a second time, removing any in resume points after
|
||||
// the last use in a definition.
|
||||
for (MUseIterator uses(ins->usesBegin()); uses != ins->usesEnd(); ) {
|
||||
if (uses->node()->isDefinition()) {
|
||||
if (uses->consumer()->isDefinition()) {
|
||||
uses++;
|
||||
continue;
|
||||
}
|
||||
MResumePoint *mrp = uses->node()->toResumePoint();
|
||||
MResumePoint *mrp = uses->consumer()->toResumePoint();
|
||||
if (mrp->block() != *block ||
|
||||
!mrp->instruction() ||
|
||||
mrp->instruction() == *ins ||
|
||||
@ -188,8 +188,8 @@ IsPhiObservable(MPhi *phi, Observability observe)
|
||||
|
||||
case ConservativeObservability:
|
||||
for (MUseIterator iter(phi->usesBegin()); iter != phi->usesEnd(); iter++) {
|
||||
if (!iter->node()->isDefinition() ||
|
||||
!iter->node()->toDefinition()->isPhi())
|
||||
if (!iter->consumer()->isDefinition() ||
|
||||
!iter->consumer()->toDefinition()->isPhi())
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@ -879,16 +879,30 @@ CheckPredecessorImpliesSuccessor(MBasicBlock *A, MBasicBlock *B)
|
||||
}
|
||||
|
||||
static bool
|
||||
CheckMarkedAsUse(MInstruction *ins, MDefinition *operand)
|
||||
CheckOperandImpliesUse(MInstruction *ins, MDefinition *operand)
|
||||
{
|
||||
for (MUseIterator i = operand->usesBegin(); i != operand->usesEnd(); i++) {
|
||||
if (i->node()->isDefinition()) {
|
||||
if (ins == i->node()->toDefinition())
|
||||
return true;
|
||||
}
|
||||
if (i->consumer()->isDefinition() && i->consumer()->toDefinition() == ins)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
CheckUseImpliesOperand(MInstruction *ins, MUse *use)
|
||||
{
|
||||
MNode *consumer = use->consumer();
|
||||
uint32_t index = use->index();
|
||||
|
||||
if (consumer->isDefinition()) {
|
||||
MDefinition *def = consumer->toDefinition();
|
||||
return (def->getOperand(index) == ins);
|
||||
}
|
||||
|
||||
JS_ASSERT(consumer->isResumePoint());
|
||||
MResumePoint *res = consumer->toResumePoint();
|
||||
return (res->getOperand(index) == ins);
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -926,9 +940,14 @@ ion::AssertGraphCoherency(MIRGraph &graph)
|
||||
for (size_t i = 0; i < block->numPredecessors(); i++)
|
||||
JS_ASSERT(CheckPredecessorImpliesSuccessor(*block, block->getPredecessor(i)));
|
||||
|
||||
// Assert that use chains are valid for this instruction.
|
||||
for (MInstructionIterator ins = block->begin(); ins != block->end(); ins++) {
|
||||
for (uint32_t i = 0; i < ins->numOperands(); i++)
|
||||
JS_ASSERT(CheckMarkedAsUse(*ins, ins->getOperand(i)));
|
||||
JS_ASSERT(CheckOperandImpliesUse(*ins, ins->getOperand(i)));
|
||||
}
|
||||
for (MInstructionIterator ins = block->begin(); ins != block->end(); ins++) {
|
||||
for (MUseIterator i(ins->usesBegin()); i != ins->usesEnd(); i++)
|
||||
JS_ASSERT(CheckUseImpliesOperand(*ins, *i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2957,14 +2957,16 @@ IonBuilder::patchInlinedReturns(CallInfo &callInfo, MIRGraphExits &exits, MBasic
|
||||
// would have been returned.
|
||||
JS_ASSERT(exits.length() > 0);
|
||||
|
||||
MPhi *retDef = NULL;
|
||||
// In the case of a single return, no phi is necessary.
|
||||
MPhi *phi = NULL;
|
||||
if (exits.length() > 1) {
|
||||
retDef = MPhi::New(bottom->stackDepth());
|
||||
bottom->addPhi(retDef);
|
||||
phi = MPhi::New(bottom->stackDepth());
|
||||
phi->initLength(exits.length());
|
||||
bottom->addPhi(phi);
|
||||
}
|
||||
|
||||
for (MBasicBlock **it = exits.begin(), **end = exits.end(); it != end; ++it) {
|
||||
MBasicBlock *exitBlock = *it;
|
||||
for (size_t i = 0; i < exits.length(); i++) {
|
||||
MBasicBlock *exitBlock = exits[i];
|
||||
|
||||
MDefinition *rval = exitBlock->lastIns()->toReturn()->getOperand(0);
|
||||
exitBlock->discardLastIns();
|
||||
@ -2988,10 +2990,10 @@ IonBuilder::patchInlinedReturns(CallInfo &callInfo, MIRGraphExits &exits, MBasic
|
||||
if (exits.length() == 1)
|
||||
return rval;
|
||||
|
||||
retDef->addInput(rval);
|
||||
phi->setOperand(i, rval);
|
||||
}
|
||||
|
||||
return retDef;
|
||||
return phi;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -3529,11 +3531,16 @@ IonBuilder::inlineScriptedCalls(AutoObjectVector &targets, AutoObjectVector &ori
|
||||
MPhi *phi = MPhi::New(inlineBottom->stackDepth() - callInfo.argc() - 2);
|
||||
inlineBottom->addPhi(phi);
|
||||
|
||||
if (!phi->initLength(retvalDefns.length()))
|
||||
return false;
|
||||
|
||||
size_t index = 0;
|
||||
MDefinition **it = retvalDefns.begin(), **end = retvalDefns.end();
|
||||
for (; it != end; ++it) {
|
||||
if (!phi->addInput(*it))
|
||||
return false;
|
||||
}
|
||||
for (; it != end; it++, index++)
|
||||
phi->setOperand(index, *it);
|
||||
|
||||
JS_ASSERT(index == retvalDefns.length());
|
||||
|
||||
// retvalDefns should become a singleton vector of 'phi'
|
||||
retvalDefns.clear();
|
||||
if (!retvalDefns.append(phi))
|
||||
@ -3578,10 +3585,16 @@ IonBuilder::inlineScriptedCalls(AutoObjectVector &targets, AutoObjectVector &ori
|
||||
MPhi *phi = MPhi::New(bottom->stackDepth());
|
||||
bottom->addPhi(phi);
|
||||
|
||||
for (MDefinition **it = retvalDefns.begin(), **end = retvalDefns.end(); it != end; ++it) {
|
||||
if (!phi->addInput(*it))
|
||||
return false;
|
||||
}
|
||||
if (!phi->initLength(retvalDefns.length()))
|
||||
return false;
|
||||
|
||||
size_t index = 0;
|
||||
MDefinition **it = retvalDefns.begin(), **end = retvalDefns.end();
|
||||
for (; it != end; it++, index++)
|
||||
phi->setOperand(index, *it);
|
||||
|
||||
JS_ASSERT(index == retvalDefns.length());
|
||||
|
||||
retvalDefn = phi;
|
||||
} else {
|
||||
retvalDefn = retvalDefns.back();
|
||||
@ -4216,10 +4229,13 @@ IonBuilder::makeCallHelper(HandleFunction target, CallInfo &callInfo,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MPassArg *newThis = MPassArg::New(create);
|
||||
|
||||
// Unwrap the MPassArg before discarding: it may have been captured by an MResumePoint.
|
||||
thisArg->replaceAllUsesWith(thisArg->getArgument());
|
||||
thisArg->block()->discard(thisArg);
|
||||
|
||||
MPassArg *newThis = MPassArg::New(create);
|
||||
current->add(newThis);
|
||||
|
||||
thisArg = newThis;
|
||||
}
|
||||
|
||||
|
@ -551,7 +551,7 @@ CanEmitCompareAtUses(MInstruction *ins)
|
||||
|
||||
bool foundTest = false;
|
||||
for (MUseIterator iter(ins->usesBegin()); iter != ins->usesEnd(); iter++) {
|
||||
MNode *node = iter->node();
|
||||
MNode *node = iter->consumer();
|
||||
if (!node->isDefinition())
|
||||
return false;
|
||||
if (!node->toDefinition()->isTest())
|
||||
|
@ -248,43 +248,70 @@ MDefinition::removeUse(MUseIterator use)
|
||||
}
|
||||
|
||||
MUseIterator
|
||||
MNode::replaceOperand(MUseIterator use, MDefinition *ins)
|
||||
MNode::replaceOperand(MUseIterator use, MDefinition *def)
|
||||
{
|
||||
MDefinition *used = getOperand(use->index());
|
||||
if (used == ins)
|
||||
JS_ASSERT(def != NULL);
|
||||
uint32_t index = use->index();
|
||||
MDefinition *prev = use->producer();
|
||||
|
||||
JS_ASSERT(use->index() < numOperands());
|
||||
JS_ASSERT(use->producer() == getOperand(index));
|
||||
JS_ASSERT(use->consumer() == this);
|
||||
|
||||
if (prev == def)
|
||||
return use;
|
||||
|
||||
MUse *save = *use;
|
||||
MUseIterator result(used->removeUse(use));
|
||||
if (ins) {
|
||||
setOperand(save->index(), ins);
|
||||
ins->linkUse(save);
|
||||
}
|
||||
MUseIterator result(prev->removeUse(use));
|
||||
setOperand(index, def);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
MNode::replaceOperand(size_t index, MDefinition *def)
|
||||
{
|
||||
MDefinition *d = getOperand(index);
|
||||
for (MUseIterator i(d->usesBegin()); i != d->usesEnd(); i++) {
|
||||
if (i->index() == index && i->node() == this) {
|
||||
replaceOperand(i, def);
|
||||
return;
|
||||
}
|
||||
}
|
||||
JS_ASSERT(def != NULL);
|
||||
MUse *use = getUseFor(index);
|
||||
MDefinition *prev = use->producer();
|
||||
|
||||
JS_NOT_REACHED("could not find use");
|
||||
JS_ASSERT(use->index() == index);
|
||||
JS_ASSERT(use->index() < numOperands());
|
||||
JS_ASSERT(use->producer() == getOperand(index));
|
||||
JS_ASSERT(use->consumer() == this);
|
||||
|
||||
if (prev == def)
|
||||
return;
|
||||
|
||||
prev->removeUse(use);
|
||||
setOperand(index, def);
|
||||
}
|
||||
|
||||
void
|
||||
MNode::discardOperand(size_t index)
|
||||
{
|
||||
MUse *use = getUseFor(index);
|
||||
|
||||
JS_ASSERT(use->index() == index);
|
||||
JS_ASSERT(use->producer() == getOperand(index));
|
||||
JS_ASSERT(use->consumer() == this);
|
||||
|
||||
use->producer()->removeUse(use);
|
||||
|
||||
#ifdef DEBUG
|
||||
// Causes any producer/consumer lookups to trip asserts.
|
||||
use->set(NULL, NULL, index);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
MDefinition::replaceAllUsesWith(MDefinition *dom)
|
||||
{
|
||||
for (MUseIterator i(uses_.begin()); i != uses_.end(); ) {
|
||||
MUse *use = *i;
|
||||
i = uses_.removeAt(i);
|
||||
use->node()->setOperand(use->index(), dom);
|
||||
dom->linkUse(use);
|
||||
JS_ASSERT(dom != NULL);
|
||||
if (dom == this)
|
||||
return;
|
||||
|
||||
for (MUseIterator i(usesBegin()); i != usesEnd(); ) {
|
||||
JS_ASSERT(i->producer() == this);
|
||||
i = i->consumer()->replaceOperand(i, dom);
|
||||
}
|
||||
}
|
||||
|
||||
@ -474,18 +501,27 @@ MPhi::New(uint32_t slot)
|
||||
void
|
||||
MPhi::removeOperand(size_t index)
|
||||
{
|
||||
MUse *use = getUseFor(index);
|
||||
|
||||
JS_ASSERT(index < inputs_.length());
|
||||
JS_ASSERT(inputs_.length() > 1);
|
||||
|
||||
JS_ASSERT(use->index() == index);
|
||||
JS_ASSERT(use->producer() == getOperand(index));
|
||||
JS_ASSERT(use->consumer() == this);
|
||||
|
||||
// Remove use from producer's use chain.
|
||||
use->producer()->removeUse(use);
|
||||
|
||||
// If we have phi(..., a, b, c, d, ..., z) and we plan
|
||||
// on removing a, then first shift downward so that we have
|
||||
// phi(..., b, c, d, ..., z, z):
|
||||
size_t length = inputs_.length();
|
||||
for (size_t i = index + 1; i < length; i++)
|
||||
replaceOperand(i - 1, getOperand(i));
|
||||
|
||||
// remove the final operand that now appears twice:
|
||||
replaceOperand(length - 1, NULL);
|
||||
for (size_t i = index; i < length - 1; i++) {
|
||||
MUse *next = MPhi::getUseFor(i + 1);
|
||||
next->producer()->removeUse(next);
|
||||
MPhi::setOperand(i, next->producer());
|
||||
}
|
||||
|
||||
// truncate the inputs_ list:
|
||||
inputs_.shrinkBy(1);
|
||||
@ -523,17 +559,56 @@ MPhi::congruentTo(MDefinition *const &ins) const
|
||||
}
|
||||
|
||||
bool
|
||||
MPhi::addInput(MDefinition *ins)
|
||||
MPhi::initLength(size_t length)
|
||||
{
|
||||
ins->addUse(this, inputs_.length());
|
||||
return inputs_.append(ins);
|
||||
// Initializes a new MPhi to have an Operand vector of at least the given
|
||||
// length. This permits use of setOperand() instead of addInputSlow(), the
|
||||
// latter of which may call realloc().
|
||||
JS_ASSERT(numOperands() == 0);
|
||||
return inputs_.resizeUninitialized(length);
|
||||
}
|
||||
|
||||
bool
|
||||
MPhi::addInputSlow(MDefinition *ins)
|
||||
{
|
||||
// The list of inputs to an MPhi is given as a vector of MUse nodes,
|
||||
// each of which is in the list of the producer MDefinition.
|
||||
// Because appending to a vector may reallocate the vector, it is possible
|
||||
// that this operation may cause the producers' linked lists to reference
|
||||
// invalid memory. Therefore, in the event of moving reallocation, each
|
||||
// MUse must be removed and reinserted from/into its producer's use chain.
|
||||
uint32_t index = inputs_.length();
|
||||
bool performingRealloc = !inputs_.canAppendWithoutRealloc(1);
|
||||
|
||||
// Remove all MUses from all use lists, in case realloc() moves.
|
||||
if (performingRealloc) {
|
||||
for (uint32_t i = 0; i < index; i++) {
|
||||
MUse *use = &inputs_[i];
|
||||
use->producer()->removeUse(use);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the new input.
|
||||
if (!inputs_.append(MUse()))
|
||||
return false;
|
||||
MPhi::setOperand(index, ins);
|
||||
|
||||
// Add all previously-removed MUses back.
|
||||
if (performingRealloc) {
|
||||
for (uint32_t i = 0; i < index; i++) {
|
||||
MUse *use = &inputs_[i];
|
||||
use->producer()->addUse(use);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MPrepareCall::argc() const
|
||||
{
|
||||
JS_ASSERT(useCount() == 1);
|
||||
MCall *call = usesBegin()->node()->toDefinition()->toCall();
|
||||
MCall *call = usesBegin()->consumer()->toDefinition()->toCall();
|
||||
return call->numStackArgs();
|
||||
}
|
||||
|
||||
@ -555,7 +630,7 @@ MCall::addArg(size_t argnum, MPassArg *arg)
|
||||
// The operand vector is initialized in reverse order by the IonBuilder.
|
||||
// It cannot be checked for consistency until all arguments are added.
|
||||
arg->setArgnum(argnum);
|
||||
MNode::initOperand(argnum + NumNonArgumentOperands, arg->toDefinition());
|
||||
setOperand(argnum + NumNonArgumentOperands, arg->toDefinition());
|
||||
}
|
||||
|
||||
void
|
||||
@ -647,10 +722,10 @@ NeedNegativeZeroCheck(MDefinition *def)
|
||||
{
|
||||
// Test if all uses have the same semantics for -0 and 0
|
||||
for (MUseIterator use = def->usesBegin(); use != def->usesEnd(); use++) {
|
||||
if (use->node()->isResumePoint())
|
||||
if (use->consumer()->isResumePoint())
|
||||
continue;
|
||||
|
||||
MDefinition *use_def = use->node()->toDefinition();
|
||||
MDefinition *use_def = use->consumer()->toDefinition();
|
||||
switch (use_def->op()) {
|
||||
case MDefinition::Op_Add: {
|
||||
// If add is truncating -0 and 0 are observed as the same.
|
||||
@ -1427,7 +1502,7 @@ MResumePoint *
|
||||
MResumePoint::New(MBasicBlock *block, jsbytecode *pc, MResumePoint *parent, Mode mode)
|
||||
{
|
||||
MResumePoint *resume = new MResumePoint(block, pc, parent, mode);
|
||||
if (!resume->init(block))
|
||||
if (!resume->init())
|
||||
return NULL;
|
||||
resume->inherit(block);
|
||||
return resume;
|
||||
@ -1444,15 +1519,6 @@ MResumePoint::MResumePoint(MBasicBlock *block, jsbytecode *pc, MResumePoint *cal
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
MResumePoint::init(MBasicBlock *block)
|
||||
{
|
||||
operands_ = block->graph().allocate<MDefinition *>(stackDepth());
|
||||
if (!operands_)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MResumePoint::inherit(MBasicBlock *block)
|
||||
{
|
||||
@ -1462,7 +1528,7 @@ MResumePoint::inherit(MBasicBlock *block)
|
||||
// and LStackArg does not define a value.
|
||||
if (def->isPassArg())
|
||||
def = def->toPassArg()->getArgument();
|
||||
initOperand(i, def);
|
||||
setOperand(i, def);
|
||||
}
|
||||
}
|
||||
|
||||
|
270
js/src/ion/MIR.h
270
js/src/ion/MIR.h
@ -67,32 +67,51 @@ class MResumePoint;
|
||||
static inline bool isOSRLikeValue (MDefinition *def);
|
||||
|
||||
// Represents a use of a node.
|
||||
class MUse : public TempObject, public InlineForwardListNode<MUse>
|
||||
class MUse : public TempObject, public InlineListNode<MUse>
|
||||
{
|
||||
friend class MDefinition;
|
||||
|
||||
MNode *node_; // The node that is using this operand.
|
||||
uint32_t index_; // The index of this operand in its owner.
|
||||
MDefinition *producer_; // MDefinition that is being used.
|
||||
MNode *consumer_; // The node that is using this operand.
|
||||
uint32_t index_; // The index of this operand in its consumer.
|
||||
|
||||
MUse(MNode *owner, uint32_t index)
|
||||
: node_(owner),
|
||||
MUse(MDefinition *producer, MNode *consumer, uint32_t index)
|
||||
: producer_(producer),
|
||||
consumer_(consumer),
|
||||
index_(index)
|
||||
{ }
|
||||
|
||||
public:
|
||||
static inline MUse *New(MNode *owner, uint32_t index) {
|
||||
return new MUse(owner, index);
|
||||
// Default constructor for use in vectors.
|
||||
MUse()
|
||||
: producer_(NULL), consumer_(NULL), index_(0)
|
||||
{ }
|
||||
|
||||
static inline MUse *New(MDefinition *producer, MNode *consumer, uint32_t index) {
|
||||
return new MUse(producer, consumer, index);
|
||||
}
|
||||
|
||||
MNode *node() const {
|
||||
return node_;
|
||||
// Set data inside the MUse.
|
||||
void set(MDefinition *producer, MNode *consumer, uint32_t index) {
|
||||
producer_ = producer;
|
||||
consumer_ = consumer;
|
||||
index_ = index;
|
||||
}
|
||||
|
||||
MDefinition *producer() const {
|
||||
JS_ASSERT(producer_ != NULL);
|
||||
return producer_;
|
||||
}
|
||||
MNode *consumer() const {
|
||||
JS_ASSERT(consumer_ != NULL);
|
||||
return consumer_;
|
||||
}
|
||||
uint32_t index() const {
|
||||
return index_;
|
||||
}
|
||||
};
|
||||
|
||||
typedef InlineForwardList<MUse>::iterator MUseIterator;
|
||||
typedef InlineList<MUse>::iterator MUseIterator;
|
||||
|
||||
// A node is an entry in the MIR graph. It has two kinds:
|
||||
// MInstruction: an instruction which appears in the IR stream.
|
||||
@ -114,9 +133,12 @@ class MNode : public TempObject
|
||||
ResumePoint
|
||||
};
|
||||
|
||||
MNode() : block_(NULL)
|
||||
MNode()
|
||||
: block_(NULL)
|
||||
{ }
|
||||
MNode(MBasicBlock *block) : block_(block)
|
||||
|
||||
MNode(MBasicBlock *block)
|
||||
: block_(block)
|
||||
{ }
|
||||
|
||||
virtual Kind kind() const = 0;
|
||||
@ -141,20 +163,25 @@ class MNode : public TempObject
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Replaces an operand, taking care to update use chains. No memory is
|
||||
// allocated; the existing data structures are re-linked.
|
||||
// Replaces an already-set operand during iteration over a use chain.
|
||||
MUseIterator replaceOperand(MUseIterator use, MDefinition *ins);
|
||||
|
||||
// Replaces an already-set operand, updating use information.
|
||||
void replaceOperand(size_t index, MDefinition *ins);
|
||||
|
||||
// Resets the operand to an uninitialized state, breaking the link
|
||||
// with the previous operand's producer.
|
||||
void discardOperand(size_t index);
|
||||
|
||||
inline MDefinition *toDefinition();
|
||||
inline MResumePoint *toResumePoint();
|
||||
|
||||
protected:
|
||||
// Sets a raw operand, ignoring updating use information.
|
||||
// Sets an unset operand, updating use information.
|
||||
virtual void setOperand(size_t index, MDefinition *operand) = 0;
|
||||
|
||||
// Initializes an operand for the first time.
|
||||
inline void initOperand(size_t index, MDefinition *ins);
|
||||
// Gets the MUse corresponding to given operand.
|
||||
virtual MUse *getUseFor(size_t index) = 0;
|
||||
};
|
||||
|
||||
class AliasSet {
|
||||
@ -230,8 +257,8 @@ class MDefinition : public MNode
|
||||
};
|
||||
|
||||
private:
|
||||
InlineForwardList<MUse> uses_; // Use chain.
|
||||
uint32_t id_; // Instruction ID, which after block re-ordering
|
||||
InlineList<MUse> uses_; // Use chain.
|
||||
uint32_t id_; // Instruction ID, which after block re-ordering
|
||||
// is sorted within a basic block.
|
||||
ValueNumberData *valueNumber_; // The instruction's value number (see GVN for details in use)
|
||||
Range *range_; // Any computed range for this def.
|
||||
@ -377,6 +404,9 @@ class MDefinition : public MNode
|
||||
|
||||
// Removes a use at the given position
|
||||
MUseIterator removeUse(MUseIterator use);
|
||||
void removeUse(MUse *use) {
|
||||
uses_.remove(use);
|
||||
}
|
||||
|
||||
// Number of uses of this instruction.
|
||||
size_t useCount() const;
|
||||
@ -389,8 +419,8 @@ class MDefinition : public MNode
|
||||
return false;
|
||||
}
|
||||
|
||||
void addUse(MNode *node, size_t index) {
|
||||
uses_.pushFront(MUse::New(node, index));
|
||||
void addUse(MUse *use) {
|
||||
uses_.pushFront(use);
|
||||
}
|
||||
void replaceAllUsesWith(MDefinition *dom);
|
||||
|
||||
@ -406,13 +436,6 @@ class MDefinition : public MNode
|
||||
return true;
|
||||
}
|
||||
|
||||
// Adds a use from a node that is being recycled during operand
|
||||
// replacement.
|
||||
void linkUse(MUse *use) {
|
||||
JS_ASSERT(use->node()->getOperand(use->index()) == this);
|
||||
uses_.pushFront(use);
|
||||
}
|
||||
|
||||
void setVirtualRegister(uint32_t vreg) {
|
||||
virtualRegister_ = vreg;
|
||||
#ifdef DEBUG
|
||||
@ -494,7 +517,7 @@ class MUseDefIterator
|
||||
MUseIterator search(MUseIterator start) {
|
||||
MUseIterator i(start);
|
||||
for (; i != def_->usesEnd(); i++) {
|
||||
if (i->node()->isDefinition())
|
||||
if (i->consumer()->isDefinition())
|
||||
return i;
|
||||
}
|
||||
return def_->usesEnd();
|
||||
@ -504,8 +527,7 @@ class MUseDefIterator
|
||||
MUseDefIterator(MDefinition *def)
|
||||
: def_(def),
|
||||
current_(search(def->usesBegin()))
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
operator bool() const {
|
||||
return current_ != def_->usesEnd();
|
||||
@ -521,7 +543,7 @@ class MUseDefIterator
|
||||
return *current_;
|
||||
}
|
||||
MDefinition *def() const {
|
||||
return current_->node()->toDefinition();
|
||||
return current_->consumer()->toDefinition();
|
||||
}
|
||||
size_t index() const {
|
||||
return current_->index();
|
||||
@ -564,15 +586,20 @@ template <size_t Arity>
|
||||
class MAryInstruction : public MInstruction
|
||||
{
|
||||
protected:
|
||||
FixedArityList<MDefinition*, Arity> operands_;
|
||||
FixedArityList<MUse, Arity> operands_;
|
||||
|
||||
void setOperand(size_t index, MDefinition *operand) {
|
||||
operands_[index] = operand;
|
||||
operands_[index].set(operand, this, index);
|
||||
operand->addUse(&operands_[index]);
|
||||
}
|
||||
|
||||
MUse *getUseFor(size_t index) {
|
||||
return &operands_[index];
|
||||
}
|
||||
|
||||
public:
|
||||
MDefinition *getOperand(size_t index) const {
|
||||
return operands_[index];
|
||||
return operands_[index].producer();
|
||||
}
|
||||
size_t numOperands() const {
|
||||
return Arity;
|
||||
@ -758,7 +785,7 @@ class MTableSwitch
|
||||
// Contains the blocks/cases that still need to get build
|
||||
Vector<MBasicBlock*, 0, IonAllocPolicy> blocks_;
|
||||
|
||||
MDefinition *operand_;
|
||||
MUse operand_;
|
||||
int32_t low_;
|
||||
int32_t high_;
|
||||
|
||||
@ -768,13 +795,19 @@ class MTableSwitch
|
||||
low_(low),
|
||||
high_(high)
|
||||
{
|
||||
initOperand(0, ins);
|
||||
setOperand(0, ins);
|
||||
}
|
||||
|
||||
protected:
|
||||
void setOperand(size_t index, MDefinition *operand) {
|
||||
JS_ASSERT(index == 0);
|
||||
operand_ = operand;
|
||||
operand_.set(operand, this, index);
|
||||
operand->addUse(&operand_);
|
||||
}
|
||||
|
||||
MUse *getUseFor(size_t index) {
|
||||
JS_ASSERT(index == 0);
|
||||
return &operand_;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -846,7 +879,7 @@ class MTableSwitch
|
||||
|
||||
MDefinition *getOperand(size_t index) const {
|
||||
JS_ASSERT(index == 0);
|
||||
return operand_;
|
||||
return operand_.producer();
|
||||
}
|
||||
|
||||
size_t numOperands() const {
|
||||
@ -857,20 +890,25 @@ class MTableSwitch
|
||||
template <size_t Arity, size_t Successors>
|
||||
class MAryControlInstruction : public MControlInstruction
|
||||
{
|
||||
FixedArityList<MDefinition *, Arity> operands_;
|
||||
FixedArityList<MUse, Arity> operands_;
|
||||
FixedArityList<MBasicBlock *, Successors> successors_;
|
||||
|
||||
protected:
|
||||
void setOperand(size_t index, MDefinition *operand) {
|
||||
operands_[index] = operand;
|
||||
operands_[index].set(operand, this, index);
|
||||
operand->addUse(&operands_[index]);
|
||||
}
|
||||
void setSuccessor(size_t index, MBasicBlock *successor) {
|
||||
successors_[index] = successor;
|
||||
}
|
||||
|
||||
MUse *getUseFor(size_t index) {
|
||||
return &operands_[index];
|
||||
}
|
||||
|
||||
public:
|
||||
MDefinition *getOperand(size_t index) const {
|
||||
return operands_[index];
|
||||
return operands_[index].producer();
|
||||
}
|
||||
size_t numOperands() const {
|
||||
return Arity;
|
||||
@ -927,7 +965,7 @@ class MTest
|
||||
MTest(MDefinition *ins, MBasicBlock *if_true, MBasicBlock *if_false)
|
||||
: operandMightEmulateUndefined_(true)
|
||||
{
|
||||
initOperand(0, ins);
|
||||
setOperand(0, ins);
|
||||
setSuccessor(0, if_true);
|
||||
setSuccessor(1, if_false);
|
||||
}
|
||||
@ -970,7 +1008,7 @@ class MReturn
|
||||
public BoxInputsPolicy
|
||||
{
|
||||
MReturn(MDefinition *ins) {
|
||||
initOperand(0, ins);
|
||||
setOperand(0, ins);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -992,7 +1030,7 @@ class MThrow
|
||||
public BoxInputsPolicy
|
||||
{
|
||||
MThrow(MDefinition *ins) {
|
||||
initOperand(0, ins);
|
||||
setOperand(0, ins);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -1093,8 +1131,8 @@ class MInitProp
|
||||
MInitProp(MDefinition *obj, HandlePropertyName name, MDefinition *value)
|
||||
: name_(name)
|
||||
{
|
||||
initOperand(0, obj);
|
||||
initOperand(1, value);
|
||||
setOperand(0, obj);
|
||||
setOperand(1, value);
|
||||
setResultType(MIRType_None);
|
||||
}
|
||||
|
||||
@ -1141,7 +1179,7 @@ class MPrepareCall : public MNullaryInstruction
|
||||
|
||||
class MVariadicInstruction : public MInstruction
|
||||
{
|
||||
FixedList<MDefinition *> operands_;
|
||||
FixedList<MUse> operands_;
|
||||
|
||||
protected:
|
||||
bool init(size_t length) {
|
||||
@ -1151,13 +1189,18 @@ class MVariadicInstruction : public MInstruction
|
||||
public:
|
||||
// Will assert if called before initialization.
|
||||
MDefinition *getOperand(size_t index) const {
|
||||
return operands_[index];
|
||||
return operands_[index].producer();
|
||||
}
|
||||
size_t numOperands() const {
|
||||
return operands_.length();
|
||||
}
|
||||
void setOperand(size_t index, MDefinition *operand) {
|
||||
operands_[index] = operand;
|
||||
operands_[index].set(operand, this, index);
|
||||
operand->addUse(&operands_[index]);
|
||||
}
|
||||
|
||||
MUse *getUseFor(size_t index) {
|
||||
return &operands_[index];
|
||||
}
|
||||
};
|
||||
|
||||
@ -1199,11 +1242,11 @@ class MCall
|
||||
|
||||
void initPrepareCall(MDefinition *start) {
|
||||
JS_ASSERT(start->isPrepareCall());
|
||||
return initOperand(PrepareCallOperandIndex, start);
|
||||
return setOperand(PrepareCallOperandIndex, start);
|
||||
}
|
||||
void initFunction(MDefinition *func) {
|
||||
JS_ASSERT(!func->isPassArg());
|
||||
return initOperand(FunctionOperandIndex, func);
|
||||
return setOperand(FunctionOperandIndex, func);
|
||||
}
|
||||
|
||||
MDefinition *getFunction() const {
|
||||
@ -1264,9 +1307,9 @@ class MApplyArgs
|
||||
MApplyArgs(JSFunction *target, MDefinition *fun, MDefinition *argc, MDefinition *self)
|
||||
: target_(target)
|
||||
{
|
||||
initOperand(0, fun);
|
||||
initOperand(1, argc);
|
||||
initOperand(2, self);
|
||||
setOperand(0, fun);
|
||||
setOperand(1, argc);
|
||||
setOperand(2, self);
|
||||
setResultType(MIRType_Value);
|
||||
}
|
||||
|
||||
@ -1301,7 +1344,7 @@ class MUnaryInstruction : public MAryInstruction<1>
|
||||
protected:
|
||||
MUnaryInstruction(MDefinition *ins)
|
||||
{
|
||||
initOperand(0, ins);
|
||||
setOperand(0, ins);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1310,8 +1353,8 @@ class MBinaryInstruction : public MAryInstruction<2>
|
||||
protected:
|
||||
MBinaryInstruction(MDefinition *left, MDefinition *right)
|
||||
{
|
||||
initOperand(0, left);
|
||||
initOperand(1, right);
|
||||
setOperand(0, left);
|
||||
setOperand(1, right);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -1375,9 +1418,9 @@ class MTernaryInstruction : public MAryInstruction<3>
|
||||
protected:
|
||||
MTernaryInstruction(MDefinition *first, MDefinition *second, MDefinition *third)
|
||||
{
|
||||
initOperand(0, first);
|
||||
initOperand(1, second);
|
||||
initOperand(2, third);
|
||||
setOperand(0, first);
|
||||
setOperand(1, second);
|
||||
setOperand(2, third);
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -1778,8 +1821,8 @@ class MReturnFromCtor
|
||||
public MixPolicy<BoxPolicy<0>, ObjectPolicy<1> >
|
||||
{
|
||||
MReturnFromCtor(MDefinition *value, MDefinition *object) {
|
||||
initOperand(0, value);
|
||||
initOperand(1, object);
|
||||
setOperand(0, value);
|
||||
setOperand(1, object);
|
||||
setResultType(MIRType_Object);
|
||||
}
|
||||
|
||||
@ -2932,10 +2975,12 @@ class MFromCharCode
|
||||
|
||||
class MPhi : public MDefinition, public InlineForwardListNode<MPhi>
|
||||
{
|
||||
js::Vector<MDefinition *, 2, IonAllocPolicy> inputs_;
|
||||
js::Vector<MUse, 2, IonAllocPolicy> inputs_;
|
||||
|
||||
uint32_t slot_;
|
||||
bool triedToSpecialize_;
|
||||
bool isIterator_;
|
||||
|
||||
MPhi(uint32_t slot)
|
||||
: slot_(slot),
|
||||
triedToSpecialize_(false),
|
||||
@ -2945,18 +2990,25 @@ class MPhi : public MDefinition, public InlineForwardListNode<MPhi>
|
||||
}
|
||||
|
||||
protected:
|
||||
void setOperand(size_t index, MDefinition *operand) {
|
||||
inputs_[index] = operand;
|
||||
MUse *getUseFor(size_t index) {
|
||||
return &inputs_[index];
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(Phi)
|
||||
static MPhi *New(uint32_t slot);
|
||||
|
||||
// Unsafe to use unless space has already been reserved via initLength().
|
||||
void setOperand(size_t index, MDefinition *operand) {
|
||||
JS_ASSERT(index < numOperands());
|
||||
inputs_[index].set(operand, this, index);
|
||||
operand->addUse(&inputs_[index]);
|
||||
}
|
||||
|
||||
void removeOperand(size_t index);
|
||||
|
||||
MDefinition *getOperand(size_t index) const {
|
||||
return inputs_[index];
|
||||
return inputs_[index].producer();
|
||||
}
|
||||
size_t numOperands() const {
|
||||
return inputs_.length();
|
||||
@ -2971,7 +3023,14 @@ class MPhi : public MDefinition, public InlineForwardListNode<MPhi>
|
||||
triedToSpecialize_ = true;
|
||||
setResultType(type);
|
||||
}
|
||||
bool addInput(MDefinition *ins);
|
||||
|
||||
// Initializes the operands vector to the given length,
|
||||
// permitting use of setOperand() instead of addInputSlow().
|
||||
bool initLength(size_t length);
|
||||
|
||||
// Appends a new input to the input vector. May call realloc().
|
||||
// Prefer initLength() and setOperand() instead, where possible.
|
||||
bool addInputSlow(MDefinition *ins);
|
||||
|
||||
MDefinition *foldsTo(bool useValueNumbers);
|
||||
|
||||
@ -3476,8 +3535,8 @@ class MSetInitializedLength
|
||||
{
|
||||
MSetInitializedLength(MDefinition *elements, MDefinition *index)
|
||||
{
|
||||
initOperand(0, elements);
|
||||
initOperand(1, index);
|
||||
setOperand(0, elements);
|
||||
setOperand(1, index);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -3855,9 +3914,9 @@ class MStoreElement
|
||||
bool needsHoleCheck_;
|
||||
|
||||
MStoreElement(MDefinition *elements, MDefinition *index, MDefinition *value, bool needsHoleCheck) {
|
||||
initOperand(0, elements);
|
||||
initOperand(1, index);
|
||||
initOperand(2, value);
|
||||
setOperand(0, elements);
|
||||
setOperand(1, index);
|
||||
setOperand(2, value);
|
||||
needsHoleCheck_ = needsHoleCheck;
|
||||
JS_ASSERT(elements->type() == MIRType_Elements);
|
||||
JS_ASSERT(index->type() == MIRType_Int32);
|
||||
@ -3904,10 +3963,10 @@ class MStoreElementHole
|
||||
{
|
||||
MStoreElementHole(MDefinition *object, MDefinition *elements,
|
||||
MDefinition *index, MDefinition *value) {
|
||||
initOperand(0, object);
|
||||
initOperand(1, elements);
|
||||
initOperand(2, index);
|
||||
initOperand(3, value);
|
||||
setOperand(0, object);
|
||||
setOperand(1, elements);
|
||||
setOperand(2, index);
|
||||
setOperand(3, value);
|
||||
JS_ASSERT(elements->type() == MIRType_Elements);
|
||||
JS_ASSERT(index->type() == MIRType_Int32);
|
||||
}
|
||||
@ -4517,39 +4576,45 @@ class MPolyInlineDispatch : public MControlInstruction, public SingleObjectPolic
|
||||
};
|
||||
Vector<Entry, 4, IonAllocPolicy> dispatchTable_;
|
||||
|
||||
MDefinition *operand_;
|
||||
MUse operand_;
|
||||
InlinePropertyTable *inlinePropertyTable_;
|
||||
MBasicBlock *fallbackPrepBlock_;
|
||||
MBasicBlock *fallbackMidBlock_;
|
||||
MBasicBlock *fallbackEndBlock_;
|
||||
|
||||
MPolyInlineDispatch(MDefinition *ins)
|
||||
: dispatchTable_(), operand_(NULL),
|
||||
: dispatchTable_(),
|
||||
inlinePropertyTable_(NULL),
|
||||
fallbackPrepBlock_(NULL),
|
||||
fallbackMidBlock_(NULL),
|
||||
fallbackEndBlock_(NULL)
|
||||
{
|
||||
initOperand(0, ins);
|
||||
setOperand(0, ins);
|
||||
}
|
||||
|
||||
MPolyInlineDispatch(MDefinition *ins, InlinePropertyTable *inlinePropertyTable,
|
||||
MBasicBlock *fallbackPrepBlock,
|
||||
MBasicBlock *fallbackMidBlock,
|
||||
MBasicBlock *fallbackEndBlock)
|
||||
: dispatchTable_(), operand_(NULL),
|
||||
: dispatchTable_(),
|
||||
inlinePropertyTable_(inlinePropertyTable),
|
||||
fallbackPrepBlock_(fallbackPrepBlock),
|
||||
fallbackMidBlock_(fallbackMidBlock),
|
||||
fallbackEndBlock_(fallbackEndBlock)
|
||||
{
|
||||
initOperand(0, ins);
|
||||
setOperand(0, ins);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void setOperand(size_t index, MDefinition *operand) {
|
||||
JS_ASSERT(index == 0);
|
||||
operand_ = operand;
|
||||
operand_.set(operand, this, index);
|
||||
operand->addUse(&operand_);
|
||||
}
|
||||
|
||||
MUse *getUseFor(size_t index) {
|
||||
JS_ASSERT(index == 0);
|
||||
return &operand_;
|
||||
}
|
||||
|
||||
void setSuccessor(size_t i, MBasicBlock *successor) {
|
||||
@ -4565,7 +4630,7 @@ class MPolyInlineDispatch : public MControlInstruction, public SingleObjectPolic
|
||||
|
||||
virtual MDefinition *getOperand(size_t index) const {
|
||||
JS_ASSERT(index == 0);
|
||||
return operand_;
|
||||
return operand_.producer();
|
||||
}
|
||||
|
||||
virtual size_t numOperands() const {
|
||||
@ -5247,9 +5312,9 @@ class MCallSetElement
|
||||
public CallSetElementPolicy
|
||||
{
|
||||
MCallSetElement(MDefinition *object, MDefinition *index, MDefinition *value) {
|
||||
initOperand(0, object);
|
||||
initOperand(1, index);
|
||||
initOperand(2, value);
|
||||
setOperand(0, object);
|
||||
setOperand(1, index);
|
||||
setOperand(2, value);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -5282,8 +5347,8 @@ class MSetDOMProperty
|
||||
MSetDOMProperty(const JSJitPropertyOp func, MDefinition *obj, MDefinition *val)
|
||||
: func_(func)
|
||||
{
|
||||
initOperand(0, obj);
|
||||
initOperand(1, val);
|
||||
setOperand(0, obj);
|
||||
setOperand(1, val);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -5323,10 +5388,10 @@ class MGetDOMProperty
|
||||
{
|
||||
JS_ASSERT(jitinfo);
|
||||
|
||||
initOperand(0, obj);
|
||||
setOperand(0, obj);
|
||||
|
||||
// Pin the guard as an operand if we want to hoist later
|
||||
initOperand(1, guard);
|
||||
setOperand(1, guard);
|
||||
|
||||
// We are movable iff the jitinfo says we can be.
|
||||
if (jitinfo->isConstant)
|
||||
@ -6023,7 +6088,7 @@ class MResumePoint : public MNode
|
||||
private:
|
||||
friend class MBasicBlock;
|
||||
|
||||
MDefinition **operands_;
|
||||
FixedList<MUse> operands_;
|
||||
uint32_t stackDepth_;
|
||||
jsbytecode *pc_;
|
||||
MResumePoint *caller_;
|
||||
@ -6031,14 +6096,24 @@ class MResumePoint : public MNode
|
||||
Mode mode_;
|
||||
|
||||
MResumePoint(MBasicBlock *block, jsbytecode *pc, MResumePoint *parent, Mode mode);
|
||||
bool init(MBasicBlock *state);
|
||||
void inherit(MBasicBlock *state);
|
||||
|
||||
protected:
|
||||
// Initializes operands_ to an empty array of a fixed length.
|
||||
// The array may then be filled in by inherit().
|
||||
bool init() {
|
||||
return operands_.init(stackDepth_);
|
||||
}
|
||||
|
||||
// Overwrites an operand without updating its Uses.
|
||||
void setOperand(size_t index, MDefinition *operand) {
|
||||
JS_ASSERT(index < stackDepth_);
|
||||
operands_[index] = operand;
|
||||
operands_[index].set(operand, this, index);
|
||||
operand->addUse(&operands_[index]);
|
||||
}
|
||||
|
||||
MUse *getUseFor(size_t index) {
|
||||
return &operands_[index];
|
||||
}
|
||||
|
||||
public:
|
||||
@ -6052,7 +6127,7 @@ class MResumePoint : public MNode
|
||||
}
|
||||
MDefinition *getOperand(size_t index) const {
|
||||
JS_ASSERT(index < stackDepth_);
|
||||
return operands_[index];
|
||||
return operands_[index].producer();
|
||||
}
|
||||
jsbytecode *pc() const {
|
||||
return pc_;
|
||||
@ -6151,11 +6226,6 @@ MInstruction *MDefinition::toInstruction()
|
||||
return (MInstruction *)this;
|
||||
}
|
||||
|
||||
void MNode::initOperand(size_t index, MDefinition *ins)
|
||||
{
|
||||
setOperand(index, ins);
|
||||
ins->addUse(this, index);
|
||||
}
|
||||
static inline bool isOSRLikeValue (MDefinition *def) {
|
||||
if (def->isOsrValue())
|
||||
return true;
|
||||
|
@ -194,7 +194,7 @@ MBasicBlock::inherit(MBasicBlock *pred, uint32_t popped)
|
||||
|
||||
// Create a resume point using our initial stack state.
|
||||
entryResumePoint_ = new MResumePoint(this, pc(), callerResumePoint, MResumePoint::ResumeAt);
|
||||
if (!entryResumePoint_->init(this))
|
||||
if (!entryResumePoint_->init())
|
||||
return false;
|
||||
|
||||
if (pred) {
|
||||
@ -204,15 +204,16 @@ MBasicBlock::inherit(MBasicBlock *pred, uint32_t popped)
|
||||
if (kind_ == PENDING_LOOP_HEADER) {
|
||||
for (size_t i = 0; i < stackDepth(); i++) {
|
||||
MPhi *phi = MPhi::New(i);
|
||||
if (!phi->addInput(pred->getSlot(i)))
|
||||
if (!phi->initLength(1))
|
||||
return false;
|
||||
phi->setOperand(0, pred->getSlot(i));
|
||||
addPhi(phi);
|
||||
setSlot(i, phi);
|
||||
entryResumePoint()->initOperand(i, phi);
|
||||
entryResumePoint()->setOperand(i, phi);
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < stackDepth(); i++)
|
||||
entryResumePoint()->initOperand(i, getSlot(i));
|
||||
entryResumePoint()->setOperand(i, getSlot(i));
|
||||
}
|
||||
}
|
||||
|
||||
@ -265,7 +266,7 @@ void
|
||||
MBasicBlock::initSlot(uint32_t slot, MDefinition *ins)
|
||||
{
|
||||
slots_[slot] = ins;
|
||||
entryResumePoint()->initOperand(slot, ins);
|
||||
entryResumePoint()->setOperand(slot, ins);
|
||||
}
|
||||
|
||||
void
|
||||
@ -464,11 +465,22 @@ MBasicBlock::moveBefore(MInstruction *at, MInstruction *ins)
|
||||
at->block()->insertBefore(at, ins);
|
||||
}
|
||||
|
||||
static inline void
|
||||
AssertSafelyDiscardable(MDefinition *def)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// Instructions captured by resume points cannot be safely discarded, since
|
||||
// they are necessary for interpreter frame reconstruction in case of bailout.
|
||||
JS_ASSERT(def->useCount() == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
MBasicBlock::discard(MInstruction *ins)
|
||||
{
|
||||
AssertSafelyDiscardable(ins);
|
||||
for (size_t i = 0; i < ins->numOperands(); i++)
|
||||
ins->replaceOperand(i, NULL);
|
||||
ins->discardOperand(i);
|
||||
|
||||
instructions_.remove(ins);
|
||||
}
|
||||
@ -476,8 +488,9 @@ MBasicBlock::discard(MInstruction *ins)
|
||||
MInstructionIterator
|
||||
MBasicBlock::discardAt(MInstructionIterator &iter)
|
||||
{
|
||||
AssertSafelyDiscardable(*iter);
|
||||
for (size_t i = 0; i < iter->numOperands(); i++)
|
||||
iter->replaceOperand(i, NULL);
|
||||
iter->discardOperand(i);
|
||||
|
||||
return instructions_.removeAt(iter);
|
||||
}
|
||||
@ -485,8 +498,9 @@ MBasicBlock::discardAt(MInstructionIterator &iter)
|
||||
MInstructionReverseIterator
|
||||
MBasicBlock::discardAt(MInstructionReverseIterator &iter)
|
||||
{
|
||||
AssertSafelyDiscardable(*iter);
|
||||
for (size_t i = 0; i < iter->numOperands(); i++)
|
||||
iter->replaceOperand(i, NULL);
|
||||
iter->discardOperand(i);
|
||||
|
||||
return instructions_.removeAt(iter);
|
||||
}
|
||||
@ -555,7 +569,7 @@ MBasicBlock::discardPhiAt(MPhiIterator &at)
|
||||
JS_ASSERT(!phis_.empty());
|
||||
|
||||
for (size_t i = 0; i < at->numOperands(); i++)
|
||||
at->replaceOperand(i, NULL);
|
||||
at->discardOperand(i);
|
||||
|
||||
MPhiIterator result = phis_.removeAt(at);
|
||||
|
||||
@ -587,33 +601,32 @@ MBasicBlock::addPredecessorPopN(MBasicBlock *pred, uint32_t popped)
|
||||
MDefinition *other = pred->getSlot(i);
|
||||
|
||||
if (mine != other) {
|
||||
MPhi *phi;
|
||||
|
||||
// If the current instruction is a phi, and it was created in this
|
||||
// basic block, then we have already placed this phi and should
|
||||
// instead append to its operands.
|
||||
if (mine->isPhi() && mine->block() == this) {
|
||||
JS_ASSERT(predecessors_.length());
|
||||
phi = mine->toPhi();
|
||||
if (!mine->toPhi()->addInputSlow(other))
|
||||
return false;
|
||||
} else {
|
||||
// Otherwise, create a new phi node.
|
||||
phi = MPhi::New(i);
|
||||
MPhi *phi = MPhi::New(i);
|
||||
addPhi(phi);
|
||||
|
||||
// Prime the phi for each predecessor, so input(x) comes from
|
||||
// predecessor(x).
|
||||
if (!phi->initLength(predecessors_.length() + 1))
|
||||
return false;
|
||||
|
||||
for (size_t j = 0; j < predecessors_.length(); j++) {
|
||||
JS_ASSERT(predecessors_[j]->getSlot(i) == mine);
|
||||
if (!phi->addInput(mine))
|
||||
return false;
|
||||
phi->setOperand(j, mine);
|
||||
}
|
||||
phi->setOperand(predecessors_.length(), other);
|
||||
|
||||
setSlot(i, phi);
|
||||
entryResumePoint()->replaceOperand(i, phi);
|
||||
}
|
||||
|
||||
if (!phi->addInput(other))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -639,8 +652,8 @@ MBasicBlock::assertUsesAreNotWithin(MUseIterator use, MUseIterator end)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
for (; use != end; use++) {
|
||||
JS_ASSERT_IF(use->node()->isDefinition(),
|
||||
use->node()->toDefinition()->block()->id() < id());
|
||||
JS_ASSERT_IF(use->consumer()->isDefinition(),
|
||||
use->consumer()->toDefinition()->block()->id() < id());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -683,7 +696,7 @@ MBasicBlock::setBackedge(MBasicBlock *pred)
|
||||
exitDef = entryDef->getOperand(0);
|
||||
}
|
||||
|
||||
if (!entryDef->addInput(exitDef))
|
||||
if (!entryDef->addInputSlow(exitDef))
|
||||
return false;
|
||||
|
||||
JS_ASSERT(entryDef->slot() < pred->stackDepth());
|
||||
|
@ -83,7 +83,7 @@ RangeAnalysis::RangeAnalysis(MIRGraph &graph)
|
||||
static bool
|
||||
IsDominatedUse(MBasicBlock *block, MUse *use)
|
||||
{
|
||||
MNode *n = use->node();
|
||||
MNode *n = use->consumer();
|
||||
bool isPhi = n->isDefinition() && n->toDefinition()->isPhi();
|
||||
|
||||
if (isPhi)
|
||||
@ -110,8 +110,8 @@ RangeAnalysis::replaceDominatedUsesWith(MDefinition *orig, MDefinition *dom,
|
||||
MBasicBlock *block)
|
||||
{
|
||||
for (MUseIterator i(orig->usesBegin()); i != orig->usesEnd(); ) {
|
||||
if (i->node() != dom && IsDominatedUse(block, *i))
|
||||
i = i->node()->replaceOperand(i, dom);
|
||||
if (i->consumer() != dom && IsDominatedUse(block, *i))
|
||||
i = i->consumer()->replaceOperand(i, dom);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ void
|
||||
UnreachableCodeElimination::removeUsesFromUnmarkedBlocks(MDefinition *instr)
|
||||
{
|
||||
for (MUseIterator iter(instr->usesBegin()); iter != instr->usesEnd(); ) {
|
||||
if (!iter->node()->block()->isMarked())
|
||||
if (!iter->consumer()->block()->isMarked())
|
||||
iter = instr->removeUse(iter);
|
||||
else
|
||||
iter++;
|
||||
|
Loading…
Reference in New Issue
Block a user