001package serp.bytecode;
002
003import java.io.*;
004import java.util.*;
005
006import 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 */
014public 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}