1 /* src/vm/string.c - java.lang.String related functions
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
31 Changes: Christian Thalinger
33 $Id: string.c 3888 2005-12-05 22:08:45Z twisti $
43 #include "vm/global.h"
45 #include "mm/memory.h"
46 #include "native/include/java_lang_String.h"
47 #include "vm/exceptions.h"
48 #include "vm/loader.h"
49 #include "vm/options.h"
50 #include "vm/stringlocal.h"
54 /* global variables ***********************************************************/
56 /* hashsize must be power of 2 */
58 #define HASHTABLE_STRING_SIZE 2048 /* initial size of javastring-hash */
60 hashtable hashtable_string; /* hashtable for javastrings */
62 #if defined(USE_THREADS)
63 static java_objectheader *lock_hashtable_string;
67 /* global string definitions **************************************************/
69 /* exception/error super class */
71 const char *string_java_lang_Throwable =
72 "java/lang/Throwable";
74 const char *string_java_lang_VMThrowable =
75 "java/lang/VMThrowable";
78 /* specify some exception strings for code generation */
80 const char *string_java_lang_ArithmeticException =
81 "java/lang/ArithmeticException";
83 const char *string_java_lang_ArithmeticException_message =
86 const char *string_java_lang_ArrayIndexOutOfBoundsException =
87 "java/lang/ArrayIndexOutOfBoundsException";
89 const char *string_java_lang_ArrayStoreException =
90 "java/lang/ArrayStoreException";
92 const char *string_java_lang_ClassCastException =
93 "java/lang/ClassCastException";
95 const char *string_java_lang_ClassNotFoundException =
96 "java/lang/ClassNotFoundException";
98 const char *string_java_lang_CloneNotSupportedException =
99 "java/lang/CloneNotSupportedException";
101 const char *string_java_lang_Exception =
102 "java/lang/Exception";
104 const char *string_java_lang_IllegalAccessException =
105 "java/lang/IllegalAccessException";
107 const char *string_java_lang_IllegalArgumentException =
108 "java/lang/IllegalArgumentException";
110 const char *string_java_lang_IllegalMonitorStateException =
111 "java/lang/IllegalMonitorStateException";
113 const char *string_java_lang_IndexOutOfBoundsException =
114 "java/lang/IndexOutOfBoundsException";
116 const char *string_java_lang_InstantiationException =
117 "java/lang/InstantiationException";
119 const char *string_java_lang_InterruptedException =
120 "java/lang/InterruptedException";
122 const char *string_java_lang_NegativeArraySizeException =
123 "java/lang/NegativeArraySizeException";
125 const char *string_java_lang_NoSuchFieldException =
126 "java/lang/NoSuchFieldException";
128 const char *string_java_lang_NoSuchMethodException =
129 "java/lang/NoSuchMethodException";
131 const char *string_java_lang_NullPointerException =
132 "java/lang/NullPointerException";
134 const char *string_java_lang_reflect_InvocationTargetException =
135 "java/lang/reflect/InvocationTargetException";
138 /* specify some error strings for code generation */
140 const char *string_java_lang_AbstractMethodError =
141 "java/lang/AbstractMethodError";
143 const char *string_java_lang_ClassCircularityError =
144 "java/lang/ClassCircularityError";
146 const char *string_java_lang_ClassFormatError =
147 "java/lang/ClassFormatError";
149 const char *string_java_lang_Error =
152 const char *string_java_lang_ExceptionInInitializerError =
153 "java/lang/ExceptionInInitializerError";
155 const char *string_java_lang_IncompatibleClassChangeError =
156 "java/lang/IncompatibleClassChangeError";
158 const char *string_java_lang_InstantiationError =
159 "java/lang/InstantiationError";
161 const char *string_java_lang_InternalError =
162 "java/lang/InternalError";
164 const char *string_java_lang_LinkageError =
165 "java/lang/LinkageError";
167 const char *string_java_lang_NoClassDefFoundError =
168 "java/lang/NoClassDefFoundError";
170 const char *string_java_lang_NoSuchFieldError =
171 "java/lang/NoSuchFieldError";
173 const char *string_java_lang_NoSuchMethodError =
174 "java/lang/NoSuchMethodError";
176 const char *string_java_lang_OutOfMemoryError =
177 "java/lang/OutOfMemoryError";
179 const char *string_java_lang_UnsatisfiedLinkError =
180 "java/lang/UnsatisfiedLinkError";
182 const char *string_java_lang_UnsupportedClassVersionError =
183 "java/lang/UnsupportedClassVersionError";
185 const char *string_java_lang_VerifyError =
186 "java/lang/VerifyError";
188 const char *string_java_lang_VirtualMachineError =
189 "java/lang/VirtualMachineError";
192 /* string_init *****************************************************************
194 Initialize the string hashtable lock.
196 *******************************************************************************/
198 bool string_init(void)
200 /* create string (javastring) hashtable */
202 hashtable_create(&hashtable_string, HASHTABLE_STRING_SIZE);
204 #if defined(USE_THREADS)
205 /* create string hashtable lock object */
207 lock_hashtable_string = NEW(java_objectheader);
209 # if defined(NATIVE_THREADS)
210 initObjectLock(lock_hashtable_string);
214 /* everything's ok */
220 /* stringtable_update **********************************************************
222 Traverses the javastring hashtable and sets the vftbl-entries of
223 javastrings which were temporarily set to NULL, because
224 java.lang.Object was not yet loaded.
226 *******************************************************************************/
228 void stringtable_update(void)
230 java_lang_String *js;
232 literalstring *s; /* hashtable entry */
235 for (i = 0; i < hashtable_string.size; i++) {
236 s = hashtable_string.ptr[i];
240 js = (java_lang_String *) s->string;
242 if (!js || !js->value) {
243 /* error in hashtable found */
244 log_text("invalid literalstring in hashtable");
250 if (!js->header.vftbl)
251 /* vftbl of javastring is NULL */
252 js->header.vftbl = class_java_lang_String->vftbl;
254 if (!a->header.objheader.vftbl)
255 /* vftbl of character-array is NULL */
256 a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
258 /* follow link in external hash chain */
266 /* javastring_new **************************************************************
268 creates a new object of type java/lang/String with the text of
269 the specified utf8-string
271 return: pointer to the string or NULL if memory is exhausted.
273 *******************************************************************************/
275 java_lang_String *javastring_new(utf *u)
277 char *utf_ptr; /* current utf character in utf string */
278 u4 utflength; /* length of utf-string if uncompressed */
279 java_lang_String *s; /* result-string */
284 *exceptionptr = new_nullpointerexception();
289 utflength = utf_strlen(u);
291 s = (java_lang_String *) builtin_new(class_java_lang_String);
292 a = builtin_newarray_char(utflength);
294 /* javastring or character-array could not be created */
298 /* decompress utf-string */
299 for (i = 0; i < utflength; i++)
300 a->data[i] = utf_nextu2(&utf_ptr);
302 /* set fields of the javastring-object */
305 s->count = utflength;
310 /* javastring_new_slash_to_dot *************************************************
312 creates a new object of type java/lang/String with the text of
313 the specified utf8-string with slashes changed to dots
315 return: pointer to the string or NULL if memory is exhausted.
317 *******************************************************************************/
319 java_lang_String *javastring_new_slash_to_dot(utf *u)
321 char *utf_ptr; /* current utf character in utf string */
322 u4 utflength; /* length of utf-string if uncompressed */
323 java_lang_String *s; /* result-string */
329 *exceptionptr = new_nullpointerexception();
334 utflength = utf_strlen(u);
336 s = (java_lang_String *) builtin_new(class_java_lang_String);
337 a = builtin_newarray_char(utflength);
339 /* javastring or character-array could not be created */
343 /* decompress utf-string */
344 for (i = 0; i < utflength; i++) {
345 ch = utf_nextu2(&utf_ptr);
351 /* set fields of the javastring-object */
354 s->count = utflength;
360 /* javastring_new_char *********************************************************
362 creates a new java/lang/String object which contains the convertet
363 C-string passed via text.
365 return: the object pointer or NULL if memory is exhausted.
367 *******************************************************************************/
369 java_lang_String *javastring_new_char(const char *text)
372 s4 len; /* length of the string */
373 java_lang_String *s; /* result-string */
377 *exceptionptr = new_nullpointerexception();
383 s = (java_lang_String *) builtin_new(class_java_lang_String);
384 a = builtin_newarray_char(len);
386 /* javastring or character-array could not be created */
391 for (i = 0; i < len; i++)
392 a->data[i] = text[i];
394 /* set fields of the javastring-object */
403 /* javastring_tochar ***********************************************************
405 converts a Java string into a C string.
407 return: pointer to C string
409 Caution: calling method MUST release the allocated memory!
411 *******************************************************************************/
413 char *javastring_tochar(java_objectheader *so)
415 java_lang_String *s = (java_lang_String *) so;
428 buf = MNEW(char, s->count + 1);
430 for (i = 0; i < s->count; i++)
431 buf[i] = a->data[s->offset + i];
439 /* javastring_toutf ************************************************************
441 Make utf symbol from javastring.
443 *******************************************************************************/
445 utf *javastring_toutf(java_lang_String *string, bool isclassname)
447 java_lang_String *str = (java_lang_String *) string;
449 return utf_new_u2(str->value->data + str->offset, str->count, isclassname);
453 /* javastring_strlen ***********************************************************
455 Returns the length of the Java string.
457 *******************************************************************************/
459 s4 javastring_strlen(java_objectheader *so)
461 java_lang_String *s = (java_lang_String *) so;
470 /* literalstring_u2 ************************************************************
472 Searches for the javastring with the specified u2-array in the
473 string hashtable, if there is no such string a new one is created.
475 If copymode is true a copy of the u2-array is made.
477 *******************************************************************************/
479 java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
482 literalstring *s; /* hashtable element */
483 java_lang_String *js; /* u2-array wrapped in javastring */
484 java_chararray *stringdata; /* copy of u2-array */
489 #if defined(USE_THREADS)
490 builtin_monitorenter(lock_hashtable_string);
493 /* find location in hashtable */
495 key = unicode_hashkey(a->data + offset, length);
496 slot = key & (hashtable_string.size - 1);
497 s = hashtable_string.ptr[slot];
500 js = (java_lang_String *) s->string;
502 if (length == js->count) {
505 for (i = 0; i < length; i++)
506 if (a->data[offset + i] != js->value->data[i])
509 /* string already in hashtable, free memory */
512 mem_free(a, sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10);
514 #if defined(USE_THREADS)
515 builtin_monitorexit(lock_hashtable_string);
518 return (java_objectheader *) js;
522 /* follow link in external hash chain */
527 /* create copy of u2-array for new javastring */
528 u4 arraysize = sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10;
529 stringdata = mem_alloc(arraysize);
530 /* memcpy(stringdata, a, arraysize); */
531 memcpy(&(stringdata->header), &(a->header), sizeof(java_arrayheader));
532 memcpy(&(stringdata->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10);
538 /* location in hashtable found, complete arrayheader */
540 stringdata->header.objheader.vftbl =
541 primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
542 stringdata->header.size = length;
544 /* XXX TWISTI: is this necessary? */
545 if (!class_java_lang_String)
546 class_java_lang_String = load_class_bootstrap(utf_java_lang_String);
548 assert(class_java_lang_String);
549 assert(class_java_lang_String->state & CLASS_LOADED);
551 /* if we use eager loading, we have to check loaded String class */
554 list_addfirst(&unlinkedclasses, class_java_lang_String);
556 /* create new javastring */
558 js = NEW(java_lang_String);
560 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
561 initObjectLock(&js->header);
564 js->header.vftbl = class_java_lang_String->vftbl;
565 js->value = stringdata;
569 /* create new literalstring */
571 s = NEW(literalstring);
572 s->hashlink = hashtable_string.ptr[slot];
573 s->string = (java_objectheader *) js;
574 hashtable_string.ptr[slot] = s;
576 /* update number of hashtable entries */
578 hashtable_string.entries++;
580 /* reorganization of hashtable */
582 if (hashtable_string.entries > (hashtable_string.size * 2)) {
583 /* reorganization of hashtable, average length of the external
584 chains is approx. 2 */
588 literalstring *nexts;
589 java_lang_String *tmpjs;
590 hashtable newhash; /* the new hashtable */
592 /* create new hashtable, double the size */
594 hashtable_create(&newhash, hashtable_string.size * 2);
595 newhash.entries = hashtable_string.entries;
597 /* transfer elements to new hashtable */
599 for (i = 0; i < hashtable_string.size; i++) {
600 s = hashtable_string.ptr[i];
604 tmpjs = (java_lang_String *) s->string;
605 slot = unicode_hashkey(tmpjs->value->data, tmpjs->count) & (newhash.size - 1);
607 s->hashlink = newhash.ptr[slot];
608 newhash.ptr[slot] = s;
610 /* follow link in external hash chain */
615 /* dispose old table */
617 MFREE(hashtable_string.ptr, void*, hashtable_string.size);
618 hashtable_string = newhash;
621 #if defined(USE_THREADS)
622 builtin_monitorexit(lock_hashtable_string);
625 return (java_objectheader *) js;
629 /* literalstring_new ***********************************************************
631 Creates a new javastring with the text of the utf-symbol and inserts it into
632 the string hashtable.
634 *******************************************************************************/
636 java_objectheader *literalstring_new(utf *u)
638 char *utf_ptr; /* pointer to current unicode character */
640 u4 utflength; /* length of utf-string if uncompressed */
641 java_chararray *a; /* u2-array constructed from utf string */
645 utflength = utf_strlen(u);
647 /* allocate memory */
648 a = mem_alloc(sizeof(java_chararray) + sizeof(u2) * (utflength - 1) + 10);
650 /* convert utf-string to u2-array */
651 for (i = 0; i < utflength; i++)
652 a->data[i] = utf_nextu2(&utf_ptr);
654 return literalstring_u2(a, utflength, 0, false);
658 /* literalstring_free **********************************************************
660 Removes a javastring from memory.
662 *******************************************************************************/
664 void literalstring_free(java_objectheader* sobj)
669 s = (java_lang_String *) sobj;
672 /* dispose memory of java.lang.String object */
673 FREE(s, java_lang_String);
675 /* dispose memory of java-characterarray */
676 FREE(a, sizeof(java_chararray) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
681 * These are local overrides for various environment variables in Emacs.
682 * Please do not remove this and leave it at the end of the file, where
683 * Emacs will automagically detect them.
684 * ---------------------------------------------------------------------
687 * indent-tabs-mode: t