Home | History | Annotate | Download | only in generic
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  */
     18 package org.apache.bcel.generic;
     19 
     20 /**
     21  * BranchHandle is returned by specialized InstructionList.append() whenever a
     22  * BranchInstruction is appended. This is useful when the target of this
     23  * instruction is not known at time of creation and must be set later
     24  * via setTarget().
     25  *
     26  * @see InstructionHandle
     27  * @see Instruction
     28  * @see InstructionList
     29  * @version $Id$
     30  */
     31 public final class BranchHandle extends InstructionHandle {
     32 
     33     // This is also a cache in case the InstructionHandle#swapInstruction() method is used
     34     // See BCEL-273
     35     private BranchInstruction bi; // An alias in fact, but saves lots of casts
     36 
     37 
     38     private BranchHandle(final BranchInstruction i) {
     39         super(i);
     40         bi = i;
     41     }
     42 
     43     /** Factory methods.
     44      */
     45     private static BranchHandle bh_list = null; // List of reusable handles
     46 
     47 
     48     static BranchHandle getBranchHandle( final BranchInstruction i ) {
     49         if (bh_list == null) {
     50             return new BranchHandle(i);
     51         }
     52         final BranchHandle bh = bh_list;
     53         bh_list = (BranchHandle) bh.getNext();
     54         bh.setInstruction(i);
     55         return bh;
     56     }
     57 
     58 
     59     /** Handle adds itself to the list of resuable handles.
     60      */
     61     @Override
     62     protected void addHandle() {
     63         super.setNext(bh_list);
     64         bh_list = this;
     65     }
     66 
     67 
     68     /* Override InstructionHandle methods: delegate to branch instruction.
     69      * Through this overriding all access to the private i_position field should
     70      * be prevented.
     71      */
     72     @Override
     73     public int getPosition() {
     74         return bi.getPosition();
     75     }
     76 
     77 
     78     @Override
     79     void setPosition( final int pos ) {
     80         // Original code: i_position = bi.position = pos;
     81         bi.setPosition(pos);
     82         super.setPosition(pos);
     83     }
     84 
     85 
     86     @Override
     87     protected int updatePosition( final int offset, final int max_offset ) {
     88         final int x = bi.updatePosition(offset, max_offset);
     89         super.setPosition(bi.getPosition());
     90         return x;
     91     }
     92 
     93 
     94     /**
     95      * Pass new target to instruction.
     96      */
     97     public void setTarget( final InstructionHandle ih ) {
     98         bi.setTarget(ih);
     99     }
    100 
    101 
    102     /**
    103      * Update target of instruction.
    104      */
    105     public void updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih ) {
    106         bi.updateTarget(old_ih, new_ih);
    107     }
    108 
    109 
    110     /**
    111      * @return target of instruction.
    112      */
    113     public InstructionHandle getTarget() {
    114         return bi.getTarget();
    115     }
    116 
    117 
    118     /**
    119      * Set new contents. Old instruction is disposed and may not be used anymore.
    120      */
    121     @Override // This is only done in order to apply the additional type check; could be merged with super impl.
    122     public void setInstruction( final Instruction i ) { // TODO could be package-protected?
    123         super.setInstruction(i);
    124         if (!(i instanceof BranchInstruction)) {
    125             throw new ClassGenException("Assigning " + i
    126                     + " to branch handle which is not a branch instruction");
    127         }
    128         bi = (BranchInstruction) i;
    129     }
    130 }
    131