* src/vm/suck.c (vm/vm.h): Added.
[cacao.git] / src / native / native.c
1 /* src/native/native.c - table of native functions
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Reinhard Grafl
28             Roman Obermaisser
29             Andreas Krall
30
31    Changes: Christian Thalinger
32
33    $Id: native.c 5810 2006-10-20 13:54:54Z twisti $
34
35 */
36
37
38 #include "config.h"
39
40 #include <assert.h>
41 #include <ctype.h>
42
43 #if !defined(WITH_STATIC_CLASSPATH)
44 # include <ltdl.h>
45 #endif
46
47 #include "vm/types.h"
48
49 #include "mm/memory.h"
50 #include "native/jni.h"
51 #include "native/native.h"
52 #include "native/include/java_lang_Throwable.h"
53
54 #if defined(ENABLE_THREADS)
55 # include "threads/native/lock.h"
56 #else
57 # include "threads/none/lock.h"
58 #endif
59
60 #include "toolbox/logging.h"
61 #include "vm/builtin.h"
62 #include "vm/exceptions.h"
63 #include "vm/global.h"
64 #include "vm/hashtable.h"
65 #include "vm/loader.h"
66 #include "vm/options.h"
67 #include "vm/resolve.h"
68 #include "vm/stringlocal.h"
69 #include "vm/vm.h"
70 #include "vm/jit/asmpart.h"
71 #include "vm/jit/jit.h"
72
73 #if defined(ENABLE_JVMTI)
74 #include "native/jvmti/cacaodbg.h"
75 #endif
76
77
78 /* include table of native functions ******************************************/
79
80 #include "native/include/java_lang_Cloneable.h"
81 #include "native/include/java_util_Properties.h"
82 #include "native/include/java_io_InputStream.h"
83 #include "native/include/java_io_PrintStream.h"
84
85 #include "native/include/gnu_classpath_VMStackWalker.h"
86 #include "native/include/gnu_classpath_VMSystemProperties.h"
87 #include "native/include/gnu_java_lang_management_VMClassLoadingMXBeanImpl.h"
88 #include "native/include/gnu_java_lang_management_VMMemoryMXBeanImpl.h"
89 #include "native/include/gnu_java_lang_management_VMRuntimeMXBeanImpl.h"
90 #include "native/include/java_lang_Class.h"
91 #include "native/include/java_lang_Object.h"
92 #include "native/include/java_lang_VMClass.h"
93 #include "native/include/java_lang_VMClassLoader.h"
94 #include "native/include/java_lang_VMObject.h"
95 #include "native/include/java_lang_VMRuntime.h"
96 #include "native/include/java_lang_VMString.h"
97 #include "native/include/java_lang_VMSystem.h"
98 #include "native/include/java_lang_VMThread.h"
99 #include "native/include/java_lang_VMThrowable.h"
100 #include "native/include/java_lang_management_VMManagementFactory.h"
101 #include "native/include/java_lang_reflect_Constructor.h"
102 #include "native/include/java_lang_reflect_Field.h"
103 #include "native/include/java_lang_reflect_Method.h"
104 #include "native/include/java_lang_reflect_VMProxy.h"
105 #include "native/include/java_security_VMAccessController.h"
106
107 #if defined(ENABLE_JVMTI)
108 #include "native/include/gnu_classpath_jdwp_event_EventRequest.h"
109 #include "native/include/java_nio_ByteBuffer.h"
110 #include "native/include/gnu_classpath_jdwp_VMVirtualMachine.h"
111 #include "native/include/gnu_classpath_jdwp_VMFrame.h"
112 #include "native/include/gnu_classpath_jdwp_VMMethod.h"
113 #endif
114
115 #if defined(WITH_STATIC_CLASSPATH)
116
117 /* these are required to prevent compiler warnings */
118
119 #include "native/include/java_net_DatagramPacket.h"
120 #include "native/include/java_net_InetAddress.h"
121 #include "native/include/java_net_SocketImpl.h"
122
123 #include "native/include/gnu_java_net_PlainDatagramSocketImpl.h"
124 #include "native/include/gnu_java_net_PlainSocketImpl.h"
125 #include "native/include/gnu_java_nio_PipeImpl.h"
126 #include "native/include/gnu_java_nio_channels_FileChannelImpl.h"
127 #include "native/include/gnu_java_nio_charset_iconv_IconvEncoder.h"
128 #include "native/include/gnu_java_nio_charset_iconv_IconvDecoder.h"
129 #include "native/include/java_lang_VMProcess.h"
130 #include "native/include/java_nio_MappedByteBufferImpl.h"
131 #include "native/include/java_nio_channels_spi_SelectorProvider.h"
132
133 /* now include the native table */
134
135 #include "native/nativetable.inc"
136
137 #elif !defined(ENABLE_LIBJVM)
138
139 /* dummynativetable ************************************************************
140
141    Ensure that symbols for functions implemented within CACAO are used
142    and exported to dlopen.
143
144    ATTENTION: Don't make this table static!!!  Otherwise the compiler
145    may optimize it away!
146
147 *******************************************************************************/
148
149 functionptr dummynativetable[] = {
150         (functionptr) Java_gnu_classpath_VMStackWalker_getClassContext,
151         (functionptr) Java_gnu_classpath_VMStackWalker_getCallingClass,
152         (functionptr) Java_gnu_classpath_VMStackWalker_getCallingClassLoader,
153         (functionptr) Java_gnu_classpath_VMStackWalker_firstNonNullClassLoader,
154
155         (functionptr) Java_gnu_classpath_VMSystemProperties_preInit,
156
157         (functionptr) Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getLoadedClassCount,
158         (functionptr) Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getUnloadedClassCount,
159         (functionptr) Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_isVerbose,
160         (functionptr) Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_setVerbose,
161
162         (functionptr) Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getHeapMemoryUsage,
163         (functionptr) Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getNonHeapMemoryUsage,
164         (functionptr) Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getObjectPendingFinalizationCount,
165         (functionptr) Java_gnu_java_lang_management_VMMemoryMXBeanImpl_isVerbose,
166         (functionptr) Java_gnu_java_lang_management_VMMemoryMXBeanImpl_setVerbose,
167
168         (functionptr) Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getInputArguments,
169         (functionptr) Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getStartTime,
170
171         (functionptr) Java_java_lang_VMClass_isInstance,
172         (functionptr) Java_java_lang_VMClass_isAssignableFrom,
173         (functionptr) Java_java_lang_VMClass_isInterface,
174         (functionptr) Java_java_lang_VMClass_isPrimitive,
175         (functionptr) Java_java_lang_VMClass_getName,
176         (functionptr) Java_java_lang_VMClass_getSuperclass,
177         (functionptr) Java_java_lang_VMClass_getInterfaces,
178         (functionptr) Java_java_lang_VMClass_getComponentType,
179         (functionptr) Java_java_lang_VMClass_getModifiers,
180         (functionptr) Java_java_lang_VMClass_getDeclaringClass,
181         (functionptr) Java_java_lang_VMClass_getDeclaredClasses,
182         (functionptr) Java_java_lang_VMClass_getDeclaredFields,
183         (functionptr) Java_java_lang_VMClass_getDeclaredMethods,
184         (functionptr) Java_java_lang_VMClass_getDeclaredConstructors,
185         (functionptr) Java_java_lang_VMClass_getClassLoader,
186         (functionptr) Java_java_lang_VMClass_forName,
187         (functionptr) Java_java_lang_VMClass_isArray,
188         (functionptr) Java_java_lang_VMClass_throwException,
189
190         (functionptr) Java_java_lang_VMClassLoader_defineClass,
191         (functionptr) Java_java_lang_VMClassLoader_resolveClass,
192         (functionptr) Java_java_lang_VMClassLoader_loadClass,
193         (functionptr) Java_java_lang_VMClassLoader_getPrimitiveClass,
194         (functionptr) Java_java_lang_VMClassLoader_nativeGetResources,
195         (functionptr) Java_java_lang_VMClassLoader_findLoadedClass,
196
197         (functionptr) Java_java_lang_VMObject_getClass,
198         (functionptr) Java_java_lang_VMObject_clone,
199         (functionptr) Java_java_lang_VMObject_notify,
200         (functionptr) Java_java_lang_VMObject_notifyAll,
201         (functionptr) Java_java_lang_VMObject_wait,
202
203         (functionptr) Java_java_lang_VMRuntime_availableProcessors,
204         (functionptr) Java_java_lang_VMRuntime_freeMemory,
205         (functionptr) Java_java_lang_VMRuntime_totalMemory,
206         (functionptr) Java_java_lang_VMRuntime_maxMemory,
207         (functionptr) Java_java_lang_VMRuntime_gc,
208         (functionptr) Java_java_lang_VMRuntime_runFinalization,
209         (functionptr) Java_java_lang_VMRuntime_runFinalizationForExit,
210         (functionptr) Java_java_lang_VMRuntime_traceInstructions,
211         (functionptr) Java_java_lang_VMRuntime_traceMethodCalls,
212         (functionptr) Java_java_lang_VMRuntime_runFinalizersOnExit,
213         (functionptr) Java_java_lang_VMRuntime_exit,
214         (functionptr) Java_java_lang_VMRuntime_nativeLoad,
215         (functionptr) Java_java_lang_VMRuntime_mapLibraryName,
216
217         (functionptr) Java_java_lang_VMString_intern,
218
219         (functionptr) Java_java_lang_VMSystem_arraycopy,
220         (functionptr) Java_java_lang_VMSystem_identityHashCode,
221
222         (functionptr) Java_java_lang_VMThread_start,
223         (functionptr) Java_java_lang_VMThread_interrupt,
224         (functionptr) Java_java_lang_VMThread_isInterrupted,
225         (functionptr) Java_java_lang_VMThread_suspend,
226         (functionptr) Java_java_lang_VMThread_resume,
227         (functionptr) Java_java_lang_VMThread_nativeSetPriority,
228         (functionptr) Java_java_lang_VMThread_nativeStop,
229         (functionptr) Java_java_lang_VMThread_currentThread,
230         (functionptr) Java_java_lang_VMThread_yield,
231         (functionptr) Java_java_lang_VMThread_interrupted,
232         (functionptr) Java_java_lang_VMThread_holdsLock,
233
234         (functionptr) Java_java_lang_VMThrowable_fillInStackTrace,
235         (functionptr) Java_java_lang_VMThrowable_getStackTrace,
236
237         (functionptr) Java_java_lang_management_VMManagementFactory_getMemoryPoolNames,
238         (functionptr) Java_java_lang_management_VMManagementFactory_getMemoryManagerNames,
239         (functionptr) Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames,
240
241         (functionptr) Java_java_lang_reflect_Constructor_getModifiersInternal,
242         (functionptr) Java_java_lang_reflect_Constructor_constructNative,
243
244         (functionptr) Java_java_lang_reflect_Field_getModifiersInternal,
245         (functionptr) Java_java_lang_reflect_Field_getType,
246         (functionptr) Java_java_lang_reflect_Field_get,
247         (functionptr) Java_java_lang_reflect_Field_getBoolean,
248         (functionptr) Java_java_lang_reflect_Field_getByte,
249         (functionptr) Java_java_lang_reflect_Field_getChar,
250         (functionptr) Java_java_lang_reflect_Field_getShort,
251         (functionptr) Java_java_lang_reflect_Field_getInt,
252         (functionptr) Java_java_lang_reflect_Field_getLong,
253         (functionptr) Java_java_lang_reflect_Field_getFloat,
254         (functionptr) Java_java_lang_reflect_Field_getDouble,
255         (functionptr) Java_java_lang_reflect_Field_set,
256         (functionptr) Java_java_lang_reflect_Field_setBoolean,
257         (functionptr) Java_java_lang_reflect_Field_setByte,
258         (functionptr) Java_java_lang_reflect_Field_setChar,
259         (functionptr) Java_java_lang_reflect_Field_setShort,
260         (functionptr) Java_java_lang_reflect_Field_setInt,
261         (functionptr) Java_java_lang_reflect_Field_setLong,
262         (functionptr) Java_java_lang_reflect_Field_setFloat,
263         (functionptr) Java_java_lang_reflect_Field_setDouble,
264
265         (functionptr) Java_java_lang_reflect_Method_getModifiersInternal,
266         (functionptr) Java_java_lang_reflect_Method_getReturnType,
267         (functionptr) Java_java_lang_reflect_Method_getParameterTypes,
268         (functionptr) Java_java_lang_reflect_Method_getExceptionTypes,
269         (functionptr) Java_java_lang_reflect_Method_invokeNative,
270
271         (functionptr) Java_java_lang_reflect_VMProxy_getProxyClass,
272         (functionptr) Java_java_lang_reflect_VMProxy_getProxyData,
273         (functionptr) Java_java_lang_reflect_VMProxy_generateProxyClass,
274
275         (functionptr) Java_java_security_VMAccessController_getStack,
276
277 #if defined(ENABLE_JVMTI)
278         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_suspendThread,
279         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_resumeThread,
280         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getSuspendCount,
281         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getAllLoadedClassesCount,
282         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getClassStatus,
283         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getAllClassMethods,
284         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getClassMethod,
285         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getFrames,
286         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getFrame,
287         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getFrameCount,
288         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getThreadStatus,
289         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getLoadRequests,
290         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_executeMethod,
291         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getSourceFile,
292         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_registerEvent,
293         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_unregisterEvent,
294         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_clearEvents,
295         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getAllLoadedClasses,
296         (functionptr) Java_gnu_classpath_jdwp_VMFrame_setValue,
297         (functionptr) Java_gnu_classpath_jdwp_VMFrame_getValue,
298         (functionptr) Java_gnu_classpath_jdwp_VMMethod_getName,
299         (functionptr) Java_gnu_classpath_jdwp_VMMethod_getSignature,
300         (functionptr) Java_gnu_classpath_jdwp_VMMethod_getModifiers,
301         (functionptr) Java_gnu_classpath_jdwp_VMMethod_getLineTable,
302         (functionptr) Java_gnu_classpath_jdwp_VMMethod_getVariableTable
303 #endif
304
305 };
306
307 #endif /* defined(ENABLE_LIBJVM) */
308
309
310 /* tables for methods *********************************************************/
311
312 #if defined(WITH_STATIC_CLASSPATH)
313 #define NATIVETABLESIZE  (sizeof(nativetable)/sizeof(struct nativeref))
314
315 /* table for fast string comparison */
316 static nativecompref nativecomptable[NATIVETABLESIZE];
317
318 /* string comparsion table initialized */
319 static bool nativecompdone = false;
320 #endif
321
322
323 /* global variables ***********************************************************/
324
325 #if !defined(WITH_STATIC_CLASSPATH)
326 static hashtable *hashtable_library;
327 static lt_dlhandle mainhandle;
328 #endif
329
330
331 /* native_init *****************************************************************
332
333    Initializes the native subsystem.
334
335 *******************************************************************************/
336
337 bool native_init(void)
338 {
339 #if !defined(WITH_STATIC_CLASSPATH)
340         /* initialize libltdl */
341
342         if (lt_dlinit())
343                 vm_abort("lt_dlinit failed: %s\n", lt_dlerror());
344
345         /* Get the handle for the main program or for the libjvm.so,
346            depends on the configuration. */
347
348 # if defined(ENABLE_LIBJVM)
349         /* First try to open where dlopen searches, e.g. LD_LIBRARY_PATH.
350            If not found, try the absolute path. */
351
352         if (!(mainhandle = lt_dlopenext("libjvm")))
353                 if (!(mainhandle = lt_dlopenext(cacao_libjvm)))
354                         vm_abort("lt_dlopenext failed: %s\n", lt_dlerror());
355 # else
356         if (!(mainhandle = lt_dlopen(NULL)))
357                 vm_abort("lt_dlopen failed: %s\n", lt_dlerror());
358 # endif
359
360         /* initialize library hashtable, 10 entries should be enough */
361
362         hashtable_library = NEW(hashtable);
363
364         hashtable_create(hashtable_library, 10);
365 #endif
366
367         /* everything's ok */
368
369         return true;
370 }
371
372
373 /* native_hashtable_library_add ************************************************
374
375    Adds an entry to the native library hashtable.
376
377 *******************************************************************************/
378
379 #if !defined(WITH_STATIC_CLASSPATH)
380 void native_hashtable_library_add(utf *filename, java_objectheader *loader,
381                                                                   lt_dlhandle handle)
382 {
383         hashtable_library_loader_entry *le;
384         hashtable_library_name_entry   *ne; /* library name                       */
385         u4   key;                           /* hashkey                            */
386         u4   slot;                          /* slot in hashtable                  */
387
388         LOCK_MONITOR_ENTER(hashtable_library->header);
389
390         /* normally addresses are aligned to 4, 8 or 16 bytes */
391
392         key  = ((u4) (ptrint) loader) >> 4;        /* align to 16-byte boundaries */
393         slot = key & (hashtable_library->size - 1);
394         le   = hashtable_library->ptr[slot];
395
396         /* search external hash chain for the entry */
397
398         while (le) {
399                 if (le->loader == loader)
400                         break;
401
402                 le = le->hashlink;                  /* next element in external chain */
403         }
404
405         /* no loader found? create a new entry */
406
407         if (le == NULL) {
408                 le = NEW(hashtable_library_loader_entry);
409
410                 le->loader   = loader;
411                 le->namelink = NULL;
412
413                 /* insert entry into hashtable */
414
415                 le->hashlink =
416                         (hashtable_library_loader_entry *) hashtable_library->ptr[slot];
417                 hashtable_library->ptr[slot] = le;
418
419                 /* update number of hashtable-entries */
420
421                 hashtable_library->entries++;
422         }
423
424
425         /* search for library name */
426
427         ne = le->namelink;
428
429         while (ne) {
430                 if (ne->name == filename) {
431                         LOCK_MONITOR_EXIT(hashtable_library->header);
432
433                         return;
434                 }
435
436                 ne = ne->hashlink;                  /* next element in external chain */
437         }
438
439         /* not found? add the library name to the classloader */
440
441         ne = NEW(hashtable_library_name_entry);
442
443         ne->name   = filename;
444         ne->handle = handle;
445
446         /* insert entry into external chain */
447
448         ne->hashlink = le->namelink;
449         le->namelink = ne;
450
451         LOCK_MONITOR_EXIT(hashtable_library->header);
452 }
453 #endif /* !defined(WITH_STATIC_CLASSPATH) */
454
455
456 /* native_hashtable_library_find ***********************************************
457
458    Find an entry in the native library hashtable.
459
460 *******************************************************************************/
461
462 #if !defined(WITH_STATIC_CLASSPATH)
463 hashtable_library_name_entry *native_hashtable_library_find(utf *filename,
464                                                                                                                         java_objectheader *loader)
465 {
466         hashtable_library_loader_entry *le;
467         hashtable_library_name_entry   *ne; /* library name                       */
468         u4   key;                           /* hashkey                            */
469         u4   slot;                          /* slot in hashtable                  */
470
471         /* normally addresses are aligned to 4, 8 or 16 bytes */
472
473         key  = ((u4) (ptrint) loader) >> 4;        /* align to 16-byte boundaries */
474         slot = key & (hashtable_library->size - 1);
475         le   = hashtable_library->ptr[slot];
476
477         /* search external hash chain for the entry */
478
479         while (le) {
480                 if (le->loader == loader)
481                         break;
482
483                 le = le->hashlink;                  /* next element in external chain */
484         }
485
486         /* no loader found? return NULL */
487
488         if (!le)
489                 return NULL;
490
491         /* search for library name */
492
493         ne = le->namelink;
494
495         while (ne) {
496                 if (ne->name == filename)
497                         return ne;
498
499                 ne = ne->hashlink;                  /* next element in external chain */
500         }
501
502         /* return entry, if no entry was found, ne is NULL */
503
504         return ne;
505 }
506 #endif /* !defined(WITH_STATIC_CLASSPATH) */
507
508
509 /* native_findfunction *********************************************************
510
511    Looks up a method (must have the same class name, method name,
512    descriptor and 'static'ness) and returns a function pointer to it.
513    Returns: function pointer or NULL (if there is no such method)
514
515    Remark: For faster operation, the names/descriptors are converted
516    from C strings to Unicode the first time this function is called.
517
518 *******************************************************************************/
519
520 #if defined(WITH_STATIC_CLASSPATH)
521 functionptr native_findfunction(utf *cname, utf *mname, utf *desc,
522                                                                 bool isstatic)
523 {
524         /* entry of table for fast string comparison */
525         struct nativecompref *n;
526         s4 i;
527
528         isstatic = isstatic ? true : false;
529         
530         if (!nativecompdone) {
531                 for (i = 0; i < NATIVETABLESIZE; i++) {
532                         nativecomptable[i].classname  = 
533                                 utf_new_char(nativetable[i].classname);
534
535                         nativecomptable[i].methodname = 
536                                 utf_new_char(nativetable[i].methodname);
537
538                         nativecomptable[i].descriptor =
539                                 utf_new_char(nativetable[i].descriptor);
540
541                         nativecomptable[i].isstatic   = nativetable[i].isstatic;
542                         nativecomptable[i].func       = nativetable[i].func;
543                 }
544
545                 nativecompdone = true;
546         }
547
548         for (i = 0; i < NATIVETABLESIZE; i++) {
549                 n = &(nativecomptable[i]);
550
551                 if (cname == n->classname && mname == n->methodname &&
552                     desc == n->descriptor && isstatic == n->isstatic)
553                         return n->func;
554         }
555
556                 
557         /* no function was found, throw exception */
558
559         *exceptionptr =
560                         new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
561                                                                          mname);
562
563         return NULL;
564 }
565 #endif /* defined(WITH_STATIC_CLASSPATH) */
566
567
568 /* native_make_overloaded_function *********************************************
569
570    XXX
571
572 *******************************************************************************/
573
574 #if !defined(WITH_STATIC_CLASSPATH)
575 static char *native_make_overloaded_function(char *name, utf *desc)
576 {
577         char *newname;
578         s4    namelen;
579         char *utf_ptr;
580         u2    c;
581         s4    i;
582
583         utf_ptr = desc->text;
584         namelen = strlen(name) + strlen("__") + strlen("0");
585
586         /* calculate additional length */
587
588         while ((c = utf_nextu2(&utf_ptr)) != ')') {
589                 switch (c) {
590                 case 'Z':
591                 case 'B':
592                 case 'C':
593                 case 'S':
594                 case 'I':
595                 case 'J':
596                 case 'F':
597                 case 'D':
598                         namelen++;
599                         break;
600                 case '[':
601                         namelen += 2;
602                         break;
603                 case 'L':
604                         namelen++;
605                         while (utf_nextu2(&utf_ptr) != ';')
606                                 namelen++;
607                         namelen += 2;
608                         break;
609                 case '(':
610                         break;
611                 default:
612                         assert(0);
613                 }
614         }
615
616
617         /* reallocate memory */
618
619         i = strlen(name);
620
621         newname = DMNEW(char, namelen);
622         MCOPY(newname, name, char, i);
623
624         utf_ptr = desc->text;
625
626         newname[i++] = '_';
627         newname[i++] = '_';
628
629         while ((c = utf_nextu2(&utf_ptr)) != ')') {
630                 switch (c) {
631                 case 'Z':
632                 case 'B':
633                 case 'C':
634                 case 'S':
635                 case 'J':
636                 case 'I':
637                 case 'F':
638                 case 'D':
639                         newname[i++] = c;
640                         break;
641                 case '[':
642                         newname[i++] = '_';
643                         newname[i++] = '3';
644                         break;
645                 case 'L':
646                         newname[i++] = 'L';
647                         while ((c = utf_nextu2(&utf_ptr)) != ';')
648                                 if (((c >= 'a') && (c <= 'z')) ||
649                                         ((c >= 'A') && (c <= 'Z')) ||
650                                         ((c >= '0') && (c <= '9')))
651                                         newname[i++] = c;
652                                 else
653                                         newname[i++] = '_';
654                         newname[i++] = '_';
655                         newname[i++] = '2';
656                         break;
657                 case '(':
658                         break;
659                 default:
660                         assert(0);
661                 }
662         }
663
664         /* close string */
665
666         newname[i] = '\0';
667
668         return newname;
669 }
670
671
672 /* native_insert_char **********************************************************
673
674    Inserts the passed UTF character into the native method name.  If
675    necessary it is escaped properly.
676
677 *******************************************************************************/
678
679 static s4 native_insert_char(char *name, u4 pos, u2 c)
680 {
681         s4 val;
682         s4 i;
683
684         switch (c) {
685         case '/':
686         case '.':
687                 /* replace '/' or '.' with '_' */
688                 name[pos] = '_';
689                 break;
690
691         case '_':
692                 /* escape sequence for '_' is '_1' */
693                 name[pos]   = '_';
694                 name[++pos] = '1';
695                 break;
696
697         case ';':
698                 /* escape sequence for ';' is '_2' */
699                 name[pos]   = '_';
700                 name[++pos] = '2';
701                 break;
702
703         case '[':
704                 /* escape sequence for '[' is '_1' */
705                 name[pos]   = '_';
706                 name[++pos] = '3';
707                 break;
708
709         default:
710                 if (isalnum(c))
711                         name[pos] = c;
712                 else {
713                         /* unicode character */
714                         name[pos]   = '_';
715                         name[++pos] = '0';
716
717                         for (i = 0; i < 4; ++i) {
718                                 val = c & 0x0f;
719                                 name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
720                                 c >>= 4;
721                         }
722
723                         pos += 4;
724                 }
725                 break;
726         }
727
728         /* return the new buffer index */
729
730         return pos;
731 }
732
733
734 /* native_resolve_function *****************************************************
735
736    Resolves a native function, maybe from a dynamic library.
737
738 *******************************************************************************/
739
740 functionptr native_resolve_function(methodinfo *m)
741 {
742         lt_ptr                          sym;
743         char                           *name;
744         char                           *newname;
745         s4                              namelen;
746         char                           *utf_ptr;
747         char                           *utf_endptr;
748         u2                              c;
749         u4                              pos;
750         s4                              dumpsize;
751         hashtable_library_loader_entry *le;
752         hashtable_library_name_entry   *ne;
753         u4                              key;    /* hashkey                        */
754         u4                              slot;   /* slot in hashtable              */
755
756         /* verbose output */
757
758         if (opt_verbosejni) {
759                 printf("[Dynamic-linking native method ");
760                 utf_display_printable_ascii_classname(m->class->name);
761                 printf(".");
762                 utf_display_printable_ascii(m->name);
763                 printf(" ... ");
764         }
765                 
766         /* Calculate length of native function name.  We multiply the
767            class and method name length by 6 as this is the maxium
768            escape-sequence that can be generated (unicode). */
769
770         namelen = strlen("Java_") +
771                 utf_get_number_of_u2s(m->class->name) * 6 +
772                 strlen("_") +
773                 utf_get_number_of_u2s(m->name) * 6 +
774                 strlen("0");
775
776         /* allocate memory */
777
778         dumpsize = dump_size();
779
780         name = DMNEW(char, namelen);
781
782         /* generate name of native functions */
783
784         strcpy(name, "Java_");
785         pos = strlen("Java_");
786
787         utf_ptr    = m->class->name->text;
788         utf_endptr = UTF_END(m->class->name);
789
790         for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
791                 c   = *utf_ptr;
792                 pos = native_insert_char(name, pos, c);
793         }
794
795         /* seperator between class and method */
796
797         name[pos++] = '_';
798
799         utf_ptr    = m->name->text;
800         utf_endptr = UTF_END(m->name);
801
802         for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
803                 c   = *utf_ptr;
804                 pos = native_insert_char(name, pos, c);
805         }
806
807         /* close string */
808
809         name[pos] = '\0';
810
811         /* check for an buffer overflow */
812
813         assert(pos <= namelen);
814
815         /* generate overloaded function (having the types in it's name)           */
816
817         newname = native_make_overloaded_function(name, m->descriptor);
818
819         /* check the library hash entries of the classloader of the
820            methods's class  */
821
822         sym = NULL;
823
824         /* normally addresses are aligned to 4, 8 or 16 bytes */
825
826         key  = ((u4) (ptrint) m->class->classloader) >> 4;    /* align to 16-byte */
827         slot = key & (hashtable_library->size - 1);
828         le   = hashtable_library->ptr[slot];
829
830         /* iterate through loaders in this hash slot */
831
832         while ((le != NULL) && (sym == NULL)) {
833                 /* iterate through names in this loader */
834
835                 ne = le->namelink;
836                         
837                 while ((ne != NULL) && (sym == NULL)) {
838                         sym = lt_dlsym(ne->handle, name);
839
840                         if (sym == NULL)
841                                 sym = lt_dlsym(ne->handle, newname);
842
843                         ne = ne->hashlink;
844                 }
845
846                 le = le->hashlink;
847         }
848
849         if (sym != NULL)
850                 if (opt_verbosejni)
851                         printf("JNI ]\n");
852
853
854         /* If not found, try to find the native function symbol in the
855            main program. */
856
857         if (sym == NULL) {
858                 sym = lt_dlsym(mainhandle, name);
859
860                 if (sym == NULL)
861                         sym = lt_dlsym(mainhandle, newname);
862
863                 if (sym != NULL)
864                         if (opt_verbosejni)
865                                 printf("internal ]\n");
866         }
867
868
869 #if defined(ENABLE_JVMTI)
870         /* fire Native Method Bind event */
871         if (jvmti) jvmti_NativeMethodBind(m, sym, &sym);
872 #endif
873
874         /* no symbol found? throw exception */
875
876         if (sym == NULL) {
877                 if (opt_verbosejni)
878                         printf("failed ]\n");
879
880                 *exceptionptr =
881                         new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
882                                                                          m->name);
883         }
884
885         /* release memory */
886
887         dump_release(dumpsize);
888
889         return (functionptr) (ptrint) sym;
890 }
891 #endif /* !defined(WITH_STATIC_CLASSPATH) */
892
893
894 /* native_new_and_init *********************************************************
895
896    Creates a new object on the heap and calls the initializer.
897    Returns the object pointer or NULL if memory is exhausted.
898                         
899 *******************************************************************************/
900
901 java_objectheader *native_new_and_init(classinfo *c)
902 {
903         methodinfo *m;
904         java_objectheader *o;
905
906         if (!c)
907                 return *exceptionptr;
908
909         /* create object */
910
911         o = builtin_new(c);
912         
913         if (!o)
914                 return NULL;
915
916         /* try to find the initializer */
917
918         m = class_findmethod(c, utf_init, utf_void__void);
919                                                       
920         /* ATTENTION: returning the object here is ok, since the class may
921        not have an initializer */
922
923         if (!m)
924                 return o;
925
926         /* call initializer */
927
928         (void) vm_call_method(m, o);
929
930         return o;
931 }
932
933
934 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
935 {
936         methodinfo *m;
937         java_objectheader *o;
938
939         if (!c)
940                 return *exceptionptr;
941
942         /* create object */
943
944         o = builtin_new(c);
945
946         if (!o)
947                 return NULL;
948
949         /* find initializer */
950
951         m = class_resolveclassmethod(c,
952                                                                  utf_init,
953                                                                  utf_java_lang_String__void,
954                                                                  NULL,
955                                                                  true);
956
957         /* initializer not found */
958
959         if (!m)
960                 return NULL;
961
962         /* call initializer */
963
964         (void) vm_call_method(m, o, s);
965
966         return o;
967 }
968
969
970 java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
971 {
972         methodinfo *m;
973         java_objectheader *o;
974
975         if (!c)
976                 return *exceptionptr;
977
978         /* create object */
979
980         o = builtin_new(c);
981         
982         if (!o)
983                 return NULL;
984
985         /* find initializer */
986
987         m = class_resolveclassmethod(c, utf_init, utf_int__void, NULL, true);
988
989         /* initializer not found  */
990
991         if (!m)
992                 return NULL;
993
994         /* call initializer */
995
996         (void) vm_call_method(m, o, i);
997
998         return o;
999 }
1000
1001
1002 java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t)
1003 {
1004         methodinfo *m;
1005         java_objectheader *o;
1006
1007         if (!c)
1008                 return *exceptionptr;
1009
1010         /* create object */
1011
1012         o = builtin_new(c);
1013         
1014         if (!o)
1015                 return NULL;
1016
1017         /* find initializer */
1018
1019         m = class_findmethod(c, utf_init, utf_java_lang_Throwable__void);
1020                                                       
1021         /* initializer not found */
1022
1023         if (!m)
1024                 return NULL;
1025
1026         /* call initializer */
1027
1028         (void) vm_call_method(m, o, t);
1029
1030         return o;
1031 }
1032
1033
1034 /* native_get_parametertypes ***************************************************
1035
1036    Use the descriptor of a method to generate a java/lang/Class array
1037    which contains the classes of the parametertypes of the method.
1038
1039 *******************************************************************************/
1040
1041 java_objectarray *native_get_parametertypes(methodinfo *m)
1042 {
1043         methoddesc       *md;
1044         typedesc         *paramtypes;
1045         s4                paramcount;
1046     java_objectarray *oa;
1047         s4                i;
1048
1049         md = m->parseddesc;
1050
1051         /* is the descriptor fully parsed? */
1052
1053         if (!m->parseddesc->params)
1054                 if (!descriptor_params_from_paramtypes(md, m->flags))
1055                         return NULL;
1056
1057         paramtypes = md->paramtypes;
1058         paramcount = md->paramcount;
1059
1060         /* skip `this' pointer */
1061
1062         if (!(m->flags & ACC_STATIC)) {
1063                 paramtypes++;
1064                 paramcount--;
1065         }
1066
1067         /* create class-array */
1068
1069         oa = builtin_anewarray(paramcount, class_java_lang_Class);
1070
1071         if (!oa)
1072                 return NULL;
1073
1074     /* get classes */
1075
1076         for (i = 0; i < paramcount; i++)
1077                 if (!resolve_class_from_typedesc(&paramtypes[i], true, false,
1078                                                                                  (classinfo **) &oa->data[i]))
1079                         return NULL;
1080
1081         return oa;
1082 }
1083
1084
1085 /* native_get_exceptiontypes ***************************************************
1086
1087    Get the exceptions which can be thrown by a method.
1088
1089 *******************************************************************************/
1090
1091 java_objectarray *native_get_exceptiontypes(methodinfo *m)
1092 {
1093         java_objectarray *oa;
1094         classinfo        *c;
1095         u2                i;
1096
1097         /* create class-array */
1098
1099         oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
1100
1101         if (!oa)
1102                 return NULL;
1103
1104         for (i = 0; i < m->thrownexceptionscount; i++) {
1105                 if (!resolve_classref_or_classinfo(NULL, m->thrownexceptions[i],
1106                                                                                    resolveEager, true, false, &c))
1107                         return NULL;
1108
1109                 oa->data[i] = (java_objectheader *) c;
1110         }
1111
1112         return oa;
1113 }
1114
1115
1116 /* native_get_returntype *******************************************************
1117
1118    Get the returntype class of a method.
1119
1120 *******************************************************************************/
1121
1122 classinfo *native_get_returntype(methodinfo *m)
1123 {
1124         classinfo *c;
1125
1126         if (!resolve_class_from_typedesc(&(m->parseddesc->returntype), true, false,
1127                                                                          &c))
1128                 return NULL;
1129
1130         return c;
1131 }
1132
1133
1134 /*
1135  * These are local overrides for various environment variables in Emacs.
1136  * Please do not remove this and leave it at the end of the file, where
1137  * Emacs will automagically detect them.
1138  * ---------------------------------------------------------------------
1139  * Local variables:
1140  * mode: c
1141  * indent-tabs-mode: t
1142  * c-basic-offset: 4
1143  * tab-width: 4
1144  * End:
1145  */