Add validate object, clean up stack indirect reference table.
Change-Id: Ifb329ae7d3bede3e95d48e6761cee1412a33d867
diff --git a/src/thread.cc b/src/thread.cc
index f37dcba..3284625 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -9,6 +9,7 @@
#include <list>
#include "class_linker.h"
+#include "heap.h"
#include "jni_internal.h"
#include "object.h"
#include "runtime.h"
@@ -204,27 +205,89 @@
return true;
}
-size_t Thread::NumShbHandles() {
+size_t Thread::NumSirtReferences() {
size_t count = 0;
- for (StackHandleBlock* cur = top_shb_; cur; cur = cur->Link()) {
+ for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
count += cur->NumberOfReferences();
}
return count;
}
-bool Thread::ShbContains(jobject obj) {
- Object** shb_entry = reinterpret_cast<Object**>(obj);
- for (StackHandleBlock* cur = top_shb_; cur; cur = cur->Link()) {
+bool Thread::SirtContains(jobject obj) {
+ Object** sirt_entry = reinterpret_cast<Object**>(obj);
+ for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
size_t num_refs = cur->NumberOfReferences();
- DCHECK_GT(num_refs, 0u); // A SHB should always have a jobject/jclass
- if ((&cur->Handles()[0] >= shb_entry) &&
- (shb_entry <= (&cur->Handles()[num_refs-1]))) {
+ // A SIRT should always have a jobject/jclass as a native method is passed
+ // in a this pointer or a class
+ DCHECK_GT(num_refs, 0u);
+ if ((&cur->References()[0] >= sirt_entry) &&
+ (sirt_entry <= (&cur->References()[num_refs-1]))) {
return true;
}
}
return false;
}
+Object* Thread::DecodeJObject(jobject obj) {
+ // TODO: Only allowed to hold Object* when in the runnable state
+ // DCHECK(state_ == kRunnable);
+ if (obj == NULL) {
+ return NULL;
+ }
+ IndirectRef ref = reinterpret_cast<IndirectRef>(obj);
+ IndirectRefKind kind = GetIndirectRefKind(ref);
+ Object* result;
+ switch (kind) {
+ case kLocal:
+ {
+ JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(jni_env_);
+ IndirectReferenceTable& locals = env->locals;
+ result = locals.Get(ref);
+ break;
+ }
+ case kGlobal:
+ {
+ JavaVMExt* vm = Runtime::Current()->GetJavaVM();
+ IndirectReferenceTable& globals = vm->globals;
+ MutexLock mu(vm->globals_lock);
+ result = globals.Get(ref);
+ break;
+ }
+ case kWeakGlobal:
+ {
+ JavaVMExt* vm = Runtime::Current()->GetJavaVM();
+ IndirectReferenceTable& weak_globals = vm->weak_globals;
+ MutexLock mu(vm->weak_globals_lock);
+ result = weak_globals.Get(ref);
+ if (result == kClearedJniWeakGlobal) {
+ // This is a special case where it's okay to return NULL.
+ return NULL;
+ }
+ break;
+ }
+ case kSirtOrInvalid:
+ default:
+ // TODO: make stack indirect reference table lookup more efficient
+ // Check if this is a local reference in the SIRT
+ if (SirtContains(obj)) {
+ result = *reinterpret_cast<Object**>(obj); // Read from SIRT
+ } else if (false /*gDvmJni.workAroundAppJniBugs*/) { // TODO
+ // Assume an invalid local reference is actually a direct pointer.
+ result = reinterpret_cast<Object*>(obj);
+ } else {
+ LOG(FATAL) << "Invalid indirect reference " << obj;
+ result = reinterpret_cast<Object*>(kInvalidIndirectRefObject);
+ }
+ }
+
+ if (result == NULL) {
+ LOG(FATAL) << "JNI ERROR (app bug): use of deleted " << kind << ": "
+ << obj;
+ }
+ Heap::VerifyObject(result);
+ return result;
+}
+
void Thread::ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...) {
std::string msg;
va_list args;