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     */
018    package org.apache.bcel.generic;
019    
020    /** 
021     * Super class for JSR - Jump to subroutine
022     *
023     * @version $Id: JsrInstruction.java 992350 2010-09-03 16:18:20Z markt $
024     * @author  <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
025     */
026    public abstract class JsrInstruction extends BranchInstruction implements UnconditionalBranch,
027            TypedInstruction, StackProducer {
028    
029        private static final long serialVersionUID = -6438850002848773481L;
030    
031    
032        JsrInstruction(short opcode, InstructionHandle target) {
033            super(opcode, target);
034        }
035    
036    
037        /**
038         * Empty constructor needed for the Class.newInstance() statement in
039         * Instruction.readInstruction(). Not to be used otherwise.
040         */
041        JsrInstruction() {
042        }
043    
044    
045        /** @return return address type
046         */
047        public Type getType( ConstantPoolGen cp ) {
048            return new ReturnaddressType(physicalSuccessor());
049        }
050    
051    
052        /**
053         * Returns an InstructionHandle to the physical successor
054         * of this JsrInstruction. <B>For this method to work,
055         * this JsrInstruction object must not be shared between
056         * multiple InstructionHandle objects!</B>
057         * Formally, there must not be InstructionHandle objects
058         * i, j where i != j and i.getInstruction() == this ==
059         * j.getInstruction().
060         * @return an InstructionHandle to the "next" instruction that
061         * will be executed when RETurned from a subroutine.
062         */
063        public InstructionHandle physicalSuccessor() {
064            InstructionHandle ih = this.target;
065            // Rewind!
066            while (ih.getPrev() != null) {
067                ih = ih.getPrev();
068            }
069            // Find the handle for "this" JsrInstruction object.
070            while (ih.getInstruction() != this) {
071                ih = ih.getNext();
072            }
073            InstructionHandle toThis = ih;
074            while (ih != null) {
075                ih = ih.getNext();
076                if ((ih != null) && (ih.getInstruction() == this)) {
077                    throw new RuntimeException("physicalSuccessor() called on a shared JsrInstruction.");
078                }
079            }
080            // Return the physical successor                
081            return toThis.getNext();
082        }
083    }