js/src/jit/shared/IonAssemblerBuffer.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifndef jit_shared_IonAssemblerBuffer_h
     8 #define jit_shared_IonAssemblerBuffer_h
    10 // needed for the definition of Label :(
    11 #include "jit/shared/Assembler-shared.h"
    13 namespace js {
    14 namespace jit {
    16 // This should theoretically reside inside of AssemblerBuffer, but that won't be nice
    17 // AssemblerBuffer is templated, BufferOffset would be indirectly.
    18 // A BufferOffset is the offset into a buffer, expressed in bytes of instructions.
    20 class BufferOffset
    21 {
    22     int offset;
    23   public:
    24     friend BufferOffset nextOffset();
    25     explicit BufferOffset(int offset_) : offset(offset_) {}
    26     // Return the offset as a raw integer.
    27     int getOffset() const { return offset; }
    29     // A BOffImm is a Branch Offset Immediate. It is an architecture-specific
    30     // structure that holds the immediate for a pc relative branch.
    31     // diffB takes the label for the destination of the branch, and encodes
    32     // the immediate for the branch.  This will need to be fixed up later, since
    33     // A pool may be inserted between the branch and its destination
    34     template <class BOffImm>
    35     BOffImm diffB(BufferOffset other) const {
    36         return BOffImm(offset - other.offset);
    37     }
    39     template <class BOffImm>
    40     BOffImm diffB(Label *other) const {
    41         JS_ASSERT(other->bound());
    42         return BOffImm(offset - other->offset());
    43     }
    45     explicit BufferOffset(Label *l) : offset(l->offset()) {
    46     }
    47     explicit BufferOffset(RepatchLabel *l) : offset(l->offset()) {
    48     }
    50     BufferOffset() : offset(INT_MIN) {}
    51     bool assigned() const { return offset != INT_MIN; };
    52 };
    54 template<int SliceSize>
    55 struct BufferSlice {
    56   protected:
    57     BufferSlice<SliceSize> *prev;
    58     BufferSlice<SliceSize> *next;
    59     // How much data has been added to the current node.
    60     uint32_t nodeSize;
    61   public:
    62     BufferSlice *getNext() { return this->next; }
    63     BufferSlice *getPrev() { return this->prev; }
    64     void setNext(BufferSlice<SliceSize> *next_) {
    65         JS_ASSERT(this->next == nullptr);
    66         JS_ASSERT(next_->prev == nullptr);
    67         this->next = next_;
    68         next_->prev = this;
    69     }
    71     mozilla::Array<uint8_t, SliceSize> instructions;
    72     unsigned int size() {
    73         return nodeSize;
    74     }
    75     BufferSlice() : prev(nullptr), next(nullptr), nodeSize(0) {}
    76     void putBlob(uint32_t instSize, uint8_t* inst) {
    77         if (inst != nullptr)
    78             memcpy(&instructions[size()], inst, instSize);
    79         nodeSize += instSize;
    80     }
    81 };
    83 template<int SliceSize, class Inst>
    84 struct AssemblerBuffer
    85 {
    86   public:
    87     AssemblerBuffer() : head(nullptr), tail(nullptr), m_oom(false), m_bail(false), bufferSize(0), LifoAlloc_(8192) {}
    88   protected:
    89     typedef BufferSlice<SliceSize> Slice;
    90     typedef AssemblerBuffer<SliceSize, Inst> AssemblerBuffer_;
    91     Slice *head;
    92     Slice *tail;
    93   public:
    94     bool m_oom;
    95     bool m_bail;
    96     // How much data has been added to the buffer thusfar.
    97     uint32_t bufferSize;
    98     uint32_t lastInstSize;
    99     bool isAligned(int alignment) const {
   100         // make sure the requested alignment is a power of two.
   101         JS_ASSERT((alignment & (alignment-1)) == 0);
   102         return !(size() & (alignment - 1));
   103     }
   104     virtual Slice *newSlice(LifoAlloc &a) {
   105         Slice *tmp = static_cast<Slice*>(a.alloc(sizeof(Slice)));
   106         if (!tmp) {
   107             m_oom = true;
   108             return nullptr;
   109         }
   110         new (tmp) Slice;
   111         return tmp;
   112     }
   113     bool ensureSpace(int size) {
   114         if (tail != nullptr && tail->size()+size <= SliceSize)
   115             return true;
   116         Slice *tmp = newSlice(LifoAlloc_);
   117         if (tmp == nullptr)
   118             return false;
   119         if (tail != nullptr) {
   120             bufferSize += tail->size();
   121             tail->setNext(tmp);
   122         }
   123         tail = tmp;
   124         if (head == nullptr) {
   125             finger = tmp;
   126             finger_offset = 0;
   127             head = tmp;
   128         }
   129         return true;
   130     }
   132     BufferOffset putByte(uint8_t value) {
   133         return putBlob(sizeof(value), (uint8_t*)&value);
   134     }
   136     BufferOffset putShort(uint16_t value) {
   137         return putBlob(sizeof(value), (uint8_t*)&value);
   138     }
   140     BufferOffset putInt(uint32_t value) {
   141         return putBlob(sizeof(value), (uint8_t*)&value);
   142     }
   143     BufferOffset putBlob(uint32_t instSize, uint8_t *inst) {
   144         if (!ensureSpace(instSize))
   145             return BufferOffset();
   146         BufferOffset ret = nextOffset();
   147         tail->putBlob(instSize, inst);
   148         return ret;
   149     }
   150     unsigned int size() const {
   151         int executableSize;
   152         if (tail != nullptr)
   153             executableSize = bufferSize + tail->size();
   154         else
   155             executableSize = bufferSize;
   156         return executableSize;
   157     }
   158     unsigned int uncheckedSize() const {
   159         return size();
   160     }
   161     bool oom() const {
   162         return m_oom || m_bail;
   163     }
   164     bool bail() const {
   165         return m_bail;
   166     }
   167     void fail_oom() {
   168         m_oom = true;
   169     }
   170     void fail_bail() {
   171         m_bail = true;
   172     }
   173     // finger for speeding up accesses
   174     Slice *finger;
   175     unsigned int finger_offset;
   176     Inst *getInst(BufferOffset off) {
   177         int local_off = off.getOffset();
   178         // don't update the structure's finger in place, so there is the option
   179         // to not update it.
   180         Slice *cur = nullptr;
   181         int cur_off;
   182         // get the offset that we'd be dealing with by walking through backwards
   183         int end_off = bufferSize - local_off;
   184         // If end_off is negative, then it is in the last chunk, and there is no
   185         // real work to be done.
   186         if (end_off <= 0) {
   187             return (Inst*)&tail->instructions[-end_off];
   188         }
   189         bool used_finger = false;
   190         int finger_off = abs((int)(local_off - finger_offset));
   191         if (finger_off < Min(local_off, end_off)) {
   192             // The finger offset is minimal, use the finger.
   193             cur = finger;
   194             cur_off = finger_offset;
   195             used_finger = true;
   196         } else if (local_off < end_off) {
   197             // it is closest to the start
   198             cur = head;
   199             cur_off = 0;
   200         } else {
   201             // it is closest to the end
   202             cur = tail;
   203             cur_off = bufferSize;
   204         }
   205         int count = 0;
   206         if (local_off < cur_off) {
   207             for (; cur != nullptr; cur = cur->getPrev(), cur_off -= cur->size()) {
   208                 if (local_off >= cur_off) {
   209                     local_off -= cur_off;
   210                     break;
   211                 }
   212                 count++;
   213             }
   214             JS_ASSERT(cur != nullptr);
   215         } else {
   216             for (; cur != nullptr; cur = cur->getNext()) {
   217                 int cur_size = cur->size();
   218                 if (local_off < cur_off + cur_size) {
   219                     local_off -= cur_off;
   220                     break;
   221                 }
   222                 cur_off += cur_size;
   223                 count++;
   224             }
   225             JS_ASSERT(cur != nullptr);
   226         }
   227         if (count > 2 || used_finger) {
   228             finger = cur;
   229             finger_offset = cur_off;
   230         }
   231         // the offset within this node should not be larger than the node itself.
   232         JS_ASSERT(local_off < (int)cur->size());
   233         return (Inst*)&cur->instructions[local_off];
   234     }
   235     BufferOffset nextOffset() const {
   236         if (tail != nullptr)
   237             return BufferOffset(bufferSize + tail->size());
   238         else
   239             return BufferOffset(bufferSize);
   240     }
   241     BufferOffset prevOffset() const {
   242         MOZ_ASSUME_UNREACHABLE("Don't current record lastInstSize");
   243     }
   245     // Break the instruction stream so we can go back and edit it at this point
   246     void perforate() {
   247         Slice *tmp = newSlice(LifoAlloc_);
   248         if (!tmp)
   249             m_oom = true;
   250         bufferSize += tail->size();
   251         tail->setNext(tmp);
   252         tail = tmp;
   253     }
   255     class AssemblerBufferInstIterator {
   256       private:
   257         BufferOffset bo;
   258         AssemblerBuffer_ *m_buffer;
   259       public:
   260         AssemblerBufferInstIterator(BufferOffset off, AssemblerBuffer_ *buff) : bo(off), m_buffer(buff) {}
   261         Inst *next() {
   262             Inst *i = m_buffer->getInst(bo);
   263             bo = BufferOffset(bo.getOffset()+i->size());
   264             return cur();
   265         };
   266         Inst *cur() {
   267             return m_buffer->getInst(bo);
   268         }
   269     };
   270   public:
   271     LifoAlloc LifoAlloc_;
   272 };
   274 } // ion
   275 } // js
   276 #endif /* jit_shared_IonAssemblerBuffer_h */

mercurial