Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

SWITCH.java

00001 package de.fub.bytecode.generic;
00002 
00003 /** 
00004  * SWITCH - Branch depending on int value, generates either LOOKUPSWITCH or
00005  * TABLESWITCH instruction, depending on whether the match values (int[]) can be
00006  * sorted with no gaps between the numbers.
00007  *
00008  * @version $Id: SWITCH.java,v 1.1.1.1 2002/01/24 03:44:05 pserver Exp $
00009  * @author  <A HREF="http://www.inf.fu-berlin.de/~dahm">M. Dahm</A>
00010  */
00011 public final class SWITCH implements CompoundInstruction {
00012   private int[]               match;
00013   private InstructionHandle[] targets;
00014   private Select              instruction;
00015   private int                 match_length;
00016 
00017   public SWITCH(int[] match, InstructionHandle[] targets,
00018         InstructionHandle target) {
00019     this(match, targets, target, 1);
00020   }  
00021   /**
00022    * Template for switch() constructs. If the match array can be
00023    * sorted in ascending order with gaps no larger than max_gap
00024    * between the numbers, a TABLESWITCH instruction is generated, and
00025    * a LOOKUPSWITCH otherwise. The former may be more efficient, but
00026    * needs more space.
00027    * 
00028    * Note, that the key array always will be sorted, though we leave
00029    * the original arrays unaltered.
00030    *
00031    * @param match array of match values (case 2: ... case 7: ..., etc.)
00032    * @param targets the instructions to be branched to for each case
00033    * @param target the default target
00034    * @param max_gap maximum gap that may between case branches
00035    */
00036   public SWITCH(int[] match, InstructionHandle[] targets,
00037         InstructionHandle target, int max_gap) {
00038     this.match   = (int[])match.clone();
00039     this.targets = (InstructionHandle[])targets.clone();
00040 
00041     if((match_length = match.length) < 2) // (almost) empty switch, or just default
00042       instruction = new TABLESWITCH(match, targets, target);
00043     else {
00044       sort(0, match_length - 1);
00045       
00046       if(matchIsOrdered(max_gap)) {
00047     fillup(max_gap, target);
00048 
00049     instruction = new TABLESWITCH(this.match, this.targets, target);
00050       }
00051       else
00052     instruction = new LOOKUPSWITCH(this.match, this.targets, target);
00053     }
00054   }  
00055   private final void fillup(int max_gap, InstructionHandle target) {
00056     int                 max_size = match_length + match_length * max_gap;
00057     int[]               m_vec    = new int[max_size];
00058     InstructionHandle[] t_vec    = new InstructionHandle[max_size];
00059     int                 count    = 1;
00060 
00061     m_vec[0] = match[0];
00062     t_vec[0] = targets[0];
00063 
00064     for(int i=1; i < match_length; i++) {
00065       int prev = match[i-1];
00066       int gap  = match[i] - prev; 
00067 
00068       for(int j=1; j < gap; j++) {
00069     m_vec[count] = prev + j;
00070     t_vec[count] = target;
00071     count++;
00072       }
00073 
00074       m_vec[count] = match[i];
00075       t_vec[count] = targets[i];
00076       count++;
00077     }   
00078 
00079     match   = new int[count];
00080     targets = new InstructionHandle[count];
00081 
00082     System.arraycopy(m_vec, 0, match, 0, count);
00083     System.arraycopy(t_vec, 0, targets, 0, count);
00084   }  
00085   public final Instruction getInstruction() {
00086     return instruction;
00087   }  
00088   public final InstructionList getInstructionList() {
00089     return new InstructionList(instruction);
00090   }  
00091   /**
00092    * @return match is sorted in ascending order with no gap bigger than max_gap?
00093    */
00094   private final boolean matchIsOrdered(int max_gap) {
00095     for(int i=1; i < match_length; i++)
00096       if(match[i] - match[i-1] > max_gap)
00097     return false;
00098 
00099     return true;
00100   }  
00101   /**
00102    * Sort match and targets array with QuickSort.
00103    */
00104   private final void sort(int l, int r) {
00105     int i = l, j = r;
00106     int h, m = match[(l + r) / 2];
00107     InstructionHandle h2;
00108 
00109     do {
00110       while(match[i] < m) i++;
00111       while(m < match[j]) j--;
00112 
00113       if(i <= j) {
00114     h=match[i]; match[i]=match[j]; match[j]=h; // Swap elements
00115     h2=targets[i]; targets[i]=targets[j]; targets[j]=h2; // Swap instructions, too
00116     i++; j--;
00117       }
00118     } while(i <= j);
00119 
00120     if(l < j) sort(l, j);
00121     if(i < r) sort(i, r);
00122   }  
00123 }

Generated at Thu Feb 7 06:56:01 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001