OSDN Git Service

Print -verbose:message on "loading", not initialization.
[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  
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
18 #pragma implementation "Class.h"
19
20 #include <gcj/cni.h>
21 #include <jvm.h>
22 #include <java-threads.h>
23
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>
59
60 #include <java-cpool.h>
61 #include <java-interp.h>
62
63 \f
64
65 using namespace gcj;
66
67 bool gcj::verbose_class_flag;
68
69 jclass
70 java::lang::Class::forName (jstring className, jboolean initialize,
71                             java::lang::ClassLoader *loader)
72 {
73   if (! className)
74     throw new java::lang::NullPointerException;
75
76   jsize length = _Jv_GetStringUTFLength (className);
77   char buffer[length];
78   _Jv_GetStringUTFRegion (className, 0, className->length(), buffer);
79
80   _Jv_Utf8Const *name = _Jv_makeUtf8Const (buffer, length);
81
82   if (! _Jv_VerifyClassName (name))
83     throw new java::lang::ClassNotFoundException (className);
84
85   jclass klass = (buffer[0] == '[' 
86                   ? _Jv_FindClassFromSignature (name->data, loader)
87                   : _Jv_FindClass (name, loader));
88
89   if (klass == NULL)
90     throw new java::lang::ClassNotFoundException (className);
91
92   if (initialize)
93     _Jv_InitClass (klass);
94
95   return klass;
96 }
97
98 jclass
99 java::lang::Class::forName (jstring className)
100 {
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;
105   try
106     {
107       for (int i = 1; !klass; i++)
108         {
109           klass = t->classAt (i);
110         }
111       loader = klass->getClassLoaderInternal();
112     }
113   catch (::java::lang::ArrayIndexOutOfBoundsException *e)
114     {
115     }
116
117   return forName (className, true, loader);
118 }
119
120 java::lang::ClassLoader *
121 java::lang::Class::getClassLoader (void)
122 {
123   java::lang::SecurityManager *s = java::lang::System::getSecurityManager();
124   if (s != NULL)
125     {
126       gnu::gcj::runtime::StackTrace *t 
127         = new gnu::gcj::runtime::StackTrace(4);
128       Class *caller = NULL;
129       ClassLoader *caller_loader = NULL;
130       try
131         {
132           for (int i = 1; !caller; i++)
133             {
134               caller = t->classAt (i);
135             }
136           caller_loader = caller->getClassLoaderInternal();
137         }
138       catch (::java::lang::ArrayIndexOutOfBoundsException *e)
139         {
140         }
141
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
144       // security check.
145       if (caller_loader != NULL && ! caller_loader->isAncestorOf(loader))
146         s->checkPermission (new RuntimePermission (JvNewStringLatin1 ("getClassLoader")));
147     }
148
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
155   // `null' instead.
156   if (isPrimitive ())
157     return NULL;
158   return loader ? loader : ClassLoader::systemClassLoader;
159 }
160
161 java::lang::reflect::Constructor *
162 java::lang::Class::getConstructor (JArray<jclass> *param_types)
163 {
164   memberAccessCheck(java::lang::reflect::Member::PUBLIC);
165
166   jstring partial_sig = getSignature (param_types, true);
167   jint hash = partial_sig->hashCode ();
168
169   int i = isPrimitive () ? 0 : method_count;
170   while (--i >= 0)
171     {
172       if (_Jv_equalUtf8Consts (methods[i].name, init_name)
173           && _Jv_equal (methods[i].signature, partial_sig, hash))
174         {
175           // Found it.  For getConstructor, the constructor must be
176           // public.
177           using namespace java::lang::reflect;
178           if (! Modifier::isPublic(methods[i].accflags))
179             break;
180           Constructor *cons = new Constructor ();
181           cons->offset = (char *) (&methods[i]) - (char *) methods;
182           cons->declaringClass = this;
183           return cons;
184         }
185     }
186   throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
187 }
188
189 JArray<java::lang::reflect::Constructor *> *
190 java::lang::Class::_getConstructors (jboolean declared)
191 {
192   memberAccessCheck(java::lang::reflect::Member::PUBLIC);
193
194   int numConstructors = 0;
195   int max = isPrimitive () ? 0 : method_count;
196   int i;
197   for (i = max; --i >= 0; )
198     {
199       _Jv_Method *method = &methods[i];
200       if (method->name == NULL
201           || ! _Jv_equalUtf8Consts (method->name, init_name))
202         continue;
203       if (! declared
204           && ! java::lang::reflect::Modifier::isPublic(method->accflags))
205         continue;
206       numConstructors++;
207     }
208   JArray<java::lang::reflect::Constructor *> *result
209     = (JArray<java::lang::reflect::Constructor *> *)
210     JvNewObjectArray (numConstructors,
211                       &java::lang::reflect::Constructor::class$,
212                       NULL);
213   java::lang::reflect::Constructor** cptr = elements (result);
214   for (i = 0;  i < max;  i++)
215     {
216       _Jv_Method *method = &methods[i];
217       if (method->name == NULL
218           || ! _Jv_equalUtf8Consts (method->name, init_name))
219         continue;
220       if (! declared
221           && ! java::lang::reflect::Modifier::isPublic(method->accflags))
222         continue;
223       java::lang::reflect::Constructor *cons
224         = new java::lang::reflect::Constructor ();
225       cons->offset = (char *) method - (char *) methods;
226       cons->declaringClass = this;
227       *cptr++ = cons;
228     }
229   return result;
230 }
231
232 java::lang::reflect::Constructor *
233 java::lang::Class::getDeclaredConstructor (JArray<jclass> *param_types)
234 {
235   memberAccessCheck(java::lang::reflect::Member::DECLARED);
236
237   jstring partial_sig = getSignature (param_types, true);
238   jint hash = partial_sig->hashCode ();
239
240   int i = isPrimitive () ? 0 : method_count;
241   while (--i >= 0)
242     {
243       if (_Jv_equalUtf8Consts (methods[i].name, init_name)
244           && _Jv_equal (methods[i].signature, partial_sig, hash))
245         {
246           // Found it.
247           using namespace java::lang::reflect;
248           Constructor *cons = new Constructor ();
249           cons->offset = (char *) (&methods[i]) - (char *) methods;
250           cons->declaringClass = this;
251           return cons;
252         }
253     }
254   throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
255 }
256
257 java::lang::reflect::Field *
258 java::lang::Class::getField (jstring name, jint hash)
259 {
260   java::lang::reflect::Field* rfield;
261   for (int i = 0;  i < field_count;  i++)
262     {
263       _Jv_Field *field = &fields[i];
264       if (! _Jv_equal (field->name, name, hash))
265         continue;
266       if (! (field->getModifiers() & java::lang::reflect::Modifier::PUBLIC))
267         continue;
268       rfield = new java::lang::reflect::Field ();
269       rfield->offset = (char*) field - (char*) fields;
270       rfield->declaringClass = this;
271       rfield->name = name;
272       return rfield;
273     }
274   jclass superclass = getSuperclass();
275   if (superclass == NULL)
276     return 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);
280   return rfield;
281 }
282
283 java::lang::reflect::Field *
284 java::lang::Class::getDeclaredField (jstring name)
285 {
286   memberAccessCheck(java::lang::reflect::Member::DECLARED);
287   int hash = name->hashCode();
288   for (int i = 0;  i < field_count;  i++)
289     {
290       _Jv_Field *field = &fields[i];
291       if (! _Jv_equal (field->name, name, hash))
292         continue;
293       java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
294       rfield->offset = (char*) field - (char*) fields;
295       rfield->declaringClass = this;
296       rfield->name = name;
297       return rfield;
298     }
299   throw new java::lang::NoSuchFieldException (name);
300 }
301
302 JArray<java::lang::reflect::Field *> *
303 java::lang::Class::getDeclaredFields (jboolean public_only)
304 {
305   int size;
306   if (public_only)
307     {
308       size = 0;
309       for (int i = 0; i < field_count; ++i)
310         {
311           _Jv_Field *field = &fields[i];
312           if ((field->flags & java::lang::reflect::Modifier::PUBLIC))
313             ++size;
314         }
315     }
316   else
317     size = field_count;
318
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++)
324     {
325       _Jv_Field *field = &fields[i];
326       if (public_only
327           && ! (field->flags & java::lang::reflect::Modifier::PUBLIC))
328         continue;
329       java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
330       rfield->offset = (char*) field - (char*) fields;
331       rfield->declaringClass = this;
332       *fptr++ = rfield;
333     }
334   return result;
335 }
336
337 void
338 java::lang::Class::getSignature (java::lang::StringBuffer *buffer)
339 {
340   if (isPrimitive())
341     buffer->append((jchar) method_count);
342   else
343     {
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) ';');
350     }
351 }
352
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.
355 jstring
356 java::lang::Class::getSignature (JArray<jclass> *param_types,
357                                  jboolean is_constructor)
358 {
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)
363     {
364       jclass *v = elements (param_types);
365       for (int i = 0; i < param_types->length; ++i)
366         v[i]->getSignature(buf);
367     }
368   buf->append((jchar) ')');
369   if (is_constructor)
370     buf->append((jchar) 'V');
371   return buf->toString();
372 }
373
374 java::lang::reflect::Method *
375 java::lang::Class::_getDeclaredMethod (jstring name,
376                                        JArray<jclass> *param_types)
377 {
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;
382   while (--i >= 0)
383     {
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)
388         {
389           // Found it.
390           using namespace java::lang::reflect;
391           Method *rmethod = new Method ();
392           rmethod->offset = (char*) (&methods[i]) - (char*) methods;
393           rmethod->declaringClass = this;
394           return rmethod;
395         }
396     }
397   return NULL;
398 }
399
400 JArray<java::lang::reflect::Method *> *
401 java::lang::Class::getDeclaredMethods (void)
402 {
403   memberAccessCheck(java::lang::reflect::Member::DECLARED);
404
405   int numMethods = 0;
406   int max = isPrimitive () ? 0 : method_count;
407   int i;
408   for (i = max; --i >= 0; )
409     {
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)
417         continue;
418       numMethods++;
419     }
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++)
425     {
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)
433         continue;
434       java::lang::reflect::Method* rmethod
435         = new java::lang::reflect::Method ();
436       rmethod->offset = (char*) method - (char*) methods;
437       rmethod->declaringClass = this;
438       *mptr++ = rmethod;
439     }
440   return result;
441 }
442
443 jstring
444 java::lang::Class::getName (void)
445 {
446   char buffer[name->length + 1];  
447   memcpy (buffer, name->data, name->length); 
448   buffer[name->length] = '\0';
449   return _Jv_NewStringUTF (buffer);
450 }
451
452 JArray<jclass> *
453 java::lang::Class::getClasses (void)
454 {
455   // FIXME: security checking.
456
457   // Until we have inner classes, it always makes sense to return an
458   // empty array.
459   JArray<jclass> *result
460     = (JArray<jclass> *) JvNewObjectArray (0, &java::lang::Class::class$,
461                                            NULL);
462   return result;
463 }
464
465 JArray<jclass> *
466 java::lang::Class::getDeclaredClasses (void)
467 {
468   memberAccessCheck (java::lang::reflect::Member::DECLARED);
469   // Until we have inner classes, it always makes sense to return an
470   // empty array.
471   JArray<jclass> *result
472     = (JArray<jclass> *) JvNewObjectArray (0, &java::lang::Class::class$,
473                                            NULL);
474   return result;
475 }
476
477 jclass
478 java::lang::Class::getDeclaringClass (void)
479 {
480   // Until we have inner classes, it makes sense to always return
481   // NULL.
482   return NULL;
483 }
484
485 JArray<jclass> *
486 java::lang::Class::getInterfaces (void)
487 {
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);
493 }
494
495 java::lang::reflect::Method *
496 java::lang::Class::_getMethod (jstring name, JArray<jclass> *param_types)
497 {
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())
502     {
503       int i = klass->isPrimitive () ? 0 : klass->method_count;
504       while (--i >= 0)
505         {
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)
510             {
511               // Found it.
512               using namespace java::lang::reflect;
513
514               // Method must be public.
515               if (! Modifier::isPublic (klass->methods[i].accflags))
516                 break;
517
518               Method *rmethod = new Method ();
519               rmethod->offset = ((char *) (&klass->methods[i])
520                                  - (char *) klass->methods);
521               rmethod->declaringClass = klass;
522               return rmethod;
523             }
524         }
525     }
526
527   // If we haven't found a match, and this class is an interface, then
528   // check all the superinterfaces.
529   if (isInterface())
530     {
531       for (int i = 0; i < interface_count; ++i)
532         {
533           using namespace java::lang::reflect;
534           Method *rmethod = interfaces[i]->_getMethod (name, param_types);
535           if (rmethod != NULL)
536             return rmethod;
537         }
538     }
539
540   return NULL;
541 }
542
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.
547 jint
548 java::lang::Class::_getMethods (JArray<java::lang::reflect::Method *> *result,
549                                 jint offset)
550 {
551   jint count = 0;
552
553   // First examine all local methods
554   for (int i = isPrimitive () ? 0 : method_count; --i >= 0; )
555     {
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)
561           || (method->accflags
562               & java::lang::reflect::Modifier::INVISIBLE) != 0)
563         continue;
564       // Only want public methods.
565       if (! java::lang::reflect::Modifier::isPublic (method->accflags))
566         continue;
567
568       // This is where we over-count the slots required if we aren't
569       // filling the result for real.
570       if (result != NULL)
571         {
572           jboolean add = true;
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
576           // methods.
577           for (int j = 0; j < offset; ++j)
578             {
579               _Jv_Method *meth_2 = _Jv_FromReflectedMethod (mp[j]);
580               if (_Jv_equalUtf8Consts (method->name, meth_2->name)
581                   && _Jv_equalUtf8Consts (method->signature,
582                                           meth_2->signature))
583                 {
584                   add = false;
585                   break;
586                 }
587             }
588           if (! add)
589             continue;
590         }
591
592       if (result != NULL)
593         {
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;
600         }
601       ++count;
602     }
603   offset += count;
604
605   // Now examine superclasses.
606   if (getSuperclass () != NULL)
607     {
608       jint s_count = getSuperclass()->_getMethods (result, offset);
609       offset += s_count;
610       count += s_count;
611     }
612
613   // Finally, examine interfaces.
614   for (int i = 0; i < interface_count; ++i)
615     {
616       int f_count = interfaces[i]->_getMethods (result, offset);
617       count += f_count;
618       offset += f_count;
619     }
620
621   return count;
622 }
623
624 JArray<java::lang::reflect::Method *> *
625 java::lang::Class::getMethods (void)
626 {
627   using namespace java::lang::reflect;
628
629   memberAccessCheck(Member::PUBLIC);
630
631   // This will overestimate the size we need.
632   jint count = _getMethods (NULL, 0);
633
634   JArray<Method *> *result
635     = ((JArray<Method *> *) JvNewObjectArray (count,
636                                               &Method::class$,
637                                               NULL));
638
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);
642
643   if (real_count != count)
644     {
645       JArray<Method *> *r2
646         = ((JArray<Method *> *) JvNewObjectArray (real_count,
647                                                   &Method::class$,
648                                                   NULL));
649       
650       Method **destp = elements (r2);
651       Method **srcp = elements (result);
652
653       for (int i = 0; i < real_count; ++i)
654         *destp++ = *srcp++;
655
656       result = r2;
657     }
658
659   return result;
660 }
661
662 jboolean
663 java::lang::Class::isAssignableFrom (jclass klass)
664 {
665   // Arguments may not have been initialized, given ".class" syntax.
666   _Jv_InitClass (this);
667   _Jv_InitClass (klass);
668   return _Jv_IsAssignableFrom (this, klass);
669 }
670
671 jboolean
672 java::lang::Class::isInstance (jobject obj)
673 {
674   if (! obj)
675     return false;
676   _Jv_InitClass (this);
677   return _Jv_IsAssignableFrom (this, JV_CLASS (obj));
678 }
679
680 jobject
681 java::lang::Class::newInstance (void)
682 {
683   memberAccessCheck(java::lang::reflect::Member::PUBLIC);
684
685   if (isPrimitive ()
686       || isInterface ()
687       || isArray ()
688       || java::lang::reflect::Modifier::isAbstract(accflags))
689     throw new java::lang::InstantiationException (getName ());
690
691   _Jv_InitClass (this);
692
693   _Jv_Method *meth = _Jv_GetMethodLocal (this, init_name, void_signature);
694   if (! meth)
695     throw new java::lang::InstantiationException (getName());
696
697   jobject r = _Jv_AllocObject (this);
698   ((void (*) (jobject)) meth->ncode) (r);
699   return r;
700 }
701
702 void
703 java::lang::Class::finalize (void)
704 {
705 #ifdef INTERPRETER
706   JvAssert (_Jv_IsInterpretedClass (this));
707   _Jv_UnregisterClass (this);
708 #endif
709 }
710
711 // This implements the initialization process for a class.  From Spec
712 // section 12.4.2.
713 void
714 java::lang::Class::initializeClass (void)
715 {
716   // short-circuit to avoid needless locking.
717   if (state == JV_STATE_DONE)
718     return;
719
720   // Step 1.
721   _Jv_MonitorEnter (this);
722
723   if (state < JV_STATE_LINKED)
724     {    
725 #ifdef INTERPRETER
726       if (_Jv_IsInterpretedClass (this))
727         {
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);
732         }
733       else
734 #endif
735         {
736           _Jv_PrepareCompiledClass (this);
737         }
738     }
739
740   // Step 2.
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)
745     wait ();
746
747   // Steps 3 &  4.
748   if (state == JV_STATE_DONE)
749     {
750       _Jv_MonitorExit (this);
751       return;
752     }
753   if (state == JV_STATE_IN_PROGRESS)
754     {
755       _Jv_MonitorExit (this);
756
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);
762
763       return;
764     }
765
766   // Step 5.
767   if (state == JV_STATE_ERROR)
768     {
769       _Jv_MonitorExit (this);
770       throw new java::lang::NoClassDefFoundError (getName());
771     }
772
773   // Step 6.
774   thread = self;
775   state = JV_STATE_IN_PROGRESS;
776   _Jv_MonitorExit (this);
777
778   // Step 7.
779   if (! isInterface () && superclass)
780     {
781       try
782         {
783           _Jv_InitClass (superclass);
784         }
785       catch (java::lang::Throwable *except)
786         {
787           // Caught an exception.
788           _Jv_MonitorEnter (this);
789           state = JV_STATE_ERROR;
790           notifyAll ();
791           _Jv_MonitorExit (this);
792           throw except;
793         }
794     }
795
796   _Jv_PrepareConstantTimeTables (this);
797
798   if (vtable == NULL)
799     _Jv_MakeVTable(this);
800
801   if (otable || atable)
802     _Jv_LinkSymbolTable(this);
803
804   _Jv_linkExceptionClassTable (this);
805
806   // Steps 8, 9, 10, 11.
807   try
808     {
809       _Jv_Method *meth = _Jv_GetMethodLocal (this, clinit_name,
810                                              void_signature);
811       if (meth)
812         ((void (*) (void)) meth->ncode) ();
813     }
814   catch (java::lang::Throwable *except)
815     {
816       if (! java::lang::Error::class$.isInstance(except))
817         {
818           try
819             {
820               except = new ExceptionInInitializerError (except);
821             }
822           catch (java::lang::Throwable *t)
823             {
824               except = t;
825             }
826         }
827       _Jv_MonitorEnter (this);
828       state = JV_STATE_ERROR;
829       notifyAll ();
830       _Jv_MonitorExit (this);
831       throw except;
832     }
833
834   _Jv_MonitorEnter (this);
835   state = JV_STATE_DONE;
836   notifyAll ();
837   _Jv_MonitorExit (this);
838 }
839
840 \f
841
842 //
843 // Some class-related convenience functions.
844 //
845
846 // Find a method declared in the class.  If it is not declared locally
847 // (or if it is inherited), return NULL.
848 _Jv_Method *
849 _Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
850                     _Jv_Utf8Const *signature)
851 {
852   for (int i = 0; i < klass->method_count; ++i)
853     {
854       if (_Jv_equalUtf8Consts (name, klass->methods[i].name)
855           && _Jv_equalUtf8Consts (signature, klass->methods[i].signature))
856         return &klass->methods[i];
857     }
858   return NULL;
859 }
860
861 _Jv_Method *
862 _Jv_LookupDeclaredMethod (jclass klass, _Jv_Utf8Const *name,
863                           _Jv_Utf8Const *signature)
864 {
865   for (; klass; klass = klass->getSuperclass())
866     {
867       _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
868
869       if (meth)
870         return meth;
871     }
872
873   return NULL;
874 }
875
876 // NOTE: MCACHE_SIZE should be a power of 2 minus one.
877 #define MCACHE_SIZE 1023
878
879 struct _Jv_mcache
880 {
881   jclass klass;
882   _Jv_Method *method;
883 };
884
885 static _Jv_mcache method_cache[MCACHE_SIZE + 1];
886
887 static void *
888 _Jv_FindMethodInCache (jclass klass,
889                        _Jv_Utf8Const *name,
890                        _Jv_Utf8Const *signature)
891 {
892   int index = name->hash & MCACHE_SIZE;
893   _Jv_mcache *mc = method_cache + index;
894   _Jv_Method *m = mc->method;
895
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;
901   return NULL;
902 }
903
904 static void
905 _Jv_AddMethodToCache (jclass klass,
906                        _Jv_Method *method)
907 {
908   _Jv_MonitorEnter (&java::lang::Class::class$); 
909
910   int index = method->name->hash & MCACHE_SIZE;
911
912   method_cache[index].method = method;
913   method_cache[index].klass = klass;
914
915   _Jv_MonitorExit (&java::lang::Class::class$);
916 }
917
918 void *
919 _Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name,
920                            _Jv_Utf8Const *signature)
921 {
922   using namespace java::lang::reflect;
923
924   void *ncode = _Jv_FindMethodInCache (klass, name, signature);
925   if (ncode != 0)
926     return ncode;
927
928   for (; klass; klass = klass->getSuperclass())
929     {
930       _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
931       if (! meth)
932         continue;
933
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));
943
944       _Jv_AddMethodToCache (klass, meth);
945
946       return meth->ncode;
947     }
948   throw new java::lang::IncompatibleClassChangeError;
949 }
950
951 // Fast interface method lookup by index.
952 void *
953 _Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface, int method_idx)
954 {
955   _Jv_IDispatchTable *cldt = klass->idt;
956   int idx = iface->idt->iface.ioffsets[cldt->cls.iindex] + method_idx;
957   return cldt->cls.itable[idx];
958 }
959
960 jboolean
961 _Jv_IsAssignableFrom (jclass target, jclass source)
962 {
963   if (source == target)
964     return true;
965
966   // If target is array, so must source be.  
967   while (target->isArray ())
968     {
969       if (! source->isArray())
970         return false;
971       target = target->getComponentType();
972       source = source->getComponentType();
973     }
974
975   if (target->isInterface())
976     {
977       // Abstract classes have no IDT, and IDTs provide no way to check
978       // two interfaces for assignability.
979       if (__builtin_expect 
980           (source->idt == NULL || source->isInterface(), false))
981         return _Jv_InterfaceAssignableFrom (target, source);
982
983       _Jv_IDispatchTable *cl_idt = source->idt;
984       _Jv_IDispatchTable *if_idt = target->idt;
985
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])
990         {
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)
994             return true;
995         }
996       return false;
997     }
998
999   // Primitive TYPE classes are only assignable to themselves.
1000   if (__builtin_expect (target->isPrimitive() || source->isPrimitive(), false))
1001     return false;
1002
1003   if (target == &java::lang::Object::class$)
1004     return true;
1005   else if (source->ancestors == NULL || target->ancestors == NULL)
1006     {
1007       // We need this case when either SOURCE or TARGET has not has
1008       // its constant-time tables prepared.
1009
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$)
1013         {
1014           if (source == target)
1015             return true;
1016           source = source->getSuperclass();
1017         }
1018     }
1019   else if (source->depth >= target->depth
1020            && source->ancestors[source->depth - target->depth] == target)
1021     return true;
1022
1023   return false;
1024 }
1025
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.
1029 jboolean
1030 _Jv_InterfaceAssignableFrom (jclass iface, jclass source)
1031 {
1032   for (int i = 0; i < source->interface_count; i++)
1033     {
1034       jclass interface = source->interfaces[i];
1035       if (iface == interface
1036           || _Jv_InterfaceAssignableFrom (iface, interface))
1037         return true;      
1038     }
1039     
1040   if (!source->isInterface()
1041       && source->superclass 
1042       && _Jv_InterfaceAssignableFrom (iface, source->superclass))
1043     return true;
1044         
1045   return false;
1046 }
1047
1048 jboolean
1049 _Jv_IsInstanceOf(jobject obj, jclass cl)
1050 {
1051   if (__builtin_expect (!obj, false))
1052     return false;
1053   return (_Jv_IsAssignableFrom (cl, JV_CLASS (obj)));
1054 }
1055
1056 void *
1057 _Jv_CheckCast (jclass c, jobject obj)
1058 {
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());
1066
1067   return obj;
1068 }
1069
1070 void
1071 _Jv_CheckArrayStore (jobject arr, jobject obj)
1072 {
1073   if (obj)
1074     {
1075       JvAssert (arr != NULL);
1076       jclass elt_class = (JV_CLASS (arr))->getComponentType();
1077       if (elt_class == &java::lang::Object::class$)
1078         return;
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());
1088     }
1089 }
1090
1091 #define INITIAL_IOFFSETS_LEN 4
1092 #define INITIAL_IFACES_LEN 4
1093
1094 static _Jv_IDispatchTable null_idt = { {SHRT_MAX, 0, NULL} };
1095
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
1100 void 
1101 _Jv_PrepareConstantTimeTables (jclass klass)
1102 {  
1103   if (klass->isPrimitive () || klass->isInterface ())
1104     return;
1105   
1106   // Short-circuit in case we've been called already.
1107   if ((klass->idt != NULL) || klass->depth != 0)
1108     return;
1109
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.
1115    
1116   jclass klass0 = klass;
1117   jboolean has_interfaces = 0;
1118   while (klass0 != &java::lang::Object::class$)
1119     {
1120       has_interfaces += klass0->interface_count;
1121       klass0 = klass0->superclass;
1122       klass->depth++;
1123     }
1124
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.
1131         
1132   klass->ancestors = (jclass *) _Jv_Malloc (klass->depth * sizeof (jclass));
1133   klass0 = klass;
1134   for (int index = 0; index < klass->depth; index++)
1135     {
1136       klass->ancestors[index] = klass0;
1137       klass0 = klass0->superclass;
1138     }
1139     
1140   if (java::lang::reflect::Modifier::isAbstract (klass->accflags))
1141     return;
1142   
1143   // Optimization: If class implements no interfaces, use a common
1144   // predefined interface table.
1145   if (!has_interfaces)
1146     {
1147       klass->idt = &null_idt;
1148       return;
1149     }
1150
1151   klass->idt = 
1152     (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable));
1153     
1154   _Jv_ifaces ifaces;
1155
1156   ifaces.count = 0;
1157   ifaces.len = INITIAL_IFACES_LEN;
1158   ifaces.list = (jclass *) _Jv_Malloc (ifaces.len * sizeof (jclass *));
1159
1160   int itable_size = _Jv_GetInterfaces (klass, &ifaces);
1161
1162   if (ifaces.count > 0)
1163     {
1164       klass->idt->cls.itable = 
1165         (void **) _Jv_Malloc (itable_size * sizeof (void *));
1166       klass->idt->cls.itable_length = itable_size;
1167           
1168       jshort *itable_offsets = 
1169         (jshort *) _Jv_Malloc (ifaces.count * sizeof (jshort));
1170
1171       _Jv_GenerateITable (klass, &ifaces, itable_offsets);
1172
1173       jshort cls_iindex = 
1174         _Jv_FindIIndex (ifaces.list, itable_offsets, ifaces.count);
1175
1176       for (int i=0; i < ifaces.count; i++)
1177         {
1178           ifaces.list[i]->idt->iface.ioffsets[cls_iindex] =
1179             itable_offsets[i];
1180         }
1181
1182       klass->idt->cls.iindex = cls_iindex;          
1183
1184       _Jv_Free (ifaces.list);
1185       _Jv_Free (itable_offsets);
1186     }
1187   else 
1188     {
1189       klass->idt->cls.iindex = SHRT_MAX;
1190     }
1191 }
1192
1193 // Return index of item in list, or -1 if item is not present.
1194 inline jshort
1195 _Jv_IndexOf (void *item, void **list, jshort list_len)
1196 {
1197   for (int i=0; i < list_len; i++)
1198     {
1199       if (list[i] == item)
1200         return i;
1201     }
1202   return -1;
1203 }
1204
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.
1209 jshort
1210 _Jv_GetInterfaces (jclass klass, _Jv_ifaces *ifaces)
1211 {
1212   jshort result = 0;
1213   
1214   for (int i=0; i < klass->interface_count; i++)
1215     {
1216       jclass iface = klass->interfaces[i];
1217
1218       /* Make sure interface is linked.  */
1219       _Jv_WaitForState(iface, JV_STATE_LINKED);
1220
1221       if (_Jv_IndexOf (iface, (void **) ifaces->list, ifaces->count) == -1)
1222         {
1223           if (ifaces->count + 1 >= ifaces->len)
1224             {
1225               /* Resize ifaces list */
1226               ifaces->len = ifaces->len * 2;
1227               ifaces->list = (jclass *) _Jv_Realloc (ifaces->list, 
1228                              ifaces->len * sizeof(jclass));
1229             }
1230           ifaces->list[ifaces->count] = iface;
1231           ifaces->count++;
1232
1233           result += _Jv_GetInterfaces (klass->interfaces[i], ifaces);
1234         }
1235     }
1236     
1237   if (klass->isInterface())
1238     {
1239       result += klass->method_count + 1;
1240     }
1241   else
1242     {
1243       if (klass->superclass)
1244         {
1245           result += _Jv_GetInterfaces (klass->superclass, ifaces);
1246         }
1247     }
1248   return result;
1249 }
1250
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].
1254 void
1255 _Jv_GenerateITable (jclass klass, _Jv_ifaces *ifaces, jshort *itable_offsets)
1256 {
1257   void **itable = klass->idt->cls.itable;
1258   jshort itable_pos = 0;
1259
1260   for (int i=0; i < ifaces->count; i++)
1261     { 
1262       jclass iface = ifaces->list[i];
1263       itable_offsets[i] = itable_pos;
1264       itable_pos = _Jv_AppendPartialITable (klass, iface, itable, itable_pos);
1265       
1266       /* Create interface dispatch table for iface */
1267       if (iface->idt == NULL)
1268         {
1269           iface->idt = 
1270             (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable));
1271
1272           // The first element of ioffsets is its length (itself included).
1273           jshort *ioffsets = 
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++)
1277             ioffsets[i] = -1;
1278
1279           iface->idt->iface.ioffsets = ioffsets;            
1280         }
1281     }
1282 }
1283
1284 // Format method name for use in error messages.
1285 jstring
1286 _Jv_GetMethodString (jclass klass, _Jv_Utf8Const *name)
1287 {
1288   jstring r = JvNewStringUTF (klass->name->data);
1289   r = r->concat (JvNewStringUTF ("."));
1290   r = r->concat (JvNewStringUTF (name->data));
1291   return r;
1292 }
1293
1294 void 
1295 _Jv_ThrowNoSuchMethodError ()
1296 {
1297   throw new java::lang::NoSuchMethodError;
1298 }
1299
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.
1307 //
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.
1311 jshort
1312 _Jv_AppendPartialITable (jclass klass, jclass iface, void **itable, 
1313                          jshort pos)
1314 {
1315   using namespace java::lang::reflect;
1316
1317   itable[pos++] = (void *) iface;
1318   _Jv_Method *meth;
1319   
1320   for (int j=0; j < iface->method_count; j++)
1321     {
1322       meth = NULL;
1323       for (jclass cl = klass; cl; cl = cl->getSuperclass())
1324         {
1325           meth = _Jv_GetMethodLocal (cl, iface->methods[j].name,
1326                                      iface->methods[j].signature);
1327                  
1328           if (meth)
1329             break;
1330         }
1331
1332       if (meth && (meth->name->data[0] == '<'))
1333         {
1334           // leave a placeholder in the itable for hidden init methods.
1335           itable[pos] = NULL;   
1336         }
1337       else if (meth)
1338         {
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));
1348
1349           itable[pos] = meth->ncode;
1350         }
1351       else
1352         {
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;
1357         }
1358       pos++;
1359     }
1360     
1361   return pos;
1362 }
1363
1364 static _Jv_Mutex_t iindex_mutex;
1365 static bool iindex_mutex_initialized = false;
1366
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.
1377 //
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.
1383 jshort
1384 _Jv_FindIIndex (jclass *ifaces, jshort *offsets, jshort num)
1385 {
1386   int i;
1387   int j;
1388   
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
1392   // single-threaded.
1393   if (! iindex_mutex_initialized)
1394     {
1395       _Jv_MutexInit (&iindex_mutex);
1396       iindex_mutex_initialized = true;
1397     }
1398   
1399   _Jv_MutexLock (&iindex_mutex);
1400   
1401   for (i=1;; i++)  /* each potential position in ioffsets */
1402     {
1403       for (j=0;; j++)  /* each iface */
1404         {
1405           if (j >= num)
1406             goto found;
1407           if (i >= ifaces[j]->idt->iface.ioffsets[0])
1408             continue;
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. */        
1413         }
1414     }
1415   found:
1416   for (j = 0; j < num; j++)
1417     {
1418       int len = ifaces[j]->idt->iface.ioffsets[0];
1419       if (i >= len) 
1420         {
1421           /* Resize ioffsets. */
1422           int newlen = 2 * len;
1423           if (i >= newlen)
1424             newlen = i + 3;
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;
1429
1430           while (len < newlen)
1431             new_ioffsets[len++] = -1;
1432           
1433           ifaces[j]->idt->iface.ioffsets = new_ioffsets;
1434         }
1435       ifaces[j]->idt->iface.ioffsets[i] = offsets[j];
1436     }
1437
1438   _Jv_MutexUnlock (&iindex_mutex);
1439
1440   return i;
1441 }
1442
1443 // Only used by serialization
1444 java::lang::reflect::Field *
1445 java::lang::Class::getPrivateField (jstring name)
1446 {
1447   int hash = name->hashCode ();
1448
1449   java::lang::reflect::Field* rfield;
1450   for (int i = 0;  i < field_count;  i++)
1451     {
1452       _Jv_Field *field = &fields[i];
1453       if (! _Jv_equal (field->name, name, hash))
1454         continue;
1455       rfield = new java::lang::reflect::Field ();
1456       rfield->offset = (char*) field - (char*) fields;
1457       rfield->declaringClass = this;
1458       rfield->name = name;
1459       return rfield;
1460     }
1461   jclass superclass = getSuperclass();
1462   if (superclass == NULL)
1463     return NULL;
1464   rfield = superclass->getPrivateField(name);
1465   for (int i = 0; i < interface_count && rfield == NULL; ++i)
1466     rfield = interfaces[i]->getPrivateField (name);
1467   return rfield;
1468 }
1469
1470 // Only used by serialization
1471 java::lang::reflect::Method *
1472 java::lang::Class::getPrivateMethod (jstring name, JArray<jclass> *param_types)
1473 {
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())
1478     {
1479       int i = klass->isPrimitive () ? 0 : klass->method_count;
1480       while (--i >= 0)
1481         {
1482           if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
1483               && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len))
1484             {
1485               // Found it.
1486               using namespace java::lang::reflect;
1487
1488               Method *rmethod = new Method ();
1489               rmethod->offset = ((char *) (&klass->methods[i])
1490                                  - (char *) klass->methods);
1491               rmethod->declaringClass = klass;
1492               return rmethod;
1493             }
1494         }
1495     }
1496   throw new java::lang::NoSuchMethodException (name);
1497 }
1498
1499 // Private accessor method for Java code to retrieve the protection domain.
1500 java::security::ProtectionDomain *
1501 java::lang::Class::getProtectionDomain0 ()
1502 {
1503   return protectionDomain;
1504 }
1505
1506 JArray<jobject> *
1507 java::lang::Class::getSigners()
1508 {
1509   return hack_signers;
1510 }
1511
1512 void
1513 java::lang::Class::setSigners(JArray<jobject> *s)
1514 {
1515   hack_signers = s;
1516 }
1517
1518 // Functions for indirect dispatch (symbolic virtual binding) support.
1519
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.
1523
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.
1529
1530 // The offset (in bytes) for each resolved method or field is placed
1531 // at the corresponding position in the virtual method offset table
1532 // (klass->otable). 
1533
1534 // The same otable and atable may be shared by many classes.
1535
1536 void
1537 _Jv_LinkSymbolTable(jclass klass)
1538 {
1539   //// FIXME: Need to lock the tables ////
1540   
1541   int index = 0;
1542   _Jv_MethodSymbol sym;
1543   if (klass->otable == NULL
1544       || klass->otable->state != 0)
1545     goto atable;
1546    
1547   klass->otable->state = 1;
1548
1549   for (index = 0; sym = klass->otable_syms[index], sym.name != NULL; index++)
1550     {
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;            
1554
1555       const _Jv_Utf8Const *signature = sym.signature;
1556
1557       {
1558         static char *bounce = (char *)_Jv_ThrowNoSuchMethodError;
1559         ptrdiff_t offset = (char *)(klass->vtable) - bounce;
1560         klass->otable->offsets[index] = offset;
1561       }
1562
1563       if (target_class == NULL)
1564         continue;
1565
1566       if (target_class->isInterface())
1567         {
1568           // FIXME: This does not yet fully conform to binary compatibility
1569           // rules. It will break if a declaration is moved into a 
1570           // superinterface.
1571           for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
1572             {
1573               for (int i=0; i < cls->method_count; i++)
1574                 {
1575                   meth = &cls->methods[i];
1576                   if (_Jv_equalUtf8Consts (sym.name, meth->name)
1577                       && _Jv_equalUtf8Consts (signature, meth->signature))
1578                     {
1579                       klass->otable->offsets[index] = i + 1;
1580                       goto found;
1581                     }
1582                 }
1583             
1584             }
1585         found:
1586           continue;
1587         }
1588
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] == '(')
1593         {
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 
1596           // it out now.
1597           if (target_class->vtable_method_count == -1)
1598             {
1599               JvSynchronize sync (target_class);
1600               _Jv_LayoutVTableMethods (target_class);
1601             }
1602                 
1603           meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
1604                                           sym.signature);
1605                 
1606           if (meth != NULL)
1607             {
1608               klass->otable->offsets[index] = 
1609                 _Jv_VTable::idx_to_offset (meth->index);              
1610             }
1611
1612           continue;
1613         }
1614
1615       // try fields
1616       {
1617         _Jv_Field *the_field = NULL;
1618
1619         for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
1620           {
1621             for (int i = 0; i < cls->field_count; i++)
1622               {
1623                 _Jv_Field *field = &cls->fields[i];
1624                 if (! _Jv_equalUtf8Consts (field->name, sym.name))
1625                   continue;
1626
1627                 // FIXME: What access checks should we perform here?
1628 //              if (_Jv_CheckAccess (klass, cls, field->flags))
1629 //                {
1630
1631                 if (!field->isResolved ())
1632                   _Jv_ResolveField (field, cls->loader);
1633
1634 //              if (field_type != 0 && field->type != field_type)
1635 //                throw new java::lang::LinkageError
1636 //                  (JvNewStringLatin1 
1637 //                   ("field type mismatch with different loaders"));
1638
1639                 the_field = field;
1640                 goto end_of_field_search;
1641               }
1642           }
1643       end_of_field_search:
1644         if (the_field != NULL)
1645           {
1646             if (the_field->flags & 0x0008 /* Modifier::STATIC */)
1647               {       
1648                 throw new java::lang::IncompatibleClassChangeError;
1649               }
1650             else
1651               {
1652                 klass->otable->offsets[index] = the_field->u.boffset;
1653               }
1654           }
1655         else
1656           {
1657             throw new java::lang::NoSuchFieldError
1658               (_Jv_NewStringUtf8Const (sym.name));
1659           }
1660       }
1661     }
1662
1663  atable:
1664   if (klass->atable == NULL
1665       || klass->atable->state != 0)
1666     return;
1667
1668   klass->atable->state = 1;
1669
1670   for (index = 0; sym = klass->atable_syms[index], sym.name != NULL; index++)
1671     {
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;
1676
1677       // ??? Setting this pointer to null will at least get us a
1678       // NullPointerException
1679       klass->atable->addresses[index] = NULL;
1680       
1681       if (target_class == NULL)
1682         continue;
1683       
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] == '(')
1688         {
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 
1691           // it out now.
1692           if (target_class->vtable_method_count == -1)
1693             {
1694               JvSynchronize sync (target_class);
1695               _Jv_LayoutVTableMethods (target_class);
1696             }
1697           
1698           meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
1699                                           sym.signature);
1700           
1701           if (meth != NULL)
1702             {
1703               if (meth->ncode) // Maybe abstract?
1704                 klass->atable->addresses[index] = meth->ncode;
1705 #ifdef INTERPRETER
1706               else if (_Jv_IsInterpretedClass (target_class))
1707                 _Jv_Defer_Resolution (target_class, meth, 
1708                                       &klass->atable->addresses[index]);
1709 #endif
1710             }
1711           else
1712             klass->atable->addresses[index] = (void *)_Jv_ThrowNoSuchMethodError;
1713
1714           continue;
1715         }
1716
1717       // try fields
1718       {
1719         _Jv_Field *the_field = NULL;
1720
1721         for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
1722           {
1723             for (int i = 0; i < cls->field_count; i++)
1724               {
1725                 _Jv_Field *field = &cls->fields[i];
1726                 if (! _Jv_equalUtf8Consts (field->name, sym.name))
1727                   continue;
1728
1729                 // FIXME: What access checks should we perform here?
1730 //              if (_Jv_CheckAccess (klass, cls, field->flags))
1731 //                {
1732
1733                 if (!field->isResolved ())
1734                   _Jv_ResolveField (field, cls->loader);
1735                 
1736 //              if (field_type != 0 && field->type != field_type)
1737 //                throw new java::lang::LinkageError
1738 //                  (JvNewStringLatin1 
1739 //                   ("field type mismatch with different loaders"));
1740
1741                 the_field = field;
1742                 goto end_of_static_field_search;
1743               }
1744           }
1745       end_of_static_field_search:
1746         if (the_field != NULL)
1747           {
1748             if (the_field->flags & 0x0008 /* Modifier::STATIC */)
1749               {       
1750                 klass->atable->addresses[index] = the_field->u.addr;
1751               }
1752             else
1753               {
1754                 throw new java::lang::IncompatibleClassChangeError;
1755               }
1756           }
1757         else
1758           {
1759             throw new java::lang::NoSuchFieldError
1760               (_Jv_NewStringUtf8Const (sym.name));
1761           }
1762       }
1763     }
1764 }
1765
1766
1767 // For each catch_record in the list of caught classes, fill in the
1768 // address field.
1769 void 
1770 _Jv_linkExceptionClassTable (jclass self)
1771 {
1772   struct _Jv_CatchClass *catch_record = self->catch_classes;
1773   if (!catch_record || catch_record->classname)
1774     return;  
1775   catch_record++;
1776   while (catch_record->classname)
1777     {
1778       jclass target_class = _Jv_FindClass (catch_record->classname,  
1779                                            self->getClassLoaderInternal ());
1780       *catch_record->address = target_class;
1781       catch_record++;
1782     }
1783   self->catch_classes->classname = (_Jv_Utf8Const *)-1;
1784 }
1785   
1786 // This is put in empty vtable slots.
1787 static void
1788 _Jv_abstractMethodError (void)
1789 {
1790   throw new java::lang::AbstractMethodError();
1791 }
1792
1793 // Set itable method indexes for members of interface IFACE.
1794 void
1795 _Jv_LayoutInterfaceMethods (jclass iface)
1796 {
1797   if (! iface->isInterface())
1798     return;
1799   
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;
1805 }
1806
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.
1811 void
1812 _Jv_LayoutVTableMethods (jclass klass)
1813 {
1814   if (klass->vtable != NULL || klass->isInterface() 
1815       || klass->vtable_method_count != -1)
1816     return;
1817
1818   jclass superclass = klass->superclass;
1819
1820   typedef unsigned int uaddr __attribute__ ((mode (pointer)));
1821
1822   // If superclass looks like a constant pool entry,
1823   // resolve it now.
1824   if ((uaddr)superclass < (uaddr)klass->constants.size)
1825     {
1826       if (klass->state < JV_STATE_LINKED)
1827         {
1828           _Jv_Utf8Const *name = klass->constants.data[(int)superclass].utf8;
1829           superclass = _Jv_FindClass (name, klass->loader);
1830           if (! superclass)
1831             {
1832               jstring str = _Jv_NewStringUTF (name->data);
1833               throw new java::lang::NoClassDefFoundError (str);
1834             }
1835         }
1836       else
1837         superclass = klass->constants.data[(int)superclass].clazz;
1838     }
1839
1840   if (superclass != NULL && superclass->vtable_method_count == -1)
1841     {
1842       JvSynchronize sync (superclass);
1843       _Jv_LayoutVTableMethods (superclass);
1844     }
1845
1846   int index = (superclass == NULL ? 0 : superclass->vtable_method_count);
1847
1848   for (int i = 0; i < klass->method_count; ++i)
1849     {
1850       _Jv_Method *meth = &klass->methods[i];
1851       _Jv_Method *super_meth = NULL;
1852
1853       if (! _Jv_isVirtualMethod (meth))
1854         continue;
1855
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.
1861
1862       if (superclass != NULL)
1863         {
1864           super_meth = _Jv_LookupDeclaredMethod (superclass, meth->name, 
1865                                                  meth->signature);
1866         }
1867
1868       if (super_meth)
1869         meth->index = super_meth->index;
1870       else
1871         meth->index = index++;
1872     }
1873
1874   klass->vtable_method_count = index;
1875 }
1876
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.
1880 void
1881 _Jv_SetVTableEntries (jclass klass, _Jv_VTable *vtable, jboolean *flags)
1882 {
1883   using namespace java::lang::reflect;
1884
1885   jclass superclass = klass->getSuperclass();
1886
1887   if (superclass != NULL && (superclass->getModifiers() & Modifier::ABSTRACT))
1888     _Jv_SetVTableEntries (superclass, vtable, flags);
1889
1890   for (int i = klass->method_count - 1; i >= 0; i--)
1891     {
1892       _Jv_Method *meth = &klass->methods[i];
1893       if (meth->index == (_Jv_ushort) -1)
1894         continue;
1895       if ((meth->accflags & Modifier::ABSTRACT))
1896         {
1897           vtable->set_method(meth->index, (void *) &_Jv_abstractMethodError);
1898           flags[meth->index] = false;
1899         }
1900       else
1901         {
1902           vtable->set_method(meth->index, meth->ncode);
1903           flags[meth->index] = true;
1904         }
1905     }
1906 }
1907
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.
1912 void
1913 _Jv_MakeVTable (jclass klass)
1914 {
1915   using namespace java::lang::reflect;  
1916
1917   if (klass->vtable != NULL || klass->isInterface() 
1918       || (klass->accflags & Modifier::ABSTRACT))
1919     return;
1920
1921   // Class must be laid out before we can create a vtable. 
1922   if (klass->vtable_method_count == -1)
1923     _Jv_LayoutVTableMethods (klass);
1924
1925   // Allocate the new vtable.
1926   _Jv_VTable *vtable = _Jv_VTable::new_vtable (klass->vtable_method_count);
1927   klass->vtable = vtable;
1928
1929   jboolean flags[klass->vtable_method_count];
1930   for (int i = 0; i < klass->vtable_method_count; ++i)
1931     flags[i] = false;
1932
1933   // Copy the vtable of the closest non-abstract superclass.
1934   jclass superclass = klass->superclass;
1935   if (superclass != NULL)
1936     {
1937       while ((superclass->accflags & Modifier::ABSTRACT) != 0)
1938         superclass = superclass->superclass;
1939
1940       if (superclass->vtable == NULL)
1941         {
1942           JvSynchronize sync (superclass);
1943           _Jv_MakeVTable (superclass);
1944         }
1945
1946       for (int i = 0; i < superclass->vtable_method_count; ++i)
1947         {
1948           vtable->set_method (i, superclass->vtable->get_method (i));
1949           flags[i] = true;
1950         }
1951     }
1952
1953   // Set the class pointer and GC descriptor.
1954   vtable->clas = klass;
1955   vtable->gc_descr = _Jv_BuildGCDescr (klass);
1956
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);
1960
1961   // It is an error to have an abstract method in a concrete class.
1962   if (! (klass->accflags & Modifier::ABSTRACT))
1963     {
1964       for (int i = 0; i < klass->vtable_method_count; ++i)
1965         if (! flags[i])
1966           {
1967             using namespace java::lang;
1968             while (klass != NULL)
1969               {
1970                 for (int j = 0; j < klass->method_count; ++j)
1971                   {
1972                     if (klass->methods[i].index == i)
1973                       {
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 ());
1979                       }
1980                   }
1981                 klass = klass->getSuperclass ();
1982               }
1983             // Couldn't find the name, which is weird.
1984             // But we still must throw the error.
1985             throw new AbstractMethodError ();
1986           }
1987     }
1988 }