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 package com.sun.org.apache.bcel.internal.generic;
  22 
  23 /**
  24  * BranchHandle is returned by specialized InstructionList.append() whenever a
  25  * BranchInstruction is appended. This is useful when the target of this
  26  * instruction is not known at time of creation and must be set later via
  27  * setTarget().
  28  *
  29  * @see InstructionHandle
  30  * @see Instruction
  31  * @see InstructionList
  32  * @version $Id: BranchHandle.java 1749603 2016-06-21 20:50:19Z ggregory $
  33  */
  34 public final class BranchHandle extends InstructionHandle {
  35 
  36     // This is also a cache in case the InstructionHandle#swapInstruction() method is used
  37     // See BCEL-273
  38     private BranchInstruction bi; // An alias in fact, but saves lots of casts
  39 
  40     private BranchHandle(final BranchInstruction i) {
  41         super(i);
  42         bi = i;
  43     }
  44 
  45     /**
  46      * Factory methods.
  47      */
  48     private static BranchHandle bh_list = null; // List of reusable handles
  49 
  50     static BranchHandle getBranchHandle(final BranchInstruction i) {
  51         if (bh_list == null) {
  52             return new BranchHandle(i);
  53         }
  54         final BranchHandle bh = bh_list;
  55         bh_list = (BranchHandle) bh.getNext();
  56         bh.setInstruction(i);
  57         return bh;
  58     }
  59 
  60     /**
  61      * Handle adds itself to the list of resuable handles.
  62      */
  63     @Override
  64     protected void addHandle() {
  65         super.setNext(bh_list);
  66         bh_list = this;
  67     }
  68 
  69 
  70     /* Override InstructionHandle methods: delegate to branch instruction.
  71      * Through this overriding all access to the private i_position field should
  72      * be prevented.
  73      */
  74     @Override
  75     public int getPosition() {
  76         return bi.getPosition();
  77     }
  78 
  79     @Override
  80     void setPosition(final int pos) {
  81         // Original code: i_position = bi.position = pos;
  82         bi.setPosition(pos);
  83         super.setPosition(pos);
  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      * Pass new target to instruction.
  95      */
  96     public void setTarget(final InstructionHandle ih) {
  97         bi.setTarget(ih);
  98     }
  99 
 100     /**
 101      * Update target of instruction.
 102      */
 103     public void updateTarget(final InstructionHandle old_ih, final InstructionHandle new_ih) {
 104         bi.updateTarget(old_ih, new_ih);
 105     }
 106 
 107     /**
 108      * @return target of instruction.
 109      */
 110     public InstructionHandle getTarget() {
 111         return bi.getTarget();
 112     }
 113 
 114     /**
 115      * Set new contents. Old instruction is disposed and may not be used
 116      * anymore.
 117      */
 118     @Override // This is only done in order to apply the additional type check; could be merged with super impl.
 119     public void setInstruction(final Instruction i) { // TODO could be package-protected?
 120         super.setInstruction(i);
 121         if (!(i instanceof BranchInstruction)) {
 122             throw new ClassGenException("Assigning " + i
 123                     + " to branch handle which is not a branch instruction");
 124         }
 125         bi = (BranchInstruction) i;
 126     }
 127 }