f588206ce1ad7b902ec030ac138297c0815072b7
[cacao.git] / src / native / native.c
1 /* src/native/native.c - table of native functions
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    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., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28             Roman Obermaisser
29             Andreas Krall
30
31    Changes: Christian Thalinger
32
33    $Id: native.c 3445 2005-10-19 11:28:41Z twisti $
34
35 */
36
37
38 #include <assert.h>
39
40 #include "config.h"
41 #include "vm/types.h"
42
43 #include "cacao/cacao.h"
44 #include "mm/memory.h"
45 #include "native/jni.h"
46 #include "native/native.h"
47 #include "native/include/java_lang_Throwable.h"
48 #include "toolbox/logging.h"
49 #include "vm/builtin.h"
50 #include "vm/exceptions.h"
51 #include "vm/global.h"
52 #include "vm/loader.h"
53 #include "vm/options.h"
54 #include "vm/resolve.h"
55 #include "vm/stringlocal.h"
56 #include "vm/tables.h"
57 #include "vm/jit/asmpart.h"
58 #include "vm/jit/jit.h"
59
60 #if !defined(ENABLE_STATICVM)
61 # include "libltdl/ltdl.h"
62 #endif
63
64
65 /* include table of native functions ******************************************/
66
67 #include "native/include/java_lang_Cloneable.h"
68 #include "native/include/java_util_Properties.h"
69 #include "native/include/java_io_InputStream.h"
70 #include "native/include/java_io_PrintStream.h"
71
72 #include "native/include/gnu_classpath_VMStackWalker.h"
73 #include "native/include/gnu_classpath_VMSystemProperties.h"
74 #include "native/include/java_lang_Class.h"
75 #include "native/include/java_lang_Object.h"
76 #include "native/include/java_lang_VMClass.h"
77 #include "native/include/java_lang_VMClassLoader.h"
78 #include "native/include/java_lang_VMObject.h"
79 #include "native/include/java_lang_VMRuntime.h"
80 #include "native/include/java_lang_VMString.h"
81 #include "native/include/java_lang_VMSystem.h"
82 #include "native/include/java_lang_VMThread.h"
83 #include "native/include/java_lang_VMThrowable.h"
84 #include "native/include/java_lang_reflect_Constructor.h"
85 #include "native/include/java_lang_reflect_Field.h"
86 #include "native/include/java_lang_reflect_Method.h"
87 #include "native/include/java_lang_reflect_VMProxy.h"
88 #include "native/include/java_security_VMAccessController.h"
89
90 #if defined(ENABLE_STATICVM)
91
92 /* these are required to prevent compiler warnings */
93
94 #include "native/include/java_net_DatagramPacket.h"
95 #include "native/include/java_net_InetAddress.h"
96 #include "native/include/java_net_SocketImpl.h"
97
98 #include "native/include/gnu_java_net_PlainDatagramSocketImpl.h"
99 #include "native/include/gnu_java_net_PlainSocketImpl.h"
100 #include "native/include/gnu_java_nio_PipeImpl.h"
101 #include "native/include/gnu_java_nio_channels_FileChannelImpl.h"
102 #include "native/include/gnu_java_nio_charset_iconv_IconvEncoder.h"
103 #include "native/include/gnu_java_nio_charset_iconv_IconvDecoder.h"
104 #include "native/include/java_lang_VMProcess.h"
105 #include "native/include/java_nio_MappedByteBufferImpl.h"
106 #include "native/include/java_nio_channels_spi_SelectorProvider.h"
107
108 /* now include the native table */
109
110 #include "native/nativetable.inc"
111
112 #else /* defined(ENABLE_STATICVM) */
113
114 /* Ensure that symbols for functions implemented within CACAO are used and    */
115 /* exported to dlopen.                                                        */
116
117 static functionptr dummynativetable[] = {
118         (functionptr) Java_gnu_classpath_VMStackWalker_getClassContext,
119
120         (functionptr) Java_gnu_classpath_VMSystemProperties_preInit,
121
122         (functionptr) Java_java_lang_VMClass_isInstance,
123         (functionptr) Java_java_lang_VMClass_isAssignableFrom,
124         (functionptr) Java_java_lang_VMClass_isInterface,
125         (functionptr) Java_java_lang_VMClass_isPrimitive,
126         (functionptr) Java_java_lang_VMClass_getName,
127         (functionptr) Java_java_lang_VMClass_getSuperclass,
128         (functionptr) Java_java_lang_VMClass_getInterfaces,
129         (functionptr) Java_java_lang_VMClass_getComponentType,
130         (functionptr) Java_java_lang_VMClass_getModifiers,
131         (functionptr) Java_java_lang_VMClass_getDeclaringClass,
132         (functionptr) Java_java_lang_VMClass_getDeclaredClasses,
133         (functionptr) Java_java_lang_VMClass_getDeclaredFields,
134         (functionptr) Java_java_lang_VMClass_getDeclaredMethods,
135         (functionptr) Java_java_lang_VMClass_getDeclaredConstructors,
136         (functionptr) Java_java_lang_VMClass_getClassLoader,
137         (functionptr) Java_java_lang_VMClass_forName,
138         (functionptr) Java_java_lang_VMClass_isArray,
139         (functionptr) Java_java_lang_VMClass_throwException,
140
141         (functionptr) Java_java_lang_VMClassLoader_defineClass,
142         (functionptr) Java_java_lang_VMClassLoader_resolveClass,
143         (functionptr) Java_java_lang_VMClassLoader_loadClass,
144         (functionptr) Java_java_lang_VMClassLoader_getPrimitiveClass,
145         (functionptr) Java_java_lang_VMClassLoader_nativeGetResources,
146         (functionptr) Java_java_lang_VMClassLoader_findLoadedClass,
147
148         (functionptr) Java_java_lang_VMObject_getClass,
149         (functionptr) Java_java_lang_VMObject_clone,
150         (functionptr) Java_java_lang_VMObject_notify,
151         (functionptr) Java_java_lang_VMObject_notifyAll,
152         (functionptr) Java_java_lang_VMObject_wait,
153
154         (functionptr) Java_java_lang_VMRuntime_availableProcessors,
155         (functionptr) Java_java_lang_VMRuntime_freeMemory,
156         (functionptr) Java_java_lang_VMRuntime_totalMemory,
157         (functionptr) Java_java_lang_VMRuntime_maxMemory,
158         (functionptr) Java_java_lang_VMRuntime_gc,
159         (functionptr) Java_java_lang_VMRuntime_runFinalization,
160         (functionptr) Java_java_lang_VMRuntime_runFinalizationForExit,
161         (functionptr) Java_java_lang_VMRuntime_traceInstructions,
162         (functionptr) Java_java_lang_VMRuntime_traceMethodCalls,
163         (functionptr) Java_java_lang_VMRuntime_runFinalizersOnExit,
164         (functionptr) Java_java_lang_VMRuntime_exit,
165         (functionptr) Java_java_lang_VMRuntime_nativeLoad,
166         (functionptr) Java_java_lang_VMRuntime_mapLibraryName,
167
168         (functionptr) Java_java_lang_VMString_intern,
169
170         (functionptr) Java_java_lang_VMSystem_arraycopy,
171         (functionptr) Java_java_lang_VMSystem_identityHashCode,
172
173         (functionptr) Java_java_lang_VMThread_start,
174         (functionptr) Java_java_lang_VMThread_interrupt,
175         (functionptr) Java_java_lang_VMThread_isInterrupted,
176         (functionptr) Java_java_lang_VMThread_suspend,
177         (functionptr) Java_java_lang_VMThread_resume,
178         (functionptr) Java_java_lang_VMThread_nativeSetPriority,
179         (functionptr) Java_java_lang_VMThread_nativeStop,
180         (functionptr) Java_java_lang_VMThread_currentThread,
181         (functionptr) Java_java_lang_VMThread_yield,
182         (functionptr) Java_java_lang_VMThread_interrupted,
183         (functionptr) Java_java_lang_VMThread_holdsLock,
184
185         (functionptr) Java_java_lang_VMThrowable_fillInStackTrace,
186         (functionptr) Java_java_lang_VMThrowable_getStackTrace,
187
188         (functionptr) Java_java_lang_reflect_Constructor_getModifiers,
189         (functionptr) Java_java_lang_reflect_Constructor_constructNative,
190
191         (functionptr) Java_java_lang_reflect_Field_getModifiers,
192         (functionptr) Java_java_lang_reflect_Field_getType,
193         (functionptr) Java_java_lang_reflect_Field_get,
194         (functionptr) Java_java_lang_reflect_Field_getBoolean,
195         (functionptr) Java_java_lang_reflect_Field_getByte,
196         (functionptr) Java_java_lang_reflect_Field_getChar,
197         (functionptr) Java_java_lang_reflect_Field_getShort,
198         (functionptr) Java_java_lang_reflect_Field_getInt,
199         (functionptr) Java_java_lang_reflect_Field_getLong,
200         (functionptr) Java_java_lang_reflect_Field_getFloat,
201         (functionptr) Java_java_lang_reflect_Field_getDouble,
202         (functionptr) Java_java_lang_reflect_Field_set,
203         (functionptr) Java_java_lang_reflect_Field_setBoolean,
204         (functionptr) Java_java_lang_reflect_Field_setByte,
205         (functionptr) Java_java_lang_reflect_Field_setChar,
206         (functionptr) Java_java_lang_reflect_Field_setShort,
207         (functionptr) Java_java_lang_reflect_Field_setInt,
208         (functionptr) Java_java_lang_reflect_Field_setLong,
209         (functionptr) Java_java_lang_reflect_Field_setFloat,
210         (functionptr) Java_java_lang_reflect_Field_setDouble,
211
212         (functionptr) Java_java_lang_reflect_Method_getModifiers,
213         (functionptr) Java_java_lang_reflect_Method_getReturnType,
214         (functionptr) Java_java_lang_reflect_Method_getParameterTypes,
215         (functionptr) Java_java_lang_reflect_Method_getExceptionTypes,
216         (functionptr) Java_java_lang_reflect_Method_invokeNative,
217
218         (functionptr) Java_java_lang_reflect_VMProxy_getProxyClass,
219         (functionptr) Java_java_lang_reflect_VMProxy_getProxyData,
220         (functionptr) Java_java_lang_reflect_VMProxy_generateProxyClass,
221
222         (functionptr) Java_java_security_VMAccessController_getStack,
223 };
224
225 #endif /* defined(ENABLE_STATICVM) */
226
227
228 /************* use classinfo structure as java.lang.Class object **************/
229
230 bool use_class_as_object(classinfo *c)
231 {
232         if (!c->classvftbl) {
233                 /* is the class loaded */
234                 if (!c->loaded) {
235 /*                      if (!class_load(c)) */
236 /*                              throw_exception_exit(); */
237                         log_text("use_class_as_object: class_load should not happen");
238                         assert(0);
239                 }
240
241                 /* is the class linked */
242                 if (!c->linked)
243                         if (!link_class(c))
244                                 return false;
245
246                 assert(class_java_lang_Class);
247
248                 c->header.vftbl = class_java_lang_Class->vftbl;
249                 c->classvftbl = true;
250         }
251
252         return true;
253 }
254
255
256 /************************** tables for methods ********************************/
257
258 #undef JOWENN_DEBUG
259 #undef JOWENN_DEBUG1
260
261 #ifdef ENABLE_STATICVM
262 #define NATIVETABLESIZE  (sizeof(nativetable)/sizeof(struct nativeref))
263
264 /* table for fast string comparison */
265 static nativecompref nativecomptable[NATIVETABLESIZE];
266
267 /* string comparsion table initialized */
268 static bool nativecompdone = false;
269 #endif
270
271
272 /* XXX don't define this in a header file!!! */
273
274 static struct nativeCall nativeCalls[] =
275 {
276 #include "nativecalls.inc"
277 };
278
279 #define NATIVECALLSSIZE    (sizeof(nativeCalls) / sizeof(struct nativeCall))
280
281 struct nativeCompCall nativeCompCalls[NATIVECALLSSIZE];
282
283
284 /* global variables ***********************************************************/
285
286 #if !defined(ENABLE_STATICVM)
287 static hashtable library_hash;
288 static lt_dlhandle mainhandle;
289 #endif
290
291
292 /* native_loadclasses **********************************************************
293
294    Load classes required for native methods.
295
296 *******************************************************************************/
297
298 bool native_init(void)
299 {
300 #if !defined(ENABLE_STATICVM)
301         void *p;
302
303         /* We need to access the dummy native table, not only to remove a warning */
304         /* but to be sure that the table is not optimized away (gcc does this     */
305         /* since 3.4).                                                            */
306
307         p = &dummynativetable;
308
309         /* initialize libltdl */
310
311         if (lt_dlinit()) {
312                 /* XXX how can we throw an exception here? */
313                 log_text(lt_dlerror());
314
315                 return false;
316         }
317
318         /* get the handle for the main program */
319
320         if (!(mainhandle = lt_dlopen(NULL)))
321                 return false;
322
323         /* initialize library hashtable, 10 entries should be enough */
324
325         init_hashtable(&library_hash, 10);
326
327 #endif
328
329         /* everything's ok */
330
331         return true;
332 }
333
334
335 /* native_library_hash_add *****************************************************
336
337    Adds an entry to the native library hashtable.
338
339 *******************************************************************************/
340
341 #if !defined(ENABLE_STATICVM)
342 void native_library_hash_add(utf *filename, java_objectheader *loader,
343                                                          lt_dlhandle handle)
344 {
345         library_hash_loader_entry *le;
346         library_hash_name_entry   *ne;      /* library name                       */
347         u4   key;                           /* hashkey                            */
348         u4   slot;                          /* slot in hashtable                  */
349
350         /* normally addresses are aligned to 4, 8 or 16 bytes */
351
352         key = ((u4) (ptrint) loader) >> 4;         /* align to 16-byte boundaries */
353         slot = key & (library_hash.size - 1);
354         le = library_hash.ptr[slot];
355
356         /* search external hash chain for the entry */
357
358         while (le) {
359                 if (le->loader == loader)
360                         break;
361
362                 le = le->hashlink;                  /* next element in external chain */
363         }
364
365         /* no loader found? create a new entry */
366
367         if (!le) {
368                 le = NEW(library_hash_loader_entry);
369
370                 le->loader = loader;
371                 le->namelink = NULL;
372
373                 /* insert entry into hashtable */
374
375                 le->hashlink = (library_hash_loader_entry *) library_hash.ptr[slot];
376                 library_hash.ptr[slot] = le;
377
378                 /* update number of hashtable-entries */
379
380                 library_hash.entries++;
381         }
382
383
384         /* search for library name */
385
386         ne = le->namelink;
387
388         while (ne) {
389                 if (ne->name == filename)
390                         return;
391
392                 ne = ne->hashlink;                  /* next element in external chain */
393         }
394
395         /* not found? add the library name to the classloader */
396
397         ne = NEW(library_hash_name_entry);
398
399         ne->name = filename;
400         ne->handle = handle;
401
402         /* insert entry into external chain */
403
404         ne->hashlink = le->namelink;
405         le->namelink = ne;
406 }
407 #endif /* !defined(ENABLE_STATICVM) */
408
409
410 /* native_library_hash_find ****************************************************
411
412    Find an entry in the native library hashtable.
413
414 *******************************************************************************/
415
416 #if !defined(ENABLE_STATICVM)
417 library_hash_name_entry *native_library_hash_find(utf *filename,
418                                                                                                   java_objectheader *loader)
419 {
420         library_hash_loader_entry *le;
421         library_hash_name_entry   *ne;      /* library name                       */
422         u4   key;                           /* hashkey                            */
423         u4   slot;                          /* slot in hashtable                  */
424
425         /* normally addresses are aligned to 4, 8 or 16 bytes */
426
427         key  = ((u4) (ptrint) loader) >> 4;        /* align to 16-byte boundaries */
428         slot = key & (library_hash.size - 1);
429         le   = library_hash.ptr[slot];
430
431         /* search external hash chain for the entry */
432
433         while (le) {
434                 if (le->loader == loader)
435                         break;
436
437                 le = le->hashlink;                  /* next element in external chain */
438         }
439
440         /* no loader found? return NULL */
441
442         if (!le)
443                 return NULL;
444
445         /* search for library name */
446
447         ne = le->namelink;
448
449         while (ne) {
450                 if (ne->name == filename)
451                         return ne;
452
453                 ne = ne->hashlink;                  /* next element in external chain */
454         }
455
456         /* return entry, if no entry was found, ne is NULL */
457
458         return ne;
459 }
460 #endif /* !defined(ENABLE_STATICVM) */
461
462
463 /* native_findfunction *********************************************************
464
465    Looks up a method (must have the same class name, method name,
466    descriptor and 'static'ness) and returns a function pointer to it.
467    Returns: function pointer or NULL (if there is no such method)
468
469    Remark: For faster operation, the names/descriptors are converted
470    from C strings to Unicode the first time this function is called.
471
472 *******************************************************************************/
473
474 #if defined(ENABLE_STATICVM)
475 functionptr native_findfunction(utf *cname, utf *mname, utf *desc,
476                                                                 bool isstatic)
477 {
478         /* entry of table for fast string comparison */
479         struct nativecompref *n;
480         s4 i;
481
482         isstatic = isstatic ? true : false;
483         
484         if (!nativecompdone) {
485                 for (i = 0; i < NATIVETABLESIZE; i++) {
486                         nativecomptable[i].classname  = 
487                                 utf_new_char(nativetable[i].classname);
488
489                         nativecomptable[i].methodname = 
490                                 utf_new_char(nativetable[i].methodname);
491
492                         nativecomptable[i].descriptor =
493                                 utf_new_char(nativetable[i].descriptor);
494
495                         nativecomptable[i].isstatic   = nativetable[i].isstatic;
496                         nativecomptable[i].func       = nativetable[i].func;
497                 }
498
499                 nativecompdone = true;
500         }
501
502         for (i = 0; i < NATIVETABLESIZE; i++) {
503                 n = &(nativecomptable[i]);
504
505                 if (cname == n->classname && mname == n->methodname &&
506                     desc == n->descriptor && isstatic == n->isstatic)
507                         return n->func;
508         }
509
510                 
511         /* no function was found, throw exception */
512
513         *exceptionptr =
514                         new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
515                                                                          mname);
516
517         return NULL;
518 }
519 #endif /* defined(ENABLE_STATICVM) */
520
521
522 /* native_make_overloaded_function *********************************************
523
524    XXX
525
526 *******************************************************************************/
527
528 #if !defined(ENABLE_STATICVM)
529 static char *native_make_overloaded_function(char *name, utf *desc)
530 {
531         char *newname;
532         s4    namelen;
533         char *utf_ptr;
534         u2    c;
535         s4    i;
536
537         utf_ptr = desc->text;
538         namelen = strlen(name) + strlen("__") + strlen("0");
539
540         /* calculate additional length */
541
542         while ((c = utf_nextu2(&utf_ptr)) != ')') {
543                 switch (c) {
544                 case 'Z':
545                 case 'B':
546                 case 'C':
547                 case 'S':
548                 case 'I':
549                 case 'J':
550                 case 'F':
551                 case 'D':
552                         namelen++;
553                         break;
554                 case '[':
555                         namelen += 2;
556                         break;
557                 case 'L':
558                         namelen++;
559                         while (utf_nextu2(&utf_ptr) != ';')
560                                 namelen++;
561                         namelen += 2;
562                         break;
563                 case '(':
564                         break;
565                 default:
566                         assert(0);
567                 }
568         }
569
570
571         /* reallocate memory */
572
573         i = strlen(name);
574
575         newname = DMNEW(char, namelen);
576         MCOPY(newname, name, char, i);
577
578         utf_ptr = desc->text;
579
580         newname[i++] = '_';
581         newname[i++] = '_';
582
583         while ((c = utf_nextu2(&utf_ptr)) != ')') {
584                 switch (c) {
585                 case 'Z':
586                 case 'B':
587                 case 'C':
588                 case 'S':
589                 case 'J':
590                 case 'I':
591                 case 'F':
592                 case 'D':
593                         newname[i++] = c;
594                         break;
595                 case '[':
596                         newname[i++] = '_';
597                         newname[i++] = '3';
598                         break;
599                 case 'L':
600                         newname[i++] = 'L';
601                         while ((c = utf_nextu2(&utf_ptr)) != ';')
602                                 if (((c >= 'a') && (c <= 'z')) ||
603                                         ((c >= 'A') && (c <= 'Z')) ||
604                                         ((c >= '0') && (c <= '9')))
605                                         newname[i++] = c;
606                                 else
607                                         newname[i++] = '_';
608                         newname[i++] = '_';
609                         newname[i++] = '2';
610                         break;
611                 case '(':
612                         break;
613                 default:
614                         assert(0);
615                 }
616         }
617
618         /* close string */
619
620         newname[i] = '\0';
621
622         return newname;
623 }
624
625
626 /* native_resolve_function *****************************************************
627
628    Resolves a native function, maybe from a dynamic library.
629
630 *******************************************************************************/
631
632 functionptr native_resolve_function(methodinfo *m)
633 {
634         lt_ptr                     sym;
635         char                      *name;
636         char                      *newname;
637         s4                         namelen;
638         char                      *utf_ptr;
639         char                      *utf_endptr;
640         s4                         dumpsize;
641         library_hash_loader_entry *le;
642         library_hash_name_entry   *ne;
643         u4                         key;     /* hashkey                            */
644         u4                         slot;    /* slot in hashtable                  */
645         u4                         i;
646
647
648         /* verbose output */
649
650         if (opt_verbosejni) {
651                 printf("[Dynamic-linking native method ");
652                 utf_display_classname(m->class->name);
653                 printf(".");
654                 utf_display(m->name);
655                 printf(" ... ");
656         }
657                 
658         /* calculate length of native function name */
659
660         namelen = strlen("Java_") + utf_strlen(m->class->name) + strlen("_") +
661                 utf_strlen(m->name) + strlen("0");
662
663         /* check for underscores in class name */
664
665         utf_ptr = m->class->name->text;
666         utf_endptr = UTF_END(m->class->name);
667
668         while (utf_ptr < utf_endptr)
669                 if (utf_nextu2(&utf_ptr) == '_')
670                         namelen++;
671
672         /* check for underscores in method name */
673
674         utf_ptr = m->name->text;
675         utf_endptr = UTF_END(m->name);
676
677         while (utf_ptr < utf_endptr)
678                 if (utf_nextu2(&utf_ptr) == '_')
679                         namelen++;
680
681         /* allocate memory */
682
683         dumpsize = dump_size();
684
685         name = DMNEW(char, namelen);
686
687
688         /* generate name of native functions */
689
690         strcpy(name, "Java_");
691         i = strlen("Java_");
692
693         utf_ptr = m->class->name->text;
694         utf_endptr = UTF_END(m->class->name);
695
696         for (; utf_ptr < utf_endptr; utf_ptr++, i++) {
697                 name[i] = *utf_ptr;
698
699                 /* escape sequence for '_' is '_1' */
700
701                 if (name[i] == '_')
702                         name[++i] = '1';
703
704                 /* replace '/' with '_' */
705
706                 if (name[i] == '/')
707                         name[i] = '_';
708         }
709
710         /* seperator between class and method */
711
712         name[i++] = '_';
713
714         utf_ptr = m->name->text;
715         utf_endptr = UTF_END(m->name);
716
717         for (; utf_ptr < utf_endptr; utf_ptr++, i++) {
718                 name[i] = *utf_ptr;
719
720                 /* escape sequence for '_' is '_1' */
721
722                 if (name[i] == '_')
723                         name[++i] = '1';
724         }
725
726         /* close string */
727
728         name[i] = '\0';
729
730
731         /* generate overloaded function (having the types in it's name)           */
732
733         newname = native_make_overloaded_function(name, m->descriptor);
734
735         /* check the library hash entries of the classloader of the methods's     */
736         /* class                                                                  */
737
738         sym = NULL;
739
740         /* normally addresses are aligned to 4, 8 or 16 bytes */
741
742         key = ((u4) (ptrint) m->class->classloader) >> 4;     /* align to 16-byte */
743         slot = key & (library_hash.size - 1);
744         le = library_hash.ptr[slot];
745
746         /* iterate through loaders in this hash slot */
747
748         while (le && !sym) {
749                 /* iterate through names in this loader */
750
751                 ne = le->namelink;
752                         
753                 while (ne && !sym) {
754                         sym = lt_dlsym(ne->handle, name);
755
756                         if (!sym)
757                                 sym = lt_dlsym(ne->handle, newname);
758
759                         ne = ne->hashlink;
760                 }
761
762                 le = le->hashlink;
763         }
764
765         if (sym)
766                 if (opt_verbosejni)
767                         printf("JNI ]\n");
768
769
770         /* if not found, try to find the native function symbol in the main       */
771         /* program                                                                */
772
773         if (!sym) {
774                 sym = lt_dlsym(mainhandle, name);
775
776                 if (!sym)
777                         sym = lt_dlsym(mainhandle, newname);
778
779                 if (sym)
780                         if (opt_verbosejni)
781                                 printf("internal ]\n");
782         }
783
784
785         /* no symbol found? throw exception */
786
787         if (!sym)
788                 *exceptionptr =
789                         new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
790                                                                          m->name);
791
792         /* release memory */
793
794         dump_release(dumpsize);
795
796         return (functionptr) (ptrint) sym;
797 }
798 #endif /* !defined(ENABLE_STATICVM) */
799
800
801 /* native_new_and_init *********************************************************
802
803    Creates a new object on the heap and calls the initializer.
804    Returns the object pointer or NULL if memory is exhausted.
805                         
806 *******************************************************************************/
807
808 java_objectheader *native_new_and_init(classinfo *c)
809 {
810         methodinfo *m;
811         java_objectheader *o;
812
813         if (!c)
814                 return *exceptionptr;
815
816         /* create object */
817
818         o = builtin_new(c);
819         
820         if (!o)
821                 return NULL;
822
823         /* find initializer */
824
825         m = class_findmethod(c, utf_init, utf_void__void);
826                                                       
827         /* initializer not found */
828
829         if (!m)
830                 return o;
831
832         /* call initializer */
833
834         asm_calljavafunction(m, o, NULL, NULL, NULL);
835
836         return o;
837 }
838
839
840 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
841 {
842         methodinfo *m;
843         java_objectheader *o;
844
845         if (!c)
846                 return *exceptionptr;
847
848         /* create object */
849
850         o = builtin_new(c);
851
852         if (!o)
853                 return NULL;
854
855         /* find initializer */
856
857         m = class_resolveclassmethod(c,
858                                                                  utf_init,
859                                                                  utf_java_lang_String__void,
860                                                                  NULL,
861                                                                  true);
862
863         /* initializer not found */
864
865         if (!m)
866                 return NULL;
867
868         /* call initializer */
869
870         asm_calljavafunction(m, o, s, NULL, NULL);
871
872         return o;
873 }
874
875
876 java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
877 {
878         methodinfo *m;
879         java_objectheader *o;
880
881         if (!c)
882                 return *exceptionptr;
883
884         /* create object */
885
886         o = builtin_new(c);
887         
888         if (!o)
889                 return NULL;
890
891         /* find initializer */
892
893         m = class_resolveclassmethod(c, utf_init, utf_int__void, NULL, true);
894
895         /* initializer not found  */
896
897         if (!m)
898                 return NULL;
899
900         /* call initializer */
901
902         asm_calljavafunction(m, o, (void *) (ptrint) i, NULL, NULL);
903
904         return o;
905 }
906
907
908 java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t)
909 {
910         methodinfo *m;
911         java_objectheader *o;
912
913         if (!c)
914                 return *exceptionptr;
915
916         /* create object */
917
918         o = builtin_new(c);
919         
920         if (!o)
921                 return NULL;
922
923         /* find initializer */
924
925         m = class_findmethod(c, utf_init, utf_java_lang_Throwable__void);
926                                                       
927         /* initializer not found */
928
929         if (!m)
930                 return NULL;
931
932         /* call initializer */
933
934         asm_calljavafunction(m, o, t, NULL, NULL);
935
936         return o;
937 }
938
939
940 void copy_vftbl(vftbl_t **dest, vftbl_t *src)
941 {
942     *dest = src;
943 #if 0
944     /* XXX this kind of copying does not work (in the general
945      * case). The interface tables would have to be copied, too. I
946      * don't see why we should make a copy anyway. -Edwin
947      */
948         *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
949         memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
950         memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
951 #endif
952 }
953
954
955 /******************************************************************************************                                                                                                             
956
957         creates method signature (excluding return type) from array of 
958         class-objects representing the parameters of the method 
959
960 *******************************************************************************************/
961
962
963 utf *create_methodsig(java_objectarray* types, char *retType)
964 {
965     char *buffer;       /* buffer for building the desciptor */
966     char *pos;          /* current position in buffer */
967     utf *result;        /* the method signature */
968     u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
969     u4 i, j;
970  
971     if (!types) return NULL;
972
973     /* determine required buffer-size */    
974     for (i = 0; i < types->header.size; i++) {
975                 classinfo *c = (classinfo *) types->data[i];
976                 buffer_size  = buffer_size + c->name->blength + 2;
977     }
978
979     if (retType) buffer_size += strlen(retType);
980
981     /* allocate buffer */
982     buffer = MNEW(char, buffer_size);
983     pos    = buffer;
984     
985     /* method-desciptor starts with parenthesis */
986     *pos++ = '(';
987
988     for (i = 0; i < types->header.size; i++) {
989                 char ch;           
990
991                 /* current argument */
992             classinfo *c = (classinfo *) types->data[i];
993
994             /* current position in utf-text */
995             char *utf_ptr = c->name->text; 
996             
997             /* determine type of argument */
998             if ((ch = utf_nextu2(&utf_ptr)) == '[') {
999                 /* arrayclass */
1000                 for (utf_ptr--; utf_ptr < UTF_END(c->name); utf_ptr++) {
1001                                 *pos++ = *utf_ptr; /* copy text */
1002                         }
1003
1004             } else {            
1005                         /* check for primitive types */
1006                         for (j = 0; j < PRIMITIVETYPE_COUNT; j++) {
1007                                 char *utf_pos   = utf_ptr - 1;
1008                                 char *primitive = primitivetype_table[j].wrapname;
1009
1010                                 /* compare text */
1011                                 while (utf_pos < UTF_END(c->name)) {
1012                                         if (*utf_pos++ != *primitive++) goto nomatch;
1013                                 }
1014
1015                                 /* primitive type found */
1016                                 *pos++ = primitivetype_table[j].typesig;
1017                                 goto next_type;
1018
1019                         nomatch:
1020                                 ;
1021                         }
1022
1023                         /* no primitive type and no arrayclass, so must be object */
1024                         *pos++ = 'L';
1025
1026                         /* copy text */
1027                         for (utf_ptr--; utf_ptr < UTF_END(c->name); utf_ptr++) {
1028                                 *pos++ = *utf_ptr;
1029                         }
1030
1031                         *pos++ = ';';
1032
1033                 next_type:
1034                         ;
1035                 }  
1036     }       
1037
1038     *pos++ = ')';
1039
1040     if (retType) {
1041                 for (i = 0; i < strlen(retType); i++) {
1042                         *pos++ = retType[i];
1043                 }
1044     }
1045
1046     /* create utf-string */
1047     result = utf_new(buffer, (pos - buffer));
1048     MFREE(buffer, char, buffer_size);
1049
1050     return result;
1051 }
1052
1053
1054 /* native_get_parametertypes ***************************************************
1055
1056    Use the descriptor of a method to generate a java/lang/Class array
1057    which contains the classes of the parametertypes of the method.
1058
1059 *******************************************************************************/
1060
1061 java_objectarray *native_get_parametertypes(methodinfo *m)
1062 {
1063         methoddesc       *md;
1064         typedesc         *paramtypes;
1065         s4                paramcount;
1066     java_objectarray *oa;
1067         s4                i;
1068
1069         md = m->parseddesc;
1070
1071         /* is the descriptor fully parsed? */
1072
1073         if (!m->parseddesc->params)
1074                 if (!descriptor_params_from_paramtypes(md, m->flags))
1075                         return NULL;
1076
1077         paramtypes = md->paramtypes;
1078         paramcount = md->paramcount;
1079
1080         /* skip `this' pointer */
1081
1082         if (!(m->flags & ACC_STATIC)) {
1083                 paramtypes++;
1084                 paramcount--;
1085         }
1086
1087         /* create class-array */
1088
1089         oa = builtin_anewarray(paramcount, class_java_lang_Class);
1090
1091         if (!oa)
1092                 return NULL;
1093
1094     /* get classes */
1095
1096         for (i = 0; i < paramcount; i++) {
1097                 if (!resolve_class_from_typedesc(&paramtypes[i], true, false,
1098                                                                                  (classinfo **) &oa->data[i]))
1099                         return NULL;
1100
1101                 use_class_as_object((classinfo *) oa->data[i]);
1102         }
1103
1104         return oa;
1105 }
1106
1107
1108 /* native_get_exceptiontypes ***************************************************
1109
1110    Get the exceptions which can be thrown by a method.
1111
1112 *******************************************************************************/
1113
1114 java_objectarray *native_get_exceptiontypes(methodinfo *m)
1115 {
1116         java_objectarray *oa;
1117         classinfo        *c;
1118         u2                i;
1119
1120         /* create class-array */
1121
1122         oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
1123
1124         if (!oa)
1125                 return NULL;
1126
1127         for (i = 0; i < m->thrownexceptionscount; i++) {
1128                 if (!resolve_classref_or_classinfo(NULL, m->thrownexceptions[i],
1129                                                                                    resolveEager, true, false, &c))
1130                         return NULL;
1131
1132                 if (!use_class_as_object(c))
1133                         return NULL;
1134
1135                 oa->data[i] = (java_objectheader *) c;
1136         }
1137
1138         return oa;
1139 }
1140
1141
1142 /* native_get_returntype *******************************************************
1143
1144    Get the returntype class of a method.
1145
1146 *******************************************************************************/
1147
1148 classinfo *native_get_returntype(methodinfo *m)
1149 {
1150         classinfo *c;
1151
1152         if (!resolve_class_from_typedesc(&(m->parseddesc->returntype), true, false,
1153                                                                          &c))
1154                 return NULL;
1155
1156         use_class_as_object(c);
1157
1158         return c;
1159 }
1160
1161
1162 /*****************************************************************************/
1163 /*****************************************************************************/
1164
1165
1166 /*--------------------------------------------------------*/
1167 void printNativeCall(nativeCall nc) {
1168   int i,j;
1169
1170   printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
1171   for (i=0; i<nc.methCnt; i++) {  
1172       printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
1173
1174     for (j=0; j<nc.callCnt[i]; j++) {  
1175         printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
1176         nc.methods[i].methodCalls[j].classname, 
1177         nc.methods[i].methodCalls[j].methodname, 
1178         nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1179       }
1180     }
1181   printf("-+++++--------------------\n");fflush(stdout);
1182 }
1183
1184 /*--------------------------------------------------------*/
1185 void printCompNativeCall(nativeCompCall nc) {
1186   int i,j;
1187   printf("printCompNativeCall BEGIN\n");fflush(stdout); 
1188   printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
1189   utf_display(nc.classname); fflush(stdout);
1190   
1191   for (i=0; i<nc.methCnt; i++) {  
1192     printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
1193     utf_display(nc.methods[i].methodname); fflush(stdout);
1194     utf_display(nc.methods[i].descriptor);fflush(stdout);
1195     printf("\n");fflush(stdout);
1196
1197     for (j=0; j<nc.callCnt[i]; j++) {  
1198       printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
1199         utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
1200         utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
1201         utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1202         printf("\n");fflush(stdout);
1203       }
1204     }
1205 printf("---------------------\n");fflush(stdout);
1206 }
1207
1208
1209 /*--------------------------------------------------------*/
1210 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d ) 
1211 {
1212     int i = 0;
1213     int j = 0;
1214     int cnt = 0;
1215     classMeth mc;
1216     mc.i_class = i;
1217     mc.j_method = j;
1218     mc.methCnt = cnt;
1219
1220     return mc;
1221 }
1222
1223 /*--------------------------------------------------------*/
1224 nativeCall* findNativeClassCalls(char *aclassname ) {
1225 int i;
1226
1227 for (i=0;i<NATIVECALLSSIZE; i++) {
1228    /* convert table to utf later to speed up search */ 
1229    if (strcmp(nativeCalls[i].classname, aclassname) == 0) 
1230         return &nativeCalls[i];
1231    }
1232
1233 return NULL;
1234 }
1235 /*--------------------------------------------------------*/
1236 /*--------------------------------------------------------*/
1237 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
1238   int i,j;
1239
1240
1241   ncc->classname = utf_new_char(nc.classname); 
1242   ncc->methCnt = nc.methCnt;
1243   
1244   for (i=0; i<nc.methCnt; i++) {  
1245     ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
1246     ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
1247     ncc->callCnt[i] = nc.callCnt[i];
1248
1249     for (j=0; j<nc.callCnt[i]; j++) {  
1250
1251         ncc->methods[i].methodCalls[j].classname  = utf_new_char(nc.methods[i].methodCalls[j].classname);
1252
1253         if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
1254           ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
1255           ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
1256           }
1257         else {
1258           ncc->methods[i].methodCalls[j].methodname = NULL;
1259           ncc->methods[i].methodCalls[j].descriptor = NULL;
1260           }
1261       }
1262     }
1263 }
1264
1265
1266
1267 /*--------------------------------------------------------*/
1268
1269 bool natcall2utf(bool natcallcompdone) {
1270 int i;
1271
1272 if (natcallcompdone) 
1273         return true;
1274
1275 for (i=0;i<NATIVECALLSSIZE; i++) {
1276    utfNativeCall  (nativeCalls[i], &nativeCompCalls[i]);  
1277    }
1278
1279 return true;
1280 }
1281
1282 /*
1283  * These are local overrides for various environment variables in Emacs.
1284  * Please do not remove this and leave it at the end of the file, where
1285  * Emacs will automagically detect them.
1286  * ---------------------------------------------------------------------
1287  * Local variables:
1288  * mode: c
1289  * indent-tabs-mode: t
1290  * c-basic-offset: 4
1291  * tab-width: 4
1292  * End:
1293  */