X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=libjava%2Fprims.cc;h=1ef56742398da718eef86a3c5c8cde3990d8a7c3;hb=61b110292905729079ef4661c75e3fa46189df8c;hp=fadc466bc0e9d3623e1ebbc6200a5990710b858d;hpb=be7d01ed62d74d9c4b7b53f96bb82c8f109f859e;p=pf3gnuchains%2Fgcc-fork.git diff --git a/libjava/prims.cc b/libjava/prims.cc index fadc466bc0e..1ef56742398 100644 --- a/libjava/prims.cc +++ b/libjava/prims.cc @@ -1,6 +1,6 @@ // prims.cc - Code for core of runtime environment. -/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation +/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation This file is part of libgcj. @@ -49,8 +49,10 @@ details. */ #include #include #include +#include #include #include +#include #include #include #include @@ -168,7 +170,6 @@ SIGNAL_HANDLER (catch_fpe) } #endif - jboolean _Jv_equalUtf8Consts (const Utf8Const* a, const Utf8Const *b) @@ -236,9 +237,123 @@ _Jv_equaln (Utf8Const *a, jstring str, jint n) return true; } +// Determines whether the given Utf8Const object contains +// a type which is primitive or some derived form of it, eg. +// an array or multi-dimensional array variant. +jboolean +_Jv_isPrimitiveOrDerived(const Utf8Const *a) +{ + unsigned char *aptr = (unsigned char *) a->data; + unsigned char *alimit = aptr + a->length; + int ac = UTF8_GET(aptr, alimit); + + // Skips any leading array marks. + while (ac == '[') + ac = UTF8_GET(aptr, alimit); + + // There should not be another character. This implies that + // the type name is only one character long. + if (UTF8_GET(aptr, alimit) == -1) + switch ( ac ) + { + case 'Z': + case 'B': + case 'C': + case 'S': + case 'I': + case 'J': + case 'F': + case 'D': + return true; + default: + break; + } + + return false; +} + +// Find out whether two _Jv_Utf8Const candidates contain the same +// classname. +// The method is written to handle the different formats of classnames. +// Eg. "Ljava/lang/Class;", "Ljava.lang.Class;", "java/lang/Class" and +// "java.lang.Class" will be seen as equal. +// Warning: This function is not smart enough to declare "Z" and "boolean" +// and similar cases as equal (and is not meant to be used this way)! +jboolean +_Jv_equalUtf8Classnames (const Utf8Const *a, const Utf8Const *b) +{ + // If the class name's length differs by two characters + // it is possible that we have candidates which are given + // in the two different formats ("Lp1/p2/cn;" vs. "p1/p2/cn") + switch (a->length - b->length) + { + case -2: + case 0: + case 2: + break; + default: + return false; + } + + unsigned char *aptr = (unsigned char *) a->data; + unsigned char *alimit = aptr + a->length; + unsigned char *bptr = (unsigned char *) b->data; + unsigned char *blimit = bptr + b->length; + + if (alimit[-1] == ';') + alimit--; + + if (blimit[-1] == ';') + blimit--; + + int ac = UTF8_GET(aptr, alimit); + int bc = UTF8_GET(bptr, blimit); + + // Checks whether both strings have the same amount of leading [ characters. + while (ac == '[') + { + if (bc == '[') + { + ac = UTF8_GET(aptr, alimit); + bc = UTF8_GET(bptr, blimit); + continue; + } + + return false; + } + + // Skips leading L character. + if (ac == 'L') + ac = UTF8_GET(aptr, alimit); + + if (bc == 'L') + bc = UTF8_GET(bptr, blimit); + + // Compares the remaining characters. + while (ac != -1 && bc != -1) + { + // Replaces package separating dots with slashes. + if (ac == '.') + ac = '/'; + + if (bc == '.') + bc = '/'; + + // Now classnames differ if there is at least one non-matching + // character. + if (ac != bc) + return false; + + ac = UTF8_GET(aptr, alimit); + bc = UTF8_GET(bptr, blimit); + } + + return (ac == bc); +} + /* Count the number of Unicode chars encoded in a given Ut8 string. */ int -_Jv_strLengthUtf8(char* str, int len) +_Jv_strLengthUtf8(const char* str, int len) { unsigned char* ptr; unsigned char* limit; @@ -259,7 +374,7 @@ _Jv_strLengthUtf8(char* str, int len) * This returns the same hash value as specified or java.lang.String.hashCode. */ jint -_Jv_hashUtf8String (char* str, int len) +_Jv_hashUtf8String (const char* str, int len) { unsigned char* ptr = (unsigned char*) str; unsigned char* limit = ptr + len; @@ -276,7 +391,7 @@ _Jv_hashUtf8String (char* str, int len) } void -_Jv_Utf8Const::init(char *s, int len) +_Jv_Utf8Const::init(const char *s, int len) { ::memcpy (data, s, len); data[len] = 0; @@ -285,7 +400,7 @@ _Jv_Utf8Const::init(char *s, int len) } _Jv_Utf8Const * -_Jv_makeUtf8Const (char* s, int len) +_Jv_makeUtf8Const (const char* s, int len) { if (len < 0) len = strlen (s); @@ -359,6 +474,22 @@ _Jv_ThrowNullPointerException () throw new java::lang::NullPointerException; } +// Resolve an entry in the constant pool and return the target +// address. +void * +_Jv_ResolvePoolEntry (jclass this_class, jint index) +{ + _Jv_Constants *pool = &this_class->constants; + + if ((pool->tags[index] & JV_CONSTANT_ResolvedFlag) != 0) + return pool->data[index].field->u.addr; + + JvSynchronize sync (this_class); + return (_Jv_Linker::resolve_pool_entry (this_class, index)) + .field->u.addr; +} + + // Explicitly throw a no memory exception. // The collector calls this when it encounters an out-of-memory condition. void _Jv_ThrowNoMemory() @@ -418,6 +549,9 @@ _Jv_AllocObjectNoInitNoFinalizer (jclass klass) jobject _Jv_AllocObjectNoFinalizer (jclass klass) { + if (_Jv_IsPhantomClass(klass) ) + throw new java::lang::NoClassDefFoundError(klass->getName()); + _Jv_InitClass (klass); jint size = klass->size (); jobject obj = (jobject) _Jv_AllocObj (size, klass); @@ -496,6 +630,11 @@ _Jv_AllocPtrFreeObject (jclass klass) jobjectArray _Jv_NewObjectArray (jsize count, jclass elementClass, jobject init) { + // Creating an array of an unresolved type is impossible. So we throw + // the NoClassDefFoundError. + if ( _Jv_IsPhantomClass(elementClass) ) + throw new java::lang::NoClassDefFoundError(elementClass->getName()); + if (__builtin_expect (count < 0, false)) throw new java::lang::NegativeArraySizeException; @@ -655,7 +794,7 @@ DECLARE_PRIM_TYPE(double) DECLARE_PRIM_TYPE(void) void -_Jv_InitPrimClass (jclass cl, char *cname, char sig, int len) +_Jv_InitPrimClass (jclass cl, const char *cname, char sig, int len) { using namespace java::lang::reflect; @@ -750,7 +889,28 @@ _Jv_FindClassFromSignature (char *sig, java::lang::ClassLoader *loader, return result; } - + +jclass +_Jv_FindClassFromSignatureNoException (char *sig, java::lang::ClassLoader *loader, + char **endp) +{ + jclass klass; + + try + { + klass = _Jv_FindClassFromSignature(sig, loader, endp); + } + catch (java::lang::NoClassDefFoundError *ncdfe) + { + return NULL; + } + catch (java::lang::ClassNotFoundException *cnfe) + { + return NULL; + } + + return klass; +} JArray * JvConvertArgv (int argc, const char **argv) @@ -841,10 +1001,6 @@ next_property_value (char *s, size_t *length) while (isspace (*s)) s++; - // If we've reached the end, return NULL. - if (*s == 0) - return NULL; - // Determine the length of the property value. while (s[l] != 0 && ! isspace (s[l]) @@ -867,13 +1023,18 @@ static void process_gcj_properties () { char *props = getenv("GCJ_PROPERTIES"); - char *p = props; - size_t length; - size_t property_count = 0; if (NULL == props) return; + // Later on we will write \0s into this string. It is simplest to + // just duplicate it here. + props = strdup (props); + + char *p = props; + size_t length; + size_t property_count = 0; + // Whip through props quickly in order to count the number of // property values. while (p && (p = next_property_key (p, &length))) @@ -937,6 +1098,15 @@ namespace gcj _Jv_Utf8Const *finit_name; bool runtimeInitialized = false; + + // When true, print debugging information about class loading. + bool verbose_class_flag; + + // When true, enable the bytecode verifier and BC-ABI type verification. + bool verifyClasses = true; + + // Thread stack size specified by the -Xss runtime argument. + size_t stack_size = 0; } // We accept all non-standard options accepted by Sun's java command, @@ -1023,7 +1193,7 @@ parse_x_arg (char* option_string) } else if (! strncmp (option_string, "ss", 2)) { - // FIXME: set thread stack size + _Jv_SetStackSize (option_string + 2); } else if (! strcmp (option_string, "X:+UseAltSigs")) { @@ -1049,7 +1219,7 @@ static jint parse_verbose_args (char* option_string, bool ignore_unrecognized) { - size_t len = sizeof ("-verbose"); + size_t len = sizeof ("-verbose") - 1; if (strlen (option_string) < len) return -1; @@ -1058,69 +1228,72 @@ parse_verbose_args (char* option_string, && option_string[len + 1] != '\0') { char* verbose_args = option_string + len + 1; - size_t last = 0; do { if (! strncmp (verbose_args, - "gc", (last = sizeof ("gc")) - 1) - && (verbose_args[last] == '\0' - || verbose_args[last] == ',')) - { - // FIXME: we should add functions to boehm-gc that - // toggle GC_print_stats, GC_PRINT_ADDRESS_MAP and - // GC_print_back_height. - - } + "gc", sizeof ("gc") - 1)) + { + if (verbose_args[sizeof ("gc") - 1] == '\0' + || verbose_args[sizeof ("gc") - 1] == ',') + { + // FIXME: we should add functions to boehm-gc that + // toggle GC_print_stats, GC_PRINT_ADDRESS_MAP and + // GC_print_back_height. + verbose_args += sizeof ("gc") - 1; + } + else + { + verbose_arg_err: + fprintf (stderr, "libgcj: unknown verbose option: %s\n", + option_string); + return -1; + } + } else if (! strncmp (verbose_args, "class", - (last = sizeof ("class")) - 1) - && (verbose_args[last] == '\0' - || verbose_args[last] == ',')) - { - gcj::verbose_class_flag = true; - } + sizeof ("class") - 1)) + { + if (verbose_args[sizeof ("class") - 1] == '\0' + || verbose_args[sizeof ("class") - 1] == ',') + { + gcj::verbose_class_flag = true; + verbose_args += sizeof ("class") - 1; + } + else + goto verbose_arg_err; + } else if (! strncmp (verbose_args, "jni", - (last = sizeof ("jni")) - 1) - && (verbose_args[last] == '\0' - || verbose_args[last] == ',')) - { - // FIXME: enable JNI messages. - } + sizeof ("jni") - 1)) + { + if (verbose_args[sizeof ("jni") - 1] == '\0' + || verbose_args[sizeof ("jni") - 1] == ',') + { + // FIXME: enable JNI messages. + verbose_args += sizeof ("jni") - 1; + } + else + goto verbose_arg_err; + } else if (ignore_unrecognized && verbose_args[0] == 'X') { // ignore unrecognized non-standard verbose option - last = 0; - while (verbose_args[last] != '\0' - && verbose_args[last++] != ','); - } - - if (strlen (verbose_args) >= last) - { - if (verbose_args[last] == ',') - { - if (verbose_args[last + 1] == '\0') - // trailing comma - return -1; - else - { - verbose_args = verbose_args + last + 1; - last = 0; - } - } - // here verbose_args[last] is either '\0' or - // the first character in the next verbose - // argument. + while (verbose_args[0] != '\0' + && verbose_args[0] != ',') + verbose_args++; } - else - // partial option - return -1; + else if (verbose_args[0] == ',') + { + verbose_args++; + } + else + goto verbose_arg_err; - // verbose_args[last] will be '\0' here if we're - // done. + if (verbose_args[0] == ',') + verbose_args++; } - while (verbose_args[last] != '\0'); + while (verbose_args[0] != '\0'); } else if (option_string[len] == 'g' && option_string[len + 1] == 'c' @@ -1359,10 +1532,10 @@ _Jv_RunMain (JvVMInitArgs *vm_args, jclass klass, const char *name, int argc, _Jv_AttachCurrentThread (main_thread); _Jv_ThreadRun (main_thread); - _Jv_ThreadWait (); - int status = (int) java::lang::ThreadGroup::had_uncaught_exception; - runtime->exit (status); + // If we got here then something went wrong, as MainThread is not + // supposed to terminate. + ::exit (1); } void @@ -1382,7 +1555,7 @@ JvRunMain (jclass klass, int argc, const char **argv) // Parse a string and return a heap size. static size_t -parse_heap_size (const char *spec) +parse_memory_size (const char *spec) { char *end; unsigned long val = strtoul (spec, &end, 10); @@ -1398,7 +1571,7 @@ parse_heap_size (const char *spec) void _Jv_SetInitialHeapSize (const char *arg) { - size_t size = parse_heap_size (arg); + size_t size = parse_memory_size (arg); _Jv_GCSetInitialHeapSize (size); } @@ -1407,11 +1580,16 @@ _Jv_SetInitialHeapSize (const char *arg) void _Jv_SetMaximumHeapSize (const char *arg) { - size_t size = parse_heap_size (arg); + size_t size = parse_memory_size (arg); _Jv_GCSetMaximumHeapSize (size); } - +void +_Jv_SetStackSize (const char *arg) +{ + size_t size = parse_memory_size (arg); + gcj::stack_size = size; +} void * _Jv_Malloc (jsize size) @@ -1532,7 +1710,7 @@ _Jv_CheckAccess (jclass self_klass, jclass other_klass, jint flags) return ((self_klass == other_klass) || ((flags & Modifier::PUBLIC) != 0) || (((flags & Modifier::PROTECTED) != 0) - && _Jv_IsAssignableFromSlow (other_klass, self_klass)) + && _Jv_IsAssignableFromSlow (self_klass, other_klass)) || (((flags & Modifier::PRIVATE) == 0) && _Jv_ClassNameSamePackage (self_klass->name, other_klass->name)));