* src/vm/jit/alpha/linux/md-os.c [ENABLE_THREADS]
[cacao.git] / src / vm / string.c
index a0e975559922962987b34e1356d2d6d0ce124d2e..a9b1d1a334d08f90a7864eb2a02aacb565f594d3 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/string.c - java.lang.String related functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Reinhard Grafl
-            Roman Obermaisser
-            Andreas Krall
-
-   Changes: Christian Thalinger
-                       Edwin Steiner
-
-   $Id: string.c 4908 2006-05-12 16:49:50Z edwin $
+   $Id: string.c 7522 2007-03-14 21:54:49Z twisti $
 
 */
 
 #include "vm/global.h"
 
 #include "mm/memory.h"
+
+#include "native/jni.h"
+
 #include "native/include/java_lang_String.h"
+
+#if defined(ENABLE_THREADS)
+# include "threads/native/lock.h"
+#else
+# include "threads/none/lock.h"
+#endif
+
+#include "vm/builtin.h"
 #include "vm/exceptions.h"
-#include "vm/loader.h"
-#include "vm/options.h"
 #include "vm/stringlocal.h"
-#include "vm/utf8.h"
+
+#include "vmcore/options.h"
+#include "vmcore/statistics.h"
+#include "vmcore/utf8.h"
 
 
 /* global variables ***********************************************************/
 
 hashtable hashtable_string;             /* hashtable for javastrings          */
 
-#if defined(USE_THREADS)
+#if defined(ENABLE_THREADS)
 static java_objectheader *lock_hashtable_string;
 #endif
 
 
-/* global string definitions **************************************************/
-
-/* exception/error super class */
-
-const char *string_java_lang_Throwable =
-    "java/lang/Throwable";
-
-const char *string_java_lang_VMThrowable =
-    "java/lang/VMThrowable";
-
-
-/* specify some exception strings for code generation */
-
-const char *string_java_lang_ArithmeticException =
-    "java/lang/ArithmeticException";
-
-const char *string_java_lang_ArithmeticException_message =
-    "/ by zero";
-
-const char *string_java_lang_ArrayIndexOutOfBoundsException =
-    "java/lang/ArrayIndexOutOfBoundsException";
-
-const char *string_java_lang_ArrayStoreException =
-    "java/lang/ArrayStoreException";
-
-const char *string_java_lang_ClassCastException =
-    "java/lang/ClassCastException";
-
-const char *string_java_lang_ClassNotFoundException =
-       "java/lang/ClassNotFoundException";
-
-const char *string_java_lang_CloneNotSupportedException =
-    "java/lang/CloneNotSupportedException";
-
-const char *string_java_lang_Exception =
-    "java/lang/Exception";
-
-const char *string_java_lang_IllegalAccessException =
-    "java/lang/IllegalAccessException";
-
-const char *string_java_lang_IllegalArgumentException =
-    "java/lang/IllegalArgumentException";
-
-const char *string_java_lang_IllegalMonitorStateException =
-    "java/lang/IllegalMonitorStateException";
-
-const char *string_java_lang_IndexOutOfBoundsException =
-    "java/lang/IndexOutOfBoundsException";
-
-const char *string_java_lang_InstantiationException =
-    "java/lang/InstantiationException";
-
-const char *string_java_lang_InterruptedException =
-    "java/lang/InterruptedException";
-
-const char *string_java_lang_NegativeArraySizeException =
-    "java/lang/NegativeArraySizeException";
-
-const char *string_java_lang_NoSuchFieldException =
-       "java/lang/NoSuchFieldException";
-
-const char *string_java_lang_NoSuchMethodException =
-       "java/lang/NoSuchMethodException";
-
-const char *string_java_lang_NullPointerException =
-    "java/lang/NullPointerException";
-
-const char *string_java_lang_StringIndexOutOfBoundsException =
-    "java/lang/StringIndexOutOfBoundsException";
-
-const char *string_java_lang_reflect_InvocationTargetException =
-    "java/lang/reflect/InvocationTargetException";
-
-
-/* specify some error strings for code generation */
-
-const char *string_java_lang_AbstractMethodError =
-    "java/lang/AbstractMethodError";
-
-const char *string_java_lang_ClassCircularityError =
-    "java/lang/ClassCircularityError";
-
-const char *string_java_lang_ClassFormatError =
-    "java/lang/ClassFormatError";
-
-const char *string_java_lang_Error =
-    "java/lang/Error";
-
-const char *string_java_lang_ExceptionInInitializerError =
-    "java/lang/ExceptionInInitializerError";
-
-const char *string_java_lang_IncompatibleClassChangeError =
-    "java/lang/IncompatibleClassChangeError";
-
-const char *string_java_lang_InstantiationError =
-    "java/lang/InstantiationError";
-
-const char *string_java_lang_InternalError =
-    "java/lang/InternalError";
-
-const char *string_java_lang_LinkageError =
-    "java/lang/LinkageError";
-
-const char *string_java_lang_NoClassDefFoundError =
-    "java/lang/NoClassDefFoundError";
-
-const char *string_java_lang_NoSuchFieldError =
-       "java/lang/NoSuchFieldError";
-
-const char *string_java_lang_NoSuchMethodError =
-       "java/lang/NoSuchMethodError";
-
-const char *string_java_lang_OutOfMemoryError =
-    "java/lang/OutOfMemoryError";
-
-const char *string_java_lang_UnsatisfiedLinkError =
-    "java/lang/UnsatisfiedLinkError";
-
-const char *string_java_lang_UnsupportedClassVersionError =
-    "java/lang/UnsupportedClassVersionError";
-
-const char *string_java_lang_VerifyError =
-    "java/lang/VerifyError";
-
-const char *string_java_lang_VirtualMachineError =
-    "java/lang/VirtualMachineError";
-
-
 /* string_init *****************************************************************
 
    Initialize the string hashtable lock.
@@ -206,14 +81,12 @@ bool string_init(void)
 
        hashtable_create(&hashtable_string, HASHTABLE_STRING_SIZE);
 
-#if defined(USE_THREADS)
+#if defined(ENABLE_THREADS)
        /* create string hashtable lock object */
 
        lock_hashtable_string = NEW(java_objectheader);
 
-# if defined(NATIVE_THREADS)
        lock_init_object_lock(lock_hashtable_string);
-# endif
 #endif
 
        /* everything's ok */
@@ -283,36 +156,103 @@ void stringtable_update(void)
 
 *******************************************************************************/
 
-java_lang_String *javastring_new_from_utf_buffer(const char *buffer, u4 blength)
+java_objectheader *javastring_new_from_utf_buffer(const char *buffer, u4 blength)
 {
        const char *utf_ptr;            /* current utf character in utf string    */
        u4 utflength;                   /* length of utf-string if uncompressed   */
-       java_lang_String *s;            /* result-string                          */
-       java_chararray *a;
+       java_objectheader *o;
+       java_lang_String  *s;           /* result-string                          */
+       java_chararray    *a;
        u4 i;
 
        assert(buffer);
 
        utflength = utf_get_number_of_u2s_for_buffer(buffer,blength);
 
-       s = (java_lang_String *) builtin_new(class_java_lang_String);
+       o = builtin_new(class_java_lang_String);
        a = builtin_newarray_char(utflength);
 
        /* javastring or character-array could not be created */
-       if (!a || !s)
+
+       if ((o == NULL) || (a == NULL))
                return NULL;
 
        /* decompress utf-string */
+
        utf_ptr = buffer;
+
        for (i = 0; i < utflength; i++)
-               a->data[i] = utf_nextu2((char **)&utf_ptr);
+               a->data[i] = utf_nextu2((char **) &utf_ptr);
        
        /* set fields of the javastring-object */
+
+       s = (java_lang_String *) o;
+
        s->value  = a;
        s->offset = 0;
        s->count  = utflength;
 
-       return s;
+       return o;
+}
+
+
+/* javastring_safe_new_from_utf8 ***********************************************
+
+   Create a new object of type java/lang/String with the text from
+   the specified UTF-8 string. This function is safe for invalid UTF-8.
+   (Invalid characters will be replaced by U+fffd.)
+
+   IN:
+      text.........the UTF-8 string, zero-terminated.
+
+   RETURN VALUE:
+      the java.lang.String object, or
+      NULL if an exception has been thrown
+
+*******************************************************************************/
+
+java_objectheader *javastring_safe_new_from_utf8(const char *text)
+{
+       java_objectheader *o;
+       java_chararray    *a;
+       java_lang_String  *s;
+       s4 nbytes;
+       s4 len;
+
+       assert(text);
+
+       /* Get number of bytes. We need this to completely emulate the messy */
+       /* behaviour of the RI. :(                                           */
+
+       nbytes = strlen(text);
+
+       /* calculate number of Java characters */
+
+       len = utf8_safe_number_of_u2s(text, nbytes);
+
+       /* allocate the String object and the char array */
+
+       o = builtin_new(class_java_lang_String);
+       a = builtin_newarray_char(len);
+
+       /* javastring or character-array could not be created? */
+
+       if ((o == NULL) || (a == NULL))
+               return NULL;
+
+       /* decompress UTF-8 string */
+
+       utf8_safe_convert_to_u2s(text, nbytes, a->data);
+
+       /* set fields of the String object */
+
+       s = (java_lang_String *) o;
+
+       s->value  = a;
+       s->offset = 0;
+       s->count  = len;
+
+       return o;
 }
 
 
@@ -331,7 +271,7 @@ java_lang_String *javastring_new_from_utf_buffer(const char *buffer, u4 blength)
 
 *******************************************************************************/
 
-java_lang_String *javastring_new_from_utf_string(const char *utfstr)
+java_objectheader *javastring_new_from_utf_string(const char *utfstr)
 {
        assert(utfstr);
 
@@ -348,15 +288,16 @@ java_lang_String *javastring_new_from_utf_string(const char *utfstr)
 
 *******************************************************************************/
 
-java_lang_String *javastring_new(utf *u)
+java_objectheader *javastring_new(utf *u)
 {
        char *utf_ptr;                  /* current utf character in utf string    */
        u4 utflength;                   /* length of utf-string if uncompressed   */
-       java_lang_String *s;            /* result-string                          */
-       java_chararray *a;
+       java_objectheader *o;
+       java_chararray    *a;
+       java_lang_String  *s;
        s4 i;
 
-       if (!u) {
+       if (u == NULL) {
                exceptions_throw_nullpointerexception();
                return NULL;
        }
@@ -364,25 +305,31 @@ java_lang_String *javastring_new(utf *u)
        utf_ptr = u->text;
        utflength = utf_get_number_of_u2s(u);
 
-       s = (java_lang_String *) builtin_new(class_java_lang_String);
+       o = builtin_new(class_java_lang_String);
        a = builtin_newarray_char(utflength);
 
        /* javastring or character-array could not be created */
-       if (!a || !s)
+
+       if ((o == NULL) || (a == NULL))
                return NULL;
 
        /* decompress utf-string */
+
        for (i = 0; i < utflength; i++)
                a->data[i] = utf_nextu2(&utf_ptr);
        
        /* set fields of the javastring-object */
+
+       s = (java_lang_String *) o;
+
        s->value  = a;
        s->offset = 0;
        s->count  = utflength;
 
-       return s;
+       return o;
 }
 
+
 /* javastring_new_slash_to_dot *************************************************
 
    creates a new object of type java/lang/String with the text of 
@@ -392,16 +339,17 @@ java_lang_String *javastring_new(utf *u)
 
 *******************************************************************************/
 
-java_lang_String *javastring_new_slash_to_dot(utf *u)
+java_objectheader *javastring_new_slash_to_dot(utf *u)
 {
        char *utf_ptr;                  /* current utf character in utf string    */
        u4 utflength;                   /* length of utf-string if uncompressed   */
-       java_lang_String *s;            /* result-string                          */
-       java_chararray *a;
+       java_objectheader *o;
+       java_chararray    *a;
+       java_lang_String  *s;
        s4 i;
        u2 ch;
 
-       if (!u) {
+       if (u == NULL) {
                exceptions_throw_nullpointerexception();
                return NULL;
        }
@@ -409,14 +357,15 @@ java_lang_String *javastring_new_slash_to_dot(utf *u)
        utf_ptr = u->text;
        utflength = utf_get_number_of_u2s(u);
 
-       s = (java_lang_String *) builtin_new(class_java_lang_String);
+       o = builtin_new(class_java_lang_String);
        a = builtin_newarray_char(utflength);
 
        /* javastring or character-array could not be created */
-       if (!a || !s)
+       if ((o == NULL) || (a == NULL))
                return NULL;
 
        /* decompress utf-string */
+
        for (i = 0; i < utflength; i++) {
                ch = utf_nextu2(&utf_ptr);
                if (ch == '/')
@@ -425,11 +374,14 @@ java_lang_String *javastring_new_slash_to_dot(utf *u)
        }
        
        /* set fields of the javastring-object */
+
+       s = (java_lang_String *) o;
+
        s->value  = a;
        s->offset = 0;
        s->count  = utflength;
 
-       return s;
+       return o;
 }
 
 
@@ -447,37 +399,43 @@ java_lang_String *javastring_new_slash_to_dot(utf *u)
 
 *******************************************************************************/
 
-java_lang_String *javastring_new_from_ascii(const char *text)
+java_objectheader *javastring_new_from_ascii(const char *text)
 {
        s4 i;
        s4 len;                             /* length of the string               */
-       java_lang_String *s;                /* result-string                      */
-       java_chararray *a;
+       java_objectheader *o;
+       java_lang_String  *s;
+       java_chararray    *a;
 
-       if (!text) {
+       if (text == NULL) {
                exceptions_throw_nullpointerexception();
                return NULL;
        }
 
        len = strlen(text);
 
-       s = (java_lang_String *) builtin_new(class_java_lang_String);
+       o = builtin_new(class_java_lang_String);
        a = builtin_newarray_char(len);
 
        /* javastring or character-array could not be created */
-       if (!a || !s)
+
+       if ((o == NULL) || (a == NULL))
                return NULL;
 
        /* copy text */
+
        for (i = 0; i < len; i++)
                a->data[i] = text[i];
        
        /* set fields of the javastring-object */
+
+       s = (java_lang_String *) o;
+
        s->value  = a;
        s->offset = 0;
        s->count  = len;
 
-       return s;
+       return o;
 }
 
 
@@ -523,26 +481,16 @@ char *javastring_tochar(java_objectheader *so)
 
 *******************************************************************************/
 
-utf *javastring_toutf(java_lang_String *string, bool isclassname)
+utf *javastring_toutf(java_objectheader *string, bool isclassname)
 {
-       java_lang_String *str = (java_lang_String *) string;
-
-       return utf_new_u2(str->value->data + str->offset, str->count, isclassname);
-}
-
-
-/* javastring_strlen ***********************************************************
+       java_lang_String *s;
 
-   Returns the length of the Java string.
-       
-*******************************************************************************/
+       s = (java_lang_String *) string;
 
-s4 javastring_strlen(java_lang_String *s)
-{
-       if (!s)
-               return 0;
+       if (s == NULL)
+               return utf_null;
 
-       return s->count;
+       return utf_new_u2(s->value->data + s->offset, s->count, isclassname);
 }
 
 
@@ -565,9 +513,7 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
     u4                slot;
     u2                i;
 
-#if defined(USE_THREADS)
-       builtin_monitorenter(lock_hashtable_string);
-#endif
+       LOCK_MONITOR_ENTER(lock_hashtable_string);
 
     /* find location in hashtable */
 
@@ -590,9 +536,7 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
                        if (!copymode)
                                mem_free(a, sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10);
 
-#if defined(USE_THREADS)
-                       builtin_monitorexit(lock_hashtable_string);
-#endif
+                       LOCK_MONITOR_EXIT(lock_hashtable_string);
 
                        return (java_objectheader *) js;
                }
@@ -626,13 +570,18 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
        /* if we use eager loading, we have to check loaded String class */
 
        if (opt_eager)
-               list_addfirst(&unlinkedclasses, class_java_lang_String);
+               list_add_first(&unlinkedclasses, class_java_lang_String);
 
        /* create new javastring */
 
        js = NEW(java_lang_String);
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_string += sizeof(java_lang_String);
+#endif
+
+#if defined(ENABLE_THREADS)
        lock_init_object_lock(&js->header);
 #endif
 
@@ -644,6 +593,12 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
        /* create new literalstring */
 
        s = NEW(literalstring);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_string += sizeof(literalstring);
+#endif
+
        s->hashlink = hashtable_string.ptr[slot];
        s->string   = (java_objectheader *) js;
        hashtable_string.ptr[slot] = s;
@@ -693,9 +648,7 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
                hashtable_string = newhash;
        }
 
-#if defined(USE_THREADS)
-       builtin_monitorexit(lock_hashtable_string);
-#endif
+       LOCK_MONITOR_EXIT(lock_hashtable_string);
 
        return (java_objectheader *) js;
 }
@@ -736,12 +689,12 @@ java_objectheader *literalstring_new(utf *u)
 
 *******************************************************************************/
 
-void literalstring_free(java_objectheader* sobj)
+void literalstring_free(java_objectheader* string)
 {
        java_lang_String *s;
        java_chararray *a;
 
-       s = (java_lang_String *) sobj;
+       s = (java_lang_String *) string;
        a = s->value;
 
        /* dispose memory of java.lang.String object */