diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 2ce57c0fdc1..93deeb2f78f 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,18 @@ +2006-05-04 Andrew Haley + + * class.c (make_field_value): Always build_address_of fdecl if + there is an initializer. + +2006-05-03 Andrew Haley + + PR libgcj/27352 + * expr.c (maybe_rewrite_invocation): New function. + (rewrite_arglist_getclass): Likewise. + (rules): New. + (expand_invoke): Call maybe_rewrite_invocation. + * parse.y (patch_invoke): Likewise. + * java-tree.h: (maybe_rewrite_invocation): New function. + 2006-04-21 Andrew Haley * lang.c (java_init): Handle flag_indirect_classes. diff --git a/gcc/java/class.c b/gcc/java/class.c index fe52e67d4ac..590925d3ab2 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -1344,7 +1344,8 @@ make_field_value (tree fdecl) { tree field_address = integer_zero_node; - if (! flag_indirect_classes && FIELD_STATIC (fdecl)) + if ((DECL_INITIAL (fdecl) || ! flag_indirect_classes) + && FIELD_STATIC (fdecl)) field_address = build_address_of (fdecl); PUSH_FIELD_VALUE diff --git a/gcc/java/expr.c b/gcc/java/expr.c index 1cd405a6bb7..b2e03fc862e 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -2020,6 +2020,86 @@ build_class_init (tree clas, tree expr) return init; } + + +/* Rewrite expensive calls that require stack unwinding at runtime to + cheaper alternatives. The logic here performs thse + transformations: + + java.lang.Class.forName("foo") -> java.lang.Class.forName("foo", class$) + java.lang.Class.getClassLoader() -> java.lang.Class.getClassLoader(class$) + +*/ + +typedef struct +{ + const char *classname; + const char *method; + const char *signature; + const char *new_signature; + int flags; + tree (*rewrite_arglist) (tree arglist); +} rewrite_rule; + +/* Add this.class to the end of an arglist. */ + +static tree +rewrite_arglist_getclass (tree arglist) +{ + return chainon (arglist, + tree_cons (NULL_TREE, build_class_ref (output_class), NULL_TREE)); +} + +static rewrite_rule rules[] = + {{"java.lang.Class", "getClassLoader", "()Ljava/lang/ClassLoader;", + "(Ljava/lang/Class;)Ljava/lang/ClassLoader;", + ACC_FINAL|ACC_PRIVATE, rewrite_arglist_getclass}, + {"java.lang.Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", + "(Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Class;", + ACC_FINAL|ACC_PRIVATE|ACC_STATIC, rewrite_arglist_getclass}, + {NULL, NULL, NULL, NULL, 0, NULL}}; + +/* Scan the rules list for replacements for *METHOD_P and replace the + args accordingly. */ + +void +maybe_rewrite_invocation (tree *method_p, tree *arg_list_p, + tree *method_signature_p) +{ + tree context = DECL_NAME (TYPE_NAME (DECL_CONTEXT (*method_p))); + rewrite_rule *p; + for (p = rules; p->classname; p++) + { + if (get_identifier (p->classname) == context) + { + tree method = DECL_NAME (*method_p); + if (get_identifier (p->method) == method + && get_identifier (p->signature) == *method_signature_p) + { + tree maybe_method + = lookup_java_method (DECL_CONTEXT (*method_p), + method, + get_identifier (p->new_signature)); + if (! maybe_method && ! flag_verify_invocations) + { + maybe_method + = add_method (DECL_CONTEXT (*method_p), p->flags, + method, get_identifier (p->new_signature)); + DECL_EXTERNAL (maybe_method) = 1; + } + *method_p = maybe_method; + gcc_assert (*method_p); + *arg_list_p = p->rewrite_arglist (*arg_list_p); + *method_signature_p = get_identifier (p->new_signature); + + break; + } + } + } +} + + + tree build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED, tree self_type, tree method_signature ATTRIBUTE_UNUSED, @@ -2394,6 +2474,8 @@ expand_invoke (int opcode, int method_ref_index, int nargs ATTRIBUTE_UNUSED) arg_list = pop_arguments (TYPE_ARG_TYPES (method_type)); flush_quick_stack (); + maybe_rewrite_invocation (&method, &arg_list, &method_signature); + func = NULL_TREE; if (opcode == OPCODE_invokestatic) func = build_known_method_ref (method, method_type, self_type, diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index 03a7ea2c142..de826b9c52d 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -1241,6 +1241,7 @@ extern tree check_for_builtin (tree, tree); extern void initialize_builtins (void); extern tree lookup_name (tree); +extern void maybe_rewrite_invocation (tree *, tree *, tree *); extern tree build_known_method_ref (tree, tree, tree, tree, tree); extern tree build_class_init (tree, tree); extern int attach_init_test_initialization_flags (void **, void *); diff --git a/gcc/java/parse.y b/gcc/java/parse.y index 118c66f8221..a606d87869e 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -11066,6 +11066,7 @@ patch_invoke (tree patch, tree method, tree args) case INVOKE_STATIC: { tree signature = build_java_signature (TREE_TYPE (method)); + maybe_rewrite_invocation (&method, &args, &signature); func = build_known_method_ref (method, TREE_TYPE (method), DECL_CONTEXT (method), signature, args); diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 161adfca458..19c06e16265 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,14 @@ +2006-05-03 Andrew Haley + + PR libgcj/27352 + * java/lang/Class.java (getClassLoader(Class)): New. + forName(String, Class): New. + * java/lang/natClass.cc (getClassLoader(Class)): New. + +2006-05-02 Andrew Haley + + * prims.cc (_Jv_NewMultiArray): Check for phantom class. + 2006-05-04 Tom Tromey PR libgcj/26861: diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h index 722129498aa..f6ca3deb949 100644 --- a/libjava/java/lang/Class.h +++ b/libjava/java/lang/Class.h @@ -297,6 +297,8 @@ public: JArray *getClasses (void); java::lang::ClassLoader *getClassLoader (void); +private: + java::lang::ClassLoader *getClassLoader (jclass caller); public: // This is an internal method that circumvents the usual security // checks when getting the class loader. diff --git a/libjava/java/lang/Class.java b/libjava/java/lang/Class.java index 60ca4577e99..66b85c7ce99 100644 --- a/libjava/java/lang/Class.java +++ b/libjava/java/lang/Class.java @@ -111,6 +111,14 @@ public final class Class implements Serializable public static native Class forName (String className) throws ClassNotFoundException; + // A private internal method that is called by compiler-generated code. + private static Class forName (String className, Class caller) + throws ClassNotFoundException + { + return forName(className, true, caller.getClassLoader()); + } + + /** * Use the specified classloader to load and link a class. If the loader * is null, this uses the bootstrap class loader (provide the security @@ -185,6 +193,9 @@ public final class Class implements Serializable */ public native ClassLoader getClassLoader (); + // A private internal method that is called by compiler-generated code. + private final native ClassLoader getClassLoader (Class caller); + /** * If this is an array, get the Class representing the type of array. * Examples: "[[Ljava.lang.String;" would return "[Ljava.lang.String;", and diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc index d88835019f4..887088933f7 100644 --- a/libjava/java/lang/natClass.cc +++ b/libjava/java/lang/natClass.cc @@ -115,9 +115,19 @@ java::lang::Class::getClassLoader (void) if (s != NULL) { jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$); - ClassLoader *caller_loader = NULL; - if (caller) - caller_loader = caller->getClassLoaderInternal(); + return getClassLoader (caller); + } + + return loader; +} + +java::lang::ClassLoader * +java::lang::Class::getClassLoader (jclass caller) +{ + java::lang::SecurityManager *s = java::lang::System::getSecurityManager(); + if (s != NULL) + { + ClassLoader *caller_loader = caller->getClassLoaderInternal(); // If the caller has a non-null class loader, and that loader // is not this class' loader or an ancestor thereof, then do a diff --git a/libjava/prims.cc b/libjava/prims.cc index 5e016c94c78..e0cdc0ae585 100644 --- a/libjava/prims.cc +++ b/libjava/prims.cc @@ -762,6 +762,11 @@ _Jv_NewMultiArray (jclass type, jint dimensions, jint *sizes) jobject _Jv_NewMultiArray (jclass array_type, jint dimensions, ...) { + // Creating an array of an unresolved type is impossible. So we throw + // the NoClassDefFoundError. + if (_Jv_IsPhantomClass(array_type)) + throw new java::lang::NoClassDefFoundError(array_type->getName()); + va_list args; jint sizes[dimensions]; va_start (args, dimensions);