aboutsummaryrefslogtreecommitdiff
path: root/gcc/java/jcf-write.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/java/jcf-write.c')
-rw-r--r--gcc/java/jcf-write.c72
1 files changed, 54 insertions, 18 deletions
diff --git a/gcc/java/jcf-write.c b/gcc/java/jcf-write.c
index 47cfd11be8a..1dec6b9e73b 100644
--- a/gcc/java/jcf-write.c
+++ b/gcc/java/jcf-write.c
@@ -276,6 +276,9 @@ struct jcf_partial
/* Information about the current switch statement. */
struct jcf_switch_state *sw_state;
+
+ /* The count of jsr instructions that have been emmitted. */
+ long num_jsrs;
};
static void generate_bytecode_insns PARAMS ((tree, int, struct jcf_partial *));
@@ -292,7 +295,7 @@ static void define_jcf_label PARAMS ((struct jcf_block *,
static struct jcf_block * get_jcf_label_here PARAMS ((struct jcf_partial *));
static void put_linenumber PARAMS ((int, struct jcf_partial *));
static void localvar_alloc PARAMS ((tree, struct jcf_partial *));
-static void localvar_free PARAMS ((tree, struct jcf_partial *));
+static void maybe_free_localvar PARAMS ((tree, struct jcf_partial *, int));
static int get_access_flags PARAMS ((tree));
static void write_chunks PARAMS ((FILE *, struct chunk *));
static int adjust_typed_op PARAMS ((tree, int));
@@ -626,9 +629,10 @@ localvar_alloc (decl, state)
}
static void
-localvar_free (decl, state)
+maybe_free_localvar (decl, state, really)
tree decl;
struct jcf_partial *state;
+ int really;
{
struct jcf_block *end_label = get_jcf_label_here (state);
int index = DECL_LOCAL_INDEX (decl);
@@ -640,6 +644,8 @@ localvar_free (decl, state)
if (info->decl != decl)
abort ();
+ if (! really)
+ return;
ptr[0] = NULL;
if (wide)
{
@@ -1144,6 +1150,7 @@ emit_jsr (target, state)
OP1 (OPCODE_jsr);
/* Value is 1 byte from reloc back to start of instruction. */
emit_reloc (RELOCATION_VALUE_1, OPCODE_jsr_w, target, state);
+ state->num_jsrs++;
}
/* Generate code to evaluate EXP. If the result is true,
@@ -1431,7 +1438,7 @@ generate_bytecode_return (exp, state)
emit_store (state->return_value_decl, state);
call_cleanups (NULL, state);
emit_load (state->return_value_decl, state);
- /* If we call localvar_free (state->return_value_decl, state),
+ /* If we call maybe_free_localvar (state->return_value_decl, state, 1),
then we risk the save decl erroneously re-used in the
finalizer. Instead, we keep the state->return_value_decl
allocated through the rest of the method. This is not
@@ -1471,6 +1478,7 @@ generate_bytecode_insns (exp, target, state)
{
tree local;
tree body = BLOCK_EXPR_BODY (exp);
+ long jsrs = state->num_jsrs;
for (local = BLOCK_EXPR_DECLS (exp); local; )
{
tree next = TREE_CHAIN (local);
@@ -1484,10 +1492,11 @@ generate_bytecode_insns (exp, target, state)
body = TREE_OPERAND (body, 1);
}
generate_bytecode_insns (body, target, state);
+
for (local = BLOCK_EXPR_DECLS (exp); local; )
{
tree next = TREE_CHAIN (local);
- localvar_free (local, state);
+ maybe_free_localvar (local, state, state->num_jsrs <= jsrs);
local = next;
}
}
@@ -1744,6 +1753,7 @@ generate_bytecode_insns (exp, target, state)
else
{
HOST_WIDE_INT i;
+ unsigned HOST_WIDE_INT delta;
/* Copy the chain of relocs into a sorted array. */
struct jcf_relocation **relocs = (struct jcf_relocation **)
xmalloc (sw_state.num_cases * sizeof (struct jcf_relocation *));
@@ -1776,8 +1786,11 @@ generate_bytecode_insns (exp, target, state)
handled by the parser. */
}
- if (2 * sw_state.num_cases
- >= sw_state.max_case - sw_state.min_case)
+ /* We could have DELTA < 0 if sw_state.min_case is
+ something like Integer.MIN_VALUE. That is why delta is
+ unsigned. */
+ delta = sw_state.max_case - sw_state.min_case;
+ if (2 * (unsigned) sw_state.num_cases >= delta)
{ /* Use tableswitch. */
int index = 0;
RESERVE (13 + 4 * (sw_state.max_case - sw_state.min_case + 1));
@@ -2437,8 +2450,8 @@ generate_bytecode_insns (exp, target, state)
if (CAN_COMPLETE_NORMALLY (finally))
{
maybe_wide (OPCODE_ret, DECL_LOCAL_INDEX (return_link), state);
- localvar_free (exception_decl, state);
- localvar_free (return_link, state);
+ maybe_free_localvar (exception_decl, state, 1);
+ maybe_free_localvar (return_link, state, 1);
define_jcf_label (finished_label, state);
}
}
@@ -3043,6 +3056,7 @@ generate_classfile (clas, state)
get_jcf_label_here (state); /* Force a first block. */
for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
localvar_alloc (t, state);
+ state->num_jsrs = 0;
generate_bytecode_insns (body, IGNORE_TARGET, state);
if (CAN_COMPLETE_NORMALLY (body))
{
@@ -3052,9 +3066,9 @@ generate_classfile (clas, state)
OP1 (OPCODE_return);
}
for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
- localvar_free (t, state);
+ maybe_free_localvar (t, state, 1);
if (state->return_value_decl != NULL_TREE)
- localvar_free (state->return_value_decl, state);
+ maybe_free_localvar (state->return_value_decl, state, 1);
finish_jcf_block (state);
perform_relocations (state);
@@ -3333,6 +3347,7 @@ make_class_file_name (clas)
const char *dname, *cname, *slash;
char *r;
struct stat sb;
+ char sep;
cname = IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas)),
"", '.', DIR_SEPARATOR,
@@ -3344,24 +3359,45 @@ make_class_file_name (clas)
char *t;
dname = DECL_SOURCE_FILE (TYPE_NAME (clas));
slash = strrchr (dname, DIR_SEPARATOR);
+#ifdef DIR_SEPARATOR_2
if (! slash)
- {
- dname = ".";
- slash = dname + 1;
- }
+ slash = strrchr (dname, DIR_SEPARATOR_2);
+#endif
+ if (! slash)
+ {
+ dname = ".";
+ slash = dname + 1;
+ sep = DIR_SEPARATOR;
+ }
+ else
+ sep = *slash;
+
t = strrchr (cname, DIR_SEPARATOR);
if (t)
cname = t + 1;
}
else
{
+ char *s;
+
dname = jcf_write_base_directory;
+
+ s = strrchr (dname, DIR_SEPARATOR);
+#ifdef DIR_SEPARATOR_2
+ if (! s)
+ s = strrchr (dname, DIR_SEPARATOR_2);
+#endif
+ if (s)
+ sep = *s;
+ else
+ sep = DIR_SEPARATOR;
+
slash = dname + strlen (dname);
}
r = xmalloc (slash - dname + strlen (cname) + 2);
strncpy (r, dname, slash - dname);
- r[slash - dname] = DIR_SEPARATOR;
+ r[slash - dname] = sep;
strcpy (&r[slash - dname + 1], cname);
/* We try to make new directories when we need them. We only do
@@ -3373,7 +3409,7 @@ make_class_file_name (clas)
dname = r + (slash - dname) + 1;
while (1)
{
- char *s = strchr (dname, DIR_SEPARATOR);
+ char *s = strchr (dname, sep);
if (s == NULL)
break;
*s = '\0';
@@ -3382,9 +3418,9 @@ make_class_file_name (clas)
&& mkdir (r, 0755) == -1)
fatal_io_error ("can't create directory %s", r);
- *s = DIR_SEPARATOR;
+ *s = sep;
/* Skip consecutive separators. */
- for (dname = s + 1; *dname && *dname == DIR_SEPARATOR; ++dname)
+ for (dname = s + 1; *dname && *dname == sep; ++dname)
;
}