2 * Copyright (C) 2008 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
24 * Prep string interning.
26 bool dvmStringInternStartup(void)
28 dvmInitMutex(&gDvm.internLock);
29 gDvm.internedStrings = dvmHashTableCreate(256, NULL);
30 if (gDvm.internedStrings == NULL)
32 gDvm.literalStrings = dvmHashTableCreate(256, NULL);
33 if (gDvm.literalStrings == NULL)
39 * Chuck the intern list.
41 * The contents of the list are StringObjects that live on the GC heap.
43 void dvmStringInternShutdown(void)
45 if (gDvm.internedStrings != NULL || gDvm.literalStrings != NULL) {
46 dvmDestroyMutex(&gDvm.internLock);
48 dvmHashTableFree(gDvm.internedStrings);
49 gDvm.internedStrings = NULL;
50 dvmHashTableFree(gDvm.literalStrings);
51 gDvm.literalStrings = NULL;
54 static StringObject* lookupInternedString(StringObject* strObj, bool isLiteral)
59 assert(strObj != NULL);
60 hash = dvmComputeStringHash(strObj);
61 dvmLockMutex(&gDvm.internLock);
64 * Check the literal table for a match.
66 StringObject* literal = dvmHashTableLookup(gDvm.literalStrings,
70 if (literal != NULL) {
72 * A match was found in the literal table, the easy case.
77 * There is no match in the literal table, check the
78 * interned string table.
80 StringObject* interned = dvmHashTableLookup(gDvm.internedStrings,
84 if (interned != NULL) {
86 * A match was found in the interned table. Move the
87 * matching string to the literal table.
89 dvmHashTableRemove(gDvm.internedStrings, hash, interned);
90 found = dvmHashTableLookup(gDvm.literalStrings,
94 assert(found == interned);
97 * No match in the literal table or the interned
98 * table. Insert into the literal table.
100 found = dvmHashTableLookup(gDvm.literalStrings,
104 assert(found == strObj);
109 * Check the literal table for a match.
111 found = dvmHashTableLookup(gDvm.literalStrings,
117 * No match was found in the literal table. Insert into
120 found = dvmHashTableLookup(gDvm.internedStrings,
126 assert(found != NULL);
127 dvmUnlockMutex(&gDvm.internLock);
132 * Find an entry in the interned string table.
134 * If the string doesn't already exist, the StringObject is added to
135 * the table. Otherwise, the existing entry is returned.
137 StringObject* dvmLookupInternedString(StringObject* strObj)
139 return lookupInternedString(strObj, false);
143 * Same as dvmLookupInternedString(), but guarantees that the
144 * returned string is a literal.
146 StringObject* dvmLookupImmortalInternedString(StringObject* strObj)
148 return lookupInternedString(strObj, true);
152 * Returns true if the object is a weak interned string. Any string
153 * interned by the user is weak.
155 bool dvmIsWeakInternedString(const StringObject* strObj)
160 assert(strObj != NULL);
161 if (gDvm.internedStrings == NULL) {
164 dvmLockMutex(&gDvm.internLock);
165 hash = dvmComputeStringHash(strObj);
166 found = dvmHashTableLookup(gDvm.internedStrings, hash, (void*)strObj,
167 dvmHashcmpStrings, false);
168 dvmUnlockMutex(&gDvm.internLock);
169 return found == strObj;
172 static int markStringObject(void* strObj, void* arg)
174 UNUSED_PARAMETER(arg);
175 dvmMarkObjectNonNull(strObj);
180 * Blacken string references from the literal string table. The
181 * literal table is a root.
183 void dvmGcScanInternedStrings()
185 /* It's possible for a GC to happen before dvmStringInternStartup()
188 if (gDvm.literalStrings != NULL) {
189 dvmHashForeach(gDvm.literalStrings, markStringObject, NULL);
194 * Clear white references from the intern table.
196 void dvmGcDetachDeadInternedStrings(int (*isUnmarkedObject)(void *))
198 /* It's possible for a GC to happen before dvmStringInternStartup()
201 if (gDvm.internedStrings != NULL) {
202 dvmLockMutex(&gDvm.internLock);
203 dvmHashForeachRemove(gDvm.internedStrings, isUnmarkedObject);
204 dvmUnlockMutex(&gDvm.internLock);