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