OSDN Git Service

Merged gcj-eclipse branch to trunk.
[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 (! (Modifier::isPublic (meth->accflags) || this->isAccessible()))
177     {
178       Class *caller = _Jv_StackTrace::GetCallingClass (&Method::class$);
179       if (! _Jv_CheckAccess(caller, declaringClass, meth->accflags))
180         throw new IllegalAccessException;
181     }
182
183   if (declaringClass->isInterface())
184     iface = declaringClass;
185   
186   return _Jv_CallAnyMethodA (obj, return_type, meth, false,
187                              parameter_types, args, iface);
188 }
189
190 jint
191 java::lang::reflect::Method::getModifiersInternal ()
192 {
193   return _Jv_FromReflectedMethod (this)->accflags;
194 }
195
196 jstring
197 java::lang::reflect::Method::getSignature()
198 {
199   return declaringClass->getReflectionSignature (this);
200 }
201
202 jobject
203 java::lang::reflect::Method::getDefaultValue()
204 {
205   return declaringClass->getMethodDefaultValue(this);
206 }
207
208 anno_a_t
209 java::lang::reflect::Method::getDeclaredAnnotationsInternal()
210 {
211   return (anno_a_t) declaringClass->getDeclaredAnnotations(this, false);
212 }
213
214 anno_aa_t
215 java::lang::reflect::Method::getParameterAnnotationsInternal()
216 {
217   return (anno_aa_t) declaringClass->getDeclaredAnnotations(this, true);
218 }
219
220 jstring
221 java::lang::reflect::Method::getName ()
222 {
223   if (name == NULL)
224     name = _Jv_NewStringUtf8Const (_Jv_FromReflectedMethod (this)->name);
225   return name;
226 }
227
228 /* Internal method to set return_type and parameter_types fields. */
229
230 void
231 java::lang::reflect::Method::getType ()
232 {
233   _Jv_Method *method = _Jv_FromReflectedMethod (this);
234   _Jv_GetTypesFromSignature (method,
235                              declaringClass,
236                              &parameter_types,
237                              &return_type);
238
239   int count = 0;
240   if (method->throws != NULL)
241     {
242       while (method->throws[count] != NULL)
243         ++count;
244     }
245
246   exception_types
247     = (JArray<jclass> *) JvNewObjectArray (count, &java::lang::Class::class$,
248                                            NULL);
249   jclass *elts = elements (exception_types);
250   for (int i = 0; i < count; ++i)
251     elts[i] = _Jv_FindClass (method->throws[i],
252                              declaringClass->getClassLoaderInternal ());
253 }
254
255 void
256 _Jv_GetTypesFromSignature (jmethodID method,
257                            jclass declaringClass,
258                            JArray<jclass> **arg_types_out,
259                            jclass *return_type_out)
260 {
261
262   _Jv_Utf8Const* sig = method->signature;
263   java::lang::ClassLoader *loader = declaringClass->getClassLoaderInternal();
264   char *ptr = sig->chars();
265   int numArgs = 0;
266   /* First just count the number of parameters. */
267   // FIXME: should do some validation here, e.g., that there is only
268   // one return type.
269   for (; ; ptr++)
270     {
271       switch (*ptr)
272         {
273         case 0:
274         case ')':
275         case 'V':
276           break;
277         case '[':
278         case '(':
279           continue;
280         case 'B':
281         case 'C':
282         case 'D':
283         case 'F':
284         case 'S':
285         case 'I':
286         case 'J':
287         case 'Z':
288           numArgs++;
289           continue;
290         case 'L':
291           numArgs++;
292           do 
293             ptr++;
294           while (*ptr != ';' && ptr[1] != '\0');
295           continue;
296         }
297       break;
298     }
299
300   JArray<jclass> *args = (JArray<jclass> *)
301     JvNewObjectArray (numArgs, &java::lang::Class::class$, NULL);
302   jclass* argPtr = elements (args);
303   for (ptr = sig->chars(); *ptr != '\0'; ptr++)
304     {
305       if (*ptr == '(')
306         continue;
307       if (*ptr == ')')
308         {
309           argPtr = return_type_out;
310           continue;
311         }
312
313       char *end_ptr;
314       jclass type = _Jv_FindClassFromSignature (ptr, loader, &end_ptr);
315       if (type == NULL)
316         // FIXME: This isn't ideal.
317         throw new java::lang::NoClassDefFoundError (sig->toString());
318
319       // ARGPTR can be NULL if we are processing the return value of a
320       // call from Constructor.
321       if (argPtr)
322         *argPtr++ = type;
323
324       ptr = end_ptr;
325     }
326   *arg_types_out = args;
327 }
328
329 // This is a very rough analog of the JNI CallNonvirtual<type>MethodA
330 // functions.  It handles both Methods and Constructors, and it can
331 // handle any return type.  In the Constructor case, the `obj'
332 // argument is unused and should be NULL; also, the `return_type' is
333 // the class that the constructor will construct.  RESULT is a pointer
334 // to a `jvalue' (see jni.h); for a void method this should be NULL.
335 // This function returns an exception (if one was thrown), or NULL if
336 // the call went ok.
337 void
338 _Jv_CallAnyMethodA (jobject obj,
339                     jclass return_type,
340                     jmethodID meth,
341                     jboolean is_constructor,
342                     jboolean is_virtual_call,
343                     JArray<jclass> *parameter_types,
344                     jvalue *args,
345                     jvalue *result,
346                     jboolean is_jni_call,
347                     jclass iface)
348 {
349   using namespace java::lang::reflect;
350   
351 #ifdef USE_LIBFFI
352   JvAssert (! is_constructor || ! obj);
353   JvAssert (! is_constructor || return_type);
354
355   // See whether call needs an object as the first argument.  A
356   // constructor does need a `this' argument, but it is one we create.
357   jboolean needs_this = false;
358   if (is_constructor
359       || ! Modifier::isStatic(meth->accflags))
360     needs_this = true;
361
362   int param_count = parameter_types->length;
363   if (needs_this)
364     ++param_count;
365
366   ffi_type *rtype;
367   // A constructor itself always returns void.
368   if (is_constructor || return_type == JvPrimClass (void))
369     rtype = &ffi_type_void;
370   else
371     rtype = get_ffi_type (return_type);
372   ffi_type **argtypes = (ffi_type **) __builtin_alloca (param_count
373                                                         * sizeof (ffi_type *));
374
375   jclass *paramelts = elements (parameter_types);
376
377   // Special case for the `this' argument of a constructor.  Note that
378   // the JDK 1.2 docs specify that the new object must be allocated
379   // before argument conversions are done.
380   if (is_constructor)
381     obj = _Jv_AllocObject (return_type);
382
383   const int size_per_arg = sizeof(jvalue);
384   ffi_cif cif;
385
386   char *p = (char *) __builtin_alloca (param_count * size_per_arg);
387                 // Overallocate to get correct alignment.
388   void **values = (void **)
389                         __builtin_alloca (param_count * sizeof (void *));
390
391   int i = 0;
392   if (needs_this)
393     {
394       // The `NULL' type is `Object'.
395       argtypes[i] = get_ffi_type (NULL);
396       values[i] = p;
397       memcpy (p, &obj, sizeof (jobject));
398       p += size_per_arg;
399       ++i;
400     }
401
402   for (int arg = 0; i < param_count; ++i, ++arg)
403     {
404       int tsize;
405
406       argtypes[i] = get_ffi_type (paramelts[arg]);
407       if (paramelts[arg]->isPrimitive())
408         tsize = paramelts[arg]->size();
409       else
410         tsize = sizeof (jobject);
411
412       // Copy appropriate bits from the jvalue into the ffi array.
413       // FIXME: we could do this copying all in one loop, above, by
414       // over-allocating a bit.
415       // How do we do this without breaking big-endian platforms?
416       values[i] = p;
417       memcpy (p, &args[arg], tsize);
418       p += size_per_arg;
419     }
420
421   if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, param_count,
422                     rtype, argtypes) != FFI_OK)
423     throw new java::lang::VirtualMachineError(JvNewStringLatin1("internal error: ffi_prep_cif failed"));
424
425   using namespace java::lang;
426   using namespace java::lang::reflect;
427
428   union
429   {
430     ffi_arg i;
431     jobject o;
432     jlong l;
433     jfloat f;
434     jdouble d;
435   } ffi_result;
436
437   switch (rtype->type)
438     {
439     case FFI_TYPE_VOID:
440       break;
441     case FFI_TYPE_SINT8:
442       result->b = 0;
443       break;
444     case FFI_TYPE_SINT16:
445       result->s = 0;
446       break;
447     case FFI_TYPE_UINT16:
448       result->c = 0;
449       break;
450     case FFI_TYPE_SINT32:
451       result->i = 0;
452       break;
453     case FFI_TYPE_SINT64:
454       result->j = 0;
455       break;
456     case FFI_TYPE_FLOAT:
457       result->f = 0;
458       break;
459     case FFI_TYPE_DOUBLE:
460       result->d = 0;
461       break;
462     case FFI_TYPE_POINTER:
463       result->l = 0;
464       break;
465     default:
466       JvFail ("Unknown ffi_call return type");
467       break;
468     }
469
470   void *ncode;
471
472   // FIXME: If a vtable index is -1 at this point it is invalid, so we
473   // have to use the ncode.  
474   //
475   // This can happen because methods in final classes don't have
476   // vtable entries, but _Jv_isVirtualMethod() doesn't know that.  We
477   // could solve this problem by allocating a vtable index for methods
478   // in final classes.
479   if (is_virtual_call 
480       && ! Modifier::isFinal (meth->accflags)
481       && (_Jv_ushort)-1 != meth->index)
482     {
483       _Jv_VTable *vtable = *(_Jv_VTable **) obj;
484       if (iface == NULL)
485         {
486           if (is_jni_call && Modifier::isAbstract (meth->accflags))
487             {
488               // With JNI we don't know if this is an interface call
489               // or a call to an abstract method.  Look up the method
490               // by name, the slow way.
491               _Jv_Method *concrete_meth
492                 = _Jv_LookupDeclaredMethod (vtable->clas,
493                                             meth->name,
494                                             meth->signature,
495                                             NULL);
496               if (concrete_meth == NULL
497                   || concrete_meth->ncode == NULL
498                   || Modifier::isAbstract(concrete_meth->accflags))
499                 throw new java::lang::IncompatibleClassChangeError
500                   (_Jv_GetMethodString (vtable->clas, meth));
501               ncode = concrete_meth->ncode;
502             }
503           else
504             ncode = vtable->get_method (meth->index);
505         }
506       else
507         ncode = _Jv_LookupInterfaceMethodIdx (vtable->clas, iface,
508                                               meth->index);
509     }
510   else
511     {
512       ncode = meth->ncode;
513     }
514
515   try
516     {
517       ffi_call (&cif, (void (*)()) ncode, &ffi_result, values);
518     }
519   catch (Throwable *ex)
520     {
521       // For JNI we just throw the real error.  For reflection, we
522       // wrap the underlying method's exception in an
523       // InvocationTargetException.
524       if (! is_jni_call)
525         ex = new InvocationTargetException (ex);
526       throw ex;
527     }
528
529   // Since ffi_call returns integer values promoted to a word, use
530   // a narrowing conversion for jbyte, jchar, etc. results.
531   // Note that boolean is handled either by the FFI_TYPE_SINT8 or
532   // FFI_TYPE_SINT32 case.
533   if (is_constructor)
534     result->l = obj;
535   else
536     {
537       switch (rtype->type)
538         {
539         case FFI_TYPE_VOID:
540           break;
541         case FFI_TYPE_SINT8:
542           result->b = (jbyte)ffi_result.i;
543           break;
544         case FFI_TYPE_SINT16:
545           result->s = (jshort)ffi_result.i;
546           break;
547         case FFI_TYPE_UINT16:
548           result->c = (jchar)ffi_result.i;
549           break;
550         case FFI_TYPE_SINT32:
551           result->i = (jint)ffi_result.i;
552           break;
553         case FFI_TYPE_SINT64:
554           result->j = (jlong)ffi_result.l;
555           break;
556         case FFI_TYPE_FLOAT:
557           result->f = (jfloat)ffi_result.f;
558           break;
559         case FFI_TYPE_DOUBLE:
560           result->d = (jdouble)ffi_result.d;
561           break;
562         case FFI_TYPE_POINTER:
563           result->l = (jobject)ffi_result.o;
564           break;
565         default:
566           JvFail ("Unknown ffi_call return type");
567           break;
568         }
569     }
570 #else
571   throw new java::lang::UnsupportedOperationException(JvNewStringLatin1("reflection not available in this build"));
572 #endif // USE_LIBFFI
573 }
574
575 // This is another version of _Jv_CallAnyMethodA, but this one does
576 // more checking and is used by the reflection (and not JNI) code.
577 jobject
578 _Jv_CallAnyMethodA (jobject obj,
579                     jclass return_type,
580                     jmethodID meth,
581                     jboolean is_constructor,
582                     JArray<jclass> *parameter_types,
583                     jobjectArray args,
584                     jclass iface)
585 {
586   if (parameter_types->length == 0 && args == NULL)
587     {
588       // The JDK accepts this, so we do too.
589     }
590   else if (parameter_types->length != args->length)
591     throw new java::lang::IllegalArgumentException;
592
593   int param_count = parameter_types->length;
594
595   jclass *paramelts = elements (parameter_types);
596   jobject *argelts = args == NULL ? NULL : elements (args);
597   jvalue argvals[param_count];
598
599 #define COPY(Where, What, Type) \
600   do { \
601     Type val = (What); \
602     memcpy ((Where), &val, sizeof (Type)); \
603   } while (0)
604
605   for (int i = 0; i < param_count; ++i)
606     {
607       jclass k = argelts[i] ? argelts[i]->getClass() : NULL;
608       if (paramelts[i]->isPrimitive())
609         {
610           if (! argelts[i]
611               || ! k
612               || ! can_widen (k, paramelts[i]))
613             throw new java::lang::IllegalArgumentException;
614             
615           if (paramelts[i] == JvPrimClass (boolean))
616             COPY (&argvals[i],
617                   ((java::lang::Boolean *) argelts[i])->booleanValue(),
618                   jboolean);
619           else if (paramelts[i] == JvPrimClass (char))
620             COPY (&argvals[i],
621                   ((java::lang::Character *) argelts[i])->charValue(),
622                   jchar);
623           else
624             {
625               java::lang::Number *num = (java::lang::Number *) argelts[i];
626               if (paramelts[i] == JvPrimClass (byte))
627                 COPY (&argvals[i], num->byteValue(), jbyte);
628               else if (paramelts[i] == JvPrimClass (short))
629                 COPY (&argvals[i], num->shortValue(), jshort);
630               else if (paramelts[i] == JvPrimClass (int))
631                 COPY (&argvals[i], num->intValue(), jint);
632               else if (paramelts[i] == JvPrimClass (long))
633                 COPY (&argvals[i], num->longValue(), jlong);
634               else if (paramelts[i] == JvPrimClass (float))
635                 COPY (&argvals[i], num->floatValue(), jfloat);
636               else if (paramelts[i] == JvPrimClass (double))
637                 COPY (&argvals[i], num->doubleValue(), jdouble);
638             }
639         }
640       else
641         {
642           if (argelts[i] && ! paramelts[i]->isAssignableFrom (k))
643             throw new java::lang::IllegalArgumentException;
644           COPY (&argvals[i], argelts[i], jobject);
645         }
646     }
647
648   jvalue ret_value;
649   _Jv_CallAnyMethodA (obj, return_type, meth, is_constructor,
650                       _Jv_isVirtualMethod (meth),
651                       parameter_types, argvals, &ret_value,
652                       false, iface);
653
654   jobject r;
655 #define VAL(Wrapper, Field)  (new Wrapper (ret_value.Field))
656   if (is_constructor)
657     r = ret_value.l;
658   else  if (return_type == JvPrimClass (byte))
659     r = VAL (java::lang::Byte, b);
660   else if (return_type == JvPrimClass (short))
661     r = VAL (java::lang::Short, s);
662   else if (return_type == JvPrimClass (int))
663     r = VAL (java::lang::Integer, i);
664   else if (return_type == JvPrimClass (long))
665     r = VAL (java::lang::Long, j);
666   else if (return_type == JvPrimClass (float))
667     r = VAL (java::lang::Float, f);
668   else if (return_type == JvPrimClass (double))
669     r = VAL (java::lang::Double, d);
670   else if (return_type == JvPrimClass (boolean))
671     r = VAL (java::lang::Boolean, z);
672   else if (return_type == JvPrimClass (char))
673     r = VAL (java::lang::Character, c);
674   else if (return_type == JvPrimClass (void))
675     r = NULL;
676   else
677     {
678       JvAssert (return_type == NULL || ! return_type->isPrimitive());
679       r = ret_value.l;
680     }
681
682   return r;
683 }