X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fjava%2Fdecl.c;h=18b1ec54ecd587a82de4adb99b6e8c5953483b40;hb=65f74cf78c01a259951c5ab69549daf85a4b9aed;hp=bd2514ad567eac19dd153521b55852ce1219ecd5;hpb=af5b25682f2c2477e8900210b0586ad3133026f4;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/java/decl.c b/gcc/java/decl.c index bd2514ad567..18b1ec54ecd 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -1,6 +1,7 @@ /* Process declarations and variables for the GNU compiler for the Java(TM) language. - Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 + Free Software Foundation, Inc. This file is part of GNU CC. @@ -35,8 +36,8 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "toplev.h" #include "function.h" #include "except.h" -#include "defaults.h" #include "java-except.h" +#include "ggc.h" #if defined (DEBUG_JAVA_BINDING_LEVELS) extern void indent PROTO((void)); @@ -46,15 +47,16 @@ static tree push_jvm_slot PARAMS ((int, tree)); static tree lookup_name_current_level PARAMS ((tree)); static tree push_promoted_type PARAMS ((const char *, tree)); static struct binding_level *make_binding_level PARAMS ((void)); +static boolean emit_init_test_initialization PARAMS ((struct hash_entry *, + hash_table_key)); +static tree create_primitive_vtable PARAMS ((const char *)); +static tree check_local_named_variable PARAMS ((tree, tree, int, int *)); +static tree check_local_unnamed_variable PARAMS ((tree, tree, tree)); /* Set to non-zero value in order to emit class initilization code before static field references. */ extern int always_initialize_class_p; -#ifndef INT_TYPE_SIZE -#define INT_TYPE_SIZE BITS_PER_WORD -#endif - /* The DECL_MAP is a mapping from (index, type) to a decl node. If index < max_locals, it is the index of a local variable. if index >= max_locals, then index-max_locals is a stack slot. @@ -68,7 +70,9 @@ tree decl_map; /* A list of local variables VAR_DECLs for this method that we have seen debug information, but we have not reached their starting (byte) PC yet. */ -tree pending_local_decls = NULL_TREE; +static tree pending_local_decls = NULL_TREE; + +tree throw_node [2]; /* Push a local variable or stack slot into the decl_map, and assign it an rtl. */ @@ -123,8 +127,7 @@ push_jvm_slot (index, decl) /* Now link the decl into the decl_map. */ if (DECL_LANG_SPECIFIC (decl) == NULL) { - DECL_LANG_SPECIFIC (decl) - = (struct lang_decl *) permalloc (sizeof (struct lang_decl_var)); + MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); DECL_LOCAL_START_PC (decl) = 0; DECL_LOCAL_END_PC (decl) = DECL_CODE_LENGTH (current_function_decl); DECL_LOCAL_SLOT_NUMBER (decl) = index; @@ -134,6 +137,58 @@ push_jvm_slot (index, decl) return decl; } +/* Find out if 'decl' passed in fits the defined PC location better than + 'best'. Return decl if it does, return best if it doesn't. If decl + is returned, then updated is set to true. */ + +static tree +check_local_named_variable (best, decl, pc, updated) + tree best; + tree decl; + int pc; + int *updated; +{ + if (pc >= DECL_LOCAL_START_PC (decl) + && pc < DECL_LOCAL_END_PC (decl)) + { + if (best == NULL_TREE + || (DECL_LOCAL_START_PC (decl) > DECL_LOCAL_START_PC (best) + && DECL_LOCAL_END_PC (decl) < DECL_LOCAL_END_PC (best))) + { + *updated = 1; + return decl; + } + } + + return best; +} + +/* Find the best declaration based upon type. If 'decl' fits 'type' better + than 'best', return 'decl'. Otherwise return 'best'. */ + +static tree +check_local_unnamed_variable (best, decl, type) + tree best; + tree decl; + tree type; +{ + if (TREE_TYPE (decl) == type + || (TREE_CODE (TREE_TYPE (decl)) == TREE_CODE (type) + && TYPE_PRECISION (TREE_TYPE (decl)) <= 32 + && TYPE_PRECISION (type) <= 32 + && TREE_CODE (type) != POINTER_TYPE) + || (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE + && type == ptr_type_node)) + { + if (best == NULL_TREE + || (TREE_TYPE (decl) == type && TREE_TYPE (best) != type)) + return decl; + } + + return best; +} + + /* Find a VAR_DECL (or PARM_DECL) at local index INDEX that has type TYPE, that is valid at PC (or -1 if any pc). If there is no existing matching decl, allocate one. */ @@ -146,33 +201,41 @@ find_local_variable (index, type, pc) { tree decl = TREE_VEC_ELT (decl_map, index); tree best = NULL_TREE; + int found_scoped_var = 0; + /* Scan through every declaration that has been created in this slot. */ while (decl != NULL_TREE) { - int in_range; - in_range = pc < 0 - || (pc >= DECL_LOCAL_START_PC (decl) - && pc < DECL_LOCAL_END_PC (decl)); - - if ((TREE_TYPE (decl) == type - || (TREE_CODE (TREE_TYPE (decl)) == TREE_CODE (type) - && TYPE_PRECISION (TREE_TYPE (decl)) <= 32 - && TYPE_PRECISION (type) <= 32 - && TREE_CODE (type) != POINTER_TYPE) - || (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE - && type == ptr_type_node)) - && in_range) + /* Variables created in give_name_to_locals() have a name and have + a specified scope, so we can handle them specifically. We want + to use the specific decls created for those so they are assigned + the right variables in the debugging information. */ + if (DECL_NAME (decl) != NULL_TREE) { - if (best == NULL_TREE - || (TREE_TYPE (decl) == type && TREE_TYPE (best) != type) - || DECL_LOCAL_START_PC (decl) > DECL_LOCAL_START_PC (best) - || DECL_LOCAL_END_PC (decl) < DECL_LOCAL_START_PC (decl)) - best = decl; - } + /* This is a variable we have a name for, so it has a scope + supplied in the class file. But it only matters when we + actually have a PC to use. If pc<0, then we are asking + for a stack slot and this decl won't be one of those. */ + if (pc >= 0) + best = check_local_named_variable (best, decl, pc, + &found_scoped_var); + } + /* We scan for type information unless we found a variable in the + proper scope already. */ + else if (!found_scoped_var) + { + /* If we don't have scoping information for a variable, we use + a different method to look it up. */ + best = check_local_unnamed_variable (best, decl, type); + } + decl = DECL_LOCAL_SLOT_CHAIN (decl); } + if (best != NULL_TREE) return best; + + /* If we don't find a match, create one with the type passed in. */ return push_jvm_slot (index, build_decl (VAR_DECL, NULL_TREE, type)); } @@ -284,106 +347,10 @@ static int keep_next_level_flag; if it has subblocks. */ static int keep_next_if_subblocks; + +tree java_global_trees[JTI_MAX]; -tree object_type_node; -tree unqualified_object_id_node; -tree object_ptr_type_node; -tree string_type_node; -tree string_ptr_type_node; -tree throwable_type_node; -tree runtime_exception_type_node; -tree error_exception_type_node; -tree *predef_filenames; -int predef_filenames_size; - -tree boolean_type_node; - -tree return_address_type_node; - -tree byte_type_node; -tree short_type_node; -tree int_type_node; -tree long_type_node; - -tree promoted_byte_type_node; -tree promoted_short_type_node; -tree promoted_char_type_node; -tree promoted_boolean_type_node; - -tree unsigned_byte_type_node; -tree unsigned_short_type_node; -tree unsigned_int_type_node; -tree unsigned_long_type_node; - -/* The type for struct methodtable. */ -tree methodtable_type; -tree methodtable_ptr_type; - -tree utf8const_type; -tree utf8const_ptr_type; -tree class_type_node; -tree class_ptr_type; -tree field_type_node; -tree field_ptr_type_node; -tree field_info_union_node; -tree jexception_type; -tree jexception_ptr_type; -tree lineNumberEntry_type; -tree lineNumbers_type; -tree constants_type_node; -tree dtable_type; -tree dtable_ptr_type; -tree method_type_node; -tree method_ptr_type_node; -tree nativecode_ptr_array_type_node; -tree one_elt_array_domain_type; -tree access_flags_type_node; -tree class_dtable_decl; - -/* Expressions that are constants with value zero, of types - `long', `float' and `double'. */ -tree long_zero_node; -tree float_zero_node; -tree double_zero_node; - -tree empty_stmt_node; - -/* Nodes for boolean constants TRUE and FALSE. */ -tree boolean_true_node; -tree boolean_false_node; - -tree TYPE_identifier_node; -tree init_identifier_node; -tree clinit_identifier_node; -tree finit_identifier_node; -tree void_signature_node; -tree length_identifier_node; -tree this_identifier_node; -tree super_identifier_node; -tree continue_identifier_node; -tree access0_identifier_node; /* 1.1 */ -tree end_params_node; - -/* References to internal libjava functions we use. */ -tree alloc_object_node; -tree soft_instanceof_node; -tree soft_checkcast_node; -tree soft_initclass_node; -tree soft_newarray_node; -tree soft_anewarray_node; -tree soft_multianewarray_node; -tree soft_badarrayindex_node; -tree throw_node [2]; -tree soft_checkarraystore_node; -tree soft_monitorenter_node; -tree soft_monitorexit_node; -tree soft_lookupinterfacemethod_node; -tree soft_fmod_node; -tree soft_exceptioninfo_call_node; -tree soft_idiv_node; -tree soft_irem_node; -tree soft_ldiv_node; -tree soft_lrem_node; +tree predef_filenames[PREDEF_FILENAMES_SIZE]; /* Build (and pushdecl) a "promoted type" for all standard types shorter than int. */ @@ -401,11 +368,9 @@ push_promoted_type (name, actual_type) tree in_min = TYPE_MIN_VALUE (actual_type); tree in_max = TYPE_MAX_VALUE (actual_type); #endif - TYPE_MIN_VALUE (type) = build_int_2 (TREE_INT_CST_LOW (in_min), - TREE_INT_CST_HIGH (in_min)); + TYPE_MIN_VALUE (type) = copy_node (in_min); TREE_TYPE (TYPE_MIN_VALUE (type)) = type; - TYPE_MAX_VALUE (type) = build_int_2 (TREE_INT_CST_LOW (in_max), - TREE_INT_CST_HIGH (in_max)); + TYPE_MAX_VALUE (type) = copy_node (in_max); TREE_TYPE (TYPE_MAX_VALUE (type)) = type; TYPE_PRECISION (type) = TYPE_PRECISION (int_type_node); layout_type (type); @@ -413,11 +378,6 @@ push_promoted_type (name, actual_type) return type; } -/* Nodes for integer constants. */ -tree integer_two_node; -tree integer_four_node; -tree integer_negative_one_node; - /* Return a definition for a builtin function named NAME and whose data type is TYPE. TYPE should be a function type with argument types. FUNCTION_CODE tells later passes how to compile calls to this function. @@ -439,13 +399,28 @@ builtin_function (name, type, function_code, class, library_name) TREE_PUBLIC (decl) = 1; if (library_name) DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name); - make_decl_rtl (decl, NULL_PTR, 1); + make_decl_rtl (decl, NULL_PTR); pushdecl (decl); DECL_BUILT_IN_CLASS (decl) = class; DECL_FUNCTION_CODE (decl) = function_code; return decl; } +/* Return tree that represents a vtable for a primitive array. */ +static tree +create_primitive_vtable (name) + const char *name; +{ + tree r; + char buf[50]; + + sprintf (buf, "_Jv_%sVTable", name); + r = build_decl (VAR_DECL, get_identifier (buf), ptr_type_node); + DECL_EXTERNAL (r) = 1; + make_decl_rtl (r, buf); + return r; +} + void init_decl_processing () { @@ -453,23 +428,21 @@ init_decl_processing () tree field = NULL_TREE; tree t; + init_class_processing (); + current_function_decl = NULL; current_binding_level = NULL_BINDING_LEVEL; free_binding_level = NULL_BINDING_LEVEL; pushlevel (0); /* make the binding_level structure for global names */ global_binding_level = current_binding_level; + /* The code here must be similar to build_common_tree_nodes{,_2} in + tree.c, especially as to the order of initializing common nodes. */ error_mark_node = make_node (ERROR_MARK); TREE_TYPE (error_mark_node) = error_mark_node; - initialize_sizetypes (); /* Create sizetype first - needed for other types. */ initialize_sizetypes (); - set_sizetype (make_unsigned_type (POINTER_SIZE)); - size_zero_node = build_int_2 (0, 0); - TREE_TYPE (size_zero_node) = sizetype; - size_one_node = build_int_2 (1, 0); - TREE_TYPE (size_one_node) = sizetype; byte_type_node = make_signed_type (8); pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"), byte_type_node)); @@ -493,13 +466,21 @@ init_decl_processing () pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned long"), unsigned_long_type_node)); - integer_type_node = type_for_size (INT_TYPE_SIZE, 0); + set_sizetype (make_unsigned_type (POINTER_SIZE)); + /* Define these next since types below may used them. */ + integer_type_node = type_for_size (INT_TYPE_SIZE, 0); integer_zero_node = build_int_2 (0, 0); integer_one_node = build_int_2 (1, 0); integer_two_node = build_int_2 (2, 0); integer_four_node = build_int_2 (4, 0); - integer_negative_one_node = build_int_2 (-1, 0); + integer_minus_one_node = build_int_2 (-1, -1); + + size_zero_node = size_int (0); + size_one_node = size_int (1); + bitsize_zero_node = bitsize_int (0); + bitsize_one_node = bitsize_int (1); + bitsize_unit_node = bitsize_int (BITS_PER_UNIT); long_zero_node = build_int_2 (0, 0); TREE_TYPE (long_zero_node) = long_type_node; @@ -564,7 +545,17 @@ init_decl_processing () float_zero_node = build_real (float_type_node, dconst0); double_zero_node = build_real (double_type_node, dconst0); - /* As your adding items here, please update the code right after + /* These are the vtables for arrays of primitives. */ + boolean_array_vtable = create_primitive_vtable ("boolean"); + byte_array_vtable = create_primitive_vtable ("byte"); + char_array_vtable = create_primitive_vtable ("char"); + short_array_vtable = create_primitive_vtable ("short"); + int_array_vtable = create_primitive_vtable ("int"); + long_array_vtable = create_primitive_vtable ("long"); + float_array_vtable = create_primitive_vtable ("float"); + double_array_vtable = create_primitive_vtable ("double"); + + /* As you're adding items here, please update the code right after this section, so that the filename containing the source code of the pre-defined class gets registered correctly. */ unqualified_object_id_node = get_identifier ("Object"); @@ -578,17 +569,18 @@ init_decl_processing () lookup_class (get_identifier ("java.lang.RuntimeException")); error_exception_type_node = lookup_class (get_identifier ("java.lang.Error")); + rawdata_ptr_type_node + = promote_type (lookup_class (get_identifier ("gnu.gcj.RawData"))); - /* This section has to be updated as items are added to the previous - section. */ - predef_filenames_size = 6; - predef_filenames = (tree *)xmalloc (predef_filenames_size * sizeof (tree)); + /* If you add to this section, don't forget to increase + PREDEF_FILENAMES_SIZE. */ predef_filenames [0] = get_identifier ("java/lang/Class.java"); predef_filenames [1] = get_identifier ("java/lang/Error.java"); predef_filenames [2] = get_identifier ("java/lang/Object.java"); predef_filenames [3] = get_identifier ("java/lang/RuntimeException.java"); predef_filenames [4] = get_identifier ("java/lang/String.java"); predef_filenames [5] = get_identifier ("java/lang/Throwable.java"); + predef_filenames [6] = get_identifier ("gnu/gcj/RawData.java"); methodtable_type = make_node (RECORD_TYPE); layout_type (methodtable_type); @@ -598,13 +590,19 @@ init_decl_processing () TYPE_identifier_node = get_identifier ("TYPE"); init_identifier_node = get_identifier (""); clinit_identifier_node = get_identifier (""); - finit_identifier_node = get_identifier ("$finit$"); + /* Legacy `$finit$' special method identifier. This needs to be + recognized as equivalent to `finit$' but isn't generated anymore. */ + finit_leg_identifier_node = get_identifier ("$finit$"); + /* The new `finit$' special method identifier. This one is now + generated in place of `$finit$'. */ + finit_identifier_node = get_identifier ("finit$"); void_signature_node = get_identifier ("()V"); length_identifier_node = get_identifier ("length"); this_identifier_node = get_identifier ("this"); super_identifier_node = get_identifier ("super"); continue_identifier_node = get_identifier ("continue"); access0_identifier_node = get_identifier ("access$0"); + classdollar_identifier_node = get_identifier ("class$"); /* for lack of a better place to put this stub call */ init_expr_processing(); @@ -675,6 +673,7 @@ init_decl_processing () PUSH_FIELD (class_type_node, field, "depth", short_type_node); PUSH_FIELD (class_type_node, field, "ancestors", ptr_type_node); PUSH_FIELD (class_type_node, field, "idt", ptr_type_node); + PUSH_FIELD (class_type_node, field, "arrayclass", ptr_type_node); for (t = TYPE_FIELDS (class_type_node); t != NULL_TREE; t = TREE_CHAIN (t)) FIELD_PRIVATE (t) = 1; push_super_field (class_type_node, object_type_node); @@ -748,12 +747,13 @@ init_decl_processing () build_function_type (ptr_type_node, t), 0, NOT_BUILT_IN, NULL_PTR); DECL_IS_MALLOC (alloc_object_node) = 1; + + t = tree_cons (NULL_TREE, ptr_type_node, endlink); soft_initclass_node = builtin_function ("_Jv_InitClass", build_function_type (void_type_node, t), 0, NOT_BUILT_IN, NULL_PTR); - t = tree_cons (NULL_TREE, ptr_type_node, endlink); throw_node[0] = builtin_function ("_Jv_Throw", build_function_type (ptr_type_node, t), 0, NOT_BUILT_IN, NULL_PTR); @@ -777,7 +777,7 @@ init_decl_processing () t = tree_cons (NULL_TREE, int_type_node, tree_cons (NULL_TREE, int_type_node, endlink)); soft_newarray_node - = builtin_function ("_Jv_NewArray", + = builtin_function ("_Jv_NewPrimArray", build_function_type(ptr_type_node, t), 0, NOT_BUILT_IN, NULL_PTR); DECL_IS_MALLOC (soft_newarray_node) = 1; @@ -809,6 +809,15 @@ init_decl_processing () TREE_THIS_VOLATILE (soft_badarrayindex_node) = 1; TREE_SIDE_EFFECTS (soft_badarrayindex_node) = 1; + soft_nullpointer_node + = builtin_function ("_Jv_ThrowNullPointerException", + build_function_type (void_type_node, endlink), + 0, NOT_BUILT_IN, NULL_PTR); + /* Mark soft_nullpointer_node as a `noreturn' function with side + effects. */ + TREE_THIS_VOLATILE (soft_nullpointer_node) = 1; + TREE_SIDE_EFFECTS (soft_nullpointer_node) = 1; + t = tree_cons (NULL_TREE, class_ptr_type, tree_cons (NULL_TREE, object_ptr_type_node, endlink)); soft_checkcast_node @@ -834,6 +843,24 @@ init_decl_processing () = builtin_function ("_Jv_LookupInterfaceMethodIdx", build_function_type (ptr_type_node, t), 0, NOT_BUILT_IN, NULL_PTR); + + t = tree_cons (NULL_TREE, object_ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, endlink))); + soft_lookupjnimethod_node + = builtin_function ("_Jv_LookupJNIMethod", + build_function_type (ptr_type_node, t), + 0, NOT_BUILT_IN, NULL_PTR); + t = tree_cons (NULL_TREE, ptr_type_node, endlink); + soft_getjnienvnewframe_node + = builtin_function ("_Jv_GetJNIEnvNewFrame", + build_function_type (ptr_type_node, t), + 0, NOT_BUILT_IN, NULL_PTR); + soft_jnipopsystemframe_node + = builtin_function ("_Jv_JNI_PopSystemFrame", + build_function_type (ptr_type_node, t), + 0, NOT_BUILT_IN, NULL_PTR); + t = tree_cons (NULL_TREE, double_type_node, tree_cons (NULL_TREE, double_type_node, endlink)); soft_fmod_node @@ -879,7 +906,17 @@ init_decl_processing () build_function_type (long_type_node, t), 0, NOT_BUILT_IN, NULL_PTR); - init_class_processing (); + init_jcf_parse (); + + /* Register nodes with the garbage collector. */ + ggc_add_tree_root (java_global_trees, + sizeof (java_global_trees) / sizeof (tree)); + ggc_add_tree_root (throw_node, + sizeof (throw_node) / sizeof (tree)); + ggc_add_tree_root (predef_filenames, + sizeof (predef_filenames) / sizeof (tree)); + ggc_add_tree_root (&decl_map, 1); + ggc_add_tree_root (&pending_local_decls, 1); } @@ -1347,7 +1384,7 @@ poplevel (keep, reverse, functionbody) define_label (input_filename, lineno, DECL_NAME (label)); } - else if (warn_unused && !TREE_USED (label)) + else if (warn_unused[UNUSED_LABEL] && !TREE_USED (label)) warning_with_decl (label, "label `%s' defined but not used"); IDENTIFIER_LABEL_VALUE (DECL_NAME (label)) = 0; @@ -1508,6 +1545,10 @@ set_block (block) register tree block; { current_binding_level->this_block = block; + current_binding_level->names = chainon (current_binding_level->names, + BLOCK_VARS (block)); + current_binding_level->blocks = chainon (current_binding_level->blocks, + BLOCK_SUBBLOCKS (block)); } /* integrate_decl_tree calls this function. */ @@ -1519,8 +1560,8 @@ copy_lang_decl (node) int lang_decl_size = TREE_CODE (node) == VAR_DECL ? sizeof (struct lang_decl_var) : sizeof (struct lang_decl); - struct lang_decl *x = (struct lang_decl *) oballoc (lang_decl_size); - bcopy ((PTR) DECL_LANG_SPECIFIC (node), (PTR) x, lang_decl_size); + struct lang_decl *x = (struct lang_decl *) ggc_alloc (lang_decl_size); + memcpy (x, DECL_LANG_SPECIFIC (node), lang_decl_size); DECL_LANG_SPECIFIC (node) = x; } @@ -1540,6 +1581,7 @@ give_name_to_locals (jcf) JCF *jcf; { int i, n = DECL_LOCALVARIABLES_OFFSET (current_function_decl); + int code_offset = DECL_CODE_OFFSET (current_function_decl); tree parm; pending_local_decls = NULL_TREE; if (n == 0) @@ -1576,8 +1618,14 @@ give_name_to_locals (jcf) "bad PC range for debug info for local `%s'"); end_pc = DECL_CODE_LENGTH (current_function_decl); } - DECL_LANG_SPECIFIC (decl) - = (struct lang_decl *) permalloc (sizeof (struct lang_decl_var)); + + /* Adjust start_pc if necessary so that the local's first + store operation will use the relevant DECL as a + destination. Fore more information, read the leading + comments for expr.c:maybe_adjust_start_pc. */ + start_pc = maybe_adjust_start_pc (jcf, code_offset, start_pc, slot); + + MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); DECL_LOCAL_SLOT_NUMBER (decl) = slot; DECL_LOCAL_START_PC (decl) = start_pc; #if 0 @@ -1641,17 +1689,29 @@ build_result_decl (fndecl) /* Called for every element in DECL_FUNCTION_INIT_TEST_TABLE in order to emit initialization code for each test flag. */ - + static boolean emit_init_test_initialization (entry, key) struct hash_entry *entry; hash_table_key key ATTRIBUTE_UNUSED; { struct init_test_hash_entry *ite = (struct init_test_hash_entry *) entry; + tree klass = build_class_ref ((tree) entry->key); expand_decl (ite->init_test_decl); - expand_expr_stmt (build (MODIFY_EXPR, boolean_type_node, - ite->init_test_decl, boolean_false_node)); + /* We initialize the class init check variable by looking at the + `state' field of the class to see if it is already initialized. + This makes things a bit faster if the class is already + initialized, which should be the common case. */ + expand_expr_stmt + (build (MODIFY_EXPR, boolean_type_node, + ite->init_test_decl, + build (GE_EXPR, boolean_type_node, + build (COMPONENT_REF, byte_type_node, + build1 (INDIRECT_REF, class_type_node, klass), + lookup_field (&class_type_node, + get_identifier ("state"))), + build_int_2 (JV_STATE_DONE, 0)))); return true; } @@ -1674,10 +1734,6 @@ complete_start_java_method (fndecl) emit_init_test_initialization, 0); } - /* Allocate further tree nodes temporarily during compilation - of this function only. */ - temporary_allocation (); - #if 0 /* If this fcn was already referenced via a block-scope `extern' decl (or an implicit decl), propagate certain information about the usage. */ @@ -1688,6 +1744,7 @@ complete_start_java_method (fndecl) if (METHOD_STATIC (fndecl) && ! METHOD_PRIVATE (fndecl) && ! flag_emit_class_files + && ! DECL_CLINIT_P (fndecl) && ! CLASS_INTERFACE (TYPE_NAME (current_class))) { tree clas = DECL_CONTEXT (fndecl); @@ -1711,7 +1768,7 @@ complete_start_java_method (fndecl) if (METHOD_SYNCHRONIZED (fndecl) && ! flag_emit_class_files) { - /* Warp function body with a monitorenter plus monitorexit cleanup. */ + /* Wrap function body with a monitorenter plus monitorexit cleanup. */ tree enter, exit, lock; if (METHOD_STATIC (fndecl)) lock = build_class_ref (DECL_CONTEXT (fndecl)); @@ -1752,7 +1809,7 @@ start_java_method (fndecl) i = DECL_MAX_LOCALS(fndecl) + DECL_MAX_STACK(fndecl); decl_map = make_tree_vec (i); - type_map = (tree *) oballoc (i * sizeof (tree)); + type_map = (tree *) xrealloc (type_map, i * sizeof (tree)); #if defined(DEBUG_JAVA_BINDING_LEVELS) fprintf (stderr, "%s:\n", (*decl_printable_name) (fndecl, 2)); @@ -1766,8 +1823,8 @@ start_java_method (fndecl) { tree parm_name = NULL_TREE, parm_decl; tree parm_type = TREE_VALUE (tem); - if (i >= DECL_MAX_LOCALS(fndecl)) - fatal ("function has more parameters than local slots"); + if (i >= DECL_MAX_LOCALS (fndecl)) + abort (); parm_decl = build_decl (PARM_DECL, parm_name, parm_type); DECL_CONTEXT (parm_decl) = fndecl; @@ -1831,6 +1888,64 @@ end_java_method () rest_of_compilation (fndecl); current_function_decl = NULL_TREE; - permanent_allocation (1); asynchronous_exceptions = flag_asynchronous_exceptions; } + +/* Mark language-specific parts of T for garbage-collection. */ + +void +lang_mark_tree (t) + tree t; +{ + if (TREE_CODE (t) == IDENTIFIER_NODE) + { + struct lang_identifier *li = (struct lang_identifier *) t; + ggc_mark_tree (li->global_value); + ggc_mark_tree (li->local_value); + ggc_mark_tree (li->utf8_ref); + } + else if (TREE_CODE (t) == VAR_DECL + || TREE_CODE (t) == PARM_DECL + || TREE_CODE (t) == FIELD_DECL) + { + struct lang_decl_var *ldv = + ((struct lang_decl_var *) DECL_LANG_SPECIFIC (t)); + if (ldv) + { + ggc_mark (ldv); + ggc_mark_tree (ldv->slot_chain); + ggc_mark_tree (ldv->am); + ggc_mark_tree (ldv->wfl); + } + } + else if (TREE_CODE (t) == FUNCTION_DECL) + { + struct lang_decl *ld = DECL_LANG_SPECIFIC (t); + + if (ld) + { + ggc_mark (ld); + ggc_mark_tree (ld->wfl); + ggc_mark_tree (ld->throws_list); + ggc_mark_tree (ld->function_decl_body); + ggc_mark_tree (ld->called_constructor); + ggc_mark_tree (ld->inner_access); + } + } + else if (TYPE_P (t)) + { + struct lang_type *lt = TYPE_LANG_SPECIFIC (t); + + if (lt) + { + ggc_mark (lt); + ggc_mark_tree (lt->signature); + ggc_mark_tree (lt->cpool_data_ref); + ggc_mark_tree (lt->finit_stmt_list); + ggc_mark_tree (lt->clinit_stmt_list); + ggc_mark_tree (lt->ii_block); + ggc_mark_tree (lt->dot_class); + ggc_mark_tree (lt->package_list); + } + } +}