diff options
Diffstat (limited to 'gcc/java/jcf-write.c')
-rw-r--r-- | gcc/java/jcf-write.c | 72 |
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) ; } |