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