src/share/classes/com/sun/tools/javac/jvm/Gen.java

changeset 0
959103a6100f
child 2525
2eb010b6cb22
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Wed Apr 27 01:34:52 2016 +0800
     1.3 @@ -0,0 +1,2917 @@
     1.4 +/*
     1.5 + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +
    1.29 +package com.sun.tools.javac.jvm;
    1.30 +
    1.31 +import java.util.*;
    1.32 +
    1.33 +import com.sun.tools.javac.util.*;
    1.34 +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    1.35 +import com.sun.tools.javac.util.List;
    1.36 +import com.sun.tools.javac.code.*;
    1.37 +import com.sun.tools.javac.code.Attribute.TypeCompound;
    1.38 +import com.sun.tools.javac.code.Symbol.VarSymbol;
    1.39 +import com.sun.tools.javac.comp.*;
    1.40 +import com.sun.tools.javac.tree.*;
    1.41 +
    1.42 +import com.sun.tools.javac.code.Symbol.*;
    1.43 +import com.sun.tools.javac.code.Type.*;
    1.44 +import com.sun.tools.javac.jvm.Code.*;
    1.45 +import com.sun.tools.javac.jvm.Items.*;
    1.46 +import com.sun.tools.javac.tree.EndPosTable;
    1.47 +import com.sun.tools.javac.tree.JCTree.*;
    1.48 +
    1.49 +import static com.sun.tools.javac.code.Flags.*;
    1.50 +import static com.sun.tools.javac.code.Kinds.*;
    1.51 +import static com.sun.tools.javac.code.TypeTag.*;
    1.52 +import static com.sun.tools.javac.jvm.ByteCodes.*;
    1.53 +import static com.sun.tools.javac.jvm.CRTFlags.*;
    1.54 +import static com.sun.tools.javac.main.Option.*;
    1.55 +import static com.sun.tools.javac.tree.JCTree.Tag.*;
    1.56 +
    1.57 +/** This pass maps flat Java (i.e. without inner classes) to bytecodes.
    1.58 + *
    1.59 + *  <p><b>This is NOT part of any supported API.
    1.60 + *  If you write code that depends on this, you do so at your own risk.
    1.61 + *  This code and its internal interfaces are subject to change or
    1.62 + *  deletion without notice.</b>
    1.63 + */
    1.64 +public class Gen extends JCTree.Visitor {
    1.65 +    protected static final Context.Key<Gen> genKey =
    1.66 +        new Context.Key<Gen>();
    1.67 +
    1.68 +    private final Log log;
    1.69 +    private final Symtab syms;
    1.70 +    private final Check chk;
    1.71 +    private final Resolve rs;
    1.72 +    private final TreeMaker make;
    1.73 +    private final Names names;
    1.74 +    private final Target target;
    1.75 +    private final Type stringBufferType;
    1.76 +    private final Map<Type,Symbol> stringBufferAppend;
    1.77 +    private Name accessDollar;
    1.78 +    private final Types types;
    1.79 +    private final Lower lower;
    1.80 +
    1.81 +    /** Switch: GJ mode?
    1.82 +     */
    1.83 +    private final boolean allowGenerics;
    1.84 +
    1.85 +    /** Set when Miranda method stubs are to be generated. */
    1.86 +    private final boolean generateIproxies;
    1.87 +
    1.88 +    /** Format of stackmap tables to be generated. */
    1.89 +    private final Code.StackMapFormat stackMap;
    1.90 +
    1.91 +    /** A type that serves as the expected type for all method expressions.
    1.92 +     */
    1.93 +    private final Type methodType;
    1.94 +
    1.95 +    public static Gen instance(Context context) {
    1.96 +        Gen instance = context.get(genKey);
    1.97 +        if (instance == null)
    1.98 +            instance = new Gen(context);
    1.99 +        return instance;
   1.100 +    }
   1.101 +
   1.102 +    /** Constant pool, reset by genClass.
   1.103 +     */
   1.104 +    private Pool pool;
   1.105 +
   1.106 +    /** LVTRanges info.
   1.107 +     */
   1.108 +    private LVTRanges lvtRanges;
   1.109 +
   1.110 +    private final boolean typeAnnoAsserts;
   1.111 +
   1.112 +    protected Gen(Context context) {
   1.113 +        context.put(genKey, this);
   1.114 +
   1.115 +        names = Names.instance(context);
   1.116 +        log = Log.instance(context);
   1.117 +        syms = Symtab.instance(context);
   1.118 +        chk = Check.instance(context);
   1.119 +        rs = Resolve.instance(context);
   1.120 +        make = TreeMaker.instance(context);
   1.121 +        target = Target.instance(context);
   1.122 +        types = Types.instance(context);
   1.123 +        methodType = new MethodType(null, null, null, syms.methodClass);
   1.124 +        allowGenerics = Source.instance(context).allowGenerics();
   1.125 +        stringBufferType = target.useStringBuilder()
   1.126 +            ? syms.stringBuilderType
   1.127 +            : syms.stringBufferType;
   1.128 +        stringBufferAppend = new HashMap<Type,Symbol>();
   1.129 +        accessDollar = names.
   1.130 +            fromString("access" + target.syntheticNameChar());
   1.131 +        lower = Lower.instance(context);
   1.132 +
   1.133 +        Options options = Options.instance(context);
   1.134 +        lineDebugInfo =
   1.135 +            options.isUnset(G_CUSTOM) ||
   1.136 +            options.isSet(G_CUSTOM, "lines");
   1.137 +        varDebugInfo =
   1.138 +            options.isUnset(G_CUSTOM)
   1.139 +            ? options.isSet(G)
   1.140 +            : options.isSet(G_CUSTOM, "vars");
   1.141 +        if (varDebugInfo) {
   1.142 +            lvtRanges = LVTRanges.instance(context);
   1.143 +        }
   1.144 +        genCrt = options.isSet(XJCOV);
   1.145 +        debugCode = options.isSet("debugcode");
   1.146 +        allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
   1.147 +        pool = new Pool(types);
   1.148 +        typeAnnoAsserts = options.isSet("TypeAnnotationAsserts");
   1.149 +
   1.150 +        generateIproxies =
   1.151 +            target.requiresIproxy() ||
   1.152 +            options.isSet("miranda");
   1.153 +
   1.154 +        if (target.generateStackMapTable()) {
   1.155 +            // ignore cldc because we cannot have both stackmap formats
   1.156 +            this.stackMap = StackMapFormat.JSR202;
   1.157 +        } else {
   1.158 +            if (target.generateCLDCStackmap()) {
   1.159 +                this.stackMap = StackMapFormat.CLDC;
   1.160 +            } else {
   1.161 +                this.stackMap = StackMapFormat.NONE;
   1.162 +            }
   1.163 +        }
   1.164 +
   1.165 +        // by default, avoid jsr's for simple finalizers
   1.166 +        int setjsrlimit = 50;
   1.167 +        String jsrlimitString = options.get("jsrlimit");
   1.168 +        if (jsrlimitString != null) {
   1.169 +            try {
   1.170 +                setjsrlimit = Integer.parseInt(jsrlimitString);
   1.171 +            } catch (NumberFormatException ex) {
   1.172 +                // ignore ill-formed numbers for jsrlimit
   1.173 +            }
   1.174 +        }
   1.175 +        this.jsrlimit = setjsrlimit;
   1.176 +        this.useJsrLocally = false; // reset in visitTry
   1.177 +    }
   1.178 +
   1.179 +    /** Switches
   1.180 +     */
   1.181 +    private final boolean lineDebugInfo;
   1.182 +    private final boolean varDebugInfo;
   1.183 +    private final boolean genCrt;
   1.184 +    private final boolean debugCode;
   1.185 +    private final boolean allowInvokedynamic;
   1.186 +
   1.187 +    /** Default limit of (approximate) size of finalizer to inline.
   1.188 +     *  Zero means always use jsr.  100 or greater means never use
   1.189 +     *  jsr.
   1.190 +     */
   1.191 +    private final int jsrlimit;
   1.192 +
   1.193 +    /** True if jsr is used.
   1.194 +     */
   1.195 +    private boolean useJsrLocally;
   1.196 +
   1.197 +    /** Code buffer, set by genMethod.
   1.198 +     */
   1.199 +    private Code code;
   1.200 +
   1.201 +    /** Items structure, set by genMethod.
   1.202 +     */
   1.203 +    private Items items;
   1.204 +
   1.205 +    /** Environment for symbol lookup, set by genClass
   1.206 +     */
   1.207 +    private Env<AttrContext> attrEnv;
   1.208 +
   1.209 +    /** The top level tree.
   1.210 +     */
   1.211 +    private JCCompilationUnit toplevel;
   1.212 +
   1.213 +    /** The number of code-gen errors in this class.
   1.214 +     */
   1.215 +    private int nerrs = 0;
   1.216 +
   1.217 +    /** An object containing mappings of syntax trees to their
   1.218 +     *  ending source positions.
   1.219 +     */
   1.220 +    EndPosTable endPosTable;
   1.221 +
   1.222 +    /** Generate code to load an integer constant.
   1.223 +     *  @param n     The integer to be loaded.
   1.224 +     */
   1.225 +    void loadIntConst(int n) {
   1.226 +        items.makeImmediateItem(syms.intType, n).load();
   1.227 +    }
   1.228 +
   1.229 +    /** The opcode that loads a zero constant of a given type code.
   1.230 +     *  @param tc   The given type code (@see ByteCode).
   1.231 +     */
   1.232 +    public static int zero(int tc) {
   1.233 +        switch(tc) {
   1.234 +        case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
   1.235 +            return iconst_0;
   1.236 +        case LONGcode:
   1.237 +            return lconst_0;
   1.238 +        case FLOATcode:
   1.239 +            return fconst_0;
   1.240 +        case DOUBLEcode:
   1.241 +            return dconst_0;
   1.242 +        default:
   1.243 +            throw new AssertionError("zero");
   1.244 +        }
   1.245 +    }
   1.246 +
   1.247 +    /** The opcode that loads a one constant of a given type code.
   1.248 +     *  @param tc   The given type code (@see ByteCode).
   1.249 +     */
   1.250 +    public static int one(int tc) {
   1.251 +        return zero(tc) + 1;
   1.252 +    }
   1.253 +
   1.254 +    /** Generate code to load -1 of the given type code (either int or long).
   1.255 +     *  @param tc   The given type code (@see ByteCode).
   1.256 +     */
   1.257 +    void emitMinusOne(int tc) {
   1.258 +        if (tc == LONGcode) {
   1.259 +            items.makeImmediateItem(syms.longType, new Long(-1)).load();
   1.260 +        } else {
   1.261 +            code.emitop0(iconst_m1);
   1.262 +        }
   1.263 +    }
   1.264 +
   1.265 +    /** Construct a symbol to reflect the qualifying type that should
   1.266 +     *  appear in the byte code as per JLS 13.1.
   1.267 +     *
   1.268 +     *  For {@literal target >= 1.2}: Clone a method with the qualifier as owner (except
   1.269 +     *  for those cases where we need to work around VM bugs).
   1.270 +     *
   1.271 +     *  For {@literal target <= 1.1}: If qualified variable or method is defined in a
   1.272 +     *  non-accessible class, clone it with the qualifier class as owner.
   1.273 +     *
   1.274 +     *  @param sym    The accessed symbol
   1.275 +     *  @param site   The qualifier's type.
   1.276 +     */
   1.277 +    Symbol binaryQualifier(Symbol sym, Type site) {
   1.278 +
   1.279 +        if (site.hasTag(ARRAY)) {
   1.280 +            if (sym == syms.lengthVar ||
   1.281 +                sym.owner != syms.arrayClass)
   1.282 +                return sym;
   1.283 +            // array clone can be qualified by the array type in later targets
   1.284 +            Symbol qualifier = target.arrayBinaryCompatibility()
   1.285 +                ? new ClassSymbol(Flags.PUBLIC, site.tsym.name,
   1.286 +                                  site, syms.noSymbol)
   1.287 +                : syms.objectType.tsym;
   1.288 +            return sym.clone(qualifier);
   1.289 +        }
   1.290 +
   1.291 +        if (sym.owner == site.tsym ||
   1.292 +            (sym.flags() & (STATIC | SYNTHETIC)) == (STATIC | SYNTHETIC)) {
   1.293 +            return sym;
   1.294 +        }
   1.295 +        if (!target.obeyBinaryCompatibility())
   1.296 +            return rs.isAccessible(attrEnv, (TypeSymbol)sym.owner)
   1.297 +                ? sym
   1.298 +                : sym.clone(site.tsym);
   1.299 +
   1.300 +        if (!target.interfaceFieldsBinaryCompatibility()) {
   1.301 +            if ((sym.owner.flags() & INTERFACE) != 0 && sym.kind == VAR)
   1.302 +                return sym;
   1.303 +        }
   1.304 +
   1.305 +        // leave alone methods inherited from Object
   1.306 +        // JLS 13.1.
   1.307 +        if (sym.owner == syms.objectType.tsym)
   1.308 +            return sym;
   1.309 +
   1.310 +        if (!target.interfaceObjectOverridesBinaryCompatibility()) {
   1.311 +            if ((sym.owner.flags() & INTERFACE) != 0 &&
   1.312 +                syms.objectType.tsym.members().lookup(sym.name).scope != null)
   1.313 +                return sym;
   1.314 +        }
   1.315 +
   1.316 +        return sym.clone(site.tsym);
   1.317 +    }
   1.318 +
   1.319 +    /** Insert a reference to given type in the constant pool,
   1.320 +     *  checking for an array with too many dimensions;
   1.321 +     *  return the reference's index.
   1.322 +     *  @param type   The type for which a reference is inserted.
   1.323 +     */
   1.324 +    int makeRef(DiagnosticPosition pos, Type type) {
   1.325 +        checkDimension(pos, type);
   1.326 +        if (type.isAnnotated()) {
   1.327 +            // Treat annotated types separately - we don't want
   1.328 +            // to collapse all of them - at least for annotated
   1.329 +            // exceptions.
   1.330 +            // TODO: review this.
   1.331 +            return pool.put((Object)type);
   1.332 +        } else {
   1.333 +            return pool.put(type.hasTag(CLASS) ? (Object)type.tsym : (Object)type);
   1.334 +        }
   1.335 +    }
   1.336 +
   1.337 +    /** Check if the given type is an array with too many dimensions.
   1.338 +     */
   1.339 +    private void checkDimension(DiagnosticPosition pos, Type t) {
   1.340 +        switch (t.getTag()) {
   1.341 +        case METHOD:
   1.342 +            checkDimension(pos, t.getReturnType());
   1.343 +            for (List<Type> args = t.getParameterTypes(); args.nonEmpty(); args = args.tail)
   1.344 +                checkDimension(pos, args.head);
   1.345 +            break;
   1.346 +        case ARRAY:
   1.347 +            if (types.dimensions(t) > ClassFile.MAX_DIMENSIONS) {
   1.348 +                log.error(pos, "limit.dimensions");
   1.349 +                nerrs++;
   1.350 +            }
   1.351 +            break;
   1.352 +        default:
   1.353 +            break;
   1.354 +        }
   1.355 +    }
   1.356 +
   1.357 +    /** Create a tempory variable.
   1.358 +     *  @param type   The variable's type.
   1.359 +     */
   1.360 +    LocalItem makeTemp(Type type) {
   1.361 +        VarSymbol v = new VarSymbol(Flags.SYNTHETIC,
   1.362 +                                    names.empty,
   1.363 +                                    type,
   1.364 +                                    env.enclMethod.sym);
   1.365 +        code.newLocal(v);
   1.366 +        return items.makeLocalItem(v);
   1.367 +    }
   1.368 +
   1.369 +    /** Generate code to call a non-private method or constructor.
   1.370 +     *  @param pos         Position to be used for error reporting.
   1.371 +     *  @param site        The type of which the method is a member.
   1.372 +     *  @param name        The method's name.
   1.373 +     *  @param argtypes    The method's argument types.
   1.374 +     *  @param isStatic    A flag that indicates whether we call a
   1.375 +     *                     static or instance method.
   1.376 +     */
   1.377 +    void callMethod(DiagnosticPosition pos,
   1.378 +                    Type site, Name name, List<Type> argtypes,
   1.379 +                    boolean isStatic) {
   1.380 +        Symbol msym = rs.
   1.381 +            resolveInternalMethod(pos, attrEnv, site, name, argtypes, null);
   1.382 +        if (isStatic) items.makeStaticItem(msym).invoke();
   1.383 +        else items.makeMemberItem(msym, name == names.init).invoke();
   1.384 +    }
   1.385 +
   1.386 +    /** Is the given method definition an access method
   1.387 +     *  resulting from a qualified super? This is signified by an odd
   1.388 +     *  access code.
   1.389 +     */
   1.390 +    private boolean isAccessSuper(JCMethodDecl enclMethod) {
   1.391 +        return
   1.392 +            (enclMethod.mods.flags & SYNTHETIC) != 0 &&
   1.393 +            isOddAccessName(enclMethod.name);
   1.394 +    }
   1.395 +
   1.396 +    /** Does given name start with "access$" and end in an odd digit?
   1.397 +     */
   1.398 +    private boolean isOddAccessName(Name name) {
   1.399 +        return
   1.400 +            name.startsWith(accessDollar) &&
   1.401 +            (name.getByteAt(name.getByteLength() - 1) & 1) == 1;
   1.402 +    }
   1.403 +
   1.404 +/* ************************************************************************
   1.405 + * Non-local exits
   1.406 + *************************************************************************/
   1.407 +
   1.408 +    /** Generate code to invoke the finalizer associated with given
   1.409 +     *  environment.
   1.410 +     *  Any calls to finalizers are appended to the environments `cont' chain.
   1.411 +     *  Mark beginning of gap in catch all range for finalizer.
   1.412 +     */
   1.413 +    void genFinalizer(Env<GenContext> env) {
   1.414 +        if (code.isAlive() && env.info.finalize != null)
   1.415 +            env.info.finalize.gen();
   1.416 +    }
   1.417 +
   1.418 +    /** Generate code to call all finalizers of structures aborted by
   1.419 +     *  a non-local
   1.420 +     *  exit.  Return target environment of the non-local exit.
   1.421 +     *  @param target      The tree representing the structure that's aborted
   1.422 +     *  @param env         The environment current at the non-local exit.
   1.423 +     */
   1.424 +    Env<GenContext> unwind(JCTree target, Env<GenContext> env) {
   1.425 +        Env<GenContext> env1 = env;
   1.426 +        while (true) {
   1.427 +            genFinalizer(env1);
   1.428 +            if (env1.tree == target) break;
   1.429 +            env1 = env1.next;
   1.430 +        }
   1.431 +        return env1;
   1.432 +    }
   1.433 +
   1.434 +    /** Mark end of gap in catch-all range for finalizer.
   1.435 +     *  @param env   the environment which might contain the finalizer
   1.436 +     *               (if it does, env.info.gaps != null).
   1.437 +     */
   1.438 +    void endFinalizerGap(Env<GenContext> env) {
   1.439 +        if (env.info.gaps != null && env.info.gaps.length() % 2 == 1)
   1.440 +            env.info.gaps.append(code.curCP());
   1.441 +    }
   1.442 +
   1.443 +    /** Mark end of all gaps in catch-all ranges for finalizers of environments
   1.444 +     *  lying between, and including to two environments.
   1.445 +     *  @param from    the most deeply nested environment to mark
   1.446 +     *  @param to      the least deeply nested environment to mark
   1.447 +     */
   1.448 +    void endFinalizerGaps(Env<GenContext> from, Env<GenContext> to) {
   1.449 +        Env<GenContext> last = null;
   1.450 +        while (last != to) {
   1.451 +            endFinalizerGap(from);
   1.452 +            last = from;
   1.453 +            from = from.next;
   1.454 +        }
   1.455 +    }
   1.456 +
   1.457 +    /** Do any of the structures aborted by a non-local exit have
   1.458 +     *  finalizers that require an empty stack?
   1.459 +     *  @param target      The tree representing the structure that's aborted
   1.460 +     *  @param env         The environment current at the non-local exit.
   1.461 +     */
   1.462 +    boolean hasFinally(JCTree target, Env<GenContext> env) {
   1.463 +        while (env.tree != target) {
   1.464 +            if (env.tree.hasTag(TRY) && env.info.finalize.hasFinalizer())
   1.465 +                return true;
   1.466 +            env = env.next;
   1.467 +        }
   1.468 +        return false;
   1.469 +    }
   1.470 +
   1.471 +/* ************************************************************************
   1.472 + * Normalizing class-members.
   1.473 + *************************************************************************/
   1.474 +
   1.475 +    /** Distribute member initializer code into constructors and {@code <clinit>}
   1.476 +     *  method.
   1.477 +     *  @param defs         The list of class member declarations.
   1.478 +     *  @param c            The enclosing class.
   1.479 +     */
   1.480 +    List<JCTree> normalizeDefs(List<JCTree> defs, ClassSymbol c) {
   1.481 +        ListBuffer<JCStatement> initCode = new ListBuffer<JCStatement>();
   1.482 +        ListBuffer<Attribute.TypeCompound> initTAs = new ListBuffer<Attribute.TypeCompound>();
   1.483 +        ListBuffer<JCStatement> clinitCode = new ListBuffer<JCStatement>();
   1.484 +        ListBuffer<Attribute.TypeCompound> clinitTAs = new ListBuffer<Attribute.TypeCompound>();
   1.485 +        ListBuffer<JCTree> methodDefs = new ListBuffer<JCTree>();
   1.486 +        // Sort definitions into three listbuffers:
   1.487 +        //  - initCode for instance initializers
   1.488 +        //  - clinitCode for class initializers
   1.489 +        //  - methodDefs for method definitions
   1.490 +        for (List<JCTree> l = defs; l.nonEmpty(); l = l.tail) {
   1.491 +            JCTree def = l.head;
   1.492 +            switch (def.getTag()) {
   1.493 +            case BLOCK:
   1.494 +                JCBlock block = (JCBlock)def;
   1.495 +                if ((block.flags & STATIC) != 0)
   1.496 +                    clinitCode.append(block);
   1.497 +                else
   1.498 +                    initCode.append(block);
   1.499 +                break;
   1.500 +            case METHODDEF:
   1.501 +                methodDefs.append(def);
   1.502 +                break;
   1.503 +            case VARDEF:
   1.504 +                JCVariableDecl vdef = (JCVariableDecl) def;
   1.505 +                VarSymbol sym = vdef.sym;
   1.506 +                checkDimension(vdef.pos(), sym.type);
   1.507 +                if (vdef.init != null) {
   1.508 +                    if ((sym.flags() & STATIC) == 0) {
   1.509 +                        // Always initialize instance variables.
   1.510 +                        JCStatement init = make.at(vdef.pos()).
   1.511 +                            Assignment(sym, vdef.init);
   1.512 +                        initCode.append(init);
   1.513 +                        endPosTable.replaceTree(vdef, init);
   1.514 +                        initTAs.addAll(getAndRemoveNonFieldTAs(sym));
   1.515 +                    } else if (sym.getConstValue() == null) {
   1.516 +                        // Initialize class (static) variables only if
   1.517 +                        // they are not compile-time constants.
   1.518 +                        JCStatement init = make.at(vdef.pos).
   1.519 +                            Assignment(sym, vdef.init);
   1.520 +                        clinitCode.append(init);
   1.521 +                        endPosTable.replaceTree(vdef, init);
   1.522 +                        clinitTAs.addAll(getAndRemoveNonFieldTAs(sym));
   1.523 +                    } else {
   1.524 +                        checkStringConstant(vdef.init.pos(), sym.getConstValue());
   1.525 +                    }
   1.526 +                }
   1.527 +                break;
   1.528 +            default:
   1.529 +                Assert.error();
   1.530 +            }
   1.531 +        }
   1.532 +        // Insert any instance initializers into all constructors.
   1.533 +        if (initCode.length() != 0) {
   1.534 +            List<JCStatement> inits = initCode.toList();
   1.535 +            initTAs.addAll(c.getInitTypeAttributes());
   1.536 +            List<Attribute.TypeCompound> initTAlist = initTAs.toList();
   1.537 +            for (JCTree t : methodDefs) {
   1.538 +                normalizeMethod((JCMethodDecl)t, inits, initTAlist);
   1.539 +            }
   1.540 +        }
   1.541 +        // If there are class initializers, create a <clinit> method
   1.542 +        // that contains them as its body.
   1.543 +        if (clinitCode.length() != 0) {
   1.544 +            MethodSymbol clinit = new MethodSymbol(
   1.545 +                STATIC | (c.flags() & STRICTFP),
   1.546 +                names.clinit,
   1.547 +                new MethodType(
   1.548 +                    List.<Type>nil(), syms.voidType,
   1.549 +                    List.<Type>nil(), syms.methodClass),
   1.550 +                c);
   1.551 +            c.members().enter(clinit);
   1.552 +            List<JCStatement> clinitStats = clinitCode.toList();
   1.553 +            JCBlock block = make.at(clinitStats.head.pos()).Block(0, clinitStats);
   1.554 +            block.endpos = TreeInfo.endPos(clinitStats.last());
   1.555 +            methodDefs.append(make.MethodDef(clinit, block));
   1.556 +
   1.557 +            if (!clinitTAs.isEmpty())
   1.558 +                clinit.appendUniqueTypeAttributes(clinitTAs.toList());
   1.559 +            if (!c.getClassInitTypeAttributes().isEmpty())
   1.560 +                clinit.appendUniqueTypeAttributes(c.getClassInitTypeAttributes());
   1.561 +        }
   1.562 +        // Return all method definitions.
   1.563 +        return methodDefs.toList();
   1.564 +    }
   1.565 +
   1.566 +    private List<Attribute.TypeCompound> getAndRemoveNonFieldTAs(VarSymbol sym) {
   1.567 +        List<TypeCompound> tas = sym.getRawTypeAttributes();
   1.568 +        ListBuffer<Attribute.TypeCompound> fieldTAs = new ListBuffer<Attribute.TypeCompound>();
   1.569 +        ListBuffer<Attribute.TypeCompound> nonfieldTAs = new ListBuffer<Attribute.TypeCompound>();
   1.570 +        for (TypeCompound ta : tas) {
   1.571 +            if (ta.getPosition().type == TargetType.FIELD) {
   1.572 +                fieldTAs.add(ta);
   1.573 +            } else {
   1.574 +                if (typeAnnoAsserts) {
   1.575 +                    Assert.error("Type annotation does not have a valid positior");
   1.576 +                }
   1.577 +
   1.578 +                nonfieldTAs.add(ta);
   1.579 +            }
   1.580 +        }
   1.581 +        sym.setTypeAttributes(fieldTAs.toList());
   1.582 +        return nonfieldTAs.toList();
   1.583 +    }
   1.584 +
   1.585 +    /** Check a constant value and report if it is a string that is
   1.586 +     *  too large.
   1.587 +     */
   1.588 +    private void checkStringConstant(DiagnosticPosition pos, Object constValue) {
   1.589 +        if (nerrs != 0 || // only complain about a long string once
   1.590 +            constValue == null ||
   1.591 +            !(constValue instanceof String) ||
   1.592 +            ((String)constValue).length() < Pool.MAX_STRING_LENGTH)
   1.593 +            return;
   1.594 +        log.error(pos, "limit.string");
   1.595 +        nerrs++;
   1.596 +    }
   1.597 +
   1.598 +    /** Insert instance initializer code into initial constructor.
   1.599 +     *  @param md        The tree potentially representing a
   1.600 +     *                   constructor's definition.
   1.601 +     *  @param initCode  The list of instance initializer statements.
   1.602 +     *  @param initTAs  Type annotations from the initializer expression.
   1.603 +     */
   1.604 +    void normalizeMethod(JCMethodDecl md, List<JCStatement> initCode, List<TypeCompound> initTAs) {
   1.605 +        if (md.name == names.init && TreeInfo.isInitialConstructor(md)) {
   1.606 +            // We are seeing a constructor that does not call another
   1.607 +            // constructor of the same class.
   1.608 +            List<JCStatement> stats = md.body.stats;
   1.609 +            ListBuffer<JCStatement> newstats = new ListBuffer<JCStatement>();
   1.610 +
   1.611 +            if (stats.nonEmpty()) {
   1.612 +                // Copy initializers of synthetic variables generated in
   1.613 +                // the translation of inner classes.
   1.614 +                while (TreeInfo.isSyntheticInit(stats.head)) {
   1.615 +                    newstats.append(stats.head);
   1.616 +                    stats = stats.tail;
   1.617 +                }
   1.618 +                // Copy superclass constructor call
   1.619 +                newstats.append(stats.head);
   1.620 +                stats = stats.tail;
   1.621 +                // Copy remaining synthetic initializers.
   1.622 +                while (stats.nonEmpty() &&
   1.623 +                       TreeInfo.isSyntheticInit(stats.head)) {
   1.624 +                    newstats.append(stats.head);
   1.625 +                    stats = stats.tail;
   1.626 +                }
   1.627 +                // Now insert the initializer code.
   1.628 +                newstats.appendList(initCode);
   1.629 +                // And copy all remaining statements.
   1.630 +                while (stats.nonEmpty()) {
   1.631 +                    newstats.append(stats.head);
   1.632 +                    stats = stats.tail;
   1.633 +                }
   1.634 +            }
   1.635 +            md.body.stats = newstats.toList();
   1.636 +            if (md.body.endpos == Position.NOPOS)
   1.637 +                md.body.endpos = TreeInfo.endPos(md.body.stats.last());
   1.638 +
   1.639 +            md.sym.appendUniqueTypeAttributes(initTAs);
   1.640 +        }
   1.641 +    }
   1.642 +
   1.643 +/* ********************************************************************
   1.644 + * Adding miranda methods
   1.645 + *********************************************************************/
   1.646 +
   1.647 +    /** Add abstract methods for all methods defined in one of
   1.648 +     *  the interfaces of a given class,
   1.649 +     *  provided they are not already implemented in the class.
   1.650 +     *
   1.651 +     *  @param c      The class whose interfaces are searched for methods
   1.652 +     *                for which Miranda methods should be added.
   1.653 +     */
   1.654 +    void implementInterfaceMethods(ClassSymbol c) {
   1.655 +        implementInterfaceMethods(c, c);
   1.656 +    }
   1.657 +
   1.658 +    /** Add abstract methods for all methods defined in one of
   1.659 +     *  the interfaces of a given class,
   1.660 +     *  provided they are not already implemented in the class.
   1.661 +     *
   1.662 +     *  @param c      The class whose interfaces are searched for methods
   1.663 +     *                for which Miranda methods should be added.
   1.664 +     *  @param site   The class in which a definition may be needed.
   1.665 +     */
   1.666 +    void implementInterfaceMethods(ClassSymbol c, ClassSymbol site) {
   1.667 +        for (List<Type> l = types.interfaces(c.type); l.nonEmpty(); l = l.tail) {
   1.668 +            ClassSymbol i = (ClassSymbol)l.head.tsym;
   1.669 +            for (Scope.Entry e = i.members().elems;
   1.670 +                 e != null;
   1.671 +                 e = e.sibling)
   1.672 +            {
   1.673 +                if (e.sym.kind == MTH && (e.sym.flags() & STATIC) == 0)
   1.674 +                {
   1.675 +                    MethodSymbol absMeth = (MethodSymbol)e.sym;
   1.676 +                    MethodSymbol implMeth = absMeth.binaryImplementation(site, types);
   1.677 +                    if (implMeth == null)
   1.678 +                        addAbstractMethod(site, absMeth);
   1.679 +                    else if ((implMeth.flags() & IPROXY) != 0)
   1.680 +                        adjustAbstractMethod(site, implMeth, absMeth);
   1.681 +                }
   1.682 +            }
   1.683 +            implementInterfaceMethods(i, site);
   1.684 +        }
   1.685 +    }
   1.686 +
   1.687 +    /** Add an abstract methods to a class
   1.688 +     *  which implicitly implements a method defined in some interface
   1.689 +     *  implemented by the class. These methods are called "Miranda methods".
   1.690 +     *  Enter the newly created method into its enclosing class scope.
   1.691 +     *  Note that it is not entered into the class tree, as the emitter
   1.692 +     *  doesn't need to see it there to emit an abstract method.
   1.693 +     *
   1.694 +     *  @param c      The class to which the Miranda method is added.
   1.695 +     *  @param m      The interface method symbol for which a Miranda method
   1.696 +     *                is added.
   1.697 +     */
   1.698 +    private void addAbstractMethod(ClassSymbol c,
   1.699 +                                   MethodSymbol m) {
   1.700 +        MethodSymbol absMeth = new MethodSymbol(
   1.701 +            m.flags() | IPROXY | SYNTHETIC, m.name,
   1.702 +            m.type, // was c.type.memberType(m), but now only !generics supported
   1.703 +            c);
   1.704 +        c.members().enter(absMeth); // add to symbol table
   1.705 +    }
   1.706 +
   1.707 +    private void adjustAbstractMethod(ClassSymbol c,
   1.708 +                                      MethodSymbol pm,
   1.709 +                                      MethodSymbol im) {
   1.710 +        MethodType pmt = (MethodType)pm.type;
   1.711 +        Type imt = types.memberType(c.type, im);
   1.712 +        pmt.thrown = chk.intersect(pmt.getThrownTypes(), imt.getThrownTypes());
   1.713 +    }
   1.714 +
   1.715 +/* ************************************************************************
   1.716 + * Traversal methods
   1.717 + *************************************************************************/
   1.718 +
   1.719 +    /** Visitor argument: The current environment.
   1.720 +     */
   1.721 +    Env<GenContext> env;
   1.722 +
   1.723 +    /** Visitor argument: The expected type (prototype).
   1.724 +     */
   1.725 +    Type pt;
   1.726 +
   1.727 +    /** Visitor result: The item representing the computed value.
   1.728 +     */
   1.729 +    Item result;
   1.730 +
   1.731 +    /** Visitor method: generate code for a definition, catching and reporting
   1.732 +     *  any completion failures.
   1.733 +     *  @param tree    The definition to be visited.
   1.734 +     *  @param env     The environment current at the definition.
   1.735 +     */
   1.736 +    public void genDef(JCTree tree, Env<GenContext> env) {
   1.737 +        Env<GenContext> prevEnv = this.env;
   1.738 +        try {
   1.739 +            this.env = env;
   1.740 +            tree.accept(this);
   1.741 +        } catch (CompletionFailure ex) {
   1.742 +            chk.completionError(tree.pos(), ex);
   1.743 +        } finally {
   1.744 +            this.env = prevEnv;
   1.745 +        }
   1.746 +    }
   1.747 +
   1.748 +    /** Derived visitor method: check whether CharacterRangeTable
   1.749 +     *  should be emitted, if so, put a new entry into CRTable
   1.750 +     *  and call method to generate bytecode.
   1.751 +     *  If not, just call method to generate bytecode.
   1.752 +     *  @see    #genStat(JCTree, Env)
   1.753 +     *
   1.754 +     *  @param  tree     The tree to be visited.
   1.755 +     *  @param  env      The environment to use.
   1.756 +     *  @param  crtFlags The CharacterRangeTable flags
   1.757 +     *                   indicating type of the entry.
   1.758 +     */
   1.759 +    public void genStat(JCTree tree, Env<GenContext> env, int crtFlags) {
   1.760 +        if (!genCrt) {
   1.761 +            genStat(tree, env);
   1.762 +            return;
   1.763 +        }
   1.764 +        int startpc = code.curCP();
   1.765 +        genStat(tree, env);
   1.766 +        if (tree.hasTag(Tag.BLOCK)) crtFlags |= CRT_BLOCK;
   1.767 +        code.crt.put(tree, crtFlags, startpc, code.curCP());
   1.768 +    }
   1.769 +
   1.770 +    /** Derived visitor method: generate code for a statement.
   1.771 +     */
   1.772 +    public void genStat(JCTree tree, Env<GenContext> env) {
   1.773 +        if (code.isAlive()) {
   1.774 +            code.statBegin(tree.pos);
   1.775 +            genDef(tree, env);
   1.776 +        } else if (env.info.isSwitch && tree.hasTag(VARDEF)) {
   1.777 +            // variables whose declarations are in a switch
   1.778 +            // can be used even if the decl is unreachable.
   1.779 +            code.newLocal(((JCVariableDecl) tree).sym);
   1.780 +        }
   1.781 +    }
   1.782 +
   1.783 +    /** Derived visitor method: check whether CharacterRangeTable
   1.784 +     *  should be emitted, if so, put a new entry into CRTable
   1.785 +     *  and call method to generate bytecode.
   1.786 +     *  If not, just call method to generate bytecode.
   1.787 +     *  @see    #genStats(List, Env)
   1.788 +     *
   1.789 +     *  @param  trees    The list of trees to be visited.
   1.790 +     *  @param  env      The environment to use.
   1.791 +     *  @param  crtFlags The CharacterRangeTable flags
   1.792 +     *                   indicating type of the entry.
   1.793 +     */
   1.794 +    public void genStats(List<JCStatement> trees, Env<GenContext> env, int crtFlags) {
   1.795 +        if (!genCrt) {
   1.796 +            genStats(trees, env);
   1.797 +            return;
   1.798 +        }
   1.799 +        if (trees.length() == 1) {        // mark one statement with the flags
   1.800 +            genStat(trees.head, env, crtFlags | CRT_STATEMENT);
   1.801 +        } else {
   1.802 +            int startpc = code.curCP();
   1.803 +            genStats(trees, env);
   1.804 +            code.crt.put(trees, crtFlags, startpc, code.curCP());
   1.805 +        }
   1.806 +    }
   1.807 +
   1.808 +    /** Derived visitor method: generate code for a list of statements.
   1.809 +     */
   1.810 +    public void genStats(List<? extends JCTree> trees, Env<GenContext> env) {
   1.811 +        for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
   1.812 +            genStat(l.head, env, CRT_STATEMENT);
   1.813 +    }
   1.814 +
   1.815 +    /** Derived visitor method: check whether CharacterRangeTable
   1.816 +     *  should be emitted, if so, put a new entry into CRTable
   1.817 +     *  and call method to generate bytecode.
   1.818 +     *  If not, just call method to generate bytecode.
   1.819 +     *  @see    #genCond(JCTree,boolean)
   1.820 +     *
   1.821 +     *  @param  tree     The tree to be visited.
   1.822 +     *  @param  crtFlags The CharacterRangeTable flags
   1.823 +     *                   indicating type of the entry.
   1.824 +     */
   1.825 +    public CondItem genCond(JCTree tree, int crtFlags) {
   1.826 +        if (!genCrt) return genCond(tree, false);
   1.827 +        int startpc = code.curCP();
   1.828 +        CondItem item = genCond(tree, (crtFlags & CRT_FLOW_CONTROLLER) != 0);
   1.829 +        code.crt.put(tree, crtFlags, startpc, code.curCP());
   1.830 +        return item;
   1.831 +    }
   1.832 +
   1.833 +    /** Derived visitor method: generate code for a boolean
   1.834 +     *  expression in a control-flow context.
   1.835 +     *  @param _tree         The expression to be visited.
   1.836 +     *  @param markBranches The flag to indicate that the condition is
   1.837 +     *                      a flow controller so produced conditions
   1.838 +     *                      should contain a proper tree to generate
   1.839 +     *                      CharacterRangeTable branches for them.
   1.840 +     */
   1.841 +    public CondItem genCond(JCTree _tree, boolean markBranches) {
   1.842 +        JCTree inner_tree = TreeInfo.skipParens(_tree);
   1.843 +        if (inner_tree.hasTag(CONDEXPR)) {
   1.844 +            JCConditional tree = (JCConditional)inner_tree;
   1.845 +            CondItem cond = genCond(tree.cond, CRT_FLOW_CONTROLLER);
   1.846 +            if (cond.isTrue()) {
   1.847 +                code.resolve(cond.trueJumps);
   1.848 +                CondItem result = genCond(tree.truepart, CRT_FLOW_TARGET);
   1.849 +                if (markBranches) result.tree = tree.truepart;
   1.850 +                return result;
   1.851 +            }
   1.852 +            if (cond.isFalse()) {
   1.853 +                code.resolve(cond.falseJumps);
   1.854 +                CondItem result = genCond(tree.falsepart, CRT_FLOW_TARGET);
   1.855 +                if (markBranches) result.tree = tree.falsepart;
   1.856 +                return result;
   1.857 +            }
   1.858 +            Chain secondJumps = cond.jumpFalse();
   1.859 +            code.resolve(cond.trueJumps);
   1.860 +            CondItem first = genCond(tree.truepart, CRT_FLOW_TARGET);
   1.861 +            if (markBranches) first.tree = tree.truepart;
   1.862 +            Chain falseJumps = first.jumpFalse();
   1.863 +            code.resolve(first.trueJumps);
   1.864 +            Chain trueJumps = code.branch(goto_);
   1.865 +            code.resolve(secondJumps);
   1.866 +            CondItem second = genCond(tree.falsepart, CRT_FLOW_TARGET);
   1.867 +            CondItem result = items.makeCondItem(second.opcode,
   1.868 +                                      Code.mergeChains(trueJumps, second.trueJumps),
   1.869 +                                      Code.mergeChains(falseJumps, second.falseJumps));
   1.870 +            if (markBranches) result.tree = tree.falsepart;
   1.871 +            return result;
   1.872 +        } else {
   1.873 +            CondItem result = genExpr(_tree, syms.booleanType).mkCond();
   1.874 +            if (markBranches) result.tree = _tree;
   1.875 +            return result;
   1.876 +        }
   1.877 +    }
   1.878 +
   1.879 +    /** Visitor class for expressions which might be constant expressions.
   1.880 +     *  This class is a subset of TreeScanner. Intended to visit trees pruned by
   1.881 +     *  Lower as long as constant expressions looking for references to any
   1.882 +     *  ClassSymbol. Any such reference will be added to the constant pool so
   1.883 +     *  automated tools can detect class dependencies better.
   1.884 +     */
   1.885 +    class ClassReferenceVisitor extends JCTree.Visitor {
   1.886 +
   1.887 +        @Override
   1.888 +        public void visitTree(JCTree tree) {}
   1.889 +
   1.890 +        @Override
   1.891 +        public void visitBinary(JCBinary tree) {
   1.892 +            tree.lhs.accept(this);
   1.893 +            tree.rhs.accept(this);
   1.894 +        }
   1.895 +
   1.896 +        @Override
   1.897 +        public void visitSelect(JCFieldAccess tree) {
   1.898 +            if (tree.selected.type.hasTag(CLASS)) {
   1.899 +                makeRef(tree.selected.pos(), tree.selected.type);
   1.900 +            }
   1.901 +        }
   1.902 +
   1.903 +        @Override
   1.904 +        public void visitIdent(JCIdent tree) {
   1.905 +            if (tree.sym.owner instanceof ClassSymbol) {
   1.906 +                pool.put(tree.sym.owner);
   1.907 +            }
   1.908 +        }
   1.909 +
   1.910 +        @Override
   1.911 +        public void visitConditional(JCConditional tree) {
   1.912 +            tree.cond.accept(this);
   1.913 +            tree.truepart.accept(this);
   1.914 +            tree.falsepart.accept(this);
   1.915 +        }
   1.916 +
   1.917 +        @Override
   1.918 +        public void visitUnary(JCUnary tree) {
   1.919 +            tree.arg.accept(this);
   1.920 +        }
   1.921 +
   1.922 +        @Override
   1.923 +        public void visitParens(JCParens tree) {
   1.924 +            tree.expr.accept(this);
   1.925 +        }
   1.926 +
   1.927 +        @Override
   1.928 +        public void visitTypeCast(JCTypeCast tree) {
   1.929 +            tree.expr.accept(this);
   1.930 +        }
   1.931 +    }
   1.932 +
   1.933 +    private ClassReferenceVisitor classReferenceVisitor = new ClassReferenceVisitor();
   1.934 +
   1.935 +    /** Visitor method: generate code for an expression, catching and reporting
   1.936 +     *  any completion failures.
   1.937 +     *  @param tree    The expression to be visited.
   1.938 +     *  @param pt      The expression's expected type (proto-type).
   1.939 +     */
   1.940 +    public Item genExpr(JCTree tree, Type pt) {
   1.941 +        Type prevPt = this.pt;
   1.942 +        try {
   1.943 +            if (tree.type.constValue() != null) {
   1.944 +                // Short circuit any expressions which are constants
   1.945 +                tree.accept(classReferenceVisitor);
   1.946 +                checkStringConstant(tree.pos(), tree.type.constValue());
   1.947 +                result = items.makeImmediateItem(tree.type, tree.type.constValue());
   1.948 +            } else {
   1.949 +                this.pt = pt;
   1.950 +                tree.accept(this);
   1.951 +            }
   1.952 +            return result.coerce(pt);
   1.953 +        } catch (CompletionFailure ex) {
   1.954 +            chk.completionError(tree.pos(), ex);
   1.955 +            code.state.stacksize = 1;
   1.956 +            return items.makeStackItem(pt);
   1.957 +        } finally {
   1.958 +            this.pt = prevPt;
   1.959 +        }
   1.960 +    }
   1.961 +
   1.962 +    /** Derived visitor method: generate code for a list of method arguments.
   1.963 +     *  @param trees    The argument expressions to be visited.
   1.964 +     *  @param pts      The expression's expected types (i.e. the formal parameter
   1.965 +     *                  types of the invoked method).
   1.966 +     */
   1.967 +    public void genArgs(List<JCExpression> trees, List<Type> pts) {
   1.968 +        for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail) {
   1.969 +            genExpr(l.head, pts.head).load();
   1.970 +            pts = pts.tail;
   1.971 +        }
   1.972 +        // require lists be of same length
   1.973 +        Assert.check(pts.isEmpty());
   1.974 +    }
   1.975 +
   1.976 +/* ************************************************************************
   1.977 + * Visitor methods for statements and definitions
   1.978 + *************************************************************************/
   1.979 +
   1.980 +    /** Thrown when the byte code size exceeds limit.
   1.981 +     */
   1.982 +    public static class CodeSizeOverflow extends RuntimeException {
   1.983 +        private static final long serialVersionUID = 0;
   1.984 +        public CodeSizeOverflow() {}
   1.985 +    }
   1.986 +
   1.987 +    public void visitMethodDef(JCMethodDecl tree) {
   1.988 +        // Create a new local environment that points pack at method
   1.989 +        // definition.
   1.990 +        Env<GenContext> localEnv = env.dup(tree);
   1.991 +        localEnv.enclMethod = tree;
   1.992 +        // The expected type of every return statement in this method
   1.993 +        // is the method's return type.
   1.994 +        this.pt = tree.sym.erasure(types).getReturnType();
   1.995 +
   1.996 +        checkDimension(tree.pos(), tree.sym.erasure(types));
   1.997 +        genMethod(tree, localEnv, false);
   1.998 +    }
   1.999 +//where
  1.1000 +        /** Generate code for a method.
  1.1001 +         *  @param tree     The tree representing the method definition.
  1.1002 +         *  @param env      The environment current for the method body.
  1.1003 +         *  @param fatcode  A flag that indicates whether all jumps are
  1.1004 +         *                  within 32K.  We first invoke this method under
  1.1005 +         *                  the assumption that fatcode == false, i.e. all
  1.1006 +         *                  jumps are within 32K.  If this fails, fatcode
  1.1007 +         *                  is set to true and we try again.
  1.1008 +         */
  1.1009 +        void genMethod(JCMethodDecl tree, Env<GenContext> env, boolean fatcode) {
  1.1010 +            MethodSymbol meth = tree.sym;
  1.1011 +            int extras = 0;
  1.1012 +            // Count up extra parameters
  1.1013 +            if (meth.isConstructor()) {
  1.1014 +                extras++;
  1.1015 +                if (meth.enclClass().isInner() &&
  1.1016 +                    !meth.enclClass().isStatic()) {
  1.1017 +                    extras++;
  1.1018 +                }
  1.1019 +            } else if ((tree.mods.flags & STATIC) == 0) {
  1.1020 +                extras++;
  1.1021 +            }
  1.1022 +            //      System.err.println("Generating " + meth + " in " + meth.owner); //DEBUG
  1.1023 +            if (Code.width(types.erasure(env.enclMethod.sym.type).getParameterTypes()) + extras >
  1.1024 +                ClassFile.MAX_PARAMETERS) {
  1.1025 +                log.error(tree.pos(), "limit.parameters");
  1.1026 +                nerrs++;
  1.1027 +            }
  1.1028 +
  1.1029 +            else if (tree.body != null) {
  1.1030 +                // Create a new code structure and initialize it.
  1.1031 +                int startpcCrt = initCode(tree, env, fatcode);
  1.1032 +
  1.1033 +                try {
  1.1034 +                    genStat(tree.body, env);
  1.1035 +                } catch (CodeSizeOverflow e) {
  1.1036 +                    // Failed due to code limit, try again with jsr/ret
  1.1037 +                    startpcCrt = initCode(tree, env, fatcode);
  1.1038 +                    genStat(tree.body, env);
  1.1039 +                }
  1.1040 +
  1.1041 +                if (code.state.stacksize != 0) {
  1.1042 +                    log.error(tree.body.pos(), "stack.sim.error", tree);
  1.1043 +                    throw new AssertionError();
  1.1044 +                }
  1.1045 +
  1.1046 +                // If last statement could complete normally, insert a
  1.1047 +                // return at the end.
  1.1048 +                if (code.isAlive()) {
  1.1049 +                    code.statBegin(TreeInfo.endPos(tree.body));
  1.1050 +                    if (env.enclMethod == null ||
  1.1051 +                        env.enclMethod.sym.type.getReturnType().hasTag(VOID)) {
  1.1052 +                        code.emitop0(return_);
  1.1053 +                    } else {
  1.1054 +                        // sometime dead code seems alive (4415991);
  1.1055 +                        // generate a small loop instead
  1.1056 +                        int startpc = code.entryPoint();
  1.1057 +                        CondItem c = items.makeCondItem(goto_);
  1.1058 +                        code.resolve(c.jumpTrue(), startpc);
  1.1059 +                    }
  1.1060 +                }
  1.1061 +                if (genCrt)
  1.1062 +                    code.crt.put(tree.body,
  1.1063 +                                 CRT_BLOCK,
  1.1064 +                                 startpcCrt,
  1.1065 +                                 code.curCP());
  1.1066 +
  1.1067 +                code.endScopes(0);
  1.1068 +
  1.1069 +                // If we exceeded limits, panic
  1.1070 +                if (code.checkLimits(tree.pos(), log)) {
  1.1071 +                    nerrs++;
  1.1072 +                    return;
  1.1073 +                }
  1.1074 +
  1.1075 +                // If we generated short code but got a long jump, do it again
  1.1076 +                // with fatCode = true.
  1.1077 +                if (!fatcode && code.fatcode) genMethod(tree, env, true);
  1.1078 +
  1.1079 +                // Clean up
  1.1080 +                if(stackMap == StackMapFormat.JSR202) {
  1.1081 +                    code.lastFrame = null;
  1.1082 +                    code.frameBeforeLast = null;
  1.1083 +                }
  1.1084 +
  1.1085 +                // Compress exception table
  1.1086 +                code.compressCatchTable();
  1.1087 +
  1.1088 +                // Fill in type annotation positions for exception parameters
  1.1089 +                code.fillExceptionParameterPositions();
  1.1090 +            }
  1.1091 +        }
  1.1092 +
  1.1093 +        private int initCode(JCMethodDecl tree, Env<GenContext> env, boolean fatcode) {
  1.1094 +            MethodSymbol meth = tree.sym;
  1.1095 +
  1.1096 +            // Create a new code structure.
  1.1097 +            meth.code = code = new Code(meth,
  1.1098 +                                        fatcode,
  1.1099 +                                        lineDebugInfo ? toplevel.lineMap : null,
  1.1100 +                                        varDebugInfo,
  1.1101 +                                        stackMap,
  1.1102 +                                        debugCode,
  1.1103 +                                        genCrt ? new CRTable(tree, env.toplevel.endPositions)
  1.1104 +                                               : null,
  1.1105 +                                        syms,
  1.1106 +                                        types,
  1.1107 +                                        pool,
  1.1108 +                                        varDebugInfo ? lvtRanges : null);
  1.1109 +            items = new Items(pool, code, syms, types);
  1.1110 +            if (code.debugCode) {
  1.1111 +                System.err.println(meth + " for body " + tree);
  1.1112 +            }
  1.1113 +
  1.1114 +            // If method is not static, create a new local variable address
  1.1115 +            // for `this'.
  1.1116 +            if ((tree.mods.flags & STATIC) == 0) {
  1.1117 +                Type selfType = meth.owner.type;
  1.1118 +                if (meth.isConstructor() && selfType != syms.objectType)
  1.1119 +                    selfType = UninitializedType.uninitializedThis(selfType);
  1.1120 +                code.setDefined(
  1.1121 +                        code.newLocal(
  1.1122 +                            new VarSymbol(FINAL, names._this, selfType, meth.owner)));
  1.1123 +            }
  1.1124 +
  1.1125 +            // Mark all parameters as defined from the beginning of
  1.1126 +            // the method.
  1.1127 +            for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
  1.1128 +                checkDimension(l.head.pos(), l.head.sym.type);
  1.1129 +                code.setDefined(code.newLocal(l.head.sym));
  1.1130 +            }
  1.1131 +
  1.1132 +            // Get ready to generate code for method body.
  1.1133 +            int startpcCrt = genCrt ? code.curCP() : 0;
  1.1134 +            code.entryPoint();
  1.1135 +
  1.1136 +            // Suppress initial stackmap
  1.1137 +            code.pendingStackMap = false;
  1.1138 +
  1.1139 +            return startpcCrt;
  1.1140 +        }
  1.1141 +
  1.1142 +    public void visitVarDef(JCVariableDecl tree) {
  1.1143 +        VarSymbol v = tree.sym;
  1.1144 +        code.newLocal(v);
  1.1145 +        if (tree.init != null) {
  1.1146 +            checkStringConstant(tree.init.pos(), v.getConstValue());
  1.1147 +            if (v.getConstValue() == null || varDebugInfo) {
  1.1148 +                genExpr(tree.init, v.erasure(types)).load();
  1.1149 +                items.makeLocalItem(v).store();
  1.1150 +            }
  1.1151 +        }
  1.1152 +        checkDimension(tree.pos(), v.type);
  1.1153 +    }
  1.1154 +
  1.1155 +    public void visitSkip(JCSkip tree) {
  1.1156 +    }
  1.1157 +
  1.1158 +    public void visitBlock(JCBlock tree) {
  1.1159 +        int limit = code.nextreg;
  1.1160 +        Env<GenContext> localEnv = env.dup(tree, new GenContext());
  1.1161 +        genStats(tree.stats, localEnv);
  1.1162 +        // End the scope of all block-local variables in variable info.
  1.1163 +        if (!env.tree.hasTag(METHODDEF)) {
  1.1164 +            code.statBegin(tree.endpos);
  1.1165 +            code.endScopes(limit);
  1.1166 +            code.pendingStatPos = Position.NOPOS;
  1.1167 +        }
  1.1168 +    }
  1.1169 +
  1.1170 +    public void visitDoLoop(JCDoWhileLoop tree) {
  1.1171 +        genLoop(tree, tree.body, tree.cond, List.<JCExpressionStatement>nil(), false);
  1.1172 +    }
  1.1173 +
  1.1174 +    public void visitWhileLoop(JCWhileLoop tree) {
  1.1175 +        genLoop(tree, tree.body, tree.cond, List.<JCExpressionStatement>nil(), true);
  1.1176 +    }
  1.1177 +
  1.1178 +    public void visitForLoop(JCForLoop tree) {
  1.1179 +        int limit = code.nextreg;
  1.1180 +        genStats(tree.init, env);
  1.1181 +        genLoop(tree, tree.body, tree.cond, tree.step, true);
  1.1182 +        code.endScopes(limit);
  1.1183 +    }
  1.1184 +    //where
  1.1185 +        /** Generate code for a loop.
  1.1186 +         *  @param loop       The tree representing the loop.
  1.1187 +         *  @param body       The loop's body.
  1.1188 +         *  @param cond       The loop's controling condition.
  1.1189 +         *  @param step       "Step" statements to be inserted at end of
  1.1190 +         *                    each iteration.
  1.1191 +         *  @param testFirst  True if the loop test belongs before the body.
  1.1192 +         */
  1.1193 +        private void genLoop(JCStatement loop,
  1.1194 +                             JCStatement body,
  1.1195 +                             JCExpression cond,
  1.1196 +                             List<JCExpressionStatement> step,
  1.1197 +                             boolean testFirst) {
  1.1198 +            Env<GenContext> loopEnv = env.dup(loop, new GenContext());
  1.1199 +            int startpc = code.entryPoint();
  1.1200 +            if (testFirst) {
  1.1201 +                CondItem c;
  1.1202 +                if (cond != null) {
  1.1203 +                    code.statBegin(cond.pos);
  1.1204 +                    c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
  1.1205 +                } else {
  1.1206 +                    c = items.makeCondItem(goto_);
  1.1207 +                }
  1.1208 +                Chain loopDone = c.jumpFalse();
  1.1209 +                code.resolve(c.trueJumps);
  1.1210 +                genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
  1.1211 +                if (varDebugInfo) {
  1.1212 +                    checkLoopLocalVarRangeEnding(loop, body,
  1.1213 +                            LoopLocalVarRangeEndingPoint.BEFORE_STEPS);
  1.1214 +                }
  1.1215 +                code.resolve(loopEnv.info.cont);
  1.1216 +                genStats(step, loopEnv);
  1.1217 +                if (varDebugInfo) {
  1.1218 +                    checkLoopLocalVarRangeEnding(loop, body,
  1.1219 +                            LoopLocalVarRangeEndingPoint.AFTER_STEPS);
  1.1220 +                }
  1.1221 +                code.resolve(code.branch(goto_), startpc);
  1.1222 +                code.resolve(loopDone);
  1.1223 +            } else {
  1.1224 +                genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
  1.1225 +                if (varDebugInfo) {
  1.1226 +                    checkLoopLocalVarRangeEnding(loop, body,
  1.1227 +                            LoopLocalVarRangeEndingPoint.BEFORE_STEPS);
  1.1228 +                }
  1.1229 +                code.resolve(loopEnv.info.cont);
  1.1230 +                genStats(step, loopEnv);
  1.1231 +                if (varDebugInfo) {
  1.1232 +                    checkLoopLocalVarRangeEnding(loop, body,
  1.1233 +                            LoopLocalVarRangeEndingPoint.AFTER_STEPS);
  1.1234 +                }
  1.1235 +                CondItem c;
  1.1236 +                if (cond != null) {
  1.1237 +                    code.statBegin(cond.pos);
  1.1238 +                    c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
  1.1239 +                } else {
  1.1240 +                    c = items.makeCondItem(goto_);
  1.1241 +                }
  1.1242 +                code.resolve(c.jumpTrue(), startpc);
  1.1243 +                code.resolve(c.falseJumps);
  1.1244 +            }
  1.1245 +            code.resolve(loopEnv.info.exit);
  1.1246 +        }
  1.1247 +
  1.1248 +        private enum LoopLocalVarRangeEndingPoint {
  1.1249 +            BEFORE_STEPS,
  1.1250 +            AFTER_STEPS,
  1.1251 +        }
  1.1252 +
  1.1253 +        /**
  1.1254 +         *  Checks whether we have reached an alive range ending point for local
  1.1255 +         *  variables after a loop.
  1.1256 +         *
  1.1257 +         *  Local variables alive range ending point for loops varies depending
  1.1258 +         *  on the loop type. The range can be closed before or after the code
  1.1259 +         *  for the steps sentences has been generated.
  1.1260 +         *
  1.1261 +         *  - While loops has no steps so in that case the range is closed just
  1.1262 +         *  after the body of the loop.
  1.1263 +         *
  1.1264 +         *  - For-like loops may have steps so as long as the steps sentences
  1.1265 +         *  can possibly contain non-synthetic local variables, the alive range
  1.1266 +         *  for local variables must be closed after the steps in this case.
  1.1267 +        */
  1.1268 +        private void checkLoopLocalVarRangeEnding(JCTree loop, JCTree body,
  1.1269 +                LoopLocalVarRangeEndingPoint endingPoint) {
  1.1270 +            if (varDebugInfo && lvtRanges.containsKey(code.meth, body)) {
  1.1271 +                switch (endingPoint) {
  1.1272 +                    case BEFORE_STEPS:
  1.1273 +                        if (!loop.hasTag(FORLOOP)) {
  1.1274 +                            code.closeAliveRanges(body);
  1.1275 +                        }
  1.1276 +                        break;
  1.1277 +                    case AFTER_STEPS:
  1.1278 +                        if (loop.hasTag(FORLOOP)) {
  1.1279 +                            code.closeAliveRanges(body);
  1.1280 +                        }
  1.1281 +                        break;
  1.1282 +                }
  1.1283 +            }
  1.1284 +        }
  1.1285 +
  1.1286 +    public void visitForeachLoop(JCEnhancedForLoop tree) {
  1.1287 +        throw new AssertionError(); // should have been removed by Lower.
  1.1288 +    }
  1.1289 +
  1.1290 +    public void visitLabelled(JCLabeledStatement tree) {
  1.1291 +        Env<GenContext> localEnv = env.dup(tree, new GenContext());
  1.1292 +        genStat(tree.body, localEnv, CRT_STATEMENT);
  1.1293 +        code.resolve(localEnv.info.exit);
  1.1294 +    }
  1.1295 +
  1.1296 +    public void visitSwitch(JCSwitch tree) {
  1.1297 +        int limit = code.nextreg;
  1.1298 +        Assert.check(!tree.selector.type.hasTag(CLASS));
  1.1299 +        int startpcCrt = genCrt ? code.curCP() : 0;
  1.1300 +        Item sel = genExpr(tree.selector, syms.intType);
  1.1301 +        List<JCCase> cases = tree.cases;
  1.1302 +        if (cases.isEmpty()) {
  1.1303 +            // We are seeing:  switch <sel> {}
  1.1304 +            sel.load().drop();
  1.1305 +            if (genCrt)
  1.1306 +                code.crt.put(TreeInfo.skipParens(tree.selector),
  1.1307 +                             CRT_FLOW_CONTROLLER, startpcCrt, code.curCP());
  1.1308 +        } else {
  1.1309 +            // We are seeing a nonempty switch.
  1.1310 +            sel.load();
  1.1311 +            if (genCrt)
  1.1312 +                code.crt.put(TreeInfo.skipParens(tree.selector),
  1.1313 +                             CRT_FLOW_CONTROLLER, startpcCrt, code.curCP());
  1.1314 +            Env<GenContext> switchEnv = env.dup(tree, new GenContext());
  1.1315 +            switchEnv.info.isSwitch = true;
  1.1316 +
  1.1317 +            // Compute number of labels and minimum and maximum label values.
  1.1318 +            // For each case, store its label in an array.
  1.1319 +            int lo = Integer.MAX_VALUE;  // minimum label.
  1.1320 +            int hi = Integer.MIN_VALUE;  // maximum label.
  1.1321 +            int nlabels = 0;               // number of labels.
  1.1322 +
  1.1323 +            int[] labels = new int[cases.length()];  // the label array.
  1.1324 +            int defaultIndex = -1;     // the index of the default clause.
  1.1325 +
  1.1326 +            List<JCCase> l = cases;
  1.1327 +            for (int i = 0; i < labels.length; i++) {
  1.1328 +                if (l.head.pat != null) {
  1.1329 +                    int val = ((Number)l.head.pat.type.constValue()).intValue();
  1.1330 +                    labels[i] = val;
  1.1331 +                    if (val < lo) lo = val;
  1.1332 +                    if (hi < val) hi = val;
  1.1333 +                    nlabels++;
  1.1334 +                } else {
  1.1335 +                    Assert.check(defaultIndex == -1);
  1.1336 +                    defaultIndex = i;
  1.1337 +                }
  1.1338 +                l = l.tail;
  1.1339 +            }
  1.1340 +
  1.1341 +            // Determine whether to issue a tableswitch or a lookupswitch
  1.1342 +            // instruction.
  1.1343 +            long table_space_cost = 4 + ((long) hi - lo + 1); // words
  1.1344 +            long table_time_cost = 3; // comparisons
  1.1345 +            long lookup_space_cost = 3 + 2 * (long) nlabels;
  1.1346 +            long lookup_time_cost = nlabels;
  1.1347 +            int opcode =
  1.1348 +                nlabels > 0 &&
  1.1349 +                table_space_cost + 3 * table_time_cost <=
  1.1350 +                lookup_space_cost + 3 * lookup_time_cost
  1.1351 +                ?
  1.1352 +                tableswitch : lookupswitch;
  1.1353 +
  1.1354 +            int startpc = code.curCP();    // the position of the selector operation
  1.1355 +            code.emitop0(opcode);
  1.1356 +            code.align(4);
  1.1357 +            int tableBase = code.curCP();  // the start of the jump table
  1.1358 +            int[] offsets = null;          // a table of offsets for a lookupswitch
  1.1359 +            code.emit4(-1);                // leave space for default offset
  1.1360 +            if (opcode == tableswitch) {
  1.1361 +                code.emit4(lo);            // minimum label
  1.1362 +                code.emit4(hi);            // maximum label
  1.1363 +                for (long i = lo; i <= hi; i++) {  // leave space for jump table
  1.1364 +                    code.emit4(-1);
  1.1365 +                }
  1.1366 +            } else {
  1.1367 +                code.emit4(nlabels);    // number of labels
  1.1368 +                for (int i = 0; i < nlabels; i++) {
  1.1369 +                    code.emit4(-1); code.emit4(-1); // leave space for lookup table
  1.1370 +                }
  1.1371 +                offsets = new int[labels.length];
  1.1372 +            }
  1.1373 +            Code.State stateSwitch = code.state.dup();
  1.1374 +            code.markDead();
  1.1375 +
  1.1376 +            // For each case do:
  1.1377 +            l = cases;
  1.1378 +            for (int i = 0; i < labels.length; i++) {
  1.1379 +                JCCase c = l.head;
  1.1380 +                l = l.tail;
  1.1381 +
  1.1382 +                int pc = code.entryPoint(stateSwitch);
  1.1383 +                // Insert offset directly into code or else into the
  1.1384 +                // offsets table.
  1.1385 +                if (i != defaultIndex) {
  1.1386 +                    if (opcode == tableswitch) {
  1.1387 +                        code.put4(
  1.1388 +                            tableBase + 4 * (labels[i] - lo + 3),
  1.1389 +                            pc - startpc);
  1.1390 +                    } else {
  1.1391 +                        offsets[i] = pc - startpc;
  1.1392 +                    }
  1.1393 +                } else {
  1.1394 +                    code.put4(tableBase, pc - startpc);
  1.1395 +                }
  1.1396 +
  1.1397 +                // Generate code for the statements in this case.
  1.1398 +                genStats(c.stats, switchEnv, CRT_FLOW_TARGET);
  1.1399 +                if (varDebugInfo && lvtRanges.containsKey(code.meth, c.stats.last())) {
  1.1400 +                    code.closeAliveRanges(c.stats.last());
  1.1401 +                }
  1.1402 +            }
  1.1403 +
  1.1404 +            // Resolve all breaks.
  1.1405 +            code.resolve(switchEnv.info.exit);
  1.1406 +
  1.1407 +            // If we have not set the default offset, we do so now.
  1.1408 +            if (code.get4(tableBase) == -1) {
  1.1409 +                code.put4(tableBase, code.entryPoint(stateSwitch) - startpc);
  1.1410 +            }
  1.1411 +
  1.1412 +            if (opcode == tableswitch) {
  1.1413 +                // Let any unfilled slots point to the default case.
  1.1414 +                int defaultOffset = code.get4(tableBase);
  1.1415 +                for (long i = lo; i <= hi; i++) {
  1.1416 +                    int t = (int)(tableBase + 4 * (i - lo + 3));
  1.1417 +                    if (code.get4(t) == -1)
  1.1418 +                        code.put4(t, defaultOffset);
  1.1419 +                }
  1.1420 +            } else {
  1.1421 +                // Sort non-default offsets and copy into lookup table.
  1.1422 +                if (defaultIndex >= 0)
  1.1423 +                    for (int i = defaultIndex; i < labels.length - 1; i++) {
  1.1424 +                        labels[i] = labels[i+1];
  1.1425 +                        offsets[i] = offsets[i+1];
  1.1426 +                    }
  1.1427 +                if (nlabels > 0)
  1.1428 +                    qsort2(labels, offsets, 0, nlabels - 1);
  1.1429 +                for (int i = 0; i < nlabels; i++) {
  1.1430 +                    int caseidx = tableBase + 8 * (i + 1);
  1.1431 +                    code.put4(caseidx, labels[i]);
  1.1432 +                    code.put4(caseidx + 4, offsets[i]);
  1.1433 +                }
  1.1434 +            }
  1.1435 +        }
  1.1436 +        code.endScopes(limit);
  1.1437 +    }
  1.1438 +//where
  1.1439 +        /** Sort (int) arrays of keys and values
  1.1440 +         */
  1.1441 +       static void qsort2(int[] keys, int[] values, int lo, int hi) {
  1.1442 +            int i = lo;
  1.1443 +            int j = hi;
  1.1444 +            int pivot = keys[(i+j)/2];
  1.1445 +            do {
  1.1446 +                while (keys[i] < pivot) i++;
  1.1447 +                while (pivot < keys[j]) j--;
  1.1448 +                if (i <= j) {
  1.1449 +                    int temp1 = keys[i];
  1.1450 +                    keys[i] = keys[j];
  1.1451 +                    keys[j] = temp1;
  1.1452 +                    int temp2 = values[i];
  1.1453 +                    values[i] = values[j];
  1.1454 +                    values[j] = temp2;
  1.1455 +                    i++;
  1.1456 +                    j--;
  1.1457 +                }
  1.1458 +            } while (i <= j);
  1.1459 +            if (lo < j) qsort2(keys, values, lo, j);
  1.1460 +            if (i < hi) qsort2(keys, values, i, hi);
  1.1461 +        }
  1.1462 +
  1.1463 +    public void visitSynchronized(JCSynchronized tree) {
  1.1464 +        int limit = code.nextreg;
  1.1465 +        // Generate code to evaluate lock and save in temporary variable.
  1.1466 +        final LocalItem lockVar = makeTemp(syms.objectType);
  1.1467 +        genExpr(tree.lock, tree.lock.type).load().duplicate();
  1.1468 +        lockVar.store();
  1.1469 +
  1.1470 +        // Generate code to enter monitor.
  1.1471 +        code.emitop0(monitorenter);
  1.1472 +        code.state.lock(lockVar.reg);
  1.1473 +
  1.1474 +        // Generate code for a try statement with given body, no catch clauses
  1.1475 +        // in a new environment with the "exit-monitor" operation as finalizer.
  1.1476 +        final Env<GenContext> syncEnv = env.dup(tree, new GenContext());
  1.1477 +        syncEnv.info.finalize = new GenFinalizer() {
  1.1478 +            void gen() {
  1.1479 +                genLast();
  1.1480 +                Assert.check(syncEnv.info.gaps.length() % 2 == 0);
  1.1481 +                syncEnv.info.gaps.append(code.curCP());
  1.1482 +            }
  1.1483 +            void genLast() {
  1.1484 +                if (code.isAlive()) {
  1.1485 +                    lockVar.load();
  1.1486 +                    code.emitop0(monitorexit);
  1.1487 +                    code.state.unlock(lockVar.reg);
  1.1488 +                }
  1.1489 +            }
  1.1490 +        };
  1.1491 +        syncEnv.info.gaps = new ListBuffer<Integer>();
  1.1492 +        genTry(tree.body, List.<JCCatch>nil(), syncEnv);
  1.1493 +        code.endScopes(limit);
  1.1494 +    }
  1.1495 +
  1.1496 +    public void visitTry(final JCTry tree) {
  1.1497 +        // Generate code for a try statement with given body and catch clauses,
  1.1498 +        // in a new environment which calls the finally block if there is one.
  1.1499 +        final Env<GenContext> tryEnv = env.dup(tree, new GenContext());
  1.1500 +        final Env<GenContext> oldEnv = env;
  1.1501 +        if (!useJsrLocally) {
  1.1502 +            useJsrLocally =
  1.1503 +                (stackMap == StackMapFormat.NONE) &&
  1.1504 +                (jsrlimit <= 0 ||
  1.1505 +                jsrlimit < 100 &&
  1.1506 +                estimateCodeComplexity(tree.finalizer)>jsrlimit);
  1.1507 +        }
  1.1508 +        tryEnv.info.finalize = new GenFinalizer() {
  1.1509 +            void gen() {
  1.1510 +                if (useJsrLocally) {
  1.1511 +                    if (tree.finalizer != null) {
  1.1512 +                        Code.State jsrState = code.state.dup();
  1.1513 +                        jsrState.push(Code.jsrReturnValue);
  1.1514 +                        tryEnv.info.cont =
  1.1515 +                            new Chain(code.emitJump(jsr),
  1.1516 +                                      tryEnv.info.cont,
  1.1517 +                                      jsrState);
  1.1518 +                    }
  1.1519 +                    Assert.check(tryEnv.info.gaps.length() % 2 == 0);
  1.1520 +                    tryEnv.info.gaps.append(code.curCP());
  1.1521 +                } else {
  1.1522 +                    Assert.check(tryEnv.info.gaps.length() % 2 == 0);
  1.1523 +                    tryEnv.info.gaps.append(code.curCP());
  1.1524 +                    genLast();
  1.1525 +                }
  1.1526 +            }
  1.1527 +            void genLast() {
  1.1528 +                if (tree.finalizer != null)
  1.1529 +                    genStat(tree.finalizer, oldEnv, CRT_BLOCK);
  1.1530 +            }
  1.1531 +            boolean hasFinalizer() {
  1.1532 +                return tree.finalizer != null;
  1.1533 +            }
  1.1534 +        };
  1.1535 +        tryEnv.info.gaps = new ListBuffer<Integer>();
  1.1536 +        genTry(tree.body, tree.catchers, tryEnv);
  1.1537 +    }
  1.1538 +    //where
  1.1539 +        /** Generate code for a try or synchronized statement
  1.1540 +         *  @param body      The body of the try or synchronized statement.
  1.1541 +         *  @param catchers  The lis of catch clauses.
  1.1542 +         *  @param env       the environment current for the body.
  1.1543 +         */
  1.1544 +        void genTry(JCTree body, List<JCCatch> catchers, Env<GenContext> env) {
  1.1545 +            int limit = code.nextreg;
  1.1546 +            int startpc = code.curCP();
  1.1547 +            Code.State stateTry = code.state.dup();
  1.1548 +            genStat(body, env, CRT_BLOCK);
  1.1549 +            int endpc = code.curCP();
  1.1550 +            boolean hasFinalizer =
  1.1551 +                env.info.finalize != null &&
  1.1552 +                env.info.finalize.hasFinalizer();
  1.1553 +            List<Integer> gaps = env.info.gaps.toList();
  1.1554 +            code.statBegin(TreeInfo.endPos(body));
  1.1555 +            genFinalizer(env);
  1.1556 +            code.statBegin(TreeInfo.endPos(env.tree));
  1.1557 +            Chain exitChain = code.branch(goto_);
  1.1558 +            if (varDebugInfo && lvtRanges.containsKey(code.meth, body)) {
  1.1559 +                code.closeAliveRanges(body);
  1.1560 +            }
  1.1561 +            endFinalizerGap(env);
  1.1562 +            if (startpc != endpc) for (List<JCCatch> l = catchers; l.nonEmpty(); l = l.tail) {
  1.1563 +                // start off with exception on stack
  1.1564 +                code.entryPoint(stateTry, l.head.param.sym.type);
  1.1565 +                genCatch(l.head, env, startpc, endpc, gaps);
  1.1566 +                genFinalizer(env);
  1.1567 +                if (hasFinalizer || l.tail.nonEmpty()) {
  1.1568 +                    code.statBegin(TreeInfo.endPos(env.tree));
  1.1569 +                    exitChain = Code.mergeChains(exitChain,
  1.1570 +                                                 code.branch(goto_));
  1.1571 +                }
  1.1572 +                endFinalizerGap(env);
  1.1573 +            }
  1.1574 +            if (hasFinalizer) {
  1.1575 +                // Create a new register segement to avoid allocating
  1.1576 +                // the same variables in finalizers and other statements.
  1.1577 +                code.newRegSegment();
  1.1578 +
  1.1579 +                // Add a catch-all clause.
  1.1580 +
  1.1581 +                // start off with exception on stack
  1.1582 +                int catchallpc = code.entryPoint(stateTry, syms.throwableType);
  1.1583 +
  1.1584 +                // Register all exception ranges for catch all clause.
  1.1585 +                // The range of the catch all clause is from the beginning
  1.1586 +                // of the try or synchronized block until the present
  1.1587 +                // code pointer excluding all gaps in the current
  1.1588 +                // environment's GenContext.
  1.1589 +                int startseg = startpc;
  1.1590 +                while (env.info.gaps.nonEmpty()) {
  1.1591 +                    int endseg = env.info.gaps.next().intValue();
  1.1592 +                    registerCatch(body.pos(), startseg, endseg,
  1.1593 +                                  catchallpc, 0);
  1.1594 +                    startseg = env.info.gaps.next().intValue();
  1.1595 +                }
  1.1596 +                code.statBegin(TreeInfo.finalizerPos(env.tree));
  1.1597 +                code.markStatBegin();
  1.1598 +
  1.1599 +                Item excVar = makeTemp(syms.throwableType);
  1.1600 +                excVar.store();
  1.1601 +                genFinalizer(env);
  1.1602 +                excVar.load();
  1.1603 +                registerCatch(body.pos(), startseg,
  1.1604 +                              env.info.gaps.next().intValue(),
  1.1605 +                              catchallpc, 0);
  1.1606 +                code.emitop0(athrow);
  1.1607 +                code.markDead();
  1.1608 +
  1.1609 +                // If there are jsr's to this finalizer, ...
  1.1610 +                if (env.info.cont != null) {
  1.1611 +                    // Resolve all jsr's.
  1.1612 +                    code.resolve(env.info.cont);
  1.1613 +
  1.1614 +                    // Mark statement line number
  1.1615 +                    code.statBegin(TreeInfo.finalizerPos(env.tree));
  1.1616 +                    code.markStatBegin();
  1.1617 +
  1.1618 +                    // Save return address.
  1.1619 +                    LocalItem retVar = makeTemp(syms.throwableType);
  1.1620 +                    retVar.store();
  1.1621 +
  1.1622 +                    // Generate finalizer code.
  1.1623 +                    env.info.finalize.genLast();
  1.1624 +
  1.1625 +                    // Return.
  1.1626 +                    code.emitop1w(ret, retVar.reg);
  1.1627 +                    code.markDead();
  1.1628 +                }
  1.1629 +            }
  1.1630 +            // Resolve all breaks.
  1.1631 +            code.resolve(exitChain);
  1.1632 +
  1.1633 +            code.endScopes(limit);
  1.1634 +        }
  1.1635 +
  1.1636 +        /** Generate code for a catch clause.
  1.1637 +         *  @param tree     The catch clause.
  1.1638 +         *  @param env      The environment current in the enclosing try.
  1.1639 +         *  @param startpc  Start pc of try-block.
  1.1640 +         *  @param endpc    End pc of try-block.
  1.1641 +         */
  1.1642 +        void genCatch(JCCatch tree,
  1.1643 +                      Env<GenContext> env,
  1.1644 +                      int startpc, int endpc,
  1.1645 +                      List<Integer> gaps) {
  1.1646 +            if (startpc != endpc) {
  1.1647 +                List<JCExpression> subClauses = TreeInfo.isMultiCatch(tree) ?
  1.1648 +                        ((JCTypeUnion)tree.param.vartype).alternatives :
  1.1649 +                        List.of(tree.param.vartype);
  1.1650 +                while (gaps.nonEmpty()) {
  1.1651 +                    for (JCExpression subCatch : subClauses) {
  1.1652 +                        int catchType = makeRef(tree.pos(), subCatch.type);
  1.1653 +                        int end = gaps.head.intValue();
  1.1654 +                        registerCatch(tree.pos(),
  1.1655 +                                      startpc,  end, code.curCP(),
  1.1656 +                                      catchType);
  1.1657 +                        if (subCatch.type.isAnnotated()) {
  1.1658 +                            for (Attribute.TypeCompound tc :
  1.1659 +                                     subCatch.type.getAnnotationMirrors()) {
  1.1660 +                                tc.position.type_index = catchType;
  1.1661 +                            }
  1.1662 +                        }
  1.1663 +                    }
  1.1664 +                    gaps = gaps.tail;
  1.1665 +                    startpc = gaps.head.intValue();
  1.1666 +                    gaps = gaps.tail;
  1.1667 +                }
  1.1668 +                if (startpc < endpc) {
  1.1669 +                    for (JCExpression subCatch : subClauses) {
  1.1670 +                        int catchType = makeRef(tree.pos(), subCatch.type);
  1.1671 +                        registerCatch(tree.pos(),
  1.1672 +                                      startpc, endpc, code.curCP(),
  1.1673 +                                      catchType);
  1.1674 +                        if (subCatch.type.isAnnotated()) {
  1.1675 +                            for (Attribute.TypeCompound tc :
  1.1676 +                                     subCatch.type.getAnnotationMirrors()) {
  1.1677 +                                tc.position.type_index = catchType;
  1.1678 +                            }
  1.1679 +                        }
  1.1680 +                    }
  1.1681 +                }
  1.1682 +                VarSymbol exparam = tree.param.sym;
  1.1683 +                code.statBegin(tree.pos);
  1.1684 +                code.markStatBegin();
  1.1685 +                int limit = code.nextreg;
  1.1686 +                int exlocal = code.newLocal(exparam);
  1.1687 +                items.makeLocalItem(exparam).store();
  1.1688 +                code.statBegin(TreeInfo.firstStatPos(tree.body));
  1.1689 +                genStat(tree.body, env, CRT_BLOCK);
  1.1690 +                code.endScopes(limit);
  1.1691 +                code.statBegin(TreeInfo.endPos(tree.body));
  1.1692 +            }
  1.1693 +        }
  1.1694 +
  1.1695 +        /** Register a catch clause in the "Exceptions" code-attribute.
  1.1696 +         */
  1.1697 +        void registerCatch(DiagnosticPosition pos,
  1.1698 +                           int startpc, int endpc,
  1.1699 +                           int handler_pc, int catch_type) {
  1.1700 +            char startpc1 = (char)startpc;
  1.1701 +            char endpc1 = (char)endpc;
  1.1702 +            char handler_pc1 = (char)handler_pc;
  1.1703 +            if (startpc1 == startpc &&
  1.1704 +                endpc1 == endpc &&
  1.1705 +                handler_pc1 == handler_pc) {
  1.1706 +                code.addCatch(startpc1, endpc1, handler_pc1,
  1.1707 +                              (char)catch_type);
  1.1708 +            } else {
  1.1709 +                if (!useJsrLocally && !target.generateStackMapTable()) {
  1.1710 +                    useJsrLocally = true;
  1.1711 +                    throw new CodeSizeOverflow();
  1.1712 +                } else {
  1.1713 +                    log.error(pos, "limit.code.too.large.for.try.stmt");
  1.1714 +                    nerrs++;
  1.1715 +                }
  1.1716 +            }
  1.1717 +        }
  1.1718 +
  1.1719 +    /** Very roughly estimate the number of instructions needed for
  1.1720 +     *  the given tree.
  1.1721 +     */
  1.1722 +    int estimateCodeComplexity(JCTree tree) {
  1.1723 +        if (tree == null) return 0;
  1.1724 +        class ComplexityScanner extends TreeScanner {
  1.1725 +            int complexity = 0;
  1.1726 +            public void scan(JCTree tree) {
  1.1727 +                if (complexity > jsrlimit) return;
  1.1728 +                super.scan(tree);
  1.1729 +            }
  1.1730 +            public void visitClassDef(JCClassDecl tree) {}
  1.1731 +            public void visitDoLoop(JCDoWhileLoop tree)
  1.1732 +                { super.visitDoLoop(tree); complexity++; }
  1.1733 +            public void visitWhileLoop(JCWhileLoop tree)
  1.1734 +                { super.visitWhileLoop(tree); complexity++; }
  1.1735 +            public void visitForLoop(JCForLoop tree)
  1.1736 +                { super.visitForLoop(tree); complexity++; }
  1.1737 +            public void visitSwitch(JCSwitch tree)
  1.1738 +                { super.visitSwitch(tree); complexity+=5; }
  1.1739 +            public void visitCase(JCCase tree)
  1.1740 +                { super.visitCase(tree); complexity++; }
  1.1741 +            public void visitSynchronized(JCSynchronized tree)
  1.1742 +                { super.visitSynchronized(tree); complexity+=6; }
  1.1743 +            public void visitTry(JCTry tree)
  1.1744 +                { super.visitTry(tree);
  1.1745 +                  if (tree.finalizer != null) complexity+=6; }
  1.1746 +            public void visitCatch(JCCatch tree)
  1.1747 +                { super.visitCatch(tree); complexity+=2; }
  1.1748 +            public void visitConditional(JCConditional tree)
  1.1749 +                { super.visitConditional(tree); complexity+=2; }
  1.1750 +            public void visitIf(JCIf tree)
  1.1751 +                { super.visitIf(tree); complexity+=2; }
  1.1752 +            // note: for break, continue, and return we don't take unwind() into account.
  1.1753 +            public void visitBreak(JCBreak tree)
  1.1754 +                { super.visitBreak(tree); complexity+=1; }
  1.1755 +            public void visitContinue(JCContinue tree)
  1.1756 +                { super.visitContinue(tree); complexity+=1; }
  1.1757 +            public void visitReturn(JCReturn tree)
  1.1758 +                { super.visitReturn(tree); complexity+=1; }
  1.1759 +            public void visitThrow(JCThrow tree)
  1.1760 +                { super.visitThrow(tree); complexity+=1; }
  1.1761 +            public void visitAssert(JCAssert tree)
  1.1762 +                { super.visitAssert(tree); complexity+=5; }
  1.1763 +            public void visitApply(JCMethodInvocation tree)
  1.1764 +                { super.visitApply(tree); complexity+=2; }
  1.1765 +            public void visitNewClass(JCNewClass tree)
  1.1766 +                { scan(tree.encl); scan(tree.args); complexity+=2; }
  1.1767 +            public void visitNewArray(JCNewArray tree)
  1.1768 +                { super.visitNewArray(tree); complexity+=5; }
  1.1769 +            public void visitAssign(JCAssign tree)
  1.1770 +                { super.visitAssign(tree); complexity+=1; }
  1.1771 +            public void visitAssignop(JCAssignOp tree)
  1.1772 +                { super.visitAssignop(tree); complexity+=2; }
  1.1773 +            public void visitUnary(JCUnary tree)
  1.1774 +                { complexity+=1;
  1.1775 +                  if (tree.type.constValue() == null) super.visitUnary(tree); }
  1.1776 +            public void visitBinary(JCBinary tree)
  1.1777 +                { complexity+=1;
  1.1778 +                  if (tree.type.constValue() == null) super.visitBinary(tree); }
  1.1779 +            public void visitTypeTest(JCInstanceOf tree)
  1.1780 +                { super.visitTypeTest(tree); complexity+=1; }
  1.1781 +            public void visitIndexed(JCArrayAccess tree)
  1.1782 +                { super.visitIndexed(tree); complexity+=1; }
  1.1783 +            public void visitSelect(JCFieldAccess tree)
  1.1784 +                { super.visitSelect(tree);
  1.1785 +                  if (tree.sym.kind == VAR) complexity+=1; }
  1.1786 +            public void visitIdent(JCIdent tree) {
  1.1787 +                if (tree.sym.kind == VAR) {
  1.1788 +                    complexity+=1;
  1.1789 +                    if (tree.type.constValue() == null &&
  1.1790 +                        tree.sym.owner.kind == TYP)
  1.1791 +                        complexity+=1;
  1.1792 +                }
  1.1793 +            }
  1.1794 +            public void visitLiteral(JCLiteral tree)
  1.1795 +                { complexity+=1; }
  1.1796 +            public void visitTree(JCTree tree) {}
  1.1797 +            public void visitWildcard(JCWildcard tree) {
  1.1798 +                throw new AssertionError(this.getClass().getName());
  1.1799 +            }
  1.1800 +        }
  1.1801 +        ComplexityScanner scanner = new ComplexityScanner();
  1.1802 +        tree.accept(scanner);
  1.1803 +        return scanner.complexity;
  1.1804 +    }
  1.1805 +
  1.1806 +    public void visitIf(JCIf tree) {
  1.1807 +        int limit = code.nextreg;
  1.1808 +        Chain thenExit = null;
  1.1809 +        CondItem c = genCond(TreeInfo.skipParens(tree.cond),
  1.1810 +                             CRT_FLOW_CONTROLLER);
  1.1811 +        Chain elseChain = c.jumpFalse();
  1.1812 +        if (!c.isFalse()) {
  1.1813 +            code.resolve(c.trueJumps);
  1.1814 +            genStat(tree.thenpart, env, CRT_STATEMENT | CRT_FLOW_TARGET);
  1.1815 +            thenExit = code.branch(goto_);
  1.1816 +            if (varDebugInfo && lvtRanges.containsKey(code.meth, tree.thenpart)) {
  1.1817 +                code.closeAliveRanges(tree.thenpart, code.cp);
  1.1818 +            }
  1.1819 +        }
  1.1820 +        if (elseChain != null) {
  1.1821 +            code.resolve(elseChain);
  1.1822 +            if (tree.elsepart != null) {
  1.1823 +                genStat(tree.elsepart, env,CRT_STATEMENT | CRT_FLOW_TARGET);
  1.1824 +                if (varDebugInfo && lvtRanges.containsKey(code.meth, tree.elsepart)) {
  1.1825 +                    code.closeAliveRanges(tree.elsepart);
  1.1826 +                }
  1.1827 +            }
  1.1828 +        }
  1.1829 +        code.resolve(thenExit);
  1.1830 +        code.endScopes(limit);
  1.1831 +    }
  1.1832 +
  1.1833 +    public void visitExec(JCExpressionStatement tree) {
  1.1834 +        // Optimize x++ to ++x and x-- to --x.
  1.1835 +        JCExpression e = tree.expr;
  1.1836 +        switch (e.getTag()) {
  1.1837 +            case POSTINC:
  1.1838 +                ((JCUnary) e).setTag(PREINC);
  1.1839 +                break;
  1.1840 +            case POSTDEC:
  1.1841 +                ((JCUnary) e).setTag(PREDEC);
  1.1842 +                break;
  1.1843 +        }
  1.1844 +        genExpr(tree.expr, tree.expr.type).drop();
  1.1845 +    }
  1.1846 +
  1.1847 +    public void visitBreak(JCBreak tree) {
  1.1848 +        Env<GenContext> targetEnv = unwind(tree.target, env);
  1.1849 +        Assert.check(code.state.stacksize == 0);
  1.1850 +        targetEnv.info.addExit(code.branch(goto_));
  1.1851 +        endFinalizerGaps(env, targetEnv);
  1.1852 +    }
  1.1853 +
  1.1854 +    public void visitContinue(JCContinue tree) {
  1.1855 +        Env<GenContext> targetEnv = unwind(tree.target, env);
  1.1856 +        Assert.check(code.state.stacksize == 0);
  1.1857 +        targetEnv.info.addCont(code.branch(goto_));
  1.1858 +        endFinalizerGaps(env, targetEnv);
  1.1859 +    }
  1.1860 +
  1.1861 +    public void visitReturn(JCReturn tree) {
  1.1862 +        int limit = code.nextreg;
  1.1863 +        final Env<GenContext> targetEnv;
  1.1864 +        if (tree.expr != null) {
  1.1865 +            Item r = genExpr(tree.expr, pt).load();
  1.1866 +            if (hasFinally(env.enclMethod, env)) {
  1.1867 +                r = makeTemp(pt);
  1.1868 +                r.store();
  1.1869 +            }
  1.1870 +            targetEnv = unwind(env.enclMethod, env);
  1.1871 +            r.load();
  1.1872 +            code.emitop0(ireturn + Code.truncate(Code.typecode(pt)));
  1.1873 +        } else {
  1.1874 +            /*  If we have a statement like:
  1.1875 +             *
  1.1876 +             *  return;
  1.1877 +             *
  1.1878 +             *  we need to store the code.pendingStatPos value before generating
  1.1879 +             *  the finalizer.
  1.1880 +             */
  1.1881 +            int tmpPos = code.pendingStatPos;
  1.1882 +            targetEnv = unwind(env.enclMethod, env);
  1.1883 +            code.pendingStatPos = tmpPos;
  1.1884 +            code.emitop0(return_);
  1.1885 +        }
  1.1886 +        endFinalizerGaps(env, targetEnv);
  1.1887 +        code.endScopes(limit);
  1.1888 +    }
  1.1889 +
  1.1890 +    public void visitThrow(JCThrow tree) {
  1.1891 +        genExpr(tree.expr, tree.expr.type).load();
  1.1892 +        code.emitop0(athrow);
  1.1893 +    }
  1.1894 +
  1.1895 +/* ************************************************************************
  1.1896 + * Visitor methods for expressions
  1.1897 + *************************************************************************/
  1.1898 +
  1.1899 +    public void visitApply(JCMethodInvocation tree) {
  1.1900 +        setTypeAnnotationPositions(tree.pos);
  1.1901 +        // Generate code for method.
  1.1902 +        Item m = genExpr(tree.meth, methodType);
  1.1903 +        // Generate code for all arguments, where the expected types are
  1.1904 +        // the parameters of the method's external type (that is, any implicit
  1.1905 +        // outer instance of a super(...) call appears as first parameter).
  1.1906 +        MethodSymbol msym = (MethodSymbol)TreeInfo.symbol(tree.meth);
  1.1907 +        genArgs(tree.args,
  1.1908 +                msym.externalType(types).getParameterTypes());
  1.1909 +        if (!msym.isDynamic()) {
  1.1910 +            code.statBegin(tree.pos);
  1.1911 +        }
  1.1912 +        result = m.invoke();
  1.1913 +    }
  1.1914 +
  1.1915 +    public void visitConditional(JCConditional tree) {
  1.1916 +        Chain thenExit = null;
  1.1917 +        CondItem c = genCond(tree.cond, CRT_FLOW_CONTROLLER);
  1.1918 +        Chain elseChain = c.jumpFalse();
  1.1919 +        if (!c.isFalse()) {
  1.1920 +            code.resolve(c.trueJumps);
  1.1921 +            int startpc = genCrt ? code.curCP() : 0;
  1.1922 +            genExpr(tree.truepart, pt).load();
  1.1923 +            code.state.forceStackTop(tree.type);
  1.1924 +            if (genCrt) code.crt.put(tree.truepart, CRT_FLOW_TARGET,
  1.1925 +                                     startpc, code.curCP());
  1.1926 +            thenExit = code.branch(goto_);
  1.1927 +        }
  1.1928 +        if (elseChain != null) {
  1.1929 +            code.resolve(elseChain);
  1.1930 +            int startpc = genCrt ? code.curCP() : 0;
  1.1931 +            genExpr(tree.falsepart, pt).load();
  1.1932 +            code.state.forceStackTop(tree.type);
  1.1933 +            if (genCrt) code.crt.put(tree.falsepart, CRT_FLOW_TARGET,
  1.1934 +                                     startpc, code.curCP());
  1.1935 +        }
  1.1936 +        code.resolve(thenExit);
  1.1937 +        result = items.makeStackItem(pt);
  1.1938 +    }
  1.1939 +
  1.1940 +    private void setTypeAnnotationPositions(int treePos) {
  1.1941 +        MethodSymbol meth = code.meth;
  1.1942 +        boolean initOrClinit = code.meth.getKind() == javax.lang.model.element.ElementKind.CONSTRUCTOR
  1.1943 +                || code.meth.getKind() == javax.lang.model.element.ElementKind.STATIC_INIT;
  1.1944 +
  1.1945 +        for (Attribute.TypeCompound ta : meth.getRawTypeAttributes()) {
  1.1946 +            if (ta.hasUnknownPosition())
  1.1947 +                ta.tryFixPosition();
  1.1948 +
  1.1949 +            if (ta.position.matchesPos(treePos))
  1.1950 +                ta.position.updatePosOffset(code.cp);
  1.1951 +        }
  1.1952 +
  1.1953 +        if (!initOrClinit)
  1.1954 +            return;
  1.1955 +
  1.1956 +        for (Attribute.TypeCompound ta : meth.owner.getRawTypeAttributes()) {
  1.1957 +            if (ta.hasUnknownPosition())
  1.1958 +                ta.tryFixPosition();
  1.1959 +
  1.1960 +            if (ta.position.matchesPos(treePos))
  1.1961 +                ta.position.updatePosOffset(code.cp);
  1.1962 +        }
  1.1963 +
  1.1964 +        ClassSymbol clazz = meth.enclClass();
  1.1965 +        for (Symbol s : new com.sun.tools.javac.model.FilteredMemberList(clazz.members())) {
  1.1966 +            if (!s.getKind().isField())
  1.1967 +                continue;
  1.1968 +
  1.1969 +            for (Attribute.TypeCompound ta : s.getRawTypeAttributes()) {
  1.1970 +                if (ta.hasUnknownPosition())
  1.1971 +                    ta.tryFixPosition();
  1.1972 +
  1.1973 +                if (ta.position.matchesPos(treePos))
  1.1974 +                    ta.position.updatePosOffset(code.cp);
  1.1975 +            }
  1.1976 +        }
  1.1977 +    }
  1.1978 +
  1.1979 +    public void visitNewClass(JCNewClass tree) {
  1.1980 +        // Enclosing instances or anonymous classes should have been eliminated
  1.1981 +        // by now.
  1.1982 +        Assert.check(tree.encl == null && tree.def == null);
  1.1983 +        setTypeAnnotationPositions(tree.pos);
  1.1984 +
  1.1985 +        code.emitop2(new_, makeRef(tree.pos(), tree.type));
  1.1986 +        code.emitop0(dup);
  1.1987 +
  1.1988 +        // Generate code for all arguments, where the expected types are
  1.1989 +        // the parameters of the constructor's external type (that is,
  1.1990 +        // any implicit outer instance appears as first parameter).
  1.1991 +        genArgs(tree.args, tree.constructor.externalType(types).getParameterTypes());
  1.1992 +
  1.1993 +        items.makeMemberItem(tree.constructor, true).invoke();
  1.1994 +        result = items.makeStackItem(tree.type);
  1.1995 +    }
  1.1996 +
  1.1997 +    public void visitNewArray(JCNewArray tree) {
  1.1998 +        setTypeAnnotationPositions(tree.pos);
  1.1999 +
  1.2000 +        if (tree.elems != null) {
  1.2001 +            Type elemtype = types.elemtype(tree.type);
  1.2002 +            loadIntConst(tree.elems.length());
  1.2003 +            Item arr = makeNewArray(tree.pos(), tree.type, 1);
  1.2004 +            int i = 0;
  1.2005 +            for (List<JCExpression> l = tree.elems; l.nonEmpty(); l = l.tail) {
  1.2006 +                arr.duplicate();
  1.2007 +                loadIntConst(i);
  1.2008 +                i++;
  1.2009 +                genExpr(l.head, elemtype).load();
  1.2010 +                items.makeIndexedItem(elemtype).store();
  1.2011 +            }
  1.2012 +            result = arr;
  1.2013 +        } else {
  1.2014 +            for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
  1.2015 +                genExpr(l.head, syms.intType).load();
  1.2016 +            }
  1.2017 +            result = makeNewArray(tree.pos(), tree.type, tree.dims.length());
  1.2018 +        }
  1.2019 +    }
  1.2020 +//where
  1.2021 +        /** Generate code to create an array with given element type and number
  1.2022 +         *  of dimensions.
  1.2023 +         */
  1.2024 +        Item makeNewArray(DiagnosticPosition pos, Type type, int ndims) {
  1.2025 +            Type elemtype = types.elemtype(type);
  1.2026 +            if (types.dimensions(type) > ClassFile.MAX_DIMENSIONS) {
  1.2027 +                log.error(pos, "limit.dimensions");
  1.2028 +                nerrs++;
  1.2029 +            }
  1.2030 +            int elemcode = Code.arraycode(elemtype);
  1.2031 +            if (elemcode == 0 || (elemcode == 1 && ndims == 1)) {
  1.2032 +                code.emitAnewarray(makeRef(pos, elemtype), type);
  1.2033 +            } else if (elemcode == 1) {
  1.2034 +                code.emitMultianewarray(ndims, makeRef(pos, type), type);
  1.2035 +            } else {
  1.2036 +                code.emitNewarray(elemcode, type);
  1.2037 +            }
  1.2038 +            return items.makeStackItem(type);
  1.2039 +        }
  1.2040 +
  1.2041 +    public void visitParens(JCParens tree) {
  1.2042 +        result = genExpr(tree.expr, tree.expr.type);
  1.2043 +    }
  1.2044 +
  1.2045 +    public void visitAssign(JCAssign tree) {
  1.2046 +        Item l = genExpr(tree.lhs, tree.lhs.type);
  1.2047 +        genExpr(tree.rhs, tree.lhs.type).load();
  1.2048 +        result = items.makeAssignItem(l);
  1.2049 +    }
  1.2050 +
  1.2051 +    public void visitAssignop(JCAssignOp tree) {
  1.2052 +        OperatorSymbol operator = (OperatorSymbol) tree.operator;
  1.2053 +        Item l;
  1.2054 +        if (operator.opcode == string_add) {
  1.2055 +            // Generate code to make a string buffer
  1.2056 +            makeStringBuffer(tree.pos());
  1.2057 +
  1.2058 +            // Generate code for first string, possibly save one
  1.2059 +            // copy under buffer
  1.2060 +            l = genExpr(tree.lhs, tree.lhs.type);
  1.2061 +            if (l.width() > 0) {
  1.2062 +                code.emitop0(dup_x1 + 3 * (l.width() - 1));
  1.2063 +            }
  1.2064 +
  1.2065 +            // Load first string and append to buffer.
  1.2066 +            l.load();
  1.2067 +            appendString(tree.lhs);
  1.2068 +
  1.2069 +            // Append all other strings to buffer.
  1.2070 +            appendStrings(tree.rhs);
  1.2071 +
  1.2072 +            // Convert buffer to string.
  1.2073 +            bufferToString(tree.pos());
  1.2074 +        } else {
  1.2075 +            // Generate code for first expression
  1.2076 +            l = genExpr(tree.lhs, tree.lhs.type);
  1.2077 +
  1.2078 +            // If we have an increment of -32768 to +32767 of a local
  1.2079 +            // int variable we can use an incr instruction instead of
  1.2080 +            // proceeding further.
  1.2081 +            if ((tree.hasTag(PLUS_ASG) || tree.hasTag(MINUS_ASG)) &&
  1.2082 +                l instanceof LocalItem &&
  1.2083 +                tree.lhs.type.getTag().isSubRangeOf(INT) &&
  1.2084 +                tree.rhs.type.getTag().isSubRangeOf(INT) &&
  1.2085 +                tree.rhs.type.constValue() != null) {
  1.2086 +                int ival = ((Number) tree.rhs.type.constValue()).intValue();
  1.2087 +                if (tree.hasTag(MINUS_ASG)) ival = -ival;
  1.2088 +                ((LocalItem)l).incr(ival);
  1.2089 +                result = l;
  1.2090 +                return;
  1.2091 +            }
  1.2092 +            // Otherwise, duplicate expression, load one copy
  1.2093 +            // and complete binary operation.
  1.2094 +            l.duplicate();
  1.2095 +            l.coerce(operator.type.getParameterTypes().head).load();
  1.2096 +            completeBinop(tree.lhs, tree.rhs, operator).coerce(tree.lhs.type);
  1.2097 +        }
  1.2098 +        result = items.makeAssignItem(l);
  1.2099 +    }
  1.2100 +
  1.2101 +    public void visitUnary(JCUnary tree) {
  1.2102 +        OperatorSymbol operator = (OperatorSymbol)tree.operator;
  1.2103 +        if (tree.hasTag(NOT)) {
  1.2104 +            CondItem od = genCond(tree.arg, false);
  1.2105 +            result = od.negate();
  1.2106 +        } else {
  1.2107 +            Item od = genExpr(tree.arg, operator.type.getParameterTypes().head);
  1.2108 +            switch (tree.getTag()) {
  1.2109 +            case POS:
  1.2110 +                result = od.load();
  1.2111 +                break;
  1.2112 +            case NEG:
  1.2113 +                result = od.load();
  1.2114 +                code.emitop0(operator.opcode);
  1.2115 +                break;
  1.2116 +            case COMPL:
  1.2117 +                result = od.load();
  1.2118 +                emitMinusOne(od.typecode);
  1.2119 +                code.emitop0(operator.opcode);
  1.2120 +                break;
  1.2121 +            case PREINC: case PREDEC:
  1.2122 +                od.duplicate();
  1.2123 +                if (od instanceof LocalItem &&
  1.2124 +                    (operator.opcode == iadd || operator.opcode == isub)) {
  1.2125 +                    ((LocalItem)od).incr(tree.hasTag(PREINC) ? 1 : -1);
  1.2126 +                    result = od;
  1.2127 +                } else {
  1.2128 +                    od.load();
  1.2129 +                    code.emitop0(one(od.typecode));
  1.2130 +                    code.emitop0(operator.opcode);
  1.2131 +                    // Perform narrowing primitive conversion if byte,
  1.2132 +                    // char, or short.  Fix for 4304655.
  1.2133 +                    if (od.typecode != INTcode &&
  1.2134 +                        Code.truncate(od.typecode) == INTcode)
  1.2135 +                      code.emitop0(int2byte + od.typecode - BYTEcode);
  1.2136 +                    result = items.makeAssignItem(od);
  1.2137 +                }
  1.2138 +                break;
  1.2139 +            case POSTINC: case POSTDEC:
  1.2140 +                od.duplicate();
  1.2141 +                if (od instanceof LocalItem &&
  1.2142 +                    (operator.opcode == iadd || operator.opcode == isub)) {
  1.2143 +                    Item res = od.load();
  1.2144 +                    ((LocalItem)od).incr(tree.hasTag(POSTINC) ? 1 : -1);
  1.2145 +                    result = res;
  1.2146 +                } else {
  1.2147 +                    Item res = od.load();
  1.2148 +                    od.stash(od.typecode);
  1.2149 +                    code.emitop0(one(od.typecode));
  1.2150 +                    code.emitop0(operator.opcode);
  1.2151 +                    // Perform narrowing primitive conversion if byte,
  1.2152 +                    // char, or short.  Fix for 4304655.
  1.2153 +                    if (od.typecode != INTcode &&
  1.2154 +                        Code.truncate(od.typecode) == INTcode)
  1.2155 +                      code.emitop0(int2byte + od.typecode - BYTEcode);
  1.2156 +                    od.store();
  1.2157 +                    result = res;
  1.2158 +                }
  1.2159 +                break;
  1.2160 +            case NULLCHK:
  1.2161 +                result = od.load();
  1.2162 +                code.emitop0(dup);
  1.2163 +                genNullCheck(tree.pos());
  1.2164 +                break;
  1.2165 +            default:
  1.2166 +                Assert.error();
  1.2167 +            }
  1.2168 +        }
  1.2169 +    }
  1.2170 +
  1.2171 +    /** Generate a null check from the object value at stack top. */
  1.2172 +    private void genNullCheck(DiagnosticPosition pos) {
  1.2173 +        callMethod(pos, syms.objectType, names.getClass,
  1.2174 +                   List.<Type>nil(), false);
  1.2175 +        code.emitop0(pop);
  1.2176 +    }
  1.2177 +
  1.2178 +    public void visitBinary(JCBinary tree) {
  1.2179 +        OperatorSymbol operator = (OperatorSymbol)tree.operator;
  1.2180 +        if (operator.opcode == string_add) {
  1.2181 +            // Create a string buffer.
  1.2182 +            makeStringBuffer(tree.pos());
  1.2183 +            // Append all strings to buffer.
  1.2184 +            appendStrings(tree);
  1.2185 +            // Convert buffer to string.
  1.2186 +            bufferToString(tree.pos());
  1.2187 +            result = items.makeStackItem(syms.stringType);
  1.2188 +        } else if (tree.hasTag(AND)) {
  1.2189 +            CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
  1.2190 +            if (!lcond.isFalse()) {
  1.2191 +                Chain falseJumps = lcond.jumpFalse();
  1.2192 +                code.resolve(lcond.trueJumps);
  1.2193 +                CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
  1.2194 +                result = items.
  1.2195 +                    makeCondItem(rcond.opcode,
  1.2196 +                                 rcond.trueJumps,
  1.2197 +                                 Code.mergeChains(falseJumps,
  1.2198 +                                                  rcond.falseJumps));
  1.2199 +            } else {
  1.2200 +                result = lcond;
  1.2201 +            }
  1.2202 +        } else if (tree.hasTag(OR)) {
  1.2203 +            CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
  1.2204 +            if (!lcond.isTrue()) {
  1.2205 +                Chain trueJumps = lcond.jumpTrue();
  1.2206 +                code.resolve(lcond.falseJumps);
  1.2207 +                CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
  1.2208 +                result = items.
  1.2209 +                    makeCondItem(rcond.opcode,
  1.2210 +                                 Code.mergeChains(trueJumps, rcond.trueJumps),
  1.2211 +                                 rcond.falseJumps);
  1.2212 +            } else {
  1.2213 +                result = lcond;
  1.2214 +            }
  1.2215 +        } else {
  1.2216 +            Item od = genExpr(tree.lhs, operator.type.getParameterTypes().head);
  1.2217 +            od.load();
  1.2218 +            result = completeBinop(tree.lhs, tree.rhs, operator);
  1.2219 +        }
  1.2220 +    }
  1.2221 +//where
  1.2222 +        /** Make a new string buffer.
  1.2223 +         */
  1.2224 +        void makeStringBuffer(DiagnosticPosition pos) {
  1.2225 +            code.emitop2(new_, makeRef(pos, stringBufferType));
  1.2226 +            code.emitop0(dup);
  1.2227 +            callMethod(
  1.2228 +                pos, stringBufferType, names.init, List.<Type>nil(), false);
  1.2229 +        }
  1.2230 +
  1.2231 +        /** Append value (on tos) to string buffer (on tos - 1).
  1.2232 +         */
  1.2233 +        void appendString(JCTree tree) {
  1.2234 +            Type t = tree.type.baseType();
  1.2235 +            if (!t.isPrimitive() && t.tsym != syms.stringType.tsym) {
  1.2236 +                t = syms.objectType;
  1.2237 +            }
  1.2238 +            items.makeMemberItem(getStringBufferAppend(tree, t), false).invoke();
  1.2239 +        }
  1.2240 +        Symbol getStringBufferAppend(JCTree tree, Type t) {
  1.2241 +            Assert.checkNull(t.constValue());
  1.2242 +            Symbol method = stringBufferAppend.get(t);
  1.2243 +            if (method == null) {
  1.2244 +                method = rs.resolveInternalMethod(tree.pos(),
  1.2245 +                                                  attrEnv,
  1.2246 +                                                  stringBufferType,
  1.2247 +                                                  names.append,
  1.2248 +                                                  List.of(t),
  1.2249 +                                                  null);
  1.2250 +                stringBufferAppend.put(t, method);
  1.2251 +            }
  1.2252 +            return method;
  1.2253 +        }
  1.2254 +
  1.2255 +        /** Add all strings in tree to string buffer.
  1.2256 +         */
  1.2257 +        void appendStrings(JCTree tree) {
  1.2258 +            tree = TreeInfo.skipParens(tree);
  1.2259 +            if (tree.hasTag(PLUS) && tree.type.constValue() == null) {
  1.2260 +                JCBinary op = (JCBinary) tree;
  1.2261 +                if (op.operator.kind == MTH &&
  1.2262 +                    ((OperatorSymbol) op.operator).opcode == string_add) {
  1.2263 +                    appendStrings(op.lhs);
  1.2264 +                    appendStrings(op.rhs);
  1.2265 +                    return;
  1.2266 +                }
  1.2267 +            }
  1.2268 +            genExpr(tree, tree.type).load();
  1.2269 +            appendString(tree);
  1.2270 +        }
  1.2271 +
  1.2272 +        /** Convert string buffer on tos to string.
  1.2273 +         */
  1.2274 +        void bufferToString(DiagnosticPosition pos) {
  1.2275 +            callMethod(
  1.2276 +                pos,
  1.2277 +                stringBufferType,
  1.2278 +                names.toString,
  1.2279 +                List.<Type>nil(),
  1.2280 +                false);
  1.2281 +        }
  1.2282 +
  1.2283 +        /** Complete generating code for operation, with left operand
  1.2284 +         *  already on stack.
  1.2285 +         *  @param lhs       The tree representing the left operand.
  1.2286 +         *  @param rhs       The tree representing the right operand.
  1.2287 +         *  @param operator  The operator symbol.
  1.2288 +         */
  1.2289 +        Item completeBinop(JCTree lhs, JCTree rhs, OperatorSymbol operator) {
  1.2290 +            MethodType optype = (MethodType)operator.type;
  1.2291 +            int opcode = operator.opcode;
  1.2292 +            if (opcode >= if_icmpeq && opcode <= if_icmple &&
  1.2293 +                rhs.type.constValue() instanceof Number &&
  1.2294 +                ((Number) rhs.type.constValue()).intValue() == 0) {
  1.2295 +                opcode = opcode + (ifeq - if_icmpeq);
  1.2296 +            } else if (opcode >= if_acmpeq && opcode <= if_acmpne &&
  1.2297 +                       TreeInfo.isNull(rhs)) {
  1.2298 +                opcode = opcode + (if_acmp_null - if_acmpeq);
  1.2299 +            } else {
  1.2300 +                // The expected type of the right operand is
  1.2301 +                // the second parameter type of the operator, except for
  1.2302 +                // shifts with long shiftcount, where we convert the opcode
  1.2303 +                // to a short shift and the expected type to int.
  1.2304 +                Type rtype = operator.erasure(types).getParameterTypes().tail.head;
  1.2305 +                if (opcode >= ishll && opcode <= lushrl) {
  1.2306 +                    opcode = opcode + (ishl - ishll);
  1.2307 +                    rtype = syms.intType;
  1.2308 +                }
  1.2309 +                // Generate code for right operand and load.
  1.2310 +                genExpr(rhs, rtype).load();
  1.2311 +                // If there are two consecutive opcode instructions,
  1.2312 +                // emit the first now.
  1.2313 +                if (opcode >= (1 << preShift)) {
  1.2314 +                    code.emitop0(opcode >> preShift);
  1.2315 +                    opcode = opcode & 0xFF;
  1.2316 +                }
  1.2317 +            }
  1.2318 +            if (opcode >= ifeq && opcode <= if_acmpne ||
  1.2319 +                opcode == if_acmp_null || opcode == if_acmp_nonnull) {
  1.2320 +                return items.makeCondItem(opcode);
  1.2321 +            } else {
  1.2322 +                code.emitop0(opcode);
  1.2323 +                return items.makeStackItem(optype.restype);
  1.2324 +            }
  1.2325 +        }
  1.2326 +
  1.2327 +    public void visitTypeCast(JCTypeCast tree) {
  1.2328 +        setTypeAnnotationPositions(tree.pos);
  1.2329 +        result = genExpr(tree.expr, tree.clazz.type).load();
  1.2330 +        // Additional code is only needed if we cast to a reference type
  1.2331 +        // which is not statically a supertype of the expression's type.
  1.2332 +        // For basic types, the coerce(...) in genExpr(...) will do
  1.2333 +        // the conversion.
  1.2334 +        if (!tree.clazz.type.isPrimitive() &&
  1.2335 +            types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) {
  1.2336 +            code.emitop2(checkcast, makeRef(tree.pos(), tree.clazz.type));
  1.2337 +        }
  1.2338 +    }
  1.2339 +
  1.2340 +    public void visitWildcard(JCWildcard tree) {
  1.2341 +        throw new AssertionError(this.getClass().getName());
  1.2342 +    }
  1.2343 +
  1.2344 +    public void visitTypeTest(JCInstanceOf tree) {
  1.2345 +        setTypeAnnotationPositions(tree.pos);
  1.2346 +        genExpr(tree.expr, tree.expr.type).load();
  1.2347 +        code.emitop2(instanceof_, makeRef(tree.pos(), tree.clazz.type));
  1.2348 +        result = items.makeStackItem(syms.booleanType);
  1.2349 +    }
  1.2350 +
  1.2351 +    public void visitIndexed(JCArrayAccess tree) {
  1.2352 +        genExpr(tree.indexed, tree.indexed.type).load();
  1.2353 +        genExpr(tree.index, syms.intType).load();
  1.2354 +        result = items.makeIndexedItem(tree.type);
  1.2355 +    }
  1.2356 +
  1.2357 +    public void visitIdent(JCIdent tree) {
  1.2358 +        Symbol sym = tree.sym;
  1.2359 +        if (tree.name == names._this || tree.name == names._super) {
  1.2360 +            Item res = tree.name == names._this
  1.2361 +                ? items.makeThisItem()
  1.2362 +                : items.makeSuperItem();
  1.2363 +            if (sym.kind == MTH) {
  1.2364 +                // Generate code to address the constructor.
  1.2365 +                res.load();
  1.2366 +                res = items.makeMemberItem(sym, true);
  1.2367 +            }
  1.2368 +            result = res;
  1.2369 +        } else if (sym.kind == VAR && sym.owner.kind == MTH) {
  1.2370 +            result = items.makeLocalItem((VarSymbol)sym);
  1.2371 +        } else if (isInvokeDynamic(sym)) {
  1.2372 +            result = items.makeDynamicItem(sym);
  1.2373 +        } else if ((sym.flags() & STATIC) != 0) {
  1.2374 +            if (!isAccessSuper(env.enclMethod))
  1.2375 +                sym = binaryQualifier(sym, env.enclClass.type);
  1.2376 +            result = items.makeStaticItem(sym);
  1.2377 +        } else {
  1.2378 +            items.makeThisItem().load();
  1.2379 +            sym = binaryQualifier(sym, env.enclClass.type);
  1.2380 +            result = items.makeMemberItem(sym, (sym.flags() & PRIVATE) != 0);
  1.2381 +        }
  1.2382 +    }
  1.2383 +
  1.2384 +    public void visitSelect(JCFieldAccess tree) {
  1.2385 +        Symbol sym = tree.sym;
  1.2386 +
  1.2387 +        if (tree.name == names._class) {
  1.2388 +            Assert.check(target.hasClassLiterals());
  1.2389 +            code.emitLdc(makeRef(tree.pos(), tree.selected.type));
  1.2390 +            result = items.makeStackItem(pt);
  1.2391 +            return;
  1.2392 +       }
  1.2393 +
  1.2394 +        Symbol ssym = TreeInfo.symbol(tree.selected);
  1.2395 +
  1.2396 +        // Are we selecting via super?
  1.2397 +        boolean selectSuper =
  1.2398 +            ssym != null && (ssym.kind == TYP || ssym.name == names._super);
  1.2399 +
  1.2400 +        // Are we accessing a member of the superclass in an access method
  1.2401 +        // resulting from a qualified super?
  1.2402 +        boolean accessSuper = isAccessSuper(env.enclMethod);
  1.2403 +
  1.2404 +        Item base = (selectSuper)
  1.2405 +            ? items.makeSuperItem()
  1.2406 +            : genExpr(tree.selected, tree.selected.type);
  1.2407 +
  1.2408 +        if (sym.kind == VAR && ((VarSymbol) sym).getConstValue() != null) {
  1.2409 +            // We are seeing a variable that is constant but its selecting
  1.2410 +            // expression is not.
  1.2411 +            if ((sym.flags() & STATIC) != 0) {
  1.2412 +                if (!selectSuper && (ssym == null || ssym.kind != TYP))
  1.2413 +                    base = base.load();
  1.2414 +                base.drop();
  1.2415 +            } else {
  1.2416 +                base.load();
  1.2417 +                genNullCheck(tree.selected.pos());
  1.2418 +            }
  1.2419 +            result = items.
  1.2420 +                makeImmediateItem(sym.type, ((VarSymbol) sym).getConstValue());
  1.2421 +        } else {
  1.2422 +            if (isInvokeDynamic(sym)) {
  1.2423 +                result = items.makeDynamicItem(sym);
  1.2424 +                return;
  1.2425 +            } else {
  1.2426 +                sym = binaryQualifier(sym, tree.selected.type);
  1.2427 +            }
  1.2428 +            if ((sym.flags() & STATIC) != 0) {
  1.2429 +                if (!selectSuper && (ssym == null || ssym.kind != TYP))
  1.2430 +                    base = base.load();
  1.2431 +                base.drop();
  1.2432 +                result = items.makeStaticItem(sym);
  1.2433 +            } else {
  1.2434 +                base.load();
  1.2435 +                if (sym == syms.lengthVar) {
  1.2436 +                    code.emitop0(arraylength);
  1.2437 +                    result = items.makeStackItem(syms.intType);
  1.2438 +                } else {
  1.2439 +                    result = items.
  1.2440 +                        makeMemberItem(sym,
  1.2441 +                                       (sym.flags() & PRIVATE) != 0 ||
  1.2442 +                                       selectSuper || accessSuper);
  1.2443 +                }
  1.2444 +            }
  1.2445 +        }
  1.2446 +    }
  1.2447 +
  1.2448 +    public boolean isInvokeDynamic(Symbol sym) {
  1.2449 +        return sym.kind == MTH && ((MethodSymbol)sym).isDynamic();
  1.2450 +    }
  1.2451 +
  1.2452 +    public void visitLiteral(JCLiteral tree) {
  1.2453 +        if (tree.type.hasTag(BOT)) {
  1.2454 +            code.emitop0(aconst_null);
  1.2455 +            if (types.dimensions(pt) > 1) {
  1.2456 +                code.emitop2(checkcast, makeRef(tree.pos(), pt));
  1.2457 +                result = items.makeStackItem(pt);
  1.2458 +            } else {
  1.2459 +                result = items.makeStackItem(tree.type);
  1.2460 +            }
  1.2461 +        }
  1.2462 +        else
  1.2463 +            result = items.makeImmediateItem(tree.type, tree.value);
  1.2464 +    }
  1.2465 +
  1.2466 +    public void visitLetExpr(LetExpr tree) {
  1.2467 +        int limit = code.nextreg;
  1.2468 +        genStats(tree.defs, env);
  1.2469 +        result = genExpr(tree.expr, tree.expr.type).load();
  1.2470 +        code.endScopes(limit);
  1.2471 +    }
  1.2472 +
  1.2473 +    private void generateReferencesToPrunedTree(ClassSymbol classSymbol, Pool pool) {
  1.2474 +        List<JCTree> prunedInfo = lower.prunedTree.get(classSymbol);
  1.2475 +        if (prunedInfo != null) {
  1.2476 +            for (JCTree prunedTree: prunedInfo) {
  1.2477 +                prunedTree.accept(classReferenceVisitor);
  1.2478 +            }
  1.2479 +        }
  1.2480 +    }
  1.2481 +
  1.2482 +/* ************************************************************************
  1.2483 + * main method
  1.2484 + *************************************************************************/
  1.2485 +
  1.2486 +    /** Generate code for a class definition.
  1.2487 +     *  @param env   The attribution environment that belongs to the
  1.2488 +     *               outermost class containing this class definition.
  1.2489 +     *               We need this for resolving some additional symbols.
  1.2490 +     *  @param cdef  The tree representing the class definition.
  1.2491 +     *  @return      True if code is generated with no errors.
  1.2492 +     */
  1.2493 +    public boolean genClass(Env<AttrContext> env, JCClassDecl cdef) {
  1.2494 +        try {
  1.2495 +            attrEnv = env;
  1.2496 +            ClassSymbol c = cdef.sym;
  1.2497 +            this.toplevel = env.toplevel;
  1.2498 +            this.endPosTable = toplevel.endPositions;
  1.2499 +            // If this is a class definition requiring Miranda methods,
  1.2500 +            // add them.
  1.2501 +            if (generateIproxies &&
  1.2502 +                (c.flags() & (INTERFACE|ABSTRACT)) == ABSTRACT
  1.2503 +                && !allowGenerics // no Miranda methods available with generics
  1.2504 +                )
  1.2505 +                implementInterfaceMethods(c);
  1.2506 +            cdef.defs = normalizeDefs(cdef.defs, c);
  1.2507 +            c.pool = pool;
  1.2508 +            pool.reset();
  1.2509 +            generateReferencesToPrunedTree(c, pool);
  1.2510 +            Env<GenContext> localEnv =
  1.2511 +                new Env<GenContext>(cdef, new GenContext());
  1.2512 +            localEnv.toplevel = env.toplevel;
  1.2513 +            localEnv.enclClass = cdef;
  1.2514 +
  1.2515 +            /*  We must not analyze synthetic methods
  1.2516 +             */
  1.2517 +            if (varDebugInfo && (cdef.sym.flags() & SYNTHETIC) == 0) {
  1.2518 +                try {
  1.2519 +                    LVTAssignAnalyzer lvtAssignAnalyzer = LVTAssignAnalyzer.make(
  1.2520 +                            lvtRanges, syms, names);
  1.2521 +                    lvtAssignAnalyzer.analyzeTree(localEnv);
  1.2522 +                } catch (Throwable e) {
  1.2523 +                    throw e;
  1.2524 +                }
  1.2525 +            }
  1.2526 +
  1.2527 +            for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
  1.2528 +                genDef(l.head, localEnv);
  1.2529 +            }
  1.2530 +            if (pool.numEntries() > Pool.MAX_ENTRIES) {
  1.2531 +                log.error(cdef.pos(), "limit.pool");
  1.2532 +                nerrs++;
  1.2533 +            }
  1.2534 +            if (nerrs != 0) {
  1.2535 +                // if errors, discard code
  1.2536 +                for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
  1.2537 +                    if (l.head.hasTag(METHODDEF))
  1.2538 +                        ((JCMethodDecl) l.head).sym.code = null;
  1.2539 +                }
  1.2540 +            }
  1.2541 +            cdef.defs = List.nil(); // discard trees
  1.2542 +            return nerrs == 0;
  1.2543 +        } finally {
  1.2544 +            // note: this method does NOT support recursion.
  1.2545 +            attrEnv = null;
  1.2546 +            this.env = null;
  1.2547 +            toplevel = null;
  1.2548 +            endPosTable = null;
  1.2549 +            nerrs = 0;
  1.2550 +        }
  1.2551 +    }
  1.2552 +
  1.2553 +/* ************************************************************************
  1.2554 + * Auxiliary classes
  1.2555 + *************************************************************************/
  1.2556 +
  1.2557 +    /** An abstract class for finalizer generation.
  1.2558 +     */
  1.2559 +    abstract class GenFinalizer {
  1.2560 +        /** Generate code to clean up when unwinding. */
  1.2561 +        abstract void gen();
  1.2562 +
  1.2563 +        /** Generate code to clean up at last. */
  1.2564 +        abstract void genLast();
  1.2565 +
  1.2566 +        /** Does this finalizer have some nontrivial cleanup to perform? */
  1.2567 +        boolean hasFinalizer() { return true; }
  1.2568 +    }
  1.2569 +
  1.2570 +    /** code generation contexts,
  1.2571 +     *  to be used as type parameter for environments.
  1.2572 +     */
  1.2573 +    static class GenContext {
  1.2574 +
  1.2575 +        /** A chain for all unresolved jumps that exit the current environment.
  1.2576 +         */
  1.2577 +        Chain exit = null;
  1.2578 +
  1.2579 +        /** A chain for all unresolved jumps that continue in the
  1.2580 +         *  current environment.
  1.2581 +         */
  1.2582 +        Chain cont = null;
  1.2583 +
  1.2584 +        /** A closure that generates the finalizer of the current environment.
  1.2585 +         *  Only set for Synchronized and Try contexts.
  1.2586 +         */
  1.2587 +        GenFinalizer finalize = null;
  1.2588 +
  1.2589 +        /** Is this a switch statement?  If so, allocate registers
  1.2590 +         * even when the variable declaration is unreachable.
  1.2591 +         */
  1.2592 +        boolean isSwitch = false;
  1.2593 +
  1.2594 +        /** A list buffer containing all gaps in the finalizer range,
  1.2595 +         *  where a catch all exception should not apply.
  1.2596 +         */
  1.2597 +        ListBuffer<Integer> gaps = null;
  1.2598 +
  1.2599 +        /** Add given chain to exit chain.
  1.2600 +         */
  1.2601 +        void addExit(Chain c)  {
  1.2602 +            exit = Code.mergeChains(c, exit);
  1.2603 +        }
  1.2604 +
  1.2605 +        /** Add given chain to cont chain.
  1.2606 +         */
  1.2607 +        void addCont(Chain c) {
  1.2608 +            cont = Code.mergeChains(c, cont);
  1.2609 +        }
  1.2610 +    }
  1.2611 +
  1.2612 +    static class LVTAssignAnalyzer
  1.2613 +        extends Flow.AbstractAssignAnalyzer<LVTAssignAnalyzer.LVTAssignPendingExit> {
  1.2614 +
  1.2615 +        final LVTBits lvtInits;
  1.2616 +        final LVTRanges lvtRanges;
  1.2617 +
  1.2618 +        /*  This class is anchored to a context dependent tree. The tree can
  1.2619 +         *  vary inside the same instruction for example in the switch instruction
  1.2620 +         *  the same FlowBits instance can be anchored to the whole tree, or
  1.2621 +         *  to a given case. The aim is to always anchor the bits to the tree
  1.2622 +         *  capable of closing a DA range.
  1.2623 +         */
  1.2624 +        static class LVTBits extends Bits {
  1.2625 +
  1.2626 +            enum BitsOpKind {
  1.2627 +                INIT,
  1.2628 +                CLEAR,
  1.2629 +                INCL_BIT,
  1.2630 +                EXCL_BIT,
  1.2631 +                ASSIGN,
  1.2632 +                AND_SET,
  1.2633 +                OR_SET,
  1.2634 +                DIFF_SET,
  1.2635 +                XOR_SET,
  1.2636 +                INCL_RANGE,
  1.2637 +                EXCL_RANGE,
  1.2638 +            }
  1.2639 +
  1.2640 +            JCTree currentTree;
  1.2641 +            LVTAssignAnalyzer analyzer;
  1.2642 +            private int[] oldBits = null;
  1.2643 +            BitsState stateBeforeOp;
  1.2644 +
  1.2645 +            LVTBits() {
  1.2646 +                super(false);
  1.2647 +            }
  1.2648 +
  1.2649 +            LVTBits(int[] bits, BitsState initState) {
  1.2650 +                super(bits, initState);
  1.2651 +            }
  1.2652 +
  1.2653 +            @Override
  1.2654 +            public void clear() {
  1.2655 +                generalOp(null, -1, BitsOpKind.CLEAR);
  1.2656 +            }
  1.2657 +
  1.2658 +            @Override
  1.2659 +            protected void internalReset() {
  1.2660 +                super.internalReset();
  1.2661 +                oldBits = null;
  1.2662 +            }
  1.2663 +
  1.2664 +            @Override
  1.2665 +            public Bits assign(Bits someBits) {
  1.2666 +                // bits can be null
  1.2667 +                oldBits = bits;
  1.2668 +                stateBeforeOp = currentState;
  1.2669 +                super.assign(someBits);
  1.2670 +                changed();
  1.2671 +                return this;
  1.2672 +            }
  1.2673 +
  1.2674 +            @Override
  1.2675 +            public void excludeFrom(int start) {
  1.2676 +                generalOp(null, start, BitsOpKind.EXCL_RANGE);
  1.2677 +            }
  1.2678 +
  1.2679 +            @Override
  1.2680 +            public void excl(int x) {
  1.2681 +                Assert.check(x >= 0);
  1.2682 +                generalOp(null, x, BitsOpKind.EXCL_BIT);
  1.2683 +            }
  1.2684 +
  1.2685 +            @Override
  1.2686 +            public Bits andSet(Bits xs) {
  1.2687 +               return generalOp(xs, -1, BitsOpKind.AND_SET);
  1.2688 +            }
  1.2689 +
  1.2690 +            @Override
  1.2691 +            public Bits orSet(Bits xs) {
  1.2692 +                return generalOp(xs, -1, BitsOpKind.OR_SET);
  1.2693 +            }
  1.2694 +
  1.2695 +            @Override
  1.2696 +            public Bits diffSet(Bits xs) {
  1.2697 +                return generalOp(xs, -1, BitsOpKind.DIFF_SET);
  1.2698 +            }
  1.2699 +
  1.2700 +            @Override
  1.2701 +            public Bits xorSet(Bits xs) {
  1.2702 +                return generalOp(xs, -1, BitsOpKind.XOR_SET);
  1.2703 +            }
  1.2704 +
  1.2705 +            private Bits generalOp(Bits xs, int i, BitsOpKind opKind) {
  1.2706 +                Assert.check(currentState != BitsState.UNKNOWN);
  1.2707 +                oldBits = dupBits();
  1.2708 +                stateBeforeOp = currentState;
  1.2709 +                switch (opKind) {
  1.2710 +                    case AND_SET:
  1.2711 +                        super.andSet(xs);
  1.2712 +                        break;
  1.2713 +                    case OR_SET:
  1.2714 +                        super.orSet(xs);
  1.2715 +                        break;
  1.2716 +                    case XOR_SET:
  1.2717 +                        super.xorSet(xs);
  1.2718 +                        break;
  1.2719 +                    case DIFF_SET:
  1.2720 +                        super.diffSet(xs);
  1.2721 +                        break;
  1.2722 +                    case CLEAR:
  1.2723 +                        super.clear();
  1.2724 +                        break;
  1.2725 +                    case EXCL_BIT:
  1.2726 +                        super.excl(i);
  1.2727 +                        break;
  1.2728 +                    case EXCL_RANGE:
  1.2729 +                        super.excludeFrom(i);
  1.2730 +                        break;
  1.2731 +                }
  1.2732 +                changed();
  1.2733 +                return this;
  1.2734 +            }
  1.2735 +
  1.2736 +            /*  The tree we need to anchor the bits instance to.
  1.2737 +             */
  1.2738 +            LVTBits at(JCTree tree) {
  1.2739 +                this.currentTree = tree;
  1.2740 +                return this;
  1.2741 +            }
  1.2742 +
  1.2743 +            /*  If the instance should be changed but the tree is not a closing
  1.2744 +             *  tree then a reset is needed or the former tree can mistakingly be
  1.2745 +             *  used.
  1.2746 +             */
  1.2747 +            LVTBits resetTree() {
  1.2748 +                this.currentTree = null;
  1.2749 +                return this;
  1.2750 +            }
  1.2751 +
  1.2752 +            /** This method will be called after any operation that causes a change to
  1.2753 +             *  the bits. Subclasses can thus override it in order to extract information
  1.2754 +             *  from the changes produced to the bits by the given operation.
  1.2755 +             */
  1.2756 +            public void changed() {
  1.2757 +                if (currentTree != null &&
  1.2758 +                        stateBeforeOp != BitsState.UNKNOWN &&
  1.2759 +                        trackTree(currentTree)) {
  1.2760 +                    List<VarSymbol> locals =
  1.2761 +                            analyzer.lvtRanges
  1.2762 +                            .getVars(analyzer.currentMethod, currentTree);
  1.2763 +                    locals = locals != null ?
  1.2764 +                            locals : List.<VarSymbol>nil();
  1.2765 +                    for (JCVariableDecl vardecl : analyzer.vardecls) {
  1.2766 +                        //once the first is null, the rest will be so.
  1.2767 +                        if (vardecl == null) {
  1.2768 +                            break;
  1.2769 +                        }
  1.2770 +                        if (trackVar(vardecl.sym) && bitChanged(vardecl.sym.adr)) {
  1.2771 +                            locals = locals.prepend(vardecl.sym);
  1.2772 +                        }
  1.2773 +                    }
  1.2774 +                    if (!locals.isEmpty()) {
  1.2775 +                        analyzer.lvtRanges.setEntry(analyzer.currentMethod,
  1.2776 +                                currentTree, locals);
  1.2777 +                    }
  1.2778 +                }
  1.2779 +            }
  1.2780 +
  1.2781 +            boolean bitChanged(int x) {
  1.2782 +                boolean isMemberOfBits = isMember(x);
  1.2783 +                int[] tmp = bits;
  1.2784 +                bits = oldBits;
  1.2785 +                boolean isMemberOfOldBits = isMember(x);
  1.2786 +                bits = tmp;
  1.2787 +                return (!isMemberOfBits && isMemberOfOldBits);
  1.2788 +            }
  1.2789 +
  1.2790 +            boolean trackVar(VarSymbol var) {
  1.2791 +                return (var.owner.kind == MTH &&
  1.2792 +                        (var.flags() & (PARAMETER | HASINIT)) == 0 &&
  1.2793 +                        analyzer.trackable(var));
  1.2794 +            }
  1.2795 +
  1.2796 +            boolean trackTree(JCTree tree) {
  1.2797 +                switch (tree.getTag()) {
  1.2798 +                    // of course a method closes the alive range of a local variable.
  1.2799 +                    case METHODDEF:
  1.2800 +                    // for while loops we want only the body
  1.2801 +                    case WHILELOOP:
  1.2802 +                        return false;
  1.2803 +                }
  1.2804 +                return true;
  1.2805 +            }
  1.2806 +
  1.2807 +        }
  1.2808 +
  1.2809 +        public class LVTAssignPendingExit extends Flow.AssignAnalyzer.AssignPendingExit {
  1.2810 +
  1.2811 +            LVTAssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
  1.2812 +                super(tree, inits, uninits);
  1.2813 +            }
  1.2814 +
  1.2815 +            @Override
  1.2816 +            public void resolveJump(JCTree tree) {
  1.2817 +                lvtInits.at(tree);
  1.2818 +                super.resolveJump(tree);
  1.2819 +            }
  1.2820 +        }
  1.2821 +
  1.2822 +        private LVTAssignAnalyzer(LVTRanges lvtRanges, Symtab syms, Names names) {
  1.2823 +            super(new LVTBits(), syms, names, false);
  1.2824 +            lvtInits = (LVTBits)inits;
  1.2825 +            this.lvtRanges = lvtRanges;
  1.2826 +        }
  1.2827 +
  1.2828 +        public static LVTAssignAnalyzer make(LVTRanges lvtRanges, Symtab syms, Names names) {
  1.2829 +            LVTAssignAnalyzer result = new LVTAssignAnalyzer(lvtRanges, syms, names);
  1.2830 +            result.lvtInits.analyzer = result;
  1.2831 +            return result;
  1.2832 +        }
  1.2833 +
  1.2834 +        @Override
  1.2835 +        protected void markDead(JCTree tree) {
  1.2836 +            lvtInits.at(tree).inclRange(returnadr, nextadr);
  1.2837 +            super.markDead(tree);
  1.2838 +        }
  1.2839 +
  1.2840 +        @Override
  1.2841 +        protected void merge(JCTree tree) {
  1.2842 +            lvtInits.at(tree);
  1.2843 +            super.merge(tree);
  1.2844 +        }
  1.2845 +
  1.2846 +        boolean isSyntheticOrMandated(Symbol sym) {
  1.2847 +            return (sym.flags() & (SYNTHETIC | MANDATED)) != 0;
  1.2848 +        }
  1.2849 +
  1.2850 +        @Override
  1.2851 +        protected boolean trackable(VarSymbol sym) {
  1.2852 +            if (isSyntheticOrMandated(sym)) {
  1.2853 +                //fast check to avoid tracking synthetic or mandated variables
  1.2854 +                return false;
  1.2855 +            }
  1.2856 +            return super.trackable(sym);
  1.2857 +        }
  1.2858 +
  1.2859 +        @Override
  1.2860 +        protected void initParam(JCVariableDecl def) {
  1.2861 +            if (!isSyntheticOrMandated(def.sym)) {
  1.2862 +                super.initParam(def);
  1.2863 +            }
  1.2864 +        }
  1.2865 +
  1.2866 +        @Override
  1.2867 +        protected void assignToInits(JCTree tree, Bits bits) {
  1.2868 +            lvtInits.at(tree);
  1.2869 +            lvtInits.assign(bits);
  1.2870 +        }
  1.2871 +
  1.2872 +        @Override
  1.2873 +        protected void andSetInits(JCTree tree, Bits bits) {
  1.2874 +            lvtInits.at(tree);
  1.2875 +            lvtInits.andSet(bits);
  1.2876 +        }
  1.2877 +
  1.2878 +        @Override
  1.2879 +        protected void orSetInits(JCTree tree, Bits bits) {
  1.2880 +            lvtInits.at(tree);
  1.2881 +            lvtInits.orSet(bits);
  1.2882 +        }
  1.2883 +
  1.2884 +        @Override
  1.2885 +        protected void exclVarFromInits(JCTree tree, int adr) {
  1.2886 +            lvtInits.at(tree);
  1.2887 +            lvtInits.excl(adr);
  1.2888 +        }
  1.2889 +
  1.2890 +        @Override
  1.2891 +        protected LVTAssignPendingExit createNewPendingExit(JCTree tree, Bits inits, Bits uninits) {
  1.2892 +            return new LVTAssignPendingExit(tree, inits, uninits);
  1.2893 +        }
  1.2894 +
  1.2895 +        MethodSymbol currentMethod;
  1.2896 +
  1.2897 +        @Override
  1.2898 +        public void visitMethodDef(JCMethodDecl tree) {
  1.2899 +            if ((tree.sym.flags() & (SYNTHETIC | GENERATEDCONSTR)) != 0
  1.2900 +                    && (tree.sym.flags() & LAMBDA_METHOD) == 0) {
  1.2901 +                return;
  1.2902 +            }
  1.2903 +            if (tree.name.equals(names.clinit)) {
  1.2904 +                return;
  1.2905 +            }
  1.2906 +            boolean enumClass = (tree.sym.owner.flags() & ENUM) != 0;
  1.2907 +            if (enumClass &&
  1.2908 +                    (tree.name.equals(names.valueOf) ||
  1.2909 +                    tree.name.equals(names.values) ||
  1.2910 +                    tree.name.equals(names.init))) {
  1.2911 +                return;
  1.2912 +            }
  1.2913 +            currentMethod = tree.sym;
  1.2914 +
  1.2915 +            super.visitMethodDef(tree);
  1.2916 +        }
  1.2917 +
  1.2918 +    }
  1.2919 +
  1.2920 +}

mercurial