Merged r5538 from trunk:
[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 5567 2006-09-28 20:20:18Z edwin $
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_loadclasses **********************************************************
332
333    Load classes required for native methods.
334
335 *******************************************************************************/
336
337 bool native_init(void)
338 {
339 #if !defined(WITH_STATIC_CLASSPATH)
340         /* initialize libltdl */
341
342         if (lt_dlinit()) {
343                 /* XXX how can we throw an exception here? */
344                 log_text(lt_dlerror());
345
346                 return false;
347         }
348
349         /* get the handle for the main program */
350
351         if (!(mainhandle = lt_dlopen(NULL)))
352                 return false;
353
354         /* initialize library hashtable, 10 entries should be enough */
355
356         hashtable_library = NEW(hashtable);
357
358         hashtable_create(hashtable_library, 10);
359 #endif
360
361         /* everything's ok */
362
363         return true;
364 }
365
366
367 /* native_hashtable_library_add ************************************************
368
369    Adds an entry to the native library hashtable.
370
371 *******************************************************************************/
372
373 #if !defined(WITH_STATIC_CLASSPATH)
374 void native_hashtable_library_add(utf *filename, java_objectheader *loader,
375                                                                   lt_dlhandle handle)
376 {
377         hashtable_library_loader_entry *le;
378         hashtable_library_name_entry   *ne; /* library name                       */
379         u4   key;                           /* hashkey                            */
380         u4   slot;                          /* slot in hashtable                  */
381
382         LOCK_MONITOR_ENTER(hashtable_library->header);
383
384         /* normally addresses are aligned to 4, 8 or 16 bytes */
385
386         key  = ((u4) (ptrint) loader) >> 4;        /* align to 16-byte boundaries */
387         slot = key & (hashtable_library->size - 1);
388         le   = hashtable_library->ptr[slot];
389
390         /* search external hash chain for the entry */
391
392         while (le) {
393                 if (le->loader == loader)
394                         break;
395
396                 le = le->hashlink;                  /* next element in external chain */
397         }
398
399         /* no loader found? create a new entry */
400
401         if (le == NULL) {
402                 le = NEW(hashtable_library_loader_entry);
403
404                 le->loader   = loader;
405                 le->namelink = NULL;
406
407                 /* insert entry into hashtable */
408
409                 le->hashlink =
410                         (hashtable_library_loader_entry *) hashtable_library->ptr[slot];
411                 hashtable_library->ptr[slot] = le;
412
413                 /* update number of hashtable-entries */
414
415                 hashtable_library->entries++;
416         }
417
418
419         /* search for library name */
420
421         ne = le->namelink;
422
423         while (ne) {
424                 if (ne->name == filename) {
425                         LOCK_MONITOR_EXIT(hashtable_library->header);
426
427                         return;
428                 }
429
430                 ne = ne->hashlink;                  /* next element in external chain */
431         }
432
433         /* not found? add the library name to the classloader */
434
435         ne = NEW(hashtable_library_name_entry);
436
437         ne->name   = filename;
438         ne->handle = handle;
439
440         /* insert entry into external chain */
441
442         ne->hashlink = le->namelink;
443         le->namelink = ne;
444
445         LOCK_MONITOR_EXIT(hashtable_library->header);
446 }
447 #endif /* !defined(WITH_STATIC_CLASSPATH) */
448
449
450 /* native_hashtable_library_find ***********************************************
451
452    Find an entry in the native library hashtable.
453
454 *******************************************************************************/
455
456 #if !defined(WITH_STATIC_CLASSPATH)
457 hashtable_library_name_entry *native_hashtable_library_find(utf *filename,
458                                                                                                                         java_objectheader *loader)
459 {
460         hashtable_library_loader_entry *le;
461         hashtable_library_name_entry   *ne; /* library name                       */
462         u4   key;                           /* hashkey                            */
463         u4   slot;                          /* slot in hashtable                  */
464
465         /* normally addresses are aligned to 4, 8 or 16 bytes */
466
467         key  = ((u4) (ptrint) loader) >> 4;        /* align to 16-byte boundaries */
468         slot = key & (hashtable_library->size - 1);
469         le   = hashtable_library->ptr[slot];
470
471         /* search external hash chain for the entry */
472
473         while (le) {
474                 if (le->loader == loader)
475                         break;
476
477                 le = le->hashlink;                  /* next element in external chain */
478         }
479
480         /* no loader found? return NULL */
481
482         if (!le)
483                 return NULL;
484
485         /* search for library name */
486
487         ne = le->namelink;
488
489         while (ne) {
490                 if (ne->name == filename)
491                         return ne;
492
493                 ne = ne->hashlink;                  /* next element in external chain */
494         }
495
496         /* return entry, if no entry was found, ne is NULL */
497
498         return ne;
499 }
500 #endif /* !defined(WITH_STATIC_CLASSPATH) */
501
502
503 /* native_findfunction *********************************************************
504
505    Looks up a method (must have the same class name, method name,
506    descriptor and 'static'ness) and returns a function pointer to it.
507    Returns: function pointer or NULL (if there is no such method)
508
509    Remark: For faster operation, the names/descriptors are converted
510    from C strings to Unicode the first time this function is called.
511
512 *******************************************************************************/
513
514 #if defined(WITH_STATIC_CLASSPATH)
515 functionptr native_findfunction(utf *cname, utf *mname, utf *desc,
516                                                                 bool isstatic)
517 {
518         /* entry of table for fast string comparison */
519         struct nativecompref *n;
520         s4 i;
521
522         isstatic = isstatic ? true : false;
523         
524         if (!nativecompdone) {
525                 for (i = 0; i < NATIVETABLESIZE; i++) {
526                         nativecomptable[i].classname  = 
527                                 utf_new_char(nativetable[i].classname);
528
529                         nativecomptable[i].methodname = 
530                                 utf_new_char(nativetable[i].methodname);
531
532                         nativecomptable[i].descriptor =
533                                 utf_new_char(nativetable[i].descriptor);
534
535                         nativecomptable[i].isstatic   = nativetable[i].isstatic;
536                         nativecomptable[i].func       = nativetable[i].func;
537                 }
538
539                 nativecompdone = true;
540         }
541
542         for (i = 0; i < NATIVETABLESIZE; i++) {
543                 n = &(nativecomptable[i]);
544
545                 if (cname == n->classname && mname == n->methodname &&
546                     desc == n->descriptor && isstatic == n->isstatic)
547                         return n->func;
548         }
549
550                 
551         /* no function was found, throw exception */
552
553         *exceptionptr =
554                         new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
555                                                                          mname);
556
557         return NULL;
558 }
559 #endif /* defined(WITH_STATIC_CLASSPATH) */
560
561
562 /* native_make_overloaded_function *********************************************
563
564    XXX
565
566 *******************************************************************************/
567
568 #if !defined(WITH_STATIC_CLASSPATH)
569 static char *native_make_overloaded_function(char *name, utf *desc)
570 {
571         char *newname;
572         s4    namelen;
573         char *utf_ptr;
574         u2    c;
575         s4    i;
576
577         utf_ptr = desc->text;
578         namelen = strlen(name) + strlen("__") + strlen("0");
579
580         /* calculate additional length */
581
582         while ((c = utf_nextu2(&utf_ptr)) != ')') {
583                 switch (c) {
584                 case 'Z':
585                 case 'B':
586                 case 'C':
587                 case 'S':
588                 case 'I':
589                 case 'J':
590                 case 'F':
591                 case 'D':
592                         namelen++;
593                         break;
594                 case '[':
595                         namelen += 2;
596                         break;
597                 case 'L':
598                         namelen++;
599                         while (utf_nextu2(&utf_ptr) != ';')
600                                 namelen++;
601                         namelen += 2;
602                         break;
603                 case '(':
604                         break;
605                 default:
606                         assert(0);
607                 }
608         }
609
610
611         /* reallocate memory */
612
613         i = strlen(name);
614
615         newname = DMNEW(char, namelen);
616         MCOPY(newname, name, char, i);
617
618         utf_ptr = desc->text;
619
620         newname[i++] = '_';
621         newname[i++] = '_';
622
623         while ((c = utf_nextu2(&utf_ptr)) != ')') {
624                 switch (c) {
625                 case 'Z':
626                 case 'B':
627                 case 'C':
628                 case 'S':
629                 case 'J':
630                 case 'I':
631                 case 'F':
632                 case 'D':
633                         newname[i++] = c;
634                         break;
635                 case '[':
636                         newname[i++] = '_';
637                         newname[i++] = '3';
638                         break;
639                 case 'L':
640                         newname[i++] = 'L';
641                         while ((c = utf_nextu2(&utf_ptr)) != ';')
642                                 if (((c >= 'a') && (c <= 'z')) ||
643                                         ((c >= 'A') && (c <= 'Z')) ||
644                                         ((c >= '0') && (c <= '9')))
645                                         newname[i++] = c;
646                                 else
647                                         newname[i++] = '_';
648                         newname[i++] = '_';
649                         newname[i++] = '2';
650                         break;
651                 case '(':
652                         break;
653                 default:
654                         assert(0);
655                 }
656         }
657
658         /* close string */
659
660         newname[i] = '\0';
661
662         return newname;
663 }
664
665
666 /* native_insert_char **********************************************************
667
668    Inserts the passed UTF character into the native method name.  If
669    necessary it is escaped properly.
670
671 *******************************************************************************/
672
673 static s4 native_insert_char(char *name, u4 pos, u2 c)
674 {
675         s4 val;
676         s4 i;
677
678         switch (c) {
679         case '/':
680         case '.':
681                 /* replace '/' or '.' with '_' */
682                 name[pos] = '_';
683                 break;
684
685         case '_':
686                 /* escape sequence for '_' is '_1' */
687                 name[pos]   = '_';
688                 name[++pos] = '1';
689                 break;
690
691         case ';':
692                 /* escape sequence for ';' is '_2' */
693                 name[pos]   = '_';
694                 name[++pos] = '2';
695                 break;
696
697         case '[':
698                 /* escape sequence for '[' is '_1' */
699                 name[pos]   = '_';
700                 name[++pos] = '3';
701                 break;
702
703         default:
704                 if (isalnum(c))
705                         name[pos] = c;
706                 else {
707                         /* unicode character */
708                         name[pos]   = '_';
709                         name[++pos] = '0';
710
711                         for (i = 0; i < 4; ++i) {
712                                 val = c & 0x0f;
713                                 name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
714                                 c >>= 4;
715                         }
716
717                         pos += 4;
718                 }
719                 break;
720         }
721
722         /* return the new buffer index */
723
724         return pos;
725 }
726
727
728 /* native_resolve_function *****************************************************
729
730    Resolves a native function, maybe from a dynamic library.
731
732 *******************************************************************************/
733
734 functionptr native_resolve_function(methodinfo *m)
735 {
736         lt_ptr                          sym;
737         char                           *name;
738         char                           *newname;
739         s4                              namelen;
740         char                           *utf_ptr;
741         char                           *utf_endptr;
742         u2                              c;
743         u4                              pos;
744         s4                              dumpsize;
745         hashtable_library_loader_entry *le;
746         hashtable_library_name_entry   *ne;
747         u4                              key;    /* hashkey                        */
748         u4                              slot;   /* slot in hashtable              */
749
750         /* verbose output */
751
752         if (opt_verbosejni) {
753                 printf("[Dynamic-linking native method ");
754                 utf_display_printable_ascii_classname(m->class->name);
755                 printf(".");
756                 utf_display_printable_ascii(m->name);
757                 printf(" ... ");
758         }
759                 
760         /* Calculate length of native function name.  We multiply the
761            class and method name length by 6 as this is the maxium
762            escape-sequence that can be generated (unicode). */
763
764         namelen = strlen("Java_") +
765                 utf_get_number_of_u2s(m->class->name) * 6 +
766                 strlen("_") +
767                 utf_get_number_of_u2s(m->name) * 6 +
768                 strlen("0");
769
770         /* allocate memory */
771
772         dumpsize = dump_size();
773
774         name = DMNEW(char, namelen);
775
776         /* generate name of native functions */
777
778         strcpy(name, "Java_");
779         pos = strlen("Java_");
780
781         utf_ptr    = m->class->name->text;
782         utf_endptr = UTF_END(m->class->name);
783
784         for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
785                 c   = *utf_ptr;
786                 pos = native_insert_char(name, pos, c);
787         }
788
789         /* seperator between class and method */
790
791         name[pos++] = '_';
792
793         utf_ptr    = m->name->text;
794         utf_endptr = UTF_END(m->name);
795
796         for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
797                 c   = *utf_ptr;
798                 pos = native_insert_char(name, pos, c);
799         }
800
801         /* close string */
802
803         name[pos] = '\0';
804
805         /* check for an buffer overflow */
806
807         assert(pos <= namelen);
808
809         /* generate overloaded function (having the types in it's name)           */
810
811         newname = native_make_overloaded_function(name, m->descriptor);
812
813         /* check the library hash entries of the classloader of the
814            methods's class  */
815
816         sym = NULL;
817
818         /* normally addresses are aligned to 4, 8 or 16 bytes */
819
820         key  = ((u4) (ptrint) m->class->classloader) >> 4;    /* align to 16-byte */
821         slot = key & (hashtable_library->size - 1);
822         le   = hashtable_library->ptr[slot];
823
824         /* iterate through loaders in this hash slot */
825
826         while ((le != NULL) && (sym == NULL)) {
827                 /* iterate through names in this loader */
828
829                 ne = le->namelink;
830                         
831                 while ((ne != NULL) && (sym == NULL)) {
832                         sym = lt_dlsym(ne->handle, name);
833
834                         if (sym == NULL)
835                                 sym = lt_dlsym(ne->handle, newname);
836
837                         ne = ne->hashlink;
838                 }
839
840                 le = le->hashlink;
841         }
842
843         if (sym != NULL)
844                 if (opt_verbosejni)
845                         printf("JNI ]\n");
846
847
848         /* If not found, try to find the native function symbol in the
849            main program. */
850
851         if (sym == NULL) {
852                 sym = lt_dlsym(mainhandle, name);
853
854                 if (sym == NULL)
855                         sym = lt_dlsym(mainhandle, newname);
856
857                 if (sym != NULL)
858                         if (opt_verbosejni)
859                                 printf("internal ]\n");
860         }
861
862
863 #if defined(ENABLE_JVMTI)
864         /* fire Native Method Bind event */
865         if (jvmti) jvmti_NativeMethodBind(m, sym, &sym);
866 #endif
867
868         /* no symbol found? throw exception */
869
870         if (sym == NULL) {
871                 if (opt_verbosejni)
872                         printf("failed ]\n");
873
874                 *exceptionptr =
875                         new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
876                                                                          m->name);
877         }
878
879         /* release memory */
880
881         dump_release(dumpsize);
882
883         return (functionptr) (ptrint) sym;
884 }
885 #endif /* !defined(WITH_STATIC_CLASSPATH) */
886
887
888 /* native_new_and_init *********************************************************
889
890    Creates a new object on the heap and calls the initializer.
891    Returns the object pointer or NULL if memory is exhausted.
892                         
893 *******************************************************************************/
894
895 java_objectheader *native_new_and_init(classinfo *c)
896 {
897         methodinfo *m;
898         java_objectheader *o;
899
900         if (!c)
901                 return *exceptionptr;
902
903         /* create object */
904
905         o = builtin_new(c);
906         
907         if (!o)
908                 return NULL;
909
910         /* try to find the initializer */
911
912         m = class_findmethod(c, utf_init, utf_void__void);
913                                                       
914         /* ATTENTION: returning the object here is ok, since the class may
915        not have an initializer */
916
917         if (!m)
918                 return o;
919
920         /* call initializer */
921
922         (void) vm_call_method(m, o);
923
924         return o;
925 }
926
927
928 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
929 {
930         methodinfo *m;
931         java_objectheader *o;
932
933         if (!c)
934                 return *exceptionptr;
935
936         /* create object */
937
938         o = builtin_new(c);
939
940         if (!o)
941                 return NULL;
942
943         /* find initializer */
944
945         m = class_resolveclassmethod(c,
946                                                                  utf_init,
947                                                                  utf_java_lang_String__void,
948                                                                  NULL,
949                                                                  true);
950
951         /* initializer not found */
952
953         if (!m)
954                 return NULL;
955
956         /* call initializer */
957
958         (void) vm_call_method(m, o, s);
959
960         return o;
961 }
962
963
964 java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
965 {
966         methodinfo *m;
967         java_objectheader *o;
968
969         if (!c)
970                 return *exceptionptr;
971
972         /* create object */
973
974         o = builtin_new(c);
975         
976         if (!o)
977                 return NULL;
978
979         /* find initializer */
980
981         m = class_resolveclassmethod(c, utf_init, utf_int__void, NULL, true);
982
983         /* initializer not found  */
984
985         if (!m)
986                 return NULL;
987
988         /* call initializer */
989
990         (void) vm_call_method(m, o, i);
991
992         return o;
993 }
994
995
996 java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t)
997 {
998         methodinfo *m;
999         java_objectheader *o;
1000
1001         if (!c)
1002                 return *exceptionptr;
1003
1004         /* create object */
1005
1006         o = builtin_new(c);
1007         
1008         if (!o)
1009                 return NULL;
1010
1011         /* find initializer */
1012
1013         m = class_findmethod(c, utf_init, utf_java_lang_Throwable__void);
1014                                                       
1015         /* initializer not found */
1016
1017         if (!m)
1018                 return NULL;
1019
1020         /* call initializer */
1021
1022         (void) vm_call_method(m, o, t);
1023
1024         return o;
1025 }
1026
1027
1028 /* native_get_parametertypes ***************************************************
1029
1030    Use the descriptor of a method to generate a java/lang/Class array
1031    which contains the classes of the parametertypes of the method.
1032
1033 *******************************************************************************/
1034
1035 java_objectarray *native_get_parametertypes(methodinfo *m)
1036 {
1037         methoddesc       *md;
1038         typedesc         *paramtypes;
1039         s4                paramcount;
1040     java_objectarray *oa;
1041         s4                i;
1042
1043         md = m->parseddesc;
1044
1045         /* is the descriptor fully parsed? */
1046
1047         if (!m->parseddesc->params)
1048                 if (!descriptor_params_from_paramtypes(md, m->flags))
1049                         return NULL;
1050
1051         paramtypes = md->paramtypes;
1052         paramcount = md->paramcount;
1053
1054         /* skip `this' pointer */
1055
1056         if (!(m->flags & ACC_STATIC)) {
1057                 paramtypes++;
1058                 paramcount--;
1059         }
1060
1061         /* create class-array */
1062
1063         oa = builtin_anewarray(paramcount, class_java_lang_Class);
1064
1065         if (!oa)
1066                 return NULL;
1067
1068     /* get classes */
1069
1070         for (i = 0; i < paramcount; i++)
1071                 if (!resolve_class_from_typedesc(&paramtypes[i], true, false,
1072                                                                                  (classinfo **) &oa->data[i]))
1073                         return NULL;
1074
1075         return oa;
1076 }
1077
1078
1079 /* native_get_exceptiontypes ***************************************************
1080
1081    Get the exceptions which can be thrown by a method.
1082
1083 *******************************************************************************/
1084
1085 java_objectarray *native_get_exceptiontypes(methodinfo *m)
1086 {
1087         java_objectarray *oa;
1088         classinfo        *c;
1089         u2                i;
1090
1091         /* create class-array */
1092
1093         oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
1094
1095         if (!oa)
1096                 return NULL;
1097
1098         for (i = 0; i < m->thrownexceptionscount; i++) {
1099                 if (!resolve_classref_or_classinfo(NULL, m->thrownexceptions[i],
1100                                                                                    resolveEager, true, false, &c))
1101                         return NULL;
1102
1103                 oa->data[i] = (java_objectheader *) c;
1104         }
1105
1106         return oa;
1107 }
1108
1109
1110 /* native_get_returntype *******************************************************
1111
1112    Get the returntype class of a method.
1113
1114 *******************************************************************************/
1115
1116 classinfo *native_get_returntype(methodinfo *m)
1117 {
1118         classinfo *c;
1119
1120         if (!resolve_class_from_typedesc(&(m->parseddesc->returntype), true, false,
1121                                                                          &c))
1122                 return NULL;
1123
1124         return c;
1125 }
1126
1127
1128 /*
1129  * These are local overrides for various environment variables in Emacs.
1130  * Please do not remove this and leave it at the end of the file, where
1131  * Emacs will automagically detect them.
1132  * ---------------------------------------------------------------------
1133  * Local variables:
1134  * mode: c
1135  * indent-tabs-mode: t
1136  * c-basic-offset: 4
1137  * tab-width: 4
1138  * End:
1139  */