X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fjava%2Fclass.c;h=ae715f14efcac4fdf3ff67cad944aa9f3d68a299;hb=9007522bf97494be0eb119dc7a5daa5207755acf;hp=21232e7f2d2e41234534814232b3245a77f5067f;hpb=e772a198f084ad036a97a4dc09e2fe8def270121;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/java/class.c b/gcc/java/class.c index 21232e7f2d2..ae715f14efc 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -35,6 +35,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "toplev.h" #include "output.h" #include "parse.h" +#include "ggc.h" static tree mangle_class_field PARAMS ((tree class)); static tree make_method_value PARAMS ((tree)); @@ -51,11 +52,14 @@ static int assume_compiled PARAMS ((const char *)); static struct hash_entry *init_test_hash_newfunc PARAMS ((struct hash_entry *, struct hash_table *, hash_table_key)); +static int utf8_cmp PARAMS ((const unsigned char *, int, const char *)); +static int cxx_keyword_p PARAMS ((const char *, int)); +static tree mangle_field PARAMS ((tree, tree)); static rtx registerClass_libfunc; extern struct obstack permanent_obstack; -extern struct obstack temporary_obstack; +struct obstack temporary_obstack; /* The compiler generates different code depending on whether or not it can assume certain classes have been compiled down to native @@ -268,7 +272,6 @@ tree make_class () { tree type; - push_obstacks (&permanent_obstack, &permanent_obstack); type = make_node (RECORD_TYPE); #ifdef JAVA_USE_HANDLES tree field1 = build_decl (FIELD_DECL, get_identifier ("obj"), @@ -286,7 +289,6 @@ make_class () TYPE_BINFO (type) = make_tree_vec (6); #endif MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type); - pop_obstacks (); return type; } @@ -323,7 +325,6 @@ push_class (class_type, class_name) const char *save_input_filename = input_filename; int save_lineno = lineno; tree source_name = identifier_subst (class_name, "", '.', '/', ".java"); - push_obstacks (&permanent_obstack, &permanent_obstack); CLASS_P (class_type) = 1; input_filename = IDENTIFIER_POINTER (source_name); lineno = 0; @@ -349,7 +350,6 @@ push_class (class_type, class_name) } #endif - pop_obstacks (); return decl; } @@ -380,7 +380,6 @@ set_super_info (access_flags, this_class, super_class, interfaces_count) if (super_class) total_supers++; - push_obstacks (&permanent_obstack, &permanent_obstack); TYPE_BINFO_BASETYPES (this_class) = make_tree_vec (total_supers); if (super_class) { @@ -392,7 +391,6 @@ set_super_info (access_flags, this_class, super_class, interfaces_count) = super_binfo; CLASS_HAS_SUPER (this_class) = 1; } - pop_obstacks (); if (access_flags & ACC_PUBLIC) CLASS_PUBLIC (class_decl) = 1; if (access_flags & ACC_FINAL) CLASS_FINAL (class_decl) = 1; @@ -400,6 +398,8 @@ set_super_info (access_flags, this_class, super_class, interfaces_count) if (access_flags & ACC_INTERFACE) CLASS_INTERFACE (class_decl) = 1; if (access_flags & ACC_ABSTRACT) CLASS_ABSTRACT (class_decl) = 1; if (access_flags & ACC_STATIC) CLASS_STATIC (class_decl) = 1; + if (access_flags & ACC_PRIVATE) CLASS_PRIVATE (class_decl) = 1; + if (access_flags & ACC_PROTECTED) CLASS_PROTECTED (class_decl) = 1; } /* Return length of inheritance chain of CLAS, where java.lang.Object is 0, @@ -486,6 +486,30 @@ enclosing_context_p (type1, type2) return 0; } +/* Return 1 iff there exists a common enclosing context between TYPE1 + and TYPE2. */ + +int common_enclosing_context_p (type1, type2) + tree type1, type2; +{ + if (!PURE_INNER_CLASS_TYPE_P (type1) || !PURE_INNER_CLASS_TYPE_P (type2)) + return 0; + + for (type1 = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type1))); type1; + type1 = (PURE_INNER_CLASS_TYPE_P (type1) ? + TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type1))) : NULL_TREE)) + { + tree current; + for (current = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type2))); current; + current = (PURE_INNER_CLASS_TYPE_P (current) ? + TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current))) : + NULL_TREE)) + if (type1 == current) + return 1; + } + return 0; +} + static void add_interface_do (basetype_vec, interface_class, i) tree basetype_vec, interface_class; @@ -619,7 +643,6 @@ add_method_1 (handle_class, access_flags, name, function_type) tree function_type; { tree method_type, fndecl; - push_obstacks (&permanent_obstack, &permanent_obstack); method_type = build_java_method_type (function_type, handle_class, access_flags); @@ -628,8 +651,7 @@ add_method_1 (handle_class, access_flags, name, function_type) DECL_CONTEXT (fndecl) = handle_class; DECL_LANG_SPECIFIC (fndecl) - = (struct lang_decl *) permalloc (sizeof (struct lang_decl)); - bzero ((PTR) DECL_LANG_SPECIFIC (fndecl), sizeof (struct lang_decl)); + = (struct lang_decl *) ggc_alloc_cleared (sizeof (struct lang_decl)); /* Initialize the static initializer test table. */ hash_table_init (&DECL_FUNCTION_INIT_TEST_TABLE (fndecl), @@ -638,7 +660,6 @@ add_method_1 (handle_class, access_flags, name, function_type) TREE_CHAIN (fndecl) = TYPE_METHODS (handle_class); TYPE_METHODS (handle_class) = fndecl; - pop_obstacks (); if (access_flags & ACC_PUBLIC) METHOD_PUBLIC (fndecl) = 1; if (access_flags & ACC_PROTECTED) METHOD_PROTECTED (fndecl) = 1; @@ -673,13 +694,11 @@ add_method (this_class, access_flags, name, method_sig) tree handle_class = CLASS_TO_HANDLE_TYPE (this_class); tree function_type, fndecl; const unsigned char *sig = (const unsigned char*)IDENTIFIER_POINTER (method_sig); - push_obstacks (&permanent_obstack, &permanent_obstack); if (sig[0] != '(') fatal ("bad method signature"); function_type = get_type_from_signature (method_sig); fndecl = add_method_1 (handle_class, access_flags, name, function_type); set_java_signature (TREE_TYPE (fndecl), method_sig); - pop_obstacks (); return fndecl; } @@ -692,10 +711,7 @@ add_field (class, name, field_type, flags) { int is_static = (flags & ACC_STATIC) != 0; tree field; - /* Push the obstack of field_type ? FIXME */ - push_obstacks (&permanent_obstack, &permanent_obstack); field = build_decl (is_static ? VAR_DECL : FIELD_DECL, name, field_type); - pop_obstacks (); TREE_CHAIN (field) = TYPE_FIELDS (class); TYPE_FIELDS (class) = field; DECL_CONTEXT (field) = class; @@ -791,7 +807,6 @@ build_utf8_ref (name) if (ref != NULL_TREE) return ref; - push_obstacks (&permanent_obstack, &permanent_obstack); ctype = make_node (RECORD_TYPE); str_type = build_prim_array_type (unsigned_byte_type_node, name_len + 1); /* Allow for final '\0'. */ @@ -843,7 +858,6 @@ build_utf8_ref (name) make_decl_rtl (decl, (char*) 0, 1); ref = build1 (ADDR_EXPR, utf8const_ptr_type, decl); IDENTIFIER_UTF8_REF (name) = ref; - pop_obstacks (); return ref; } @@ -869,7 +883,6 @@ build_class_ref (type) decl = IDENTIFIER_GLOBAL_VALUE (decl_name); if (decl == NULL_TREE) { - push_obstacks (&permanent_obstack, &permanent_obstack); decl = build_decl (VAR_DECL, decl_name, class_type_node); DECL_SIZE (decl) = TYPE_SIZE (class_type_node); DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (class_type_node); @@ -882,7 +895,6 @@ build_class_ref (type) pushdecl_top_level (decl); if (is_compiled == 1) DECL_EXTERNAL (decl) = 1; - pop_obstacks (); } } else @@ -928,7 +940,6 @@ build_class_ref (type) decl = IDENTIFIER_GLOBAL_VALUE (decl_name); if (decl == NULL_TREE) { - push_obstacks (&permanent_obstack, &permanent_obstack); decl = build_decl (VAR_DECL, decl_name, class_type_node); TREE_STATIC (decl) = 1; TREE_PUBLIC (decl) = 1; @@ -936,7 +947,6 @@ build_class_ref (type) pushdecl_top_level (decl); if (is_compiled == 1) DECL_EXTERNAL (decl) = 1; - pop_obstacks (); } } @@ -947,11 +957,9 @@ build_class_ref (type) { int index; tree cl; - push_obstacks (&permanent_obstack, &permanent_obstack); index = alloc_class_constant (type); cl = build_ref_from_constant_pool (index); TREE_TYPE (cl) = promote_type (class_ptr_type); - pop_obstacks (); return cl; } } @@ -966,9 +974,7 @@ build_static_field_ref (fdecl) { if (DECL_RTL (fdecl) == 0) { - push_obstacks (&permanent_obstack, &permanent_obstack); make_decl_rtl (fdecl, NULL, 1); - pop_obstacks (); if (is_compiled == 1) DECL_EXTERNAL (fdecl) = 1; } @@ -985,9 +991,15 @@ build_static_field_ref (fdecl) int field_index = 0; ref = build1 (INDIRECT_REF, class_type_node, ref); if (fields_ident == NULL_TREE) - fields_ident = get_identifier ("fields"); + { + fields_ident = get_identifier ("fields"); + ggc_add_tree_root (&fields_ident, 1); + } if (info_ident == NULL_TREE) - info_ident = get_identifier ("info"); + { + info_ident = get_identifier ("info"); + ggc_add_tree_root (&info_ident, 1); + } ref = build (COMPONENT_REF, field_ptr_type_node, ref, lookup_field (&class_type_node, fields_ident)); @@ -1050,6 +1062,10 @@ get_access_flags_from_decl (decl) access_flags |= ACC_ABSTRACT; if (CLASS_STATIC (decl)) access_flags |= ACC_STATIC; + if (CLASS_PRIVATE (decl)) + access_flags |= ACC_PRIVATE; + if (CLASS_PROTECTED (decl)) + access_flags |= ACC_PROTECTED; return access_flags; } if (TREE_CODE (decl) == FUNCTION_DECL) @@ -1188,6 +1204,7 @@ static tree get_dispatch_table (type, this_class_addr) tree type, this_class_addr; { + int abstract_p = CLASS_ABSTRACT (TYPE_NAME (type)); tree vtable = get_dispatch_vector (type); int i; tree list = NULL_TREE; @@ -1196,17 +1213,26 @@ get_dispatch_table (type, this_class_addr) { tree method = TREE_VEC_ELT (vtable, i); if (METHOD_ABSTRACT (method)) - warning_with_decl (method, "abstract method in non-abstract class"); - if (DECL_RTL (method) == 0) - make_decl_rtl (method, NULL, 1); + { + if (! abstract_p) + warning_with_decl (method, + "abstract method in non-abstract class"); + method = null_pointer_node; + } + else + { + if (DECL_RTL (method) == 0) + make_decl_rtl (method, NULL, 1); + method = build1 (ADDR_EXPR, nativecode_ptr_type_node, method); + } list = tree_cons (NULL_TREE /*DECL_VINDEX (method) + 2*/, - build1 (ADDR_EXPR, nativecode_ptr_type_node, method), - list); + method, list); } /* Dummy entry for compatibility with G++ -fvtable-thunks. When using the Boehm GC we sometimes stash a GC type descriptor - there. */ - list = tree_cons (integer_zero_node, get_boehm_type_descriptor (type), + there. We set the PURPOSE to NULL_TREE not to interfere (reset) + the emitted byte count during the output to the assembly file. */ + list = tree_cons (NULL_TREE, get_boehm_type_descriptor (type), list); list = tree_cons (integer_zero_node, this_class_addr, list); return build (CONSTRUCTOR, build_prim_array_type (nativecode_ptr_type_node, @@ -1314,7 +1340,7 @@ make_class_data (type) rest_of_decl_compilation (methods_decl, (char*) 0, 1, 0); if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl))) - && ! CLASS_ABSTRACT (type_decl) && ! CLASS_INTERFACE (type_decl)) + && ! CLASS_INTERFACE (type_decl)) { tree dtable = get_dispatch_table (type, this_class_addr); dtable_decl = build_dtable_decl (type); @@ -1415,6 +1441,7 @@ make_class_data (type) PUSH_FIELD_VALUE (cons, "depth", integer_zero_node); PUSH_FIELD_VALUE (cons, "ancestors", null_pointer_node); PUSH_FIELD_VALUE (cons, "idt", null_pointer_node); + PUSH_FIELD_VALUE (cons, "arrayclass", null_pointer_node); FINISH_RECORD_CONSTRUCTOR (cons); @@ -1453,9 +1480,7 @@ finish_class () || ! METHOD_PRIVATE (method) || saw_native_method) { - temporary_allocation (); output_inline_function (method); - permanent_allocation (1); /* Scan the list again to see if there are any earlier methods to emit. */ method = type_methods; @@ -1580,29 +1605,13 @@ append_gpp_mangled_type (obstack, type) } } -/* Build the mangled name of the `class' field. */ +/* Build the mangled name of a field, given the class name and the + field name. */ static tree -mangle_class_field (class) - tree class; +mangle_field (class, name) + tree class, name; { - tree name; - obstack_grow (&temporary_obstack, "_CL_", 4); - append_gpp_mangled_type (&temporary_obstack, class); - obstack_1grow (&temporary_obstack, '\0'); - name = get_identifier (obstack_base (&temporary_obstack)); - obstack_free (&temporary_obstack, obstack_base (&temporary_obstack)); - return name; -} - -/* Build the mangled (assembly-level) name of the static field FIELD. */ - -static tree -mangle_static_field (field) - tree field; -{ - tree class = DECL_CONTEXT (field); - tree name = DECL_NAME (field); int encoded_len; #if ! defined (NO_DOLLAR_IN_LABEL) || ! defined (NO_DOT_IN_LABEL) obstack_1grow (&temporary_obstack, '_'); @@ -1637,25 +1646,72 @@ mangle_static_field (field) IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)); } + + /* Mangle C++ keywords by appending a `$'. */ + /* FIXME: NO_DOLLAR_IN_LABEL */ + if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name))) + obstack_grow (&temporary_obstack, "$", 1); + obstack_1grow (&temporary_obstack, '\0'); name = get_identifier (obstack_base (&temporary_obstack)); obstack_free (&temporary_obstack, obstack_base (&temporary_obstack)); return name; } +/* Build the mangled name of the `class' field. */ + +static tree +mangle_class_field (class) + tree class; +{ + /* We know that we can use `class$' to mangle the class object, + because `class' is a reserved word in Java and thus can't appear + as a field or method name. */ + return mangle_field (class, get_identifier ("class$")); +} + +/* Build the mangled (assembly-level) name of the static field FIELD. */ + +static tree +mangle_static_field (field) + tree field; +{ + return mangle_field (DECL_CONTEXT (field), DECL_NAME (field)); +} + /* Build a VAR_DECL for the dispatch table (vtable) for class TYPE. */ tree build_dtable_decl (type) tree type; { - tree name; + tree name, dtype; + + /* We need to build a new dtable type so that its size is uniquely + computed when we're dealing with the class for real and not just + faking it (like java.lang.Class during the initialization of the + compiler.) We now we're not faking a class when CURRENT_CLASS is + TYPE. */ + if (current_class == type) + { + tree dummy = NULL_TREE, aomt, n; + + dtype = make_node (RECORD_TYPE); + PUSH_FIELD (dtype, dummy, "class", class_ptr_type); + n = build_int_2 (TREE_VEC_LENGTH (get_dispatch_vector (type)), 0); + aomt = build_array_type (ptr_type_node, build_index_type (n)); + PUSH_FIELD (dtype, dummy, "methods", aomt); + layout_type (dtype); + } + else + dtype = dtable_type; + obstack_grow (&temporary_obstack, "__vt_", 5); append_gpp_mangled_type (&temporary_obstack, type); obstack_1grow (&temporary_obstack, '\0'); name = get_identifier (obstack_base (&temporary_obstack)); obstack_free (&temporary_obstack, obstack_base (&temporary_obstack)); - return build_decl (VAR_DECL, name, dtable_type); + return build_decl (VAR_DECL, name, dtype); } /* Pre-pend the TYPE_FIELDS of THIS_CLASS with a dummy FIELD_DECL for the @@ -1669,9 +1725,7 @@ push_super_field (this_class, super_class) /* Don't insert the field if we're just re-laying the class out. */ if (TYPE_FIELDS (this_class) && !DECL_NAME (TYPE_FIELDS (this_class))) return; - push_obstacks (&permanent_obstack, &permanent_obstack); base_decl = build_decl (FIELD_DECL, NULL_TREE, super_class); - pop_obstacks (); DECL_IGNORED_P (base_decl) = 1; TREE_CHAIN (base_decl) = TYPE_FIELDS (this_class); TYPE_FIELDS (this_class) = base_decl; @@ -1688,8 +1742,7 @@ maybe_layout_super_class (super_class, this_class) { if (TREE_CODE (super_class) == RECORD_TYPE) { - if (!CLASS_LOADED_P (super_class) - && CLASS_FROM_SOURCE_P (super_class)) + if (!CLASS_LOADED_P (super_class) && CLASS_FROM_SOURCE_P (super_class)) safe_layout_class (super_class); if (!CLASS_LOADED_P (super_class)) load_class (super_class, 1); @@ -1720,13 +1773,22 @@ layout_class (this_class) tree this_class; { static tree list = NULL_TREE; + static int initialized_p; tree super_class = CLASSTYPE_SUPER (this_class); tree field; + /* Register LIST with the garbage collector. */ + if (!initialized_p) + { + ggc_add_tree_root (&list, 1); + initialized_p = 1; + } + list = tree_cons (this_class, NULL_TREE, list); if (CLASS_BEING_LAIDOUT (this_class)) { char buffer [1024]; + char *report; tree current; sprintf (buffer, " with `%s'", @@ -1744,7 +1806,9 @@ layout_class (this_class) obstack_grow (&temporary_obstack, buffer, strlen (buffer)); } obstack_1grow (&temporary_obstack, '\0'); - cyclic_inheritance_report = obstack_finish (&temporary_obstack); + report = obstack_finish (&temporary_obstack); + cyclic_inheritance_report = ggc_strdup (report); + obstack_free (&temporary_obstack, report); TYPE_SIZE (this_class) = error_mark_node; return; } @@ -1752,8 +1816,10 @@ layout_class (this_class) if (super_class) { - super_class = maybe_layout_super_class (super_class, this_class); - if (TREE_CODE (TYPE_SIZE (super_class)) == ERROR_MARK) + tree maybe_super_class + = maybe_layout_super_class (super_class, this_class); + if (maybe_super_class == NULL + || TREE_CODE (TYPE_SIZE (maybe_super_class)) == ERROR_MARK) { TYPE_SIZE (this_class) = error_mark_node; CLASS_BEING_LAIDOUT (this_class) = 0; @@ -1776,6 +1842,35 @@ layout_class (this_class) layout_type (this_class); + /* Also recursively load/layout any superinterfaces, but only if class was + loaded from bytecode. The source parser will take care of this itself. */ + if (!CLASS_FROM_SOURCE_P (this_class)) + { + tree basetype_vec = TYPE_BINFO_BASETYPES (this_class); + + if (basetype_vec) + { + int n = TREE_VEC_LENGTH (basetype_vec) - 1; + int i; + for (i = n; i > 0; i--) + { + tree vec_elt = TREE_VEC_ELT (basetype_vec, i); + tree super_interface = BINFO_TYPE (vec_elt); + + tree maybe_super_interface + = maybe_layout_super_class (super_interface, NULL_TREE); + if (maybe_super_interface == NULL + || TREE_CODE (TYPE_SIZE (maybe_super_interface)) == ERROR_MARK) + { + TYPE_SIZE (this_class) = error_mark_node; + CLASS_BEING_LAIDOUT (this_class) = 0; + list = TREE_CHAIN (list); + return; + } + } + } + } + /* Convert the size back to an SI integer value */ TYPE_SIZE_UNIT (this_class) = fold (convert (int_type_node, TYPE_SIZE_UNIT (this_class))); @@ -1794,7 +1889,6 @@ layout_class_methods (this_class) if (TYPE_NVIRTUALS (this_class)) return; - push_obstacks (&permanent_obstack, &permanent_obstack); super_class = CLASSTYPE_SUPER (this_class); handle_type = CLASS_TO_HANDLE_TYPE (this_class); @@ -1807,7 +1901,7 @@ layout_class_methods (this_class) } else dtable_count = integer_zero_node; - + TYPE_METHODS (handle_type) = nreverse (TYPE_METHODS (handle_type)); for (method_decl = TYPE_METHODS (handle_type); @@ -1820,7 +1914,105 @@ layout_class_methods (this_class) #ifdef JAVA_USE_HANDLES layout_type (handle_type); #endif - pop_obstacks (); +} + +/* A sorted list of all C++ keywords. */ + +static const char *cxx_keywords[] = +{ + "asm", + "auto", + "bool", + "const_cast", + "delete", + "dynamic_cast", + "enum", + "explicit", + "extern", + "friend", + "inline", + "mutable", + "namespace", + "overload", + "register", + "reinterpret_cast", + "signed", + "sizeof", + "static_cast", + "struct", + "template", + "typedef", + "typeid", + "typename", + "typenameopt", + "union", + "unsigned", + "using", + "virtual", + "volatile", + "wchar_t" +}; + +/* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME, + and 1 if STR is "greater" than NAME. */ + +static int +utf8_cmp (str, length, name) + const unsigned char *str; + int length; + const char *name; +{ + const unsigned char *limit = str + length; + int i; + + for (i = 0; name[i]; ++i) + { + int ch = UTF8_GET (str, limit); + if (ch != name[i]) + return ch - name[i]; + } + + return str == limit ? 0 : 1; +} + +/* Return true if NAME is a C++ keyword. */ + +static int +cxx_keyword_p (name, length) + const char *name; + int length; +{ + int last = ARRAY_SIZE (cxx_keywords); + int first = 0; + int mid = (last + first) / 2; + int old = -1; + + for (mid = (last + first) / 2; + mid != old; + old = mid, mid = (last + first) / 2) + { + int kwl = strlen (cxx_keywords[mid]); + int min_length = kwl > length ? length : kwl; + int r = utf8_cmp (name, min_length, cxx_keywords[mid]); + + if (r == 0) + { + int i; + /* We've found a match if all the remaining characters are + `$'. */ + for (i = min_length; i < length && name[i] == '$'; ++i) + ; + if (i == length) + return 1; + r = 1; + } + + if (r < 0) + last = mid; + else + first = mid; + } + return 0; } /* Lay METHOD_DECL out, returning a possibly new value of @@ -1858,8 +2050,14 @@ layout_class_method (this_class, super_class, method_decl, dtable_count) IDENTIFIER_POINTER (method_name), IDENTIFIER_LENGTH (method_name)); } + + /* Mangle C++ keywords by appending a `$'. */ + /* FIXME: NO_DOLLAR_IN_LABEL */ + if (cxx_keyword_p (IDENTIFIER_POINTER (method_name), + IDENTIFIER_LENGTH (method_name))) + obstack_grow (&temporary_obstack, "$", 1); } - + obstack_grow (&temporary_obstack, "__", 2); if (ID_FINIT_P (method_name)) obstack_grow (&temporary_obstack, "finit", 5); @@ -1985,6 +2183,9 @@ static tree registered_class = NULL_TREE; void register_class () { + /* END does not need to be registered with the garbage collector + because it always points into the list given by REGISTERED_CLASS, + and that variable is registered with the collector. */ static tree end; tree node = TREE_OPERAND (build_class_ref (current_class), 0); tree current = copy_node (node); @@ -2043,4 +2244,7 @@ void init_class_processing () { registerClass_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_Jv_RegisterClass"); + ggc_add_tree_root (®istered_class, 1); + ggc_add_rtx_root (®isterClass_libfunc, 1); + gcc_obstack_init (&temporary_obstack); }