Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / libjava / java / lang / natClass.cc
blobbd68eb224358375ad40687b9125770126ce2857b
1 // natClass.cc - Implementation of java.lang.Class native methods.
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
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
10 details. */
12 #include <config.h>
14 #include <limits.h>
15 #include <string.h>
16 #include <stddef.h>
17 #include <stdio.h>
19 #pragma implementation "Class.h"
21 #include <gcj/cni.h>
22 #include <jvm.h>
23 #include <java-threads.h>
25 #include <java/lang/Class.h>
26 #include <java/lang/ClassLoader.h>
27 #include <java/lang/String.h>
28 #include <java/lang/reflect/Modifier.h>
29 #include <java/lang/reflect/Member.h>
30 #include <java/lang/reflect/Method.h>
31 #include <java/lang/reflect/Field.h>
32 #include <java/lang/reflect/Constructor.h>
33 #include <java/lang/AbstractMethodError.h>
34 #include <java/lang/ArrayStoreException.h>
35 #include <java/lang/ClassCastException.h>
36 #include <java/lang/ClassNotFoundException.h>
37 #include <java/lang/ExceptionInInitializerError.h>
38 #include <java/lang/IllegalAccessException.h>
39 #include <java/lang/IllegalAccessError.h>
40 #include <java/lang/IllegalArgumentException.h>
41 #include <java/lang/IncompatibleClassChangeError.h>
42 #include <java/lang/NoSuchFieldError.h>
43 #include <java/lang/ArrayIndexOutOfBoundsException.h>
44 #include <java/lang/InstantiationException.h>
45 #include <java/lang/NoClassDefFoundError.h>
46 #include <java/lang/NoSuchFieldException.h>
47 #include <java/lang/NoSuchMethodError.h>
48 #include <java/lang/NoSuchMethodException.h>
49 #include <java/lang/Thread.h>
50 #include <java/lang/NullPointerException.h>
51 #include <java/lang/RuntimePermission.h>
52 #include <java/lang/System.h>
53 #include <java/lang/SecurityManager.h>
54 #include <java/lang/StringBuffer.h>
55 #include <java/lang/VMClassLoader.h>
56 #include <gcj/method.h>
57 #include <gnu/gcj/RawData.h>
58 #include <java/lang/VerifyError.h>
60 #include <java-cpool.h>
61 #include <java-interp.h>
62 #include <java-assert.h>
63 #include <java-stack.h>
64 #include <execution.h>
68 using namespace gcj;
70 jclass
71 java::lang::Class::forName (jstring className, jboolean initialize,
72 java::lang::ClassLoader *loader)
74 if (! className)
75 throw new java::lang::NullPointerException;
77 jsize length = _Jv_GetStringUTFLength (className);
78 char buffer[length];
79 _Jv_GetStringUTFRegion (className, 0, className->length(), buffer);
81 _Jv_Utf8Const *name = _Jv_makeUtf8Const (buffer, length);
83 if (! _Jv_VerifyClassName (name))
84 throw new java::lang::ClassNotFoundException (className);
86 jclass klass = (buffer[0] == '['
87 ? _Jv_FindClassFromSignature (name->chars(), loader)
88 : _Jv_FindClass (name, loader));
90 if (klass == NULL)
91 throw new java::lang::ClassNotFoundException (className);
93 if (initialize)
94 _Jv_InitClass (klass);
96 return klass;
99 jclass
100 java::lang::Class::forName (jstring className)
102 java::lang::ClassLoader *loader = NULL;
104 jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$);
105 if (caller)
106 loader = caller->getClassLoaderInternal();
108 return forName (className, true, loader);
111 java::lang::ClassLoader *
112 java::lang::Class::getClassLoader (void)
114 java::lang::SecurityManager *s = java::lang::System::getSecurityManager();
115 if (s != NULL)
117 jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$);
118 ClassLoader *caller_loader = NULL;
119 if (caller)
120 caller_loader = caller->getClassLoaderInternal();
122 // If the caller has a non-null class loader, and that loader
123 // is not this class' loader or an ancestor thereof, then do a
124 // security check.
125 if (caller_loader != NULL && ! caller_loader->isAncestorOf(loader))
126 s->checkPermission (new RuntimePermission (JvNewStringLatin1 ("getClassLoader")));
129 return loader;
132 java::lang::reflect::Constructor *
133 java::lang::Class::getConstructor (JArray<jclass> *param_types)
135 memberAccessCheck(java::lang::reflect::Member::PUBLIC);
137 jstring partial_sig = getSignature (param_types, true);
138 jint hash = partial_sig->hashCode ();
140 int i = isPrimitive () ? 0 : method_count;
141 while (--i >= 0)
143 if (_Jv_equalUtf8Consts (methods[i].name, init_name)
144 && _Jv_equal (methods[i].signature, partial_sig, hash))
146 // Found it. For getConstructor, the constructor must be
147 // public.
148 using namespace java::lang::reflect;
149 if (! Modifier::isPublic(methods[i].accflags))
150 break;
151 Constructor *cons = new Constructor ();
152 cons->offset = (char *) (&methods[i]) - (char *) methods;
153 cons->declaringClass = this;
154 return cons;
157 throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
160 JArray<java::lang::reflect::Constructor *> *
161 java::lang::Class::getDeclaredConstructors (jboolean publicOnly)
163 int numConstructors = 0;
164 int max = isPrimitive () ? 0 : method_count;
165 int i;
166 for (i = max; --i >= 0; )
168 _Jv_Method *method = &methods[i];
169 if (method->name == NULL
170 || ! _Jv_equalUtf8Consts (method->name, init_name))
171 continue;
172 if (publicOnly
173 && ! java::lang::reflect::Modifier::isPublic(method->accflags))
174 continue;
175 numConstructors++;
177 JArray<java::lang::reflect::Constructor *> *result
178 = (JArray<java::lang::reflect::Constructor *> *)
179 JvNewObjectArray (numConstructors,
180 &java::lang::reflect::Constructor::class$,
181 NULL);
182 java::lang::reflect::Constructor** cptr = elements (result);
183 for (i = 0; i < max; i++)
185 _Jv_Method *method = &methods[i];
186 if (method->name == NULL
187 || ! _Jv_equalUtf8Consts (method->name, init_name))
188 continue;
189 if (publicOnly
190 && ! java::lang::reflect::Modifier::isPublic(method->accflags))
191 continue;
192 java::lang::reflect::Constructor *cons
193 = new java::lang::reflect::Constructor ();
194 cons->offset = (char *) method - (char *) methods;
195 cons->declaringClass = this;
196 *cptr++ = cons;
198 return result;
201 java::lang::reflect::Constructor *
202 java::lang::Class::getDeclaredConstructor (JArray<jclass> *param_types)
204 memberAccessCheck(java::lang::reflect::Member::DECLARED);
206 jstring partial_sig = getSignature (param_types, true);
207 jint hash = partial_sig->hashCode ();
209 int i = isPrimitive () ? 0 : method_count;
210 while (--i >= 0)
212 if (_Jv_equalUtf8Consts (methods[i].name, init_name)
213 && _Jv_equal (methods[i].signature, partial_sig, hash))
215 // Found it.
216 using namespace java::lang::reflect;
217 Constructor *cons = new Constructor ();
218 cons->offset = (char *) (&methods[i]) - (char *) methods;
219 cons->declaringClass = this;
220 return cons;
223 throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
226 java::lang::reflect::Field *
227 java::lang::Class::getField (jstring name, jint hash)
229 java::lang::reflect::Field* rfield;
230 for (int i = 0; i < field_count; i++)
232 _Jv_Field *field = &fields[i];
233 if (! _Jv_equal (field->name, name, hash))
234 continue;
235 if (! (field->getModifiers() & java::lang::reflect::Modifier::PUBLIC))
236 continue;
237 rfield = new java::lang::reflect::Field ();
238 rfield->offset = (char*) field - (char*) fields;
239 rfield->declaringClass = this;
240 rfield->name = name;
241 return rfield;
243 jclass superclass = getSuperclass();
244 if (superclass == NULL)
245 return NULL;
246 rfield = superclass->getField(name, hash);
247 for (int i = 0; i < interface_count && rfield == NULL; ++i)
248 rfield = interfaces[i]->getField (name, hash);
249 return rfield;
252 java::lang::reflect::Field *
253 java::lang::Class::getDeclaredField (jstring name)
255 memberAccessCheck(java::lang::reflect::Member::DECLARED);
256 int hash = name->hashCode();
257 for (int i = 0; i < field_count; i++)
259 _Jv_Field *field = &fields[i];
260 if (! _Jv_equal (field->name, name, hash))
261 continue;
262 java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
263 rfield->offset = (char*) field - (char*) fields;
264 rfield->declaringClass = this;
265 rfield->name = name;
266 return rfield;
268 throw new java::lang::NoSuchFieldException (name);
271 JArray<java::lang::reflect::Field *> *
272 java::lang::Class::getDeclaredFields (jboolean public_only)
274 int size;
275 if (public_only)
277 size = 0;
278 for (int i = 0; i < field_count; ++i)
280 _Jv_Field *field = &fields[i];
281 if ((field->flags & java::lang::reflect::Modifier::PUBLIC))
282 ++size;
285 else
286 size = field_count;
288 JArray<java::lang::reflect::Field *> *result
289 = (JArray<java::lang::reflect::Field *> *)
290 JvNewObjectArray (size, &java::lang::reflect::Field::class$, NULL);
291 java::lang::reflect::Field** fptr = elements (result);
292 for (int i = 0; i < field_count; i++)
294 _Jv_Field *field = &fields[i];
295 if (public_only
296 && ! (field->flags & java::lang::reflect::Modifier::PUBLIC))
297 continue;
298 java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
299 rfield->offset = (char*) field - (char*) fields;
300 rfield->declaringClass = this;
301 *fptr++ = rfield;
303 return result;
306 void
307 java::lang::Class::getSignature (java::lang::StringBuffer *buffer)
309 if (isPrimitive())
310 buffer->append((jchar) method_count);
311 else
313 jstring name = getName();
314 if (name->charAt(0) != '[')
315 buffer->append((jchar) 'L');
316 buffer->append(name);
317 if (name->charAt(0) != '[')
318 buffer->append((jchar) ';');
322 // This doesn't have to be native. It is an implementation detail
323 // only called from the C++ code, though, so maybe this is clearer.
324 jstring
325 java::lang::Class::getSignature (JArray<jclass> *param_types,
326 jboolean is_constructor)
328 java::lang::StringBuffer *buf = new java::lang::StringBuffer ();
329 buf->append((jchar) '(');
330 // A NULL param_types means "no parameters".
331 if (param_types != NULL)
333 jclass *v = elements (param_types);
334 for (int i = 0; i < param_types->length; ++i)
335 v[i]->getSignature(buf);
337 buf->append((jchar) ')');
338 if (is_constructor)
339 buf->append((jchar) 'V');
340 return buf->toString();
343 java::lang::reflect::Method *
344 java::lang::Class::_getDeclaredMethod (jstring name,
345 JArray<jclass> *param_types)
347 jstring partial_sig = getSignature (param_types, false);
348 jint p_len = partial_sig->length();
349 _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
350 int i = isPrimitive () ? 0 : method_count;
351 while (--i >= 0)
353 if (_Jv_equalUtf8Consts (methods[i].name, utf_name)
354 && _Jv_equaln (methods[i].signature, partial_sig, p_len)
355 && (methods[i].accflags
356 & java::lang::reflect::Modifier::INVISIBLE) == 0)
358 // Found it.
359 using namespace java::lang::reflect;
360 Method *rmethod = new Method ();
361 rmethod->offset = (char*) (&methods[i]) - (char*) methods;
362 rmethod->declaringClass = this;
363 return rmethod;
366 return NULL;
369 JArray<java::lang::reflect::Method *> *
370 java::lang::Class::getDeclaredMethods (void)
372 memberAccessCheck(java::lang::reflect::Member::DECLARED);
374 int numMethods = 0;
375 int max = isPrimitive () ? 0 : method_count;
376 int i;
377 for (i = max; --i >= 0; )
379 _Jv_Method *method = &methods[i];
380 if (method->name == NULL
381 || _Jv_equalUtf8Consts (method->name, clinit_name)
382 || _Jv_equalUtf8Consts (method->name, init_name)
383 || _Jv_equalUtf8Consts (method->name, finit_name)
384 || (methods[i].accflags
385 & java::lang::reflect::Modifier::INVISIBLE) != 0)
386 continue;
387 numMethods++;
389 JArray<java::lang::reflect::Method *> *result
390 = (JArray<java::lang::reflect::Method *> *)
391 JvNewObjectArray (numMethods, &java::lang::reflect::Method::class$, NULL);
392 java::lang::reflect::Method** mptr = elements (result);
393 for (i = 0; i < max; i++)
395 _Jv_Method *method = &methods[i];
396 if (method->name == NULL
397 || _Jv_equalUtf8Consts (method->name, clinit_name)
398 || _Jv_equalUtf8Consts (method->name, init_name)
399 || _Jv_equalUtf8Consts (method->name, finit_name)
400 || (methods[i].accflags
401 & java::lang::reflect::Modifier::INVISIBLE) != 0)
402 continue;
403 java::lang::reflect::Method* rmethod
404 = new java::lang::reflect::Method ();
405 rmethod->offset = (char*) method - (char*) methods;
406 rmethod->declaringClass = this;
407 *mptr++ = rmethod;
409 return result;
412 jstring
413 java::lang::Class::getName (void)
415 return name->toString();
418 JArray<jclass> *
419 java::lang::Class::getDeclaredClasses (jboolean /*publicOnly*/)
421 // Until we have inner classes, it always makes sense to return an
422 // empty array.
423 JArray<jclass> *result
424 = (JArray<jclass> *) JvNewObjectArray (0, &java::lang::Class::class$,
425 NULL);
426 return result;
429 jclass
430 java::lang::Class::getDeclaringClass (void)
432 // Until we have inner classes, it makes sense to always return
433 // NULL.
434 return NULL;
437 JArray<jclass> *
438 java::lang::Class::getInterfaces (void)
440 jobjectArray r = JvNewObjectArray (interface_count, getClass (), NULL);
441 jobject *data = elements (r);
442 for (int i = 0; i < interface_count; ++i)
444 typedef unsigned int uaddr __attribute__ ((mode (pointer)));
445 data[i] = interfaces[i];
446 if ((uaddr)data[i] < (uaddr)constants.size)
447 fprintf (stderr, "ERROR !!!\n");
449 return reinterpret_cast<JArray<jclass> *> (r);
452 java::lang::reflect::Method *
453 java::lang::Class::_getMethod (jstring name, JArray<jclass> *param_types)
455 jstring partial_sig = getSignature (param_types, false);
456 jint p_len = partial_sig->length();
457 _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
459 for (Class *klass = this; klass; klass = klass->getSuperclass())
461 int i = klass->isPrimitive () ? 0 : klass->method_count;
462 while (--i >= 0)
464 if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
465 && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len)
466 && (klass->methods[i].accflags
467 & java::lang::reflect::Modifier::INVISIBLE) == 0)
469 // Found it.
470 using namespace java::lang::reflect;
472 // Method must be public.
473 if (! Modifier::isPublic (klass->methods[i].accflags))
474 break;
476 Method *rmethod = new Method ();
477 rmethod->offset = ((char *) (&klass->methods[i])
478 - (char *) klass->methods);
479 rmethod->declaringClass = klass;
480 return rmethod;
485 // If we haven't found a match, and this class is an interface, then
486 // check all the superinterfaces.
487 if (isInterface())
489 for (int i = 0; i < interface_count; ++i)
491 using namespace java::lang::reflect;
492 Method *rmethod = interfaces[i]->_getMethod (name, param_types);
493 if (rmethod != NULL)
494 return rmethod;
498 return NULL;
501 // This is a very slow implementation, since it re-scans all the
502 // methods we've already listed to make sure we haven't duplicated a
503 // method. It also over-estimates the required size, so we have to
504 // shrink the result array later.
505 jint
506 java::lang::Class::_getMethods (JArray<java::lang::reflect::Method *> *result,
507 jint offset)
509 jint count = 0;
511 // First examine all local methods
512 for (int i = isPrimitive () ? 0 : method_count; --i >= 0; )
514 _Jv_Method *method = &methods[i];
515 if (method->name == NULL
516 || _Jv_equalUtf8Consts (method->name, clinit_name)
517 || _Jv_equalUtf8Consts (method->name, init_name)
518 || _Jv_equalUtf8Consts (method->name, finit_name)
519 || (method->accflags
520 & java::lang::reflect::Modifier::INVISIBLE) != 0)
521 continue;
522 // Only want public methods.
523 if (! java::lang::reflect::Modifier::isPublic (method->accflags))
524 continue;
526 // This is where we over-count the slots required if we aren't
527 // filling the result for real.
528 if (result != NULL)
530 jboolean add = true;
531 java::lang::reflect::Method **mp = elements (result);
532 // If we already have a method with this name and signature,
533 // then ignore this one. This can happen with virtual
534 // methods.
535 for (int j = 0; j < offset; ++j)
537 _Jv_Method *meth_2 = _Jv_FromReflectedMethod (mp[j]);
538 if (_Jv_equalUtf8Consts (method->name, meth_2->name)
539 && _Jv_equalUtf8Consts (method->signature,
540 meth_2->signature))
542 add = false;
543 break;
546 if (! add)
547 continue;
550 if (result != NULL)
552 using namespace java::lang::reflect;
553 Method *rmethod = new Method ();
554 rmethod->offset = (char *) method - (char *) methods;
555 rmethod->declaringClass = this;
556 Method **mp = elements (result);
557 mp[offset + count] = rmethod;
559 ++count;
561 offset += count;
563 // Now examine superclasses.
564 if (getSuperclass () != NULL)
566 jint s_count = getSuperclass()->_getMethods (result, offset);
567 offset += s_count;
568 count += s_count;
571 // Finally, examine interfaces.
572 for (int i = 0; i < interface_count; ++i)
574 int f_count = interfaces[i]->_getMethods (result, offset);
575 count += f_count;
576 offset += f_count;
579 return count;
582 JArray<java::lang::reflect::Method *> *
583 java::lang::Class::getMethods (void)
585 using namespace java::lang::reflect;
587 memberAccessCheck(Member::PUBLIC);
589 // This will overestimate the size we need.
590 jint count = _getMethods (NULL, 0);
592 JArray<Method *> *result
593 = ((JArray<Method *> *) JvNewObjectArray (count,
594 &Method::class$,
595 NULL));
597 // When filling the array for real, we get the actual count. Then
598 // we resize the array.
599 jint real_count = _getMethods (result, 0);
601 if (real_count != count)
603 JArray<Method *> *r2
604 = ((JArray<Method *> *) JvNewObjectArray (real_count,
605 &Method::class$,
606 NULL));
608 Method **destp = elements (r2);
609 Method **srcp = elements (result);
611 for (int i = 0; i < real_count; ++i)
612 *destp++ = *srcp++;
614 result = r2;
617 return result;
620 jboolean
621 java::lang::Class::isAssignableFrom (jclass klass)
623 // Arguments may not have been initialized, given ".class" syntax.
624 _Jv_InitClass (this);
625 _Jv_InitClass (klass);
626 return _Jv_IsAssignableFrom (klass, this);
629 jboolean
630 java::lang::Class::isInstance (jobject obj)
632 if (! obj)
633 return false;
634 _Jv_InitClass (this);
635 return _Jv_IsAssignableFrom (JV_CLASS (obj), this);
638 jobject
639 java::lang::Class::newInstance (void)
641 memberAccessCheck(java::lang::reflect::Member::PUBLIC);
643 if (isPrimitive ()
644 || isInterface ()
645 || isArray ()
646 || java::lang::reflect::Modifier::isAbstract(accflags))
647 throw new java::lang::InstantiationException (getName ());
649 _Jv_InitClass (this);
651 _Jv_Method *meth = _Jv_GetMethodLocal (this, init_name, void_signature);
652 if (! meth)
653 throw new java::lang::InstantiationException (getName());
655 jobject r = _Jv_AllocObject (this);
656 ((void (*) (jobject)) meth->ncode) (r);
657 return r;
660 void
661 java::lang::Class::finalize (void)
663 engine->unregister(this);
666 // This implements the initialization process for a class. From Spec
667 // section 12.4.2.
668 void
669 java::lang::Class::initializeClass (void)
671 // Short-circuit to avoid needless locking.
672 if (state == JV_STATE_DONE)
673 return;
675 // Step 1. We introduce a new scope so we can synchronize more
676 // easily.
678 JvSynchronize sync (this);
680 if (state < JV_STATE_LINKED)
684 _Jv_Linker::wait_for_state(this, JV_STATE_LINKED);
686 catch (java::lang::Throwable *x)
688 // Turn into a NoClassDefFoundError.
689 java::lang::NoClassDefFoundError *result
690 = new java::lang::NoClassDefFoundError(getName());
691 result->initCause(x);
692 throw result;
696 // Step 2.
697 java::lang::Thread *self = java::lang::Thread::currentThread();
698 self = (java::lang::Thread *) ((long) self | 1);
699 while (state == JV_STATE_IN_PROGRESS && thread && thread != self)
700 wait ();
702 // Steps 3 & 4.
703 if (state == JV_STATE_DONE || state == JV_STATE_IN_PROGRESS)
704 return;
706 // Step 5.
707 if (state == JV_STATE_ERROR)
708 throw new java::lang::NoClassDefFoundError (getName());
710 // Step 6.
711 thread = self;
712 _Jv_Linker::wait_for_state (this, JV_STATE_LINKED);
713 state = JV_STATE_IN_PROGRESS;
716 // Step 7.
717 if (! isInterface () && superclass)
721 _Jv_InitClass (superclass);
723 catch (java::lang::Throwable *except)
725 // Caught an exception.
726 JvSynchronize sync (this);
727 state = JV_STATE_ERROR;
728 notifyAll ();
729 throw except;
733 // Steps 8, 9, 10, 11.
736 _Jv_Method *meth = _Jv_GetMethodLocal (this, clinit_name,
737 void_signature);
738 if (meth)
739 ((void (*) (void)) meth->ncode) ();
741 catch (java::lang::Throwable *except)
743 if (! java::lang::Error::class$.isInstance(except))
747 except = new ExceptionInInitializerError (except);
749 catch (java::lang::Throwable *t)
751 except = t;
755 JvSynchronize sync (this);
756 state = JV_STATE_ERROR;
757 notifyAll ();
758 throw except;
761 JvSynchronize sync (this);
762 state = JV_STATE_DONE;
763 notifyAll ();
766 // Only used by serialization
767 java::lang::reflect::Field *
768 java::lang::Class::getPrivateField (jstring name)
770 int hash = name->hashCode ();
772 java::lang::reflect::Field* rfield;
773 for (int i = 0; i < field_count; i++)
775 _Jv_Field *field = &fields[i];
776 if (! _Jv_equal (field->name, name, hash))
777 continue;
778 rfield = new java::lang::reflect::Field ();
779 rfield->offset = (char*) field - (char*) fields;
780 rfield->declaringClass = this;
781 rfield->name = name;
782 return rfield;
784 jclass superclass = getSuperclass();
785 if (superclass == NULL)
786 return NULL;
787 rfield = superclass->getPrivateField(name);
788 for (int i = 0; i < interface_count && rfield == NULL; ++i)
789 rfield = interfaces[i]->getPrivateField (name);
790 return rfield;
793 // Only used by serialization
794 java::lang::reflect::Method *
795 java::lang::Class::getPrivateMethod (jstring name, JArray<jclass> *param_types)
797 jstring partial_sig = getSignature (param_types, false);
798 jint p_len = partial_sig->length();
799 _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
800 for (Class *klass = this; klass; klass = klass->getSuperclass())
802 int i = klass->isPrimitive () ? 0 : klass->method_count;
803 while (--i >= 0)
805 if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
806 && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len))
808 // Found it.
809 using namespace java::lang::reflect;
811 Method *rmethod = new Method ();
812 rmethod->offset = ((char *) (&klass->methods[i])
813 - (char *) klass->methods);
814 rmethod->declaringClass = klass;
815 return rmethod;
819 throw new java::lang::NoSuchMethodException (name);
822 // Private accessor method for Java code to retrieve the protection domain.
823 java::security::ProtectionDomain *
824 java::lang::Class::getProtectionDomain0 ()
826 return protectionDomain;
829 JArray<jobject> *
830 java::lang::Class::getSigners()
832 return hack_signers;
835 void
836 java::lang::Class::setSigners(JArray<jobject> *s)
838 hack_signers = s;
844 // Some class-related convenience functions.
847 // Find a method declared in the class. If it is not declared locally
848 // (or if it is inherited), return NULL.
849 _Jv_Method *
850 _Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
851 _Jv_Utf8Const *signature)
853 for (int i = 0; i < klass->method_count; ++i)
855 if (_Jv_equalUtf8Consts (name, klass->methods[i].name)
856 && _Jv_equalUtf8Consts (signature, klass->methods[i].signature))
857 return &klass->methods[i];
859 return NULL;
862 _Jv_Method *
863 _Jv_LookupDeclaredMethod (jclass klass, _Jv_Utf8Const *name,
864 _Jv_Utf8Const *signature,
865 jclass *declarer_result)
867 for (; klass; klass = klass->getSuperclass())
869 _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
871 if (meth)
873 if (declarer_result)
874 *declarer_result = klass;
875 return meth;
879 return NULL;
882 #ifdef HAVE_TLS
884 // NOTE: MCACHE_SIZE should be a power of 2 minus one.
885 #define MCACHE_SIZE 31
887 struct _Jv_mcache
889 jclass klass;
890 _Jv_Method *method;
893 static __thread _Jv_mcache *method_cache;
894 #endif // HAVE_TLS
896 static void *
897 _Jv_FindMethodInCache (jclass klass,
898 _Jv_Utf8Const *name,
899 _Jv_Utf8Const *signature)
901 #ifdef HAVE_TLS
902 _Jv_mcache *cache = method_cache;
903 if (cache)
905 int index = name->hash16 () & MCACHE_SIZE;
906 _Jv_mcache *mc = &cache[index];
907 _Jv_Method *m = mc->method;
909 if (mc->klass == klass
910 && _Jv_equalUtf8Consts (m->name, name)
911 && _Jv_equalUtf8Consts (m->signature, signature))
912 return mc->method->ncode;
914 #endif // HAVE_TLS
915 return NULL;
918 static void
919 _Jv_AddMethodToCache (jclass klass, _Jv_Method *method)
921 #ifdef HAVE_TLS
922 if (method_cache == NULL)
923 method_cache = (_Jv_mcache *) _Jv_MallocUnchecked((MCACHE_SIZE + 1)
924 * sizeof (_Jv_mcache));
925 // If the allocation failed, just keep going.
926 if (method_cache != NULL)
928 int index = method->name->hash16 () & MCACHE_SIZE;
929 method_cache[index].method = method;
930 method_cache[index].klass = klass;
932 #endif // HAVE_TLS
935 // Free this thread's method cache. We explicitly manage this memory
936 // as the GC does not yet know how to scan TLS on all platforms.
937 void
938 _Jv_FreeMethodCache ()
940 #ifdef HAVE_TLS
941 if (method_cache != NULL)
943 _Jv_Free(method_cache);
944 method_cache = NULL;
946 #endif // HAVE_TLS
949 void *
950 _Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name,
951 _Jv_Utf8Const *signature)
953 using namespace java::lang::reflect;
955 void *ncode = _Jv_FindMethodInCache (klass, name, signature);
956 if (ncode != 0)
957 return ncode;
959 for (; klass; klass = klass->getSuperclass())
961 _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
962 if (! meth)
963 continue;
965 if (Modifier::isStatic(meth->accflags))
966 throw new java::lang::IncompatibleClassChangeError
967 (_Jv_GetMethodString (klass, meth));
968 if (Modifier::isAbstract(meth->accflags))
969 throw new java::lang::AbstractMethodError
970 (_Jv_GetMethodString (klass, meth));
971 if (! Modifier::isPublic(meth->accflags))
972 throw new java::lang::IllegalAccessError
973 (_Jv_GetMethodString (klass, meth));
975 _Jv_AddMethodToCache (klass, meth);
977 return meth->ncode;
979 throw new java::lang::IncompatibleClassChangeError;
982 // Fast interface method lookup by index.
983 void *
984 _Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface, int method_idx)
986 _Jv_IDispatchTable *cldt = klass->idt;
987 int idx = iface->idt->iface.ioffsets[cldt->cls.iindex] + method_idx;
988 return cldt->cls.itable[idx];
991 jboolean
992 _Jv_IsAssignableFrom (jclass source, jclass target)
994 if (source == target)
995 return true;
997 // If target is array, so must source be.
998 while (target->isArray ())
1000 if (! source->isArray())
1001 return false;
1002 target = target->getComponentType();
1003 source = source->getComponentType();
1006 if (target->isInterface())
1008 // Abstract classes have no IDT, and IDTs provide no way to check
1009 // two interfaces for assignability.
1010 if (__builtin_expect
1011 (source->idt == NULL || source->isInterface(), false))
1012 return _Jv_InterfaceAssignableFrom (source, target);
1014 _Jv_IDispatchTable *cl_idt = source->idt;
1015 _Jv_IDispatchTable *if_idt = target->idt;
1017 if (__builtin_expect ((if_idt == NULL), false))
1018 return false; // No class implementing TARGET has been loaded.
1019 jshort cl_iindex = cl_idt->cls.iindex;
1020 if (cl_iindex < if_idt->iface.ioffsets[0])
1022 jshort offset = if_idt->iface.ioffsets[cl_iindex];
1023 if (offset != -1 && offset < cl_idt->cls.itable_length
1024 && cl_idt->cls.itable[offset] == target)
1025 return true;
1027 return false;
1030 // Primitive TYPE classes are only assignable to themselves.
1031 if (__builtin_expect (target->isPrimitive() || source->isPrimitive(), false))
1032 return false;
1034 if (target == &java::lang::Object::class$)
1035 return true;
1036 else if (source->ancestors == NULL || target->ancestors == NULL)
1038 // We need this case when either SOURCE or TARGET has not has
1039 // its constant-time tables prepared.
1041 // At this point we know that TARGET can't be Object, so it is
1042 // safe to use that as the termination point.
1043 while (source && source != &java::lang::Object::class$)
1045 if (source == target)
1046 return true;
1047 source = source->getSuperclass();
1050 else if (source->depth >= target->depth
1051 && source->ancestors[source->depth - target->depth] == target)
1052 return true;
1054 return false;
1057 // Interface type checking, the slow way. Returns TRUE if IFACE is a
1058 // superinterface of SOURCE. This is used when SOURCE is also an interface,
1059 // or a class with no interface dispatch table.
1060 jboolean
1061 _Jv_InterfaceAssignableFrom (jclass source, jclass iface)
1063 for (int i = 0; i < source->interface_count; i++)
1065 jclass interface = source->interfaces[i];
1066 if (iface == interface
1067 || _Jv_InterfaceAssignableFrom (interface, iface))
1068 return true;
1071 if (!source->isInterface()
1072 && source->superclass
1073 && _Jv_InterfaceAssignableFrom (source->superclass, iface))
1074 return true;
1076 return false;
1079 jboolean
1080 _Jv_IsInstanceOf(jobject obj, jclass cl)
1082 if (__builtin_expect (!obj, false))
1083 return false;
1084 return _Jv_IsAssignableFrom (JV_CLASS (obj), cl);
1087 void *
1088 _Jv_CheckCast (jclass c, jobject obj)
1090 if (__builtin_expect
1091 (obj != NULL && ! _Jv_IsAssignableFrom(JV_CLASS (obj), c), false))
1092 throw new java::lang::ClassCastException
1093 ((new java::lang::StringBuffer
1094 (obj->getClass()->getName()))->append
1095 (JvNewStringUTF(" cannot be cast to "))->append
1096 (c->getName())->toString());
1098 return obj;
1101 void
1102 _Jv_CheckArrayStore (jobject arr, jobject obj)
1104 if (obj)
1106 JvAssert (arr != NULL);
1107 jclass elt_class = (JV_CLASS (arr))->getComponentType();
1108 if (elt_class == &java::lang::Object::class$)
1109 return;
1110 jclass obj_class = JV_CLASS (obj);
1111 if (__builtin_expect
1112 (! _Jv_IsAssignableFrom (obj_class, elt_class), false))
1113 throw new java::lang::ArrayStoreException
1114 ((new java::lang::StringBuffer
1115 (JvNewStringUTF("Cannot store ")))->append
1116 (obj_class->getName())->append
1117 (JvNewStringUTF(" in array of type "))->append
1118 (elt_class->getName())->toString());
1122 jboolean
1123 _Jv_IsAssignableFromSlow (jclass source, jclass target)
1125 // First, strip arrays.
1126 while (target->isArray ())
1128 // If target is array, source must be as well.
1129 if (! source->isArray ())
1130 return false;
1131 target = target->getComponentType ();
1132 source = source->getComponentType ();
1135 // Quick success.
1136 if (target == &java::lang::Object::class$)
1137 return true;
1139 // Ensure that the classes have their supers installed.
1140 _Jv_Linker::wait_for_state (source, JV_STATE_LOADING);
1141 _Jv_Linker::wait_for_state (target, JV_STATE_LOADING);
1145 if (source == target)
1146 return true;
1148 if (target->isPrimitive () || source->isPrimitive ())
1149 return false;
1151 if (target->isInterface ())
1153 for (int i = 0; i < source->interface_count; ++i)
1155 // We use a recursive call because we also need to
1156 // check superinterfaces.
1157 if (_Jv_IsAssignableFromSlow (source->getInterface (i), target))
1158 return true;
1161 source = source->getSuperclass ();
1163 while (source != NULL);
1165 return false;
1168 // Lookup an interface method by name. This is very similar to
1169 // purpose to _getMethod, but the interfaces are quite different. It
1170 // might be a good idea for _getMethod to call this function.
1172 // Return true of the method is found, with the class in FOUND_CLASS
1173 // and the index in INDEX.
1174 bool
1175 _Jv_getInterfaceMethod (jclass search_class, jclass &found_class, int &index,
1176 const _Jv_Utf8Const *utf_name,
1177 const _Jv_Utf8Const *utf_sig)
1179 for (jclass klass = search_class; klass; klass = klass->getSuperclass())
1181 // FIXME: Throw an exception?
1182 if (!klass->isInterface ())
1183 return false;
1185 int i = klass->method_count;
1186 while (--i >= 0)
1188 if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
1189 && _Jv_equalUtf8Consts (klass->methods[i].signature, utf_sig))
1191 // Found it.
1192 using namespace java::lang::reflect;
1194 // FIXME: Method must be public. Throw an exception?
1195 if (! Modifier::isPublic (klass->methods[i].accflags))
1196 break;
1198 found_class = klass;
1199 // Interface method indexes count from 1.
1200 index = i+1;
1201 return true;
1206 // If we haven't found a match, and this class is an interface, then
1207 // check all the superinterfaces.
1208 if (search_class->isInterface())
1210 for (int i = 0; i < search_class->interface_count; ++i)
1212 using namespace java::lang::reflect;
1213 bool found = _Jv_getInterfaceMethod (search_class->interfaces[i],
1214 found_class, index,
1215 utf_name, utf_sig);
1216 if (found)
1217 return true;
1221 return false;