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