1 // natClass.cc - Implementation of java.lang.Class native methods.
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
4 Free Software Foundation
6 This file is part of libgcj.
8 This software is copyrighted work licensed under the terms of the
9 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
18 #pragma implementation "Class.h"
22 #include <java-threads.h>
24 #include <java/lang/Class.h>
25 #include <java/lang/ClassLoader.h>
26 #include <java/lang/String.h>
27 #include <java/lang/reflect/Modifier.h>
28 #include <java/lang/reflect/Member.h>
29 #include <java/lang/reflect/Method.h>
30 #include <java/lang/reflect/Field.h>
31 #include <java/lang/reflect/Constructor.h>
32 #include <java/lang/AbstractMethodError.h>
33 #include <java/lang/ArrayStoreException.h>
34 #include <java/lang/ClassCastException.h>
35 #include <java/lang/ClassNotFoundException.h>
36 #include <java/lang/ExceptionInInitializerError.h>
37 #include <java/lang/IllegalAccessException.h>
38 #include <java/lang/IllegalAccessError.h>
39 #include <java/lang/IllegalArgumentException.h>
40 #include <java/lang/IncompatibleClassChangeError.h>
41 #include <java/lang/NoSuchFieldError.h>
42 #include <java/lang/ArrayIndexOutOfBoundsException.h>
43 #include <java/lang/InstantiationException.h>
44 #include <java/lang/NoClassDefFoundError.h>
45 #include <java/lang/NoSuchFieldException.h>
46 #include <java/lang/NoSuchMethodError.h>
47 #include <java/lang/NoSuchMethodException.h>
48 #include <java/lang/Thread.h>
49 #include <java/lang/NullPointerException.h>
50 #include <java/lang/RuntimePermission.h>
51 #include <java/lang/System.h>
52 #include <java/lang/SecurityManager.h>
53 #include <java/lang/StringBuffer.h>
54 #include <java/lang/VMClassLoader.h>
55 #include <gnu/gcj/runtime/StackTrace.h>
56 #include <gcj/method.h>
57 #include <gnu/gcj/runtime/MethodRef.h>
58 #include <gnu/gcj/RawData.h>
60 #include <java-cpool.h>
61 #include <java-interp.h>
67 bool gcj::verbose_class_flag;
70 java::lang::Class::forName (jstring className, jboolean initialize,
71 java::lang::ClassLoader *loader)
74 throw new java::lang::NullPointerException;
76 jsize length = _Jv_GetStringUTFLength (className);
78 _Jv_GetStringUTFRegion (className, 0, className->length(), buffer);
80 _Jv_Utf8Const *name = _Jv_makeUtf8Const (buffer, length);
82 if (! _Jv_VerifyClassName (name))
83 throw new java::lang::ClassNotFoundException (className);
85 jclass klass = (buffer[0] == '['
86 ? _Jv_FindClassFromSignature (name->data, loader)
87 : _Jv_FindClass (name, loader));
90 throw new java::lang::ClassNotFoundException (className);
93 _Jv_InitClass (klass);
99 java::lang::Class::forName (jstring className)
101 java::lang::ClassLoader *loader = NULL;
102 gnu::gcj::runtime::StackTrace *t
103 = new gnu::gcj::runtime::StackTrace(4);
104 java::lang::Class *klass = NULL;
107 for (int i = 1; !klass; i++)
109 klass = t->classAt (i);
111 loader = klass->getClassLoaderInternal();
113 catch (::java::lang::ArrayIndexOutOfBoundsException *e)
117 return forName (className, true, loader);
120 java::lang::ClassLoader *
121 java::lang::Class::getClassLoader (void)
123 java::lang::SecurityManager *s = java::lang::System::getSecurityManager();
126 gnu::gcj::runtime::StackTrace *t
127 = new gnu::gcj::runtime::StackTrace(4);
128 Class *caller = NULL;
129 ClassLoader *caller_loader = NULL;
132 for (int i = 1; !caller; i++)
134 caller = t->classAt (i);
136 caller_loader = caller->getClassLoaderInternal();
138 catch (::java::lang::ArrayIndexOutOfBoundsException *e)
142 // If the caller has a non-null class loader, and that loader
143 // is not this class' loader or an ancestor thereof, then do a
145 if (caller_loader != NULL && ! caller_loader->isAncestorOf(loader))
146 s->checkPermission (new RuntimePermission (JvNewStringLatin1 ("getClassLoader")));
149 // The spec requires us to return `null' for primitive classes. In
150 // other cases we have the option of returning `null' for classes
151 // loaded with the bootstrap loader. All gcj-compiled classes which
152 // are linked into the application used to return `null' here, but
153 // that confuses some poorly-written applications. It is a useful
154 // and apparently harmless compatibility hack to simply never return
158 return loader ? loader : ClassLoader::systemClassLoader;
161 java::lang::reflect::Constructor *
162 java::lang::Class::getConstructor (JArray<jclass> *param_types)
164 memberAccessCheck(java::lang::reflect::Member::PUBLIC);
166 jstring partial_sig = getSignature (param_types, true);
167 jint hash = partial_sig->hashCode ();
169 int i = isPrimitive () ? 0 : method_count;
172 if (_Jv_equalUtf8Consts (methods[i].name, init_name)
173 && _Jv_equal (methods[i].signature, partial_sig, hash))
175 // Found it. For getConstructor, the constructor must be
177 using namespace java::lang::reflect;
178 if (! Modifier::isPublic(methods[i].accflags))
180 Constructor *cons = new Constructor ();
181 cons->offset = (char *) (&methods[i]) - (char *) methods;
182 cons->declaringClass = this;
186 throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
189 JArray<java::lang::reflect::Constructor *> *
190 java::lang::Class::_getConstructors (jboolean declared)
192 memberAccessCheck(java::lang::reflect::Member::PUBLIC);
194 int numConstructors = 0;
195 int max = isPrimitive () ? 0 : method_count;
197 for (i = max; --i >= 0; )
199 _Jv_Method *method = &methods[i];
200 if (method->name == NULL
201 || ! _Jv_equalUtf8Consts (method->name, init_name))
204 && ! java::lang::reflect::Modifier::isPublic(method->accflags))
208 JArray<java::lang::reflect::Constructor *> *result
209 = (JArray<java::lang::reflect::Constructor *> *)
210 JvNewObjectArray (numConstructors,
211 &java::lang::reflect::Constructor::class$,
213 java::lang::reflect::Constructor** cptr = elements (result);
214 for (i = 0; i < max; i++)
216 _Jv_Method *method = &methods[i];
217 if (method->name == NULL
218 || ! _Jv_equalUtf8Consts (method->name, init_name))
221 && ! java::lang::reflect::Modifier::isPublic(method->accflags))
223 java::lang::reflect::Constructor *cons
224 = new java::lang::reflect::Constructor ();
225 cons->offset = (char *) method - (char *) methods;
226 cons->declaringClass = this;
232 java::lang::reflect::Constructor *
233 java::lang::Class::getDeclaredConstructor (JArray<jclass> *param_types)
235 memberAccessCheck(java::lang::reflect::Member::DECLARED);
237 jstring partial_sig = getSignature (param_types, true);
238 jint hash = partial_sig->hashCode ();
240 int i = isPrimitive () ? 0 : method_count;
243 if (_Jv_equalUtf8Consts (methods[i].name, init_name)
244 && _Jv_equal (methods[i].signature, partial_sig, hash))
247 using namespace java::lang::reflect;
248 Constructor *cons = new Constructor ();
249 cons->offset = (char *) (&methods[i]) - (char *) methods;
250 cons->declaringClass = this;
254 throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
257 java::lang::reflect::Field *
258 java::lang::Class::getField (jstring name, jint hash)
260 java::lang::reflect::Field* rfield;
261 for (int i = 0; i < field_count; i++)
263 _Jv_Field *field = &fields[i];
264 if (! _Jv_equal (field->name, name, hash))
266 if (! (field->getModifiers() & java::lang::reflect::Modifier::PUBLIC))
268 rfield = new java::lang::reflect::Field ();
269 rfield->offset = (char*) field - (char*) fields;
270 rfield->declaringClass = this;
274 jclass superclass = getSuperclass();
275 if (superclass == NULL)
277 rfield = superclass->getField(name, hash);
278 for (int i = 0; i < interface_count && rfield == NULL; ++i)
279 rfield = interfaces[i]->getField (name, hash);
283 java::lang::reflect::Field *
284 java::lang::Class::getDeclaredField (jstring name)
286 memberAccessCheck(java::lang::reflect::Member::DECLARED);
287 int hash = name->hashCode();
288 for (int i = 0; i < field_count; i++)
290 _Jv_Field *field = &fields[i];
291 if (! _Jv_equal (field->name, name, hash))
293 java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
294 rfield->offset = (char*) field - (char*) fields;
295 rfield->declaringClass = this;
299 throw new java::lang::NoSuchFieldException (name);
302 JArray<java::lang::reflect::Field *> *
303 java::lang::Class::getDeclaredFields (jboolean public_only)
309 for (int i = 0; i < field_count; ++i)
311 _Jv_Field *field = &fields[i];
312 if ((field->flags & java::lang::reflect::Modifier::PUBLIC))
319 JArray<java::lang::reflect::Field *> *result
320 = (JArray<java::lang::reflect::Field *> *)
321 JvNewObjectArray (size, &java::lang::reflect::Field::class$, NULL);
322 java::lang::reflect::Field** fptr = elements (result);
323 for (int i = 0; i < field_count; i++)
325 _Jv_Field *field = &fields[i];
327 && ! (field->flags & java::lang::reflect::Modifier::PUBLIC))
329 java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
330 rfield->offset = (char*) field - (char*) fields;
331 rfield->declaringClass = this;
338 java::lang::Class::getSignature (java::lang::StringBuffer *buffer)
341 buffer->append((jchar) method_count);
344 jstring name = getName();
345 if (name->charAt(0) != '[')
346 buffer->append((jchar) 'L');
347 buffer->append(name);
348 if (name->charAt(0) != '[')
349 buffer->append((jchar) ';');
353 // This doesn't have to be native. It is an implementation detail
354 // only called from the C++ code, though, so maybe this is clearer.
356 java::lang::Class::getSignature (JArray<jclass> *param_types,
357 jboolean is_constructor)
359 java::lang::StringBuffer *buf = new java::lang::StringBuffer ();
360 buf->append((jchar) '(');
361 // A NULL param_types means "no parameters".
362 if (param_types != NULL)
364 jclass *v = elements (param_types);
365 for (int i = 0; i < param_types->length; ++i)
366 v[i]->getSignature(buf);
368 buf->append((jchar) ')');
370 buf->append((jchar) 'V');
371 return buf->toString();
374 java::lang::reflect::Method *
375 java::lang::Class::_getDeclaredMethod (jstring name,
376 JArray<jclass> *param_types)
378 jstring partial_sig = getSignature (param_types, false);
379 jint p_len = partial_sig->length();
380 _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
381 int i = isPrimitive () ? 0 : method_count;
384 if (_Jv_equalUtf8Consts (methods[i].name, utf_name)
385 && _Jv_equaln (methods[i].signature, partial_sig, p_len)
386 && (methods[i].accflags
387 & java::lang::reflect::Modifier::INVISIBLE) == 0)
390 using namespace java::lang::reflect;
391 Method *rmethod = new Method ();
392 rmethod->offset = (char*) (&methods[i]) - (char*) methods;
393 rmethod->declaringClass = this;
400 JArray<java::lang::reflect::Method *> *
401 java::lang::Class::getDeclaredMethods (void)
403 memberAccessCheck(java::lang::reflect::Member::DECLARED);
406 int max = isPrimitive () ? 0 : method_count;
408 for (i = max; --i >= 0; )
410 _Jv_Method *method = &methods[i];
411 if (method->name == NULL
412 || _Jv_equalUtf8Consts (method->name, clinit_name)
413 || _Jv_equalUtf8Consts (method->name, init_name)
414 || _Jv_equalUtf8Consts (method->name, finit_name)
415 || (methods[i].accflags
416 & java::lang::reflect::Modifier::INVISIBLE) != 0)
420 JArray<java::lang::reflect::Method *> *result
421 = (JArray<java::lang::reflect::Method *> *)
422 JvNewObjectArray (numMethods, &java::lang::reflect::Method::class$, NULL);
423 java::lang::reflect::Method** mptr = elements (result);
424 for (i = 0; i < max; i++)
426 _Jv_Method *method = &methods[i];
427 if (method->name == NULL
428 || _Jv_equalUtf8Consts (method->name, clinit_name)
429 || _Jv_equalUtf8Consts (method->name, init_name)
430 || _Jv_equalUtf8Consts (method->name, finit_name)
431 || (methods[i].accflags
432 & java::lang::reflect::Modifier::INVISIBLE) != 0)
434 java::lang::reflect::Method* rmethod
435 = new java::lang::reflect::Method ();
436 rmethod->offset = (char*) method - (char*) methods;
437 rmethod->declaringClass = this;
444 java::lang::Class::getName (void)
446 char buffer[name->length + 1];
447 memcpy (buffer, name->data, name->length);
448 buffer[name->length] = '\0';
449 return _Jv_NewStringUTF (buffer);
453 java::lang::Class::getClasses (void)
455 // FIXME: security checking.
457 // Until we have inner classes, it always makes sense to return an
459 JArray<jclass> *result
460 = (JArray<jclass> *) JvNewObjectArray (0, &java::lang::Class::class$,
466 java::lang::Class::getDeclaredClasses (void)
468 memberAccessCheck (java::lang::reflect::Member::DECLARED);
469 // Until we have inner classes, it always makes sense to return an
471 JArray<jclass> *result
472 = (JArray<jclass> *) JvNewObjectArray (0, &java::lang::Class::class$,
478 java::lang::Class::getDeclaringClass (void)
480 // Until we have inner classes, it makes sense to always return
486 java::lang::Class::getInterfaces (void)
488 jobjectArray r = JvNewObjectArray (interface_count, getClass (), NULL);
489 jobject *data = elements (r);
490 for (int i = 0; i < interface_count; ++i)
491 data[i] = interfaces[i];
492 return reinterpret_cast<JArray<jclass> *> (r);
495 java::lang::reflect::Method *
496 java::lang::Class::_getMethod (jstring name, JArray<jclass> *param_types)
498 jstring partial_sig = getSignature (param_types, false);
499 jint p_len = partial_sig->length();
500 _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
501 for (Class *klass = this; klass; klass = klass->getSuperclass())
503 int i = klass->isPrimitive () ? 0 : klass->method_count;
506 if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
507 && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len)
508 && (klass->methods[i].accflags
509 & java::lang::reflect::Modifier::INVISIBLE) == 0)
512 using namespace java::lang::reflect;
514 // Method must be public.
515 if (! Modifier::isPublic (klass->methods[i].accflags))
518 Method *rmethod = new Method ();
519 rmethod->offset = ((char *) (&klass->methods[i])
520 - (char *) klass->methods);
521 rmethod->declaringClass = klass;
527 // If we haven't found a match, and this class is an interface, then
528 // check all the superinterfaces.
531 for (int i = 0; i < interface_count; ++i)
533 using namespace java::lang::reflect;
534 Method *rmethod = interfaces[i]->_getMethod (name, param_types);
543 // This is a very slow implementation, since it re-scans all the
544 // methods we've already listed to make sure we haven't duplicated a
545 // method. It also over-estimates the required size, so we have to
546 // shrink the result array later.
548 java::lang::Class::_getMethods (JArray<java::lang::reflect::Method *> *result,
553 // First examine all local methods
554 for (int i = isPrimitive () ? 0 : method_count; --i >= 0; )
556 _Jv_Method *method = &methods[i];
557 if (method->name == NULL
558 || _Jv_equalUtf8Consts (method->name, clinit_name)
559 || _Jv_equalUtf8Consts (method->name, init_name)
560 || _Jv_equalUtf8Consts (method->name, finit_name)
562 & java::lang::reflect::Modifier::INVISIBLE) != 0)
564 // Only want public methods.
565 if (! java::lang::reflect::Modifier::isPublic (method->accflags))
568 // This is where we over-count the slots required if we aren't
569 // filling the result for real.
573 java::lang::reflect::Method **mp = elements (result);
574 // If we already have a method with this name and signature,
575 // then ignore this one. This can happen with virtual
577 for (int j = 0; j < offset; ++j)
579 _Jv_Method *meth_2 = _Jv_FromReflectedMethod (mp[j]);
580 if (_Jv_equalUtf8Consts (method->name, meth_2->name)
581 && _Jv_equalUtf8Consts (method->signature,
594 using namespace java::lang::reflect;
595 Method *rmethod = new Method ();
596 rmethod->offset = (char *) method - (char *) methods;
597 rmethod->declaringClass = this;
598 Method **mp = elements (result);
599 mp[offset + count] = rmethod;
605 // Now examine superclasses.
606 if (getSuperclass () != NULL)
608 jint s_count = getSuperclass()->_getMethods (result, offset);
613 // Finally, examine interfaces.
614 for (int i = 0; i < interface_count; ++i)
616 int f_count = interfaces[i]->_getMethods (result, offset);
624 JArray<java::lang::reflect::Method *> *
625 java::lang::Class::getMethods (void)
627 using namespace java::lang::reflect;
629 memberAccessCheck(Member::PUBLIC);
631 // This will overestimate the size we need.
632 jint count = _getMethods (NULL, 0);
634 JArray<Method *> *result
635 = ((JArray<Method *> *) JvNewObjectArray (count,
639 // When filling the array for real, we get the actual count. Then
640 // we resize the array.
641 jint real_count = _getMethods (result, 0);
643 if (real_count != count)
646 = ((JArray<Method *> *) JvNewObjectArray (real_count,
650 Method **destp = elements (r2);
651 Method **srcp = elements (result);
653 for (int i = 0; i < real_count; ++i)
663 java::lang::Class::isAssignableFrom (jclass klass)
665 // Arguments may not have been initialized, given ".class" syntax.
666 _Jv_InitClass (this);
667 _Jv_InitClass (klass);
668 return _Jv_IsAssignableFrom (this, klass);
672 java::lang::Class::isInstance (jobject obj)
676 _Jv_InitClass (this);
677 return _Jv_IsAssignableFrom (this, JV_CLASS (obj));
681 java::lang::Class::newInstance (void)
683 memberAccessCheck(java::lang::reflect::Member::PUBLIC);
688 || java::lang::reflect::Modifier::isAbstract(accflags))
689 throw new java::lang::InstantiationException (getName ());
691 _Jv_InitClass (this);
693 _Jv_Method *meth = _Jv_GetMethodLocal (this, init_name, void_signature);
695 throw new java::lang::InstantiationException (getName());
697 jobject r = _Jv_AllocObject (this);
698 ((void (*) (jobject)) meth->ncode) (r);
703 java::lang::Class::finalize (void)
706 JvAssert (_Jv_IsInterpretedClass (this));
707 _Jv_UnregisterClass (this);
711 // This implements the initialization process for a class. From Spec
714 java::lang::Class::initializeClass (void)
716 // short-circuit to avoid needless locking.
717 if (state == JV_STATE_DONE)
721 _Jv_MonitorEnter (this);
723 if (state < JV_STATE_LINKED)
726 if (_Jv_IsInterpretedClass (this))
728 // this can throw exceptions, so exit the monitor as a precaution.
729 _Jv_MonitorExit (this);
730 java::lang::VMClassLoader::resolveClass (this);
731 _Jv_MonitorEnter (this);
736 _Jv_PrepareCompiledClass (this);
741 java::lang::Thread *self = java::lang::Thread::currentThread();
742 // FIXME: `self' can be null at startup. Hence this nasty trick.
743 self = (java::lang::Thread *) ((long) self | 1);
744 while (state == JV_STATE_IN_PROGRESS && thread && thread != self)
748 if (state == JV_STATE_DONE)
750 _Jv_MonitorExit (this);
753 if (state == JV_STATE_IN_PROGRESS)
755 _Jv_MonitorExit (this);
757 /* Initialization in progress. The class is linked now,
758 so ensure internal tables are built. */
759 _Jv_PrepareConstantTimeTables (this);
760 _Jv_MakeVTable(this);
761 _Jv_LinkSymbolTable(this);
767 if (state == JV_STATE_ERROR)
769 _Jv_MonitorExit (this);
770 throw new java::lang::NoClassDefFoundError (getName());
775 state = JV_STATE_IN_PROGRESS;
776 _Jv_MonitorExit (this);
779 if (! isInterface () && superclass)
783 _Jv_InitClass (superclass);
785 catch (java::lang::Throwable *except)
787 // Caught an exception.
788 _Jv_MonitorEnter (this);
789 state = JV_STATE_ERROR;
791 _Jv_MonitorExit (this);
796 _Jv_PrepareConstantTimeTables (this);
799 _Jv_MakeVTable(this);
801 if (otable || atable)
802 _Jv_LinkSymbolTable(this);
804 _Jv_linkExceptionClassTable (this);
806 // Steps 8, 9, 10, 11.
809 _Jv_Method *meth = _Jv_GetMethodLocal (this, clinit_name,
812 ((void (*) (void)) meth->ncode) ();
814 catch (java::lang::Throwable *except)
816 if (! java::lang::Error::class$.isInstance(except))
820 except = new ExceptionInInitializerError (except);
822 catch (java::lang::Throwable *t)
827 _Jv_MonitorEnter (this);
828 state = JV_STATE_ERROR;
830 _Jv_MonitorExit (this);
834 _Jv_MonitorEnter (this);
835 state = JV_STATE_DONE;
837 _Jv_MonitorExit (this);
843 // Some class-related convenience functions.
846 // Find a method declared in the class. If it is not declared locally
847 // (or if it is inherited), return NULL.
849 _Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
850 _Jv_Utf8Const *signature)
852 for (int i = 0; i < klass->method_count; ++i)
854 if (_Jv_equalUtf8Consts (name, klass->methods[i].name)
855 && _Jv_equalUtf8Consts (signature, klass->methods[i].signature))
856 return &klass->methods[i];
862 _Jv_LookupDeclaredMethod (jclass klass, _Jv_Utf8Const *name,
863 _Jv_Utf8Const *signature)
865 for (; klass; klass = klass->getSuperclass())
867 _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
876 // NOTE: MCACHE_SIZE should be a power of 2 minus one.
877 #define MCACHE_SIZE 1023
885 static _Jv_mcache method_cache[MCACHE_SIZE + 1];
888 _Jv_FindMethodInCache (jclass klass,
890 _Jv_Utf8Const *signature)
892 int index = name->hash & MCACHE_SIZE;
893 _Jv_mcache *mc = method_cache + index;
894 _Jv_Method *m = mc->method;
896 if (mc->klass == klass
897 && m != NULL // thread safe check
898 && _Jv_equalUtf8Consts (m->name, name)
899 && _Jv_equalUtf8Consts (m->signature, signature))
900 return mc->method->ncode;
905 _Jv_AddMethodToCache (jclass klass,
908 _Jv_MonitorEnter (&java::lang::Class::class$);
910 int index = method->name->hash & MCACHE_SIZE;
912 method_cache[index].method = method;
913 method_cache[index].klass = klass;
915 _Jv_MonitorExit (&java::lang::Class::class$);
919 _Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name,
920 _Jv_Utf8Const *signature)
922 using namespace java::lang::reflect;
924 void *ncode = _Jv_FindMethodInCache (klass, name, signature);
928 for (; klass; klass = klass->getSuperclass())
930 _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
934 if (Modifier::isStatic(meth->accflags))
935 throw new java::lang::IncompatibleClassChangeError
936 (_Jv_GetMethodString (klass, meth->name));
937 if (Modifier::isAbstract(meth->accflags))
938 throw new java::lang::AbstractMethodError
939 (_Jv_GetMethodString (klass, meth->name));
940 if (! Modifier::isPublic(meth->accflags))
941 throw new java::lang::IllegalAccessError
942 (_Jv_GetMethodString (klass, meth->name));
944 _Jv_AddMethodToCache (klass, meth);
948 throw new java::lang::IncompatibleClassChangeError;
951 // Fast interface method lookup by index.
953 _Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface, int method_idx)
955 _Jv_IDispatchTable *cldt = klass->idt;
956 int idx = iface->idt->iface.ioffsets[cldt->cls.iindex] + method_idx;
957 return cldt->cls.itable[idx];
961 _Jv_IsAssignableFrom (jclass target, jclass source)
963 if (source == target)
966 // If target is array, so must source be.
967 while (target->isArray ())
969 if (! source->isArray())
971 target = target->getComponentType();
972 source = source->getComponentType();
975 if (target->isInterface())
977 // Abstract classes have no IDT, and IDTs provide no way to check
978 // two interfaces for assignability.
980 (source->idt == NULL || source->isInterface(), false))
981 return _Jv_InterfaceAssignableFrom (target, source);
983 _Jv_IDispatchTable *cl_idt = source->idt;
984 _Jv_IDispatchTable *if_idt = target->idt;
986 if (__builtin_expect ((if_idt == NULL), false))
987 return false; // No class implementing TARGET has been loaded.
988 jshort cl_iindex = cl_idt->cls.iindex;
989 if (cl_iindex < if_idt->iface.ioffsets[0])
991 jshort offset = if_idt->iface.ioffsets[cl_iindex];
992 if (offset != -1 && offset < cl_idt->cls.itable_length
993 && cl_idt->cls.itable[offset] == target)
999 // Primitive TYPE classes are only assignable to themselves.
1000 if (__builtin_expect (target->isPrimitive() || source->isPrimitive(), false))
1003 if (target == &java::lang::Object::class$)
1005 else if (source->ancestors == NULL || target->ancestors == NULL)
1007 // We need this case when either SOURCE or TARGET has not has
1008 // its constant-time tables prepared.
1010 // At this point we know that TARGET can't be Object, so it is
1011 // safe to use that as the termination point.
1012 while (source && source != &java::lang::Object::class$)
1014 if (source == target)
1016 source = source->getSuperclass();
1019 else if (source->depth >= target->depth
1020 && source->ancestors[source->depth - target->depth] == target)
1026 // Interface type checking, the slow way. Returns TRUE if IFACE is a
1027 // superinterface of SOURCE. This is used when SOURCE is also an interface,
1028 // or a class with no interface dispatch table.
1030 _Jv_InterfaceAssignableFrom (jclass iface, jclass source)
1032 for (int i = 0; i < source->interface_count; i++)
1034 jclass interface = source->interfaces[i];
1035 if (iface == interface
1036 || _Jv_InterfaceAssignableFrom (iface, interface))
1040 if (!source->isInterface()
1041 && source->superclass
1042 && _Jv_InterfaceAssignableFrom (iface, source->superclass))
1049 _Jv_IsInstanceOf(jobject obj, jclass cl)
1051 if (__builtin_expect (!obj, false))
1053 return (_Jv_IsAssignableFrom (cl, JV_CLASS (obj)));
1057 _Jv_CheckCast (jclass c, jobject obj)
1059 if (__builtin_expect
1060 (obj != NULL && ! _Jv_IsAssignableFrom(c, JV_CLASS (obj)), false))
1061 throw new java::lang::ClassCastException
1062 ((new java::lang::StringBuffer
1063 (obj->getClass()->getName()))->append
1064 (JvNewStringUTF(" cannot be cast to "))->append
1065 (c->getName())->toString());
1071 _Jv_CheckArrayStore (jobject arr, jobject obj)
1075 JvAssert (arr != NULL);
1076 jclass elt_class = (JV_CLASS (arr))->getComponentType();
1077 if (elt_class == &java::lang::Object::class$)
1079 jclass obj_class = JV_CLASS (obj);
1080 if (__builtin_expect
1081 (! _Jv_IsAssignableFrom (elt_class, obj_class), false))
1082 throw new java::lang::ArrayStoreException
1083 ((new java::lang::StringBuffer
1084 (JvNewStringUTF("Cannot store ")))->append
1085 (obj_class->getName())->append
1086 (JvNewStringUTF(" in array of type "))->append
1087 (elt_class->getName())->toString());
1091 #define INITIAL_IOFFSETS_LEN 4
1092 #define INITIAL_IFACES_LEN 4
1094 static _Jv_IDispatchTable null_idt = { {SHRT_MAX, 0, NULL} };
1096 // Generate tables for constant-time assignment testing and interface
1097 // method lookup. This implements the technique described by Per Bothner
1098 // <per@bothner.com> on the java-discuss mailing list on 1999-09-02:
1099 // http://gcc.gnu.org/ml/java/1999-q3/msg00377.html
1101 _Jv_PrepareConstantTimeTables (jclass klass)
1103 if (klass->isPrimitive () || klass->isInterface ())
1106 // Short-circuit in case we've been called already.
1107 if ((klass->idt != NULL) || klass->depth != 0)
1110 // Calculate the class depth and ancestor table. The depth of a class
1111 // is how many "extends" it is removed from Object. Thus the depth of
1112 // java.lang.Object is 0, but the depth of java.io.FilterOutputStream
1113 // is 2. Depth is defined for all regular and array classes, but not
1114 // interfaces or primitive types.
1116 jclass klass0 = klass;
1117 jboolean has_interfaces = 0;
1118 while (klass0 != &java::lang::Object::class$)
1120 has_interfaces += klass0->interface_count;
1121 klass0 = klass0->superclass;
1125 // We do class member testing in constant time by using a small table
1126 // of all the ancestor classes within each class. The first element is
1127 // a pointer to the current class, and the rest are pointers to the
1128 // classes ancestors, ordered from the current class down by decreasing
1129 // depth. We do not include java.lang.Object in the table of ancestors,
1130 // since it is redundant.
1132 klass->ancestors = (jclass *) _Jv_Malloc (klass->depth * sizeof (jclass));
1134 for (int index = 0; index < klass->depth; index++)
1136 klass->ancestors[index] = klass0;
1137 klass0 = klass0->superclass;
1140 if (java::lang::reflect::Modifier::isAbstract (klass->accflags))
1143 // Optimization: If class implements no interfaces, use a common
1144 // predefined interface table.
1145 if (!has_interfaces)
1147 klass->idt = &null_idt;
1152 (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable));
1157 ifaces.len = INITIAL_IFACES_LEN;
1158 ifaces.list = (jclass *) _Jv_Malloc (ifaces.len * sizeof (jclass *));
1160 int itable_size = _Jv_GetInterfaces (klass, &ifaces);
1162 if (ifaces.count > 0)
1164 klass->idt->cls.itable =
1165 (void **) _Jv_Malloc (itable_size * sizeof (void *));
1166 klass->idt->cls.itable_length = itable_size;
1168 jshort *itable_offsets =
1169 (jshort *) _Jv_Malloc (ifaces.count * sizeof (jshort));
1171 _Jv_GenerateITable (klass, &ifaces, itable_offsets);
1174 _Jv_FindIIndex (ifaces.list, itable_offsets, ifaces.count);
1176 for (int i=0; i < ifaces.count; i++)
1178 ifaces.list[i]->idt->iface.ioffsets[cls_iindex] =
1182 klass->idt->cls.iindex = cls_iindex;
1184 _Jv_Free (ifaces.list);
1185 _Jv_Free (itable_offsets);
1189 klass->idt->cls.iindex = SHRT_MAX;
1193 // Return index of item in list, or -1 if item is not present.
1195 _Jv_IndexOf (void *item, void **list, jshort list_len)
1197 for (int i=0; i < list_len; i++)
1199 if (list[i] == item)
1205 // Find all unique interfaces directly or indirectly implemented by klass.
1206 // Returns the size of the interface dispatch table (itable) for klass, which
1207 // is the number of unique interfaces plus the total number of methods that
1208 // those interfaces declare. May extend ifaces if required.
1210 _Jv_GetInterfaces (jclass klass, _Jv_ifaces *ifaces)
1214 for (int i=0; i < klass->interface_count; i++)
1216 jclass iface = klass->interfaces[i];
1218 /* Make sure interface is linked. */
1219 _Jv_WaitForState(iface, JV_STATE_LINKED);
1221 if (_Jv_IndexOf (iface, (void **) ifaces->list, ifaces->count) == -1)
1223 if (ifaces->count + 1 >= ifaces->len)
1225 /* Resize ifaces list */
1226 ifaces->len = ifaces->len * 2;
1227 ifaces->list = (jclass *) _Jv_Realloc (ifaces->list,
1228 ifaces->len * sizeof(jclass));
1230 ifaces->list[ifaces->count] = iface;
1233 result += _Jv_GetInterfaces (klass->interfaces[i], ifaces);
1237 if (klass->isInterface())
1239 result += klass->method_count + 1;
1243 if (klass->superclass)
1245 result += _Jv_GetInterfaces (klass->superclass, ifaces);
1251 // Fill out itable in klass, resolving method declarations in each ifaces.
1252 // itable_offsets is filled out with the position of each iface in itable,
1253 // such that itable[itable_offsets[n]] == ifaces.list[n].
1255 _Jv_GenerateITable (jclass klass, _Jv_ifaces *ifaces, jshort *itable_offsets)
1257 void **itable = klass->idt->cls.itable;
1258 jshort itable_pos = 0;
1260 for (int i=0; i < ifaces->count; i++)
1262 jclass iface = ifaces->list[i];
1263 itable_offsets[i] = itable_pos;
1264 itable_pos = _Jv_AppendPartialITable (klass, iface, itable, itable_pos);
1266 /* Create interface dispatch table for iface */
1267 if (iface->idt == NULL)
1270 (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable));
1272 // The first element of ioffsets is its length (itself included).
1274 (jshort *) _Jv_Malloc (INITIAL_IOFFSETS_LEN * sizeof (jshort));
1275 ioffsets[0] = INITIAL_IOFFSETS_LEN;
1276 for (int i=1; i < INITIAL_IOFFSETS_LEN; i++)
1279 iface->idt->iface.ioffsets = ioffsets;
1284 // Format method name for use in error messages.
1286 _Jv_GetMethodString (jclass klass, _Jv_Utf8Const *name)
1288 jstring r = JvNewStringUTF (klass->name->data);
1289 r = r->concat (JvNewStringUTF ("."));
1290 r = r->concat (JvNewStringUTF (name->data));
1295 _Jv_ThrowNoSuchMethodError ()
1297 throw new java::lang::NoSuchMethodError;
1300 // Each superinterface of a class (i.e. each interface that the class
1301 // directly or indirectly implements) has a corresponding "Partial
1302 // Interface Dispatch Table" whose size is (number of methods + 1) words.
1303 // The first word is a pointer to the interface (i.e. the java.lang.Class
1304 // instance for that interface). The remaining words are pointers to the
1305 // actual methods that implement the methods declared in the interface,
1306 // in order of declaration.
1308 // Append partial interface dispatch table for "iface" to "itable", at
1309 // position itable_pos.
1310 // Returns the offset at which the next partial ITable should be appended.
1312 _Jv_AppendPartialITable (jclass klass, jclass iface, void **itable,
1315 using namespace java::lang::reflect;
1317 itable[pos++] = (void *) iface;
1320 for (int j=0; j < iface->method_count; j++)
1323 for (jclass cl = klass; cl; cl = cl->getSuperclass())
1325 meth = _Jv_GetMethodLocal (cl, iface->methods[j].name,
1326 iface->methods[j].signature);
1332 if (meth && (meth->name->data[0] == '<'))
1334 // leave a placeholder in the itable for hidden init methods.
1339 if (Modifier::isStatic(meth->accflags))
1340 throw new java::lang::IncompatibleClassChangeError
1341 (_Jv_GetMethodString (klass, meth->name));
1342 if (Modifier::isAbstract(meth->accflags))
1343 throw new java::lang::AbstractMethodError
1344 (_Jv_GetMethodString (klass, meth->name));
1345 if (! Modifier::isPublic(meth->accflags))
1346 throw new java::lang::IllegalAccessError
1347 (_Jv_GetMethodString (klass, meth->name));
1349 itable[pos] = meth->ncode;
1353 // The method doesn't exist in klass. Binary compatibility rules
1354 // permit this, so we delay the error until runtime using a pointer
1355 // to a method which throws an exception.
1356 itable[pos] = (void *) _Jv_ThrowNoSuchMethodError;
1364 static _Jv_Mutex_t iindex_mutex;
1365 static bool iindex_mutex_initialized = false;
1367 // We need to find the correct offset in the Class Interface Dispatch
1368 // Table for a given interface. Once we have that, invoking an interface
1369 // method just requires combining the Method's index in the interface
1370 // (known at compile time) to get the correct method. Doing a type test
1371 // (cast or instanceof) is the same problem: Once we have a possible Partial
1372 // Interface Dispatch Table, we just compare the first element to see if it
1373 // matches the desired interface. So how can we find the correct offset?
1374 // Our solution is to keep a vector of candiate offsets in each interface
1375 // (idt->iface.ioffsets), and in each class we have an index
1376 // (idt->cls.iindex) used to select the correct offset from ioffsets.
1378 // Calculate and return iindex for a new class.
1379 // ifaces is a vector of num interfaces that the class implements.
1380 // offsets[j] is the offset in the interface dispatch table for the
1381 // interface corresponding to ifaces[j].
1382 // May extend the interface ioffsets if required.
1384 _Jv_FindIIndex (jclass *ifaces, jshort *offsets, jshort num)
1389 // Acquire a global lock to prevent itable corruption in case of multiple
1390 // classes that implement an intersecting set of interfaces being linked
1391 // simultaneously. We can assume that the mutex will be initialized
1393 if (! iindex_mutex_initialized)
1395 _Jv_MutexInit (&iindex_mutex);
1396 iindex_mutex_initialized = true;
1399 _Jv_MutexLock (&iindex_mutex);
1401 for (i=1;; i++) /* each potential position in ioffsets */
1403 for (j=0;; j++) /* each iface */
1407 if (i >= ifaces[j]->idt->iface.ioffsets[0])
1409 int ioffset = ifaces[j]->idt->iface.ioffsets[i];
1410 /* We can potentially share this position with another class. */
1411 if (ioffset >= 0 && ioffset != offsets[j])
1412 break; /* Nope. Try next i. */
1416 for (j = 0; j < num; j++)
1418 int len = ifaces[j]->idt->iface.ioffsets[0];
1421 /* Resize ioffsets. */
1422 int newlen = 2 * len;
1425 jshort *old_ioffsets = ifaces[j]->idt->iface.ioffsets;
1426 jshort *new_ioffsets = (jshort *) _Jv_Realloc (old_ioffsets,
1427 newlen * sizeof(jshort));
1428 new_ioffsets[0] = newlen;
1430 while (len < newlen)
1431 new_ioffsets[len++] = -1;
1433 ifaces[j]->idt->iface.ioffsets = new_ioffsets;
1435 ifaces[j]->idt->iface.ioffsets[i] = offsets[j];
1438 _Jv_MutexUnlock (&iindex_mutex);
1443 // Only used by serialization
1444 java::lang::reflect::Field *
1445 java::lang::Class::getPrivateField (jstring name)
1447 int hash = name->hashCode ();
1449 java::lang::reflect::Field* rfield;
1450 for (int i = 0; i < field_count; i++)
1452 _Jv_Field *field = &fields[i];
1453 if (! _Jv_equal (field->name, name, hash))
1455 rfield = new java::lang::reflect::Field ();
1456 rfield->offset = (char*) field - (char*) fields;
1457 rfield->declaringClass = this;
1458 rfield->name = name;
1461 jclass superclass = getSuperclass();
1462 if (superclass == NULL)
1464 rfield = superclass->getPrivateField(name);
1465 for (int i = 0; i < interface_count && rfield == NULL; ++i)
1466 rfield = interfaces[i]->getPrivateField (name);
1470 // Only used by serialization
1471 java::lang::reflect::Method *
1472 java::lang::Class::getPrivateMethod (jstring name, JArray<jclass> *param_types)
1474 jstring partial_sig = getSignature (param_types, false);
1475 jint p_len = partial_sig->length();
1476 _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
1477 for (Class *klass = this; klass; klass = klass->getSuperclass())
1479 int i = klass->isPrimitive () ? 0 : klass->method_count;
1482 if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
1483 && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len))
1486 using namespace java::lang::reflect;
1488 Method *rmethod = new Method ();
1489 rmethod->offset = ((char *) (&klass->methods[i])
1490 - (char *) klass->methods);
1491 rmethod->declaringClass = klass;
1496 throw new java::lang::NoSuchMethodException (name);
1499 // Private accessor method for Java code to retrieve the protection domain.
1500 java::security::ProtectionDomain *
1501 java::lang::Class::getProtectionDomain0 ()
1503 return protectionDomain;
1507 java::lang::Class::getSigners()
1509 return hack_signers;
1513 java::lang::Class::setSigners(JArray<jobject> *s)
1518 // Functions for indirect dispatch (symbolic virtual binding) support.
1520 // There are two tables, atable and otable. atable is an array of
1521 // addresses, and otable is an array of offsets, and these are used
1522 // for static and virtual members respectively.
1524 // {a,o}table_syms is an array of _Jv_MethodSymbols. Each such symbol
1525 // is a tuple of {classname, member name, signature}.
1526 // _Jv_LinkSymbolTable() scans these two arrays and fills in the
1527 // corresponding atable and otable with the addresses of static
1528 // members and the offsets of virtual members.
1530 // The offset (in bytes) for each resolved method or field is placed
1531 // at the corresponding position in the virtual method offset table
1534 // The same otable and atable may be shared by many classes.
1537 _Jv_LinkSymbolTable(jclass klass)
1539 //// FIXME: Need to lock the tables ////
1542 _Jv_MethodSymbol sym;
1543 if (klass->otable == NULL
1544 || klass->otable->state != 0)
1547 klass->otable->state = 1;
1549 for (index = 0; sym = klass->otable_syms[index], sym.name != NULL; index++)
1551 // FIXME: Why are we passing NULL as the class loader?
1552 jclass target_class = _Jv_FindClass (sym.class_name, NULL);
1553 _Jv_Method *meth = NULL;
1555 const _Jv_Utf8Const *signature = sym.signature;
1558 static char *bounce = (char *)_Jv_ThrowNoSuchMethodError;
1559 ptrdiff_t offset = (char *)(klass->vtable) - bounce;
1560 klass->otable->offsets[index] = offset;
1563 if (target_class == NULL)
1566 if (target_class->isInterface())
1568 // FIXME: This does not yet fully conform to binary compatibility
1569 // rules. It will break if a declaration is moved into a
1571 for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
1573 for (int i=0; i < cls->method_count; i++)
1575 meth = &cls->methods[i];
1576 if (_Jv_equalUtf8Consts (sym.name, meth->name)
1577 && _Jv_equalUtf8Consts (signature, meth->signature))
1579 klass->otable->offsets[index] = i + 1;
1589 // We're looking for a field or a method, and we can tell
1590 // which is needed by looking at the signature.
1591 if (signature->length >= 2
1592 && signature->data[0] == '(')
1594 // If the target class does not have a vtable_method_count yet,
1595 // then we can't tell the offsets for its methods, so we must lay
1597 if (target_class->vtable_method_count == -1)
1599 JvSynchronize sync (target_class);
1600 _Jv_LayoutVTableMethods (target_class);
1603 meth = _Jv_LookupDeclaredMethod(target_class, sym.name,
1608 klass->otable->offsets[index] =
1609 _Jv_VTable::idx_to_offset (meth->index);
1617 _Jv_Field *the_field = NULL;
1619 for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
1621 for (int i = 0; i < cls->field_count; i++)
1623 _Jv_Field *field = &cls->fields[i];
1624 if (! _Jv_equalUtf8Consts (field->name, sym.name))
1627 // FIXME: What access checks should we perform here?
1628 // if (_Jv_CheckAccess (klass, cls, field->flags))
1631 if (!field->isResolved ())
1632 _Jv_ResolveField (field, cls->loader);
1634 // if (field_type != 0 && field->type != field_type)
1635 // throw new java::lang::LinkageError
1636 // (JvNewStringLatin1
1637 // ("field type mismatch with different loaders"));
1640 goto end_of_field_search;
1643 end_of_field_search:
1644 if (the_field != NULL)
1646 if (the_field->flags & 0x0008 /* Modifier::STATIC */)
1648 throw new java::lang::IncompatibleClassChangeError;
1652 klass->otable->offsets[index] = the_field->u.boffset;
1657 throw new java::lang::NoSuchFieldError
1658 (_Jv_NewStringUtf8Const (sym.name));
1664 if (klass->atable == NULL
1665 || klass->atable->state != 0)
1668 klass->atable->state = 1;
1670 for (index = 0; sym = klass->atable_syms[index], sym.name != NULL; index++)
1672 // FIXME: Why are we passing NULL as the class loader?
1673 jclass target_class = _Jv_FindClass (sym.class_name, NULL);
1674 _Jv_Method *meth = NULL;
1675 const _Jv_Utf8Const *signature = sym.signature;
1677 // ??? Setting this pointer to null will at least get us a
1678 // NullPointerException
1679 klass->atable->addresses[index] = NULL;
1681 if (target_class == NULL)
1684 // We're looking for a static field or a static method, and we
1685 // can tell which is needed by looking at the signature.
1686 if (signature->length >= 2
1687 && signature->data[0] == '(')
1689 // If the target class does not have a vtable_method_count yet,
1690 // then we can't tell the offsets for its methods, so we must lay
1692 if (target_class->vtable_method_count == -1)
1694 JvSynchronize sync (target_class);
1695 _Jv_LayoutVTableMethods (target_class);
1698 meth = _Jv_LookupDeclaredMethod(target_class, sym.name,
1703 if (meth->ncode) // Maybe abstract?
1704 klass->atable->addresses[index] = meth->ncode;
1706 else if (_Jv_IsInterpretedClass (target_class))
1707 _Jv_Defer_Resolution (target_class, meth,
1708 &klass->atable->addresses[index]);
1712 klass->atable->addresses[index] = (void *)_Jv_ThrowNoSuchMethodError;
1719 _Jv_Field *the_field = NULL;
1721 for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
1723 for (int i = 0; i < cls->field_count; i++)
1725 _Jv_Field *field = &cls->fields[i];
1726 if (! _Jv_equalUtf8Consts (field->name, sym.name))
1729 // FIXME: What access checks should we perform here?
1730 // if (_Jv_CheckAccess (klass, cls, field->flags))
1733 if (!field->isResolved ())
1734 _Jv_ResolveField (field, cls->loader);
1736 // if (field_type != 0 && field->type != field_type)
1737 // throw new java::lang::LinkageError
1738 // (JvNewStringLatin1
1739 // ("field type mismatch with different loaders"));
1742 goto end_of_static_field_search;
1745 end_of_static_field_search:
1746 if (the_field != NULL)
1748 if (the_field->flags & 0x0008 /* Modifier::STATIC */)
1750 klass->atable->addresses[index] = the_field->u.addr;
1754 throw new java::lang::IncompatibleClassChangeError;
1759 throw new java::lang::NoSuchFieldError
1760 (_Jv_NewStringUtf8Const (sym.name));
1767 // For each catch_record in the list of caught classes, fill in the
1770 _Jv_linkExceptionClassTable (jclass self)
1772 struct _Jv_CatchClass *catch_record = self->catch_classes;
1773 if (!catch_record || catch_record->classname)
1776 while (catch_record->classname)
1778 jclass target_class = _Jv_FindClass (catch_record->classname,
1779 self->getClassLoaderInternal ());
1780 *catch_record->address = target_class;
1783 self->catch_classes->classname = (_Jv_Utf8Const *)-1;
1786 // This is put in empty vtable slots.
1788 _Jv_abstractMethodError (void)
1790 throw new java::lang::AbstractMethodError();
1793 // Set itable method indexes for members of interface IFACE.
1795 _Jv_LayoutInterfaceMethods (jclass iface)
1797 if (! iface->isInterface())
1800 // itable indexes start at 1.
1801 // FIXME: Static initalizers currently get a NULL placeholder entry in the
1802 // itable so they are also assigned an index here.
1803 for (int i = 0; i < iface->method_count; i++)
1804 iface->methods[i].index = i + 1;
1807 // Prepare virtual method declarations in KLASS, and any superclasses as
1808 // required, by determining their vtable index, setting method->index, and
1809 // finally setting the class's vtable_method_count. Must be called with the
1810 // lock for KLASS held.
1812 _Jv_LayoutVTableMethods (jclass klass)
1814 if (klass->vtable != NULL || klass->isInterface()
1815 || klass->vtable_method_count != -1)
1818 jclass superclass = klass->superclass;
1820 typedef unsigned int uaddr __attribute__ ((mode (pointer)));
1822 // If superclass looks like a constant pool entry,
1824 if ((uaddr)superclass < (uaddr)klass->constants.size)
1826 if (klass->state < JV_STATE_LINKED)
1828 _Jv_Utf8Const *name = klass->constants.data[(int)superclass].utf8;
1829 superclass = _Jv_FindClass (name, klass->loader);
1832 jstring str = _Jv_NewStringUTF (name->data);
1833 throw new java::lang::NoClassDefFoundError (str);
1837 superclass = klass->constants.data[(int)superclass].clazz;
1840 if (superclass != NULL && superclass->vtable_method_count == -1)
1842 JvSynchronize sync (superclass);
1843 _Jv_LayoutVTableMethods (superclass);
1846 int index = (superclass == NULL ? 0 : superclass->vtable_method_count);
1848 for (int i = 0; i < klass->method_count; ++i)
1850 _Jv_Method *meth = &klass->methods[i];
1851 _Jv_Method *super_meth = NULL;
1853 if (! _Jv_isVirtualMethod (meth))
1856 // FIXME: Must check that we don't override:
1857 // - Package-private method where superclass is in different package.
1858 // - Final or less-accessible declaration in superclass (check binary
1859 // spec, do we allocate new vtable entry or put throw node in vtable?)
1860 // - Static or private method in superclass.
1862 if (superclass != NULL)
1864 super_meth = _Jv_LookupDeclaredMethod (superclass, meth->name,
1869 meth->index = super_meth->index;
1871 meth->index = index++;
1874 klass->vtable_method_count = index;
1877 // Set entries in VTABLE for virtual methods declared in KLASS. If
1878 // KLASS has an immediate abstract parent, recursively do its methods
1879 // first. FLAGS is used to determine which slots we've actually set.
1881 _Jv_SetVTableEntries (jclass klass, _Jv_VTable *vtable, jboolean *flags)
1883 using namespace java::lang::reflect;
1885 jclass superclass = klass->getSuperclass();
1887 if (superclass != NULL && (superclass->getModifiers() & Modifier::ABSTRACT))
1888 _Jv_SetVTableEntries (superclass, vtable, flags);
1890 for (int i = klass->method_count - 1; i >= 0; i--)
1892 _Jv_Method *meth = &klass->methods[i];
1893 if (meth->index == (_Jv_ushort) -1)
1895 if ((meth->accflags & Modifier::ABSTRACT))
1897 vtable->set_method(meth->index, (void *) &_Jv_abstractMethodError);
1898 flags[meth->index] = false;
1902 vtable->set_method(meth->index, meth->ncode);
1903 flags[meth->index] = true;
1908 // Allocate and lay out the virtual method table for KLASS. This will also
1909 // cause vtables to be generated for any non-abstract superclasses, and
1910 // virtual method layout to occur for any abstract superclasses. Must be
1911 // called with monitor lock for KLASS held.
1913 _Jv_MakeVTable (jclass klass)
1915 using namespace java::lang::reflect;
1917 if (klass->vtable != NULL || klass->isInterface()
1918 || (klass->accflags & Modifier::ABSTRACT))
1921 // Class must be laid out before we can create a vtable.
1922 if (klass->vtable_method_count == -1)
1923 _Jv_LayoutVTableMethods (klass);
1925 // Allocate the new vtable.
1926 _Jv_VTable *vtable = _Jv_VTable::new_vtable (klass->vtable_method_count);
1927 klass->vtable = vtable;
1929 jboolean flags[klass->vtable_method_count];
1930 for (int i = 0; i < klass->vtable_method_count; ++i)
1933 // Copy the vtable of the closest non-abstract superclass.
1934 jclass superclass = klass->superclass;
1935 if (superclass != NULL)
1937 while ((superclass->accflags & Modifier::ABSTRACT) != 0)
1938 superclass = superclass->superclass;
1940 if (superclass->vtable == NULL)
1942 JvSynchronize sync (superclass);
1943 _Jv_MakeVTable (superclass);
1946 for (int i = 0; i < superclass->vtable_method_count; ++i)
1948 vtable->set_method (i, superclass->vtable->get_method (i));
1953 // Set the class pointer and GC descriptor.
1954 vtable->clas = klass;
1955 vtable->gc_descr = _Jv_BuildGCDescr (klass);
1957 // For each virtual declared in klass and any immediate abstract
1958 // superclasses, set new vtable entry or override an old one.
1959 _Jv_SetVTableEntries (klass, vtable, flags);
1961 // It is an error to have an abstract method in a concrete class.
1962 if (! (klass->accflags & Modifier::ABSTRACT))
1964 for (int i = 0; i < klass->vtable_method_count; ++i)
1967 using namespace java::lang;
1968 while (klass != NULL)
1970 for (int j = 0; j < klass->method_count; ++j)
1972 if (klass->methods[i].index == i)
1974 StringBuffer *buf = new StringBuffer ();
1975 buf->append (_Jv_NewStringUtf8Const (klass->methods[i].name));
1976 buf->append ((jchar) ' ');
1977 buf->append (_Jv_NewStringUtf8Const (klass->methods[i].signature));
1978 throw new AbstractMethodError (buf->toString ());
1981 klass = klass->getSuperclass ();
1983 // Couldn't find the name, which is weird.
1984 // But we still must throw the error.
1985 throw new AbstractMethodError ();