OSDN Git Service

2008-01-04 Andrew Haley <aph@redhat.com>
[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, 2007
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/Proxy.h>
33 #include <java/lang/reflect/Constructor.h>
34 #include <java/lang/AbstractMethodError.h>
35 #include <java/lang/ArrayStoreException.h>
36 #include <java/lang/ClassCastException.h>
37 #include <java/lang/ClassNotFoundException.h>
38 #include <java/lang/ExceptionInInitializerError.h>
39 #include <java/lang/IllegalAccessException.h>
40 #include <java/lang/IllegalAccessError.h>
41 #include <java/lang/IllegalArgumentException.h>
42 #include <java/lang/IncompatibleClassChangeError.h>
43 #include <java/lang/NoSuchFieldError.h>
44 #include <java/lang/ArrayIndexOutOfBoundsException.h>
45 #include <java/lang/InstantiationException.h>
46 #include <java/lang/NoClassDefFoundError.h>
47 #include <java/lang/NoSuchFieldException.h>
48 #include <java/lang/NoSuchMethodError.h>
49 #include <java/lang/NoSuchMethodException.h>
50 #include <java/lang/Thread.h>
51 #include <java/lang/NullPointerException.h>
52 #include <java/lang/RuntimePermission.h>
53 #include <java/lang/System.h>
54 #include <java/lang/SecurityException.h>
55 #include <java/lang/SecurityManager.h>
56 #include <java/lang/StringBuffer.h>
57 #include <java/lang/VMClassLoader.h>
58 #include <gcj/method.h>
59 #include <gnu/gcj/RawData.h>
60 #include <java/lang/VerifyError.h>
61 #include <java/lang/InternalError.h>
62 #include <java/lang/TypeNotPresentException.h>
63 #include <java/lang/Byte.h>
64 #include <java/lang/Short.h>
65 #include <java/lang/Integer.h>
66 #include <java/lang/Float.h>
67 #include <java/lang/Double.h>
68 #include <java/lang/Long.h>
69 #include <java/lang/Character.h>
70 #include <java/lang/Boolean.h>
71 #include <java/lang/annotation/Annotation.h>
72 #include <java/util/HashMap.h>
73 #include <java/util/Map.h>
74 #include <sun/reflect/annotation/AnnotationInvocationHandler.h>
75 #include <java/lang/Enum.h>
76
77 #include <java-cpool.h>
78 #include <java-interp.h>
79 #include <java-assert.h>
80 #include <java-stack.h>
81 #include <execution.h>
82
83 \f
84
85 using namespace gcj;
86
87 jclass
88 java::lang::Class::forName (jstring className, jboolean initialize,
89                             java::lang::ClassLoader *loader)
90 {
91   if (! className)
92     throw new java::lang::NullPointerException;
93
94   jsize length = _Jv_GetStringUTFLength (className);
95   char buffer[length];
96   _Jv_GetStringUTFRegion (className, 0, className->length(), buffer);
97
98   _Jv_Utf8Const *name = _Jv_makeUtf8Const (buffer, length);
99
100   if (! _Jv_VerifyClassName (name))
101     throw new java::lang::ClassNotFoundException (className);
102
103   jclass klass = (buffer[0] == '[' 
104                   ? _Jv_FindClassFromSignature (name->chars(), loader)
105                   : _Jv_FindClass (name, loader));
106
107   if (klass == NULL)
108     throw new java::lang::ClassNotFoundException (className);
109
110   if (initialize)
111     _Jv_InitClass (klass);
112
113   return klass;
114 }
115
116 jclass
117 java::lang::Class::forName (jstring className)
118 {
119   java::lang::ClassLoader *loader = NULL;
120
121   jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$);
122   if (caller)
123     loader = caller->getClassLoaderInternal();
124
125   return forName (className, true, loader);
126 }
127
128 java::lang::ClassLoader *
129 java::lang::Class::getClassLoader (void)
130 {
131   java::lang::SecurityManager *s = java::lang::System::getSecurityManager();
132   if (s != NULL)
133     {
134       jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$);
135       return getClassLoader (caller);
136    }
137
138   return loader;
139 }
140
141 java::lang::ClassLoader *
142 java::lang::Class::getClassLoader (jclass caller)
143 {
144   java::lang::SecurityManager *s = java::lang::System::getSecurityManager();
145   if (s != NULL)
146     {
147       ClassLoader *caller_loader = caller->getClassLoaderInternal();
148
149       // If the caller has a non-null class loader, and that loader
150       // is not this class' loader or an ancestor thereof, then do a
151       // security check.
152       if (caller_loader != NULL && ! caller_loader->isAncestorOf(loader))
153         s->checkPermission (new RuntimePermission (JvNewStringLatin1 ("getClassLoader")));
154     }
155
156   return loader;
157 }
158
159 java::lang::reflect::Constructor *
160 java::lang::Class::getConstructor (JArray<jclass> *param_types)
161 {
162   memberAccessCheck(java::lang::reflect::Member::PUBLIC);
163
164   jstring partial_sig = getSignature (param_types, true);
165   jint hash = partial_sig->hashCode ();
166
167   int i = isPrimitive () ? 0 : method_count;
168   while (--i >= 0)
169     {
170       if (_Jv_equalUtf8Consts (methods[i].name, init_name)
171           && _Jv_equal (methods[i].signature, partial_sig, hash))
172         {
173           // Found it.  For getConstructor, the constructor must be
174           // public.
175           using namespace java::lang::reflect;
176           if (! Modifier::isPublic(methods[i].accflags))
177             break;
178           Constructor *cons = new Constructor ();
179           cons->offset = (char *) (&methods[i]) - (char *) methods;
180           cons->declaringClass = this;
181           return cons;
182         }
183     }
184   throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
185 }
186
187 JArray<java::lang::reflect::Constructor *> *
188 java::lang::Class::getDeclaredConstructors (jboolean publicOnly)
189 {
190   int numConstructors = 0;
191   int max = isPrimitive () ? 0 : method_count;
192   int i;
193   for (i = max; --i >= 0; )
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       numConstructors++;
203     }
204   JArray<java::lang::reflect::Constructor *> *result
205     = (JArray<java::lang::reflect::Constructor *> *)
206     JvNewObjectArray (numConstructors,
207                       &java::lang::reflect::Constructor::class$,
208                       NULL);
209   java::lang::reflect::Constructor** cptr = elements (result);
210   for (i = 0;  i < max;  i++)
211     {
212       _Jv_Method *method = &methods[i];
213       if (method->name == NULL
214           || ! _Jv_equalUtf8Consts (method->name, init_name))
215         continue;
216       if (publicOnly
217           && ! java::lang::reflect::Modifier::isPublic(method->accflags))
218         continue;
219       java::lang::reflect::Constructor *cons
220         = new java::lang::reflect::Constructor ();
221       cons->offset = (char *) method - (char *) methods;
222       cons->declaringClass = this;
223       *cptr++ = cons;
224     }
225   return result;
226 }
227
228 java::lang::reflect::Constructor *
229 java::lang::Class::getDeclaredConstructor (JArray<jclass> *param_types)
230 {
231   memberAccessCheck(java::lang::reflect::Member::DECLARED);
232
233   jstring partial_sig = getSignature (param_types, true);
234   jint hash = partial_sig->hashCode ();
235
236   int i = isPrimitive () ? 0 : method_count;
237   while (--i >= 0)
238     {
239       if (_Jv_equalUtf8Consts (methods[i].name, init_name)
240           && _Jv_equal (methods[i].signature, partial_sig, hash))
241         {
242           // Found it.
243           using namespace java::lang::reflect;
244           Constructor *cons = new Constructor ();
245           cons->offset = (char *) (&methods[i]) - (char *) methods;
246           cons->declaringClass = this;
247           return cons;
248         }
249     }
250   throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
251 }
252
253 java::lang::reflect::Field *
254 java::lang::Class::getField (jstring name, jint hash)
255 {
256   java::lang::reflect::Field* rfield;
257   for (int i = 0;  i < field_count;  i++)
258     {
259       _Jv_Field *field = &fields[i];
260       if (! _Jv_equal (field->name, name, hash))
261         continue;
262       if (! (field->getModifiers() & java::lang::reflect::Modifier::PUBLIC))
263         continue;
264       rfield = new java::lang::reflect::Field ();
265       rfield->offset = (char*) field - (char*) fields;
266       rfield->declaringClass = this;
267       rfield->name = name;
268       return rfield;
269     }
270   jclass superclass = getSuperclass();
271   if (superclass == NULL)
272     return NULL;
273   rfield = superclass->getField(name, hash);
274   for (int i = 0; i < interface_count && rfield == NULL; ++i)
275     rfield = interfaces[i]->getField (name, hash);
276   return rfield;
277 }
278
279 java::lang::reflect::Field *
280 java::lang::Class::getDeclaredField (jstring name)
281 {
282   memberAccessCheck(java::lang::reflect::Member::DECLARED);
283   int hash = name->hashCode();
284   for (int i = 0;  i < field_count;  i++)
285     {
286       _Jv_Field *field = &fields[i];
287       if (! _Jv_equal (field->name, name, hash))
288         continue;
289       java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
290       rfield->offset = (char*) field - (char*) fields;
291       rfield->declaringClass = this;
292       rfield->name = name;
293       return rfield;
294     }
295   throw new java::lang::NoSuchFieldException (name);
296 }
297
298 JArray<java::lang::reflect::Field *> *
299 java::lang::Class::getDeclaredFields (jboolean public_only)
300 {
301   int size;
302   if (public_only)
303     {
304       size = 0;
305       for (int i = 0; i < field_count; ++i)
306         {
307           _Jv_Field *field = &fields[i];
308           if ((field->flags & java::lang::reflect::Modifier::PUBLIC))
309             ++size;
310         }
311     }
312   else
313     size = field_count;
314
315   JArray<java::lang::reflect::Field *> *result
316     = (JArray<java::lang::reflect::Field *> *)
317     JvNewObjectArray (size, &java::lang::reflect::Field::class$, NULL);
318   java::lang::reflect::Field** fptr = elements (result);
319   for (int i = 0;  i < field_count;  i++)
320     {
321       _Jv_Field *field = &fields[i];
322       if (public_only
323           && ! (field->flags & java::lang::reflect::Modifier::PUBLIC))
324         continue;
325       java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
326       rfield->offset = (char*) field - (char*) fields;
327       rfield->declaringClass = this;
328       *fptr++ = rfield;
329     }
330   return result;
331 }
332
333 void
334 java::lang::Class::getSignature (java::lang::StringBuffer *buffer)
335 {
336   if (isPrimitive())
337     buffer->append((jchar) method_count);
338   else
339     {
340       jstring name = getName();
341       if (name->charAt(0) != '[')
342         buffer->append((jchar) 'L');
343       buffer->append(name);
344       if (name->charAt(0) != '[')
345         buffer->append((jchar) ';');
346     }
347 }
348
349 // This doesn't have to be native.  It is an implementation detail
350 // only called from the C++ code, though, so maybe this is clearer.
351 jstring
352 java::lang::Class::getSignature (JArray<jclass> *param_types,
353                                  jboolean is_constructor)
354 {
355   java::lang::StringBuffer *buf = new java::lang::StringBuffer ();
356   buf->append((jchar) '(');
357   // A NULL param_types means "no parameters".
358   if (param_types != NULL)
359     {
360       jclass *v = elements (param_types);
361       for (int i = 0; i < param_types->length; ++i)
362         v[i]->getSignature(buf);
363     }
364   buf->append((jchar) ')');
365   if (is_constructor)
366     buf->append((jchar) 'V');
367   return buf->toString();
368 }
369
370 java::lang::reflect::Method *
371 java::lang::Class::_getDeclaredMethod (jstring name,
372                                        JArray<jclass> *param_types)
373 {
374   jstring partial_sig = getSignature (param_types, false);
375   jint p_len = partial_sig->length();
376   _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
377   int i = isPrimitive () ? 0 : method_count;
378   while (--i >= 0)
379     {
380       if (_Jv_equalUtf8Consts (methods[i].name, utf_name)
381           && _Jv_equaln (methods[i].signature, partial_sig, p_len)
382           && (methods[i].accflags
383               & java::lang::reflect::Modifier::INVISIBLE) == 0)
384         {
385           // Found it.
386           using namespace java::lang::reflect;
387           Method *rmethod = new Method ();
388           rmethod->offset = (char*) (&methods[i]) - (char*) methods;
389           rmethod->declaringClass = this;
390           return rmethod;
391         }
392     }
393   return NULL;
394 }
395
396 JArray<java::lang::reflect::Method *> *
397 java::lang::Class::getDeclaredMethods (void)
398 {
399   memberAccessCheck(java::lang::reflect::Member::DECLARED);
400
401   int numMethods = 0;
402   int max = isPrimitive () ? 0 : method_count;
403   int i;
404   for (i = max; --i >= 0; )
405     {
406       _Jv_Method *method = &methods[i];
407       if (method->name == NULL
408           || _Jv_equalUtf8Consts (method->name, clinit_name)
409           || _Jv_equalUtf8Consts (method->name, init_name)
410           || _Jv_equalUtf8Consts (method->name, finit_name)
411           || (methods[i].accflags
412               & java::lang::reflect::Modifier::INVISIBLE) != 0)
413         continue;
414       numMethods++;
415     }
416   JArray<java::lang::reflect::Method *> *result
417     = (JArray<java::lang::reflect::Method *> *)
418     JvNewObjectArray (numMethods, &java::lang::reflect::Method::class$, NULL);
419   java::lang::reflect::Method** mptr = elements (result);
420   for (i = 0;  i < max;  i++)
421     {
422       _Jv_Method *method = &methods[i];
423       if (method->name == NULL
424           || _Jv_equalUtf8Consts (method->name, clinit_name)
425           || _Jv_equalUtf8Consts (method->name, init_name)
426           || _Jv_equalUtf8Consts (method->name, finit_name)
427           || (methods[i].accflags
428               & java::lang::reflect::Modifier::INVISIBLE) != 0)
429         continue;
430       java::lang::reflect::Method* rmethod
431         = new java::lang::reflect::Method ();
432       rmethod->offset = (char*) method - (char*) methods;
433       rmethod->declaringClass = this;
434       *mptr++ = rmethod;
435     }
436   return result;
437 }
438
439 jstring
440 java::lang::Class::getName (void)
441 {
442   return name->toString();
443 }
444
445 JArray<jclass> *
446 java::lang::Class::getInterfaces (void)
447 {
448   jobjectArray r = JvNewObjectArray (interface_count, getClass (), NULL);
449   jobject *data = elements (r);
450   for (int i = 0; i < interface_count; ++i)
451     {
452       typedef unsigned int uaddr __attribute__ ((mode (pointer)));
453       data[i] = interfaces[i];
454       if ((uaddr)data[i] < (uaddr)constants.size)
455         fprintf (stderr, "ERROR !!!\n");
456     }
457   return reinterpret_cast<JArray<jclass> *> (r);
458 }
459
460 java::lang::reflect::Method *
461 java::lang::Class::_getMethod (jstring name, JArray<jclass> *param_types)
462 {
463   jstring partial_sig = getSignature (param_types, false);
464   jint p_len = partial_sig->length();
465   _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
466
467    for (Class *klass = this; klass; klass = klass->getSuperclass())
468     {
469       int i = klass->isPrimitive () ? 0 : klass->method_count;
470       while (--i >= 0)
471         {
472           if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
473               && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len)
474               && (klass->methods[i].accflags
475                   & java::lang::reflect::Modifier::INVISIBLE) == 0)
476             {
477               // Found it.
478               using namespace java::lang::reflect;
479
480               // Method must be public.
481               if (! Modifier::isPublic (klass->methods[i].accflags))
482                 break;
483
484               Method *rmethod = new Method ();
485               rmethod->offset = ((char *) (&klass->methods[i])
486                                  - (char *) klass->methods);
487               rmethod->declaringClass = klass;
488               return rmethod;
489             }
490         }
491     }
492
493   // If we haven't found a match, and this class is an interface, then
494   // check all the superinterfaces.
495   if (isInterface())
496     {
497       for (int i = 0; i < interface_count; ++i)
498         {
499           using namespace java::lang::reflect;
500           Method *rmethod = interfaces[i]->_getMethod (name, param_types);
501           if (rmethod != NULL)
502             return rmethod;
503         }
504     }
505
506   return NULL;
507 }
508
509 // This is a very slow implementation, since it re-scans all the
510 // methods we've already listed to make sure we haven't duplicated a
511 // method.  It also over-estimates the required size, so we have to
512 // shrink the result array later.
513 jint
514 java::lang::Class::_getMethods (JArray<java::lang::reflect::Method *> *result,
515                                 jint offset)
516 {
517   jint count = 0;
518
519   // First examine all local methods
520   for (int i = isPrimitive () ? 0 : method_count; --i >= 0; )
521     {
522       _Jv_Method *method = &methods[i];
523       if (method->name == NULL
524           || _Jv_equalUtf8Consts (method->name, clinit_name)
525           || _Jv_equalUtf8Consts (method->name, init_name)
526           || _Jv_equalUtf8Consts (method->name, finit_name)
527           || (method->accflags
528               & java::lang::reflect::Modifier::INVISIBLE) != 0)
529         continue;
530       // Only want public methods.
531       if (! java::lang::reflect::Modifier::isPublic (method->accflags))
532         continue;
533
534       // This is where we over-count the slots required if we aren't
535       // filling the result for real.
536       if (result != NULL)
537         {
538           jboolean add = true;
539           java::lang::reflect::Method **mp = elements (result);
540           // If we already have a method with this name and signature,
541           // then ignore this one.  This can happen with virtual
542           // methods.
543           for (int j = 0; j < offset; ++j)
544             {
545               _Jv_Method *meth_2 = _Jv_FromReflectedMethod (mp[j]);
546               if (_Jv_equalUtf8Consts (method->name, meth_2->name)
547                   && _Jv_equalUtf8Consts (method->signature,
548                                           meth_2->signature))
549                 {
550                   add = false;
551                   break;
552                 }
553             }
554           if (! add)
555             continue;
556         }
557
558       if (result != NULL)
559         {
560           using namespace java::lang::reflect;
561           Method *rmethod = new Method ();
562           rmethod->offset = (char *) method - (char *) methods;
563           rmethod->declaringClass = this;
564           Method **mp = elements (result);
565           mp[offset + count] = rmethod;
566         }
567       ++count;
568     }
569   offset += count;
570
571   // Now examine superclasses.
572   if (getSuperclass () != NULL)
573     {
574       jint s_count = getSuperclass()->_getMethods (result, offset);
575       offset += s_count;
576       count += s_count;
577     }
578
579   // Finally, examine interfaces.
580   for (int i = 0; i < interface_count; ++i)
581     {
582       int f_count = interfaces[i]->_getMethods (result, offset);
583       count += f_count;
584       offset += f_count;
585     }
586
587   return count;
588 }
589
590 JArray<java::lang::reflect::Method *> *
591 java::lang::Class::getMethods (void)
592 {
593   using namespace java::lang::reflect;
594
595   memberAccessCheck(Member::PUBLIC);
596
597   // This will overestimate the size we need.
598   jint count = _getMethods (NULL, 0);
599
600   JArray<Method *> *result
601     = ((JArray<Method *> *) JvNewObjectArray (count,
602                                               &Method::class$,
603                                               NULL));
604
605   // When filling the array for real, we get the actual count.  Then
606   // we resize the array.
607   jint real_count = _getMethods (result, 0);
608
609   if (real_count != count)
610     {
611       JArray<Method *> *r2
612         = ((JArray<Method *> *) JvNewObjectArray (real_count,
613                                                   &Method::class$,
614                                                   NULL));
615       
616       Method **destp = elements (r2);
617       Method **srcp = elements (result);
618
619       for (int i = 0; i < real_count; ++i)
620         *destp++ = *srcp++;
621
622       result = r2;
623     }
624
625   return result;
626 }
627
628 jboolean
629 java::lang::Class::isAssignableFrom (jclass klass)
630 {
631   // Arguments may not have been initialized, given ".class" syntax.
632   // This ensures we can at least look at their superclasses.
633   _Jv_Linker::wait_for_state (this, JV_STATE_LOADING);
634   _Jv_Linker::wait_for_state (klass, JV_STATE_LOADING);
635   return _Jv_IsAssignableFrom (klass, this);
636 }
637
638 jboolean
639 java::lang::Class::isInstance (jobject obj)
640 {
641   if (! obj)
642     return false;
643   return _Jv_IsAssignableFrom (JV_CLASS (obj), this);
644 }
645
646 jobject
647 java::lang::Class::newInstance (void)
648 {
649   memberAccessCheck(java::lang::reflect::Member::PUBLIC);
650
651   if (isPrimitive ()
652       || isInterface ()
653       || isArray ()
654       || java::lang::reflect::Modifier::isAbstract(accflags))
655     throw new java::lang::InstantiationException (getName ());
656
657   _Jv_InitClass (this);
658
659   _Jv_Method *meth = _Jv_GetMethodLocal (this, init_name, void_signature);
660   if (! meth)
661     throw new java::lang::InstantiationException (getName());
662
663   jobject r = _Jv_AllocObject (this);
664   ((void (*) (jobject)) meth->ncode) (r);
665   return r;
666 }
667
668 void
669 java::lang::Class::finalize (void)
670 {
671   engine->unregister(this);
672 }
673
674 #ifdef INTERPRETER
675 void
676 _Jv_ClosureList::releaseClosures (_Jv_ClosureList **closures)
677 {
678   if (!closures)
679     return;
680
681   while (_Jv_ClosureList *current = *closures)
682     {
683       *closures = current->next;
684       ffi_closure_free (current->ptr);
685     }
686 }
687
688 void
689 _Jv_ClosureList::registerClosure (jclass klass, void *ptr)
690 {
691   _Jv_ClosureList **closures = klass->engine->get_closure_list (klass);
692   this->ptr = ptr;
693   this->next = *closures;
694   *closures = this;
695 }
696 #endif
697
698 // This implements the initialization process for a class.  From Spec
699 // section 12.4.2.
700 void
701 java::lang::Class::initializeClass (void)
702 {
703   // Short-circuit to avoid needless locking (expression includes
704   // JV_STATE_PHANTOM and JV_STATE_DONE).
705   if (state >= JV_STATE_PHANTOM)
706     return;
707
708   // Step 1.  We introduce a new scope so we can synchronize more
709   // easily.
710   {
711     JvSynchronize sync (this);
712
713     if (state < JV_STATE_LINKED)
714       {
715         try
716           {
717             _Jv_Linker::wait_for_state(this, JV_STATE_LINKED);
718           }
719         catch (java::lang::SecurityException *x)
720           {
721             throw x;
722           }
723         catch (java::lang::Throwable *x)
724           {
725             // Turn into a NoClassDefFoundError.
726             java::lang::NoClassDefFoundError *result
727               = new java::lang::NoClassDefFoundError(getName());
728             result->initCause(x);
729             throw result;
730           }
731       }
732
733     // Step 2.
734     java::lang::Thread *self = java::lang::Thread::currentThread();
735     self = (java::lang::Thread *) ((long) self | 1);
736     while (state == JV_STATE_IN_PROGRESS && thread && thread != self)
737       wait ();
738
739     // Steps 3 &  4.
740     if (state == JV_STATE_DONE || state == JV_STATE_IN_PROGRESS)
741       return;
742
743     // Step 5.
744     if (state == JV_STATE_ERROR)
745       throw new java::lang::NoClassDefFoundError (getName());
746
747     // Step 6.
748     thread = self;
749     _Jv_Linker::wait_for_state (this, JV_STATE_LINKED);
750     state = JV_STATE_IN_PROGRESS;
751   }
752
753   // Step 7.
754   if (! isInterface () && superclass)
755     {
756       try
757         {
758           _Jv_InitClass (superclass);
759         }
760       catch (java::lang::SecurityException *x)
761         {
762           throw x;
763         }
764       catch (java::lang::Throwable *except)
765         {
766           // Caught an exception.
767           JvSynchronize sync (this);
768           state = JV_STATE_ERROR;
769           notifyAll ();
770           throw except;
771         }
772     }
773
774   // Steps 8, 9, 10, 11.
775   try
776     {
777       _Jv_Method *meth = _Jv_GetMethodLocal (this, clinit_name,
778                                              void_signature);
779       if (meth)
780         ((void (*) (void)) meth->ncode) ();
781     }
782   catch (java::lang::SecurityException *x)
783     {
784       throw x;
785     }
786   catch (java::lang::Throwable *except)
787     {
788       if (! java::lang::Error::class$.isInstance(except))
789         {
790           try
791             {
792               except = new ExceptionInInitializerError (except);
793             }
794           catch (java::lang::Throwable *t)
795             {
796               except = t;
797             }
798         }
799
800       JvSynchronize sync (this);
801       state = JV_STATE_ERROR;
802       notifyAll ();
803       throw except;
804     }
805
806   JvSynchronize sync (this);
807   state = JV_STATE_DONE;
808   notifyAll ();
809 }
810
811 // Only used by serialization
812 java::lang::reflect::Field *
813 java::lang::Class::getPrivateField (jstring name)
814 {
815   int hash = name->hashCode ();
816
817   java::lang::reflect::Field* rfield;
818   for (int i = 0;  i < field_count;  i++)
819     {
820       _Jv_Field *field = &fields[i];
821       if (! _Jv_equal (field->name, name, hash))
822         continue;
823       rfield = new java::lang::reflect::Field ();
824       rfield->offset = (char*) field - (char*) fields;
825       rfield->declaringClass = this;
826       rfield->name = name;
827       return rfield;
828     }
829   jclass superclass = getSuperclass();
830   if (superclass == NULL)
831     return NULL;
832   rfield = superclass->getPrivateField(name);
833   for (int i = 0; i < interface_count && rfield == NULL; ++i)
834     rfield = interfaces[i]->getPrivateField (name);
835   return rfield;
836 }
837
838 // Only used by serialization
839 java::lang::reflect::Method *
840 java::lang::Class::getPrivateMethod (jstring name, JArray<jclass> *param_types)
841 {
842   jstring partial_sig = getSignature (param_types, false);
843   jint p_len = partial_sig->length();
844   _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
845   for (Class *klass = this; klass; klass = klass->getSuperclass())
846     {
847       int i = klass->isPrimitive () ? 0 : klass->method_count;
848       while (--i >= 0)
849         {
850           if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
851               && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len))
852             {
853               // Found it.
854               using namespace java::lang::reflect;
855
856               Method *rmethod = new Method ();
857               rmethod->offset = ((char *) (&klass->methods[i])
858                                  - (char *) klass->methods);
859               rmethod->declaringClass = klass;
860               return rmethod;
861             }
862         }
863     }
864   throw new java::lang::NoSuchMethodException (name);
865 }
866
867 // Private accessor method for Java code to retrieve the protection domain.
868 java::security::ProtectionDomain *
869 java::lang::Class::getProtectionDomain0 ()
870 {
871   return protectionDomain;
872 }
873
874 JArray<jobject> *
875 java::lang::Class::getSigners()
876 {
877   return hack_signers;
878 }
879
880 void
881 java::lang::Class::setSigners(JArray<jobject> *s)
882 {
883   hack_signers = s;
884 }
885
886 \f
887
888 static unsigned char
889 read_u1 (unsigned char *&p)
890 {
891   return *p++;
892 }
893
894 static unsigned char
895 read_u1 (unsigned char *&p, unsigned char *next)
896 {
897   if (next - p < 1)
898     throw new java::lang::InternalError();
899   return *p++;
900 }
901
902 static unsigned int
903 read_u2 (unsigned char *&p)
904 {
905   unsigned int b1 = *p++;
906   unsigned int b2 = *p++;
907   return (b1 << 8) | b2;
908 }
909
910 static unsigned int
911 read_u2 (unsigned char *&p, unsigned char *next)
912 {
913   if (next - p < 2)
914     throw new java::lang::InternalError();
915   return read_u2 (p);
916 }
917
918 static int
919 read_4 (unsigned char *&p)
920 {
921   int b1 = *p++;
922   int b2 = *p++;
923   int b3 = *p++;
924   int b4 = *p++;
925   return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
926 }
927
928 jstring
929 java::lang::Class::getReflectionSignature (jint /*jv_attr_type*/ type,
930                                            jint obj_index)
931 {
932   // We just re-parse the bytecode for this data each time.  If
933   // necessary we can cache results, but I suspect this is not
934   // performance sensitive.
935   unsigned char *bytes = reflection_data;
936   if (bytes == NULL)
937     return NULL;
938   while (true)
939     {
940       int kind = read_u1 (bytes);
941       if (kind == JV_DONE_ATTR)
942         return NULL;
943       int len = read_4 (bytes);
944       unsigned char *next = bytes + len;
945       if (kind != type)
946         {
947           bytes = next;
948           continue;
949         }
950       if (type != JV_CLASS_ATTR)
951         {
952           unsigned short index = read_u2 (bytes, next);
953           if (index != obj_index)
954             {
955               bytes = next;
956               continue;
957             }
958         }
959       int nt = read_u1 (bytes, next);
960       if (nt != JV_SIGNATURE_KIND)
961         {
962           bytes = next;
963           continue;
964         }
965       unsigned int cpool_idx = read_u2 (bytes, next);
966       if (cpool_idx >= (unsigned int) constants.size
967           || constants.tags[cpool_idx] != JV_CONSTANT_Utf8)
968         {
969           // We just ignore errors for now.  It isn't clear what is
970           // best to do here, as an encoding error here means a bug
971           // either in the compiler or in defineclass.cc.
972           return NULL;
973         }
974       return _Jv_NewStringUtf8Const (constants.data[cpool_idx].utf8);
975     }
976 }
977
978 jstring
979 java::lang::Class::getReflectionSignature (::java::lang::reflect::Constructor *c)
980 {
981   _Jv_Method *meth = _Jv_FromReflectedConstructor (c);
982   unsigned short meth_index = meth - methods;
983   return getReflectionSignature (JV_METHOD_ATTR, meth_index);
984 }
985
986 jstring
987 java::lang::Class::getReflectionSignature (::java::lang::reflect::Method *m)
988 {
989   _Jv_Method *meth = _Jv_FromReflectedMethod (m);
990   unsigned short meth_index = meth - methods;
991   return getReflectionSignature (JV_METHOD_ATTR, meth_index);
992 }
993
994 jstring
995 java::lang::Class::getReflectionSignature (::java::lang::reflect::Field *f)
996 {
997   _Jv_Field *fld = _Jv_FromReflectedField (f);
998   unsigned short fld_index = fld - fields;
999   return getReflectionSignature (JV_FIELD_ATTR, fld_index);
1000 }
1001
1002 jstring
1003 java::lang::Class::getClassSignature()
1004 {
1005   return getReflectionSignature (JV_CLASS_ATTR, 0);
1006 }
1007
1008 jint
1009 java::lang::Class::getEnclosingMethodData()
1010 {
1011   unsigned char *bytes = reflection_data;
1012   if (bytes == NULL)
1013     return 0;
1014   while (true)
1015     {
1016       int kind = read_u1 (bytes);
1017       if (kind == JV_DONE_ATTR)
1018         return 0;
1019       int len = read_4 (bytes);
1020       unsigned char *next = bytes + len;
1021       if (kind != JV_CLASS_ATTR)
1022         {
1023           bytes = next;
1024           continue;
1025         }
1026       int type = read_u1 (bytes, next);
1027       if (type != JV_ENCLOSING_METHOD_KIND)
1028         {
1029           bytes = next;
1030           continue;
1031         }
1032       int class_index = read_u2 (bytes, next);
1033       int method_index = read_u2 (bytes, next);
1034       _Jv_word result;
1035       _Jv_storeIndexes (&result, class_index, method_index);
1036       return result.i;
1037     }
1038 }
1039
1040 jclass
1041 java::lang::Class::getEnclosingClass()
1042 {
1043   _Jv_word indexes;
1044   indexes.i = getEnclosingMethodData();
1045   if (indexes.i == 0)
1046     // No enclosing method, but perhaps a member or anonymous class
1047     return getDeclaringClass();
1048   _Jv_ushort class_index, method_index;
1049   _Jv_loadIndexes (&indexes, class_index, method_index);
1050   return _Jv_Linker::resolve_pool_entry (this, class_index).clazz;
1051 }
1052
1053 ::java::lang::reflect::Method *
1054 java::lang::Class::getEnclosingMethod()
1055 {
1056   _Jv_word indexes;
1057   indexes.i = getEnclosingMethodData();
1058   if (indexes.i == 0)
1059     return NULL;
1060   _Jv_ushort class_index, method_index;
1061   _Jv_loadIndexes (&indexes, class_index, method_index);
1062   jclass found_class;
1063   _Jv_Method *method = _Jv_Linker::resolve_method_entry (this, found_class,
1064                                                          class_index,
1065                                                          method_index,
1066                                                          false, false);
1067   using namespace java::lang::reflect;
1068   Method *rmethod = new Method ();
1069   rmethod->offset = (char *) method - (char *) found_class->methods;
1070   rmethod->declaringClass = found_class;
1071   return rmethod;
1072 }
1073
1074 ::java::lang::reflect::Constructor *
1075 java::lang::Class::getEnclosingConstructor()
1076 {
1077   _Jv_word indexes;
1078   indexes.i = getEnclosingMethodData();
1079   if (indexes.i == 0)
1080     return NULL;
1081   _Jv_ushort class_index, method_index;
1082   _Jv_loadIndexes (&indexes, class_index, method_index);
1083   jclass found_class;
1084   _Jv_Method *method = _Jv_Linker::resolve_method_entry (this, found_class,
1085                                                          class_index,
1086                                                          method_index,
1087                                                          false, false);
1088   using namespace java::lang::reflect;
1089   Constructor *cons = new Constructor ();
1090   cons->offset = (char *) method - (char *) found_class->methods;
1091   cons->declaringClass = this;
1092   return cons;
1093 }
1094
1095 static void
1096 check_constant (_Jv_Constants *pool, jint cpool_index, jint type)
1097 {
1098   if (cpool_index <= 0 || cpool_index >= pool->size)
1099     throw new InternalError(JvNewStringLatin1("invalid constant pool index"));
1100   if ((pool->tags[cpool_index] & 
1101         ~(JV_CONSTANT_ResolvedFlag|JV_CONSTANT_LazyFlag)) != type)
1102     {
1103       ::java::lang::StringBuffer *sb = new ::java::lang::StringBuffer();
1104       sb->append(JvNewStringLatin1("expected pool constant "));
1105       sb->append(type);
1106       sb->append(JvNewStringLatin1(" but got "));
1107       sb->append(jint (pool->tags[cpool_index]));
1108       throw new InternalError(sb->toString());
1109     }
1110 }
1111
1112 // Forward declaration
1113 static ::java::lang::annotation::Annotation *
1114 parseAnnotation(jclass klass, _Jv_Constants *pool,
1115                 unsigned char *&bytes, unsigned char *last);
1116
1117 static jobject
1118 parseAnnotationElement(jclass klass, _Jv_Constants *pool,
1119                        unsigned char *&bytes, unsigned char *last)
1120 {
1121   int tag = read_u1 (bytes, last);
1122   jobject result;
1123   switch (tag)
1124     {
1125     case 'B':
1126       {
1127         int cindex = read_u2 (bytes, last);
1128         check_constant (pool, cindex, JV_CONSTANT_Integer);
1129         result = Byte::valueOf (pool->data[cindex].i);
1130       }
1131       break;
1132     case 'C':
1133       {
1134         int cindex = read_u2 (bytes, last);
1135         check_constant (pool, cindex, JV_CONSTANT_Integer);
1136         result = Character::valueOf (pool->data[cindex].i);
1137       }
1138       break;
1139     case 'S':
1140       {
1141         int cindex = read_u2 (bytes, last);
1142         check_constant (pool, cindex, JV_CONSTANT_Integer);
1143         result = Short::valueOf (pool->data[cindex].i);
1144       }
1145       break;
1146     case 'Z':
1147       {
1148         int cindex = read_u2 (bytes, last);
1149         check_constant (pool, cindex, JV_CONSTANT_Integer);
1150         result = Boolean::valueOf (jboolean (pool->data[cindex].i));
1151       }
1152       break;
1153     case 'I':
1154       {
1155         int cindex = read_u2 (bytes, last);
1156         check_constant (pool, cindex, JV_CONSTANT_Integer);
1157         result = Integer::valueOf (pool->data[cindex].i);
1158       }
1159       break;
1160     case 'D':
1161       {
1162         int cindex = read_u2 (bytes, last);
1163         check_constant (pool, cindex, JV_CONSTANT_Double);
1164         _Jv_word2 word;
1165         memcpy (&word, &pool->data[cindex], 2 * sizeof (_Jv_word));
1166         result = Double::valueOf (word.d);
1167       }
1168       break;
1169     case 'F':
1170       {
1171         int cindex = read_u2 (bytes, last);
1172         check_constant (pool, cindex, JV_CONSTANT_Float);
1173         result = Float::valueOf (pool->data[cindex].f);
1174       }
1175       break;
1176     case 'J':
1177       {
1178         int cindex = read_u2 (bytes, last);
1179         check_constant (pool, cindex, JV_CONSTANT_Long);
1180         _Jv_word2 word;
1181         memcpy (&word, &pool->data[cindex], 2 * sizeof (_Jv_word));
1182         result = Long::valueOf (word.l);
1183       }
1184       break;
1185     case 's':
1186       {
1187         int cindex = read_u2 (bytes, last);
1188         // Despite what the JVM spec says, compilers generate a Utf8
1189         // constant here, not a String.
1190         check_constant (pool, cindex, JV_CONSTANT_Utf8);
1191         result = pool->data[cindex].utf8->toString();
1192       }
1193       break;
1194     case 'e':
1195       {
1196         int type_name_index = read_u2 (bytes, last);
1197         check_constant (pool, type_name_index, JV_CONSTANT_Utf8);
1198         int const_name_index = read_u2 (bytes, last);
1199         check_constant (pool, const_name_index, JV_CONSTANT_Utf8);
1200
1201         _Jv_Utf8Const *u_name = pool->data[type_name_index].utf8;
1202         _Jv_Utf8Const *e_name = pool->data[const_name_index].utf8;
1203
1204         // FIXME: throw correct exceptions at the correct times.
1205         jclass e_class = _Jv_FindClassFromSignature(u_name->chars(),
1206                                                     klass->getClassLoaderInternal());
1207         result = ::java::lang::Enum::valueOf(e_class, e_name->toString());
1208       }
1209       break;
1210     case 'c':
1211       {
1212         int cindex = read_u2 (bytes, last);
1213         check_constant (pool, cindex, JV_CONSTANT_Utf8);
1214         _Jv_Utf8Const *u_name = pool->data[cindex].utf8;
1215         jclass anno_class
1216           = _Jv_FindClassFromSignatureNoException(u_name->chars(),
1217                                                   klass->getClassLoaderInternal());
1218         // FIXME: not correct: we should lazily do this when trying to
1219         // read the element.  This means that
1220         // AnnotationInvocationHandler needs to have a special case.
1221         if (! anno_class)
1222           // FIXME: original exception...
1223           throw new TypeNotPresentException(u_name->toString(), NULL);
1224         result = anno_class;
1225       }
1226       break;
1227     case '@':
1228       result = parseAnnotation (klass, pool, bytes, last);
1229       break;
1230     case '[':
1231       {
1232         int n_array_elts = read_u2 (bytes, last);
1233         jobjectArray aresult = _Jv_NewObjectArray (n_array_elts,
1234                                                    &Object::class$, NULL);
1235         jobject *elts = elements (aresult);
1236         for (int i = 0; i < n_array_elts; ++i)
1237           elts[i] = parseAnnotationElement(klass, pool, bytes, last);
1238         result = aresult;
1239       }
1240       break;
1241     default:
1242       throw new java::lang::InternalError();
1243     }
1244   return result;
1245 }
1246
1247 static ::java::lang::annotation::Annotation *
1248 parseAnnotation(jclass klass, _Jv_Constants *pool,
1249                 unsigned char *&bytes, unsigned char *last)
1250 {
1251   int type_index = read_u2 (bytes, last);
1252   check_constant (pool, type_index, JV_CONSTANT_Utf8);
1253
1254   _Jv_Utf8Const *u_name = pool->data[type_index].utf8;
1255   jclass anno_class = _Jv_FindClassFromSignatureNoException(u_name->chars(),
1256                                                             klass->getClassLoaderInternal());
1257   // FIXME: what to do if anno_class==NULL?
1258
1259   ::java::util::HashMap *hmap = new ::java::util::HashMap();
1260   int npairs = read_u2 (bytes, last);
1261   for (int i = 0; i < npairs; ++i)
1262     {
1263       int name_index = read_u2 (bytes, last);
1264       check_constant (pool, name_index, JV_CONSTANT_Utf8);
1265       jstring name = _Jv_NewStringUtf8Const (pool->data[name_index].utf8);
1266       jobject value = parseAnnotationElement (klass, pool, bytes, last);
1267       // FIXME: any checks needed for name?
1268       hmap->put(name, value);
1269     }
1270   using namespace ::sun::reflect::annotation;
1271   return AnnotationInvocationHandler::create (anno_class,
1272                                               (::java::util::Map *) hmap);
1273 }
1274
1275 static jobjectArray
1276 parseAnnotations(jclass klass, _Jv_Constants *pool,
1277                  unsigned char *&bytes, unsigned char *last)
1278 {
1279   int num = read_u2 (bytes, last);
1280   jobjectArray result = _Jv_NewObjectArray (num,
1281                                             &::java::lang::annotation::Annotation::class$,
1282                                             NULL);
1283   jobject *elts = elements (result);
1284   for (int i = 0; i < num; ++i)
1285     elts[i] = parseAnnotation(klass, pool, bytes, last);
1286   return result;
1287 }
1288
1289 static jobjectArray
1290 parseParameterAnnotations(jclass klass, _Jv_Constants *pool,
1291                           unsigned char *&bytes, unsigned char *last)
1292 {
1293   jclass anno = &::java::lang::annotation::Annotation::class$;
1294   jclass annoary = _Jv_GetArrayClass (anno, anno->getClassLoaderInternal());
1295
1296   // FIXME: something should check the number of params versus the
1297   // method
1298   int n_params = read_u1 (bytes, last);
1299   jobjectArray result = _Jv_NewObjectArray (n_params, annoary, NULL);
1300   jobject *elts = elements (result);
1301   for (int i = 0; i < n_params; ++i)
1302     elts[i] = parseAnnotations(klass, pool, bytes, last);
1303   return result;
1304 }
1305
1306 jobject
1307 java::lang::Class::getMethodDefaultValue(::java::lang::reflect::Method *meth)
1308 {
1309   // FIXME: could cache the value here...
1310
1311   unsigned char *bytes = reflection_data;
1312   if (bytes == NULL)
1313     return 0;
1314
1315   unsigned short meth_index = _Jv_FromReflectedMethod (meth) - methods;
1316
1317   while (true)
1318     {
1319       int type = read_u1 (bytes);
1320       if (type == JV_DONE_ATTR)
1321         return NULL;
1322       int len = read_4 (bytes);
1323       unsigned char *next = bytes + len;
1324       if (type != JV_METHOD_ATTR)
1325         {
1326           bytes = next;
1327           continue;
1328         }
1329       int kind = read_u1 (bytes, next);
1330       if (kind != JV_ANNOTATION_DEFAULT_KIND)
1331         {
1332           bytes = next;
1333           continue;
1334         }
1335       int index = read_u2 (bytes, next);
1336       if (meth_index != index)
1337         {
1338           bytes = next;
1339           continue;
1340         }
1341
1342       // FIXME: could cache here.  If we do then we have to clone any
1343       // array result.
1344       return parseAnnotationElement(this, &this->constants, bytes, next);
1345     }
1346 }
1347
1348 jobjectArray
1349 java::lang::Class::getDeclaredAnnotations(jint /* jv_attr_type */ member_type,
1350                                           jint member_index,
1351                                           jint /* jv_attr_kind */ kind_req)
1352 {
1353   using namespace java::lang::annotation;
1354   jobjectArray result;
1355
1356   unsigned char *bytes = reflection_data;
1357   if (bytes == NULL)
1358     return 0;
1359
1360   if (loader == NULL)
1361     loader = (ClassLoader *)VMClassLoader::bootLoader;
1362
1363   result = (loader->getDeclaredAnnotations
1364             (this, member_type, member_index, kind_req));
1365   if (result)
1366     return result;
1367
1368   for (;;)
1369     {
1370       int type = read_u1 (bytes);
1371       if (type == JV_DONE_ATTR)
1372         return NULL;
1373       int len = read_4 (bytes);
1374       unsigned char *next = bytes + len;
1375       if (type != member_type)
1376         {
1377           bytes = next;
1378           continue;
1379         }
1380       int kind = read_u1 (bytes, next);
1381       if (kind != kind_req)
1382         {
1383           bytes = next;
1384           continue;
1385         }
1386       if (member_type != JV_CLASS_ATTR)
1387         {
1388           int index = read_u2 (bytes, next);
1389           if (member_index != index)
1390             {
1391               bytes = next;
1392               continue;
1393             }
1394         }
1395
1396       if (kind_req == JV_PARAMETER_ANNOTATIONS_KIND)
1397         result = ((parseParameterAnnotations 
1398                    (this, &this->constants, bytes, next)));
1399       else
1400         result = ((parseAnnotations (this, &this->constants, bytes, next)));
1401       break;
1402     }
1403
1404   return (loader->putDeclaredAnnotations
1405           (this, member_type, member_index, kind_req, result));
1406 }
1407
1408 jobjectArray
1409 java::lang::Class::getDeclaredAnnotations(::java::lang::reflect::Method *meth,
1410                                           jboolean is_param)
1411 {
1412   unsigned short meth_index = _Jv_FromReflectedMethod (meth) - methods;
1413   return getDeclaredAnnotations(JV_METHOD_ATTR, meth_index,
1414                                 (is_param
1415                                  ? JV_PARAMETER_ANNOTATIONS_KIND
1416                                  : JV_ANNOTATIONS_KIND));
1417 }
1418
1419 jobjectArray
1420 java::lang::Class::getDeclaredAnnotations(::java::lang::reflect::Constructor *cons,
1421                                           jboolean is_param)
1422 {
1423   unsigned short meth_index = _Jv_FromReflectedConstructor (cons) - methods;
1424   return getDeclaredAnnotations(JV_METHOD_ATTR, meth_index,
1425                                 (is_param
1426                                  ? JV_PARAMETER_ANNOTATIONS_KIND
1427                                  : JV_ANNOTATIONS_KIND));
1428 }
1429
1430 jobjectArray
1431 java::lang::Class::getDeclaredAnnotations(::java::lang::reflect::Field *fld)
1432 {
1433   unsigned short field_index = _Jv_FromReflectedField (fld) - fields;
1434   return getDeclaredAnnotations(JV_FIELD_ATTR, field_index,
1435                                 JV_ANNOTATIONS_KIND);
1436 }
1437
1438 JArray< ::java::lang::annotation::Annotation *> *
1439 java::lang::Class::getDeclaredAnnotationsInternal()
1440 {
1441   return (JArray< ::java::lang::annotation::Annotation *> *) getDeclaredAnnotations(JV_CLASS_ATTR, 0, JV_ANNOTATIONS_KIND);
1442 }
1443
1444 static jclass
1445 resolve_class_constant (jclass klass, _Jv_Constants *pool, int cpool_index)
1446 {
1447   check_constant (pool, cpool_index, JV_CONSTANT_Class);
1448   // FIXME: what is the correct thing to do with an exception here?
1449   return _Jv_Linker::resolve_pool_entry (klass, cpool_index, false).clazz;
1450 }
1451
1452 jint
1453 java::lang::Class::findInnerClassAttribute()
1454 {
1455   unsigned char *bytes = reflection_data;
1456   if (bytes == NULL)
1457     return -1;
1458   while (true)
1459     {
1460       int type = read_u1 (bytes);
1461       if (type == JV_DONE_ATTR)
1462         break;
1463       // After the type but before the length.
1464       unsigned char *save = bytes;
1465       int len = read_4 (bytes);
1466       unsigned char *next = bytes + len;
1467       if (type != JV_CLASS_ATTR)
1468         {
1469           bytes = next;
1470           continue;
1471         }
1472       int kind = read_u1 (bytes, next);
1473       if (kind != JV_INNER_CLASSES_KIND)
1474         {
1475           bytes = next;
1476           continue;
1477         }
1478       return save - reflection_data;
1479     }
1480   return -1;
1481 }
1482
1483 jint
1484 java::lang::Class::findDeclaredClasses(JArray<jclass> *result,
1485                                        jboolean publicOnly,
1486                                        jint offset)
1487 {
1488   unsigned char *bytes = reflection_data + offset;
1489   int len = read_4 (bytes);
1490   unsigned char *next = bytes + len;
1491   // Skip a byte.
1492   read_u1 (bytes, next);
1493   int n_classes = read_u2 (bytes, next);
1494   int count = 0;
1495   for (int i = 0; i < n_classes; ++i)
1496     {
1497       int inner_class_index = read_u2 (bytes, next);
1498       int outer_class_index = read_u2 (bytes, next);
1499       /*int inner_name_index = */ read_u2 (bytes, next);
1500       int inner_flags = read_u2 (bytes, next);
1501
1502       if (inner_class_index == 0 || outer_class_index == 0)
1503         continue;
1504       if (resolve_class_constant (this, &constants, outer_class_index) == this)
1505         {
1506           jclass inner = resolve_class_constant (this, &constants,
1507                                                  inner_class_index);
1508           if (! publicOnly
1509               || ((inner_flags
1510                    & java::lang::reflect::Modifier::PUBLIC) != 0))
1511             {
1512               if (result)
1513                 {
1514                   jclass *elts = elements (result);
1515                   elts[count] = inner;
1516                 }
1517               ++count;
1518             }
1519         }
1520     }
1521
1522   return count;
1523 }
1524
1525 JArray<jclass> *
1526 java::lang::Class::getDeclaredClasses (jboolean publicOnly)
1527 {
1528   int offset = findInnerClassAttribute();
1529   int count;
1530   if (offset == -1)
1531     {
1532       // No InnerClasses attribute, so no declared classes.
1533       count = 0;
1534     }
1535   else
1536     count = findDeclaredClasses(NULL, publicOnly, offset);
1537   JArray<jclass> *result
1538     = (JArray<jclass> *) JvNewObjectArray (count, &java::lang::Class::class$,
1539                                            NULL);
1540   if (count > 0)
1541     findDeclaredClasses(result, publicOnly, offset);
1542   return result;
1543 }
1544
1545 jclass
1546 java::lang::Class::getDeclaringClass (void)
1547 {
1548   int offset = findInnerClassAttribute();
1549   if (offset == -1)
1550     return NULL;
1551
1552   unsigned char *bytes = reflection_data + offset;
1553   int len = read_4 (bytes);
1554   unsigned char *next = bytes + len;
1555   // Skip a byte.
1556   read_u1 (bytes, next);
1557   int n_classes = read_u2 (bytes, next);
1558   for (int i = 0; i < n_classes; ++i)
1559     {
1560       int inner_class_index = read_u2 (bytes, next);
1561       int outer_class_index = read_u2 (bytes, next);
1562       /*int inner_name_index = */read_u2 (bytes, next);
1563       /*int inner_flags = */read_u2 (bytes, next);
1564
1565       if (inner_class_index == 0 || outer_class_index == 0)
1566         continue;
1567       if (resolve_class_constant (this, &constants, inner_class_index) == this)
1568         return resolve_class_constant (this, &constants, outer_class_index);
1569     }
1570
1571   return NULL;
1572 }
1573
1574 jboolean
1575 java::lang::Class::isAnonymousClass()
1576 {
1577   int offset = findInnerClassAttribute();
1578   if (offset == -1)
1579     return false;
1580
1581   unsigned char *bytes = reflection_data + offset;
1582   int len = read_4 (bytes);
1583   unsigned char *next = bytes + len;
1584   // Skip a byte.
1585   read_u1 (bytes, next);
1586   int n_classes = read_u2 (bytes, next);
1587   for (int i = 0; i < n_classes; ++i)
1588     {
1589       int inner_class_index = read_u2 (bytes, next);
1590       /*int outer_class_index = */read_u2 (bytes, next);
1591       int inner_name_index = read_u2 (bytes, next);
1592       /*int inner_flags = */read_u2 (bytes, next);
1593
1594       if (inner_class_index == 0)
1595         continue;
1596       if (resolve_class_constant (this, &constants, inner_class_index) == this)
1597         return inner_name_index == 0;
1598     }
1599
1600   return false;
1601 }
1602
1603 jboolean
1604 java::lang::Class::isLocalClass()
1605 {
1606   _Jv_word indexes;
1607   indexes.i = getEnclosingMethodData();
1608   return indexes.i != 0;
1609 }
1610
1611 jboolean
1612 java::lang::Class::isMemberClass()
1613 {
1614   // FIXME: is this correct?
1615   return !isLocalClass() && getDeclaringClass() != NULL;
1616 }
1617
1618 \f
1619
1620 //
1621 // Some class-related convenience functions.
1622 //
1623
1624 // Find a method declared in the class.  If it is not declared locally
1625 // (or if it is inherited), return NULL.
1626 _Jv_Method *
1627 _Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
1628                     _Jv_Utf8Const *signature)
1629 {
1630   for (int i = 0; i < klass->method_count; ++i)
1631     {
1632       if (_Jv_equalUtf8Consts (name, klass->methods[i].name)
1633           && _Jv_equalUtf8Consts (signature, klass->methods[i].signature))
1634         return &klass->methods[i];
1635     }
1636   return NULL;
1637 }
1638
1639 _Jv_Method *
1640 _Jv_LookupDeclaredMethod (jclass klass, _Jv_Utf8Const *name,
1641                           _Jv_Utf8Const *signature,
1642                           jclass *declarer_result)
1643 {
1644   for (; klass; klass = klass->getSuperclass())
1645     {
1646       _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
1647
1648       if (meth)
1649         {
1650           if (declarer_result)
1651             *declarer_result = klass;
1652           return meth;
1653         }
1654     }
1655
1656   return NULL;
1657 }
1658
1659 java::lang::reflect::Method *
1660 _Jv_GetReflectedMethod (jclass klass, _Jv_Utf8Const *name,
1661                        _Jv_Utf8Const *signature)
1662 {
1663   for (; klass; klass = klass->getSuperclass())
1664     {
1665       _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
1666       if (meth)
1667         {
1668           using namespace java::lang::reflect;
1669           Method *rmethod = new Method ();
1670           rmethod->offset = (char*) meth - (char*) klass->methods;
1671           rmethod->declaringClass = klass;
1672           return rmethod;
1673         }
1674     }
1675   
1676   return NULL;
1677 }
1678
1679 #ifdef HAVE_TLS
1680
1681 // NOTE: MCACHE_SIZE should be a power of 2 minus one.
1682 #define MCACHE_SIZE 31
1683
1684 struct _Jv_mcache
1685 {
1686   jclass klass;
1687   _Jv_Method *method;
1688 };
1689
1690 static __thread _Jv_mcache *method_cache;
1691 #endif // HAVE_TLS
1692
1693 static void *
1694 _Jv_FindMethodInCache (jclass klass MAYBE_UNUSED,
1695                        _Jv_Utf8Const *name MAYBE_UNUSED,
1696                        _Jv_Utf8Const *signature MAYBE_UNUSED)
1697 {
1698 #ifdef HAVE_TLS
1699   _Jv_mcache *cache = method_cache;
1700   if (cache)
1701     {
1702       int index = name->hash16 () & MCACHE_SIZE;
1703       _Jv_mcache *mc = &cache[index];
1704       _Jv_Method *m = mc->method;
1705
1706       if (mc->klass == klass
1707           && _Jv_equalUtf8Consts (m->name, name)
1708           && _Jv_equalUtf8Consts (m->signature, signature))
1709         return mc->method->ncode;
1710     }
1711 #endif // HAVE_TLS
1712   return NULL;
1713 }
1714
1715 static void
1716 _Jv_AddMethodToCache (jclass klass MAYBE_UNUSED,
1717                       _Jv_Method *method MAYBE_UNUSED)
1718 {
1719 #ifdef HAVE_TLS
1720   if (method_cache == NULL)
1721     method_cache = (_Jv_mcache *) _Jv_MallocUnchecked((MCACHE_SIZE + 1)
1722                                                       * sizeof (_Jv_mcache));
1723   // If the allocation failed, just keep going.
1724   if (method_cache != NULL)
1725     {
1726       int index = method->name->hash16 () & MCACHE_SIZE;
1727       method_cache[index].method = method;
1728       method_cache[index].klass = klass;
1729     }
1730 #endif // HAVE_TLS
1731 }
1732
1733 // Free this thread's method cache.  We explicitly manage this memory
1734 // as the GC does not yet know how to scan TLS on all platforms.
1735 void
1736 _Jv_FreeMethodCache ()
1737 {
1738 #ifdef HAVE_TLS
1739   if (method_cache != NULL)
1740     {
1741       _Jv_Free(method_cache);
1742       method_cache = NULL;
1743     }
1744 #endif // HAVE_TLS
1745 }
1746
1747 void *
1748 _Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name,
1749                            _Jv_Utf8Const *signature)
1750 {
1751   using namespace java::lang::reflect;
1752
1753   void *ncode = _Jv_FindMethodInCache (klass, name, signature);
1754   if (ncode != 0)
1755     return ncode;
1756
1757   for (; klass; klass = klass->getSuperclass())
1758     {
1759       _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
1760       if (! meth)
1761         continue;
1762
1763       if (Modifier::isStatic(meth->accflags))
1764         throw new java::lang::IncompatibleClassChangeError
1765           (_Jv_GetMethodString (klass, meth));
1766       if (Modifier::isAbstract(meth->accflags))
1767         throw new java::lang::AbstractMethodError
1768           (_Jv_GetMethodString (klass, meth));
1769       if (! Modifier::isPublic(meth->accflags))
1770         throw new java::lang::IllegalAccessError
1771           (_Jv_GetMethodString (klass, meth));
1772
1773       _Jv_AddMethodToCache (klass, meth);
1774
1775       return meth->ncode;
1776     }
1777   throw new java::lang::IncompatibleClassChangeError;
1778 }
1779
1780 // Fast interface method lookup by index.
1781 void *
1782 _Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface, int method_idx)
1783 {
1784   _Jv_IDispatchTable *cldt = klass->idt;
1785   int idx = iface->ioffsets[cldt->iindex] + method_idx;
1786   return cldt->itable[idx];
1787 }
1788
1789 jboolean
1790 _Jv_IsAssignableFrom (jclass source, jclass target)
1791 {
1792   if (source == target)
1793     return true;
1794
1795   // If target is array, so must source be.  
1796   while (target->isArray ())
1797     {
1798       if (! source->isArray())
1799         return false;
1800       target = target->getComponentType();
1801       source = source->getComponentType();
1802     }
1803
1804   if (target->isInterface())
1805     {
1806       // Abstract classes have no IDT, and IDTs provide no way to check
1807       // two interfaces for assignability.
1808       if (__builtin_expect 
1809           (source->idt == NULL || source->isInterface(), false))
1810         return _Jv_InterfaceAssignableFrom (source, target);
1811
1812       _Jv_IDispatchTable *cl_idt = source->idt;
1813
1814       if (__builtin_expect ((target->ioffsets == NULL), false))
1815         return false; // No class implementing TARGET has been loaded.    
1816       jshort cl_iindex = cl_idt->iindex;
1817       if (cl_iindex < target->ioffsets[0])
1818         {
1819           jshort offset = target->ioffsets[cl_iindex];
1820           if (offset != -1 && offset < cl_idt->itable_length
1821               && cl_idt->itable[offset] == target)
1822             return true;
1823         }
1824       return false;
1825     }
1826
1827   // Primitive TYPE classes are only assignable to themselves.
1828   if (__builtin_expect (target->isPrimitive() || source->isPrimitive(), false))
1829     return false;
1830
1831   if (target == &java::lang::Object::class$)
1832     return true;
1833   else if (source->ancestors == NULL || target->ancestors == NULL)
1834     {
1835       // We need this case when either SOURCE or TARGET has not has
1836       // its constant-time tables prepared.
1837
1838       // At this point we know that TARGET can't be Object, so it is
1839       // safe to use that as the termination point.
1840       while (source && source != &java::lang::Object::class$)
1841         {
1842           if (source == target)
1843             return true;
1844           source = source->getSuperclass();
1845         }
1846     }
1847   else if (source->depth >= target->depth
1848            && source->ancestors[source->depth - target->depth] == target)
1849     return true;
1850
1851   return false;
1852 }
1853
1854 // Interface type checking, the slow way. Returns TRUE if IFACE is a 
1855 // superinterface of SOURCE. This is used when SOURCE is also an interface,
1856 // or a class with no interface dispatch table.
1857 jboolean
1858 _Jv_InterfaceAssignableFrom (jclass source, jclass iface)
1859 {
1860   for (int i = 0; i < source->interface_count; i++)
1861     {
1862       jclass interface = source->interfaces[i];
1863       if (iface == interface
1864           || _Jv_InterfaceAssignableFrom (interface, iface))
1865         return true;      
1866     }
1867     
1868   if (!source->isInterface()
1869       && source->superclass 
1870       && _Jv_InterfaceAssignableFrom (source->superclass, iface))
1871     return true;
1872         
1873   return false;
1874 }
1875
1876 jboolean
1877 _Jv_IsInstanceOf(jobject obj, jclass cl)
1878 {
1879   if (__builtin_expect (!obj, false))
1880     return false;
1881   return _Jv_IsAssignableFrom (JV_CLASS (obj), cl);
1882 }
1883
1884 void *
1885 _Jv_CheckCast (jclass c, jobject obj)
1886 {
1887   if (__builtin_expect 
1888       (obj != NULL && ! _Jv_IsAssignableFrom(JV_CLASS (obj), c), false))
1889     throw new java::lang::ClassCastException
1890       ((new java::lang::StringBuffer
1891         (obj->getClass()->getName()))->append
1892        (JvNewStringUTF(" cannot be cast to "))->append
1893        (c->getName())->toString());
1894
1895   return obj;
1896 }
1897
1898 void
1899 _Jv_CheckArrayStore (jobject arr, jobject obj)
1900 {
1901   if (obj)
1902     {
1903       JvAssert (arr != NULL);
1904       jclass elt_class = (JV_CLASS (arr))->getComponentType();
1905       if (elt_class == &java::lang::Object::class$)
1906         return;
1907       jclass obj_class = JV_CLASS (obj);
1908       if (__builtin_expect 
1909           (! _Jv_IsAssignableFrom (obj_class, elt_class), false))
1910         throw new java::lang::ArrayStoreException
1911                 ((new java::lang::StringBuffer
1912                  (JvNewStringUTF("Cannot store ")))->append
1913                  (obj_class->getName())->append
1914                  (JvNewStringUTF(" in array of type "))->append
1915                  (elt_class->getName())->toString());
1916     }
1917 }
1918
1919 jboolean
1920 _Jv_IsAssignableFromSlow (jclass source, jclass target)
1921 {
1922   // First, strip arrays.
1923   while (target->isArray ())
1924     {
1925       // If target is array, source must be as well.
1926       if (! source->isArray ())
1927        return false;
1928       target = target->getComponentType ();
1929       source = source->getComponentType ();
1930     }
1931
1932   // Quick success.
1933   if (target == &java::lang::Object::class$)
1934     return true;
1935
1936   // Ensure that the classes have their supers installed.
1937   _Jv_Linker::wait_for_state (source, JV_STATE_LOADING);
1938   _Jv_Linker::wait_for_state (target, JV_STATE_LOADING);
1939
1940   do
1941     {
1942       if (source == target)
1943        return true;
1944
1945       if (target->isPrimitive () || source->isPrimitive ())
1946        return false;
1947
1948       if (target->isInterface ())
1949        {
1950          for (int i = 0; i < source->interface_count; ++i)
1951            {
1952              // We use a recursive call because we also need to
1953              // check superinterfaces.
1954              if (_Jv_IsAssignableFromSlow (source->getInterface (i), target))
1955                return true;
1956            }
1957        }
1958       source = source->getSuperclass ();
1959     }
1960   while (source != NULL);
1961
1962   return false;
1963 }
1964
1965 // Lookup an interface method by name.  This is very similar to
1966 // purpose to _getMethod, but the interfaces are quite different.  It
1967 // might be a good idea for _getMethod to call this function.
1968 //
1969 // Return true of the method is found, with the class in FOUND_CLASS
1970 // and the index in INDEX.
1971 bool
1972 _Jv_getInterfaceMethod (jclass search_class, jclass &found_class, int &index,
1973                         const _Jv_Utf8Const *utf_name,  
1974                         const _Jv_Utf8Const *utf_sig)
1975 {
1976    for (jclass klass = search_class; klass; klass = klass->getSuperclass())
1977     {
1978       // FIXME: Throw an exception?
1979       if (!klass->isInterface ())
1980         return false;
1981       
1982       int max = klass->method_count;
1983       int offset = 0;
1984       for (int i = 0; i < max; ++i)
1985         {
1986           // Skip <clinit> here, as it will not be in the IDT.
1987           if (klass->methods[i].name->first() == '<')
1988             continue;
1989
1990           if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
1991               && _Jv_equalUtf8Consts (klass->methods[i].signature, utf_sig))
1992             {
1993               // Found it.
1994               using namespace java::lang::reflect;
1995
1996               // FIXME: Method must be public.  Throw an exception?
1997               if (! Modifier::isPublic (klass->methods[i].accflags))
1998                 break;
1999
2000               found_class = klass;
2001               // Interface method indexes count from 1.
2002               index = offset + 1;
2003               return true;
2004             }
2005
2006           ++offset;
2007         }
2008     }
2009
2010   // If we haven't found a match, and this class is an interface, then
2011   // check all the superinterfaces.
2012   if (search_class->isInterface())
2013     {
2014       for (int i = 0; i < search_class->interface_count; ++i)
2015         {
2016           using namespace java::lang::reflect;
2017           bool found = _Jv_getInterfaceMethod (search_class->interfaces[i], 
2018                                                found_class, index,
2019                                                utf_name, utf_sig);
2020           if (found)
2021             return true;
2022         }
2023     }
2024
2025   return false;
2026 }
2027
2028 #ifdef INTERPRETER
2029 _Jv_MethodBase *
2030 _Jv_FindInterpreterMethod (jclass klass, jmethodID desired_method)
2031 {
2032   using namespace java::lang::reflect;
2033
2034   _Jv_InterpClass *iclass
2035     = reinterpret_cast<_Jv_InterpClass *> (klass->aux_info);
2036   _Jv_MethodBase **imethods = _Jv_GetFirstMethod (iclass);
2037
2038   for (int i = 0; i < JvNumMethods (klass); ++i)
2039     {
2040       _Jv_MethodBase *imeth = imethods[i];
2041       if (imeth->get_method () == desired_method)
2042         return imeth;
2043     }
2044
2045   return NULL;
2046 }
2047 #endif
2048
2049 // Return Utf8 name of a class. This function is here for code that
2050 // can't access klass->name directly.
2051 _Jv_Utf8Const*
2052 _Jv_GetClassNameUtf8 (jclass klass)
2053 {
2054   return klass->name;
2055 }
2056
2057 jclass
2058 _Jv_GetMethodDeclaringClass (jmethodID method)
2059 {
2060   _Jv_StackTrace::UpdateNCodeMap ();
2061   jobject obj = reinterpret_cast<jobject> (method->ncode);
2062   return reinterpret_cast<jclass> (_Jv_StackTrace::ncodeMap->get (obj));
2063 }
2064
2065 jbyte
2066 _Jv_GetClassState (jclass klass)
2067 {
2068   return klass->state;
2069 }
2070
2071 #ifdef INTERPRETER
2072 jstring
2073 _Jv_GetInterpClassSourceFile (jclass klass)
2074 {
2075   if (_Jv_IsInterpretedClass (klass))
2076     {
2077       _Jv_InterpClass *iclass =
2078         reinterpret_cast<_Jv_InterpClass *> (klass->aux_info);
2079       return iclass->source_file_name;
2080     }
2081
2082   return NULL;
2083 }
2084 #endif