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    import java.io.DataOutputStream;
021    import java.io.IOException;
022    
023    /** 
024     * JSR - Jump to subroutine
025     *
026     * @version $Id: JSR.java 1152072 2011-07-29 01:54:05Z dbrosius $
027     * @author  <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
028     */
029    public class JSR extends JsrInstruction implements VariableLengthInstruction {
030    
031        private static final long serialVersionUID = 7425681395340093184L;
032    
033    
034        /**
035         * Empty constructor needed for the Class.newInstance() statement in
036         * Instruction.readInstruction(). Not to be used otherwise.
037         */
038        JSR() {
039        }
040    
041    
042        public JSR(InstructionHandle target) {
043            super(org.apache.bcel.Constants.JSR, target);
044        }
045    
046    
047        /**
048         * Dump instruction as byte code to stream out.
049         * @param out Output stream
050         */
051        @Override
052        public void dump( DataOutputStream out ) throws IOException {
053            index = getTargetOffset();
054            if (opcode == org.apache.bcel.Constants.JSR) {
055                super.dump(out);
056            } else { // JSR_W
057                index = getTargetOffset();
058                out.writeByte(opcode);
059                out.writeInt(index);
060            }
061        }
062    
063    
064        @Override
065        protected int updatePosition( int offset, int max_offset ) {
066            int i = getTargetOffset(); // Depending on old position value
067            position += offset; // Position may be shifted by preceding expansions
068            if (Math.abs(i) >= (32767 - max_offset)) { // to large for short (estimate)
069                opcode = org.apache.bcel.Constants.JSR_W;
070                short old_length = length;
071                length = 5;
072                return length - old_length;
073            }
074            return 0;
075        }
076    
077    
078        /**
079         * Call corresponding visitor method(s). The order is:
080         * Call visitor methods of implemented interfaces first, then
081         * call methods according to the class hierarchy in descending order,
082         * i.e., the most specific visitXXX() call comes last.
083         *
084         * @param v Visitor object
085         */
086        @Override
087        public void accept( Visitor v ) {
088            v.visitStackProducer(this);
089            v.visitVariableLengthInstruction(this);
090            v.visitBranchInstruction(this);
091            v.visitJsrInstruction(this);
092            v.visitJSR(this);
093        }
094    }