diff options
author | Anthony Green <green@gcc.gnu.org> | 1999-08-08 14:06:23 +0000 |
---|---|---|
committer | Anthony Green <green@gcc.gnu.org> | 1999-08-08 14:06:23 +0000 |
commit | 58eb6e7cef1cea515f8da18d24341a4aa53ccb70 (patch) | |
tree | 277498eeeff558237a9cd88b0ea8b3788b31d645 /libjava/java/lang/natClass.cc | |
parent | 63e5e3e0dbb7207e95c0437499b980a304665589 (diff) | |
download | gcc-58eb6e7cef1cea515f8da18d24341a4aa53ccb70.zip gcc-58eb6e7cef1cea515f8da18d24341a4aa53ccb70.tar.gz gcc-58eb6e7cef1cea515f8da18d24341a4aa53ccb70.tar.bz2 |
[multiple changes]
1999-08-09 Anthony Green <green@cygnus.com>
* gij.cc: New file.
* include/config.h.in: Rebuilt.
* acconfig.h: Add INTERPRETER.
* configure: Rebuilt.
* Makefile.in: Rebuilt.
* Makefile.am (libffi_files): Identify the libffi object files for
inclusion in libgcj.
(LIBFFIINCS): Define.
* interpret.cc (gnu::gcj::runtime::MethodInvocation::continue1):
Dummy definition for configurations without an interpreter.
* java/net/natPlainSocketImpl.cc (getOption): Disamiguate call to
java::lang::Boolean constructor.
* include/java-interp.h: Always include java-cpool.h.
* java/lang/natClassLoader.cc (getVMClassLoader0): Always return 0
when INTERPRETER not defined.
* java/lang/Class.h (finalize): Define.
* gnu/gcj/util/path/DirectoryPathEntry.java (getURL): Catch
IOException from File.getCanonicalPath.
(getStream): Likewise.
* NEWS: More news.
* THANKS: More thanks.
1999-08-09 Kresten Krab Thorup <krab@gnu.org>
* resolve.cc (get_ffi_type_from_signature): Generate uint16 for
jchar type.
(_Jv_PrepareClass): Allow non-abstract classes to
have abstract subclasses.
(_Jv_ResolvePoolEntry): Revert subclass check for protected
fields and methods.
* interpret.cc (continue1/perform_invoke): Don't sign extend
uint16 return val.
(continue1/lshl,lshr): Push long, not int.
(continue1/ulshr): Use UINT64, not long long.
* defineclass.cc (handleFieldsEnd): Handle case when all fields
are static.
* java/lang/natClass.cc (forName): Add call to _Jv_InitClass.
* java/lang/FirstThread.java (run): Add top-level exception
handler.
(run0): Renamed from run.
1999-08-08 Kresten Krab Thorup <krab@gnu.org>
* configure.in (--with-interpreter): Added.
* include/config.h.in (INTERPRETER): Added.
* java/lang/ClassLoader.java: File replaced.
* java/lang/VMClassLoader.java: New file.
* java/lang/natClassLoader.cc: New file.
* gnu/gcj/runtime/MethodInvocation.java: New file.
* gnu/gcj/util/path/SearchPath.java: New file.
* gnu/gcj/util/path/PathEntry.java: New file.
* gnu/gcj/util/path/DirectoryPathEntry.java: New file.
* gnu/gcj/util/path/ZipPathEntry.java: New file.
* gnu/gcj/util/path/URLPathEntry.java: New file.
* gnu/gcj/util/path/CacheEntry.java: New file.
* include/java-interp.h: New file.
* include/java-cpool.h: New file.
* include/java-insns.h: New file.
* defineclass.cc: New file.
* interpret.cc: New file.
* resolve.cc: New file.
* java/lang/natClass.cc (loaded_classes, _Jv_RegisterClass,
_Jv_RegisterClasses, _Jv_FindClassInCache, _Jv_FindClass,
_Jv_NewClass, _Jv_FindArrayClass): Moved to natClassLoader.cc.
(finalize): New.
(STATE_NOTHING, STATE_RESOLVED, STATE_IN_PROGRESS, STATE_DONE,
STATE_ERROR): Moved to java/lang/Class.h and renamed with JV_
prefix.
(initializeClass): Use new JV_ prefixed names. Also, call
ClassLoader::resolveClass instead of _Jv_ResolveClass.
* java/lang/Class.h (JV_STATE_PRELOADING, JV_STATE_LOADING,
JV_STATE_LOADED, JV_STATE_COMPILED, JV_STATE_PREPARED,
JV_STATE_LINKED): New.
(_Jv_WaitForState, _Jv_RegisterInitiatingLoader,
_Jv_UnregisterClass, _Jv_InternClassStrings): New friends.
(_Jv_IsInterpretedClass, _Jv_InitField, _Jv_LookupDeclaredMethod,
_Jv_DetermineVTableIndex, _Jv_ResolvePoolEntry, _Jv_PrepareClass,
_Jv_ClassReader, _Jv_InterpClass, _Jv_InterpMethod,
_Jv_InterpMethodInvocation): New friends for interpreter.
(finalize): New.
(CONSTANT_Class, CONSTANT_String, etc.): Moved to
include/java-cpool.h and renamed with JV_ prefix.
* include/jvm.h (_Jv_makeUtf8Const, _Jv_makeUtf8TypeConst): New
decls.
(_Jv_UnregisterClass): New decl.
* java/lang/natClassLoader.cc (_Jv_FindArrayClass): Added
class loader argument.
(_Jv_FindClass): Use class loader.
* prims.cc (_Jv_makeUtf8Const): New function.
(_Jv_NewObjectArray): Change use of _Jv_FindArrayClass.
(_Jv_NewPrimArray): Ditto.
(_Jv_FindClassFromSignature): Ditto.
* java/lang/reflect/natArray.cc (newInstance): Ditto.
* java/lang/reflect/natMethod.cc (getType): Ditto.
* include/java-field.h (_Jv_Field::isRef): Make robust for
non-resolved contexts.
* boehm.cc (_Jv_MarkObj): Mark interpreter-related fields.
Also, don't mark class->next field.
* java/lang/VirtualMachineError.java: Added FIXME note.
* configure.in (INTERPSPEC): New spec.
* libgcj.spec.in: Added INTERPSPEC.
* Makefile.am: Added gcjh friends for java/lang/VMClassLoader and
gnu/gcj/runtime/MethodInvocation.
(libgcj_la_SOURCES): Added resolve.cc defineclass.cc interpret.cc.
(ordinary_java_source_files): Added above mentioned java classes.
* configure: Rebuilt.
* Makefile.in: Rebuilt.
From-SVN: r28597
Diffstat (limited to 'libjava/java/lang/natClass.cc')
-rw-r--r-- | libjava/java/lang/natClass.cc | 386 |
1 files changed, 109 insertions, 277 deletions
diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc index 1768df5..367f14a 100644 --- a/libjava/java/lang/natClass.cc +++ b/libjava/java/lang/natClass.cc @@ -39,6 +39,8 @@ details. */ #include <java/lang/System.h> #include <java/lang/SecurityManager.h> +#include <java-cpool.h> + #define CloneableClass _CL_Q34java4lang9Cloneable @@ -59,28 +61,6 @@ static _Jv_Utf8Const *void_signature = _Jv_makeUtf8Const ("()V", 3); static _Jv_Utf8Const *clinit_name = _Jv_makeUtf8Const ("<clinit>", 8); static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6); -// These are the possible values for the `state' field. They more or -// less follow the section numbers in the Java Language Spec. Right -// now we don't bother to represent other interesting states, e.g. the -// states a class might inhabit before it is prepared. Note that -// ordering is important here; in particular `resolved' must come -// between `nothing' and the other states. -#define STATE_NOTHING 0 -#define STATE_RESOLVED 1 -#define STATE_IN_PROGRESS 6 -#define STATE_DONE 9 -#define STATE_ERROR 10 - -// Size of local hash table. -#define HASH_LEN 256 - -// Hash function for Utf8Consts. -#define HASH_UTF(Utf) (((Utf)->hash) % HASH_LEN) - -// This is the table we use to keep track of loaded classes. See Spec -// section 12.2. -static jclass loaded_classes[HASH_LEN]; - jclass @@ -111,6 +91,9 @@ java::lang::Class::forName (jstring className) #endif if (! klass) JvThrow (new java::lang::ClassNotFoundException (className)); + + _Jv_InitClass (klass); + return klass; } @@ -380,33 +363,13 @@ java::lang::Class::newInstance (void) return r; } -// Initialize the constants. void -java::lang::Class::resolveConstants (void) +java::lang::Class::finalize (void) { - for (int i = 0; i < constants.size; ++i) - { - if (constants.tags[i] == CONSTANT_String) - { - jstring str; - str = _Jv_NewStringUtf8Const ((_Jv_Utf8Const *) constants.data[i]); - constants.data[i] = (void *) str; - constants.tags[i] = CONSTANT_ResolvedString; - } - else if (constants.tags[i] == CONSTANT_Class) - { - _Jv_Utf8Const *name = (_Jv_Utf8Const *) constants.data[i]; - jclass klass = _Jv_FindClassFromSignature (name->data, loader); - if (! klass) - { - jstring str = _Jv_NewStringUtf8Const (name); - JvThrow (new java::lang::ClassNotFoundException (str)); - } - - constants.data[i] = (void *) klass; - constants.tags[i] = CONSTANT_ResolvedClass; - } - } +#ifdef INTERPRETER + JvAssert (_Jv_IsInterpretedClass (this)); + _Jv_UnregisterClass (this); +#endif } // FIXME. @@ -424,38 +387,52 @@ void java::lang::Class::initializeClass (void) { // Short-circuit to avoid needless locking. - if (state == STATE_DONE) + if (state == JV_STATE_DONE) return; - // Step 1. - _Jv_MonitorEnter (this); + // do this before we enter the monitor below, since this can cause + // exceptions. Here we assume, that reading "state" is an atomic + // operation, I pressume that is true? --Kresten + if (state < JV_STATE_LINKED) + { +#ifdef INTERPRETER + if (_Jv_IsInterpretedClass (this)) + { + java::lang::ClassLoader::resolveClass (this); - // FIXME: This should actually be handled by calling into the class - // loader. For now we put it here. - if (state < STATE_RESOLVED) + // Step 1. + _Jv_MonitorEnter (this); + } + else +#endif + { + // Step 1. + _Jv_MonitorEnter (this); + _Jv_InternClassStrings (this); + } + } + else { - // We set the state before calling resolveConstants to avoid - // infinite recursion when processing String or Class. - state = STATE_RESOLVED; - resolveConstants (); + // Step 1. + _Jv_MonitorEnter (this); } // Step 2. java::lang::Thread *self = java::lang::Thread::currentThread(); // FIXME: `self' can be null at startup. Hence this nasty trick. self = (java::lang::Thread *) ((long) self | 1); - while (state == STATE_IN_PROGRESS && thread && thread != self) + while (state == JV_STATE_IN_PROGRESS && thread && thread != self) wait (); // Steps 3 & 4. - if (state == STATE_DONE || state == STATE_IN_PROGRESS || thread == self) + if (state == JV_STATE_DONE || state == JV_STATE_IN_PROGRESS || thread == self) { _Jv_MonitorExit (this); return; } // Step 5. - if (state == STATE_ERROR) + if (state == JV_STATE_ERROR) { _Jv_MonitorExit (this); JvThrow (new java::lang::NoClassDefFoundError); @@ -463,7 +440,7 @@ java::lang::Class::initializeClass (void) // Step 6. thread = self; - state = STATE_IN_PROGRESS; + state = JV_STATE_IN_PROGRESS; _Jv_MonitorExit (this); // Step 7. @@ -477,7 +454,7 @@ java::lang::Class::initializeClass (void) { // Caught an exception. _Jv_MonitorEnter (this); - state = STATE_ERROR; + state = JV_STATE_ERROR; notify (); _Jv_MonitorExit (this); JvThrow (except); @@ -492,7 +469,7 @@ java::lang::Class::initializeClass (void) if (! except) { _Jv_MonitorEnter (this); - state = STATE_DONE; + state = JV_STATE_DONE; } else { @@ -503,7 +480,7 @@ java::lang::Class::initializeClass (void) except = hackTrampoline(2, except); } _Jv_MonitorEnter (this); - state = STATE_ERROR; + state = JV_STATE_ERROR; } notify (); _Jv_MonitorExit (this); @@ -530,6 +507,64 @@ _Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name, return NULL; } +#define MCACHE_SIZE 1013 + +struct _Jv_mcache { + jclass klass; + _Jv_Method *method; +}; + +static _Jv_mcache method_cache[MCACHE_SIZE]; +static int method_cache_count; + +static void* +_Jv_FindMethodInCache (jclass klass, + _Jv_Utf8Const *name, + _Jv_Utf8Const *signature) +{ + for (int index = name->hash % MCACHE_SIZE; + method_cache[index].klass != NULL; + index = (index+1) % MCACHE_SIZE) + { + _Jv_mcache *mc = (method_cache+index); + _Jv_Method *m = mc->method; + + if (mc->klass == klass + && m != NULL // thread safe check + && _Jv_equalUtf8Consts (m->name, name) + && _Jv_equalUtf8Consts (m->signature, signature)) + { + return mc->method->ncode; + } + } + return NULL; +} + +static void +_Jv_AddMethodToCache (jclass klass, + _Jv_Method *method) +{ + _Jv_MonitorEnter (&ClassClass); + + if (method_cache_count > MCACHE_SIZE*2/3) + { + for (int i = 0; i < MCACHE_SIZE; i++) + method_cache[i].klass = 0; + } + + for (int index = method->name->hash % MCACHE_SIZE; + method_cache[index].klass != NULL; + index = (index+1) % MCACHE_SIZE) + { + method_cache[index].method = method; + method_cache[index].klass = klass; + } + + method_cache_count += 1; + + _Jv_MonitorExit (&ClassClass); +} + void * _Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name, _Jv_Utf8Const *signature) @@ -539,6 +574,14 @@ _Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name, // call a method of a class until the class is linked. But this // captures the general idea. // klass->getClassLoader()->resolveClass(klass); + // + // KKT: This is unnessecary, exactly for the reason you present: + // _Jv_LookupInterfaceMethod is only called on object instances, and + // such have already been initialized (which includes resolving). + + void *ncode = _Jv_FindMethodInCache (klass, name, signature); + if (ncode != 0) + return ncode; for (; klass; klass = klass->getSuperclass()) { @@ -553,6 +596,8 @@ _Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name, if (! java::lang::reflect::Modifier::isPublic(meth->accflags)) JvThrow (new java::lang::IllegalAccessError); + _Jv_AddMethodToCache (klass, meth); + return meth->ncode; } JvThrow (new java::lang::IncompatibleClassChangeError); @@ -565,219 +610,6 @@ _Jv_InitClass (jclass klass) klass->initializeClass(); } -// 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. -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; - jint hash = HASH_UTF (klass->name); - klass->next = loaded_classes[hash]; - loaded_classes[hash] = klass; - } -} - -void -_Jv_RegisterClass (jclass klass) -{ - jclass classes[2]; - classes[0] = klass; - classes[1] = NULL; - _Jv_RegisterClasses (classes); -} - -jclass -_Jv_FindClassInCache (_Jv_Utf8Const *name, java::lang::ClassLoader *loader) -{ - JvSynchronize sync (&ClassClass); - jint hash = HASH_UTF (name); - jclass klass; - for (klass = loaded_classes[hash]; klass; klass = klass->next) - { - if (loader == klass->loader && _Jv_equalUtf8Consts (name, klass->name)) - break; - } - return klass; -} - -#if 0 -jclass -_Jv_FindClassInCache (jstring name, java::lang::ClassLoader *loader) -{ - JvSynchronize sync (&ClassClass); - jint hash = name->hashCode(); - jclass klass = loaded_classes[(_Jv_ushort) hash % HASH_LEN]; - for ( ; klass; klass = klass->next) - { - if (loader == klass->loader - && _Jv_equalUtf8Consts (klass->name, name, hash)) - break; - } - return klass; -} -#endif - -jclass -_Jv_FindClass (_Jv_Utf8Const* name, java::lang::ClassLoader *loader) -{ - jclass klass = _Jv_FindClassInCache (name, loader); - if (loader && ! klass) - { - klass = loader->loadClass(_Jv_NewStringUtf8Const (name)); - if (klass) - _Jv_RegisterClass (klass); - } - return klass; -} - -#if 0 -jclass -_Jv_FindClass (jstring name, java::lang::ClassLoader *loader) -{ - jclass klass = _Jv_FindClassInCache (name, loader); - if (loader && ! klass) - { - klass = loader->loadClass(name); - if (klass) - _Jv_RegisterClass (klass); - } - return klass; -} -#endif - -jclass -_Jv_NewClass (_Jv_Utf8Const *name, jclass superclass, - java::lang::ClassLoader *loader) -{ - jclass ret = (jclass) JvAllocObject (&ClassClass); - - ret->next = NULL; - ret->name = name; - ret->accflags = 0; - ret->superclass = superclass; - ret->constants.size = 0; - ret->constants.tags = NULL; - ret->constants.data = NULL; - ret->methods = NULL; - ret->method_count = 0; - ret->vtable_method_count = 0; - ret->fields = NULL; - ret->size_in_bytes = 0; - ret->field_count = 0; - ret->static_field_count = 0; - ret->vtable = NULL; - ret->interfaces = NULL; - ret->loader = loader; - ret->interface_count = 0; - ret->state = 0; - ret->thread = NULL; - - _Jv_RegisterClass (ret); - - return ret; -} - -jclass -_Jv_FindArrayClass (jclass element) -{ - _Jv_Utf8Const *array_name; - int len; - if (element->isPrimitive()) - { - // For primitive types the array is cached in the class. - jclass ret = (jclass) element->methods; - if (ret) - return ret; - len = 3; - } - else - len = element->name->length + 5; - - { - char signature[len]; - int index = 0; - signature[index++] = '['; - // Compute name of array class to see if we've already cached it. - if (element->isPrimitive()) - { - signature[index++] = (char) element->method_count; - } - else - { - size_t length = element->name->length; - const char *const name = element->name->data; - if (name[0] != '[') - signature[index++] = 'L'; - memcpy (&signature[index], name, length); - index += length; - if (name[0] != '[') - signature[index++] = ';'; - } - array_name = _Jv_makeUtf8Const (signature, index); - } - - jclass array_class = _Jv_FindClassInCache (array_name, element->loader); - - if (! array_class) - { - // Create new array class. - array_class = _Jv_NewClass (array_name, &ObjectClass, element->loader); - - // Note that `vtable_method_count' doesn't include the initial - // NULL slot. - int dm_count = ObjectClass.vtable_method_count + 1; - - // Create a new vtable by copying Object's vtable (except the - // class pointer, of course). Note that we allocate this as - // unscanned memory -- the vtables are handled specially by the - // GC. - int size = (sizeof (_Jv_VTable) + - ((dm_count - 1) * sizeof (void *))); - _Jv_VTable *vtable = (_Jv_VTable *) _Jv_AllocBytes (size); - vtable->clas = array_class; - memcpy (vtable->method, ObjectClass.vtable->method, - dm_count * sizeof (void *)); - array_class->vtable = vtable; - array_class->vtable_method_count = ObjectClass.vtable_method_count; - - // Stash the pointer to the element type. - array_class->methods = (_Jv_Method *) element; - - // Register our interfaces. - // FIXME: for JDK 1.2 we need Serializable. - static jclass interfaces[] = { &CloneableClass }; - array_class->interfaces = interfaces; - array_class->interface_count = 1; - - // FIXME: initialize other Class instance variables, - // e.g. `fields'. - - array_class->state = STATE_DONE; - } - - // For primitive types, point back at this array. - if (element->isPrimitive()) - element->methods = (_Jv_Method *) array_class; - - return array_class; -} - jboolean _Jv_IsInstanceOf(jobject obj, jclass cl) { |