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 2138 2005-03-30 10:23: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 static int classesLoaded = 0; /*temporary hack JoWenn*/
141 #if !defined(STATIC_CLASSPATH)
150 #if !defined(STATIC_CLASSPATH)
151 /* We need to access the dummy native table, not only to remove a warning */
152 /* but to be sure that the table is not optimized away (gcc does this */
154 p = &dummynativetable;
157 /* load classes for wrapping primitive types */
159 if (!class_load(class_java_lang_Void) ||
160 !class_link(class_java_lang_Void))
163 if (!class_load(class_java_lang_Boolean) ||
164 !class_link(class_java_lang_Boolean))
167 if (!class_load(class_java_lang_Byte) ||
168 !class_link(class_java_lang_Byte))
171 if (!class_load(class_java_lang_Character) ||
172 !class_link(class_java_lang_Character))
175 if (!class_load(class_java_lang_Short) ||
176 !class_link(class_java_lang_Short))
179 if (!class_load(class_java_lang_Integer) ||
180 !class_link(class_java_lang_Integer))
183 if (!class_load(class_java_lang_Long) ||
184 !class_link(class_java_lang_Long))
187 if (!class_load(class_java_lang_Float) ||
188 !class_link(class_java_lang_Float))
191 if (!class_load(class_java_lang_Double) ||
192 !class_link(class_java_lang_Double))
195 /* everything's ok */
201 /*********************** Function: native_findfunction *************************
203 Looks up a method (must have the same class name, method name, descriptor
204 and 'static'ness) and returns a function pointer to it.
205 Returns: function pointer or NULL (if there is no such method)
207 Remark: For faster operation, the names/descriptors are converted from C
208 strings to Unicode the first time this function is called.
210 *******************************************************************************/
212 functionptr native_findfunction(utf *cname, utf *mname,
213 utf *desc, bool isstatic)
215 #ifdef STATIC_CLASSPATH
217 /* entry of table for fast string comparison */
218 struct nativecompref *n;
219 /* for warning message if no function is found */
223 isstatic = isstatic ? true : false;
225 if (!nativecompdone) {
226 for (i = 0; i < NATIVETABLESIZE; i++) {
227 nativecomptable[i].classname =
228 utf_new_char(nativetable[i].classname);
229 nativecomptable[i].methodname =
230 utf_new_char(nativetable[i].methodname);
231 nativecomptable[i].descriptor =
232 utf_new_char(nativetable[i].descriptor);
233 nativecomptable[i].isstatic =
234 nativetable[i].isstatic;
235 nativecomptable[i].func =
238 nativecompdone = true;
243 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
245 buffer = MNEW(char, buffer_len);
247 strcpy(buffer, "searching matching function in native table:");
248 utf_sprint(buffer+strlen(buffer), mname);
249 strcpy(buffer+strlen(buffer), ": ");
250 utf_sprint(buffer+strlen(buffer), desc);
251 strcpy(buffer+strlen(buffer), " for class ");
252 utf_sprint(buffer+strlen(buffer), cname);
256 MFREE(buffer, char, buffer_len);
259 for (i = 0; i < NATIVETABLESIZE; i++) {
260 n = &(nativecomptable[i]);
262 if (cname == n->classname && mname == n->methodname &&
263 desc == n->descriptor && isstatic == n->isstatic)
267 if (cname == n->classname && mname == n->methodname ) log_text("static and descriptor mismatch");
271 utf_strlen(n->classname) + utf_strlen(n->methodname) + utf_strlen(n->descriptor) + 64;
273 buffer = MNEW(char, buffer_len);
275 strcpy(buffer, "comparing with:");
276 utf_sprint(buffer+strlen(buffer), n->methodname);
277 strcpy (buffer+strlen(buffer), ": ");
278 utf_sprint(buffer+strlen(buffer), n->descriptor);
279 strcpy(buffer+strlen(buffer), " for class ");
280 utf_sprint(buffer+strlen(buffer), n->classname);
284 MFREE(buffer, char, buffer_len);
291 /* no function was found, display warning */
294 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
296 buffer = MNEW(char, buffer_len);
298 strcpy(buffer, "warning: native function ");
299 utf_sprint(buffer + strlen(buffer), mname);
300 strcpy(buffer + strlen(buffer), ": ");
301 utf_sprint(buffer + strlen(buffer), desc);
302 strcpy(buffer + strlen(buffer), " not found in class ");
303 utf_sprint(buffer + strlen(buffer), cname);
307 MFREE(buffer, char, buffer_len);
311 /* keep compiler happy */
314 /* dynamic classpath */
320 /****************** function class_findfield_approx ****************************
322 searches in 'classinfo'-structure for a field with the
325 *******************************************************************************/
327 fieldinfo *class_findfield_approx(classinfo *c, utf *name)
331 for (i = 0; i < c->fieldscount; i++) {
332 /* compare field names */
333 if ((c->fields[i].name == name))
334 return &(c->fields[i]);
337 /* field was not found, raise exception */
338 *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
344 s4 class_findfield_index_approx(classinfo *c, utf *name)
348 for (i = 0; i < c->fieldscount; i++) {
349 /* compare field names */
350 if ((c->fields[i].name == name))
354 /* field was not found, raise exception */
355 *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
361 /* native_new_and_init *********************************************************
363 Creates a new object on the heap and calls the initializer.
364 Returns the object pointer or NULL if memory is exhausted.
366 *******************************************************************************/
368 java_objectheader *native_new_and_init(classinfo *c)
371 java_objectheader *o;
374 return *exceptionptr;
383 /* find initializer */
385 m = class_findmethod(c, utf_init, utf_void__void);
387 /* initializer not found */
392 /* call initializer */
394 asm_calljavafunction(m, o, NULL, NULL, NULL);
400 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
403 java_objectheader *o;
406 return *exceptionptr;
415 /* find initializer */
417 m = class_resolveclassmethod(c,
419 utf_java_lang_String__void,
423 /* initializer not found */
428 /* call initializer */
430 asm_calljavafunction(m, o, s, NULL, NULL);
436 java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
439 java_objectheader *o;
442 return *exceptionptr;
451 /* find initializer */
453 m = class_resolveclassmethod(c, utf_init, utf_int__void, NULL, true);
455 /* initializer not found */
460 /* call initializer */
462 asm_calljavafunction(m, o, (void *) (ptrint) i, NULL, NULL);
468 java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t)
471 java_objectheader *o;
474 return *exceptionptr;
483 /* find initializer */
485 m = class_findmethod(c, utf_init, utf_java_lang_Throwable__void);
487 /* initializer not found */
492 /* call initializer */
494 asm_calljavafunction(m, o, t, NULL, NULL);
500 void copy_vftbl(vftbl_t **dest, vftbl_t *src)
504 /* XXX this kind of copying does not work (in the general
505 * case). The interface tables would have to be copied, too. I
506 * don't see why we should make a copy anyway. -Edwin
508 *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
509 memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
510 memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
515 /******************************************************************************************
517 creates method signature (excluding return type) from array of
518 class-objects representing the parameters of the method
520 *******************************************************************************************/
523 utf *create_methodsig(java_objectarray* types, char *retType)
525 char *buffer; /* buffer for building the desciptor */
526 char *pos; /* current position in buffer */
527 utf *result; /* the method signature */
528 u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
531 if (!types) return NULL;
533 /* determine required buffer-size */
534 for (i = 0; i < types->header.size; i++) {
535 classinfo *c = (classinfo *) types->data[i];
536 buffer_size = buffer_size + c->name->blength + 2;
539 if (retType) buffer_size += strlen(retType);
541 /* allocate buffer */
542 buffer = MNEW(char, buffer_size);
545 /* method-desciptor starts with parenthesis */
548 for (i = 0; i < types->header.size; i++) {
551 /* current argument */
552 classinfo *c = (classinfo *) types->data[i];
554 /* current position in utf-text */
555 char *utf_ptr = c->name->text;
557 /* determine type of argument */
558 if ((ch = utf_nextu2(&utf_ptr)) == '[') {
560 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
561 *pos++ = *utf_ptr; /* copy text */
565 /* check for primitive types */
566 for (j = 0; j < PRIMITIVETYPE_COUNT; j++) {
567 char *utf_pos = utf_ptr - 1;
568 char *primitive = primitivetype_table[j].wrapname;
571 while (utf_pos < utf_end(c->name)) {
572 if (*utf_pos++ != *primitive++) goto nomatch;
575 /* primitive type found */
576 *pos++ = primitivetype_table[j].typesig;
583 /* no primitive type and no arrayclass, so must be object */
587 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
601 for (i = 0; i < strlen(retType); i++) {
606 /* create utf-string */
607 result = utf_new(buffer, (pos - buffer));
608 MFREE(buffer, char, buffer_size);
614 /******************************************************************************************
616 retrieve the next argument or returntype from a descriptor
617 and return the corresponding class
619 *******************************************************************************************/
621 classinfo *get_type(char **utf_ptr,char *desc_end, bool skip)
623 classinfo *c = class_from_descriptor(*utf_ptr,desc_end,utf_ptr,
624 (skip) ? CLASSLOAD_SKIP : CLASSLOAD_LOAD);
627 panic("illegal descriptor");
629 if (skip) return NULL;
631 use_class_as_object(c);
636 /* get_parametertypes **********************************************************
638 use the descriptor of a method to generate a java/lang/Class array
639 which contains the classes of the parametertypes of the method
641 *******************************************************************************/
643 java_objectarray* get_parametertypes(methodinfo *m)
645 utf *descr = m->descriptor; /* method-descriptor */
646 char *utf_ptr = descr->text; /* current position in utf-text */
647 char *desc_end = utf_end(descr); /* points behind utf string */
648 java_objectarray* result;
649 int parametercount = 0;
653 utf_nextu2(&utf_ptr);
655 /* determine number of parameters */
656 while (*utf_ptr != ')') {
657 get_type(&utf_ptr, desc_end, true);
661 /* create class-array */
662 result = builtin_anewarray(parametercount, class_java_lang_Class);
664 utf_ptr = descr->text;
665 utf_nextu2(&utf_ptr);
667 /* get returntype classes */
668 for (i = 0; i < parametercount; i++)
670 (java_objectheader *) get_type(&utf_ptr, desc_end, false);
676 /* get_exceptiontypes **********************************************************
678 get the exceptions which can be thrown by a method
680 *******************************************************************************/
682 java_objectarray* get_exceptiontypes(methodinfo *m)
686 java_objectarray *result;
688 excount = m->thrownexceptionscount;
690 /* create class-array */
691 result = builtin_anewarray(excount, class_java_lang_Class);
693 for (i = 0; i < excount; i++) {
694 java_objectheader *o = (java_objectheader *) (m->thrownexceptions[i]);
695 use_class_as_object((classinfo *) o);
706 /******************************************************************************************
708 get the returntype class of a method
710 *******************************************************************************************/
712 classinfo *get_returntype(methodinfo *m)
714 char *utf_ptr; /* current position in utf-text */
715 char *desc_end; /* points behind utf string */
716 utf *desc = m->descriptor; /* method-descriptor */
718 utf_ptr = desc->text;
719 desc_end = utf_end(desc);
721 /* ignore parametertypes */
722 while ((utf_ptr<desc_end) && utf_nextu2(&utf_ptr)!=')')
725 return get_type(&utf_ptr,desc_end, false);
729 /*****************************************************************************/
730 /*****************************************************************************/
733 /*--------------------------------------------------------*/
734 void printNativeCall(nativeCall nc) {
737 printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
738 for (i=0; i<nc.methCnt; i++) {
739 printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
741 for (j=0; j<nc.callCnt[i]; j++) {
742 printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
743 nc.methods[i].methodCalls[j].classname,
744 nc.methods[i].methodCalls[j].methodname,
745 nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
748 printf("-+++++--------------------\n");fflush(stdout);
751 /*--------------------------------------------------------*/
752 void printCompNativeCall(nativeCompCall nc) {
754 printf("printCompNativeCall BEGIN\n");fflush(stdout);
755 printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
756 utf_display(nc.classname); fflush(stdout);
758 for (i=0; i<nc.methCnt; i++) {
759 printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
760 utf_display(nc.methods[i].methodname); fflush(stdout);
761 utf_display(nc.methods[i].descriptor);fflush(stdout);
762 printf("\n");fflush(stdout);
764 for (j=0; j<nc.callCnt[i]; j++) {
765 printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
766 utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
767 utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
768 utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
769 printf("\n");fflush(stdout);
772 printf("---------------------\n");fflush(stdout);
776 /*--------------------------------------------------------*/
777 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d )
790 /*--------------------------------------------------------*/
791 nativeCall* findNativeClassCalls(char *aclassname ) {
794 for (i=0;i<NATIVECALLSSIZE; i++) {
795 /* convert table to utf later to speed up search */
796 if (strcmp(nativeCalls[i].classname, aclassname) == 0)
797 return &nativeCalls[i];
802 /*--------------------------------------------------------*/
803 /*--------------------------------------------------------*/
804 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
808 ncc->classname = utf_new_char(nc.classname);
809 ncc->methCnt = nc.methCnt;
811 for (i=0; i<nc.methCnt; i++) {
812 ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
813 ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
814 ncc->callCnt[i] = nc.callCnt[i];
816 for (j=0; j<nc.callCnt[i]; j++) {
818 ncc->methods[i].methodCalls[j].classname = utf_new_char(nc.methods[i].methodCalls[j].classname);
820 if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
821 ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
822 ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
825 ncc->methods[i].methodCalls[j].methodname = NULL;
826 ncc->methods[i].methodCalls[j].descriptor = NULL;
834 /*--------------------------------------------------------*/
836 bool natcall2utf(bool natcallcompdone) {
842 for (i=0;i<NATIVECALLSSIZE; i++) {
843 utfNativeCall (nativeCalls[i], &nativeCompCalls[i]);
849 /*--------------------------------------------------------*/
852 java_objectarray *builtin_asm_createclasscontextarray(classinfo **end, classinfo **start)
854 #if defined(__GNUC__)
855 #warning platform dependend
857 java_objectarray *tmpArray;
863 size = (((size_t) start) - ((size_t) end)) / sizeof(classinfo*);
865 /*printf("end %p, start %p, size %ld\n",end,start,size);*/
866 if (!class_java_lang_Class)
867 class_java_lang_Class = class_new(utf_new_char("java/lang/Class"));
869 if (!class_java_lang_SecurityManager)
870 class_java_lang_SecurityManager =
871 class_new(utf_new_char("java/lang/SecurityManager"));
874 if (start == class_java_lang_SecurityManager) {
881 builtin_newarray(size, class_array_of(class_java_lang_Class)->vftbl);
883 for(i = 0, current = start; i < size; i++, current--) {
886 utf_display(c->name);*/
887 use_class_as_object(c);
888 tmpArray->data[i] = (java_objectheader *) c;
895 java_lang_ClassLoader *builtin_asm_getclassloader(classinfo **end, classinfo **start)
897 #if defined(__GNUC__)
898 #warning platform dependend
903 classinfo *privilegedAction;
906 size = (((size_t) start) - ((size_t) end)) / sizeof(classinfo*);
908 /* log_text("builtin_asm_getclassloader");
909 printf("end %p, start %p, size %ld\n",end,start,size);*/
911 if (!class_java_lang_SecurityManager)
912 class_java_lang_SecurityManager =
913 class_new(utf_new_char("java/lang/SecurityManager"));
916 if (start == class_java_lang_SecurityManager) {
922 privilegedAction=class_new(utf_new_char("java/security/PrivilegedAction"));
924 for(i = 0, current = start; i < size; i++, current--) {
927 if (c == privilegedAction)
931 return (java_lang_ClassLoader *) c->classloader;
939 * These are local overrides for various environment variables in Emacs.
940 * Please do not remove this and leave it at the end of the file, where
941 * Emacs will automagically detect them.
942 * ---------------------------------------------------------------------
945 * indent-tabs-mode: t