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