jaxp/src/com/sun/org/apache/bcel/internal/generic/Select.java
changeset 12457 c348e06f0e82
parent 6 7f561c08de6b
child 17538 d8d911c4e5d4
equal deleted inserted replaced
12324:1d7e6da6adc8 12457:c348e06f0e82
       
     1 /*
       
     2  * reserved comment block
       
     3  * DO NOT REMOVE OR ALTER!
       
     4  */
       
     5 package com.sun.org.apache.bcel.internal.generic;
       
     6 
       
     7 /* ====================================================================
       
     8  * The Apache Software License, Version 1.1
       
     9  *
       
    10  * Copyright (c) 2001 The Apache Software Foundation.  All rights
       
    11  * reserved.
       
    12  *
       
    13  * Redistribution and use in source and binary forms, with or without
       
    14  * modification, are permitted provided that the following conditions
       
    15  * are met:
       
    16  *
       
    17  * 1. Redistributions of source code must retain the above copyright
       
    18  *    notice, this list of conditions and the following disclaimer.
       
    19  *
       
    20  * 2. Redistributions in binary form must reproduce the above copyright
       
    21  *    notice, this list of conditions and the following disclaimer in
       
    22  *    the documentation and/or other materials provided with the
       
    23  *    distribution.
       
    24  *
       
    25  * 3. The end-user documentation included with the redistribution,
       
    26  *    if any, must include the following acknowledgment:
       
    27  *       "This product includes software developed by the
       
    28  *        Apache Software Foundation (http://www.apache.org/)."
       
    29  *    Alternately, this acknowledgment may appear in the software itself,
       
    30  *    if and wherever such third-party acknowledgments normally appear.
       
    31  *
       
    32  * 4. The names "Apache" and "Apache Software Foundation" and
       
    33  *    "Apache BCEL" must not be used to endorse or promote products
       
    34  *    derived from this software without prior written permission. For
       
    35  *    written permission, please contact apache@apache.org.
       
    36  *
       
    37  * 5. Products derived from this software may not be called "Apache",
       
    38  *    "Apache BCEL", nor may "Apache" appear in their name, without
       
    39  *    prior written permission of the Apache Software Foundation.
       
    40  *
       
    41  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
       
    42  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
       
    43  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
       
    44  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
       
    45  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    46  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    47  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
       
    48  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
       
    49  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
       
    50  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
       
    51  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
       
    52  * SUCH DAMAGE.
       
    53  * ====================================================================
       
    54  *
       
    55  * This software consists of voluntary contributions made by many
       
    56  * individuals on behalf of the Apache Software Foundation.  For more
       
    57  * information on the Apache Software Foundation, please see
       
    58  * <http://www.apache.org/>.
       
    59  */
       
    60 import java.io.*;
       
    61 import com.sun.org.apache.bcel.internal.util.ByteSequence;
       
    62 
       
    63 /**
       
    64  * Select - Abstract super class for LOOKUPSWITCH and TABLESWITCH instructions.
       
    65  *
       
    66  * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
       
    67  * @see LOOKUPSWITCH
       
    68  * @see TABLESWITCH
       
    69  * @see InstructionList
       
    70  */
       
    71 public abstract class Select extends BranchInstruction
       
    72   implements VariableLengthInstruction, StackProducer
       
    73 {
       
    74   protected int[]               match;        // matches, i.e., case 1: ...
       
    75   protected int[]               indices;      // target offsets
       
    76   protected InstructionHandle[] targets;      // target objects in instruction list
       
    77   protected int                 fixed_length; // fixed length defined by subclasses
       
    78   protected int                 match_length; // number of cases
       
    79   protected int                 padding = 0;  // number of pad bytes for alignment
       
    80 
       
    81   /**
       
    82    * Empty constructor needed for the Class.newInstance() statement in
       
    83    * Instruction.readInstruction(). Not to be used otherwise.
       
    84    */
       
    85   Select() {}
       
    86 
       
    87   /**
       
    88    * (Match, target) pairs for switch.
       
    89    * `Match' and `targets' must have the same length of course.
       
    90    *
       
    91    * @param match array of matching values
       
    92    * @param targets instruction targets
       
    93    * @param target default instruction target
       
    94    */
       
    95   Select(short opcode, int[] match, InstructionHandle[] targets,
       
    96          InstructionHandle target) {
       
    97     super(opcode, target);
       
    98 
       
    99     this.targets = targets;
       
   100     for(int i=0; i < targets.length; i++)
       
   101       notifyTarget(null, targets[i], this);
       
   102 
       
   103     this.match = match;
       
   104 
       
   105     if((match_length = match.length) != targets.length)
       
   106       throw new ClassGenException("Match and target array have not the same length");
       
   107 
       
   108     indices = new int[match_length];
       
   109   }
       
   110 
       
   111   /**
       
   112    * Since this is a variable length instruction, it may shift the following
       
   113    * instructions which then need to update their position.
       
   114    *
       
   115    * Called by InstructionList.setPositions when setting the position for every
       
   116    * instruction. In the presence of variable length instructions `setPositions'
       
   117    * performs multiple passes over the instruction list to calculate the
       
   118    * correct (byte) positions and offsets by calling this function.
       
   119    *
       
   120    * @param offset additional offset caused by preceding (variable length) instructions
       
   121    * @param max_offset the maximum offset that may be caused by these instructions
       
   122    * @return additional offset caused by possible change of this instruction's length
       
   123    */
       
   124   protected int updatePosition(int offset, int max_offset) {
       
   125     position += offset; // Additional offset caused by preceding SWITCHs, GOTOs, etc.
       
   126 
       
   127     short old_length = length;
       
   128 
       
   129     /* Alignment on 4-byte-boundary, + 1, because of tag byte.
       
   130      */
       
   131     padding = (4 - ((position + 1) % 4)) % 4;
       
   132     length  = (short)(fixed_length + padding); // Update length
       
   133 
       
   134     return length - old_length;
       
   135   }
       
   136 
       
   137   /**
       
   138    * Dump instruction as byte code to stream out.
       
   139    * @param out Output stream
       
   140    */
       
   141   public void dump(DataOutputStream out) throws IOException {
       
   142     out.writeByte(opcode);
       
   143 
       
   144     for(int i=0; i < padding; i++) // Padding bytes
       
   145       out.writeByte(0);
       
   146 
       
   147     index = getTargetOffset();     // Write default target offset
       
   148     out.writeInt(index);
       
   149   }
       
   150 
       
   151   /**
       
   152    * Read needed data (e.g. index) from file.
       
   153    */
       
   154   protected void initFromFile(ByteSequence bytes, boolean wide) throws IOException
       
   155   {
       
   156     padding = (4 - (bytes.getIndex() % 4)) % 4; // Compute number of pad bytes
       
   157 
       
   158     for(int i=0; i < padding; i++) {
       
   159       bytes.readByte();
       
   160     }
       
   161 
       
   162     // Default branch target common for both cases (TABLESWITCH, LOOKUPSWITCH)
       
   163     index = bytes.readInt();
       
   164   }
       
   165 
       
   166   /**
       
   167    * @return mnemonic for instruction
       
   168    */
       
   169   public String toString(boolean verbose) {
       
   170     StringBuffer buf = new StringBuffer(super.toString(verbose));
       
   171 
       
   172     if(verbose) {
       
   173       for(int i=0; i < match_length; i++) {
       
   174         String s = "null";
       
   175 
       
   176         if(targets[i] != null)
       
   177           s = targets[i].getInstruction().toString();
       
   178 
       
   179         buf.append("(" + match[i] + ", " + s + " = {" + indices[i] + "})");
       
   180       }
       
   181     }
       
   182     else
       
   183       buf.append(" ...");
       
   184 
       
   185     return buf.toString();
       
   186   }
       
   187 
       
   188   /**
       
   189    * Set branch target for `i'th case
       
   190    */
       
   191   public void setTarget(int i, InstructionHandle target) {
       
   192     notifyTarget(targets[i], target, this);
       
   193     targets[i] = target;
       
   194   }
       
   195 
       
   196   /**
       
   197    * @param old_ih old target
       
   198    * @param new_ih new target
       
   199    */
       
   200   public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
       
   201     boolean targeted = false;
       
   202 
       
   203     if(target == old_ih) {
       
   204       targeted = true;
       
   205       setTarget(new_ih);
       
   206     }
       
   207 
       
   208     for(int i=0; i < targets.length; i++) {
       
   209       if(targets[i] == old_ih) {
       
   210         targeted = true;
       
   211         setTarget(i, new_ih);
       
   212       }
       
   213     }
       
   214 
       
   215     if(!targeted)
       
   216       throw new ClassGenException("Not targeting " + old_ih);
       
   217   }
       
   218 
       
   219   /**
       
   220    * @return true, if ih is target of this instruction
       
   221    */
       
   222   public boolean containsTarget(InstructionHandle ih) {
       
   223     if(target == ih)
       
   224       return true;
       
   225 
       
   226     for(int i=0; i < targets.length; i++)
       
   227       if(targets[i] == ih)
       
   228         return true;
       
   229 
       
   230     return false;
       
   231   }
       
   232 
       
   233   /**
       
   234    * Inform targets that they're not targeted anymore.
       
   235    */
       
   236   void dispose() {
       
   237     super.dispose();
       
   238 
       
   239     for(int i=0; i < targets.length; i++)
       
   240       targets[i].removeTargeter(this);
       
   241   }
       
   242 
       
   243   /**
       
   244    * @return array of match indices
       
   245    */
       
   246   public int[] getMatchs() { return match; }
       
   247 
       
   248   /**
       
   249    * @return array of match target offsets
       
   250    */
       
   251   public int[] getIndices() { return indices; }
       
   252 
       
   253   /**
       
   254    * @return array of match targets
       
   255    */
       
   256   public InstructionHandle[] getTargets() { return targets; }
       
   257 }