* Removed all Id tags.
[cacao.git] / src / vm / string.c
index aa4c3c65048ecded80fba801001d0af6e653abad..d8a1520b4e2d894a3c9c2d35359790459576d8f6 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
-
-   $Id: string.c 4872 2006-05-05 13:48:25Z edwin $
-
 */
 
 
 #include "vm/global.h"
 
 #include "mm/memory.h"
+
+#include "native/jni.h"
+#include "native/llni.h"
+
 #include "native/include/java_lang_String.h"
+
+#include "threads/lock-common.h"
+
+#include "vm/array.h"
+#include "vm/builtin.h"
 #include "vm/exceptions.h"
-#include "vm/loader.h"
-#include "vm/options.h"
+#include "vm/primitive.h"
 #include "vm/stringlocal.h"
-#include "vm/utf8.h"
+#include "vm/vm.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)
-static java_objectheader *lock_hashtable_string;
+#if defined(ENABLE_THREADS)
+static java_object_t *lock_hashtable_string;
 #endif
 
 
-/* global string definitions **************************************************/
+/* string_init *****************************************************************
 
-/* exception/error super class */
+   Initialize the string hashtable lock.
 
-const char *string_java_lang_Throwable =
-    "java/lang/Throwable";
+*******************************************************************************/
 
-const char *string_java_lang_VMThrowable =
-    "java/lang/VMThrowable";
+bool string_init(void)
+{
+       /* create string (javastring) hashtable */
 
+       hashtable_create(&hashtable_string, HASHTABLE_STRING_SIZE);
 
-/* specify some exception strings for code generation */
+#if defined(ENABLE_THREADS)
+       /* create string hashtable lock object */
 
-const char *string_java_lang_ArithmeticException =
-    "java/lang/ArithmeticException";
+       lock_hashtable_string = NEW(java_object_t);
 
-const char *string_java_lang_ArithmeticException_message =
-    "/ by zero";
+       LOCK_INIT_OBJECT_LOCK(lock_hashtable_string);
+#endif
 
-const char *string_java_lang_ArrayIndexOutOfBoundsException =
-    "java/lang/ArrayIndexOutOfBoundsException";
+       /* everything's ok */
 
-const char *string_java_lang_ArrayStoreException =
-    "java/lang/ArrayStoreException";
+       return true;
+}
 
-const char *string_java_lang_ClassCastException =
-    "java/lang/ClassCastException";
 
-const char *string_java_lang_ClassNotFoundException =
-       "java/lang/ClassNotFoundException";
+/* stringtable_update **********************************************************
 
-const char *string_java_lang_CloneNotSupportedException =
-    "java/lang/CloneNotSupportedException";
+   Traverses the javastring hashtable and sets the vftbl-entries of
+   javastrings which were temporarily set to NULL, because
+   java.lang.Object was not yet loaded.
 
-const char *string_java_lang_Exception =
-    "java/lang/Exception";
+*******************************************************************************/
+void stringtable_update(void)
+{
+       java_lang_String *js;
+       java_chararray_t *a;
+       literalstring    *s;       /* hashtable entry */
+       int i;
 
-const char *string_java_lang_IllegalAccessException =
-    "java/lang/IllegalAccessException";
+       for (i = 0; i < hashtable_string.size; i++) {
+               s = hashtable_string.ptr[i];
+               if (s) {
+                       while (s) {
+                               js = (java_lang_String *) s->string;
+                               
+                               if ((js == NULL) || (js->value == NULL)) {
+                                       /* error in hashtable found */
 
-const char *string_java_lang_IllegalArgumentException =
-    "java/lang/IllegalArgumentException";
+                                       vm_abort("stringtable_update: invalid literalstring in hashtable");
+                               }
 
-const char *string_java_lang_IllegalMonitorStateException =
-    "java/lang/IllegalMonitorStateException";
+                               LLNI_field_get_ref(js, value, a);
 
-const char *string_java_lang_IndexOutOfBoundsException =
-    "java/lang/IndexOutOfBoundsException";
+                               if (!js->header.vftbl) 
+                                       /* vftbl of javastring is NULL */ 
+                                       js->header.vftbl = class_java_lang_String->vftbl;
 
-const char *string_java_lang_InstantiationException =
-    "java/lang/InstantiationException";
+                               if (!a->header.objheader.vftbl) 
+                                       /* vftbl of character-array is NULL */ 
+                                       a->header.objheader.vftbl =
+                                               primitive_arrayclass_get_by_type(ARRAYTYPE_CHAR)->vftbl;
 
-const char *string_java_lang_InterruptedException =
-    "java/lang/InterruptedException";
+                               /* follow link in external hash chain */
+                               s = s->hashlink;
+                       }       
+               }               
+       }
+}
 
-const char *string_java_lang_NegativeArraySizeException =
-    "java/lang/NegativeArraySizeException";
 
-const char *string_java_lang_NoSuchFieldException =
-       "java/lang/NoSuchFieldException";
+/* javastring_new_from_utf_buffer **********************************************
 
-const char *string_java_lang_NoSuchMethodException =
-       "java/lang/NoSuchMethodException";
+   Create a new object of type java/lang/String with the text from
+   the specified utf8 buffer.
 
-const char *string_java_lang_NullPointerException =
-    "java/lang/NullPointerException";
+   IN:
+      buffer.......points to first char in the buffer
+         blength......number of bytes to read from the buffer
 
-const char *string_java_lang_StringIndexOutOfBoundsException =
-    "java/lang/StringIndexOutOfBoundsException";
+   RETURN VALUE:
+      the java.lang.String object, or
+      NULL if an exception has been thrown
 
-const char *string_java_lang_reflect_InvocationTargetException =
-    "java/lang/reflect/InvocationTargetException";
+*******************************************************************************/
 
+static java_handle_t *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_handle_t     *o;
+       java_lang_String  *s;           /* result-string                          */
+       java_handle_chararray_t *a;
+       u4 i;
 
-/* specify some error strings for code generation */
+       assert(buffer);
 
-const char *string_java_lang_AbstractMethodError =
-    "java/lang/AbstractMethodError";
+       utflength = utf_get_number_of_u2s_for_buffer(buffer,blength);
 
-const char *string_java_lang_ClassCircularityError =
-    "java/lang/ClassCircularityError";
+       o = builtin_new(class_java_lang_String);
+       a = builtin_newarray_char(utflength);
 
-const char *string_java_lang_ClassFormatError =
-    "java/lang/ClassFormatError";
+       /* javastring or character-array could not be created */
 
-const char *string_java_lang_Error =
-    "java/lang/Error";
+       if ((o == NULL) || (a == NULL))
+               return NULL;
 
-const char *string_java_lang_ExceptionInInitializerError =
-    "java/lang/ExceptionInInitializerError";
+       /* decompress utf-string */
 
-const char *string_java_lang_IncompatibleClassChangeError =
-    "java/lang/IncompatibleClassChangeError";
+       utf_ptr = buffer;
 
-const char *string_java_lang_InstantiationError =
-    "java/lang/InstantiationError";
+       for (i = 0; i < utflength; i++)
+               LLNI_array_direct(a, i) = utf_nextu2((char **) &utf_ptr);
+       
+       /* set fields of the javastring-object */
 
-const char *string_java_lang_InternalError =
-    "java/lang/InternalError";
+       s = (java_lang_String *) o;
 
-const char *string_java_lang_LinkageError =
-    "java/lang/LinkageError";
+       LLNI_field_set_ref(s, value , a);
+       LLNI_field_set_val(s, offset, 0);
+       LLNI_field_set_val(s, count , utflength);
 
-const char *string_java_lang_NoClassDefFoundError =
-    "java/lang/NoClassDefFoundError";
+       return o;
+}
 
-const char *string_java_lang_NoSuchFieldError =
-       "java/lang/NoSuchFieldError";
 
-const char *string_java_lang_NoSuchMethodError =
-       "java/lang/NoSuchMethodError";
+/* javastring_safe_new_from_utf8 ***********************************************
 
-const char *string_java_lang_OutOfMemoryError =
-    "java/lang/OutOfMemoryError";
+   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.)
 
-const char *string_java_lang_UnsatisfiedLinkError =
-    "java/lang/UnsatisfiedLinkError";
+   IN:
+      text.........the UTF-8 string, zero-terminated.
 
-const char *string_java_lang_UnsupportedClassVersionError =
-    "java/lang/UnsupportedClassVersionError";
+   RETURN VALUE:
+      the java.lang.String object, or
+      NULL if an exception has been thrown
 
-const char *string_java_lang_VerifyError =
-    "java/lang/VerifyError";
+*******************************************************************************/
 
-const char *string_java_lang_VirtualMachineError =
-    "java/lang/VirtualMachineError";
+java_handle_t *javastring_safe_new_from_utf8(const char *text)
+{
+       java_handle_t           *o;
+       java_handle_chararray_t *a;
+       java_lang_String        *s;
+       s4 nbytes;
+       s4 len;
 
+       assert(text);
 
-/* string_init *****************************************************************
+       /* Get number of bytes. We need this to completely emulate the messy */
+       /* behaviour of the RI. :(                                           */
 
-   Initialize the string hashtable lock.
+       nbytes = strlen(text);
 
-*******************************************************************************/
+       /* calculate number of Java characters */
 
-bool string_init(void)
-{
-       /* create string (javastring) hashtable */
+       len = utf8_safe_number_of_u2s(text, nbytes);
 
-       hashtable_create(&hashtable_string, HASHTABLE_STRING_SIZE);
+       /* allocate the String object and the char array */
 
-#if defined(USE_THREADS)
-       /* create string hashtable lock object */
+       o = builtin_new(class_java_lang_String);
+       a = builtin_newarray_char(len);
 
-       lock_hashtable_string = NEW(java_objectheader);
+       /* javastring or character-array could not be created? */
 
-# if defined(NATIVE_THREADS)
-       initObjectLock(lock_hashtable_string);
-# endif
-#endif
+       if ((o == NULL) || (a == NULL))
+               return NULL;
 
-       /* everything's ok */
+       /* decompress UTF-8 string */
 
-       return true;
-}
+       utf8_safe_convert_to_u2s(text, nbytes, a->data);
 
+       /* set fields of the String object */
 
-/* stringtable_update **********************************************************
+       s = (java_lang_String *) o;
 
-   Traverses the javastring hashtable and sets the vftbl-entries of
-   javastrings which were temporarily set to NULL, because
-   java.lang.Object was not yet loaded.
+       LLNI_field_set_ref(s, value , a);
+       LLNI_field_set_val(s, offset, 0);
+       LLNI_field_set_val(s, count , len);
 
-*******************************************************************************/
-void stringtable_update(void)
-{
-       java_lang_String *js;   
-       java_chararray *a;
-       literalstring *s;       /* hashtable entry */
-       int i;
+       return o;
+}
 
-       for (i = 0; i < hashtable_string.size; i++) {
-               s = hashtable_string.ptr[i];
-               if (s) {
-                       while (s) {
-                                                               
-                               js = (java_lang_String *) s->string;
-                               
-                               if (!js || !js->value) {
-                                       /* error in hashtable found */
-                                       log_text("invalid literalstring in hashtable");
-                                       assert(0);
-                               }
 
-                               a = js->value;
+/* javastring_new_from_utf_string **********************************************
 
-                               if (!js->header.vftbl) 
-                                       /* vftbl of javastring is NULL */ 
-                                       js->header.vftbl = class_java_lang_String->vftbl;
+   Create a new object of type java/lang/String with the text from
+   the specified zero-terminated utf8 string.
 
-                               if (!a->header.objheader.vftbl) 
-                                       /* vftbl of character-array is NULL */ 
-                                       a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
+   IN:
+      buffer.......points to first char in the buffer
+         blength......number of bytes to read from the buffer
 
-                               /* follow link in external hash chain */
-                               s = s->hashlink;
-                       }       
-               }               
-       }
+   RETURN VALUE:
+      the java.lang.String object, or
+      NULL if an exception has been thrown
+
+*******************************************************************************/
+
+java_handle_t *javastring_new_from_utf_string(const char *utfstr)
+{
+       assert(utfstr);
+
+       return javastring_new_from_utf_buffer(utfstr, strlen(utfstr));
 }
 
 
@@ -276,15 +287,16 @@ void stringtable_update(void)
 
 *******************************************************************************/
 
-java_lang_String *javastring_new(utf *u)
+java_handle_t *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_handle_t           *o;
+       java_handle_chararray_t *a;
+       java_lang_String        *s;
        s4 i;
 
-       if (!u) {
+       if (u == NULL) {
                exceptions_throw_nullpointerexception();
                return NULL;
        }
@@ -292,25 +304,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);
+               LLNI_array_direct(a, i) = utf_nextu2(&utf_ptr);
        
        /* set fields of the javastring-object */
-       s->value  = a;
-       s->offset = 0;
-       s->count  = utflength;
 
-       return s;
+       s = (java_lang_String *) o;
+
+       LLNI_field_set_ref(s, value , a);
+       LLNI_field_set_val(s, offset, 0);
+       LLNI_field_set_val(s, count , utflength);
+
+       return o;
 }
 
+
 /* javastring_new_slash_to_dot *************************************************
 
    creates a new object of type java/lang/String with the text of 
@@ -320,16 +338,17 @@ java_lang_String *javastring_new(utf *u)
 
 *******************************************************************************/
 
-java_lang_String *javastring_new_slash_to_dot(utf *u)
+java_handle_t *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_handle_t           *o;
+       java_handle_chararray_t *a;
+       java_lang_String        *s;
        s4 i;
        u2 ch;
 
-       if (!u) {
+       if (u == NULL) {
                exceptions_throw_nullpointerexception();
                return NULL;
        }
@@ -337,70 +356,85 @@ 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 == '/')
                        ch = '.';
-               a->data[i] = ch;
+               LLNI_array_direct(a, i) = ch;
        }
        
        /* set fields of the javastring-object */
-       s->value  = a;
-       s->offset = 0;
-       s->count  = utflength;
 
-       return s;
+       s = (java_lang_String *) o;
+
+       LLNI_field_set_ref(s, value , a);
+       LLNI_field_set_val(s, offset, 0);
+       LLNI_field_set_val(s, count , utflength);
+
+       return o;
 }
 
 
-/* javastring_new_char *********************************************************
+/* javastring_new_from_ascii ***************************************************
+
+   creates a new java/lang/String object which contains the given ASCII
+   C-string converted to UTF-16.
 
-   creates a new java/lang/String object which contains the convertet
-   C-string passed via text.
+   IN:
+      text.........string of ASCII characters
 
-   return: the object pointer or NULL if memory is exhausted.
+   RETURN VALUE:
+      the java.lang.String object, or 
+      NULL if an exception has been thrown.
 
 *******************************************************************************/
 
-java_lang_String *javastring_new_char(const char *text)
+java_handle_t *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_handle_t           *o;
+       java_lang_String        *s;
+       java_handle_chararray_t *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];
+               LLNI_array_direct(a, i) = text[i];
        
        /* set fields of the javastring-object */
-       s->value  = a;
-       s->offset = 0;
-       s->count  = len;
 
-       return s;
+       s = (java_lang_String *) o;
+
+       LLNI_field_set_ref(s, value , a);
+       LLNI_field_set_val(s, offset, 0);
+       LLNI_field_set_val(s, count , len);
+
+       return o;
 }
 
 
@@ -414,25 +448,25 @@ java_lang_String *javastring_new_char(const char *text)
        
 *******************************************************************************/
 
-char *javastring_tochar(java_objectheader *so) 
+char *javastring_tochar(java_handle_t *so) 
 {
-       java_lang_String *s = (java_lang_String *) so;
-       java_chararray *a;
+       java_lang_String        *s = (java_lang_String *) so;
+       java_handle_chararray_t *a;
        char *buf;
        s4 i;
        
        if (!s)
                return "";
 
-       a = s->value;
+       LLNI_field_get_ref(s, value, a);
 
        if (!a)
                return "";
 
-       buf = MNEW(char, s->count + 1);
+       buf = MNEW(char, LLNI_field_direct(s, count) + 1);
 
-       for (i = 0; i < s->count; i++)
-               buf[i] = a->data[s->offset + i];
+       for (i = 0; i < LLNI_field_direct(s, count); i++)
+               buf[i] = a->data[LLNI_field_direct(s, offset) + i];
 
        buf[i] = '\0';
 
@@ -446,26 +480,16 @@ char *javastring_tochar(java_objectheader *so)
 
 *******************************************************************************/
 
-utf *javastring_toutf(java_lang_String *string, bool isclassname)
+utf *javastring_toutf(java_handle_t *string, bool isclassname)
 {
-       java_lang_String *str = (java_lang_String *) string;
-
-       return utf_new_u2(str->value->data + str->offset, str->count, isclassname);
-}
-
+       java_lang_String *s;
 
-/* javastring_strlen ***********************************************************
+       s = (java_lang_String *) string;
 
-   Returns the length of the Java string.
-       
-*******************************************************************************/
+       if (s == NULL)
+               return utf_null;
 
-s4 javastring_strlen(java_lang_String *s)
-{
-       if (!s)
-               return 0;
-
-       return s->count;
+       return utf_new_u2(LLNI_field_direct(s, value)->data + LLNI_field_direct(s, offset), LLNI_field_direct(s, count), isclassname);
 }
 
 
@@ -478,19 +502,17 @@ s4 javastring_strlen(java_lang_String *s)
 
 *******************************************************************************/
 
-java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
-                                                                       bool copymode)
+java_object_t *literalstring_u2(java_chararray_t *a, u4 length, u4 offset,
+                                                               bool copymode)
 {
     literalstring    *s;                /* hashtable element                  */
     java_lang_String *js;               /* u2-array wrapped in javastring     */
-    java_chararray   *stringdata;       /* copy of u2-array                   */
+    java_chararray_t *ca;               /* copy of u2-array                   */
     u4                key;
     u4                slot;
     u2                i;
 
-#if defined(USE_THREADS)
-       builtin_monitorenter(lock_hashtable_string);
-#endif
+       LOCK_MONITOR_ENTER(lock_hashtable_string);
 
     /* find location in hashtable */
 
@@ -511,13 +533,11 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
                        /* string already in hashtable, free memory */
 
                        if (!copymode)
-                               mem_free(a, sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10);
+                               mem_free(a, sizeof(java_chararray_t) + 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;
+                       return (java_object_t *) js;
                }
 
        nomatch:
@@ -527,52 +547,54 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
 
     if (copymode) {
                /* create copy of u2-array for new javastring */
-               u4 arraysize = sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10;
-               stringdata = mem_alloc(arraysize);
-/*             memcpy(stringdata, a, arraysize); */
-               memcpy(&(stringdata->header), &(a->header), sizeof(java_arrayheader));
-               memcpy(&(stringdata->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10);
+               u4 arraysize = sizeof(java_chararray_t) + sizeof(u2) * (length - 1) + 10;
+               ca = mem_alloc(arraysize);
+/*             memcpy(ca, a, arraysize); */
+               memcpy(&(ca->header), &(a->header), sizeof(java_array_t));
+               memcpy(&(ca->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10);
 
     } else {
-               stringdata = a;
+               ca = a;
        }
 
     /* location in hashtable found, complete arrayheader */
 
-    stringdata->header.objheader.vftbl =
-               primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
-    stringdata->header.size = length;
-
-       /* XXX TWISTI: is this necessary? */
-       if (!class_java_lang_String)
-               class_java_lang_String = load_class_bootstrap(utf_java_lang_String);
+    ca->header.objheader.vftbl =
+               primitive_arrayclass_get_by_type(ARRAYTYPE_CHAR)->vftbl;
+    ca->header.size            = length;
 
        assert(class_java_lang_String);
        assert(class_java_lang_String->state & CLASS_LOADED);
 
-       /* if we use eager loading, we have to check loaded String class */
-
-       if (opt_eager)
-               list_addfirst(&unlinkedclasses, class_java_lang_String);
-
        /* create new javastring */
 
        js = NEW(java_lang_String);
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       initObjectLock(&js->header);
+#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
 
        js->header.vftbl = class_java_lang_String->vftbl;
-       js->value  = stringdata;
+       js->value  = ca;
        js->offset = 0;
        js->count  = length;
 
        /* 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;
+       s->string   = (java_object_t *) js;
        hashtable_string.ptr[slot] = s;
 
        /* update number of hashtable entries */
@@ -620,11 +642,9 @@ 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;
+       return (java_object_t *) js;
 }
 
 
@@ -635,19 +655,19 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
 
 *******************************************************************************/
 
-java_objectheader *literalstring_new(utf *u)
+java_object_t *literalstring_new(utf *u)
 {
-    char           *utf_ptr;         /* pointer to current unicode character  */
+    char             *utf_ptr;       /* pointer to current unicode character  */
                                         /* utf string                            */
-    u4              utflength;       /* length of utf-string if uncompressed  */
-    java_chararray *a;               /* u2-array constructed from utf string  */
-    u4              i;
+    u4                utflength;     /* length of utf-string if uncompressed  */
+    java_chararray_t *a;             /* u2-array constructed from utf string  */
+    u4                i;
 
        utf_ptr = u->text;
        utflength = utf_get_number_of_u2s(u);
 
     /* allocate memory */ 
-    a = mem_alloc(sizeof(java_chararray) + sizeof(u2) * (utflength - 1) + 10);
+    a = mem_alloc(sizeof(java_chararray_t) + sizeof(u2) * (utflength - 1) + 10);
 
     /* convert utf-string to u2-array */
     for (i = 0; i < utflength; i++)
@@ -663,19 +683,74 @@ java_objectheader *literalstring_new(utf *u)
 
 *******************************************************************************/
 
-void literalstring_free(java_objectheader* sobj)
+void literalstring_free(java_object_t* string)
 {
        java_lang_String *s;
-       java_chararray *a;
+       java_chararray_t *a;
 
-       s = (java_lang_String *) sobj;
+       s = (java_lang_String *) string;
        a = s->value;
 
        /* dispose memory of java.lang.String object */
        FREE(s, java_lang_String);
 
        /* dispose memory of java-characterarray */
-       FREE(a, sizeof(java_chararray) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
+       FREE(a, sizeof(java_chararray_t) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
+}
+
+
+/* javastring_intern ***********************************************************
+
+   Intern the given Java string.
+
+*******************************************************************************/
+
+java_handle_t *javastring_intern(java_handle_t *s)
+{
+       java_lang_String *so;
+       java_chararray_t *value;
+       int32_t           count;
+       int32_t           offset;
+/*     java_lang_String *o; */
+       java_object_t    *o;
+
+       so = (java_lang_String *) s;
+
+       value  = LLNI_field_direct(so, value);
+       count  = LLNI_field_direct(so, count);
+       offset = LLNI_field_direct(so, offset);
+
+       o = literalstring_u2(value, count, offset, true);
+
+       return o;
+}
+
+
+/* javastring_print ************************************************************
+
+   Print the given Java string.
+
+*******************************************************************************/
+
+void javastring_print(java_handle_t *s)
+{
+       java_lang_String *so;
+       java_chararray_t *value;
+       int32_t           count;
+       int32_t           offset;
+       uint16_t          c;
+       int               i;
+
+       so = (java_lang_String *) s;
+
+       value  = LLNI_field_direct(so, value);
+       count  = LLNI_field_direct(so, count);
+       offset = LLNI_field_direct(so, offset);
+
+       for (i = offset; i < offset + count; i++) {
+               c = LLNI_array_direct(value, i);
+               putchar(c);
+       }
 }
 
 
@@ -690,4 +765,5 @@ void literalstring_free(java_objectheader* sobj)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */