1 /* src/native/native.c - table of native functions
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
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.
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.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
31 Changes: Christian Thalinger
33 $Id: native.c 2151 2005-03-30 19:27:47Z twisti $
47 /* Include files for IO functions */
51 #include <sys/types.h>
58 #include "cacao/cacao.h"
59 #include "mm/memory.h"
60 #include "native/jni.h"
61 #include "native/native.h"
62 #include "native/include/java_lang_Throwable.h"
63 #include "toolbox/logging.h"
64 #include "vm/builtin.h"
65 #include "vm/exceptions.h"
66 #include "vm/global.h"
67 #include "vm/loader.h"
68 #include "vm/options.h"
69 #include "vm/stringlocal.h"
70 #include "vm/tables.h"
71 #include "vm/jit/asmpart.h"
72 #include "vm/jit/jit.h"
75 /* include table of native functions ******************************************/
77 #include "nativetable.inc"
80 /************* use classinfo structure as java.lang.Class object **************/
82 void use_class_as_object(classinfo *c)
85 /* is the class loaded */
87 /* if (!class_load(c)) */
88 /* throw_exception_exit(); */
89 panic("use_class_as_object: class_load should not happen");
91 /* is the class linked */
94 throw_exception_exit();
96 /*if (class_java_lang_Class ==0) panic("java/lang/Class not loaded in use_class_as_object");
97 if (class_java_lang_Class->vftbl ==0) panic ("vftbl == 0 in use_class_as_object");*/
98 c->header.vftbl = class_java_lang_Class->vftbl;
104 /************************** tables for methods ********************************/
109 #ifdef STATIC_CLASSPATH
110 #define NATIVETABLESIZE (sizeof(nativetable)/sizeof(struct nativeref))
112 /* table for fast string comparison */
113 static nativecompref nativecomptable[NATIVETABLESIZE];
115 /* string comparsion table initialized */
116 static bool nativecompdone = false;
120 /* XXX don't define this in a header file!!! */
122 static struct nativeCall nativeCalls[] =
124 #include "nativecalls.inc"
127 #define NATIVECALLSSIZE (sizeof(nativeCalls) / sizeof(struct nativeCall))
129 struct nativeCompCall nativeCompCalls[NATIVECALLSSIZE];
132 /* native_loadclasses **********************************************************
134 Load classes required for native methods.
136 *******************************************************************************/
138 bool native_init(void)
140 #if !defined(STATIC_CLASSPATH)
143 /* We need to access the dummy native table, not only to remove a warning */
144 /* but to be sure that the table is not optimized away (gcc does this */
146 p = &dummynativetable;
149 /* everything's ok */
155 /*********************** Function: native_findfunction *************************
157 Looks up a method (must have the same class name, method name, descriptor
158 and 'static'ness) and returns a function pointer to it.
159 Returns: function pointer or NULL (if there is no such method)
161 Remark: For faster operation, the names/descriptors are converted from C
162 strings to Unicode the first time this function is called.
164 *******************************************************************************/
166 functionptr native_findfunction(utf *cname, utf *mname,
167 utf *desc, bool isstatic)
169 #ifdef STATIC_CLASSPATH
171 /* entry of table for fast string comparison */
172 struct nativecompref *n;
173 /* for warning message if no function is found */
177 isstatic = isstatic ? true : false;
179 if (!nativecompdone) {
180 for (i = 0; i < NATIVETABLESIZE; i++) {
181 nativecomptable[i].classname =
182 utf_new_char(nativetable[i].classname);
183 nativecomptable[i].methodname =
184 utf_new_char(nativetable[i].methodname);
185 nativecomptable[i].descriptor =
186 utf_new_char(nativetable[i].descriptor);
187 nativecomptable[i].isstatic =
188 nativetable[i].isstatic;
189 nativecomptable[i].func =
192 nativecompdone = true;
197 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
199 buffer = MNEW(char, buffer_len);
201 strcpy(buffer, "searching matching function in native table:");
202 utf_sprint(buffer+strlen(buffer), mname);
203 strcpy(buffer+strlen(buffer), ": ");
204 utf_sprint(buffer+strlen(buffer), desc);
205 strcpy(buffer+strlen(buffer), " for class ");
206 utf_sprint(buffer+strlen(buffer), cname);
210 MFREE(buffer, char, buffer_len);
213 for (i = 0; i < NATIVETABLESIZE; i++) {
214 n = &(nativecomptable[i]);
216 if (cname == n->classname && mname == n->methodname &&
217 desc == n->descriptor && isstatic == n->isstatic)
221 if (cname == n->classname && mname == n->methodname ) log_text("static and descriptor mismatch");
225 utf_strlen(n->classname) + utf_strlen(n->methodname) + utf_strlen(n->descriptor) + 64;
227 buffer = MNEW(char, buffer_len);
229 strcpy(buffer, "comparing with:");
230 utf_sprint(buffer+strlen(buffer), n->methodname);
231 strcpy (buffer+strlen(buffer), ": ");
232 utf_sprint(buffer+strlen(buffer), n->descriptor);
233 strcpy(buffer+strlen(buffer), " for class ");
234 utf_sprint(buffer+strlen(buffer), n->classname);
238 MFREE(buffer, char, buffer_len);
245 /* no function was found, display warning */
248 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
250 buffer = MNEW(char, buffer_len);
252 strcpy(buffer, "warning: native function ");
253 utf_sprint(buffer + strlen(buffer), mname);
254 strcpy(buffer + strlen(buffer), ": ");
255 utf_sprint(buffer + strlen(buffer), desc);
256 strcpy(buffer + strlen(buffer), " not found in class ");
257 utf_sprint(buffer + strlen(buffer), cname);
261 MFREE(buffer, char, buffer_len);
265 /* keep compiler happy */
268 /* dynamic classpath */
274 /****************** function class_findfield_approx ****************************
276 searches in 'classinfo'-structure for a field with the
279 *******************************************************************************/
281 fieldinfo *class_findfield_approx(classinfo *c, utf *name)
285 for (i = 0; i < c->fieldscount; i++) {
286 /* compare field names */
287 if ((c->fields[i].name == name))
288 return &(c->fields[i]);
291 /* field was not found, raise exception */
292 *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
298 s4 class_findfield_index_approx(classinfo *c, utf *name)
302 for (i = 0; i < c->fieldscount; i++) {
303 /* compare field names */
304 if ((c->fields[i].name == name))
308 /* field was not found, raise exception */
309 *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
315 /* native_new_and_init *********************************************************
317 Creates a new object on the heap and calls the initializer.
318 Returns the object pointer or NULL if memory is exhausted.
320 *******************************************************************************/
322 java_objectheader *native_new_and_init(classinfo *c)
325 java_objectheader *o;
328 return *exceptionptr;
337 /* find initializer */
339 m = class_findmethod(c, utf_init, utf_void__void);
341 /* initializer not found */
346 /* call initializer */
348 asm_calljavafunction(m, o, NULL, NULL, NULL);
354 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
357 java_objectheader *o;
360 return *exceptionptr;
369 /* find initializer */
371 m = class_resolveclassmethod(c,
373 utf_java_lang_String__void,
377 /* initializer not found */
382 /* call initializer */
384 asm_calljavafunction(m, o, s, NULL, NULL);
390 java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
393 java_objectheader *o;
396 return *exceptionptr;
405 /* find initializer */
407 m = class_resolveclassmethod(c, utf_init, utf_int__void, NULL, true);
409 /* initializer not found */
414 /* call initializer */
416 asm_calljavafunction(m, o, (void *) (ptrint) i, NULL, NULL);
422 java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t)
425 java_objectheader *o;
428 return *exceptionptr;
437 /* find initializer */
439 m = class_findmethod(c, utf_init, utf_java_lang_Throwable__void);
441 /* initializer not found */
446 /* call initializer */
448 asm_calljavafunction(m, o, t, NULL, NULL);
454 void copy_vftbl(vftbl_t **dest, vftbl_t *src)
458 /* XXX this kind of copying does not work (in the general
459 * case). The interface tables would have to be copied, too. I
460 * don't see why we should make a copy anyway. -Edwin
462 *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
463 memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
464 memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
469 /******************************************************************************************
471 creates method signature (excluding return type) from array of
472 class-objects representing the parameters of the method
474 *******************************************************************************************/
477 utf *create_methodsig(java_objectarray* types, char *retType)
479 char *buffer; /* buffer for building the desciptor */
480 char *pos; /* current position in buffer */
481 utf *result; /* the method signature */
482 u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
485 if (!types) return NULL;
487 /* determine required buffer-size */
488 for (i = 0; i < types->header.size; i++) {
489 classinfo *c = (classinfo *) types->data[i];
490 buffer_size = buffer_size + c->name->blength + 2;
493 if (retType) buffer_size += strlen(retType);
495 /* allocate buffer */
496 buffer = MNEW(char, buffer_size);
499 /* method-desciptor starts with parenthesis */
502 for (i = 0; i < types->header.size; i++) {
505 /* current argument */
506 classinfo *c = (classinfo *) types->data[i];
508 /* current position in utf-text */
509 char *utf_ptr = c->name->text;
511 /* determine type of argument */
512 if ((ch = utf_nextu2(&utf_ptr)) == '[') {
514 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
515 *pos++ = *utf_ptr; /* copy text */
519 /* check for primitive types */
520 for (j = 0; j < PRIMITIVETYPE_COUNT; j++) {
521 char *utf_pos = utf_ptr - 1;
522 char *primitive = primitivetype_table[j].wrapname;
525 while (utf_pos < utf_end(c->name)) {
526 if (*utf_pos++ != *primitive++) goto nomatch;
529 /* primitive type found */
530 *pos++ = primitivetype_table[j].typesig;
537 /* no primitive type and no arrayclass, so must be object */
541 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
555 for (i = 0; i < strlen(retType); i++) {
560 /* create utf-string */
561 result = utf_new(buffer, (pos - buffer));
562 MFREE(buffer, char, buffer_size);
568 /******************************************************************************************
570 retrieve the next argument or returntype from a descriptor
571 and return the corresponding class
573 *******************************************************************************************/
575 classinfo *get_type(char **utf_ptr,char *desc_end, bool skip)
577 classinfo *c = class_from_descriptor(*utf_ptr,desc_end,utf_ptr,
578 (skip) ? CLASSLOAD_SKIP : CLASSLOAD_LOAD);
581 panic("illegal descriptor");
583 if (skip) return NULL;
585 use_class_as_object(c);
590 /* get_parametertypes **********************************************************
592 use the descriptor of a method to generate a java/lang/Class array
593 which contains the classes of the parametertypes of the method
595 *******************************************************************************/
597 java_objectarray* get_parametertypes(methodinfo *m)
599 utf *descr = m->descriptor; /* method-descriptor */
600 char *utf_ptr = descr->text; /* current position in utf-text */
601 char *desc_end = utf_end(descr); /* points behind utf string */
602 java_objectarray* result;
603 int parametercount = 0;
607 utf_nextu2(&utf_ptr);
609 /* determine number of parameters */
610 while (*utf_ptr != ')') {
611 get_type(&utf_ptr, desc_end, true);
615 /* create class-array */
616 result = builtin_anewarray(parametercount, class_java_lang_Class);
618 utf_ptr = descr->text;
619 utf_nextu2(&utf_ptr);
621 /* get returntype classes */
622 for (i = 0; i < parametercount; i++)
624 (java_objectheader *) get_type(&utf_ptr, desc_end, false);
630 /* get_exceptiontypes **********************************************************
632 get the exceptions which can be thrown by a method
634 *******************************************************************************/
636 java_objectarray* get_exceptiontypes(methodinfo *m)
640 java_objectarray *result;
642 excount = m->thrownexceptionscount;
644 /* create class-array */
645 result = builtin_anewarray(excount, class_java_lang_Class);
647 for (i = 0; i < excount; i++) {
648 java_objectheader *o = (java_objectheader *) (m->thrownexceptions[i]);
649 use_class_as_object((classinfo *) o);
660 /******************************************************************************************
662 get the returntype class of a method
664 *******************************************************************************************/
666 classinfo *get_returntype(methodinfo *m)
668 char *utf_ptr; /* current position in utf-text */
669 char *desc_end; /* points behind utf string */
670 utf *desc = m->descriptor; /* method-descriptor */
672 utf_ptr = desc->text;
673 desc_end = utf_end(desc);
675 /* ignore parametertypes */
676 while ((utf_ptr<desc_end) && utf_nextu2(&utf_ptr)!=')')
679 return get_type(&utf_ptr,desc_end, false);
683 /*****************************************************************************/
684 /*****************************************************************************/
687 /*--------------------------------------------------------*/
688 void printNativeCall(nativeCall nc) {
691 printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
692 for (i=0; i<nc.methCnt; i++) {
693 printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
695 for (j=0; j<nc.callCnt[i]; j++) {
696 printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
697 nc.methods[i].methodCalls[j].classname,
698 nc.methods[i].methodCalls[j].methodname,
699 nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
702 printf("-+++++--------------------\n");fflush(stdout);
705 /*--------------------------------------------------------*/
706 void printCompNativeCall(nativeCompCall nc) {
708 printf("printCompNativeCall BEGIN\n");fflush(stdout);
709 printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
710 utf_display(nc.classname); fflush(stdout);
712 for (i=0; i<nc.methCnt; i++) {
713 printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
714 utf_display(nc.methods[i].methodname); fflush(stdout);
715 utf_display(nc.methods[i].descriptor);fflush(stdout);
716 printf("\n");fflush(stdout);
718 for (j=0; j<nc.callCnt[i]; j++) {
719 printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
720 utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
721 utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
722 utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
723 printf("\n");fflush(stdout);
726 printf("---------------------\n");fflush(stdout);
730 /*--------------------------------------------------------*/
731 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d )
744 /*--------------------------------------------------------*/
745 nativeCall* findNativeClassCalls(char *aclassname ) {
748 for (i=0;i<NATIVECALLSSIZE; i++) {
749 /* convert table to utf later to speed up search */
750 if (strcmp(nativeCalls[i].classname, aclassname) == 0)
751 return &nativeCalls[i];
756 /*--------------------------------------------------------*/
757 /*--------------------------------------------------------*/
758 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
762 ncc->classname = utf_new_char(nc.classname);
763 ncc->methCnt = nc.methCnt;
765 for (i=0; i<nc.methCnt; i++) {
766 ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
767 ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
768 ncc->callCnt[i] = nc.callCnt[i];
770 for (j=0; j<nc.callCnt[i]; j++) {
772 ncc->methods[i].methodCalls[j].classname = utf_new_char(nc.methods[i].methodCalls[j].classname);
774 if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
775 ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
776 ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
779 ncc->methods[i].methodCalls[j].methodname = NULL;
780 ncc->methods[i].methodCalls[j].descriptor = NULL;
788 /*--------------------------------------------------------*/
790 bool natcall2utf(bool natcallcompdone) {
796 for (i=0;i<NATIVECALLSSIZE; i++) {
797 utfNativeCall (nativeCalls[i], &nativeCompCalls[i]);
803 /*--------------------------------------------------------*/
806 java_objectarray *builtin_asm_createclasscontextarray(classinfo **end, classinfo **start)
808 #if defined(__GNUC__)
809 #warning platform dependend
811 java_objectarray *tmpArray;
817 size = (((size_t) start) - ((size_t) end)) / sizeof(classinfo*);
819 /*printf("end %p, start %p, size %ld\n",end,start,size);*/
820 if (!class_java_lang_Class)
821 class_java_lang_Class = class_new(utf_new_char("java/lang/Class"));
823 if (!class_java_lang_SecurityManager)
824 class_java_lang_SecurityManager =
825 class_new(utf_new_char("java/lang/SecurityManager"));
828 if (start == class_java_lang_SecurityManager) {
835 builtin_newarray(size, class_array_of(class_java_lang_Class)->vftbl);
837 for(i = 0, current = start; i < size; i++, current--) {
840 utf_display(c->name);*/
841 use_class_as_object(c);
842 tmpArray->data[i] = (java_objectheader *) c;
849 java_lang_ClassLoader *builtin_asm_getclassloader(classinfo **end, classinfo **start)
851 #if defined(__GNUC__)
852 #warning platform dependend
857 classinfo *privilegedAction;
860 size = (((size_t) start) - ((size_t) end)) / sizeof(classinfo*);
862 /* log_text("builtin_asm_getclassloader");
863 printf("end %p, start %p, size %ld\n",end,start,size);*/
865 if (!class_java_lang_SecurityManager)
866 class_java_lang_SecurityManager =
867 class_new(utf_new_char("java/lang/SecurityManager"));
870 if (start == class_java_lang_SecurityManager) {
876 privilegedAction=class_new(utf_new_char("java/security/PrivilegedAction"));
878 for(i = 0, current = start; i < size; i++, current--) {
881 if (c == privilegedAction)
885 return (java_lang_ClassLoader *) c->classloader;
893 * These are local overrides for various environment variables in Emacs.
894 * Please do not remove this and leave it at the end of the file, where
895 * Emacs will automagically detect them.
896 * ---------------------------------------------------------------------
899 * indent-tabs-mode: t