Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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_MIRGraph_h |
michael@0 | 8 | #define jit_MIRGraph_h |
michael@0 | 9 | |
michael@0 | 10 | // This file declares the data structures used to build a control-flow graph |
michael@0 | 11 | // containing MIR. |
michael@0 | 12 | |
michael@0 | 13 | #include "jit/FixedList.h" |
michael@0 | 14 | #include "jit/IonAllocPolicy.h" |
michael@0 | 15 | #include "jit/MIR.h" |
michael@0 | 16 | |
michael@0 | 17 | namespace js { |
michael@0 | 18 | namespace jit { |
michael@0 | 19 | |
michael@0 | 20 | class BytecodeAnalysis; |
michael@0 | 21 | class MBasicBlock; |
michael@0 | 22 | class MIRGraph; |
michael@0 | 23 | class MStart; |
michael@0 | 24 | |
michael@0 | 25 | class MDefinitionIterator; |
michael@0 | 26 | |
michael@0 | 27 | typedef InlineListIterator<MInstruction> MInstructionIterator; |
michael@0 | 28 | typedef InlineListReverseIterator<MInstruction> MInstructionReverseIterator; |
michael@0 | 29 | typedef InlineForwardListIterator<MPhi> MPhiIterator; |
michael@0 | 30 | typedef InlineForwardListIterator<MResumePoint> MResumePointIterator; |
michael@0 | 31 | |
michael@0 | 32 | class LBlock; |
michael@0 | 33 | |
michael@0 | 34 | class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock> |
michael@0 | 35 | { |
michael@0 | 36 | public: |
michael@0 | 37 | enum Kind { |
michael@0 | 38 | NORMAL, |
michael@0 | 39 | PENDING_LOOP_HEADER, |
michael@0 | 40 | LOOP_HEADER, |
michael@0 | 41 | SPLIT_EDGE, |
michael@0 | 42 | DEAD |
michael@0 | 43 | }; |
michael@0 | 44 | |
michael@0 | 45 | private: |
michael@0 | 46 | MBasicBlock(MIRGraph &graph, CompileInfo &info, jsbytecode *pc, Kind kind); |
michael@0 | 47 | bool init(); |
michael@0 | 48 | void copySlots(MBasicBlock *from); |
michael@0 | 49 | bool inherit(TempAllocator &alloc, BytecodeAnalysis *analysis, MBasicBlock *pred, |
michael@0 | 50 | uint32_t popped, unsigned stackPhiCount = 0); |
michael@0 | 51 | bool inheritResumePoint(MBasicBlock *pred); |
michael@0 | 52 | void assertUsesAreNotWithin(MUseIterator use, MUseIterator end); |
michael@0 | 53 | |
michael@0 | 54 | // This block cannot be reached by any means. |
michael@0 | 55 | bool unreachable_; |
michael@0 | 56 | |
michael@0 | 57 | // Pushes a copy of a local variable or argument. |
michael@0 | 58 | void pushVariable(uint32_t slot); |
michael@0 | 59 | |
michael@0 | 60 | // Sets a variable slot to the top of the stack, correctly creating copies |
michael@0 | 61 | // as needed. |
michael@0 | 62 | void setVariable(uint32_t slot); |
michael@0 | 63 | |
michael@0 | 64 | public: |
michael@0 | 65 | /////////////////////////////////////////////////////// |
michael@0 | 66 | ////////// BEGIN GRAPH BUILDING INSTRUCTIONS ////////// |
michael@0 | 67 | /////////////////////////////////////////////////////// |
michael@0 | 68 | |
michael@0 | 69 | // Creates a new basic block for a MIR generator. If |pred| is not nullptr, |
michael@0 | 70 | // its slots and stack depth are initialized from |pred|. |
michael@0 | 71 | static MBasicBlock *New(MIRGraph &graph, BytecodeAnalysis *analysis, CompileInfo &info, |
michael@0 | 72 | MBasicBlock *pred, jsbytecode *entryPc, Kind kind); |
michael@0 | 73 | static MBasicBlock *NewPopN(MIRGraph &graph, CompileInfo &info, |
michael@0 | 74 | MBasicBlock *pred, jsbytecode *entryPc, Kind kind, uint32_t popn); |
michael@0 | 75 | static MBasicBlock *NewWithResumePoint(MIRGraph &graph, CompileInfo &info, |
michael@0 | 76 | MBasicBlock *pred, jsbytecode *entryPc, |
michael@0 | 77 | MResumePoint *resumePoint); |
michael@0 | 78 | static MBasicBlock *NewPendingLoopHeader(MIRGraph &graph, CompileInfo &info, |
michael@0 | 79 | MBasicBlock *pred, jsbytecode *entryPc, |
michael@0 | 80 | unsigned loopStateSlots); |
michael@0 | 81 | static MBasicBlock *NewSplitEdge(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred); |
michael@0 | 82 | static MBasicBlock *NewAbortPar(MIRGraph &graph, CompileInfo &info, |
michael@0 | 83 | MBasicBlock *pred, jsbytecode *entryPc, |
michael@0 | 84 | MResumePoint *resumePoint); |
michael@0 | 85 | static MBasicBlock *NewAsmJS(MIRGraph &graph, CompileInfo &info, |
michael@0 | 86 | MBasicBlock *pred, Kind kind); |
michael@0 | 87 | |
michael@0 | 88 | bool dominates(const MBasicBlock *other) const; |
michael@0 | 89 | |
michael@0 | 90 | void setId(uint32_t id) { |
michael@0 | 91 | id_ = id; |
michael@0 | 92 | } |
michael@0 | 93 | |
michael@0 | 94 | // Mark the current block and all dominated blocks as unreachable. |
michael@0 | 95 | void setUnreachable(); |
michael@0 | 96 | bool unreachable() const { |
michael@0 | 97 | return unreachable_; |
michael@0 | 98 | } |
michael@0 | 99 | // Move the definition to the top of the stack. |
michael@0 | 100 | void pick(int32_t depth); |
michael@0 | 101 | |
michael@0 | 102 | // Exchange 2 stack slots at the defined depth |
michael@0 | 103 | void swapAt(int32_t depth); |
michael@0 | 104 | |
michael@0 | 105 | // Gets the instruction associated with various slot types. |
michael@0 | 106 | MDefinition *peek(int32_t depth); |
michael@0 | 107 | |
michael@0 | 108 | MDefinition *scopeChain(); |
michael@0 | 109 | MDefinition *argumentsObject(); |
michael@0 | 110 | |
michael@0 | 111 | // Increase the number of slots available |
michael@0 | 112 | bool increaseSlots(size_t num); |
michael@0 | 113 | bool ensureHasSlots(size_t num); |
michael@0 | 114 | |
michael@0 | 115 | // Initializes a slot value; must not be called for normal stack |
michael@0 | 116 | // operations, as it will not create new SSA names for copies. |
michael@0 | 117 | void initSlot(uint32_t index, MDefinition *ins); |
michael@0 | 118 | |
michael@0 | 119 | // Discard the slot at the given depth, lowering all slots above. |
michael@0 | 120 | void shimmySlots(int discardDepth); |
michael@0 | 121 | |
michael@0 | 122 | // In an OSR block, set all MOsrValues to use the MResumePoint attached to |
michael@0 | 123 | // the MStart. |
michael@0 | 124 | void linkOsrValues(MStart *start); |
michael@0 | 125 | |
michael@0 | 126 | // Sets the instruction associated with various slot types. The |
michael@0 | 127 | // instruction must lie at the top of the stack. |
michael@0 | 128 | void setLocal(uint32_t local); |
michael@0 | 129 | void setArg(uint32_t arg); |
michael@0 | 130 | void setSlot(uint32_t slot); |
michael@0 | 131 | void setSlot(uint32_t slot, MDefinition *ins); |
michael@0 | 132 | |
michael@0 | 133 | // Rewrites a slot directly, bypassing the stack transition. This should |
michael@0 | 134 | // not be used under most circumstances. |
michael@0 | 135 | void rewriteSlot(uint32_t slot, MDefinition *ins); |
michael@0 | 136 | |
michael@0 | 137 | // Rewrites a slot based on its depth (same as argument to peek()). |
michael@0 | 138 | void rewriteAtDepth(int32_t depth, MDefinition *ins); |
michael@0 | 139 | |
michael@0 | 140 | // Tracks an instruction as being pushed onto the operand stack. |
michael@0 | 141 | void push(MDefinition *ins); |
michael@0 | 142 | void pushArg(uint32_t arg); |
michael@0 | 143 | void pushLocal(uint32_t local); |
michael@0 | 144 | void pushSlot(uint32_t slot); |
michael@0 | 145 | void setScopeChain(MDefinition *ins); |
michael@0 | 146 | void setArgumentsObject(MDefinition *ins); |
michael@0 | 147 | |
michael@0 | 148 | // Returns the top of the stack, then decrements the virtual stack pointer. |
michael@0 | 149 | MDefinition *pop(); |
michael@0 | 150 | void popn(uint32_t n); |
michael@0 | 151 | |
michael@0 | 152 | // Adds an instruction to this block's instruction list. |ins| may be |
michael@0 | 153 | // nullptr to simplify OOM checking. |
michael@0 | 154 | void add(MInstruction *ins); |
michael@0 | 155 | |
michael@0 | 156 | // Marks the last instruction of the block; no further instructions |
michael@0 | 157 | // can be added. |
michael@0 | 158 | void end(MControlInstruction *ins); |
michael@0 | 159 | |
michael@0 | 160 | // Adds a phi instruction, but does not set successorWithPhis. |
michael@0 | 161 | void addPhi(MPhi *phi); |
michael@0 | 162 | |
michael@0 | 163 | // Adds a resume point to this block. |
michael@0 | 164 | void addResumePoint(MResumePoint *resume) { |
michael@0 | 165 | resumePoints_.pushFront(resume); |
michael@0 | 166 | } |
michael@0 | 167 | |
michael@0 | 168 | // Adds a predecessor. Every predecessor must have the same exit stack |
michael@0 | 169 | // depth as the entry state to this block. Adding a predecessor |
michael@0 | 170 | // automatically creates phi nodes and rewrites uses as needed. |
michael@0 | 171 | bool addPredecessor(TempAllocator &alloc, MBasicBlock *pred); |
michael@0 | 172 | bool addPredecessorPopN(TempAllocator &alloc, MBasicBlock *pred, uint32_t popped); |
michael@0 | 173 | |
michael@0 | 174 | // Stranger utilities used for inlining. |
michael@0 | 175 | bool addPredecessorWithoutPhis(MBasicBlock *pred); |
michael@0 | 176 | void inheritSlots(MBasicBlock *parent); |
michael@0 | 177 | bool initEntrySlots(TempAllocator &alloc); |
michael@0 | 178 | |
michael@0 | 179 | // Replaces an edge for a given block with a new block. This is |
michael@0 | 180 | // used for critical edge splitting and also for inserting |
michael@0 | 181 | // bailouts during ParallelSafetyAnalysis. |
michael@0 | 182 | // |
michael@0 | 183 | // Note: If successorWithPhis is set, you must not be replacing it. |
michael@0 | 184 | void replacePredecessor(MBasicBlock *old, MBasicBlock *split); |
michael@0 | 185 | void replaceSuccessor(size_t pos, MBasicBlock *split); |
michael@0 | 186 | |
michael@0 | 187 | // Removes `pred` from the predecessor list. `pred` should not be |
michael@0 | 188 | // the final predecessor. If this block defines phis, removes the |
michael@0 | 189 | // entry for `pred` and updates the indices of later entries. |
michael@0 | 190 | // This may introduce redundant phis if the new block has fewer |
michael@0 | 191 | // than two predecessors. |
michael@0 | 192 | void removePredecessor(MBasicBlock *pred); |
michael@0 | 193 | |
michael@0 | 194 | // Resets all the dominator info so that it can be recomputed. |
michael@0 | 195 | void clearDominatorInfo(); |
michael@0 | 196 | |
michael@0 | 197 | // Sets a back edge. This places phi nodes and rewrites instructions within |
michael@0 | 198 | // the current loop as necessary. If the backedge introduces new types for |
michael@0 | 199 | // phis at the loop header, returns a disabling abort. |
michael@0 | 200 | AbortReason setBackedge(MBasicBlock *block); |
michael@0 | 201 | bool setBackedgeAsmJS(MBasicBlock *block); |
michael@0 | 202 | |
michael@0 | 203 | // Resets a LOOP_HEADER block to a NORMAL block. This is needed when |
michael@0 | 204 | // optimizations remove the backedge. |
michael@0 | 205 | void clearLoopHeader(); |
michael@0 | 206 | |
michael@0 | 207 | // Propagates phis placed in a loop header down to this successor block. |
michael@0 | 208 | void inheritPhis(MBasicBlock *header); |
michael@0 | 209 | |
michael@0 | 210 | // Compute the types for phis in this block according to their inputs. |
michael@0 | 211 | bool specializePhis(); |
michael@0 | 212 | |
michael@0 | 213 | void insertBefore(MInstruction *at, MInstruction *ins); |
michael@0 | 214 | void insertAfter(MInstruction *at, MInstruction *ins); |
michael@0 | 215 | |
michael@0 | 216 | // Add an instruction to this block, from elsewhere in the graph. |
michael@0 | 217 | void addFromElsewhere(MInstruction *ins); |
michael@0 | 218 | |
michael@0 | 219 | // Move an instruction. Movement may cross block boundaries. |
michael@0 | 220 | void moveBefore(MInstruction *at, MInstruction *ins); |
michael@0 | 221 | |
michael@0 | 222 | // Removes an instruction with the intention to discard it. |
michael@0 | 223 | void discard(MInstruction *ins); |
michael@0 | 224 | void discardLastIns(); |
michael@0 | 225 | MInstructionIterator discardAt(MInstructionIterator &iter); |
michael@0 | 226 | MInstructionReverseIterator discardAt(MInstructionReverseIterator &iter); |
michael@0 | 227 | MDefinitionIterator discardDefAt(MDefinitionIterator &iter); |
michael@0 | 228 | void discardAllInstructions(); |
michael@0 | 229 | void discardAllPhiOperands(); |
michael@0 | 230 | void discardAllPhis(); |
michael@0 | 231 | void discardAllResumePoints(bool discardEntry = true); |
michael@0 | 232 | |
michael@0 | 233 | // Discards a phi instruction and updates predecessor successorWithPhis. |
michael@0 | 234 | MPhiIterator discardPhiAt(MPhiIterator &at); |
michael@0 | 235 | |
michael@0 | 236 | // Mark this block as having been removed from the graph. |
michael@0 | 237 | void markAsDead() { |
michael@0 | 238 | kind_ = DEAD; |
michael@0 | 239 | } |
michael@0 | 240 | |
michael@0 | 241 | /////////////////////////////////////////////////////// |
michael@0 | 242 | /////////// END GRAPH BUILDING INSTRUCTIONS /////////// |
michael@0 | 243 | /////////////////////////////////////////////////////// |
michael@0 | 244 | |
michael@0 | 245 | MIRGraph &graph() { |
michael@0 | 246 | return graph_; |
michael@0 | 247 | } |
michael@0 | 248 | CompileInfo &info() const { |
michael@0 | 249 | return info_; |
michael@0 | 250 | } |
michael@0 | 251 | jsbytecode *pc() const { |
michael@0 | 252 | return pc_; |
michael@0 | 253 | } |
michael@0 | 254 | uint32_t nslots() const { |
michael@0 | 255 | return slots_.length(); |
michael@0 | 256 | } |
michael@0 | 257 | uint32_t id() const { |
michael@0 | 258 | return id_; |
michael@0 | 259 | } |
michael@0 | 260 | uint32_t numPredecessors() const { |
michael@0 | 261 | return predecessors_.length(); |
michael@0 | 262 | } |
michael@0 | 263 | |
michael@0 | 264 | uint32_t domIndex() const { |
michael@0 | 265 | JS_ASSERT(!isDead()); |
michael@0 | 266 | return domIndex_; |
michael@0 | 267 | } |
michael@0 | 268 | void setDomIndex(uint32_t d) { |
michael@0 | 269 | domIndex_ = d; |
michael@0 | 270 | } |
michael@0 | 271 | |
michael@0 | 272 | MBasicBlock *getPredecessor(uint32_t i) const { |
michael@0 | 273 | return predecessors_[i]; |
michael@0 | 274 | } |
michael@0 | 275 | MControlInstruction *lastIns() const { |
michael@0 | 276 | return lastIns_; |
michael@0 | 277 | } |
michael@0 | 278 | MPhiIterator phisBegin() const { |
michael@0 | 279 | return phis_.begin(); |
michael@0 | 280 | } |
michael@0 | 281 | MPhiIterator phisEnd() const { |
michael@0 | 282 | return phis_.end(); |
michael@0 | 283 | } |
michael@0 | 284 | bool phisEmpty() const { |
michael@0 | 285 | return phis_.empty(); |
michael@0 | 286 | } |
michael@0 | 287 | MResumePointIterator resumePointsBegin() const { |
michael@0 | 288 | return resumePoints_.begin(); |
michael@0 | 289 | } |
michael@0 | 290 | MResumePointIterator resumePointsEnd() const { |
michael@0 | 291 | return resumePoints_.end(); |
michael@0 | 292 | } |
michael@0 | 293 | bool resumePointsEmpty() const { |
michael@0 | 294 | return resumePoints_.empty(); |
michael@0 | 295 | } |
michael@0 | 296 | MInstructionIterator begin() { |
michael@0 | 297 | return instructions_.begin(); |
michael@0 | 298 | } |
michael@0 | 299 | MInstructionIterator begin(MInstruction *at) { |
michael@0 | 300 | JS_ASSERT(at->block() == this); |
michael@0 | 301 | return instructions_.begin(at); |
michael@0 | 302 | } |
michael@0 | 303 | MInstructionIterator end() { |
michael@0 | 304 | return instructions_.end(); |
michael@0 | 305 | } |
michael@0 | 306 | MInstructionReverseIterator rbegin() { |
michael@0 | 307 | return instructions_.rbegin(); |
michael@0 | 308 | } |
michael@0 | 309 | MInstructionReverseIterator rbegin(MInstruction *at) { |
michael@0 | 310 | JS_ASSERT(at->block() == this); |
michael@0 | 311 | return instructions_.rbegin(at); |
michael@0 | 312 | } |
michael@0 | 313 | MInstructionReverseIterator rend() { |
michael@0 | 314 | return instructions_.rend(); |
michael@0 | 315 | } |
michael@0 | 316 | bool isLoopHeader() const { |
michael@0 | 317 | return kind_ == LOOP_HEADER; |
michael@0 | 318 | } |
michael@0 | 319 | bool hasUniqueBackedge() const { |
michael@0 | 320 | JS_ASSERT(isLoopHeader()); |
michael@0 | 321 | JS_ASSERT(numPredecessors() >= 2); |
michael@0 | 322 | return numPredecessors() == 2; |
michael@0 | 323 | } |
michael@0 | 324 | MBasicBlock *backedge() const { |
michael@0 | 325 | JS_ASSERT(hasUniqueBackedge()); |
michael@0 | 326 | return getPredecessor(numPredecessors() - 1); |
michael@0 | 327 | } |
michael@0 | 328 | MBasicBlock *loopHeaderOfBackedge() const { |
michael@0 | 329 | JS_ASSERT(isLoopBackedge()); |
michael@0 | 330 | return getSuccessor(numSuccessors() - 1); |
michael@0 | 331 | } |
michael@0 | 332 | MBasicBlock *loopPredecessor() const { |
michael@0 | 333 | JS_ASSERT(isLoopHeader()); |
michael@0 | 334 | return getPredecessor(0); |
michael@0 | 335 | } |
michael@0 | 336 | bool isLoopBackedge() const { |
michael@0 | 337 | if (!numSuccessors()) |
michael@0 | 338 | return false; |
michael@0 | 339 | MBasicBlock *lastSuccessor = getSuccessor(numSuccessors() - 1); |
michael@0 | 340 | return lastSuccessor->isLoopHeader() && |
michael@0 | 341 | lastSuccessor->hasUniqueBackedge() && |
michael@0 | 342 | lastSuccessor->backedge() == this; |
michael@0 | 343 | } |
michael@0 | 344 | bool isSplitEdge() const { |
michael@0 | 345 | return kind_ == SPLIT_EDGE; |
michael@0 | 346 | } |
michael@0 | 347 | bool isDead() const { |
michael@0 | 348 | return kind_ == DEAD; |
michael@0 | 349 | } |
michael@0 | 350 | |
michael@0 | 351 | uint32_t stackDepth() const { |
michael@0 | 352 | return stackPosition_; |
michael@0 | 353 | } |
michael@0 | 354 | void setStackDepth(uint32_t depth) { |
michael@0 | 355 | stackPosition_ = depth; |
michael@0 | 356 | } |
michael@0 | 357 | bool isMarked() const { |
michael@0 | 358 | return mark_; |
michael@0 | 359 | } |
michael@0 | 360 | void mark() { |
michael@0 | 361 | mark_ = true; |
michael@0 | 362 | } |
michael@0 | 363 | void unmark() { |
michael@0 | 364 | mark_ = false; |
michael@0 | 365 | } |
michael@0 | 366 | void makeStart(MStart *start) { |
michael@0 | 367 | add(start); |
michael@0 | 368 | start_ = start; |
michael@0 | 369 | } |
michael@0 | 370 | MStart *start() const { |
michael@0 | 371 | return start_; |
michael@0 | 372 | } |
michael@0 | 373 | |
michael@0 | 374 | MBasicBlock *immediateDominator() const { |
michael@0 | 375 | return immediateDominator_; |
michael@0 | 376 | } |
michael@0 | 377 | |
michael@0 | 378 | void setImmediateDominator(MBasicBlock *dom) { |
michael@0 | 379 | immediateDominator_ = dom; |
michael@0 | 380 | } |
michael@0 | 381 | |
michael@0 | 382 | MTest *immediateDominatorBranch(BranchDirection *pdirection); |
michael@0 | 383 | |
michael@0 | 384 | size_t numImmediatelyDominatedBlocks() const { |
michael@0 | 385 | return immediatelyDominated_.length(); |
michael@0 | 386 | } |
michael@0 | 387 | |
michael@0 | 388 | MBasicBlock *getImmediatelyDominatedBlock(size_t i) const { |
michael@0 | 389 | return immediatelyDominated_[i]; |
michael@0 | 390 | } |
michael@0 | 391 | |
michael@0 | 392 | MBasicBlock **immediatelyDominatedBlocksBegin() { |
michael@0 | 393 | return immediatelyDominated_.begin(); |
michael@0 | 394 | } |
michael@0 | 395 | |
michael@0 | 396 | MBasicBlock **immediatelyDominatedBlocksEnd() { |
michael@0 | 397 | return immediatelyDominated_.end(); |
michael@0 | 398 | } |
michael@0 | 399 | |
michael@0 | 400 | size_t numDominated() const { |
michael@0 | 401 | return numDominated_; |
michael@0 | 402 | } |
michael@0 | 403 | |
michael@0 | 404 | void addNumDominated(size_t n) { |
michael@0 | 405 | numDominated_ += n; |
michael@0 | 406 | } |
michael@0 | 407 | |
michael@0 | 408 | bool addImmediatelyDominatedBlock(MBasicBlock *child); |
michael@0 | 409 | |
michael@0 | 410 | // This function retrieves the internal instruction associated with a |
michael@0 | 411 | // slot, and should not be used for normal stack operations. It is an |
michael@0 | 412 | // internal helper that is also used to enhance spew. |
michael@0 | 413 | MDefinition *getSlot(uint32_t index); |
michael@0 | 414 | |
michael@0 | 415 | MResumePoint *entryResumePoint() const { |
michael@0 | 416 | return entryResumePoint_; |
michael@0 | 417 | } |
michael@0 | 418 | MResumePoint *callerResumePoint() { |
michael@0 | 419 | return entryResumePoint()->caller(); |
michael@0 | 420 | } |
michael@0 | 421 | void setCallerResumePoint(MResumePoint *caller) { |
michael@0 | 422 | entryResumePoint()->setCaller(caller); |
michael@0 | 423 | } |
michael@0 | 424 | size_t numEntrySlots() const { |
michael@0 | 425 | return entryResumePoint()->numOperands(); |
michael@0 | 426 | } |
michael@0 | 427 | MDefinition *getEntrySlot(size_t i) const { |
michael@0 | 428 | JS_ASSERT(i < numEntrySlots()); |
michael@0 | 429 | return entryResumePoint()->getOperand(i); |
michael@0 | 430 | } |
michael@0 | 431 | |
michael@0 | 432 | LBlock *lir() const { |
michael@0 | 433 | return lir_; |
michael@0 | 434 | } |
michael@0 | 435 | void assignLir(LBlock *lir) { |
michael@0 | 436 | JS_ASSERT(!lir_); |
michael@0 | 437 | lir_ = lir; |
michael@0 | 438 | } |
michael@0 | 439 | |
michael@0 | 440 | MBasicBlock *successorWithPhis() const { |
michael@0 | 441 | return successorWithPhis_; |
michael@0 | 442 | } |
michael@0 | 443 | uint32_t positionInPhiSuccessor() const { |
michael@0 | 444 | return positionInPhiSuccessor_; |
michael@0 | 445 | } |
michael@0 | 446 | void setSuccessorWithPhis(MBasicBlock *successor, uint32_t id) { |
michael@0 | 447 | successorWithPhis_ = successor; |
michael@0 | 448 | positionInPhiSuccessor_ = id; |
michael@0 | 449 | } |
michael@0 | 450 | size_t numSuccessors() const; |
michael@0 | 451 | MBasicBlock *getSuccessor(size_t index) const; |
michael@0 | 452 | size_t getSuccessorIndex(MBasicBlock *) const; |
michael@0 | 453 | |
michael@0 | 454 | void setLoopDepth(uint32_t loopDepth) { |
michael@0 | 455 | loopDepth_ = loopDepth; |
michael@0 | 456 | } |
michael@0 | 457 | uint32_t loopDepth() const { |
michael@0 | 458 | return loopDepth_; |
michael@0 | 459 | } |
michael@0 | 460 | |
michael@0 | 461 | bool strict() const { |
michael@0 | 462 | return info_.script()->strict(); |
michael@0 | 463 | } |
michael@0 | 464 | |
michael@0 | 465 | void dumpStack(FILE *fp); |
michael@0 | 466 | |
michael@0 | 467 | void dump(FILE *fp); |
michael@0 | 468 | void dump(); |
michael@0 | 469 | |
michael@0 | 470 | // Track bailouts by storing the current pc in MIR instruction added at this |
michael@0 | 471 | // cycle. This is also used for tracking calls when profiling. |
michael@0 | 472 | void updateTrackedPc(jsbytecode *pc) { |
michael@0 | 473 | trackedPc_ = pc; |
michael@0 | 474 | } |
michael@0 | 475 | |
michael@0 | 476 | jsbytecode *trackedPc() { |
michael@0 | 477 | return trackedPc_; |
michael@0 | 478 | } |
michael@0 | 479 | |
michael@0 | 480 | private: |
michael@0 | 481 | MIRGraph &graph_; |
michael@0 | 482 | CompileInfo &info_; // Each block originates from a particular script. |
michael@0 | 483 | InlineList<MInstruction> instructions_; |
michael@0 | 484 | Vector<MBasicBlock *, 1, IonAllocPolicy> predecessors_; |
michael@0 | 485 | InlineForwardList<MPhi> phis_; |
michael@0 | 486 | InlineForwardList<MResumePoint> resumePoints_; |
michael@0 | 487 | FixedList<MDefinition *> slots_; |
michael@0 | 488 | uint32_t stackPosition_; |
michael@0 | 489 | MControlInstruction *lastIns_; |
michael@0 | 490 | jsbytecode *pc_; |
michael@0 | 491 | uint32_t id_; |
michael@0 | 492 | uint32_t domIndex_; // Index in the dominator tree. |
michael@0 | 493 | LBlock *lir_; |
michael@0 | 494 | MStart *start_; |
michael@0 | 495 | MResumePoint *entryResumePoint_; |
michael@0 | 496 | MBasicBlock *successorWithPhis_; |
michael@0 | 497 | uint32_t positionInPhiSuccessor_; |
michael@0 | 498 | Kind kind_; |
michael@0 | 499 | uint32_t loopDepth_; |
michael@0 | 500 | |
michael@0 | 501 | // Utility mark for traversal algorithms. |
michael@0 | 502 | bool mark_; |
michael@0 | 503 | |
michael@0 | 504 | Vector<MBasicBlock *, 1, IonAllocPolicy> immediatelyDominated_; |
michael@0 | 505 | MBasicBlock *immediateDominator_; |
michael@0 | 506 | size_t numDominated_; |
michael@0 | 507 | |
michael@0 | 508 | jsbytecode *trackedPc_; |
michael@0 | 509 | |
michael@0 | 510 | #if defined (JS_ION_PERF) |
michael@0 | 511 | unsigned lineno_; |
michael@0 | 512 | unsigned columnIndex_; |
michael@0 | 513 | |
michael@0 | 514 | public: |
michael@0 | 515 | void setLineno(unsigned l) { lineno_ = l; } |
michael@0 | 516 | unsigned lineno() const { return lineno_; } |
michael@0 | 517 | void setColumnIndex(unsigned c) { columnIndex_ = c; } |
michael@0 | 518 | unsigned columnIndex() const { return columnIndex_; } |
michael@0 | 519 | #endif |
michael@0 | 520 | }; |
michael@0 | 521 | |
michael@0 | 522 | typedef InlineListIterator<MBasicBlock> MBasicBlockIterator; |
michael@0 | 523 | typedef InlineListIterator<MBasicBlock> ReversePostorderIterator; |
michael@0 | 524 | typedef InlineListReverseIterator<MBasicBlock> PostorderIterator; |
michael@0 | 525 | |
michael@0 | 526 | typedef Vector<MBasicBlock *, 1, IonAllocPolicy> MIRGraphReturns; |
michael@0 | 527 | |
michael@0 | 528 | class MIRGraph |
michael@0 | 529 | { |
michael@0 | 530 | InlineList<MBasicBlock> blocks_; |
michael@0 | 531 | TempAllocator *alloc_; |
michael@0 | 532 | MIRGraphReturns *returnAccumulator_; |
michael@0 | 533 | uint32_t blockIdGen_; |
michael@0 | 534 | uint32_t idGen_; |
michael@0 | 535 | MBasicBlock *osrBlock_; |
michael@0 | 536 | MStart *osrStart_; |
michael@0 | 537 | |
michael@0 | 538 | size_t numBlocks_; |
michael@0 | 539 | bool hasTryBlock_; |
michael@0 | 540 | |
michael@0 | 541 | public: |
michael@0 | 542 | MIRGraph(TempAllocator *alloc) |
michael@0 | 543 | : alloc_(alloc), |
michael@0 | 544 | returnAccumulator_(nullptr), |
michael@0 | 545 | blockIdGen_(0), |
michael@0 | 546 | idGen_(1), |
michael@0 | 547 | osrBlock_(nullptr), |
michael@0 | 548 | osrStart_(nullptr), |
michael@0 | 549 | numBlocks_(0), |
michael@0 | 550 | hasTryBlock_(false) |
michael@0 | 551 | { } |
michael@0 | 552 | |
michael@0 | 553 | TempAllocator &alloc() const { |
michael@0 | 554 | return *alloc_; |
michael@0 | 555 | } |
michael@0 | 556 | |
michael@0 | 557 | void addBlock(MBasicBlock *block); |
michael@0 | 558 | void insertBlockAfter(MBasicBlock *at, MBasicBlock *block); |
michael@0 | 559 | |
michael@0 | 560 | void unmarkBlocks(); |
michael@0 | 561 | |
michael@0 | 562 | void setReturnAccumulator(MIRGraphReturns *accum) { |
michael@0 | 563 | returnAccumulator_ = accum; |
michael@0 | 564 | } |
michael@0 | 565 | MIRGraphReturns *returnAccumulator() const { |
michael@0 | 566 | return returnAccumulator_; |
michael@0 | 567 | } |
michael@0 | 568 | |
michael@0 | 569 | bool addReturn(MBasicBlock *returnBlock) { |
michael@0 | 570 | if (!returnAccumulator_) |
michael@0 | 571 | return true; |
michael@0 | 572 | |
michael@0 | 573 | return returnAccumulator_->append(returnBlock); |
michael@0 | 574 | } |
michael@0 | 575 | |
michael@0 | 576 | MBasicBlock *entryBlock() { |
michael@0 | 577 | return *blocks_.begin(); |
michael@0 | 578 | } |
michael@0 | 579 | |
michael@0 | 580 | void clearBlockList() { |
michael@0 | 581 | blocks_.clear(); |
michael@0 | 582 | blockIdGen_ = 0; |
michael@0 | 583 | numBlocks_ = 0; |
michael@0 | 584 | } |
michael@0 | 585 | void resetInstructionNumber() { |
michael@0 | 586 | // This intentionally starts above 0. The id 0 is in places used to |
michael@0 | 587 | // indicate a failure to perform an operation on an instruction. |
michael@0 | 588 | idGen_ = 1; |
michael@0 | 589 | } |
michael@0 | 590 | MBasicBlockIterator begin() { |
michael@0 | 591 | return blocks_.begin(); |
michael@0 | 592 | } |
michael@0 | 593 | MBasicBlockIterator begin(MBasicBlock *at) { |
michael@0 | 594 | return blocks_.begin(at); |
michael@0 | 595 | } |
michael@0 | 596 | MBasicBlockIterator end() { |
michael@0 | 597 | return blocks_.end(); |
michael@0 | 598 | } |
michael@0 | 599 | PostorderIterator poBegin() { |
michael@0 | 600 | return blocks_.rbegin(); |
michael@0 | 601 | } |
michael@0 | 602 | PostorderIterator poEnd() { |
michael@0 | 603 | return blocks_.rend(); |
michael@0 | 604 | } |
michael@0 | 605 | ReversePostorderIterator rpoBegin() { |
michael@0 | 606 | return blocks_.begin(); |
michael@0 | 607 | } |
michael@0 | 608 | ReversePostorderIterator rpoBegin(MBasicBlock *at) { |
michael@0 | 609 | return blocks_.begin(at); |
michael@0 | 610 | } |
michael@0 | 611 | ReversePostorderIterator rpoEnd() { |
michael@0 | 612 | return blocks_.end(); |
michael@0 | 613 | } |
michael@0 | 614 | void removeBlocksAfter(MBasicBlock *block); |
michael@0 | 615 | void removeBlock(MBasicBlock *block); |
michael@0 | 616 | void moveBlockToEnd(MBasicBlock *block) { |
michael@0 | 617 | JS_ASSERT(block->id()); |
michael@0 | 618 | blocks_.remove(block); |
michael@0 | 619 | blocks_.pushBack(block); |
michael@0 | 620 | } |
michael@0 | 621 | size_t numBlocks() const { |
michael@0 | 622 | return numBlocks_; |
michael@0 | 623 | } |
michael@0 | 624 | uint32_t numBlockIds() const { |
michael@0 | 625 | return blockIdGen_; |
michael@0 | 626 | } |
michael@0 | 627 | void allocDefinitionId(MDefinition *ins) { |
michael@0 | 628 | ins->setId(idGen_++); |
michael@0 | 629 | } |
michael@0 | 630 | uint32_t getNumInstructionIds() { |
michael@0 | 631 | return idGen_; |
michael@0 | 632 | } |
michael@0 | 633 | MResumePoint *entryResumePoint() { |
michael@0 | 634 | return blocks_.begin()->entryResumePoint(); |
michael@0 | 635 | } |
michael@0 | 636 | |
michael@0 | 637 | void copyIds(const MIRGraph &other) { |
michael@0 | 638 | idGen_ = other.idGen_; |
michael@0 | 639 | blockIdGen_ = other.blockIdGen_; |
michael@0 | 640 | numBlocks_ = other.numBlocks_; |
michael@0 | 641 | } |
michael@0 | 642 | |
michael@0 | 643 | void setOsrBlock(MBasicBlock *osrBlock) { |
michael@0 | 644 | JS_ASSERT(!osrBlock_); |
michael@0 | 645 | osrBlock_ = osrBlock; |
michael@0 | 646 | } |
michael@0 | 647 | MBasicBlock *osrBlock() { |
michael@0 | 648 | return osrBlock_; |
michael@0 | 649 | } |
michael@0 | 650 | void setOsrStart(MStart *osrStart) { |
michael@0 | 651 | osrStart_ = osrStart; |
michael@0 | 652 | } |
michael@0 | 653 | MStart *osrStart() { |
michael@0 | 654 | return osrStart_; |
michael@0 | 655 | } |
michael@0 | 656 | |
michael@0 | 657 | bool hasTryBlock() const { |
michael@0 | 658 | return hasTryBlock_; |
michael@0 | 659 | } |
michael@0 | 660 | void setHasTryBlock() { |
michael@0 | 661 | hasTryBlock_ = true; |
michael@0 | 662 | } |
michael@0 | 663 | |
michael@0 | 664 | // The per-thread context. So as not to modify the calling convention for |
michael@0 | 665 | // parallel code, we obtain the current ForkJoinContext from thread-local |
michael@0 | 666 | // storage. This helper method will lazilly insert an MForkJoinContext |
michael@0 | 667 | // instruction in the entry block and return the definition. |
michael@0 | 668 | MDefinition *forkJoinContext(); |
michael@0 | 669 | |
michael@0 | 670 | void dump(FILE *fp); |
michael@0 | 671 | void dump(); |
michael@0 | 672 | }; |
michael@0 | 673 | |
michael@0 | 674 | class MDefinitionIterator |
michael@0 | 675 | { |
michael@0 | 676 | |
michael@0 | 677 | friend class MBasicBlock; |
michael@0 | 678 | |
michael@0 | 679 | private: |
michael@0 | 680 | MBasicBlock *block_; |
michael@0 | 681 | MPhiIterator phiIter_; |
michael@0 | 682 | MInstructionIterator iter_; |
michael@0 | 683 | |
michael@0 | 684 | bool atPhi() const { |
michael@0 | 685 | return phiIter_ != block_->phisEnd(); |
michael@0 | 686 | } |
michael@0 | 687 | |
michael@0 | 688 | MDefinition *getIns() { |
michael@0 | 689 | if (atPhi()) |
michael@0 | 690 | return *phiIter_; |
michael@0 | 691 | return *iter_; |
michael@0 | 692 | } |
michael@0 | 693 | |
michael@0 | 694 | void next() { |
michael@0 | 695 | if (atPhi()) |
michael@0 | 696 | phiIter_++; |
michael@0 | 697 | else |
michael@0 | 698 | iter_++; |
michael@0 | 699 | } |
michael@0 | 700 | |
michael@0 | 701 | bool more() const { |
michael@0 | 702 | return atPhi() || (*iter_) != block_->lastIns(); |
michael@0 | 703 | } |
michael@0 | 704 | |
michael@0 | 705 | public: |
michael@0 | 706 | MDefinitionIterator(MBasicBlock *block) |
michael@0 | 707 | : block_(block), |
michael@0 | 708 | phiIter_(block->phisBegin()), |
michael@0 | 709 | iter_(block->begin()) |
michael@0 | 710 | { } |
michael@0 | 711 | |
michael@0 | 712 | MDefinitionIterator operator ++(int) { |
michael@0 | 713 | MDefinitionIterator old(*this); |
michael@0 | 714 | if (more()) |
michael@0 | 715 | next(); |
michael@0 | 716 | return old; |
michael@0 | 717 | } |
michael@0 | 718 | |
michael@0 | 719 | operator bool() const { |
michael@0 | 720 | return more(); |
michael@0 | 721 | } |
michael@0 | 722 | |
michael@0 | 723 | MDefinition *operator *() { |
michael@0 | 724 | return getIns(); |
michael@0 | 725 | } |
michael@0 | 726 | |
michael@0 | 727 | MDefinition *operator ->() { |
michael@0 | 728 | return getIns(); |
michael@0 | 729 | } |
michael@0 | 730 | |
michael@0 | 731 | }; |
michael@0 | 732 | |
michael@0 | 733 | } // namespace jit |
michael@0 | 734 | } // namespace js |
michael@0 | 735 | |
michael@0 | 736 | #endif /* jit_MIRGraph_h */ |