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