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