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