001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.compilers.opt.ir;
014    
015    import static org.jikesrvm.compilers.opt.driver.OptConstants.NO;
016    import static org.jikesrvm.compilers.opt.ir.Operators.ATHROW_opcode;
017    import static org.jikesrvm.compilers.opt.ir.Operators.BBEND;
018    import static org.jikesrvm.compilers.opt.ir.Operators.BOUNDS_CHECK_opcode;
019    import static org.jikesrvm.compilers.opt.ir.Operators.CHECKCAST_NOTNULL_opcode;
020    import static org.jikesrvm.compilers.opt.ir.Operators.CHECKCAST_UNRESOLVED_opcode;
021    import static org.jikesrvm.compilers.opt.ir.Operators.CHECKCAST_opcode;
022    import static org.jikesrvm.compilers.opt.ir.Operators.GOTO;
023    import static org.jikesrvm.compilers.opt.ir.Operators.INT_ZERO_CHECK_opcode;
024    import static org.jikesrvm.compilers.opt.ir.Operators.IR_PROLOGUE_opcode;
025    import static org.jikesrvm.compilers.opt.ir.Operators.LABEL;
026    import static org.jikesrvm.compilers.opt.ir.Operators.LONG_ZERO_CHECK_opcode;
027    import static org.jikesrvm.compilers.opt.ir.Operators.NULL_CHECK_opcode;
028    import static org.jikesrvm.compilers.opt.ir.Operators.OBJARRAY_STORE_CHECK_opcode;
029    
030    import java.util.Enumeration;
031    import java.util.HashSet;
032    
033    import org.jikesrvm.VM;
034    import org.jikesrvm.classloader.TypeReference;
035    import org.jikesrvm.compilers.opt.driver.OptConstants;
036    import org.jikesrvm.compilers.opt.inlining.InlineSequence;
037    import org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand;
038    import org.jikesrvm.compilers.opt.ir.operand.BranchOperand;
039    import org.jikesrvm.compilers.opt.ir.operand.MethodOperand;
040    import org.jikesrvm.compilers.opt.liveness.LiveIntervalEnumeration;
041    import org.jikesrvm.compilers.opt.regalloc.LiveIntervalElement;
042    import org.jikesrvm.compilers.opt.util.SortedGraphNode;
043    import org.jikesrvm.compilers.opt.util.SpaceEffGraphEdge;
044    import org.jikesrvm.compilers.opt.util.SpaceEffGraphNode;
045    import org.jikesrvm.runtime.Entrypoints;
046    import org.jikesrvm.util.EmptyEnumeration;
047    import org.vmmagic.pragma.NoInline;
048    
049    /**
050     * A basic block in the
051     * {@link ControlFlowGraph Factored Control Flow Graph (FCFG)}.
052     * <p>
053     * Just like in a standard control flow graph (CFG), a FCFG basic block
054     * contains a linear sequence of instructions. However, in the FCFG,
055     * a Potentially Excepting Instruction (PEI) does not necessarily end its
056     * basic block.  Therefore, although instructions within a FCFG basic block
057     * have the expected dominance relationships, they do <em>not</em> have the
058     * same post-dominance relationships as they would under the traditional
059     * basic block formulation used in a CFG.
060     * We chose to use an FCFG because doing so significantly reduces the
061     * number of basic blocks and control flow graph edges, thus reducing
062     * the time and space costs of representing the FCFG and also
063     * increasing the effectiveness of local (within a single basic block)
064     * analysis.  However, using an FCFG does complicate flow-sensitive
065     * global analaysis.  Many analyses can be easily extended to
066     * work on the FCFG.  For those analyses that cannot, we provide utilities
067     * ({@link IR#unfactor()}, {@link #unfactor(IR)})
068     * to effectively convert the FCFG into a CFG.
069     * For a more detailed description of the FCFG and its implications for
070     * program analysis see the PASTE'99 paper by Choi et al.
071     *   <a href="http://www.research.ibm.com/jalapeno/publication.html#paste99">
072     *   Efficient and Precise Modeling of Exceptions for the Analysis of Java Programs </a>
073     * <p>
074     * The instructions in a basic block have the following structure
075     * <ul>
076     * <li> The block begins with a <code>LABEL</code>.
077     * <li> Next come zero or more non-branch instructions.
078     * <li> Next come zero or more conditional branches
079     * <li> Next comes zero or one unconditional branch
080     * <li> Finally the block ends with a <code>BBEND</code>
081     * </ul>
082     * <code>CALL</code> instructions do not end their basic block.
083     * <code>ATHROW</code> instructions do end their basic block.
084     * Conventionally, we refer to the <em>real</em> instructions of
085     * the block as those that are between the LABEL and the BBEND.
086     * We say that the block is empty if it contains no real instructions.
087     * <p>
088     *
089     * @see IR
090     * @see Instruction
091     * @see ControlFlowGraph
092     */
093    
094    public class BasicBlock extends SortedGraphNode {
095    
096      /** Bitfield used in flag encoding */
097      static final short CAN_THROW_EXCEPTIONS = 0x01;
098      /** Bitfield used in flag encoding */
099      static final short IMPLICIT_EXIT_EDGE = 0x02;
100      /** Bitfield used in flag encoding */
101      static final short EXCEPTION_HANDLER = 0x04;
102      /** Bitfield used in flag encoding */
103      static final short REACHABLE_FROM_EXCEPTION_HANDLER = 0x08;
104      /** Bitfield used in flag encoding */
105      static final short UNSAFE_TO_SCHEDULE = 0x10;
106      /** Bitfield used in flag encoding */
107      static final short INFREQUENT = 0x20;
108      /** Bitfield used in flag encoding */
109      static final short SCRATCH = 0x40;
110      /** Bitfield used in flag encoding */
111      static final short LANDING_PAD = 0x80;
112      /** Bitfield used in flag encoding */
113      static final short EXCEPTION_HANDLER_WITH_NORMAL_IN = 0x100;
114    
115      /**
116       * Used to encode various properties of the block.
117       */
118      protected short flags;
119    
120      /**
121       * Encodes exception handler info for this block.
122       * May be shared if multiple blocks have exactly the same chain
123       * of exception handlers.
124       */
125      public ExceptionHandlerBasicBlockBag exceptionHandlers;
126    
127      /**
128       * First instruction of the basic block (LABEL).
129       */
130      final Instruction start;
131    
132      /**
133       * Last instruction of the basic block (BBEND).
134       */
135      final Instruction end;
136    
137      /**
138       * Relative execution frequency of this basic block.
139       * The entry block to a CFG has weight 1.0;
140       */
141      protected float freq;
142    
143      /**
144       * Creates a new basic block at the specified location.
145       * It initially contains a single label instruction pointed to
146       * by start and a BBEND instruction pointed to by end.
147       *
148       * @param i         bytecode index to create basic block at
149       * @param position  the inline context for this basic block
150       * @param cfg       the FCFG that will contain the basic block
151       */
152      public BasicBlock(int i, InlineSequence position, ControlFlowGraph cfg) {
153        this(i, position, cfg.allocateNodeNumber());
154      }
155    
156      /**
157       * Creates a new basic block at the specified location with
158       * the given basic block number.
159       * It initially contains a single label instruction pointed to
160       * by start and a BBEND instruction pointed to by end.
161       * WARNING: Don't call this constructor directly if the created basic
162       * block is going to be in some control flow graph, since it
163       * may not get assigned a unique number.
164       *
165       * @param i         bytecode index to create basic block at
166       * @param position  the inline context for this basic block
167       * @param num       the number to assign the basic block
168       */
169      protected BasicBlock(int i, InlineSequence position, int num) {
170        setNumber(num);
171        start = Label.create(LABEL, new BasicBlockOperand(this));
172        start.bcIndex = i;
173    
174        start.position = position;
175        end = BBend.create(BBEND, new BasicBlockOperand(this));
176        // NOTE: we have no idea where this block will end so it
177        // makes no sense to set its bcIndex or position.
178        // In fact, the block may end in a different method entirely,
179        // so setting its position to the same as start may silently
180        // get us into all kinds of trouble. --dave.
181        end.bcIndex = OptConstants.UNKNOWN_BCI;
182        start.linkWithNext(end);
183        initInOutSets();
184      }
185    
186      /**
187       * This constructor is only used for creating an EXIT node
188       */
189      private BasicBlock() {
190        start = end = null;
191        setNumber(1);
192      }
193    
194      final void initInOutSets() { }
195    
196      /**
197       * Make an EXIT node.
198       */
199      static BasicBlock makeExit() {
200        return new BasicBlock();
201      }
202    
203      /**
204       * Returns the string representation of this basic block.
205       * @return a String that is the name of the block.
206       */
207      @Override
208      public String toString() {
209        int number = getNumber();
210        if (isExit()) return "EXIT" + number;
211        if (number == 0) return "BB0 (ENTRY)";
212        return "BB" + number;
213      }
214    
215      /**
216       * Print a detailed dump of the block to the sysWrite stream
217       */
218      @Override
219      public final void printExtended() {
220        VM.sysWrite("Basic block " + toString() + "\n");
221    
222        // print in set.
223        BasicBlock bb2;
224        Enumeration<BasicBlock> e2 = getIn();
225        VM.sysWrite("\tin: ");
226        if (!e2.hasMoreElements()) {
227          VM.sysWrite("<none>\n");
228        } else {
229          bb2 = e2.nextElement();
230          VM.sysWrite(bb2.toString());
231          while (e2.hasMoreElements()) {
232            bb2 = e2.nextElement();
233            VM.sysWrite(", " + bb2.toString());
234          }
235          VM.sysWrite("\n");
236        }
237    
238        // print out set.
239        e2 = getNormalOut();
240        VM.sysWrite("\tnormal out: ");
241        if (!e2.hasMoreElements()) {
242          VM.sysWrite("<none>\n");
243        } else {
244          bb2 = e2.nextElement();
245          VM.sysWrite(bb2.toString());
246          while (e2.hasMoreElements()) {
247            bb2 = e2.nextElement();
248            VM.sysWrite(", " + bb2.toString());
249          }
250          VM.sysWrite("\n");
251        }
252    
253        e2 = getExceptionalOut();
254        VM.sysWrite("\texceptional out: ");
255        if (!e2.hasMoreElements()) {
256          VM.sysWrite("<none>\n");
257        } else {
258          bb2 = e2.nextElement();
259          VM.sysWrite(bb2.toString());
260          while (e2.hasMoreElements()) {
261            bb2 = e2.nextElement();
262            VM.sysWrite(", " + bb2.toString());
263          }
264          VM.sysWrite("\n");
265        }
266    
267        if (mayThrowUncaughtException()) {
268          VM.sysWrite("\tMay throw uncaught exceptions, implicit edge to EXIT\n");
269        }
270    
271        if (hasExceptionHandlers()) {
272          VM.sysWrite("\tIn scope exception handlers: ");
273          e2 = getExceptionHandlers();
274          if (e2.hasMoreElements()) {
275            bb2 = e2.nextElement();
276            VM.sysWrite(bb2.toString());
277            while (e2.hasMoreElements()) {
278              bb2 = e2.nextElement();
279              VM.sysWrite(", " + bb2.toString());
280            }
281          } else {
282            VM.sysWrite("<none>");
283          }
284          VM.sysWrite("\n");
285        }
286    
287        if (getNext() != null) {
288          VM.sysWrite("\tNext in code order: " + getNext().toString() + "\n");
289        }
290    
291        if (start != null) {
292          VM.sysWrite("\tInstructions:\n");
293          Instruction inst = start;
294          while (inst != end) {
295            VM.sysWrite(inst.bcIndex + ":\t" + inst + "\n");
296            inst = inst.getNext();
297          }
298          VM.sysWrite(inst.bcIndex + ":\t" + inst + "\n");
299        }
300        VM.sysWrite("\n");
301      }
302    
303      /**
304       * Clear the scratch object from previous uses
305       * (rename scratchObject manipulations for GCMaps/RegAlloc).
306       */
307      public final void initializeLiveRange() {
308        scratchObject = null;
309      }
310    
311      /**
312       * @return an enumeration of the live interval elements for this basic
313       * block.
314       */
315      public final LiveIntervalEnumeration enumerateLiveIntervals() {
316        return new LiveIntervalEnumeration((LiveIntervalElement) scratchObject);
317      }
318    
319      /**
320       * Returns NULL or an LiveIntervalElement (GCMaps/RegAlloc).
321       * @return scratchObject cast as an LiveIntevalElement
322       */
323      public final LiveIntervalElement getFirstLiveIntervalElement() {
324        if (scratchObject != null) {
325          return (LiveIntervalElement) scratchObject;
326        } else {
327          return null;
328        }
329      }
330    
331      /**
332       * Prepend a live interval element to the list being maintained
333       * in scratchObject (GCMaps/RegAlloc).
334       *
335       * @param li the live interval element to add
336       */
337      public final void prependLiveIntervalElement(LiveIntervalElement li) {
338        li.setNext((LiveIntervalElement) scratchObject);
339        scratchObject = li;
340      }
341    
342      /**
343       * Can this block possibly throw an exception?
344       * May conservatively return true even if the block
345       * does not contain a PEI.
346       *
347       * @return <code>true</code> if the block might raise an
348       *         exception or <code>false</code> if it cannot
349       */
350      public final boolean canThrowExceptions() {
351        return (flags & CAN_THROW_EXCEPTIONS) != 0;
352      }
353    
354      /**
355       * Can a PEI in this block possibly raise an uncaught exception?
356       * May conservatively return true even if the block
357       * does not contain a PEI. When this is true it implies
358       * that there is an implicit edge from this node to the
359       * exit node in the FCFG.
360       * <p>
361       * NOTE: This method says nothing about the presence/absence
362       * of an explicit throw of an uncaught exception, and thus does
363       * not rule out the block having an <em>explicit</em>
364       * edge to the exit node caused by a throw of an uncaught exception.
365       *
366       * @return <code>true</code> if the block might raise an
367       *         exception uncaught or <code>false</code> if it cannot
368       */
369      public final boolean mayThrowUncaughtException() {
370        return (flags & IMPLICIT_EXIT_EDGE) != 0;
371      }
372    
373      /**
374       * Is this block the first basic block in an exception handler?
375       * NOTE: This doesn't seem particularly useful to me anymore,
376       * since it is the same as asking if the block is an instanceof
377       * and ExceptionHandlerBasicBlock. Perhaps we should phase this out?
378       *
379       * @return <code>true</code> if the block is the first block in
380       *         an exception hander or <code>false</code> if it is not
381       */
382      public final boolean isExceptionHandlerBasicBlock() {
383        return (flags & EXCEPTION_HANDLER) != 0;
384      }
385    
386      /**
387       * Has the block been marked as being reachable from an
388       * exception handler?
389       *
390       * @return <code>true</code> if the block is reachable from
391       *         an exception hander or <code>false</code> if it is not
392       */
393      public final boolean isReachableFromExceptionHandler() {
394        return (flags & REACHABLE_FROM_EXCEPTION_HANDLER) != 0;
395      }
396    
397      /**
398       * Compare the in scope exception handlers of two blocks.
399       *
400       * @param other block to be compared to this.
401       * @return <code>true</code> if this and other have equivalent in
402       * scope exception handlers.
403       */
404      public final boolean isExceptionHandlerEquivalent(BasicBlock other) {
405        // We might be able to do something,
406        // by considering the (subset) of reachable exception handlers,
407        // but it would be awfully tricky to get it right,
408        // so just give up if they aren't equivalent.
409        if (exceptionHandlers != other.exceptionHandlers) {
410          // Even if not pointer ==, they still may be equivalent
411          Enumeration<BasicBlock> e1 = getExceptionHandlers();
412          Enumeration<BasicBlock> e2 = other.getExceptionHandlers();
413          while (e1.hasMoreElements()) {
414            if (!e2.hasMoreElements()) return false;
415            if (e1.nextElement() != e2.nextElement()) return false;
416          }
417          if (e2.hasMoreElements()) return false;
418        }
419        return true;
420      }
421    
422      /**
423       * Has the block been marked as being unsafe to schedule
424       * (due to the presence of Magic)?
425       *
426       * @return <code>true</code> if the block is marked as unsafe
427       *         to schedule or <code>false</code> if it is not
428       */
429      public final boolean isUnsafeToSchedule() {
430        return (flags & UNSAFE_TO_SCHEDULE) != 0;
431      }
432    
433      /**
434       * Has the block been marked as being infrequently executed?
435       * NOTE: Only blocks that are truly icy cold should be marked
436       * as infrequent.
437       *
438       * @return <code>true</code> if the block is marked as infrequently
439       *         executed or <code>false</code> if it is not
440       */
441      public final boolean getInfrequent() {
442        return (flags & INFREQUENT) != 0;
443      }
444    
445      /**
446       * Is the scratch flag set on the block?
447       *
448       * @return <code>true</code> if the block scratch flag is set
449       *         or <code>false</code> if it is not
450       */
451      public final boolean getScratchFlag() {
452        return (flags & SCRATCH) != 0;
453      }
454    
455      /**
456       * Has the block been marked as landing pad?
457       *
458       * @return <code>true</code> if the block is marked as landing pad
459       *         or <code>false</code> if it is not
460       */
461      public final boolean getLandingPad() {
462        return (flags & LANDING_PAD) != 0;
463      }
464    
465      /**
466       * Mark the block as possibly raising an exception.
467       */
468      public final void setCanThrowExceptions() {
469        flags |= CAN_THROW_EXCEPTIONS;
470      }
471    
472      /**
473       * Mark the block as possibly raising an uncaught exception.
474       */
475      public final void setMayThrowUncaughtException() {
476        flags |= IMPLICIT_EXIT_EDGE;
477      }
478    
479      /**
480       * Mark the block as the first block in an exception handler.
481       */
482      public final void setExceptionHandlerBasicBlock() {
483        flags |= EXCEPTION_HANDLER;
484      }
485    
486      /**
487       * Mark the block as being reachable from an exception handler.
488       */
489      public final void setReachableFromExceptionHandler() {
490        flags |= REACHABLE_FROM_EXCEPTION_HANDLER;
491      }
492    
493      /**
494       * Mark the block as being unsafe to schedule.
495       */
496      public final void setUnsafeToSchedule() {
497        flags |= UNSAFE_TO_SCHEDULE;
498      }
499    
500      /**
501       * Mark the block as being infrequently executed.
502       */
503      public final void setInfrequent() {
504        flags |= INFREQUENT;
505      }
506    
507      /**
508       * Set the scratch flag
509       */
510      public final void setScratchFlag() {
511        flags |= SCRATCH;
512      }
513    
514      /**
515       * Mark the block as a landing pad for loop invariant code motion.
516       */
517      public final void setLandingPad() {
518        flags |= LANDING_PAD;
519      }
520    
521      /**
522       * Clear the may raise an exception property of the block
523       */
524      public final void clearCanThrowExceptions() {
525        flags &= ~CAN_THROW_EXCEPTIONS;
526      }
527    
528      /**
529       * Clear the may raise uncaught exception property of the block
530       */
531      public final void clearMayThrowUncaughtException() {
532        flags &= ~IMPLICIT_EXIT_EDGE;
533      }
534    
535      /**
536       * Clear the block is the first one in an exception handler
537       * property of the block.
538       */
539      public final void clearExceptionHandlerBasicBlock() {
540        flags &= ~EXCEPTION_HANDLER;
541      }
542    
543      /**
544       * Clear the block is reachable from an exception handler
545       * property of the block.
546       */
547      public final void clearReachableFromExceptionHandler() {
548        flags &= ~REACHABLE_FROM_EXCEPTION_HANDLER;
549      }
550    
551      /**
552       * Clear the unsafe to schedule property of the block
553       */
554      public final void clearUnsafeToSchedule() {
555        flags &= ~UNSAFE_TO_SCHEDULE;
556      }
557    
558      /**
559       * Clear the infrequently executed property of the block
560       */
561      public final void clearInfrequent() {
562        flags &= ~INFREQUENT;
563      }
564    
565      /**
566       * Clear the scratch flag.
567       */
568      public final void clearScratchFlag() {
569        flags &= ~SCRATCH;
570      }
571    
572      /**
573       * Clear the landing pad property of the block
574       */
575      public final void clearLandingPad() {
576        flags &= ~LANDING_PAD;
577      }
578    
579      private void setCanThrowExceptions(boolean v) {
580        if (v) {
581          setCanThrowExceptions();
582        } else {
583          clearCanThrowExceptions();
584        }
585      }
586    
587      private void setMayThrowUncaughtException(boolean v) {
588        if (v) {
589          setMayThrowUncaughtException();
590        } else {
591          clearMayThrowUncaughtException();
592        }
593      }
594    
595      @SuppressWarnings("unused")
596      // FIXME can this be deleted ??
597      private void setIsExceptionHandlerBasicBlock(boolean v) {
598        if (v) {
599          setExceptionHandlerBasicBlock();
600        } else {
601          clearExceptionHandlerBasicBlock();
602        }
603      }
604    
605      private void setUnsafeToSchedule(boolean v) {
606        if (v) {
607          setUnsafeToSchedule();
608        } else {
609          clearUnsafeToSchedule();
610        }
611      }
612    
613      final void setInfrequent(boolean v) {
614        if (v) {
615          setInfrequent();
616        } else {
617          clearInfrequent();
618        }
619      }
620    
621      public final void setExceptionHandlerWithNormalIn() {
622        flags |= EXCEPTION_HANDLER_WITH_NORMAL_IN;
623      }
624    
625      public final boolean isExceptionHandlerWithNormalIn() {
626        return (flags & EXCEPTION_HANDLER_WITH_NORMAL_IN) != 0;
627      }
628    
629      /**
630       * Make a branch operand with the label instruction
631       * of this block.
632       *
633       * @return an BranchOperand holding this blocks label
634       */
635      public final BranchOperand makeJumpTarget() {
636        return new BranchOperand(firstInstruction());
637      }
638    
639      /**
640       * Make a GOTO instruction, branching to the first instruction of
641       * this basic block.
642       *
643       * @return a GOTO instruction that jumps to this block
644       */
645      public final Instruction makeGOTO() {
646        return Goto.create(GOTO, makeJumpTarget());
647      }
648    
649      /**
650       * @return the first instruciton of the basic block (the label)
651       */
652      public final Instruction firstInstruction() {
653        return start;
654      }
655    
656      /**
657       * @return the first 'real' instruction of the basic block;
658       *         null if the block is empty
659       */
660      public final Instruction firstRealInstruction() {
661        if (isEmpty()) {
662          return null;
663        } else {
664          return start.getNext();
665        }
666      }
667    
668      /**
669       * @return the last instruction of the basic block (the BBEND)
670       */
671      public final Instruction lastInstruction() {
672        return end;
673      }
674    
675      /**
676       * @return the last 'real' instruction of the basic block;
677       *         null if the block is empty
678       */
679      public final Instruction lastRealInstruction() {
680        if (isEmpty()) {
681          return null;
682        } else {
683          return end.getPrev();
684        }
685      }
686    
687      /**
688       * Return the estimated relative execution frequency of the block
689       */
690      public final float getExecutionFrequency() {
691        return freq;
692      }
693    
694      /**
695       * Set the estimated relative execution frequency of this block.
696       */
697      public final void setExecutionFrequency(float f) {
698        freq = f;
699      }
700    
701      /**
702       * Scale the estimated relative execution frequency of this block.
703       */
704      public final void scaleExecutionFrequency(float f) {
705        freq *= f;
706      }
707    
708      /**
709       * Augment the estimated relative execution frequency of this block.
710       */
711      public final void augmentExecutionFrequency(float f) {
712        freq += f;
713      }
714    
715      /**
716       * Is this block the exit basic block?
717       *
718       * @return <code>true</code> if this block is the EXIT or
719       *         <code>false</code> if it is not
720       */
721      public final boolean isExit() {
722        return start == null;
723      }
724    
725      /**
726       * Forward enumeration of all the instruction in the block.
727       * @return a forward enumeration of the block's instructons.
728       */
729      public final Enumeration<Instruction> forwardInstrEnumerator() {
730        return IREnumeration.forwardIntraBlockIE(firstInstruction(), lastInstruction());
731      }
732    
733      /**
734       * Reverse enumeration of all the instruction in the block.
735       * @return a reverse enumeration of the block's instructons.
736       */
737      public final Enumeration<Instruction> reverseInstrEnumerator() {
738        return IREnumeration.reverseIntraBlockIE(lastInstruction(), firstInstruction());
739      }
740    
741      /**
742       * Forward enumeration of all the real instruction in the block.
743       * @return a forward enumeration of the block's real instructons.
744       */
745      public final Enumeration<Instruction> forwardRealInstrEnumerator() {
746        return IREnumeration.forwardIntraBlockIE(firstRealInstruction(), lastRealInstruction());
747      }
748    
749      /**
750       * Reverse enumeration of all the real instruction in the block.
751       * @return a reverse enumeration of the block's real instructons.
752       */
753      public final Enumeration<Instruction> reverseRealInstrEnumerator() {
754        return IREnumeration.reverseIntraBlockIE(lastRealInstruction(), firstRealInstruction());
755      }
756    
757      /**
758       * How many real instructions does the block contain?
759       * WARNING: This method actually counts the instructions,
760       * thus it has a linear time complexity!
761       *
762       * @return the number of "real" instructions in this basic block.
763       */
764      public int getNumberOfRealInstructions() {
765        int count = 0;
766        for (Enumeration<Instruction> e = forwardRealInstrEnumerator(); e.hasMoreElements(); e.nextElement()) {
767          count++;
768        }
769    
770        return count;
771      }
772    
773      /**
774       * Does this basic block end in a GOTO instruction?
775       *
776       * @return <code>true</code> if the block ends in a GOTO
777       *         or <code>false</code> if it does not
778       */
779      public final boolean hasGoto() {
780        if (isEmpty()) return false;
781        return Goto.conforms(lastRealInstruction()) || MIR_Branch.conforms(lastRealInstruction());
782      }
783    
784      /**
785       * Does this basic block end in a RETURN instruction?
786       *
787       * @return <code>true</code> if the block ends in a RETURN
788       *         or <code>false</code> if it does not
789       */
790      public final boolean hasReturn() {
791        if (isEmpty()) return false;
792        return Return.conforms(lastRealInstruction()) || MIR_Return.conforms(lastRealInstruction());
793      }
794    
795      /**
796       * Does this basic block end in a SWITCH instruction?
797       *
798       * @return <code>true</code> if the block ends in a SWITCH
799       *         or <code>false</code> if it does not
800       */
801      public final boolean hasSwitch() {
802        if (isEmpty()) return false;
803        Instruction s = lastRealInstruction();
804        return TableSwitch.conforms(s) || LowTableSwitch.conforms(s) || LookupSwitch.conforms(s);
805      }
806    
807      /**
808       * Does this basic block contain an explicit athrow instruction?
809       *
810       * @return <code>true</code> if the block ends in an explicit Athrow
811       *         instruction or <code>false</code> if it does not
812       */
813      public final boolean hasAthrowInst() {
814        if (isEmpty()) return false;
815        Instruction s = lastRealInstruction();
816    
817        if (VM.BuildForIA32 && Operators.helper.isAdviseESP(s.operator)) {
818          s = s.getPrev();
819        }
820    
821        if (Athrow.conforms(s)) {
822          return true;
823        }
824        MethodOperand mop = null;
825        if (MIR_Call.conforms(s)) {
826          mop = MIR_Call.getMethod(s);
827        } else if (Call.conforms(s)) {
828          mop = Call.getMethod(s);
829        }
830        return mop != null && mop.getTarget() == Entrypoints.athrowMethod;
831      }
832    
833      /**
834       * Does this basic block end in an explicit trap?
835       *
836       * @return <code>true</code> if the block ends in a an explicit trap
837       *         or <code>false</code> if it does not
838       */
839      public final boolean hasTrap() {
840        if (isEmpty()) return false;
841        Instruction s = lastRealInstruction();
842    
843        return Trap.conforms(s);
844      }
845    
846      /**
847       * Does this basic block end in a call that never returns?
848       * (For example, a call to athrow())
849       *
850       * @return <code>true</code> if the block ends in a call that never
851       *         returns or <code>false</code> if it does not
852       */
853      public final boolean hasNonReturningCall() {
854        if (isEmpty()) return false;
855        Instruction s = lastRealInstruction();
856    
857        if (Call.conforms(s)) {
858          MethodOperand methodOp = Call.getMethod(s);
859          if (methodOp != null && methodOp.isNonReturningCall()) {
860            return true;
861          }
862        }
863    
864        return false;
865      }
866    
867      public final boolean hasNonReturningOsr() {
868        if (isEmpty()) return false;
869        Instruction s = lastRealInstruction();
870        return OsrPoint.conforms(s);
871      }
872    
873      /**
874       * If there is a fallthrough FCFG successor of this node
875       * return it.
876       *
877       * @return the fall-through successor of this node or
878       *         <code>null</code> if none exists
879       */
880      public final BasicBlock getFallThroughBlock() {
881        if (hasGoto()) return null;
882        if (hasSwitch()) return null;
883        if (hasReturn()) return null;
884        if (hasAthrowInst()) return null;
885        if (hasTrap()) return null;
886        if (hasNonReturningCall()) return null;
887        if (hasNonReturningOsr()) return null;
888    
889        return nextBasicBlockInCodeOrder();
890      }
891    
892      /**
893       * @return the FCFG successor if all conditional branches in this are
894       * <em> not </em> taken
895       */
896      public final BasicBlock getNotTakenNextBlock() {
897        Instruction last = lastRealInstruction();
898        if (Goto.conforms(last) || MIR_Branch.conforms(last)) {
899          return last.getBranchTarget();
900        } else {
901          return nextBasicBlockInCodeOrder();
902        }
903      }
904    
905      /**
906       * Replace fall through in this block by an explicit goto
907       */
908      public void killFallThrough() {
909        BasicBlock fallThrough = getFallThroughBlock();
910        if (fallThrough != null) {
911          lastInstruction().insertBefore(Goto.create(GOTO, fallThrough.makeJumpTarget()));
912        }
913      }
914    
915      /**
916       * Prepend instruction to this basic block by inserting it right after
917       * the LABEL instruction in the instruction list.
918       *
919       * @param i instruction to append
920       */
921      public final void prependInstruction(Instruction i) {
922        start.insertAfter(i);
923      }
924    
925      /**
926       * Prepend instruction to this basic block but respect the prologue
927       * instruction, which must come first.
928       *
929       * @param i instruction to append
930       */
931      public final void prependInstructionRespectingPrologue(Instruction i) {
932        Instruction first = firstRealInstruction();
933        if ((first != null) && (first.getOpcode() == IR_PROLOGUE_opcode)) {
934          first.insertAfter(i);
935        } else {
936          start.insertAfter(i);
937        }
938      }
939    
940      /**
941       * Append instruction to this basic block by inserting it right before
942       * the BBEND instruction in the instruction list.
943       *
944       * @param i instruction to append
945       */
946      public final void appendInstruction(Instruction i) {
947        end.insertBefore(i);
948      }
949    
950      /**
951       * Append instruction to this basic block by inserting it right before
952       * the BBEND instruction in the instruction list. However, if
953       * the basic block ends in a sequence of branch instructions, insert
954       * the instruction before the first branch instruction.
955       *
956       * @param i instruction to append
957       */
958      public final void appendInstructionRespectingTerminalBranch(Instruction i) {
959        Instruction s = end;
960        while (s.getPrev().operator().isBranch()) s = s.getPrev();
961        s.insertBefore(i);
962      }
963    
964      /**
965       * Append instruction to this basic block by inserting it right before
966       * the BBEND instruction in the instruction list. However, if
967       * the basic block ends in a sequence of branch instructions, insert
968       * the instruction before the first branch instruction. If the block
969       * ends in a PEI, insert the instruction before the PEI.
970       * This function is meant to be used when the block has
971       * been {@link #unfactor(IR) unfactored} and thus is in CFG form.
972       *
973       * @param i instruction to append
974       */
975      public final void appendInstructionRespectingTerminalBranchOrPEI(Instruction i) {
976        Instruction s = end;
977        while (s.getPrev().operator().isBranch() ||
978               s.getPrev().operator().isThrow() ||
979               (s.getPrev().isPEI() && getApplicableExceptionalOut(s.getPrev()).hasMoreElements())) {
980          s = s.getPrev();
981        }
982        s.insertBefore(i);
983      }
984    
985      /**
986       * Return an enumeration of the branch instructions in this
987       * basic block.
988       * @return an forward enumeration of this blocks branch instruction
989       */
990      public final Enumeration<Instruction> enumerateBranchInstructions() {
991        Instruction start = firstBranchInstruction();
992        Instruction end = (start == null) ? null : lastRealInstruction();
993        return IREnumeration.forwardIntraBlockIE(start, end);
994      }
995    
996      /**
997       * Return the first branch instruction in the block.
998       *
999       * @return the first branch instruction in the block
1000       *         or <code>null</code> if there are none.
1001       */
1002      public final Instruction firstBranchInstruction() {
1003        Instruction s = lastRealInstruction();
1004        if (s == null) return null;
1005        if (!s.operator().isBranch()) return null;
1006        while (s.getPrev().isBranch()) {
1007          s = s.getPrev();
1008        }
1009        return s;
1010      }
1011    
1012      /**
1013       * Return the next basic block in with respect to the current
1014       * code linearization order.
1015       *
1016       * @return the next basic block in the code order or
1017       *         <code>null</code> if no such block exists
1018       */
1019      public final BasicBlock nextBasicBlockInCodeOrder() {
1020        return (BasicBlock) getNext();
1021      }
1022    
1023      /**
1024       * Return the previous basic block in with respect to the current
1025       * code linearization order.
1026       *
1027       * @return the previous basic block in the code order or
1028       *         <code>null</code> if no such block exists
1029       */
1030      public final BasicBlock prevBasicBlockInCodeOrder() {
1031        return (BasicBlock) getPrev();
1032      }
1033    
1034      /**
1035       * Returns true if the block contains no real instructions
1036       *
1037       * @return <code>true</code> if the block contains no real instructions
1038       *         or <code>false</code> if it does.
1039       */
1040      public final boolean isEmpty() {
1041        return start.getNext() == end;
1042      }
1043    
1044      /**
1045       * Are there any exceptional out edges that are applicable
1046       * to the given instruction (assumed to be in instruction in 'this')
1047       *
1048       * @param instr the instruction in question
1049       * @return true or false;
1050       */
1051      public final boolean hasApplicableExceptionalOut(Instruction instr) {
1052        return getApplicableExceptionalOut(instr).hasMoreElements();
1053      }
1054    
1055      /**
1056       * An enumeration of the subset of exceptional out edges that are applicable
1057       * to the given instruction (assumed to be in instruction in 'this')
1058       *
1059       * @param instr the instruction in question
1060       * @return an enumeration of the exceptional out edges applicable to instr
1061       */
1062      public final Enumeration<BasicBlock> getApplicableExceptionalOut(Instruction instr) {
1063        if (instr.isPEI()) {
1064          int numPossible = getNumberOfExceptionalOut();
1065          if (numPossible == 0) return EmptyEnumeration.<BasicBlock>emptyEnumeration();
1066          ComputedBBEnum e = new ComputedBBEnum(numPossible);
1067          switch (instr.getOpcode()) {
1068            case ATHROW_opcode:
1069              TypeReference type = Athrow.getValue(instr).getType();
1070              addTargets(e, type);
1071              break;
1072            case CHECKCAST_opcode:
1073            case CHECKCAST_NOTNULL_opcode:
1074            case CHECKCAST_UNRESOLVED_opcode:
1075              addTargets(e, TypeReference.JavaLangClassCastException);
1076              break;
1077            case NULL_CHECK_opcode:
1078              addTargets(e, TypeReference.JavaLangNullPointerException);
1079              break;
1080            case BOUNDS_CHECK_opcode:
1081              addTargets(e, TypeReference.JavaLangArrayIndexOutOfBoundsException);
1082              break;
1083            case INT_ZERO_CHECK_opcode:
1084            case LONG_ZERO_CHECK_opcode:
1085              addTargets(e, TypeReference.JavaLangArithmeticException);
1086              break;
1087            case OBJARRAY_STORE_CHECK_opcode:
1088              addTargets(e, TypeReference.JavaLangArrayStoreException);
1089              break;
1090            default:
1091              // Not an operator for which we have a more refined notion of
1092              // its exception semantics, so assume that any reachable exception
1093              // handler might be a potential target of this PEI
1094              return getExceptionalOut();
1095          }
1096          return e;
1097        } else {
1098          return EmptyEnumeration.<BasicBlock>emptyEnumeration();
1099        }
1100      }
1101    
1102      // add all handler blocks in this's out set that might possibly catch
1103      // an exception of static type throwException
1104      // (may dynamically be any subtype of thrownException)
1105      private void addTargets(ComputedBBEnum e, TypeReference thrownException) {
1106        for (SpaceEffGraphEdge ed = _outEdgeStart; ed != null; ed = ed.getNextOut()) {
1107          BasicBlock bb = (BasicBlock) ed.toNode();
1108          if (bb.isExceptionHandlerBasicBlock()) {
1109            ExceptionHandlerBasicBlock eblock = (ExceptionHandlerBasicBlock) bb;
1110            if (eblock.mayCatchException(thrownException) != NO) {
1111              e.addPossiblyDuplicateElement(eblock);
1112            }
1113          }
1114        }
1115      }
1116    
1117      /**
1118       * An enumeration of the in scope exception handlers for this basic block.
1119       * Note that this may be a superset of the exception handlers
1120       * actually included in the out set of this basic block.
1121       *
1122       * @return an enumeration of all inscope exception handlers
1123       */
1124      public final Enumeration<BasicBlock> getExceptionHandlers() {
1125        if (exceptionHandlers == null) {
1126          return EmptyEnumeration.<BasicBlock>emptyEnumeration();
1127        } else {
1128          return exceptionHandlers.enumerator();
1129        }
1130      }
1131    
1132      /**
1133       * Is this block in the scope of at least exception handler?
1134       *
1135       * @return <code>true</code> if there is at least one in scope
1136       *         exception handler, <code>false</code> otherwise
1137       */
1138      public final boolean hasExceptionHandlers() {
1139        return exceptionHandlers != null;
1140      }
1141    
1142      /**
1143       * Returns an Enumeration of the in scope exception handlers that are
1144       * actually reachable from this basic block in the order that they are
1145       * applicable (which is semantically meaningful).
1146       * IE, this is those blocks in getExceptionalOut ordered as
1147       * in getExceptionHandlers.
1148       *
1149       * @return an enumeration of the reachable exception handlers
1150       */
1151      public final Enumeration<BasicBlock> getReachableExceptionHandlers() {
1152        if (hasExceptionHandlers()) {
1153          int count = 0;
1154          for (Enumeration<BasicBlock> inScope = getExceptionHandlers(); inScope.hasMoreElements(); inScope.nextElement()) {
1155            count++;
1156          }
1157    
1158          ComputedBBEnum ans = new ComputedBBEnum(count);
1159    
1160          for (Enumeration<BasicBlock> inScope = getExceptionHandlers(); inScope.hasMoreElements();) {
1161            BasicBlock cand = inScope.nextElement();
1162            if (pointsOut(cand)) ans.addPossiblyDuplicateElement(cand);
1163          }
1164          return ans;
1165        } else {
1166          return EmptyEnumeration.<BasicBlock>emptyEnumeration();
1167        }
1168      }
1169    
1170      /**
1171       * Delete all the non-exceptional out edges.
1172       * A useful primitive routine for some CFG manipulations.
1173       */
1174      public final void deleteNormalOut() {
1175        for (SpaceEffGraphEdge e = _outEdgeStart; e != null; e = e.getNextOut()) {
1176          BasicBlock out = (BasicBlock) e.toNode();
1177          if (!out.isExceptionHandlerBasicBlock()) {
1178            deleteOut(e);
1179          }
1180        }
1181      }
1182    
1183      /**
1184       * Recompute the normal out edges of 'this' based on the
1185       * semantics of the branch instructions in the block.<p>
1186       *
1187       * WARNING: Use this method with caution.  It does not update the
1188       * CFG edges correctly if the method contains certain instructions
1189       * such as throws and returns.  Incorrect liveness info and GC maps
1190       * result, causing crashes during GC.<p>
1191       *
1192       * TODO check if warning is still current and if there's info on
1193       *  CMVC Defect 171189 anywhere
1194       */
1195      public final void recomputeNormalOut(IR ir) {
1196        deleteNormalOut();
1197        for (Enumeration<Instruction> e = enumerateBranchInstructions(); e.hasMoreElements();) {
1198          Instruction branch = e.nextElement();
1199          Enumeration<BasicBlock> targets = branch.getBranchTargets();
1200          while (targets.hasMoreElements()) {
1201            BasicBlock targetBlock = targets.nextElement();
1202            if (targetBlock.isExceptionHandlerBasicBlock()) {
1203              targetBlock.setExceptionHandlerWithNormalIn();
1204            }
1205            insertOut(targetBlock);
1206          }
1207        }
1208        // Check for fallthrough edge
1209        BasicBlock fallThrough = getFallThroughBlock();
1210        if (fallThrough != null) {
1211          if (fallThrough.isExceptionHandlerBasicBlock()) {
1212            fallThrough.setExceptionHandlerWithNormalIn();
1213          }
1214          insertOut(fallThrough);
1215        }
1216    
1217        // Check special cases that require edge to exit
1218        if (hasReturn()) {
1219          insertOut(ir.cfg.exit());
1220        } else if (hasAthrowInst() || hasNonReturningCall()) {
1221          if (mayThrowUncaughtException()) {
1222            insertOut(ir.cfg.exit());
1223          }
1224        } else if (hasNonReturningOsr()) {
1225          insertOut(ir.cfg.exit());
1226        }
1227      }
1228    
1229      /**
1230       * Ensure that the target instruction is the only real instruction
1231       * in its basic block and that it has exactly one successor and
1232       * one predecessor basic blocks that are linked to it by fall through edges.
1233       *
1234       * @param target the Instruction that must be placed in its own BB
1235       * @param ir the containing IR object
1236       * @return the BasicBlock containing target
1237       */
1238      public final BasicBlock segregateInstruction(Instruction target, IR ir) {
1239        if (IR.PARANOID) VM._assert(this == target.getBasicBlock());
1240    
1241        BasicBlock BB1 = splitNodeAt(target.getPrev(), ir);
1242        this.insertOut(BB1);
1243        ir.cfg.linkInCodeOrder(this, BB1);
1244        BasicBlock BB2 = BB1.splitNodeAt(target, ir);
1245        BB1.insertOut(BB2);
1246        ir.cfg.linkInCodeOrder(BB1, BB2);
1247        return BB1;
1248      }
1249    
1250      /**
1251       * Splits a node at an instruction point.  All the instructions up to and
1252       * including the argument instruction remain in the original basic block.
1253       * All instructions in this basic block but after s in the instruction list
1254       * are moved to the new basic block.
1255       * <ul>
1256       * <li> does not establish control flow edge out of B1 -- caller responsibility
1257       * <li> does not establish control flow edge into B2 -- caller responsibility
1258       * <li> Leaves a break in the code order -- caller responsibility
1259       *      to patch back together. If the original code order was
1260       *      BB_before -> BB1 -> BB_after
1261       *      then the new code order is
1262       *      BB_before -> BB1 <break> BB2 -> BB_after.
1263       *      Note that if BB_after == null, splitNodeAt does handle
1264       *      updating ir.cfg._lastNode to point to BB2.
1265       * </ul>
1266       *
1267       * @param last_instr_BB1 the instr that is to become the last instruction
1268       *                       in this basic block
1269       * @param ir             the containing IR object
1270       * @return the newly created basic block which is the successor to this
1271       */
1272      public final BasicBlock splitNodeAt(Instruction last_instr_BB1, IR ir) {
1273        if (IR.PARANOID) VM._assert(this == last_instr_BB1.getBasicBlock());
1274    
1275        BasicBlock BB1 = this;
1276        BasicBlock BB2 = new BasicBlock(last_instr_BB1.bcIndex, last_instr_BB1.position, ir.cfg);
1277        BasicBlock BB3 = (BasicBlock) BB1.next;
1278    
1279        // move last_instr_BB1 ... BB1.end.prev into BB2
1280        if (last_instr_BB1 == BB1.end || last_instr_BB1.getNext() == BB1.end) {
1281          // there are no such instructions; nothing to do
1282        } else {
1283          Instruction first_instr_BB2 = last_instr_BB1.getNext();
1284          Instruction last_instr_BB2 = BB1.end.getPrev();
1285          last_instr_BB1.linkWithNext(BB1.end);
1286          BB2.start.linkWithNext(first_instr_BB2);
1287          last_instr_BB2.linkWithNext(BB2.end);
1288        }
1289    
1290        // Update code ordering (see header comment above)
1291        if (BB3 == null) {
1292          ir.cfg.addLastInCodeOrder(BB2);
1293          if (IR.PARANOID) VM._assert(BB1.next == BB2 && BB2.prev == BB1);
1294          ir.cfg.breakCodeOrder(BB1, BB2);
1295        } else {
1296          ir.cfg.breakCodeOrder(BB1, BB3);
1297          ir.cfg.linkInCodeOrder(BB2, BB3);
1298        }
1299    
1300        // Update control flow graph to transfer BB1's out edges to BB2.
1301        // But it's not as simple as that.  Any edge that is present to represent
1302        // potential exception behavior (out.isExceptionHandlerBasicBlock == true)
1303        // needs to be both left in BB1's out set and transfered to BB2's out set
1304        // Note this may be overly conservative, but will be correct.
1305        for (Enumeration<BasicBlock> e = getOut(); e.hasMoreElements();) {
1306          BasicBlock out = e.nextElement();
1307          BB2.insertOut(out);
1308        }
1309    
1310        // Initialize the rest of BB2's exception related state to match BB1
1311        BB2.exceptionHandlers = BB1.exceptionHandlers;
1312        BB2.setCanThrowExceptions(BB1.canThrowExceptions());
1313        BB2.setMayThrowUncaughtException(BB1.mayThrowUncaughtException());
1314        BB2.setUnsafeToSchedule(BB1.isUnsafeToSchedule());
1315        BB2.setExecutionFrequency(BB1.getExecutionFrequency());
1316    
1317        BB1.deleteNormalOut();
1318    
1319        return BB2;
1320      }
1321    
1322      /**
1323       * Splits a node at an instruction point. All the instructions up to and
1324       * including the argument instruction remain in the original basic block
1325       * all instructions in this basic block but after s in the instruction list
1326       * are moved to the new basic block. The blocks are linked together in
1327       * the FCFG and the code order.
1328       * The key difference between this function and
1329       * {@link #splitNodeAt(Instruction,IR)} is that it does
1330       * establish the FCFG edges and code order such that B1 falls into B2.
1331       *
1332       * @param last_instr_BB1 the instr that is to become
1333       *                       the last instruction in this basic block
1334       * @param ir             the containing IR object
1335       * @return the newly created basic block which is the successor to this
1336       */
1337      public final BasicBlock splitNodeWithLinksAt(Instruction last_instr_BB1, IR ir) {
1338    
1339        if (IR.PARANOID) VM._assert(this == last_instr_BB1.getBasicBlock());
1340    
1341        BasicBlock BB2 = splitNodeAt(last_instr_BB1, ir);
1342        this.insertOut(BB2);
1343        ir.cfg.linkInCodeOrder(this, BB2);
1344        return BB2;
1345      }
1346    
1347      /**
1348       * Copies a basic block. The copy differs from the original as follows:
1349       * <ul>
1350       * <li> the copy's number and labels are new, and will be unique in the
1351       *      containing IR
1352       * <li> the copy is NOT linked into the IR's bblist
1353       * <li> the copy does NOT appear in the IR's cfg.
1354       * </ul>
1355       * The copy
1356       * <ul>
1357       * <li> inherits the original block's exception handlers
1358       * <li> inherits the original block's bytecode index
1359       * <li> has NEW copies of each instruction.
1360       *
1361       * @param ir the containing IR
1362       * @return the copy
1363       */
1364      public final BasicBlock copyWithoutLinks(IR ir) {
1365        // create a new block with the same bytecode index and exception handlers
1366        int bytecodeIndex = -1;
1367    
1368        // Make the label instruction of the new block have the same
1369        // bc info as the label of the original block.
1370        if (firstInstruction() != null) {
1371          bytecodeIndex = firstInstruction().bcIndex;
1372        }
1373    
1374        BasicBlock newBlock = createSubBlock(bytecodeIndex, ir, 1f);
1375    
1376        // copy each instruction from the original block.
1377        for (Instruction s = firstInstruction().getNext(); s != lastInstruction(); s = s.getNext()) {
1378          newBlock.appendInstruction(s.copyWithoutLinks());
1379        }
1380    
1381        // copy other properties of the block.
1382        newBlock.flags = flags;
1383    
1384        return newBlock;
1385      }
1386    
1387      /**
1388       * For each basic block b which is a "normal" successor of this,
1389       * make a copy of b, and set up the CFG so that this block has
1390       * normal out edges to the copies.<p>
1391       *
1392       * WARNING: Use this method with caution.  See comment on
1393       * BasicBlock.recomputeNormalOut()
1394       *
1395       * @param ir the containing IR
1396       */
1397      public final void replicateNormalOut(IR ir) {
1398        // for each normal out successor (b) of 'this' ....
1399        for (Enumeration<BasicBlock> e = getNormalOut(); e.hasMoreElements();) {
1400          BasicBlock b = e.nextElement();
1401          replicateThisOut(ir, b);
1402        }
1403      }
1404    
1405      /**
1406       * For basic block b which has to be a "normal" successor of this,
1407       * make a copy of b, and set up the CFG so that this block has
1408       * normal out edges to the copy.<p>
1409       *
1410       * WARNING: Use this method with caution.  See comment on
1411       * BasicBlock.recomputeNormalOut()
1412       *
1413       * @param ir the governing IR
1414       * @param b the block to replicate
1415       */
1416      public final BasicBlock replicateThisOut(IR ir, BasicBlock b) {
1417        return replicateThisOut(ir, b, this);
1418      }
1419    
1420      /**
1421       * For basic block b which has to be a "normal" successor of this,
1422       * make a copy of b, and set up the CFG so that this block has
1423       * normal out edges to the copy.<p>
1424       *
1425       * WARNING: Use this method with caution.  See comment on
1426       * BasicBlock.recomputeNormalOut()
1427       *
1428       * @param ir the governing IR
1429       * @param b the block to replicate
1430       * @param pred code order predecessor for new block
1431       */
1432      public final BasicBlock replicateThisOut(IR ir, BasicBlock b, BasicBlock pred) {
1433        // don't replicate the exit node
1434        if (b.isExit()) return null;
1435    
1436        // 1. create the replicated block (bCopy)
1437        BasicBlock bCopy = b.copyWithoutLinks(ir);
1438    
1439        // 2. If b has a fall-through edge, insert the appropriate GOTO at
1440        // the end of bCopy
1441        BasicBlock bFallThrough = b.getFallThroughBlock();
1442        if (bFallThrough != null) {
1443          Instruction g = Goto.create(GOTO, bFallThrough.makeJumpTarget());
1444          bCopy.appendInstruction(g);
1445        }
1446        bCopy.recomputeNormalOut(ir);
1447    
1448        // 3. update the branch instructions in 'this' to point to bCopy
1449        redirectOuts(b, bCopy, ir);
1450    
1451        // 4. link the new basic into the code order, immediately following pred
1452        pred.killFallThrough();
1453        BasicBlock next = pred.nextBasicBlockInCodeOrder();
1454        if (next != null) {
1455          ir.cfg.breakCodeOrder(pred, next);
1456          ir.cfg.linkInCodeOrder(bCopy, next);
1457        }
1458        ir.cfg.linkInCodeOrder(pred, bCopy);
1459    
1460        return bCopy;
1461      }
1462    
1463      /**
1464       * Move me behind `pred'.
1465       *
1466       * @param pred my desired code order predecessor
1467       * @param ir the governing IR
1468       */
1469      public void moveBehind(BasicBlock pred, IR ir) {
1470        killFallThrough();
1471        pred.killFallThrough();
1472        BasicBlock thisPred = prevBasicBlockInCodeOrder();
1473        BasicBlock thisSucc = nextBasicBlockInCodeOrder();
1474        if (thisPred != null) {
1475          thisPred.killFallThrough();
1476          ir.cfg.breakCodeOrder(thisPred, this);
1477        }
1478        if (thisSucc != null) ir.cfg.breakCodeOrder(this, thisSucc);
1479    
1480        if (thisPred != null && thisSucc != null) {
1481          ir.cfg.linkInCodeOrder(thisPred, thisSucc);
1482        }
1483    
1484        thisPred = pred;
1485        thisSucc = pred.nextBasicBlockInCodeOrder();
1486    
1487        if (thisSucc != null) {
1488          ir.cfg.breakCodeOrder(thisPred, thisSucc);
1489          ir.cfg.linkInCodeOrder(this, thisSucc);
1490        }
1491        ir.cfg.linkInCodeOrder(thisPred, this);
1492      }
1493    
1494      /**
1495       * Change all branches from this to b to branches that go to bCopy instead.
1496       * This method also handles this.fallThrough, so `this' should still be in
1497       * the code order when this method is called.<p>
1498       *
1499       * WARNING: Use this method with caution.  See comment on
1500       * BasicBlock.recomputeNormalOut()
1501       *
1502       * @param b     the original target
1503       * @param bCopy the future target
1504       */
1505      public final void redirectOuts(BasicBlock b, BasicBlock bCopy, IR ir) {
1506        BranchOperand copyTarget = bCopy.makeJumpTarget();
1507        BranchOperand bTarget = b.makeJumpTarget();
1508        // 1. update the branch instructions in 'this' to point to bCopy
1509        for (Enumeration<Instruction> ie = enumerateBranchInstructions(); ie.hasMoreElements();) {
1510          Instruction s = ie.nextElement();
1511          s.replaceSimilarOperands(bTarget, copyTarget);
1512        }
1513    
1514        // 2. if this falls through to b, make it jump to bCopy
1515        if (getFallThroughBlock() == b) {
1516          Instruction g = Goto.create(GOTO, copyTarget); //no copy needed.
1517          appendInstruction(g);
1518        }
1519    
1520        // 3. recompute normal control flow edges.
1521        recomputeNormalOut(ir);
1522      }
1523    
1524      /*
1525       * TODO: work on eliminating this method by converting callers to
1526       *       three argument form
1527       */
1528      public final BasicBlock createSubBlock(int bc, IR ir) {
1529        return createSubBlock(bc, ir, 1f);
1530      }
1531    
1532      /**
1533       * Creates a new basic block that inherits its exception handling,
1534       * etc from 'this'. This method is intended to be used in conjunction
1535       * with splitNodeAt when splitting instructions in one original block
1536       * into a sequence of sublocks
1537       *
1538       * @param bc the bytecode index to start the block
1539       * @param ir the containing IR
1540       * @param wf the fraction of this's execution frequency that should be
1541       *           inherited by the new block. In the range [0.0, 1.0]
1542       * @return the new empty BBlock
1543       */
1544      public final BasicBlock createSubBlock(int bc, IR ir, float wf) {
1545        // For now, give the basic block the same inline context as the
1546        // original block.
1547        // TODO: This won't always work. (In fact, in the presence of inlining
1548        //       it will be wrong quite often). --dave
1549        //       We really have to pass the position in if we except this to work.
1550        BasicBlock temp = new BasicBlock(bc, firstInstruction().position, ir.cfg);
1551    
1552        // Conservatively transfer all exception handling behavior of the
1553        // parent block  (this) to the new child block (temp)
1554        temp.exceptionHandlers = exceptionHandlers;
1555        temp.setCanThrowExceptions(canThrowExceptions());
1556        temp.setMayThrowUncaughtException(mayThrowUncaughtException());
1557        temp.setUnsafeToSchedule(isUnsafeToSchedule());
1558        temp.setExecutionFrequency(getExecutionFrequency() * wf);
1559        for (Enumeration<BasicBlock> e = getOut(); e.hasMoreElements();) {
1560          BasicBlock out = e.nextElement();
1561          if (out.isExceptionHandlerBasicBlock()) {
1562            temp.insertOut(out);
1563          }
1564        }
1565    
1566        return temp;
1567      }
1568    
1569      /**
1570       * If this block has a single non-Exception successor in the CFG
1571       * then we may be able to merge the two blocks together.
1572       * In order for this to be legal, it must be the case that:
1573       * <ol>
1574       *  <li>The successor block has no other in edges than the one from this.
1575       *  <li>Both blocks have the same exception handlers.
1576       * </ol>
1577       * Merging the blocks is always desirable when
1578       * <ol>
1579       *  <li>the successor block is the next block in code order
1580       *  <li>the successor block is not the next block in the code order,
1581       *      but ends in an unconditional branch (ie it doesn't have a
1582       *      fallthrough successor in the code order that we could be screwing up).
1583       * </ol>
1584       *
1585       * @param ir the IR object containing the basic block to be merged
1586       * @return <code>true</code> if  the block was merged or
1587       *         <code>false</code> otherwise
1588       */
1589      public final boolean mergeFallThrough(IR ir) {
1590        if (getNumberOfNormalOut() != 1) return false; // this has other out edges.
1591        BasicBlock succBB = (BasicBlock) next;
1592        if (succBB == null || !pointsOut(succBB)) {
1593          // get the successor from the CFG rather than the code order (case (b))
1594          succBB = getNormalOut().nextElement();
1595          if (succBB.isExit()) return false;
1596          if (succBB.lastRealInstruction() == null || !succBB.lastRealInstruction().isUnconditionalBranch()) {
1597            return false;
1598          }
1599        }
1600    
1601        if (succBB.isExceptionHandlerBasicBlock()) return false; // must preserve special exception info!
1602        if (succBB.getNumberOfIn() != 1) return false; // succBB has other in edges
1603    
1604        // Different in scope Exception handlers?
1605        if (!isExceptionHandlerEquivalent(succBB)) return false;
1606    
1607        // There may be a redundant goto at the end of this -- remove it.
1608        // There may also be redundant conditional branches (also to succBB).
1609        // Remove them as well.
1610        // Branch instructions to blocks other than succBB are errors.
1611        if (VM.VerifyAssertions) {
1612          for (Enumeration<Instruction> e = enumerateBranchInstructions(); e.hasMoreElements();) {
1613            Enumeration<BasicBlock> targets = e.nextElement().getBranchTargets();
1614            while (targets.hasMoreElements()) {
1615              BasicBlock target = targets.nextElement();
1616              VM._assert(target == succBB);
1617            }
1618          }
1619        }
1620        Instruction s = this.end.getPrev();
1621        while (s.isBranch()) {
1622          s = s.remove();
1623        }
1624    
1625        // splice together the instruction lists of the two basic blocks into
1626        // a single list and update this's BBEND info
1627        this.end.getPrev().linkWithNext(succBB.start.getNext());
1628        succBB.end.getPrev().linkWithNext(this.end);
1629    
1630        // Add succBB's CFG sucessors to this's CFG out edges
1631        for (OutEdgeEnum e = succBB.getOut(); e.hasMoreElements();) {
1632          BasicBlock out = e.nextElement();
1633          this.insertOut(out);
1634        }
1635    
1636        // Blow away sucBB.
1637        ir.cfg.removeFromCFGAndCodeOrder(succBB);
1638    
1639        // Merge misc BB state
1640        setCanThrowExceptions(canThrowExceptions() || succBB.canThrowExceptions());
1641        setMayThrowUncaughtException(mayThrowUncaughtException() || succBB.mayThrowUncaughtException());
1642        setUnsafeToSchedule(isUnsafeToSchedule() || succBB.isUnsafeToSchedule());
1643        if (succBB.getInfrequent()) setInfrequent();
1644    
1645        return true;
1646      }
1647    
1648      /**
1649       * Convert a block in the FCFG into the equivalent set of
1650       * CFG blocks by splitting the original block into sub-blocks
1651       * at each PEI that reaches at least one exception handelr.
1652       * NOTE: This is sufficient for intraprocedural analysis, since the
1653       * only program point at which the "wrong" answers will
1654       * be computed is the exit node, but is not good enough for
1655       * interprocedural analyses.  To do an interprocedural analysis,
1656       * either the analysis needs to deal with the FCFG or all nodes
1657       * that modify globally visible state must be unfactored.
1658       * @see IR#unfactor
1659       * @param ir the containing IR object
1660       */
1661      final void unfactor(IR ir) {
1662        for (Enumeration<Instruction> e = forwardRealInstrEnumerator(); e.hasMoreElements();) {
1663          Instruction s = e.nextElement();
1664          Enumeration<BasicBlock> expOuts = getApplicableExceptionalOut(s);
1665          if (expOuts.hasMoreElements() && e.hasMoreElements()) {
1666            BasicBlock next = splitNodeWithLinksAt(s, ir);
1667            next.unfactor(ir);
1668            pruneExceptionalOut(ir);
1669            return;
1670          }
1671        }
1672      }
1673    
1674      /**
1675       * Prune away exceptional out edges that are not reachable given this
1676       * block's instructions.
1677       */
1678      final void pruneExceptionalOut(IR ir) {
1679        int n = getNumberOfExceptionalOut();
1680        if (n > 0) {
1681          ComputedBBEnum handlers = new ComputedBBEnum(n);
1682          Enumeration<Instruction> e = forwardRealInstrEnumerator();
1683          while (e.hasMoreElements()) {
1684            Instruction x = e.nextElement();
1685            Enumeration<BasicBlock> bbs = getApplicableExceptionalOut(x);
1686            while (bbs.hasMoreElements()) {
1687              BasicBlock bb = bbs.nextElement();
1688              handlers.addPossiblyDuplicateElement(bb);
1689            }
1690          }
1691    
1692          deleteExceptionalOut();
1693    
1694          for (int i = 0; handlers.hasMoreElements(); i++) {
1695            ExceptionHandlerBasicBlock b = (ExceptionHandlerBasicBlock) handlers.nextElement();
1696            insertOut(b);
1697          }
1698        }
1699    
1700        // Since any edge to an exception handler is an "exceptional" edge,
1701        // the previous procedure has thrown away any "normal" CFG edges to
1702        // exception handlers.  So, recompute normal edges to recover them.
1703        recomputeNormalOut(ir);
1704    
1705      }
1706    
1707      // helper function for unfactor
1708      private void deleteExceptionalOut() {
1709        for (SpaceEffGraphEdge e = _outEdgeStart; e != null; e = e.getNextOut()) {
1710          BasicBlock out = (BasicBlock) e.toNode();
1711          if (out.isExceptionHandlerBasicBlock()) {
1712            deleteOut(e);
1713          }
1714        }
1715      }
1716    
1717      /**
1718       * An enumeration of the FCFG in nodes.
1719       *
1720       * @return an enumeration of the in nodes
1721       */
1722      public final Enumeration<BasicBlock> getIn() {
1723        return new InEdgeEnum(this);
1724      }
1725    
1726      /**
1727       * An enumeration of the FCFG in nodes.
1728       *
1729       * @return an enumeration of the in nodes
1730       */
1731      @Override
1732      public final Enumeration<BasicBlock> getInNodes() {
1733        return new InEdgeEnum(this);
1734      }
1735    
1736      /**
1737       * Is there an in edge from the given basic block?
1738       *
1739       * @param bb basic block in question
1740       * @return <code>true</code> if an in edge exists from bb
1741       *         <code>false</code> otherwise
1742       */
1743      public final boolean isIn(BasicBlock bb) {
1744        InEdgeEnum iee = new InEdgeEnum(this);
1745        while (iee.hasMoreElements()) {
1746          if (iee.nextElement() == bb) {
1747            return true;
1748          }
1749        }
1750        return false;
1751      }
1752    
1753      /**
1754       * An enumeration of the FCFG out nodes.
1755       *
1756       * @return an enumeration of the out nodes
1757       */
1758      public final OutEdgeEnum getOut() {
1759        return new OutEdgeEnum(this);
1760      }
1761    
1762      /**
1763       * An enumeration of the FCFG out nodes.
1764       *
1765       * @return an enumeration of the out nodes
1766       */
1767      @Override
1768      public final OutEdgeEnum getOutNodes() {
1769        return new OutEdgeEnum(this);
1770      }
1771    
1772      /**
1773       * Is there an out edge to the given basic block?
1774       *
1775       * @param bb basic block in question
1776       * @return <code>true</code> if an out edge exists to bb
1777       *         <code>false</code> otherwise
1778       */
1779      public final boolean isOut(BasicBlock bb) {
1780        OutEdgeEnum oee = new OutEdgeEnum(this);
1781        while (oee.hasMoreElements()) {
1782          if (oee.nextElement() == bb) {
1783            return true;
1784          }
1785        }
1786        return false;
1787      }
1788    
1789      /**
1790       * An enumeration of the 'normal' (not reached via exceptional control flow)
1791       * out nodes of the block.
1792       *
1793       * @return an enumeration of the out nodes that are not
1794       *         reachable via as a result of exceptional control flow
1795       */
1796      public final Enumeration<BasicBlock> getNormalOut() {
1797        return new NormalOutEdgeEnum(this);
1798      }
1799    
1800      /**
1801       * Is there a 'normal' out edge to the given basic block?
1802       *
1803       * @param bb basic block in question
1804       * @return <code>true</code> if a normal out edge exists to bb
1805       *         <code>false</code> otherwise
1806       */
1807      public final boolean isNormalOut(BasicBlock bb) {
1808        NormalOutEdgeEnum noee = new NormalOutEdgeEnum(this);
1809        while (noee.hasMoreElements()) {
1810          if (noee.nextElement() == bb) {
1811            return true;
1812          }
1813        }
1814        return false;
1815      }
1816    
1817      /**
1818       * An enumeration of the 'exceptional' (reached via exceptional control flow)
1819       * out nodes of the block.
1820       *
1821       * @return an enumeration of the out nodes that are
1822       *         reachable via as a result of exceptional control flow
1823       */
1824      public final Enumeration<BasicBlock> getExceptionalOut() {
1825        if (canThrowExceptions()) {
1826          return new ExceptionOutEdgeEnum(this);
1827        } else {
1828          return EmptyEnumeration.<BasicBlock>emptyEnumeration();
1829        }
1830      }
1831    
1832      /**
1833       * Is there an 'exceptional' out edge to the given basic block?
1834       *
1835       * @param bb basic block in question
1836       * @return <code>true</code> if an exceptional out edge exists to bb
1837       *         <code>false</code> otherwise
1838       */
1839      public final boolean isExceptionalOut(BasicBlock bb) {
1840        if (!canThrowExceptions()) return false;
1841        ExceptionOutEdgeEnum eoee = new ExceptionOutEdgeEnum(this);
1842        while (eoee.hasMoreElements()) {
1843          if (eoee.nextElement() == bb) {
1844            return true;
1845          }
1846        }
1847        return false;
1848      }
1849    
1850      /**
1851       * Get the number of out nodes that are to "normal" basic blocks
1852       *
1853       * @return the number of out nodes that are not the start of
1854       *         exception handlers
1855       */
1856      public final int getNumberOfNormalOut() {
1857        int count = 0;
1858        boolean countValid = true;
1859        for (SpaceEffGraphEdge e = _outEdgeStart; e != null; e = e.getNextOut()) {
1860          BasicBlock bb = (BasicBlock) e.toNode();
1861          if (!bb.isExceptionHandlerBasicBlock()) {
1862            count++;
1863          } else if (bb.isExceptionHandlerWithNormalIn()) {
1864            countValid = false;
1865            break;
1866          }
1867        }
1868        if (countValid) {
1869          return count;
1870        } else {
1871          HashSet<BasicBlock> setOfTargets = new HashSet<BasicBlock>();
1872          for (SpaceEffGraphEdge e = _outEdgeStart; e != null; e = e.getNextOut()) {
1873            BasicBlock bb = (BasicBlock) e.toNode();
1874            if (!bb.isExceptionHandlerBasicBlock()) {
1875              setOfTargets.add(bb);
1876            }
1877          }
1878          for (Enumeration<Instruction> e = enumerateBranchInstructions(); e.hasMoreElements();) {
1879            Enumeration<BasicBlock> targets = e.nextElement().getBranchTargets();
1880            while (targets.hasMoreElements()) {
1881              setOfTargets.add(targets.nextElement());
1882            }
1883          }
1884          return setOfTargets.size();
1885        }
1886      }
1887    
1888      /**
1889       * Get the number of out nodes that are to exception handler basic blocks
1890       *
1891       * @return the number of out nodes that are exception handlers
1892       */
1893      public final int getNumberOfExceptionalOut() {
1894        int count = 0;
1895        if (canThrowExceptions()) {
1896          for (SpaceEffGraphEdge e = _outEdgeStart; e != null; e = e.getNextOut()) {
1897            BasicBlock bb = (BasicBlock) e.toNode();
1898            if (bb.isExceptionHandlerBasicBlock()) {
1899              count++;
1900            }
1901          }
1902        }
1903        return count;
1904      }
1905    
1906      /**
1907       * Are there exceptinal handlers that are reachable via
1908       * exceptional control flow from this basic block?
1909       *
1910       * @return <code>true</code> if an exceptional handler
1911       *          is reachable from this block or
1912       *          <code>false</code> otherwise.
1913       */
1914      public final boolean hasReachableExceptionHandlers() {
1915        if (canThrowExceptions()) {
1916          for (SpaceEffGraphEdge e = _outEdgeStart; e != null; e = e.getNextOut()) {
1917            BasicBlock bb = (BasicBlock) e.toNode();
1918            if (bb.isExceptionHandlerBasicBlock()) {
1919              return true;
1920            }
1921          }
1922        }
1923        return false;
1924      }
1925    
1926      /*
1927      * Primitive BasicBlock enumerators.
1928      * We don't really intend clients to directly instantiate these, but rather to
1929      * call the appropriate utility function that creates/initializes one of these
1930      */
1931      abstract static class BBEnum implements Enumeration<BasicBlock> {
1932        protected BasicBlock current;
1933    
1934        @Override
1935        public final boolean hasMoreElements() { return current != null; }
1936    
1937        @Override
1938        public final BasicBlock nextElement() {
1939          if (current == null) fail();
1940          BasicBlock value = current;
1941          current = advance();
1942          return value;
1943        }
1944    
1945        protected abstract BasicBlock advance();
1946    
1947        @NoInline
1948        protected static void fail() throws java.util.NoSuchElementException {
1949          throw new java.util.NoSuchElementException("Basic Block Enumeration");
1950        }
1951      }
1952    
1953      // Arbitrary constructed enumeration of some set of basic blocks
1954      static final class ComputedBBEnum implements Enumeration<BasicBlock> {
1955        private BasicBlock[] blocks;
1956        private int numBlocks;
1957        private int current;
1958    
1959        ComputedBBEnum(int maxBlocks) {
1960          blocks = new BasicBlock[maxBlocks];
1961        }
1962    
1963        void addElement(BasicBlock b) {
1964          blocks[numBlocks++] = b;
1965        }
1966    
1967        void addPossiblyDuplicateElement(BasicBlock b) {
1968          for (int i = 0; i < numBlocks; i++) {
1969            if (blocks[i] == b) return;
1970          }
1971          addElement(b);
1972        }
1973    
1974        public int totalCount() { return numBlocks; }
1975    
1976        @Override
1977        public boolean hasMoreElements() { return current < numBlocks; }
1978    
1979        @Override
1980        public BasicBlock nextElement() {
1981          if (current >= numBlocks) fail();
1982          return blocks[current++];
1983        }
1984    
1985        @NoInline
1986        static void fail() throws java.util.NoSuchElementException {
1987          throw new java.util.NoSuchElementException("Basic Block Enumeration");
1988        }
1989      }
1990    
1991      // this class needs to be implemented efficiently, as it is used heavily.
1992      static final class InEdgeEnum implements Enumeration<BasicBlock> {
1993        private SpaceEffGraphEdge _edge;
1994    
1995        public InEdgeEnum(SpaceEffGraphNode n) { _edge = n.firstInEdge(); }
1996    
1997        @Override
1998        public boolean hasMoreElements() { return _edge != null; }
1999    
2000        @Override
2001        public BasicBlock nextElement() {
2002          SpaceEffGraphEdge e = _edge;
2003          _edge = e.getNextIn();
2004          return (BasicBlock) e.fromNode();
2005        }
2006      }
2007    
2008      // this class needs to be implemented efficiently, as it is used heavily.
2009      static final class OutEdgeEnum implements Enumeration<BasicBlock> {
2010        private SpaceEffGraphEdge _edge;
2011    
2012        public OutEdgeEnum(SpaceEffGraphNode n) { _edge = n.firstOutEdge(); }
2013    
2014        @Override
2015        public boolean hasMoreElements() { return _edge != null; }
2016    
2017        @Override
2018        public BasicBlock nextElement() {
2019          SpaceEffGraphEdge e = _edge;
2020          _edge = e.getNextOut();
2021          return (BasicBlock) e.toNode();
2022        }
2023      }
2024    
2025      // Enumerate the non-handler blocks in the edge set
2026      final class NormalOutEdgeEnum extends BBEnum {
2027        private SpaceEffGraphEdge _edge;
2028    
2029        NormalOutEdgeEnum(SpaceEffGraphNode n) {
2030          _edge = n.firstOutEdge();
2031          current = advance();
2032        }
2033    
2034        @Override
2035        protected BasicBlock advance() {
2036          while (_edge != null) {
2037            BasicBlock cand = (BasicBlock) _edge.toNode();
2038            _edge = _edge.getNextOut();
2039            if (!cand.isExceptionHandlerBasicBlock()) {
2040              return cand;
2041            } else if (cand.isExceptionHandlerWithNormalIn()) {
2042              for (Enumeration<Instruction> e = enumerateBranchInstructions(); e.hasMoreElements();) {
2043                Enumeration<BasicBlock> targets = e.nextElement().getBranchTargets();
2044                while (targets.hasMoreElements()) {
2045                  if (cand == targets.nextElement()) {
2046                    return cand;
2047                  }
2048                }
2049              }
2050            }
2051          }
2052          return null;
2053        }
2054      }
2055    
2056      // Enumerate the non-handler blocks in the edge set
2057      static final class ExceptionOutEdgeEnum extends BBEnum {
2058        private SpaceEffGraphEdge _edge;
2059    
2060        ExceptionOutEdgeEnum(SpaceEffGraphNode n) {
2061          _edge = n.firstOutEdge();
2062          current = advance();
2063        }
2064    
2065        @Override
2066        protected BasicBlock advance() {
2067          while (_edge != null) {
2068            BasicBlock cand = (BasicBlock) _edge.toNode();
2069            _edge = _edge.getNextOut();
2070            if (cand.isExceptionHandlerBasicBlock()) {
2071              return cand;
2072            }
2073          }
2074          return null;
2075        }
2076      }
2077    
2078      public void discardInstructions() {
2079        start.getNext().setPrev(null);
2080        end.getPrev().setNext(null);
2081        start.linkWithNext(end);
2082      }
2083    }