* src/vm/primitive.c: Removed.
[cacao.git] / src / vm / string.c
index 1d127f76f57c0248bdaf7d18043a187bc915e6ac..74400828214dddca58a96e3403a2af24e4842b42 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/string.c - java.lang.String related functions
 
-   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
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -22,8 +20,6 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: string.c 7813 2007-04-25 19:20:13Z twisti $
-
 */
 
 
@@ -31,6 +27,8 @@
 
 #include <assert.h>
 
+#include "vmcore/system.h"
+
 #include "vm/types.h"
 
 #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/primitive.hpp"
 #include "vm/stringlocal.h"
+#include "vm/vm.h"
 
 #include "vmcore/options.h"
 #include "vmcore/statistics.h"
 hashtable hashtable_string;             /* hashtable for javastrings          */
 
 #if defined(ENABLE_THREADS)
-static java_objectheader *lock_hashtable_string;
+static java_object_t *lock_hashtable_string;
+#endif
+
+
+/* XXX preliminary typedef, will be removed once string.c and utf8.c are
+   unified. */
+
+#if defined(ENABLE_HANDLES)
+typedef heap_java_lang_String heapstring_t;
+#else
+typedef java_lang_String heapstring_t;
 #endif
 
 
@@ -73,6 +85,8 @@ static java_objectheader *lock_hashtable_string;
 
 bool string_init(void)
 {
+       TRACESUBSYSTEMINITIALIZATION("string_init");
+
        /* create string (javastring) hashtable */
 
        hashtable_create(&hashtable_string, HASHTABLE_STRING_SIZE);
@@ -80,7 +94,7 @@ bool string_init(void)
 #if defined(ENABLE_THREADS)
        /* create string hashtable lock object */
 
-       lock_hashtable_string = NEW(java_objectheader);
+       lock_hashtable_string = NEW(java_object_t);
 
        LOCK_INIT_OBJECT_LOCK(lock_hashtable_string);
 #endif
@@ -101,22 +115,21 @@ bool string_init(void)
  
 void stringtable_update(void)
 {
-       java_lang_String *js;   
-       java_chararray *a;
-       literalstring *s;       /* hashtable entry */
+       heapstring_t     *js;
+       java_chararray_t *a;
+       literalstring    *s;       /* hashtable entry */
        int i;
 
        for (i = 0; i < hashtable_string.size; i++) {
                s = hashtable_string.ptr[i];
                if (s) {
                        while (s) {
-                                                               
-                               js = (java_lang_String *) s->string;
+                               js = (heapstring_t *) s->string;
                                
-                               if (!js || !js->value) {
+                               if ((js == NULL) || (js->value == NULL)) {
                                        /* error in hashtable found */
-                                       log_text("invalid literalstring in hashtable");
-                                       assert(0);
+
+                                       vm_abort("stringtable_update: invalid literalstring in hashtable");
                                }
 
                                a = js->value;
@@ -127,7 +140,8 @@ void stringtable_update(void)
 
                                if (!a->header.objheader.vftbl) 
                                        /* vftbl of character-array is NULL */ 
-                                       a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
+                                       a->header.objheader.vftbl =
+                                               Primitive_get_arrayclass_by_type(ARRAYTYPE_CHAR)->vftbl;
 
                                /* follow link in external hash chain */
                                s = s->hashlink;
@@ -152,13 +166,14 @@ void stringtable_update(void)
 
 *******************************************************************************/
 
-java_objectheader *javastring_new_from_utf_buffer(const char *buffer, u4 blength)
+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_objectheader *o;
+       java_handle_t     *o;
        java_lang_String  *s;           /* result-string                          */
-       java_chararray    *a;
+       java_handle_chararray_t *a;
        u4 i;
 
        assert(buffer);
@@ -178,15 +193,15 @@ java_objectheader *javastring_new_from_utf_buffer(const char *buffer, u4 blength
        utf_ptr = buffer;
 
        for (i = 0; i < utflength; i++)
-               a->data[i] = utf_nextu2((char **) &utf_ptr);
+               LLNI_array_direct(a, 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;
+       LLNI_field_set_ref(s, value , a);
+       LLNI_field_set_val(s, offset, 0);
+       LLNI_field_set_val(s, count , utflength);
 
        return o;
 }
@@ -207,15 +222,16 @@ java_objectheader *javastring_new_from_utf_buffer(const char *buffer, u4 blength
 
 *******************************************************************************/
 
-java_objectheader *javastring_safe_new_from_utf8(const char *text)
+java_handle_t *javastring_safe_new_from_utf8(const char *text)
 {
-       java_objectheader *o;
-       java_chararray    *a;
-       java_lang_String  *s;
+       java_handle_t           *o;
+       java_handle_chararray_t *a;
+       java_lang_String        *s;
        s4 nbytes;
        s4 len;
 
-       assert(text);
+       if (text == NULL)
+               return NULL;
 
        /* Get number of bytes. We need this to completely emulate the messy */
        /* behaviour of the RI. :(                                           */
@@ -238,15 +254,15 @@ java_objectheader *javastring_safe_new_from_utf8(const char *text)
 
        /* decompress UTF-8 string */
 
-       utf8_safe_convert_to_u2s(text, nbytes, a->data);
+       utf8_safe_convert_to_u2s(text, nbytes, LLNI_array_data(a));
 
        /* set fields of the String object */
 
        s = (java_lang_String *) o;
 
-       s->value  = a;
-       s->offset = 0;
-       s->count  = len;
+       LLNI_field_set_ref(s, value , a);
+       LLNI_field_set_val(s, offset, 0);
+       LLNI_field_set_val(s, count , len);
 
        return o;
 }
@@ -267,7 +283,7 @@ java_objectheader *javastring_safe_new_from_utf8(const char *text)
 
 *******************************************************************************/
 
-java_objectheader *javastring_new_from_utf_string(const char *utfstr)
+java_handle_t *javastring_new_from_utf_string(const char *utfstr)
 {
        assert(utfstr);
 
@@ -284,13 +300,13 @@ java_objectheader *javastring_new_from_utf_string(const char *utfstr)
 
 *******************************************************************************/
 
-java_objectheader *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_objectheader *o;
-       java_chararray    *a;
-       java_lang_String  *s;
+       java_handle_t           *o;
+       java_handle_chararray_t *a;
+       java_lang_String        *s;
        s4 i;
 
        if (u == NULL) {
@@ -312,15 +328,15 @@ java_objectheader *javastring_new(utf *u)
        /* 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 = (java_lang_String *) o;
 
-       s->value  = a;
-       s->offset = 0;
-       s->count  = utflength;
+       LLNI_field_set_ref(s, value , a);
+       LLNI_field_set_val(s, offset, 0);
+       LLNI_field_set_val(s, count , utflength);
 
        return o;
 }
@@ -335,13 +351,13 @@ java_objectheader *javastring_new(utf *u)
 
 *******************************************************************************/
 
-java_objectheader *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_objectheader *o;
-       java_chararray    *a;
-       java_lang_String  *s;
+       java_handle_t           *o;
+       java_handle_chararray_t *a;
+       java_lang_String        *s;
        s4 i;
        u2 ch;
 
@@ -366,16 +382,16 @@ java_objectheader *javastring_new_slash_to_dot(utf *u)
                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 = (java_lang_String *) o;
 
-       s->value  = a;
-       s->offset = 0;
-       s->count  = utflength;
+       LLNI_field_set_ref(s, value , a);
+       LLNI_field_set_val(s, offset, 0);
+       LLNI_field_set_val(s, count , utflength);
 
        return o;
 }
@@ -395,13 +411,13 @@ java_objectheader *javastring_new_slash_to_dot(utf *u)
 
 *******************************************************************************/
 
-java_objectheader *javastring_new_from_ascii(const char *text)
+java_handle_t *javastring_new_from_ascii(const char *text)
 {
        s4 i;
        s4 len;                             /* length of the string               */
-       java_objectheader *o;
-       java_lang_String  *s;
-       java_chararray    *a;
+       java_handle_t           *o;
+       java_lang_String        *s;
+       java_handle_chararray_t *a;
 
        if (text == NULL) {
                exceptions_throw_nullpointerexception();
@@ -421,15 +437,15 @@ java_objectheader *javastring_new_from_ascii(const char *text)
        /* 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 = (java_lang_String *) o;
 
-       s->value  = a;
-       s->offset = 0;
-       s->count  = len;
+       LLNI_field_set_ref(s, value , a);
+       LLNI_field_set_val(s, offset, 0);
+       LLNI_field_set_val(s, count , len);
 
        return o;
 }
@@ -445,25 +461,30 @@ java_objectheader *javastring_new_from_ascii(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;
+       int32_t                  count;
+       int32_t                  offset;
        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);
+       LLNI_field_get_val(s, count, count);
+       LLNI_field_get_val(s, offset, offset);
 
-       for (i = 0; i < s->count; i++)
-               buf[i] = a->data[s->offset + i];
+       buf = MNEW(char, count + 1);
+
+       for (i = 0; i < count; i++)
+               buf[i] = LLNI_array_direct(a, offset + i);
 
        buf[i] = '\0';
 
@@ -477,34 +498,45 @@ char *javastring_tochar(java_objectheader *so)
 
 *******************************************************************************/
 
-utf *javastring_toutf(java_objectheader *string, bool isclassname)
+utf *javastring_toutf(java_handle_t *string, bool isclassname)
 {
-       java_lang_String *s;
+       java_lang_String        *s;
+       java_handle_chararray_t *value;
+       int32_t                  count;
+       int32_t                  offset;
 
        s = (java_lang_String *) string;
 
        if (s == NULL)
                return utf_null;
 
-       return utf_new_u2(s->value->data + s->offset, s->count, isclassname);
+       LLNI_field_get_ref(s, value, value);
+
+       if (value == NULL)
+               return utf_null;
+
+       LLNI_field_get_val(s, count, count);
+       LLNI_field_get_val(s, offset, offset);
+
+       return utf_new_u2(LLNI_array_data(value) + offset, count, isclassname);
 }
 
 
 /* literalstring_u2 ************************************************************
 
-   Searches for the javastring with the specified u2-array in the
+   Searches for the literalstring with the specified u2-array in the
    string hashtable, if there is no such string a new one is created.
 
    If copymode is true a copy of the u2-array is made.
 
 *******************************************************************************/
 
-java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
-                                                                       bool copymode)
+static 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                   */
+    heapstring_t     *js;               /* u2-array wrapped in javastring     */
+    java_chararray_t *ca;               /* copy of u2-array                   */
     u4                key;
     u4                slot;
     u2                i;
@@ -518,7 +550,7 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
     s    = hashtable_string.ptr[slot];
 
     while (s) {
-               js = (java_lang_String *) s->string;
+               js = (heapstring_t *) s->string;
 
                if (length == js->count) {
                        /* compare text */
@@ -530,11 +562,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);
 
                        LOCK_MONITOR_EXIT(lock_hashtable_string);
 
-                       return (java_objectheader *) js;
+                       return (java_object_t *) js;
                }
 
        nomatch:
@@ -544,37 +576,32 @@ 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;
+    ca->header.objheader.vftbl =
+               Primitive_get_arrayclass_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_add_first(&unlinkedclasses, class_java_lang_String);
-
        /* create new javastring */
 
-       js = NEW(java_lang_String);
+       js = NEW(heapstring_t);
 
 #if defined(ENABLE_STATISTICS)
        if (opt_stat)
-               size_string += sizeof(java_lang_String);
+               size_string += sizeof(heapstring_t);
 #endif
 
 #if defined(ENABLE_THREADS)
@@ -582,7 +609,7 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
 #endif
 
        js->header.vftbl = class_java_lang_String->vftbl;
-       js->value  = stringdata;
+       js->value  = ca;
        js->offset = 0;
        js->count  = length;
 
@@ -596,7 +623,7 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
 #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 */
@@ -609,11 +636,11 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
                /* reorganization of hashtable, average length of the external
                   chains is approx. 2 */
 
-               u4                i;
-               literalstring    *s;
-               literalstring    *nexts;
-               java_lang_String *tmpjs;
-               hashtable         newhash;                       /* the new hashtable */
+               u4             i;
+               literalstring *s;
+               literalstring *nexts;
+               heapstring_t  *tmpjs;
+               hashtable      newhash;                          /* the new hashtable */
       
                /* create new hashtable, double the size */
 
@@ -627,7 +654,7 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
 
                        while (s) {
                                nexts = s->hashlink;
-                               tmpjs = (java_lang_String *) s->string;
+                               tmpjs = (heapstring_t *) s->string;
                                slot  = unicode_hashkey(tmpjs->value->data, tmpjs->count) & (newhash.size - 1);
          
                                s->hashlink = newhash.ptr[slot];
@@ -646,30 +673,30 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
 
        LOCK_MONITOR_EXIT(lock_hashtable_string);
 
-       return (java_objectheader *) js;
+       return (java_object_t *) js;
 }
 
 
 /* literalstring_new ***********************************************************
 
-   Creates a new javastring with the text of the utf-symbol and inserts it into
-   the string hashtable.
+   Creates a new literalstring with the text of the utf-symbol and inserts
+   it into the string hashtable.
 
 *******************************************************************************/
 
-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++)
@@ -681,23 +708,85 @@ java_objectheader *literalstring_new(utf *u)
 
 /* literalstring_free **********************************************************
 
-   Removes a javastring from memory.
+   Removes a literalstring from memory.
 
 *******************************************************************************/
 
-void literalstring_free(java_objectheader* string)
+#if 0
+/* TWISTI This one is currently not used. */
+
+static void literalstring_free(java_object_t* string)
 {
-       java_lang_String *s;
-       java_chararray *a;
+       heapstring_t     *s;
+       java_chararray_t *a;
 
-       s = (java_lang_String *) string;
+       s = (heapstring_t *) string;
        a = s->value;
 
        /* dispose memory of java.lang.String object */
-       FREE(s, java_lang_String);
+       FREE(s, heapstring_t);
 
        /* 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 ?? */
+}
+#endif
+
+
+/* javastring_intern ***********************************************************
+
+   Intern the given Java string.
+
+   XXX NOTE: Literal Strings are direct references since they are not placed
+   onto the GC-Heap. That's why this function looks so "different".
+
+*******************************************************************************/
+
+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; /* XXX see note above */
+
+       so = (java_lang_String *) s;
+
+       value  = LLNI_field_direct(so, value); /* XXX see note above */
+       LLNI_field_get_val(so, count, count);
+       LLNI_field_get_val(so, offset, offset);
+
+       o = literalstring_u2(value, count, offset, true);
+
+       return LLNI_WRAP(o); /* XXX see note above */
+}
+
+
+/* javastring_fprint ***********************************************************
+
+   Print the given Java string to the given stream.
+
+*******************************************************************************/
+
+void javastring_fprint(java_handle_t *s, FILE *stream)
+{
+       java_lang_String        *so;
+       java_handle_chararray_t *value;
+       int32_t                  count;
+       int32_t                  offset;
+       uint16_t                 c;
+       int                      i;
+
+       so = (java_lang_String *) s;
+
+       LLNI_field_get_ref(so, value, value);
+       LLNI_field_get_val(so, count, count);
+       LLNI_field_get_val(so, offset, offset);
+
+       for (i = offset; i < offset + count; i++) {
+               c = LLNI_array_direct(value, i);
+               fputc(c, stream);
+       }
 }