< prev index next >

src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java

Print this page


   1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.bcel.internal.generic;
  23 
  24 import java.io.*;


  25 import com.sun.org.apache.bcel.internal.util.ByteSequence;
  26 
  27 /**
  28  * Select - Abstract super class for LOOKUPSWITCH and TABLESWITCH instructions.
  29  *
  30  * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>



  31  * @see LOOKUPSWITCH
  32  * @see TABLESWITCH
  33  * @see InstructionList
  34  */
  35 public abstract class Select extends BranchInstruction
  36   implements VariableLengthInstruction, StackProducer
  37 {
  38   protected int[]               match;        // matches, i.e., case 1: ...
  39   protected int[]               indices;      // target offsets
  40   protected InstructionHandle[] targets;      // target objects in instruction list
  41   protected int                 fixed_length; // fixed length defined by subclasses
  42   protected int                 match_length; // number of cases
  43   protected int                 padding = 0;  // number of pad bytes for alignment
  44 
  45   /**
  46    * Empty constructor needed for the Class.newInstance() statement in
  47    * Instruction.readInstruction(). Not to be used otherwise.
  48    */
  49   Select() {}

  50 
  51   /**
  52    * (Match, target) pairs for switch.
  53    * `Match' and `targets' must have the same length of course.
  54    *
  55    * @param match array of matching values
  56    * @param targets instruction targets
  57    * @param target default instruction target
  58    */
  59   Select(short opcode, int[] match, InstructionHandle[] targets,
  60          InstructionHandle target) {
  61     super(opcode, target);
  62 
  63     this.targets = targets;
  64     for(int i=0; i < targets.length; i++) {
  65       BranchInstruction.notifyTargetChanged(targets[i], this);






  66     }
  67 
  68     this.match = match;
  69 
  70     if((match_length = match.length) != targets.length)
  71       throw new ClassGenException("Match and target array have not the same length");
  72 
  73     indices = new int[match_length];
  74   }
  75 
  76   /**
  77    * Since this is a variable length instruction, it may shift the following
  78    * instructions which then need to update their position.
  79    *
  80    * Called by InstructionList.setPositions when setting the position for every
  81    * instruction. In the presence of variable length instructions `setPositions'
  82    * performs multiple passes over the instruction list to calculate the
  83    * correct (byte) positions and offsets by calling this function.

  84    *
  85    * @param offset additional offset caused by preceding (variable length) instructions
  86    * @param max_offset the maximum offset that may be caused by these instructions
  87    * @return additional offset caused by possible change of this instruction's length



  88    */
  89   @Override
  90   protected int updatePosition(int offset, int max_offset) {
  91     position += offset; // Additional offset caused by preceding SWITCHs, GOTOs, etc.
  92 
  93     short old_length = length;
  94 
  95     /* Alignment on 4-byte-boundary, + 1, because of tag byte.
  96      */
  97     padding = (4 - ((position + 1) % 4)) % 4;
  98     length  = (short)(fixed_length + padding); // Update length
  99 
 100     return length - old_length;
 101   }
 102 
 103   /**
 104    * Dump instruction as byte code to stream out.

 105    * @param out Output stream
 106    */
 107   @Override
 108   public void dump(DataOutputStream out) throws IOException {
 109     out.writeByte(opcode);
 110 
 111     for(int i=0; i < padding; i++) // Padding bytes
 112       out.writeByte(0);
 113 
 114     index = getTargetOffset();     // Write default target offset
 115     out.writeInt(index);
 116   }
 117 
 118   /**
 119    * Read needed data (e.g. index) from file.
 120    */
 121   @Override
 122   protected void initFromFile(ByteSequence bytes, boolean wide) throws IOException
 123   {
 124     padding = (4 - (bytes.getIndex() % 4)) % 4; // Compute number of pad bytes
 125 
 126     for(int i=0; i < padding; i++) {
 127       bytes.readByte();
 128     }
 129 
 130     // Default branch target common for both cases (TABLESWITCH, LOOKUPSWITCH)
 131     index = bytes.readInt();
 132   }
 133 
 134   /**
 135    * @return mnemonic for instruction
 136    */
 137   @Override
 138   public String toString(boolean verbose) {
 139     final StringBuilder buf = new StringBuilder(super.toString(verbose));
 140 
 141     if(verbose) {
 142       for(int i=0; i < match_length; i++) {
 143         String s = "null";
 144 
 145         if(targets[i] != null)
 146           s = targets[i].getInstruction().toString();
 147 
 148           buf.append("(").append(match[i]).append(", ")
 149              .append(s).append(" = {").append(indices[i]).append("})");
 150       }


 151     }
 152     else
 153       buf.append(" ...");
 154 
 155     return buf.toString();
 156   }
 157 
 158   /**
 159    * Set branch target for `i'th case
 160    */
 161   public final void setTarget(int i, InstructionHandle target) {
 162     notifyTargetChanging(targets[i], this);
 163     targets[i] = target;
 164     notifyTargetChanged(targets[i], this);
 165   }
 166 
 167   /**
 168    * @param old_ih old target
 169    * @param new_ih new target
 170    */
 171   @Override
 172   public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
 173     boolean targeted = false;
 174 
 175     if(target == old_ih) {
 176       targeted = true;
 177       setTarget(new_ih);
 178     }
 179 
 180     for(int i=0; i < targets.length; i++) {
 181       if(targets[i] == old_ih) {
 182         targeted = true;
 183         setTarget(i, new_ih);
 184       }
 185     }
 186 
 187     if(!targeted)
 188       throw new ClassGenException("Not targeting " + old_ih);
 189   }

 190 
 191   /**
 192    * @return true, if ih is target of this instruction
 193    */
 194   @Override
 195   public boolean containsTarget(InstructionHandle ih) {
 196     if(target == ih)
 197       return true;
 198 
 199     for(int i=0; i < targets.length; i++)
 200       if(targets[i] == ih)
 201         return true;
 202 

 203     return false;
 204   }
 205 









 206   /**
 207    * Inform targets that they're not targeted anymore.
 208    */
 209   @Override
 210   void dispose() {
 211     super.dispose();
 212 
 213     for(int i=0; i < targets.length; i++)
 214       targets[i].removeTargeter(this);
 215   }
 216 
 217   /**
 218    * @return array of match indices
 219    */
 220   public int[] getMatchs() { return match; }


 221 
 222   /**
 223    * @return array of match target offsets
 224    */
 225   public int[] getIndices() { return indices; }


 226 
 227   /**
 228    * @return array of match targets
 229    */
 230   public InstructionHandle[] getTargets() { return targets; }

















































































































 231 }
   1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.

   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */

  20 package com.sun.org.apache.bcel.internal.generic;
  21 
  22 import java.io.DataOutputStream;
  23 import java.io.IOException;
  24 
  25 import com.sun.org.apache.bcel.internal.util.ByteSequence;
  26 
  27 /**
  28  * Select - Abstract super class for LOOKUPSWITCH and TABLESWITCH instructions.
  29  *
  30  * <p>
  31  * We use our super's <code>target</code> property as the default target.
  32  *
  33  * @version $Id: Select.java 1749603 2016-06-21 20:50:19Z ggregory $
  34  * @see LOOKUPSWITCH
  35  * @see TABLESWITCH
  36  * @see InstructionList
  37  */
  38 public abstract class Select extends BranchInstruction implements VariableLengthInstruction,
  39         StackConsumer /* @since 6.0 */, StackProducer {
  40 
  41     private int[] match; // matches, i.e., case 1: ... TODO could be package-protected?
  42     private int[] indices; // target offsets TODO could be package-protected?
  43     private InstructionHandle[] targets; // target objects in instruction list TODO could be package-protected?
  44     private int fixed_length; // fixed length defined by subclasses TODO could be package-protected?
  45     private int match_length; // number of cases TODO could be package-protected?
  46     private int padding = 0; // number of pad bytes for alignment TODO could be package-protected?
  47 
  48     /**
  49      * Empty constructor needed for the Class.newInstance() statement in
  50      * Instruction.readInstruction(). Not to be used otherwise.
  51      */
  52     Select() {
  53     }
  54 
  55     /**
  56      * (Match, target) pairs for switch. `Match' and `targets' must have the
  57      * same length of course.
  58      *
  59      * @param match array of matching values
  60      * @param targets instruction targets
  61      * @param defaultTarget default instruction target
  62      */
  63     Select(final short opcode, final int[] match, final InstructionHandle[] targets, final InstructionHandle defaultTarget) {
  64         // don't set default target before instuction is built
  65         super(opcode, null);
  66         this.match = match;
  67         this.targets = targets;
  68         // now it's safe to set default target
  69         setTarget(defaultTarget);
  70         for (final InstructionHandle target2 : targets) {
  71             notifyTarget(null, target2, this);
  72         }
  73         if ((match_length = match.length) != targets.length) {
  74             throw new ClassGenException("Match and target array have not the same length: Match length: "
  75                     + match.length + " Target length: " + targets.length);
  76         }






  77         indices = new int[match_length];
  78     }
  79 
  80     /**
  81      * Since this is a variable length instruction, it may shift the following
  82      * instructions which then need to update their position.
  83      *
  84      * Called by InstructionList.setPositions when setting the position for
  85      * every instruction. In the presence of variable length instructions
  86      * `setPositions' performs multiple passes over the instruction list to
  87      * calculate the correct (byte) positions and offsets by calling this
  88      * function.
  89      *
  90      * @param offset additional offset caused by preceding (variable length)
  91      * instructions
  92      * @param max_offset the maximum offset that may be caused by these
  93      * instructions
  94      * @return additional offset caused by possible change of this instruction's
  95      * length
  96      */
  97     @Override
  98     protected int updatePosition(final int offset, final int max_offset) {
  99         setPosition(getPosition() + offset); // Additional offset caused by preceding SWITCHs, GOTOs, etc.
 100         final short old_length = (short) super.getLength();


 101         /* Alignment on 4-byte-boundary, + 1, because of tag byte.
 102          */
 103         padding = (4 - ((getPosition() + 1) % 4)) % 4;
 104         super.setLength((short) (fixed_length + padding)); // Update length
 105         return super.getLength() - old_length;

 106     }
 107 
 108     /**
 109      * Dump instruction as byte code to stream out.
 110      *
 111      * @param out Output stream
 112      */
 113     @Override
 114     public void dump(final DataOutputStream out) throws IOException {
 115         out.writeByte(super.getOpcode());
 116         for (int i = 0; i < padding; i++) {

 117             out.writeByte(0);
 118         }
 119         super.setIndex(getTargetOffset()); // Write default target offset
 120         out.writeInt(super.getIndex());
 121     }
 122 
 123     /**
 124      * Read needed data (e.g. index) from file.
 125      */
 126     @Override
 127     protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException {

 128         padding = (4 - (bytes.getIndex() % 4)) % 4; // Compute number of pad bytes
 129         for (int i = 0; i < padding; i++) {

 130             bytes.readByte();
 131         }

 132         // Default branch target common for both cases (TABLESWITCH, LOOKUPSWITCH)
 133         super.setIndex(bytes.readInt());
 134     }
 135 
 136     /**
 137      * @return mnemonic for instruction
 138      */
 139     @Override
 140     public String toString(final boolean verbose) {
 141         final StringBuilder buf = new StringBuilder(super.toString(verbose));
 142         if (verbose) {
 143             for (int i = 0; i < match_length; i++) {

 144                 String s = "null";
 145                 if (targets[i] != null) {

 146                     s = targets[i].getInstruction().toString();



 147                 }
 148                 buf.append("(").append(match[i]).append(", ").append(s).append(" = {").append(
 149                         indices[i]).append("})");
 150             }
 151         } else {
 152             buf.append(" ...");
 153         }
 154         return buf.toString();
 155     }
 156 
 157     /**
 158      * Set branch target for `i'th case
 159      */
 160     public void setTarget(final int i, final InstructionHandle target) { // TODO could be package-protected?
 161         notifyTarget(targets[i], target, this);
 162         targets[i] = target;

 163     }
 164 
 165     /**
 166      * @param old_ih old target
 167      * @param new_ih new target
 168      */
 169     @Override
 170     public void updateTarget(final InstructionHandle old_ih, final InstructionHandle new_ih) {
 171         boolean targeted = false;
 172         if (super.getTarget() == old_ih) {

 173             targeted = true;
 174             setTarget(new_ih);
 175         }
 176         for (int i = 0; i < targets.length; i++) {
 177             if (targets[i] == old_ih) {

 178                 targeted = true;
 179                 setTarget(i, new_ih);
 180             }
 181         }
 182         if (!targeted) {

 183             throw new ClassGenException("Not targeting " + old_ih);
 184         }
 185     }
 186 
 187     /**
 188      * @return true, if ih is target of this instruction
 189      */
 190     @Override
 191     public boolean containsTarget(final InstructionHandle ih) {
 192         if (super.getTarget() == ih) {
 193             return true;
 194         }
 195         for (final InstructionHandle target2 : targets) {
 196             if (target2 == ih) {
 197                 return true;
 198             }
 199         }
 200         return false;
 201     }
 202 
 203     @Override
 204     protected Object clone() throws CloneNotSupportedException {
 205         final Select copy = (Select) super.clone();
 206         copy.match = match.clone();
 207         copy.indices = indices.clone();
 208         copy.targets = targets.clone();
 209         return copy;
 210     }
 211 
 212     /**
 213      * Inform targets that they're not targeted anymore.
 214      */
 215     @Override
 216     void dispose() {
 217         super.dispose();
 218         for (final InstructionHandle target2 : targets) {
 219             target2.removeTargeter(this);
 220         }
 221     }
 222 
 223     /**
 224      * @return array of match indices
 225      */
 226     public int[] getMatchs() {
 227         return match;
 228     }
 229 
 230     /**
 231      * @return array of match target offsets
 232      */
 233     public int[] getIndices() {
 234         return indices;
 235     }
 236 
 237     /**
 238      * @return array of match targets
 239      */
 240     public InstructionHandle[] getTargets() {
 241         return targets;
 242     }
 243 
 244     /**
 245      * @return match entry
 246      * @since 6.0
 247      */
 248     final int getMatch(final int index) {
 249         return match[index];
 250     }
 251 
 252     /**
 253      * @return index entry from indices
 254      * @since 6.0
 255      */
 256     final int getIndices(final int index) {
 257         return indices[index];
 258     }
 259 
 260     /**
 261      * @return target entry
 262      * @since 6.0
 263      */
 264     final InstructionHandle getTarget(final int index) {
 265         return targets[index];
 266     }
 267 
 268     /**
 269      * @return the fixed_length
 270      * @since 6.0
 271      */
 272     final int getFixed_length() {
 273         return fixed_length;
 274     }
 275 
 276     /**
 277      * @param fixed_length the fixed_length to set
 278      * @since 6.0
 279      */
 280     final void setFixed_length(final int fixed_length) {
 281         this.fixed_length = fixed_length;
 282     }
 283 
 284     /**
 285      * @return the match_length
 286      * @since 6.0
 287      */
 288     final int getMatch_length() {
 289         return match_length;
 290     }
 291 
 292     /**
 293      * @param match_length the match_length to set
 294      * @since 6.0
 295      */
 296     final int setMatch_length(final int match_length) {
 297         this.match_length = match_length;
 298         return match_length;
 299     }
 300 
 301     /**
 302      *
 303      * @param index
 304      * @param value
 305      * @since 6.0
 306      */
 307     final void setMatch(final int index, final int value) {
 308         match[index] = value;
 309     }
 310 
 311     /**
 312      *
 313      * @param array
 314      * @since 6.0
 315      */
 316     final void setIndices(final int[] array) {
 317         indices = array;
 318     }
 319 
 320     /**
 321      *
 322      * @param array
 323      * @since 6.0
 324      */
 325     final void setMatches(final int[] array) {
 326         match = array;
 327     }
 328 
 329     /**
 330      *
 331      * @param array
 332      * @since 6.0
 333      */
 334     final void setTargets(final InstructionHandle[] array) {
 335         targets = array;
 336     }
 337 
 338     /**
 339      *
 340      * @return the padding
 341      * @since 6.0
 342      */
 343     final int getPadding() {
 344         return padding;
 345     }
 346 
 347     /**
 348      * @since 6.0
 349      */
 350     final int setIndices(final int i, final int value) {
 351         indices[i] = value;
 352         return value;  // Allow use in nested calls
 353     }
 354 }
< prev index next >