7c28b22b6c7efb8b9fd2085402274e10b9f358d1
[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 7674 2007-04-05 13:27:11Z 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 "vm/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 #include "native/include/sun_misc_Unsafe.h"
107
108 #if defined(ENABLE_JVMTI)
109 #include "native/include/gnu_classpath_jdwp_event_EventRequest.h"
110 #include "native/include/java_nio_ByteBuffer.h"
111 #include "native/include/gnu_classpath_jdwp_VMVirtualMachine.h"
112 #include "native/include/gnu_classpath_jdwp_VMFrame.h"
113 #include "native/include/gnu_classpath_jdwp_VMMethod.h"
114 #endif
115
116 #elif defined(ENABLE_JAVAME_CLDC1_1)
117
118 #include "native/include/com_sun_cldchi_io_ConsoleOutputStream.h"
119 #include "native/include/java_lang_Class.h"
120 #include "native/include/java_lang_Double.h"
121 #include "native/include/java_lang_Float.h"
122 #include "native/include/java_lang_Math.h"
123 #include "native/include/java_lang_Runtime.h"
124 #include "native/include/java_lang_System.h"
125 #include "native/include/java_lang_Thread.h"
126
127 #endif
128
129 #if defined(WITH_STATIC_CLASSPATH)
130
131 /* these are required to prevent compiler warnings */
132
133 #include "native/include/java_net_DatagramPacket.h"
134 #include "native/include/java_net_InetAddress.h"
135 #include "native/include/java_net_SocketImpl.h"
136
137 #include "native/include/gnu_java_net_PlainDatagramSocketImpl.h"
138 #include "native/include/gnu_java_net_PlainSocketImpl.h"
139 #include "native/include/gnu_java_nio_PipeImpl.h"
140 #include "native/include/gnu_java_nio_channels_FileChannelImpl.h"
141 #include "native/include/gnu_java_nio_charset_iconv_IconvEncoder.h"
142 #include "native/include/gnu_java_nio_charset_iconv_IconvDecoder.h"
143 #include "native/include/java_lang_VMProcess.h"
144 #include "native/include/java_nio_MappedByteBufferImpl.h"
145 #include "native/include/java_nio_channels_spi_SelectorProvider.h"
146
147 /* now include the native table */
148
149 #include "native/nativetable.inc"
150
151 #elif !defined(ENABLE_LIBJVM)
152
153 /* dummynativetable ************************************************************
154
155    Ensure that symbols for functions implemented within CACAO are used
156    and exported to dlopen.
157
158    ATTENTION: Don't make this table static!!!  Otherwise the compiler
159    may optimize it away!
160
161 *******************************************************************************/
162
163 functionptr dummynativetable[] = {
164 #if defined(ENABLE_JAVASE)
165         (functionptr) Java_gnu_classpath_VMStackWalker_getClassContext,
166         (functionptr) Java_gnu_classpath_VMStackWalker_getCallingClass,
167         (functionptr) Java_gnu_classpath_VMStackWalker_getCallingClassLoader,
168         (functionptr) Java_gnu_classpath_VMStackWalker_firstNonNullClassLoader,
169
170         (functionptr) Java_gnu_classpath_VMSystemProperties_preInit,
171
172         (functionptr) Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getLoadedClassCount,
173         (functionptr) Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getUnloadedClassCount,
174         (functionptr) Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_isVerbose,
175         (functionptr) Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_setVerbose,
176
177         (functionptr) Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getHeapMemoryUsage,
178         (functionptr) Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getNonHeapMemoryUsage,
179         (functionptr) Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getObjectPendingFinalizationCount,
180         (functionptr) Java_gnu_java_lang_management_VMMemoryMXBeanImpl_isVerbose,
181         (functionptr) Java_gnu_java_lang_management_VMMemoryMXBeanImpl_setVerbose,
182
183         (functionptr) Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getInputArguments,
184         (functionptr) Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getStartTime,
185
186         (functionptr) Java_java_lang_VMClass_isInstance,
187         (functionptr) Java_java_lang_VMClass_isAssignableFrom,
188         (functionptr) Java_java_lang_VMClass_isInterface,
189         (functionptr) Java_java_lang_VMClass_isPrimitive,
190         (functionptr) Java_java_lang_VMClass_getName,
191         (functionptr) Java_java_lang_VMClass_getSuperclass,
192         (functionptr) Java_java_lang_VMClass_getInterfaces,
193         (functionptr) Java_java_lang_VMClass_getComponentType,
194         (functionptr) Java_java_lang_VMClass_getModifiers,
195         (functionptr) Java_java_lang_VMClass_getDeclaringClass,
196         (functionptr) Java_java_lang_VMClass_getDeclaredClasses,
197         (functionptr) Java_java_lang_VMClass_getDeclaredFields,
198         (functionptr) Java_java_lang_VMClass_getDeclaredMethods,
199         (functionptr) Java_java_lang_VMClass_getDeclaredConstructors,
200         (functionptr) Java_java_lang_VMClass_getClassLoader,
201         (functionptr) Java_java_lang_VMClass_forName,
202         (functionptr) Java_java_lang_VMClass_isArray,
203         (functionptr) Java_java_lang_VMClass_throwException,
204
205         (functionptr) Java_java_lang_VMClassLoader_defineClass,
206         (functionptr) Java_java_lang_VMClassLoader_resolveClass,
207         (functionptr) Java_java_lang_VMClassLoader_loadClass,
208         (functionptr) Java_java_lang_VMClassLoader_getPrimitiveClass,
209         (functionptr) Java_java_lang_VMClassLoader_nativeGetResources,
210         (functionptr) Java_java_lang_VMClassLoader_findLoadedClass,
211
212         (functionptr) Java_java_lang_VMObject_getClass,
213         (functionptr) Java_java_lang_VMObject_clone,
214         (functionptr) Java_java_lang_VMObject_notify,
215         (functionptr) Java_java_lang_VMObject_notifyAll,
216         (functionptr) Java_java_lang_VMObject_wait,
217
218         (functionptr) Java_java_lang_VMRuntime_availableProcessors,
219         (functionptr) Java_java_lang_VMRuntime_freeMemory,
220         (functionptr) Java_java_lang_VMRuntime_totalMemory,
221         (functionptr) Java_java_lang_VMRuntime_maxMemory,
222         (functionptr) Java_java_lang_VMRuntime_gc,
223         (functionptr) Java_java_lang_VMRuntime_runFinalization,
224         (functionptr) Java_java_lang_VMRuntime_runFinalizationForExit,
225         (functionptr) Java_java_lang_VMRuntime_traceInstructions,
226         (functionptr) Java_java_lang_VMRuntime_traceMethodCalls,
227         (functionptr) Java_java_lang_VMRuntime_runFinalizersOnExit,
228         (functionptr) Java_java_lang_VMRuntime_exit,
229         (functionptr) Java_java_lang_VMRuntime_nativeLoad,
230         (functionptr) Java_java_lang_VMRuntime_mapLibraryName,
231
232         (functionptr) Java_java_lang_VMString_intern,
233
234         (functionptr) Java_java_lang_VMSystem_arraycopy,
235         (functionptr) Java_java_lang_VMSystem_identityHashCode,
236
237         (functionptr) Java_java_lang_VMThread_start,
238         (functionptr) Java_java_lang_VMThread_interrupt,
239         (functionptr) Java_java_lang_VMThread_isInterrupted,
240         (functionptr) Java_java_lang_VMThread_suspend,
241         (functionptr) Java_java_lang_VMThread_resume,
242         (functionptr) Java_java_lang_VMThread_nativeSetPriority,
243         (functionptr) Java_java_lang_VMThread_nativeStop,
244         (functionptr) Java_java_lang_VMThread_currentThread,
245         (functionptr) Java_java_lang_VMThread_yield,
246         (functionptr) Java_java_lang_VMThread_interrupted,
247         (functionptr) Java_java_lang_VMThread_holdsLock,
248         (functionptr) Java_java_lang_VMThread_getState,
249
250         (functionptr) Java_java_lang_VMThrowable_fillInStackTrace,
251         (functionptr) Java_java_lang_VMThrowable_getStackTrace,
252
253         (functionptr) Java_java_lang_management_VMManagementFactory_getMemoryPoolNames,
254         (functionptr) Java_java_lang_management_VMManagementFactory_getMemoryManagerNames,
255         (functionptr) Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames,
256
257         (functionptr) Java_java_lang_reflect_Constructor_getModifiersInternal,
258         (functionptr) Java_java_lang_reflect_Constructor_constructNative,
259
260         (functionptr) Java_java_lang_reflect_Field_getModifiersInternal,
261         (functionptr) Java_java_lang_reflect_Field_getType,
262         (functionptr) Java_java_lang_reflect_Field_get,
263         (functionptr) Java_java_lang_reflect_Field_getBoolean,
264         (functionptr) Java_java_lang_reflect_Field_getByte,
265         (functionptr) Java_java_lang_reflect_Field_getChar,
266         (functionptr) Java_java_lang_reflect_Field_getShort,
267         (functionptr) Java_java_lang_reflect_Field_getInt,
268         (functionptr) Java_java_lang_reflect_Field_getLong,
269         (functionptr) Java_java_lang_reflect_Field_getFloat,
270         (functionptr) Java_java_lang_reflect_Field_getDouble,
271         (functionptr) Java_java_lang_reflect_Field_set,
272         (functionptr) Java_java_lang_reflect_Field_setBoolean,
273         (functionptr) Java_java_lang_reflect_Field_setByte,
274         (functionptr) Java_java_lang_reflect_Field_setChar,
275         (functionptr) Java_java_lang_reflect_Field_setShort,
276         (functionptr) Java_java_lang_reflect_Field_setInt,
277         (functionptr) Java_java_lang_reflect_Field_setLong,
278         (functionptr) Java_java_lang_reflect_Field_setFloat,
279         (functionptr) Java_java_lang_reflect_Field_setDouble,
280
281         (functionptr) Java_java_lang_reflect_Method_getModifiersInternal,
282         (functionptr) Java_java_lang_reflect_Method_getReturnType,
283         (functionptr) Java_java_lang_reflect_Method_getParameterTypes,
284         (functionptr) Java_java_lang_reflect_Method_getExceptionTypes,
285         (functionptr) Java_java_lang_reflect_Method_invokeNative,
286
287         (functionptr) Java_java_lang_reflect_VMProxy_getProxyClass,
288         (functionptr) Java_java_lang_reflect_VMProxy_getProxyData,
289         (functionptr) Java_java_lang_reflect_VMProxy_generateProxyClass,
290
291         (functionptr) Java_java_security_VMAccessController_getStack,
292
293         (functionptr) Java_sun_misc_Unsafe_objectFieldOffset,
294         (functionptr) Java_sun_misc_Unsafe_compareAndSwapInt,
295
296 #if defined(ENABLE_JVMTI)
297         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_suspendThread,
298         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_resumeThread,
299         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getSuspendCount,
300         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getAllLoadedClassesCount,
301         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getClassStatus,
302         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getAllClassMethods,
303         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getClassMethod,
304         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getFrames,
305         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getFrame,
306         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getFrameCount,
307         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getThreadStatus,
308         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getLoadRequests,
309         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_executeMethod,
310         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getSourceFile,
311         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_registerEvent,
312         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_unregisterEvent,
313         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_clearEvents,
314         (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getAllLoadedClasses,
315         (functionptr) Java_gnu_classpath_jdwp_VMFrame_setValue,
316         (functionptr) Java_gnu_classpath_jdwp_VMFrame_getValue,
317         (functionptr) Java_gnu_classpath_jdwp_VMMethod_getName,
318         (functionptr) Java_gnu_classpath_jdwp_VMMethod_getSignature,
319         (functionptr) Java_gnu_classpath_jdwp_VMMethod_getModifiers,
320         (functionptr) Java_gnu_classpath_jdwp_VMMethod_getLineTable,
321         (functionptr) Java_gnu_classpath_jdwp_VMMethod_getVariableTable
322 #endif
323
324 #elif defined(ENABLE_JAVAME_CLDC1_1)
325         (functionptr) Java_com_sun_cldc_io_ResourceInputStream_open,
326
327         (functionptr) Java_com_sun_cldc_io_j2me_socket_Protocol_open0,
328         (functionptr) Java_com_sun_cldc_io_j2me_socket_Protocol_readBuf,
329         (functionptr) Java_com_sun_cldc_io_j2me_socket_Protocol_writeByte,
330
331         (functionptr) Java_com_sun_cldchi_io_ConsoleOutputStream_write,
332
333         (functionptr) Java_java_lang_Class_forName,
334         (functionptr) Java_java_lang_Class_newInstance,
335         (functionptr) Java_java_lang_Class_isInstance,
336         (functionptr) Java_java_lang_Class_isAssignableFrom,
337         (functionptr) Java_java_lang_Class_isInterface,
338         (functionptr) Java_java_lang_Class_isArray,
339         (functionptr) Java_java_lang_Class_getName,
340
341         (functionptr) Java_java_lang_Double_doubleToLongBits,
342
343         (functionptr) Java_java_lang_Float_floatToIntBits,
344
345         (functionptr) Java_java_lang_Math_ceil,
346         (functionptr) Java_java_lang_Math_cos,
347         (functionptr) Java_java_lang_Math_floor,
348         (functionptr) Java_java_lang_Math_sin,
349         (functionptr) Java_java_lang_Math_sqrt,
350         (functionptr) Java_java_lang_Math_tan,
351
352         (functionptr) Java_java_lang_Object_hashCode,
353         (functionptr) Java_java_lang_Object_notify,
354         (functionptr) Java_java_lang_Object_wait,
355
356         (functionptr) Java_java_lang_Runtime_exitInternal,
357         (functionptr) Java_java_lang_Runtime_freeMemory,
358         (functionptr) Java_java_lang_Runtime_totalMemory,
359         (functionptr) Java_java_lang_Runtime_gc,
360
361         (functionptr) Java_java_lang_String_hashCode,
362         (functionptr) Java_java_lang_String_indexOf__I,
363         (functionptr) Java_java_lang_String_indexOf__II,
364         (functionptr) Java_java_lang_String_lastIndexOf__II,
365         (functionptr) Java_java_lang_String_intern,
366
367         (functionptr) Java_java_lang_System_getProperty0,
368
369         (functionptr) Java_java_lang_Thread_currentThread,
370         (functionptr) Java_java_lang_Thread_setPriority0,
371         (functionptr) Java_java_lang_Thread_start0,
372         (functionptr) Java_java_lang_Thread_yield,
373
374         (functionptr) Java_java_lang_Throwable_printStackTrace,
375         (functionptr) Java_java_lang_Throwable_fillInStackTrace
376 #endif
377 };
378
379 #endif /* defined(ENABLE_LIBJVM) */
380
381
382 /* tables for methods *********************************************************/
383
384 #if defined(WITH_STATIC_CLASSPATH)
385 #define NATIVETABLESIZE  (sizeof(nativetable)/sizeof(struct nativeref))
386
387 /* table for fast string comparison */
388 static nativecompref nativecomptable[NATIVETABLESIZE];
389
390 /* string comparsion table initialized */
391 static bool nativecompdone = false;
392 #endif
393
394
395 /* global variables ***********************************************************/
396
397 #if !defined(WITH_STATIC_CLASSPATH)
398 static hashtable *hashtable_library;
399 static lt_dlhandle mainhandle;
400 #endif
401
402
403 /* native_init *****************************************************************
404
405    Initializes the native subsystem.
406
407 *******************************************************************************/
408
409 bool native_init(void)
410 {
411 #if !defined(WITH_STATIC_CLASSPATH)
412         /* initialize libltdl */
413
414         if (lt_dlinit())
415                 vm_abort("native_init: lt_dlinit failed: %s\n", lt_dlerror());
416
417         /* Get the handle for the main program or for the libjvm.so,
418            depends on the configuration. */
419
420 # if defined(ENABLE_LIBJVM)
421         /* First try to open where dlopen searches, e.g. LD_LIBRARY_PATH.
422            If not found, try the absolute path. */
423
424         if (!(mainhandle = lt_dlopenext("libjvm")))
425                 if (!(mainhandle = lt_dlopenext(cacao_libjvm)))
426                         vm_abort("native_init: lt_dlopenext failed: %s\n", lt_dlerror());
427 # else
428         if (!(mainhandle = lt_dlopen(NULL)))
429                 vm_abort("native_init: lt_dlopen failed: %s\n", lt_dlerror());
430 # endif
431
432         /* initialize library hashtable, 10 entries should be enough */
433
434         hashtable_library = NEW(hashtable);
435
436         hashtable_create(hashtable_library, 10);
437 #endif
438
439         /* everything's ok */
440
441         return true;
442 }
443
444
445 /* native_hashtable_library_add ************************************************
446
447    Adds an entry to the native library hashtable.
448
449 *******************************************************************************/
450
451 #if !defined(WITH_STATIC_CLASSPATH)
452 void native_hashtable_library_add(utf *filename, java_objectheader *loader,
453                                                                   lt_dlhandle handle)
454 {
455         hashtable_classloader_entry    *cle;
456         hashtable_library_loader_entry *le;
457         hashtable_library_name_entry   *ne; /* library name                       */
458         u4   key;                           /* hashkey                            */
459         u4   slot;                          /* slot in hashtable                  */
460
461         LOCK_MONITOR_ENTER(hashtable_library->header);
462
463         /* insert loader into the classloader hashtable */
464
465         cle = loader_hashtable_classloader_add(loader);
466
467         /* normally addresses are aligned to 4, 8 or 16 bytes */
468
469         key  = ((u4) (ptrint) cle) >> 4;        /* align to 16-byte boundaries    */
470         slot = key & (hashtable_library->size - 1);
471         le   = hashtable_library->ptr[slot];
472
473         /* search external hash chain for the entry */
474
475         while (le) {
476                 if (le->cle == cle)
477                         break;
478
479                 le = le->hashlink;                  /* next element in external chain */
480         }
481
482         /* no loader found? create a new entry */
483
484         if (le == NULL) {
485                 le = NEW(hashtable_library_loader_entry);
486
487                 le->cle   = cle;
488                 le->namelink = NULL;
489
490                 /* insert entry into hashtable */
491
492                 le->hashlink =
493                         (hashtable_library_loader_entry *) hashtable_library->ptr[slot];
494                 hashtable_library->ptr[slot] = le;
495
496                 /* update number of hashtable-entries */
497
498                 hashtable_library->entries++;
499         }
500
501
502         /* search for library name */
503
504         ne = le->namelink;
505
506         while (ne) {
507                 if (ne->name == filename) {
508                         LOCK_MONITOR_EXIT(hashtable_library->header);
509
510                         return;
511                 }
512
513                 ne = ne->hashlink;                  /* next element in external chain */
514         }
515
516         /* not found? add the library name to the classloader */
517
518         ne = NEW(hashtable_library_name_entry);
519
520         ne->name   = filename;
521         ne->handle = handle;
522
523         /* insert entry into external chain */
524
525         ne->hashlink = le->namelink;
526         le->namelink = ne;
527
528         LOCK_MONITOR_EXIT(hashtable_library->header);
529 }
530 #endif /* !defined(WITH_STATIC_CLASSPATH) */
531
532
533 /* native_hashtable_library_find ***********************************************
534
535    Find an entry in the native library hashtable.
536
537 *******************************************************************************/
538
539 #if !defined(WITH_STATIC_CLASSPATH)
540 hashtable_library_name_entry *native_hashtable_library_find(utf *filename,
541                                                                                                                         java_objectheader *loader)
542 {
543         hashtable_classloader_entry    *cle;
544         hashtable_library_loader_entry *le;
545         hashtable_library_name_entry   *ne; /* library name                       */
546         u4   key;                           /* hashkey                            */
547         u4   slot;                          /* slot in hashtable                  */
548
549         /* search loader in the classloader hashtable */
550
551         cle = loader_hashtable_classloader_find(loader);
552
553         if (!cle)
554                 return NULL;
555
556         /* normally addresses are aligned to 4, 8 or 16 bytes */
557
558         key  = ((u4) (ptrint) cle) >> 4;        /* align to 16-byte boundaries    */
559         slot = key & (hashtable_library->size - 1);
560         le   = hashtable_library->ptr[slot];
561
562         /* search external hash chain for the entry */
563
564         while (le) {
565                 if (le->cle == cle)
566                         break;
567
568                 le = le->hashlink;                  /* next element in external chain */
569         }
570
571         /* no loader found? return NULL */
572
573         if (!le)
574                 return NULL;
575
576         /* search for library name */
577
578         ne = le->namelink;
579
580         while (ne) {
581                 if (ne->name == filename)
582                         return ne;
583
584                 ne = ne->hashlink;                  /* next element in external chain */
585         }
586
587         /* return entry, if no entry was found, ne is NULL */
588
589         return ne;
590 }
591 #endif /* !defined(WITH_STATIC_CLASSPATH) */
592
593
594 /* native_findfunction *********************************************************
595
596    Looks up a method (must have the same class name, method name,
597    descriptor and 'static'ness) and returns a function pointer to it.
598    Returns: function pointer or NULL (if there is no such method)
599
600    Remark: For faster operation, the names/descriptors are converted
601    from C strings to Unicode the first time this function is called.
602
603 *******************************************************************************/
604
605 #if defined(WITH_STATIC_CLASSPATH)
606 functionptr native_findfunction(utf *cname, utf *mname, utf *desc,
607                                                                 bool isstatic)
608 {
609         /* entry of table for fast string comparison */
610         struct nativecompref *n;
611         s4 i;
612
613         isstatic = isstatic ? true : false;
614         
615         if (!nativecompdone) {
616                 for (i = 0; i < NATIVETABLESIZE; i++) {
617                         nativecomptable[i].classname  = 
618                                 utf_new_char(nativetable[i].classname);
619
620                         nativecomptable[i].methodname = 
621                                 utf_new_char(nativetable[i].methodname);
622
623                         nativecomptable[i].descriptor =
624                                 utf_new_char(nativetable[i].descriptor);
625
626                         nativecomptable[i].isstatic   = nativetable[i].isstatic;
627                         nativecomptable[i].func       = nativetable[i].func;
628                 }
629
630                 nativecompdone = true;
631         }
632
633         for (i = 0; i < NATIVETABLESIZE; i++) {
634                 n = &(nativecomptable[i]);
635
636                 if (cname == n->classname && mname == n->methodname &&
637                     desc == n->descriptor && isstatic == n->isstatic)
638                         return n->func;
639         }
640
641         /* no function was found, throw exception */
642
643         *exceptionptr =
644                         new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
645                                                                          mname);
646
647         return NULL;
648 }
649 #endif /* defined(WITH_STATIC_CLASSPATH) */
650
651
652 /* native_make_overloaded_function *********************************************
653
654    XXX
655
656 *******************************************************************************/
657
658 #if !defined(WITH_STATIC_CLASSPATH)
659 static char *native_make_overloaded_function(char *name, utf *desc)
660 {
661         char *newname;
662         s4    namelen;
663         char *utf_ptr;
664         u2    c;
665         s4    i;
666
667         utf_ptr = desc->text;
668         namelen = strlen(name) + strlen("__") + strlen("0");
669
670         /* calculate additional length */
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 'I':
679                 case 'J':
680                 case 'F':
681                 case 'D':
682                         namelen++;
683                         break;
684                 case '[':
685                         namelen += 2;
686                         break;
687                 case 'L':
688                         namelen++;
689                         while (utf_nextu2(&utf_ptr) != ';')
690                                 namelen++;
691                         namelen += 2;
692                         break;
693                 case '(':
694                         break;
695                 default:
696                         assert(0);
697                 }
698         }
699
700
701         /* reallocate memory */
702
703         i = strlen(name);
704
705         newname = DMNEW(char, namelen);
706         MCOPY(newname, name, char, i);
707
708         utf_ptr = desc->text;
709
710         newname[i++] = '_';
711         newname[i++] = '_';
712
713         while ((c = utf_nextu2(&utf_ptr)) != ')') {
714                 switch (c) {
715                 case 'Z':
716                 case 'B':
717                 case 'C':
718                 case 'S':
719                 case 'J':
720                 case 'I':
721                 case 'F':
722                 case 'D':
723                         newname[i++] = c;
724                         break;
725                 case '[':
726                         newname[i++] = '_';
727                         newname[i++] = '3';
728                         break;
729                 case 'L':
730                         newname[i++] = 'L';
731                         while ((c = utf_nextu2(&utf_ptr)) != ';')
732                                 if (((c >= 'a') && (c <= 'z')) ||
733                                         ((c >= 'A') && (c <= 'Z')) ||
734                                         ((c >= '0') && (c <= '9')))
735                                         newname[i++] = c;
736                                 else
737                                         newname[i++] = '_';
738                         newname[i++] = '_';
739                         newname[i++] = '2';
740                         break;
741                 case '(':
742                         break;
743                 default:
744                         assert(0);
745                 }
746         }
747
748         /* close string */
749
750         newname[i] = '\0';
751
752         return newname;
753 }
754
755
756 /* native_insert_char **********************************************************
757
758    Inserts the passed UTF character into the native method name.  If
759    necessary it is escaped properly.
760
761 *******************************************************************************/
762
763 static s4 native_insert_char(char *name, u4 pos, u2 c)
764 {
765         s4 val;
766         s4 i;
767
768         switch (c) {
769         case '/':
770         case '.':
771                 /* replace '/' or '.' with '_' */
772                 name[pos] = '_';
773                 break;
774
775         case '_':
776                 /* escape sequence for '_' is '_1' */
777                 name[pos]   = '_';
778                 name[++pos] = '1';
779                 break;
780
781         case ';':
782                 /* escape sequence for ';' is '_2' */
783                 name[pos]   = '_';
784                 name[++pos] = '2';
785                 break;
786
787         case '[':
788                 /* escape sequence for '[' is '_1' */
789                 name[pos]   = '_';
790                 name[++pos] = '3';
791                 break;
792
793         default:
794                 if (isalnum(c))
795                         name[pos] = c;
796                 else {
797                         /* unicode character */
798                         name[pos]   = '_';
799                         name[++pos] = '0';
800
801                         for (i = 0; i < 4; ++i) {
802                                 val = c & 0x0f;
803                                 name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
804                                 c >>= 4;
805                         }
806
807                         pos += 4;
808                 }
809                 break;
810         }
811
812         /* return the new buffer index */
813
814         return pos;
815 }
816
817
818 /* native_resolve_function *****************************************************
819
820    Resolves a native function, maybe from a dynamic library.
821
822 *******************************************************************************/
823
824 functionptr native_resolve_function(methodinfo *m)
825 {
826         lt_ptr                          sym;
827         char                           *name;
828         char                           *newname;
829         s4                              namelen;
830         char                           *utf_ptr;
831         char                           *utf_endptr;
832         u2                              c;
833         u4                              pos;
834         s4                              dumpsize;
835         hashtable_library_loader_entry *le;
836         hashtable_library_name_entry   *ne;
837         u4                              key;    /* hashkey                        */
838         u4                              slot;   /* slot in hashtable              */
839
840         /* verbose output */
841
842         if (opt_verbosejni) {
843                 printf("[Dynamic-linking native method ");
844                 utf_display_printable_ascii_classname(m->class->name);
845                 printf(".");
846                 utf_display_printable_ascii(m->name);
847                 printf(" ... ");
848         }
849                 
850         /* Calculate length of native function name.  We multiply the
851            class and method name length by 6 as this is the maxium
852            escape-sequence that can be generated (unicode). */
853
854         namelen = strlen("Java_") +
855                 utf_get_number_of_u2s(m->class->name) * 6 +
856                 strlen("_") +
857                 utf_get_number_of_u2s(m->name) * 6 +
858                 strlen("0");
859
860         /* allocate memory */
861
862         dumpsize = dump_size();
863
864         name = DMNEW(char, namelen);
865
866         /* generate name of native functions */
867
868         strcpy(name, "Java_");
869         pos = strlen("Java_");
870
871         utf_ptr    = m->class->name->text;
872         utf_endptr = UTF_END(m->class->name);
873
874         for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
875                 c   = *utf_ptr;
876                 pos = native_insert_char(name, pos, c);
877         }
878
879         /* seperator between class and method */
880
881         name[pos++] = '_';
882
883         utf_ptr    = m->name->text;
884         utf_endptr = UTF_END(m->name);
885
886         for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
887                 c   = *utf_ptr;
888                 pos = native_insert_char(name, pos, c);
889         }
890
891         /* close string */
892
893         name[pos] = '\0';
894
895         /* check for an buffer overflow */
896
897         assert(pos <= namelen);
898
899         /* generate overloaded function (having the types in it's name)           */
900
901         newname = native_make_overloaded_function(name, m->descriptor);
902
903         /* check the library hash entries of the classloader of the
904            methods's class  */
905
906         sym = NULL;
907
908         /* normally addresses are aligned to 4, 8 or 16 bytes */
909
910         key  = ((u4) (ptrint) m->class->classloader) >> 4;    /* align to 16-byte */
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 /*
1157  * These are local overrides for various environment variables in Emacs.
1158  * Please do not remove this and leave it at the end of the file, where
1159  * Emacs will automagically detect them.
1160  * ---------------------------------------------------------------------
1161  * Local variables:
1162  * mode: c
1163  * indent-tabs-mode: t
1164  * c-basic-offset: 4
1165  * tab-width: 4
1166  * End:
1167  */