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.
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
) {
47 Object
*array
= (Object
*)INST_DATA(ptr
)[value_offset
];
49 Object
*array
= JAM_ARRAY((uintptr_t *)INST_DATA(ptr
)[value_offset
]);
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
;
57 hash
= hash
* 37 + *dpntr
++;
62 int stringComp(Object
*ptr
, Object
*ptr2
) {
63 int len
= INST_DATA(ptr
)[count_offset
];
64 int len2
= INST_DATA(ptr2
)[count_offset
];
68 Object
*array
= (Object
*)INST_DATA(ptr
)[value_offset
];
69 Object
*array2
= (Object
*)INST_DATA(ptr2
)[value_offset
];
71 Object
*array
= JAM_ARRAY((uintptr_t *)INST_DATA(ptr
)[value_offset
]);
72 Object
*array2
= JAM_ARRAY((uintptr_t *)INST_DATA(ptr2
)[value_offset
]);
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
--);
88 Object
*createString(char *utf8
) {
89 int len
= utf8Len(utf8
);
97 if((array
= allocTypeArray(T_CHAR
, len
)) == NULL
||
98 (ob
= allocObject(string_class
)) == NULL
)
101 data
= ARRAY_DATA(array
);
102 convertUtf8(utf8
, data
);
104 INST_DATA(ob
)[count_offset
] = len
;
106 INST_DATA(ob
)[value_offset
] = (uintptr_t)array
;
108 INST_DATA(ob
)[value_offset
] = (uintptr_t)ARRAY_DATA(array
);
114 Object
*findInternedString(Object
*string
) {
117 /* Add if absent, no scavenge, locked */
118 findHashEntry(hash_table
, string
, interned
, TRUE
, FALSE
, TRUE
);
123 #define ITERATE(ptr) \
124 if(!isMarked(*ptr)) { \
129 void freeInternedStrings() {
132 hashIterateP(hash_table
);
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
);
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
];
160 Object
*array
= (Object
*)(INST_DATA(string
)[value_offset
]);
162 Object
*array
= JAM_ARRAY((uintptr_t *)(INST_DATA(string
)[value_offset
]));
164 unsigned short *str
= ((unsigned short *)ARRAY_DATA(array
))+offset
;
167 for(pntr
= buff
; len
> 0; len
--)
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() {
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");
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
);
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
;
229 INST_DATA(ob
)[value_offset
] = (uintptr_t)array
;
231 INST_DATA(ob
)[value_offset
] = (uintptr_t)ARRAY_DATA(array
);
238 Object
*getStringCharsArray(Object
*string
) {
240 return (Object
*)INST_DATA(string
)[value_offset
];
242 return JAM_ARRAY((uintptr_t *)INST_DATA(string
)[value_offset
]);
246 unsigned short *getStringChars(Object
*string
) {
248 Object
*array
= (Object
*)INST_DATA(string
)[value_offset
];
250 Object
*array
= JAM_ARRAY((uintptr_t *)INST_DATA(string
)[value_offset
]);
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
);