* src/mm/dumpmemory.c (dump_release): Renamed to dumpmemory_release.
[cacao.git] / src / native / native.c
1 /* src/native/native.c - table of native functions
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <ctype.h>
30
31 #if defined(ENABLE_LTDL) && defined(HAVE_LTDL_H)
32 # include <ltdl.h>
33 #endif
34
35 #include <stdint.h>
36
37 #include "vm/types.h"
38
39 #include "mm/memory.h"
40
41 #include "native/jni.h"
42 #include "native/native.h"
43
44 #include "native/vm/nativevm.h"
45
46 #include "threads/lock-common.h"
47
48 #include "toolbox/avl.h"
49 #include "toolbox/hashtable.h"
50 #include "toolbox/logging.h"
51
52 #include "vm/builtin.h"
53 #include "vm/exceptions.h"
54 #include "vm/global.h"
55 #include "vm/stringlocal.h"
56 #include "vm/vm.h"
57
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/jit.h"
60
61 #include "vmcore/loader.h"
62 #include "vmcore/options.h"
63 #include "vm/resolve.h"
64
65 #if defined(ENABLE_JVMTI)
66 #include "native/jvmti/cacaodbg.h"
67 #endif
68
69
70 /* global variables ***********************************************************/
71
72 static avl_tree_t *tree_native_methods;
73
74 #if defined(ENABLE_LTDL)
75 static hashtable *hashtable_library;
76 #endif
77
78
79 /* prototypes *****************************************************************/
80
81 static s4 native_tree_native_methods_comparator(const void *treenode, const void *node);
82
83
84 /* native_init *****************************************************************
85
86    Initializes the native subsystem.
87
88 *******************************************************************************/
89
90 bool native_init(void)
91 {
92 #if defined(ENABLE_LTDL)
93         /* initialize libltdl */
94
95         if (lt_dlinit())
96                 vm_abort("native_init: lt_dlinit failed: %s\n", lt_dlerror());
97
98         /* initialize library hashtable, 10 entries should be enough */
99
100         hashtable_library = NEW(hashtable);
101
102         hashtable_create(hashtable_library, 10);
103 #endif
104
105         /* initialize the native methods table */
106
107         tree_native_methods = avl_create(&native_tree_native_methods_comparator);
108
109         /* everything's ok */
110
111         return true;
112 }
113
114
115 /* native_tree_native_methods_comparator ***************************************
116
117    Comparison function for AVL tree of native methods.
118
119    IN:
120        treenode....node in the tree
121            node........node to compare with tree-node
122
123    RETURN VALUE:
124        -1, 0, +1
125
126 *******************************************************************************/
127
128 static s4 native_tree_native_methods_comparator(const void *treenode, const void *node)
129 {
130         const native_methods_node_t *treenmn;
131         const native_methods_node_t *nmn;
132
133         treenmn = treenode;
134         nmn     = node;
135
136         /* these are for walking the tree */
137
138         if (treenmn->classname < nmn->classname)
139                 return -1;
140         else if (treenmn->classname > nmn->classname)
141                 return 1;
142
143         if (treenmn->name < nmn->name)
144                 return -1;
145         else if (treenmn->name > nmn->name)
146                 return 1;
147
148         if (treenmn->descriptor < nmn->descriptor)
149                 return -1;
150         else if (treenmn->descriptor > nmn->descriptor)
151                 return 1;
152
153         /* all pointers are equal, we have found the entry */
154
155         return 0;
156 }
157
158
159 /* native_make_overloaded_function *********************************************
160
161    XXX
162
163 *******************************************************************************/
164
165 static utf *native_make_overloaded_function(utf *name, utf *descriptor)
166 {
167         char *newname;
168         s4    namelen;
169         char *utf_ptr;
170         u2    c;
171         s4    i;
172         utf  *u;
173         int32_t dumpmarker;
174
175         /* mark memory */
176
177         DMARKER;
178
179         utf_ptr = descriptor->text;
180         namelen = strlen(name->text) + strlen("__") + strlen("0");
181
182         /* calculate additional length */
183
184         while ((c = utf_nextu2(&utf_ptr)) != ')') {
185                 switch (c) {
186                 case 'Z':
187                 case 'B':
188                 case 'C':
189                 case 'S':
190                 case 'I':
191                 case 'J':
192                 case 'F':
193                 case 'D':
194                         namelen++;
195                         break;
196                 case '[':
197                         namelen += 2;
198                         break;
199                 case 'L':
200                         namelen++;
201                         while (utf_nextu2(&utf_ptr) != ';')
202                                 namelen++;
203                         namelen += 2;
204                         break;
205                 case '(':
206                         break;
207                 default:
208                         assert(0);
209                 }
210         }
211
212         /* reallocate memory */
213
214         i = strlen(name->text);
215
216         newname = DMNEW(char, namelen);
217         MCOPY(newname, name->text, char, i);
218
219         utf_ptr = descriptor->text;
220
221         newname[i++] = '_';
222         newname[i++] = '_';
223
224         while ((c = utf_nextu2(&utf_ptr)) != ')') {
225                 switch (c) {
226                 case 'Z':
227                 case 'B':
228                 case 'C':
229                 case 'S':
230                 case 'J':
231                 case 'I':
232                 case 'F':
233                 case 'D':
234                         newname[i++] = c;
235                         break;
236                 case '[':
237                         newname[i++] = '_';
238                         newname[i++] = '3';
239                         break;
240                 case 'L':
241                         newname[i++] = 'L';
242                         while ((c = utf_nextu2(&utf_ptr)) != ';')
243                                 if (((c >= 'a') && (c <= 'z')) ||
244                                         ((c >= 'A') && (c <= 'Z')) ||
245                                         ((c >= '0') && (c <= '9')))
246                                         newname[i++] = c;
247                                 else
248                                         newname[i++] = '_';
249                         newname[i++] = '_';
250                         newname[i++] = '2';
251                         break;
252                 case '(':
253                         break;
254                 default:
255                         assert(0);
256                 }
257         }
258
259         /* close string */
260
261         newname[i] = '\0';
262
263         /* make a utf-string */
264
265         u = utf_new_char(newname);
266
267         /* release memory */
268
269         DRELEASE;
270
271         return u;
272 }
273
274
275 /* native_insert_char **********************************************************
276
277    Inserts the passed UTF character into the native method name.  If
278    necessary it is escaped properly.
279
280 *******************************************************************************/
281
282 static s4 native_insert_char(char *name, u4 pos, u2 c)
283 {
284         s4 val;
285         s4 i;
286
287         switch (c) {
288         case '/':
289         case '.':
290                 /* replace '/' or '.' with '_' */
291                 name[pos] = '_';
292                 break;
293
294         case '_':
295                 /* escape sequence for '_' is '_1' */
296                 name[pos]   = '_';
297                 name[++pos] = '1';
298                 break;
299
300         case ';':
301                 /* escape sequence for ';' is '_2' */
302                 name[pos]   = '_';
303                 name[++pos] = '2';
304                 break;
305
306         case '[':
307                 /* escape sequence for '[' is '_1' */
308                 name[pos]   = '_';
309                 name[++pos] = '3';
310                 break;
311
312         default:
313                 if (isalnum(c))
314                         name[pos] = c;
315                 else {
316                         /* unicode character */
317                         name[pos]   = '_';
318                         name[++pos] = '0';
319
320                         for (i = 0; i < 4; ++i) {
321                                 val = c & 0x0f;
322                                 name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
323                                 c >>= 4;
324                         }
325
326                         pos += 4;
327                 }
328                 break;
329         }
330
331         /* return the new buffer index */
332
333         return pos;
334 }
335
336
337 /* native_method_symbol ********************************************************
338
339    Generate a method-symbol string out of the class name and the
340    method name.
341
342 *******************************************************************************/
343
344 static utf *native_method_symbol(utf *classname, utf *methodname)
345 {
346         char *name;
347         s4    namelen;
348         char *utf_ptr;
349         char *utf_endptr;
350         u2    c;
351         u4    pos;
352         utf  *u;
353         int32_t dumpmarker;
354
355         /* mark memory */
356
357         DMARKER;
358
359         /* Calculate length of native function name.  We multiply the
360            class and method name length by 6 as this is the maxium
361            escape-sequence that can be generated (unicode). */
362
363         namelen =
364                 strlen("Java_") +
365                 utf_get_number_of_u2s(classname) * 6 +
366                 strlen("_") +
367                 utf_get_number_of_u2s(methodname) * 6 +
368                 strlen("0");
369
370         /* allocate memory */
371
372         name = DMNEW(char, namelen);
373
374         /* generate name of native functions */
375
376         strcpy(name, "Java_");
377         pos = strlen("Java_");
378
379         utf_ptr    = classname->text;
380         utf_endptr = UTF_END(classname);
381
382         for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
383                 c   = *utf_ptr;
384                 pos = native_insert_char(name, pos, c);
385         }
386
387         /* seperator between class and method */
388
389         name[pos++] = '_';
390
391         utf_ptr    = methodname->text;
392         utf_endptr = UTF_END(methodname);
393
394         for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
395                 c   = *utf_ptr;
396                 pos = native_insert_char(name, pos, c);
397         }
398
399         /* close string */
400
401         name[pos] = '\0';
402
403         /* check for an buffer overflow */
404
405         assert(pos <= namelen);
406
407         /* make a utf-string */
408
409         u = utf_new_char(name);
410
411         /* release memory */
412
413         DRELEASE;
414
415         return u;
416 }
417
418
419 /* native_method_register ******************************************************
420
421    Register a native method in the native method table.
422
423 *******************************************************************************/
424
425 void native_method_register(utf *classname, const JNINativeMethod *methods,
426                                                         int32_t count)
427 {
428         native_methods_node_t *nmn;
429         utf                   *name;
430         utf                   *descriptor;
431         int32_t                i;
432
433         /* insert all methods passed */
434
435         for (i = 0; i < count; i++) {
436                 if (opt_verbosejni) {
437                         printf("[Registering JNI native method ");
438                         utf_display_printable_ascii_classname(classname);
439                         printf(".%s]\n", methods[i].name);
440                 }
441
442                 /* generate the utf8 names */
443
444                 name       = utf_new_char(methods[i].name);
445                 descriptor = utf_new_char(methods[i].signature);
446
447                 /* allocate a new tree node */
448
449                 nmn = NEW(native_methods_node_t);
450
451                 nmn->classname  = classname;
452                 nmn->name       = name;
453                 nmn->descriptor = descriptor;
454                 nmn->function   = (functionptr) (ptrint) methods[i].fnPtr;
455
456                 /* insert the method into the tree */
457
458                 avl_insert(tree_native_methods, nmn);
459         }
460 }
461
462
463 /* native_method_find **********************************************************
464
465    Find a native method in the native method table.
466
467 *******************************************************************************/
468
469 static functionptr native_method_find(methodinfo *m)
470 {
471         native_methods_node_t  tmpnmn;
472         native_methods_node_t *nmn;
473
474         /* fill the temporary structure used for searching the tree */
475
476         tmpnmn.classname  = m->class->name;
477         tmpnmn.name       = m->name;
478         tmpnmn.descriptor = m->descriptor;
479
480         /* find the entry in the AVL-tree */
481
482         nmn = avl_find(tree_native_methods, &tmpnmn);
483
484         if (nmn == NULL)
485                 return NULL;
486
487         return nmn->function;
488 }
489
490
491 /* native_method_resolve *******************************************************
492
493    Resolves a native method, maybe from a dynamic library.
494
495    IN:
496        m ... methodinfo of the native Java method to resolve
497
498    RESULT:
499        pointer to the resolved method (symbol)
500
501 *******************************************************************************/
502
503 functionptr native_method_resolve(methodinfo *m)
504 {
505         utf                            *name;
506         utf                            *newname;
507         functionptr                     f;
508 #if defined(ENABLE_LTDL)
509         classloader                    *cl;
510         hashtable_library_loader_entry *le;
511         hashtable_library_name_entry   *ne;
512         u4                              key;    /* hashkey                        */
513         u4                              slot;   /* slot in hashtable              */
514 #endif
515 #if defined(WITH_CLASSPATH_SUN)
516         methodinfo                     *method_findNative;
517         java_handle_t                  *s;
518 #endif
519
520         /* verbose output */
521
522         if (opt_verbosejni) {
523                 printf("[Dynamic-linking native method ");
524                 utf_display_printable_ascii_classname(m->class->name);
525                 printf(".");
526                 utf_display_printable_ascii(m->name);
527                 printf(" ... ");
528         }
529
530         /* generate method symbol string */
531
532         name = native_method_symbol(m->class->name, m->name);
533
534         /* generate overloaded function (having the types in it's name)           */
535
536         newname = native_make_overloaded_function(name, m->descriptor);
537
538         /* check the library hash entries of the classloader of the
539            methods's class  */
540
541         f = NULL;
542
543 #if defined(ENABLE_LTDL)
544         /* Get the classloader. */
545
546         cl = class_get_classloader(m->class);
547
548         /* normally addresses are aligned to 4, 8 or 16 bytes */
549
550         key  = ((u4) (ptrint) cl) >> 4;                       /* align to 16-byte */
551         slot = key & (hashtable_library->size - 1);
552         le   = hashtable_library->ptr[slot];
553
554         /* iterate through loaders in this hash slot */
555
556         while ((le != NULL) && (f == NULL)) {
557                 /* iterate through names in this loader */
558
559                 ne = le->namelink;
560                         
561                 while ((ne != NULL) && (f == NULL)) {
562                         f = (functionptr) (ptrint) lt_dlsym(ne->handle, name->text);
563
564                         if (f == NULL)
565                                 f = (functionptr) (ptrint) lt_dlsym(ne->handle, newname->text);
566
567                         ne = ne->hashlink;
568                 }
569
570                 le = le->hashlink;
571         }
572
573 # if defined(WITH_CLASSPATH_SUN)
574         if (f == NULL) {
575                 /* We can resolve the function directly from
576                    java.lang.ClassLoader as it's a static function. */
577                 /* XXX should be done in native_init */
578
579                 method_findNative =
580                         class_resolveclassmethod(class_java_lang_ClassLoader,
581                                                                          utf_findNative,
582                                                                          utf_java_lang_ClassLoader_java_lang_String__J,
583                                                                          class_java_lang_ClassLoader,
584                                                                          true);
585
586                 if (method_findNative == NULL)
587                         return NULL;
588
589                 /* try the normal name */
590
591                 s = javastring_new(name);
592
593                 f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
594                                                                                                                  NULL, cl, s);
595
596                 /* if not found, try the mangled name */
597
598                 if (f == NULL) {
599                         s = javastring_new(newname);
600
601                         f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
602                                                                                                                          NULL, cl, s);
603                 }
604         }
605 # endif
606
607         if (f != NULL)
608                 if (opt_verbosejni)
609                         printf("JNI ]\n");
610 #endif
611
612         /* If not found, try to find the native function symbol in the
613            main program. */
614
615         if (f == NULL) {
616                 f = native_method_find(m);
617
618                 if (f != NULL)
619                         if (opt_verbosejni)
620                                 printf("internal ]\n");
621         }
622
623 #if defined(ENABLE_JVMTI)
624         /* fire Native Method Bind event */
625         if (jvmti) jvmti_NativeMethodBind(m, f, &f);
626 #endif
627
628         /* no symbol found? throw exception */
629
630         if (f == NULL) {
631                 if (opt_verbosejni)
632                         printf("failed ]\n");
633
634                 exceptions_throw_unsatisfiedlinkerror(m->name);
635         }
636
637         return f;
638 }
639
640
641 /* native_library_open *********************************************************
642
643    Open a native library with the given utf8 name.
644
645    IN:
646        filename ... filename of the library to open
647
648    RETURN:
649        handle of the opened library
650
651 *******************************************************************************/
652
653 #if defined(ENABLE_LTDL)
654 lt_dlhandle native_library_open(utf *filename)
655 {
656         lt_dlhandle handle;
657
658         if (opt_verbosejni) {
659                 printf("[Loading native library ");
660                 utf_display_printable_ascii(filename);
661                 printf(" ... ");
662         }
663
664         /* try to open the library */
665
666         handle = lt_dlopen(filename->text);
667
668         if (handle == NULL) {
669                 if (opt_verbosejni)
670                         printf("failed ]\n");
671
672                 if (opt_verbose) {
673                         log_start();
674                         log_print("native_library_open: lt_dlopen failed: ");
675                         log_print(lt_dlerror());
676                         log_finish();
677                 }
678
679                 return NULL;
680         }
681
682         if (opt_verbosejni)
683                 printf("OK ]\n");
684
685         return handle;
686 }
687 #endif
688
689
690 /* native_library_close ********************************************************
691
692    Close the native library of the given handle.
693
694    IN:
695        handle ... handle of the open library
696
697 *******************************************************************************/
698
699 #if defined(ENABLE_LTDL)
700 void native_library_close(lt_dlhandle handle)
701 {
702         int result;
703
704         if (opt_verbosejni) {
705                 printf("[Unloading native library ");
706 /*              utf_display_printable_ascii(filename); */
707                 printf(" ... ");
708         }
709
710         /* Close the library. */
711
712         result = lt_dlclose(handle);
713
714         if (result != 0) {
715                 if (opt_verbose) {
716                         log_start();
717                         log_print("native_library_close: lt_dlclose failed: ");
718                         log_print(lt_dlerror());
719                         log_finish();
720                 }
721         }
722 }
723 #endif
724
725
726 /* native_library_add **********************************************************
727
728    Adds an entry to the native library hashtable.
729
730 *******************************************************************************/
731
732 #if defined(ENABLE_LTDL)
733 void native_library_add(utf *filename, classloader *loader, lt_dlhandle handle)
734 {
735         hashtable_library_loader_entry *le;
736         hashtable_library_name_entry   *ne; /* library name                       */
737         u4   key;                           /* hashkey                            */
738         u4   slot;                          /* slot in hashtable                  */
739
740         LOCK_MONITOR_ENTER(hashtable_library->header);
741
742         /* normally addresses are aligned to 4, 8 or 16 bytes */
743
744         key  = ((u4) (ptrint) loader) >> 4;        /* align to 16-byte boundaries */
745         slot = key & (hashtable_library->size - 1);
746         le   = hashtable_library->ptr[slot];
747
748         /* search external hash chain for the entry */
749
750         while (le) {
751                 if (le->loader == loader)
752                         break;
753
754                 le = le->hashlink;                  /* next element in external chain */
755         }
756
757         /* no loader found? create a new entry */
758
759         if (le == NULL) {
760                 le = NEW(hashtable_library_loader_entry);
761
762                 le->loader   = loader;
763                 le->namelink = NULL;
764
765                 /* insert entry into hashtable */
766
767                 le->hashlink =
768                         (hashtable_library_loader_entry *) hashtable_library->ptr[slot];
769                 hashtable_library->ptr[slot] = le;
770
771                 /* update number of hashtable-entries */
772
773                 hashtable_library->entries++;
774         }
775
776
777         /* search for library name */
778
779         ne = le->namelink;
780
781         while (ne) {
782                 if (ne->name == filename) {
783                         LOCK_MONITOR_EXIT(hashtable_library->header);
784
785                         return;
786                 }
787
788                 ne = ne->hashlink;                  /* next element in external chain */
789         }
790
791         /* not found? add the library name to the classloader */
792
793         ne = NEW(hashtable_library_name_entry);
794
795         ne->name   = filename;
796         ne->handle = handle;
797
798         /* insert entry into external chain */
799
800         ne->hashlink = le->namelink;
801         le->namelink = ne;
802
803         LOCK_MONITOR_EXIT(hashtable_library->header);
804 }
805 #endif
806
807
808 /* native_library_find *********************************************************
809
810    Find an entry in the native library hashtable.
811
812 *******************************************************************************/
813
814 #if defined(ENABLE_LTDL)
815 hashtable_library_name_entry *native_library_find(utf *filename,
816                                                                                                   classloader *loader)
817 {
818         hashtable_library_loader_entry *le;
819         hashtable_library_name_entry   *ne; /* library name                       */
820         u4   key;                           /* hashkey                            */
821         u4   slot;                          /* slot in hashtable                  */
822
823         /* normally addresses are aligned to 4, 8 or 16 bytes */
824
825         key  = ((u4) (ptrint) loader) >> 4;        /* align to 16-byte boundaries */
826         slot = key & (hashtable_library->size - 1);
827         le   = hashtable_library->ptr[slot];
828
829         /* search external hash chain for the entry */
830
831         while (le) {
832                 if (le->loader == loader)
833                         break;
834
835                 le = le->hashlink;                  /* next element in external chain */
836         }
837
838         /* no loader found? return NULL */
839
840         if (le == NULL)
841                 return NULL;
842
843         /* search for library name */
844
845         ne = le->namelink;
846
847         while (ne) {
848                 if (ne->name == filename)
849                         return ne;
850
851                 ne = ne->hashlink;                  /* next element in external chain */
852         }
853
854         /* return entry, if no entry was found, ne is NULL */
855
856         return ne;
857 }
858 #endif
859
860
861 /* native_new_and_init *********************************************************
862
863    Creates a new object on the heap and calls the initializer.
864    Returns the object pointer or NULL if memory is exhausted.
865                         
866 *******************************************************************************/
867
868 java_handle_t *native_new_and_init(classinfo *c)
869 {
870         methodinfo    *m;
871         java_handle_t *o;
872
873         if (c == NULL)
874                 vm_abort("native_new_and_init: c == NULL");
875
876         /* create object */
877
878         o = builtin_new(c);
879         
880         if (o == NULL)
881                 return NULL;
882
883         /* try to find the initializer */
884
885         m = class_findmethod(c, utf_init, utf_void__void);
886                                                       
887         /* ATTENTION: returning the object here is ok, since the class may
888        not have an initializer */
889
890         if (m == NULL)
891                 return o;
892
893         /* call initializer */
894
895         (void) vm_call_method(m, o);
896
897         return o;
898 }
899
900
901 java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
902 {
903         methodinfo    *m;
904         java_handle_t *o;
905
906         if (c == NULL)
907                 vm_abort("native_new_and_init_string: c == NULL");
908
909         /* create object */
910
911         o = builtin_new(c);
912
913         if (o == NULL)
914                 return NULL;
915
916         /* find initializer */
917
918         m = class_findmethod(c, utf_init, utf_java_lang_String__void);
919
920         /* initializer not found */
921
922         if (m == NULL)
923                 return NULL;
924
925         /* call initializer */
926
927         (void) vm_call_method(m, o, s);
928
929         return o;
930 }
931
932
933 /*
934  * These are local overrides for various environment variables in Emacs.
935  * Please do not remove this and leave it at the end of the file, where
936  * Emacs will automagically detect them.
937  * ---------------------------------------------------------------------
938  * Local variables:
939  * mode: c
940  * indent-tabs-mode: t
941  * c-basic-offset: 4
942  * tab-width: 4
943  * End:
944  * vim:noexpandtab:sw=4:ts=4:
945  */