⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 code.java

📁 GJC编译器的源代码。是一个开放源代码的工业级编译器。
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/**
 * @(#)Code.java	1.23 03/01/23
 *
 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.sun.tools.javac.v8.code;
import com.sun.tools.javac.v8.util.*;

import com.sun.tools.javac.v8.code.Symbol.*;


/**
 * An internal structure that corresponds to the code attribute of
 *  methods in a classfile. The class also provides some utility operations to
 *  generate bytecode instructions.
 */
public class Code implements ByteCodes, TypeTags {
    public static final boolean debugCode = false;

    /**
     * The maximum stack size.
     */
    public int max_stack = 0;

    /**
     * The maximum number of local variable slots.
     */
    public int max_locals = 0;

    /**
     * The code buffer.
     */
    public byte[] code = new byte[64];

    /**
     * the current code pointer.
     */
    public int cp = 0;

    /**
     * Check the code against VM spec limits; if
     *  problems report them and return true.
     */
    public boolean checkLimits(int pos, Log log) {
        if (cp > ClassFile.MAX_CODE) {
            log.error(pos, "limit.code");
            return true;
        }
        if (max_locals > ClassFile.MAX_LOCALS) {
            log.error(pos, "limit.locals");
            return true;
        }
        if (max_stack > ClassFile.MAX_STACK) {
            log.error(pos, "limit.stack");
            return true;
        }
        return false;
    }

    /**
      * A buffer for expression catch data. Each enter is a vector
      *  of four unsigned shorts.
      */
    ListBuffer catchInfo = new ListBuffer();

    /**
     * A buffer for line number information. Each entry is a vector
     *  of two unsigned shorts.
     */
    List lineInfo = new List();

    /**
     * The CharacterRangeTable
     */
    public CRTable crt;

    /**
     * Are we generating code with jumps >= 32K?
     */
    public boolean fatcode;

    /**
     * Code generation enabled?
     */
    private boolean alive = true;

    /**
     * The current stacksize.
     */
    public int stacksize = 0;

    /**
     * Is it forbidden to compactify code, because something is
     *  pointing to current location?
     */
    private boolean fixedPc = false;

    /**
     * The next available register.
     */
    public int nextreg = 0;

    /**
     * A chain for jumps to be resolved before the next opcode is emitted.
     *  We do this lazily to avoid jumps to jumps.
     */
    Chain pendingJumps = null;

    /**
     * The position of the currently statement, if we are at the
     *  start of this statement, NOPOS otherwise.
     *  We need this to emit line numbers lazily, which we need to do
     *  because of jump-to-jump optimization.
     */
    int pendingStatPos = 0;

    /**
     * Switch: emit variable debug info.
     */
    boolean varDebugInfo;

    /**
     * Switch: emit line number info.
     */
    boolean lineDebugInfo;

    /**
     * Construct a code object, given the settings of the fatcode,
     *  debugging info switches and the CharacterRangeTable.
     */
    public Code(boolean fatcode, boolean lineDebugInfo, boolean varDebugInfo,
            CRTable crt) {
        super();
        this.fatcode = fatcode;
        this.lineDebugInfo = lineDebugInfo;
        this.varDebugInfo = varDebugInfo;
        this.crt = crt;
        if (varDebugInfo) {
            defined = new Bits();
            lvar = new LocalVar[20];
        }
    }

    /**
      * Given a type, return its type code (used implicitly in the
      *  JVM architecture).
      */
    public static int typecode(Type type) {
        switch (type.tag) {
        case BYTE:
            return BYTEcode;

        case SHORT:
            return SHORTcode;

        case CHAR:
            return CHARcode;

        case INT:
            return INTcode;

        case LONG:
            return LONGcode;

        case FLOAT:
            return FLOATcode;

        case DOUBLE:
            return DOUBLEcode;

        case BOOLEAN:
            return BYTEcode;

        case VOID:
            return VOIDcode;

        case CLASS:

        case ARRAY:

        case METHOD:

        case BOT:
            return OBJECTcode;

        default:
            throw new AssertionError("typecode " + type.tag);

        }
    }

    /**
      * Collapse type code for subtypes of int to INTcode.
      */
    public static int truncate(int tc) {
        switch (tc) {
        case BYTEcode:

        case SHORTcode:

        case CHARcode:
            return INTcode;

        default:
            return tc;

        }
    }

    /**
      * The width in bytes of objects of the type.
      */
    public static int width(int typecode) {
        switch (typecode) {
        case LONGcode:

        case DOUBLEcode:
            return 2;

        case VOIDcode:
            return 0;

        default:
            return 1;

        }
    }

    public static int width(Type type) {
        return width(typecode(type));
    }

    /**
      * The total width taken up by a vector of objects.
      */
    public static int width(List types) {
        int w = 0;
        for (List l = types; l.nonEmpty(); l = l.tail)
            w = w + width((Type) l.head);
        return w;
    }

    /**
      * Given a type, return its code for allocating arrays of that type.
      */
    public static int arraycode(Type type) {
        switch (type.tag) {
        case BYTE:
            return 8;

        case BOOLEAN:
            return 4;

        case SHORT:
            return 9;

        case CHAR:
            return 5;

        case INT:
            return 10;

        case LONG:
            return 11;

        case FLOAT:
            return 6;

        case DOUBLE:
            return 7;

        case CLASS:
            return 0;

        case ARRAY:
            return 1;

        default:
            throw new AssertionError("arraycode " + type);

        }
    }

    /**
      * The current output code pointer.
      */
    public int curPc() {
        if (pendingJumps != null)
            resolvePending();
        if (pendingStatPos != Position.NOPOS)
            markStatBegin();
        fixedPc = true;
        return cp;
    }

    /**
      * Emit a byte of code.
      */
    public void emit1(int od) {
        if (alive) {
            if (cp == code.length) {
                byte[] newcode = new byte[cp * 2];
                System.arraycopy(code, 0, newcode, 0, cp);
                code = newcode;
            }
            code[cp++] = (byte) od;
        }
    }

    /**
      * Emit two bytes of code.
      */
    public void emit2(int od) {
        if (alive) {
            if (cp + 2 > code.length) {
                emit1(od >> 8);
                emit1(od);
            } else {
                code[cp++] = (byte)(od >> 8);
                code[cp++] = (byte) od;
            }
        }
    }

    /**
      * Emit four bytes of code.
      */
    public void emit4(int od) {
        if (alive) {
            if (cp + 4 > code.length) {
                emit1(od >> 24);
                emit1(od >> 16);
                emit1(od >> 8);
                emit1(od);
            } else {
                code[cp++] = (byte)(od >> 24);
                code[cp++] = (byte)(od >> 16);
                code[cp++] = (byte)(od >> 8);
                code[cp++] = (byte) od;
            }
        }
    }

    /**
      * Emit an opcode, adjust stacksize by sdiff.
      */
    public void emitop(int op, int sdiff) {
        if (pendingJumps != null)
            resolvePending();
        if (alive) {
            if (pendingStatPos != Position.NOPOS)
                markStatBegin();
            if (debugCode)
                System.err.println(cp + ":" + stacksize + ": " + mnem(op));
            emit1(op);
            if (sdiff <= -1000) {
                stacksize = stacksize + sdiff + 1000;
                alive = false;
                assert stacksize == 0;
            } else {
                stacksize = stacksize + sdiff;
                assert stacksize >= 0;
                if (stacksize > max_stack)
                    max_stack = stacksize;
            }
        }
    }

    /**
      * Emit an opcode, adjust stacksize by stackdiff[op].
      */
    public void emitop(int op) {
        emitop(op, stackdiff[op]);
    }

    /**
      * Emit an opcode with a one-byte operand field.
      */
    public void emitop1(int op, int od) {
        emitop(op);
        emit1(od);
    }

    /**
      * Emit an opcode with a one-byte operand field;
      *  widen if field does not fit in a byte.
      */
    public void emitop1w(int op, int od) {
        if (od > 255) {
            emitop(wide);
            emitop2(op, od);
        } else {
            emitop1(op, od);
        }
    }

    /**
      * Emit an opcode with a two-byte operand field.
      */
    public void emitop2(int op, int od) {
        emitop(op);
        emit2(od);
    }

    /**
      * Emit an opcode with a four-byte operand field.
      */
    public void emitop4(int op, int od) {
        emitop(op);
        emit4(od);
    }

    /**
      * Align code pointer to next `incr' boundary.
      */
    public void align(int incr) {
        if (alive)
            while (cp % incr != 0)
                emit1(0);
    }

    /**
      * Place a byte into code at address pc. Pre: pc + 1 <= cp.
      */
    public void put1(int pc, int op) {
        code[pc] = (byte) op;
    }

    /**
      * Place two bytes into code at address pc. Pre: pc + 2 <= cp.
      */
    public void put2(int pc, int od) {
        put1(pc, od >> 8);
        put1(pc + 1, od);
    }

    /**
      * Place four  bytes into code at address pc. Pre: pc + 4 <= cp.
      */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -