001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 */ 018package org.apache.bcel.generic; 019 020/** 021 * Super class for JSR - Jump to subroutine 022 * 023 */ 024public abstract class JsrInstruction extends BranchInstruction implements UnconditionalBranch, 025 TypedInstruction, StackProducer { 026 027 JsrInstruction(final short opcode, final InstructionHandle target) { 028 super(opcode, target); 029 } 030 031 032 /** 033 * Empty constructor needed for Instruction.readInstruction. 034 * Not to be used otherwise. 035 */ 036 JsrInstruction() { 037 } 038 039 040 /** @return return address type 041 */ 042 @Override 043 public Type getType( final ConstantPoolGen cp ) { 044 return new ReturnaddressType(physicalSuccessor()); 045 } 046 047 048 /** 049 * Returns an InstructionHandle to the physical successor 050 * of this JsrInstruction. <B>For this method to work, 051 * this JsrInstruction object must not be shared between 052 * multiple InstructionHandle objects!</B> 053 * Formally, there must not be InstructionHandle objects 054 * i, j where i != j and i.getInstruction() == this == 055 * j.getInstruction(). 056 * @return an InstructionHandle to the "next" instruction that 057 * will be executed when RETurned from a subroutine. 058 */ 059 public InstructionHandle physicalSuccessor() { 060 InstructionHandle ih = super.getTarget(); 061 // Rewind! 062 while (ih.getPrev() != null) { 063 ih = ih.getPrev(); 064 } 065 // Find the handle for "this" JsrInstruction object. 066 while (ih.getInstruction() != this) { 067 ih = ih.getNext(); 068 } 069 final InstructionHandle toThis = ih; 070 while (ih != null) { 071 ih = ih.getNext(); 072 if ((ih != null) && (ih.getInstruction() == this)) { 073 throw new RuntimeException("physicalSuccessor() called on a shared JsrInstruction."); 074 } 075 } 076 // Return the physical successor 077 return toThis.getNext(); 078 } 079}