920 |
931 |
921 new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { |
932 new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { |
922 void read(Symbol sym, int attrLen) { |
933 void read(Symbol sym, int attrLen) { |
923 int newbp = bp + attrLen; |
934 int newbp = bp + attrLen; |
924 if (saveParameterNames) { |
935 if (saveParameterNames) { |
925 // pick up parameter names from the variable table |
936 // Pick up parameter names from the variable table. |
926 List<Name> parameterNames = List.nil(); |
937 // Parameter names are not explicitly identified as such, |
927 int firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0; |
938 // but all parameter name entries in the LocalVariableTable |
928 int endParam = firstParam + Code.width(sym.type.getParameterTypes()); |
939 // have a start_pc of 0. Therefore, we record the name |
|
940 // indicies of all slots with a start_pc of zero in the |
|
941 // parameterNameIndicies array. |
|
942 // Note that this implicitly honors the JVMS spec that |
|
943 // there may be more than one LocalVariableTable, and that |
|
944 // there is no specified ordering for the entries. |
929 int numEntries = nextChar(); |
945 int numEntries = nextChar(); |
930 for (int i=0; i<numEntries; i++) { |
946 for (int i = 0; i < numEntries; i++) { |
931 int start_pc = nextChar(); |
947 int start_pc = nextChar(); |
932 int length = nextChar(); |
948 int length = nextChar(); |
933 int nameIndex = nextChar(); |
949 int nameIndex = nextChar(); |
934 int sigIndex = nextChar(); |
950 int sigIndex = nextChar(); |
935 int register = nextChar(); |
951 int register = nextChar(); |
936 if (start_pc == 0 && |
952 if (start_pc == 0) { |
937 firstParam <= register && |
953 // ensure array large enough |
938 register < endParam) { |
954 if (register >= parameterNameIndices.length) { |
939 int index = firstParam; |
955 int newSize = Math.max(register, parameterNameIndices.length + 8); |
940 for (Type t : sym.type.getParameterTypes()) { |
956 parameterNameIndices = |
941 if (index == register) { |
957 Arrays.copyOf(parameterNameIndices, newSize); |
942 parameterNames = parameterNames.prepend(readName(nameIndex)); |
|
943 break; |
|
944 } |
|
945 index += Code.width(t); |
|
946 } |
958 } |
|
959 parameterNameIndices[register] = nameIndex; |
|
960 haveParameterNameIndices = true; |
947 } |
961 } |
948 } |
962 } |
949 parameterNames = parameterNames.reverse(); |
|
950 ((MethodSymbol)sym).savedParameterNames = parameterNames; |
|
951 } |
963 } |
952 bp = newbp; |
964 bp = newbp; |
953 } |
965 } |
954 }, |
966 }, |
955 |
967 |
1837 type.getReturnType(), |
1849 type.getReturnType(), |
1838 type.getThrownTypes(), |
1850 type.getThrownTypes(), |
1839 syms.methodClass); |
1851 syms.methodClass); |
1840 } |
1852 } |
1841 MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner); |
1853 MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner); |
|
1854 if (saveParameterNames) |
|
1855 initParameterNames(m); |
1842 Symbol prevOwner = currentOwner; |
1856 Symbol prevOwner = currentOwner; |
1843 currentOwner = m; |
1857 currentOwner = m; |
1844 try { |
1858 try { |
1845 readMemberAttrs(m); |
1859 readMemberAttrs(m); |
1846 } finally { |
1860 } finally { |
1847 currentOwner = prevOwner; |
1861 currentOwner = prevOwner; |
1848 } |
1862 } |
|
1863 if (saveParameterNames) |
|
1864 setParameterNames(m, type); |
1849 return m; |
1865 return m; |
|
1866 } |
|
1867 |
|
1868 /** |
|
1869 * Init the parameter names array. |
|
1870 * Parameter names are currently inferred from the names in the |
|
1871 * LocalVariableTable attributes of a Code attribute. |
|
1872 * (Note: this means parameter names are currently not available for |
|
1873 * methods without a Code attribute.) |
|
1874 * This method initializes an array in which to store the name indexes |
|
1875 * of parameter names found in LocalVariableTable attributes. It is |
|
1876 * slightly supersized to allow for additional slots with a start_pc of 0. |
|
1877 */ |
|
1878 void initParameterNames(MethodSymbol sym) { |
|
1879 // make allowance for synthetic parameters. |
|
1880 final int excessSlots = 4; |
|
1881 int expectedParameterSlots = |
|
1882 Code.width(sym.type.getParameterTypes()) + excessSlots; |
|
1883 if (parameterNameIndices == null |
|
1884 || parameterNameIndices.length < expectedParameterSlots) { |
|
1885 parameterNameIndices = new int[expectedParameterSlots]; |
|
1886 } else |
|
1887 Arrays.fill(parameterNameIndices, 0); |
|
1888 haveParameterNameIndices = false; |
|
1889 } |
|
1890 |
|
1891 /** |
|
1892 * Set the parameter names for a symbol from the name index in the |
|
1893 * parameterNameIndicies array. The type of the symbol may have changed |
|
1894 * while reading the method attributes (see the Signature attribute). |
|
1895 * This may be because of generic information or because anonymous |
|
1896 * synthetic parameters were added. The original type (as read from |
|
1897 * the method descriptor) is used to help guess the existence of |
|
1898 * anonymous synthetic parameters. |
|
1899 * On completion, sym.savedParameter names will either be null (if |
|
1900 * no parameter names were found in the class file) or will be set to a |
|
1901 * list of names, one per entry in sym.type.getParameterTypes, with |
|
1902 * any missing names represented by the empty name. |
|
1903 */ |
|
1904 void setParameterNames(MethodSymbol sym, Type jvmType) { |
|
1905 // if no names were found in the class file, there's nothing more to do |
|
1906 if (!haveParameterNameIndices) |
|
1907 return; |
|
1908 |
|
1909 int firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0; |
|
1910 // the code in readMethod may have skipped the first parameter when |
|
1911 // setting up the MethodType. If so, we make a corresponding allowance |
|
1912 // here for the position of the first parameter. Note that this |
|
1913 // assumes the skipped parameter has a width of 1 -- i.e. it is not |
|
1914 // a double width type (long or double.) |
|
1915 if (sym.name == names.init && currentOwner.hasOuterInstance()) { |
|
1916 // Sometimes anonymous classes don't have an outer |
|
1917 // instance, however, there is no reliable way to tell so |
|
1918 // we never strip this$n |
|
1919 if (!currentOwner.name.isEmpty()) |
|
1920 firstParam += 1; |
|
1921 } |
|
1922 |
|
1923 if (sym.type != jvmType) { |
|
1924 // reading the method attributes has caused the symbol's type to |
|
1925 // be changed. (i.e. the Signature attribute.) This may happen if |
|
1926 // there are hidden (synthetic) parameters in the descriptor, but |
|
1927 // not in the Signature. The position of these hidden parameters |
|
1928 // is unspecified; for now, assume they are at the beginning, and |
|
1929 // so skip over them. The primary case for this is two hidden |
|
1930 // parameters passed into Enum constructors. |
|
1931 int skip = Code.width(jvmType.getParameterTypes()) |
|
1932 - Code.width(sym.type.getParameterTypes()); |
|
1933 firstParam += skip; |
|
1934 } |
|
1935 List<Name> paramNames = List.nil(); |
|
1936 int index = firstParam; |
|
1937 for (Type t: sym.type.getParameterTypes()) { |
|
1938 int nameIdx = (index < parameterNameIndices.length |
|
1939 ? parameterNameIndices[index] : 0); |
|
1940 Name name = nameIdx == 0 ? names.empty : readName(nameIdx); |
|
1941 paramNames = paramNames.prepend(name); |
|
1942 index += Code.width(t); |
|
1943 } |
|
1944 sym.savedParameterNames = paramNames.reverse(); |
1850 } |
1945 } |
1851 |
1946 |
1852 /** Skip a field or method |
1947 /** Skip a field or method |
1853 */ |
1948 */ |
1854 void skipMember() { |
1949 void skipMember() { |