js/src/jit/MIRGraph.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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 */

mercurial