Put wrappers on all stores of Object pointers into heap Objects.
Also:
Changed ++ loops to [i] loops where I'm touching.
Added some asserts.
Added dvmHeapSourceContainsAddress
Added dvmIsValidObjectAddress
Change-Id: I6586688246064aecabb1e22e1dca276fecee7795
diff --git a/vm/Exception.c b/vm/Exception.c
index 3cbd74d..fb3b9f8 100644
--- a/vm/Exception.c
+++ b/vm/Exception.c
@@ -1127,7 +1127,6 @@
ArrayObject* dvmGetStackTraceRaw(const int* intVals, int stackDepth)
{
ArrayObject* steArray = NULL;
- Object** stePtr;
int i;
/* init this if we haven't yet */
@@ -1139,7 +1138,6 @@
stackDepth, kObjectArrayRefWidth, ALLOC_DEFAULT);
if (steArray == NULL)
goto bail;
- stePtr = (Object**) steArray->contents;
/*
* Allocate and initialize a StackTraceElement for each stack frame.
@@ -1196,7 +1194,7 @@
if (dvmCheckException(dvmThreadSelf()))
goto bail;
- *stePtr++ = ste;
+ dvmSetObjectArrayElement(steArray, i, ste);
}
bail:
diff --git a/vm/Jni.c b/vm/Jni.c
index 5beefcf..9973508 100644
--- a/vm/Jni.c
+++ b/vm/Jni.c
@@ -3093,7 +3093,7 @@
//LOGV("JNI: set element %d in array %p to %p\n", index, array, value);
Object* obj = dvmDecodeIndirectRef(env, jobj);
- ((Object**) arrayObj->contents)[index] = obj;
+ dvmSetObjectArrayElement(arrayObj, index, obj);
bail:
JNI_EXIT();
diff --git a/vm/alloc/Alloc.c b/vm/alloc/Alloc.c
index 960ec93..23dc65b 100644
--- a/vm/alloc/Alloc.c
+++ b/vm/alloc/Alloc.c
@@ -227,6 +227,7 @@
memcpy(copy, obj, size);
DVM_LOCK_INIT(©->lock);
+ dvmWriteBarrierObject(copy);
return copy;
}
diff --git a/vm/alloc/Alloc.h b/vm/alloc/Alloc.h
index 7af68f0..1200788 100644
--- a/vm/alloc/Alloc.h
+++ b/vm/alloc/Alloc.h
@@ -91,6 +91,11 @@
bool dvmIsValidObject(const Object* obj);
/*
+ * Returns true iff <ptr> points within allocation-managed address space.
+ */
+bool dvmIsValidObjectAddress(const void *ptr);
+
+/*
* Create a copy of an object.
*
* The new object will be added to the "tracked alloc" table.
diff --git a/vm/alloc/Heap.c b/vm/alloc/Heap.c
index a9c3208..bc852ca 100644
--- a/vm/alloc/Heap.c
+++ b/vm/alloc/Heap.c
@@ -541,6 +541,20 @@
return false;
}
+/*
+ * Returns true iff <obj> points to a word-aligned address within Heap
+ * address space.
+ */
+bool dvmIsValidObjectAddress(const void* ptr)
+{
+ /* Don't bother if it's not 4-byte aligned.
+ */
+ if (((uintptr_t)ptr & (4-1)) == 0) {
+ return dvmHeapSourceContainsAddress(ptr);
+ }
+ return false;
+}
+
size_t dvmObjectSizeInHeap(const Object *obj)
{
return dvmHeapSourceChunkSize(obj);
diff --git a/vm/alloc/HeapSource.c b/vm/alloc/HeapSource.c
index f9234f0..0891506 100644
--- a/vm/alloc/HeapSource.c
+++ b/vm/alloc/HeapSource.c
@@ -924,6 +924,17 @@
}
/*
+ * Returns true iff <ptr> is in the heap source.
+ */
+bool
+dvmHeapSourceContainsAddress(const void *ptr)
+{
+ HS_BOILERPLATE();
+
+ return (dvmHeapBitmapCoversAddress(&gHs->liveBits, ptr));
+}
+
+/*
* Returns true iff <ptr> was allocated from the heap source.
*/
bool
@@ -931,7 +942,7 @@
{
HS_BOILERPLATE();
- if (dvmHeapBitmapCoversAddress(&gHs->liveBits, ptr)) {
+ if (dvmHeapSourceContainsAddress(ptr)) {
return dvmHeapBitmapIsObjectBitSet(&gHs->liveBits, ptr) != 0;
}
return false;
diff --git a/vm/alloc/HeapSource.h b/vm/alloc/HeapSource.h
index 6df3df0..465e7c9 100644
--- a/vm/alloc/HeapSource.h
+++ b/vm/alloc/HeapSource.h
@@ -104,6 +104,11 @@
bool dvmHeapSourceContains(const void *ptr);
/*
+ * Returns true iff <ptr> is within the address space managed by heap source.
+ */
+bool dvmHeapSourceContainsAddress(const void *ptr);
+
+/*
* Returns the value of the requested flag.
*/
enum HeapSourcePtrFlag {
diff --git a/vm/interp/Interp.c b/vm/interp/Interp.c
index dafdbda..da8fa79 100644
--- a/vm/interp/Interp.c
+++ b/vm/interp/Interp.c
@@ -1377,6 +1377,8 @@
}
}
+ /* Never on the heap, so no write barrier needed. */
+ assert(!dvmIsValidObjectAddress(pResult));
*pResult = interpState.retval;
#if defined(WITH_JIT)
dvmJitCalleeRestore(interpState.calleeSave);
diff --git a/vm/mterp/c/OP_APUT_OBJECT.c b/vm/mterp/c/OP_APUT_OBJECT.c
index cc87f5d..07e48c6 100644
--- a/vm/mterp/c/OP_APUT_OBJECT.c
+++ b/vm/mterp/c/OP_APUT_OBJECT.c
@@ -32,8 +32,9 @@
}
}
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));
- ((u4*) arrayObj->contents)[GET_REGISTER(vsrc2)] =
- GET_REGISTER(vdst);
+ dvmSetObjectArrayElement(arrayObj,
+ GET_REGISTER(vsrc2),
+ (Object *)GET_REGISTER(vdst));
}
FINISH(2);
OP_END
diff --git a/vm/mterp/c/gotoTargets.c b/vm/mterp/c/gotoTargets.c
index acbde1c..c6c118b 100644
--- a/vm/mterp/c/gotoTargets.c
+++ b/vm/mterp/c/gotoTargets.c
@@ -94,6 +94,9 @@
vdst >>= 4;
}
}
+ if (typeCh == 'L' || typeCh == '[') {
+ dvmWriteBarrierArray(newArray, 0, newArray->length);
+ }
retval.l = newArray;
}
diff --git a/vm/mterp/out/InterpC-allstubs.c b/vm/mterp/out/InterpC-allstubs.c
index 6a50b64..39cd6ba 100644
--- a/vm/mterp/out/InterpC-allstubs.c
+++ b/vm/mterp/out/InterpC-allstubs.c
@@ -2100,8 +2100,9 @@
}
}
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));
- ((u4*) arrayObj->contents)[GET_REGISTER(vsrc2)] =
- GET_REGISTER(vdst);
+ dvmSetObjectArrayElement(arrayObj,
+ GET_REGISTER(vsrc2),
+ (Object *)GET_REGISTER(vdst));
}
FINISH(2);
OP_END
@@ -3227,6 +3228,9 @@
vdst >>= 4;
}
}
+ if (typeCh == 'L' || typeCh == '[') {
+ dvmWriteBarrierArray(newArray, 0, newArray->length);
+ }
retval.l = newArray;
}
diff --git a/vm/mterp/out/InterpC-portdbg.c b/vm/mterp/out/InterpC-portdbg.c
index 18433f8..9468b24 100644
--- a/vm/mterp/out/InterpC-portdbg.c
+++ b/vm/mterp/out/InterpC-portdbg.c
@@ -2466,8 +2466,9 @@
}
}
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));
- ((u4*) arrayObj->contents)[GET_REGISTER(vsrc2)] =
- GET_REGISTER(vdst);
+ dvmSetObjectArrayElement(arrayObj,
+ GET_REGISTER(vsrc2),
+ (Object *)GET_REGISTER(vdst));
}
FINISH(2);
OP_END
@@ -3511,6 +3512,9 @@
vdst >>= 4;
}
}
+ if (typeCh == 'L' || typeCh == '[') {
+ dvmWriteBarrierArray(newArray, 0, newArray->length);
+ }
retval.l = newArray;
}
diff --git a/vm/mterp/out/InterpC-portstd.c b/vm/mterp/out/InterpC-portstd.c
index a4c4b54..5b0d45b 100644
--- a/vm/mterp/out/InterpC-portstd.c
+++ b/vm/mterp/out/InterpC-portstd.c
@@ -2205,8 +2205,9 @@
}
}
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));
- ((u4*) arrayObj->contents)[GET_REGISTER(vsrc2)] =
- GET_REGISTER(vdst);
+ dvmSetObjectArrayElement(arrayObj,
+ GET_REGISTER(vsrc2),
+ (Object *)GET_REGISTER(vdst));
}
FINISH(2);
OP_END
@@ -3250,6 +3251,9 @@
vdst >>= 4;
}
}
+ if (typeCh == 'L' || typeCh == '[') {
+ dvmWriteBarrierArray(newArray, 0, newArray->length);
+ }
retval.l = newArray;
}
diff --git a/vm/mterp/out/InterpC-x86-atom.c b/vm/mterp/out/InterpC-x86-atom.c
index 9d208a3..7da241c 100644
--- a/vm/mterp/out/InterpC-x86-atom.c
+++ b/vm/mterp/out/InterpC-x86-atom.c
@@ -1422,6 +1422,9 @@
vdst >>= 4;
}
}
+ if (typeCh == 'L' || typeCh == '[') {
+ dvmWriteBarrierArray(newArray, 0, newArray->length);
+ }
retval.l = newArray;
}
diff --git a/vm/mterp/out/InterpC-x86.c b/vm/mterp/out/InterpC-x86.c
index d9e599e..86fe972 100644
--- a/vm/mterp/out/InterpC-x86.c
+++ b/vm/mterp/out/InterpC-x86.c
@@ -1391,6 +1391,9 @@
vdst >>= 4;
}
}
+ if (typeCh == 'L' || typeCh == '[') {
+ dvmWriteBarrierArray(newArray, 0, newArray->length);
+ }
retval.l = newArray;
}
diff --git a/vm/native/dalvik_system_DexFile.c b/vm/native/dalvik_system_DexFile.c
index e031289..25c9dfb 100644
--- a/vm/native/dalvik_system_DexFile.c
+++ b/vm/native/dalvik_system_DexFile.c
@@ -335,6 +335,7 @@
DvmDex* pDvmDex;
DexFile* pDexFile;
ArrayObject* stringArray;
+ Thread* self = dvmThreadSelf();
if (!validateCookie(cookie))
RETURN_VOID();
@@ -349,10 +350,13 @@
int count = pDexFile->pHeader->classDefsSize;
stringArray = dvmAllocObjectArray(gDvm.classJavaLangString, count,
ALLOC_DEFAULT);
- if (stringArray == NULL)
- RETURN_VOID(); // should be an OOM pending
+ if (stringArray == NULL) {
+ /* probably OOM */
+ LOGD("Failed allocating array of %d strings\n", count);
+ assert(dvmCheckException(self));
+ RETURN_VOID();
+ }
- StringObject** contents = (StringObject**) stringArray->contents;
int i;
for (i = 0; i < count; i++) {
const DexClassDef* pClassDef = dexGetClassDef(pDexFile, i);
@@ -360,12 +364,13 @@
dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
char* className = dvmDescriptorToDot(descriptor);
- contents[i] = dvmCreateStringFromCstr(className);
- dvmReleaseTrackedAlloc((Object*) contents[i], NULL);
+ StringObject* str = dvmCreateStringFromCstr(className);
+ dvmSetObjectArrayElement(stringArray, i, (Object *)str);
+ dvmReleaseTrackedAlloc((Object *)str, self);
free(className);
}
- dvmReleaseTrackedAlloc((Object*)stringArray, NULL);
+ dvmReleaseTrackedAlloc((Object*)stringArray, self);
RETURN_PTR(stringArray);
}
diff --git a/vm/native/dalvik_system_VMDebug.c b/vm/native/dalvik_system_VMDebug.c
index dd6ac8a..d27926c 100644
--- a/vm/native/dalvik_system_VMDebug.c
+++ b/vm/native/dalvik_system_VMDebug.c
@@ -30,6 +30,8 @@
*/
static ArrayObject* convertStringArray(char** strings, size_t count)
{
+ Thread* self = dvmThreadSelf();
+
/*
* Allocate an array to hold the String objects.
*/
@@ -46,27 +48,26 @@
if (stringArray == NULL) {
/* probably OOM */
LOGD("Failed allocating array of %d strings\n", count);
+ assert(dvmCheckException(self));
return NULL;
}
- Thread* self = dvmThreadSelf();
-
/*
* Create the individual String objects and add them to the array.
*/
- StringObject** contents = (StringObject**) stringArray->contents;
size_t i;
for (i = 0; i < count; i++) {
- contents[i] = dvmCreateStringFromCstr(strings[i]);
- if (contents[i] == NULL) {
+ Object *str =
+ (Object *)dvmCreateStringFromCstr(strings[i]);
+ if (str == NULL) {
/* probably OOM; drop out now */
assert(dvmCheckException(self));
dvmReleaseTrackedAlloc((Object*)stringArray, self);
return NULL;
}
-
+ dvmSetObjectArrayElement(stringArray, i, str);
/* stored in tracked array, okay to release */
- dvmReleaseTrackedAlloc((Object*)contents[i], self);
+ dvmReleaseTrackedAlloc(str, self);
}
dvmReleaseTrackedAlloc((Object*)stringArray, self);
diff --git a/vm/native/dalvik_system_VMStack.c b/vm/native/dalvik_system_VMStack.c
index 4a1ce53..8db4a6b 100644
--- a/vm/native/dalvik_system_VMStack.c
+++ b/vm/native/dalvik_system_VMStack.c
@@ -150,18 +150,16 @@
/*
* Fill in the array.
*/
- ClassObject** objects = (ClassObject**) classes->contents;
-
- unsigned int sidx = 0;
- for (idx = kSkip; (int) idx < methodCount && sidx < size; idx++) {
- const Method* meth = methods[idx];
-
- if (dvmIsReflectionMethod(meth))
+ unsigned int objCount = 0;
+ for (idx = kSkip; (int) idx < methodCount; idx++) {
+ if (dvmIsReflectionMethod(methods[idx])) {
continue;
-
- *objects++ = meth->clazz;
- sidx++;
+ }
+ dvmSetObjectArrayElement(classes, objCount,
+ (Object *)methods[idx]->clazz);
+ objCount++;
}
+ assert(objCount == classes->length);
bail:
free(methods);
diff --git a/vm/native/java_lang_Class.c b/vm/native/java_lang_Class.c
index b873466..1bb9241 100644
--- a/vm/native/java_lang_Class.c
+++ b/vm/native/java_lang_Class.c
@@ -191,12 +191,13 @@
0, ALLOC_DEFAULT);
}
} else if (publicOnly) {
- int i, newIdx, publicCount = 0;
+ u4 count, newIdx, publicCount = 0;
ClassObject** pSource = (ClassObject**) classes->contents;
+ u4 length = classes->length;
/* count up public classes */
- for (i = 0; i < (int)classes->length; i++) {
- if (dvmIsPublicClass(pSource[i]))
+ for (count = 0; count < length; count++) {
+ if (dvmIsPublicClass(pSource[count]))
publicCount++;
}
@@ -206,12 +207,13 @@
publicCount, ALLOC_DEFAULT);
/* copy them over */
- ClassObject** pDest = (ClassObject**) newClasses->contents;
- for (i = newIdx = 0; i < (int)classes->length; i++) {
- if (dvmIsPublicClass(pSource[i]))
- pDest[newIdx++] = pSource[i];
+ for (count = newIdx = 0; count < length; count++) {
+ if (dvmIsPublicClass(pSource[count])) {
+ dvmSetObjectArrayElement(newClasses, newIdx,
+ (Object *)pSource[count]);
+ newIdx++;
+ }
}
-
assert(newIdx == publicCount);
dvmReleaseTrackedAlloc((Object*) classes, NULL);
classes = newClasses;
diff --git a/vm/native/java_lang_System.c b/vm/native/java_lang_System.c
index 82b93d2..064d6da 100644
--- a/vm/native/java_lang_System.c
+++ b/vm/native/java_lang_System.c
@@ -148,6 +148,7 @@
(*copyFunc)((u1*)dstArray->contents + dstPos * width,
(const u1*)srcArray->contents + srcPos * width,
length * width);
+ dvmWriteBarrierArray(dstArray, dstPos, dstPos+length);
} else {
/*
* The arrays are not fundamentally compatible. However, we may
@@ -194,7 +195,7 @@
(*copyFunc)((u1*)dstArray->contents + dstPos * width,
(const u1*)srcArray->contents + srcPos * width,
copyCount * width);
-
+ dvmWriteBarrierArray(dstArray, 0, copyCount);
if (copyCount != length) {
dvmThrowExceptionFmt("Ljava/lang/ArrayStoreException;",
"source[%d] of type %s cannot be stored in destination array of type %s",
diff --git a/vm/native/java_lang_reflect_Field.c b/vm/native/java_lang_reflect_Field.c
index 65879f4..cb9f2bf 100644
--- a/vm/native/java_lang_reflect_Field.c
+++ b/vm/native/java_lang_reflect_Field.c
@@ -231,6 +231,17 @@
fieldType->primitiveType == PRIM_DOUBLE)
{
fieldPtr->j = value.j;
+ } else if (fieldType->primitiveType == PRIM_NOT) {
+ if (slot < 0) {
+ StaticField *sfield;
+ sfield = (StaticField *)dvmSlotToField(declaringClass, slot);
+ assert(fieldPtr == &sfield->value);
+ dvmSetStaticFieldObject(sfield, value.l);
+ } else {
+ int offset = declaringClass->ifields[slot].byteOffset;
+ assert(fieldPtr == (JValue *)BYTE_OFFSET(obj, offset));
+ dvmSetFieldObject(obj, offset, value.l);
+ }
} else {
fieldPtr->i = value.i;
}
diff --git a/vm/native/java_security_AccessController.c b/vm/native/java_security_AccessController.c
index 1c35b0e..378fb94 100644
--- a/vm/native/java_security_AccessController.c
+++ b/vm/native/java_security_AccessController.c
@@ -121,9 +121,8 @@
}
/* copy the ProtectionDomain objects out */
- Object** objects = (Object**) domains->contents;
- for (idx = 0; idx < subIdx; idx++)
- *objects++ = subSet[idx];
+ memcpy(domains->contents, subSet, subIdx * sizeof(Object *));
+ dvmWriteBarrierArray(domains, 0, subIdx);
bail:
free(subSet);
diff --git a/vm/native/sun_misc_Unsafe.c b/vm/native/sun_misc_Unsafe.c
index b3c7141..7a64c46 100644
--- a/vm/native/sun_misc_Unsafe.c
+++ b/vm/native/sun_misc_Unsafe.c
@@ -128,7 +128,7 @@
// Note: android_atomic_cmpxchg() returns 0 on success, not failure.
int result = android_atomic_release_cas((int32_t) expectedValue,
(int32_t) newValue, address);
-
+ dvmWriteBarrierField(obj, address);
RETURN_BOOLEAN(result == 0);
}
@@ -221,6 +221,7 @@
volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset);
android_atomic_release_store((int32_t)value, address);
+ dvmWriteBarrierField(obj, (void *)address);
RETURN_VOID();
}
@@ -305,6 +306,7 @@
Object** address = (Object**) (((u1*) obj) + offset);
*address = value;
+ dvmWriteBarrierField(obj, address);
RETURN_VOID();
}
diff --git a/vm/oo/Array.c b/vm/oo/Array.c
index 6e706ef..9749f77 100644
--- a/vm/oo/Array.c
+++ b/vm/oo/Array.c
@@ -246,7 +246,6 @@
}
} else {
ClassObject* subArrayClass;
- Object** contents;
int i;
/* if we have X[][], find X[] */
@@ -269,19 +268,16 @@
/*
* Create a new sub-array in every element of the array.
*/
- contents = (Object**) newArray->contents;
for (i = 0; i < *dimensions; i++) {
- ArrayObject* newSubArray;
-
- newSubArray = dvmAllocMultiArray(subArrayClass, curDim-1,
- dimensions+1);
+ ArrayObject* newSubArray;
+ newSubArray = dvmAllocMultiArray(subArrayClass, curDim-1,
+ dimensions+1);
if (newSubArray == NULL) {
dvmReleaseTrackedAlloc((Object*) newArray, NULL);
assert(dvmCheckException(dvmThreadSelf()));
return NULL;
}
-
- *contents++ = (Object*) newSubArray;
+ dvmSetObjectArrayElement(newArray, i, (Object *)newSubArray);
dvmReleaseTrackedAlloc((Object*) newSubArray, NULL);
}
}
@@ -427,12 +423,18 @@
dvmSetClassSerialNumber(newClass);
newClass->descriptorAlloc = strdup(descriptor);
newClass->descriptor = newClass->descriptorAlloc;
- newClass->super = gDvm.classJavaLangObject;
+ dvmSetFieldObject((Object *)newClass,
+ offsetof(ClassObject, super),
+ (Object *)gDvm.classJavaLangObject);
newClass->vtableCount = gDvm.classJavaLangObject->vtableCount;
newClass->vtable = gDvm.classJavaLangObject->vtable;
newClass->primitiveType = PRIM_NOT;
- newClass->elementClass = elementClass;
- newClass->classLoader = elementClass->classLoader;
+ dvmSetFieldObject((Object *)newClass,
+ offsetof(ClassObject, elementClass),
+ (Object *)elementClass);
+ dvmSetFieldObject((Object *)newClass,
+ offsetof(ClassObject, classLoader),
+ (Object *)elementClass->classLoader);
newClass->arrayDim = arrayDim;
newClass->status = CLASS_INITIALIZED;
#if WITH_HPROF && WITH_HPROF_STACK
@@ -530,9 +532,6 @@
assert(newClass != NULL);
return newClass;
}
-
- /* make it available to the GC */
- newClass->obj.clazz = gDvm.classJavaLangClass;
dvmReleaseTrackedAlloc((Object*) newClass, NULL);
LOGV("Created array class '%s' %p (access=0x%04x.%04x)\n",
@@ -664,21 +663,21 @@
ClassObject* dstElemClass)
{
Object** src = (Object**)srcArray->contents;
- Object** dst = (Object**)dstArray->contents;
- u4 count = dstArray->length;
+ u4 length, count;
assert(srcArray->length == dstArray->length);
assert(dstArray->obj.clazz->elementClass == dstElemClass ||
(dstArray->obj.clazz->elementClass == dstElemClass->elementClass &&
dstArray->obj.clazz->arrayDim == dstElemClass->arrayDim+1));
- while (count--) {
- if (!dvmInstanceof((*src)->clazz, dstElemClass)) {
+ length = dstArray->length;
+ for (count = 0; count < length; count++) {
+ if (!dvmInstanceof(src[count]->clazz, dstElemClass)) {
LOGW("dvmCopyObjectArray: can't store %s in %s\n",
- (*src)->clazz->descriptor, dstElemClass->descriptor);
+ src[count]->clazz->descriptor, dstElemClass->descriptor);
return false;
}
- *dst++ = *src++;
+ dvmSetObjectArrayElement(dstArray, count, src[count]);
}
return true;
diff --git a/vm/oo/Class.c b/vm/oo/Class.c
index 40535cc..feb4fdb 100644
--- a/vm/oo/Class.c
+++ b/vm/oo/Class.c
@@ -1695,7 +1695,9 @@
newClass->descriptor = descriptor;
assert(newClass->descriptorAlloc == NULL);
newClass->accessFlags = pClassDef->accessFlags;
- newClass->classLoader = classLoader;
+ dvmSetFieldObject((Object *)newClass,
+ offsetof(ClassObject, classLoader),
+ (Object *)classLoader);
newClass->pDvmDex = pDvmDex;
newClass->primitiveType = PRIM_NOT;
newClass->status = CLASS_IDX;
@@ -2506,8 +2508,8 @@
clazz->status = CLASS_LOADED;
if (superclassIdx != kDexNoIndex) {
- clazz->super = dvmResolveClass(clazz, superclassIdx, false);
- if (clazz->super == NULL) {
+ ClassObject* super = dvmResolveClass(clazz, superclassIdx, false);
+ if (super == NULL) {
assert(dvmCheckException(dvmThreadSelf()));
if (gDvm.optimizing) {
/* happens with "external" libs */
@@ -2519,6 +2521,9 @@
}
goto bail;
}
+ dvmSetFieldObject((Object *)clazz,
+ offsetof(ClassObject, super),
+ (Object *)super);
}
if (clazz->interfaceCount > 0) {
@@ -3825,7 +3830,7 @@
bool parsed = dvmEncodedArrayIteratorGetNext(&iterator, &value);
StaticField* sfield = &clazz->sfields[i];
const char* descriptor = sfield->field.signature;
- bool needRelease = false;
+ bool isObj = false;
if (! parsed) {
/*
@@ -3859,13 +3864,13 @@
case kDexAnnotationString: {
parsed =
(strcmp(descriptor, "Ljava/lang/String;") == 0);
- needRelease = true;
+ isObj = true;
break;
}
case kDexAnnotationType: {
parsed =
(strcmp(descriptor, "Ljava/lang/Class;") == 0);
- needRelease = true;
+ isObj = true;
break;
}
default: {
@@ -3883,13 +3888,18 @@
if (parsed) {
/*
- * All's well, so store the value. Note: This always
- * stores the full width of a JValue, even though most of
- * the time only the first word is needed.
+ * All's well, so store the value.
*/
- sfield->value = value.value;
- if (needRelease) {
+ if (isObj) {
+ dvmSetStaticFieldObject(sfield, value.value.l);
dvmReleaseTrackedAlloc(value.value.l, self);
+ } else {
+ /*
+ * Note: This always stores the full width of a
+ * JValue, even though most of the time only the first
+ * word is needed.
+ */
+ sfield->value = value.value;
}
} else {
/*
@@ -4279,7 +4289,9 @@
verify_failed:
dvmThrowExceptionWithClassMessage("Ljava/lang/VerifyError;",
clazz->descriptor);
- clazz->verifyErrorClass = dvmGetException(self)->clazz;
+ dvmSetFieldObject((Object *)clazz,
+ offsetof(ClassObject, verifyErrorClass),
+ (Object *)dvmGetException(self)->clazz);
clazz->status = CLASS_ERROR;
goto bail_unlock;
}
diff --git a/vm/oo/Object.h b/vm/oo/Object.h
index 041e1e8..935f670 100644
--- a/vm/oo/Object.h
+++ b/vm/oo/Object.h
@@ -255,8 +255,12 @@
* Properly initialize an Object.
* void DVM_OBJECT_INIT(Object *obj, ClassObject *clazz_)
*/
-#define DVM_OBJECT_INIT(obj, clazz_) \
- do { (obj)->clazz = (clazz_); DVM_LOCK_INIT(&(obj)->lock); } while (0)
+#define DVM_OBJECT_INIT(obj, clazz_) \
+ do { \
+ dvmSetFieldObject((Object *)obj, offsetof(Object, clazz), \
+ (Object *)clazz_); \
+ DVM_LOCK_INIT(&(obj)->lock); \
+ } while (0)
/*
* Data objects have an Object header followed by their instance data.
@@ -673,6 +677,26 @@
}
/*
+ * Note writes to the heap.
+ */
+INLINE void dvmWriteBarrierField(Object *obj, void *addr) {
+}
+INLINE void dvmWriteBarrierObject(Object *obj) {
+}
+INLINE void dvmWriteBarrierArray(const ArrayObject* obj,
+ size_t start, size_t end) {
+}
+/*
+ * Store a single value in the array, and note in the write barrier.
+ */
+INLINE void dvmSetObjectArrayElement(const ArrayObject* obj, int index,
+ Object* val) {
+ ((Object **)(obj)->contents)[index] = val;
+ dvmWriteBarrierArray(obj, index, index+1);
+}
+
+
+/*
* Field access functions. Pass in the word offset from Field->byteOffset.
*
* We guarantee that long/double field data is 64-bit aligned, so it's safe
@@ -754,7 +778,9 @@
((JValue*)BYTE_OFFSET(obj, offset))->d = val;
}
INLINE void dvmSetFieldObject(Object* obj, int offset, Object* val) {
- ((JValue*)BYTE_OFFSET(obj, offset))->l = val;
+ JValue* lhs = BYTE_OFFSET(obj, offset);
+ lhs->l = val;
+ dvmWriteBarrierField(obj, &lhs->l);
}
INLINE void dvmSetFieldIntVolatile(Object* obj, int offset, s4 val) {
s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
@@ -763,6 +789,7 @@
INLINE void dvmSetFieldObjectVolatile(Object* obj, int offset, Object* val) {
void** ptr = &((JValue*)BYTE_OFFSET(obj, offset))->l;
android_atomic_release_store((int32_t)val, (int32_t*)ptr);
+ dvmWriteBarrierField(obj, ptr);
}
INLINE void dvmSetFieldLongVolatile(Object* obj, int offset, s8 val) {
s8* addr = BYTE_OFFSET(obj, offset);
@@ -845,6 +872,7 @@
}
INLINE void dvmSetStaticFieldObject(StaticField* sfield, Object* val) {
sfield->value.l = val;
+ dvmWriteBarrierField((Object *)sfield->field.clazz, &sfield->value.l);
}
INLINE void dvmSetStaticFieldIntVolatile(StaticField* sfield, s4 val) {
s4* ptr = &(sfield->value.i);
@@ -853,6 +881,7 @@
INLINE void dvmSetStaticFieldObjectVolatile(StaticField* sfield, Object* val) {
void** ptr = &(sfield->value.l);
android_atomic_release_store((int32_t)val, (int32_t*)ptr);
+ dvmWriteBarrierField((Object *)sfield->field.clazz, &sfield->value.l);
}
INLINE void dvmSetStaticFieldLongVolatile(StaticField* sfield, s8 val) {
s8* addr = &sfield->value.j;
diff --git a/vm/reflect/Annotation.c b/vm/reflect/Annotation.c
index 86f800e..a5007ba 100644
--- a/vm/reflect/Annotation.c
+++ b/vm/reflect/Annotation.c
@@ -544,8 +544,7 @@
return false;
} else {
ArrayObject* newArray;
- Object** pObj;
- u4 size;
+ u4 size, count;
size = readUleb128(&ptr);
LOGVV("--- annotation array, size is %u at %p\n", size, ptr);
@@ -555,18 +554,17 @@
LOGE("annotation element array alloc failed (%d)\n", size);
return false;
}
- pObj = (Object**)newArray->contents;
AnnotationValue avalue;
- while (size--) {
+ for (count = 0; count < size; count++) {
if (!processAnnotationValue(clazz, &ptr, &avalue,
kAllObjects)) {
dvmReleaseTrackedAlloc((Object*)newArray, self);
return false;
}
Object* obj = avalue.value.l;
+ dvmSetObjectArrayElement(newArray, count, obj);
dvmReleaseTrackedAlloc(obj, self);
- *pObj++ = obj;
}
elemObj = (Object*) newArray;
@@ -807,7 +805,7 @@
ArrayObject* elementArray = NULL;
const ClassObject* annoClass;
const u1* ptr;
- u4 typeIdx, size;
+ u4 typeIdx, size, count;
ptr = *pPtr;
typeIdx = readUleb128(&ptr);
@@ -836,7 +834,6 @@
* default values get merged in later.
*/
JValue result;
- Object** pElement = NULL;
if (size > 0) {
elementArray = dvmAllocArrayByClass(
@@ -847,20 +844,19 @@
size);
goto bail;
}
- pElement = (Object**) elementArray->contents;
}
/*
* "ptr" points to a byte stream with "size" occurrences of
* annotation_element.
*/
- while (size--) {
+ for (count = 0; count < size; count++) {
Object* newMember = createAnnotationMember(clazz, annoClass, &ptr);
if (newMember == NULL)
goto bail;
/* add it to the array */
- *pElement++ = newMember;
+ dvmSetObjectArrayElement(elementArray, count, newMember);
}
dvmCallMethod(self,
@@ -898,8 +894,8 @@
DexFile* pDexFile = clazz->pDvmDex->pDexFile;
const DexAnnotationItem* pAnnoItem;
ArrayObject* annoArray;
- Object** pContents;
int i, count;
+ u4 dstIndex;
/* we need these later; make sure they're initialized */
if (!dvmIsClassInitialized(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory))
@@ -914,27 +910,29 @@
count++;
}
- annoArray =dvmAllocArrayByClass(gDvm.classJavaLangAnnotationAnnotationArray,
- count, ALLOC_DEFAULT);
+ annoArray =
+ dvmAllocArrayByClass(gDvm.classJavaLangAnnotationAnnotationArray,
+ count, ALLOC_DEFAULT);
if (annoArray == NULL)
return NULL;
- pContents = (Object**) annoArray->contents;
/*
* Generate Annotation objects. We must put them into the array
* immediately (or add them to the tracked ref table).
*/
+ dstIndex = 0;
for (i = 0; i < (int) pAnnoSet->size; i++) {
pAnnoItem = dexGetAnnotationItem(pDexFile, pAnnoSet, i);
if (pAnnoItem->visibility != visibility)
continue;
const u1* ptr = pAnnoItem->annotation;
- *pContents = processEncodedAnnotation(clazz, &ptr);
- if (*pContents == NULL) {
+ Object *anno = processEncodedAnnotation(clazz, &ptr);
+ if (anno == NULL) {
dvmReleaseTrackedAlloc((Object*) annoArray, NULL);
return NULL;
}
- pContents++;
+ dvmSetObjectArrayElement(annoArray, dstIndex, anno);
+ ++dstIndex;
}
return annoArray;
@@ -1987,7 +1985,6 @@
{
DexFile* pDexFile = clazz->pDvmDex->pDexFile;
ArrayObject* annoArrayArray = NULL;
- ArrayObject** pContents;
u4 idx;
/* allocate an array of Annotation arrays to hold results */
@@ -1998,24 +1995,24 @@
goto bail;
}
- pContents = (ArrayObject**) annoArrayArray->contents;
-
for (idx = 0; idx < count; idx++) {
Thread* self = dvmThreadSelf();
const DexAnnotationSetRefItem* pItem;
const DexAnnotationSetItem* pAnnoSet;
+ Object *annoSet;
pItem = dexGetParameterAnnotationSetRef(pAnnoSetList, idx);
pAnnoSet = dexGetSetRefItemItem(pDexFile, pItem);
- *pContents = processAnnotationSet(clazz, pAnnoSet,
- kDexVisibilityRuntime);
- if (*pContents == NULL) {
+ annoSet = (Object *)processAnnotationSet(clazz,
+ pAnnoSet,
+ kDexVisibilityRuntime);
+ if (annoSet == NULL) {
LOGW("processAnnotationSet failed\n");
annoArrayArray = NULL;
goto bail;
}
- dvmReleaseTrackedAlloc((Object*) *pContents, self);
- pContents++;
+ dvmSetObjectArrayElement(annoArrayArray, idx, annoSet);
+ dvmReleaseTrackedAlloc((Object*) annoSet, self);
}
bail:
diff --git a/vm/reflect/Proxy.c b/vm/reflect/Proxy.c
index 4984b12..eef658d 100644
--- a/vm/reflect/Proxy.c
+++ b/vm/reflect/Proxy.c
@@ -188,9 +188,13 @@
newClass->descriptorAlloc = dvmNameToDescriptor(nameStr);
newClass->descriptor = newClass->descriptorAlloc;
newClass->accessFlags = ACC_PUBLIC | ACC_FINAL;
- newClass->super = gDvm.classJavaLangReflectProxy;
+ dvmSetFieldObject((Object *)newClass,
+ offsetof(ClassObject, super),
+ (Object *)gDvm.classJavaLangReflectProxy);
newClass->primitiveType = PRIM_NOT;
- newClass->classLoader = loader;
+ dvmSetFieldObject((Object *)newClass,
+ offsetof(ClassObject, classLoader),
+ (Object *)loader);
#if WITH_HPROF && WITH_HPROF_STACK
hprofFillInStackTrace(newClass);
#endif
diff --git a/vm/reflect/Reflect.c b/vm/reflect/Reflect.c
index 8e128b7..cf63462 100644
--- a/vm/reflect/Reflect.c
+++ b/vm/reflect/Reflect.c
@@ -240,7 +240,6 @@
ClassObject* defClass)
{
ArrayObject* classArray;
- ClassObject** classes;
char* signature = *pSignature;
char* cp;
int i, count;
@@ -273,7 +272,6 @@
return NULL;
/* fill it in */
- classes = (ClassObject**) classArray->contents;
cp = signature;
for (i = 0; i < count; i++) {
ClassObject* clazz;
@@ -284,8 +282,7 @@
return NULL;
}
LOGVV("REFLECT %d: '%s'\n", i, clazz->descriptor);
-
- *classes++ = clazz;
+ dvmSetObjectArrayElement(classArray, i, (Object *)clazz);
}
*pSignature = cp;
@@ -395,7 +392,6 @@
ArrayObject* dvmGetDeclaredFields(ClassObject* clazz, bool publicOnly)
{
ArrayObject* fieldArray = NULL;
- Object** fields;
int i, count;
if (!dvmIsClassInitialized(gDvm.classJavaLangReflectField))
@@ -421,34 +417,38 @@
kObjectArrayRefWidth, ALLOC_DEFAULT);
if (fieldArray == NULL)
return NULL;
- fields = (Object**) fieldArray->contents;
/* populate */
+ size_t fieldCount = 0;
for (i = 0; i < clazz->sfieldCount; i++) {
if (!publicOnly ||
(clazz->sfields[i].field.accessFlags & ACC_PUBLIC) != 0)
{
- *fields = createFieldObject(&clazz->sfields[i].field, clazz);
- if (*fields == NULL)
+ Object* field = createFieldObject(&clazz->sfields[i].field, clazz);
+ if (field == NULL) {
goto fail;
- dvmReleaseTrackedAlloc(*fields, NULL);
- fields++;
- count--;
+ }
+ dvmSetObjectArrayElement(fieldArray, fieldCount, field);
+ dvmReleaseTrackedAlloc(field, NULL);
+ ++fieldCount;
}
}
for (i = 0; i < clazz->ifieldCount; i++) {
if (!publicOnly ||
(clazz->ifields[i].field.accessFlags & ACC_PUBLIC) != 0)
{
- *fields = createFieldObject(&clazz->ifields[i].field, clazz);
- if (*fields == NULL)
+ Object* field = createFieldObject(&clazz->ifields[i].field, clazz);
+ if (field == NULL) {
goto fail;
- dvmReleaseTrackedAlloc(*fields, NULL);
- fields++;
- count--;
+ }
+ dvmSetObjectArrayElement(fieldArray, fieldCount, field);
+ dvmReleaseTrackedAlloc(field, NULL);
+ ++fieldCount;
}
}
+ assert(fieldCount == fieldArray->length);
+
/* caller must call dvmReleaseTrackedAlloc */
return fieldArray;
@@ -575,7 +575,6 @@
ArrayObject* dvmGetDeclaredConstructors(ClassObject* clazz, bool publicOnly)
{
ArrayObject* consArray;
- Object** consObjPtr;
Method* meth;
int i, count;
@@ -610,12 +609,11 @@
if (consArray == NULL)
return NULL;
- consObjPtr = (Object**) consArray->contents;
-
/*
* Fill out the array.
*/
meth = clazz->directMethods;
+ size_t consObjCount = 0;
for (i = 0; i < clazz->directMethodCount; i++, meth++) {
if ((!publicOnly || dvmIsPublicMethod(meth)) &&
dvmIsConstructorMethod(meth) && !dvmIsStaticMethod(meth))
@@ -623,12 +621,13 @@
Object* consObj = createConstructorObject(meth);
if (consObj == NULL)
goto fail;
- *consObjPtr++ = consObj;
+ dvmSetObjectArrayElement(consArray, consObjCount, consObj);
+ ++consObjCount;
dvmReleaseTrackedAlloc(consObj, NULL);
}
}
- assert(consObjPtr - (Object**) consArray->contents == count);
+ assert(consObjCount == consArray->length);
/* caller must call dvmReleaseTrackedAlloc */
return consArray;
@@ -740,7 +739,6 @@
ArrayObject* dvmGetDeclaredMethods(ClassObject* clazz, bool publicOnly)
{
ArrayObject* methodArray;
- Object** methObjPtr;
Method* meth;
int i, count;
@@ -778,12 +776,12 @@
if (methodArray == NULL)
return NULL;
- methObjPtr = (Object**) methodArray->contents;
/*
* Fill out the array.
*/
meth = clazz->virtualMethods;
+ size_t methObjCount = 0;
for (i = 0; i < clazz->virtualMethodCount; i++, meth++) {
if ((!publicOnly || dvmIsPublicMethod(meth)) &&
!dvmIsMirandaMethod(meth))
@@ -791,7 +789,8 @@
Object* methObj = dvmCreateReflectMethodObject(meth);
if (methObj == NULL)
goto fail;
- *methObjPtr++ = methObj;
+ dvmSetObjectArrayElement(methodArray, methObjCount, methObj);
+ ++methObjCount;
dvmReleaseTrackedAlloc(methObj, NULL);
}
}
@@ -803,12 +802,13 @@
Object* methObj = dvmCreateReflectMethodObject(meth);
if (methObj == NULL)
goto fail;
- *methObjPtr++ = methObj;
+ dvmSetObjectArrayElement(methodArray, methObjCount, methObj);
+ ++methObjCount;
dvmReleaseTrackedAlloc(methObj, NULL);
}
}
- assert(methObjPtr - (Object**) methodArray->contents == count);
+ assert(methObjCount == methodArray->length);
/* caller must call dvmReleaseTrackedAlloc */
return methodArray;
@@ -841,11 +841,9 @@
/*
* Fill out the array.
*/
- Object** interfaceObjPtr = (Object**) interfaceArray->contents;
- int i;
- for (i = 0; i < count; i++) {
- *interfaceObjPtr++ = (Object*) clazz->interfaces[i];
- }
+ memcpy(interfaceArray->contents, clazz->interfaces,
+ count * sizeof(Object *));
+ dvmWriteBarrierArray(interfaceArray, 0, count);
/* caller must call dvmReleaseTrackedAlloc */
return interfaceArray;
@@ -1102,6 +1100,8 @@
value->clazz->descriptor, returnType->descriptor);
return false;
}
+ /* Never on the heap, so no write barrier needed. */
+ assert(!dvmIsValidObjectAddress(pResult));
pResult->l = value;
return true;
} else if (typeIndex == PRIM_VOID) {