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 1296 2004-07-10 17:02:15Z stefan $
59 #include "toolbox/logging.h"
60 #include "toolbox/memory.h"
61 #include "threads/thread.h"
62 #include "threads/threadio.h"
63 #include "threads/locks.h"
64 #include "nat/java_lang_VMClass.h"
65 #include "nat/java_lang_Throwable.h"
67 /* Include files for IO functions */
71 #include <sys/types.h>
77 #include "threads/threadio.h"
79 /* include table of native functions */
81 #include "nativetable.inc"
84 /* searchpath for classfiles */
87 /* for java-string to char conversion */
88 #define MAXSTRINGSIZE 1000
91 /******************** systemclasses required for native methods ***************/
93 classinfo *class_java_lang_Class;
94 classinfo *class_java_lang_VMClass;
95 classinfo *class_java_lang_System;
96 classinfo *class_java_lang_ClassLoader;
97 classinfo *class_gnu_java_lang_SystemClassLoader;
98 classinfo *class_java_lang_SecurityManager;
99 classinfo *class_java_lang_Double;
100 classinfo *class_java_lang_Float;
101 classinfo *class_java_lang_Long;
102 classinfo *class_java_lang_Byte;
103 classinfo *class_java_lang_Short;
104 classinfo *class_java_lang_Boolean;
105 classinfo *class_java_lang_Void;
106 classinfo *class_java_lang_Character;
107 classinfo *class_java_lang_Integer;
109 methodinfo *method_vmclass_init;
112 /* system exception classes required in cacao */
114 classinfo *class_java_lang_Throwable;
115 classinfo *class_java_lang_Exception;
116 classinfo *class_java_lang_Error;
119 /* exception/error super class */
121 char *string_java_lang_Throwable =
122 "java/lang/Throwable";
124 char *string_java_lang_VMThrowable =
125 "java/lang/VMThrowable";
128 /* specify some exception strings for code generation */
130 char *string_java_lang_ArithmeticException =
131 "java/lang/ArithmeticException";
133 char *string_java_lang_ArithmeticException_message =
136 char *string_java_lang_ArrayIndexOutOfBoundsException =
137 "java/lang/ArrayIndexOutOfBoundsException";
139 char *string_java_lang_ArrayStoreException =
140 "java/lang/ArrayStoreException";
142 char *string_java_lang_ClassCastException =
143 "java/lang/ClassCastException";
145 char *string_java_lang_ClassNotFoundException =
146 "java/lang/ClassNotFoundException";
148 char *string_java_lang_CloneNotSupportedException =
149 "java/lang/CloneNotSupportedException";
151 char *string_java_lang_Exception =
152 "java/lang/Exception";
154 char *string_java_lang_IllegalArgumentException =
155 "java/lang/IllegalArgumentException";
157 char *string_java_lang_IllegalMonitorStateException =
158 "java/lang/IllegalMonitorStateException";
160 char *string_java_lang_NegativeArraySizeException =
161 "java/lang/NegativeArraySizeException";
163 char *string_java_lang_NoSuchFieldException =
164 "java/lang/NoSuchFieldException";
166 char *string_java_lang_NoSuchMethodException =
167 "java/lang/NoSuchMethodException";
169 char *string_java_lang_NullPointerException =
170 "java/lang/NullPointerException";
173 /* specify some error strings for code generation */
175 char *string_java_lang_AbstractMethodError =
176 "java/lang/AbstractMethodError";
178 char *string_java_lang_ClassCircularityError =
179 "java/lang/ClassCircularityError";
181 char *string_java_lang_ClassFormatError =
182 "java/lang/ClassFormatError";
184 char *string_java_lang_Error =
187 char *string_java_lang_ExceptionInInitializerError =
188 "java/lang/ExceptionInInitializerError";
190 char *string_java_lang_IncompatibleClassChangeError =
191 "java/lang/IncompatibleClassChangeError";
193 char *string_java_lang_InternalError =
194 "java/lang/InternalError";
196 char *string_java_lang_LinkageError =
197 "java/lang/LinkageError";
199 char *string_java_lang_NoClassDefFoundError =
200 "java/lang/NoClassDefFoundError";
202 char *string_java_lang_NoSuchFieldError =
203 "java/lang/NoSuchFieldError";
205 char *string_java_lang_NoSuchMethodError =
206 "java/lang/NoSuchMethodError";
208 char *string_java_lang_OutOfMemoryError =
209 "java/lang/OutOfMemoryError";
211 char *string_java_lang_VerifyError =
212 "java/lang/VerifyError";
214 char *string_java_lang_VirtualMachineError =
215 "java/lang/VirtualMachineError";
218 /* the system classloader object */
219 struct java_lang_ClassLoader *SystemClassLoader = NULL;
221 /* for raising exceptions from native methods */
222 #if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
223 java_objectheader* _exceptionptr = NULL;
226 /************* use classinfo structure as java.lang.Class object **************/
228 void use_class_as_object(classinfo *c)
230 if (!c->classvftbl) {
231 c->header.vftbl = class_java_lang_Class->vftbl;
232 c->classvftbl = true;
238 /*************************** include native methods ***************************/
241 #include "nat/GdkGraphics.c"
242 #include "nat/GtkComponentPeer.c"
243 #include "nat/GdkPixbufDecoder.c"
244 #include "nat/GtkScrollPanePeer.c"
245 #include "nat/GtkFileDialogPeer.c"
246 #include "nat/GtkLabelPeer.c"
250 /************************** tables for methods ********************************/
255 #define NATIVETABLESIZE (sizeof(nativetable)/sizeof(struct nativeref))
257 /* table for fast string comparison */
258 static nativecompref nativecomptable[NATIVETABLESIZE];
260 /* string comparsion table initialized */
261 static bool nativecompdone = false;
264 /******************************************************************************/
265 /******************************************************************************/
266 #include "natcalls.h"
268 /* string call comparison table initialized */
270 /******************************************************************************/
271 /******************************************************************************/
273 /* init_system_exceptions *****************************************************
275 load, link and compile exceptions used in the system
277 *******************************************************************************/
279 void init_system_exceptions()
281 /* java/lang/Throwable */
283 class_java_lang_Throwable =
284 class_new(utf_new_char(string_java_lang_Throwable));
285 class_load(class_java_lang_Throwable);
286 class_link(class_java_lang_Throwable);
288 /* java/lang/Exception */
290 class_java_lang_Exception =
291 class_new(utf_new_char(string_java_lang_Exception));
292 class_load(class_java_lang_Exception);
293 class_link(class_java_lang_Exception);
295 /* java/lang/Error */
297 class_java_lang_Error =
298 class_new(utf_new_char(string_java_lang_Error));
299 class_load(class_java_lang_Error);
300 class_link(class_java_lang_Error);
304 void compile_all_class_methods(classinfo *c)
308 for (i = 0; i < c->methodscount; i++) {
309 (void) jit_compile(&(c->methods[i]));
314 static void throw_exception_exit_intern(bool doexit)
316 java_objectheader *xptr;
321 xptr = *exceptionptr;
323 /* clear exception, because we are calling jit code again */
324 *exceptionptr = NULL;
326 c = xptr->vftbl->class;
328 pss = class_resolveclassmethod(c,
329 utf_new_char("printStackTrace"),
331 class_java_lang_Object,
334 /* print the stacktrace */
336 asm_calljavafunction(pss, xptr, NULL, NULL, NULL);
338 /* this normally means, we are EXTREMLY out of memory, but may be
339 any other exception */
341 utf_fprint_classname(stderr, c->name);
342 fprintf(stderr, "\n");
346 utf_fprint_classname(stderr, c->name);
347 fprintf(stderr, ": printStackTrace()V not found!\n");
360 void throw_exception()
362 throw_exception_exit_intern(false);
366 void throw_exception_exit()
368 throw_exception_exit_intern(true);
372 void throw_main_exception()
374 fprintf(stderr, "Exception in thread \"main\" ");
377 throw_exception_exit_intern(false);
381 void throw_main_exception_exit()
383 fprintf(stderr, "Exception in thread \"main\" ");
386 throw_exception_exit_intern(true);
390 void throw_cacao_exception_exit(char *exception, char *message)
396 len = strlen(exception);
397 tmp = MNEW(char, len);
398 strncpy(tmp, exception, len);
400 /* convert to classname */
402 for (i = len - 1; i >= 0; i--) {
403 if (tmp[i] == '/') tmp[i] = '.';
406 fprintf(stderr, "Exception in thread \"main\" %s", tmp);
408 MFREE(tmp, char, len);
410 if (strlen(message) > 0)
411 fprintf(stderr, ": %s", message);
413 fprintf(stderr, "\n");
421 #define CREATENEW_EXCEPTION(ex) \
422 java_objectheader *newEx; \
423 java_objectheader *oldexception=*exceptionptr;\
426 *exceptionptr=oldexception;\
429 java_objectheader *new_exception(char *classname)
431 classinfo *c = class_new(utf_new_char(classname));
433 CREATENEW_EXCEPTION(native_new_and_init(c));
436 java_objectheader *new_exception_message(char *classname, char *message)
438 classinfo *c = class_new(utf_new_char(classname));
440 CREATENEW_EXCEPTION(native_new_and_init_string(c, javastring_new_char(message)));
444 java_objectheader *new_exception_throwable(char *classname, java_lang_Throwable *throwable)
446 classinfo *c = class_new(utf_new_char(classname));
448 CREATENEW_EXCEPTION(native_new_and_init_throwable(c, throwable));
452 java_objectheader *new_exception_utfmessage(char *classname, utf *message)
454 classinfo *c = class_new(utf_new_char(classname));
456 CREATENEW_EXCEPTION(native_new_and_init_string(c, javastring_new(message)));
460 java_objectheader *new_exception_javastring(char *classname, java_lang_String *message)
462 classinfo *c = class_new(utf_new_char(classname));
464 CREATENEW_EXCEPTION(native_new_and_init_string(c, message));
468 java_objectheader *new_exception_int(char *classname, s4 i)
470 classinfo *c = class_new(utf_new_char(classname));
472 CREATENEW_EXCEPTION(native_new_and_init_int(c, i));
476 /*********************** function: native_loadclasses **************************
478 load classes required for native methods
480 *******************************************************************************/
482 void native_loadclasses()
484 static int classesLoaded = 0; /*temporary hack JoWenn*/
491 class_java_lang_Cloneable =
492 class_new(utf_new_char("java/lang/Cloneable"));
493 class_load(class_java_lang_Cloneable);
494 class_link(class_java_lang_Cloneable);
496 class_java_lang_Class =
497 class_new(utf_new_char("java/lang/Class"));
498 class_load(class_java_lang_Class);
499 class_link(class_java_lang_Class);
501 class_java_lang_VMClass =
502 class_new(utf_new_char("java/lang/VMClass"));
503 class_load(class_java_lang_VMClass);
504 class_link(class_java_lang_VMClass);
506 class_java_lang_ClassLoader =
507 class_new(utf_new_char("java/lang/ClassLoader"));
508 class_load(class_java_lang_ClassLoader);
509 class_link(class_java_lang_ClassLoader);
511 /* load classes for wrapping primitive types */
512 class_java_lang_Double = class_new(utf_new_char("java/lang/Double"));
513 class_load(class_java_lang_Double);
514 class_link(class_java_lang_Double);
516 class_java_lang_Float = class_new(utf_new_char("java/lang/Float"));
517 class_load(class_java_lang_Float);
518 class_link(class_java_lang_Float);
520 class_java_lang_Character = class_new(utf_new_char("java/lang/Character"));
521 class_load(class_java_lang_Character);
522 class_link(class_java_lang_Character);
524 class_java_lang_Integer = class_new(utf_new_char("java/lang/Integer"));
525 class_load(class_java_lang_Integer);
526 class_link(class_java_lang_Integer);
528 class_java_lang_Long = class_new(utf_new_char("java/lang/Long"));
529 class_load(class_java_lang_Long);
530 class_link(class_java_lang_Long);
532 class_java_lang_Byte = class_new(utf_new_char("java/lang/Byte"));
533 class_load(class_java_lang_Byte);
534 class_link(class_java_lang_Byte);
536 class_java_lang_Short = class_new(utf_new_char("java/lang/Short"));
537 class_load(class_java_lang_Short);
538 class_link(class_java_lang_Short);
540 class_java_lang_Boolean = class_new(utf_new_char("java/lang/Boolean"));
541 class_load(class_java_lang_Boolean);
542 class_link(class_java_lang_Boolean);
544 class_java_lang_Void = class_new(utf_new_char("java/lang/Void"));
545 class_load(class_java_lang_Void);
546 class_link(class_java_lang_Void);
551 /*****************************************************************************
553 create systemclassloader object and initialize instance fields
555 ******************************************************************************/
557 void init_systemclassloader()
559 log_text("init_systemclassloader");
560 if (!SystemClassLoader) {
561 native_loadclasses();
562 log_text("Initializing new system class loader");
563 /* create object and call initializer */
564 SystemClassLoader = (java_lang_ClassLoader *) native_new_and_init(class_new(utf_new_char("gnu/java/lang/SystemClassLoader")));
566 /* systemclassloader has no parent */
567 SystemClassLoader->parent = NULL;
568 SystemClassLoader->initialized = true;
570 log_text("leaving system class loader");
574 /********************* function: native_setclasspath **************************/
576 void native_setclasspath(char *path)
578 /* set searchpath for classfiles */
583 /*********************** Function: native_findfunction *************************
585 Looks up a method (must have the same class name, method name, descriptor
586 and 'static'ness) and returns a function pointer to it.
587 Returns: function pointer or NULL (if there is no such method)
589 Remark: For faster operation, the names/descriptors are converted from C
590 strings to Unicode the first time this function is called.
592 *******************************************************************************/
594 functionptr native_findfunction(utf *cname, utf *mname,
595 utf *desc, bool isstatic)
598 /* entry of table for fast string comparison */
599 struct nativecompref *n;
600 /* for warning message if no function is found */
604 isstatic = isstatic ? true : false;
606 if (!nativecompdone) {
607 for (i = 0; i < NATIVETABLESIZE; i++) {
608 nativecomptable[i].classname =
609 utf_new_char(nativetable[i].classname);
610 nativecomptable[i].methodname =
611 utf_new_char(nativetable[i].methodname);
612 nativecomptable[i].descriptor =
613 utf_new_char(nativetable[i].descriptor);
614 nativecomptable[i].isstatic =
615 nativetable[i].isstatic;
616 nativecomptable[i].func =
619 nativecompdone = true;
624 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
626 buffer = MNEW(char, buffer_len);
628 strcpy(buffer, "searching matching function in native table:");
629 utf_sprint(buffer+strlen(buffer), mname);
630 strcpy(buffer+strlen(buffer), ": ");
631 utf_sprint(buffer+strlen(buffer), desc);
632 strcpy(buffer+strlen(buffer), " for class ");
633 utf_sprint(buffer+strlen(buffer), cname);
637 MFREE(buffer, char, buffer_len);
640 for (i = 0; i < NATIVETABLESIZE; i++) {
641 n = &(nativecomptable[i]);
643 if (cname == n->classname && mname == n->methodname &&
644 desc == n->descriptor && isstatic == n->isstatic)
648 if (cname == n->classname && mname == n->methodname ) log_text("static and descriptor mismatch");
652 utf_strlen(n->classname) + utf_strlen(n->methodname) + utf_strlen(n->descriptor) + 64;
654 buffer = MNEW(char, buffer_len);
656 strcpy(buffer, "comparing with:");
657 utf_sprint(buffer+strlen(buffer), n->methodname);
658 strcpy (buffer+strlen(buffer), ": ");
659 utf_sprint(buffer+strlen(buffer), n->descriptor);
660 strcpy(buffer+strlen(buffer), " for class ");
661 utf_sprint(buffer+strlen(buffer), n->classname);
665 MFREE(buffer, char, buffer_len);
672 /* no function was found, display warning */
675 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
677 buffer = MNEW(char, buffer_len);
679 strcpy(buffer, "warning: native function ");
680 utf_sprint(buffer + strlen(buffer), mname);
681 strcpy(buffer + strlen(buffer), ": ");
682 utf_sprint(buffer + strlen(buffer), desc);
683 strcpy(buffer + strlen(buffer), " not found in class ");
684 utf_sprint(buffer + strlen(buffer), cname);
688 MFREE(buffer, char, buffer_len);
692 /* keep compiler happy */
697 /********************** function: javastring_new *******************************
699 creates a new object of type java/lang/String with the text of
700 the specified utf8-string
702 return: pointer to the string or NULL if memory is exhausted.
704 *******************************************************************************/
706 java_lang_String *javastring_new(utf *u)
708 char *utf_ptr = u->text; /* current utf character in utf string */
709 int utflength = utf_strlen(u); /* length of utf-string if uncompressed */
710 java_lang_String *s; /* result-string */
714 s = (java_lang_String *) builtin_new(class_java_lang_String);
715 a = builtin_newarray_char(utflength);
717 /* javastring or character-array could not be created */
721 /* decompress utf-string */
722 for (i = 0; i < utflength; i++)
723 a->data[i] = utf_nextu2(&utf_ptr);
725 /* set fields of the javastring-object */
728 s->count = utflength;
734 /********************** function: javastring_new_char **************************
736 creates a new java/lang/String object which contains the convertet
737 C-string passed via text.
739 return: the object pointer or NULL if memory is exhausted.
741 *******************************************************************************/
743 java_lang_String *javastring_new_char(char *text)
746 s4 len = strlen(text); /* length of the string */
747 java_lang_String *s; /* result-string */
750 s = (java_lang_String *) builtin_new(class_java_lang_String);
751 a = builtin_newarray_char(len);
753 /* javastring or character-array could not be created */
758 for (i = 0; i < len; i++)
759 a->data[i] = text[i];
761 /* set fields of the javastring-object */
770 /************************* function javastring_tochar **************************
772 converts a Java string into a C string.
774 return: pointer to C string
776 Caution: every call of this function overwrites the previous string !!!
778 *******************************************************************************/
780 static char stringbuffer[MAXSTRINGSIZE];
782 char *javastring_tochar(java_objectheader *so)
784 java_lang_String *s = (java_lang_String *) so;
796 if (s->count > MAXSTRINGSIZE)
799 for (i = 0; i < s->count; i++)
800 stringbuffer[i] = a->data[s->offset + i];
802 stringbuffer[i] = '\0';
808 /****************** function class_findfield_approx ****************************
810 searches in 'classinfo'-structure for a field with the
813 *******************************************************************************/
815 fieldinfo *class_findfield_approx(classinfo *c, utf *name)
819 for (i = 0; i < c->fieldscount; i++) {
820 /* compare field names */
821 if ((c->fields[i].name == name))
822 return &(c->fields[i]);
825 /* field was not found, raise exception */
826 *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
832 s4 class_findfield_index_approx(classinfo *c, utf *name)
836 for (i = 0; i < c->fieldscount; i++) {
837 /* compare field names */
838 if ((c->fields[i].name == name))
842 /* field was not found, raise exception */
843 *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
849 /********************** function: native_new_and_init *************************
851 Creates a new object on the heap and calls the initializer.
852 Returns the object pointer or NULL if memory is exhausted.
854 *******************************************************************************/
856 java_objectheader *native_new_and_init(classinfo *c)
859 java_objectheader *o;
862 return *exceptionptr;
864 o = builtin_new(c); /* create object */
869 /* find initializer */
871 m = class_findmethod(c,
872 utf_new_char("<init>"),
873 utf_new_char("()V"));
875 if (!m) { /* initializer not found */
877 char logtext[MAXLOGTEXT];
878 sprintf(logtext, "Warning: class has no instance-initializer: ");
879 utf_sprint_classname(logtext + strlen(logtext), c->name);
885 /* call initializer */
887 asm_calljavafunction(m, o, NULL, NULL, NULL);
893 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
896 java_objectheader *o;
899 return *exceptionptr;
901 o = builtin_new(c); /* create object */
906 /* find initializer */
908 m = class_findmethod(c,
909 utf_new_char("<init>"),
910 utf_new_char("(Ljava/lang/String;)V"));
912 if (!m) { /* initializer not found */
914 char logtext[MAXLOGTEXT];
915 sprintf(logtext, "Warning: class has no instance-initializer: ");
916 utf_sprint_classname(logtext + strlen(logtext), c->name);
922 /* call initializer */
924 asm_calljavafunction(m, o, s, NULL, NULL);
930 java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
933 java_objectheader *o;
936 return *exceptionptr;
938 o = builtin_new(c); /* create object */
942 /* find initializer */
944 m = class_findmethod(c,
945 utf_new_char("<init>"),
946 utf_new_char("(I)V"));
948 if (!m) { /* initializer not found */
950 char logtext[MAXLOGTEXT];
951 sprintf(logtext, "Warning: class has no instance-initializer: ");
952 utf_sprint_classname(logtext + strlen(logtext), c->name);
958 /* call initializer */
960 #if defined(__I386__) || defined(__POWERPC__)
961 asm_calljavafunction(m, o, (void *) i, NULL, NULL);
963 asm_calljavafunction(m, o, (void *) (s8) i, NULL, NULL);
970 java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t)
973 java_objectheader *o;
976 return *exceptionptr;
978 o = builtin_new(c); /* create object */
982 /* find initializer */
984 m = class_findmethod(c,
985 utf_new_char("<init>"),
986 utf_new_char("(Ljava/lang/Throwable;)V"));
988 if (!m) { /* initializer not found */
990 char logtext[MAXLOGTEXT];
991 sprintf(logtext, "Warning: class has no instance-initializer: ");
992 utf_sprint_classname(logtext + strlen(logtext), c->name);
998 /* call initializer */
1000 asm_calljavafunction(m, o, t, NULL, NULL);
1006 /******************** function: stringtable_update ****************************
1008 traverses the javastring hashtable and sets the vftbl-entries of
1009 javastrings which were temporarily set to NULL, because
1010 java.lang.Object was not yet loaded
1012 *******************************************************************************/
1014 void stringtable_update ()
1016 java_lang_String *js;
1018 literalstring *s; /* hashtable entry */
1021 for (i = 0; i < string_hash.size; i++) {
1022 s = string_hash.ptr[i];
1026 js = (java_lang_String *) s->string;
1028 if (!js || !js->value)
1029 /* error in hashtable found */
1030 panic("invalid literalstring in hashtable");
1034 if (!js->header.vftbl)
1035 /* vftbl of javastring is NULL */
1036 js->header.vftbl = class_java_lang_String->vftbl;
1038 if (!a->header.objheader.vftbl)
1039 /* vftbl of character-array is NULL */
1040 a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
1042 /* follow link in external hash chain */
1050 /************************* function: u2_utflength ***************************
1052 returns the utf length in bytes of a u2 array
1054 *****************************************************************************/
1056 u4 u2_utflength(u2 *text, u4 u2_length)
1058 u4 result_len = 0; /* utf length in bytes */
1059 u2 ch; /* current unicode character */
1062 for (len = 0; len < u2_length; len++) {
1063 /* next unicode character */
1066 /* determine bytes required to store unicode character as utf */
1067 if (ch && (ch < 0x80))
1069 else if (ch < 0x800)
1079 /********************* function: utf_new_u2 ***********************************
1081 make utf symbol from u2 array,
1082 if isclassname is true '.' is replaced by '/'
1084 *******************************************************************************/
1086 utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
1088 char *buffer; /* memory buffer for unicode characters */
1089 char *pos; /* pointer to current position in buffer */
1090 u4 left; /* unicode characters left */
1091 u4 buflength; /* utf length in bytes of the u2 array */
1092 utf *result; /* resulting utf-string */
1095 /* determine utf length in bytes and allocate memory */
1096 /* printf("utf_new_u2: unicode_length=%d\n",unicode_length); */
1097 buflength = u2_utflength(unicode_pos, unicode_length);
1098 buffer = MNEW(char, buflength);
1103 for (i = 0; i++ < unicode_length; unicode_pos++) {
1104 /* next unicode character */
1105 u2 c = *unicode_pos;
1107 if ((c != 0) && (c < 0x80)) {
1110 if ((int) left < 0) break;
1111 /* convert classname */
1112 if (isclassname && c == '.')
1117 } else if (c < 0x800) {
1119 unsigned char high = c >> 6;
1120 unsigned char low = c & 0x3F;
1122 if ((int) left < 0) break;
1123 *pos++ = high | 0xC0;
1124 *pos++ = low | 0x80;
1128 char low = c & 0x3f;
1129 char mid = (c >> 6) & 0x3F;
1130 char high = c >> 12;
1132 if ((int) left < 0) break;
1133 *pos++ = high | 0xE0;
1134 *pos++ = mid | 0x80;
1135 *pos++ = low | 0x80;
1139 /* insert utf-string into symbol-table */
1140 result = utf_new(buffer,buflength);
1142 MFREE(buffer, char, buflength);
1148 /********************* function: javastring_toutf *****************************
1150 make utf symbol from javastring
1152 *******************************************************************************/
1154 utf *javastring_toutf(java_lang_String *string, bool isclassname)
1156 java_lang_String *str = (java_lang_String *) string;
1158 /* printf("javastring_toutf offset: %d, len %d\n",str->offset, str->count); */
1159 /* fflush(stdout); */
1161 return utf_new_u2(str->value->data + str->offset, str->count, isclassname);
1165 /********************* function: literalstring_u2 *****************************
1167 searches for the javastring with the specified u2-array in
1168 the string hashtable, if there is no such string a new one is
1171 if copymode is true a copy of the u2-array is made
1173 *******************************************************************************/
1175 java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
1178 literalstring *s; /* hashtable element */
1179 java_lang_String *js; /* u2-array wrapped in javastring */
1180 java_chararray *stringdata; /* copy of u2-array */
1186 //#define DEBUG_LITERALSTRING_U2
1187 #ifdef DEBUG_LITERALSTRING_U2
1188 printf("literalstring_u2: length=%d, offset=%d\n", length, offset);
1192 /* find location in hashtable */
1193 key = unicode_hashkey(a->data + offset, length);
1194 slot = key & (string_hash.size - 1);
1195 s = string_hash.ptr[slot];
1198 js = (java_lang_String *) s->string;
1200 if (length == js->count) {
1202 for (i = 0; i < length; i++) {
1203 if (a->data[offset + i] != js->value->data[i])
1207 /* string already in hashtable, free memory */
1209 lit_mem_free(a, sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10);
1211 #ifdef DEBUG_LITERALSTRING_U2
1212 printf("literalstring_u2: foundentry at %p\n", js);
1213 utf_display(javastring_toutf(js, 0));
1217 return (java_objectheader *) js;
1221 /* follow link in external hash chain */
1226 /* create copy of u2-array for new javastring */
1227 u4 arraysize = sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10;
1228 stringdata = lit_mem_alloc(arraysize);
1229 /* memcpy(stringdata, a, arraysize); */
1230 memcpy(&(stringdata->header), &(a->header), sizeof(java_arrayheader));
1231 memcpy(&(stringdata->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10);
1237 /* location in hashtable found, complete arrayheader */
1238 stringdata->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
1239 stringdata->header.size = length;
1241 /* if we use eager loading, we have to check loaded String class */
1243 class_java_lang_String =
1244 class_new_intern(utf_new_char("java/lang/String"));
1246 if (!class_load(class_java_lang_String))
1249 list_addfirst(&unlinkedclasses, class_java_lang_String);
1252 /* create new javastring */
1253 js = LNEW(java_lang_String);
1254 js->header.vftbl = class_java_lang_String->vftbl;
1255 js->value = stringdata;
1259 #ifdef DEBUG_LITERALSTRING_U2
1260 printf("literalstring_u2: newly created at %p\n", js);
1261 utf_display(javastring_toutf(js, 0));
1266 /* create new literalstring */
1267 s = NEW(literalstring);
1268 s->hashlink = string_hash.ptr[slot];
1269 s->string = (java_objectheader *) js;
1270 string_hash.ptr[slot] = s;
1272 /* update number of hashtable entries */
1273 string_hash.entries++;
1275 /* reorganization of hashtable */
1276 if (string_hash.entries > (string_hash.size * 2)) {
1277 /* reorganization of hashtable, average length of
1278 the external chains is approx. 2 */
1282 hashtable newhash; /* the new hashtable */
1284 /* create new hashtable, double the size */
1285 init_hashtable(&newhash, string_hash.size * 2);
1286 newhash.entries = string_hash.entries;
1288 /* transfer elements to new hashtable */
1289 for (i = 0; i < string_hash.size; i++) {
1290 s = string_hash.ptr[i];
1292 literalstring *nexts = s->hashlink;
1293 js = (java_lang_String *) s->string;
1294 slot = unicode_hashkey(js->value->data, js->count) & (newhash.size - 1);
1296 s->hashlink = newhash.ptr[slot];
1297 newhash.ptr[slot] = s;
1299 /* follow link in external hash chain */
1304 /* dispose old table */
1305 MFREE(string_hash.ptr, void*, string_hash.size);
1306 string_hash = newhash;
1309 return (java_objectheader *) js;
1313 /******************** Function: literalstring_new *****************************
1315 creates a new javastring with the text of the utf-symbol
1316 and inserts it into the string hashtable
1318 *******************************************************************************/
1320 java_objectheader *literalstring_new(utf *u)
1322 char *utf_ptr = u->text; /* pointer to current unicode character in utf string */
1323 u4 utflength = utf_strlen(u); /* length of utf-string if uncompressed */
1324 java_chararray *a; /* u2-array constructed from utf string */
1327 /* allocate memory */
1328 a = lit_mem_alloc(sizeof(java_chararray) + sizeof(u2) * (utflength - 1) + 10);
1330 /* convert utf-string to u2-array */
1331 for (i = 0; i < utflength; i++)
1332 a->data[i] = utf_nextu2(&utf_ptr);
1334 return literalstring_u2(a, utflength, 0, false);
1338 /********************** function: literalstring_free **************************
1340 removes a javastring from memory
1342 ******************************************************************************/
1344 void literalstring_free(java_objectheader* sobj)
1346 java_lang_String *s = (java_lang_String *) sobj;
1347 java_chararray *a = s->value;
1349 /* dispose memory of java.lang.String object */
1350 LFREE(s, java_lang_String);
1352 /* dispose memory of java-characterarray */
1353 LFREE(a, sizeof(java_chararray) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
1357 void copy_vftbl(vftbl_t **dest, vftbl_t *src)
1361 /* XXX this kind of copying does not work (in the general
1362 * case). The interface tables would have to be copied, too. I
1363 * don't see why we should make a copy anyway. -Edwin
1365 *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
1366 memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
1367 memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
1372 /******************************************************************************************
1374 creates method signature (excluding return type) from array of
1375 class-objects representing the parameters of the method
1377 *******************************************************************************************/
1380 utf *create_methodsig(java_objectarray* types, char *retType)
1382 char *buffer; /* buffer for building the desciptor */
1383 char *pos; /* current position in buffer */
1384 utf *result; /* the method signature */
1385 u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
1388 if (!types) return NULL;
1390 /* determine required buffer-size */
1391 for (i = 0; i < types->header.size; i++) {
1392 classinfo *c = (classinfo *) types->data[i];
1393 buffer_size = buffer_size + c->name->blength + 2;
1396 if (retType) buffer_size += strlen(retType);
1398 /* allocate buffer */
1399 buffer = MNEW(u1, buffer_size);
1402 /* method-desciptor starts with parenthesis */
1405 for (i = 0; i < types->header.size; i++) {
1408 /* current argument */
1409 classinfo *c = (classinfo *) types->data[i];
1411 /* current position in utf-text */
1412 char *utf_ptr = c->name->text;
1414 /* determine type of argument */
1415 if ((ch = utf_nextu2(&utf_ptr)) == '[') {
1417 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
1418 *pos++ = *utf_ptr; /* copy text */
1422 /* check for primitive types */
1423 for (j = 0; j < PRIMITIVETYPE_COUNT; j++) {
1424 char *utf_pos = utf_ptr - 1;
1425 char *primitive = primitivetype_table[j].wrapname;
1428 while (utf_pos < utf_end(c->name)) {
1429 if (*utf_pos++ != *primitive++) goto nomatch;
1432 /* primitive type found */
1433 *pos++ = primitivetype_table[j].typesig;
1440 /* no primitive type and no arrayclass, so must be object */
1444 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
1458 for (i = 0; i < strlen(retType); i++) {
1459 *pos++ = retType[i];
1463 /* create utf-string */
1464 result = utf_new(buffer, (pos - buffer));
1465 MFREE(buffer, u1, buffer_size);
1471 /******************************************************************************************
1473 retrieve the next argument or returntype from a descriptor
1474 and return the corresponding class
1476 *******************************************************************************************/
1478 classinfo *get_type(char **utf_ptr,char *desc_end, bool skip)
1480 classinfo *c = class_from_descriptor(*utf_ptr,desc_end,utf_ptr,
1481 (skip) ? CLASSLOAD_SKIP : CLASSLOAD_LOAD);
1484 panic("illegal descriptor");
1486 if (skip) return NULL;
1488 use_class_as_object(c);
1493 /* get_parametertypes **********************************************************
1495 use the descriptor of a method to generate a java/lang/Class array
1496 which contains the classes of the parametertypes of the method
1498 *******************************************************************************/
1500 java_objectarray* get_parametertypes(methodinfo *m)
1502 utf *descr = m->descriptor; /* method-descriptor */
1503 char *utf_ptr = descr->text; /* current position in utf-text */
1504 char *desc_end = utf_end(descr); /* points behind utf string */
1505 java_objectarray* result;
1506 int parametercount = 0;
1510 utf_nextu2(&utf_ptr);
1512 /* determine number of parameters */
1513 while (*utf_ptr != ')') {
1514 get_type(&utf_ptr, desc_end, true);
1518 /* create class-array */
1519 result = builtin_anewarray(parametercount, class_java_lang_Class);
1521 utf_ptr = descr->text;
1522 utf_nextu2(&utf_ptr);
1524 /* get returntype classes */
1525 for (i = 0; i < parametercount; i++)
1527 (java_objectheader *) get_type(&utf_ptr, desc_end, false);
1533 /* get_exceptiontypes **********************************************************
1535 get the exceptions which can be thrown by a method
1537 *******************************************************************************/
1539 java_objectarray* get_exceptiontypes(methodinfo *m) {
1540 u2 exccount=m->thrownexceptionscount;
1542 java_objectarray *result;
1543 /* create class-array */
1544 result = builtin_anewarray(exccount, class_java_lang_Class);
1545 for (i=0;i<exccount;i++) {
1546 java_objectheader *oh=(java_objectheader*)(m->thrownexceptions[i]);
1547 use_class_as_object(oh);
1557 /******************************************************************************************
1559 get the returntype class of a method
1561 *******************************************************************************************/
1563 classinfo *get_returntype(methodinfo *m)
1565 char *utf_ptr; /* current position in utf-text */
1566 char *desc_end; /* points behind utf string */
1567 utf *desc = m->descriptor; /* method-descriptor */
1569 utf_ptr = desc->text;
1570 desc_end = utf_end(desc);
1572 /* ignore parametertypes */
1573 while ((utf_ptr<desc_end) && utf_nextu2(&utf_ptr)!=')')
1576 return get_type(&utf_ptr,desc_end, false);
1580 /*****************************************************************************/
1581 /*****************************************************************************/
1584 /*--------------------------------------------------------*/
1585 void printNativeCall(nativeCall nc) {
1588 printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
1589 for (i=0; i<nc.methCnt; i++) {
1590 printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
1592 for (j=0; j<nc.callCnt[i]; j++) {
1593 printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
1594 nc.methods[i].methodCalls[j].classname,
1595 nc.methods[i].methodCalls[j].methodname,
1596 nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1599 printf("-+++++--------------------\n");fflush(stdout);
1602 /*--------------------------------------------------------*/
1603 void printCompNativeCall(nativeCompCall nc) {
1605 printf("printCompNativeCall BEGIN\n");fflush(stdout);
1606 printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
1607 utf_display(nc.classname); fflush(stdout);
1609 for (i=0; i<nc.methCnt; i++) {
1610 printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
1611 utf_display(nc.methods[i].methodname); fflush(stdout);
1612 utf_display(nc.methods[i].descriptor);fflush(stdout);
1613 printf("\n");fflush(stdout);
1615 for (j=0; j<nc.callCnt[i]; j++) {
1616 printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
1617 utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
1618 utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
1619 utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1620 printf("\n");fflush(stdout);
1623 printf("---------------------\n");fflush(stdout);
1627 /*--------------------------------------------------------*/
1628 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d )
1641 /*--------------------------------------------------------*/
1642 nativeCall* findNativeClassCalls(char *aclassname ) {
1645 for (i=0;i<NATIVECALLSSIZE; i++) {
1646 /* convert table to utf later to speed up search */
1647 if (strcmp(nativeCalls[i].classname, aclassname) == 0)
1648 return &nativeCalls[i];
1653 /*--------------------------------------------------------*/
1654 /*--------------------------------------------------------*/
1655 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
1659 ncc->classname = utf_new_char(nc.classname);
1660 ncc->methCnt = nc.methCnt;
1662 for (i=0; i<nc.methCnt; i++) {
1663 ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
1664 ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
1665 ncc->callCnt[i] = nc.callCnt[i];
1667 for (j=0; j<nc.callCnt[i]; j++) {
1669 ncc->methods[i].methodCalls[j].classname = utf_new_char(nc.methods[i].methodCalls[j].classname);
1671 if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
1672 ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
1673 ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
1676 ncc->methods[i].methodCalls[j].methodname = NULL;
1677 ncc->methods[i].methodCalls[j].descriptor = NULL;
1685 /*--------------------------------------------------------*/
1687 bool natcall2utf(bool natcallcompdone) {
1690 if (natcallcompdone)
1693 for (i=0;i<NATIVECALLSSIZE; i++) {
1694 utfNativeCall (nativeCalls[i], &nativeCompCalls[i]);
1700 /*--------------------------------------------------------*/
1703 java_objectarray *builtin_asm_createclasscontextarray(classinfo **end,classinfo **start)
1705 #if defined(__GNUC__)
1706 #warning platform dependend
1708 java_objectarray *tmpArray;
1710 classinfo **current;
1712 size_t size=(((size_t)start)-((size_t)end)) / sizeof (classinfo*);
1713 /*printf("end %p, start %p, size %ld\n",end,start,size);*/
1714 if (!class_java_lang_Class)
1715 class_java_lang_Class = class_new(utf_new_char ("java/lang/Class"));
1716 if (!class_java_lang_SecurityManager)
1717 class_java_lang_SecurityManager = class_new(utf_new_char ("java/lang/SecurityManager"));
1719 if (start==class_java_lang_SecurityManager) {
1724 tmpArray=builtin_newarray(size, class_array_of(class_java_lang_Class)->vftbl);
1726 for(i=0,current=start;i<size;i++,current--) {
1728 /* printf("%d\n",i);
1729 utf_display(c->name);*/
1730 use_class_as_object(c);
1731 tmpArray->data[i]=c;
1737 java_lang_ClassLoader *builtin_asm_getclassloader(classinfo **end,classinfo **start)
1739 #if defined(__GNUC__)
1740 #warning platform dependend
1743 classinfo **current;
1745 classinfo *privilegedAction;
1746 size_t size=(((size_t)start)-((size_t)end)) / sizeof (classinfo*);
1747 /* log_text("builtin_asm_getclassloader");
1748 printf("end %p, start %p, size %ld\n",end,start,size);*/
1750 if (!class_java_lang_SecurityManager)
1751 class_java_lang_SecurityManager = class_new(utf_new_char ("java/lang/SecurityManager"));
1753 if (start==class_java_lang_SecurityManager) {
1759 privilegedAction=class_new(utf_new_char("java/security/PrivilegedAction"));
1761 for(i=0,current=start;i<size;i++,current--) {
1763 if (c==privilegedAction) return NULL;
1764 if (c->classloader) return c->classloader;
1772 log_text("Java_java_lang_VMSecurityManager_currentClassLoader");
1773 init_systemclassloader();
1775 return SystemClassLoader;*/
1779 * These are local overrides for various environment variables in Emacs.
1780 * Please do not remove this and leave it at the end of the file, where
1781 * Emacs will automagically detect them.
1782 * ---------------------------------------------------------------------
1785 * indent-tabs-mode: t