Message ID | 4F855B49.2070605@redhat.com |
---|---|
State | New |
Headers | show |
On Wed, Apr 11, 2012 at 12:22 PM, Andrew Haley <aph@redhat.com> wrote: > This adds support for the new (Version 51.0) class file format. It > doesn't actually generate code for invokedynamic bcause we don't have > any runtime support yet, but it's a start. jcf-dump prints all of the > new attributes. This breaks bootstrap for me: In file included from /space/rguenther/src/svn/trunk/gcc/java/jcf-parse.c:1009:0: /space/rguenther/src/svn/trunk/gcc/java/jcf-reader.c:550:1: error: 'int jcf_parse_bootstrap_methods(JCF*, int)' defined but not used [-Werror=unused-function] jcf_parse_bootstrap_methods (JCF* jcf, int attribute_length ATTRIBUTE_UNUSED) ^ cc1plus: all warnings being treated as errors make[3]: *** [java/jcf-parse.o] Error 1 make[3]: *** Waiting for unfinished jobs.... > Andrew. > > > 2012-04-11 Andrew Haley <aph@redhat.com> > > * jcf.h (bootstrap_method): New. > (BootstrapMethods): New. > (JCF): Add BootstrapMethods. > (enum cpool_tag): Add MethodHandle, MethodType, and InvokeDynamic. > * jcf-reader.c (jcf_parse_bootstrap_methods): New. > (jcf_parse_constant_pool): Handlers for MethodHandle, MethodType, > and InvokeDynamic. > (jcf_parse_bootstrap_methods): New. > * javaop.def (invokedynamic): New opcode. > * jcf-parse.c (get_constant): An unknown constant type should not > be an internal error, but a fatal one. Make it so. > * jcf-dump.c (HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE): New. > (HANDLE_END_BOOTSTRAP_METHODS): New. > (print_constant): Handlers for MethodHandle, MethodType, and > InvokeDynamic. > > Index: java/jcf-dump.c > =================================================================== > --- java/jcf-dump.c (revision 186103) > +++ java/jcf-dump.c (working copy) > @@ -430,7 +430,24 @@ > print_element_value (out, jcf, 1); \ > } > > +#define HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE() \ > +{ \ > + COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \ > + fputc ('\n', out); jcf_parse_bootstrap_methods (jcf, attribute_length); \ > +} > > +#define HANDLE_END_BOOTSTRAP_METHODS(NUM_METHODS) \ > + { \ > + int i; \ > + for (i = 0; i < NUM_METHODS; i++) \ > + { \ > + bootstrap_method *m = &jcf->bootstrap_methods.methods[i]; \ > + fprintf (out, " %d: ", i); \ > + print_constant (out, jcf, m->method_ref, 1); \ > + fprintf (out, "\n"); \ > + } \ > + } > + > #define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \ > { COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \ > fputc ('\n', out); JCF_SKIP (JCF, LENGTH); } > @@ -898,6 +915,53 @@ > fputc ('\"', out); > } > break; > + case CONSTANT_MethodHandle: > + { > + int kind = JPOOL_USHORT1 (jcf, index); > + if (verbosity > 0) > + fprintf (out, "MethodHandle kind: %d=", kind); > + switch(kind) { > + case 1: > + case 2: > + case 3: > + case 4: > + if (verbosity > 0) > + fprintf (out, "Fieldref: %ld=", JPOOL_USHORT2 (jcf, index)); > + print_constant (out, jcf, JPOOL_USHORT2 (jcf, index), 0); > + case 5: > + case 6: > + case 7: > + case 8: > + if (verbosity > 0) > + fprintf (out, "Methodref: %ld=", JPOOL_USHORT2 (jcf, index)); > + print_constant (out, jcf, JPOOL_USHORT2 (jcf, index), 0); > + break; > + case 9: > + if (verbosity > 0) > + fprintf (out, "InterfaceMethodref: %ld=", JPOOL_USHORT2 (jcf, index)); > + print_constant (out, jcf, JPOOL_USHORT2 (jcf, index), 0); > + break; > + } > + break; > + } > + case CONSTANT_MethodType: > + if (verbosity > 0) > + fprintf (out, "MethodType %ld: ", JPOOL_USHORT1 (jcf, index)); > + print_signature (out, jcf, JPOOL_USHORT1 (jcf, index), 0); > + break; > + case CONSTANT_InvokeDynamic: > + { > + uint16 name_and_type = JPOOL_USHORT2 (jcf, index); > + if (verbosity > 0) > + fprintf (out, "InvokeDynamic: "); > + fprintf (out, "bootstrap_method: %ld ", JPOOL_USHORT1 (jcf, index)); > + if (verbosity == 2) > + fprintf (out, " name_and_type: %d=<", name_and_type); > + print_constant_terse (out, jcf, name_and_type, CONSTANT_NameAndType); > + if (verbosity == 2) > + fputc ('>', out); > + break; > + } > default: > fprintf (out, "(Unknown constant type %d)", kind); > } > Index: java/jcf-parse.c > =================================================================== > --- java/jcf-parse.c (revision 186103) > +++ java/jcf-parse.c (working copy) > @@ -1113,8 +1113,8 @@ > jcf->cpool.data[index].t = value; > return value; > bad: > - internal_error ("bad value constant type %d, index %d", > - JPOOL_TAG (jcf, index), index); > + fatal_error ("bad value constant type %d, index %d", > + JPOOL_TAG (jcf, index), index); > } > > tree > Index: java/javaop.def > =================================================================== > --- java/javaop.def (revision 186103) > +++ java/javaop.def (working copy) > @@ -292,6 +292,7 @@ > JAVAOP (invokespecial, 183, INVOKE, SPECIAL, 0) > JAVAOP (invokestatic, 184, INVOKE, STATIC, 0) > JAVAOP (invokeinterface,185, INVOKE, INTERFACE, 1) > +JAVAOP (invokedynamic, 186, INVOKE, DYNAMIC, 1) > JAVAOP (new, 187, OBJECT, PTR, NEW) > JAVAOP (newarray, 188, ARRAY, NUM, NEW) > JAVAOP (anewarray, 189, ARRAY, PTR, NEW) > Index: java/jcf-reader.c > =================================================================== > --- java/jcf-reader.c (revision 186103) > +++ java/jcf-reader.c (working copy) > @@ -36,6 +36,7 @@ > static int jcf_parse_one_method (JCF *, int); > static int jcf_parse_methods (JCF *); > static int jcf_parse_final_attributes (JCF *); > +static int jcf_parse_bootstrap_methods (JCF *, int ); > #ifdef NEED_PEEK_ATTRIBUTE > static int peek_attribute (JCF *, int, const char *, int); > #endif > @@ -293,7 +294,16 @@ > } > else > #endif > + if (MATCH_ATTRIBUTE ("BootstrapMethods")) > { > +#ifdef HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE > + HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE(); > +#else > + JCF_SKIP (jcf, attribute_length); > +#endif > + } > + else > + { > #ifdef PROCESS_OTHER_ATTRIBUTE > PROCESS_OTHER_ATTRIBUTE(jcf, attribute_name, attribute_length); > #else > @@ -382,6 +392,17 @@ > JCF_SKIP (jcf, n); > #endif > break; > + case CONSTANT_MethodHandle: > + jcf->cpool.data[i].w = JCF_readu (jcf); > + jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16; > + break; > + case CONSTANT_MethodType: > + jcf->cpool.data[i].w = JCF_readu2 (jcf); > + break; > + case CONSTANT_InvokeDynamic: > + jcf->cpool.data[i].w = JCF_readu2 (jcf); > + jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16; > + break; > default: > return i; > } > @@ -521,3 +542,39 @@ > return 0; > } > > +/* Read and handle the "BootstrapMethods" attribute. > + > + Return 0 if OK. > +*/ > +static int > +jcf_parse_bootstrap_methods (JCF* jcf, int attribute_length ATTRIBUTE_UNUSED) > +{ > + int i; > + uint16 num_methods = JCF_readu2 (jcf); > + jcf->bootstrap_methods.count = num_methods; > + jcf->bootstrap_methods.methods > + = (bootstrap_method *) ggc_alloc_atomic (num_methods > + * sizeof (bootstrap_method)); > +#ifdef HANDLE_START_BOOTSTRAP_METHODS > + HANDLE_START_BOOTSTRAP_METHODS (jcf, num_methods); > +#endif > + > + for (i = 0; i < num_methods; i++) > + { > + unsigned j; > + bootstrap_method *m = &jcf->bootstrap_methods.methods[i]; > + m->method_ref = JCF_readu2 (jcf); > + m->num_arguments = JCF_readu2 (jcf); > + m->bootstrap_arguments > + = (unsigned *) ggc_alloc_atomic (m->num_arguments > + * sizeof (unsigned)); > + for (j = 0; j < m->num_arguments; j++) > + m->bootstrap_arguments[j] = JCF_readu2 (jcf); > + } > + > +#ifdef HANDLE_END_BOOTSTRAP_METHODS > + HANDLE_END_BOOTSTRAP_METHODS (num_methods); > +#endif > + > + return 0; > +} > Index: java/jcf.h > =================================================================== > --- java/jcf.h (revision 186103) > +++ java/jcf.h (working copy) > @@ -88,6 +88,17 @@ > desc ("cpool_entry_is_tree (%1.tags%a)"))) data; > } CPool; > > +typedef struct GTY(()) bootstrap_method { > + unsigned method_ref; > + unsigned num_arguments; > + unsigned* GTY((length ("%h.num_arguments"))) bootstrap_arguments; > +} bootstrap_method; > + > +typedef struct GTY(()) BootstrapMethods { > + unsigned count; > + bootstrap_method* GTY((length ("%h.count"))) methods; > +} BootstrapMethods; > + > struct ZipDirectory; > > /* JCF encapsulates the state of reading a Java Class File. */ > @@ -109,6 +120,7 @@ > JCF_u2 this_class; > JCF_u2 super_class; > CPool cpool; > + BootstrapMethods bootstrap_methods; > } JCF; > /*typedef JCF* JCF_FILE;*/ > > @@ -245,6 +257,10 @@ > CONSTANT_NameAndType = 12, > CONSTANT_Utf8 = 1, > CONSTANT_Unicode = 2, > + CONSTANT_MethodHandle = 15, > + CONSTANT_MethodType = 16, > + CONSTANT_InvokeDynamic = 18, > + > CONSTANT_None = 0 > }; > > Index: java/jcf-io.c > =================================================================== > --- java/jcf-io.c (revision 186103) > +++ java/jcf-io.c (working copy) > @@ -518,6 +518,26 @@ > case CONSTANT_Utf8: > case CONSTANT_Unicode: > break; > + case CONSTANT_MethodHandle: > + n = JPOOL_USHORT1 (jcf, i); > + if (n < 1 || n > 9) > + return i; > + n = JPOOL_USHORT2 (jcf, i); > + if (n <= 0 || n >= JPOOL_SIZE(jcf)) > + return i; > + break; > + case CONSTANT_MethodType: > + n = JPOOL_USHORT1 (jcf, i); > + if (n <= 0 || n >= JPOOL_SIZE(jcf) > + || JPOOL_TAG (jcf, n) != CONSTANT_Utf8) > + return i; > + break; > + case CONSTANT_InvokeDynamic: > + n = JPOOL_USHORT2 (jcf, i); > + if (n <= 0 || n >= JPOOL_SIZE(jcf) > + || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType) > + return i; > + break; > default: > return i; > }
Index: java/jcf-dump.c =================================================================== --- java/jcf-dump.c (revision 186103) +++ java/jcf-dump.c (working copy) @@ -430,7 +430,24 @@ print_element_value (out, jcf, 1); \ } +#define HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE() \ +{ \ + COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \ + fputc ('\n', out); jcf_parse_bootstrap_methods (jcf, attribute_length); \ +} +#define HANDLE_END_BOOTSTRAP_METHODS(NUM_METHODS) \ + { \ + int i; \ + for (i = 0; i < NUM_METHODS; i++) \ + { \ + bootstrap_method *m = &jcf->bootstrap_methods.methods[i]; \ + fprintf (out, " %d: ", i); \ + print_constant (out, jcf, m->method_ref, 1); \ + fprintf (out, "\n"); \ + } \ + } + #define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \ { COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \ fputc ('\n', out); JCF_SKIP (JCF, LENGTH); } @@ -898,6 +915,53 @@ fputc ('\"', out); } break; + case CONSTANT_MethodHandle: + { + int kind = JPOOL_USHORT1 (jcf, index); + if (verbosity > 0) + fprintf (out, "MethodHandle kind: %d=", kind); + switch(kind) { + case 1: + case 2: + case 3: + case 4: + if (verbosity > 0) + fprintf (out, "Fieldref: %ld=", JPOOL_USHORT2 (jcf, index)); + print_constant (out, jcf, JPOOL_USHORT2 (jcf, index), 0); + case 5: + case 6: + case 7: + case 8: + if (verbosity > 0) + fprintf (out, "Methodref: %ld=", JPOOL_USHORT2 (jcf, index)); + print_constant (out, jcf, JPOOL_USHORT2 (jcf, index), 0); + break; + case 9: + if (verbosity > 0) + fprintf (out, "InterfaceMethodref: %ld=", JPOOL_USHORT2 (jcf, index)); + print_constant (out, jcf, JPOOL_USHORT2 (jcf, index), 0); + break; + } + break; + } + case CONSTANT_MethodType: + if (verbosity > 0) + fprintf (out, "MethodType %ld: ", JPOOL_USHORT1 (jcf, index)); + print_signature (out, jcf, JPOOL_USHORT1 (jcf, index), 0); + break; + case CONSTANT_InvokeDynamic: + { + uint16 name_and_type = JPOOL_USHORT2 (jcf, index); + if (verbosity > 0) + fprintf (out, "InvokeDynamic: "); + fprintf (out, "bootstrap_method: %ld ", JPOOL_USHORT1 (jcf, index)); + if (verbosity == 2) + fprintf (out, " name_and_type: %d=<", name_and_type); + print_constant_terse (out, jcf, name_and_type, CONSTANT_NameAndType); + if (verbosity == 2) + fputc ('>', out); + break; + } default: fprintf (out, "(Unknown constant type %d)", kind); } Index: java/jcf-parse.c =================================================================== --- java/jcf-parse.c (revision 186103) +++ java/jcf-parse.c (working copy) @@ -1113,8 +1113,8 @@ jcf->cpool.data[index].t = value; return value; bad: - internal_error ("bad value constant type %d, index %d", - JPOOL_TAG (jcf, index), index); + fatal_error ("bad value constant type %d, index %d", + JPOOL_TAG (jcf, index), index); } tree Index: java/javaop.def =================================================================== --- java/javaop.def (revision 186103) +++ java/javaop.def (working copy) @@ -292,6 +292,7 @@ JAVAOP (invokespecial, 183, INVOKE, SPECIAL, 0) JAVAOP (invokestatic, 184, INVOKE, STATIC, 0) JAVAOP (invokeinterface,185, INVOKE, INTERFACE, 1) +JAVAOP (invokedynamic, 186, INVOKE, DYNAMIC, 1) JAVAOP (new, 187, OBJECT, PTR, NEW) JAVAOP (newarray, 188, ARRAY, NUM, NEW) JAVAOP (anewarray, 189, ARRAY, PTR, NEW) Index: java/jcf-reader.c =================================================================== --- java/jcf-reader.c (revision 186103) +++ java/jcf-reader.c (working copy) @@ -36,6 +36,7 @@ static int jcf_parse_one_method (JCF *, int); static int jcf_parse_methods (JCF *); static int jcf_parse_final_attributes (JCF *); +static int jcf_parse_bootstrap_methods (JCF *, int ); #ifdef NEED_PEEK_ATTRIBUTE static int peek_attribute (JCF *, int, const char *, int); #endif @@ -293,7 +294,16 @@ } else #endif + if (MATCH_ATTRIBUTE ("BootstrapMethods")) { +#ifdef HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE + HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE(); +#else + JCF_SKIP (jcf, attribute_length); +#endif + } + else + { #ifdef PROCESS_OTHER_ATTRIBUTE PROCESS_OTHER_ATTRIBUTE(jcf, attribute_name, attribute_length); #else @@ -382,6 +392,17 @@ JCF_SKIP (jcf, n); #endif break; + case CONSTANT_MethodHandle: + jcf->cpool.data[i].w = JCF_readu (jcf); + jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16; + break; + case CONSTANT_MethodType: + jcf->cpool.data[i].w = JCF_readu2 (jcf); + break; + case CONSTANT_InvokeDynamic: + jcf->cpool.data[i].w = JCF_readu2 (jcf); + jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16; + break; default: return i; } @@ -521,3 +542,39 @@ return 0; } +/* Read and handle the "BootstrapMethods" attribute. + + Return 0 if OK. +*/ +static int +jcf_parse_bootstrap_methods (JCF* jcf, int attribute_length ATTRIBUTE_UNUSED) +{ + int i; + uint16 num_methods = JCF_readu2 (jcf); + jcf->bootstrap_methods.count = num_methods; + jcf->bootstrap_methods.methods + = (bootstrap_method *) ggc_alloc_atomic (num_methods + * sizeof (bootstrap_method)); +#ifdef HANDLE_START_BOOTSTRAP_METHODS + HANDLE_START_BOOTSTRAP_METHODS (jcf, num_methods); +#endif + + for (i = 0; i < num_methods; i++) + { + unsigned j; + bootstrap_method *m = &jcf->bootstrap_methods.methods[i]; + m->method_ref = JCF_readu2 (jcf); + m->num_arguments = JCF_readu2 (jcf); + m->bootstrap_arguments + = (unsigned *) ggc_alloc_atomic (m->num_arguments + * sizeof (unsigned)); + for (j = 0; j < m->num_arguments; j++) + m->bootstrap_arguments[j] = JCF_readu2 (jcf); + } + +#ifdef HANDLE_END_BOOTSTRAP_METHODS + HANDLE_END_BOOTSTRAP_METHODS (num_methods); +#endif + + return 0; +} Index: java/jcf.h =================================================================== --- java/jcf.h (revision 186103) +++ java/jcf.h (working copy) @@ -88,6 +88,17 @@ desc ("cpool_entry_is_tree (%1.tags%a)"))) data; } CPool; +typedef struct GTY(()) bootstrap_method { + unsigned method_ref; + unsigned num_arguments; + unsigned* GTY((length ("%h.num_arguments"))) bootstrap_arguments; +} bootstrap_method; + +typedef struct GTY(()) BootstrapMethods { + unsigned count; + bootstrap_method* GTY((length ("%h.count"))) methods; +} BootstrapMethods; + struct ZipDirectory; /* JCF encapsulates the state of reading a Java Class File. */ @@ -109,6 +120,7 @@ JCF_u2 this_class; JCF_u2 super_class; CPool cpool; + BootstrapMethods bootstrap_methods; } JCF; /*typedef JCF* JCF_FILE;*/ @@ -245,6 +257,10 @@ CONSTANT_NameAndType = 12, CONSTANT_Utf8 = 1, CONSTANT_Unicode = 2, + CONSTANT_MethodHandle = 15, + CONSTANT_MethodType = 16, + CONSTANT_InvokeDynamic = 18, + CONSTANT_None = 0 }; Index: java/jcf-io.c =================================================================== --- java/jcf-io.c (revision 186103) +++ java/jcf-io.c (working copy) @@ -518,6 +518,26 @@ case CONSTANT_Utf8: case CONSTANT_Unicode: break; + case CONSTANT_MethodHandle: + n = JPOOL_USHORT1 (jcf, i); + if (n < 1 || n > 9) + return i; + n = JPOOL_USHORT2 (jcf, i); + if (n <= 0 || n >= JPOOL_SIZE(jcf)) + return i; + break; + case CONSTANT_MethodType: + n = JPOOL_USHORT1 (jcf, i); + if (n <= 0 || n >= JPOOL_SIZE(jcf) + || JPOOL_TAG (jcf, n) != CONSTANT_Utf8) + return i; + break; + case CONSTANT_InvokeDynamic: + n = JPOOL_USHORT2 (jcf, i); + if (n <= 0 || n >= JPOOL_SIZE(jcf) + || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType) + return i; + break; default: return i; }