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 package org.apache.bcel.generic;
18
19 /**
20 * Super class for JSR - Jump to subroutine
21 */
22 public abstract class JsrInstruction extends BranchInstruction implements UnconditionalBranch, TypedInstruction, StackProducer {
23
24 /**
25 * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise.
26 */
27 JsrInstruction() {
28 }
29
30 JsrInstruction(final short opcode, final InstructionHandle target) {
31 super(opcode, target);
32 }
33
34 /**
35 * @return return address type
36 */
37 @Override
38 public Type getType(final ConstantPoolGen cp) {
39 return new ReturnaddressType(physicalSuccessor());
40 }
41
42 /**
43 * Returns an InstructionHandle to the physical successor of this JsrInstruction. <B>For this method to work, this
44 * JsrInstruction object must not be shared between multiple InstructionHandle objects!</B> Formally, there must not be
45 * InstructionHandle objects i, j where i != j and i.getInstruction() == this == j.getInstruction().
46 *
47 * @return an InstructionHandle to the "next" instruction that will be executed when RETurned from a subroutine.
48 */
49 public InstructionHandle physicalSuccessor() {
50 InstructionHandle ih = super.getTarget();
51 // Rewind!
52 while (ih.getPrev() != null) {
53 ih = ih.getPrev();
54 }
55 // Find the handle for "this" JsrInstruction object.
56 while (ih.getInstruction() != this) {
57 ih = ih.getNext();
58 }
59 final InstructionHandle toThis = ih;
60 while (ih != null) {
61 ih = ih.getNext();
62 if (ih != null && ih.getInstruction() == this) {
63 throw new IllegalStateException("physicalSuccessor() called on a shared JsrInstruction.");
64 }
65 }
66 // Return the physical successor
67 return toThis.getNext();
68 }
69 }