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