View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.bcel.generic;
20  
21  /**
22   * Super class for JSR - Jump to subroutine
23   */
24  public abstract class JsrInstruction extends BranchInstruction implements UnconditionalBranch, TypedInstruction, StackProducer {
25  
26      /**
27       * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise.
28       */
29      JsrInstruction() {
30      }
31  
32      JsrInstruction(final short opcode, final InstructionHandle target) {
33          super(opcode, target);
34      }
35  
36      /**
37       * @return return address type
38       */
39      @Override
40      public Type getType(final ConstantPoolGen cp) {
41          return new ReturnaddressType(physicalSuccessor());
42      }
43  
44      /**
45       * Returns an InstructionHandle to the physical successor of this JsrInstruction. <B>For this method to work, this
46       * JsrInstruction object must not be shared between multiple InstructionHandle objects!</B> Formally, there must not be
47       * InstructionHandle objects i, j where i != j and i.getInstruction() == this == j.getInstruction().
48       *
49       * @return an InstructionHandle to the "next" instruction that will be executed when RETurned from a subroutine.
50       */
51      public InstructionHandle physicalSuccessor() {
52          InstructionHandle ih = super.getTarget();
53          // Rewind!
54          while (ih.getPrev() != null) {
55              ih = ih.getPrev();
56          }
57          // Find the handle for "this" JsrInstruction object.
58          while (ih.getInstruction() != this) {
59              ih = ih.getNext();
60          }
61          final InstructionHandle toThis = ih;
62          while (ih != null) {
63              ih = ih.getNext();
64              if (ih != null && ih.getInstruction() == this) {
65                  throw new IllegalStateException("physicalSuccessor() called on a shared JsrInstruction.");
66              }
67          }
68          // Return the physical successor
69          return toThis.getNext();
70      }
71  }