OSDN Git Service

2007-04-16 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / java / lang / reflect / natMethod.cc
1 // natMethod.cc - Native code for Method class.
2
3 /* Copyright (C) 1998, 1999, 2000, 2001 , 2002, 2003, 2004, 2005, 2006 Free Software Foundation
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 #include <config.h>
12
13 #include <gcj/cni.h>
14 #include <jvm.h>
15 #include <jni.h>
16 #include <java-stack.h>
17
18 #include <java/lang/reflect/Method.h>
19 #include <java/lang/reflect/Constructor.h>
20 #include <java/lang/reflect/InvocationTargetException.h>
21 #include <java/lang/reflect/Modifier.h>
22
23 #include <java/lang/Void.h>
24 #include <java/lang/Byte.h>
25 #include <java/lang/Boolean.h>
26 #include <java/lang/Character.h>
27 #include <java/lang/Short.h>
28 #include <java/lang/Integer.h>
29 #include <java/lang/Long.h>
30 #include <java/lang/Float.h>
31 #include <java/lang/Double.h>
32 #include <java/lang/IllegalAccessException.h>
33 #include <java/lang/IllegalArgumentException.h>
34 #include <java/lang/IncompatibleClassChangeError.h>
35 #include <java/lang/NullPointerException.h>
36 #include <java/lang/ArrayIndexOutOfBoundsException.h>
37 #include <java/lang/VirtualMachineError.h>
38 #include <java/lang/Class.h>
39 #include <gcj/method.h>
40 #include <gnu/gcj/RawData.h>
41 #include <java/lang/NoClassDefFoundError.h>
42
43 #include <stdlib.h>
44
45 #if USE_LIBFFI
46 #include <ffi.h>
47 #else
48 #include <java/lang/UnsupportedOperationException.h>
49 #endif
50
51 typedef JArray< ::java::lang::annotation::Annotation * > * anno_a_t;
52 typedef JArray< JArray< ::java::lang::annotation::Annotation * > *> * anno_aa_t;
53
54 \f
55
56 struct cpair
57 {
58   jclass prim;
59   jclass wrap;
60 };
61
62 // This is used to determine when a primitive widening conversion is
63 // allowed.
64 static cpair primitives[] =
65 {
66 #define BOOLEAN 0
67   { JvPrimClass (boolean), &java::lang::Boolean::class$ },
68   { JvPrimClass (byte), &java::lang::Byte::class$ },
69 #define SHORT 2
70   { JvPrimClass (short), &java::lang::Short::class$ },
71 #define CHAR 3
72   { JvPrimClass (char), &java::lang::Character::class$ },
73   { JvPrimClass (int), &java::lang::Integer::class$ },
74   { JvPrimClass (long), &java::lang::Long::class$ },
75   { JvPrimClass (float), &java::lang::Float::class$ },
76   { JvPrimClass (double), &java::lang::Double::class$ },
77   { NULL, NULL }
78 };
79
80 static inline jboolean
81 can_widen (jclass from, jclass to)
82 {
83   int fromx = -1, tox = -1;
84
85   for (int i = 0; primitives[i].prim; ++i)
86     {
87       if (primitives[i].wrap == from)
88         fromx = i;
89       if (primitives[i].prim == to)
90         tox = i;
91     }
92
93   // Can't handle a miss.
94   if (fromx == -1 || tox == -1)
95     return false;
96   // Boolean arguments may not be widened.
97   if (fromx == BOOLEAN && tox != BOOLEAN)
98     return false;
99   // Nothing promotes to char.
100   if (tox == CHAR && fromx != CHAR)
101     return false;
102
103   return fromx <= tox;
104 }
105
106 #ifdef USE_LIBFFI
107 static inline ffi_type *
108 get_ffi_type (jclass klass)
109 {
110   // A special case.
111   if (klass == NULL)
112     return &ffi_type_pointer;
113
114   ffi_type *r;
115   if (klass == JvPrimClass (byte))
116     r = &ffi_type_sint8;
117   else if (klass == JvPrimClass (short))
118     r = &ffi_type_sint16;
119   else if (klass == JvPrimClass (int))
120     r = &ffi_type_sint32;
121   else if (klass == JvPrimClass (long))
122     r = &ffi_type_sint64;
123   else if (klass == JvPrimClass (float))
124     r = &ffi_type_float;
125   else if (klass == JvPrimClass (double))
126     r = &ffi_type_double;
127   else if (klass == JvPrimClass (boolean))
128     {
129       // On some platforms a bool is a byte, on others an int.
130       if (sizeof (jboolean) == sizeof (jbyte))
131         r = &ffi_type_sint8;
132       else
133         {
134           JvAssert (sizeof (jboolean) == sizeof (jint));
135           r = &ffi_type_sint32;
136         }
137     }
138   else if (klass == JvPrimClass (char))
139     r = &ffi_type_uint16;
140   else
141     {
142       JvAssert (! klass->isPrimitive());
143       r = &ffi_type_pointer;
144     }
145
146   return r;
147 }
148 #endif // USE_LIBFFI
149
150 jobject
151 java::lang::reflect::Method::invoke (jobject obj, jobjectArray args)
152 {
153   using namespace java::lang::reflect;
154   jclass iface = NULL;
155   
156   if (parameter_types == NULL)
157     getType ();
158     
159   jmethodID meth = _Jv_FromReflectedMethod (this);
160
161   if (Modifier::isStatic(meth->accflags))
162     {
163       // We have to initialize a static class.  It is safe to do this
164       // here and not in _Jv_CallAnyMethodA because JNI initializes a
165       // class whenever a method lookup is done.
166       _Jv_InitClass (declaringClass);
167     }
168   else
169     {
170       jclass objClass = JV_CLASS (obj);
171       if (! _Jv_IsAssignableFrom (objClass, declaringClass))
172         throw new java::lang::IllegalArgumentException;
173     }
174
175   // Check accessibility, if required.
176   if (! this->isAccessible())
177     {
178       if (! (Modifier::isPublic (meth->accflags)))
179         {
180           Class *caller = _Jv_StackTrace::GetCallingClass (&Method::class$);
181           if (! _Jv_CheckAccess(caller, declaringClass, meth->accflags))
182             throw new IllegalAccessException;
183         }
184       else
185         // Method is public, check to see if class is accessible.
186         {
187           jint flags = (declaringClass->accflags
188                         & (Modifier::PUBLIC
189                            | Modifier::PROTECTED
190                            | Modifier::PRIVATE));
191           if (flags == 0) // i.e. class is package private
192             {
193               Class *caller = _Jv_StackTrace::GetCallingClass (&Method::class$);
194               if (! _Jv_ClassNameSamePackage (caller->name,
195                                               declaringClass->name))
196                 throw new IllegalAccessException;
197             }
198         }
199     }
200
201   if (declaringClass->isInterface())
202     iface = declaringClass;
203
204   return _Jv_CallAnyMethodA (obj, return_type, meth, false,
205                              parameter_types, args, iface);
206 }
207
208 jint
209 java::lang::reflect::Method::getModifiersInternal ()
210 {
211   return _Jv_FromReflectedMethod (this)->accflags;
212 }
213
214 jstring
215 java::lang::reflect::Method::getSignature()
216 {
217   return declaringClass->getReflectionSignature (this);
218 }
219
220 jobject
221 java::lang::reflect::Method::getDefaultValue()
222 {
223   return declaringClass->getMethodDefaultValue(this);
224 }
225
226 anno_a_t
227 java::lang::reflect::Method::getDeclaredAnnotationsInternal()
228 {
229   return (anno_a_t) declaringClass->getDeclaredAnnotations(this, false);
230 }
231
232 anno_aa_t
233 java::lang::reflect::Method::getParameterAnnotationsInternal()
234 {
235   return (anno_aa_t) declaringClass->getDeclaredAnnotations(this, true);
236 }
237
238 jstring
239 java::lang::reflect::Method::getName ()
240 {
241   if (name == NULL)
242     name = _Jv_NewStringUtf8Const (_Jv_FromReflectedMethod (this)->name);
243   return name;
244 }
245
246 /* Internal method to set return_type and parameter_types fields. */
247
248 void
249 java::lang::reflect::Method::getType ()
250 {
251   _Jv_Method *method = _Jv_FromReflectedMethod (this);
252   _Jv_GetTypesFromSignature (method,
253                              declaringClass,
254                              &parameter_types,
255                              &return_type);
256
257   int count = 0;
258   if (method->throws != NULL)
259     {
260       while (method->throws[count] != NULL)
261         ++count;
262     }
263
264   exception_types
265     = (JArray<jclass> *) JvNewObjectArray (count, &java::lang::Class::class$,
266                                            NULL);
267   jclass *elts = elements (exception_types);
268   for (int i = 0; i < count; ++i)
269     elts[i] = _Jv_FindClass (method->throws[i],
270                              declaringClass->getClassLoaderInternal ());
271 }
272
273 void
274 _Jv_GetTypesFromSignature (jmethodID method,
275                            jclass declaringClass,
276                            JArray<jclass> **arg_types_out,
277                            jclass *return_type_out)
278 {
279
280   _Jv_Utf8Const* sig = method->signature;
281   java::lang::ClassLoader *loader = declaringClass->getClassLoaderInternal();
282   char *ptr = sig->chars();
283   int numArgs = 0;
284   /* First just count the number of parameters. */
285   // FIXME: should do some validation here, e.g., that there is only
286   // one return type.
287   for (; ; ptr++)
288     {
289       switch (*ptr)
290         {
291         case 0:
292         case ')':
293         case 'V':
294           break;
295         case '[':
296         case '(':
297           continue;
298         case 'B':
299         case 'C':
300         case 'D':
301         case 'F':
302         case 'S':
303         case 'I':
304         case 'J':
305         case 'Z':
306           numArgs++;
307           continue;
308         case 'L':
309           numArgs++;
310           do 
311             ptr++;
312           while (*ptr != ';' && ptr[1] != '\0');
313           continue;
314         }
315       break;
316     }
317
318   JArray<jclass> *args = (JArray<jclass> *)
319     JvNewObjectArray (numArgs, &java::lang::Class::class$, NULL);
320   jclass* argPtr = elements (args);
321   for (ptr = sig->chars(); *ptr != '\0'; ptr++)
322     {
323       if (*ptr == '(')
324         continue;
325       if (*ptr == ')')
326         {
327           argPtr = return_type_out;
328           continue;
329         }
330
331       char *end_ptr;
332       jclass type = _Jv_FindClassFromSignature (ptr, loader, &end_ptr);
333       if (type == NULL)
334         // FIXME: This isn't ideal.
335         throw new java::lang::NoClassDefFoundError (sig->toString());
336
337       // ARGPTR can be NULL if we are processing the return value of a
338       // call from Constructor.
339       if (argPtr)
340         *argPtr++ = type;
341
342       ptr = end_ptr;
343     }
344   *arg_types_out = args;
345 }
346
347 // This is a very rough analog of the JNI CallNonvirtual<type>MethodA
348 // functions.  It handles both Methods and Constructors, and it can
349 // handle any return type.  In the Constructor case, the `obj'
350 // argument is unused and should be NULL; also, the `return_type' is
351 // the class that the constructor will construct.  RESULT is a pointer
352 // to a `jvalue' (see jni.h); for a void method this should be NULL.
353 // This function returns an exception (if one was thrown), or NULL if
354 // the call went ok.
355 void
356 _Jv_CallAnyMethodA (jobject obj,
357                     jclass return_type,
358                     jmethodID meth,
359                     jboolean is_constructor,
360                     jboolean is_virtual_call,
361                     JArray<jclass> *parameter_types,
362                     jvalue *args,
363                     jvalue *result,
364                     jboolean is_jni_call,
365                     jclass iface)
366 {
367   using namespace java::lang::reflect;
368   
369 #ifdef USE_LIBFFI
370   JvAssert (! is_constructor || ! obj);
371   JvAssert (! is_constructor || return_type);
372
373   // See whether call needs an object as the first argument.  A
374   // constructor does need a `this' argument, but it is one we create.
375   jboolean needs_this = false;
376   if (is_constructor
377       || ! Modifier::isStatic(meth->accflags))
378     needs_this = true;
379
380   int param_count = parameter_types->length;
381   if (needs_this)
382     ++param_count;
383
384   ffi_type *rtype;
385   // A constructor itself always returns void.
386   if (is_constructor || return_type == JvPrimClass (void))
387     rtype = &ffi_type_void;
388   else
389     rtype = get_ffi_type (return_type);
390   ffi_type **argtypes = (ffi_type **) __builtin_alloca (param_count
391                                                         * sizeof (ffi_type *));
392
393   jclass *paramelts = elements (parameter_types);
394
395   // Special case for the `this' argument of a constructor.  Note that
396   // the JDK 1.2 docs specify that the new object must be allocated
397   // before argument conversions are done.
398   if (is_constructor)
399     obj = _Jv_AllocObject (return_type);
400
401   const int size_per_arg = sizeof(jvalue);
402   ffi_cif cif;
403
404   char *p = (char *) __builtin_alloca (param_count * size_per_arg);
405                 // Overallocate to get correct alignment.
406   void **values = (void **)
407                         __builtin_alloca (param_count * sizeof (void *));
408
409   int i = 0;
410   if (needs_this)
411     {
412       // The `NULL' type is `Object'.
413       argtypes[i] = get_ffi_type (NULL);
414       values[i] = p;
415       memcpy (p, &obj, sizeof (jobject));
416       p += size_per_arg;
417       ++i;
418     }
419
420   for (int arg = 0; i < param_count; ++i, ++arg)
421     {
422       int tsize;
423
424       argtypes[i] = get_ffi_type (paramelts[arg]);
425       if (paramelts[arg]->isPrimitive())
426         tsize = paramelts[arg]->size();
427       else
428         tsize = sizeof (jobject);
429
430       // Copy appropriate bits from the jvalue into the ffi array.
431       // FIXME: we could do this copying all in one loop, above, by
432       // over-allocating a bit.
433       // How do we do this without breaking big-endian platforms?
434       values[i] = p;
435       memcpy (p, &args[arg], tsize);
436       p += size_per_arg;
437     }
438
439   if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, param_count,
440                     rtype, argtypes) != FFI_OK)
441     throw new java::lang::VirtualMachineError(JvNewStringLatin1("internal error: ffi_prep_cif failed"));
442
443   using namespace java::lang;
444   using namespace java::lang::reflect;
445
446   union
447   {
448     ffi_arg i;
449     jobject o;
450     jlong l;
451     jfloat f;
452     jdouble d;
453   } ffi_result;
454
455   switch (rtype->type)
456     {
457     case FFI_TYPE_VOID:
458       break;
459     case FFI_TYPE_SINT8:
460       result->b = 0;
461       break;
462     case FFI_TYPE_SINT16:
463       result->s = 0;
464       break;
465     case FFI_TYPE_UINT16:
466       result->c = 0;
467       break;
468     case FFI_TYPE_SINT32:
469       result->i = 0;
470       break;
471     case FFI_TYPE_SINT64:
472       result->j = 0;
473       break;
474     case FFI_TYPE_FLOAT:
475       result->f = 0;
476       break;
477     case FFI_TYPE_DOUBLE:
478       result->d = 0;
479       break;
480     case FFI_TYPE_POINTER:
481       result->l = 0;
482       break;
483     default:
484       JvFail ("Unknown ffi_call return type");
485       break;
486     }
487
488   void *ncode;
489
490   // FIXME: If a vtable index is -1 at this point it is invalid, so we
491   // have to use the ncode.  
492   //
493   // This can happen because methods in final classes don't have
494   // vtable entries, but _Jv_isVirtualMethod() doesn't know that.  We
495   // could solve this problem by allocating a vtable index for methods
496   // in final classes.
497   if (is_virtual_call 
498       && ! Modifier::isFinal (meth->accflags)
499       && (_Jv_ushort)-1 != meth->index)
500     {
501       _Jv_VTable *vtable = *(_Jv_VTable **) obj;
502       if (iface == NULL)
503         {
504           if (is_jni_call && Modifier::isAbstract (meth->accflags))
505             {
506               // With JNI we don't know if this is an interface call
507               // or a call to an abstract method.  Look up the method
508               // by name, the slow way.
509               _Jv_Method *concrete_meth
510                 = _Jv_LookupDeclaredMethod (vtable->clas,
511                                             meth->name,
512                                             meth->signature,
513                                             NULL);
514               if (concrete_meth == NULL
515                   || concrete_meth->ncode == NULL
516                   || Modifier::isAbstract(concrete_meth->accflags))
517                 throw new java::lang::IncompatibleClassChangeError
518                   (_Jv_GetMethodString (vtable->clas, meth));
519               ncode = concrete_meth->ncode;
520             }
521           else
522             ncode = vtable->get_method (meth->index);
523         }
524       else
525         ncode = _Jv_LookupInterfaceMethodIdx (vtable->clas, iface,
526                                               meth->index);
527     }
528   else
529     {
530       ncode = meth->ncode;
531     }
532
533   try
534     {
535       ffi_call (&cif, (void (*)()) ncode, &ffi_result, values);
536     }
537   catch (Throwable *ex)
538     {
539       // For JNI we just throw the real error.  For reflection, we
540       // wrap the underlying method's exception in an
541       // InvocationTargetException.
542       if (! is_jni_call)
543         ex = new InvocationTargetException (ex);
544       throw ex;
545     }
546
547   // Since ffi_call returns integer values promoted to a word, use
548   // a narrowing conversion for jbyte, jchar, etc. results.
549   // Note that boolean is handled either by the FFI_TYPE_SINT8 or
550   // FFI_TYPE_SINT32 case.
551   if (is_constructor)
552     result->l = obj;
553   else
554     {
555       switch (rtype->type)
556         {
557         case FFI_TYPE_VOID:
558           break;
559         case FFI_TYPE_SINT8:
560           result->b = (jbyte)ffi_result.i;
561           break;
562         case FFI_TYPE_SINT16:
563           result->s = (jshort)ffi_result.i;
564           break;
565         case FFI_TYPE_UINT16:
566           result->c = (jchar)ffi_result.i;
567           break;
568         case FFI_TYPE_SINT32:
569           result->i = (jint)ffi_result.i;
570           break;
571         case FFI_TYPE_SINT64:
572           result->j = (jlong)ffi_result.l;
573           break;
574         case FFI_TYPE_FLOAT:
575           result->f = (jfloat)ffi_result.f;
576           break;
577         case FFI_TYPE_DOUBLE:
578           result->d = (jdouble)ffi_result.d;
579           break;
580         case FFI_TYPE_POINTER:
581           result->l = (jobject)ffi_result.o;
582           break;
583         default:
584           JvFail ("Unknown ffi_call return type");
585           break;
586         }
587     }
588 #else
589   throw new java::lang::UnsupportedOperationException(JvNewStringLatin1("reflection not available in this build"));
590 #endif // USE_LIBFFI
591 }
592
593 // This is another version of _Jv_CallAnyMethodA, but this one does
594 // more checking and is used by the reflection (and not JNI) code.
595 jobject
596 _Jv_CallAnyMethodA (jobject obj,
597                     jclass return_type,
598                     jmethodID meth,
599                     jboolean is_constructor,
600                     JArray<jclass> *parameter_types,
601                     jobjectArray args,
602                     jclass iface)
603 {
604   if (parameter_types->length == 0 && args == NULL)
605     {
606       // The JDK accepts this, so we do too.
607     }
608   else if (parameter_types->length != args->length)
609     throw new java::lang::IllegalArgumentException;
610
611   int param_count = parameter_types->length;
612
613   jclass *paramelts = elements (parameter_types);
614   jobject *argelts = args == NULL ? NULL : elements (args);
615   jvalue argvals[param_count];
616
617 #define COPY(Where, What, Type) \
618   do { \
619     Type val = (What); \
620     memcpy ((Where), &val, sizeof (Type)); \
621   } while (0)
622
623   for (int i = 0; i < param_count; ++i)
624     {
625       jclass k = argelts[i] ? argelts[i]->getClass() : NULL;
626       if (paramelts[i]->isPrimitive())
627         {
628           if (! argelts[i]
629               || ! k
630               || ! can_widen (k, paramelts[i]))
631             throw new java::lang::IllegalArgumentException;
632             
633           if (paramelts[i] == JvPrimClass (boolean))
634             COPY (&argvals[i],
635                   ((java::lang::Boolean *) argelts[i])->booleanValue(),
636                   jboolean);
637           else if (paramelts[i] == JvPrimClass (char))
638             COPY (&argvals[i],
639                   ((java::lang::Character *) argelts[i])->charValue(),
640                   jchar);
641           else
642             {
643               java::lang::Number *num = (java::lang::Number *) argelts[i];
644               if (paramelts[i] == JvPrimClass (byte))
645                 COPY (&argvals[i], num->byteValue(), jbyte);
646               else if (paramelts[i] == JvPrimClass (short))
647                 COPY (&argvals[i], num->shortValue(), jshort);
648               else if (paramelts[i] == JvPrimClass (int))
649                 COPY (&argvals[i], num->intValue(), jint);
650               else if (paramelts[i] == JvPrimClass (long))
651                 COPY (&argvals[i], num->longValue(), jlong);
652               else if (paramelts[i] == JvPrimClass (float))
653                 COPY (&argvals[i], num->floatValue(), jfloat);
654               else if (paramelts[i] == JvPrimClass (double))
655                 COPY (&argvals[i], num->doubleValue(), jdouble);
656             }
657         }
658       else
659         {
660           if (argelts[i] && ! paramelts[i]->isAssignableFrom (k))
661             throw new java::lang::IllegalArgumentException;
662           COPY (&argvals[i], argelts[i], jobject);
663         }
664     }
665
666   jvalue ret_value;
667   _Jv_CallAnyMethodA (obj, return_type, meth, is_constructor,
668                       _Jv_isVirtualMethod (meth),
669                       parameter_types, argvals, &ret_value,
670                       false, iface);
671
672   jobject r;
673 #define VAL(Wrapper, Field)  (new Wrapper (ret_value.Field))
674   if (is_constructor)
675     r = ret_value.l;
676   else  if (return_type == JvPrimClass (byte))
677     r = VAL (java::lang::Byte, b);
678   else if (return_type == JvPrimClass (short))
679     r = VAL (java::lang::Short, s);
680   else if (return_type == JvPrimClass (int))
681     r = VAL (java::lang::Integer, i);
682   else if (return_type == JvPrimClass (long))
683     r = VAL (java::lang::Long, j);
684   else if (return_type == JvPrimClass (float))
685     r = VAL (java::lang::Float, f);
686   else if (return_type == JvPrimClass (double))
687     r = VAL (java::lang::Double, d);
688   else if (return_type == JvPrimClass (boolean))
689     r = VAL (java::lang::Boolean, z);
690   else if (return_type == JvPrimClass (char))
691     r = VAL (java::lang::Character, c);
692   else if (return_type == JvPrimClass (void))
693     r = NULL;
694   else
695     {
696       JvAssert (return_type == NULL || ! return_type->isPrimitive());
697       r = ret_value.l;
698     }
699
700   return r;
701 }