001    package serp.bytecode;
002    
003    import java.io.*;
004    import java.util.*;
005    
006    import serp.bytecode.visitor.*;
007    
008    /**
009     * An instruction that specifies a position in the code block to jump to.
010     * Examples include <code>go2, jsr</code>, etc.
011     *
012     * @author Abe White
013     */
014    public class GotoInstruction extends JumpInstruction {
015    
016        GotoInstruction(Code owner, int opcode) {
017            super(owner, opcode);
018        }
019    
020        public int getStackChange() {
021            if (getOpcode() == Constants.JSR)
022                return 1;
023            return 0;
024        }
025    
026        int getLength() {
027            switch (getOpcode()) {
028            case Constants.GOTOW:
029            case Constants.JSRW:
030                return super.getLength() + 4;
031            default:
032                return super.getLength() + 2;
033            }
034        }
035    
036        public void setOffset(int offset) {
037            super.setOffset(offset);
038            calculateOpcode();
039        }
040    
041        /**
042         * Calculate our opcode based on the offset size.
043         */
044        private void calculateOpcode() {
045            int len = getLength();
046            int offset;
047            switch (getOpcode()) {
048            case Constants.GOTO:
049            case Constants.GOTOW:
050                offset = getOffset();
051                if (offset < (2 << 16))
052                    setOpcode(Constants.GOTO);
053                else
054                    setOpcode(Constants.GOTOW);
055                break;
056            case Constants.JSR:
057            case Constants.JSRW:
058                offset = getOffset();
059                if (offset < (2 << 16))
060                    setOpcode(Constants.JSR);
061                else
062                    setOpcode(Constants.JSRW);
063                break;
064            }
065            if (len != getLength())
066                invalidateByteIndexes();
067        }
068    }