Fix LDC, LDC_W, and INSTANCEOF opcodes, more debugging
[jamvm-avr32-jem.git] / src / string.c
blob85cc66c1fa7ed5effdfc6d44936362b112bfd29e
1 /*
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007
3 * Robert Lougher <rob@lougher.org.uk>.
5 * This file is part of JamVM.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include "jam.h"
26 #include "hash.h"
28 #define HASHTABSZE 1<<10
29 #define HASH(ptr) stringHash(ptr)
30 #define COMPARE(ptr1, ptr2, hash1, hash2) (ptr1 == ptr2) || \
31 ((hash1 == hash2) && stringComp(ptr1, ptr2))
32 #define PREPARE(ptr) ptr
33 #define SCAVENGE(ptr) FALSE
34 #define FOUND(ptr) ptr
36 static Class *string_class;
37 static int count_offset;
38 static int value_offset;
39 static int offset_offset;
41 static HashTable hash_table;
43 static int inited = FALSE;
45 int stringHash(Object *ptr) {
46 #if JAM_ON_STACK
47 Object *array = (Object*)INST_DATA(ptr)[value_offset];
48 #else
49 Object *array = JAM_ARRAY((uintptr_t *)INST_DATA(ptr)[value_offset]);
50 #endif
51 int len = INST_DATA(ptr)[count_offset];
52 int offset = INST_DATA(ptr)[offset_offset];
53 unsigned short *dpntr = ((unsigned short *)ARRAY_DATA(array))+offset;
54 int hash = 0;
56 for(; len > 0; len--)
57 hash = hash * 37 + *dpntr++;
59 return hash;
62 int stringComp(Object *ptr, Object *ptr2) {
63 int len = INST_DATA(ptr)[count_offset];
64 int len2 = INST_DATA(ptr2)[count_offset];
66 if(len == len2) {
67 #if JAM_ON_STACK
68 Object *array = (Object*)INST_DATA(ptr)[value_offset];
69 Object *array2 = (Object*)INST_DATA(ptr2)[value_offset];
70 #else
71 Object *array = JAM_ARRAY((uintptr_t *)INST_DATA(ptr)[value_offset]);
72 Object *array2 = JAM_ARRAY((uintptr_t *)INST_DATA(ptr2)[value_offset]);
73 #endif
74 int offset = INST_DATA(ptr)[offset_offset];
75 int offset2 = INST_DATA(ptr2)[offset_offset];
76 unsigned short *src = ((unsigned short *)ARRAY_DATA(array))+offset;
77 unsigned short *dst = ((unsigned short *)ARRAY_DATA(array2))+offset2;
79 for(; (len > 0) && (*src++ == *dst++); len--);
81 if(len == 0)
82 return TRUE;
85 return FALSE;
88 Object *createString(char *utf8) {
89 int len = utf8Len(utf8);
90 unsigned short *data;
91 Object *array;
92 Object *ob;
94 if(!inited)
95 initialiseString();
97 if((array = allocTypeArray(T_CHAR, len)) == NULL ||
98 (ob = allocObject(string_class)) == NULL)
99 return NULL;
101 data = ARRAY_DATA(array);
102 convertUtf8(utf8, data);
104 INST_DATA(ob)[count_offset] = len;
105 #if JAM_ON_STACK
106 INST_DATA(ob)[value_offset] = (uintptr_t)array;
107 #else
108 INST_DATA(ob)[value_offset] = (uintptr_t)ARRAY_DATA(array);
109 #endif
111 return ob;
114 Object *findInternedString(Object *string) {
115 Object *interned;
117 /* Add if absent, no scavenge, locked */
118 findHashEntry(hash_table, string, interned, TRUE, FALSE, TRUE);
120 return interned;
123 #define ITERATE(ptr) \
124 if(!isMarked(*ptr)) { \
125 *ptr = NULL; \
126 unmarked++; \
129 void freeInternedStrings() {
130 int unmarked = 0;
132 hashIterateP(hash_table);
134 if(unmarked) {
135 int size;
137 /* Update count to remaining number of strings */
138 hash_table.hash_count -= unmarked;
140 /* Calculate nearest multiple of 2 larger than count */
141 for(size = 1; size < hash_table.hash_count; size <<= 1);
143 /* Ensure new table is less than 2/3 full */
144 size = hash_table.hash_count*3 > size*2 ? size<< 1 : size;
146 resizeHash(&hash_table, size);
150 #undef ITERATE
151 #define ITERATE(ptr) threadReference((Object**)ptr);
153 void threadInternedStrings() {
154 hashIterateP(hash_table);
157 char *String2Buff0(Object *string, char *buff, int len) {
158 int offset = INST_DATA(string)[offset_offset];
159 #if JAM_ON_STACK
160 Object *array = (Object *)(INST_DATA(string)[value_offset]);
161 #else
162 Object *array = JAM_ARRAY((uintptr_t *)(INST_DATA(string)[value_offset]));
163 #endif
164 unsigned short *str = ((unsigned short *)ARRAY_DATA(array))+offset;
165 char *pntr;
167 for(pntr = buff; len > 0; len--)
168 *pntr++ = *str++;
170 *pntr = '\0';
171 return buff;
174 char *String2Buff(Object *string, char *buff, int buff_len) {
175 int str_len = INST_DATA(string)[count_offset];
176 int len = buff_len-1 < str_len ? buff_len-1 : str_len;
178 return String2Buff0(string, buff, len);
181 char *String2Cstr(Object *string) {
182 int len = INST_DATA(string)[count_offset];
183 char *buff = (char *)sysMalloc(len + 1);
185 return String2Buff0(string, buff, len);
188 void initialiseString() {
189 if(!inited) {
190 FieldBlock *count, *value, *offset;
192 /* As we're initialising, VM will abort if String can't be found */
193 string_class = findSystemClass0("java/lang/String");
194 registerStaticClassRef(&string_class);
196 count = findField(string_class, "count", "I");
197 value = findField(string_class, "value", "[C");
198 offset = findField(string_class, "offset", "I");
200 /* findField doesn't throw an exception... */
201 if((count == NULL) || (value == NULL) || (offset == NULL)) {
202 jam_fprintf(stderr, "Error initialising VM (initialiseString)\n");
203 exitVM(1);
206 count_offset = count->offset;
207 value_offset = value->offset;
208 offset_offset = offset->offset;
210 /* Init hash table and create lock */
211 initHashTable(hash_table, HASHTABSZE, TRUE);
212 inited = TRUE;
216 #ifndef NO_JNI
217 /* Functions used by JNI */
219 Object *createStringFromUnicode(unsigned short *unicode, int len) {
220 Object *array = allocTypeArray(T_CHAR, len);
221 Object *ob = allocObject(string_class);
223 if(array != NULL && ob != NULL) {
224 unsigned short *data = ARRAY_DATA(array);
225 memcpy(data, unicode, len*sizeof(unsigned short));
227 INST_DATA(ob)[count_offset] = len;
228 #if JAM_ON_STACK
229 INST_DATA(ob)[value_offset] = (uintptr_t)array;
230 #else
231 INST_DATA(ob)[value_offset] = (uintptr_t)ARRAY_DATA(array);
232 #endif
233 return ob;
235 return NULL;
238 Object *getStringCharsArray(Object *string) {
239 #if JAM_ON_STACK
240 return (Object*)INST_DATA(string)[value_offset];
241 #else
242 return JAM_ARRAY((uintptr_t *)INST_DATA(string)[value_offset]);
243 #endif
246 unsigned short *getStringChars(Object *string) {
247 #if JAM_ON_STACK
248 Object *array = (Object*)INST_DATA(string)[value_offset];
249 #else
250 Object *array = JAM_ARRAY((uintptr_t *)INST_DATA(string)[value_offset]);
251 #endif
252 int offset = INST_DATA(string)[offset_offset];
253 return ((unsigned short*)ARRAY_DATA(array))+offset;
256 int getStringLen(Object *string) {
257 return INST_DATA(string)[count_offset];
260 int getStringUtf8Len(Object *string) {
261 return utf8CharLen(getStringChars(string), getStringLen(string));
264 char *StringRegion2Utf8(Object *string, int start, int len, char *utf8) {
265 return unicode2Utf8(getStringChars(string) + start, len, utf8);
268 char *String2Utf8(Object *string) {
269 int len = getStringLen(string);
270 unsigned short *unicode = getStringChars(string);
271 char *utf8 = (char*)sysMalloc(utf8CharLen(unicode, len) + 1);
273 return unicode2Utf8(unicode, len, utf8);
275 #endif