1 /* src/vm/string.c - java.lang.String related functions
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Reinhard Grafl
31 Changes: Christian Thalinger
34 $Id: string.c 4921 2006-05-15 14:24:36Z twisti $
45 #include "vm/global.h"
47 #include "mm/memory.h"
48 #include "native/include/java_lang_String.h"
49 #include "vm/exceptions.h"
50 #include "vm/loader.h"
51 #include "vm/options.h"
52 #include "vm/stringlocal.h"
56 /* global variables ***********************************************************/
58 /* hashsize must be power of 2 */
60 #define HASHTABLE_STRING_SIZE 2048 /* initial size of javastring-hash */
62 hashtable hashtable_string; /* hashtable for javastrings */
64 #if defined(ENABLE_THREADS)
65 static java_objectheader *lock_hashtable_string;
69 /* global string definitions **************************************************/
71 /* exception/error super class */
73 const char *string_java_lang_Throwable =
74 "java/lang/Throwable";
76 const char *string_java_lang_VMThrowable =
77 "java/lang/VMThrowable";
80 /* specify some exception strings for code generation */
82 const char *string_java_lang_ArithmeticException =
83 "java/lang/ArithmeticException";
85 const char *string_java_lang_ArithmeticException_message =
88 const char *string_java_lang_ArrayIndexOutOfBoundsException =
89 "java/lang/ArrayIndexOutOfBoundsException";
91 const char *string_java_lang_ArrayStoreException =
92 "java/lang/ArrayStoreException";
94 const char *string_java_lang_ClassCastException =
95 "java/lang/ClassCastException";
97 const char *string_java_lang_ClassNotFoundException =
98 "java/lang/ClassNotFoundException";
100 const char *string_java_lang_CloneNotSupportedException =
101 "java/lang/CloneNotSupportedException";
103 const char *string_java_lang_Exception =
104 "java/lang/Exception";
106 const char *string_java_lang_IllegalAccessException =
107 "java/lang/IllegalAccessException";
109 const char *string_java_lang_IllegalArgumentException =
110 "java/lang/IllegalArgumentException";
112 const char *string_java_lang_IllegalMonitorStateException =
113 "java/lang/IllegalMonitorStateException";
115 const char *string_java_lang_IndexOutOfBoundsException =
116 "java/lang/IndexOutOfBoundsException";
118 const char *string_java_lang_InstantiationException =
119 "java/lang/InstantiationException";
121 const char *string_java_lang_InterruptedException =
122 "java/lang/InterruptedException";
124 const char *string_java_lang_NegativeArraySizeException =
125 "java/lang/NegativeArraySizeException";
127 const char *string_java_lang_NoSuchFieldException =
128 "java/lang/NoSuchFieldException";
130 const char *string_java_lang_NoSuchMethodException =
131 "java/lang/NoSuchMethodException";
133 const char *string_java_lang_NullPointerException =
134 "java/lang/NullPointerException";
136 const char *string_java_lang_StringIndexOutOfBoundsException =
137 "java/lang/StringIndexOutOfBoundsException";
139 const char *string_java_lang_reflect_InvocationTargetException =
140 "java/lang/reflect/InvocationTargetException";
143 /* specify some error strings for code generation */
145 const char *string_java_lang_AbstractMethodError =
146 "java/lang/AbstractMethodError";
148 const char *string_java_lang_ClassCircularityError =
149 "java/lang/ClassCircularityError";
151 const char *string_java_lang_ClassFormatError =
152 "java/lang/ClassFormatError";
154 const char *string_java_lang_Error =
157 const char *string_java_lang_ExceptionInInitializerError =
158 "java/lang/ExceptionInInitializerError";
160 const char *string_java_lang_IncompatibleClassChangeError =
161 "java/lang/IncompatibleClassChangeError";
163 const char *string_java_lang_InstantiationError =
164 "java/lang/InstantiationError";
166 const char *string_java_lang_InternalError =
167 "java/lang/InternalError";
169 const char *string_java_lang_LinkageError =
170 "java/lang/LinkageError";
172 const char *string_java_lang_NoClassDefFoundError =
173 "java/lang/NoClassDefFoundError";
175 const char *string_java_lang_NoSuchFieldError =
176 "java/lang/NoSuchFieldError";
178 const char *string_java_lang_NoSuchMethodError =
179 "java/lang/NoSuchMethodError";
181 const char *string_java_lang_OutOfMemoryError =
182 "java/lang/OutOfMemoryError";
184 const char *string_java_lang_UnsatisfiedLinkError =
185 "java/lang/UnsatisfiedLinkError";
187 const char *string_java_lang_UnsupportedClassVersionError =
188 "java/lang/UnsupportedClassVersionError";
190 const char *string_java_lang_VerifyError =
191 "java/lang/VerifyError";
193 const char *string_java_lang_VirtualMachineError =
194 "java/lang/VirtualMachineError";
197 /* string_init *****************************************************************
199 Initialize the string hashtable lock.
201 *******************************************************************************/
203 bool string_init(void)
205 /* create string (javastring) hashtable */
207 hashtable_create(&hashtable_string, HASHTABLE_STRING_SIZE);
209 #if defined(ENABLE_THREADS)
210 /* create string hashtable lock object */
212 lock_hashtable_string = NEW(java_objectheader);
214 lock_init_object_lock(lock_hashtable_string);
217 /* everything's ok */
223 /* stringtable_update **********************************************************
225 Traverses the javastring hashtable and sets the vftbl-entries of
226 javastrings which were temporarily set to NULL, because
227 java.lang.Object was not yet loaded.
229 *******************************************************************************/
231 void stringtable_update(void)
233 java_lang_String *js;
235 literalstring *s; /* hashtable entry */
238 for (i = 0; i < hashtable_string.size; i++) {
239 s = hashtable_string.ptr[i];
243 js = (java_lang_String *) s->string;
245 if (!js || !js->value) {
246 /* error in hashtable found */
247 log_text("invalid literalstring in hashtable");
253 if (!js->header.vftbl)
254 /* vftbl of javastring is NULL */
255 js->header.vftbl = class_java_lang_String->vftbl;
257 if (!a->header.objheader.vftbl)
258 /* vftbl of character-array is NULL */
259 a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
261 /* follow link in external hash chain */
269 /* javastring_new_from_utf_buffer **********************************************
271 Create a new object of type java/lang/String with the text from
272 the specified utf8 buffer.
275 buffer.......points to first char in the buffer
276 blength......number of bytes to read from the buffer
279 the java.lang.String object, or
280 NULL if an exception has been thrown
282 *******************************************************************************/
284 java_lang_String *javastring_new_from_utf_buffer(const char *buffer, u4 blength)
286 const char *utf_ptr; /* current utf character in utf string */
287 u4 utflength; /* length of utf-string if uncompressed */
288 java_lang_String *s; /* result-string */
294 utflength = utf_get_number_of_u2s_for_buffer(buffer,blength);
296 s = (java_lang_String *) builtin_new(class_java_lang_String);
297 a = builtin_newarray_char(utflength);
299 /* javastring or character-array could not be created */
303 /* decompress utf-string */
305 for (i = 0; i < utflength; i++)
306 a->data[i] = utf_nextu2((char **)&utf_ptr);
308 /* set fields of the javastring-object */
311 s->count = utflength;
317 /* javastring_new_from_utf_string **********************************************
319 Create a new object of type java/lang/String with the text from
320 the specified zero-terminated utf8 string.
323 buffer.......points to first char in the buffer
324 blength......number of bytes to read from the buffer
327 the java.lang.String object, or
328 NULL if an exception has been thrown
330 *******************************************************************************/
332 java_lang_String *javastring_new_from_utf_string(const char *utfstr)
336 return javastring_new_from_utf_buffer(utfstr, strlen(utfstr));
340 /* javastring_new **************************************************************
342 creates a new object of type java/lang/String with the text of
343 the specified utf8-string
345 return: pointer to the string or NULL if memory is exhausted.
347 *******************************************************************************/
349 java_lang_String *javastring_new(utf *u)
351 char *utf_ptr; /* current utf character in utf string */
352 u4 utflength; /* length of utf-string if uncompressed */
353 java_lang_String *s; /* result-string */
358 exceptions_throw_nullpointerexception();
363 utflength = utf_get_number_of_u2s(u);
365 s = (java_lang_String *) builtin_new(class_java_lang_String);
366 a = builtin_newarray_char(utflength);
368 /* javastring or character-array could not be created */
372 /* decompress utf-string */
373 for (i = 0; i < utflength; i++)
374 a->data[i] = utf_nextu2(&utf_ptr);
376 /* set fields of the javastring-object */
379 s->count = utflength;
384 /* javastring_new_slash_to_dot *************************************************
386 creates a new object of type java/lang/String with the text of
387 the specified utf8-string with slashes changed to dots
389 return: pointer to the string or NULL if memory is exhausted.
391 *******************************************************************************/
393 java_lang_String *javastring_new_slash_to_dot(utf *u)
395 char *utf_ptr; /* current utf character in utf string */
396 u4 utflength; /* length of utf-string if uncompressed */
397 java_lang_String *s; /* result-string */
403 exceptions_throw_nullpointerexception();
408 utflength = utf_get_number_of_u2s(u);
410 s = (java_lang_String *) builtin_new(class_java_lang_String);
411 a = builtin_newarray_char(utflength);
413 /* javastring or character-array could not be created */
417 /* decompress utf-string */
418 for (i = 0; i < utflength; i++) {
419 ch = utf_nextu2(&utf_ptr);
425 /* set fields of the javastring-object */
428 s->count = utflength;
434 /* javastring_new_from_ascii ***************************************************
436 creates a new java/lang/String object which contains the given ASCII
437 C-string converted to UTF-16.
440 text.........string of ASCII characters
443 the java.lang.String object, or
444 NULL if an exception has been thrown.
446 *******************************************************************************/
448 java_lang_String *javastring_new_from_ascii(const char *text)
451 s4 len; /* length of the string */
452 java_lang_String *s; /* result-string */
456 exceptions_throw_nullpointerexception();
462 s = (java_lang_String *) builtin_new(class_java_lang_String);
463 a = builtin_newarray_char(len);
465 /* javastring or character-array could not be created */
470 for (i = 0; i < len; i++)
471 a->data[i] = text[i];
473 /* set fields of the javastring-object */
482 /* javastring_tochar ***********************************************************
484 converts a Java string into a C string.
486 return: pointer to C string
488 Caution: calling method MUST release the allocated memory!
490 *******************************************************************************/
492 char *javastring_tochar(java_objectheader *so)
494 java_lang_String *s = (java_lang_String *) so;
507 buf = MNEW(char, s->count + 1);
509 for (i = 0; i < s->count; i++)
510 buf[i] = a->data[s->offset + i];
518 /* javastring_toutf ************************************************************
520 Make utf symbol from javastring.
522 *******************************************************************************/
524 utf *javastring_toutf(java_lang_String *string, bool isclassname)
526 java_lang_String *str = (java_lang_String *) string;
528 return utf_new_u2(str->value->data + str->offset, str->count, isclassname);
532 /* javastring_strlen ***********************************************************
534 Returns the length of the Java string.
536 *******************************************************************************/
538 s4 javastring_strlen(java_lang_String *s)
547 /* literalstring_u2 ************************************************************
549 Searches for the javastring with the specified u2-array in the
550 string hashtable, if there is no such string a new one is created.
552 If copymode is true a copy of the u2-array is made.
554 *******************************************************************************/
556 java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
559 literalstring *s; /* hashtable element */
560 java_lang_String *js; /* u2-array wrapped in javastring */
561 java_chararray *stringdata; /* copy of u2-array */
566 #if defined(ENABLE_THREADS)
567 builtin_monitorenter(lock_hashtable_string);
570 /* find location in hashtable */
572 key = unicode_hashkey(a->data + offset, length);
573 slot = key & (hashtable_string.size - 1);
574 s = hashtable_string.ptr[slot];
577 js = (java_lang_String *) s->string;
579 if (length == js->count) {
582 for (i = 0; i < length; i++)
583 if (a->data[offset + i] != js->value->data[i])
586 /* string already in hashtable, free memory */
589 mem_free(a, sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10);
591 #if defined(ENABLE_THREADS)
592 builtin_monitorexit(lock_hashtable_string);
595 return (java_objectheader *) js;
599 /* follow link in external hash chain */
604 /* create copy of u2-array for new javastring */
605 u4 arraysize = sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10;
606 stringdata = mem_alloc(arraysize);
607 /* memcpy(stringdata, a, arraysize); */
608 memcpy(&(stringdata->header), &(a->header), sizeof(java_arrayheader));
609 memcpy(&(stringdata->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10);
615 /* location in hashtable found, complete arrayheader */
617 stringdata->header.objheader.vftbl =
618 primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
619 stringdata->header.size = length;
621 assert(class_java_lang_String);
622 assert(class_java_lang_String->state & CLASS_LOADED);
624 /* if we use eager loading, we have to check loaded String class */
627 list_addfirst(&unlinkedclasses, class_java_lang_String);
629 /* create new javastring */
631 js = NEW(java_lang_String);
633 #if defined(ENABLE_THREADS)
634 lock_init_object_lock(&js->header);
637 js->header.vftbl = class_java_lang_String->vftbl;
638 js->value = stringdata;
642 /* create new literalstring */
644 s = NEW(literalstring);
645 s->hashlink = hashtable_string.ptr[slot];
646 s->string = (java_objectheader *) js;
647 hashtable_string.ptr[slot] = s;
649 /* update number of hashtable entries */
651 hashtable_string.entries++;
653 /* reorganization of hashtable */
655 if (hashtable_string.entries > (hashtable_string.size * 2)) {
656 /* reorganization of hashtable, average length of the external
657 chains is approx. 2 */
661 literalstring *nexts;
662 java_lang_String *tmpjs;
663 hashtable newhash; /* the new hashtable */
665 /* create new hashtable, double the size */
667 hashtable_create(&newhash, hashtable_string.size * 2);
668 newhash.entries = hashtable_string.entries;
670 /* transfer elements to new hashtable */
672 for (i = 0; i < hashtable_string.size; i++) {
673 s = hashtable_string.ptr[i];
677 tmpjs = (java_lang_String *) s->string;
678 slot = unicode_hashkey(tmpjs->value->data, tmpjs->count) & (newhash.size - 1);
680 s->hashlink = newhash.ptr[slot];
681 newhash.ptr[slot] = s;
683 /* follow link in external hash chain */
688 /* dispose old table */
690 MFREE(hashtable_string.ptr, void*, hashtable_string.size);
691 hashtable_string = newhash;
694 #if defined(ENABLE_THREADS)
695 builtin_monitorexit(lock_hashtable_string);
698 return (java_objectheader *) js;
702 /* literalstring_new ***********************************************************
704 Creates a new javastring with the text of the utf-symbol and inserts it into
705 the string hashtable.
707 *******************************************************************************/
709 java_objectheader *literalstring_new(utf *u)
711 char *utf_ptr; /* pointer to current unicode character */
713 u4 utflength; /* length of utf-string if uncompressed */
714 java_chararray *a; /* u2-array constructed from utf string */
718 utflength = utf_get_number_of_u2s(u);
720 /* allocate memory */
721 a = mem_alloc(sizeof(java_chararray) + sizeof(u2) * (utflength - 1) + 10);
723 /* convert utf-string to u2-array */
724 for (i = 0; i < utflength; i++)
725 a->data[i] = utf_nextu2(&utf_ptr);
727 return literalstring_u2(a, utflength, 0, false);
731 /* literalstring_free **********************************************************
733 Removes a javastring from memory.
735 *******************************************************************************/
737 void literalstring_free(java_objectheader* sobj)
742 s = (java_lang_String *) sobj;
745 /* dispose memory of java.lang.String object */
746 FREE(s, java_lang_String);
748 /* dispose memory of java-characterarray */
749 FREE(a, sizeof(java_chararray) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
754 * These are local overrides for various environment variables in Emacs.
755 * Please do not remove this and leave it at the end of the file, where
756 * Emacs will automagically detect them.
757 * ---------------------------------------------------------------------
760 * indent-tabs-mode: t
764 * vim:noexpandtab:sw=4:ts=4: