OSDN Git Service

* include/java-stack.h (ncodeMap): Declare.
[pf3gnuchains/gcc-fork.git] / libjava / java / lang / natClass.cc
1 // natClass.cc - Implementation of java.lang.Class native methods.
2
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
4    Free Software Foundation
5
6    This file is part of libgcj.
7
8 This software is copyrighted work licensed under the terms of the
9 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
10 details.  */
11
12 #include <config.h>
13
14 #include <limits.h>
15 #include <string.h>
16 #include <stddef.h>
17 #include <stdio.h>
18
19 #pragma implementation "Class.h"
20
21 #include <gcj/cni.h>
22 #include <jvm.h>
23 #include <java-threads.h>
24
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>
59
60 #include <java-cpool.h>
61 #include <java-interp.h>
62 #include <java-assert.h>
63 #include <java-stack.h>
64 #include <execution.h>
65
66 \f
67
68 using namespace gcj;
69
70 jclass
71 java::lang::Class::forName (jstring className, jboolean initialize,
72                             java::lang::ClassLoader *loader)
73 {
74   if (! className)
75     throw new java::lang::NullPointerException;
76
77   jsize length = _Jv_GetStringUTFLength (className);
78   char buffer[length];
79   _Jv_GetStringUTFRegion (className, 0, className->length(), buffer);
80
81   _Jv_Utf8Const *name = _Jv_makeUtf8Const (buffer, length);
82
83   if (! _Jv_VerifyClassName (name))
84     throw new java::lang::ClassNotFoundException (className);
85
86   jclass klass = (buffer[0] == '[' 
87                   ? _Jv_FindClassFromSignature (name->chars(), loader)
88                   : _Jv_FindClass (name, loader));
89
90   if (klass == NULL)
91     throw new java::lang::ClassNotFoundException (className);
92
93   if (initialize)
94     _Jv_InitClass (klass);
95
96   return klass;
97 }
98
99 jclass
100 java::lang::Class::forName (jstring className)
101 {
102   java::lang::ClassLoader *loader = NULL;
103
104   jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$);
105   if (caller)
106     loader = caller->getClassLoaderInternal();
107
108   return forName (className, true, loader);
109 }
110
111 java::lang::ClassLoader *
112 java::lang::Class::getClassLoader (void)
113 {
114   java::lang::SecurityManager *s = java::lang::System::getSecurityManager();
115   if (s != NULL)
116     {
117       jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$);
118       return getClassLoader (caller);
119    }
120
121   return loader;
122 }
123
124 java::lang::ClassLoader *
125 java::lang::Class::getClassLoader (jclass caller)
126 {
127   java::lang::SecurityManager *s = java::lang::System::getSecurityManager();
128   if (s != NULL)
129     {
130       ClassLoader *caller_loader = caller->getClassLoaderInternal();
131
132       // If the caller has a non-null class loader, and that loader
133       // is not this class' loader or an ancestor thereof, then do a
134       // security check.
135       if (caller_loader != NULL && ! caller_loader->isAncestorOf(loader))
136         s->checkPermission (new RuntimePermission (JvNewStringLatin1 ("getClassLoader")));
137     }
138
139   return loader;
140 }
141
142 java::lang::reflect::Constructor *
143 java::lang::Class::getConstructor (JArray<jclass> *param_types)
144 {
145   memberAccessCheck(java::lang::reflect::Member::PUBLIC);
146
147   jstring partial_sig = getSignature (param_types, true);
148   jint hash = partial_sig->hashCode ();
149
150   int i = isPrimitive () ? 0 : method_count;
151   while (--i >= 0)
152     {
153       if (_Jv_equalUtf8Consts (methods[i].name, init_name)
154           && _Jv_equal (methods[i].signature, partial_sig, hash))
155         {
156           // Found it.  For getConstructor, the constructor must be
157           // public.
158           using namespace java::lang::reflect;
159           if (! Modifier::isPublic(methods[i].accflags))
160             break;
161           Constructor *cons = new Constructor ();
162           cons->offset = (char *) (&methods[i]) - (char *) methods;
163           cons->declaringClass = this;
164           return cons;
165         }
166     }
167   throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
168 }
169
170 JArray<java::lang::reflect::Constructor *> *
171 java::lang::Class::getDeclaredConstructors (jboolean publicOnly)
172 {
173   int numConstructors = 0;
174   int max = isPrimitive () ? 0 : method_count;
175   int i;
176   for (i = max; --i >= 0; )
177     {
178       _Jv_Method *method = &methods[i];
179       if (method->name == NULL
180           || ! _Jv_equalUtf8Consts (method->name, init_name))
181         continue;
182       if (publicOnly
183           && ! java::lang::reflect::Modifier::isPublic(method->accflags))
184         continue;
185       numConstructors++;
186     }
187   JArray<java::lang::reflect::Constructor *> *result
188     = (JArray<java::lang::reflect::Constructor *> *)
189     JvNewObjectArray (numConstructors,
190                       &java::lang::reflect::Constructor::class$,
191                       NULL);
192   java::lang::reflect::Constructor** cptr = elements (result);
193   for (i = 0;  i < max;  i++)
194     {
195       _Jv_Method *method = &methods[i];
196       if (method->name == NULL
197           || ! _Jv_equalUtf8Consts (method->name, init_name))
198         continue;
199       if (publicOnly
200           && ! java::lang::reflect::Modifier::isPublic(method->accflags))
201         continue;
202       java::lang::reflect::Constructor *cons
203         = new java::lang::reflect::Constructor ();
204       cons->offset = (char *) method - (char *) methods;
205       cons->declaringClass = this;
206       *cptr++ = cons;
207     }
208   return result;
209 }
210
211 java::lang::reflect::Constructor *
212 java::lang::Class::getDeclaredConstructor (JArray<jclass> *param_types)
213 {
214   memberAccessCheck(java::lang::reflect::Member::DECLARED);
215
216   jstring partial_sig = getSignature (param_types, true);
217   jint hash = partial_sig->hashCode ();
218
219   int i = isPrimitive () ? 0 : method_count;
220   while (--i >= 0)
221     {
222       if (_Jv_equalUtf8Consts (methods[i].name, init_name)
223           && _Jv_equal (methods[i].signature, partial_sig, hash))
224         {
225           // Found it.
226           using namespace java::lang::reflect;
227           Constructor *cons = new Constructor ();
228           cons->offset = (char *) (&methods[i]) - (char *) methods;
229           cons->declaringClass = this;
230           return cons;
231         }
232     }
233   throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
234 }
235
236 java::lang::reflect::Field *
237 java::lang::Class::getField (jstring name, jint hash)
238 {
239   java::lang::reflect::Field* rfield;
240   for (int i = 0;  i < field_count;  i++)
241     {
242       _Jv_Field *field = &fields[i];
243       if (! _Jv_equal (field->name, name, hash))
244         continue;
245       if (! (field->getModifiers() & java::lang::reflect::Modifier::PUBLIC))
246         continue;
247       rfield = new java::lang::reflect::Field ();
248       rfield->offset = (char*) field - (char*) fields;
249       rfield->declaringClass = this;
250       rfield->name = name;
251       return rfield;
252     }
253   jclass superclass = getSuperclass();
254   if (superclass == NULL)
255     return NULL;
256   rfield = superclass->getField(name, hash);
257   for (int i = 0; i < interface_count && rfield == NULL; ++i)
258     rfield = interfaces[i]->getField (name, hash);
259   return rfield;
260 }
261
262 java::lang::reflect::Field *
263 java::lang::Class::getDeclaredField (jstring name)
264 {
265   memberAccessCheck(java::lang::reflect::Member::DECLARED);
266   int hash = name->hashCode();
267   for (int i = 0;  i < field_count;  i++)
268     {
269       _Jv_Field *field = &fields[i];
270       if (! _Jv_equal (field->name, name, hash))
271         continue;
272       java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
273       rfield->offset = (char*) field - (char*) fields;
274       rfield->declaringClass = this;
275       rfield->name = name;
276       return rfield;
277     }
278   throw new java::lang::NoSuchFieldException (name);
279 }
280
281 JArray<java::lang::reflect::Field *> *
282 java::lang::Class::getDeclaredFields (jboolean public_only)
283 {
284   int size;
285   if (public_only)
286     {
287       size = 0;
288       for (int i = 0; i < field_count; ++i)
289         {
290           _Jv_Field *field = &fields[i];
291           if ((field->flags & java::lang::reflect::Modifier::PUBLIC))
292             ++size;
293         }
294     }
295   else
296     size = field_count;
297
298   JArray<java::lang::reflect::Field *> *result
299     = (JArray<java::lang::reflect::Field *> *)
300     JvNewObjectArray (size, &java::lang::reflect::Field::class$, NULL);
301   java::lang::reflect::Field** fptr = elements (result);
302   for (int i = 0;  i < field_count;  i++)
303     {
304       _Jv_Field *field = &fields[i];
305       if (public_only
306           && ! (field->flags & java::lang::reflect::Modifier::PUBLIC))
307         continue;
308       java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
309       rfield->offset = (char*) field - (char*) fields;
310       rfield->declaringClass = this;
311       *fptr++ = rfield;
312     }
313   return result;
314 }
315
316 void
317 java::lang::Class::getSignature (java::lang::StringBuffer *buffer)
318 {
319   if (isPrimitive())
320     buffer->append((jchar) method_count);
321   else
322     {
323       jstring name = getName();
324       if (name->charAt(0) != '[')
325         buffer->append((jchar) 'L');
326       buffer->append(name);
327       if (name->charAt(0) != '[')
328         buffer->append((jchar) ';');
329     }
330 }
331
332 // This doesn't have to be native.  It is an implementation detail
333 // only called from the C++ code, though, so maybe this is clearer.
334 jstring
335 java::lang::Class::getSignature (JArray<jclass> *param_types,
336                                  jboolean is_constructor)
337 {
338   java::lang::StringBuffer *buf = new java::lang::StringBuffer ();
339   buf->append((jchar) '(');
340   // A NULL param_types means "no parameters".
341   if (param_types != NULL)
342     {
343       jclass *v = elements (param_types);
344       for (int i = 0; i < param_types->length; ++i)
345         v[i]->getSignature(buf);
346     }
347   buf->append((jchar) ')');
348   if (is_constructor)
349     buf->append((jchar) 'V');
350   return buf->toString();
351 }
352
353 java::lang::reflect::Method *
354 java::lang::Class::_getDeclaredMethod (jstring name,
355                                        JArray<jclass> *param_types)
356 {
357   jstring partial_sig = getSignature (param_types, false);
358   jint p_len = partial_sig->length();
359   _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
360   int i = isPrimitive () ? 0 : method_count;
361   while (--i >= 0)
362     {
363       if (_Jv_equalUtf8Consts (methods[i].name, utf_name)
364           && _Jv_equaln (methods[i].signature, partial_sig, p_len)
365           && (methods[i].accflags
366               & java::lang::reflect::Modifier::INVISIBLE) == 0)
367         {
368           // Found it.
369           using namespace java::lang::reflect;
370           Method *rmethod = new Method ();
371           rmethod->offset = (char*) (&methods[i]) - (char*) methods;
372           rmethod->declaringClass = this;
373           return rmethod;
374         }
375     }
376   return NULL;
377 }
378
379 JArray<java::lang::reflect::Method *> *
380 java::lang::Class::getDeclaredMethods (void)
381 {
382   memberAccessCheck(java::lang::reflect::Member::DECLARED);
383
384   int numMethods = 0;
385   int max = isPrimitive () ? 0 : method_count;
386   int i;
387   for (i = max; --i >= 0; )
388     {
389       _Jv_Method *method = &methods[i];
390       if (method->name == NULL
391           || _Jv_equalUtf8Consts (method->name, clinit_name)
392           || _Jv_equalUtf8Consts (method->name, init_name)
393           || _Jv_equalUtf8Consts (method->name, finit_name)
394           || (methods[i].accflags
395               & java::lang::reflect::Modifier::INVISIBLE) != 0)
396         continue;
397       numMethods++;
398     }
399   JArray<java::lang::reflect::Method *> *result
400     = (JArray<java::lang::reflect::Method *> *)
401     JvNewObjectArray (numMethods, &java::lang::reflect::Method::class$, NULL);
402   java::lang::reflect::Method** mptr = elements (result);
403   for (i = 0;  i < max;  i++)
404     {
405       _Jv_Method *method = &methods[i];
406       if (method->name == NULL
407           || _Jv_equalUtf8Consts (method->name, clinit_name)
408           || _Jv_equalUtf8Consts (method->name, init_name)
409           || _Jv_equalUtf8Consts (method->name, finit_name)
410           || (methods[i].accflags
411               & java::lang::reflect::Modifier::INVISIBLE) != 0)
412         continue;
413       java::lang::reflect::Method* rmethod
414         = new java::lang::reflect::Method ();
415       rmethod->offset = (char*) method - (char*) methods;
416       rmethod->declaringClass = this;
417       *mptr++ = rmethod;
418     }
419   return result;
420 }
421
422 jstring
423 java::lang::Class::getName (void)
424 {
425   return name->toString();
426 }
427
428 JArray<jclass> *
429 java::lang::Class::getDeclaredClasses (jboolean /*publicOnly*/)
430 {
431   // Until we have inner classes, it always makes sense to return an
432   // empty array.
433   JArray<jclass> *result
434     = (JArray<jclass> *) JvNewObjectArray (0, &java::lang::Class::class$,
435                                            NULL);
436   return result;
437 }
438
439 jclass
440 java::lang::Class::getDeclaringClass (void)
441 {
442   // Until we have inner classes, it makes sense to always return
443   // NULL.
444   return NULL;
445 }
446
447 JArray<jclass> *
448 java::lang::Class::getInterfaces (void)
449 {
450   jobjectArray r = JvNewObjectArray (interface_count, getClass (), NULL);
451   jobject *data = elements (r);
452   for (int i = 0; i < interface_count; ++i)
453     {
454       typedef unsigned int uaddr __attribute__ ((mode (pointer)));
455       data[i] = interfaces[i];
456       if ((uaddr)data[i] < (uaddr)constants.size)
457         fprintf (stderr, "ERROR !!!\n");
458     }
459   return reinterpret_cast<JArray<jclass> *> (r);
460 }
461
462 java::lang::reflect::Method *
463 java::lang::Class::_getMethod (jstring name, JArray<jclass> *param_types)
464 {
465   jstring partial_sig = getSignature (param_types, false);
466   jint p_len = partial_sig->length();
467   _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
468
469    for (Class *klass = this; klass; klass = klass->getSuperclass())
470     {
471       int i = klass->isPrimitive () ? 0 : klass->method_count;
472       while (--i >= 0)
473         {
474           if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
475               && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len)
476               && (klass->methods[i].accflags
477                   & java::lang::reflect::Modifier::INVISIBLE) == 0)
478             {
479               // Found it.
480               using namespace java::lang::reflect;
481
482               // Method must be public.
483               if (! Modifier::isPublic (klass->methods[i].accflags))
484                 break;
485
486               Method *rmethod = new Method ();
487               rmethod->offset = ((char *) (&klass->methods[i])
488                                  - (char *) klass->methods);
489               rmethod->declaringClass = klass;
490               return rmethod;
491             }
492         }
493     }
494
495   // If we haven't found a match, and this class is an interface, then
496   // check all the superinterfaces.
497   if (isInterface())
498     {
499       for (int i = 0; i < interface_count; ++i)
500         {
501           using namespace java::lang::reflect;
502           Method *rmethod = interfaces[i]->_getMethod (name, param_types);
503           if (rmethod != NULL)
504             return rmethod;
505         }
506     }
507
508   return NULL;
509 }
510
511 // This is a very slow implementation, since it re-scans all the
512 // methods we've already listed to make sure we haven't duplicated a
513 // method.  It also over-estimates the required size, so we have to
514 // shrink the result array later.
515 jint
516 java::lang::Class::_getMethods (JArray<java::lang::reflect::Method *> *result,
517                                 jint offset)
518 {
519   jint count = 0;
520
521   // First examine all local methods
522   for (int i = isPrimitive () ? 0 : method_count; --i >= 0; )
523     {
524       _Jv_Method *method = &methods[i];
525       if (method->name == NULL
526           || _Jv_equalUtf8Consts (method->name, clinit_name)
527           || _Jv_equalUtf8Consts (method->name, init_name)
528           || _Jv_equalUtf8Consts (method->name, finit_name)
529           || (method->accflags
530               & java::lang::reflect::Modifier::INVISIBLE) != 0)
531         continue;
532       // Only want public methods.
533       if (! java::lang::reflect::Modifier::isPublic (method->accflags))
534         continue;
535
536       // This is where we over-count the slots required if we aren't
537       // filling the result for real.
538       if (result != NULL)
539         {
540           jboolean add = true;
541           java::lang::reflect::Method **mp = elements (result);
542           // If we already have a method with this name and signature,
543           // then ignore this one.  This can happen with virtual
544           // methods.
545           for (int j = 0; j < offset; ++j)
546             {
547               _Jv_Method *meth_2 = _Jv_FromReflectedMethod (mp[j]);
548               if (_Jv_equalUtf8Consts (method->name, meth_2->name)
549                   && _Jv_equalUtf8Consts (method->signature,
550                                           meth_2->signature))
551                 {
552                   add = false;
553                   break;
554                 }
555             }
556           if (! add)
557             continue;
558         }
559
560       if (result != NULL)
561         {
562           using namespace java::lang::reflect;
563           Method *rmethod = new Method ();
564           rmethod->offset = (char *) method - (char *) methods;
565           rmethod->declaringClass = this;
566           Method **mp = elements (result);
567           mp[offset + count] = rmethod;
568         }
569       ++count;
570     }
571   offset += count;
572
573   // Now examine superclasses.
574   if (getSuperclass () != NULL)
575     {
576       jint s_count = getSuperclass()->_getMethods (result, offset);
577       offset += s_count;
578       count += s_count;
579     }
580
581   // Finally, examine interfaces.
582   for (int i = 0; i < interface_count; ++i)
583     {
584       int f_count = interfaces[i]->_getMethods (result, offset);
585       count += f_count;
586       offset += f_count;
587     }
588
589   return count;
590 }
591
592 JArray<java::lang::reflect::Method *> *
593 java::lang::Class::getMethods (void)
594 {
595   using namespace java::lang::reflect;
596
597   memberAccessCheck(Member::PUBLIC);
598
599   // This will overestimate the size we need.
600   jint count = _getMethods (NULL, 0);
601
602   JArray<Method *> *result
603     = ((JArray<Method *> *) JvNewObjectArray (count,
604                                               &Method::class$,
605                                               NULL));
606
607   // When filling the array for real, we get the actual count.  Then
608   // we resize the array.
609   jint real_count = _getMethods (result, 0);
610
611   if (real_count != count)
612     {
613       JArray<Method *> *r2
614         = ((JArray<Method *> *) JvNewObjectArray (real_count,
615                                                   &Method::class$,
616                                                   NULL));
617       
618       Method **destp = elements (r2);
619       Method **srcp = elements (result);
620
621       for (int i = 0; i < real_count; ++i)
622         *destp++ = *srcp++;
623
624       result = r2;
625     }
626
627   return result;
628 }
629
630 jboolean
631 java::lang::Class::isAssignableFrom (jclass klass)
632 {
633   // Arguments may not have been initialized, given ".class" syntax.
634   // This ensures we can at least look at their superclasses.
635   _Jv_Linker::wait_for_state (this, JV_STATE_LOADING);
636   _Jv_Linker::wait_for_state (klass, JV_STATE_LOADING);
637   return _Jv_IsAssignableFrom (klass, this);
638 }
639
640 jboolean
641 java::lang::Class::isInstance (jobject obj)
642 {
643   if (! obj)
644     return false;
645   return _Jv_IsAssignableFrom (JV_CLASS (obj), this);
646 }
647
648 jobject
649 java::lang::Class::newInstance (void)
650 {
651   memberAccessCheck(java::lang::reflect::Member::PUBLIC);
652
653   if (isPrimitive ()
654       || isInterface ()
655       || isArray ()
656       || java::lang::reflect::Modifier::isAbstract(accflags))
657     throw new java::lang::InstantiationException (getName ());
658
659   _Jv_InitClass (this);
660
661   _Jv_Method *meth = _Jv_GetMethodLocal (this, init_name, void_signature);
662   if (! meth)
663     throw new java::lang::InstantiationException (getName());
664
665   jobject r = _Jv_AllocObject (this);
666   ((void (*) (jobject)) meth->ncode) (r);
667   return r;
668 }
669
670 void
671 java::lang::Class::finalize (void)
672 {
673   engine->unregister(this);
674 }
675
676 // This implements the initialization process for a class.  From Spec
677 // section 12.4.2.
678 void
679 java::lang::Class::initializeClass (void)
680 {
681   // Short-circuit to avoid needless locking (expression includes
682   // JV_STATE_PHANTOM and JV_STATE_DONE).
683   if (state >= JV_STATE_PHANTOM)
684     return;
685
686   // Step 1.  We introduce a new scope so we can synchronize more
687   // easily.
688   {
689     JvSynchronize sync (this);
690
691     if (state < JV_STATE_LINKED)
692       {
693         try
694           {
695             _Jv_Linker::wait_for_state(this, JV_STATE_LINKED);
696           }
697         catch (java::lang::Throwable *x)
698           {
699             // Turn into a NoClassDefFoundError.
700             java::lang::NoClassDefFoundError *result
701               = new java::lang::NoClassDefFoundError(getName());
702             result->initCause(x);
703             throw result;
704           }
705       }
706
707     // Step 2.
708     java::lang::Thread *self = java::lang::Thread::currentThread();
709     self = (java::lang::Thread *) ((long) self | 1);
710     while (state == JV_STATE_IN_PROGRESS && thread && thread != self)
711       wait ();
712
713     // Steps 3 &  4.
714     if (state == JV_STATE_DONE || state == JV_STATE_IN_PROGRESS)
715       return;
716
717     // Step 5.
718     if (state == JV_STATE_ERROR)
719       throw new java::lang::NoClassDefFoundError (getName());
720
721     // Step 6.
722     thread = self;
723     _Jv_Linker::wait_for_state (this, JV_STATE_LINKED);
724     state = JV_STATE_IN_PROGRESS;
725   }
726
727   // Step 7.
728   if (! isInterface () && superclass)
729     {
730       try
731         {
732           _Jv_InitClass (superclass);
733         }
734       catch (java::lang::Throwable *except)
735         {
736           // Caught an exception.
737           JvSynchronize sync (this);
738           state = JV_STATE_ERROR;
739           notifyAll ();
740           throw except;
741         }
742     }
743
744   // Steps 8, 9, 10, 11.
745   try
746     {
747       _Jv_Method *meth = _Jv_GetMethodLocal (this, clinit_name,
748                                              void_signature);
749       if (meth)
750         ((void (*) (void)) meth->ncode) ();
751     }
752   catch (java::lang::Throwable *except)
753     {
754       if (! java::lang::Error::class$.isInstance(except))
755         {
756           try
757             {
758               except = new ExceptionInInitializerError (except);
759             }
760           catch (java::lang::Throwable *t)
761             {
762               except = t;
763             }
764         }
765
766       JvSynchronize sync (this);
767       state = JV_STATE_ERROR;
768       notifyAll ();
769       throw except;
770     }
771
772   JvSynchronize sync (this);
773   state = JV_STATE_DONE;
774   notifyAll ();
775 }
776
777 // Only used by serialization
778 java::lang::reflect::Field *
779 java::lang::Class::getPrivateField (jstring name)
780 {
781   int hash = name->hashCode ();
782
783   java::lang::reflect::Field* rfield;
784   for (int i = 0;  i < field_count;  i++)
785     {
786       _Jv_Field *field = &fields[i];
787       if (! _Jv_equal (field->name, name, hash))
788         continue;
789       rfield = new java::lang::reflect::Field ();
790       rfield->offset = (char*) field - (char*) fields;
791       rfield->declaringClass = this;
792       rfield->name = name;
793       return rfield;
794     }
795   jclass superclass = getSuperclass();
796   if (superclass == NULL)
797     return NULL;
798   rfield = superclass->getPrivateField(name);
799   for (int i = 0; i < interface_count && rfield == NULL; ++i)
800     rfield = interfaces[i]->getPrivateField (name);
801   return rfield;
802 }
803
804 // Only used by serialization
805 java::lang::reflect::Method *
806 java::lang::Class::getPrivateMethod (jstring name, JArray<jclass> *param_types)
807 {
808   jstring partial_sig = getSignature (param_types, false);
809   jint p_len = partial_sig->length();
810   _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
811   for (Class *klass = this; klass; klass = klass->getSuperclass())
812     {
813       int i = klass->isPrimitive () ? 0 : klass->method_count;
814       while (--i >= 0)
815         {
816           if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
817               && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len))
818             {
819               // Found it.
820               using namespace java::lang::reflect;
821
822               Method *rmethod = new Method ();
823               rmethod->offset = ((char *) (&klass->methods[i])
824                                  - (char *) klass->methods);
825               rmethod->declaringClass = klass;
826               return rmethod;
827             }
828         }
829     }
830   throw new java::lang::NoSuchMethodException (name);
831 }
832
833 // Private accessor method for Java code to retrieve the protection domain.
834 java::security::ProtectionDomain *
835 java::lang::Class::getProtectionDomain0 ()
836 {
837   return protectionDomain;
838 }
839
840 JArray<jobject> *
841 java::lang::Class::getSigners()
842 {
843   return hack_signers;
844 }
845
846 void
847 java::lang::Class::setSigners(JArray<jobject> *s)
848 {
849   hack_signers = s;
850 }
851
852 \f
853
854 //
855 // Some class-related convenience functions.
856 //
857
858 // Find a method declared in the class.  If it is not declared locally
859 // (or if it is inherited), return NULL.
860 _Jv_Method *
861 _Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
862                     _Jv_Utf8Const *signature)
863 {
864   for (int i = 0; i < klass->method_count; ++i)
865     {
866       if (_Jv_equalUtf8Consts (name, klass->methods[i].name)
867           && _Jv_equalUtf8Consts (signature, klass->methods[i].signature))
868         return &klass->methods[i];
869     }
870   return NULL;
871 }
872
873 _Jv_Method *
874 _Jv_LookupDeclaredMethod (jclass klass, _Jv_Utf8Const *name,
875                           _Jv_Utf8Const *signature,
876                           jclass *declarer_result)
877 {
878   for (; klass; klass = klass->getSuperclass())
879     {
880       _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
881
882       if (meth)
883         {
884           if (declarer_result)
885             *declarer_result = klass;
886           return meth;
887         }
888     }
889
890   return NULL;
891 }
892
893 #ifdef HAVE_TLS
894
895 // NOTE: MCACHE_SIZE should be a power of 2 minus one.
896 #define MCACHE_SIZE 31
897
898 struct _Jv_mcache
899 {
900   jclass klass;
901   _Jv_Method *method;
902 };
903
904 static __thread _Jv_mcache *method_cache;
905 #endif // HAVE_TLS
906
907 static void *
908 _Jv_FindMethodInCache (jclass klass MAYBE_UNUSED,
909                        _Jv_Utf8Const *name MAYBE_UNUSED,
910                        _Jv_Utf8Const *signature MAYBE_UNUSED)
911 {
912 #ifdef HAVE_TLS
913   _Jv_mcache *cache = method_cache;
914   if (cache)
915     {
916       int index = name->hash16 () & MCACHE_SIZE;
917       _Jv_mcache *mc = &cache[index];
918       _Jv_Method *m = mc->method;
919
920       if (mc->klass == klass
921           && _Jv_equalUtf8Consts (m->name, name)
922           && _Jv_equalUtf8Consts (m->signature, signature))
923         return mc->method->ncode;
924     }
925 #endif // HAVE_TLS
926   return NULL;
927 }
928
929 static void
930 _Jv_AddMethodToCache (jclass klass MAYBE_UNUSED,
931                       _Jv_Method *method MAYBE_UNUSED)
932 {
933 #ifdef HAVE_TLS
934   if (method_cache == NULL)
935     method_cache = (_Jv_mcache *) _Jv_MallocUnchecked((MCACHE_SIZE + 1)
936                                                       * sizeof (_Jv_mcache));
937   // If the allocation failed, just keep going.
938   if (method_cache != NULL)
939     {
940       int index = method->name->hash16 () & MCACHE_SIZE;
941       method_cache[index].method = method;
942       method_cache[index].klass = klass;
943     }
944 #endif // HAVE_TLS
945 }
946
947 // Free this thread's method cache.  We explicitly manage this memory
948 // as the GC does not yet know how to scan TLS on all platforms.
949 void
950 _Jv_FreeMethodCache ()
951 {
952 #ifdef HAVE_TLS
953   if (method_cache != NULL)
954     {
955       _Jv_Free(method_cache);
956       method_cache = NULL;
957     }
958 #endif // HAVE_TLS
959 }
960
961 void *
962 _Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name,
963                            _Jv_Utf8Const *signature)
964 {
965   using namespace java::lang::reflect;
966
967   void *ncode = _Jv_FindMethodInCache (klass, name, signature);
968   if (ncode != 0)
969     return ncode;
970
971   for (; klass; klass = klass->getSuperclass())
972     {
973       _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
974       if (! meth)
975         continue;
976
977       if (Modifier::isStatic(meth->accflags))
978         throw new java::lang::IncompatibleClassChangeError
979           (_Jv_GetMethodString (klass, meth));
980       if (Modifier::isAbstract(meth->accflags))
981         throw new java::lang::AbstractMethodError
982           (_Jv_GetMethodString (klass, meth));
983       if (! Modifier::isPublic(meth->accflags))
984         throw new java::lang::IllegalAccessError
985           (_Jv_GetMethodString (klass, meth));
986
987       _Jv_AddMethodToCache (klass, meth);
988
989       return meth->ncode;
990     }
991   throw new java::lang::IncompatibleClassChangeError;
992 }
993
994 // Fast interface method lookup by index.
995 void *
996 _Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface, int method_idx)
997 {
998   _Jv_IDispatchTable *cldt = klass->idt;
999   int idx = iface->ioffsets[cldt->iindex] + method_idx;
1000   return cldt->itable[idx];
1001 }
1002
1003 jboolean
1004 _Jv_IsAssignableFrom (jclass source, jclass target)
1005 {
1006   if (source == target)
1007     return true;
1008
1009   // If target is array, so must source be.  
1010   while (target->isArray ())
1011     {
1012       if (! source->isArray())
1013         return false;
1014       target = target->getComponentType();
1015       source = source->getComponentType();
1016     }
1017
1018   if (target->isInterface())
1019     {
1020       // Abstract classes have no IDT, and IDTs provide no way to check
1021       // two interfaces for assignability.
1022       if (__builtin_expect 
1023           (source->idt == NULL || source->isInterface(), false))
1024         return _Jv_InterfaceAssignableFrom (source, target);
1025
1026       _Jv_IDispatchTable *cl_idt = source->idt;
1027
1028       if (__builtin_expect ((target->ioffsets == NULL), false))
1029         return false; // No class implementing TARGET has been loaded.    
1030       jshort cl_iindex = cl_idt->iindex;
1031       if (cl_iindex < target->ioffsets[0])
1032         {
1033           jshort offset = target->ioffsets[cl_iindex];
1034           if (offset != -1 && offset < cl_idt->itable_length
1035               && cl_idt->itable[offset] == target)
1036             return true;
1037         }
1038       return false;
1039     }
1040
1041   // Primitive TYPE classes are only assignable to themselves.
1042   if (__builtin_expect (target->isPrimitive() || source->isPrimitive(), false))
1043     return false;
1044
1045   if (target == &java::lang::Object::class$)
1046     return true;
1047   else if (source->ancestors == NULL || target->ancestors == NULL)
1048     {
1049       // We need this case when either SOURCE or TARGET has not has
1050       // its constant-time tables prepared.
1051
1052       // At this point we know that TARGET can't be Object, so it is
1053       // safe to use that as the termination point.
1054       while (source && source != &java::lang::Object::class$)
1055         {
1056           if (source == target)
1057             return true;
1058           source = source->getSuperclass();
1059         }
1060     }
1061   else if (source->depth >= target->depth
1062            && source->ancestors[source->depth - target->depth] == target)
1063     return true;
1064
1065   return false;
1066 }
1067
1068 // Interface type checking, the slow way. Returns TRUE if IFACE is a 
1069 // superinterface of SOURCE. This is used when SOURCE is also an interface,
1070 // or a class with no interface dispatch table.
1071 jboolean
1072 _Jv_InterfaceAssignableFrom (jclass source, jclass iface)
1073 {
1074   for (int i = 0; i < source->interface_count; i++)
1075     {
1076       jclass interface = source->interfaces[i];
1077       if (iface == interface
1078           || _Jv_InterfaceAssignableFrom (interface, iface))
1079         return true;      
1080     }
1081     
1082   if (!source->isInterface()
1083       && source->superclass 
1084       && _Jv_InterfaceAssignableFrom (source->superclass, iface))
1085     return true;
1086         
1087   return false;
1088 }
1089
1090 jboolean
1091 _Jv_IsInstanceOf(jobject obj, jclass cl)
1092 {
1093   if (__builtin_expect (!obj, false))
1094     return false;
1095   return _Jv_IsAssignableFrom (JV_CLASS (obj), cl);
1096 }
1097
1098 void *
1099 _Jv_CheckCast (jclass c, jobject obj)
1100 {
1101   if (__builtin_expect 
1102       (obj != NULL && ! _Jv_IsAssignableFrom(JV_CLASS (obj), c), false))
1103     throw new java::lang::ClassCastException
1104       ((new java::lang::StringBuffer
1105         (obj->getClass()->getName()))->append
1106        (JvNewStringUTF(" cannot be cast to "))->append
1107        (c->getName())->toString());
1108
1109   return obj;
1110 }
1111
1112 void
1113 _Jv_CheckArrayStore (jobject arr, jobject obj)
1114 {
1115   if (obj)
1116     {
1117       JvAssert (arr != NULL);
1118       jclass elt_class = (JV_CLASS (arr))->getComponentType();
1119       if (elt_class == &java::lang::Object::class$)
1120         return;
1121       jclass obj_class = JV_CLASS (obj);
1122       if (__builtin_expect 
1123           (! _Jv_IsAssignableFrom (obj_class, elt_class), false))
1124         throw new java::lang::ArrayStoreException
1125                 ((new java::lang::StringBuffer
1126                  (JvNewStringUTF("Cannot store ")))->append
1127                  (obj_class->getName())->append
1128                  (JvNewStringUTF(" in array of type "))->append
1129                  (elt_class->getName())->toString());
1130     }
1131 }
1132
1133 jboolean
1134 _Jv_IsAssignableFromSlow (jclass source, jclass target)
1135 {
1136   // First, strip arrays.
1137   while (target->isArray ())
1138     {
1139       // If target is array, source must be as well.
1140       if (! source->isArray ())
1141        return false;
1142       target = target->getComponentType ();
1143       source = source->getComponentType ();
1144     }
1145
1146   // Quick success.
1147   if (target == &java::lang::Object::class$)
1148     return true;
1149
1150   // Ensure that the classes have their supers installed.
1151   _Jv_Linker::wait_for_state (source, JV_STATE_LOADING);
1152   _Jv_Linker::wait_for_state (target, JV_STATE_LOADING);
1153
1154   do
1155     {
1156       if (source == target)
1157        return true;
1158
1159       if (target->isPrimitive () || source->isPrimitive ())
1160        return false;
1161
1162       if (target->isInterface ())
1163        {
1164          for (int i = 0; i < source->interface_count; ++i)
1165            {
1166              // We use a recursive call because we also need to
1167              // check superinterfaces.
1168              if (_Jv_IsAssignableFromSlow (source->getInterface (i), target))
1169                return true;
1170            }
1171        }
1172       source = source->getSuperclass ();
1173     }
1174   while (source != NULL);
1175
1176   return false;
1177 }
1178
1179 // Lookup an interface method by name.  This is very similar to
1180 // purpose to _getMethod, but the interfaces are quite different.  It
1181 // might be a good idea for _getMethod to call this function.
1182 //
1183 // Return true of the method is found, with the class in FOUND_CLASS
1184 // and the index in INDEX.
1185 bool
1186 _Jv_getInterfaceMethod (jclass search_class, jclass &found_class, int &index,
1187                         const _Jv_Utf8Const *utf_name,  
1188                         const _Jv_Utf8Const *utf_sig)
1189 {
1190    for (jclass klass = search_class; klass; klass = klass->getSuperclass())
1191     {
1192       // FIXME: Throw an exception?
1193       if (!klass->isInterface ())
1194         return false;
1195       
1196       int max = klass->method_count;
1197       int offset = 0;
1198       for (int i = 0; i < max; ++i)
1199         {
1200           // Skip <clinit> here, as it will not be in the IDT.
1201           if (klass->methods[i].name->first() == '<')
1202             continue;
1203
1204           if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
1205               && _Jv_equalUtf8Consts (klass->methods[i].signature, utf_sig))
1206             {
1207               // Found it.
1208               using namespace java::lang::reflect;
1209
1210               // FIXME: Method must be public.  Throw an exception?
1211               if (! Modifier::isPublic (klass->methods[i].accflags))
1212                 break;
1213
1214               found_class = klass;
1215               // Interface method indexes count from 1.
1216               index = offset + 1;
1217               return true;
1218             }
1219
1220           ++offset;
1221         }
1222     }
1223
1224   // If we haven't found a match, and this class is an interface, then
1225   // check all the superinterfaces.
1226   if (search_class->isInterface())
1227     {
1228       for (int i = 0; i < search_class->interface_count; ++i)
1229         {
1230           using namespace java::lang::reflect;
1231           bool found = _Jv_getInterfaceMethod (search_class->interfaces[i], 
1232                                                found_class, index,
1233                                                utf_name, utf_sig);
1234           if (found)
1235             return true;
1236         }
1237     }
1238
1239   return false;
1240 }
1241
1242 #ifdef INTERPRETER
1243 _Jv_MethodBase *
1244 _Jv_FindInterpreterMethod (jclass klass, jmethodID desired_method)
1245 {
1246   using namespace java::lang::reflect;
1247
1248   _Jv_InterpClass *iclass
1249     = reinterpret_cast<_Jv_InterpClass *> (klass->aux_info);
1250   _Jv_MethodBase **imethods = _Jv_GetFirstMethod (iclass);
1251
1252   for (int i = 0; i < JvNumMethods (klass); ++i)
1253     {
1254       _Jv_MethodBase *imeth = imethods[i];
1255       if (imeth->get_method () == desired_method)
1256         return imeth;
1257     }
1258
1259   return NULL;
1260 }
1261 #endif
1262
1263 // Return Utf8 name of a class. This function is here for code that
1264 // can't access klass->name directly.
1265 _Jv_Utf8Const*
1266 _Jv_GetClassNameUtf8 (jclass klass)
1267 {
1268   return klass->name;
1269 }
1270
1271 jclass
1272 _Jv_GetMethodDeclaringClass (jmethodID method)
1273 {
1274   _Jv_StackTrace::UpdateNCodeMap ();
1275   jobject obj = reinterpret_cast<jobject> (method->ncode);
1276   return reinterpret_cast<jclass> (_Jv_StackTrace::ncodeMap->get (obj));
1277 }
1278