OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [java/] [lang/] [natClass.cc] - Blame information for rev 14

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.