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 org.jikesrvm.compilers.opt.OptimizingCompilerException;
016    
017    /**
018     * A container for the chain of exception handlers for a basic block.
019     *
020     *
021     * @see BasicBlock
022     * @see ExceptionHandlerBasicBlock
023     */
024    public final class ExceptionHandlerBasicBlockBag {
025    
026      /**
027       * The array of ExceptionHandlerBasicBlocks constructed by BC2IR
028       * based on the local set of handlers visible within a single method
029       */
030      private ExceptionHandlerBasicBlock[] local;
031    
032      /**
033       * If this is an inlined method, then this points to the enclosing
034       * method's (the caller's) ExcpetionHandlerBasicBlockBag.  If this is
035       * the outermost method, then this is null
036       */
037      private final ExceptionHandlerBasicBlockBag caller;
038    
039      /**
040       * only for use by BC2IR; return {@link #caller}
041       * @return the contents of {@link #caller}
042       */
043      public ExceptionHandlerBasicBlockBag getCaller() {
044        return caller;
045      }
046    
047      /**
048       * Create an EHBBB
049       * @param l the local array of EHBBs
050       * @param c the enclosing EHBBB
051       */
052      public ExceptionHandlerBasicBlockBag(ExceptionHandlerBasicBlock[] l, ExceptionHandlerBasicBlockBag c) {
053        local = l;
054        caller = c;
055      }
056    
057      /**
058       * take an element out f the bag.  Throw an exception if the block
059       * to remove is not in the bag
060       */
061      public void remove(BasicBlock bb) {
062        for (int i = 0; i < local.length; i++) {
063          if (bb == local[i]) {
064            ExceptionHandlerBasicBlock[] newLocal = new ExceptionHandlerBasicBlock[local.length - 1];
065    
066            for (int j = 0; j < i; j++) newLocal[j] = local[j];
067    
068            for (int j = i + 1; j < local.length; j++) newLocal[j - 1] = local[j];
069    
070            local = newLocal;
071            return;
072          }
073        }
074    
075        throw new OptimizingCompilerException("Removing block not present in bag: " + bb);
076      }
077    
078      /**
079       * An enumeration of all the exception handler basic blocks
080       * (transitively) in the EHBBB.
081       * @return An enumeration of the exception handler basic blocks in the bag.
082       */
083      public BasicBlockEnumeration enumerator() {
084        return new BasicBlockEnumeration() {
085          private int cur_idx = 0;
086          private ExceptionHandlerBasicBlockBag cur_bag = null;
087    
088          // Initialize enumeration to point to first ehbb (if any)
089          {
090            ExceptionHandlerBasicBlockBag c = ExceptionHandlerBasicBlockBag.this;
091            while (c != null && (c.local == null || c.local.length == 0)) { c = c.caller; }
092            if (c != null) {
093              cur_bag = c;
094            }
095          }
096    
097          public boolean hasMoreElements() { return cur_bag != null; }
098    
099          public BasicBlock nextElement() { return next(); }
100    
101          public BasicBlock next() {
102            ExceptionHandlerBasicBlock ans;
103            try {
104              ans = cur_bag.local[cur_idx++];
105            } catch (NullPointerException e) {
106              throw new java.util.NoSuchElementException();
107            }
108            // Now advance state to point to next element.
109            if (cur_idx == cur_bag.local.length) {
110              cur_bag = cur_bag.caller;
111              while (cur_bag != null && (cur_bag.local == null || cur_bag.local.length == 0)) {
112                cur_bag = cur_bag.caller;
113              }
114              if (cur_bag != null) {
115                cur_idx = 0; // found the next array, reset idx to first element.
116              }
117            }
118            return ans;
119          }
120        };
121      }
122    }
123