From 107abb2f61f6e53ebb7aa05b78fdd9234ee7877c Mon Sep 17 00:00:00 2001 From: Bryce McKinlay Date: Tue, 16 Oct 2001 08:35:17 +0000 Subject: [PATCH] Eliminate use of C++ static constructors. * interpret.cc: Remove static Utf8Consts. Use namespace gcj. * jni.cc: Likewise. * resolve.cc: Likewise. * defineclass.cc: Likewise. (_Jv_ClassReader::handleClassBegin): Synchronize call to _Jv_RegisterClass. * include/jvm.h (void_signature, clinit_name, init_name, finit_name): Declare in namespace gcj. * java/lang/Class.h (Class): Remove initialization for primitive types. (friend void _Jv_InitPrimClass): This is in prims.cc. * prims.cc (_Jv_InitPrimClass): Do primitive type initialization here instead. (void_signature, clinit_name, init_name, finit_name): Define in namespace gcj. (_Jv_CreateJavaVM): Call _Jv_InitThreads, _Jv_InitGC, and _Jv_InitializeSyncMutex from here. Initialize Utf8 constants. Initialize primitive types. * java/lang/natClassLoader.cc (_Jv_RegisterClasses): Don't call initialization routines. Don't synchronize. * java/lang/natRuntime.cc (_load): Synchronize on java.lang.Class across dlopen call. From-SVN: r46282 --- libjava/ChangeLog | 24 ++++++++ libjava/defineclass.cc | 11 ++-- libjava/include/jvm.h | 9 +++ libjava/interpret.cc | 2 +- libjava/java/lang/natClass.cc | 23 ++------ libjava/java/lang/natClassLoader.cc | 20 ++----- libjava/java/lang/natRuntime.cc | 9 ++- libjava/jni.cc | 5 +- libjava/prims.cc | 86 ++++++++++++++++++++++++----- libjava/resolve.cc | 5 +- 10 files changed, 132 insertions(+), 62 deletions(-) diff --git a/libjava/ChangeLog b/libjava/ChangeLog index c3364d05e78..88639b9fa6a 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -2,6 +2,30 @@ * name-finder.cc (_Jv_name_finder::lookup): Check for NULL dli_sname. + Eliminate use of C++ static constructors. + * interpret.cc: Remove static Utf8Consts. Use namespace gcj. + * jni.cc: Likewise. + * resolve.cc: Likewise. + * defineclass.cc: Likewise. + (_Jv_ClassReader::handleClassBegin): Synchronize call to + _Jv_RegisterClass. + * include/jvm.h (void_signature, clinit_name, init_name, finit_name): + Declare in namespace gcj. + * java/lang/Class.h (Class): Remove initialization for primitive + types. + (friend void _Jv_InitPrimClass): This is in prims.cc. + * prims.cc (_Jv_InitPrimClass): Do primitive type initialization + here instead. + (void_signature, clinit_name, init_name, finit_name): Define in + namespace gcj. + (_Jv_CreateJavaVM): Call _Jv_InitThreads, _Jv_InitGC, and + _Jv_InitializeSyncMutex from here. Initialize Utf8 constants. + Initialize primitive types. + * java/lang/natClassLoader.cc (_Jv_RegisterClasses): Don't call + initialization routines. Don't synchronize. + * java/lang/natRuntime.cc (_load): Synchronize on java.lang.Class + across dlopen call. + 2001-10-15 Bryce McKinlay * java/util/HashMap.java (HashEntry.clone): Removed. diff --git a/libjava/defineclass.cc b/libjava/defineclass.cc index e25b106b2d8..85f6ce3a65e 100644 --- a/libjava/defineclass.cc +++ b/libjava/defineclass.cc @@ -41,10 +41,7 @@ details. */ #include #include -// we don't verify method names that match these. -static _Jv_Utf8Const *clinit_name = _Jv_makeUtf8Const ("", 8); -static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("", 6); - +using namespace gcj; // these go in some separate functions, to avoid having _Jv_InitClass // inserted all over the place. @@ -934,7 +931,11 @@ _Jv_ClassReader::handleClassBegin // to include references to this class. def->state = JV_STATE_PRELOADING; - _Jv_RegisterClass (def); + + { + JvSynchronize sync (&java::lang::Class::class$); + _Jv_RegisterClass (def); + } if (super_class != 0) { diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h index 27a1c6f3223..bb54c8b58d8 100644 --- a/libjava/include/jvm.h +++ b/libjava/include/jvm.h @@ -124,6 +124,15 @@ extern jboolean _Jv_equaln (_Jv_Utf8Const *, jstring, jint); // FIXME: remove this define. #define StringClass java::lang::String::class$ +namespace gcj +{ + /* Some constants used during lookup of special class methods. */ + extern _Jv_Utf8Const *void_signature; /* "()V" */ + extern _Jv_Utf8Const *clinit_name; /* "" */ + extern _Jv_Utf8Const *init_name; /* "" */ + extern _Jv_Utf8Const *finit_name; /* "finit$", */ +}; + /* Type of pointer used as finalizer. */ typedef void _Jv_FinalizerFunc (jobject); diff --git a/libjava/interpret.cc b/libjava/interpret.cc index 42c342a3281..5bfe4e7fbba 100644 --- a/libjava/interpret.cc +++ b/libjava/interpret.cc @@ -37,7 +37,7 @@ details. */ #include -static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("", 6); +using namespace gcj; static void throw_internal_error (char *msg) __attribute__ ((__noreturn__)); diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc index 7b6b8b554a8..2ca7960466d 100644 --- a/libjava/java/lang/natClass.cc +++ b/libjava/java/lang/natClass.cc @@ -60,17 +60,10 @@ details. */ #define FieldClass java::lang::reflect::Field::class$ #define ConstructorClass java::lang::reflect::Constructor::class$ -// Some constants we use to look up the class initializer. -static _Jv_Utf8Const *void_signature = _Jv_makeUtf8Const ("()V", 3); -static _Jv_Utf8Const *clinit_name = _Jv_makeUtf8Const ("", 8); -static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("", 6); -static _Jv_Utf8Const *finit_name = _Jv_makeUtf8Const ("finit$", 6); -// The legacy `$finit$' method name, which still needs to be -// recognized as equivalent to the now prefered `finit$' name. -static _Jv_Utf8Const *finit_leg_name = _Jv_makeUtf8Const ("$finit$", 7); - +using namespace gcj; + jclass java::lang::Class::forName (jstring className, jboolean initialize, java::lang::ClassLoader *loader) @@ -341,9 +334,7 @@ java::lang::Class::getDeclaredMethods (void) if (method->name == NULL || _Jv_equalUtf8Consts (method->name, clinit_name) || _Jv_equalUtf8Consts (method->name, init_name) - || _Jv_equalUtf8Consts (method->name, finit_name) - // Backward compatibility hack: match the legacy `$finit$' name - || _Jv_equalUtf8Consts (method->name, finit_leg_name)) + || _Jv_equalUtf8Consts (method->name, finit_name)) continue; numMethods++; } @@ -357,9 +348,7 @@ java::lang::Class::getDeclaredMethods (void) if (method->name == NULL || _Jv_equalUtf8Consts (method->name, clinit_name) || _Jv_equalUtf8Consts (method->name, init_name) - || _Jv_equalUtf8Consts (method->name, finit_name) - // Backward compatibility hack: match the legacy `$finit$' name - || _Jv_equalUtf8Consts (method->name, finit_leg_name)) + || _Jv_equalUtf8Consts (method->name, finit_name)) continue; java::lang::reflect::Method* rmethod = new java::lang::reflect::Method (); @@ -522,9 +511,7 @@ java::lang::Class::_getMethods (JArray *result, if (method->name == NULL || _Jv_equalUtf8Consts (method->name, clinit_name) || _Jv_equalUtf8Consts (method->name, init_name) - || _Jv_equalUtf8Consts (method->name, finit_name) - // Backward compatibility hack: match the legacy `$finit$' name - || _Jv_equalUtf8Consts (method->name, finit_leg_name)) + || _Jv_equalUtf8Consts (method->name, finit_name)) continue; // Only want public methods. if (! java::lang::reflect::Modifier::isPublic (method->accflags)) diff --git a/libjava/java/lang/natClassLoader.cc b/libjava/java/lang/natClassLoader.cc index 004b9d14b73..3c2679bd8b4 100644 --- a/libjava/java/lang/natClassLoader.cc +++ b/libjava/java/lang/natClassLoader.cc @@ -175,7 +175,6 @@ java::lang::ClassLoader::markClassErrorState0 (java::lang::Class *klass) klass->notifyAll (); } - // This is the findClass() implementation for the System classloader. It is // the only native method in VMClassLoader, so we define it here. jclass @@ -419,24 +418,13 @@ _Jv_RegisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader) } // This function is called many times during startup, before main() is -// run. We do our runtime initialization here the very first time we -// are called. At that point in time we know for certain we are -// running single-threaded, so we don't need to lock when modifying -// `init'. CLASSES is NULL-terminated. +// run. At that point in time we know for certain we are running +// single-threaded, so we don't need to lock when adding classes to the +// class chain. At all other times, the caller should synchronize on +// Class::class$. void _Jv_RegisterClasses (jclass *classes) { - static bool init = false; - - if (! init) - { - init = true; - _Jv_InitThreads (); - _Jv_InitGC (); - _Jv_InitializeSyncMutex (); - } - - JvSynchronize sync (&ClassClass); for (; *classes; ++classes) { jclass klass = *classes; diff --git a/libjava/java/lang/natRuntime.cc b/libjava/java/lang/natRuntime.cc index 0551ba620a6..18bc3cb9bf9 100644 --- a/libjava/java/lang/natRuntime.cc +++ b/libjava/java/lang/natRuntime.cc @@ -138,8 +138,15 @@ java::lang::Runtime::_load (jstring path, jboolean do_search) #endif jsize total = JvGetStringUTFRegion (path, 0, path->length(), &buf[offset]); buf[offset + total] = '\0'; + lt_dlhandle h; // FIXME: make sure path is absolute. - lt_dlhandle h = do_search ? lt_dlopenext (buf) : lt_dlopen (buf); + { + // Synchronize on java.lang.Class. This is to protect the class chain from + // concurrent modification by class registration calls which may be run + // during the dlopen(). + JvSynchronize sync (&java::lang::Class::class$); + h = do_search ? lt_dlopenext (buf) : lt_dlopen (buf); + } if (h == NULL) { const char *msg = lt_dlerror (); diff --git a/libjava/jni.cc b/libjava/jni.cc index 8f4e4f14e22..8e586fa38f1 100644 --- a/libjava/jni.cc +++ b/libjava/jni.cc @@ -48,6 +48,8 @@ details. */ #include #include +using namespace gcj; + // This enum is used to select different template instantiations in // the invocation code. enum invocation_type @@ -1502,9 +1504,6 @@ _Jv_JNI_ToReflectedMethod (JNIEnv *env, jclass klass, jmethodID id, { using namespace java::lang::reflect; - // FIXME. - static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("", 6); - jobject result = NULL; try diff --git a/libjava/prims.cc b/libjava/prims.cc index 7205e1f6bfc..7b3dd6c6a00 100644 --- a/libjava/prims.cc +++ b/libjava/prims.cc @@ -574,21 +574,39 @@ _Jv_NewMultiArray (jclass array_type, jint dimensions, ...) -#define DECLARE_PRIM_TYPE(NAME, SIG, LEN) \ - _Jv_ArrayVTable _Jv_##NAME##VTable; \ - java::lang::Class _Jv_##NAME##Class ((jobject) #NAME, \ - (jbyte) SIG, (jint) LEN, \ - (jobject) &_Jv_##NAME##VTable); - -DECLARE_PRIM_TYPE(byte, 'B', 1); -DECLARE_PRIM_TYPE(short, 'S', 2); -DECLARE_PRIM_TYPE(int, 'I', 4); -DECLARE_PRIM_TYPE(long, 'J', 8); -DECLARE_PRIM_TYPE(boolean, 'Z', 1); -DECLARE_PRIM_TYPE(char, 'C', 2); -DECLARE_PRIM_TYPE(float, 'F', 4); -DECLARE_PRIM_TYPE(double, 'D', 8); -DECLARE_PRIM_TYPE(void, 'V', 0); +#define DECLARE_PRIM_TYPE(NAME) \ + _Jv_ArrayVTable _Jv_##NAME##VTable; \ + java::lang::Class _Jv_##NAME##Class; + +DECLARE_PRIM_TYPE(byte); +DECLARE_PRIM_TYPE(short); +DECLARE_PRIM_TYPE(int); +DECLARE_PRIM_TYPE(long); +DECLARE_PRIM_TYPE(boolean); +DECLARE_PRIM_TYPE(char); +DECLARE_PRIM_TYPE(float); +DECLARE_PRIM_TYPE(double); +DECLARE_PRIM_TYPE(void); + +void +_Jv_InitPrimClass (jclass cl, char *cname, char sig, int len, + _Jv_ArrayVTable *array_vtable) +{ + using namespace java::lang::reflect; + + // We must initialize every field of the class. We do this in the + // same order they are declared in Class.h, except for fields that + // are initialized to NULL. + cl->name = _Jv_makeUtf8Const ((char *) cname, -1); + cl->accflags = Modifier::PUBLIC | Modifier::FINAL | Modifier::ABSTRACT; + cl->method_count = sig; + cl->size_in_bytes = len; + cl->vtable = JV_PRIMITIVE_VTABLE; + cl->state = JV_STATE_DONE; + cl->depth = -1; + if (sig != 'V') + _Jv_NewArrayClass (cl, NULL, (_Jv_VTable *) array_vtable); +} jclass _Jv_FindClassFromSignature (char *sig, java::lang::ClassLoader *loader) @@ -848,11 +866,49 @@ process_gcj_properties () } #endif // DISABLE_GETENV_PROPERTIES +namespace gcj +{ + _Jv_Utf8Const *void_signature; + _Jv_Utf8Const *clinit_name; + _Jv_Utf8Const *init_name; + _Jv_Utf8Const *finit_name; +} + jint _Jv_CreateJavaVM (void* /*vm_args*/) { + using namespace gcj; + + static bool init = false; + + if (init) + return -1; + + init = true; + PROCESS_GCJ_PROPERTIES; + _Jv_InitThreads (); + _Jv_InitGC (); + _Jv_InitializeSyncMutex (); + + /* Initialize Utf8 constants declared in jvm.h. */ + void_signature = _Jv_makeUtf8Const ("()V", 3); + clinit_name = _Jv_makeUtf8Const ("", 8); + init_name = _Jv_makeUtf8Const ("", 6); + finit_name = _Jv_makeUtf8Const ("finit$", 6); + + /* Initialize built-in classes to represent primitive TYPEs. */ + _Jv_InitPrimClass (&_Jv_byteClass, "byte", 'B', 1, &_Jv_byteVTable); + _Jv_InitPrimClass (&_Jv_shortClass, "short", 'S', 2, &_Jv_shortVTable); + _Jv_InitPrimClass (&_Jv_intClass, "int", 'I', 4, &_Jv_intVTable); + _Jv_InitPrimClass (&_Jv_longClass, "long", 'J', 8, &_Jv_longVTable); + _Jv_InitPrimClass (&_Jv_booleanClass, "boolean", 'Z', 1, &_Jv_booleanVTable); + _Jv_InitPrimClass (&_Jv_charClass, "char", 'C', 2, &_Jv_charVTable); + _Jv_InitPrimClass (&_Jv_floatClass, "float", 'F', 4, &_Jv_floatVTable); + _Jv_InitPrimClass (&_Jv_doubleClass, "double", 'D', 8, &_Jv_doubleVTable); + _Jv_InitPrimClass (&_Jv_voidClass, "void", 'V', 0, &_Jv_voidVTable); + // Turn stack trace generation off while creating exception objects. _Jv_InitClass (&java::lang::Throwable::class$); java::lang::Throwable::trace_enabled = 0; diff --git a/libjava/resolve.cc b/libjava/resolve.cc index df48c269c67..ea0faadf221 100644 --- a/libjava/resolve.cc +++ b/libjava/resolve.cc @@ -32,6 +32,8 @@ details. */ #include #include +using namespace gcj; + void _Jv_ResolveField (_Jv_Field *field, java::lang::ClassLoader *loader) { @@ -65,9 +67,6 @@ _Jv_BuildResolvedMethod (_Jv_Method*, jint); -// We need to know the name of a constructor. -static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("", 6); - static void throw_incompatible_class_change_error (jstring msg) { throw new java::lang::IncompatibleClassChangeError (msg); -- 2.30.2