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()
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()
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* lookupString(HashTable* table, u4 key, StringObject* value)
56 void* entry = dvmHashTableLookup(table, key, (void*)value,
57 dvmHashcmpStrings, false);
58 return (StringObject*)entry;
61 static StringObject* insertString(HashTable* table, u4 key, StringObject* value)
63 if (dvmIsNonMovingObject(value) == false) {
64 value = (StringObject*)dvmCloneObject(value, ALLOC_NON_MOVING);
66 void* entry = dvmHashTableLookup(table, key, (void*)value,
67 dvmHashcmpStrings, true);
68 return (StringObject*)entry;
71 static StringObject* lookupInternedString(StringObject* strObj, bool isLiteral)
75 assert(strObj != NULL);
76 u4 key = dvmComputeStringHash(strObj);
77 dvmLockMutex(&gDvm.internLock);
80 * Check the literal table for a match.
82 StringObject* literal = lookupString(gDvm.literalStrings, key, strObj);
83 if (literal != NULL) {
85 * A match was found in the literal table, the easy case.
90 * There is no match in the literal table, check the
91 * interned string table.
93 StringObject* interned = lookupString(gDvm.internedStrings, key, strObj);
94 if (interned != NULL) {
96 * A match was found in the interned table. Move the
97 * matching string to the literal table.
99 dvmHashTableRemove(gDvm.internedStrings, key, interned);
100 found = insertString(gDvm.literalStrings, key, interned);
101 assert(found == interned);
104 * No match in the literal table or the interned
105 * table. Insert into the literal table.
107 found = insertString(gDvm.literalStrings, key, strObj);
108 assert(found == strObj);
113 * Check the literal table for a match.
115 found = lookupString(gDvm.literalStrings, key, strObj);
118 * No match was found in the literal table. Insert into
119 * the intern table if it does not already exist.
121 found = insertString(gDvm.internedStrings, key, strObj);
124 assert(found != NULL);
125 dvmUnlockMutex(&gDvm.internLock);
130 * Find an entry in the interned string table.
132 * If the string doesn't already exist, the StringObject is added to
133 * the table. Otherwise, the existing entry is returned.
135 StringObject* dvmLookupInternedString(StringObject* strObj)
137 return lookupInternedString(strObj, false);
141 * Same as dvmLookupInternedString(), but guarantees that the
142 * returned string is a literal.
144 StringObject* dvmLookupImmortalInternedString(StringObject* strObj)
146 return lookupInternedString(strObj, true);
150 * Returns true if the object is a weak interned string. Any string
151 * interned by the user is weak.
153 bool dvmIsWeakInternedString(StringObject* strObj)
155 assert(strObj != NULL);
156 if (gDvm.internedStrings == NULL) {
159 dvmLockMutex(&gDvm.internLock);
160 u4 key = dvmComputeStringHash(strObj);
161 StringObject* found = lookupString(gDvm.internedStrings, key, strObj);
162 dvmUnlockMutex(&gDvm.internLock);
163 return found == strObj;
167 * Clear white references from the intern table.
169 void dvmGcDetachDeadInternedStrings(int (*isUnmarkedObject)(void *))
171 /* It's possible for a GC to happen before dvmStringInternStartup()
174 if (gDvm.internedStrings != NULL) {
175 dvmLockMutex(&gDvm.internLock);
176 dvmHashForeachRemove(gDvm.internedStrings, isUnmarkedObject);
177 dvmUnlockMutex(&gDvm.internLock);