From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31542 invoked by alias); 11 Apr 2012 10:22:35 -0000 Received: (qmail 31520 invoked by uid 22791); 11 Apr 2012 10:22:33 -0000 X-SWARE-Spam-Status: No, hits=-6.3 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,RCVD_IN_DNSWL_HI,RCVD_IN_HOSTKARMA_W,SPF_HELO_PASS,TW_JC,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 11 Apr 2012 10:22:03 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q3BAM2ER023147 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 11 Apr 2012 06:22:03 -0400 Received: from zebedee.pink (ovpn-113-60.phx2.redhat.com [10.3.113.60]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q3BAM1YZ010944; Wed, 11 Apr 2012 06:22:02 -0400 Message-ID: <4F855B49.2070605@redhat.com> Date: Wed, 11 Apr 2012 10:22:00 -0000 From: Andrew Haley User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:11.0) Gecko/20120329 Thunderbird/11.0.1 MIME-Version: 1.0 To: GCC Patches , GCJ-patches Subject: jcf-reader: support for JSR 292 classfile extensions Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Mailing-List: contact java-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: java-patches-owner@gcc.gnu.org X-SW-Source: 2012-q2/txt/msg00008.txt.bz2 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. Andrew. 2012-04-11 Andrew Haley * 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; }