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