1 /* native.c - table of native functions
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
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 The .hh files created with the header file generator are all
32 included here as are the C functions implementing these methods.
34 $Id: native.c 1113 2004-06-02 10:31:09Z twisti $
53 #include "nativetypes.hh"
60 #include "toolbox/logging.h"
61 #include "toolbox/memory.h"
62 #include "threads/thread.h"
63 #include "threads/threadio.h"
64 #include "threads/locks.h"
65 #include "nat/java_lang_VMClass.h"
66 #include "nat/java_lang_Throwable.h"
68 /* Include files for IO functions */
72 #include <sys/types.h>
78 #include "threads/threadio.h"
80 /* searchpath for classfiles */
83 /* for java-string to char conversion */
84 #define MAXSTRINGSIZE 1000
87 /******************** systemclasses required for native methods ***************/
89 classinfo *class_java_lang_Class;
90 classinfo *class_java_lang_VMClass;
91 classinfo *class_java_lang_System;
92 classinfo *class_java_lang_ClassLoader;
93 classinfo *class_gnu_java_lang_SystemClassLoader;
94 classinfo *class_java_lang_SecurityManager;
95 classinfo *class_java_lang_Double;
96 classinfo *class_java_lang_Float;
97 classinfo *class_java_lang_Long;
98 classinfo *class_java_lang_Byte;
99 classinfo *class_java_lang_Short;
100 classinfo *class_java_lang_Boolean;
101 classinfo *class_java_lang_Void;
102 classinfo *class_java_lang_Character;
103 classinfo *class_java_lang_Integer;
105 methodinfo *method_vmclass_init;
108 /* system exception classes required while compiling */
110 classinfo *class_java_lang_Throwable;
113 /* exception/error super class */
115 char *string_java_lang_Throwable =
116 "java/lang/Throwable";
118 char *string_java_lang_VMThrowable =
119 "java/lang/VMThrowable";
122 /* specify some exception strings for code generation */
124 char *string_java_lang_ArithmeticException =
125 "java/lang/ArithmeticException";
127 char *string_java_lang_ArithmeticException_message =
130 char *string_java_lang_ArrayIndexOutOfBoundsException =
131 "java/lang/ArrayIndexOutOfBoundsException";
133 char *string_java_lang_ArrayStoreException =
134 "java/lang/ArrayStoreException";
136 char *string_java_lang_ClassCastException =
137 "java/lang/ClassCastException";
139 char *string_java_lang_ClassNotFoundException =
140 "java/lang/ClassNotFoundException";
142 char *string_java_lang_CloneNotSupportedException =
143 "java/lang/CloneNotSupportedException";
145 char *string_java_lang_Exception =
146 "java/lang/Exception";
148 char *string_java_lang_IllegalArgumentException =
149 "java/lang/IllegalArgumentException";
151 char *string_java_lang_IllegalMonitorStateException =
152 "java/lang/IllegalMonitorStateException";
154 char *string_java_lang_NegativeArraySizeException =
155 "java/lang/NegativeArraySizeException";
157 char *string_java_lang_NoSuchFieldException =
158 "java/lang/NoSuchFieldException";
160 char *string_java_lang_NoSuchMethodException =
161 "java/lang/NoSuchMethodException";
163 char *string_java_lang_NullPointerException =
164 "java/lang/NullPointerException";
167 /* specify some error strings for code generation */
169 char *string_java_lang_AbstractMethodError =
170 "java/lang/AbstractMethodError";
172 char *string_java_lang_ClassCircularityError =
173 "java/lang/ClassCircularityError";
175 char *string_java_lang_ClassFormatError =
176 "java/lang/ClassFormatError";
178 char *string_java_lang_Error =
181 char *string_java_lang_ExceptionInInitializerError =
182 "java/lang/ExceptionInInitializerError";
184 char *string_java_lang_IncompatibleClassChangeError =
185 "java/lang/IncompatibleClassChangeError";
187 char *string_java_lang_InternalError =
188 "java/lang/InternalError";
190 char *string_java_lang_LinkageError =
191 "java/lang/LinkageError";
193 char *string_java_lang_NoClassDefFoundError =
194 "java/lang/NoClassDefFoundError";
196 char *string_java_lang_NoSuchFieldError =
197 "java/lang/NoSuchFieldError";
199 char *string_java_lang_NoSuchMethodError =
200 "java/lang/NoSuchMethodError";
202 char *string_java_lang_OutOfMemoryError =
203 "java/lang/OutOfMemoryError";
205 char *string_java_lang_VerifyError =
206 "java/lang/VerifyError";
208 char *string_java_lang_VirtualMachineError =
209 "java/lang/VirtualMachineError";
212 /* the system classloader object */
213 struct java_lang_ClassLoader *SystemClassLoader = NULL;
215 /* for raising exceptions from native methods */
216 #if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
217 java_objectheader* _exceptionptr = NULL;
220 /************* use classinfo structure as java.lang.Class object **************/
222 void use_class_as_object(classinfo *c)
226 java_objectheader *vmo;
228 /* vt = class_java_lang_Class->vftbl; */
230 if (!c->classvftbl) {
231 c->classvftbl = true;
233 /* copy_vftbl(&newtbl, vt);
234 newtbl->class = c->header.vftbl->class;
235 newtbl->baseval = c->header.vftbl->baseval;
236 newtbl->diffval = c->header.vftbl->diffval;
237 c->header.vftbl = newtbl;*/
239 c->header.vftbl = class_java_lang_Class->vftbl;
241 method_vmclass_init =
242 class_findmethod(class_java_lang_VMClass,
243 utf_new_char("<init>"),
244 utf_new_char("(Lgnu/classpath/RawData;)V"));
246 if (method_vmclass_init == 0) {
247 class_showmethods(class_java_lang_VMClass);
248 panic("Needed class initializer for VMClass could not be found");
251 vmo = builtin_new(class_java_lang_VMClass);
254 panic("Error while creating instance of java/lang/VMClass");
256 asm_calljavafunction(method_vmclass_init, vmo, c, NULL, NULL);
258 c->vmClass = (java_lang_VMClass *) vmo;
260 setfield_critical(class_java_lang_Class,vmo,"vmClass", "Ljava/lang/VMClass;", jobject, (jobject) class_java_lang_Class /*this*/);
268 /*************************** include native methods ***************************/
271 #include "nat/GdkGraphics.c"
272 #include "nat/GtkComponentPeer.c"
273 #include "nat/GdkPixbufDecoder.c"
274 #include "nat/GtkScrollPanePeer.c"
275 #include "nat/GtkFileDialogPeer.c"
276 #include "nat/GtkLabelPeer.c"
280 /************************** tables for methods ********************************/
285 /* table for locating native methods */
286 static struct nativeref {
294 #include "nativetable.hh"
299 #define NATIVETABLESIZE (sizeof(nativetable)/sizeof(struct nativeref))
301 /* table for fast string comparison */
302 static struct nativecompref {
308 } nativecomptable [NATIVETABLESIZE];
310 /* string comparsion table initialized */
311 static bool nativecompdone = false;
314 /******************************************************************************/
315 /******************************************************************************/
316 #include "natcalls.h"
318 /* string call comparison table initialized */
320 /******************************************************************************/
321 /******************************************************************************/
323 /* init_system_exceptions *****************************************************
325 load, link and compile exceptions used in the system
327 *******************************************************************************/
329 void init_system_exceptions()
333 /* java/lang/Throwable */
335 class_java_lang_Throwable =
336 class_new(utf_new_char(string_java_lang_Throwable));
337 class_load(class_java_lang_Throwable);
338 class_link(class_java_lang_Throwable);
339 compile_all_class_methods(class_java_lang_Throwable);
341 /* java/lang/VMThrowable */
343 c = class_new(utf_new_char(string_java_lang_VMThrowable));
346 compile_all_class_methods(c);
348 /* java/lang/ClassFormatError */
350 c = class_new(utf_new_char(string_java_lang_ClassFormatError));
353 compile_all_class_methods(c);
355 /* java/lang/Error */
357 c = class_new(utf_new_char(string_java_lang_Error));
360 compile_all_class_methods(c);
362 /* java/lang/Exception */
364 c = class_new(utf_new_char(string_java_lang_Exception));
367 compile_all_class_methods(c);
369 /* java/lang/IncompatibleClassChangeError */
371 c = class_new(utf_new_char(string_java_lang_IncompatibleClassChangeError));
374 compile_all_class_methods(c);
376 /* java/lang/LinkageError */
378 c = class_new(utf_new_char(string_java_lang_LinkageError));
381 compile_all_class_methods(c);
383 /* java/lang/NoClassDefFoundError */
385 c = class_new(utf_new_char(string_java_lang_NoClassDefFoundError));
388 compile_all_class_methods(c);
390 /* java/lang/NoSuchFieldError */
392 c = class_new(utf_new_char(string_java_lang_NoSuchFieldError));
395 compile_all_class_methods(c);
397 /* java/lang/NoSuchMethodError */
399 c = class_new(utf_new_char(string_java_lang_NoSuchMethodError));
402 compile_all_class_methods(c);
404 /* java/lang/OutOfMemoryError */
406 c = class_new(utf_new_char(string_java_lang_OutOfMemoryError));
409 compile_all_class_methods(c);
411 /* java/lang/VerifyError */
413 c = class_new(utf_new_char(string_java_lang_VerifyError));
416 compile_all_class_methods(c);
418 /* java/lang/VirtualMachineError */
420 c = class_new(utf_new_char(string_java_lang_VirtualMachineError));
423 compile_all_class_methods(c);
427 void compile_all_class_methods(classinfo *c)
431 for (i = 0; i < c->methodscount; i++) {
432 (void) jit_compile(&(c->methods[i]));
437 void throw_exception_exit()
439 java_objectheader *xptr;
444 xptr = *exceptionptr;
446 /* clear exception, because we are calling jit code again */
447 *exceptionptr = NULL;
449 fprintf(stderr, "Exception in thread \"main\" ");
452 c = xptr->vftbl->class;
454 /* ts = class_resolveclassmethod(c, */
455 /* utf_new_char("toString"), */
456 /* utf_new_char("()Ljava/lang/String;"), */
457 /* class_java_lang_Object, */
461 /* panic("internal error"); */
464 /* tostring = asm_calljavafunction(ts, xptr, NULL, NULL, NULL); */
466 /* utf_display(javastring_toutf(tostring, false)); */
468 pss = class_resolveclassmethod(c,
469 utf_new_char("printStackTrace"),
471 class_java_lang_Object,
474 /* print the stacktrace */
476 asm_calljavafunction(pss, xptr, NULL, NULL, NULL);
478 /* this normally means, we are EXTREMLY out of memory, but may be
479 any other exception */
481 utf_fprint_classname(stderr, c->name);
482 fprintf(stderr, "\n");
486 utf_fprint_classname(stderr, c->name);
487 fprintf(stderr, ": printStackTrace()V not found!\n");
498 void throw_cacao_exception_exit(char *exception, char *message)
504 len = strlen(exception);
505 tmp = MNEW(char, len);
506 strncpy(tmp, exception, len);
508 /* convert to classname */
510 for (i = len - 1; i >= 0; i--) {
511 if (tmp[i] == '/') tmp[i] = '.';
514 fprintf(stderr, "Exception in thread \"main\" %s", tmp);
516 MFREE(tmp, char, len);
518 if (strlen(message) > 0)
519 fprintf(stderr, ": %s", message);
521 fprintf(stderr, "\n");
529 #define CREATENEW_EXCEPTION(ex) \
530 java_objectheader *newEx; \
531 java_objectheader *oldexception=*exceptionptr;\
534 *exceptionptr=oldexception;\
537 java_objectheader *new_exception(char *classname)
539 classinfo *c = class_new(utf_new_char(classname));
541 CREATENEW_EXCEPTION(native_new_and_init(c));
544 java_objectheader *new_exception_message(char *classname, char *message)
546 classinfo *c = class_new(utf_new_char(classname));
548 CREATENEW_EXCEPTION(native_new_and_init_string(c, javastring_new_char(message)));
552 java_objectheader *new_exception_throwable(char *classname, java_lang_Throwable *throwable)
554 classinfo *c = class_new(utf_new_char(classname));
556 CREATENEW_EXCEPTION(native_new_and_init_throwable(c, throwable));
560 java_objectheader *new_exception_utfmessage(char *classname, utf *message)
562 classinfo *c = class_new(utf_new_char(classname));
564 CREATENEW_EXCEPTION(native_new_and_init_string(c, javastring_new(message)));
568 java_objectheader *new_exception_javastring(char *classname, java_lang_String *message)
570 classinfo *c = class_new(utf_new_char(classname));
572 CREATENEW_EXCEPTION(native_new_and_init_string(c, message));
576 java_objectheader *new_exception_int(char *classname, s4 i)
578 classinfo *c = class_new(utf_new_char(classname));
580 CREATENEW_EXCEPTION(native_new_and_init_int(c, i));
584 /*********************** function: native_loadclasses **************************
586 load classes required for native methods
588 *******************************************************************************/
590 void native_loadclasses()
592 static int classesLoaded = 0; /*temporary hack JoWenn*/
599 class_java_lang_Cloneable =
600 class_new(utf_new_char("java/lang/Cloneable"));
601 class_load(class_java_lang_Cloneable);
602 class_link(class_java_lang_Cloneable);
604 class_java_lang_Class =
605 class_new(utf_new_char("java/lang/Class"));
606 class_load(class_java_lang_Class);
607 class_link(class_java_lang_Class);
609 class_java_lang_VMClass =
610 class_new(utf_new_char("java/lang/VMClass"));
611 class_load(class_java_lang_VMClass);
612 class_link(class_java_lang_VMClass);
614 class_java_lang_ClassLoader =
615 class_new(utf_new_char("java/lang/ClassLoader"));
616 class_load(class_java_lang_ClassLoader);
617 class_link(class_java_lang_ClassLoader);
619 /* load classes for wrapping primitive types */
620 class_java_lang_Double = class_new(utf_new_char("java/lang/Double"));
621 class_load(class_java_lang_Double);
622 class_link(class_java_lang_Double);
624 class_java_lang_Float = class_new(utf_new_char("java/lang/Float"));
625 class_load(class_java_lang_Float);
626 class_link(class_java_lang_Float);
628 class_java_lang_Character = class_new(utf_new_char("java/lang/Character"));
629 class_load(class_java_lang_Character);
630 class_link(class_java_lang_Character);
632 class_java_lang_Integer = class_new(utf_new_char("java/lang/Integer"));
633 class_load(class_java_lang_Integer);
634 class_link(class_java_lang_Integer);
636 class_java_lang_Long = class_new(utf_new_char("java/lang/Long"));
637 class_load(class_java_lang_Long);
638 class_link(class_java_lang_Long);
640 class_java_lang_Byte = class_new(utf_new_char("java/lang/Byte"));
641 class_load(class_java_lang_Byte);
642 class_link(class_java_lang_Byte);
644 class_java_lang_Short = class_new(utf_new_char("java/lang/Short"));
645 class_load(class_java_lang_Short);
646 class_link(class_java_lang_Short);
648 class_java_lang_Boolean = class_new(utf_new_char("java/lang/Boolean"));
649 class_load(class_java_lang_Boolean);
650 class_link(class_java_lang_Boolean);
652 class_java_lang_Void = class_new(utf_new_char("java/lang/Void"));
653 class_load(class_java_lang_Void);
654 class_link(class_java_lang_Void);
658 /*****************************************************************************
660 create systemclassloader object and initialize instance fields
662 ******************************************************************************/
664 void init_systemclassloader()
666 log_text("init_systemclassloader");
667 if (!SystemClassLoader) {
668 native_loadclasses();
669 log_text("Initializing new system class loader");
670 /* create object and call initializer */
671 SystemClassLoader = (java_lang_ClassLoader *) native_new_and_init(class_new(utf_new_char("gnu/java/lang/SystemClassLoader")));
673 /* systemclassloader has no parent */
674 SystemClassLoader->parent = NULL;
675 SystemClassLoader->initialized = true;
677 log_text("leaving system class loader");
681 /********************* function: native_setclasspath **************************/
683 void native_setclasspath(char *path)
685 /* set searchpath for classfiles */
690 /*********************** Function: native_findfunction *************************
692 Looks up a method (must have the same class name, method name, descriptor
693 and 'static'ness) and returns a function pointer to it.
694 Returns: function pointer or NULL (if there is no such method)
696 Remark: For faster operation, the names/descriptors are converted from C
697 strings to Unicode the first time this function is called.
699 *******************************************************************************/
701 functionptr native_findfunction(utf *cname, utf *mname,
702 utf *desc, bool isstatic)
705 /* entry of table for fast string comparison */
706 struct nativecompref *n;
707 /* for warning message if no function is found */
711 isstatic = isstatic ? true : false;
713 if (!nativecompdone) {
714 for (i = 0; i < NATIVETABLESIZE; i++) {
715 nativecomptable[i].classname =
716 utf_new_char(nativetable[i].classname);
717 nativecomptable[i].methodname =
718 utf_new_char(nativetable[i].methodname);
719 nativecomptable[i].descriptor =
720 utf_new_char(nativetable[i].descriptor);
721 nativecomptable[i].isstatic =
722 nativetable[i].isstatic;
723 nativecomptable[i].func =
726 nativecompdone = true;
731 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
733 buffer = MNEW(char, buffer_len);
735 strcpy(buffer, "searching matching function in native table:");
736 utf_sprint(buffer+strlen(buffer), mname);
737 strcpy(buffer+strlen(buffer), ": ");
738 utf_sprint(buffer+strlen(buffer), desc);
739 strcpy(buffer+strlen(buffer), " for class ");
740 utf_sprint(buffer+strlen(buffer), cname);
744 MFREE(buffer, char, buffer_len);
747 for (i = 0; i < NATIVETABLESIZE; i++) {
748 n = &(nativecomptable[i]);
750 if (cname == n->classname && mname == n->methodname &&
751 desc == n->descriptor && isstatic == n->isstatic)
755 if (cname == n->classname && mname == n->methodname ) log_text("static and descriptor mismatch");
759 utf_strlen(n->classname) + utf_strlen(n->methodname) + utf_strlen(n->descriptor) + 64;
761 buffer = MNEW(char, buffer_len);
763 strcpy(buffer, "comparing with:");
764 utf_sprint(buffer+strlen(buffer), n->methodname);
765 strcpy (buffer+strlen(buffer), ": ");
766 utf_sprint(buffer+strlen(buffer), n->descriptor);
767 strcpy(buffer+strlen(buffer), " for class ");
768 utf_sprint(buffer+strlen(buffer), n->classname);
772 MFREE(buffer, char, buffer_len);
779 /* no function was found, display warning */
782 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
784 buffer = MNEW(char, buffer_len);
786 strcpy(buffer, "warning: native function ");
787 utf_sprint(buffer + strlen(buffer), mname);
788 strcpy(buffer + strlen(buffer), ": ");
789 utf_sprint(buffer + strlen(buffer), desc);
790 strcpy(buffer + strlen(buffer), " not found in class ");
791 utf_sprint(buffer + strlen(buffer), cname);
795 MFREE(buffer, char, buffer_len);
799 /* keep compiler happy */
804 /********************** function: javastring_new *******************************
806 creates a new object of type java/lang/String with the text of
807 the specified utf8-string
809 return: pointer to the string or NULL if memory is exhausted.
811 *******************************************************************************/
813 java_lang_String *javastring_new(utf *u)
815 char *utf_ptr = u->text; /* current utf character in utf string */
816 int utflength = utf_strlen(u); /* length of utf-string if uncompressed */
817 java_lang_String *s; /* result-string */
821 s = (java_lang_String *) builtin_new(class_java_lang_String);
822 a = builtin_newarray_char(utflength);
824 /* javastring or character-array could not be created */
828 /* decompress utf-string */
829 for (i = 0; i < utflength; i++)
830 a->data[i] = utf_nextu2(&utf_ptr);
832 /* set fields of the javastring-object */
835 s->count = utflength;
841 /********************** function: javastring_new_char **************************
843 creates a new java/lang/String object which contains the convertet
844 C-string passed via text.
846 return: the object pointer or NULL if memory is exhausted.
848 *******************************************************************************/
850 java_lang_String *javastring_new_char(char *text)
853 s4 len = strlen(text); /* length of the string */
854 java_lang_String *s; /* result-string */
857 s = (java_lang_String *) builtin_new(class_java_lang_String);
858 a = builtin_newarray_char(len);
860 /* javastring or character-array could not be created */
865 for (i = 0; i < len; i++)
866 a->data[i] = text[i];
868 /* set fields of the javastring-object */
877 /************************* function javastring_tochar **************************
879 converts a Java string into a C string.
881 return: pointer to C string
883 Caution: every call of this function overwrites the previous string !!!
885 *******************************************************************************/
887 static char stringbuffer[MAXSTRINGSIZE];
889 char *javastring_tochar(java_objectheader *so)
891 java_lang_String *s = (java_lang_String *) so;
903 if (s->count > MAXSTRINGSIZE)
906 for (i = 0; i < s->count; i++)
907 stringbuffer[i] = a->data[s->offset + i];
909 stringbuffer[i] = '\0';
915 /****************** function class_findfield_approx ****************************
917 searches in 'classinfo'-structure for a field with the
920 *******************************************************************************/
922 fieldinfo *class_findfield_approx(classinfo *c, utf *name)
926 for (i = 0; i < c->fieldscount; i++) {
927 /* compare field names */
928 if ((c->fields[i].name == name))
929 return &(c->fields[i]);
932 /* field was not found, raise exception */
933 *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
939 s4 class_findfield_index_approx(classinfo *c, utf *name)
943 for (i = 0; i < c->fieldscount; i++) {
944 /* compare field names */
945 if ((c->fields[i].name == name))
949 /* field was not found, raise exception */
950 *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
956 /********************** function: native_new_and_init *************************
958 Creates a new object on the heap and calls the initializer.
959 Returns the object pointer or NULL if memory is exhausted.
961 *******************************************************************************/
963 java_objectheader *native_new_and_init(classinfo *c)
966 java_objectheader *o;
969 return *exceptionptr;
971 o = builtin_new(c); /* create object */
976 /* find initializer */
978 m = class_findmethod(c,
979 utf_new_char("<init>"),
980 utf_new_char("()V"));
982 if (!m) { /* initializer not found */
984 char logtext[MAXLOGTEXT];
985 sprintf(logtext, "Warning: class has no instance-initializer: ");
986 utf_sprint_classname(logtext + strlen(logtext), c->name);
992 /* call initializer */
994 asm_calljavafunction(m, o, NULL, NULL, NULL);
1000 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
1003 java_objectheader *o;
1006 return *exceptionptr;
1008 o = builtin_new(c); /* create object */
1013 /* find initializer */
1015 m = class_findmethod(c,
1016 utf_new_char("<init>"),
1017 utf_new_char("(Ljava/lang/String;)V"));
1019 if (!m) { /* initializer not found */
1021 char logtext[MAXLOGTEXT];
1022 sprintf(logtext, "Warning: class has no instance-initializer: ");
1023 utf_sprint_classname(logtext + strlen(logtext), c->name);
1029 /* call initializer */
1031 asm_calljavafunction(m, o, s, NULL, NULL);
1037 java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
1040 java_objectheader *o;
1043 return *exceptionptr;
1045 o = builtin_new(c); /* create object */
1047 if (!o) return NULL;
1049 /* find initializer */
1051 m = class_findmethod(c,
1052 utf_new_char("<init>"),
1053 utf_new_char("(I)V"));
1055 if (!m) { /* initializer not found */
1057 char logtext[MAXLOGTEXT];
1058 sprintf(logtext, "Warning: class has no instance-initializer: ");
1059 utf_sprint_classname(logtext + strlen(logtext), c->name);
1065 /* call initializer */
1067 #if defined(__I386__) || defined(__POWERPC__)
1068 asm_calljavafunction(m, o, (void *) i, NULL, NULL);
1070 asm_calljavafunction(m, o, (void *) (s8) i, NULL, NULL);
1077 java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t)
1080 java_objectheader *o;
1083 return *exceptionptr;
1085 o = builtin_new(c); /* create object */
1087 if (!o) return NULL;
1089 /* find initializer */
1091 m = class_findmethod(c,
1092 utf_new_char("<init>"),
1093 utf_new_char("(Ljava/lang/Throwable;)V"));
1095 if (!m) { /* initializer not found */
1097 char logtext[MAXLOGTEXT];
1098 sprintf(logtext, "Warning: class has no instance-initializer: ");
1099 utf_sprint_classname(logtext + strlen(logtext), c->name);
1105 /* call initializer */
1107 asm_calljavafunction(m, o, t, NULL, NULL);
1113 /******************** function: stringtable_update ****************************
1115 traverses the javastring hashtable and sets the vftbl-entries of
1116 javastrings which were temporarily set to NULL, because
1117 java.lang.Object was not yet loaded
1119 *******************************************************************************/
1121 void stringtable_update ()
1123 java_lang_String *js;
1125 literalstring *s; /* hashtable entry */
1128 for (i = 0; i < string_hash.size; i++) {
1129 s = string_hash.ptr[i];
1133 js = (java_lang_String *) s->string;
1135 if (!js || !js->value)
1136 /* error in hashtable found */
1137 panic("invalid literalstring in hashtable");
1141 if (!js->header.vftbl)
1142 /* vftbl of javastring is NULL */
1143 js->header.vftbl = class_java_lang_String->vftbl;
1145 if (!a->header.objheader.vftbl)
1146 /* vftbl of character-array is NULL */
1147 a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
1149 /* follow link in external hash chain */
1157 /************************* function: u2_utflength ***************************
1159 returns the utf length in bytes of a u2 array
1161 *****************************************************************************/
1163 u4 u2_utflength(u2 *text, u4 u2_length)
1165 u4 result_len = 0; /* utf length in bytes */
1166 u2 ch; /* current unicode character */
1169 for (len = 0; len < u2_length; len++) {
1170 /* next unicode character */
1173 /* determine bytes required to store unicode character as utf */
1174 if (ch && (ch < 0x80))
1176 else if (ch < 0x800)
1186 /********************* function: utf_new_u2 ***********************************
1188 make utf symbol from u2 array,
1189 if isclassname is true '.' is replaced by '/'
1191 *******************************************************************************/
1193 utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
1195 char *buffer; /* memory buffer for unicode characters */
1196 char *pos; /* pointer to current position in buffer */
1197 u4 left; /* unicode characters left */
1198 u4 buflength; /* utf length in bytes of the u2 array */
1199 utf *result; /* resulting utf-string */
1202 /* determine utf length in bytes and allocate memory */
1203 /* printf("utf_new_u2: unicode_length=%d\n",unicode_length); */
1204 buflength = u2_utflength(unicode_pos, unicode_length);
1205 buffer = MNEW(char, buflength);
1207 /* memory allocation failed */
1209 printf("length: %d\n",buflength);
1210 log_text("utf_new_u2:buffer==NULL");
1216 for (i = 0; i++ < unicode_length; unicode_pos++) {
1217 /* next unicode character */
1218 u2 c = *unicode_pos;
1220 if ((c != 0) && (c < 0x80)) {
1223 if ((int) left < 0) break;
1224 /* convert classname */
1225 if (isclassname && c == '.')
1230 } else if (c < 0x800) {
1232 unsigned char high = c >> 6;
1233 unsigned char low = c & 0x3F;
1235 if ((int) left < 0) break;
1236 *pos++ = high | 0xC0;
1237 *pos++ = low | 0x80;
1241 char low = c & 0x3f;
1242 char mid = (c >> 6) & 0x3F;
1243 char high = c >> 12;
1245 if ((int) left < 0) break;
1246 *pos++ = high | 0xE0;
1247 *pos++ = mid | 0x80;
1248 *pos++ = low | 0x80;
1252 /* insert utf-string into symbol-table */
1253 result = utf_new(buffer,buflength);
1255 MFREE(buffer, char, buflength);
1261 /********************* function: javastring_toutf *****************************
1263 make utf symbol from javastring
1265 *******************************************************************************/
1267 utf *javastring_toutf(java_lang_String *string, bool isclassname)
1269 java_lang_String *str = (java_lang_String *) string;
1271 /* printf("javastring_toutf offset: %d, len %d\n",str->offset, str->count); */
1272 /* fflush(stdout); */
1274 return utf_new_u2(str->value->data + str->offset, str->count, isclassname);
1278 /********************* function: literalstring_u2 *****************************
1280 searches for the javastring with the specified u2-array in
1281 the string hashtable, if there is no such string a new one is
1284 if copymode is true a copy of the u2-array is made
1286 *******************************************************************************/
1288 java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
1291 literalstring *s; /* hashtable element */
1292 java_lang_String *js; /* u2-array wrapped in javastring */
1293 java_chararray *stringdata; /* copy of u2-array */
1298 //#define DEBUG_LITERALSTRING_U2
1299 #ifdef DEBUG_LITERALSTRING_U2
1300 printf("literalstring_u2: length=%d, offset=%d\n", length, offset);
1304 /* find location in hashtable */
1305 key = unicode_hashkey(a->data + offset, length);
1306 slot = key & (string_hash.size - 1);
1307 s = string_hash.ptr[slot];
1310 js = (java_lang_String *) s->string;
1312 if (length == js->count) {
1314 for (i = 0; i < length; i++) {
1315 if (a->data[offset + i] != js->value->data[i])
1319 /* string already in hashtable, free memory */
1321 lit_mem_free(a, sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10);
1323 #ifdef DEBUG_LITERALSTRING_U2
1324 printf("literalstring_u2: foundentry at %p\n", js);
1325 utf_display(javastring_toutf(js, 0));
1329 return (java_objectheader *) js;
1333 /* follow link in external hash chain */
1338 /* create copy of u2-array for new javastring */
1339 u4 arraysize = sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10;
1340 stringdata = lit_mem_alloc(arraysize);
1341 /* memcpy(stringdata, a, arraysize); */
1342 memcpy(&(stringdata->header), &(a->header), sizeof(java_arrayheader));
1343 memcpy(&(stringdata->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10);
1349 /* location in hashtable found, complete arrayheader */
1350 stringdata->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
1351 stringdata->header.size = length;
1353 /* create new javastring */
1354 js = LNEW(java_lang_String);
1356 /* js->header.vftbl = class_java_lang_String->vftbl; */
1357 js->header.vftbl = class_load(class_new(utf_new_char("java/lang/String")))->vftbl;
1358 js->value = stringdata;
1362 /* create new literalstring */
1363 s = NEW(literalstring);
1364 s->hashlink = string_hash.ptr[slot];
1365 s->string = (java_objectheader *) js;
1366 string_hash.ptr[slot] = s;
1368 /* update numbe of hashtable entries */
1369 string_hash.entries++;
1371 /* reorganization of hashtable */
1372 if (string_hash.entries > (string_hash.size * 2)) {
1373 /* reorganization of hashtable, average length of
1374 the external chains is approx. 2 */
1378 hashtable newhash; /* the new hashtable */
1380 /* create new hashtable, double the size */
1381 init_hashtable(&newhash, string_hash.size * 2);
1382 newhash.entries = string_hash.entries;
1384 /* transfer elements to new hashtable */
1385 for (i = 0; i < string_hash.size; i++) {
1386 s = string_hash.ptr[i];
1388 literalstring *nexts = s->hashlink;
1389 js = (java_lang_String *) s->string;
1390 slot = unicode_hashkey(js->value->data, js->count) & (newhash.size - 1);
1392 s->hashlink = newhash.ptr[slot];
1393 newhash.ptr[slot] = s;
1395 /* follow link in external hash chain */
1400 /* dispose old table */
1401 MFREE(string_hash.ptr, void*, string_hash.size);
1402 string_hash = newhash;
1405 #ifdef DEBUG_LITERALSTRING_U2
1406 printf("literalstring_u2: newly created at %p\n", js);
1407 utf_display(javastring_toutf(js, 0));
1412 return (java_objectheader *) js;
1416 /******************** Function: literalstring_new *****************************
1418 creates a new javastring with the text of the utf-symbol
1419 and inserts it into the string hashtable
1421 *******************************************************************************/
1423 java_objectheader *literalstring_new(utf *u)
1425 char *utf_ptr = u->text; /* pointer to current unicode character in utf string */
1426 u4 utflength = utf_strlen(u); /* length of utf-string if uncompressed */
1427 java_chararray *a; /* u2-array constructed from utf string */
1430 /* allocate memory */
1431 a = lit_mem_alloc(sizeof(java_chararray) + sizeof(u2) * (utflength - 1) + 10);
1433 /* convert utf-string to u2-array */
1434 for (i = 0; i < utflength; i++)
1435 a->data[i] = utf_nextu2(&utf_ptr);
1437 return literalstring_u2(a, utflength, 0, false);
1441 /********************** function: literalstring_free **************************
1443 removes a javastring from memory
1445 ******************************************************************************/
1447 void literalstring_free(java_objectheader* sobj)
1449 java_lang_String *s = (java_lang_String *) sobj;
1450 java_chararray *a = s->value;
1452 /* dispose memory of java.lang.String object */
1453 LFREE(s, java_lang_String);
1455 /* dispose memory of java-characterarray */
1456 LFREE(a, sizeof(java_chararray) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
1460 void copy_vftbl(vftbl **dest, vftbl *src)
1464 /* XXX this kind of copying does not work (in the general
1465 * case). The interface tables would have to be copied, too. I
1466 * don't see why we should make a copy anyway. -Edwin
1468 *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
1469 memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
1470 memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
1475 /******************************************************************************************
1477 creates method signature (excluding return type) from array of
1478 class-objects representing the parameters of the method
1480 *******************************************************************************************/
1483 utf *create_methodsig(java_objectarray* types, char *retType)
1485 char *buffer; /* buffer for building the desciptor */
1486 char *pos; /* current position in buffer */
1487 utf *result; /* the method signature */
1488 u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
1491 if (!types) return NULL;
1493 /* determine required buffer-size */
1494 for (i = 0; i < types->header.size; i++) {
1495 classinfo *c = (classinfo *) types->data[i];
1496 buffer_size = buffer_size + c->name->blength + 2;
1499 if (retType) buffer_size += strlen(retType);
1501 /* allocate buffer */
1502 buffer = MNEW(u1, buffer_size);
1505 /* method-desciptor starts with parenthesis */
1508 for (i = 0; i < types->header.size; i++) {
1511 /* current argument */
1512 classinfo *c = (classinfo *) types->data[i];
1514 /* current position in utf-text */
1515 char *utf_ptr = c->name->text;
1517 /* determine type of argument */
1518 if ((ch = utf_nextu2(&utf_ptr)) == '[') {
1520 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
1521 *pos++ = *utf_ptr; /* copy text */
1525 /* check for primitive types */
1526 for (j = 0; j < PRIMITIVETYPE_COUNT; j++) {
1527 char *utf_pos = utf_ptr - 1;
1528 char *primitive = primitivetype_table[j].wrapname;
1531 while (utf_pos < utf_end(c->name)) {
1532 if (*utf_pos++ != *primitive++) goto nomatch;
1535 /* primitive type found */
1536 *pos++ = primitivetype_table[j].typesig;
1543 /* no primitive type and no arrayclass, so must be object */
1547 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
1561 for (i = 0; i < strlen(retType); i++) {
1562 *pos++ = retType[i];
1566 /* create utf-string */
1567 result = utf_new(buffer, (pos - buffer));
1568 MFREE(buffer, u1, buffer_size);
1574 /******************************************************************************************
1576 retrieve the next argument or returntype from a descriptor
1577 and return the corresponding class
1579 *******************************************************************************************/
1581 classinfo *get_type(char **utf_ptr,char *desc_end, bool skip)
1583 classinfo *c = class_from_descriptor(*utf_ptr,desc_end,utf_ptr,
1584 (skip) ? CLASSLOAD_SKIP : CLASSLOAD_LOAD);
1587 panic("illegal descriptor");
1589 if (skip) return NULL;
1591 use_class_as_object(c);
1596 /******************************************************************************************
1598 use the descriptor of a method to generate a java/lang/Class array
1599 which contains the classes of the parametertypes of the method
1601 *******************************************************************************************/
1603 java_objectarray* get_parametertypes(methodinfo *m)
1605 utf *descr = m->descriptor; /* method-descriptor */
1606 char *utf_ptr = descr->text; /* current position in utf-text */
1607 char *desc_end = utf_end(descr); /* points behind utf string */
1608 java_objectarray* result;
1609 int parametercount = 0;
1613 utf_nextu2(&utf_ptr);
1615 /* determine number of parameters */
1616 while ( *utf_ptr != ')' ) {
1617 get_type(&utf_ptr,desc_end,true);
1621 /* create class-array */
1622 result = builtin_anewarray(parametercount, class_java_lang_Class);
1624 utf_ptr = descr->text;
1625 utf_nextu2(&utf_ptr);
1627 /* get returntype classes */
1628 for (i = 0; i < parametercount; i++)
1629 result->data[i] = (java_objectheader *) get_type(&utf_ptr,desc_end, false);
1638 /******************************************************************************************
1640 get the exceptions which can be thrown by a method
1642 *******************************************************************************************/
1644 java_objectarray* get_exceptiontypes(methodinfo *m) {
1645 u2 exccount=m->thrownexceptionscount;
1647 java_objectarray *result;
1648 /* create class-array */
1649 result = builtin_anewarray(exccount, class_java_lang_Class);
1650 for (i=0;i<exccount;i++) {
1651 java_objectheader *oh=(java_objectheader*)(m->thrownexceptions[i]);
1652 use_class_as_object(oh);
1662 /******************************************************************************************
1664 get the returntype class of a method
1666 *******************************************************************************************/
1668 classinfo *get_returntype(methodinfo *m)
1670 char *utf_ptr; /* current position in utf-text */
1671 char *desc_end; /* points behind utf string */
1672 utf *desc = m->descriptor; /* method-descriptor */
1674 utf_ptr = desc->text;
1675 desc_end = utf_end(desc);
1677 /* ignore parametertypes */
1678 while ((utf_ptr<desc_end) && utf_nextu2(&utf_ptr)!=')')
1681 return get_type(&utf_ptr,desc_end, false);
1685 /*****************************************************************************/
1686 /*****************************************************************************/
1689 /*--------------------------------------------------------*/
1690 void printNativeCall(nativeCall nc) {
1693 printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
1694 for (i=0; i<nc.methCnt; i++) {
1695 printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
1697 for (j=0; j<nc.callCnt[i]; j++) {
1698 printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
1699 nc.methods[i].methodCalls[j].classname,
1700 nc.methods[i].methodCalls[j].methodname,
1701 nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1704 printf("-+++++--------------------\n");fflush(stdout);
1707 /*--------------------------------------------------------*/
1708 void printCompNativeCall(nativeCompCall nc) {
1710 printf("printCompNativeCall BEGIN\n");fflush(stdout);
1711 printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
1712 utf_display(nc.classname); fflush(stdout);
1714 for (i=0; i<nc.methCnt; i++) {
1715 printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
1716 utf_display(nc.methods[i].methodname); fflush(stdout);
1717 utf_display(nc.methods[i].descriptor);fflush(stdout);
1718 printf("\n");fflush(stdout);
1720 for (j=0; j<nc.callCnt[i]; j++) {
1721 printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
1722 utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
1723 utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
1724 utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1725 printf("\n");fflush(stdout);
1728 printf("---------------------\n");fflush(stdout);
1732 /*--------------------------------------------------------*/
1733 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d )
1746 /*--------------------------------------------------------*/
1747 nativeCall* findNativeClassCalls(char *aclassname ) {
1750 for (i=0;i<NATIVECALLSSIZE; i++) {
1751 /* convert table to utf later to speed up search */
1752 if (strcmp(nativeCalls[i].classname, aclassname) == 0)
1753 return &nativeCalls[i];
1758 /*--------------------------------------------------------*/
1759 /*--------------------------------------------------------*/
1760 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
1764 ncc->classname = utf_new_char(nc.classname);
1765 ncc->methCnt = nc.methCnt;
1767 for (i=0; i<nc.methCnt; i++) {
1768 ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
1769 ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
1770 ncc->callCnt[i] = nc.callCnt[i];
1772 for (j=0; j<nc.callCnt[i]; j++) {
1774 ncc->methods[i].methodCalls[j].classname = utf_new_char(nc.methods[i].methodCalls[j].classname);
1776 if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
1777 ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
1778 ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
1781 ncc->methods[i].methodCalls[j].methodname = NULL;
1782 ncc->methods[i].methodCalls[j].descriptor = NULL;
1790 /*--------------------------------------------------------*/
1792 bool natcall2utf(bool natcallcompdone) {
1795 if (natcallcompdone)
1798 for (i=0;i<NATIVECALLSSIZE; i++) {
1799 utfNativeCall (nativeCalls[i], &nativeCompCalls[i]);
1805 /*--------------------------------------------------------*/
1808 java_objectarray *builtin_asm_createclasscontextarray(classinfo **end,classinfo **start)
1810 #if defined(__GNUC__)
1811 #warning platform dependend
1813 java_objectarray *tmpArray;
1815 classinfo **current;
1817 size_t size=(((size_t)start)-((size_t)end)) / sizeof (classinfo*);
1818 /* printf("end %p, start %p, size %ld\n",end,start,size);*/
1819 if (!class_java_lang_Class)
1820 class_java_lang_Class = class_new(utf_new_char ("java/lang/Class"));
1821 if (!class_java_lang_SecurityManager)
1822 class_java_lang_SecurityManager = class_new(utf_new_char ("java/lang/SecurityManager"));
1824 if (start==class_java_lang_SecurityManager) {
1829 tmpArray=builtin_newarray(size, class_array_of(class_java_lang_Class)->vftbl);
1831 for(i=0,current=start;i<size;i++,current--) {
1833 /* printf("%d\n",i);
1834 utf_display(c->name);*/
1835 use_class_as_object(c);
1836 tmpArray->data[i]=c;
1842 java_lang_ClassLoader *builtin_asm_getclassloader(classinfo **end,classinfo **start)
1844 #if defined(__GNUC__)
1845 #warning platform dependend
1848 classinfo **current;
1850 classinfo *privilegedAction;
1851 size_t size=(((size_t)start)-((size_t)end)) / sizeof (classinfo*);
1852 /* log_text("builtin_asm_getclassloader");
1853 printf("end %p, start %p, size %ld\n",end,start,size);*/
1855 if (!class_java_lang_SecurityManager)
1856 class_java_lang_SecurityManager = class_new(utf_new_char ("java/lang/SecurityManager"));
1858 if (start==class_java_lang_SecurityManager) {
1864 privilegedAction=class_new(utf_new_char("java/security/PrivilegedAction"));
1866 for(i=0,current=start;i<size;i++,current--) {
1868 if (c==privilegedAction) return NULL;
1869 if (c->classloader) return c->classloader;
1877 log_text("Java_java_lang_VMSecurityManager_currentClassLoader");
1878 init_systemclassloader();
1880 return SystemClassLoader;*/
1884 * These are local overrides for various environment variables in Emacs.
1885 * Please do not remove this and leave it at the end of the file, where
1886 * Emacs will automagically detect them.
1887 * ---------------------------------------------------------------------
1890 * indent-tabs-mode: t