src/share/classes/com/sun/tools/javac/jvm/ClassReader.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/ClassReader.java	Wed Apr 27 01:34:52 2016 +0800
     1.3 @@ -0,0 +1,2963 @@
     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.io.*;
    1.32 +import java.net.URI;
    1.33 +import java.net.URISyntaxException;
    1.34 +import java.nio.CharBuffer;
    1.35 +import java.util.Arrays;
    1.36 +import java.util.EnumSet;
    1.37 +import java.util.HashMap;
    1.38 +import java.util.HashSet;
    1.39 +import java.util.Map;
    1.40 +import java.util.Set;
    1.41 +import javax.lang.model.SourceVersion;
    1.42 +import javax.tools.JavaFileObject;
    1.43 +import javax.tools.JavaFileManager;
    1.44 +import javax.tools.JavaFileManager.Location;
    1.45 +import javax.tools.StandardJavaFileManager;
    1.46 +
    1.47 +import static javax.tools.StandardLocation.*;
    1.48 +
    1.49 +import com.sun.tools.javac.comp.Annotate;
    1.50 +import com.sun.tools.javac.code.*;
    1.51 +import com.sun.tools.javac.code.Lint.LintCategory;
    1.52 +import com.sun.tools.javac.code.Type.*;
    1.53 +import com.sun.tools.javac.code.Symbol.*;
    1.54 +import com.sun.tools.javac.code.Symtab;
    1.55 +import com.sun.tools.javac.file.BaseFileObject;
    1.56 +import com.sun.tools.javac.util.*;
    1.57 +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    1.58 +
    1.59 +import static com.sun.tools.javac.code.Flags.*;
    1.60 +import static com.sun.tools.javac.code.Kinds.*;
    1.61 +import static com.sun.tools.javac.code.TypeTag.CLASS;
    1.62 +import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
    1.63 +import static com.sun.tools.javac.jvm.ClassFile.*;
    1.64 +import static com.sun.tools.javac.jvm.ClassFile.Version.*;
    1.65 +
    1.66 +import static com.sun.tools.javac.main.Option.*;
    1.67 +
    1.68 +/** This class provides operations to read a classfile into an internal
    1.69 + *  representation. The internal representation is anchored in a
    1.70 + *  ClassSymbol which contains in its scope symbol representations
    1.71 + *  for all other definitions in the classfile. Top-level Classes themselves
    1.72 + *  appear as members of the scopes of PackageSymbols.
    1.73 + *
    1.74 + *  <p><b>This is NOT part of any supported API.
    1.75 + *  If you write code that depends on this, you do so at your own risk.
    1.76 + *  This code and its internal interfaces are subject to change or
    1.77 + *  deletion without notice.</b>
    1.78 + */
    1.79 +public class ClassReader {
    1.80 +    /** The context key for the class reader. */
    1.81 +    protected static final Context.Key<ClassReader> classReaderKey =
    1.82 +        new Context.Key<ClassReader>();
    1.83 +
    1.84 +    public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
    1.85 +
    1.86 +    Annotate annotate;
    1.87 +
    1.88 +    /** Switch: verbose output.
    1.89 +     */
    1.90 +    boolean verbose;
    1.91 +
    1.92 +    /** Switch: check class file for correct minor version, unrecognized
    1.93 +     *  attributes.
    1.94 +     */
    1.95 +    boolean checkClassFile;
    1.96 +
    1.97 +    /** Switch: read constant pool and code sections. This switch is initially
    1.98 +     *  set to false but can be turned on from outside.
    1.99 +     */
   1.100 +    public boolean readAllOfClassFile = false;
   1.101 +
   1.102 +    /** Switch: read GJ signature information.
   1.103 +     */
   1.104 +    boolean allowGenerics;
   1.105 +
   1.106 +    /** Switch: read varargs attribute.
   1.107 +     */
   1.108 +    boolean allowVarargs;
   1.109 +
   1.110 +    /** Switch: allow annotations.
   1.111 +     */
   1.112 +    boolean allowAnnotations;
   1.113 +
   1.114 +    /** Switch: allow simplified varargs.
   1.115 +     */
   1.116 +    boolean allowSimplifiedVarargs;
   1.117 +
   1.118 +   /** Lint option: warn about classfile issues
   1.119 +     */
   1.120 +    boolean lintClassfile;
   1.121 +
   1.122 +    /** Switch: preserve parameter names from the variable table.
   1.123 +     */
   1.124 +    public boolean saveParameterNames;
   1.125 +
   1.126 +    /**
   1.127 +     * Switch: cache completion failures unless -XDdev is used
   1.128 +     */
   1.129 +    private boolean cacheCompletionFailure;
   1.130 +
   1.131 +    /**
   1.132 +     * Switch: prefer source files instead of newer when both source
   1.133 +     * and class are available
   1.134 +     **/
   1.135 +    public boolean preferSource;
   1.136 +
   1.137 +    /**
   1.138 +     * The currently selected profile.
   1.139 +     */
   1.140 +    public final Profile profile;
   1.141 +
   1.142 +    /** The log to use for verbose output
   1.143 +     */
   1.144 +    final Log log;
   1.145 +
   1.146 +    /** The symbol table. */
   1.147 +    Symtab syms;
   1.148 +
   1.149 +    Types types;
   1.150 +
   1.151 +    /** The name table. */
   1.152 +    final Names names;
   1.153 +
   1.154 +    /** Force a completion failure on this name
   1.155 +     */
   1.156 +    final Name completionFailureName;
   1.157 +
   1.158 +    /** Access to files
   1.159 +     */
   1.160 +    private final JavaFileManager fileManager;
   1.161 +
   1.162 +    /** Factory for diagnostics
   1.163 +     */
   1.164 +    JCDiagnostic.Factory diagFactory;
   1.165 +
   1.166 +    /** Can be reassigned from outside:
   1.167 +     *  the completer to be used for ".java" files. If this remains unassigned
   1.168 +     *  ".java" files will not be loaded.
   1.169 +     */
   1.170 +    public SourceCompleter sourceCompleter = null;
   1.171 +
   1.172 +    /** A hashtable containing the encountered top-level and member classes,
   1.173 +     *  indexed by flat names. The table does not contain local classes.
   1.174 +     */
   1.175 +    private Map<Name,ClassSymbol> classes;
   1.176 +
   1.177 +    /** A hashtable containing the encountered packages.
   1.178 +     */
   1.179 +    private Map<Name, PackageSymbol> packages;
   1.180 +
   1.181 +    /** The current scope where type variables are entered.
   1.182 +     */
   1.183 +    protected Scope typevars;
   1.184 +
   1.185 +    /** The path name of the class file currently being read.
   1.186 +     */
   1.187 +    protected JavaFileObject currentClassFile = null;
   1.188 +
   1.189 +    /** The class or method currently being read.
   1.190 +     */
   1.191 +    protected Symbol currentOwner = null;
   1.192 +
   1.193 +    /** The buffer containing the currently read class file.
   1.194 +     */
   1.195 +    byte[] buf = new byte[INITIAL_BUFFER_SIZE];
   1.196 +
   1.197 +    /** The current input pointer.
   1.198 +     */
   1.199 +    protected int bp;
   1.200 +
   1.201 +    /** The objects of the constant pool.
   1.202 +     */
   1.203 +    Object[] poolObj;
   1.204 +
   1.205 +    /** For every constant pool entry, an index into buf where the
   1.206 +     *  defining section of the entry is found.
   1.207 +     */
   1.208 +    int[] poolIdx;
   1.209 +
   1.210 +    /** The major version number of the class file being read. */
   1.211 +    int majorVersion;
   1.212 +    /** The minor version number of the class file being read. */
   1.213 +    int minorVersion;
   1.214 +
   1.215 +    /** A table to hold the constant pool indices for method parameter
   1.216 +     * names, as given in LocalVariableTable attributes.
   1.217 +     */
   1.218 +    int[] parameterNameIndices;
   1.219 +
   1.220 +    /**
   1.221 +     * Whether or not any parameter names have been found.
   1.222 +     */
   1.223 +    boolean haveParameterNameIndices;
   1.224 +
   1.225 +    /** Set this to false every time we start reading a method
   1.226 +     * and are saving parameter names.  Set it to true when we see
   1.227 +     * MethodParameters, if it's set when we see a LocalVariableTable,
   1.228 +     * then we ignore the parameter names from the LVT.
   1.229 +     */
   1.230 +    boolean sawMethodParameters;
   1.231 +
   1.232 +    /**
   1.233 +     * The set of attribute names for which warnings have been generated for the current class
   1.234 +     */
   1.235 +    Set<Name> warnedAttrs = new HashSet<Name>();
   1.236 +
   1.237 +    /**
   1.238 +     * Completer that delegates to the complete-method of this class.
   1.239 +     */
   1.240 +    private final Completer thisCompleter = new Completer() {
   1.241 +        @Override
   1.242 +        public void complete(Symbol sym) throws CompletionFailure {
   1.243 +            ClassReader.this.complete(sym);
   1.244 +        }
   1.245 +    };
   1.246 +
   1.247 +
   1.248 +    /** Get the ClassReader instance for this invocation. */
   1.249 +    public static ClassReader instance(Context context) {
   1.250 +        ClassReader instance = context.get(classReaderKey);
   1.251 +        if (instance == null)
   1.252 +            instance = new ClassReader(context, true);
   1.253 +        return instance;
   1.254 +    }
   1.255 +
   1.256 +    /** Initialize classes and packages, treating this as the definitive classreader. */
   1.257 +    public void init(Symtab syms) {
   1.258 +        init(syms, true);
   1.259 +    }
   1.260 +
   1.261 +    /** Initialize classes and packages, optionally treating this as
   1.262 +     *  the definitive classreader.
   1.263 +     */
   1.264 +    private void init(Symtab syms, boolean definitive) {
   1.265 +        if (classes != null) return;
   1.266 +
   1.267 +        if (definitive) {
   1.268 +            Assert.check(packages == null || packages == syms.packages);
   1.269 +            packages = syms.packages;
   1.270 +            Assert.check(classes == null || classes == syms.classes);
   1.271 +            classes = syms.classes;
   1.272 +        } else {
   1.273 +            packages = new HashMap<Name, PackageSymbol>();
   1.274 +            classes = new HashMap<Name, ClassSymbol>();
   1.275 +        }
   1.276 +
   1.277 +        packages.put(names.empty, syms.rootPackage);
   1.278 +        syms.rootPackage.completer = thisCompleter;
   1.279 +        syms.unnamedPackage.completer = thisCompleter;
   1.280 +    }
   1.281 +
   1.282 +    /** Construct a new class reader, optionally treated as the
   1.283 +     *  definitive classreader for this invocation.
   1.284 +     */
   1.285 +    protected ClassReader(Context context, boolean definitive) {
   1.286 +        if (definitive) context.put(classReaderKey, this);
   1.287 +
   1.288 +        names = Names.instance(context);
   1.289 +        syms = Symtab.instance(context);
   1.290 +        types = Types.instance(context);
   1.291 +        fileManager = context.get(JavaFileManager.class);
   1.292 +        if (fileManager == null)
   1.293 +            throw new AssertionError("FileManager initialization error");
   1.294 +        diagFactory = JCDiagnostic.Factory.instance(context);
   1.295 +
   1.296 +        init(syms, definitive);
   1.297 +        log = Log.instance(context);
   1.298 +
   1.299 +        Options options = Options.instance(context);
   1.300 +        annotate = Annotate.instance(context);
   1.301 +        verbose        = options.isSet(VERBOSE);
   1.302 +        checkClassFile = options.isSet("-checkclassfile");
   1.303 +
   1.304 +        Source source = Source.instance(context);
   1.305 +        allowGenerics    = source.allowGenerics();
   1.306 +        allowVarargs     = source.allowVarargs();
   1.307 +        allowAnnotations = source.allowAnnotations();
   1.308 +        allowSimplifiedVarargs = source.allowSimplifiedVarargs();
   1.309 +
   1.310 +        saveParameterNames = options.isSet("save-parameter-names");
   1.311 +        cacheCompletionFailure = options.isUnset("dev");
   1.312 +        preferSource = "source".equals(options.get("-Xprefer"));
   1.313 +
   1.314 +        profile = Profile.instance(context);
   1.315 +
   1.316 +        completionFailureName =
   1.317 +            options.isSet("failcomplete")
   1.318 +            ? names.fromString(options.get("failcomplete"))
   1.319 +            : null;
   1.320 +
   1.321 +        typevars = new Scope(syms.noSymbol);
   1.322 +
   1.323 +        lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
   1.324 +
   1.325 +        initAttributeReaders();
   1.326 +    }
   1.327 +
   1.328 +    /** Add member to class unless it is synthetic.
   1.329 +     */
   1.330 +    private void enterMember(ClassSymbol c, Symbol sym) {
   1.331 +        // Synthetic members are not entered -- reason lost to history (optimization?).
   1.332 +        // Lambda methods must be entered because they may have inner classes (which reference them)
   1.333 +        if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda))
   1.334 +            c.members_field.enter(sym);
   1.335 +    }
   1.336 +
   1.337 +/************************************************************************
   1.338 + * Error Diagnoses
   1.339 + ***********************************************************************/
   1.340 +
   1.341 +
   1.342 +    public class BadClassFile extends CompletionFailure {
   1.343 +        private static final long serialVersionUID = 0;
   1.344 +
   1.345 +        public BadClassFile(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag) {
   1.346 +            super(sym, createBadClassFileDiagnostic(file, diag));
   1.347 +        }
   1.348 +    }
   1.349 +    // where
   1.350 +    private JCDiagnostic createBadClassFileDiagnostic(JavaFileObject file, JCDiagnostic diag) {
   1.351 +        String key = (file.getKind() == JavaFileObject.Kind.SOURCE
   1.352 +                    ? "bad.source.file.header" : "bad.class.file.header");
   1.353 +        return diagFactory.fragment(key, file, diag);
   1.354 +    }
   1.355 +
   1.356 +    public BadClassFile badClassFile(String key, Object... args) {
   1.357 +        return new BadClassFile (
   1.358 +            currentOwner.enclClass(),
   1.359 +            currentClassFile,
   1.360 +            diagFactory.fragment(key, args));
   1.361 +    }
   1.362 +
   1.363 +/************************************************************************
   1.364 + * Buffer Access
   1.365 + ***********************************************************************/
   1.366 +
   1.367 +    /** Read a character.
   1.368 +     */
   1.369 +    char nextChar() {
   1.370 +        return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF));
   1.371 +    }
   1.372 +
   1.373 +    /** Read a byte.
   1.374 +     */
   1.375 +    int nextByte() {
   1.376 +        return buf[bp++] & 0xFF;
   1.377 +    }
   1.378 +
   1.379 +    /** Read an integer.
   1.380 +     */
   1.381 +    int nextInt() {
   1.382 +        return
   1.383 +            ((buf[bp++] & 0xFF) << 24) +
   1.384 +            ((buf[bp++] & 0xFF) << 16) +
   1.385 +            ((buf[bp++] & 0xFF) << 8) +
   1.386 +            (buf[bp++] & 0xFF);
   1.387 +    }
   1.388 +
   1.389 +    /** Extract a character at position bp from buf.
   1.390 +     */
   1.391 +    char getChar(int bp) {
   1.392 +        return
   1.393 +            (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF));
   1.394 +    }
   1.395 +
   1.396 +    /** Extract an integer at position bp from buf.
   1.397 +     */
   1.398 +    int getInt(int bp) {
   1.399 +        return
   1.400 +            ((buf[bp] & 0xFF) << 24) +
   1.401 +            ((buf[bp+1] & 0xFF) << 16) +
   1.402 +            ((buf[bp+2] & 0xFF) << 8) +
   1.403 +            (buf[bp+3] & 0xFF);
   1.404 +    }
   1.405 +
   1.406 +
   1.407 +    /** Extract a long integer at position bp from buf.
   1.408 +     */
   1.409 +    long getLong(int bp) {
   1.410 +        DataInputStream bufin =
   1.411 +            new DataInputStream(new ByteArrayInputStream(buf, bp, 8));
   1.412 +        try {
   1.413 +            return bufin.readLong();
   1.414 +        } catch (IOException e) {
   1.415 +            throw new AssertionError(e);
   1.416 +        }
   1.417 +    }
   1.418 +
   1.419 +    /** Extract a float at position bp from buf.
   1.420 +     */
   1.421 +    float getFloat(int bp) {
   1.422 +        DataInputStream bufin =
   1.423 +            new DataInputStream(new ByteArrayInputStream(buf, bp, 4));
   1.424 +        try {
   1.425 +            return bufin.readFloat();
   1.426 +        } catch (IOException e) {
   1.427 +            throw new AssertionError(e);
   1.428 +        }
   1.429 +    }
   1.430 +
   1.431 +    /** Extract a double at position bp from buf.
   1.432 +     */
   1.433 +    double getDouble(int bp) {
   1.434 +        DataInputStream bufin =
   1.435 +            new DataInputStream(new ByteArrayInputStream(buf, bp, 8));
   1.436 +        try {
   1.437 +            return bufin.readDouble();
   1.438 +        } catch (IOException e) {
   1.439 +            throw new AssertionError(e);
   1.440 +        }
   1.441 +    }
   1.442 +
   1.443 +/************************************************************************
   1.444 + * Constant Pool Access
   1.445 + ***********************************************************************/
   1.446 +
   1.447 +    /** Index all constant pool entries, writing their start addresses into
   1.448 +     *  poolIdx.
   1.449 +     */
   1.450 +    void indexPool() {
   1.451 +        poolIdx = new int[nextChar()];
   1.452 +        poolObj = new Object[poolIdx.length];
   1.453 +        int i = 1;
   1.454 +        while (i < poolIdx.length) {
   1.455 +            poolIdx[i++] = bp;
   1.456 +            byte tag = buf[bp++];
   1.457 +            switch (tag) {
   1.458 +            case CONSTANT_Utf8: case CONSTANT_Unicode: {
   1.459 +                int len = nextChar();
   1.460 +                bp = bp + len;
   1.461 +                break;
   1.462 +            }
   1.463 +            case CONSTANT_Class:
   1.464 +            case CONSTANT_String:
   1.465 +            case CONSTANT_MethodType:
   1.466 +                bp = bp + 2;
   1.467 +                break;
   1.468 +            case CONSTANT_MethodHandle:
   1.469 +                bp = bp + 3;
   1.470 +                break;
   1.471 +            case CONSTANT_Fieldref:
   1.472 +            case CONSTANT_Methodref:
   1.473 +            case CONSTANT_InterfaceMethodref:
   1.474 +            case CONSTANT_NameandType:
   1.475 +            case CONSTANT_Integer:
   1.476 +            case CONSTANT_Float:
   1.477 +            case CONSTANT_InvokeDynamic:
   1.478 +                bp = bp + 4;
   1.479 +                break;
   1.480 +            case CONSTANT_Long:
   1.481 +            case CONSTANT_Double:
   1.482 +                bp = bp + 8;
   1.483 +                i++;
   1.484 +                break;
   1.485 +            default:
   1.486 +                throw badClassFile("bad.const.pool.tag.at",
   1.487 +                                   Byte.toString(tag),
   1.488 +                                   Integer.toString(bp -1));
   1.489 +            }
   1.490 +        }
   1.491 +    }
   1.492 +
   1.493 +    /** Read constant pool entry at start address i, use pool as a cache.
   1.494 +     */
   1.495 +    Object readPool(int i) {
   1.496 +        Object result = poolObj[i];
   1.497 +        if (result != null) return result;
   1.498 +
   1.499 +        int index = poolIdx[i];
   1.500 +        if (index == 0) return null;
   1.501 +
   1.502 +        byte tag = buf[index];
   1.503 +        switch (tag) {
   1.504 +        case CONSTANT_Utf8:
   1.505 +            poolObj[i] = names.fromUtf(buf, index + 3, getChar(index + 1));
   1.506 +            break;
   1.507 +        case CONSTANT_Unicode:
   1.508 +            throw badClassFile("unicode.str.not.supported");
   1.509 +        case CONSTANT_Class:
   1.510 +            poolObj[i] = readClassOrType(getChar(index + 1));
   1.511 +            break;
   1.512 +        case CONSTANT_String:
   1.513 +            // FIXME: (footprint) do not use toString here
   1.514 +            poolObj[i] = readName(getChar(index + 1)).toString();
   1.515 +            break;
   1.516 +        case CONSTANT_Fieldref: {
   1.517 +            ClassSymbol owner = readClassSymbol(getChar(index + 1));
   1.518 +            NameAndType nt = readNameAndType(getChar(index + 3));
   1.519 +            poolObj[i] = new VarSymbol(0, nt.name, nt.uniqueType.type, owner);
   1.520 +            break;
   1.521 +        }
   1.522 +        case CONSTANT_Methodref:
   1.523 +        case CONSTANT_InterfaceMethodref: {
   1.524 +            ClassSymbol owner = readClassSymbol(getChar(index + 1));
   1.525 +            NameAndType nt = readNameAndType(getChar(index + 3));
   1.526 +            poolObj[i] = new MethodSymbol(0, nt.name, nt.uniqueType.type, owner);
   1.527 +            break;
   1.528 +        }
   1.529 +        case CONSTANT_NameandType:
   1.530 +            poolObj[i] = new NameAndType(
   1.531 +                readName(getChar(index + 1)),
   1.532 +                readType(getChar(index + 3)), types);
   1.533 +            break;
   1.534 +        case CONSTANT_Integer:
   1.535 +            poolObj[i] = getInt(index + 1);
   1.536 +            break;
   1.537 +        case CONSTANT_Float:
   1.538 +            poolObj[i] = new Float(getFloat(index + 1));
   1.539 +            break;
   1.540 +        case CONSTANT_Long:
   1.541 +            poolObj[i] = new Long(getLong(index + 1));
   1.542 +            break;
   1.543 +        case CONSTANT_Double:
   1.544 +            poolObj[i] = new Double(getDouble(index + 1));
   1.545 +            break;
   1.546 +        case CONSTANT_MethodHandle:
   1.547 +            skipBytes(4);
   1.548 +            break;
   1.549 +        case CONSTANT_MethodType:
   1.550 +            skipBytes(3);
   1.551 +            break;
   1.552 +        case CONSTANT_InvokeDynamic:
   1.553 +            skipBytes(5);
   1.554 +            break;
   1.555 +        default:
   1.556 +            throw badClassFile("bad.const.pool.tag", Byte.toString(tag));
   1.557 +        }
   1.558 +        return poolObj[i];
   1.559 +    }
   1.560 +
   1.561 +    /** Read signature and convert to type.
   1.562 +     */
   1.563 +    Type readType(int i) {
   1.564 +        int index = poolIdx[i];
   1.565 +        return sigToType(buf, index + 3, getChar(index + 1));
   1.566 +    }
   1.567 +
   1.568 +    /** If name is an array type or class signature, return the
   1.569 +     *  corresponding type; otherwise return a ClassSymbol with given name.
   1.570 +     */
   1.571 +    Object readClassOrType(int i) {
   1.572 +        int index =  poolIdx[i];
   1.573 +        int len = getChar(index + 1);
   1.574 +        int start = index + 3;
   1.575 +        Assert.check(buf[start] == '[' || buf[start + len - 1] != ';');
   1.576 +        // by the above assertion, the following test can be
   1.577 +        // simplified to (buf[start] == '[')
   1.578 +        return (buf[start] == '[' || buf[start + len - 1] == ';')
   1.579 +            ? (Object)sigToType(buf, start, len)
   1.580 +            : (Object)enterClass(names.fromUtf(internalize(buf, start,
   1.581 +                                                           len)));
   1.582 +    }
   1.583 +
   1.584 +    /** Read signature and convert to type parameters.
   1.585 +     */
   1.586 +    List<Type> readTypeParams(int i) {
   1.587 +        int index = poolIdx[i];
   1.588 +        return sigToTypeParams(buf, index + 3, getChar(index + 1));
   1.589 +    }
   1.590 +
   1.591 +    /** Read class entry.
   1.592 +     */
   1.593 +    ClassSymbol readClassSymbol(int i) {
   1.594 +        Object obj = readPool(i);
   1.595 +        if (obj != null && !(obj instanceof ClassSymbol))
   1.596 +            throw badClassFile("bad.const.pool.entry",
   1.597 +                               currentClassFile.toString(),
   1.598 +                               "CONSTANT_Class_info", i);
   1.599 +        return (ClassSymbol)obj;
   1.600 +    }
   1.601 +
   1.602 +    /** Read name.
   1.603 +     */
   1.604 +    Name readName(int i) {
   1.605 +        Object obj = readPool(i);
   1.606 +        if (obj != null && !(obj instanceof Name))
   1.607 +            throw badClassFile("bad.const.pool.entry",
   1.608 +                               currentClassFile.toString(),
   1.609 +                               "CONSTANT_Utf8_info or CONSTANT_String_info", i);
   1.610 +        return (Name)obj;
   1.611 +    }
   1.612 +
   1.613 +    /** Read name and type.
   1.614 +     */
   1.615 +    NameAndType readNameAndType(int i) {
   1.616 +        Object obj = readPool(i);
   1.617 +        if (obj != null && !(obj instanceof NameAndType))
   1.618 +            throw badClassFile("bad.const.pool.entry",
   1.619 +                               currentClassFile.toString(),
   1.620 +                               "CONSTANT_NameAndType_info", i);
   1.621 +        return (NameAndType)obj;
   1.622 +    }
   1.623 +
   1.624 +/************************************************************************
   1.625 + * Reading Types
   1.626 + ***********************************************************************/
   1.627 +
   1.628 +    /** The unread portion of the currently read type is
   1.629 +     *  signature[sigp..siglimit-1].
   1.630 +     */
   1.631 +    byte[] signature;
   1.632 +    int sigp;
   1.633 +    int siglimit;
   1.634 +    boolean sigEnterPhase = false;
   1.635 +
   1.636 +    /** Convert signature to type, where signature is a byte array segment.
   1.637 +     */
   1.638 +    Type sigToType(byte[] sig, int offset, int len) {
   1.639 +        signature = sig;
   1.640 +        sigp = offset;
   1.641 +        siglimit = offset + len;
   1.642 +        return sigToType();
   1.643 +    }
   1.644 +
   1.645 +    /** Convert signature to type, where signature is implicit.
   1.646 +     */
   1.647 +    Type sigToType() {
   1.648 +        switch ((char) signature[sigp]) {
   1.649 +        case 'T':
   1.650 +            sigp++;
   1.651 +            int start = sigp;
   1.652 +            while (signature[sigp] != ';') sigp++;
   1.653 +            sigp++;
   1.654 +            return sigEnterPhase
   1.655 +                ? Type.noType
   1.656 +                : findTypeVar(names.fromUtf(signature, start, sigp - 1 - start));
   1.657 +        case '+': {
   1.658 +            sigp++;
   1.659 +            Type t = sigToType();
   1.660 +            return new WildcardType(t, BoundKind.EXTENDS,
   1.661 +                                    syms.boundClass);
   1.662 +        }
   1.663 +        case '*':
   1.664 +            sigp++;
   1.665 +            return new WildcardType(syms.objectType, BoundKind.UNBOUND,
   1.666 +                                    syms.boundClass);
   1.667 +        case '-': {
   1.668 +            sigp++;
   1.669 +            Type t = sigToType();
   1.670 +            return new WildcardType(t, BoundKind.SUPER,
   1.671 +                                    syms.boundClass);
   1.672 +        }
   1.673 +        case 'B':
   1.674 +            sigp++;
   1.675 +            return syms.byteType;
   1.676 +        case 'C':
   1.677 +            sigp++;
   1.678 +            return syms.charType;
   1.679 +        case 'D':
   1.680 +            sigp++;
   1.681 +            return syms.doubleType;
   1.682 +        case 'F':
   1.683 +            sigp++;
   1.684 +            return syms.floatType;
   1.685 +        case 'I':
   1.686 +            sigp++;
   1.687 +            return syms.intType;
   1.688 +        case 'J':
   1.689 +            sigp++;
   1.690 +            return syms.longType;
   1.691 +        case 'L':
   1.692 +            {
   1.693 +                // int oldsigp = sigp;
   1.694 +                Type t = classSigToType();
   1.695 +                if (sigp < siglimit && signature[sigp] == '.')
   1.696 +                    throw badClassFile("deprecated inner class signature syntax " +
   1.697 +                                       "(please recompile from source)");
   1.698 +                /*
   1.699 +                System.err.println(" decoded " +
   1.700 +                                   new String(signature, oldsigp, sigp-oldsigp) +
   1.701 +                                   " => " + t + " outer " + t.outer());
   1.702 +                */
   1.703 +                return t;
   1.704 +            }
   1.705 +        case 'S':
   1.706 +            sigp++;
   1.707 +            return syms.shortType;
   1.708 +        case 'V':
   1.709 +            sigp++;
   1.710 +            return syms.voidType;
   1.711 +        case 'Z':
   1.712 +            sigp++;
   1.713 +            return syms.booleanType;
   1.714 +        case '[':
   1.715 +            sigp++;
   1.716 +            return new ArrayType(sigToType(), syms.arrayClass);
   1.717 +        case '(':
   1.718 +            sigp++;
   1.719 +            List<Type> argtypes = sigToTypes(')');
   1.720 +            Type restype = sigToType();
   1.721 +            List<Type> thrown = List.nil();
   1.722 +            while (signature[sigp] == '^') {
   1.723 +                sigp++;
   1.724 +                thrown = thrown.prepend(sigToType());
   1.725 +            }
   1.726 +            // if there is a typevar in the throws clause we should state it.
   1.727 +            for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) {
   1.728 +                if (l.head.hasTag(TYPEVAR)) {
   1.729 +                    l.head.tsym.flags_field |= THROWS;
   1.730 +                }
   1.731 +            }
   1.732 +            return new MethodType(argtypes,
   1.733 +                                  restype,
   1.734 +                                  thrown.reverse(),
   1.735 +                                  syms.methodClass);
   1.736 +        case '<':
   1.737 +            typevars = typevars.dup(currentOwner);
   1.738 +            Type poly = new ForAll(sigToTypeParams(), sigToType());
   1.739 +            typevars = typevars.leave();
   1.740 +            return poly;
   1.741 +        default:
   1.742 +            throw badClassFile("bad.signature",
   1.743 +                               Convert.utf2string(signature, sigp, 10));
   1.744 +        }
   1.745 +    }
   1.746 +
   1.747 +    byte[] signatureBuffer = new byte[0];
   1.748 +    int sbp = 0;
   1.749 +    /** Convert class signature to type, where signature is implicit.
   1.750 +     */
   1.751 +    Type classSigToType() {
   1.752 +        if (signature[sigp] != 'L')
   1.753 +            throw badClassFile("bad.class.signature",
   1.754 +                               Convert.utf2string(signature, sigp, 10));
   1.755 +        sigp++;
   1.756 +        Type outer = Type.noType;
   1.757 +        int startSbp = sbp;
   1.758 +
   1.759 +        while (true) {
   1.760 +            final byte c = signature[sigp++];
   1.761 +            switch (c) {
   1.762 +
   1.763 +            case ';': {         // end
   1.764 +                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
   1.765 +                                                         startSbp,
   1.766 +                                                         sbp - startSbp));
   1.767 +
   1.768 +                try {
   1.769 +                    return (outer == Type.noType) ?
   1.770 +                            t.erasure(types) :
   1.771 +                            new ClassType(outer, List.<Type>nil(), t);
   1.772 +                } finally {
   1.773 +                    sbp = startSbp;
   1.774 +                }
   1.775 +            }
   1.776 +
   1.777 +            case '<':           // generic arguments
   1.778 +                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
   1.779 +                                                         startSbp,
   1.780 +                                                         sbp - startSbp));
   1.781 +                outer = new ClassType(outer, sigToTypes('>'), t) {
   1.782 +                        boolean completed = false;
   1.783 +                        @Override
   1.784 +                        public Type getEnclosingType() {
   1.785 +                            if (!completed) {
   1.786 +                                completed = true;
   1.787 +                                tsym.complete();
   1.788 +                                Type enclosingType = tsym.type.getEnclosingType();
   1.789 +                                if (enclosingType != Type.noType) {
   1.790 +                                    List<Type> typeArgs =
   1.791 +                                        super.getEnclosingType().allparams();
   1.792 +                                    List<Type> typeParams =
   1.793 +                                        enclosingType.allparams();
   1.794 +                                    if (typeParams.length() != typeArgs.length()) {
   1.795 +                                        // no "rare" types
   1.796 +                                        super.setEnclosingType(types.erasure(enclosingType));
   1.797 +                                    } else {
   1.798 +                                        super.setEnclosingType(types.subst(enclosingType,
   1.799 +                                                                           typeParams,
   1.800 +                                                                           typeArgs));
   1.801 +                                    }
   1.802 +                                } else {
   1.803 +                                    super.setEnclosingType(Type.noType);
   1.804 +                                }
   1.805 +                            }
   1.806 +                            return super.getEnclosingType();
   1.807 +                        }
   1.808 +                        @Override
   1.809 +                        public void setEnclosingType(Type outer) {
   1.810 +                            throw new UnsupportedOperationException();
   1.811 +                        }
   1.812 +                    };
   1.813 +                switch (signature[sigp++]) {
   1.814 +                case ';':
   1.815 +                    if (sigp < signature.length && signature[sigp] == '.') {
   1.816 +                        // support old-style GJC signatures
   1.817 +                        // The signature produced was
   1.818 +                        // Lfoo/Outer<Lfoo/X;>;.Lfoo/Outer$Inner<Lfoo/Y;>;
   1.819 +                        // rather than say
   1.820 +                        // Lfoo/Outer<Lfoo/X;>.Inner<Lfoo/Y;>;
   1.821 +                        // so we skip past ".Lfoo/Outer$"
   1.822 +                        sigp += (sbp - startSbp) + // "foo/Outer"
   1.823 +                            3;  // ".L" and "$"
   1.824 +                        signatureBuffer[sbp++] = (byte)'$';
   1.825 +                        break;
   1.826 +                    } else {
   1.827 +                        sbp = startSbp;
   1.828 +                        return outer;
   1.829 +                    }
   1.830 +                case '.':
   1.831 +                    signatureBuffer[sbp++] = (byte)'$';
   1.832 +                    break;
   1.833 +                default:
   1.834 +                    throw new AssertionError(signature[sigp-1]);
   1.835 +                }
   1.836 +                continue;
   1.837 +
   1.838 +            case '.':
   1.839 +                //we have seen an enclosing non-generic class
   1.840 +                if (outer != Type.noType) {
   1.841 +                    t = enterClass(names.fromUtf(signatureBuffer,
   1.842 +                                                 startSbp,
   1.843 +                                                 sbp - startSbp));
   1.844 +                    outer = new ClassType(outer, List.<Type>nil(), t);
   1.845 +                }
   1.846 +                signatureBuffer[sbp++] = (byte)'$';
   1.847 +                continue;
   1.848 +            case '/':
   1.849 +                signatureBuffer[sbp++] = (byte)'.';
   1.850 +                continue;
   1.851 +            default:
   1.852 +                signatureBuffer[sbp++] = c;
   1.853 +                continue;
   1.854 +            }
   1.855 +        }
   1.856 +    }
   1.857 +
   1.858 +    /** Convert (implicit) signature to list of types
   1.859 +     *  until `terminator' is encountered.
   1.860 +     */
   1.861 +    List<Type> sigToTypes(char terminator) {
   1.862 +        List<Type> head = List.of(null);
   1.863 +        List<Type> tail = head;
   1.864 +        while (signature[sigp] != terminator)
   1.865 +            tail = tail.setTail(List.of(sigToType()));
   1.866 +        sigp++;
   1.867 +        return head.tail;
   1.868 +    }
   1.869 +
   1.870 +    /** Convert signature to type parameters, where signature is a byte
   1.871 +     *  array segment.
   1.872 +     */
   1.873 +    List<Type> sigToTypeParams(byte[] sig, int offset, int len) {
   1.874 +        signature = sig;
   1.875 +        sigp = offset;
   1.876 +        siglimit = offset + len;
   1.877 +        return sigToTypeParams();
   1.878 +    }
   1.879 +
   1.880 +    /** Convert signature to type parameters, where signature is implicit.
   1.881 +     */
   1.882 +    List<Type> sigToTypeParams() {
   1.883 +        List<Type> tvars = List.nil();
   1.884 +        if (signature[sigp] == '<') {
   1.885 +            sigp++;
   1.886 +            int start = sigp;
   1.887 +            sigEnterPhase = true;
   1.888 +            while (signature[sigp] != '>')
   1.889 +                tvars = tvars.prepend(sigToTypeParam());
   1.890 +            sigEnterPhase = false;
   1.891 +            sigp = start;
   1.892 +            while (signature[sigp] != '>')
   1.893 +                sigToTypeParam();
   1.894 +            sigp++;
   1.895 +        }
   1.896 +        return tvars.reverse();
   1.897 +    }
   1.898 +
   1.899 +    /** Convert (implicit) signature to type parameter.
   1.900 +     */
   1.901 +    Type sigToTypeParam() {
   1.902 +        int start = sigp;
   1.903 +        while (signature[sigp] != ':') sigp++;
   1.904 +        Name name = names.fromUtf(signature, start, sigp - start);
   1.905 +        TypeVar tvar;
   1.906 +        if (sigEnterPhase) {
   1.907 +            tvar = new TypeVar(name, currentOwner, syms.botType);
   1.908 +            typevars.enter(tvar.tsym);
   1.909 +        } else {
   1.910 +            tvar = (TypeVar)findTypeVar(name);
   1.911 +        }
   1.912 +        List<Type> bounds = List.nil();
   1.913 +        boolean allInterfaces = false;
   1.914 +        if (signature[sigp] == ':' && signature[sigp+1] == ':') {
   1.915 +            sigp++;
   1.916 +            allInterfaces = true;
   1.917 +        }
   1.918 +        while (signature[sigp] == ':') {
   1.919 +            sigp++;
   1.920 +            bounds = bounds.prepend(sigToType());
   1.921 +        }
   1.922 +        if (!sigEnterPhase) {
   1.923 +            types.setBounds(tvar, bounds.reverse(), allInterfaces);
   1.924 +        }
   1.925 +        return tvar;
   1.926 +    }
   1.927 +
   1.928 +    /** Find type variable with given name in `typevars' scope.
   1.929 +     */
   1.930 +    Type findTypeVar(Name name) {
   1.931 +        Scope.Entry e = typevars.lookup(name);
   1.932 +        if (e.scope != null) {
   1.933 +            return e.sym.type;
   1.934 +        } else {
   1.935 +            if (readingClassAttr) {
   1.936 +                // While reading the class attribute, the supertypes
   1.937 +                // might refer to a type variable from an enclosing element
   1.938 +                // (method or class).
   1.939 +                // If the type variable is defined in the enclosing class,
   1.940 +                // we can actually find it in
   1.941 +                // currentOwner.owner.type.getTypeArguments()
   1.942 +                // However, until we have read the enclosing method attribute
   1.943 +                // we don't know for sure if this owner is correct.  It could
   1.944 +                // be a method and there is no way to tell before reading the
   1.945 +                // enclosing method attribute.
   1.946 +                TypeVar t = new TypeVar(name, currentOwner, syms.botType);
   1.947 +                missingTypeVariables = missingTypeVariables.prepend(t);
   1.948 +                // System.err.println("Missing type var " + name);
   1.949 +                return t;
   1.950 +            }
   1.951 +            throw badClassFile("undecl.type.var", name);
   1.952 +        }
   1.953 +    }
   1.954 +
   1.955 +/************************************************************************
   1.956 + * Reading Attributes
   1.957 + ***********************************************************************/
   1.958 +
   1.959 +    protected enum AttributeKind { CLASS, MEMBER };
   1.960 +    protected abstract class AttributeReader {
   1.961 +        protected AttributeReader(Name name, ClassFile.Version version, Set<AttributeKind> kinds) {
   1.962 +            this.name = name;
   1.963 +            this.version = version;
   1.964 +            this.kinds = kinds;
   1.965 +        }
   1.966 +
   1.967 +        protected boolean accepts(AttributeKind kind) {
   1.968 +            if (kinds.contains(kind)) {
   1.969 +                if (majorVersion > version.major || (majorVersion == version.major && minorVersion >= version.minor))
   1.970 +                    return true;
   1.971 +
   1.972 +                if (lintClassfile && !warnedAttrs.contains(name)) {
   1.973 +                    JavaFileObject prev = log.useSource(currentClassFile);
   1.974 +                    try {
   1.975 +                        log.warning(LintCategory.CLASSFILE, (DiagnosticPosition) null, "future.attr",
   1.976 +                                name, version.major, version.minor, majorVersion, minorVersion);
   1.977 +                    } finally {
   1.978 +                        log.useSource(prev);
   1.979 +                    }
   1.980 +                    warnedAttrs.add(name);
   1.981 +                }
   1.982 +            }
   1.983 +            return false;
   1.984 +        }
   1.985 +
   1.986 +        protected abstract void read(Symbol sym, int attrLen);
   1.987 +
   1.988 +        protected final Name name;
   1.989 +        protected final ClassFile.Version version;
   1.990 +        protected final Set<AttributeKind> kinds;
   1.991 +    }
   1.992 +
   1.993 +    protected Set<AttributeKind> CLASS_ATTRIBUTE =
   1.994 +            EnumSet.of(AttributeKind.CLASS);
   1.995 +    protected Set<AttributeKind> MEMBER_ATTRIBUTE =
   1.996 +            EnumSet.of(AttributeKind.MEMBER);
   1.997 +    protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE =
   1.998 +            EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER);
   1.999 +
  1.1000 +    protected Map<Name, AttributeReader> attributeReaders = new HashMap<Name, AttributeReader>();
  1.1001 +
  1.1002 +    private void initAttributeReaders() {
  1.1003 +        AttributeReader[] readers = {
  1.1004 +            // v45.3 attributes
  1.1005 +
  1.1006 +            new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
  1.1007 +                protected void read(Symbol sym, int attrLen) {
  1.1008 +                    if (readAllOfClassFile || saveParameterNames)
  1.1009 +                        ((MethodSymbol)sym).code = readCode(sym);
  1.1010 +                    else
  1.1011 +                        bp = bp + attrLen;
  1.1012 +                }
  1.1013 +            },
  1.1014 +
  1.1015 +            new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
  1.1016 +                protected void read(Symbol sym, int attrLen) {
  1.1017 +                    Object v = readPool(nextChar());
  1.1018 +                    // Ignore ConstantValue attribute if field not final.
  1.1019 +                    if ((sym.flags() & FINAL) != 0)
  1.1020 +                        ((VarSymbol) sym).setData(v);
  1.1021 +                }
  1.1022 +            },
  1.1023 +
  1.1024 +            new AttributeReader(names.Deprecated, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
  1.1025 +                protected void read(Symbol sym, int attrLen) {
  1.1026 +                    sym.flags_field |= DEPRECATED;
  1.1027 +                }
  1.1028 +            },
  1.1029 +
  1.1030 +            new AttributeReader(names.Exceptions, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
  1.1031 +                protected void read(Symbol sym, int attrLen) {
  1.1032 +                    int nexceptions = nextChar();
  1.1033 +                    List<Type> thrown = List.nil();
  1.1034 +                    for (int j = 0; j < nexceptions; j++)
  1.1035 +                        thrown = thrown.prepend(readClassSymbol(nextChar()).type);
  1.1036 +                    if (sym.type.getThrownTypes().isEmpty())
  1.1037 +                        sym.type.asMethodType().thrown = thrown.reverse();
  1.1038 +                }
  1.1039 +            },
  1.1040 +
  1.1041 +            new AttributeReader(names.InnerClasses, V45_3, CLASS_ATTRIBUTE) {
  1.1042 +                protected void read(Symbol sym, int attrLen) {
  1.1043 +                    ClassSymbol c = (ClassSymbol) sym;
  1.1044 +                    readInnerClasses(c);
  1.1045 +                }
  1.1046 +            },
  1.1047 +
  1.1048 +            new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
  1.1049 +                protected void read(Symbol sym, int attrLen) {
  1.1050 +                    int newbp = bp + attrLen;
  1.1051 +                    if (saveParameterNames && !sawMethodParameters) {
  1.1052 +                        // Pick up parameter names from the variable table.
  1.1053 +                        // Parameter names are not explicitly identified as such,
  1.1054 +                        // but all parameter name entries in the LocalVariableTable
  1.1055 +                        // have a start_pc of 0.  Therefore, we record the name
  1.1056 +                        // indicies of all slots with a start_pc of zero in the
  1.1057 +                        // parameterNameIndicies array.
  1.1058 +                        // Note that this implicitly honors the JVMS spec that
  1.1059 +                        // there may be more than one LocalVariableTable, and that
  1.1060 +                        // there is no specified ordering for the entries.
  1.1061 +                        int numEntries = nextChar();
  1.1062 +                        for (int i = 0; i < numEntries; i++) {
  1.1063 +                            int start_pc = nextChar();
  1.1064 +                            int length = nextChar();
  1.1065 +                            int nameIndex = nextChar();
  1.1066 +                            int sigIndex = nextChar();
  1.1067 +                            int register = nextChar();
  1.1068 +                            if (start_pc == 0) {
  1.1069 +                                // ensure array large enough
  1.1070 +                                if (register >= parameterNameIndices.length) {
  1.1071 +                                    int newSize = Math.max(register, parameterNameIndices.length + 8);
  1.1072 +                                    parameterNameIndices =
  1.1073 +                                            Arrays.copyOf(parameterNameIndices, newSize);
  1.1074 +                                }
  1.1075 +                                parameterNameIndices[register] = nameIndex;
  1.1076 +                                haveParameterNameIndices = true;
  1.1077 +                            }
  1.1078 +                        }
  1.1079 +                    }
  1.1080 +                    bp = newbp;
  1.1081 +                }
  1.1082 +            },
  1.1083 +
  1.1084 +            new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) {
  1.1085 +                protected void read(Symbol sym, int attrlen) {
  1.1086 +                    int newbp = bp + attrlen;
  1.1087 +                    if (saveParameterNames) {
  1.1088 +                        sawMethodParameters = true;
  1.1089 +                        int numEntries = nextByte();
  1.1090 +                        parameterNameIndices = new int[numEntries];
  1.1091 +                        haveParameterNameIndices = true;
  1.1092 +                        for (int i = 0; i < numEntries; i++) {
  1.1093 +                            int nameIndex = nextChar();
  1.1094 +                            int flags = nextChar();
  1.1095 +                            parameterNameIndices[i] = nameIndex;
  1.1096 +                        }
  1.1097 +                    }
  1.1098 +                    bp = newbp;
  1.1099 +                }
  1.1100 +            },
  1.1101 +
  1.1102 +
  1.1103 +            new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) {
  1.1104 +                protected void read(Symbol sym, int attrLen) {
  1.1105 +                    ClassSymbol c = (ClassSymbol) sym;
  1.1106 +                    Name n = readName(nextChar());
  1.1107 +                    c.sourcefile = new SourceFileObject(n, c.flatname);
  1.1108 +                    // If the class is a toplevel class, originating from a Java source file,
  1.1109 +                    // but the class name does not match the file name, then it is
  1.1110 +                    // an auxiliary class.
  1.1111 +                    String sn = n.toString();
  1.1112 +                    if (c.owner.kind == Kinds.PCK &&
  1.1113 +                        sn.endsWith(".java") &&
  1.1114 +                        !sn.equals(c.name.toString()+".java")) {
  1.1115 +                        c.flags_field |= AUXILIARY;
  1.1116 +                    }
  1.1117 +                }
  1.1118 +            },
  1.1119 +
  1.1120 +            new AttributeReader(names.Synthetic, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
  1.1121 +                protected void read(Symbol sym, int attrLen) {
  1.1122 +                    // bridge methods are visible when generics not enabled
  1.1123 +                    if (allowGenerics || (sym.flags_field & BRIDGE) == 0)
  1.1124 +                        sym.flags_field |= SYNTHETIC;
  1.1125 +                }
  1.1126 +            },
  1.1127 +
  1.1128 +            // standard v49 attributes
  1.1129 +
  1.1130 +            new AttributeReader(names.EnclosingMethod, V49, CLASS_ATTRIBUTE) {
  1.1131 +                protected void read(Symbol sym, int attrLen) {
  1.1132 +                    int newbp = bp + attrLen;
  1.1133 +                    readEnclosingMethodAttr(sym);
  1.1134 +                    bp = newbp;
  1.1135 +                }
  1.1136 +            },
  1.1137 +
  1.1138 +            new AttributeReader(names.Signature, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
  1.1139 +                @Override
  1.1140 +                protected boolean accepts(AttributeKind kind) {
  1.1141 +                    return super.accepts(kind) && allowGenerics;
  1.1142 +                }
  1.1143 +
  1.1144 +                protected void read(Symbol sym, int attrLen) {
  1.1145 +                    if (sym.kind == TYP) {
  1.1146 +                        ClassSymbol c = (ClassSymbol) sym;
  1.1147 +                        readingClassAttr = true;
  1.1148 +                        try {
  1.1149 +                            ClassType ct1 = (ClassType)c.type;
  1.1150 +                            Assert.check(c == currentOwner);
  1.1151 +                            ct1.typarams_field = readTypeParams(nextChar());
  1.1152 +                            ct1.supertype_field = sigToType();
  1.1153 +                            ListBuffer<Type> is = new ListBuffer<Type>();
  1.1154 +                            while (sigp != siglimit) is.append(sigToType());
  1.1155 +                            ct1.interfaces_field = is.toList();
  1.1156 +                        } finally {
  1.1157 +                            readingClassAttr = false;
  1.1158 +                        }
  1.1159 +                    } else {
  1.1160 +                        List<Type> thrown = sym.type.getThrownTypes();
  1.1161 +                        sym.type = readType(nextChar());
  1.1162 +                        //- System.err.println(" # " + sym.type);
  1.1163 +                        if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
  1.1164 +                            sym.type.asMethodType().thrown = thrown;
  1.1165 +
  1.1166 +                    }
  1.1167 +                }
  1.1168 +            },
  1.1169 +
  1.1170 +            // v49 annotation attributes
  1.1171 +
  1.1172 +            new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
  1.1173 +                protected void read(Symbol sym, int attrLen) {
  1.1174 +                    attachAnnotationDefault(sym);
  1.1175 +                }
  1.1176 +            },
  1.1177 +
  1.1178 +            new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
  1.1179 +                protected void read(Symbol sym, int attrLen) {
  1.1180 +                    attachAnnotations(sym);
  1.1181 +                }
  1.1182 +            },
  1.1183 +
  1.1184 +            new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
  1.1185 +                protected void read(Symbol sym, int attrLen) {
  1.1186 +                    attachParameterAnnotations(sym);
  1.1187 +                }
  1.1188 +            },
  1.1189 +
  1.1190 +            new AttributeReader(names.RuntimeVisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
  1.1191 +                protected void read(Symbol sym, int attrLen) {
  1.1192 +                    attachAnnotations(sym);
  1.1193 +                }
  1.1194 +            },
  1.1195 +
  1.1196 +            new AttributeReader(names.RuntimeVisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
  1.1197 +                protected void read(Symbol sym, int attrLen) {
  1.1198 +                    attachParameterAnnotations(sym);
  1.1199 +                }
  1.1200 +            },
  1.1201 +
  1.1202 +            // additional "legacy" v49 attributes, superceded by flags
  1.1203 +
  1.1204 +            new AttributeReader(names.Annotation, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
  1.1205 +                protected void read(Symbol sym, int attrLen) {
  1.1206 +                    if (allowAnnotations)
  1.1207 +                        sym.flags_field |= ANNOTATION;
  1.1208 +                }
  1.1209 +            },
  1.1210 +
  1.1211 +            new AttributeReader(names.Bridge, V49, MEMBER_ATTRIBUTE) {
  1.1212 +                protected void read(Symbol sym, int attrLen) {
  1.1213 +                    sym.flags_field |= BRIDGE;
  1.1214 +                    if (!allowGenerics)
  1.1215 +                        sym.flags_field &= ~SYNTHETIC;
  1.1216 +                }
  1.1217 +            },
  1.1218 +
  1.1219 +            new AttributeReader(names.Enum, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
  1.1220 +                protected void read(Symbol sym, int attrLen) {
  1.1221 +                    sym.flags_field |= ENUM;
  1.1222 +                }
  1.1223 +            },
  1.1224 +
  1.1225 +            new AttributeReader(names.Varargs, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
  1.1226 +                protected void read(Symbol sym, int attrLen) {
  1.1227 +                    if (allowVarargs)
  1.1228 +                        sym.flags_field |= VARARGS;
  1.1229 +                }
  1.1230 +            },
  1.1231 +
  1.1232 +            new AttributeReader(names.RuntimeVisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) {
  1.1233 +                protected void read(Symbol sym, int attrLen) {
  1.1234 +                    attachTypeAnnotations(sym);
  1.1235 +                }
  1.1236 +            },
  1.1237 +
  1.1238 +            new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) {
  1.1239 +                protected void read(Symbol sym, int attrLen) {
  1.1240 +                    attachTypeAnnotations(sym);
  1.1241 +                }
  1.1242 +            },
  1.1243 +
  1.1244 +
  1.1245 +            // The following attributes for a Code attribute are not currently handled
  1.1246 +            // StackMapTable
  1.1247 +            // SourceDebugExtension
  1.1248 +            // LineNumberTable
  1.1249 +            // LocalVariableTypeTable
  1.1250 +        };
  1.1251 +
  1.1252 +        for (AttributeReader r: readers)
  1.1253 +            attributeReaders.put(r.name, r);
  1.1254 +    }
  1.1255 +
  1.1256 +    /** Report unrecognized attribute.
  1.1257 +     */
  1.1258 +    void unrecognized(Name attrName) {
  1.1259 +        if (checkClassFile)
  1.1260 +            printCCF("ccf.unrecognized.attribute", attrName);
  1.1261 +    }
  1.1262 +
  1.1263 +
  1.1264 +
  1.1265 +    protected void readEnclosingMethodAttr(Symbol sym) {
  1.1266 +        // sym is a nested class with an "Enclosing Method" attribute
  1.1267 +        // remove sym from it's current owners scope and place it in
  1.1268 +        // the scope specified by the attribute
  1.1269 +        sym.owner.members().remove(sym);
  1.1270 +        ClassSymbol self = (ClassSymbol)sym;
  1.1271 +        ClassSymbol c = readClassSymbol(nextChar());
  1.1272 +        NameAndType nt = readNameAndType(nextChar());
  1.1273 +
  1.1274 +        if (c.members_field == null)
  1.1275 +            throw badClassFile("bad.enclosing.class", self, c);
  1.1276 +
  1.1277 +        MethodSymbol m = findMethod(nt, c.members_field, self.flags());
  1.1278 +        if (nt != null && m == null)
  1.1279 +            throw badClassFile("bad.enclosing.method", self);
  1.1280 +
  1.1281 +        self.name = simpleBinaryName(self.flatname, c.flatname) ;
  1.1282 +        self.owner = m != null ? m : c;
  1.1283 +        if (self.name.isEmpty())
  1.1284 +            self.fullname = names.empty;
  1.1285 +        else
  1.1286 +            self.fullname = ClassSymbol.formFullName(self.name, self.owner);
  1.1287 +
  1.1288 +        if (m != null) {
  1.1289 +            ((ClassType)sym.type).setEnclosingType(m.type);
  1.1290 +        } else if ((self.flags_field & STATIC) == 0) {
  1.1291 +            ((ClassType)sym.type).setEnclosingType(c.type);
  1.1292 +        } else {
  1.1293 +            ((ClassType)sym.type).setEnclosingType(Type.noType);
  1.1294 +        }
  1.1295 +        enterTypevars(self);
  1.1296 +        if (!missingTypeVariables.isEmpty()) {
  1.1297 +            ListBuffer<Type> typeVars =  new ListBuffer<Type>();
  1.1298 +            for (Type typevar : missingTypeVariables) {
  1.1299 +                typeVars.append(findTypeVar(typevar.tsym.name));
  1.1300 +            }
  1.1301 +            foundTypeVariables = typeVars.toList();
  1.1302 +        } else {
  1.1303 +            foundTypeVariables = List.nil();
  1.1304 +        }
  1.1305 +    }
  1.1306 +
  1.1307 +    // See java.lang.Class
  1.1308 +    private Name simpleBinaryName(Name self, Name enclosing) {
  1.1309 +        String simpleBinaryName = self.toString().substring(enclosing.toString().length());
  1.1310 +        if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$')
  1.1311 +            throw badClassFile("bad.enclosing.method", self);
  1.1312 +        int index = 1;
  1.1313 +        while (index < simpleBinaryName.length() &&
  1.1314 +               isAsciiDigit(simpleBinaryName.charAt(index)))
  1.1315 +            index++;
  1.1316 +        return names.fromString(simpleBinaryName.substring(index));
  1.1317 +    }
  1.1318 +
  1.1319 +    private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) {
  1.1320 +        if (nt == null)
  1.1321 +            return null;
  1.1322 +
  1.1323 +        MethodType type = nt.uniqueType.type.asMethodType();
  1.1324 +
  1.1325 +        for (Scope.Entry e = scope.lookup(nt.name); e.scope != null; e = e.next())
  1.1326 +            if (e.sym.kind == MTH && isSameBinaryType(e.sym.type.asMethodType(), type))
  1.1327 +                return (MethodSymbol)e.sym;
  1.1328 +
  1.1329 +        if (nt.name != names.init)
  1.1330 +            // not a constructor
  1.1331 +            return null;
  1.1332 +        if ((flags & INTERFACE) != 0)
  1.1333 +            // no enclosing instance
  1.1334 +            return null;
  1.1335 +        if (nt.uniqueType.type.getParameterTypes().isEmpty())
  1.1336 +            // no parameters
  1.1337 +            return null;
  1.1338 +
  1.1339 +        // A constructor of an inner class.
  1.1340 +        // Remove the first argument (the enclosing instance)
  1.1341 +        nt.setType(new MethodType(nt.uniqueType.type.getParameterTypes().tail,
  1.1342 +                                 nt.uniqueType.type.getReturnType(),
  1.1343 +                                 nt.uniqueType.type.getThrownTypes(),
  1.1344 +                                 syms.methodClass));
  1.1345 +        // Try searching again
  1.1346 +        return findMethod(nt, scope, flags);
  1.1347 +    }
  1.1348 +
  1.1349 +    /** Similar to Types.isSameType but avoids completion */
  1.1350 +    private boolean isSameBinaryType(MethodType mt1, MethodType mt2) {
  1.1351 +        List<Type> types1 = types.erasure(mt1.getParameterTypes())
  1.1352 +            .prepend(types.erasure(mt1.getReturnType()));
  1.1353 +        List<Type> types2 = mt2.getParameterTypes().prepend(mt2.getReturnType());
  1.1354 +        while (!types1.isEmpty() && !types2.isEmpty()) {
  1.1355 +            if (types1.head.tsym != types2.head.tsym)
  1.1356 +                return false;
  1.1357 +            types1 = types1.tail;
  1.1358 +            types2 = types2.tail;
  1.1359 +        }
  1.1360 +        return types1.isEmpty() && types2.isEmpty();
  1.1361 +    }
  1.1362 +
  1.1363 +    /**
  1.1364 +     * Character.isDigit answers <tt>true</tt> to some non-ascii
  1.1365 +     * digits.  This one does not.  <b>copied from java.lang.Class</b>
  1.1366 +     */
  1.1367 +    private static boolean isAsciiDigit(char c) {
  1.1368 +        return '0' <= c && c <= '9';
  1.1369 +    }
  1.1370 +
  1.1371 +    /** Read member attributes.
  1.1372 +     */
  1.1373 +    void readMemberAttrs(Symbol sym) {
  1.1374 +        readAttrs(sym, AttributeKind.MEMBER);
  1.1375 +    }
  1.1376 +
  1.1377 +    void readAttrs(Symbol sym, AttributeKind kind) {
  1.1378 +        char ac = nextChar();
  1.1379 +        for (int i = 0; i < ac; i++) {
  1.1380 +            Name attrName = readName(nextChar());
  1.1381 +            int attrLen = nextInt();
  1.1382 +            AttributeReader r = attributeReaders.get(attrName);
  1.1383 +            if (r != null && r.accepts(kind))
  1.1384 +                r.read(sym, attrLen);
  1.1385 +            else  {
  1.1386 +                unrecognized(attrName);
  1.1387 +                bp = bp + attrLen;
  1.1388 +            }
  1.1389 +        }
  1.1390 +    }
  1.1391 +
  1.1392 +    private boolean readingClassAttr = false;
  1.1393 +    private List<Type> missingTypeVariables = List.nil();
  1.1394 +    private List<Type> foundTypeVariables = List.nil();
  1.1395 +
  1.1396 +    /** Read class attributes.
  1.1397 +     */
  1.1398 +    void readClassAttrs(ClassSymbol c) {
  1.1399 +        readAttrs(c, AttributeKind.CLASS);
  1.1400 +    }
  1.1401 +
  1.1402 +    /** Read code block.
  1.1403 +     */
  1.1404 +    Code readCode(Symbol owner) {
  1.1405 +        nextChar(); // max_stack
  1.1406 +        nextChar(); // max_locals
  1.1407 +        final int  code_length = nextInt();
  1.1408 +        bp += code_length;
  1.1409 +        final char exception_table_length = nextChar();
  1.1410 +        bp += exception_table_length * 8;
  1.1411 +        readMemberAttrs(owner);
  1.1412 +        return null;
  1.1413 +    }
  1.1414 +
  1.1415 +/************************************************************************
  1.1416 + * Reading Java-language annotations
  1.1417 + ***********************************************************************/
  1.1418 +
  1.1419 +    /** Attach annotations.
  1.1420 +     */
  1.1421 +    void attachAnnotations(final Symbol sym) {
  1.1422 +        int numAttributes = nextChar();
  1.1423 +        if (numAttributes != 0) {
  1.1424 +            ListBuffer<CompoundAnnotationProxy> proxies =
  1.1425 +                new ListBuffer<CompoundAnnotationProxy>();
  1.1426 +            for (int i = 0; i<numAttributes; i++) {
  1.1427 +                CompoundAnnotationProxy proxy = readCompoundAnnotation();
  1.1428 +                if (proxy.type.tsym == syms.proprietaryType.tsym)
  1.1429 +                    sym.flags_field |= PROPRIETARY;
  1.1430 +                else if (proxy.type.tsym == syms.profileType.tsym) {
  1.1431 +                    if (profile != Profile.DEFAULT) {
  1.1432 +                        for (Pair<Name,Attribute> v: proxy.values) {
  1.1433 +                            if (v.fst == names.value && v.snd instanceof Attribute.Constant) {
  1.1434 +                                Attribute.Constant c = (Attribute.Constant) v.snd;
  1.1435 +                                if (c.type == syms.intType && ((Integer) c.value) > profile.value) {
  1.1436 +                                    sym.flags_field |= NOT_IN_PROFILE;
  1.1437 +                                }
  1.1438 +                            }
  1.1439 +                        }
  1.1440 +                    }
  1.1441 +                } else
  1.1442 +                    proxies.append(proxy);
  1.1443 +            }
  1.1444 +            annotate.normal(new AnnotationCompleter(sym, proxies.toList()));
  1.1445 +        }
  1.1446 +    }
  1.1447 +
  1.1448 +    /** Attach parameter annotations.
  1.1449 +     */
  1.1450 +    void attachParameterAnnotations(final Symbol method) {
  1.1451 +        final MethodSymbol meth = (MethodSymbol)method;
  1.1452 +        int numParameters = buf[bp++] & 0xFF;
  1.1453 +        List<VarSymbol> parameters = meth.params();
  1.1454 +        int pnum = 0;
  1.1455 +        while (parameters.tail != null) {
  1.1456 +            attachAnnotations(parameters.head);
  1.1457 +            parameters = parameters.tail;
  1.1458 +            pnum++;
  1.1459 +        }
  1.1460 +        if (pnum != numParameters) {
  1.1461 +            throw badClassFile("bad.runtime.invisible.param.annotations", meth);
  1.1462 +        }
  1.1463 +    }
  1.1464 +
  1.1465 +    void attachTypeAnnotations(final Symbol sym) {
  1.1466 +        int numAttributes = nextChar();
  1.1467 +        if (numAttributes != 0) {
  1.1468 +            ListBuffer<TypeAnnotationProxy> proxies = new ListBuffer<>();
  1.1469 +            for (int i = 0; i < numAttributes; i++)
  1.1470 +                proxies.append(readTypeAnnotation());
  1.1471 +            annotate.normal(new TypeAnnotationCompleter(sym, proxies.toList()));
  1.1472 +        }
  1.1473 +    }
  1.1474 +
  1.1475 +    /** Attach the default value for an annotation element.
  1.1476 +     */
  1.1477 +    void attachAnnotationDefault(final Symbol sym) {
  1.1478 +        final MethodSymbol meth = (MethodSymbol)sym; // only on methods
  1.1479 +        final Attribute value = readAttributeValue();
  1.1480 +
  1.1481 +        // The default value is set later during annotation. It might
  1.1482 +        // be the case that the Symbol sym is annotated _after_ the
  1.1483 +        // repeating instances that depend on this default value,
  1.1484 +        // because of this we set an interim value that tells us this
  1.1485 +        // element (most likely) has a default.
  1.1486 +        //
  1.1487 +        // Set interim value for now, reset just before we do this
  1.1488 +        // properly at annotate time.
  1.1489 +        meth.defaultValue = value;
  1.1490 +        annotate.normal(new AnnotationDefaultCompleter(meth, value));
  1.1491 +    }
  1.1492 +
  1.1493 +    Type readTypeOrClassSymbol(int i) {
  1.1494 +        // support preliminary jsr175-format class files
  1.1495 +        if (buf[poolIdx[i]] == CONSTANT_Class)
  1.1496 +            return readClassSymbol(i).type;
  1.1497 +        return readType(i);
  1.1498 +    }
  1.1499 +    Type readEnumType(int i) {
  1.1500 +        // support preliminary jsr175-format class files
  1.1501 +        int index = poolIdx[i];
  1.1502 +        int length = getChar(index + 1);
  1.1503 +        if (buf[index + length + 2] != ';')
  1.1504 +            return enterClass(readName(i)).type;
  1.1505 +        return readType(i);
  1.1506 +    }
  1.1507 +
  1.1508 +    CompoundAnnotationProxy readCompoundAnnotation() {
  1.1509 +        Type t = readTypeOrClassSymbol(nextChar());
  1.1510 +        int numFields = nextChar();
  1.1511 +        ListBuffer<Pair<Name,Attribute>> pairs =
  1.1512 +            new ListBuffer<Pair<Name,Attribute>>();
  1.1513 +        for (int i=0; i<numFields; i++) {
  1.1514 +            Name name = readName(nextChar());
  1.1515 +            Attribute value = readAttributeValue();
  1.1516 +            pairs.append(new Pair<Name,Attribute>(name, value));
  1.1517 +        }
  1.1518 +        return new CompoundAnnotationProxy(t, pairs.toList());
  1.1519 +    }
  1.1520 +
  1.1521 +    TypeAnnotationProxy readTypeAnnotation() {
  1.1522 +        TypeAnnotationPosition position = readPosition();
  1.1523 +        CompoundAnnotationProxy proxy = readCompoundAnnotation();
  1.1524 +
  1.1525 +        return new TypeAnnotationProxy(proxy, position);
  1.1526 +    }
  1.1527 +
  1.1528 +    TypeAnnotationPosition readPosition() {
  1.1529 +        int tag = nextByte(); // TargetType tag is a byte
  1.1530 +
  1.1531 +        if (!TargetType.isValidTargetTypeValue(tag))
  1.1532 +            throw this.badClassFile("bad.type.annotation.value", String.format("0x%02X", tag));
  1.1533 +
  1.1534 +        TypeAnnotationPosition position = new TypeAnnotationPosition();
  1.1535 +        TargetType type = TargetType.fromTargetTypeValue(tag);
  1.1536 +
  1.1537 +        position.type = type;
  1.1538 +
  1.1539 +        switch (type) {
  1.1540 +        // instanceof
  1.1541 +        case INSTANCEOF:
  1.1542 +        // new expression
  1.1543 +        case NEW:
  1.1544 +        // constructor/method reference receiver
  1.1545 +        case CONSTRUCTOR_REFERENCE:
  1.1546 +        case METHOD_REFERENCE:
  1.1547 +            position.offset = nextChar();
  1.1548 +            break;
  1.1549 +        // local variable
  1.1550 +        case LOCAL_VARIABLE:
  1.1551 +        // resource variable
  1.1552 +        case RESOURCE_VARIABLE:
  1.1553 +            int table_length = nextChar();
  1.1554 +            position.lvarOffset = new int[table_length];
  1.1555 +            position.lvarLength = new int[table_length];
  1.1556 +            position.lvarIndex = new int[table_length];
  1.1557 +
  1.1558 +            for (int i = 0; i < table_length; ++i) {
  1.1559 +                position.lvarOffset[i] = nextChar();
  1.1560 +                position.lvarLength[i] = nextChar();
  1.1561 +                position.lvarIndex[i] = nextChar();
  1.1562 +            }
  1.1563 +            break;
  1.1564 +        // exception parameter
  1.1565 +        case EXCEPTION_PARAMETER:
  1.1566 +            position.exception_index = nextChar();
  1.1567 +            break;
  1.1568 +        // method receiver
  1.1569 +        case METHOD_RECEIVER:
  1.1570 +            // Do nothing
  1.1571 +            break;
  1.1572 +        // type parameter
  1.1573 +        case CLASS_TYPE_PARAMETER:
  1.1574 +        case METHOD_TYPE_PARAMETER:
  1.1575 +            position.parameter_index = nextByte();
  1.1576 +            break;
  1.1577 +        // type parameter bound
  1.1578 +        case CLASS_TYPE_PARAMETER_BOUND:
  1.1579 +        case METHOD_TYPE_PARAMETER_BOUND:
  1.1580 +            position.parameter_index = nextByte();
  1.1581 +            position.bound_index = nextByte();
  1.1582 +            break;
  1.1583 +        // class extends or implements clause
  1.1584 +        case CLASS_EXTENDS:
  1.1585 +            position.type_index = nextChar();
  1.1586 +            break;
  1.1587 +        // throws
  1.1588 +        case THROWS:
  1.1589 +            position.type_index = nextChar();
  1.1590 +            break;
  1.1591 +        // method parameter
  1.1592 +        case METHOD_FORMAL_PARAMETER:
  1.1593 +            position.parameter_index = nextByte();
  1.1594 +            break;
  1.1595 +        // type cast
  1.1596 +        case CAST:
  1.1597 +        // method/constructor/reference type argument
  1.1598 +        case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
  1.1599 +        case METHOD_INVOCATION_TYPE_ARGUMENT:
  1.1600 +        case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
  1.1601 +        case METHOD_REFERENCE_TYPE_ARGUMENT:
  1.1602 +            position.offset = nextChar();
  1.1603 +            position.type_index = nextByte();
  1.1604 +            break;
  1.1605 +        // We don't need to worry about these
  1.1606 +        case METHOD_RETURN:
  1.1607 +        case FIELD:
  1.1608 +            break;
  1.1609 +        case UNKNOWN:
  1.1610 +            throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!");
  1.1611 +        default:
  1.1612 +            throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + position);
  1.1613 +        }
  1.1614 +
  1.1615 +        { // See whether there is location info and read it
  1.1616 +            int len = nextByte();
  1.1617 +            ListBuffer<Integer> loc = new ListBuffer<>();
  1.1618 +            for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i)
  1.1619 +                loc = loc.append(nextByte());
  1.1620 +            position.location = TypeAnnotationPosition.getTypePathFromBinary(loc.toList());
  1.1621 +        }
  1.1622 +
  1.1623 +        return position;
  1.1624 +    }
  1.1625 +
  1.1626 +    Attribute readAttributeValue() {
  1.1627 +        char c = (char) buf[bp++];
  1.1628 +        switch (c) {
  1.1629 +        case 'B':
  1.1630 +            return new Attribute.Constant(syms.byteType, readPool(nextChar()));
  1.1631 +        case 'C':
  1.1632 +            return new Attribute.Constant(syms.charType, readPool(nextChar()));
  1.1633 +        case 'D':
  1.1634 +            return new Attribute.Constant(syms.doubleType, readPool(nextChar()));
  1.1635 +        case 'F':
  1.1636 +            return new Attribute.Constant(syms.floatType, readPool(nextChar()));
  1.1637 +        case 'I':
  1.1638 +            return new Attribute.Constant(syms.intType, readPool(nextChar()));
  1.1639 +        case 'J':
  1.1640 +            return new Attribute.Constant(syms.longType, readPool(nextChar()));
  1.1641 +        case 'S':
  1.1642 +            return new Attribute.Constant(syms.shortType, readPool(nextChar()));
  1.1643 +        case 'Z':
  1.1644 +            return new Attribute.Constant(syms.booleanType, readPool(nextChar()));
  1.1645 +        case 's':
  1.1646 +            return new Attribute.Constant(syms.stringType, readPool(nextChar()).toString());
  1.1647 +        case 'e':
  1.1648 +            return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar()));
  1.1649 +        case 'c':
  1.1650 +            return new Attribute.Class(types, readTypeOrClassSymbol(nextChar()));
  1.1651 +        case '[': {
  1.1652 +            int n = nextChar();
  1.1653 +            ListBuffer<Attribute> l = new ListBuffer<Attribute>();
  1.1654 +            for (int i=0; i<n; i++)
  1.1655 +                l.append(readAttributeValue());
  1.1656 +            return new ArrayAttributeProxy(l.toList());
  1.1657 +        }
  1.1658 +        case '@':
  1.1659 +            return readCompoundAnnotation();
  1.1660 +        default:
  1.1661 +            throw new AssertionError("unknown annotation tag '" + c + "'");
  1.1662 +        }
  1.1663 +    }
  1.1664 +
  1.1665 +    interface ProxyVisitor extends Attribute.Visitor {
  1.1666 +        void visitEnumAttributeProxy(EnumAttributeProxy proxy);
  1.1667 +        void visitArrayAttributeProxy(ArrayAttributeProxy proxy);
  1.1668 +        void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy);
  1.1669 +    }
  1.1670 +
  1.1671 +    static class EnumAttributeProxy extends Attribute {
  1.1672 +        Type enumType;
  1.1673 +        Name enumerator;
  1.1674 +        public EnumAttributeProxy(Type enumType, Name enumerator) {
  1.1675 +            super(null);
  1.1676 +            this.enumType = enumType;
  1.1677 +            this.enumerator = enumerator;
  1.1678 +        }
  1.1679 +        public void accept(Visitor v) { ((ProxyVisitor)v).visitEnumAttributeProxy(this); }
  1.1680 +        @Override
  1.1681 +        public String toString() {
  1.1682 +            return "/*proxy enum*/" + enumType + "." + enumerator;
  1.1683 +        }
  1.1684 +    }
  1.1685 +
  1.1686 +    static class ArrayAttributeProxy extends Attribute {
  1.1687 +        List<Attribute> values;
  1.1688 +        ArrayAttributeProxy(List<Attribute> values) {
  1.1689 +            super(null);
  1.1690 +            this.values = values;
  1.1691 +        }
  1.1692 +        public void accept(Visitor v) { ((ProxyVisitor)v).visitArrayAttributeProxy(this); }
  1.1693 +        @Override
  1.1694 +        public String toString() {
  1.1695 +            return "{" + values + "}";
  1.1696 +        }
  1.1697 +    }
  1.1698 +
  1.1699 +    /** A temporary proxy representing a compound attribute.
  1.1700 +     */
  1.1701 +    static class CompoundAnnotationProxy extends Attribute {
  1.1702 +        final List<Pair<Name,Attribute>> values;
  1.1703 +        public CompoundAnnotationProxy(Type type,
  1.1704 +                                      List<Pair<Name,Attribute>> values) {
  1.1705 +            super(type);
  1.1706 +            this.values = values;
  1.1707 +        }
  1.1708 +        public void accept(Visitor v) { ((ProxyVisitor)v).visitCompoundAnnotationProxy(this); }
  1.1709 +        @Override
  1.1710 +        public String toString() {
  1.1711 +            StringBuilder buf = new StringBuilder();
  1.1712 +            buf.append("@");
  1.1713 +            buf.append(type.tsym.getQualifiedName());
  1.1714 +            buf.append("/*proxy*/{");
  1.1715 +            boolean first = true;
  1.1716 +            for (List<Pair<Name,Attribute>> v = values;
  1.1717 +                 v.nonEmpty(); v = v.tail) {
  1.1718 +                Pair<Name,Attribute> value = v.head;
  1.1719 +                if (!first) buf.append(",");
  1.1720 +                first = false;
  1.1721 +                buf.append(value.fst);
  1.1722 +                buf.append("=");
  1.1723 +                buf.append(value.snd);
  1.1724 +            }
  1.1725 +            buf.append("}");
  1.1726 +            return buf.toString();
  1.1727 +        }
  1.1728 +    }
  1.1729 +
  1.1730 +    /** A temporary proxy representing a type annotation.
  1.1731 +     */
  1.1732 +    static class TypeAnnotationProxy {
  1.1733 +        final CompoundAnnotationProxy compound;
  1.1734 +        final TypeAnnotationPosition position;
  1.1735 +        public TypeAnnotationProxy(CompoundAnnotationProxy compound,
  1.1736 +                TypeAnnotationPosition position) {
  1.1737 +            this.compound = compound;
  1.1738 +            this.position = position;
  1.1739 +        }
  1.1740 +    }
  1.1741 +
  1.1742 +    class AnnotationDeproxy implements ProxyVisitor {
  1.1743 +        private ClassSymbol requestingOwner = currentOwner.kind == MTH
  1.1744 +            ? currentOwner.enclClass() : (ClassSymbol)currentOwner;
  1.1745 +
  1.1746 +        List<Attribute.Compound> deproxyCompoundList(List<CompoundAnnotationProxy> pl) {
  1.1747 +            // also must fill in types!!!!
  1.1748 +            ListBuffer<Attribute.Compound> buf =
  1.1749 +                new ListBuffer<Attribute.Compound>();
  1.1750 +            for (List<CompoundAnnotationProxy> l = pl; l.nonEmpty(); l=l.tail) {
  1.1751 +                buf.append(deproxyCompound(l.head));
  1.1752 +            }
  1.1753 +            return buf.toList();
  1.1754 +        }
  1.1755 +
  1.1756 +        Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) {
  1.1757 +            ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf =
  1.1758 +                new ListBuffer<Pair<Symbol.MethodSymbol,Attribute>>();
  1.1759 +            for (List<Pair<Name,Attribute>> l = a.values;
  1.1760 +                 l.nonEmpty();
  1.1761 +                 l = l.tail) {
  1.1762 +                MethodSymbol meth = findAccessMethod(a.type, l.head.fst);
  1.1763 +                buf.append(new Pair<Symbol.MethodSymbol,Attribute>
  1.1764 +                           (meth, deproxy(meth.type.getReturnType(), l.head.snd)));
  1.1765 +            }
  1.1766 +            return new Attribute.Compound(a.type, buf.toList());
  1.1767 +        }
  1.1768 +
  1.1769 +        MethodSymbol findAccessMethod(Type container, Name name) {
  1.1770 +            CompletionFailure failure = null;
  1.1771 +            try {
  1.1772 +                for (Scope.Entry e = container.tsym.members().lookup(name);
  1.1773 +                     e.scope != null;
  1.1774 +                     e = e.next()) {
  1.1775 +                    Symbol sym = e.sym;
  1.1776 +                    if (sym.kind == MTH && sym.type.getParameterTypes().length() == 0)
  1.1777 +                        return (MethodSymbol) sym;
  1.1778 +                }
  1.1779 +            } catch (CompletionFailure ex) {
  1.1780 +                failure = ex;
  1.1781 +            }
  1.1782 +            // The method wasn't found: emit a warning and recover
  1.1783 +            JavaFileObject prevSource = log.useSource(requestingOwner.classfile);
  1.1784 +            try {
  1.1785 +                if (failure == null) {
  1.1786 +                    log.warning("annotation.method.not.found",
  1.1787 +                                container,
  1.1788 +                                name);
  1.1789 +                } else {
  1.1790 +                    log.warning("annotation.method.not.found.reason",
  1.1791 +                                container,
  1.1792 +                                name,
  1.1793 +                                failure.getDetailValue());//diagnostic, if present
  1.1794 +                }
  1.1795 +            } finally {
  1.1796 +                log.useSource(prevSource);
  1.1797 +            }
  1.1798 +            // Construct a new method type and symbol.  Use bottom
  1.1799 +            // type (typeof null) as return type because this type is
  1.1800 +            // a subtype of all reference types and can be converted
  1.1801 +            // to primitive types by unboxing.
  1.1802 +            MethodType mt = new MethodType(List.<Type>nil(),
  1.1803 +                                           syms.botType,
  1.1804 +                                           List.<Type>nil(),
  1.1805 +                                           syms.methodClass);
  1.1806 +            return new MethodSymbol(PUBLIC | ABSTRACT, name, mt, container.tsym);
  1.1807 +        }
  1.1808 +
  1.1809 +        Attribute result;
  1.1810 +        Type type;
  1.1811 +        Attribute deproxy(Type t, Attribute a) {
  1.1812 +            Type oldType = type;
  1.1813 +            try {
  1.1814 +                type = t;
  1.1815 +                a.accept(this);
  1.1816 +                return result;
  1.1817 +            } finally {
  1.1818 +                type = oldType;
  1.1819 +            }
  1.1820 +        }
  1.1821 +
  1.1822 +        // implement Attribute.Visitor below
  1.1823 +
  1.1824 +        public void visitConstant(Attribute.Constant value) {
  1.1825 +            // assert value.type == type;
  1.1826 +            result = value;
  1.1827 +        }
  1.1828 +
  1.1829 +        public void visitClass(Attribute.Class clazz) {
  1.1830 +            result = clazz;
  1.1831 +        }
  1.1832 +
  1.1833 +        public void visitEnum(Attribute.Enum e) {
  1.1834 +            throw new AssertionError(); // shouldn't happen
  1.1835 +        }
  1.1836 +
  1.1837 +        public void visitCompound(Attribute.Compound compound) {
  1.1838 +            throw new AssertionError(); // shouldn't happen
  1.1839 +        }
  1.1840 +
  1.1841 +        public void visitArray(Attribute.Array array) {
  1.1842 +            throw new AssertionError(); // shouldn't happen
  1.1843 +        }
  1.1844 +
  1.1845 +        public void visitError(Attribute.Error e) {
  1.1846 +            throw new AssertionError(); // shouldn't happen
  1.1847 +        }
  1.1848 +
  1.1849 +        public void visitEnumAttributeProxy(EnumAttributeProxy proxy) {
  1.1850 +            // type.tsym.flatName() should == proxy.enumFlatName
  1.1851 +            TypeSymbol enumTypeSym = proxy.enumType.tsym;
  1.1852 +            VarSymbol enumerator = null;
  1.1853 +            CompletionFailure failure = null;
  1.1854 +            try {
  1.1855 +                for (Scope.Entry e = enumTypeSym.members().lookup(proxy.enumerator);
  1.1856 +                     e.scope != null;
  1.1857 +                     e = e.next()) {
  1.1858 +                    if (e.sym.kind == VAR) {
  1.1859 +                        enumerator = (VarSymbol)e.sym;
  1.1860 +                        break;
  1.1861 +                    }
  1.1862 +                }
  1.1863 +            }
  1.1864 +            catch (CompletionFailure ex) {
  1.1865 +                failure = ex;
  1.1866 +            }
  1.1867 +            if (enumerator == null) {
  1.1868 +                if (failure != null) {
  1.1869 +                    log.warning("unknown.enum.constant.reason",
  1.1870 +                              currentClassFile, enumTypeSym, proxy.enumerator,
  1.1871 +                              failure.getDiagnostic());
  1.1872 +                } else {
  1.1873 +                    log.warning("unknown.enum.constant",
  1.1874 +                              currentClassFile, enumTypeSym, proxy.enumerator);
  1.1875 +                }
  1.1876 +                result = new Attribute.Enum(enumTypeSym.type,
  1.1877 +                        new VarSymbol(0, proxy.enumerator, syms.botType, enumTypeSym));
  1.1878 +            } else {
  1.1879 +                result = new Attribute.Enum(enumTypeSym.type, enumerator);
  1.1880 +            }
  1.1881 +        }
  1.1882 +
  1.1883 +        public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) {
  1.1884 +            int length = proxy.values.length();
  1.1885 +            Attribute[] ats = new Attribute[length];
  1.1886 +            Type elemtype = types.elemtype(type);
  1.1887 +            int i = 0;
  1.1888 +            for (List<Attribute> p = proxy.values; p.nonEmpty(); p = p.tail) {
  1.1889 +                ats[i++] = deproxy(elemtype, p.head);
  1.1890 +            }
  1.1891 +            result = new Attribute.Array(type, ats);
  1.1892 +        }
  1.1893 +
  1.1894 +        public void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy) {
  1.1895 +            result = deproxyCompound(proxy);
  1.1896 +        }
  1.1897 +    }
  1.1898 +
  1.1899 +    class AnnotationDefaultCompleter extends AnnotationDeproxy implements Annotate.Worker {
  1.1900 +        final MethodSymbol sym;
  1.1901 +        final Attribute value;
  1.1902 +        final JavaFileObject classFile = currentClassFile;
  1.1903 +        @Override
  1.1904 +        public String toString() {
  1.1905 +            return " ClassReader store default for " + sym.owner + "." + sym + " is " + value;
  1.1906 +        }
  1.1907 +        AnnotationDefaultCompleter(MethodSymbol sym, Attribute value) {
  1.1908 +            this.sym = sym;
  1.1909 +            this.value = value;
  1.1910 +        }
  1.1911 +        // implement Annotate.Worker.run()
  1.1912 +        public void run() {
  1.1913 +            JavaFileObject previousClassFile = currentClassFile;
  1.1914 +            try {
  1.1915 +                // Reset the interim value set earlier in
  1.1916 +                // attachAnnotationDefault().
  1.1917 +                sym.defaultValue = null;
  1.1918 +                currentClassFile = classFile;
  1.1919 +                sym.defaultValue = deproxy(sym.type.getReturnType(), value);
  1.1920 +            } finally {
  1.1921 +                currentClassFile = previousClassFile;
  1.1922 +            }
  1.1923 +        }
  1.1924 +    }
  1.1925 +
  1.1926 +    class AnnotationCompleter extends AnnotationDeproxy implements Annotate.Worker {
  1.1927 +        final Symbol sym;
  1.1928 +        final List<CompoundAnnotationProxy> l;
  1.1929 +        final JavaFileObject classFile;
  1.1930 +        @Override
  1.1931 +        public String toString() {
  1.1932 +            return " ClassReader annotate " + sym.owner + "." + sym + " with " + l;
  1.1933 +        }
  1.1934 +        AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) {
  1.1935 +            this.sym = sym;
  1.1936 +            this.l = l;
  1.1937 +            this.classFile = currentClassFile;
  1.1938 +        }
  1.1939 +        // implement Annotate.Worker.run()
  1.1940 +        public void run() {
  1.1941 +            JavaFileObject previousClassFile = currentClassFile;
  1.1942 +            try {
  1.1943 +                currentClassFile = classFile;
  1.1944 +                List<Attribute.Compound> newList = deproxyCompoundList(l);
  1.1945 +                if (sym.annotationsPendingCompletion()) {
  1.1946 +                    sym.setDeclarationAttributes(newList);
  1.1947 +                } else {
  1.1948 +                    sym.appendAttributes(newList);
  1.1949 +                }
  1.1950 +            } finally {
  1.1951 +                currentClassFile = previousClassFile;
  1.1952 +            }
  1.1953 +        }
  1.1954 +    }
  1.1955 +
  1.1956 +    class TypeAnnotationCompleter extends AnnotationCompleter {
  1.1957 +
  1.1958 +        List<TypeAnnotationProxy> proxies;
  1.1959 +
  1.1960 +        TypeAnnotationCompleter(Symbol sym,
  1.1961 +                List<TypeAnnotationProxy> proxies) {
  1.1962 +            super(sym, List.<CompoundAnnotationProxy>nil());
  1.1963 +            this.proxies = proxies;
  1.1964 +        }
  1.1965 +
  1.1966 +        List<Attribute.TypeCompound> deproxyTypeCompoundList(List<TypeAnnotationProxy> proxies) {
  1.1967 +            ListBuffer<Attribute.TypeCompound> buf = new ListBuffer<>();
  1.1968 +            for (TypeAnnotationProxy proxy: proxies) {
  1.1969 +                Attribute.Compound compound = deproxyCompound(proxy.compound);
  1.1970 +                Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position);
  1.1971 +                buf.add(typeCompound);
  1.1972 +            }
  1.1973 +            return buf.toList();
  1.1974 +        }
  1.1975 +
  1.1976 +        @Override
  1.1977 +        public void run() {
  1.1978 +            JavaFileObject previousClassFile = currentClassFile;
  1.1979 +            try {
  1.1980 +                currentClassFile = classFile;
  1.1981 +                List<Attribute.TypeCompound> newList = deproxyTypeCompoundList(proxies);
  1.1982 +                sym.setTypeAttributes(newList.prependList(sym.getRawTypeAttributes()));
  1.1983 +            } finally {
  1.1984 +                currentClassFile = previousClassFile;
  1.1985 +            }
  1.1986 +        }
  1.1987 +    }
  1.1988 +
  1.1989 +
  1.1990 +/************************************************************************
  1.1991 + * Reading Symbols
  1.1992 + ***********************************************************************/
  1.1993 +
  1.1994 +    /** Read a field.
  1.1995 +     */
  1.1996 +    VarSymbol readField() {
  1.1997 +        long flags = adjustFieldFlags(nextChar());
  1.1998 +        Name name = readName(nextChar());
  1.1999 +        Type type = readType(nextChar());
  1.2000 +        VarSymbol v = new VarSymbol(flags, name, type, currentOwner);
  1.2001 +        readMemberAttrs(v);
  1.2002 +        return v;
  1.2003 +    }
  1.2004 +
  1.2005 +    /** Read a method.
  1.2006 +     */
  1.2007 +    MethodSymbol readMethod() {
  1.2008 +        long flags = adjustMethodFlags(nextChar());
  1.2009 +        Name name = readName(nextChar());
  1.2010 +        Type type = readType(nextChar());
  1.2011 +        if (currentOwner.isInterface() &&
  1.2012 +                (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
  1.2013 +            if (majorVersion > Target.JDK1_8.majorVersion ||
  1.2014 +                    (majorVersion == Target.JDK1_8.majorVersion && minorVersion >= Target.JDK1_8.minorVersion)) {
  1.2015 +                if ((flags & STATIC) == 0) {
  1.2016 +                    currentOwner.flags_field |= DEFAULT;
  1.2017 +                    flags |= DEFAULT | ABSTRACT;
  1.2018 +                }
  1.2019 +            } else {
  1.2020 +                //protect against ill-formed classfiles
  1.2021 +                throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface",
  1.2022 +                                   Integer.toString(majorVersion),
  1.2023 +                                   Integer.toString(minorVersion));
  1.2024 +            }
  1.2025 +        }
  1.2026 +        if (name == names.init && currentOwner.hasOuterInstance()) {
  1.2027 +            // Sometimes anonymous classes don't have an outer
  1.2028 +            // instance, however, there is no reliable way to tell so
  1.2029 +            // we never strip this$n
  1.2030 +            if (!currentOwner.name.isEmpty())
  1.2031 +                type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()),
  1.2032 +                                      type.getReturnType(),
  1.2033 +                                      type.getThrownTypes(),
  1.2034 +                                      syms.methodClass);
  1.2035 +        }
  1.2036 +        MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
  1.2037 +        if (types.isSignaturePolymorphic(m)) {
  1.2038 +            m.flags_field |= SIGNATURE_POLYMORPHIC;
  1.2039 +        }
  1.2040 +        if (saveParameterNames)
  1.2041 +            initParameterNames(m);
  1.2042 +        Symbol prevOwner = currentOwner;
  1.2043 +        currentOwner = m;
  1.2044 +        try {
  1.2045 +            readMemberAttrs(m);
  1.2046 +        } finally {
  1.2047 +            currentOwner = prevOwner;
  1.2048 +        }
  1.2049 +        if (saveParameterNames)
  1.2050 +            setParameterNames(m, type);
  1.2051 +        return m;
  1.2052 +    }
  1.2053 +
  1.2054 +    private List<Type> adjustMethodParams(long flags, List<Type> args) {
  1.2055 +        boolean isVarargs = (flags & VARARGS) != 0;
  1.2056 +        if (isVarargs) {
  1.2057 +            Type varargsElem = args.last();
  1.2058 +            ListBuffer<Type> adjustedArgs = new ListBuffer<>();
  1.2059 +            for (Type t : args) {
  1.2060 +                adjustedArgs.append(t != varargsElem ?
  1.2061 +                    t :
  1.2062 +                    ((ArrayType)t).makeVarargs());
  1.2063 +            }
  1.2064 +            args = adjustedArgs.toList();
  1.2065 +        }
  1.2066 +        return args.tail;
  1.2067 +    }
  1.2068 +
  1.2069 +    /**
  1.2070 +     * Init the parameter names array.
  1.2071 +     * Parameter names are currently inferred from the names in the
  1.2072 +     * LocalVariableTable attributes of a Code attribute.
  1.2073 +     * (Note: this means parameter names are currently not available for
  1.2074 +     * methods without a Code attribute.)
  1.2075 +     * This method initializes an array in which to store the name indexes
  1.2076 +     * of parameter names found in LocalVariableTable attributes. It is
  1.2077 +     * slightly supersized to allow for additional slots with a start_pc of 0.
  1.2078 +     */
  1.2079 +    void initParameterNames(MethodSymbol sym) {
  1.2080 +        // make allowance for synthetic parameters.
  1.2081 +        final int excessSlots = 4;
  1.2082 +        int expectedParameterSlots =
  1.2083 +                Code.width(sym.type.getParameterTypes()) + excessSlots;
  1.2084 +        if (parameterNameIndices == null
  1.2085 +                || parameterNameIndices.length < expectedParameterSlots) {
  1.2086 +            parameterNameIndices = new int[expectedParameterSlots];
  1.2087 +        } else
  1.2088 +            Arrays.fill(parameterNameIndices, 0);
  1.2089 +        haveParameterNameIndices = false;
  1.2090 +        sawMethodParameters = false;
  1.2091 +    }
  1.2092 +
  1.2093 +    /**
  1.2094 +     * Set the parameter names for a symbol from the name index in the
  1.2095 +     * parameterNameIndicies array. The type of the symbol may have changed
  1.2096 +     * while reading the method attributes (see the Signature attribute).
  1.2097 +     * This may be because of generic information or because anonymous
  1.2098 +     * synthetic parameters were added.   The original type (as read from
  1.2099 +     * the method descriptor) is used to help guess the existence of
  1.2100 +     * anonymous synthetic parameters.
  1.2101 +     * On completion, sym.savedParameter names will either be null (if
  1.2102 +     * no parameter names were found in the class file) or will be set to a
  1.2103 +     * list of names, one per entry in sym.type.getParameterTypes, with
  1.2104 +     * any missing names represented by the empty name.
  1.2105 +     */
  1.2106 +    void setParameterNames(MethodSymbol sym, Type jvmType) {
  1.2107 +        // if no names were found in the class file, there's nothing more to do
  1.2108 +        if (!haveParameterNameIndices)
  1.2109 +            return;
  1.2110 +        // If we get parameter names from MethodParameters, then we
  1.2111 +        // don't need to skip.
  1.2112 +        int firstParam = 0;
  1.2113 +        if (!sawMethodParameters) {
  1.2114 +            firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
  1.2115 +            // the code in readMethod may have skipped the first
  1.2116 +            // parameter when setting up the MethodType. If so, we
  1.2117 +            // make a corresponding allowance here for the position of
  1.2118 +            // the first parameter.  Note that this assumes the
  1.2119 +            // skipped parameter has a width of 1 -- i.e. it is not
  1.2120 +        // a double width type (long or double.)
  1.2121 +        if (sym.name == names.init && currentOwner.hasOuterInstance()) {
  1.2122 +            // Sometimes anonymous classes don't have an outer
  1.2123 +            // instance, however, there is no reliable way to tell so
  1.2124 +            // we never strip this$n
  1.2125 +            if (!currentOwner.name.isEmpty())
  1.2126 +                firstParam += 1;
  1.2127 +        }
  1.2128 +
  1.2129 +        if (sym.type != jvmType) {
  1.2130 +                // reading the method attributes has caused the
  1.2131 +                // symbol's type to be changed. (i.e. the Signature
  1.2132 +                // attribute.)  This may happen if there are hidden
  1.2133 +                // (synthetic) parameters in the descriptor, but not
  1.2134 +                // in the Signature.  The position of these hidden
  1.2135 +                // parameters is unspecified; for now, assume they are
  1.2136 +                // at the beginning, and so skip over them. The
  1.2137 +                // primary case for this is two hidden parameters
  1.2138 +                // passed into Enum constructors.
  1.2139 +            int skip = Code.width(jvmType.getParameterTypes())
  1.2140 +                    - Code.width(sym.type.getParameterTypes());
  1.2141 +            firstParam += skip;
  1.2142 +        }
  1.2143 +        }
  1.2144 +        List<Name> paramNames = List.nil();
  1.2145 +        int index = firstParam;
  1.2146 +        for (Type t: sym.type.getParameterTypes()) {
  1.2147 +            int nameIdx = (index < parameterNameIndices.length
  1.2148 +                    ? parameterNameIndices[index] : 0);
  1.2149 +            Name name = nameIdx == 0 ? names.empty : readName(nameIdx);
  1.2150 +            paramNames = paramNames.prepend(name);
  1.2151 +            index += Code.width(t);
  1.2152 +        }
  1.2153 +        sym.savedParameterNames = paramNames.reverse();
  1.2154 +    }
  1.2155 +
  1.2156 +    /**
  1.2157 +     * skip n bytes
  1.2158 +     */
  1.2159 +    void skipBytes(int n) {
  1.2160 +        bp = bp + n;
  1.2161 +    }
  1.2162 +
  1.2163 +    /** Skip a field or method
  1.2164 +     */
  1.2165 +    void skipMember() {
  1.2166 +        bp = bp + 6;
  1.2167 +        char ac = nextChar();
  1.2168 +        for (int i = 0; i < ac; i++) {
  1.2169 +            bp = bp + 2;
  1.2170 +            int attrLen = nextInt();
  1.2171 +            bp = bp + attrLen;
  1.2172 +        }
  1.2173 +    }
  1.2174 +
  1.2175 +    /** Enter type variables of this classtype and all enclosing ones in
  1.2176 +     *  `typevars'.
  1.2177 +     */
  1.2178 +    protected void enterTypevars(Type t) {
  1.2179 +        if (t.getEnclosingType() != null && t.getEnclosingType().hasTag(CLASS))
  1.2180 +            enterTypevars(t.getEnclosingType());
  1.2181 +        for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail)
  1.2182 +            typevars.enter(xs.head.tsym);
  1.2183 +    }
  1.2184 +
  1.2185 +    protected void enterTypevars(Symbol sym) {
  1.2186 +        if (sym.owner.kind == MTH) {
  1.2187 +            enterTypevars(sym.owner);
  1.2188 +            enterTypevars(sym.owner.owner);
  1.2189 +        }
  1.2190 +        enterTypevars(sym.type);
  1.2191 +    }
  1.2192 +
  1.2193 +    /** Read contents of a given class symbol `c'. Both external and internal
  1.2194 +     *  versions of an inner class are read.
  1.2195 +     */
  1.2196 +    void readClass(ClassSymbol c) {
  1.2197 +        ClassType ct = (ClassType)c.type;
  1.2198 +
  1.2199 +        // allocate scope for members
  1.2200 +        c.members_field = new Scope(c);
  1.2201 +
  1.2202 +        // prepare type variable table
  1.2203 +        typevars = typevars.dup(currentOwner);
  1.2204 +        if (ct.getEnclosingType().hasTag(CLASS))
  1.2205 +            enterTypevars(ct.getEnclosingType());
  1.2206 +
  1.2207 +        // read flags, or skip if this is an inner class
  1.2208 +        long flags = adjustClassFlags(nextChar());
  1.2209 +        if (c.owner.kind == PCK) c.flags_field = flags;
  1.2210 +
  1.2211 +        // read own class name and check that it matches
  1.2212 +        ClassSymbol self = readClassSymbol(nextChar());
  1.2213 +        if (c != self)
  1.2214 +            throw badClassFile("class.file.wrong.class",
  1.2215 +                               self.flatname);
  1.2216 +
  1.2217 +        // class attributes must be read before class
  1.2218 +        // skip ahead to read class attributes
  1.2219 +        int startbp = bp;
  1.2220 +        nextChar();
  1.2221 +        char interfaceCount = nextChar();
  1.2222 +        bp += interfaceCount * 2;
  1.2223 +        char fieldCount = nextChar();
  1.2224 +        for (int i = 0; i < fieldCount; i++) skipMember();
  1.2225 +        char methodCount = nextChar();
  1.2226 +        for (int i = 0; i < methodCount; i++) skipMember();
  1.2227 +        readClassAttrs(c);
  1.2228 +
  1.2229 +        if (readAllOfClassFile) {
  1.2230 +            for (int i = 1; i < poolObj.length; i++) readPool(i);
  1.2231 +            c.pool = new Pool(poolObj.length, poolObj, types);
  1.2232 +        }
  1.2233 +
  1.2234 +        // reset and read rest of classinfo
  1.2235 +        bp = startbp;
  1.2236 +        int n = nextChar();
  1.2237 +        if (ct.supertype_field == null)
  1.2238 +            ct.supertype_field = (n == 0)
  1.2239 +                ? Type.noType
  1.2240 +                : readClassSymbol(n).erasure(types);
  1.2241 +        n = nextChar();
  1.2242 +        List<Type> is = List.nil();
  1.2243 +        for (int i = 0; i < n; i++) {
  1.2244 +            Type _inter = readClassSymbol(nextChar()).erasure(types);
  1.2245 +            is = is.prepend(_inter);
  1.2246 +        }
  1.2247 +        if (ct.interfaces_field == null)
  1.2248 +            ct.interfaces_field = is.reverse();
  1.2249 +
  1.2250 +        Assert.check(fieldCount == nextChar());
  1.2251 +        for (int i = 0; i < fieldCount; i++) enterMember(c, readField());
  1.2252 +        Assert.check(methodCount == nextChar());
  1.2253 +        for (int i = 0; i < methodCount; i++) enterMember(c, readMethod());
  1.2254 +
  1.2255 +        typevars = typevars.leave();
  1.2256 +    }
  1.2257 +
  1.2258 +    /** Read inner class info. For each inner/outer pair allocate a
  1.2259 +     *  member class.
  1.2260 +     */
  1.2261 +    void readInnerClasses(ClassSymbol c) {
  1.2262 +        int n = nextChar();
  1.2263 +        for (int i = 0; i < n; i++) {
  1.2264 +            nextChar(); // skip inner class symbol
  1.2265 +            ClassSymbol outer = readClassSymbol(nextChar());
  1.2266 +            Name name = readName(nextChar());
  1.2267 +            if (name == null) name = names.empty;
  1.2268 +            long flags = adjustClassFlags(nextChar());
  1.2269 +            if (outer != null) { // we have a member class
  1.2270 +                if (name == names.empty)
  1.2271 +                    name = names.one;
  1.2272 +                ClassSymbol member = enterClass(name, outer);
  1.2273 +                if ((flags & STATIC) == 0) {
  1.2274 +                    ((ClassType)member.type).setEnclosingType(outer.type);
  1.2275 +                    if (member.erasure_field != null)
  1.2276 +                        ((ClassType)member.erasure_field).setEnclosingType(types.erasure(outer.type));
  1.2277 +                }
  1.2278 +                if (c == outer) {
  1.2279 +                    member.flags_field = flags;
  1.2280 +                    enterMember(c, member);
  1.2281 +                }
  1.2282 +            }
  1.2283 +        }
  1.2284 +    }
  1.2285 +
  1.2286 +    /** Read a class file.
  1.2287 +     */
  1.2288 +    private void readClassFile(ClassSymbol c) throws IOException {
  1.2289 +        int magic = nextInt();
  1.2290 +        if (magic != JAVA_MAGIC)
  1.2291 +            throw badClassFile("illegal.start.of.class.file");
  1.2292 +
  1.2293 +        minorVersion = nextChar();
  1.2294 +        majorVersion = nextChar();
  1.2295 +        int maxMajor = Target.MAX().majorVersion;
  1.2296 +        int maxMinor = Target.MAX().minorVersion;
  1.2297 +        if (majorVersion > maxMajor ||
  1.2298 +            majorVersion * 1000 + minorVersion <
  1.2299 +            Target.MIN().majorVersion * 1000 + Target.MIN().minorVersion)
  1.2300 +        {
  1.2301 +            if (majorVersion == (maxMajor + 1))
  1.2302 +                log.warning("big.major.version",
  1.2303 +                            currentClassFile,
  1.2304 +                            majorVersion,
  1.2305 +                            maxMajor);
  1.2306 +            else
  1.2307 +                throw badClassFile("wrong.version",
  1.2308 +                                   Integer.toString(majorVersion),
  1.2309 +                                   Integer.toString(minorVersion),
  1.2310 +                                   Integer.toString(maxMajor),
  1.2311 +                                   Integer.toString(maxMinor));
  1.2312 +        }
  1.2313 +        else if (checkClassFile &&
  1.2314 +                 majorVersion == maxMajor &&
  1.2315 +                 minorVersion > maxMinor)
  1.2316 +        {
  1.2317 +            printCCF("found.later.version",
  1.2318 +                     Integer.toString(minorVersion));
  1.2319 +        }
  1.2320 +        indexPool();
  1.2321 +        if (signatureBuffer.length < bp) {
  1.2322 +            int ns = Integer.highestOneBit(bp) << 1;
  1.2323 +            signatureBuffer = new byte[ns];
  1.2324 +        }
  1.2325 +        readClass(c);
  1.2326 +    }
  1.2327 +
  1.2328 +/************************************************************************
  1.2329 + * Adjusting flags
  1.2330 + ***********************************************************************/
  1.2331 +
  1.2332 +    long adjustFieldFlags(long flags) {
  1.2333 +        return flags;
  1.2334 +    }
  1.2335 +    long adjustMethodFlags(long flags) {
  1.2336 +        if ((flags & ACC_BRIDGE) != 0) {
  1.2337 +            flags &= ~ACC_BRIDGE;
  1.2338 +            flags |= BRIDGE;
  1.2339 +            if (!allowGenerics)
  1.2340 +                flags &= ~SYNTHETIC;
  1.2341 +        }
  1.2342 +        if ((flags & ACC_VARARGS) != 0) {
  1.2343 +            flags &= ~ACC_VARARGS;
  1.2344 +            flags |= VARARGS;
  1.2345 +        }
  1.2346 +        return flags;
  1.2347 +    }
  1.2348 +    long adjustClassFlags(long flags) {
  1.2349 +        return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
  1.2350 +    }
  1.2351 +
  1.2352 +/************************************************************************
  1.2353 + * Loading Classes
  1.2354 + ***********************************************************************/
  1.2355 +
  1.2356 +    /** Define a new class given its name and owner.
  1.2357 +     */
  1.2358 +    public ClassSymbol defineClass(Name name, Symbol owner) {
  1.2359 +        ClassSymbol c = new ClassSymbol(0, name, owner);
  1.2360 +        if (owner.kind == PCK)
  1.2361 +            Assert.checkNull(classes.get(c.flatname), c);
  1.2362 +        c.completer = thisCompleter;
  1.2363 +        return c;
  1.2364 +    }
  1.2365 +
  1.2366 +    /** Create a new toplevel or member class symbol with given name
  1.2367 +     *  and owner and enter in `classes' unless already there.
  1.2368 +     */
  1.2369 +    public ClassSymbol enterClass(Name name, TypeSymbol owner) {
  1.2370 +        Name flatname = TypeSymbol.formFlatName(name, owner);
  1.2371 +        ClassSymbol c = classes.get(flatname);
  1.2372 +        if (c == null) {
  1.2373 +            c = defineClass(name, owner);
  1.2374 +            classes.put(flatname, c);
  1.2375 +        } else if ((c.name != name || c.owner != owner) && owner.kind == TYP && c.owner.kind == PCK) {
  1.2376 +            // reassign fields of classes that might have been loaded with
  1.2377 +            // their flat names.
  1.2378 +            c.owner.members().remove(c);
  1.2379 +            c.name = name;
  1.2380 +            c.owner = owner;
  1.2381 +            c.fullname = ClassSymbol.formFullName(name, owner);
  1.2382 +        }
  1.2383 +        return c;
  1.2384 +    }
  1.2385 +
  1.2386 +    /**
  1.2387 +     * Creates a new toplevel class symbol with given flat name and
  1.2388 +     * given class (or source) file.
  1.2389 +     *
  1.2390 +     * @param flatName a fully qualified binary class name
  1.2391 +     * @param classFile the class file or compilation unit defining
  1.2392 +     * the class (may be {@code null})
  1.2393 +     * @return a newly created class symbol
  1.2394 +     * @throws AssertionError if the class symbol already exists
  1.2395 +     */
  1.2396 +    public ClassSymbol enterClass(Name flatName, JavaFileObject classFile) {
  1.2397 +        ClassSymbol cs = classes.get(flatName);
  1.2398 +        if (cs != null) {
  1.2399 +            String msg = Log.format("%s: completer = %s; class file = %s; source file = %s",
  1.2400 +                                    cs.fullname,
  1.2401 +                                    cs.completer,
  1.2402 +                                    cs.classfile,
  1.2403 +                                    cs.sourcefile);
  1.2404 +            throw new AssertionError(msg);
  1.2405 +        }
  1.2406 +        Name packageName = Convert.packagePart(flatName);
  1.2407 +        PackageSymbol owner = packageName.isEmpty()
  1.2408 +                                ? syms.unnamedPackage
  1.2409 +                                : enterPackage(packageName);
  1.2410 +        cs = defineClass(Convert.shortName(flatName), owner);
  1.2411 +        cs.classfile = classFile;
  1.2412 +        classes.put(flatName, cs);
  1.2413 +        return cs;
  1.2414 +    }
  1.2415 +
  1.2416 +    /** Create a new member or toplevel class symbol with given flat name
  1.2417 +     *  and enter in `classes' unless already there.
  1.2418 +     */
  1.2419 +    public ClassSymbol enterClass(Name flatname) {
  1.2420 +        ClassSymbol c = classes.get(flatname);
  1.2421 +        if (c == null)
  1.2422 +            return enterClass(flatname, (JavaFileObject)null);
  1.2423 +        else
  1.2424 +            return c;
  1.2425 +    }
  1.2426 +
  1.2427 +    /** Completion for classes to be loaded. Before a class is loaded
  1.2428 +     *  we make sure its enclosing class (if any) is loaded.
  1.2429 +     */
  1.2430 +    private void complete(Symbol sym) throws CompletionFailure {
  1.2431 +        if (sym.kind == TYP) {
  1.2432 +            ClassSymbol c = (ClassSymbol)sym;
  1.2433 +            c.members_field = new Scope.ErrorScope(c); // make sure it's always defined
  1.2434 +            annotate.enterStart();
  1.2435 +            try {
  1.2436 +                completeOwners(c.owner);
  1.2437 +                completeEnclosing(c);
  1.2438 +            } finally {
  1.2439 +                // The flush needs to happen only after annotations
  1.2440 +                // are filled in.
  1.2441 +                annotate.enterDoneWithoutFlush();
  1.2442 +            }
  1.2443 +            fillIn(c);
  1.2444 +        } else if (sym.kind == PCK) {
  1.2445 +            PackageSymbol p = (PackageSymbol)sym;
  1.2446 +            try {
  1.2447 +                fillIn(p);
  1.2448 +            } catch (IOException ex) {
  1.2449 +                throw new CompletionFailure(sym, ex.getLocalizedMessage()).initCause(ex);
  1.2450 +            }
  1.2451 +        }
  1.2452 +        if (!filling)
  1.2453 +            annotate.flush(); // finish attaching annotations
  1.2454 +    }
  1.2455 +
  1.2456 +    /** complete up through the enclosing package. */
  1.2457 +    private void completeOwners(Symbol o) {
  1.2458 +        if (o.kind != PCK) completeOwners(o.owner);
  1.2459 +        o.complete();
  1.2460 +    }
  1.2461 +
  1.2462 +    /**
  1.2463 +     * Tries to complete lexically enclosing classes if c looks like a
  1.2464 +     * nested class.  This is similar to completeOwners but handles
  1.2465 +     * the situation when a nested class is accessed directly as it is
  1.2466 +     * possible with the Tree API or javax.lang.model.*.
  1.2467 +     */
  1.2468 +    private void completeEnclosing(ClassSymbol c) {
  1.2469 +        if (c.owner.kind == PCK) {
  1.2470 +            Symbol owner = c.owner;
  1.2471 +            for (Name name : Convert.enclosingCandidates(Convert.shortName(c.name))) {
  1.2472 +                Symbol encl = owner.members().lookup(name).sym;
  1.2473 +                if (encl == null)
  1.2474 +                    encl = classes.get(TypeSymbol.formFlatName(name, owner));
  1.2475 +                if (encl != null)
  1.2476 +                    encl.complete();
  1.2477 +            }
  1.2478 +        }
  1.2479 +    }
  1.2480 +
  1.2481 +    /** We can only read a single class file at a time; this
  1.2482 +     *  flag keeps track of when we are currently reading a class
  1.2483 +     *  file.
  1.2484 +     */
  1.2485 +    private boolean filling = false;
  1.2486 +
  1.2487 +    /** Fill in definition of class `c' from corresponding class or
  1.2488 +     *  source file.
  1.2489 +     */
  1.2490 +    private void fillIn(ClassSymbol c) {
  1.2491 +        if (completionFailureName == c.fullname) {
  1.2492 +            throw new CompletionFailure(c, "user-selected completion failure by class name");
  1.2493 +        }
  1.2494 +        currentOwner = c;
  1.2495 +        warnedAttrs.clear();
  1.2496 +        JavaFileObject classfile = c.classfile;
  1.2497 +        if (classfile != null) {
  1.2498 +            JavaFileObject previousClassFile = currentClassFile;
  1.2499 +            try {
  1.2500 +                if (filling) {
  1.2501 +                    Assert.error("Filling " + classfile.toUri() + " during " + previousClassFile);
  1.2502 +                }
  1.2503 +                currentClassFile = classfile;
  1.2504 +                if (verbose) {
  1.2505 +                    log.printVerbose("loading", currentClassFile.toString());
  1.2506 +                }
  1.2507 +                if (classfile.getKind() == JavaFileObject.Kind.CLASS) {
  1.2508 +                    filling = true;
  1.2509 +                    try {
  1.2510 +                        bp = 0;
  1.2511 +                        buf = readInputStream(buf, classfile.openInputStream());
  1.2512 +                        readClassFile(c);
  1.2513 +                        if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
  1.2514 +                            List<Type> missing = missingTypeVariables;
  1.2515 +                            List<Type> found = foundTypeVariables;
  1.2516 +                            missingTypeVariables = List.nil();
  1.2517 +                            foundTypeVariables = List.nil();
  1.2518 +                            filling = false;
  1.2519 +                            ClassType ct = (ClassType)currentOwner.type;
  1.2520 +                            ct.supertype_field =
  1.2521 +                                types.subst(ct.supertype_field, missing, found);
  1.2522 +                            ct.interfaces_field =
  1.2523 +                                types.subst(ct.interfaces_field, missing, found);
  1.2524 +                        } else if (missingTypeVariables.isEmpty() !=
  1.2525 +                                   foundTypeVariables.isEmpty()) {
  1.2526 +                            Name name = missingTypeVariables.head.tsym.name;
  1.2527 +                            throw badClassFile("undecl.type.var", name);
  1.2528 +                        }
  1.2529 +                    } finally {
  1.2530 +                        missingTypeVariables = List.nil();
  1.2531 +                        foundTypeVariables = List.nil();
  1.2532 +                        filling = false;
  1.2533 +                    }
  1.2534 +                } else {
  1.2535 +                    if (sourceCompleter != null) {
  1.2536 +                        sourceCompleter.complete(c);
  1.2537 +                    } else {
  1.2538 +                        throw new IllegalStateException("Source completer required to read "
  1.2539 +                                                        + classfile.toUri());
  1.2540 +                    }
  1.2541 +                }
  1.2542 +                return;
  1.2543 +            } catch (IOException ex) {
  1.2544 +                throw badClassFile("unable.to.access.file", ex.getMessage());
  1.2545 +            } finally {
  1.2546 +                currentClassFile = previousClassFile;
  1.2547 +            }
  1.2548 +        } else {
  1.2549 +            JCDiagnostic diag =
  1.2550 +                diagFactory.fragment("class.file.not.found", c.flatname);
  1.2551 +            throw
  1.2552 +                newCompletionFailure(c, diag);
  1.2553 +        }
  1.2554 +    }
  1.2555 +    // where
  1.2556 +        private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
  1.2557 +            try {
  1.2558 +                buf = ensureCapacity(buf, s.available());
  1.2559 +                int r = s.read(buf);
  1.2560 +                int bp = 0;
  1.2561 +                while (r != -1) {
  1.2562 +                    bp += r;
  1.2563 +                    buf = ensureCapacity(buf, bp);
  1.2564 +                    r = s.read(buf, bp, buf.length - bp);
  1.2565 +                }
  1.2566 +                return buf;
  1.2567 +            } finally {
  1.2568 +                try {
  1.2569 +                    s.close();
  1.2570 +                } catch (IOException e) {
  1.2571 +                    /* Ignore any errors, as this stream may have already
  1.2572 +                     * thrown a related exception which is the one that
  1.2573 +                     * should be reported.
  1.2574 +                     */
  1.2575 +                }
  1.2576 +            }
  1.2577 +        }
  1.2578 +        /*
  1.2579 +         * ensureCapacity will increase the buffer as needed, taking note that
  1.2580 +         * the new buffer will always be greater than the needed and never
  1.2581 +         * exactly equal to the needed size or bp. If equal then the read (above)
  1.2582 +         * will infinitely loop as buf.length - bp == 0.
  1.2583 +         */
  1.2584 +        private static byte[] ensureCapacity(byte[] buf, int needed) {
  1.2585 +            if (buf.length <= needed) {
  1.2586 +                byte[] old = buf;
  1.2587 +                buf = new byte[Integer.highestOneBit(needed) << 1];
  1.2588 +                System.arraycopy(old, 0, buf, 0, old.length);
  1.2589 +            }
  1.2590 +            return buf;
  1.2591 +        }
  1.2592 +        /** Static factory for CompletionFailure objects.
  1.2593 +         *  In practice, only one can be used at a time, so we share one
  1.2594 +         *  to reduce the expense of allocating new exception objects.
  1.2595 +         */
  1.2596 +        private CompletionFailure newCompletionFailure(TypeSymbol c,
  1.2597 +                                                       JCDiagnostic diag) {
  1.2598 +            if (!cacheCompletionFailure) {
  1.2599 +                // log.warning("proc.messager",
  1.2600 +                //             Log.getLocalizedString("class.file.not.found", c.flatname));
  1.2601 +                // c.debug.printStackTrace();
  1.2602 +                return new CompletionFailure(c, diag);
  1.2603 +            } else {
  1.2604 +                CompletionFailure result = cachedCompletionFailure;
  1.2605 +                result.sym = c;
  1.2606 +                result.diag = diag;
  1.2607 +                return result;
  1.2608 +            }
  1.2609 +        }
  1.2610 +        private CompletionFailure cachedCompletionFailure =
  1.2611 +            new CompletionFailure(null, (JCDiagnostic) null);
  1.2612 +        {
  1.2613 +            cachedCompletionFailure.setStackTrace(new StackTraceElement[0]);
  1.2614 +        }
  1.2615 +
  1.2616 +    /** Load a toplevel class with given fully qualified name
  1.2617 +     *  The class is entered into `classes' only if load was successful.
  1.2618 +     */
  1.2619 +    public ClassSymbol loadClass(Name flatname) throws CompletionFailure {
  1.2620 +        boolean absent = classes.get(flatname) == null;
  1.2621 +        ClassSymbol c = enterClass(flatname);
  1.2622 +        if (c.members_field == null && c.completer != null) {
  1.2623 +            try {
  1.2624 +                c.complete();
  1.2625 +            } catch (CompletionFailure ex) {
  1.2626 +                if (absent) classes.remove(flatname);
  1.2627 +                throw ex;
  1.2628 +            }
  1.2629 +        }
  1.2630 +        return c;
  1.2631 +    }
  1.2632 +
  1.2633 +/************************************************************************
  1.2634 + * Loading Packages
  1.2635 + ***********************************************************************/
  1.2636 +
  1.2637 +    /** Check to see if a package exists, given its fully qualified name.
  1.2638 +     */
  1.2639 +    public boolean packageExists(Name fullname) {
  1.2640 +        return enterPackage(fullname).exists();
  1.2641 +    }
  1.2642 +
  1.2643 +    /** Make a package, given its fully qualified name.
  1.2644 +     */
  1.2645 +    public PackageSymbol enterPackage(Name fullname) {
  1.2646 +        PackageSymbol p = packages.get(fullname);
  1.2647 +        if (p == null) {
  1.2648 +            Assert.check(!fullname.isEmpty(), "rootPackage missing!");
  1.2649 +            p = new PackageSymbol(
  1.2650 +                Convert.shortName(fullname),
  1.2651 +                enterPackage(Convert.packagePart(fullname)));
  1.2652 +            p.completer = thisCompleter;
  1.2653 +            packages.put(fullname, p);
  1.2654 +        }
  1.2655 +        return p;
  1.2656 +    }
  1.2657 +
  1.2658 +    /** Make a package, given its unqualified name and enclosing package.
  1.2659 +     */
  1.2660 +    public PackageSymbol enterPackage(Name name, PackageSymbol owner) {
  1.2661 +        return enterPackage(TypeSymbol.formFullName(name, owner));
  1.2662 +    }
  1.2663 +
  1.2664 +    /** Include class corresponding to given class file in package,
  1.2665 +     *  unless (1) we already have one the same kind (.class or .java), or
  1.2666 +     *         (2) we have one of the other kind, and the given class file
  1.2667 +     *             is older.
  1.2668 +     */
  1.2669 +    protected void includeClassFile(PackageSymbol p, JavaFileObject file) {
  1.2670 +        if ((p.flags_field & EXISTS) == 0)
  1.2671 +            for (Symbol q = p; q != null && q.kind == PCK; q = q.owner)
  1.2672 +                q.flags_field |= EXISTS;
  1.2673 +        JavaFileObject.Kind kind = file.getKind();
  1.2674 +        int seen;
  1.2675 +        if (kind == JavaFileObject.Kind.CLASS)
  1.2676 +            seen = CLASS_SEEN;
  1.2677 +        else
  1.2678 +            seen = SOURCE_SEEN;
  1.2679 +        String binaryName = fileManager.inferBinaryName(currentLoc, file);
  1.2680 +        int lastDot = binaryName.lastIndexOf(".");
  1.2681 +        Name classname = names.fromString(binaryName.substring(lastDot + 1));
  1.2682 +        boolean isPkgInfo = classname == names.package_info;
  1.2683 +        ClassSymbol c = isPkgInfo
  1.2684 +            ? p.package_info
  1.2685 +            : (ClassSymbol) p.members_field.lookup(classname).sym;
  1.2686 +        if (c == null) {
  1.2687 +            c = enterClass(classname, p);
  1.2688 +            if (c.classfile == null) // only update the file if's it's newly created
  1.2689 +                c.classfile = file;
  1.2690 +            if (isPkgInfo) {
  1.2691 +                p.package_info = c;
  1.2692 +            } else {
  1.2693 +                if (c.owner == p)  // it might be an inner class
  1.2694 +                    p.members_field.enter(c);
  1.2695 +            }
  1.2696 +        } else if (c.classfile != null && (c.flags_field & seen) == 0) {
  1.2697 +            // if c.classfile == null, we are currently compiling this class
  1.2698 +            // and no further action is necessary.
  1.2699 +            // if (c.flags_field & seen) != 0, we have already encountered
  1.2700 +            // a file of the same kind; again no further action is necessary.
  1.2701 +            if ((c.flags_field & (CLASS_SEEN | SOURCE_SEEN)) != 0)
  1.2702 +                c.classfile = preferredFileObject(file, c.classfile);
  1.2703 +        }
  1.2704 +        c.flags_field |= seen;
  1.2705 +    }
  1.2706 +
  1.2707 +    /** Implement policy to choose to derive information from a source
  1.2708 +     *  file or a class file when both are present.  May be overridden
  1.2709 +     *  by subclasses.
  1.2710 +     */
  1.2711 +    protected JavaFileObject preferredFileObject(JavaFileObject a,
  1.2712 +                                           JavaFileObject b) {
  1.2713 +
  1.2714 +        if (preferSource)
  1.2715 +            return (a.getKind() == JavaFileObject.Kind.SOURCE) ? a : b;
  1.2716 +        else {
  1.2717 +            long adate = a.getLastModified();
  1.2718 +            long bdate = b.getLastModified();
  1.2719 +            // 6449326: policy for bad lastModifiedTime in ClassReader
  1.2720 +            //assert adate >= 0 && bdate >= 0;
  1.2721 +            return (adate > bdate) ? a : b;
  1.2722 +        }
  1.2723 +    }
  1.2724 +
  1.2725 +    /**
  1.2726 +     * specifies types of files to be read when filling in a package symbol
  1.2727 +     */
  1.2728 +    protected EnumSet<JavaFileObject.Kind> getPackageFileKinds() {
  1.2729 +        return EnumSet.of(JavaFileObject.Kind.CLASS, JavaFileObject.Kind.SOURCE);
  1.2730 +    }
  1.2731 +
  1.2732 +    /**
  1.2733 +     * this is used to support javadoc
  1.2734 +     */
  1.2735 +    protected void extraFileActions(PackageSymbol pack, JavaFileObject fe) {
  1.2736 +    }
  1.2737 +
  1.2738 +    protected Location currentLoc; // FIXME
  1.2739 +
  1.2740 +    private boolean verbosePath = true;
  1.2741 +
  1.2742 +    /** Load directory of package into members scope.
  1.2743 +     */
  1.2744 +    private void fillIn(PackageSymbol p) throws IOException {
  1.2745 +        if (p.members_field == null) p.members_field = new Scope(p);
  1.2746 +        String packageName = p.fullname.toString();
  1.2747 +
  1.2748 +        Set<JavaFileObject.Kind> kinds = getPackageFileKinds();
  1.2749 +
  1.2750 +        fillIn(p, PLATFORM_CLASS_PATH,
  1.2751 +               fileManager.list(PLATFORM_CLASS_PATH,
  1.2752 +                                packageName,
  1.2753 +                                EnumSet.of(JavaFileObject.Kind.CLASS),
  1.2754 +                                false));
  1.2755 +
  1.2756 +        Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds);
  1.2757 +        classKinds.remove(JavaFileObject.Kind.SOURCE);
  1.2758 +        boolean wantClassFiles = !classKinds.isEmpty();
  1.2759 +
  1.2760 +        Set<JavaFileObject.Kind> sourceKinds = EnumSet.copyOf(kinds);
  1.2761 +        sourceKinds.remove(JavaFileObject.Kind.CLASS);
  1.2762 +        boolean wantSourceFiles = !sourceKinds.isEmpty();
  1.2763 +
  1.2764 +        boolean haveSourcePath = fileManager.hasLocation(SOURCE_PATH);
  1.2765 +
  1.2766 +        if (verbose && verbosePath) {
  1.2767 +            if (fileManager instanceof StandardJavaFileManager) {
  1.2768 +                StandardJavaFileManager fm = (StandardJavaFileManager)fileManager;
  1.2769 +                if (haveSourcePath && wantSourceFiles) {
  1.2770 +                    List<File> path = List.nil();
  1.2771 +                    for (File file : fm.getLocation(SOURCE_PATH)) {
  1.2772 +                        path = path.prepend(file);
  1.2773 +                    }
  1.2774 +                    log.printVerbose("sourcepath", path.reverse().toString());
  1.2775 +                } else if (wantSourceFiles) {
  1.2776 +                    List<File> path = List.nil();
  1.2777 +                    for (File file : fm.getLocation(CLASS_PATH)) {
  1.2778 +                        path = path.prepend(file);
  1.2779 +                    }
  1.2780 +                    log.printVerbose("sourcepath", path.reverse().toString());
  1.2781 +                }
  1.2782 +                if (wantClassFiles) {
  1.2783 +                    List<File> path = List.nil();
  1.2784 +                    for (File file : fm.getLocation(PLATFORM_CLASS_PATH)) {
  1.2785 +                        path = path.prepend(file);
  1.2786 +                    }
  1.2787 +                    for (File file : fm.getLocation(CLASS_PATH)) {
  1.2788 +                        path = path.prepend(file);
  1.2789 +                    }
  1.2790 +                    log.printVerbose("classpath",  path.reverse().toString());
  1.2791 +                }
  1.2792 +            }
  1.2793 +        }
  1.2794 +
  1.2795 +        if (wantSourceFiles && !haveSourcePath) {
  1.2796 +            fillIn(p, CLASS_PATH,
  1.2797 +                   fileManager.list(CLASS_PATH,
  1.2798 +                                    packageName,
  1.2799 +                                    kinds,
  1.2800 +                                    false));
  1.2801 +        } else {
  1.2802 +            if (wantClassFiles)
  1.2803 +                fillIn(p, CLASS_PATH,
  1.2804 +                       fileManager.list(CLASS_PATH,
  1.2805 +                                        packageName,
  1.2806 +                                        classKinds,
  1.2807 +                                        false));
  1.2808 +            if (wantSourceFiles)
  1.2809 +                fillIn(p, SOURCE_PATH,
  1.2810 +                       fileManager.list(SOURCE_PATH,
  1.2811 +                                        packageName,
  1.2812 +                                        sourceKinds,
  1.2813 +                                        false));
  1.2814 +        }
  1.2815 +        verbosePath = false;
  1.2816 +    }
  1.2817 +    // where
  1.2818 +        private void fillIn(PackageSymbol p,
  1.2819 +                            Location location,
  1.2820 +                            Iterable<JavaFileObject> files)
  1.2821 +        {
  1.2822 +            currentLoc = location;
  1.2823 +            for (JavaFileObject fo : files) {
  1.2824 +                switch (fo.getKind()) {
  1.2825 +                case CLASS:
  1.2826 +                case SOURCE: {
  1.2827 +                    // TODO pass binaryName to includeClassFile
  1.2828 +                    String binaryName = fileManager.inferBinaryName(currentLoc, fo);
  1.2829 +                    String simpleName = binaryName.substring(binaryName.lastIndexOf(".") + 1);
  1.2830 +                    if (SourceVersion.isIdentifier(simpleName) ||
  1.2831 +                        simpleName.equals("package-info"))
  1.2832 +                        includeClassFile(p, fo);
  1.2833 +                    break;
  1.2834 +                }
  1.2835 +                default:
  1.2836 +                    extraFileActions(p, fo);
  1.2837 +                }
  1.2838 +            }
  1.2839 +        }
  1.2840 +
  1.2841 +    /** Output for "-checkclassfile" option.
  1.2842 +     *  @param key The key to look up the correct internationalized string.
  1.2843 +     *  @param arg An argument for substitution into the output string.
  1.2844 +     */
  1.2845 +    private void printCCF(String key, Object arg) {
  1.2846 +        log.printLines(key, arg);
  1.2847 +    }
  1.2848 +
  1.2849 +
  1.2850 +    public interface SourceCompleter {
  1.2851 +        void complete(ClassSymbol sym)
  1.2852 +            throws CompletionFailure;
  1.2853 +    }
  1.2854 +
  1.2855 +    /**
  1.2856 +     * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
  1.2857 +     * The attribute is only the last component of the original filename, so is unlikely
  1.2858 +     * to be valid as is, so operations other than those to access the name throw
  1.2859 +     * UnsupportedOperationException
  1.2860 +     */
  1.2861 +    private static class SourceFileObject extends BaseFileObject {
  1.2862 +
  1.2863 +        /** The file's name.
  1.2864 +         */
  1.2865 +        private Name name;
  1.2866 +        private Name flatname;
  1.2867 +
  1.2868 +        public SourceFileObject(Name name, Name flatname) {
  1.2869 +            super(null); // no file manager; never referenced for this file object
  1.2870 +            this.name = name;
  1.2871 +            this.flatname = flatname;
  1.2872 +        }
  1.2873 +
  1.2874 +        @Override
  1.2875 +        public URI toUri() {
  1.2876 +            try {
  1.2877 +                return new URI(null, name.toString(), null);
  1.2878 +            } catch (URISyntaxException e) {
  1.2879 +                throw new CannotCreateUriError(name.toString(), e);
  1.2880 +            }
  1.2881 +        }
  1.2882 +
  1.2883 +        @Override
  1.2884 +        public String getName() {
  1.2885 +            return name.toString();
  1.2886 +        }
  1.2887 +
  1.2888 +        @Override
  1.2889 +        public String getShortName() {
  1.2890 +            return getName();
  1.2891 +        }
  1.2892 +
  1.2893 +        @Override
  1.2894 +        public JavaFileObject.Kind getKind() {
  1.2895 +            return getKind(getName());
  1.2896 +        }
  1.2897 +
  1.2898 +        @Override
  1.2899 +        public InputStream openInputStream() {
  1.2900 +            throw new UnsupportedOperationException();
  1.2901 +        }
  1.2902 +
  1.2903 +        @Override
  1.2904 +        public OutputStream openOutputStream() {
  1.2905 +            throw new UnsupportedOperationException();
  1.2906 +        }
  1.2907 +
  1.2908 +        @Override
  1.2909 +        public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
  1.2910 +            throw new UnsupportedOperationException();
  1.2911 +        }
  1.2912 +
  1.2913 +        @Override
  1.2914 +        public Reader openReader(boolean ignoreEncodingErrors) {
  1.2915 +            throw new UnsupportedOperationException();
  1.2916 +        }
  1.2917 +
  1.2918 +        @Override
  1.2919 +        public Writer openWriter() {
  1.2920 +            throw new UnsupportedOperationException();
  1.2921 +        }
  1.2922 +
  1.2923 +        @Override
  1.2924 +        public long getLastModified() {
  1.2925 +            throw new UnsupportedOperationException();
  1.2926 +        }
  1.2927 +
  1.2928 +        @Override
  1.2929 +        public boolean delete() {
  1.2930 +            throw new UnsupportedOperationException();
  1.2931 +        }
  1.2932 +
  1.2933 +        @Override
  1.2934 +        protected String inferBinaryName(Iterable<? extends File> path) {
  1.2935 +            return flatname.toString();
  1.2936 +        }
  1.2937 +
  1.2938 +        @Override
  1.2939 +        public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
  1.2940 +            return true; // fail-safe mode
  1.2941 +        }
  1.2942 +
  1.2943 +        /**
  1.2944 +         * Check if two file objects are equal.
  1.2945 +         * SourceFileObjects are just placeholder objects for the value of a
  1.2946 +         * SourceFile attribute, and do not directly represent specific files.
  1.2947 +         * Two SourceFileObjects are equal if their names are equal.
  1.2948 +         */
  1.2949 +        @Override
  1.2950 +        public boolean equals(Object other) {
  1.2951 +            if (this == other)
  1.2952 +                return true;
  1.2953 +
  1.2954 +            if (!(other instanceof SourceFileObject))
  1.2955 +                return false;
  1.2956 +
  1.2957 +            SourceFileObject o = (SourceFileObject) other;
  1.2958 +            return name.equals(o.name);
  1.2959 +        }
  1.2960 +
  1.2961 +        @Override
  1.2962 +        public int hashCode() {
  1.2963 +            return name.hashCode();
  1.2964 +        }
  1.2965 +    }
  1.2966 +}

mercurial