langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java

Print this page

        

@@ -27,10 +27,11 @@
 
 import java.io.*;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.nio.CharBuffer;
+import java.util.Arrays;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 import javax.lang.model.SourceVersion;

@@ -189,10 +190,15 @@
 
     /** Switch: debug output for JSR 308-related operations.
      */
     boolean debugJSR308;
 
+    /** A table to hold the constant pool indices for method parameter
+     * names, as given in LocalVariableTable attributes.
+     */
+    int[] parameterNameIndices;
+
     /** Get the ClassReader instance for this invocation. */
     public static ClassReader instance(Context context) {
         ClassReader instance = context.get(classReaderKey);
         if (instance == null)
             instance = new ClassReader(context, true);

@@ -921,36 +927,28 @@
             new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
                 void read(Symbol sym, int attrLen) {
                     int newbp = bp + attrLen;
                     if (saveParameterNames) {
                         // pick up parameter names from the variable table
-                        List<Name> parameterNames = List.nil();
-                        int firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
-                        int endParam = firstParam + Code.width(sym.type.getParameterTypes());
                         int numEntries = nextChar();
-                        for (int i=0; i<numEntries; i++) {
+                        for (int i = 0; i < numEntries; i++) {
                             int start_pc = nextChar();
                             int length = nextChar();
                             int nameIndex = nextChar();
                             int sigIndex = nextChar();
                             int register = nextChar();
-                            if (start_pc == 0 &&
-                                firstParam <= register &&
-                                register < endParam) {
-                                int index = firstParam;
-                                for (Type t : sym.type.getParameterTypes()) {
-                                    if (index == register) {
-                                        parameterNames = parameterNames.prepend(readName(nameIndex));
-                                        break;
+                            if (start_pc == 0) {
+                                // ensure array large enough
+                                if (register >= parameterNameIndices.length) {
+                                    int newSize = Math.max(register, parameterNameIndices.length + 8);
+                                    parameterNameIndices =
+                                            Arrays.copyOf(parameterNameIndices, newSize);
                                     }
-                                    index += Code.width(t);
+                                parameterNameIndices[register] = nameIndex;
                                 }
                             }
                         }
-                        parameterNames = parameterNames.reverse();
-                        ((MethodSymbol)sym).savedParameterNames = parameterNames;
-                    }
                     bp = newbp;
                 }
             },
 
             new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) {

@@ -1837,20 +1835,75 @@
                                       type.getReturnType(),
                                       type.getThrownTypes(),
                                       syms.methodClass);
         }
         MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
+        if (saveParameterNames)
+            initParameterNames(m);
         Symbol prevOwner = currentOwner;
         currentOwner = m;
         try {
             readMemberAttrs(m);
         } finally {
             currentOwner = prevOwner;
         }
+        if (saveParameterNames)
+            setParameterNames(m, type);
         return m;
     }
 
+    void initParameterNames(MethodSymbol sym) {
+        // make allowance for synthetic parameters.
+        final int excessSlots = 4;
+        int expectedParameterSlots =
+                Code.width(sym.type.getParameterTypes()) + excessSlots;
+        if (parameterNameIndices == null
+                || parameterNameIndices.length < expectedParameterSlots) {
+            parameterNameIndices = new int[expectedParameterSlots];
+        } else
+            Arrays.fill(parameterNameIndices, 0);
+    }
+
+    void setParameterNames(MethodSymbol sym, Type jvmType) {
+        int firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
+        // the code in readMethod may have skipped the first parameter when
+        // setting up the MethodType. If so, we make a corresponding allowance
+        // here for the position of the first parameter.  Note that this
+        // assumes the skipped parameter has a width of 1 -- i.e. it is not
+        // a double width type (long or double.)
+        if (sym.name == names.init && currentOwner.hasOuterInstance()) {
+            // Sometimes anonymous classes don't have an outer
+            // instance, however, there is no reliable way to tell so
+            // we never strip this$n
+            if (!currentOwner.name.isEmpty())
+                firstParam += 1;
+        }
+
+        if (sym.type != jvmType) {
+            // reading the method attributes has caused the symbol's type to
+            // be changed. (i.e. the Signature attribute.)  This may happen if
+            // there are hidden (synthetic) parameters in the descriptor, but
+            // not in the Signature.  The position of these hidden parameters
+            // is unspecified; for now, assume they are at the beginning, and
+            // so skip over them. The primary case for this is two hidden
+            // parameters passed into Enum constructors.
+            int skip = Code.width(jvmType.getParameterTypes())
+                    - Code.width(sym.type.getParameterTypes());
+            firstParam += skip;
+        }
+        List<Name> paramNames = List.nil();
+        int index = firstParam;
+        for (Type t: sym.type.getParameterTypes()) {
+            int nameIdx = (index < parameterNameIndices.length
+                    ? parameterNameIndices[index] : 0);
+            Name name = nameIdx == 0 ? names.empty : readName(nameIdx);
+            paramNames = paramNames.prepend(name);
+            index += Code.width(t);
+        }
+        sym.savedParameterNames = paramNames.reverse();
+    }
+
     /** Skip a field or method
      */
     void skipMember() {
         bp = bp + 6;
         char ac = nextChar();