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

📄 gen.java

📁 java编译器gjc源码 java编译环境
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/**
 * @(#)Gen.java	1.97 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.comp;
import java.io.IOException;

import com.sun.tools.javac.v8.util.*;

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

import com.sun.tools.javac.v8.tree.*;

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

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

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

import com.sun.tools.javac.v8.tree.Tree.*;

import com.sun.tools.javac.v8.comp.Items.*;


/**
 * This pass maps flat Java (i.e. without inner classes) to bytecodes.
 */
public class Gen extends Tree.Visitor implements Flags, Kinds, TypeTags,
ByteCodes, CRTFlags {
    private static final Context.Key genKey = new Context.Key();
    private final Log log;
    private final Symtab syms;
    private final Check chk;
    private final Resolve rs;
    private final TreeMaker make;
    private final ClassWriter writer;
    private final Name.Table names;
    private final Target target;
    private final boolean generateIproxies;

    /**
     * A type that serves as the expected type for all method expressions.
     */
    private final Type methodType;

    public static Gen instance(Context context) {
        Gen instance = (Gen) context.get(genKey);
        if (instance == null)
            instance = new Gen(context);
        return instance;
    }

    private Gen(Context context) {
        super();
        context.put(genKey, this);
        names = Name.Table.instance(context);
        log = Log.instance(context);
        syms = Symtab.instance(context);
        chk = Check.instance(context);
        rs = Resolve.instance(context);
        make = TreeMaker.instance(context);
        writer = ClassWriter.instance(context);
        target = Target.instance(context);
        methodType = new MethodType(null, null, null, syms.methodClass);
        Options options = Options.instance(context);
        lineDebugInfo = options.get("-g:") == null || options.get("-g:lines") != null;
        varDebugInfo = options.get("-g:") == null ? options.get("-g") != null :
                options.get("-g:vars") != null;
        genCrt = options.get("-Xjcov") != null;
        generateIproxies = target.requiresIproxy() || options.get("miranda") != null;
        int setjsrlimit = 10;
        String jsrlimitString = (String) options.get("jsrlimit");
        if (jsrlimitString != null) {
            try {
                setjsrlimit = Integer.parseInt(jsrlimitString);
            } catch (NumberFormatException ex) {
            }
        }
        this.jsrlimit = setjsrlimit;
    }

    /**
      * Switches
      */
    private final boolean lineDebugInfo;
    private final boolean varDebugInfo;
    private final boolean genCrt;

    /**
     * Default limit of (approximate) size of finalizer to inline.
     *  Zero means always use jsr.  100 or greater means never use
     *  jsr.
     */
    private final int jsrlimit;
    private Pool pool = new Pool();

    /**
     * Code buffer, set by genMethod.
     */
    private Code code;

    /**
     * Items structure, set by genMethod.
     */
    private Items items;

    /**
     * Environment for symbol lookup, set by genClass
     */
    private Env attrEnv;

    /**
     * The top level tree.
     */
    private TopLevel toplevel;

    /**
     * The number of code-gen errors in this class.
     */
    private int nerrs = 0;

    /**
     * A hash table mapping syntax trees to their ending source positions.
     */
    private Hashtable endPositions;

    /**
     * Generate code to load an integer constant.
     *  @param n     The integer to be loaded.
     */
    void loadIntConst(int n) {
        items.makeImmediateItem(syms.intType, new Integer(n)).load();
    }

    /**
      * The opcode that loads a zero constant of a given type code.
      *  @param tc   The given type code (@see ByteCode).
      */
    public static int zero(int tc) {
        switch (tc) {
        case INTcode:

        case BYTEcode:

        case SHORTcode:

        case CHARcode:
            return iconst_0;

        case LONGcode:
            return lconst_0;

        case FLOATcode:
            return fconst_0;

        case DOUBLEcode:
            return dconst_0;

        default:
            throw new AssertionError("zero");

        }
    }

    /**
      * The opcode that loads a one constant of a given type code.
      *  @param tc   The given type code (@see ByteCode).
      */
    public static int one(int tc) {
        return zero(tc) + 1;
    }

    /**
      * Generate code to load -1 of the given type code (either int or long).
      *  @param tc   The given type code (@see ByteCode).
      */
    void emitMinusOne(int tc) {
        if (tc == LONGcode) {
            items.makeImmediateItem(syms.longType, new Long(-1)).load();
        } else {
            code.emitop(iconst_m1);
        }
    }

    /**
      * Construct a symbol to reflect the qualifying type that should
      *  appear in the byte code as per JLS 13.1.
      *
      *  For target >= 1.2: Clone a method with the qualifier as owner (except
      *  for those cases where we need to work around VM bugs).
      *
      *  For target <= 1.1: If qualified variable or method is defined in a
      *  non-accessible class, clone it with the qualifier class as owner.
      *
      *  @param sym    The accessed symbol
      *  @param site   The qualifier's type.
      */
    Symbol binaryQualifier(Symbol sym, Type site) {
        if (site.tag == ARRAY) {
            if (sym == syms.lengthVar || sym.owner != syms.arrayClass)
                return sym;
            Symbol qualifier = target.arrayBinaryCompatibility() ?
                    new ClassSymbol(Flags.PUBLIC, site.tsym.name, site,
                    syms.noSymbol) : syms.objectType.tsym;
            return sym.clone(qualifier);
        }
        if (sym.owner == site.tsym ||
                (sym.flags() & (STATIC | SYNTHETIC)) == (STATIC | SYNTHETIC)) {
            return sym;
        }
        if (!target.obeyBinaryCompatibility())
            return rs.isAccessible(attrEnv, (TypeSymbol) sym.owner) ? sym :
                    sym.clone(site.tsym);
        if (!target.interfaceFieldsBinaryCompatibility()) {
            if ((sym.owner.flags() & INTERFACE) != 0 && sym.kind == VAR)
                return sym;
        }
        if (sym.owner == syms.objectType.tsym)
            return sym;
        if (!target.interfaceObjectOverridesBinaryCompatibility()) {
            if ((sym.owner.flags() & INTERFACE) != 0 &&
                    syms.objectType.tsym.members().lookup(sym.name).scope != null)
                return sym;
        }
        return sym.clone(site.tsym);
    }

    /**
      * Insert a reference to given type in the constant pool,
      *  checking for an array with too many dimensions;
      *  return the reference's index.
      *  @param type   The type for which a reference is inserted.
      */
    int makeRef(int pos, Type type) {
        checkDimension(pos, type);
        return pool.put(type.tag == CLASS ? (Object) type.tsym : (Object) type);
    }

    /**
      * Check if the given type is an array with too many dimensions.
      */
    private void checkDimension(int pos, Type t) {
        switch (t.tag) {
        case METHOD:
            checkDimension(pos, t.restype());
            for (List args = t.argtypes(); args.nonEmpty(); args = args.tail)
                checkDimension(pos, (Type) args.head);
            break;

        case ARRAY:
            if (t.dimensions() > ClassFile.MAX_DIMENSIONS) {
                log.error(pos, "limit.dimensions");
                nerrs++;
            }
            break;

        default:
            break;

        }
    }

    /**
      * Create a tempory variable.
      *  @param type   The variable's type.
      */
    LocalItem makeTemp(Type type) {
        return (LocalItem) items.makeLocalItem(type, code.newLocal(type));
    }

    /**
      * Generate code to call a non-private method or constructor.
      *  @param pos         Position to be used for error reporting.
      *  @param site        The type of which the method is a member.
      *  @param name        The method's name.
      *  @param argtypes    The method's argument types.
      *  @param isStatic    A flag that indicates whether we call a
      *                     static or instance method.
      */
    void callMethod(int pos, Type site, Name name, List argtypes, boolean isStatic) {
        Symbol msym = rs.resolveInternalMethod(pos, attrEnv, site, name, argtypes);
        if (isStatic)
            items.makeStaticItem(msym).invoke();
        else
            items.makeMemberItem(msym, name == names.init).invoke();
    }

    /**
      * Is the given method definition an access method
      *  resulting from a qualified super? This is signified by an odd
      *  access code.
      */
    private boolean isAccessSuper(MethodDef enclMethod) {
        return (enclMethod.flags & SYNTHETIC) != 0 &&
                isOddAccessName(enclMethod.name);
    }

    /**
      * Does given name start with "access$" and end in an odd digit?
      */
    private boolean isOddAccessName(Name name) {
        return name.startsWith(names.accessDollar) &&
                (name.byteAt(name.len - 1) & 1) == 1;
    }

    /**
      * Generate code to invoke the finalizer associated with given
      *  environment.
      *  Any calls to finalizers are appended to the environments `cont' chain.
      *  Mark beginning of gap in catch all range for finalizer.
      */
    void genFinalizer(Env env) {
        if (code.isAlive() && ((Gen.GenContext) env.info).finalize != null)
            ((Gen.GenContext) env.info).finalize.gen();
    }

    /**
      * Generate code to call all finalizers of structures aborted by
      *  a non-local
      *  exit.  Return target environment of the non-local exit.
      *  @param target      The tree representing the structure that's aborted
      *  @param env         The environment current at the non-local exit.
      */
    Env unwind(Tree target, Env env) {
        Env env1 = env;
        while (true) {
            genFinalizer(env1);
            if (env1.tree == target)
                break;
            env1 = env1.next;
        }
        return env1;
    }

    /**
      * Mark end of gap in catch-all range for finalizer.
      *  @param env   the environment which might contain the finalizer
      *               (if it does, env.info.gaps != null).
      */
    void endFinalizerGap(Env env) {
        if (((Gen.GenContext) env.info).gaps != null &&
                ((Gen.GenContext) env.info).gaps.length() % 2 == 1)
            ((Gen.GenContext) env.info).gaps.append(new Integer(code.curPc()));
    }

    /**
      * Mark end of all gaps in catch-all ranges for finalizers of environments
      *  lying between, and including to two environments.
      *  @param from    the most deeply nested environment to mark

⌨️ 快捷键说明

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