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 }