bug 760642: Speed improvements for IonAssemblerBuffer (r=jbramley)
authorMarty Rosenberg <mrosenberg@mozilla.com>
Thu, 27 Jun 2013 16:51:09 -0400
changeset 136732 379e3345913f6c21aad397efcf4ec2ac464fb95e
parent 136731 632e3a94bd224ecd178f9e7f4a2249828a26087e
child 136733 ee1918b17e986d41bc9fd082e9fc561c8492e55b
push id30241
push uservladimir@pobox.com
push dateThu, 27 Jun 2013 23:03:59 +0000
treeherdermozilla-inbound@ee1918b17e98 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjbramley
bugs760642
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 760642: Speed improvements for IonAssemblerBuffer (r=jbramley) * Use a doubly linked list rather than one list for keeping track of the chunks * Add a hueristic to determine whether we do lookups from the front of the list or the back
js/src/ion/shared/IonAssemblerBuffer.h
--- a/js/src/ion/shared/IonAssemblerBuffer.h
+++ b/js/src/ion/shared/IonAssemblerBuffer.h
@@ -46,31 +46,37 @@ class BufferOffset
     explicit BufferOffset(RepatchLabel *l) : offset(l->offset()) {
     }
 
     BufferOffset() : offset(INT_MIN) {}
     bool assigned() const { return offset != INT_MIN; };
 };
 
 template<int SliceSize>
-struct BufferSlice : public InlineForwardListNode<BufferSlice<SliceSize> > {
+struct BufferSlice {
   protected:
+    BufferSlice<SliceSize> *prev;
+    BufferSlice<SliceSize> *next;
     // How much data has been added to the current node.
     uint32_t nodeSize;
   public:
-    BufferSlice *getNext() { return static_cast<BufferSlice *>(this->next); }
+    BufferSlice *getNext() { return this->next; }
+    BufferSlice *getPrev() { return this->prev; }
     void setNext(BufferSlice<SliceSize> *next_) {
         JS_ASSERT(this->next == NULL);
+        JS_ASSERT(next_->prev == NULL);
         this->next = next_;
+        next_->prev = this;
     }
+
     uint8_t instructions [SliceSize];
     unsigned int size() {
         return nodeSize;
     }
-    BufferSlice() : InlineForwardListNode<BufferSlice<SliceSize> >(NULL), nodeSize(0) {}
+    BufferSlice() : next(NULL), prev(NULL), nodeSize(0) {}
     void putBlob(uint32_t instSize, uint8_t* inst) {
         if (inst != NULL)
             memcpy(&instructions[size()], inst, instSize);
         nodeSize += instSize;
     }
 };
 
 template<int SliceSize, class Inst>
@@ -158,29 +164,35 @@ struct AssemblerBuffer
         m_oom = true;
     }
     void fail_bail() {
         m_bail = true;
     }
     Inst *getInst(BufferOffset off) {
         unsigned int local_off = off.getOffset();
         Slice *cur = NULL;
-        if (local_off > bufferSize) {
-            local_off -= bufferSize;
-            cur = tail;
+        if (local_off > bufferSize / 2) {
+            unsigned int max_off = bufferSize;
+            for (cur = tail; cur != NULL; cur = cur->getPrev(), max_off -= cur->size()) {
+                if (local_off >= max_off) {
+                    local_off -= max_off;
+                    break;
+                }
+            }
         } else {
             for (cur = head; cur != NULL; cur = cur->getNext()) {
                 if (local_off < cur->size())
                     break;
                 local_off -= cur->size();
             }
             JS_ASSERT(cur != NULL);
         }
         // the offset within this node should not be larger than the node itself.
-        JS_ASSERT(local_off < cur->size());
+        // this check is now completely bogus since a slightly different algorithm is used.
+        // JS_ASSERT(local_off < cur->size());
         return (Inst*)&cur->instructions[local_off];
     }
     BufferOffset nextOffset() const {
         if (tail != NULL)
             return BufferOffset(bufferSize + tail->size());
         else
             return BufferOffset(bufferSize);
     }