natVMProxy.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. // natVMProxy.cc -- Implementation of VMProxy methods.
  2. /* Copyright (C) 2006, 2007
  3. Free Software Foundation
  4. This file is part of libgcj.
  5. This software is copyrighted work licensed under the terms of the
  6. Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
  7. details. */
  8. // The idea of behind this code is to utilize libffi's ability to
  9. // create closures to provide a fast "cut-through" way to generate
  10. // proxy classes. Instead of generating bytecode and then
  11. // interpreting that, we copy the method definitions for each of the
  12. // methods we're supposed to be prxying and generate a libffi closure
  13. // for each one.
  14. #include <config.h>
  15. #include <platform.h>
  16. #include <sysdep/descriptor.h>
  17. #include <limits.h>
  18. #include <string.h>
  19. #include <stddef.h>
  20. #include <stdio.h>
  21. #include <gcj/cni.h>
  22. #include <gcj/javaprims.h>
  23. #include <jvm.h>
  24. #include <jni.h>
  25. #include <java-threads.h>
  26. #include <java-interp.h>
  27. #include <ffi.h>
  28. #include <execution.h>
  29. #include <gcj/method.h>
  30. #include <gnu/gcj/runtime/BootClassLoader.h>
  31. #include <java/lang/Class.h>
  32. #include <java/lang/ClassCastException.h>
  33. #include <java/lang/Error.h>
  34. #include <java/lang/IllegalArgumentException.h>
  35. #include <java/lang/Integer.h>
  36. #include <java/lang/StringBuffer.h>
  37. #include <java/lang/UnsupportedOperationException.h>
  38. #include <java/lang/VMClassLoader.h>
  39. #include <java/lang/VMCompiler.h>
  40. #include <java/lang/reflect/InvocationHandler.h>
  41. #include <java/lang/reflect/Method.h>
  42. #include <java/lang/reflect/Proxy$ClassFactory.h>
  43. #include <java/lang/reflect/Proxy$ProxyData.h>
  44. #include <java/lang/reflect/Proxy.h>
  45. #include <java/lang/reflect/UndeclaredThrowableException.h>
  46. #include <java/lang/reflect/VMProxy.h>
  47. #include <java/lang/Byte.h>
  48. #include <java/lang/Short.h>
  49. #include <java/lang/Integer.h>
  50. #include <java/lang/Long.h>
  51. #include <java/lang/Float.h>
  52. #include <java/lang/Double.h>
  53. #include <java/lang/Boolean.h>
  54. #include <java/lang/Character.h>
  55. using namespace java::lang::reflect;
  56. using namespace java::lang;
  57. #ifndef INTERPRETER
  58. jclass
  59. java::lang::reflect::VMProxy::generateProxyClass
  60. (ClassLoader *, Proxy$ProxyData *)
  61. {
  62. throw new UnsupportedOperationException (
  63. JvNewStringLatin1 ("Interpreter not available"));
  64. }
  65. #else
  66. typedef void (*closure_fun) (ffi_cif*, void*, void**, void*);
  67. static void *ncode (int method_index, jclass klass, _Jv_Method *self, closure_fun fun);
  68. static void run_proxy (ffi_cif*, void*, void**, void*);
  69. typedef jobject
  70. #if defined (X86_WIN32) && !defined (__CYGWIN__)
  71. __attribute__ ((thiscall))
  72. #endif
  73. invoke_t (jobject, Proxy *, Method *, JArray< jobject > *);
  74. // True if pc points to a proxy frame.
  75. bool
  76. _Jv_is_proxy (void *pc)
  77. {
  78. return pc == UNWRAP_FUNCTION_DESCRIPTOR ((void*)&run_proxy);
  79. }
  80. // Generate a proxy class by using libffi closures for each entry
  81. // point.
  82. jclass
  83. java::lang::reflect::VMProxy::generateProxyClass
  84. (ClassLoader *loader, Proxy$ProxyData *d)
  85. {
  86. // If we're precompiling, generate bytecode and allow VMCompiler to
  87. // precompile it.
  88. if (VMCompiler::precompiles ())
  89. return (new Proxy$ClassFactory(d))->generate(loader);
  90. jclass klass = new Class ();
  91. // Synchronize on the class, so that it is not attempted initialized
  92. // until we're done.
  93. JvSynchronize sync (klass);
  94. klass->superclass = &Proxy::class$;
  95. klass->engine = &_Jv_soleIndirectCompiledEngine;
  96. klass->size_in_bytes = -1;
  97. klass->vtable_method_count = -1;
  98. // Declare private static transient java.lang.reflect.Method[] $Proxy0.m
  99. klass->field_count = klass->static_field_count = 1;
  100. klass->fields = (_Jv_Field*)_Jv_AllocRawObj (sizeof (_Jv_Field));
  101. klass->fields[0].name = _Jv_makeUtf8Const ("m");
  102. klass->fields[0].type = d->methods->getClass();
  103. klass->fields[0].flags = (Modifier::PRIVATE | Modifier::STATIC
  104. | Modifier::TRANSIENT);
  105. // Record the defining loader. For the bootstrap class loader,
  106. // we record NULL.
  107. if (loader != VMClassLoader::bootLoader)
  108. klass->loader = loader;
  109. {
  110. StringBuffer *sb = new StringBuffer();
  111. sb->append(JvNewStringLatin1 ("$Proxy"));
  112. sb->append(Integer::toString (d->id));
  113. klass->name = _Jv_makeUtf8Const (sb->toString());
  114. }
  115. // Allocate space for the interfaces.
  116. klass->interface_count = d->interfaces->length;
  117. klass->interfaces = (jclass*) _Jv_AllocRawObj (klass->interface_count
  118. *sizeof (jclass));
  119. for (int i = 0; i < klass->interface_count; i++)
  120. klass->interfaces[i] = elements(d->interfaces)[i];
  121. size_t count = d->methods->length;
  122. {
  123. size_t total_count = count + Proxy::class$.method_count + 1;
  124. if (total_count >= 65536)
  125. throw new IllegalArgumentException ();
  126. // Allocate space for the methods. This is a worst case
  127. // estimate.
  128. klass->methods
  129. = (_Jv_Method *) _Jv_AllocRawObj (sizeof (_Jv_Method)
  130. * total_count);
  131. }
  132. jshort &method_count = klass->method_count;
  133. // Copy all reachable methods from Proxy.
  134. for (int i = 0; i < Proxy::class$.method_count; i++)
  135. {
  136. if (_Jv_CheckAccess (klass, &Proxy::class$,
  137. Proxy::class$.methods[i].accflags))
  138. {
  139. klass->methods[method_count] = Proxy::class$.methods[i];
  140. method_count++;
  141. }
  142. }
  143. _Jv_Method *init_method
  144. = (_Jv_Linker::search_method_in_class
  145. (klass, klass,
  146. _Jv_makeUtf8Const ("<init>"),
  147. _Jv_makeUtf8Const ("(Ljava.lang.reflect.InvocationHandler;)V"),
  148. false));
  149. init_method->accflags |= Modifier::PUBLIC;
  150. // Create the methods for all of the interfaces.
  151. for (size_t i = 0; i < count; i++)
  152. {
  153. _Jv_Method &method = klass->methods[method_count++];
  154. const _Jv_Method &imethod
  155. = *_Jv_FromReflectedMethod (elements(d->methods)[i]);
  156. // We use a shallow copy of IMETHOD rather than a deep copy;
  157. // this means that the pointer fields of METHOD point into the
  158. // interface. As long as this subclass of Proxy is reachable,
  159. // the interfaces of which it is a proxy will also be reachable,
  160. // so this is safe.
  161. method = imethod;
  162. method.ncode = ncode (i, klass, &method, run_proxy);
  163. method.accflags &= ~Modifier::ABSTRACT;
  164. }
  165. _Jv_Linker::layout_vtable_methods (klass);
  166. _Jv_RegisterInitiatingLoader (klass, klass->loader);
  167. // Set $Proxy0.m to point to the methods arrray
  168. java::lang::reflect::Field *f
  169. = klass->getDeclaredField (JvNewStringLatin1 ("m"));
  170. f->flag = true;
  171. f->set(NULL, d->methods);
  172. return klass;
  173. }
  174. // Box things with primitive types.
  175. static inline jobject
  176. box (void *thing, jclass klass, FFI_TYPE type)
  177. {
  178. jobject o;
  179. switch (type)
  180. {
  181. case FFI_TYPE_VOID:
  182. return NULL;
  183. case FFI_TYPE_POINTER:
  184. o = *(jobject*)thing;
  185. return o;
  186. default:
  187. ;
  188. }
  189. if (klass == JvPrimClass (byte))
  190. o = new Byte (*(jbyte*)thing);
  191. else if (klass == JvPrimClass (short))
  192. o = new Short (*(jshort*)thing);
  193. else if (klass == JvPrimClass (int))
  194. o = new Integer (*(jint*)thing);
  195. else if (klass == JvPrimClass (long))
  196. o = new Long (*(jlong*)thing);
  197. else if (klass == JvPrimClass (float))
  198. o = new Float (*(jfloat*)thing);
  199. else if (klass == JvPrimClass (double))
  200. o = new Double (*(jdouble*)thing);
  201. else if (klass == JvPrimClass (boolean))
  202. o = new Boolean (*(jboolean*)thing);
  203. else if (klass == JvPrimClass (char))
  204. o = new Character (*(jchar*)thing);
  205. else
  206. JvFail ("Bad ffi type in proxy");
  207. return o;
  208. }
  209. // Unbox things with primitive types.
  210. static inline void
  211. unbox (jobject o, jclass klass, void *rvalue, FFI_TYPE type)
  212. {
  213. switch (type)
  214. {
  215. case FFI_TYPE_VOID:
  216. return;
  217. case FFI_TYPE_POINTER:
  218. _Jv_CheckCast (klass, o);
  219. *(jobject*)rvalue = o;
  220. return;
  221. default:
  222. ;
  223. }
  224. // If the value returned ... is null and the interface method's
  225. // return type is primitive, then a NullPointerException will be
  226. // thrown ...
  227. if (klass == JvPrimClass (byte))
  228. {
  229. _Jv_CheckCast (&Byte::class$, o);
  230. *(jbyte*)rvalue = ((Byte*)o)->byteValue();
  231. }
  232. else if (klass == JvPrimClass (short))
  233. {
  234. _Jv_CheckCast (&Short::class$, o);
  235. *(jshort*)rvalue = ((Short*)o)->shortValue();
  236. }
  237. else if (klass == JvPrimClass (int))
  238. {
  239. _Jv_CheckCast (&Integer::class$, o);
  240. *(jint*)rvalue = ((Integer*)o)->intValue();
  241. }
  242. else if (klass == JvPrimClass (long))
  243. {
  244. _Jv_CheckCast (&Long::class$, o);
  245. *(jlong*)rvalue = ((Long*)o)->longValue();
  246. }
  247. else if (klass == JvPrimClass (float))
  248. {
  249. _Jv_CheckCast (&Float::class$, o);
  250. *(jfloat*)rvalue = ((Float*)o)->floatValue();
  251. }
  252. else if (klass == JvPrimClass (double))
  253. {
  254. _Jv_CheckCast (&Double::class$, o);
  255. *(jdouble*)rvalue = ((Double*)o)->doubleValue();
  256. }
  257. else if (klass == JvPrimClass (boolean))
  258. {
  259. _Jv_CheckCast (&Boolean::class$, o);
  260. *(jboolean*)rvalue = ((Boolean*)o)->booleanValue();
  261. }
  262. else if (klass == JvPrimClass (char))
  263. {
  264. _Jv_CheckCast (&Character::class$, o);
  265. *(jchar*)rvalue = ((Character*)o)->charValue();
  266. }
  267. else
  268. JvFail ("Bad ffi type in proxy");
  269. }
  270. // _Jv_getFieldInternal is declared as a friend of reflect.Field in
  271. // libjava/headers.txt. This gives us a way to call the private
  272. // method Field.get (Class caller, Object obj).
  273. extern inline jobject
  274. _Jv_getFieldInternal (java::lang::reflect::Field *f, jclass c, jobject o)
  275. {
  276. return f->get(c, o);
  277. }
  278. // run_proxy is the entry point for all proxy methods. It boxes up
  279. // all the arguments and then invokes the invocation handler's invoke()
  280. // method. Exceptions are caught and propagated.
  281. typedef struct {
  282. ffi_closure closure;
  283. _Jv_ClosureList list;
  284. ffi_cif cif;
  285. _Jv_Method *self;
  286. int method_index;
  287. ffi_type *arg_types[0];
  288. } ncode_closure;
  289. static void
  290. run_proxy (ffi_cif *cif,
  291. void *rvalue,
  292. void **args,
  293. void*user_data)
  294. {
  295. using namespace java::lang::reflect;
  296. Proxy *proxy = *(Proxy**)args[0];
  297. ncode_closure *self = (ncode_closure *) user_data;
  298. jclass proxyClass = proxy->getClass();
  299. // FRAME_DESC registers this particular invocation as the top-most
  300. // interpreter frame. This lets the stack tracing code (for
  301. // Throwable) print information about the Proxy being run rather
  302. // than about Proxy.class itself. FRAME_DESC has a destructor so it
  303. // cleans up automatically when this proxy invocation returns.
  304. Thread *thread = Thread::currentThread();
  305. _Jv_InterpFrame frame_desc (self->self, thread, proxyClass,
  306. NULL, frame_proxy);
  307. // The method to invoke is saved in $Proxy0.m[method_index].
  308. // FIXME: We could somewhat improve efficiency by storing a pointer
  309. // to the method (rather than its index) in ncode_closure. This
  310. // would avoid the lookup, but it probably wouldn't make a huge
  311. // difference. We'd still have to save the method array because
  312. // ncode structs are not scanned by the gc.
  313. Field *f = proxyClass->getDeclaredField (JvNewStringLatin1 ("m"));
  314. JArray<Method*> *methods
  315. = (JArray<Method*>*)_Jv_getFieldInternal (f, proxyClass, NULL);
  316. Method *meth = elements(methods)[self->method_index];
  317. JArray<jclass> *parameter_types = meth->internalGetParameterTypes ();
  318. JArray<jclass> *exception_types = meth->internalGetExceptionTypes ();
  319. InvocationHandler *handler = proxy->h;
  320. JArray<jobject> *argsArray = NULL;
  321. jobject *jargs = NULL;
  322. if (parameter_types->length)
  323. {
  324. void *poo
  325. = _Jv_NewObjectArray (parameter_types->length, &Object::class$, NULL);
  326. argsArray = (JArray<jobject> *) poo;
  327. jargs = elements(argsArray);
  328. }
  329. // FIXME: It must be possible to use fast interface dispatch here,
  330. // but I've not quite figured out how to do it.
  331. invoke_t *invoke
  332. = (invoke_t *)(_Jv_LookupInterfaceMethod
  333. (handler->getClass (),
  334. _Jv_makeUtf8Const ("invoke"),
  335. (_Jv_makeUtf8Const
  336. ("(Ljava.lang.Object;Ljava.lang.reflect.Method;[Ljava.lang.Object;)"
  337. "Ljava.lang.Object;"))));
  338. // Copy and box all the args.
  339. int index = 1;
  340. for (int i = 0; i < parameter_types->length; i++, index++)
  341. jargs[i] = box (args[index], elements(parameter_types)[i],
  342. cif->arg_types[index]->type);
  343. jobject ret;
  344. try
  345. {
  346. ret = invoke (handler, proxy, meth, argsArray);
  347. }
  348. catch (Throwable *t)
  349. {
  350. if (_Jv_IsInstanceOf (t, &RuntimeException::class$)
  351. || _Jv_IsInstanceOf (t, &Error::class$))
  352. throw t;
  353. Class **throwables = elements (exception_types);
  354. for (int i = 0; i < exception_types->length; i++)
  355. if (_Jv_IsInstanceOf (t, throwables[i]))
  356. throw t;
  357. throw new UndeclaredThrowableException (t);
  358. }
  359. unbox (ret, meth->return_type, rvalue, cif->rtype->type);
  360. }
  361. // Given a method and a closure function, create libffi CIF and return
  362. // the address of its closure.
  363. static void *
  364. ncode (int method_index, jclass klass, _Jv_Method *self, closure_fun fun)
  365. {
  366. using namespace java::lang::reflect;
  367. jboolean staticp = (self->accflags & Modifier::STATIC) != 0;
  368. int arg_count = _Jv_count_arguments (self->signature, staticp);
  369. void *code;
  370. ncode_closure *closure =
  371. (ncode_closure*)ffi_closure_alloc (sizeof (ncode_closure)
  372. + arg_count * sizeof (ffi_type*),
  373. &code);
  374. closure->method_index = method_index;
  375. closure->list.registerClosure (klass, closure);
  376. _Jv_init_cif (self->signature,
  377. arg_count,
  378. staticp,
  379. &closure->cif,
  380. &closure->arg_types[0],
  381. NULL);
  382. closure->self = self;
  383. JvAssert ((self->accflags & Modifier::NATIVE) == 0);
  384. ffi_prep_closure_loc (&closure->closure,
  385. &closure->cif,
  386. fun,
  387. code,
  388. code);
  389. self->ncode = code;
  390. return self->ncode;
  391. }
  392. #endif // INTERPRETER