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

📄 classwriter.java

📁 GJC编译器的源代码。是一个开放源代码的工业级编译器。
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/**
 * @(#)ClassWriter.java	1.48 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 java.io.*;

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

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


/**
 * This class provides operations to map an internal symbol table graph
 *  rooted in a ClassSymbol into a classfile.
 */
public class ClassWriter extends ClassFile implements Flags, Kinds, TypeTags {
    private static final Context.Key classWriterKey = new Context.Key();
    private final Symtab syms;

    /**
     * Can be reassigned from outside: the output directory.
     *  If outDir = null, files are written into same directory as the sources
     *  the were generated from.
     */
    public File outDir = null;

    /**
     * Switch: verbose output.
     */
    private boolean verbose;

    /**
     * Switch: scrable private names.
     */
    private boolean scramble;

    /**
     * Switch: scrable private names.
     */
    private boolean scrambleAll;

    /**
     * Switch: retrofit mode.
     */
    private boolean retrofit;

    /**
     * Switch: emit source file attribute.
     */
    private boolean emitSourceFile;

    /**
     * Switch: generate CharacterRangeTable attribute.
     */
    private boolean genCrt;

    /**
     * Target class version.
     */
    private Target target;

    /**
     * The initial sizes of the data and constant pool buffers.
     *  sizes are increased when buffers get full.
     */
    static final int DATA_BUF_SIZE = 65520;
    static final int POOL_BUF_SIZE = 131056;

    /**
     * An output buffer for member info.
     */
    ByteBuffer databuf = new ByteBuffer(DATA_BUF_SIZE);

    /**
     * An output buffer for the constant pool.
     */
    ByteBuffer poolbuf = new ByteBuffer(POOL_BUF_SIZE);

    /**
     * An output buffer for type signatures.
     */
    ByteBuffer sigbuf = new ByteBuffer();

    /**
     * The constant pool.
     */
    Pool pool;

    /**
     * The inner classes to be written, as a set.
     */
    Set innerClasses;

    /**
     * The inner classes to be written, as a queue where
     *  enclosing classes come first.
     */
    ListBuffer innerClassesQueue;

    /**
     * The log to use for verbose output.
     */
    private final Log log;

    /**
     * The name table.
     */
    private final Name.Table names;

    /**
     * Get the ClassWriter instance for this context.
     */
    public static ClassWriter instance(Context context) {
        ClassWriter instance = (ClassWriter) context.get(classWriterKey);
        if (instance == null)
            instance = new ClassWriter(context);
        return instance;
    }

    /**
      * Construct a class writer, given an options table.
      */
    private ClassWriter(Context context) {
        super();
        context.put(classWriterKey, this);
        log = Log.instance(context);
        names = Name.Table.instance(context);
        syms = Symtab.instance(context);
        Options options = Options.instance(context);
        target = Target.instance(context);
        verbose = options.get("-verbose") != null;
        scramble = options.get("-scramble") != null;
        scrambleAll = options.get("-scrambleAll") != null;
        retrofit = options.get("-retrofit") != null;
        genCrt = options.get("-Xjcov") != null;
        emitSourceFile =
                options.get("-g:") == null || options.get("-g:source") != null;
        String od = (String) options.get("-d");
        if (od != null)
            outDir = new File(od);
        String dumpModFlags = (String) options.get("dumpmodifiers");
        dumpClassModifiers =
                (dumpModFlags != null && dumpModFlags.indexOf('c') != -1);
        dumpFieldModifiers =
                (dumpModFlags != null && dumpModFlags.indexOf('f') != -1);
        dumpInnerClassModifiers =
                (dumpModFlags != null && dumpModFlags.indexOf('i') != -1);
        dumpMethodModifiers =
                (dumpModFlags != null && dumpModFlags.indexOf('m') != -1);
    }

    /**
      * Value of option 'dumpmodifiers' is a string
      *  indicating which modifiers should be dumped for debugging:
      *    'c' -- classes
      *    'f' -- fields
      *    'i' -- innerclass attributes
      *    'm' -- methods
      *  For example, to dump everything:
      *    javac -XDdumpmodifiers=cifm MyProg.java
      */
    private final boolean dumpClassModifiers;
    private final boolean dumpFieldModifiers;
    private final boolean dumpInnerClassModifiers;
    private final boolean dumpMethodModifiers;

    /**
     * Return flags as a string, separated by " ".
     */
    public static String flagNames(long flags) {
        StringBuffer sbuf = new StringBuffer();
        int i = 0;
        long f = flags & StandardFlags;
        while (f != 0) {
            if ((f & 1) != 0)
                sbuf.append(" " + flagName[i]);
            f = f >> 1;
            i++;
        }
        return sbuf.toString();
    }
    private static final String[] flagName = {"PUBLIC", "PRIVATE", "PROTECTED", "STATIC",
    "FINAL", "SUPER", "VOLATILE", "TRANSIENT", "NATIVE", "INTERFACE", "ABSTRACT",
    "STRICTFP"};

    /**
     * Write a character into given byte buffer;
     *  byte buffer will not be grown.
     */
    void putChar(ByteBuffer buf, int op, int x) {
        buf.elems[op] = (byte)((x >> 8) & 255);
        buf.elems[op + 1] = (byte)((x) & 255);
    }

    /**
      * Write an integer into given byte buffer;
      *  byte buffer will not be grown.
      */
    void putInt(ByteBuffer buf, int adr, int x) {
        buf.elems[adr] = (byte)((x >> 24) & 255);
        buf.elems[adr + 1] = (byte)((x >> 16) & 255);
        buf.elems[adr + 2] = (byte)((x >> 8) & 255);
        buf.elems[adr + 3] = (byte)((x) & 255);
    }

    /**
      * Assemble signature of given type in string buffer.
      */
    void assembleSig(Type type) {
        switch (type.tag) {
        case BYTE:
            sigbuf.appendByte('B');
            break;

        case SHORT:
            sigbuf.appendByte('S');
            break;

        case CHAR:
            sigbuf.appendByte('C');
            break;

        case INT:
            sigbuf.appendByte('I');
            break;

        case LONG:
            sigbuf.appendByte('J');
            break;

        case FLOAT:
            sigbuf.appendByte('F');
            break;

        case DOUBLE:
            sigbuf.appendByte('D');
            break;

        case BOOLEAN:
            sigbuf.appendByte('Z');
            break;

        case VOID:
            sigbuf.appendByte('V');
            break;

        case CLASS:
            ClassType ct = (ClassType) type;
            ClassSymbol c = (ClassSymbol) ct.tsym;
            enterInner(c);
            if (ct.outer().allparams().nonEmpty()) {
                assembleSig(ct.outer());
                sigbuf.appendByte('.');
            }
            sigbuf.appendByte('L');
            sigbuf.appendBytes(externalize(c.flatname));
            sigbuf.appendByte(';');
            break;

        case ARRAY:
            ArrayType at = (ArrayType) type;
            sigbuf.appendByte('[');
            assembleSig(at.elemtype);
            break;

        case METHOD:
            MethodType mt = (MethodType) type;
            sigbuf.appendByte('(');
            assembleSig(mt.argtypes);
            sigbuf.appendByte(')');
            assembleSig(mt.restype);
            break;

        default:
            assert false :
            "typeSig" + type.tag;

        }
    }

    void assembleSig(List types) {
        for (List ts = types; ts.nonEmpty(); ts = ts.tail)
            assembleSig((Type) ts.head);
    }

    /**
      * Return signature of given type
      */
    Name typeSig(Type type) {
        assert sigbuf.length == 0;
        assembleSig(type);
        Name n = sigbuf.toName(names);
        sigbuf.reset();
        return n;
    }

    /**
      * Given a type t, return the extended class name of its erasure in
      *  external representation.
      */
    public Name xClassName(Type t) {
        if (t.tag == CLASS) {
            return names.fromUtf(externalize(t.tsym.flatName()));
        } else if (t.tag == ARRAY) {
            return typeSig(t.erasure());
        } else {
            throw new AssertionError("xClassName");
        }
    }

    /**
      * Thrown when the constant pool is over full.
      */
    public static class PoolOverflow extends Exception {

        public PoolOverflow() {
            super();
        }
    }

    public static class StringOverflow extends Exception {
        public final String value;

        public StringOverflow(String s) {
            super();
            value = s;
        }
    }

    /**
      * Write constant pool to pool buffer.
      *  Note: during writing, constant pool
      *  might grow since some parts of constants still need to be entered.
      */
    void writePool(Pool pool) throws PoolOverflow, StringOverflow {
        int poolCountIdx = poolbuf.length;
        poolbuf.appendChar(0);
        int i = 1;
        while (i < pool.pp) {
            Object value = pool.pool[i];
            assert value != null;
            if (value instanceof Pool.Method)
                value = ((Pool.Method) value).m;
            else if (value instanceof Pool.Variable)
                value = ((Pool.Variable) value).v;
            if (value instanceof MethodSymbol) {
                MethodSymbol m = (MethodSymbol) value;
                poolbuf.appendByte((m.owner.flags() & INTERFACE) != 0 ?
                        CONSTANT_InterfaceMethodref : CONSTANT_Methodref);
                poolbuf.appendChar(pool.put(m.owner));
                poolbuf.appendChar(pool.put(nameType(m)));
            } else if (value instanceof VarSymbol) {
                VarSymbol v = (VarSymbol) value;
                poolbuf.appendByte(CONSTANT_Fieldref);
                poolbuf.appendChar(pool.put(v.owner));
                poolbuf.appendChar(pool.put(nameType(v)));
            } else if (value instanceof Name) {
                poolbuf.appendByte(CONSTANT_Utf8);
                byte[] bs = ((Name) value).toUtf();
                poolbuf.appendChar(bs.length);
                poolbuf.appendBytes(bs, 0, bs.length);
                if (bs.length > Pool.MAX_STRING_LENGTH)
                    throw new StringOverflow(value.toString());
            } else if (value instanceof ClassSymbol) {
                ClassSymbol c = (ClassSymbol) value;
                if (c.owner.kind == TYP)
                    pool.put(c.owner);
                poolbuf.appendByte(CONSTANT_Class);
                if (c.type.tag == ARRAY) {
                    poolbuf.appendChar(pool.put(typeSig(c.type)));
                } else {
                    poolbuf.appendChar(
                            pool.put(names.fromUtf(externalize(c.flatname))));
                    enterInner(c);
                }
            } else if (value instanceof NameAndType) {
                NameAndType nt = (NameAndType) value;
                poolbuf.appendByte(CONSTANT_NameandType);
                poolbuf.appendChar(pool.put(nt.name));
                poolbuf.appendChar(pool.put(typeSig(nt.type)));
            } else if (value instanceof Integer) {
                poolbuf.appendByte(CONSTANT_Integer);
                poolbuf.appendInt(((Integer) value).intValue());
            } else if (value instanceof Long) {
                poolbuf.appendByte(CONSTANT_Long);
                poolbuf.appendLong(((Long) value).longValue());
                i++;
            } else if (value instanceof Float) {
                poolbuf.appendByte(CONSTANT_Float);
                poolbuf.appendFloat(((Float) value).floatValue());
            } else if (value instanceof Double) {
                poolbuf.appendByte(CONSTANT_Double);
                poolbuf.appendDouble(((Double) value).doubleValue());
                i++;
            } else if (value instanceof String) {
                poolbuf.appendByte(CONSTANT_String);
                poolbuf.appendChar(pool.put(names.fromString((String) value)));
            } else if (value instanceof Type) {
                poolbuf.appendByte(CONSTANT_Class);
                poolbuf.appendChar(pool.put(xClassName((Type) value)));
            } else {
                assert false :
                "writePool " + value;
            }
            i++;
        }
        if (pool.pp > Pool.MAX_ENTRIES)
            throw new PoolOverflow();
        putChar(poolbuf, poolCountIdx, pool.pp);
    }

    /**
      * Given a field, return its name.
      */
    Name fieldName(Symbol sym) {
        if (scramble && (sym.flags() & PRIVATE) != 0 || scrambleAll &&
                (sym.flags() & (PROTECTED | PUBLIC)) == 0)
            return names.fromString("_$" + sym.name.index);
        else

⌨️ 快捷键说明

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