diff options
Diffstat (limited to 'libjava/java/lang/natClass.cc')
-rw-r--r-- | libjava/java/lang/natClass.cc | 2095 |
1 files changed, 0 insertions, 2095 deletions
diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc deleted file mode 100644 index 00766d0..0000000 --- a/libjava/java/lang/natClass.cc +++ /dev/null @@ -1,2095 +0,0 @@ -// natClass.cc - Implementation of java.lang.Class native methods. - -/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2010 Free Software Foundation - - This file is part of libgcj. - -This software is copyrighted work licensed under the terms of the -Libgcj License. Please consult the file "LIBGCJ_LICENSE" for -details. */ - -#include <config.h> - -#include <limits.h> -#include <string.h> -#include <stddef.h> -#include <stdio.h> - -#pragma implementation "Class.h" - -#include <gcj/cni.h> -#include <jvm.h> -#include <java-threads.h> - -#include <java/lang/Class.h> -#include <java/lang/ClassLoader.h> -#include <java/lang/String.h> -#include <java/lang/reflect/Modifier.h> -#include <java/lang/reflect/Member.h> -#include <java/lang/reflect/Method.h> -#include <java/lang/reflect/Field.h> -#include <java/lang/reflect/Proxy.h> -#include <java/lang/reflect/Constructor.h> -#include <java/lang/AbstractMethodError.h> -#include <java/lang/ArrayStoreException.h> -#include <java/lang/ClassCastException.h> -#include <java/lang/ClassNotFoundException.h> -#include <java/lang/ExceptionInInitializerError.h> -#include <java/lang/IllegalAccessException.h> -#include <java/lang/IllegalAccessError.h> -#include <java/lang/IllegalArgumentException.h> -#include <java/lang/IncompatibleClassChangeError.h> -#include <java/lang/NoSuchFieldError.h> -#include <java/lang/ArrayIndexOutOfBoundsException.h> -#include <java/lang/InstantiationException.h> -#include <java/lang/NoClassDefFoundError.h> -#include <java/lang/NoSuchFieldException.h> -#include <java/lang/NoSuchMethodError.h> -#include <java/lang/NoSuchMethodException.h> -#include <java/lang/Thread.h> -#include <java/lang/NullPointerException.h> -#include <java/lang/RuntimePermission.h> -#include <java/lang/System.h> -#include <java/lang/SecurityException.h> -#include <java/lang/SecurityManager.h> -#include <java/lang/StringBuffer.h> -#include <java/lang/VMClassLoader.h> -#include <gcj/method.h> -#include <gnu/gcj/RawData.h> -#include <java/lang/VerifyError.h> -#include <java/lang/InternalError.h> -#include <java/lang/TypeNotPresentException.h> -#include <java/lang/Byte.h> -#include <java/lang/Short.h> -#include <java/lang/Integer.h> -#include <java/lang/Float.h> -#include <java/lang/Double.h> -#include <java/lang/Long.h> -#include <java/lang/Character.h> -#include <java/lang/Boolean.h> -#include <java/lang/annotation/Annotation.h> -#include <java/util/HashMap.h> -#include <java/util/Map.h> -#include <sun/reflect/annotation/AnnotationInvocationHandler.h> -#include <java/lang/Enum.h> - -#include <java-cpool.h> -#include <java-interp.h> -#include <java-assert.h> -#include <java-stack.h> -#include <execution.h> - - - -using namespace gcj; - -jclass -java::lang::Class::forName (jstring className, jboolean initialize, - java::lang::ClassLoader *loader) -{ - if (! className) - throw new java::lang::NullPointerException; - - jsize length = _Jv_GetStringUTFLength (className); - char buffer[length]; - _Jv_GetStringUTFRegion (className, 0, className->length(), buffer); - - _Jv_Utf8Const *name = _Jv_makeUtf8Const (buffer, length); - - if (! _Jv_VerifyClassName (name)) - throw new java::lang::ClassNotFoundException (className); - - jclass klass = (buffer[0] == '[' - ? _Jv_FindClassFromSignature (name->chars(), loader) - : _Jv_FindClass (name, loader)); - - if (klass == NULL) - throw new java::lang::ClassNotFoundException (className); - - if (initialize) - _Jv_InitClass (klass); - - return klass; -} - -jclass -java::lang::Class::forName (jstring className) -{ - java::lang::ClassLoader *loader = NULL; - - jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$); - if (caller) - loader = caller->getClassLoaderInternal(); - - return forName (className, true, loader); -} - -java::lang::ClassLoader * -java::lang::Class::getClassLoader (void) -{ - java::lang::SecurityManager *s = java::lang::System::getSecurityManager(); - if (s != NULL) - { - jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$); - 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 - // security check. - if (caller_loader != NULL && ! caller_loader->isAncestorOf(loader)) - s->checkPermission (new RuntimePermission (JvNewStringLatin1 ("getClassLoader"))); - } - - return loader; -} - -java::lang::reflect::Constructor * -java::lang::Class::getConstructor (JArray<jclass> *param_types) -{ - memberAccessCheck(java::lang::reflect::Member::PUBLIC); - - jstring partial_sig = getSignature (param_types, true); - jint hash = partial_sig->hashCode (); - - int i = isPrimitive () ? 0 : method_count; - while (--i >= 0) - { - if (_Jv_equalUtf8Consts (methods[i].name, init_name) - && _Jv_equal (methods[i].signature, partial_sig, hash)) - { - // Found it. For getConstructor, the constructor must be - // public. - using namespace java::lang::reflect; - if (! Modifier::isPublic(methods[i].accflags)) - break; - Constructor *cons = new Constructor (); - cons->offset = (char *) (&methods[i]) - (char *) methods; - cons->declaringClass = this; - return cons; - } - } - throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name)); -} - -JArray<java::lang::reflect::Constructor *> * -java::lang::Class::getDeclaredConstructors (jboolean publicOnly) -{ - int numConstructors = 0; - int max = isPrimitive () ? 0 : method_count; - int i; - for (i = max; --i >= 0; ) - { - _Jv_Method *method = &methods[i]; - if (method->name == NULL - || ! _Jv_equalUtf8Consts (method->name, init_name)) - continue; - if (publicOnly - && ! java::lang::reflect::Modifier::isPublic(method->accflags)) - continue; - numConstructors++; - } - JArray<java::lang::reflect::Constructor *> *result - = (JArray<java::lang::reflect::Constructor *> *) - JvNewObjectArray (numConstructors, - &java::lang::reflect::Constructor::class$, - NULL); - java::lang::reflect::Constructor** cptr = elements (result); - for (i = 0; i < max; i++) - { - _Jv_Method *method = &methods[i]; - if (method->name == NULL - || ! _Jv_equalUtf8Consts (method->name, init_name)) - continue; - if (publicOnly - && ! java::lang::reflect::Modifier::isPublic(method->accflags)) - continue; - java::lang::reflect::Constructor *cons - = new java::lang::reflect::Constructor (); - cons->offset = (char *) method - (char *) methods; - cons->declaringClass = this; - *cptr++ = cons; - } - return result; -} - -java::lang::reflect::Constructor * -java::lang::Class::getDeclaredConstructor (JArray<jclass> *param_types) -{ - memberAccessCheck(java::lang::reflect::Member::DECLARED); - - jstring partial_sig = getSignature (param_types, true); - jint hash = partial_sig->hashCode (); - - int i = isPrimitive () ? 0 : method_count; - while (--i >= 0) - { - if (_Jv_equalUtf8Consts (methods[i].name, init_name) - && _Jv_equal (methods[i].signature, partial_sig, hash)) - { - // Found it. - using namespace java::lang::reflect; - Constructor *cons = new Constructor (); - cons->offset = (char *) (&methods[i]) - (char *) methods; - cons->declaringClass = this; - return cons; - } - } - throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name)); -} - -java::lang::reflect::Field * -java::lang::Class::getField (jstring name, jint hash) -{ - java::lang::reflect::Field* rfield; - for (int i = 0; i < field_count; i++) - { - _Jv_Field *field = &fields[i]; - if (! _Jv_equal (field->name, name, hash)) - continue; - if (! (field->getModifiers() & java::lang::reflect::Modifier::PUBLIC)) - continue; - rfield = new java::lang::reflect::Field (); - rfield->offset = (char*) field - (char*) fields; - rfield->declaringClass = this; - rfield->name = name; - return rfield; - } - jclass superclass = getSuperclass(); - if (superclass == NULL) - return NULL; - rfield = superclass->getField(name, hash); - for (int i = 0; i < interface_count && rfield == NULL; ++i) - rfield = interfaces[i]->getField (name, hash); - return rfield; -} - -java::lang::reflect::Field * -java::lang::Class::getDeclaredField (jstring name) -{ - memberAccessCheck(java::lang::reflect::Member::DECLARED); - int hash = name->hashCode(); - for (int i = 0; i < field_count; i++) - { - _Jv_Field *field = &fields[i]; - if (! _Jv_equal (field->name, name, hash)) - continue; - java::lang::reflect::Field* rfield = new java::lang::reflect::Field (); - rfield->offset = (char*) field - (char*) fields; - rfield->declaringClass = this; - rfield->name = name; - return rfield; - } - throw new java::lang::NoSuchFieldException (name); -} - -JArray<java::lang::reflect::Field *> * -java::lang::Class::getDeclaredFields (jboolean public_only) -{ - int size; - if (public_only) - { - size = 0; - for (int i = 0; i < field_count; ++i) - { - _Jv_Field *field = &fields[i]; - if ((field->flags & java::lang::reflect::Modifier::PUBLIC)) - ++size; - } - } - else - size = field_count; - - JArray<java::lang::reflect::Field *> *result - = (JArray<java::lang::reflect::Field *> *) - JvNewObjectArray (size, &java::lang::reflect::Field::class$, NULL); - java::lang::reflect::Field** fptr = elements (result); - for (int i = 0; i < field_count; i++) - { - _Jv_Field *field = &fields[i]; - if (public_only - && ! (field->flags & java::lang::reflect::Modifier::PUBLIC)) - continue; - java::lang::reflect::Field* rfield = new java::lang::reflect::Field (); - rfield->offset = (char*) field - (char*) fields; - rfield->declaringClass = this; - *fptr++ = rfield; - } - return result; -} - -void -java::lang::Class::getSignature (java::lang::StringBuffer *buffer) -{ - if (isPrimitive()) - buffer->append((jchar) method_count); - else - { - jstring name = getName(); - if (name->charAt(0) != '[') - buffer->append((jchar) 'L'); - buffer->append(name); - if (name->charAt(0) != '[') - buffer->append((jchar) ';'); - } -} - -// This doesn't have to be native. It is an implementation detail -// only called from the C++ code, though, so maybe this is clearer. -jstring -java::lang::Class::getSignature (JArray<jclass> *param_types, - jboolean is_constructor) -{ - java::lang::StringBuffer *buf = new java::lang::StringBuffer (); - buf->append((jchar) '('); - // A NULL param_types means "no parameters". - if (param_types != NULL) - { - jclass *v = elements (param_types); - for (int i = 0; i < param_types->length; ++i) - v[i]->getSignature(buf); - } - buf->append((jchar) ')'); - if (is_constructor) - buf->append((jchar) 'V'); - return buf->toString(); -} - -java::lang::reflect::Method * -java::lang::Class::_getDeclaredMethod (jstring name, - JArray<jclass> *param_types) -{ - jstring partial_sig = getSignature (param_types, false); - jint p_len = partial_sig->length(); - _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name); - int i = isPrimitive () ? 0 : method_count; - while (--i >= 0) - { - if (_Jv_equalUtf8Consts (methods[i].name, utf_name) - && _Jv_equaln (methods[i].signature, partial_sig, p_len) - && (methods[i].accflags - & java::lang::reflect::Modifier::INVISIBLE) == 0) - { - // Found it. - using namespace java::lang::reflect; - Method *rmethod = new Method (); - rmethod->offset = (char*) (&methods[i]) - (char*) methods; - rmethod->declaringClass = this; - return rmethod; - } - } - return NULL; -} - -JArray<java::lang::reflect::Method *> * -java::lang::Class::getDeclaredMethods (void) -{ - memberAccessCheck(java::lang::reflect::Member::DECLARED); - - int numMethods = 0; - int max = isPrimitive () ? 0 : method_count; - int i; - for (i = max; --i >= 0; ) - { - _Jv_Method *method = &methods[i]; - if (method->name == NULL - || _Jv_equalUtf8Consts (method->name, clinit_name) - || _Jv_equalUtf8Consts (method->name, init_name) - || _Jv_equalUtf8Consts (method->name, finit_name) - || (methods[i].accflags - & java::lang::reflect::Modifier::INVISIBLE) != 0) - continue; - numMethods++; - } - JArray<java::lang::reflect::Method *> *result - = (JArray<java::lang::reflect::Method *> *) - JvNewObjectArray (numMethods, &java::lang::reflect::Method::class$, NULL); - java::lang::reflect::Method** mptr = elements (result); - for (i = 0; i < max; i++) - { - _Jv_Method *method = &methods[i]; - if (method->name == NULL - || _Jv_equalUtf8Consts (method->name, clinit_name) - || _Jv_equalUtf8Consts (method->name, init_name) - || _Jv_equalUtf8Consts (method->name, finit_name) - || (methods[i].accflags - & java::lang::reflect::Modifier::INVISIBLE) != 0) - continue; - java::lang::reflect::Method* rmethod - = new java::lang::reflect::Method (); - rmethod->offset = (char*) method - (char*) methods; - rmethod->declaringClass = this; - *mptr++ = rmethod; - } - return result; -} - -jstring -java::lang::Class::getName (void) -{ - return name->toString(); -} - -JArray<jclass> * -java::lang::Class::getInterfaces (void) -{ - jobjectArray r = JvNewObjectArray (interface_count, getClass (), NULL); - jobject *data = elements (r); - for (int i = 0; i < interface_count; ++i) - { - typedef unsigned int uaddr __attribute__ ((mode (pointer))); - data[i] = interfaces[i]; - if ((uaddr)data[i] < (uaddr)constants.size) - fprintf (stderr, "ERROR !!!\n"); - } - return reinterpret_cast<JArray<jclass> *> (r); -} - -java::lang::reflect::Method * -java::lang::Class::_getMethod (jstring name, JArray<jclass> *param_types) -{ - jstring partial_sig = getSignature (param_types, false); - jint p_len = partial_sig->length(); - _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name); - - for (Class *klass = this; klass; klass = klass->getSuperclass()) - { - int i = klass->isPrimitive () ? 0 : klass->method_count; - while (--i >= 0) - { - if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name) - && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len) - && (klass->methods[i].accflags - & java::lang::reflect::Modifier::INVISIBLE) == 0) - { - // Found it. - using namespace java::lang::reflect; - - // Method must be public. - if (! Modifier::isPublic (klass->methods[i].accflags)) - break; - - Method *rmethod = new Method (); - rmethod->offset = ((char *) (&klass->methods[i]) - - (char *) klass->methods); - rmethod->declaringClass = klass; - return rmethod; - } - } - } - - // If we haven't found a match, and this class is an interface, then - // check all the superinterfaces. - if (isInterface()) - { - for (int i = 0; i < interface_count; ++i) - { - using namespace java::lang::reflect; - Method *rmethod = interfaces[i]->_getMethod (name, param_types); - if (rmethod != NULL) - return rmethod; - } - } - - return NULL; -} - -// This is a very slow implementation, since it re-scans all the -// methods we've already listed to make sure we haven't duplicated a -// method. It also over-estimates the required size, so we have to -// shrink the result array later. -jint -java::lang::Class::_getMethods (JArray<java::lang::reflect::Method *> *result, - jint offset) -{ - jint count = 0; - - // First examine all local methods - for (int i = isPrimitive () ? 0 : method_count; --i >= 0; ) - { - _Jv_Method *method = &methods[i]; - if (method->name == NULL - || _Jv_equalUtf8Consts (method->name, clinit_name) - || _Jv_equalUtf8Consts (method->name, init_name) - || _Jv_equalUtf8Consts (method->name, finit_name) - || (method->accflags - & java::lang::reflect::Modifier::INVISIBLE) != 0) - continue; - // Only want public methods. - if (! java::lang::reflect::Modifier::isPublic (method->accflags)) - continue; - - // This is where we over-count the slots required if we aren't - // filling the result for real. - if (result != NULL) - { - jboolean add = true; - java::lang::reflect::Method **mp = elements (result); - // If we already have a method with this name and signature, - // then ignore this one. This can happen with virtual - // methods. - for (int j = 0; j < offset; ++j) - { - _Jv_Method *meth_2 = _Jv_FromReflectedMethod (mp[j]); - if (_Jv_equalUtf8Consts (method->name, meth_2->name) - && _Jv_equalUtf8Consts (method->signature, - meth_2->signature)) - { - add = false; - break; - } - } - if (! add) - continue; - } - - if (result != NULL) - { - using namespace java::lang::reflect; - Method *rmethod = new Method (); - rmethod->offset = (char *) method - (char *) methods; - rmethod->declaringClass = this; - Method **mp = elements (result); - mp[offset + count] = rmethod; - } - ++count; - } - offset += count; - - // Now examine superclasses. - if (getSuperclass () != NULL) - { - jint s_count = getSuperclass()->_getMethods (result, offset); - offset += s_count; - count += s_count; - } - - // Finally, examine interfaces. - for (int i = 0; i < interface_count; ++i) - { - int f_count = interfaces[i]->_getMethods (result, offset); - count += f_count; - offset += f_count; - } - - return count; -} - -JArray<java::lang::reflect::Method *> * -java::lang::Class::getMethods (void) -{ - using namespace java::lang::reflect; - - memberAccessCheck(Member::PUBLIC); - - // This will overestimate the size we need. - jint count = _getMethods (NULL, 0); - - JArray<Method *> *result - = ((JArray<Method *> *) JvNewObjectArray (count, - &Method::class$, - NULL)); - - // When filling the array for real, we get the actual count. Then - // we resize the array. - jint real_count = _getMethods (result, 0); - - if (real_count != count) - { - JArray<Method *> *r2 - = ((JArray<Method *> *) JvNewObjectArray (real_count, - &Method::class$, - NULL)); - - Method **destp = elements (r2); - Method **srcp = elements (result); - - for (int i = 0; i < real_count; ++i) - *destp++ = *srcp++; - - result = r2; - } - - return result; -} - -jboolean -java::lang::Class::isAssignableFrom (jclass klass) -{ - // Arguments may not have been initialized, given ".class" syntax. - // This ensures we can at least look at their superclasses. - _Jv_Linker::wait_for_state (this, JV_STATE_LOADING); - _Jv_Linker::wait_for_state (klass, JV_STATE_LOADING); - return _Jv_IsAssignableFrom (klass, this); -} - -jboolean -java::lang::Class::isInstance (jobject obj) -{ - if (! obj) - return false; - return _Jv_IsAssignableFrom (JV_CLASS (obj), this); -} - -jobject -java::lang::Class::newInstance (void) -{ - memberAccessCheck(java::lang::reflect::Member::PUBLIC); - - if (isPrimitive () - || isInterface () - || isArray () - || java::lang::reflect::Modifier::isAbstract(accflags)) - throw new java::lang::InstantiationException (getName ()); - - _Jv_InitClass (this); - - _Jv_Method *meth = _Jv_GetMethodLocal (this, init_name, void_signature); - if (! meth) - throw new java::lang::InstantiationException (getName()); - - jobject r = _Jv_AllocObject (this); - /* Class constructors/destructors have __thiscall calling - convention for 32-bit native Windows ABI. */ -#if defined (__MINGW32__) && defined (__i386__) - ((void (__thiscall *) (jobject)) meth->ncode) (r); -#else - ((void (*) (jobject)) meth->ncode) (r); -#endif - return r; -} - -void -java::lang::Class::finalize (void) -{ - // Array classes don't have an engine, and don't need to be finalized. - if (engine) - engine->unregister(this); -} - -#ifdef INTERPRETER -void -_Jv_ClosureList::releaseClosures (_Jv_ClosureList **closures) -{ - if (!closures) - return; - - while (_Jv_ClosureList *current = *closures) - { - *closures = current->next; - ffi_closure_free (current->ptr); - } -} - -void -_Jv_ClosureList::registerClosure (jclass klass, void *ptr) -{ - _Jv_ClosureList **closures = klass->engine->get_closure_list (klass); - if (closures) - { - this->ptr = ptr; - this->next = *closures; - *closures = this; - } -} -#endif - -// This implements the initialization process for a class. From Spec -// section 12.4.2. -void -java::lang::Class::initializeClass (void) -{ - // Short-circuit to avoid needless locking (expression includes - // JV_STATE_PHANTOM and JV_STATE_DONE). - if (state >= JV_STATE_PHANTOM) - return; - - // Step 1. We introduce a new scope so we can synchronize more - // easily. - { - JvSynchronize sync (this); - - if (state < JV_STATE_LINKED) - { - try - { - _Jv_Linker::wait_for_state(this, JV_STATE_LINKED); - } - catch (java::lang::SecurityException *x) - { - throw x; - } - catch (java::lang::Throwable *x) - { - // Turn into a NoClassDefFoundError. - java::lang::NoClassDefFoundError *result - = new java::lang::NoClassDefFoundError(getName()); - result->initCause(x); - throw result; - } - } - - // Step 2. - java::lang::Thread *self = java::lang::Thread::currentThread(); - self = (java::lang::Thread *) ((long) self | 1); - while (state == JV_STATE_IN_PROGRESS && thread && thread != self) - wait (); - - // Steps 3 & 4. - if (state == JV_STATE_DONE || state == JV_STATE_IN_PROGRESS) - return; - - // Step 5. - if (state == JV_STATE_ERROR) - throw new java::lang::NoClassDefFoundError (getName()); - - // Step 6. - thread = self; - _Jv_Linker::wait_for_state (this, JV_STATE_LINKED); - state = JV_STATE_IN_PROGRESS; - } - - // Step 7. - if (! isInterface () && superclass) - { - try - { - _Jv_InitClass (superclass); - } - catch (java::lang::SecurityException *x) - { - throw x; - } - catch (java::lang::Throwable *except) - { - // Caught an exception. - JvSynchronize sync (this); - state = JV_STATE_ERROR; - notifyAll (); - throw except; - } - } - - // Steps 8, 9, 10, 11. - try - { - _Jv_Method *meth = _Jv_GetMethodLocal (this, clinit_name, - void_signature); - if (meth) - ((void (*) (void)) meth->ncode) (); - } - catch (java::lang::SecurityException *x) - { - throw x; - } - catch (java::lang::Throwable *except) - { - if (! java::lang::Error::class$.isInstance(except)) - { - try - { - except = new ExceptionInInitializerError (except); - } - catch (java::lang::Throwable *t) - { - except = t; - } - } - - JvSynchronize sync (this); - state = JV_STATE_ERROR; - notifyAll (); - throw except; - } - - JvSynchronize sync (this); - state = JV_STATE_DONE; - notifyAll (); -} - -// Only used by serialization -java::lang::reflect::Field * -java::lang::Class::getPrivateField (jstring name) -{ - int hash = name->hashCode (); - - java::lang::reflect::Field* rfield; - for (int i = 0; i < field_count; i++) - { - _Jv_Field *field = &fields[i]; - if (! _Jv_equal (field->name, name, hash)) - continue; - rfield = new java::lang::reflect::Field (); - rfield->offset = (char*) field - (char*) fields; - rfield->declaringClass = this; - rfield->name = name; - return rfield; - } - jclass superclass = getSuperclass(); - if (superclass == NULL) - return NULL; - rfield = superclass->getPrivateField(name); - for (int i = 0; i < interface_count && rfield == NULL; ++i) - rfield = interfaces[i]->getPrivateField (name); - return rfield; -} - -// Only used by serialization -java::lang::reflect::Method * -java::lang::Class::getPrivateMethod (jstring name, JArray<jclass> *param_types) -{ - jstring partial_sig = getSignature (param_types, false); - jint p_len = partial_sig->length(); - _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name); - for (Class *klass = this; klass; klass = klass->getSuperclass()) - { - int i = klass->isPrimitive () ? 0 : klass->method_count; - while (--i >= 0) - { - if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name) - && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len)) - { - // Found it. - using namespace java::lang::reflect; - - Method *rmethod = new Method (); - rmethod->offset = ((char *) (&klass->methods[i]) - - (char *) klass->methods); - rmethod->declaringClass = klass; - return rmethod; - } - } - } - throw new java::lang::NoSuchMethodException (name); -} - -// Private accessor method for Java code to retrieve the protection domain. -java::security::ProtectionDomain * -java::lang::Class::getProtectionDomain0 () -{ - return protectionDomain; -} - -JArray<jobject> * -java::lang::Class::getSigners() -{ - return hack_signers; -} - -void -java::lang::Class::setSigners(JArray<jobject> *s) -{ - hack_signers = s; -} - - - -static unsigned char -read_u1 (unsigned char *&p) -{ - return *p++; -} - -static unsigned char -read_u1 (unsigned char *&p, unsigned char *next) -{ - if (next - p < 1) - throw new java::lang::InternalError(); - return *p++; -} - -static unsigned int -read_u2 (unsigned char *&p) -{ - unsigned int b1 = *p++; - unsigned int b2 = *p++; - return (b1 << 8) | b2; -} - -static unsigned int -read_u2 (unsigned char *&p, unsigned char *next) -{ - if (next - p < 2) - throw new java::lang::InternalError(); - return read_u2 (p); -} - -static int -read_4 (unsigned char *&p) -{ - int b1 = *p++; - int b2 = *p++; - int b3 = *p++; - int b4 = *p++; - return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4; -} - -jstring -java::lang::Class::getReflectionSignature (jint /*jv_attr_type*/ type, - jint obj_index) -{ - // We just re-parse the bytecode for this data each time. If - // necessary we can cache results, but I suspect this is not - // performance sensitive. - unsigned char *bytes = reflection_data; - if (bytes == NULL) - return NULL; - while (true) - { - int kind = read_u1 (bytes); - if (kind == JV_DONE_ATTR) - return NULL; - int len = read_4 (bytes); - unsigned char *next = bytes + len; - if (kind != type) - { - bytes = next; - continue; - } - if (type != JV_CLASS_ATTR) - { - unsigned short index = read_u2 (bytes, next); - if (index != obj_index) - { - bytes = next; - continue; - } - } - int nt = read_u1 (bytes, next); - if (nt != JV_SIGNATURE_KIND) - { - bytes = next; - continue; - } - unsigned int cpool_idx = read_u2 (bytes, next); - if (cpool_idx >= (unsigned int) constants.size - || constants.tags[cpool_idx] != JV_CONSTANT_Utf8) - { - // We just ignore errors for now. It isn't clear what is - // best to do here, as an encoding error here means a bug - // either in the compiler or in defineclass.cc. - return NULL; - } - return _Jv_NewStringUtf8Const (constants.data[cpool_idx].utf8); - } -} - -jstring -java::lang::Class::getReflectionSignature (::java::lang::reflect::Constructor *c) -{ - _Jv_Method *meth = _Jv_FromReflectedConstructor (c); - unsigned short meth_index = meth - methods; - return getReflectionSignature (JV_METHOD_ATTR, meth_index); -} - -jstring -java::lang::Class::getReflectionSignature (::java::lang::reflect::Method *m) -{ - _Jv_Method *meth = _Jv_FromReflectedMethod (m); - unsigned short meth_index = meth - methods; - return getReflectionSignature (JV_METHOD_ATTR, meth_index); -} - -jstring -java::lang::Class::getReflectionSignature (::java::lang::reflect::Field *f) -{ - _Jv_Field *fld = _Jv_FromReflectedField (f); - unsigned short fld_index = fld - fields; - return getReflectionSignature (JV_FIELD_ATTR, fld_index); -} - -jstring -java::lang::Class::getClassSignature() -{ - return getReflectionSignature (JV_CLASS_ATTR, 0); -} - -jint -java::lang::Class::getEnclosingMethodData() -{ - unsigned char *bytes = reflection_data; - if (bytes == NULL) - return 0; - while (true) - { - int kind = read_u1 (bytes); - if (kind == JV_DONE_ATTR) - return 0; - int len = read_4 (bytes); - unsigned char *next = bytes + len; - if (kind != JV_CLASS_ATTR) - { - bytes = next; - continue; - } - int type = read_u1 (bytes, next); - if (type != JV_ENCLOSING_METHOD_KIND) - { - bytes = next; - continue; - } - int class_index = read_u2 (bytes, next); - int method_index = read_u2 (bytes, next); - _Jv_word result; - _Jv_storeIndexes (&result, class_index, method_index); - return result.i; - } -} - -jclass -java::lang::Class::getEnclosingClass() -{ - _Jv_word indexes; - indexes.i = getEnclosingMethodData(); - if (indexes.i == 0) - // No enclosing method, but perhaps a member or anonymous class - return getDeclaringClass(); - _Jv_ushort class_index, method_index; - _Jv_loadIndexes (&indexes, class_index, method_index); - return _Jv_Linker::resolve_pool_entry (this, class_index).clazz; -} - -::java::lang::reflect::Method * -java::lang::Class::getEnclosingMethod() -{ - _Jv_word indexes; - indexes.i = getEnclosingMethodData(); - if (indexes.i == 0) - return NULL; - _Jv_ushort class_index, method_index; - _Jv_loadIndexes (&indexes, class_index, method_index); - jclass found_class; - _Jv_Method *method = _Jv_Linker::resolve_method_entry (this, found_class, - class_index, - method_index, - false, false); - using namespace java::lang::reflect; - Method *rmethod = new Method (); - rmethod->offset = (char *) method - (char *) found_class->methods; - rmethod->declaringClass = found_class; - return rmethod; -} - -::java::lang::reflect::Constructor * -java::lang::Class::getEnclosingConstructor() -{ - _Jv_word indexes; - indexes.i = getEnclosingMethodData(); - if (indexes.i == 0) - return NULL; - _Jv_ushort class_index, method_index; - _Jv_loadIndexes (&indexes, class_index, method_index); - jclass found_class; - _Jv_Method *method = _Jv_Linker::resolve_method_entry (this, found_class, - class_index, - method_index, - false, false); - using namespace java::lang::reflect; - Constructor *cons = new Constructor (); - cons->offset = (char *) method - (char *) found_class->methods; - cons->declaringClass = this; - return cons; -} - -static void -check_constant (_Jv_Constants *pool, jint cpool_index, jint type) -{ - if (cpool_index <= 0 || cpool_index >= pool->size) - throw new InternalError(JvNewStringLatin1("invalid constant pool index")); - if ((pool->tags[cpool_index] & - ~(JV_CONSTANT_ResolvedFlag|JV_CONSTANT_LazyFlag)) != type) - { - ::java::lang::StringBuffer *sb = new ::java::lang::StringBuffer(); - sb->append(JvNewStringLatin1("expected pool constant ")); - sb->append(type); - sb->append(JvNewStringLatin1(" but got ")); - sb->append(jint (pool->tags[cpool_index])); - throw new InternalError(sb->toString()); - } -} - -// Forward declaration -static ::java::lang::annotation::Annotation * -parseAnnotation(jclass klass, _Jv_Constants *pool, - unsigned char *&bytes, unsigned char *last); - -static jobject -parseAnnotationElement(jclass klass, _Jv_Constants *pool, - unsigned char *&bytes, unsigned char *last) -{ - int tag = read_u1 (bytes, last); - jobject result; - switch (tag) - { - case 'B': - { - int cindex = read_u2 (bytes, last); - check_constant (pool, cindex, JV_CONSTANT_Integer); - result = Byte::valueOf (pool->data[cindex].i); - } - break; - case 'C': - { - int cindex = read_u2 (bytes, last); - check_constant (pool, cindex, JV_CONSTANT_Integer); - result = Character::valueOf (pool->data[cindex].i); - } - break; - case 'S': - { - int cindex = read_u2 (bytes, last); - check_constant (pool, cindex, JV_CONSTANT_Integer); - result = Short::valueOf (pool->data[cindex].i); - } - break; - case 'Z': - { - int cindex = read_u2 (bytes, last); - check_constant (pool, cindex, JV_CONSTANT_Integer); - result = Boolean::valueOf (jboolean (pool->data[cindex].i)); - } - break; - case 'I': - { - int cindex = read_u2 (bytes, last); - check_constant (pool, cindex, JV_CONSTANT_Integer); - result = Integer::valueOf (pool->data[cindex].i); - } - break; - case 'D': - { - int cindex = read_u2 (bytes, last); - check_constant (pool, cindex, JV_CONSTANT_Double); - _Jv_word2 word; - memcpy (&word, &pool->data[cindex], 2 * sizeof (_Jv_word)); - result = Double::valueOf (word.d); - } - break; - case 'F': - { - int cindex = read_u2 (bytes, last); - check_constant (pool, cindex, JV_CONSTANT_Float); - result = Float::valueOf (pool->data[cindex].f); - } - break; - case 'J': - { - int cindex = read_u2 (bytes, last); - check_constant (pool, cindex, JV_CONSTANT_Long); - _Jv_word2 word; - memcpy (&word, &pool->data[cindex], 2 * sizeof (_Jv_word)); - result = Long::valueOf (word.l); - } - break; - case 's': - { - int cindex = read_u2 (bytes, last); - // Despite what the JVM spec says, compilers generate a Utf8 - // constant here, not a String. - check_constant (pool, cindex, JV_CONSTANT_Utf8); - result = pool->data[cindex].utf8->toString(); - } - break; - case 'e': - { - int type_name_index = read_u2 (bytes, last); - check_constant (pool, type_name_index, JV_CONSTANT_Utf8); - int const_name_index = read_u2 (bytes, last); - check_constant (pool, const_name_index, JV_CONSTANT_Utf8); - - _Jv_Utf8Const *u_name = pool->data[type_name_index].utf8; - _Jv_Utf8Const *e_name = pool->data[const_name_index].utf8; - - // FIXME: throw correct exceptions at the correct times. - jclass e_class = _Jv_FindClassFromSignature(u_name->chars(), - klass->getClassLoaderInternal()); - result = ::java::lang::Enum::valueOf(e_class, e_name->toString()); - } - break; - case 'c': - { - int cindex = read_u2 (bytes, last); - check_constant (pool, cindex, JV_CONSTANT_Utf8); - _Jv_Utf8Const *u_name = pool->data[cindex].utf8; - jclass anno_class - = _Jv_FindClassFromSignatureNoException(u_name->chars(), - klass->getClassLoaderInternal()); - // FIXME: not correct: we should lazily do this when trying to - // read the element. This means that - // AnnotationInvocationHandler needs to have a special case. - if (! anno_class) - // FIXME: original exception... - throw new TypeNotPresentException(u_name->toString(), NULL); - result = anno_class; - } - break; - case '@': - result = parseAnnotation (klass, pool, bytes, last); - break; - case '[': - { - int n_array_elts = read_u2 (bytes, last); - jobjectArray aresult = _Jv_NewObjectArray (n_array_elts, - &Object::class$, NULL); - jobject *elts = elements (aresult); - for (int i = 0; i < n_array_elts; ++i) - elts[i] = parseAnnotationElement(klass, pool, bytes, last); - result = aresult; - } - break; - default: - throw new java::lang::InternalError(); - } - return result; -} - -static ::java::lang::annotation::Annotation * -parseAnnotation(jclass klass, _Jv_Constants *pool, - unsigned char *&bytes, unsigned char *last) -{ - int type_index = read_u2 (bytes, last); - check_constant (pool, type_index, JV_CONSTANT_Utf8); - - _Jv_Utf8Const *u_name = pool->data[type_index].utf8; - jclass anno_class = _Jv_FindClassFromSignatureNoException(u_name->chars(), - klass->getClassLoaderInternal()); - // FIXME: what to do if anno_class==NULL? - - ::java::util::HashMap *hmap = new ::java::util::HashMap(); - int npairs = read_u2 (bytes, last); - for (int i = 0; i < npairs; ++i) - { - int name_index = read_u2 (bytes, last); - check_constant (pool, name_index, JV_CONSTANT_Utf8); - jstring name = _Jv_NewStringUtf8Const (pool->data[name_index].utf8); - jobject value = parseAnnotationElement (klass, pool, bytes, last); - // FIXME: any checks needed for name? - hmap->put(name, value); - } - using namespace ::sun::reflect::annotation; - return AnnotationInvocationHandler::create (anno_class, - (::java::util::Map *) hmap); -} - -static jobjectArray -parseAnnotations(jclass klass, _Jv_Constants *pool, - unsigned char *&bytes, unsigned char *last) -{ - int num = read_u2 (bytes, last); - jobjectArray result = _Jv_NewObjectArray (num, - &::java::lang::annotation::Annotation::class$, - NULL); - jobject *elts = elements (result); - for (int i = 0; i < num; ++i) - elts[i] = parseAnnotation(klass, pool, bytes, last); - return result; -} - -static jobjectArray -parseParameterAnnotations(jclass klass, _Jv_Constants *pool, - unsigned char *&bytes, unsigned char *last) -{ - jclass anno = &::java::lang::annotation::Annotation::class$; - jclass annoary = _Jv_GetArrayClass (anno, anno->getClassLoaderInternal()); - - // FIXME: something should check the number of params versus the - // method - int n_params = read_u1 (bytes, last); - jobjectArray result = _Jv_NewObjectArray (n_params, annoary, NULL); - jobject *elts = elements (result); - for (int i = 0; i < n_params; ++i) - elts[i] = parseAnnotations(klass, pool, bytes, last); - return result; -} - -jobject -java::lang::Class::getMethodDefaultValue(::java::lang::reflect::Method *meth) -{ - // FIXME: could cache the value here... - - unsigned char *bytes = reflection_data; - if (bytes == NULL) - return 0; - - unsigned short meth_index = _Jv_FromReflectedMethod (meth) - methods; - - while (true) - { - int type = read_u1 (bytes); - if (type == JV_DONE_ATTR) - return NULL; - int len = read_4 (bytes); - unsigned char *next = bytes + len; - if (type != JV_METHOD_ATTR) - { - bytes = next; - continue; - } - int kind = read_u1 (bytes, next); - if (kind != JV_ANNOTATION_DEFAULT_KIND) - { - bytes = next; - continue; - } - int index = read_u2 (bytes, next); - if (meth_index != index) - { - bytes = next; - continue; - } - - // FIXME: could cache here. If we do then we have to clone any - // array result. - return parseAnnotationElement(this, &this->constants, bytes, next); - } -} - -jobjectArray -java::lang::Class::getDeclaredAnnotations(jint /* jv_attr_type */ member_type, - jint member_index, - jint /* jv_attr_kind */ kind_req) -{ - using namespace java::lang::annotation; - jobjectArray result; - - unsigned char *bytes = reflection_data; - if (bytes == NULL) - return 0; - - if (loader == NULL) - loader = (ClassLoader *)VMClassLoader::bootLoader; - - result = (loader->getDeclaredAnnotations - (this, member_type, member_index, kind_req)); - if (result) - return result; - - for (;;) - { - int type = read_u1 (bytes); - if (type == JV_DONE_ATTR) - return NULL; - int len = read_4 (bytes); - unsigned char *next = bytes + len; - if (type != member_type) - { - bytes = next; - continue; - } - int kind = read_u1 (bytes, next); - if (kind != kind_req) - { - bytes = next; - continue; - } - if (member_type != JV_CLASS_ATTR) - { - int index = read_u2 (bytes, next); - if (member_index != index) - { - bytes = next; - continue; - } - } - - if (kind_req == JV_PARAMETER_ANNOTATIONS_KIND) - result = ((parseParameterAnnotations - (this, &this->constants, bytes, next))); - else - result = ((parseAnnotations (this, &this->constants, bytes, next))); - break; - } - - return (loader->putDeclaredAnnotations - (this, member_type, member_index, kind_req, result)); -} - -jobjectArray -java::lang::Class::getDeclaredAnnotations(::java::lang::reflect::Method *meth, - jboolean is_param) -{ - unsigned short meth_index = _Jv_FromReflectedMethod (meth) - methods; - return getDeclaredAnnotations(JV_METHOD_ATTR, meth_index, - (is_param - ? JV_PARAMETER_ANNOTATIONS_KIND - : JV_ANNOTATIONS_KIND)); -} - -jobjectArray -java::lang::Class::getDeclaredAnnotations(::java::lang::reflect::Constructor *cons, - jboolean is_param) -{ - unsigned short meth_index = _Jv_FromReflectedConstructor (cons) - methods; - return getDeclaredAnnotations(JV_METHOD_ATTR, meth_index, - (is_param - ? JV_PARAMETER_ANNOTATIONS_KIND - : JV_ANNOTATIONS_KIND)); -} - -jobjectArray -java::lang::Class::getDeclaredAnnotations(::java::lang::reflect::Field *fld) -{ - unsigned short field_index = _Jv_FromReflectedField (fld) - fields; - return getDeclaredAnnotations(JV_FIELD_ATTR, field_index, - JV_ANNOTATIONS_KIND); -} - -JArray< ::java::lang::annotation::Annotation *> * -java::lang::Class::getDeclaredAnnotationsInternal() -{ - return (JArray< ::java::lang::annotation::Annotation *> *) getDeclaredAnnotations(JV_CLASS_ATTR, 0, JV_ANNOTATIONS_KIND); -} - -static jclass -resolve_class_constant (jclass klass, _Jv_Constants *pool, int cpool_index) -{ - check_constant (pool, cpool_index, JV_CONSTANT_Class); - // FIXME: what is the correct thing to do with an exception here? - return _Jv_Linker::resolve_pool_entry (klass, cpool_index, false).clazz; -} - -jint -java::lang::Class::findInnerClassAttribute() -{ - unsigned char *bytes = reflection_data; - if (bytes == NULL) - return -1; - while (true) - { - int type = read_u1 (bytes); - if (type == JV_DONE_ATTR) - break; - // After the type but before the length. - unsigned char *save = bytes; - int len = read_4 (bytes); - unsigned char *next = bytes + len; - if (type != JV_CLASS_ATTR) - { - bytes = next; - continue; - } - int kind = read_u1 (bytes, next); - if (kind != JV_INNER_CLASSES_KIND) - { - bytes = next; - continue; - } - return save - reflection_data; - } - return -1; -} - -jint -java::lang::Class::findDeclaredClasses(JArray<jclass> *result, - jboolean publicOnly, - jint offset) -{ - unsigned char *bytes = reflection_data + offset; - int len = read_4 (bytes); - unsigned char *next = bytes + len; - // Skip a byte. - read_u1 (bytes, next); - int n_classes = read_u2 (bytes, next); - int count = 0; - for (int i = 0; i < n_classes; ++i) - { - int inner_class_index = read_u2 (bytes, next); - int outer_class_index = read_u2 (bytes, next); - /*int inner_name_index = */ read_u2 (bytes, next); - int inner_flags = read_u2 (bytes, next); - - if (inner_class_index == 0 || outer_class_index == 0) - continue; - if (resolve_class_constant (this, &constants, outer_class_index) == this) - { - jclass inner = resolve_class_constant (this, &constants, - inner_class_index); - if (! publicOnly - || ((inner_flags - & java::lang::reflect::Modifier::PUBLIC) != 0)) - { - if (result) - { - jclass *elts = elements (result); - elts[count] = inner; - } - ++count; - } - } - } - - return count; -} - -JArray<jclass> * -java::lang::Class::getDeclaredClasses (jboolean publicOnly) -{ - int offset = findInnerClassAttribute(); - int count; - if (offset == -1) - { - // No InnerClasses attribute, so no declared classes. - count = 0; - } - else - count = findDeclaredClasses(NULL, publicOnly, offset); - JArray<jclass> *result - = (JArray<jclass> *) JvNewObjectArray (count, &java::lang::Class::class$, - NULL); - if (count > 0) - findDeclaredClasses(result, publicOnly, offset); - return result; -} - -jclass -java::lang::Class::getDeclaringClass (void) -{ - int offset = findInnerClassAttribute(); - if (offset == -1) - return NULL; - - unsigned char *bytes = reflection_data + offset; - int len = read_4 (bytes); - unsigned char *next = bytes + len; - // Skip a byte. - read_u1 (bytes, next); - int n_classes = read_u2 (bytes, next); - for (int i = 0; i < n_classes; ++i) - { - int inner_class_index = read_u2 (bytes, next); - int outer_class_index = read_u2 (bytes, next); - /*int inner_name_index = */read_u2 (bytes, next); - /*int inner_flags = */read_u2 (bytes, next); - - if (inner_class_index == 0 || outer_class_index == 0) - continue; - if (resolve_class_constant (this, &constants, inner_class_index) == this) - return resolve_class_constant (this, &constants, outer_class_index); - } - - return NULL; -} - -jboolean -java::lang::Class::isAnonymousClass() -{ - int offset = findInnerClassAttribute(); - if (offset == -1) - return false; - - unsigned char *bytes = reflection_data + offset; - int len = read_4 (bytes); - unsigned char *next = bytes + len; - // Skip a byte. - read_u1 (bytes, next); - int n_classes = read_u2 (bytes, next); - for (int i = 0; i < n_classes; ++i) - { - int inner_class_index = read_u2 (bytes, next); - /*int outer_class_index = */read_u2 (bytes, next); - int inner_name_index = read_u2 (bytes, next); - /*int inner_flags = */read_u2 (bytes, next); - - if (inner_class_index == 0) - continue; - if (resolve_class_constant (this, &constants, inner_class_index) == this) - return inner_name_index == 0; - } - - return false; -} - -jboolean -java::lang::Class::isLocalClass() -{ - _Jv_word indexes; - indexes.i = getEnclosingMethodData(); - return indexes.i != 0; -} - -jboolean -java::lang::Class::isMemberClass() -{ - // FIXME: is this correct? - return !isLocalClass() && getDeclaringClass() != NULL; -} - - - -// -// Some class-related convenience functions. -// - -// Find a method declared in the class. If it is not declared locally -// (or if it is inherited), return NULL. -_Jv_Method * -_Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name, - _Jv_Utf8Const *signature) -{ - for (int i = 0; i < klass->method_count; ++i) - { - if (_Jv_equalUtf8Consts (name, klass->methods[i].name) - && _Jv_equalUtf8Consts (signature, klass->methods[i].signature)) - return &klass->methods[i]; - } - return NULL; -} - -_Jv_Method * -_Jv_LookupDeclaredMethod (jclass klass, _Jv_Utf8Const *name, - _Jv_Utf8Const *signature, - jclass *declarer_result) -{ - for (; klass; klass = klass->getSuperclass()) - { - _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature); - - if (meth) - { - if (declarer_result) - *declarer_result = klass; - return meth; - } - } - - return NULL; -} - -java::lang::reflect::Method * -_Jv_GetReflectedMethod (jclass klass, _Jv_Utf8Const *name, - _Jv_Utf8Const *signature) -{ - for (; klass; klass = klass->getSuperclass()) - { - _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature); - if (meth) - { - using namespace java::lang::reflect; - Method *rmethod = new Method (); - rmethod->offset = (char*) meth - (char*) klass->methods; - rmethod->declaringClass = klass; - return rmethod; - } - } - - return NULL; -} - -#ifdef HAVE_TLS - -// NOTE: MCACHE_SIZE should be a power of 2 minus one. -#define MCACHE_SIZE 31 - -struct _Jv_mcache -{ - jclass klass; - _Jv_Method *method; -}; - -static __thread _Jv_mcache *method_cache; -#endif // HAVE_TLS - -static void * -_Jv_FindMethodInCache (jclass klass MAYBE_UNUSED, - _Jv_Utf8Const *name MAYBE_UNUSED, - _Jv_Utf8Const *signature MAYBE_UNUSED) -{ -#ifdef HAVE_TLS - _Jv_mcache *cache = method_cache; - if (cache) - { - int index = name->hash16 () & MCACHE_SIZE; - _Jv_mcache *mc = &cache[index]; - _Jv_Method *m = mc->method; - - if (mc->klass == klass - && _Jv_equalUtf8Consts (m->name, name) - && _Jv_equalUtf8Consts (m->signature, signature)) - return mc->method->ncode; - } -#endif // HAVE_TLS - return NULL; -} - -static void -_Jv_AddMethodToCache (jclass klass MAYBE_UNUSED, - _Jv_Method *method MAYBE_UNUSED) -{ -#ifdef HAVE_TLS - if (method_cache == NULL) - method_cache = (_Jv_mcache *) _Jv_MallocUnchecked((MCACHE_SIZE + 1) - * sizeof (_Jv_mcache)); - // If the allocation failed, just keep going. - if (method_cache != NULL) - { - int index = method->name->hash16 () & MCACHE_SIZE; - method_cache[index].method = method; - method_cache[index].klass = klass; - } -#endif // HAVE_TLS -} - -// Free this thread's method cache. We explicitly manage this memory -// as the GC does not yet know how to scan TLS on all platforms. -void -_Jv_FreeMethodCache () -{ -#ifdef HAVE_TLS - if (method_cache != NULL) - { - _Jv_Free(method_cache); - method_cache = NULL; - } -#endif // HAVE_TLS -} - -void * -_Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name, - _Jv_Utf8Const *signature) -{ - using namespace java::lang::reflect; - - void *ncode = _Jv_FindMethodInCache (klass, name, signature); - if (ncode != 0) - return ncode; - - for (; klass; klass = klass->getSuperclass()) - { - _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature); - if (! meth) - continue; - - if (Modifier::isStatic(meth->accflags)) - throw new java::lang::IncompatibleClassChangeError - (_Jv_GetMethodString (klass, meth)); - if (Modifier::isAbstract(meth->accflags)) - throw new java::lang::AbstractMethodError - (_Jv_GetMethodString (klass, meth)); - if (! Modifier::isPublic(meth->accflags)) - throw new java::lang::IllegalAccessError - (_Jv_GetMethodString (klass, meth)); - - _Jv_AddMethodToCache (klass, meth); - - return meth->ncode; - } - throw new java::lang::IncompatibleClassChangeError; -} - -// Fast interface method lookup by index. -void * -_Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface, int method_idx) -{ - _Jv_IDispatchTable *cldt = klass->idt; - int idx = iface->ioffsets[cldt->iindex] + method_idx; - return cldt->itable[idx]; -} - -jboolean -_Jv_IsAssignableFrom (jclass source, jclass target) -{ - if (source == target) - return true; - - // If target is array, so must source be. - while (target->isArray ()) - { - if (! source->isArray()) - return false; - target = target->getComponentType(); - source = source->getComponentType(); - } - - if (target->isInterface()) - { - // Abstract classes have no IDT, and IDTs provide no way to check - // two interfaces for assignability. - if (__builtin_expect - (source->idt == NULL || source->isInterface(), false)) - return _Jv_InterfaceAssignableFrom (source, target); - - _Jv_IDispatchTable *cl_idt = source->idt; - - if (__builtin_expect ((target->ioffsets == NULL), false)) - return false; // No class implementing TARGET has been loaded. - jshort cl_iindex = cl_idt->iindex; - if (cl_iindex < target->ioffsets[0]) - { - jshort offset = target->ioffsets[cl_iindex]; - if (offset != -1 && offset < cl_idt->itable_length - && cl_idt->itable[offset] == target) - return true; - } - return false; - } - - // Primitive TYPE classes are only assignable to themselves. - if (__builtin_expect (target->isPrimitive() || source->isPrimitive(), false)) - return false; - - if (target == &java::lang::Object::class$) - return true; - else if (source->ancestors == NULL || target->ancestors == NULL) - { - // We need this case when either SOURCE or TARGET has not has - // its constant-time tables prepared. - - // At this point we know that TARGET can't be Object, so it is - // safe to use that as the termination point. - while (source && source != &java::lang::Object::class$) - { - if (source == target) - return true; - source = source->getSuperclass(); - } - } - else if (source->depth >= target->depth - && source->ancestors[source->depth - target->depth] == target) - return true; - - return false; -} - -// Interface type checking, the slow way. Returns TRUE if IFACE is a -// superinterface of SOURCE. This is used when SOURCE is also an interface, -// or a class with no interface dispatch table. -jboolean -_Jv_InterfaceAssignableFrom (jclass source, jclass iface) -{ - for (int i = 0; i < source->interface_count; i++) - { - jclass source_interface = source->interfaces[i]; - if (iface == source_interface - || _Jv_InterfaceAssignableFrom (source_interface, iface)) - return true; - } - - if (!source->isInterface() - && source->superclass - && _Jv_InterfaceAssignableFrom (source->superclass, iface)) - return true; - - return false; -} - -jboolean -_Jv_IsInstanceOf(jobject obj, jclass cl) -{ - if (__builtin_expect (!obj, false)) - return false; - return _Jv_IsAssignableFrom (JV_CLASS (obj), cl); -} - -void * -_Jv_CheckCast (jclass c, jobject obj) -{ - if (__builtin_expect - (obj != NULL && ! _Jv_IsAssignableFrom(JV_CLASS (obj), c), false)) - throw new java::lang::ClassCastException - ((new java::lang::StringBuffer - (obj->getClass()->getName()))->append - (JvNewStringUTF(" cannot be cast to "))->append - (c->getName())->toString()); - - return obj; -} - -void -_Jv_CheckArrayStore (jobject arr, jobject obj) -{ - if (obj) - { - JvAssert (arr != NULL); - jclass elt_class = (JV_CLASS (arr))->getComponentType(); - if (elt_class == &java::lang::Object::class$) - return; - jclass obj_class = JV_CLASS (obj); - if (__builtin_expect - (! _Jv_IsAssignableFrom (obj_class, elt_class), false)) - throw new java::lang::ArrayStoreException - ((new java::lang::StringBuffer - (JvNewStringUTF("Cannot store ")))->append - (obj_class->getName())->append - (JvNewStringUTF(" in array of type "))->append - (elt_class->getName())->toString()); - } -} - -jboolean -_Jv_IsAssignableFromSlow (jclass source, jclass target) -{ - // First, strip arrays. - while (target->isArray ()) - { - // If target is array, source must be as well. - if (! source->isArray ()) - return false; - target = target->getComponentType (); - source = source->getComponentType (); - } - - // Quick success. - if (target == &java::lang::Object::class$) - return true; - - // Ensure that the classes have their supers installed. - _Jv_Linker::wait_for_state (source, JV_STATE_LOADING); - _Jv_Linker::wait_for_state (target, JV_STATE_LOADING); - - do - { - if (source == target) - return true; - - if (target->isPrimitive () || source->isPrimitive ()) - return false; - - if (target->isInterface ()) - { - for (int i = 0; i < source->interface_count; ++i) - { - // We use a recursive call because we also need to - // check superinterfaces. - if (_Jv_IsAssignableFromSlow (source->getInterface (i), target)) - return true; - } - } - source = source->getSuperclass (); - } - while (source != NULL); - - return false; -} - -// Lookup an interface method by name. This is very similar to -// purpose to _getMethod, but the interfaces are quite different. It -// might be a good idea for _getMethod to call this function. -// -// Return true of the method is found, with the class in FOUND_CLASS -// and the index in INDEX. -bool -_Jv_getInterfaceMethod (jclass search_class, jclass &found_class, int &index, - const _Jv_Utf8Const *utf_name, - const _Jv_Utf8Const *utf_sig) -{ - for (jclass klass = search_class; klass; klass = klass->getSuperclass()) - { - // FIXME: Throw an exception? - if (!klass->isInterface ()) - return false; - - int max = klass->method_count; - int offset = 0; - for (int i = 0; i < max; ++i) - { - // Skip <clinit> here, as it will not be in the IDT. - if (klass->methods[i].name->first() == '<') - continue; - - if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name) - && _Jv_equalUtf8Consts (klass->methods[i].signature, utf_sig)) - { - // Found it. - using namespace java::lang::reflect; - - // FIXME: Method must be public. Throw an exception? - if (! Modifier::isPublic (klass->methods[i].accflags)) - break; - - found_class = klass; - // Interface method indexes count from 1. - index = offset + 1; - return true; - } - - ++offset; - } - } - - // If we haven't found a match, and this class is an interface, then - // check all the superinterfaces. - if (search_class->isInterface()) - { - for (int i = 0; i < search_class->interface_count; ++i) - { - using namespace java::lang::reflect; - bool found = _Jv_getInterfaceMethod (search_class->interfaces[i], - found_class, index, - utf_name, utf_sig); - if (found) - return true; - } - } - - return false; -} - -#ifdef INTERPRETER -_Jv_MethodBase * -_Jv_FindInterpreterMethod (jclass klass, jmethodID desired_method) -{ - using namespace java::lang::reflect; - - _Jv_InterpClass *iclass - = reinterpret_cast<_Jv_InterpClass *> (klass->aux_info); - _Jv_MethodBase **imethods = _Jv_GetFirstMethod (iclass); - - for (int i = 0; i < JvNumMethods (klass); ++i) - { - _Jv_MethodBase *imeth = imethods[i]; - if (imeth->get_method () == desired_method) - return imeth; - } - - return NULL; -} -#endif - -// Return Utf8 name of a class. This function is here for code that -// can't access klass->name directly. -_Jv_Utf8Const* -_Jv_GetClassNameUtf8 (jclass klass) -{ - return klass->name; -} - -jclass -_Jv_GetMethodDeclaringClass (jmethodID method) -{ - _Jv_StackTrace::UpdateNCodeMap (); - jobject obj = reinterpret_cast<jobject> (method->ncode); - return reinterpret_cast<jclass> (_Jv_StackTrace::ncodeMap->get (obj)); -} - -jbyte -_Jv_GetClassState (jclass klass) -{ - return klass->state; -} - -#ifdef INTERPRETER -jstring -_Jv_GetInterpClassSourceFile (jclass klass) -{ - if (_Jv_IsInterpretedClass (klass)) - { - _Jv_InterpClass *iclass = - reinterpret_cast<_Jv_InterpClass *> (klass->aux_info); - return iclass->source_file_name; - } - - return NULL; -} -#endif |