diff options
author | Andy McFadden <fadden@android.com> | 2010-10-07 15:11:43 -0700 |
---|---|---|
committer | Andy McFadden <fadden@android.com> | 2010-10-08 10:51:11 -0700 |
commit | 50cab51bb381c5da01adfd61954ddca37607f51e (patch) | |
tree | fc23276ce8a8773de2d4c3cd31ff374152b73b21 | |
parent | a7f5f9043f1ec312b3020ddae9b98937c9d462d3 (diff) | |
download | android_dalvik-50cab51bb381c5da01adfd61954ddca37607f51e.tar.gz android_dalvik-50cab51bb381c5da01adfd61954ddca37607f51e.tar.bz2 android_dalvik-50cab51bb381c5da01adfd61954ddca37607f51e.zip |
Track result from dvmCallMethod
When dvmCallMethod returns an object reference, we need to ensure
that the GC doesn't release or relocate the storage. Unless we have
a clear view of how the object is used, we need to explicitly track
and release it.
This adds additional tracking, or comments indicating that explicit
tracking is not necessary.
On a similar note, clearing/restoring a pending exception requires
explicit tracking of that exception, since there's a fair chance
that it's no longer in the root set. That needed fixing in a couple
of places.
Bug 3009076.
Change-Id: I39def8c3a5a628f0ee86fc094e34d7c69248c28b
-rw-r--r-- | vm/Ddm.c | 10 | ||||
-rw-r--r-- | vm/Debugger.c | 2 | ||||
-rw-r--r-- | vm/Exception.c | 4 | ||||
-rw-r--r-- | vm/Jni.c | 5 | ||||
-rw-r--r-- | vm/Properties.c | 7 | ||||
-rw-r--r-- | vm/Thread.c | 1 | ||||
-rw-r--r-- | vm/oo/Class.c | 6 | ||||
-rw-r--r-- | vm/reflect/Proxy.c | 4 |
8 files changed, 32 insertions, 7 deletions
@@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + /* * Handle Dalvik Debug Monitor requests and events. * @@ -41,6 +42,7 @@ bool dvmDdmHandlePacket(const u1* buf, int dataLen, u1** pReplyBuf, Thread* self = dvmThreadSelf(); const int kChunkHdrLen = 8; ArrayObject* dataArray = NULL; + Object* chunk = NULL; bool result = false; assert(dataLen >= 0); @@ -122,17 +124,18 @@ bool dvmDdmHandlePacket(const u1* buf, int dataLen, u1** pReplyBuf, goto bail; } - Object* chunk; ArrayObject* replyData; chunk = (Object*) callRes.l; if (chunk == NULL) goto bail; + /* not strictly necessary -- we don't alloc from managed heap here */ + dvmAddTrackedAlloc(chunk, self); + /* * Pull the pieces out of the chunk. We copy the results into a * newly-allocated buffer that the caller can free. We don't want to * continue using the Chunk object because nothing has a reference to it. - * (If we do an alloc in here, we need to dvmAddTrackedAlloc it.) * * We could avoid this by returning type/data/offset/length and having * the caller be aware of the object lifetime issues, but that @@ -175,7 +178,8 @@ bool dvmDdmHandlePacket(const u1* buf, int dataLen, u1** pReplyBuf, (char*) reply, reply, length); bail: - dvmReleaseTrackedAlloc((Object*) dataArray, NULL); + dvmReleaseTrackedAlloc((Object*) dataArray, self); + dvmReleaseTrackedAlloc(chunk, self); return result; } diff --git a/vm/Debugger.c b/vm/Debugger.c index 7706efb50..4f392360b 100644 --- a/vm/Debugger.c +++ b/vm/Debugger.c @@ -2888,6 +2888,7 @@ void dvmDbgExecuteMethod(DebugInvokeReq* pReq) * to preserve that across the method invocation. */ oldExcept = dvmGetException(self); + dvmAddTrackedAlloc(oldExcept, self); dvmClearException(self); oldStatus = dvmChangeStatus(self, THREAD_RUNNING); @@ -2941,6 +2942,7 @@ void dvmDbgExecuteMethod(DebugInvokeReq* pReq) if (oldExcept != NULL) dvmSetException(self, oldExcept); + dvmReleaseTrackedAlloc(oldExcept, self); dvmChangeStatus(self, oldStatus); } diff --git a/vm/Exception.c b/vm/Exception.c index ddb84e5fa..9ca80e65c 100644 --- a/vm/Exception.c +++ b/vm/Exception.c @@ -723,6 +723,7 @@ void dvmPrintExceptionStackTrace(void) if (exception == NULL) return; + dvmAddTrackedAlloc(exception, self); self->exception = NULL; printMethod = dvmFindVirtualMethodHierByDescriptor(exception->clazz, "printStackTrace", "()V"); @@ -740,6 +741,7 @@ void dvmPrintExceptionStackTrace(void) } self->exception = exception; + dvmReleaseTrackedAlloc(exception, self); } /* @@ -1250,6 +1252,7 @@ static StringObject* getExceptionMessage(Object* exception) StringObject* messageStr = NULL; assert(exception == self->exception); + dvmAddTrackedAlloc(exception, self); self->exception = NULL; getMessageMethod = dvmFindVirtualMethodHierByDescriptor(exception->clazz, @@ -1276,6 +1279,7 @@ static StringObject* getExceptionMessage(Object* exception) } self->exception = exception; + dvmReleaseTrackedAlloc(exception, self); return messageStr; } @@ -1852,6 +1852,7 @@ static jclass FindClass(JNIEnv* env, const char* name) ClassObject* clazz; jclass jclazz = NULL; Object* loader; + Object* trackedLoader = NULL; char* descriptor = NULL; thisMethod = dvmGetCurrentJNIMethod(); @@ -1871,7 +1872,7 @@ static jclass FindClass(JNIEnv* env, const char* name) } else if (thisMethod == gDvm.methFakeNativeEntry) { /* start point of invocation interface */ if (!gDvm.initializing) - loader = dvmGetSystemClassLoader(); + loader = trackedLoader = dvmGetSystemClassLoader(); else loader = NULL; } else { @@ -1881,6 +1882,8 @@ static jclass FindClass(JNIEnv* env, const char* name) clazz = dvmFindClassNoInit(descriptor, loader); jclazz = addLocalReference(env, (Object*) clazz); + dvmReleaseTrackedAlloc(trackedLoader, _self); + bail: free(descriptor); diff --git a/vm/Properties.c b/vm/Properties.c index 288085b66..243dc3ee3 100644 --- a/vm/Properties.c +++ b/vm/Properties.c @@ -246,6 +246,7 @@ void dvmSetCommandLineProperties(Object* propObj) */ char* dvmGetProperty(const char* key) { + Thread* self = dvmThreadSelf(); ClassObject* system; Method* getProp; StringObject* keyObj = NULL; @@ -270,15 +271,17 @@ char* dvmGetProperty(const char* key) goto bail; JValue val; - dvmCallMethod(dvmThreadSelf(), getProp, NULL, &val, keyObj); + dvmCallMethod(self, getProp, NULL, &val, keyObj); valueObj = (StringObject*) val.l; if (valueObj == NULL) goto bail; + /* don't need to call dvmAddTrackedAlloc on result; conv to C string safe */ + result = dvmCreateCstrFromString(valueObj); /* fall through with result */ bail: - dvmReleaseTrackedAlloc((Object*)keyObj, NULL); + dvmReleaseTrackedAlloc((Object*)keyObj, self); return result; } diff --git a/vm/Thread.c b/vm/Thread.c index 635fe56c0..afe6f68dc 100644 --- a/vm/Thread.c +++ b/vm/Thread.c @@ -887,6 +887,7 @@ bool dvmPrepMainThread(void) return false; } dvmSetFieldObject(threadObj, ctxtClassLoaderOffset, systemLoader); + dvmReleaseTrackedAlloc(systemLoader, NULL); /* * Finish our thread prep. diff --git a/vm/oo/Class.c b/vm/oo/Class.c index 9bf7118ad..9de277f53 100644 --- a/vm/oo/Class.c +++ b/vm/oo/Class.c @@ -4636,9 +4636,12 @@ ClassObject* dvmFindLoadedClass(const char* descriptor) /* * Retrieve the system (a/k/a application) class loader. + * + * The caller must call dvmReleaseTrackedAlloc on the result. */ Object* dvmGetSystemClassLoader(void) { + Thread* self = dvmThreadSelf(); ClassObject* clazz; Method* getSysMeth; Object* loader; @@ -4653,8 +4656,9 @@ Object* dvmGetSystemClassLoader(void) return NULL; JValue result; - dvmCallMethod(dvmThreadSelf(), getSysMeth, NULL, &result); + dvmCallMethod(self, getSysMeth, NULL, &result); loader = (Object*)result.l; + dvmAddTrackedAlloc(loader, self); return loader; } diff --git a/vm/reflect/Proxy.c b/vm/reflect/Proxy.c index eef658dd1..d76877750 100644 --- a/vm/reflect/Proxy.c +++ b/vm/reflect/Proxy.c @@ -1013,6 +1013,10 @@ static void proxyInvoker(const u4* args, JValue* pResult, * * We don't need to repackage exceptions, so if one has been thrown * just jump to the end. + * + * We're not adding invokeResult.l to the tracked allocation list, but + * since we're just unboxing it or returning it to interpreted code + * that shouldn't be a problem. */ dvmCallMethod(self, invoke, handler, &invokeResult, thisObj, methodObj, argArray); |