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