?? gen.java
字號:
/** * @(#)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 * @param to the least deeply nested environment to mark */ void endFinalizerGaps(Env from, Env to) { Env last = null; while (last != to) { endFinalizerGap(from); last = from; from = from.next; } }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -