Commit cd9643f7 by Per Bothner

class.c (make_field_value): DECL_INITIAL may be a string literal...

d
	* class.c (make_field_value):  DECL_INITIAL may be a string literal;
	temporarily zero it while calling rest_of_decl_compilation.
	* java-tree.h (string_ptr_type_node):  Add declaration.
	* decl.c:  Define and initialize string_ptr_type_node.
	* parse.y (patch_string_cst):  Use string_ptr_type_node.
	* parse.h (LOOP_HAS_LABEL_P, LOOP_HAS_LABEL_SKIP_P):  Removed.
	* parse.y (for_statement):  Now unconditionally exit_block.
	(finish_labeled_statement):  No longer exit_block if for-loop.
	(patch_loop_statement):  Check harder if the loop is already labeled.
	* parse.y (patch_initialized_static_field):  Removed function.
	(maybe_generate_clinit):  Removed special handling for interfaces.
	(java_complete_expand_methods):  Do a preliminary java_complete_tree
	on <clinit> to determine if it can be removed.
	(java_complete_expand_method):  Remove special handling for <clinit>.
	(java_complete_lhs):  For BLOCK and EXPR_WITH_FILE_LOCATION
	optimize if we get back empty_stmt_node.
	For MODIFY_EXPR, re-do checking of static initializers.
	(fold_constant_for_init):  Don't return immediate if VAR_DECL.
	For VAR_DECL, pass correct context.

From-SVN: r26790
parent c14cff58
...@@ -1025,9 +1025,16 @@ make_class_data (type) ...@@ -1025,9 +1025,16 @@ make_class_data (type)
tree init = make_field_value (field); tree init = make_field_value (field);
if (FIELD_STATIC (field)) if (FIELD_STATIC (field))
{ {
tree initial = DECL_INITIAL (field);
static_field_count++; static_field_count++;
static_fields = tree_cons (NULL_TREE, init, static_fields); static_fields = tree_cons (NULL_TREE, init, static_fields);
/* If the initial value is a string constant,
prevent output_constant from trying to assemble the value. */
if (initial != NULL_TREE
&& TREE_TYPE (initial) == string_ptr_type_node)
DECL_INITIAL (field) = NULL_TREE;
rest_of_decl_compilation (field, (char*) 0, 1, 1); rest_of_decl_compilation (field, (char*) 0, 1, 1);
DECL_INITIAL (field) = initial;
} }
else else
{ {
......
...@@ -254,6 +254,7 @@ tree object_type_node; ...@@ -254,6 +254,7 @@ tree object_type_node;
tree unqualified_object_id_node; tree unqualified_object_id_node;
tree object_ptr_type_node; tree object_ptr_type_node;
tree string_type_node; tree string_type_node;
tree string_ptr_type_node;
tree throwable_type_node; tree throwable_type_node;
tree runtime_exception_type_node; tree runtime_exception_type_node;
tree error_exception_type_node; tree error_exception_type_node;
...@@ -549,6 +550,7 @@ init_decl_processing () ...@@ -549,6 +550,7 @@ init_decl_processing ()
object_type_node = lookup_class (get_identifier ("java.lang.Object")); object_type_node = lookup_class (get_identifier ("java.lang.Object"));
object_ptr_type_node = promote_type (object_type_node); object_ptr_type_node = promote_type (object_type_node);
string_type_node = lookup_class (get_identifier ("java.lang.String")); string_type_node = lookup_class (get_identifier ("java.lang.String"));
string_ptr_type_node = promote_type (string_type_node);
class_type_node = lookup_class (get_identifier ("java.lang.Class")); class_type_node = lookup_class (get_identifier ("java.lang.Class"));
throwable_type_node = lookup_class (get_identifier ("java.lang.Throwable")); throwable_type_node = lookup_class (get_identifier ("java.lang.Throwable"));
runtime_exception_type_node = runtime_exception_type_node =
......
...@@ -198,6 +198,7 @@ extern tree object_type_node; ...@@ -198,6 +198,7 @@ extern tree object_type_node;
extern tree unqualified_object_id_node; extern tree unqualified_object_id_node;
extern tree object_ptr_type_node; extern tree object_ptr_type_node;
extern tree string_type_node; extern tree string_type_node;
extern tree string_ptr_type_node;
extern tree throwable_type_node; extern tree throwable_type_node;
extern tree runtime_exception_type_node; extern tree runtime_exception_type_node;
extern tree error_exception_type_node; extern tree error_exception_type_node;
......
...@@ -258,18 +258,6 @@ extern tree stabilize_reference PROTO ((tree)); ...@@ -258,18 +258,6 @@ extern tree stabilize_reference PROTO ((tree));
#define LOOP_EXPR_BODY_BODY_EXPR(NODE, R) \ #define LOOP_EXPR_BODY_BODY_EXPR(NODE, R) \
LABELED_BLOCK_BODY (LOOP_EXPR_BODY_LABELED_BODY(NODE, R)) LABELED_BLOCK_BODY (LOOP_EXPR_BODY_LABELED_BODY(NODE, R))
/* Does a loop have a label ? */
#define LOOP_HAS_LABEL_P(LOOP) \
(ctxp->current_labeled_block \
&& LABELED_BLOCK_BODY (ctxp->current_labeled_block) == (LOOP))
/* Same operation than the one performed above, but considering the
previous labeled block */
#define LOOP_HAS_LABEL_SKIP_P(LOOP) \
(ctxp->current_labeled_block \
&& TREE_CHAIN (ctxp->current_labeled_block) \
&& LABELED_BLOCK_BODY (TREE_CHAIN (ctxp->current_labeled_block)) == (LOOP))
#define PUSH_LABELED_BLOCK(B) \ #define PUSH_LABELED_BLOCK(B) \
{ \ { \
TREE_CHAIN (B) = ctxp->current_labeled_block; \ TREE_CHAIN (B) = ctxp->current_labeled_block; \
......
...@@ -237,7 +237,6 @@ static tree patch_new_array_init PROTO ((tree, tree)); ...@@ -237,7 +237,6 @@ static tree patch_new_array_init PROTO ((tree, tree));
static tree maybe_build_array_element_wfl PROTO ((tree)); static tree maybe_build_array_element_wfl PROTO ((tree));
static int array_constructor_check_entry PROTO ((tree, tree)); static int array_constructor_check_entry PROTO ((tree, tree));
static char *purify_type_name PROTO ((char *)); static char *purify_type_name PROTO ((char *));
static tree patch_initialized_static_field PROTO ((tree));
static tree fold_constant_for_init PROTO ((tree, tree)); static tree fold_constant_for_init PROTO ((tree, tree));
static tree strip_out_static_field_access_decl PROTO ((tree)); static tree strip_out_static_field_access_decl PROTO ((tree));
static jdeplist *reverse_jdep_list PROTO ((struct parser_ctxt *)); static jdeplist *reverse_jdep_list PROTO ((struct parser_ctxt *));
...@@ -1220,13 +1219,7 @@ statement: ...@@ -1220,13 +1219,7 @@ statement:
| if_then_else_statement | if_then_else_statement
| while_statement | while_statement
| for_statement | for_statement
{ { $$ = exit_block (); }
/* If the for loop is unlabeled, we must return the
block it was defined it. It our last chance to
get a hold on it. */
if (!LOOP_HAS_LABEL_P ($$))
$$ = exit_block ();
}
; ;
statement_nsi: statement_nsi:
...@@ -3264,19 +3257,11 @@ static void ...@@ -3264,19 +3257,11 @@ static void
maybe_generate_clinit () maybe_generate_clinit ()
{ {
tree mdecl, c; tree mdecl, c;
int is_interface = CLASS_INTERFACE (ctxp->current_parsed_class);
int has_non_primitive_fields = 0; int has_non_primitive_fields = 0;
if (!ctxp->static_initialized || java_error_count) if (!ctxp->static_initialized || java_error_count)
return; return;
if (is_interface)
for (c = TYPE_FIELDS (TREE_TYPE (ctxp->current_parsed_class));
c; c = TREE_CHAIN (c))
has_non_primitive_fields |= !JPRIMITIVE_TYPE_P (TREE_TYPE (c));
if (!has_non_primitive_fields && is_interface)
return;
mdecl = create_artificial_method (TREE_TYPE (ctxp->current_parsed_class), mdecl = create_artificial_method (TREE_TYPE (ctxp->current_parsed_class),
ACC_STATIC, void_type_node, ACC_STATIC, void_type_node,
clinit_identifier_node, end_params_node); clinit_identifier_node, end_params_node);
...@@ -5728,18 +5713,41 @@ java_complete_expand_methods () ...@@ -5728,18 +5713,41 @@ java_complete_expand_methods ()
decl = tree_last (TYPE_METHODS (class_type)); decl = tree_last (TYPE_METHODS (class_type));
if (IS_CLINIT (decl)) if (IS_CLINIT (decl))
{ {
tree list = nreverse (TYPE_METHODS (class_type)); tree fbody = DECL_FUNCTION_BODY (decl);
list = TREE_CHAIN (list); tree list;
TREE_CHAIN (decl) = NULL_TREE; if (fbody != NULL_TREE)
TYPE_METHODS (class_type) = chainon (decl, nreverse (list)); {
/* First check if we can ignore empty <clinit> */
tree block_body = BLOCK_EXPR_BODY (fbody);
current_this = NULL_TREE;
current_function_decl = decl;
if (block_body != NULL_TREE)
{
/* Prevent the use of `this' inside <clinit> */
ctxp->explicit_constructor_p = 1;
block_body = java_complete_tree (block_body);
ctxp->explicit_constructor_p = 0;
BLOCK_EXPR_BODY (fbody) = block_body;
if (block_body != NULL_TREE
&& TREE_CODE (block_body) == BLOCK
&& BLOCK_EXPR_BODY (block_body) == empty_stmt_node)
decl = NULL_TREE;
}
}
list = nreverse (TREE_CHAIN (nreverse (TYPE_METHODS (class_type))));
if (decl != NULL_TREE)
{
TREE_CHAIN (decl) = list;
TYPE_METHODS (class_type) = decl;
}
else
TYPE_METHODS (class_type) = list;
} }
for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl)) for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
{ {
/* Process only <clinit> method bodies in interfaces. */
if (is_interface && decl != TYPE_METHODS (class_type))
break;
current_function_decl = decl; current_function_decl = decl;
/* Don't generate debug info on line zero when expanding a /* Don't generate debug info on line zero when expanding a
generated constructor. */ generated constructor. */
...@@ -5816,10 +5824,6 @@ java_complete_expand_method (mdecl) ...@@ -5816,10 +5824,6 @@ java_complete_expand_method (mdecl)
if (block_body != NULL_TREE) if (block_body != NULL_TREE)
{ {
/* Prevent the use of `this' inside <clinit> */
if (IS_CLINIT (current_function_decl))
ctxp->explicit_constructor_p = 1;
block_body = java_complete_tree (block_body); block_body = java_complete_tree (block_body);
check_for_initialization (block_body); check_for_initialization (block_body);
ctxp->explicit_constructor_p = 0; ctxp->explicit_constructor_p = 0;
...@@ -7755,6 +7759,13 @@ java_complete_lhs (node) ...@@ -7755,6 +7759,13 @@ java_complete_lhs (node)
tree cur = java_complete_tree (TREE_OPERAND (*ptr, 0)); tree cur = java_complete_tree (TREE_OPERAND (*ptr, 0));
tree *next = &TREE_OPERAND (*ptr, 1); tree *next = &TREE_OPERAND (*ptr, 1);
TREE_OPERAND (*ptr, 0) = cur; TREE_OPERAND (*ptr, 0) = cur;
if (cur == empty_stmt_node)
{
/* Optimization; makes it easier to detect empty bodies.
Most useful for <clinit> with all-constant initializer. */
*ptr = *next;
continue;
}
if (TREE_CODE (cur) == ERROR_MARK) if (TREE_CODE (cur) == ERROR_MARK)
error_seen++; error_seen++;
else if (! CAN_COMPLETE_NORMALLY (cur)) else if (! CAN_COMPLETE_NORMALLY (cur))
...@@ -8022,6 +8033,11 @@ java_complete_lhs (node) ...@@ -8022,6 +8033,11 @@ java_complete_lhs (node)
EXPR_WFL_NODE (node) = body; EXPR_WFL_NODE (node) = body;
TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (body); TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (body);
CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (body); CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (body);
if (body == empty_stmt_node)
{
/* Optimization; makes it easier to detect empty bodies. */
return body;
}
if (body == error_mark_node) if (body == error_mark_node)
{ {
/* Its important for the evaluation of assignment that /* Its important for the evaluation of assignment that
...@@ -8091,8 +8107,22 @@ java_complete_lhs (node) ...@@ -8091,8 +8107,22 @@ java_complete_lhs (node)
case MODIFY_EXPR: case MODIFY_EXPR:
/* Save potential wfls */ /* Save potential wfls */
wfl_op1 = TREE_OPERAND (node, 0); wfl_op1 = TREE_OPERAND (node, 0);
TREE_OPERAND (node, 0) = nn = java_complete_lhs (wfl_op1);
if (MODIFY_EXPR_FROM_INITIALIZATION_P (node)
&& TREE_CODE (nn) == VAR_DECL && TREE_STATIC (nn)
&& DECL_INITIAL (nn) != NULL_TREE)
{
tree value = fold_constant_for_init (nn, nn);
if (value != NULL_TREE)
{
tree type = TREE_TYPE (value);
if (JPRIMITIVE_TYPE_P (type) || type == string_ptr_type_node)
return empty_stmt_node;
}
DECL_INITIAL (nn) = NULL_TREE;
}
wfl_op2 = TREE_OPERAND (node, 1); wfl_op2 = TREE_OPERAND (node, 1);
TREE_OPERAND (node, 0) = java_complete_lhs (wfl_op1);
if (TREE_OPERAND (node, 0) == error_mark_node) if (TREE_OPERAND (node, 0) == error_mark_node)
return error_mark_node; return error_mark_node;
...@@ -8138,17 +8168,6 @@ java_complete_lhs (node) ...@@ -8138,17 +8168,6 @@ java_complete_lhs (node)
TREE_OPERAND (node, 1) = nn; TREE_OPERAND (node, 1) = nn;
node = patch_assignment (node, wfl_op1, wfl_op2); node = patch_assignment (node, wfl_op1, wfl_op2);
CAN_COMPLETE_NORMALLY (node) = 1; CAN_COMPLETE_NORMALLY (node) = 1;
/* Before returning the node, in the context of a static field
assignment in <clinit>, we may want to carray further
optimizations. (VAR_DECL means it's a static field. See
add_field. */
if (IS_CLINIT (current_function_decl)
&& MODIFY_EXPR_FROM_INITIALIZATION_P (node)
&& TREE_CODE (TREE_OPERAND (node, 0)) == VAR_DECL
&& !flag_emit_xref)
node = patch_initialized_static_field (node);
return node; return node;
case MULT_EXPR: case MULT_EXPR:
...@@ -8800,35 +8819,6 @@ patch_assignment (node, wfl_op1, wfl_op2) ...@@ -8800,35 +8819,6 @@ patch_assignment (node, wfl_op1, wfl_op2)
return node; return node;
} }
/* Optimize static (final) field initialized upon declaration.
- If the field is static final and is assigned to a primitive
constant type, then set its DECL_INITIAL to the value.
- More to come. */
static tree
patch_initialized_static_field (node)
tree node;
{
tree field = TREE_OPERAND (node, 0);
tree value = TREE_OPERAND (node, 1);
if (DECL_INITIAL (field) != NULL_TREE)
{
tree type = TREE_TYPE (value);
if (FIELD_FINAL (field) && TREE_CONSTANT (value)
&& (JPRIMITIVE_TYPE_P (type)
|| (flag_emit_class_files
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_TYPE (type) == string_type_node)))
{
DECL_INITIAL (field) = value;
return empty_stmt_node;
}
DECL_INITIAL (field) = NULL_TREE;
}
return node;
}
/* Check that type SOURCE can be cast into type DEST. If the cast /* Check that type SOURCE can be cast into type DEST. If the cast
can't occur at all, return 0 otherwise 1. This function is used to can't occur at all, return 0 otherwise 1. This function is used to
produce accurate error messages on the reasons why an assignment produce accurate error messages on the reasons why an assignment
...@@ -9733,7 +9723,7 @@ patch_string_cst (node) ...@@ -9733,7 +9723,7 @@ patch_string_cst (node)
location = alloc_name_constant (CONSTANT_String, node); location = alloc_name_constant (CONSTANT_String, node);
node = build_ref_from_constant_pool (location); node = build_ref_from_constant_pool (location);
} }
TREE_TYPE (node) = promote_type (string_type_node); TREE_TYPE (node) = string_ptr_type_node;
TREE_CONSTANT (node) = 1; TREE_CONSTANT (node) = 1;
return node; return node;
} }
...@@ -10632,15 +10622,6 @@ finish_labeled_statement (lbe, statement) ...@@ -10632,15 +10622,6 @@ finish_labeled_statement (lbe, statement)
{ {
/* In anyways, tie the loop to its statement */ /* In anyways, tie the loop to its statement */
LABELED_BLOCK_BODY (lbe) = statement; LABELED_BLOCK_BODY (lbe) = statement;
/* Ok, if statement is a for loop, we have to attach the labeled
statement to the block the for loop belongs to and return the
block instead */
if (TREE_CODE (statement) == LOOP_EXPR && IS_FOR_LOOP_P (statement))
{
java_method_add_stmt (current_function_decl, lbe);
lbe = exit_block ();
}
pop_labeled_block (); pop_labeled_block ();
POP_LABELED_BLOCK (); POP_LABELED_BLOCK ();
return lbe; return lbe;
...@@ -10752,14 +10733,33 @@ static tree ...@@ -10752,14 +10733,33 @@ static tree
patch_loop_statement (loop) patch_loop_statement (loop)
tree loop; tree loop;
{ {
if (! LOOP_HAS_LABEL_P (loop)) tree loop_label;
tree block = ctxp->current_labeled_block;
TREE_TYPE (loop) = void_type_node;
if (block != NULL_TREE)
{ {
tree loop_label = build_labeled_block (0, NULL_TREE); tree block_body = LABELED_BLOCK_BODY (block);
LABELED_BLOCK_BODY (loop_label) = loop; if (IS_FOR_LOOP_P (loop))
PUSH_LABELED_BLOCK (loop_label); {
loop = loop_label; if (TREE_CODE (block_body) == BLOCK)
{
block_body = BLOCK_EXPR_BODY (block_body);
if (block_body == loop
|| (TREE_CODE (block_body) == COMPOUND_EXPR
&& TREE_OPERAND (block_body, 1) == loop))
return loop;
}
}
else
{
if (block_body == loop)
return loop;
}
} }
TREE_TYPE (loop) = void_type_node; loop_label = build_labeled_block (0, NULL_TREE);
LABELED_BLOCK_BODY (loop_label) = loop;
PUSH_LABELED_BLOCK (loop_label);
loop = loop_label;
return loop; return loop;
} }
...@@ -11431,7 +11431,7 @@ fold_constant_for_init (node, context) ...@@ -11431,7 +11431,7 @@ fold_constant_for_init (node, context)
if (code == INTEGER_CST || code == REAL_CST || code == STRING_CST) if (code == INTEGER_CST || code == REAL_CST || code == STRING_CST)
return node; return node;
if (TREE_TYPE (node) != NULL_TREE) if (TREE_TYPE (node) != NULL_TREE && code != VAR_DECL)
return NULL_TREE; return NULL_TREE;
switch (code) switch (code)
...@@ -11503,7 +11503,7 @@ fold_constant_for_init (node, context) ...@@ -11503,7 +11503,7 @@ fold_constant_for_init (node, context)
val = DECL_INITIAL (node); val = DECL_INITIAL (node);
/* Guard against infinite recursion. */ /* Guard against infinite recursion. */
DECL_INITIAL (node) = NULL_TREE; DECL_INITIAL (node) = NULL_TREE;
val = fold_constant_for_init (val, DECL_CONTEXT (node)); val = fold_constant_for_init (val, node);
DECL_INITIAL (node) = val; DECL_INITIAL (node) = val;
return val; return val;
...@@ -11519,7 +11519,7 @@ fold_constant_for_init (node, context) ...@@ -11519,7 +11519,7 @@ fold_constant_for_init (node, context)
else if (! QUALIFIED_P (name)) else if (! QUALIFIED_P (name))
{ {
decl = lookup_field_wrapper (DECL_CONTEXT (context), name); decl = lookup_field_wrapper (DECL_CONTEXT (context), name);
if (! FIELD_STATIC (decl)) if (decl == NULL_TREE || ! FIELD_STATIC (decl))
return NULL_TREE; return NULL_TREE;
return fold_constant_for_init (decl, decl); return fold_constant_for_init (decl, decl);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment