Refactor iterator logic

This diff refactors some of the VM's logic for iterators (with a focus on
mutable iteration), delivering several improvements:
  1) MIterCtx was renamed to MArrayIter, and the m_key and m_val fields
     were eliminated.
  2) Eliminated the need for MArrayIter to dynamically allocate a
     MutableArrayIter object, and removed other layers of indirection as
     well.
  3) Reduced the size of HPHP::VM::Iter from 64 bytes down to 32 bytes.
  4) Removed the "if (siPastEnd())" check when adding a new element to an
     HphpArray or a ZendArray.
  5) Moved all of the iterator logic into a single .cpp file.

This diff reworks FullPos's to point to current element instead of pointing
to the next element. It also splits up the IterFree instruction into two
instructions (IterFree and MIterFree). These changes allowed various logic
to be simplified and data structures to be reduced in size. There is
definitely more opportunity for refactoring, but I know the JIT helpers for
iteration have been carefully tuned and so I'll leave further refactoring
for future diffs.

Finally, I spent a little time cleaning up the bytecode spec a bit, mostly
with respect to iteration.
Esse commit está contido em:
andrewparoski
2013-02-04 15:31:42 -08:00
commit de Sara Golemon
commit dec99505a6
41 arquivos alterados com 1518 adições e 1215 exclusões
+29 -20
Ver Arquivo
@@ -280,26 +280,26 @@ ArrayData *ArrayData::dequeue(Variant &value) {
// MutableArrayIter related functions
void ArrayData::newFullPos(FullPos &fp) {
assert(fp.container == NULL);
fp.container = this;
fp.next = strongIterators();
assert(fp.getContainer() == NULL);
fp.setContainer(this);
fp.setNext(strongIterators());
setStrongIterators(&fp);
getFullPos(fp);
}
void ArrayData::freeFullPos(FullPos &fp) {
assert(strongIterators() != 0 && fp.container == (ArrayData*)this);
// search for fp in our list, then remove it. Usually its the first one.
assert(strongIterators() != 0 && fp.getContainer() == (ArrayData*)this);
// search for fp in our list, then remove it. Usually its the first one.
FullPos* p = strongIterators();
if (p == &fp) {
setStrongIterators(p->next);
fp.container = NULL;
setStrongIterators(p->getNext());
fp.setContainer(NULL);
return;
}
for (; p->next; p = p->next) {
if (p->next == &fp) {
p->next = p->next->next;
fp.container = NULL;
for (; p->getNext(); p = p->getNext()) {
if (p->getNext() == &fp) {
p->setNext(p->getNext()->getNext());
fp.setContainer(NULL);
return;
}
}
@@ -308,26 +308,35 @@ void ArrayData::freeFullPos(FullPos &fp) {
assert(false);
}
void ArrayData::getFullPos(FullPos &fp) {
assert(fp.container == (ArrayData*)this);
fp.pos = ArrayData::invalid_index;
}
bool ArrayData::setFullPos(const FullPos &fp) {
assert(fp.container == (ArrayData*)this);
bool ArrayData::validFullPos(const FullPos& fp) const {
assert(fp.getContainer() == (ArrayData*)this);
return false;
}
void ArrayData::getFullPos(FullPos &fp) {
assert(fp.getContainer() == (ArrayData*)this);
fp.m_pos = ArrayData::invalid_index;
}
bool ArrayData::setFullPos(const FullPos &fp) {
assert(fp.getContainer() == (ArrayData*)this);
return false;
}
void ArrayData::nextForFullPos() {
next();
}
void ArrayData::freeStrongIterators() {
for (FullPosRange r(strongIterators()); !r.empty(); r.popFront()) {
r.front()->container = NULL;
r.front()->setContainer(NULL);
}
setStrongIterators(0);
}
void ArrayData::moveStrongIterators(ArrayData* dest, ArrayData* src) {
for (FullPosRange r(src->strongIterators()); !r.empty(); r.popFront()) {
r.front()->container = dest;
r.front()->setContainer(dest);
}
// move pointer to list and flag in one copy
dest->m_strongIterators = src->m_strongIterators;