js/src/jit/MoveResolver.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial