mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1077720 - IonMonkey: Optimize MPhi's addInput and addInputSlow r=nbp
This commit is contained in:
parent
eaa509d20f
commit
f044bd49a6
@ -78,6 +78,13 @@ class FixedList
|
||||
MOZ_ASSERT(index < length_);
|
||||
return list_[index];
|
||||
}
|
||||
|
||||
T *begin() {
|
||||
return list_;
|
||||
}
|
||||
T *end() {
|
||||
return list_ + length_;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace jit
|
||||
|
@ -211,7 +211,26 @@ class InlineListNode : public InlineForwardListNode<T>
|
||||
prev(p)
|
||||
{ }
|
||||
|
||||
// Move constructor. Nodes may be moved without being removed from their
|
||||
// containing lists. For example, this allows list nodes to be safely
|
||||
// stored in a resizable Vector -- when the Vector resizes, the new storage
|
||||
// is initialized by this move constructor. |other| is a reference to the
|
||||
// old node which the |this| node here is replacing.
|
||||
InlineListNode(InlineListNode<T> &&other)
|
||||
: InlineForwardListNode<T>(other.next)
|
||||
{
|
||||
InlineListNode<T> *newNext = static_cast<InlineListNode<T> *>(other.next);
|
||||
InlineListNode<T> *newPrev = other.prev;
|
||||
prev = newPrev;
|
||||
|
||||
// Update the pointers in the adjacent nodes to point to this node's new
|
||||
// location.
|
||||
newNext->prev = this;
|
||||
newPrev->next = this;
|
||||
}
|
||||
|
||||
InlineListNode(const InlineListNode<T> &) MOZ_DELETE;
|
||||
void operator=(const InlineListNode<T> &) MOZ_DELETE;
|
||||
|
||||
protected:
|
||||
friend class InlineList<T>;
|
||||
|
@ -1361,19 +1361,6 @@ MPhi::congruentTo(const MDefinition *ins) const
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
bool
|
||||
MPhi::reserveLength(size_t length)
|
||||
{
|
||||
// Initializes a new MPhi to have an Operand vector of at least the given
|
||||
// capacity. This permits use of addInput() instead of addInputSlow(), the
|
||||
// latter of which may call pod_realloc().
|
||||
MOZ_ASSERT(numOperands() == 0);
|
||||
#if DEBUG
|
||||
capacity_ = length;
|
||||
#endif
|
||||
return inputs_.reserve(length);
|
||||
}
|
||||
|
||||
static inline types::TemporaryTypeSet *
|
||||
MakeMIRTypeSet(MIRType type)
|
||||
{
|
||||
@ -1502,65 +1489,20 @@ MPhi::typeIncludes(MDefinition *def)
|
||||
return this->mightBeType(def->type());
|
||||
}
|
||||
|
||||
void
|
||||
MPhi::addInput(MDefinition *ins)
|
||||
{
|
||||
// This can only been done if the length was reserved through reserveLength,
|
||||
// else the slower addInputSlow need to get called.
|
||||
MOZ_ASSERT(inputs_.length() < capacity_);
|
||||
|
||||
inputs_.append(MUse());
|
||||
inputs_.back().init(ins, this);
|
||||
}
|
||||
|
||||
bool
|
||||
MPhi::addInputSlow(MDefinition *ins, bool *ptypeChange)
|
||||
MPhi::checkForTypeChange(MDefinition *ins, bool *ptypeChange)
|
||||
{
|
||||
// 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);
|
||||
MIRType resultType = this->type();
|
||||
types::TemporaryTypeSet *resultTypeSet = this->resultTypeSet();
|
||||
|
||||
// Remove all MUses from all use lists, in case pod_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()))
|
||||
if (!MergeTypes(&resultType, &resultTypeSet, ins->type(), ins->resultTypeSet()))
|
||||
return false;
|
||||
|
||||
inputs_.back().init(ins, this);
|
||||
|
||||
if (ptypeChange) {
|
||||
MIRType resultType = this->type();
|
||||
types::TemporaryTypeSet *resultTypeSet = this->resultTypeSet();
|
||||
|
||||
if (!MergeTypes(&resultType, &resultTypeSet, ins->type(), ins->resultTypeSet()))
|
||||
return false;
|
||||
|
||||
if (resultType != this->type() || resultTypeSet != this->resultTypeSet()) {
|
||||
*ptypeChange = true;
|
||||
setResultType(resultType);
|
||||
setResultTypeSet(resultTypeSet);
|
||||
}
|
||||
if (resultType != this->type() || resultTypeSet != this->resultTypeSet()) {
|
||||
*ptypeChange = true;
|
||||
setResultType(resultType);
|
||||
setResultTypeSet(resultTypeSet);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -127,11 +127,6 @@ class MUse : public TempObject, public InlineListNode<MUse>
|
||||
MDefinition *producer_; // MDefinition that is being used.
|
||||
MNode *consumer_; // The node that is using this operand.
|
||||
|
||||
MUse(MDefinition *producer, MNode *consumer)
|
||||
: producer_(producer),
|
||||
consumer_(consumer)
|
||||
{ }
|
||||
|
||||
// Low-level unchecked edit method for replaceAllUsesWith and
|
||||
// MPhi::removeOperand. This doesn't update use lists!
|
||||
// replaceAllUsesWith and MPhi::removeOperand do that manually.
|
||||
@ -148,11 +143,17 @@ class MUse : public TempObject, public InlineListNode<MUse>
|
||||
: producer_(nullptr), consumer_(nullptr)
|
||||
{ }
|
||||
|
||||
// MUses can only be copied when they are not in a use list.
|
||||
explicit MUse(const MUse &other)
|
||||
: producer_(other.producer_), consumer_(other.consumer_)
|
||||
// Move constructor for use in vectors. When an MUse is moved, it stays
|
||||
// in its containing use list.
|
||||
MUse(MUse &&other)
|
||||
: InlineListNode<MUse>(mozilla::Move(other)),
|
||||
producer_(other.producer_), consumer_(other.consumer_)
|
||||
{ }
|
||||
|
||||
// Construct an MUse initialized with |producer| and |consumer|.
|
||||
MUse(MDefinition *producer, MNode *consumer)
|
||||
{
|
||||
MOZ_ASSERT(!other.next && !other.prev);
|
||||
initUnchecked(producer, consumer);
|
||||
}
|
||||
|
||||
// Set this use, which was previously clear.
|
||||
@ -5904,7 +5905,6 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineListNode<MPhi>
|
||||
|
||||
#if DEBUG
|
||||
bool specialized_;
|
||||
uint32_t capacity_;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@ -5933,7 +5933,6 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineListNode<MPhi>
|
||||
canConsumeFloat32_(false)
|
||||
#if DEBUG
|
||||
, specialized_(false)
|
||||
, capacity_(0)
|
||||
#endif
|
||||
{
|
||||
setResultType(resultType);
|
||||
@ -6003,14 +6002,36 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineListNode<MPhi>
|
||||
|
||||
// Initializes the operands vector to the given capacity,
|
||||
// permitting use of addInput() instead of addInputSlow().
|
||||
bool reserveLength(size_t length);
|
||||
bool reserveLength(size_t length) {
|
||||
return inputs_.reserve(length);
|
||||
}
|
||||
|
||||
// Use only if capacity has been reserved by reserveLength
|
||||
void addInput(MDefinition *ins);
|
||||
void addInput(MDefinition *ins) {
|
||||
// Use infallibleGrowByUninitialized and placement-new instead of just
|
||||
// infallibleAppend to avoid creating a temporary MUse which will get
|
||||
// linked into |ins|'s use list and then unlinked in favor of the
|
||||
// MUse in the Vector. We'd ideally like to use an emplace method here,
|
||||
// once Vector supports that.
|
||||
inputs_.infallibleGrowByUninitialized(1);
|
||||
new (&inputs_.back()) MUse(ins, this);
|
||||
}
|
||||
|
||||
// Appends a new input to the input vector. May call pod_realloc().
|
||||
// Appends a new input to the input vector. May perform reallocation.
|
||||
// Prefer reserveLength() and addInput() instead, where possible.
|
||||
bool addInputSlow(MDefinition *ins, bool *ptypeChange = nullptr);
|
||||
bool addInputSlow(MDefinition *ins) {
|
||||
// Use growByUninitialized and placement-new instead of just append,
|
||||
// similar to what addInput does.
|
||||
if (!inputs_.growByUninitialized(1))
|
||||
return false;
|
||||
|
||||
new (&inputs_.back()) MUse(ins, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Update the type of this phi after adding |ins| as an input. Set
|
||||
// |*ptypeChange| to true if the type changed.
|
||||
bool checkForTypeChange(MDefinition *ins, bool *ptypeChange);
|
||||
|
||||
MDefinition *foldsTo(TempAllocator &alloc);
|
||||
MDefinition *foldsTernary();
|
||||
|
@ -335,7 +335,6 @@ MBasicBlock::NewAsmJS(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred, Kin
|
||||
MOZ_ASSERT(predSlot->type() != MIRType_Value);
|
||||
MPhi *phi = new(phis + i) MPhi(alloc, predSlot->type());
|
||||
|
||||
JS_ALWAYS_TRUE(phi->reserveLength(2));
|
||||
phi->addInput(predSlot);
|
||||
|
||||
// Add append Phis in the block.
|
||||
@ -407,8 +406,10 @@ MBasicBlock::copySlots(MBasicBlock *from)
|
||||
{
|
||||
MOZ_ASSERT(stackPosition_ <= from->stackPosition_);
|
||||
|
||||
for (uint32_t i = 0; i < stackPosition_; i++)
|
||||
slots_[i] = from->slots_[i];
|
||||
MDefinition **thisSlots = slots_.begin();
|
||||
MDefinition **fromSlots = from->slots_.begin();
|
||||
for (size_t i = 0, e = stackPosition_; i < e; ++i)
|
||||
thisSlots[i] = fromSlots[i];
|
||||
}
|
||||
|
||||
bool
|
||||
@ -447,8 +448,7 @@ MBasicBlock::inherit(TempAllocator &alloc, BytecodeAnalysis *analysis, MBasicBlo
|
||||
size_t i = 0;
|
||||
for (i = 0; i < info().firstStackSlot(); i++) {
|
||||
MPhi *phi = MPhi::New(alloc);
|
||||
if (!phi->addInputSlow(pred->getSlot(i)))
|
||||
return false;
|
||||
phi->addInput(pred->getSlot(i));
|
||||
addPhi(phi);
|
||||
setSlot(i, phi);
|
||||
entryResumePoint()->initOperand(i, phi);
|
||||
@ -468,8 +468,7 @@ MBasicBlock::inherit(TempAllocator &alloc, BytecodeAnalysis *analysis, MBasicBlo
|
||||
|
||||
for (; i < stackDepth(); i++) {
|
||||
MPhi *phi = MPhi::New(alloc);
|
||||
if (!phi->addInputSlow(pred->getSlot(i)))
|
||||
return false;
|
||||
phi->addInput(pred->getSlot(i));
|
||||
addPhi(phi);
|
||||
setSlot(i, phi);
|
||||
entryResumePoint()->initOperand(i, phi);
|
||||
@ -1025,7 +1024,7 @@ MBasicBlock::addPredecessorPopN(TempAllocator &alloc, MBasicBlock *pred, uint32_
|
||||
MOZ_ASSERT(pred->hasLastIns());
|
||||
MOZ_ASSERT(pred->stackPosition_ == stackPosition_ + popped);
|
||||
|
||||
for (uint32_t i = 0; i < stackPosition_; i++) {
|
||||
for (uint32_t i = 0, e = stackPosition_; i < e; ++i) {
|
||||
MDefinition *mine = getSlot(i);
|
||||
MDefinition *other = pred->getSlot(i);
|
||||
|
||||
@ -1051,7 +1050,7 @@ MBasicBlock::addPredecessorPopN(TempAllocator &alloc, MBasicBlock *pred, uint32_
|
||||
if (!phi->reserveLength(predecessors_.length() + 1))
|
||||
return false;
|
||||
|
||||
for (size_t j = 0; j < predecessors_.length(); j++) {
|
||||
for (size_t j = 0, numPreds = predecessors_.length(); j < numPreds; ++j) {
|
||||
MOZ_ASSERT(predecessors_[j]->getSlot(i) == mine);
|
||||
phi->addInput(mine);
|
||||
}
|
||||
@ -1197,7 +1196,7 @@ MBasicBlock::setBackedgeAsmJS(MBasicBlock *pred)
|
||||
exitDef = entryDef->getOperand(0);
|
||||
}
|
||||
|
||||
// MBasicBlock::NewAsmJS calls reserveLength(2) for loop header phis.
|
||||
// Phis always have room for 2 operands, so we can use addInput.
|
||||
entryDef->addInput(exitDef);
|
||||
|
||||
MOZ_ASSERT(slot < pred->stackDepth());
|
||||
@ -1436,9 +1435,10 @@ MBasicBlock::inheritPhisFromBackedge(MBasicBlock *backedge, bool *hadTypeChange)
|
||||
|
||||
bool typeChange = false;
|
||||
|
||||
if (!entryDef->addInputSlow(exitDef, &typeChange))
|
||||
if (!entryDef->addInputSlow(exitDef))
|
||||
return false;
|
||||
if (!entryDef->checkForTypeChange(exitDef, &typeChange))
|
||||
return false;
|
||||
|
||||
*hadTypeChange |= typeChange;
|
||||
setSlot(slot, entryDef);
|
||||
}
|
||||
|
@ -472,6 +472,7 @@ public:
|
||||
* -- leave them as uninitialized memory.
|
||||
*/
|
||||
bool growByUninitialized(size_t aIncr);
|
||||
void infallibleGrowByUninitialized(size_t aIncr);
|
||||
bool resizeUninitialized(size_t aNewLength);
|
||||
|
||||
/** Shorthand for shrinkBy(length()). */
|
||||
@ -879,6 +880,14 @@ VectorBase<T, N, AP, TV>::growByUninitialized(size_t aIncr)
|
||||
if (aIncr > mCapacity - mLength && !growStorageBy(aIncr)) {
|
||||
return false;
|
||||
}
|
||||
infallibleGrowByUninitialized(aIncr);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T, size_t N, class AP, class TV>
|
||||
MOZ_ALWAYS_INLINE void
|
||||
VectorBase<T, N, AP, TV>::infallibleGrowByUninitialized(size_t aIncr)
|
||||
{
|
||||
MOZ_ASSERT(mLength + aIncr <= mCapacity);
|
||||
mLength += aIncr;
|
||||
#ifdef DEBUG
|
||||
@ -886,7 +895,6 @@ VectorBase<T, N, AP, TV>::growByUninitialized(size_t aIncr)
|
||||
mReserved = mLength;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T, size_t N, class AP, class TV>
|
||||
|
Loading…
Reference in New Issue
Block a user