js/src/jit/MoveResolver.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_MoveResolver_h
     8 #define jit_MoveResolver_h
    10 #include "jit/InlineList.h"
    11 #include "jit/IonAllocPolicy.h"
    12 #include "jit/Registers.h"
    14 namespace js {
    15 namespace jit {
    17 // This is similar to Operand, but carries more information. We're also not
    18 // guaranteed that Operand looks like this on all ISAs.
    19 class MoveOperand
    20 {
    21   public:
    22     enum Kind {
    23         // A register in the "integer", aka "general purpose", class.
    24         REG,
    25         // A register in the "float" register class.
    26         FLOAT_REG,
    27         // A memory region.
    28         MEMORY,
    29         // The address of a memory region.
    30         EFFECTIVE_ADDRESS
    31     };
    33   private:
    34     Kind kind_;
    35     uint32_t code_;
    36     int32_t disp_;
    38   public:
    39     MoveOperand()
    40     { }
    41     explicit MoveOperand(const Register &reg) : kind_(REG), code_(reg.code())
    42     { }
    43     explicit MoveOperand(const FloatRegister &reg) : kind_(FLOAT_REG), code_(reg.code())
    44     { }
    45     MoveOperand(const Register &reg, int32_t disp, Kind kind = MEMORY)
    46         : kind_(kind),
    47         code_(reg.code()),
    48         disp_(disp)
    49     {
    50         JS_ASSERT(isMemoryOrEffectiveAddress());
    52         // With a zero offset, this is a plain reg-to-reg move.
    53         if (disp == 0 && kind_ == EFFECTIVE_ADDRESS)
    54             kind_ = REG;
    55     }
    56     MoveOperand(const MoveOperand &other)
    57       : kind_(other.kind_),
    58         code_(other.code_),
    59         disp_(other.disp_)
    60     { }
    61     bool isFloatReg() const {
    62         return kind_ == FLOAT_REG;
    63     }
    64     bool isGeneralReg() const {
    65         return kind_ == REG;
    66     }
    67     bool isMemory() const {
    68         return kind_ == MEMORY;
    69     }
    70     bool isEffectiveAddress() const {
    71         return kind_ == EFFECTIVE_ADDRESS;
    72     }
    73     bool isMemoryOrEffectiveAddress() const {
    74         return isMemory() || isEffectiveAddress();
    75     }
    76     Register reg() const {
    77         JS_ASSERT(isGeneralReg());
    78         return Register::FromCode(code_);
    79     }
    80     FloatRegister floatReg() const {
    81         JS_ASSERT(isFloatReg());
    82         return FloatRegister::FromCode(code_);
    83     }
    84     Register base() const {
    85         JS_ASSERT(isMemoryOrEffectiveAddress());
    86         return Register::FromCode(code_);
    87     }
    88     int32_t disp() const {
    89         JS_ASSERT(isMemoryOrEffectiveAddress());
    90         return disp_;
    91     }
    93     bool operator ==(const MoveOperand &other) const {
    94         if (kind_ != other.kind_)
    95             return false;
    96         if (code_ != other.code_)
    97             return false;
    98         if (isMemoryOrEffectiveAddress())
    99             return disp_ == other.disp_;
   100         return true;
   101     }
   102     bool operator !=(const MoveOperand &other) const {
   103         return !operator==(other);
   104     }
   105 };
   107 // This represents a move operation.
   108 class MoveOp
   109 {
   110   protected:
   111     MoveOperand from_;
   112     MoveOperand to_;
   113     bool cycleBegin_;
   114     bool cycleEnd_;
   116   public:
   117     enum Type {
   118         GENERAL,
   119         INT32,
   120         FLOAT32,
   121         DOUBLE
   122     };
   124   protected:
   125     Type type_;
   127     // If cycleBegin_ is true, endCycleType_ is the type of the move at the end
   128     // of the cycle. For example, given these moves:
   129     //       INT32 move a -> b
   130     //     GENERAL move b -> a
   131     // the move resolver starts by copying b into a temporary location, so that
   132     // the last move can read it. This copy needs to use use type GENERAL.
   133     Type endCycleType_;
   135   public:
   136     MoveOp()
   137     { }
   138     MoveOp(const MoveOperand &from, const MoveOperand &to, Type type)
   139       : from_(from),
   140         to_(to),
   141         cycleBegin_(false),
   142         cycleEnd_(false),
   143         type_(type)
   144     { }
   146     bool isCycleBegin() const {
   147         return cycleBegin_;
   148     }
   149     bool isCycleEnd() const {
   150         return cycleEnd_;
   151     }
   152     const MoveOperand &from() const {
   153         return from_;
   154     }
   155     const MoveOperand &to() const {
   156         return to_;
   157     }
   158     Type type() const {
   159         return type_;
   160     }
   161     Type endCycleType() const {
   162         JS_ASSERT(isCycleBegin());
   163         return endCycleType_;
   164     }
   165 };
   167 class MoveResolver
   168 {
   169   private:
   170     struct PendingMove
   171       : public MoveOp,
   172         public TempObject,
   173         public InlineListNode<PendingMove>
   174     {
   175         PendingMove()
   176         { }
   177         PendingMove(const MoveOperand &from, const MoveOperand &to, Type type)
   178           : MoveOp(from, to, type)
   179         { }
   181         void setCycleBegin(Type endCycleType) {
   182             JS_ASSERT(!isCycleBegin() && !isCycleEnd());
   183             cycleBegin_ = true;
   184             endCycleType_ = endCycleType;
   185         }
   186         void setCycleEnd() {
   187             JS_ASSERT(!isCycleBegin() && !isCycleEnd());
   188             cycleEnd_ = true;
   189         }
   190     };
   192     typedef InlineList<MoveResolver::PendingMove>::iterator PendingMoveIterator;
   194   private:
   195     // Moves that are definitely unblocked (constants to registers). These are
   196     // emitted last.
   197     js::Vector<MoveOp, 16, SystemAllocPolicy> orderedMoves_;
   198     bool hasCycles_;
   200     TempObjectPool<PendingMove> movePool_;
   202     InlineList<PendingMove> pending_;
   204     PendingMove *findBlockingMove(const PendingMove *last);
   206     // Internal reset function. Does not clear lists.
   207     void resetState();
   209   public:
   210     MoveResolver();
   212     // Resolves a move group into two lists of ordered moves. These moves must
   213     // be executed in the order provided. Some moves may indicate that they
   214     // participate in a cycle. For every cycle there are two such moves, and it
   215     // is guaranteed that cycles do not nest inside each other in the list.
   216     //
   217     // After calling addMove() for each parallel move, resolve() performs the
   218     // cycle resolution algorithm. Calling addMove() again resets the resolver.
   219     bool addMove(const MoveOperand &from, const MoveOperand &to, MoveOp::Type type);
   220     bool resolve();
   222     size_t numMoves() const {
   223         return orderedMoves_.length();
   224     }
   225     const MoveOp &getMove(size_t i) const {
   226         return orderedMoves_[i];
   227     }
   228     bool hasCycles() const {
   229         return hasCycles_;
   230     }
   231     void clearTempObjectPool() {
   232         movePool_.clear();
   233     }
   234     void setAllocator(TempAllocator &alloc) {
   235         movePool_.setAllocator(alloc);
   236     }
   237 };
   239 } // namespace jit
   240 } // namespace js
   242 #endif /* jit_MoveResolver_h */

mercurial