src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java
changeset 55496 8e0ae3830fca
parent 47216 71c04702a3d5
equal deleted inserted replaced
55495:badfa812b82a 55496:8e0ae3830fca
     1 /*
     1 /*
     2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
     3  */
     3  */
     4 /*
     4 /*
     5  * Licensed to the Apache Software Foundation (ASF) under one or more
     5  * Licensed to the Apache Software Foundation (ASF) under one or more
     6  * contributor license agreements.  See the NOTICE file distributed with
     6  * contributor license agreements.  See the NOTICE file distributed with
     7  * this work for additional information regarding copyright ownership.
     7  * this work for additional information regarding copyright ownership.
    25 import com.sun.org.apache.bcel.internal.util.ByteSequence;
    25 import com.sun.org.apache.bcel.internal.util.ByteSequence;
    26 
    26 
    27 /**
    27 /**
    28  * Select - Abstract super class for LOOKUPSWITCH and TABLESWITCH instructions.
    28  * Select - Abstract super class for LOOKUPSWITCH and TABLESWITCH instructions.
    29  *
    29  *
    30  * <p>
    30  * <p>We use our super's <code>target</code> property as the default target.
    31  * We use our super's <code>target</code> property as the default target.
       
    32  *
    31  *
    33  * @version $Id: Select.java 1749603 2016-06-21 20:50:19Z ggregory $
    32  * @version $Id$
    34  * @see LOOKUPSWITCH
    33  * @see LOOKUPSWITCH
    35  * @see TABLESWITCH
    34  * @see TABLESWITCH
    36  * @see InstructionList
    35  * @see InstructionList
       
    36  * @LastModified: Jun 2019
    37  */
    37  */
    38 public abstract class Select extends BranchInstruction implements VariableLengthInstruction,
    38 public abstract class Select extends BranchInstruction implements VariableLengthInstruction,
    39         StackConsumer /* @since 6.0 */, StackProducer {
    39         StackConsumer /* @since 6.0 */, StackProducer {
    40 
    40 
    41     private int[] match; // matches, i.e., case 1: ... TODO could be package-protected?
    41     private int[] match; // matches, i.e., case 1: ... TODO could be package-protected?
    50      * Instruction.readInstruction(). Not to be used otherwise.
    50      * Instruction.readInstruction(). Not to be used otherwise.
    51      */
    51      */
    52     Select() {
    52     Select() {
    53     }
    53     }
    54 
    54 
    55     /**
    55 
    56      * (Match, target) pairs for switch. `Match' and `targets' must have the
    56     /**
    57      * same length of course.
    57      * (Match, target) pairs for switch.
       
    58      * `Match' and `targets' must have the same length of course.
    58      *
    59      *
    59      * @param match array of matching values
    60      * @param match array of matching values
    60      * @param targets instruction targets
    61      * @param targets instruction targets
    61      * @param defaultTarget default instruction target
    62      * @param defaultTarget default instruction target
    62      */
    63      */
    69         setTarget(defaultTarget);
    70         setTarget(defaultTarget);
    70         for (final InstructionHandle target2 : targets) {
    71         for (final InstructionHandle target2 : targets) {
    71             notifyTarget(null, target2, this);
    72             notifyTarget(null, target2, this);
    72         }
    73         }
    73         if ((match_length = match.length) != targets.length) {
    74         if ((match_length = match.length) != targets.length) {
    74             throw new ClassGenException("Match and target array have not the same length: Match length: "
    75             throw new ClassGenException("Match and target array have not the same length: Match length: " +
    75                     + match.length + " Target length: " + targets.length);
    76                 match.length + " Target length: " + targets.length);
    76         }
    77         }
    77         indices = new int[match_length];
    78         indices = new int[match_length];
    78     }
    79     }
       
    80 
    79 
    81 
    80     /**
    82     /**
    81      * Since this is a variable length instruction, it may shift the following
    83      * Since this is a variable length instruction, it may shift the following
    82      * instructions which then need to update their position.
    84      * instructions which then need to update their position.
    83      *
    85      *
    84      * Called by InstructionList.setPositions when setting the position for
    86      * Called by InstructionList.setPositions when setting the position for every
    85      * every instruction. In the presence of variable length instructions
    87      * instruction. In the presence of variable length instructions `setPositions'
    86      * `setPositions' performs multiple passes over the instruction list to
    88      * performs multiple passes over the instruction list to calculate the
    87      * calculate the correct (byte) positions and offsets by calling this
    89      * correct (byte) positions and offsets by calling this function.
    88      * function.
    90      *
    89      *
    91      * @param offset additional offset caused by preceding (variable length) instructions
    90      * @param offset additional offset caused by preceding (variable length)
    92      * @param max_offset the maximum offset that may be caused by these instructions
    91      * instructions
    93      * @return additional offset caused by possible change of this instruction's length
    92      * @param max_offset the maximum offset that may be caused by these
    94      */
    93      * instructions
    95     @Override
    94      * @return additional offset caused by possible change of this instruction's
    96     protected int updatePosition( final int offset, final int max_offset ) {
    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.
    97         setPosition(getPosition() + offset); // Additional offset caused by preceding SWITCHs, GOTOs, etc.
   100         final short old_length = (short) super.getLength();
    98         final short old_length = (short) super.getLength();
   101         /* Alignment on 4-byte-boundary, + 1, because of tag byte.
    99         /* Alignment on 4-byte-boundary, + 1, because of tag byte.
   102          */
   100          */
   103         padding = (4 - ((getPosition() + 1) % 4)) % 4;
   101         padding = (4 - ((getPosition() + 1) % 4)) % 4;
   104         super.setLength((short) (fixed_length + padding)); // Update length
   102         super.setLength((short) (fixed_length + padding)); // Update length
   105         return super.getLength() - old_length;
   103         return super.getLength() - old_length;
   106     }
   104     }
   107 
   105 
       
   106 
   108     /**
   107     /**
   109      * Dump instruction as byte code to stream out.
   108      * Dump instruction as byte code to stream out.
   110      *
       
   111      * @param out Output stream
   109      * @param out Output stream
   112      */
   110      */
   113     @Override
   111     @Override
   114     public void dump(final DataOutputStream out) throws IOException {
   112     public void dump( final DataOutputStream out ) throws IOException {
   115         out.writeByte(super.getOpcode());
   113         out.writeByte(super.getOpcode());
   116         for (int i = 0; i < padding; i++) {
   114         for (int i = 0; i < padding; i++) {
   117             out.writeByte(0);
   115             out.writeByte(0);
   118         }
   116         }
   119         super.setIndex(getTargetOffset()); // Write default target offset
   117         super.setIndex(getTargetOffset()); // Write default target offset
   120         out.writeInt(super.getIndex());
   118         out.writeInt(super.getIndex());
   121     }
   119     }
   122 
   120 
       
   121 
   123     /**
   122     /**
   124      * Read needed data (e.g. index) from file.
   123      * Read needed data (e.g. index) from file.
   125      */
   124      */
   126     @Override
   125     @Override
   127     protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException {
   126     protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException {
   128         padding = (4 - (bytes.getIndex() % 4)) % 4; // Compute number of pad bytes
   127         padding = (4 - (bytes.getIndex() % 4)) % 4; // Compute number of pad bytes
   129         for (int i = 0; i < padding; i++) {
   128         for (int i = 0; i < padding; i++) {
   130             bytes.readByte();
   129             bytes.readByte();
   131         }
   130         }
   132         // Default branch target common for both cases (TABLESWITCH, LOOKUPSWITCH)
   131         // Default branch target common for both cases (TABLESWITCH, LOOKUPSWITCH)
   133         super.setIndex(bytes.readInt());
   132         super.setIndex(bytes.readInt());
   134     }
   133     }
   135 
   134 
       
   135 
   136     /**
   136     /**
   137      * @return mnemonic for instruction
   137      * @return mnemonic for instruction
   138      */
   138      */
   139     @Override
   139     @Override
   140     public String toString(final boolean verbose) {
   140     public String toString( final boolean verbose ) {
   141         final StringBuilder buf = new StringBuilder(super.toString(verbose));
   141         final StringBuilder buf = new StringBuilder(super.toString(verbose));
   142         if (verbose) {
   142         if (verbose) {
   143             for (int i = 0; i < match_length; i++) {
   143             for (int i = 0; i < match_length; i++) {
   144                 String s = "null";
   144                 String s = "null";
   145                 if (targets[i] != null) {
   145                 if (targets[i] != null) {
   152             buf.append(" ...");
   152             buf.append(" ...");
   153         }
   153         }
   154         return buf.toString();
   154         return buf.toString();
   155     }
   155     }
   156 
   156 
       
   157 
   157     /**
   158     /**
   158      * Set branch target for `i'th case
   159      * Set branch target for `i'th case
   159      */
   160      */
   160     public void setTarget(final int i, final InstructionHandle target) { // TODO could be package-protected?
   161     public void setTarget( final int i, final InstructionHandle target ) { // TODO could be package-protected?
   161         notifyTarget(targets[i], target, this);
   162         notifyTarget(targets[i], target, this);
   162         targets[i] = target;
   163         targets[i] = target;
   163     }
   164     }
   164 
   165 
       
   166 
   165     /**
   167     /**
   166      * @param old_ih old target
   168      * @param old_ih old target
   167      * @param new_ih new target
   169      * @param new_ih new target
   168      */
   170      */
   169     @Override
   171     @Override
   170     public void updateTarget(final InstructionHandle old_ih, final InstructionHandle new_ih) {
   172     public void updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih ) {
   171         boolean targeted = false;
   173         boolean targeted = false;
   172         if (super.getTarget() == old_ih) {
   174         if (super.getTarget() == old_ih) {
   173             targeted = true;
   175             targeted = true;
   174             setTarget(new_ih);
   176             setTarget(new_ih);
   175         }
   177         }
   182         if (!targeted) {
   184         if (!targeted) {
   183             throw new ClassGenException("Not targeting " + old_ih);
   185             throw new ClassGenException("Not targeting " + old_ih);
   184         }
   186         }
   185     }
   187     }
   186 
   188 
       
   189 
   187     /**
   190     /**
   188      * @return true, if ih is target of this instruction
   191      * @return true, if ih is target of this instruction
   189      */
   192      */
   190     @Override
   193     @Override
   191     public boolean containsTarget(final InstructionHandle ih) {
   194     public boolean containsTarget( final InstructionHandle ih ) {
   192         if (super.getTarget() == ih) {
   195         if (super.getTarget() == ih) {
   193             return true;
   196             return true;
   194         }
   197         }
   195         for (final InstructionHandle target2 : targets) {
   198         for (final InstructionHandle target2 : targets) {
   196             if (target2 == ih) {
   199             if (target2 == ih) {
   197                 return true;
   200                 return true;
   198             }
   201             }
   199         }
   202         }
   200         return false;
   203         return false;
   201     }
   204     }
       
   205 
   202 
   206 
   203     @Override
   207     @Override
   204     protected Object clone() throws CloneNotSupportedException {
   208     protected Object clone() throws CloneNotSupportedException {
   205         final Select copy = (Select) super.clone();
   209         final Select copy = (Select) super.clone();
   206         copy.match = match.clone();
   210         copy.match = match.clone();
   207         copy.indices = indices.clone();
   211         copy.indices = indices.clone();
   208         copy.targets = targets.clone();
   212         copy.targets = targets.clone();
   209         return copy;
   213         return copy;
   210     }
   214     }
   211 
   215 
       
   216 
   212     /**
   217     /**
   213      * Inform targets that they're not targeted anymore.
   218      * Inform targets that they're not targeted anymore.
   214      */
   219      */
   215     @Override
   220     @Override
   216     void dispose() {
   221     void dispose() {
   218         for (final InstructionHandle target2 : targets) {
   223         for (final InstructionHandle target2 : targets) {
   219             target2.removeTargeter(this);
   224             target2.removeTargeter(this);
   220         }
   225         }
   221     }
   226     }
   222 
   227 
       
   228 
   223     /**
   229     /**
   224      * @return array of match indices
   230      * @return array of match indices
   225      */
   231      */
   226     public int[] getMatchs() {
   232     public int[] getMatchs() {
   227         return match;
   233         return match;
   228     }
   234     }
   229 
   235 
       
   236 
   230     /**
   237     /**
   231      * @return array of match target offsets
   238      * @return array of match target offsets
   232      */
   239      */
   233     public int[] getIndices() {
   240     public int[] getIndices() {
   234         return indices;
   241         return indices;
   235     }
   242     }
   236 
   243 
       
   244 
   237     /**
   245     /**
   238      * @return array of match targets
   246      * @return array of match targets
   239      */
   247      */
   240     public InstructionHandle[] getTargets() {
   248     public InstructionHandle[] getTargets() {
   241         return targets;
   249         return targets;
   247      */
   255      */
   248     final int getMatch(final int index) {
   256     final int getMatch(final int index) {
   249         return match[index];
   257         return match[index];
   250     }
   258     }
   251 
   259 
       
   260 
   252     /**
   261     /**
   253      * @return index entry from indices
   262      * @return index entry from indices
   254      * @since 6.0
   263      * @since 6.0
   255      */
   264      */
   256     final int getIndices(final int index) {
   265     final int getIndices(final int index) {
   263      */
   272      */
   264     final InstructionHandle getTarget(final int index) {
   273     final InstructionHandle getTarget(final int index) {
   265         return targets[index];
   274         return targets[index];
   266     }
   275     }
   267 
   276 
       
   277 
   268     /**
   278     /**
   269      * @return the fixed_length
   279      * @return the fixed_length
   270      * @since 6.0
   280      * @since 6.0
   271      */
   281      */
   272     final int getFixed_length() {
   282     final int getFixed_length() {
   273         return fixed_length;
   283         return fixed_length;
   274     }
   284     }
   275 
   285 
       
   286 
   276     /**
   287     /**
   277      * @param fixed_length the fixed_length to set
   288      * @param fixed_length the fixed_length to set
   278      * @since 6.0
   289      * @since 6.0
   279      */
   290      */
   280     final void setFixed_length(final int fixed_length) {
   291     final void setFixed_length(final int fixed_length) {
   281         this.fixed_length = fixed_length;
   292         this.fixed_length = fixed_length;
   282     }
   293     }
   283 
   294 
       
   295 
   284     /**
   296     /**
   285      * @return the match_length
   297      * @return the match_length
   286      * @since 6.0
   298      * @since 6.0
   287      */
   299      */
   288     final int getMatch_length() {
   300     final int getMatch_length() {
   289         return match_length;
   301         return match_length;
   290     }
   302     }
       
   303 
   291 
   304 
   292     /**
   305     /**
   293      * @param match_length the match_length to set
   306      * @param match_length the match_length to set
   294      * @since 6.0
   307      * @since 6.0
   295      */
   308      */
   342      */
   355      */
   343     final int getPadding() {
   356     final int getPadding() {
   344         return padding;
   357         return padding;
   345     }
   358     }
   346 
   359 
   347     /**
   360 
   348      * @since 6.0
   361     /** @since 6.0 */
   349      */
       
   350     final int setIndices(final int i, final int value) {
   362     final int setIndices(final int i, final int value) {
   351         indices[i] = value;
   363         indices[i] = value;
   352         return value;  // Allow use in nested calls
   364         return value;  // Allow use in nested calls
   353     }
   365     }
   354 }
   366 }