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 1082 2004-05-26 15:04:54Z jowenn $
53 #include "nativetypes.hh"
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 /* searchpath for classfiles */
82 /* for java-string to char conversion */
83 #define MAXSTRINGSIZE 1000
85 /******************** systemclasses required for native methods ***************/
87 classinfo *class_java_lang_Class;
88 classinfo *class_java_lang_VMClass;
89 classinfo *class_java_lang_System;
90 classinfo *class_java_lang_ClassLoader;
91 classinfo *class_gnu_java_lang_SystemClassLoader;
92 classinfo *class_java_lang_SecurityManager;
93 classinfo *class_java_lang_Double;
94 classinfo *class_java_lang_Float;
95 classinfo *class_java_lang_Long;
96 classinfo *class_java_lang_Byte;
97 classinfo *class_java_lang_Short;
98 classinfo *class_java_lang_Boolean;
99 classinfo *class_java_lang_Void;
100 classinfo *class_java_lang_Character;
101 classinfo *class_java_lang_Integer;
103 methodinfo *method_vmclass_init;
106 /* specify some exception strings for code generation */
108 char *string_java_lang_ArithmeticException =
109 "java/lang/ArithmeticException";
111 char *string_java_lang_ArithmeticException_message =
114 char *string_java_lang_ArrayIndexOutOfBoundsException =
115 "java/lang/ArrayIndexOutOfBoundsException";
117 char *string_java_lang_ArrayStoreException =
118 "java/lang/ArrayStoreException";
120 char *string_java_lang_ClassCastException =
121 "java/lang/ClassCastException";
123 char *string_java_lang_ClassNotFoundException =
124 "java/lang/ClassNotFoundException";
126 char *string_java_lang_CloneNotSupportedException =
127 "java/lang/CloneNotSupportedException";
129 char *string_java_lang_IllegalArgumentException =
130 "java/lang/IllegalArgumentException";
132 char *string_java_lang_IllegalMonitorStateException =
133 "java/lang/IllegalMonitorStateException";
135 char *string_java_lang_NegativeArraySizeException =
136 "java/lang/NegativeArraySizeException";
138 char *string_java_lang_NoSuchFieldException =
139 "java/lang/NoSuchFieldException";
141 char *string_java_lang_NoSuchMethodException =
142 "java/lang/NoSuchMethodException";
144 char *string_java_lang_NullPointerException =
145 "java/lang/NullPointerException";
148 /* specify some error strings for code generation */
150 char *string_java_lang_ClassCircularityError =
151 "java/lang/ClassCircularityError";
153 char *string_java_lang_ClassFormatError =
154 "java/lang/ClassFormatError";
156 char *string_java_lang_LinkageError =
157 "java/lang/LinkageError";
159 char *string_java_lang_NoClassDefFoundError =
160 "java/lang/NoClassDefFoundError";
162 char *string_java_lang_NoSuchFieldError =
163 "java/lang/NoSuchFieldError";
165 char *string_java_lang_NoSuchMethodError =
166 "java/lang/NoSuchMethodError";
168 char *string_java_lang_OutOfMemoryError =
169 "java/lang/OutOfMemoryError";
172 /* the system classloader object */
173 struct java_lang_ClassLoader *SystemClassLoader = NULL;
175 /* for raising exceptions from native methods */
176 #if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
177 java_objectheader* _exceptionptr = NULL;
180 /************* use classinfo structure as java.lang.Class object **************/
182 void use_class_as_object(classinfo *c)
186 java_objectheader *vmo;
188 /* vt = class_java_lang_Class->vftbl; */
190 if (!c->classvftbl) {
191 c->classvftbl = true;
193 /* copy_vftbl(&newtbl, vt);
194 newtbl->class = c->header.vftbl->class;
195 newtbl->baseval = c->header.vftbl->baseval;
196 newtbl->diffval = c->header.vftbl->diffval;
197 c->header.vftbl = newtbl;*/
199 c->header.vftbl = class_java_lang_Class->vftbl;
201 method_vmclass_init =
202 class_findmethod(class_java_lang_VMClass,
203 utf_new_char("<init>"),
204 utf_new_char("(Lgnu/classpath/RawData;)V"));
206 if (method_vmclass_init == 0) {
207 class_showmethods(class_java_lang_VMClass);
208 panic("Needed class initializer for VMClass could not be found");
211 vmo = builtin_new(class_java_lang_VMClass);
214 panic("Error while creating instance of java/lang/VMClass");
216 asm_calljavafunction(method_vmclass_init, vmo, c, NULL, NULL);
218 c->vmClass = (java_lang_VMClass *) vmo;
220 setfield_critical(class_java_lang_Class,vmo,"vmClass", "Ljava/lang/VMClass;", jobject, (jobject) class_java_lang_Class /*this*/);
228 /*************************** include native methods ***************************/
231 #include "nat/GdkGraphics.c"
232 #include "nat/GtkComponentPeer.c"
233 #include "nat/GdkPixbufDecoder.c"
234 #include "nat/GtkScrollPanePeer.c"
235 #include "nat/GtkFileDialogPeer.c"
236 #include "nat/GtkLabelPeer.c"
240 /************************** tables for methods ********************************/
245 /* table for locating native methods */
246 static struct nativeref {
254 #include "nativetable.hh"
259 #define NATIVETABLESIZE (sizeof(nativetable)/sizeof(struct nativeref))
261 /* table for fast string comparison */
262 static struct nativecompref {
268 } nativecomptable [NATIVETABLESIZE];
270 /* string comparsion table initialized */
271 static bool nativecompdone = false;
274 /******************************************************************************/
275 /******************************************************************************/
276 #include "natcalls.h"
278 /* string call comparison table initialized */
280 /******************************************************************************/
281 /******************************************************************************/
283 /*--------------- native method calls & classes used -------------------------*/
285 void throw_exception_exit()
287 java_objectheader *xptr;
292 xptr = *exceptionptr;
294 /* clear exception, because we are calling jit code again */
295 *exceptionptr = NULL;
297 printf("Exception in thread \"main\" ");
300 c = xptr->vftbl->class;
302 /* ts = class_resolveclassmethod(c, */
303 /* utf_new_char("toString"), */
304 /* utf_new_char("()Ljava/lang/String;"), */
305 /* class_java_lang_Object, */
309 /* panic("internal error"); */
312 /* tostring = asm_calljavafunction(ts, xptr, NULL, NULL, NULL); */
314 /* utf_display(javastring_toutf(tostring, false)); */
316 pss = class_resolveclassmethod(c,
317 utf_new_char("printStackTrace"),
319 class_java_lang_Object,
322 /* print the stacktrace */
324 asm_calljavafunction(pss, xptr, NULL, NULL, NULL);
327 panic("printStackTrace not found!");
338 java_objectheader *new_exception(char *classname)
340 classinfo *c = class_new(utf_new_char(classname));
342 return native_new_and_init(c);
345 java_objectheader *new_exception_message(char *classname, char *message)
347 classinfo *c = class_new(utf_new_char(classname));
349 return native_new_and_init_string(c, javastring_new_char(message));
353 java_objectheader *new_exception_throwable(char *classname, java_lang_Throwable *throwable)
355 classinfo *c = class_new(utf_new_char(classname));
357 return native_new_and_init_throwable(c, throwable);
361 java_objectheader *new_exception_utfmessage(char *classname, utf *message)
363 classinfo *c = class_new(utf_new_char(classname));
365 return native_new_and_init_string(c, javastring_new(message));
369 java_objectheader *new_exception_javastring(char *classname, java_lang_String *message)
371 classinfo *c = class_new(utf_new_char(classname));
373 return native_new_and_init_string(c, message);
377 java_objectheader *new_exception_int(char *classname, s4 i)
379 classinfo *c = class_new(utf_new_char(classname));
381 return native_new_and_init_int(c, i);
385 /*********************** function: native_loadclasses **************************
387 load classes required for native methods
389 *******************************************************************************/
391 void native_loadclasses()
393 static int classesLoaded = 0; /*temporary hack JoWenn*/
400 class_java_lang_Cloneable =
401 class_new(utf_new_char("java/lang/Cloneable"));
402 class_load(class_java_lang_Cloneable);
403 class_link(class_java_lang_Cloneable);
405 class_java_lang_Class =
406 class_new(utf_new_char("java/lang/Class"));
407 class_load(class_java_lang_Class);
408 class_link(class_java_lang_Class);
410 class_java_lang_VMClass =
411 class_new(utf_new_char("java/lang/VMClass"));
412 class_load(class_java_lang_VMClass);
413 class_link(class_java_lang_VMClass);
415 class_java_lang_ClassLoader =
416 class_new(utf_new_char("java/lang/ClassLoader"));
417 class_load(class_java_lang_ClassLoader);
418 class_link(class_java_lang_ClassLoader);
420 /* load classes for wrapping primitive types */
421 class_java_lang_Double = class_new(utf_new_char("java/lang/Double"));
422 class_load(class_java_lang_Double);
423 class_link(class_java_lang_Double);
425 class_java_lang_Float = class_new(utf_new_char("java/lang/Float"));
426 class_load(class_java_lang_Float);
427 class_link(class_java_lang_Float);
429 class_java_lang_Character = class_new(utf_new_char("java/lang/Character"));
430 class_load(class_java_lang_Character);
431 class_link(class_java_lang_Character);
433 class_java_lang_Integer = class_new(utf_new_char("java/lang/Integer"));
434 class_load(class_java_lang_Integer);
435 class_link(class_java_lang_Integer);
437 class_java_lang_Long = class_new(utf_new_char("java/lang/Long"));
438 class_load(class_java_lang_Long);
439 class_link(class_java_lang_Long);
441 class_java_lang_Byte = class_new(utf_new_char("java/lang/Byte"));
442 class_load(class_java_lang_Byte);
443 class_link(class_java_lang_Byte);
445 class_java_lang_Short = class_new(utf_new_char("java/lang/Short"));
446 class_load(class_java_lang_Short);
447 class_link(class_java_lang_Short);
449 class_java_lang_Boolean = class_new(utf_new_char("java/lang/Boolean"));
450 class_load(class_java_lang_Boolean);
451 class_link(class_java_lang_Boolean);
453 class_java_lang_Void = class_new(utf_new_char("java/lang/Void"));
454 class_load(class_java_lang_Void);
455 class_link(class_java_lang_Void);
459 /*****************************************************************************
461 create systemclassloader object and initialize instance fields
463 ******************************************************************************/
465 void init_systemclassloader()
467 log_text("init_systemclassloader");
468 if (!SystemClassLoader) {
469 native_loadclasses();
470 log_text("Initializing new system class loader");
471 /* create object and call initializer */
472 SystemClassLoader = (java_lang_ClassLoader *) native_new_and_init(class_new(utf_new_char("gnu/java/lang/SystemClassLoader")));
474 /* systemclassloader has no parent */
475 SystemClassLoader->parent = NULL;
476 SystemClassLoader->initialized = true;
478 log_text("leaving system class loader");
482 /********************* function: native_setclasspath **************************/
484 void native_setclasspath(char *path)
486 /* set searchpath for classfiles */
491 /*********************** Function: native_findfunction *************************
493 Looks up a method (must have the same class name, method name, descriptor
494 and 'static'ness) and returns a function pointer to it.
495 Returns: function pointer or NULL (if there is no such method)
497 Remark: For faster operation, the names/descriptors are converted from C
498 strings to Unicode the first time this function is called.
500 *******************************************************************************/
502 functionptr native_findfunction(utf *cname, utf *mname,
503 utf *desc, bool isstatic)
506 /* entry of table for fast string comparison */
507 struct nativecompref *n;
508 /* for warning message if no function is found */
512 isstatic = isstatic ? true : false;
514 if (!nativecompdone) {
515 for (i = 0; i < NATIVETABLESIZE; i++) {
516 nativecomptable[i].classname =
517 utf_new_char(nativetable[i].classname);
518 nativecomptable[i].methodname =
519 utf_new_char(nativetable[i].methodname);
520 nativecomptable[i].descriptor =
521 utf_new_char(nativetable[i].descriptor);
522 nativecomptable[i].isstatic =
523 nativetable[i].isstatic;
524 nativecomptable[i].func =
527 nativecompdone = true;
532 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
534 buffer = MNEW(char, buffer_len);
536 strcpy(buffer, "searching matching function in native table:");
537 utf_sprint(buffer+strlen(buffer), mname);
538 strcpy(buffer+strlen(buffer), ": ");
539 utf_sprint(buffer+strlen(buffer), desc);
540 strcpy(buffer+strlen(buffer), " for class ");
541 utf_sprint(buffer+strlen(buffer), cname);
545 MFREE(buffer, char, buffer_len);
548 for (i = 0; i < NATIVETABLESIZE; i++) {
549 n = &(nativecomptable[i]);
551 if (cname == n->classname && mname == n->methodname &&
552 desc == n->descriptor && isstatic == n->isstatic)
556 if (cname == n->classname && mname == n->methodname ) log_text("static and descriptor mismatch");
560 utf_strlen(n->classname) + utf_strlen(n->methodname) + utf_strlen(n->descriptor) + 64;
562 buffer = MNEW(char, buffer_len);
564 strcpy(buffer, "comparing with:");
565 utf_sprint(buffer+strlen(buffer), n->methodname);
566 strcpy (buffer+strlen(buffer), ": ");
567 utf_sprint(buffer+strlen(buffer), n->descriptor);
568 strcpy(buffer+strlen(buffer), " for class ");
569 utf_sprint(buffer+strlen(buffer), n->classname);
573 MFREE(buffer, char, buffer_len);
580 /* no function was found, display warning */
583 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
585 buffer = MNEW(char, buffer_len);
587 strcpy(buffer, "warning: native function ");
588 utf_sprint(buffer + strlen(buffer), mname);
589 strcpy(buffer + strlen(buffer), ": ");
590 utf_sprint(buffer + strlen(buffer), desc);
591 strcpy(buffer + strlen(buffer), " not found in class ");
592 utf_sprint(buffer + strlen(buffer), cname);
596 MFREE(buffer, char, buffer_len);
600 /* keep compiler happy */
605 /********************** function: javastring_new *******************************
607 creates a new object of type java/lang/String with the text of
608 the specified utf8-string
610 return: pointer to the string or NULL if memory is exhausted.
612 *******************************************************************************/
614 java_lang_String *javastring_new(utf *u)
616 char *utf_ptr = u->text; /* current utf character in utf string */
617 int utflength = utf_strlen(u); /* length of utf-string if uncompressed */
618 java_lang_String *s; /* result-string */
622 s = (java_lang_String *) builtin_new(class_java_lang_String);
623 a = builtin_newarray_char(utflength);
625 /* javastring or character-array could not be created */
629 /* decompress utf-string */
630 for (i = 0; i < utflength; i++)
631 a->data[i] = utf_nextu2(&utf_ptr);
633 /* set fields of the javastring-object */
636 s->count = utflength;
642 /********************** function: javastring_new_char **************************
644 creates a new java/lang/String object which contains the convertet
645 C-string passed via text.
647 return: the object pointer or NULL if memory is exhausted.
649 *******************************************************************************/
651 java_lang_String *javastring_new_char(char *text)
654 s4 len = strlen(text); /* length of the string */
655 java_lang_String *s; /* result-string */
658 s = (java_lang_String *) builtin_new(class_java_lang_String);
659 a = builtin_newarray_char(len);
661 /* javastring or character-array could not be created */
666 for (i = 0; i < len; i++)
667 a->data[i] = text[i];
669 /* set fields of the javastring-object */
678 /************************* function javastring_tochar **************************
680 converts a Java string into a C string.
682 return: pointer to C string
684 Caution: every call of this function overwrites the previous string !!!
686 *******************************************************************************/
688 static char stringbuffer[MAXSTRINGSIZE];
690 char *javastring_tochar(java_objectheader *so)
692 java_lang_String *s = (java_lang_String *) so;
704 if (s->count > MAXSTRINGSIZE)
707 for (i = 0; i < s->count; i++)
708 stringbuffer[i] = a->data[s->offset + i];
710 stringbuffer[i] = '\0';
716 /****************** function class_findfield_approx ****************************
718 searches in 'classinfo'-structure for a field with the
721 *******************************************************************************/
723 fieldinfo *class_findfield_approx(classinfo *c, utf *name)
727 for (i = 0; i < c->fieldscount; i++) {
728 /* compare field names */
729 if ((c->fields[i].name == name))
730 return &(c->fields[i]);
733 /* field was not found, raise exception */
734 *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
740 s4 class_findfield_index_approx(classinfo *c, utf *name)
744 for (i = 0; i < c->fieldscount; i++) {
745 /* compare field names */
746 if ((c->fields[i].name == name))
750 /* field was not found, raise exception */
751 *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
757 /********************** function: native_new_and_init *************************
759 Creates a new object on the heap and calls the initializer.
760 Returns the object pointer or NULL if memory is exhausted.
762 *******************************************************************************/
764 java_objectheader *native_new_and_init(classinfo *c)
767 java_objectheader *o;
770 return *exceptionptr;
772 o = builtin_new(c); /* create object */
777 /* find initializer */
779 m = class_findmethod(c,
780 utf_new_char("<init>"),
781 utf_new_char("()V"));
783 if (!m) { /* initializer not found */
785 char logtext[MAXLOGTEXT];
786 sprintf(logtext, "Warning: class has no instance-initializer: ");
787 utf_sprint_classname(logtext + strlen(logtext), c->name);
793 /* call initializer */
795 asm_calljavafunction(m, o, NULL, NULL, NULL);
801 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
804 java_objectheader *o;
807 return *exceptionptr;
809 o = builtin_new(c); /* create object */
814 /* find initializer */
816 m = class_findmethod(c,
817 utf_new_char("<init>"),
818 utf_new_char("(Ljava/lang/String;)V"));
820 if (!m) { /* initializer not found */
822 char logtext[MAXLOGTEXT];
823 sprintf(logtext, "Warning: class has no instance-initializer: ");
824 utf_sprint_classname(logtext + strlen(logtext), c->name);
830 /* call initializer */
832 asm_calljavafunction(m, o, s, NULL, NULL);
838 java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
841 java_objectheader *o;
844 return *exceptionptr;
846 o = builtin_new(c); /* create object */
850 /* find initializer */
852 m = class_findmethod(c,
853 utf_new_char("<init>"),
854 utf_new_char("(I)V"));
856 if (!m) { /* initializer not found */
858 char logtext[MAXLOGTEXT];
859 sprintf(logtext, "Warning: class has no instance-initializer: ");
860 utf_sprint_classname(logtext + strlen(logtext), c->name);
866 /* call initializer */
868 asm_calljavafunction(m, o, (void *) i, NULL, NULL);
874 java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t)
877 java_objectheader *o;
880 return *exceptionptr;
882 o = builtin_new(c); /* create object */
886 /* find initializer */
888 m = class_findmethod(c,
889 utf_new_char("<init>"),
890 utf_new_char("(Ljava/lang/Throwable;)V"));
892 if (!m) { /* initializer not found */
894 char logtext[MAXLOGTEXT];
895 sprintf(logtext, "Warning: class has no instance-initializer: ");
896 utf_sprint_classname(logtext + strlen(logtext), c->name);
902 /* call initializer */
904 asm_calljavafunction(m, o, t, NULL, NULL);
910 /******************** function: stringtable_update ****************************
912 traverses the javastring hashtable and sets the vftbl-entries of
913 javastrings which were temporarily set to NULL, because
914 java.lang.Object was not yet loaded
916 *******************************************************************************/
918 void stringtable_update ()
920 java_lang_String *js;
922 literalstring *s; /* hashtable entry */
925 for (i = 0; i < string_hash.size; i++) {
926 s = string_hash.ptr[i];
930 js = (java_lang_String *) s->string;
932 if (!js || !js->value)
933 /* error in hashtable found */
934 panic("invalid literalstring in hashtable");
938 if (!js->header.vftbl)
939 /* vftbl of javastring is NULL */
940 js->header.vftbl = class_java_lang_String->vftbl;
942 if (!a->header.objheader.vftbl)
943 /* vftbl of character-array is NULL */
944 a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
946 /* follow link in external hash chain */
954 /************************* function: u2_utflength ***************************
956 returns the utf length in bytes of a u2 array
958 *****************************************************************************/
960 u4 u2_utflength(u2 *text, u4 u2_length)
962 u4 result_len = 0; /* utf length in bytes */
963 u2 ch; /* current unicode character */
966 for (len = 0; len < u2_length; len++) {
967 /* next unicode character */
970 /* determine bytes required to store unicode character as utf */
971 if (ch && (ch < 0x80))
983 /********************* function: utf_new_u2 ***********************************
985 make utf symbol from u2 array,
986 if isclassname is true '.' is replaced by '/'
988 *******************************************************************************/
990 utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
992 char *buffer; /* memory buffer for unicode characters */
993 char *pos; /* pointer to current position in buffer */
994 u4 left; /* unicode characters left */
995 u4 buflength; /* utf length in bytes of the u2 array */
996 utf *result; /* resulting utf-string */
999 /* determine utf length in bytes and allocate memory */
1000 /* printf("utf_new_u2: unicode_length=%d\n",unicode_length); */
1001 buflength = u2_utflength(unicode_pos, unicode_length);
1002 buffer = MNEW(char, buflength);
1004 /* memory allocation failed */
1006 printf("length: %d\n",buflength);
1007 log_text("utf_new_u2:buffer==NULL");
1013 for (i = 0; i++ < unicode_length; unicode_pos++) {
1014 /* next unicode character */
1015 u2 c = *unicode_pos;
1017 if ((c != 0) && (c < 0x80)) {
1020 if ((int) left < 0) break;
1021 /* convert classname */
1022 if (isclassname && c == '.')
1027 } else if (c < 0x800) {
1029 unsigned char high = c >> 6;
1030 unsigned char low = c & 0x3F;
1032 if ((int) left < 0) break;
1033 *pos++ = high | 0xC0;
1034 *pos++ = low | 0x80;
1038 char low = c & 0x3f;
1039 char mid = (c >> 6) & 0x3F;
1040 char high = c >> 12;
1042 if ((int) left < 0) break;
1043 *pos++ = high | 0xE0;
1044 *pos++ = mid | 0x80;
1045 *pos++ = low | 0x80;
1049 /* insert utf-string into symbol-table */
1050 result = utf_new(buffer,buflength);
1052 MFREE(buffer, char, buflength);
1058 /********************* function: javastring_toutf *****************************
1060 make utf symbol from javastring
1062 *******************************************************************************/
1064 utf *javastring_toutf(java_lang_String *string, bool isclassname)
1066 java_lang_String *str = (java_lang_String *) string;
1068 /* printf("javastring_toutf offset: %d, len %d\n",str->offset, str->count); */
1069 /* fflush(stdout); */
1071 return utf_new_u2(str->value->data + str->offset, str->count, isclassname);
1075 /********************* function: literalstring_u2 *****************************
1077 searches for the javastring with the specified u2-array in
1078 the string hashtable, if there is no such string a new one is
1081 if copymode is true a copy of the u2-array is made
1083 *******************************************************************************/
1085 java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
1088 literalstring *s; /* hashtable element */
1089 java_lang_String *js; /* u2-array wrapped in javastring */
1090 java_chararray *stringdata; /* copy of u2-array */
1095 //#define DEBUG_LITERALSTRING_U2
1096 #ifdef DEBUG_LITERALSTRING_U2
1097 printf("literalstring_u2: length=%d, offset=%d\n", length, offset);
1101 /* find location in hashtable */
1102 key = unicode_hashkey(a->data + offset, length);
1103 slot = key & (string_hash.size - 1);
1104 s = string_hash.ptr[slot];
1107 js = (java_lang_String *) s->string;
1109 if (length == js->count) {
1111 for (i = 0; i < length; i++) {
1112 if (a->data[offset + i] != js->value->data[i])
1116 /* string already in hashtable, free memory */
1118 lit_mem_free(a, sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10);
1120 #ifdef DEBUG_LITERALSTRING_U2
1121 printf("literalstring_u2: foundentry at %p\n", js);
1122 utf_display(javastring_toutf(js, 0));
1126 return (java_objectheader *) js;
1130 /* follow link in external hash chain */
1135 /* create copy of u2-array for new javastring */
1136 u4 arraysize = sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10;
1137 stringdata = lit_mem_alloc(arraysize);
1138 /* memcpy(stringdata, a, arraysize); */
1139 memcpy(&(stringdata->header), &(a->header), sizeof(java_arrayheader));
1140 memcpy(&(stringdata->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10);
1146 /* location in hashtable found, complete arrayheader */
1147 stringdata->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
1148 stringdata->header.size = length;
1150 /* create new javastring */
1151 js = LNEW(java_lang_String);
1153 /* js->header.vftbl = class_java_lang_String->vftbl; */
1154 js->header.vftbl = class_load(class_new(utf_new_char("java/lang/String")))->vftbl;
1155 js->value = stringdata;
1159 /* create new literalstring */
1160 s = NEW(literalstring);
1161 s->hashlink = string_hash.ptr[slot];
1162 s->string = (java_objectheader *) js;
1163 string_hash.ptr[slot] = s;
1165 /* update numbe of hashtable entries */
1166 string_hash.entries++;
1168 /* reorganization of hashtable */
1169 if (string_hash.entries > (string_hash.size * 2)) {
1170 /* reorganization of hashtable, average length of
1171 the external chains is approx. 2 */
1175 hashtable newhash; /* the new hashtable */
1177 /* create new hashtable, double the size */
1178 init_hashtable(&newhash, string_hash.size * 2);
1179 newhash.entries = string_hash.entries;
1181 /* transfer elements to new hashtable */
1182 for (i = 0; i < string_hash.size; i++) {
1183 s = string_hash.ptr[i];
1185 literalstring *nexts = s->hashlink;
1186 js = (java_lang_String *) s->string;
1187 slot = unicode_hashkey(js->value->data, js->count) & (newhash.size - 1);
1189 s->hashlink = newhash.ptr[slot];
1190 newhash.ptr[slot] = s;
1192 /* follow link in external hash chain */
1197 /* dispose old table */
1198 MFREE(string_hash.ptr, void*, string_hash.size);
1199 string_hash = newhash;
1202 #ifdef DEBUG_LITERALSTRING_U2
1203 printf("literalstring_u2: newly created at %p\n", js);
1204 utf_display(javastring_toutf(js, 0));
1209 return (java_objectheader *) js;
1213 /******************** Function: literalstring_new *****************************
1215 creates a new javastring with the text of the utf-symbol
1216 and inserts it into the string hashtable
1218 *******************************************************************************/
1220 java_objectheader *literalstring_new(utf *u)
1222 char *utf_ptr = u->text; /* pointer to current unicode character in utf string */
1223 u4 utflength = utf_strlen(u); /* length of utf-string if uncompressed */
1224 java_chararray *a; /* u2-array constructed from utf string */
1227 /* allocate memory */
1228 a = lit_mem_alloc(sizeof(java_chararray) + sizeof(u2) * (utflength - 1) + 10);
1230 /* convert utf-string to u2-array */
1231 for (i = 0; i < utflength; i++)
1232 a->data[i] = utf_nextu2(&utf_ptr);
1234 return literalstring_u2(a, utflength, 0, false);
1238 /********************** function: literalstring_free **************************
1240 removes a javastring from memory
1242 ******************************************************************************/
1244 void literalstring_free(java_objectheader* sobj)
1246 java_lang_String *s = (java_lang_String *) sobj;
1247 java_chararray *a = s->value;
1249 /* dispose memory of java.lang.String object */
1250 LFREE(s, java_lang_String);
1252 /* dispose memory of java-characterarray */
1253 LFREE(a, sizeof(java_chararray) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
1257 void copy_vftbl(vftbl **dest, vftbl *src)
1261 /* XXX this kind of copying does not work (in the general
1262 * case). The interface tables would have to be copied, too. I
1263 * don't see why we should make a copy anyway. -Edwin
1265 *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
1266 memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
1267 memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
1272 /******************************************************************************************
1274 creates method signature (excluding return type) from array of
1275 class-objects representing the parameters of the method
1277 *******************************************************************************************/
1280 utf *create_methodsig(java_objectarray* types, char *retType)
1282 char *buffer; /* buffer for building the desciptor */
1283 char *pos; /* current position in buffer */
1284 utf *result; /* the method signature */
1285 u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
1288 if (!types) return NULL;
1290 /* determine required buffer-size */
1291 for (i = 0; i < types->header.size; i++) {
1292 classinfo *c = (classinfo *) types->data[i];
1293 buffer_size = buffer_size + c->name->blength + 2;
1296 if (retType) buffer_size += strlen(retType);
1298 /* allocate buffer */
1299 buffer = MNEW(u1, buffer_size);
1302 /* method-desciptor starts with parenthesis */
1305 for (i = 0; i < types->header.size; i++) {
1308 /* current argument */
1309 classinfo *c = (classinfo *) types->data[i];
1311 /* current position in utf-text */
1312 char *utf_ptr = c->name->text;
1314 /* determine type of argument */
1315 if ((ch = utf_nextu2(&utf_ptr)) == '[') {
1317 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
1318 *pos++ = *utf_ptr; /* copy text */
1322 /* check for primitive types */
1323 for (j = 0; j < PRIMITIVETYPE_COUNT; j++) {
1324 char *utf_pos = utf_ptr - 1;
1325 char *primitive = primitivetype_table[j].wrapname;
1328 while (utf_pos < utf_end(c->name)) {
1329 if (*utf_pos++ != *primitive++) goto nomatch;
1332 /* primitive type found */
1333 *pos++ = primitivetype_table[j].typesig;
1340 /* no primitive type and no arrayclass, so must be object */
1344 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
1358 for (i = 0; i < strlen(retType); i++) {
1359 *pos++ = retType[i];
1363 /* create utf-string */
1364 result = utf_new(buffer, (pos - buffer));
1365 MFREE(buffer, u1, buffer_size);
1371 /******************************************************************************************
1373 retrieve the next argument or returntype from a descriptor
1374 and return the corresponding class
1376 *******************************************************************************************/
1378 classinfo *get_type(char **utf_ptr,char *desc_end, bool skip)
1380 classinfo *c = class_from_descriptor(*utf_ptr,desc_end,utf_ptr,
1381 (skip) ? CLASSLOAD_SKIP : CLASSLOAD_LOAD);
1384 panic("illegal descriptor");
1386 if (skip) return NULL;
1388 use_class_as_object(c);
1393 /******************************************************************************************
1395 use the descriptor of a method to generate a java/lang/Class array
1396 which contains the classes of the parametertypes of the method
1398 *******************************************************************************************/
1400 java_objectarray* get_parametertypes(methodinfo *m)
1402 utf *descr = m->descriptor; /* method-descriptor */
1403 char *utf_ptr = descr->text; /* current position in utf-text */
1404 char *desc_end = utf_end(descr); /* points behind utf string */
1405 java_objectarray* result;
1406 int parametercount = 0;
1410 utf_nextu2(&utf_ptr);
1412 /* determine number of parameters */
1413 while ( *utf_ptr != ')' ) {
1414 get_type(&utf_ptr,desc_end,true);
1418 /* create class-array */
1419 result = builtin_anewarray(parametercount, class_java_lang_Class);
1421 utf_ptr = descr->text;
1422 utf_nextu2(&utf_ptr);
1424 /* get returntype classes */
1425 for (i = 0; i < parametercount; i++)
1426 result->data[i] = (java_objectheader *) get_type(&utf_ptr,desc_end, false);
1435 /******************************************************************************************
1437 get the exceptions which can be thrown by a method
1439 *******************************************************************************************/
1441 java_objectarray* get_exceptiontypes(methodinfo *m) {
1442 u2 exccount=m->thrownexceptionscount;
1444 java_objectarray *result;
1445 /* create class-array */
1446 result = builtin_anewarray(exccount, class_java_lang_Class);
1447 for (i=0;i<exccount;i++) {
1448 java_objectheader *oh=(java_objectheader*)(m->thrownexceptions[i]);
1449 use_class_as_object(oh);
1459 /******************************************************************************************
1461 get the returntype class of a method
1463 *******************************************************************************************/
1465 classinfo *get_returntype(methodinfo *m)
1467 char *utf_ptr; /* current position in utf-text */
1468 char *desc_end; /* points behind utf string */
1469 utf *desc = m->descriptor; /* method-descriptor */
1471 utf_ptr = desc->text;
1472 desc_end = utf_end(desc);
1474 /* ignore parametertypes */
1475 while ((utf_ptr<desc_end) && utf_nextu2(&utf_ptr)!=')')
1478 return get_type(&utf_ptr,desc_end, false);
1482 /*****************************************************************************/
1483 /*****************************************************************************/
1486 /*--------------------------------------------------------*/
1487 void printNativeCall(nativeCall nc) {
1490 printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
1491 for (i=0; i<nc.methCnt; i++) {
1492 printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
1494 for (j=0; j<nc.callCnt[i]; j++) {
1495 printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
1496 nc.methods[i].methodCalls[j].classname,
1497 nc.methods[i].methodCalls[j].methodname,
1498 nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1501 printf("-+++++--------------------\n");fflush(stdout);
1504 /*--------------------------------------------------------*/
1505 void printCompNativeCall(nativeCompCall nc) {
1507 printf("printCompNativeCall BEGIN\n");fflush(stdout);
1508 printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
1509 utf_display(nc.classname); fflush(stdout);
1511 for (i=0; i<nc.methCnt; i++) {
1512 printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
1513 utf_display(nc.methods[i].methodname); fflush(stdout);
1514 utf_display(nc.methods[i].descriptor);fflush(stdout);
1515 printf("\n");fflush(stdout);
1517 for (j=0; j<nc.callCnt[i]; j++) {
1518 printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
1519 utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
1520 utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
1521 utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1522 printf("\n");fflush(stdout);
1525 printf("---------------------\n");fflush(stdout);
1529 /*--------------------------------------------------------*/
1530 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d )
1543 /*--------------------------------------------------------*/
1544 nativeCall* findNativeClassCalls(char *aclassname ) {
1547 for (i=0;i<NATIVECALLSSIZE; i++) {
1548 /* convert table to utf later to speed up search */
1549 if (strcmp(nativeCalls[i].classname, aclassname) == 0)
1550 return &nativeCalls[i];
1555 /*--------------------------------------------------------*/
1556 /*--------------------------------------------------------*/
1557 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
1561 ncc->classname = utf_new_char(nc.classname);
1562 ncc->methCnt = nc.methCnt;
1564 for (i=0; i<nc.methCnt; i++) {
1565 ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
1566 ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
1567 ncc->callCnt[i] = nc.callCnt[i];
1569 for (j=0; j<nc.callCnt[i]; j++) {
1571 ncc->methods[i].methodCalls[j].classname = utf_new_char(nc.methods[i].methodCalls[j].classname);
1573 if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
1574 ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
1575 ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
1578 ncc->methods[i].methodCalls[j].methodname = NULL;
1579 ncc->methods[i].methodCalls[j].descriptor = NULL;
1587 /*--------------------------------------------------------*/
1589 bool natcall2utf(bool natcallcompdone) {
1592 if (natcallcompdone)
1595 for (i=0;i<NATIVECALLSSIZE; i++) {
1596 utfNativeCall (nativeCalls[i], &nativeCompCalls[i]);
1602 /*--------------------------------------------------------*/
1605 java_objectarray *builtin_asm_createclasscontextarray(classinfo **end,classinfo **start) {
1606 #warning platform dependend
1607 java_objectarray *tmpArray;
1609 classinfo **current;
1611 size_t size=(((size_t)start)-((size_t)end)) / sizeof (classinfo*);
1612 /* printf("end %p, start %p, size %ld\n",end,start,size);*/
1613 if (!class_java_lang_Class)
1614 class_java_lang_Class = class_new(utf_new_char ("java/lang/Class"));
1615 if (!class_java_lang_SecurityManager)
1616 class_java_lang_SecurityManager = class_new(utf_new_char ("java/lang/SecurityManager"));
1618 if (start==class_java_lang_SecurityManager) {
1623 tmpArray=builtin_newarray(size, class_array_of(class_java_lang_Class)->vftbl);
1625 for(i=0,current=start;i<size;i++,current--) {
1627 /* printf("%d\n",i);
1628 utf_display(c->name);*/
1629 use_class_as_object(c);
1630 tmpArray->data[i]=c;
1636 java_lang_ClassLoader *builtin_asm_getclassloader(classinfo **end,classinfo **start) {
1637 #warning platform dependend
1639 classinfo **current;
1641 classinfo *privilegedAction;
1642 size_t size=(((size_t)start)-((size_t)end)) / sizeof (classinfo*);
1643 /* log_text("builtin_asm_getclassloader");
1644 printf("end %p, start %p, size %ld\n",end,start,size);*/
1646 if (!class_java_lang_SecurityManager)
1647 class_java_lang_SecurityManager = class_new(utf_new_char ("java/lang/SecurityManager"));
1649 if (start==class_java_lang_SecurityManager) {
1655 privilegedAction=class_new(utf_new_char("java/security/PrivilegedAction"));
1657 for(i=0,current=start;i<size;i++,current--) {
1659 if (c==privilegedAction) return NULL;
1660 if (c->classloader) return c->classloader;
1668 log_text("Java_java_lang_VMSecurityManager_currentClassLoader");
1669 init_systemclassloader();
1671 return SystemClassLoader;*/
1675 * These are local overrides for various environment variables in Emacs.
1676 * Please do not remove this and leave it at the end of the file, where
1677 * Emacs will automagically detect them.
1678 * ---------------------------------------------------------------------
1681 * indent-tabs-mode: t