summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarl Shapiro <cshapiro@google.com>2011-05-05 16:01:26 -0700
committerCarl Shapiro <cshapiro@google.com>2011-05-05 17:33:58 -0700
commitdc9e44cc0af797679822484d88ef76bff15ffc98 (patch)
tree7b600921d5421d76a903eab561c0cf36c23f9c06
parent38e191b85851e8ff3126ce680c615a189558e5ff (diff)
downloadandroid_dalvik-dc9e44cc0af797679822484d88ef76bff15ffc98.tar.gz
android_dalvik-dc9e44cc0af797679822484d88ef76bff15ffc98.tar.bz2
android_dalvik-dc9e44cc0af797679822484d88ef76bff15ffc98.zip
Make interned strings non-movable.
At present objects referenced from dex files must have stable reference values. With this change, only non-moving strings are interned. If a user interns a movable string a non-moving copy is made and the copy is added to the intern table. As part of this change, the internal string hash code access routine will update the hash code slot of a string object. In addition, StringObject has been made a subclass of Object eliminating various down-casts that would otherwise be explicitly required. Change-Id: I6b015b972aac44948470c0034ad17e5eef456aeb
-rw-r--r--vm/Intern.cpp65
-rw-r--r--vm/Intern.h2
-rw-r--r--vm/UtfString.cpp16
-rw-r--r--vm/UtfString.h5
-rw-r--r--vm/alloc/Alloc.cpp5
-rw-r--r--vm/alloc/Alloc.h2
-rw-r--r--vm/oo/Object.h4
-rw-r--r--vm/reflect/Annotation.cpp2
8 files changed, 53 insertions, 48 deletions
diff --git a/vm/Intern.cpp b/vm/Intern.cpp
index 8215107ba..9faca45e0 100644
--- a/vm/Intern.cpp
+++ b/vm/Intern.cpp
@@ -51,22 +51,36 @@ void dvmStringInternShutdown()
gDvm.literalStrings = NULL;
}
+static StringObject* lookupString(HashTable* table, u4 key, StringObject* value)
+{
+ void* entry = dvmHashTableLookup(table, key, (void*)value,
+ dvmHashcmpStrings, false);
+ return (StringObject*)entry;
+}
+
+static StringObject* insertString(HashTable* table, u4 key, StringObject* value)
+{
+ if (dvmIsNonMovingObject(value) == false) {
+ value = (StringObject*)dvmCloneObject(value, ALLOC_NON_MOVING);
+ }
+ void* entry = dvmHashTableLookup(table, key, (void*)value,
+ dvmHashcmpStrings, true);
+ assert(entry == value);
+ return (StringObject*)entry;
+}
+
static StringObject* lookupInternedString(StringObject* strObj, bool isLiteral)
{
StringObject* found;
- u4 hash;
assert(strObj != NULL);
- hash = dvmComputeStringHash(strObj);
+ u4 key = dvmComputeStringHash(strObj);
dvmLockMutex(&gDvm.internLock);
if (isLiteral) {
/*
* Check the literal table for a match.
*/
- StringObject* literal = (StringObject*)dvmHashTableLookup(gDvm.literalStrings,
- hash, strObj,
- dvmHashcmpStrings,
- false);
+ StringObject* literal = lookupString(gDvm.literalStrings, key, strObj);
if (literal != NULL) {
/*
* A match was found in the literal table, the easy case.
@@ -77,50 +91,33 @@ static StringObject* lookupInternedString(StringObject* strObj, bool isLiteral)
* There is no match in the literal table, check the
* interned string table.
*/
- StringObject* interned = (StringObject*)dvmHashTableLookup(gDvm.internedStrings,
- hash, strObj,
- dvmHashcmpStrings,
- false);
+ StringObject* interned = lookupString(gDvm.internedStrings, key, strObj);
if (interned != NULL) {
/*
* A match was found in the interned table. Move the
* matching string to the literal table.
*/
- dvmHashTableRemove(gDvm.internedStrings, hash, interned);
- found = (StringObject*)dvmHashTableLookup(gDvm.literalStrings,
- hash, interned,
- dvmHashcmpStrings,
- true);
- assert(found == interned);
+ dvmHashTableRemove(gDvm.internedStrings, key, interned);
+ found = insertString(gDvm.literalStrings, key, interned);
} else {
/*
* No match in the literal table or the interned
* table. Insert into the literal table.
*/
- found = (StringObject*)dvmHashTableLookup(gDvm.literalStrings,
- hash, strObj,
- dvmHashcmpStrings,
- true);
- assert(found == strObj);
+ found = insertString(gDvm.literalStrings, key, strObj);
}
}
} else {
/*
* Check the literal table for a match.
*/
- found = (StringObject*)dvmHashTableLookup(gDvm.literalStrings,
- hash, strObj,
- dvmHashcmpStrings,
- false);
+ found = lookupString(gDvm.literalStrings, key, strObj);
if (found == NULL) {
/*
* No match was found in the literal table. Insert into
* the intern table.
*/
- found = (StringObject*)dvmHashTableLookup(gDvm.internedStrings,
- hash, strObj,
- dvmHashcmpStrings,
- true);
+ found = insertString(gDvm.internedStrings, key, strObj);
}
}
assert(found != NULL);
@@ -152,19 +149,15 @@ StringObject* dvmLookupImmortalInternedString(StringObject* strObj)
* Returns true if the object is a weak interned string. Any string
* interned by the user is weak.
*/
-bool dvmIsWeakInternedString(const StringObject* strObj)
+bool dvmIsWeakInternedString(StringObject* strObj)
{
- StringObject* found;
- u4 hash;
-
assert(strObj != NULL);
if (gDvm.internedStrings == NULL) {
return false;
}
dvmLockMutex(&gDvm.internLock);
- hash = dvmComputeStringHash(strObj);
- found = (StringObject*)dvmHashTableLookup(gDvm.internedStrings, hash,
- (StringObject*)strObj, dvmHashcmpStrings, false);
+ u4 key = dvmComputeStringHash(strObj);
+ StringObject* found = lookupString(gDvm.internedStrings, key, strObj);
dvmUnlockMutex(&gDvm.internLock);
return found == strObj;
}
diff --git a/vm/Intern.h b/vm/Intern.h
index 6630b69f3..207a038df 100644
--- a/vm/Intern.h
+++ b/vm/Intern.h
@@ -23,7 +23,7 @@ bool dvmStringInternStartup(void);
void dvmStringInternShutdown(void);
StringObject* dvmLookupInternedString(StringObject* strObj);
StringObject* dvmLookupImmortalInternedString(StringObject* strObj);
-bool dvmIsWeakInternedString(const StringObject* strObj);
+bool dvmIsWeakInternedString(StringObject* strObj);
void dvmGcDetachDeadInternedStrings(int (*isUnmarkedObject)(void *));
#endif /*_DALVIK_INTERN*/
diff --git a/vm/UtfString.cpp b/vm/UtfString.cpp
index 17ce40ad5..0b7e4a091 100644
--- a/vm/UtfString.cpp
+++ b/vm/UtfString.cpp
@@ -204,12 +204,18 @@ static inline u4 computeUtf16Hash(const u2* utf16Str, size_t len)
return hash;
}
-u4 dvmComputeStringHash(const StringObject* strObj) {
- const ArrayObject* chars = (ArrayObject*) dvmGetFieldObject((Object*) strObj,
+u4 dvmComputeStringHash(StringObject* strObj) {
+ int hashCode = dvmGetFieldInt(strObj, STRING_FIELDOFF_HASHCODE);
+ if (hashCode != 0) {
+ return hashCode;
+ }
+ int len = dvmGetFieldInt(strObj, STRING_FIELDOFF_COUNT);
+ int offset = dvmGetFieldInt(strObj, STRING_FIELDOFF_OFFSET);
+ ArrayObject* chars = (ArrayObject*) dvmGetFieldObject(strObj,
STRING_FIELDOFF_VALUE);
- int len = dvmGetFieldInt((Object*) strObj, STRING_FIELDOFF_COUNT);
- int offset = dvmGetFieldInt((Object*) strObj, STRING_FIELDOFF_OFFSET);
- return computeUtf16Hash((u2*)(void*)chars->contents + offset, len);
+ hashCode = computeUtf16Hash((u2*)(void*)chars->contents + offset, len);
+ dvmSetFieldInt(strObj, STRING_FIELDOFF_HASHCODE, hashCode);
+ return hashCode;
}
/*
diff --git a/vm/UtfString.h b/vm/UtfString.h
index b577d3a59..488ba9b8a 100644
--- a/vm/UtfString.h
+++ b/vm/UtfString.h
@@ -51,9 +51,10 @@
u4 dvmComputeUtf8Hash(const char* str);
/*
- * Hash function for string objects.
+ * Hash function for string objects. Ensures the hash code field is
+ * populated and returns its value.
*/
-u4 dvmComputeStringHash(const StringObject* strObj);
+u4 dvmComputeStringHash(StringObject* strObj);
/*
* Create a java.lang.String[] from an array of C strings.
diff --git a/vm/alloc/Alloc.cpp b/vm/alloc/Alloc.cpp
index a77c770bc..0fe22eaec 100644
--- a/vm/alloc/Alloc.cpp
+++ b/vm/alloc/Alloc.cpp
@@ -366,3 +366,8 @@ bool dvmIsHeapAddress(void *address)
{
return dvmHeapSourceContainsAddress(address);
}
+
+bool dvmIsNonMovingObject(const Object* object)
+{
+ return true;
+}
diff --git a/vm/alloc/Alloc.h b/vm/alloc/Alloc.h
index c215fc2b3..41a346651 100644
--- a/vm/alloc/Alloc.h
+++ b/vm/alloc/Alloc.h
@@ -144,4 +144,6 @@ void dvmClearGrowthLimit(void);
*/
bool dvmIsHeapAddress(void *address);
+bool dvmIsNonMovingObject(const Object* object);
+
#endif /*_DALVIK_ALLOC_ALLOC*/
diff --git a/vm/oo/Object.h b/vm/oo/Object.h
index c647a905a..0b4d740e4 100644
--- a/vm/oo/Object.h
+++ b/vm/oo/Object.h
@@ -242,9 +242,7 @@ struct DataObject : Object {
* Currently this is just equal to DataObject, and we pull the fields out
* like we do for any other object.
*/
-struct StringObject {
- Object obj; /* MUST be first item */
-
+struct StringObject : Object {
/* variable #of u4 slots; u8 uses 2 slots */
u4 instanceData[1];
};
diff --git a/vm/reflect/Annotation.cpp b/vm/reflect/Annotation.cpp
index 6b33af369..f01591031 100644
--- a/vm/reflect/Annotation.cpp
+++ b/vm/reflect/Annotation.cpp
@@ -1490,7 +1490,7 @@ bool dvmGetInnerClass(const ClassObject* clazz, StringObject** pName,
}
*pName = (StringObject*) avalue.value.l;
- assert(*pName == NULL || (*pName)->obj.clazz == gDvm.classJavaLangString);
+ assert(*pName == NULL || (*pName)->clazz == gDvm.classJavaLangString);
ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "accessFlags");
if (ptr == NULL) {