2000-08-07 Alexandre Petit-Bianco <apbianco@cygnus.com

* parse.y (build_dot_class_method_invocation): Changed parameter
	name to `type.' Build signature from `type' and convert it to a
	STRING_CST if it's an array.
	(patch_incomplete_class_ref): `build_dot_class_method_invocation'
	to use `ref_type' directly.

2000-08-01  Alexandre Petit-Bianco  <apbianco@cygnus.com>

	* parse.y (maybe_yank_clinit): When generating bytecode: non empty
	method bodies not to rule out discarding `<clinit>'; don't use
	<clinit> to initialize static fields with constant initializers.

2000-08-01  Alexandre Petit-Bianco  <apbianco@cygnus.com>

	* gjavah.c (print_method_info): Added `synth' parameter. Skip
	synthetic methods.
	(method_synthetic): New global.
	(HANDLE_METHOD): Recognize synthetic method and tell
	`print_method_info' about it.
	(HANDLE_END_METHOD): Do not issue an additional `;\n' if we're
	processing a synthetic method.
	* jcf-reader.c (skip_attribute): New function.
	( skip_attribute): Likewise.

2000-08-01  Alexandre Petit-Bianco  <apbianco@cygnus.com>

	* parse.y (build_outer_field_access): Fixed comments.
	(fix_constructors): Emit the initialization of this$<n> before
	calling $finit$.
	(resolve_qualified_expression_name): Build an access to `decl' if
	necessary.

2000-07-31  Alexandre Petit-Bianco  <apbianco@cygnus.com>

	* parse-scan.y (curent_class): Non longer const.
	(inner_qualifier, inner_qualifier_length): Deleted.
	(current_class_length): New global.
	(bracket_count): Fixed typo in leading comment.
	(anonymous_count): New global.
	(class_instance_creation_expression:): Handle anonymous classes.
	(anonymous_class_creation:): New rule.
	(push_class_context): Rewritten.
	(pop_class_context): Likewise.
	(INNER_QUALIFIER): Macro deleted.
	(report_class_declaration): call `push_class_context' when
	entering the function. `fprintf' format modified not to use
	INNER_QUALIFIER.
	(report_class_declaration): Assign `package_name' and
	`current_class' to NULL separatly.

2000-07-31  Alexandre Petit-Bianco  <apbianco@cygnus.com>

	* expr.c (build_invokeinterface): Call layout_class_methods on
	target interface.

(http://gcc.gnu.org/ml/gcc-patches/2000-08/msg00339.html)

From-SVN: r35560
This commit is contained in:
Alexandre Petit-Bianco 2000-08-08 03:33:36 +00:00 committed by Alexandre Petit-Bianco
parent 0da9afa6d6
commit f0f3a77740
6 changed files with 290 additions and 78 deletions

View File

@ -1,3 +1,11 @@
2000-08-07 Alexandre Petit-Bianco <apbianco@cygnus.com
* parse.y (build_dot_class_method_invocation): Changed parameter
name to `type.' Build signature from `type' and convert it to a
STRING_CST if it's an array.
(patch_incomplete_class_ref): `build_dot_class_method_invocation'
to use `ref_type' directly.
Sun Aug 6 00:47:24 2000 Ovidiu Predescu <ovidiu@cup.hp.com>
* lang-options.h: Added a comma after the last element to avoid
@ -17,6 +25,55 @@ Sun Aug 6 00:47:24 2000 Ovidiu Predescu <ovidiu@cup.hp.com>
* class.c (build_dtable_decl): Initialize dummy.
2000-08-01 Alexandre Petit-Bianco <apbianco@cygnus.com>
* parse.y (maybe_yank_clinit): When generating bytecode: non empty
method bodies not to rule out discarding `<clinit>'; don't use
<clinit> to initialize static fields with constant initializers.
2000-08-01 Alexandre Petit-Bianco <apbianco@cygnus.com>
* gjavah.c (print_method_info): Added `synth' parameter. Skip
synthetic methods.
(method_synthetic): New global.
(HANDLE_METHOD): Recognize synthetic method and tell
`print_method_info' about it.
(HANDLE_END_METHOD): Do not issue an additional `;\n' if we're
processing a synthetic method.
* jcf-reader.c (skip_attribute): New function.
( skip_attribute): Likewise.
2000-08-01 Alexandre Petit-Bianco <apbianco@cygnus.com>
* parse.y (build_outer_field_access): Fixed comments.
(fix_constructors): Emit the initialization of this$<n> before
calling $finit$.
(resolve_qualified_expression_name): Build an access to `decl' if
necessary.
2000-07-31 Alexandre Petit-Bianco <apbianco@cygnus.com>
* parse-scan.y (curent_class): Non longer const.
(inner_qualifier, inner_qualifier_length): Deleted.
(current_class_length): New global.
(bracket_count): Fixed typo in leading comment.
(anonymous_count): New global.
(class_instance_creation_expression:): Handle anonymous classes.
(anonymous_class_creation:): New rule.
(push_class_context): Rewritten.
(pop_class_context): Likewise.
(INNER_QUALIFIER): Macro deleted.
(report_class_declaration): call `push_class_context' when
entering the function. `fprintf' format modified not to use
INNER_QUALIFIER.
(report_class_declaration): Assign `package_name' and
`current_class' to NULL separatly.
2000-07-31 Alexandre Petit-Bianco <apbianco@cygnus.com>
* expr.c (build_invokeinterface): Call layout_class_methods on
target interface.
2000-07-27 Tom Tromey <tromey@cygnus.com>
Anthony Green <green@cygnus.com>
Alexandre Petit-Bianco <apbianco@cygnus.com>

View File

@ -1783,6 +1783,7 @@ build_invokeinterface (dtable, method)
lookup_field (&dtable_type, class_ident));
interface = DECL_CONTEXT (method);
layout_class_methods (interface);
i = 1;
for (meth = TYPE_METHODS (interface); ; meth = TREE_CHAIN (meth), i++)

View File

@ -116,7 +116,7 @@ static struct method_name *method_name_list;
static void print_field_info PARAMS ((FILE*, JCF*, int, int, JCF_u2));
static void print_mangled_classname PARAMS ((FILE*, JCF*, const char*, int));
static int print_cxx_classname PARAMS ((FILE*, const char*, JCF*, int));
static void print_method_info PARAMS ((FILE*, JCF*, int, int, JCF_u2));
static void print_method_info PARAMS ((FILE*, JCF*, int, int, JCF_u2, int));
static void print_c_decl PARAMS ((FILE*, JCF*, int, int, int, const char *,
int));
static void print_stub_or_jni PARAMS ((FILE*, JCF*, int, int, int,
@ -182,26 +182,45 @@ static int method_pass;
static int method_declared = 0;
static int method_access = 0;
static int method_printed = 0;
#define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
if (method_pass) \
{ \
decompiled = 0; method_printed = 0; \
if (out) \
print_method_info (out, jcf, NAME, SIGNATURE, ACCESS_FLAGS); \
} \
else \
{ \
print_method_info (NULL, jcf, NAME, SIGNATURE, ACCESS_FLAGS); \
if (! stubs && ! flag_jni) \
add_class_decl (out, jcf, SIGNATURE); \
}
static int method_synthetic = 0;
#define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
{ \
method_synthetic = 0; \
if (ATTRIBUTE_COUNT) \
method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \
(const char *)"Synthetic", 9); \
/* If a synthetic methods have been declared, its attribute aren't \
worth reading (and triggering side-effects). We skip them an \
set ATTRIBUTE_COUNT to zero so that they'll be skipped in \
jcf_parse_one_method. */ \
if (method_synthetic) \
{ \
skip_attribute (jcf, ATTRIBUTE_COUNT); \
ATTRIBUTE_COUNT = 0; \
} \
if (method_pass && !method_synthetic) \
{ \
decompiled = 0; method_printed = 0; \
if (out) \
print_method_info (out, jcf, NAME, SIGNATURE, \
ACCESS_FLAGS, method_synthetic); \
} \
else if (!method_synthetic) \
{ \
print_method_info (NULL, jcf, NAME, SIGNATURE, \
ACCESS_FLAGS, method_synthetic); \
if (! stubs && ! flag_jni) \
add_class_decl (out, jcf, SIGNATURE); \
} \
}
#define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
#define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
static int decompiled = 0;
#define HANDLE_END_METHOD() \
if (out && method_printed) fputs (decompiled || stubs ? "\n" : ";\n", out);
#define HANDLE_END_METHOD() \
if (out && method_printed && !method_synthetic) \
fputs (decompiled || stubs ? "\n" : ";\n", out);
#include "jcf-reader.c"
@ -670,9 +689,9 @@ DEFUN(print_field_info, (stream, jcf, name_index, sig_index, flags),
static void
DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags, synth),
FILE *stream AND JCF* jcf
AND int name_index AND int sig_index AND JCF_u2 flags)
AND int name_index AND int sig_index AND JCF_u2 flags AND int synth)
{
const unsigned char *str;
int length, is_init = 0;
@ -684,10 +703,15 @@ DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
fprintf (stream, "<not a UTF8 constant>");
str = JPOOL_UTF_DATA (jcf, name_index);
length = JPOOL_UTF_LENGTH (jcf, name_index);
if (str[0] == '<' || str[0] == '$')
/* Ignore synthetic methods. */
if (synth)
return;
if (str[0] == '<')
{
/* Ignore internally generated methods like <clinit> and
$finit$. However, treat <init> as a constructor. */
/* Ignore the internally generated method <clinit>. However,
treat <init> as a constructor. */
if (! utf8_cmp (str, length, "<init>"))
is_init = 1;
else if (! METHOD_IS_FINAL (jcf->access_flags, flags)

View File

@ -27,6 +27,8 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "zipfile.h"
static int get_attribute PARAMS ((JCF *));
static int peek_attribute PARAMS ((JCF *, int, const char *, int));
static void skip_attribute PARAMS ((JCF *, int));
static int jcf_parse_preamble PARAMS ((JCF *));
static int jcf_parse_constant_pool PARAMS ((JCF *));
static void jcf_parse_class PARAMS ((JCF *));
@ -35,6 +37,64 @@ static int jcf_parse_one_method PARAMS ((JCF *));
static int jcf_parse_methods PARAMS ((JCF *));
static int jcf_parse_final_attributes PARAMS ((JCF *));
/* Go through all available attribute (ATTRIBUTE_NUMER) and try to
identify PEEKED_NAME. Return 1 if PEEKED_NAME was found, 0
otherwise. JCF is restored to its initial position before
returning. */
static int
peek_attribute (jcf, attribute_number, peeked_name, peeked_name_length)
JCF *jcf;
int attribute_number;
const char *peeked_name;
int peeked_name_length;
{
int to_return = 0;
long absolute_offset = (long)JCF_TELL (jcf);
int i;
for (i = 0; !to_return && i < attribute_number; i++)
{
uint16 attribute_name = (JCF_FILL (jcf, 6), JCF_readu2 (jcf));
uint32 attribute_length = JCF_readu4 (jcf);
int name_length;
const unsigned char *name_data;
JCF_FILL (jcf, (long) attribute_length);
if (attribute_name <= 0 || attribute_name >= JPOOL_SIZE(jcf)
|| JPOOL_TAG (jcf, attribute_name) != CONSTANT_Utf8)
continue;
name_length = JPOOL_UTF_LENGTH (jcf, attribute_name);
name_data = JPOOL_UTF_DATA (jcf, attribute_name);
if (name_length == peeked_name_length
&& ! memcmp (name_data, peeked_name, peeked_name_length))
{
to_return = 1;
break;
}
JCF_SKIP (jcf, attribute_length);
}
JCF_SEEK (jcf, absolute_offset);
return to_return;
}
static void
skip_attribute (jcf, number_of_attribute)
JCF *jcf;
int number_of_attribute;
{
while (number_of_attribute--)
{
JCF_FILL (jcf, 6);
(void) JCF_readu2 (jcf);
JCF_SKIP (jcf, JCF_readu4 (jcf));
}
}
static int
DEFUN(get_attribute, (jcf),
JCF *jcf)

View File

@ -63,12 +63,11 @@ static int absorber;
#define USE_ABSORBER absorber = 0
/* Keep track of the current class name and package name. */
static const char *current_class;
static char *current_class;
static const char *package_name;
/* Keep track of the current inner class qualifier. */
static char *inner_qualifier;
static int inner_qualifier_length;
static int current_class_length;
/* Keep track of whether things have be listed before. */
static int previous_output;
@ -76,10 +75,13 @@ static int previous_output;
/* Record modifier uses */
static int modifier_value;
/* Keep track of number of bracket pairs after a variable declarator
/* Keeps track of number of bracket pairs after a variable declarator
id. */
static int bracket_count;
/* Numbers anonymous classes */
static int anonymous_count;
/* Record a method declaration */
struct method_declarator {
const char *method_name;
@ -897,20 +899,22 @@ primary_no_new_array:
class_instance_creation_expression:
NEW_TK class_type OP_TK argument_list CP_TK
| NEW_TK class_type OP_TK CP_TK
/* Added, JDK1.1 inner classes but modified to use
'class_type' instead of 'TypeName' (type_name) mentionned
in the documentation but doesn't exist. */
| NEW_TK class_type OP_TK argument_list CP_TK class_body
| NEW_TK class_type OP_TK CP_TK class_body
/* Added, JDK1.1 inner classes, modified to use name or
primary instead of primary solely which couldn't work in
all situations. */
| anonymous_class_creation
| something_dot_new identifier OP_TK CP_TK
| something_dot_new identifier OP_TK CP_TK class_body
| something_dot_new identifier OP_TK argument_list CP_TK
| something_dot_new identifier OP_TK argument_list CP_TK class_body
;
anonymous_class_creation:
NEW_TK class_type OP_TK CP_TK
{ report_class_declaration (NULL); }
class_body
| NEW_TK class_type OP_TK argument_list CP_TK
{ report_class_declaration (NULL); }
class_body
;
something_dot_new: /* Added, not part of the specs. */
name DOT_TK NEW_TK
{ USE_ABSORBER; }
@ -1128,29 +1132,61 @@ static void
push_class_context (name)
const char *name;
{
size_t name_length = strlen (name);
inner_qualifier = xrealloc (inner_qualifier,
inner_qualifier_length + name_length+2);
memcpy (inner_qualifier+inner_qualifier_length, name, name_length);
inner_qualifier_length += name_length;
inner_qualifier [inner_qualifier_length] = '$';
inner_qualifier [++inner_qualifier_length] = '\0';
/* If we already have CURRENT_CLASS set, we're in an inter
class. Mangle its name. */
if (current_class)
{
const char *p;
char anonymous [3];
int additional_length;
/* NAME set to NULL indicates an anonymous class, which are named by
numbering them. */
if (!name)
{
sprintf (anonymous, "%d", ++anonymous_count);
p = anonymous;
}
else
p = name;
additional_length = strlen (p)+1; /* +1 for `$' */
current_class = xrealloc (current_class,
current_class_length + additional_length + 1);
current_class [current_class_length] = '$';
strcpy (&current_class [current_class_length+1], p);
current_class_length += additional_length;
}
else
{
if (!name)
return;
current_class_length = strlen (name);
current_class = xmalloc (current_class_length+1);
strcpy (current_class, name);
}
}
static void
pop_class_context ()
{
while (--inner_qualifier_length > 0
&& inner_qualifier [inner_qualifier_length-1] != '$')
/* Go back to the last `$' and cut. */
while (--current_class_length > 0
&& current_class [current_class_length] != '$')
;
inner_qualifier = xrealloc (inner_qualifier, inner_qualifier_length+1);
if (inner_qualifier_length == -1)
inner_qualifier_length = 0;
inner_qualifier [inner_qualifier_length] = '\0';
if (current_class_length)
{
current_class = xrealloc (current_class, current_class_length+1);
current_class [current_class_length] = '\0';
}
else
{
current_class = NULL;
anonymous_count = 0;
}
}
/* Actions defined here */
#define INNER_QUALIFIER (inner_qualifier ? inner_qualifier : "")
static void
report_class_declaration (name)
@ -1158,6 +1194,7 @@ report_class_declaration (name)
{
extern int flag_dump_class, flag_list_filename;
push_class_context (name);
if (flag_dump_class)
{
if (!previous_output)
@ -1168,13 +1205,10 @@ report_class_declaration (name)
}
if (package_name)
fprintf (out, "%s.%s%s ", package_name, INNER_QUALIFIER, name);
fprintf (out, "%s.%s ", package_name, current_class);
else
fprintf (out, "%s%s ", INNER_QUALIFIER, name);
fprintf (out, "%s ", current_class);
}
push_class_context (name);
current_class = name;
}
static void
@ -1208,7 +1242,8 @@ report_main_declaration (declarator)
void reset_report ()
{
previous_output = 0;
current_class = package_name = NULL;
package_name = NULL;
current_class = NULL;
}
void

View File

@ -7523,12 +7523,14 @@ maybe_yank_clinit (mdecl)
if (!DECL_CLINIT_P (mdecl))
return 0;
/* If the body isn't empty, then we keep <clinit> */
/* If the body isn't empty, then we keep <clinit>. Note that if
we're emitting classfiles, this isn't enough not to rule it
out. */
fbody = DECL_FUNCTION_BODY (mdecl);
if ((bbody = BLOCK_EXPR_BODY (fbody)))
bbody = BLOCK_EXPR_BODY (bbody);
if (bbody && bbody != empty_stmt_node)
if (bbody && ! flag_emit_class_files && bbody != empty_stmt_node)
return 0;
type = DECL_CONTEXT (mdecl);
@ -7536,9 +7538,34 @@ maybe_yank_clinit (mdecl)
for (current = (current ? TREE_CHAIN (current) : current);
current; current = TREE_CHAIN (current))
if (!(FIELD_STATIC (current) && FIELD_FINAL (current)
&& DECL_INITIAL (current) && TREE_CONSTANT (DECL_INITIAL (current))))
break;
{
tree f_init;
/* We're not interested in non static field */
if (!FIELD_STATIC (current))
continue;
/* Anything that isn't String or a basic type is ruled out -- or
if we now how to deal with it (when doing things natively) we
should generated an empty <clinit> so that SUID are computed
correctly. */
if (! JSTRING_TYPE_P (TREE_TYPE (current))
&& ! JNUMERIC_TYPE_P (TREE_TYPE (current)))
break;
f_init = DECL_INITIAL (current);
/* If we're emitting native code, we want static final fields to
have constant initializers. If we don't meet these
conditions, we keep <clinit> */
if (!flag_emit_class_files
&& !(FIELD_FINAL (current) && f_init && TREE_CONSTANT (f_init)))
break;
/* If we're emitting bytecode, we want static fields to have
constant initializers or no initializer. If we don't meet
these conditions, we keep <clinit> */
if (flag_emit_class_files && f_init && !TREE_CONSTANT (f_init))
break;
}
if (current)
return 0;
@ -7661,7 +7688,7 @@ build_outer_field_access (id, decl)
tree ctx = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current_class)));
/* If decl's class is the direct outer class of the current_class,
build the access as `this$<n>.<field>'. Not that we will break
build the access as `this$<n>.<field>'. Note that we will break
the `private' barrier if we're not emitting bytecodes. */
if (ctx == DECL_CONTEXT (decl)
&& (!FIELD_PRIVATE (decl) || !flag_emit_class_files ))
@ -7677,7 +7704,7 @@ build_outer_field_access (id, decl)
int lc = EXPR_WFL_LINECOL (id);
/* Now we chain the required number of calls to the access$0 to
get a hold to the enclosing instance we need, and the we
get a hold to the enclosing instance we need, and then we
build the field access. */
access = build_access_to_thisn (ctx, DECL_CONTEXT (decl), lc);
@ -8269,14 +8296,21 @@ build_dot_class_method (class)
}
static tree
build_dot_class_method_invocation (name)
tree name;
build_dot_class_method_invocation (type)
tree type;
{
tree s = make_node (STRING_CST);
TREE_STRING_LENGTH (s) = IDENTIFIER_LENGTH (name);
tree sig_id, s;
if (TYPE_ARRAY_P (type))
sig_id = build_java_signature (type);
else
sig_id = DECL_NAME (TYPE_NAME (type));
s = make_node (STRING_CST);
TREE_STRING_LENGTH (s) = IDENTIFIER_LENGTH (sig_id);
TREE_STRING_POINTER (s) = obstack_alloc (expression_obstack,
TREE_STRING_LENGTH (s)+1);
strcpy (TREE_STRING_POINTER (s), IDENTIFIER_POINTER (name));
strcpy (TREE_STRING_POINTER (s), IDENTIFIER_POINTER (sig_id));
return build_method_invocation (build_wfl_node (get_identifier ("class$")),
build_tree_list (NULL_TREE, s));
}
@ -8318,6 +8352,11 @@ fix_constructors (mdecl)
CLASSNAME() constructor */
start_artificial_method_body (mdecl);
/* Insert an assignment to the this$<n> hidden field, if
necessary */
if ((thisn_assign = build_thisn_assign ()))
java_method_add_stmt (mdecl, thisn_assign);
/* We don't generate a super constructor invocation if we're
compiling java.lang.Object. build_super_invocation takes care
of that. */
@ -8327,11 +8366,6 @@ fix_constructors (mdecl)
super invocation. */
add_instance_initializer (mdecl);
/* Insert an assignment to the this$<n> hidden field, if
necessary */
if ((thisn_assign = build_thisn_assign ()))
java_method_add_stmt (mdecl, thisn_assign);
end_artificial_method_body (mdecl);
}
/* Search for an explicit constructor invocation */
@ -8363,14 +8397,14 @@ fix_constructors (mdecl)
compound = add_stmt_to_compound (compound, NULL_TREE,
build_super_invocation (mdecl));
/* Insert the instance initializer block right here, after the
super invocation. */
add_instance_initializer (mdecl);
/* Generate the assignment to this$<n>, if necessary */
if ((thisn_assign = build_thisn_assign ()))
compound = add_stmt_to_compound (compound, NULL_TREE, thisn_assign);
/* Insert the instance initializer block right here, after the
super invocation. */
add_instance_initializer (mdecl);
/* Fix the constructor main block if we're adding extra stmts */
if (compound)
{
@ -9170,6 +9204,8 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
current_class);
return 1;
}
if (outer_field_access_p (current_class, decl))
decl = build_outer_field_access (qual_wfl, decl);
}
else
{
@ -13114,8 +13150,7 @@ patch_incomplete_class_ref (node)
synthetic static method `class$'. */
if (!TYPE_DOT_CLASS (current_class))
build_dot_class_method (current_class);
ref_type =
build_dot_class_method_invocation (DECL_NAME (TYPE_NAME (ref_type)));
ref_type = build_dot_class_method_invocation (ref_type);
return java_complete_tree (ref_type);
}