diff options
-rw-r--r-- | runtime/check_jni.cc | 30 | ||||
-rw-r--r-- | runtime/class_linker-inl.h | 5 | ||||
-rw-r--r-- | runtime/class_linker.h | 3 | ||||
-rw-r--r-- | runtime/debugger.cc | 737 | ||||
-rw-r--r-- | runtime/debugger.h | 51 | ||||
-rw-r--r-- | runtime/entrypoints/entrypoint_utils.cc | 11 | ||||
-rw-r--r-- | runtime/indirect_reference_table-inl.h | 20 | ||||
-rw-r--r-- | runtime/indirect_reference_table.cc | 4 | ||||
-rw-r--r-- | runtime/indirect_reference_table.h | 15 | ||||
-rw-r--r-- | runtime/indirect_reference_table_test.cc | 62 | ||||
-rw-r--r-- | runtime/java_vm_ext.cc | 3 | ||||
-rw-r--r-- | runtime/jdwp/jdwp.h | 2 | ||||
-rw-r--r-- | runtime/jdwp/jdwp_event.cc | 4 | ||||
-rw-r--r-- | runtime/jdwp/jdwp_handler.cc | 490 | ||||
-rw-r--r-- | runtime/jdwp/jdwp_main.cc | 2 | ||||
-rw-r--r-- | runtime/jdwp/object_registry.cc | 8 | ||||
-rw-r--r-- | runtime/jdwp/object_registry.h | 15 | ||||
-rw-r--r-- | runtime/jni_internal.cc | 18 | ||||
-rw-r--r-- | runtime/jni_internal_test.cc | 31 | ||||
-rw-r--r-- | runtime/reference_table.cc | 17 | ||||
-rw-r--r-- | runtime/runtime-inl.h | 12 | ||||
-rw-r--r-- | runtime/runtime.cc | 8 | ||||
-rw-r--r-- | runtime/runtime.h | 10 | ||||
-rw-r--r-- | runtime/thread.cc | 17 |
24 files changed, 829 insertions, 746 deletions
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc index b0f8e22ab2..95223d856c 100644 --- a/runtime/check_jni.cc +++ b/runtime/check_jni.cc @@ -650,6 +650,24 @@ class ScopedCheck { } mirror::Object* obj = soa.Decode<mirror::Object*>(java_object); + if (obj == nullptr) { + // Either java_object is invalid or is a cleared weak. + IndirectRef ref = reinterpret_cast<IndirectRef>(java_object); + bool okay; + if (GetIndirectRefKind(ref) != kWeakGlobal) { + okay = false; + } else { + obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref); + okay = Runtime::Current()->IsClearedJniWeakGlobal(obj); + } + if (!okay) { + AbortF("%s is an invalid %s: %p (%p)", + what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), + java_object, obj); + return false; + } + } + if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) { Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR)); AbortF("%s is an invalid %s: %p (%p)", @@ -784,8 +802,7 @@ class ScopedCheck { mirror::Class* c = soa.Decode<mirror::Class*>(jc); if (c == nullptr) { *msg += "NULL"; - } else if (c == kInvalidIndirectRefObject || - !Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) { + } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) { StringAppendF(msg, "INVALID POINTER:%p", jc); } else if (!c->IsClass()) { *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c); @@ -1453,12 +1470,13 @@ class CheckJNI { } static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) { - // Note: we use "Ep" rather than "EL" because this is the one JNI function that it's okay to - // pass an invalid reference to. + // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to + // know the object is invalid. The spec says that passing invalid objects or even ones that + // are deleted isn't supported. ScopedObjectAccess soa(env); ScopedCheck sc(kFlag_Default, __FUNCTION__); - JniValueType args[2] = {{.E = env }, {.p = obj}}; - if (sc.Check(soa, true, "Ep", args)) { + JniValueType args[2] = {{.E = env }, {.L = obj}}; + if (sc.Check(soa, true, "EL", args)) { JniValueType result; result.w = baseEnv(env)->GetObjectRefType(env, obj); if (sc.Check(soa, false, "w", &result)) { diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index d05f7af870..1306546801 100644 --- a/runtime/class_linker-inl.h +++ b/runtime/class_linker-inl.h @@ -155,6 +155,11 @@ inline mirror::ArtField* ClassLinker::ResolveField(uint32_t field_idx, mirror::A return resolved_field; } +inline mirror::Object* ClassLinker::AllocObject(Thread* self) { + return GetClassRoot(kJavaLangObject)->Alloc<false, false>(self, + Runtime::Current()->GetHeap()->GetCurrentAllocator()); +} + template <class T> inline mirror::ObjectArray<T>* ClassLinker::AllocObjectArray(Thread* self, size_t length) { return mirror::ObjectArray<T>::Alloc(self, GetClassRoot(kObjectArrayClass), length); diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 064a85d130..a7a68b7546 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -288,6 +288,9 @@ class ClassLinker { InstructionSet instruction_set, std::string* error_msg); + // Allocate an instance of a java.lang.Object. + mirror::Object* AllocObject(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // TODO: replace this with multiple methods that allocate the correct managed type. template <class T> mirror::ObjectArray<T>* AllocObjectArray(Thread* self, size_t length) diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 9136f9f8d8..8b8e7c827e 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -132,12 +132,12 @@ class AllocRecord { } void SetType(mirror::Class* t) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - type_ = Dbg::GetTypeCache().Add(t); + type_ = Dbg::GetTypeCache()->Add(t); } size_t GetDepth() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { size_t depth = 0; - while (depth < kMaxAllocRecordStackDepth && stack_[depth].Method() != NULL) { + while (depth < kMaxAllocRecordStackDepth && stack_[depth].Method() != nullptr) { ++depth; } return depth; @@ -168,7 +168,7 @@ class AllocRecord { jobject type_; // This is a weak global. size_t byte_count_; uint16_t thin_lock_id_; - AllocRecordStackTraceElement stack_[kMaxAllocRecordStackDepth]; // Unused entries have NULL method. + AllocRecordStackTraceElement stack_[kMaxAllocRecordStackDepth]; // Unused entries have nullptr method. }; class Breakpoint { @@ -287,7 +287,7 @@ static bool gJdwpConfigured = false; static JDWP::JdwpOptions gJdwpOptions; // Runtime JDWP state. -static JDWP::JdwpState* gJdwpState = NULL; +static JDWP::JdwpState* gJdwpState = nullptr; static bool gDebuggerConnected; // debugger or DDMS is connected. static bool gDebuggerActive; // debugger is making requests. static bool gDisposed; // debugger called VirtualMachine.Dispose, so we should drop the connection. @@ -391,58 +391,60 @@ static bool IsSuspendedForDebugger(ScopedObjectAccessUnchecked& soa, Thread* thr return thread->IsSuspended() && thread->GetDebugSuspendCount() > 0; } -static mirror::Array* DecodeArray(JDWP::RefTypeId id, JDWP::JdwpError& status) +static mirror::Array* DecodeNonNullArray(JDWP::RefTypeId id, JDWP::JdwpError* error) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::Object* o = gRegistry->Get<mirror::Object*>(id); - if (o == NULL || o == ObjectRegistry::kInvalidObject) { - status = JDWP::ERR_INVALID_OBJECT; - return NULL; + mirror::Object* o = gRegistry->Get<mirror::Object*>(id, error); + if (o == nullptr) { + *error = JDWP::ERR_INVALID_OBJECT; + return nullptr; } if (!o->IsArrayInstance()) { - status = JDWP::ERR_INVALID_ARRAY; - return NULL; + *error = JDWP::ERR_INVALID_ARRAY; + return nullptr; } - status = JDWP::ERR_NONE; + *error = JDWP::ERR_NONE; return o->AsArray(); } -static mirror::Class* DecodeClass(JDWP::RefTypeId id, JDWP::JdwpError& status) +static mirror::Class* DecodeClass(JDWP::RefTypeId id, JDWP::JdwpError* error) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::Object* o = gRegistry->Get<mirror::Object*>(id); - if (o == NULL || o == ObjectRegistry::kInvalidObject) { - status = JDWP::ERR_INVALID_OBJECT; - return NULL; + mirror::Object* o = gRegistry->Get<mirror::Object*>(id, error); + if (o == nullptr) { + *error = JDWP::ERR_INVALID_OBJECT; + return nullptr; } if (!o->IsClass()) { - status = JDWP::ERR_INVALID_CLASS; - return NULL; + *error = JDWP::ERR_INVALID_CLASS; + return nullptr; } - status = JDWP::ERR_NONE; + *error = JDWP::ERR_NONE; return o->AsClass(); } -static JDWP::JdwpError DecodeThread(ScopedObjectAccessUnchecked& soa, JDWP::ObjectId thread_id, Thread*& thread) +static Thread* DecodeThread(ScopedObjectAccessUnchecked& soa, JDWP::ObjectId thread_id, + JDWP::JdwpError* error) EXCLUSIVE_LOCKS_REQUIRED(Locks::thread_list_lock_) LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::Object* thread_peer = gRegistry->Get<mirror::Object*>(thread_id); - if (thread_peer == NULL || thread_peer == ObjectRegistry::kInvalidObject) { + mirror::Object* thread_peer = gRegistry->Get<mirror::Object*>(thread_id, error); + if (thread_peer == nullptr) { // This isn't even an object. - return JDWP::ERR_INVALID_OBJECT; + *error = JDWP::ERR_INVALID_OBJECT; + return nullptr; } mirror::Class* java_lang_Thread = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread); if (!java_lang_Thread->IsAssignableFrom(thread_peer->GetClass())) { // This isn't a thread. - return JDWP::ERR_INVALID_THREAD; + *error = JDWP::ERR_INVALID_THREAD; + return nullptr; } - thread = Thread::FromManagedThread(soa, thread_peer); - if (thread == NULL) { - // This is a java.lang.Thread without a Thread*. Must be a zombie. - return JDWP::ERR_THREAD_NOT_ALIVE; - } - return JDWP::ERR_NONE; + Thread* thread = Thread::FromManagedThread(soa, thread_peer); + // If thread is null then this a java.lang.Thread without a Thread*. Must be a un-started or a + // zombie. + *error = (thread == nullptr) ? JDWP::ERR_THREAD_NOT_ALIVE : JDWP::ERR_NONE; + return thread; } static JDWP::JdwpTag BasicTagFromDescriptor(const char* descriptor) { @@ -460,7 +462,7 @@ static JDWP::JdwpTag BasicTagFromClass(mirror::Class* klass) static JDWP::JdwpTag TagFromClass(const ScopedObjectAccessUnchecked& soa, mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - CHECK(c != NULL); + CHECK(c != nullptr); if (c->IsArrayClass()) { return JDWP::JT_ARRAY; } @@ -503,7 +505,7 @@ static JDWP::JdwpTag TagFromClass(const ScopedObjectAccessUnchecked& soa, mirror */ static JDWP::JdwpTag TagFromObject(const ScopedObjectAccessUnchecked& soa, mirror::Object* o) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return (o == NULL) ? JDWP::JT_OBJECT : TagFromClass(soa, o->GetClass()); + return (o == nullptr) ? JDWP::JT_OBJECT : TagFromClass(soa, o->GetClass()); } static bool IsPrimitiveTag(JDWP::JdwpTag tag) { @@ -646,7 +648,7 @@ void Dbg::StartJdwp() { // debugger, passively listen for a debugger, or block waiting for a // debugger. gJdwpState = JDWP::JdwpState::Create(&gJdwpOptions); - if (gJdwpState == NULL) { + if (gJdwpState == nullptr) { // We probably failed because some other process has the port already, which means that // if we don't abort the user is likely to think they're talking to us when they're actually // talking to that other process. @@ -708,7 +710,7 @@ DebugInvokeReq* Dbg::GetInvokeReq() { } Thread* Dbg::GetDebugThread() { - return (gJdwpState != NULL) ? gJdwpState->GetDebugThread() : NULL; + return (gJdwpState != nullptr) ? gJdwpState->GetDebugThread() : nullptr; } void Dbg::ClearWaitForEventThread() { @@ -826,12 +828,14 @@ void Dbg::UndoDebuggerSuspensions() { } std::string Dbg::GetClassName(JDWP::RefTypeId class_id) { - mirror::Object* o = gRegistry->Get<mirror::Object*>(class_id); - if (o == NULL) { - return "NULL"; - } - if (o == ObjectRegistry::kInvalidObject) { - return StringPrintf("invalid object %p", reinterpret_cast<void*>(class_id)); + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get<mirror::Object*>(class_id, &error); + if (o == nullptr) { + if (error == JDWP::ERR_NONE) { + return "NULL"; + } else { + return StringPrintf("invalid object %p", reinterpret_cast<void*>(class_id)); + } } if (!o->IsClass()) { return StringPrintf("non-class %p", o); // This is only used for debugging output anyway. @@ -840,34 +844,37 @@ std::string Dbg::GetClassName(JDWP::RefTypeId class_id) { return DescriptorToName(o->AsClass()->GetDescriptor(&temp)); } -JDWP::JdwpError Dbg::GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId& class_object_id) { +JDWP::JdwpError Dbg::GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId* class_object_id) { JDWP::JdwpError status; - mirror::Class* c = DecodeClass(id, status); - if (c == NULL) { + mirror::Class* c = DecodeClass(id, &status); + if (c == nullptr) { + *class_object_id = 0; return status; } - class_object_id = gRegistry->Add(c); + *class_object_id = gRegistry->Add(c); return JDWP::ERR_NONE; } -JDWP::JdwpError Dbg::GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId& superclass_id) { +JDWP::JdwpError Dbg::GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId* superclass_id) { JDWP::JdwpError status; - mirror::Class* c = DecodeClass(id, status); - if (c == NULL) { + mirror::Class* c = DecodeClass(id, &status); + if (c == nullptr) { + *superclass_id = 0; return status; } if (c->IsInterface()) { // http://code.google.com/p/android/issues/detail?id=20856 - superclass_id = 0; + *superclass_id = 0; } else { - superclass_id = gRegistry->Add(c->GetSuperClass()); + *superclass_id = gRegistry->Add(c->GetSuperClass()); } return JDWP::ERR_NONE; } JDWP::JdwpError Dbg::GetClassLoader(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) { - mirror::Object* o = gRegistry->Get<mirror::Object*>(id); - if (o == NULL || o == ObjectRegistry::kInvalidObject) { + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get<mirror::Object*>(id, &error); + if (o == nullptr) { return JDWP::ERR_INVALID_OBJECT; } expandBufAddObjectId(pReply, gRegistry->Add(o->GetClass()->GetClassLoader())); @@ -875,10 +882,10 @@ JDWP::JdwpError Dbg::GetClassLoader(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) } JDWP::JdwpError Dbg::GetModifiers(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) { - JDWP::JdwpError status; - mirror::Class* c = DecodeClass(id, status); - if (c == NULL) { - return status; + JDWP::JdwpError error; + mirror::Class* c = DecodeClass(id, &error); + if (c == nullptr) { + return error; } uint32_t access_flags = c->GetAccessFlags() & kAccJavaFlagsMask; @@ -895,10 +902,10 @@ JDWP::JdwpError Dbg::GetModifiers(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) { return JDWP::ERR_NONE; } -JDWP::JdwpError Dbg::GetMonitorInfo(JDWP::ObjectId object_id, JDWP::ExpandBuf* reply) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); - if (o == NULL || o == ObjectRegistry::kInvalidObject) { +JDWP::JdwpError Dbg::GetMonitorInfo(JDWP::ObjectId object_id, JDWP::ExpandBuf* reply) { + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error); + if (o == nullptr) { return JDWP::ERR_INVALID_OBJECT; } @@ -913,10 +920,10 @@ JDWP::JdwpError Dbg::GetMonitorInfo(JDWP::ObjectId object_id, JDWP::ExpandBuf* r Runtime::Current()->GetThreadList()->ResumeAll(); self->TransitionFromSuspendedToRunnable(); - if (monitor_info.owner_ != NULL) { + if (monitor_info.owner_ != nullptr) { expandBufAddObjectId(reply, gRegistry->Add(monitor_info.owner_->GetPeer())); } else { - expandBufAddObjectId(reply, gRegistry->Add(NULL)); + expandBufAddObjectId(reply, gRegistry->Add(nullptr)); } expandBufAdd4BE(reply, monitor_info.entry_count_); expandBufAdd4BE(reply, monitor_info.waiters_.size()); @@ -927,8 +934,8 @@ JDWP::JdwpError Dbg::GetMonitorInfo(JDWP::ObjectId object_id, JDWP::ExpandBuf* r } JDWP::JdwpError Dbg::GetOwnedMonitors(JDWP::ObjectId thread_id, - std::vector<JDWP::ObjectId>& monitors, - std::vector<uint32_t>& stack_depths) { + std::vector<JDWP::ObjectId>* monitors, + std::vector<uint32_t>* stack_depths) { struct OwnedMonitorVisitor : public StackVisitor { OwnedMonitorVisitor(Thread* thread, Context* context, std::vector<JDWP::ObjectId>* monitor_vector, @@ -955,16 +962,17 @@ JDWP::JdwpError Dbg::GetOwnedMonitors(JDWP::ObjectId thread_id, } size_t current_stack_depth; - std::vector<JDWP::ObjectId>* monitors; - std::vector<uint32_t>* stack_depths; + std::vector<JDWP::ObjectId>* const monitors; + std::vector<uint32_t>* const stack_depths; }; ScopedObjectAccessUnchecked soa(Thread::Current()); Thread* thread; { MutexLock mu(soa.Self(), *Locks::thread_list_lock_); - JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); - if (error != JDWP::ERR_NONE) { + JDWP::JdwpError error; + thread = DecodeThread(soa, thread_id, &error); + if (thread == nullptr) { return error; } if (!IsSuspendedForDebugger(soa, thread)) { @@ -972,20 +980,21 @@ JDWP::JdwpError Dbg::GetOwnedMonitors(JDWP::ObjectId thread_id, } } std::unique_ptr<Context> context(Context::Create()); - OwnedMonitorVisitor visitor(thread, context.get(), &monitors, &stack_depths); + OwnedMonitorVisitor visitor(thread, context.get(), monitors, stack_depths); visitor.WalkStack(); return JDWP::ERR_NONE; } JDWP::JdwpError Dbg::GetContendedMonitor(JDWP::ObjectId thread_id, - JDWP::ObjectId& contended_monitor) { + JDWP::ObjectId* contended_monitor) { mirror::Object* contended_monitor_obj; ScopedObjectAccessUnchecked soa(Thread::Current()); + *contended_monitor = 0; { MutexLock mu(soa.Self(), *Locks::thread_list_lock_); - Thread* thread; - JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); - if (error != JDWP::ERR_NONE) { + JDWP::JdwpError error; + Thread* thread = DecodeThread(soa, thread_id, &error); + if (thread == nullptr) { return error; } if (!IsSuspendedForDebugger(soa, thread)) { @@ -995,108 +1004,105 @@ JDWP::JdwpError Dbg::GetContendedMonitor(JDWP::ObjectId thread_id, } // Add() requires the thread_list_lock_ not held to avoid the lock // level violation. - contended_monitor = gRegistry->Add(contended_monitor_obj); + *contended_monitor = gRegistry->Add(contended_monitor_obj); return JDWP::ERR_NONE; } JDWP::JdwpError Dbg::GetInstanceCounts(const std::vector<JDWP::RefTypeId>& class_ids, - std::vector<uint64_t>& counts) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + std::vector<uint64_t>* counts) { gc::Heap* heap = Runtime::Current()->GetHeap(); heap->CollectGarbage(false); std::vector<mirror::Class*> classes; - counts.clear(); + counts->clear(); for (size_t i = 0; i < class_ids.size(); ++i) { - JDWP::JdwpError status; - mirror::Class* c = DecodeClass(class_ids[i], status); - if (c == NULL) { - return status; + JDWP::JdwpError error; + mirror::Class* c = DecodeClass(class_ids[i], &error); + if (c == nullptr) { + return error; } classes.push_back(c); - counts.push_back(0); + counts->push_back(0); } - heap->CountInstances(classes, false, &counts[0]); + heap->CountInstances(classes, false, &(*counts)[0]); return JDWP::ERR_NONE; } -JDWP::JdwpError Dbg::GetInstances(JDWP::RefTypeId class_id, int32_t max_count, std::vector<JDWP::ObjectId>& instances) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +JDWP::JdwpError Dbg::GetInstances(JDWP::RefTypeId class_id, int32_t max_count, + std::vector<JDWP::ObjectId>* instances) { gc::Heap* heap = Runtime::Current()->GetHeap(); // We only want reachable instances, so do a GC. heap->CollectGarbage(false); - JDWP::JdwpError status; - mirror::Class* c = DecodeClass(class_id, status); + JDWP::JdwpError error; + mirror::Class* c = DecodeClass(class_id, &error); if (c == nullptr) { - return status; + return error; } std::vector<mirror::Object*> raw_instances; Runtime::Current()->GetHeap()->GetInstances(c, max_count, raw_instances); for (size_t i = 0; i < raw_instances.size(); ++i) { - instances.push_back(gRegistry->Add(raw_instances[i])); + instances->push_back(gRegistry->Add(raw_instances[i])); } return JDWP::ERR_NONE; } JDWP::JdwpError Dbg::GetReferringObjects(JDWP::ObjectId object_id, int32_t max_count, - std::vector<JDWP::ObjectId>& referring_objects) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + std::vector<JDWP::ObjectId>* referring_objects) { gc::Heap* heap = Runtime::Current()->GetHeap(); heap->CollectGarbage(false); - mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); - if (o == NULL || o == ObjectRegistry::kInvalidObject) { + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error); + if (o == nullptr) { return JDWP::ERR_INVALID_OBJECT; } std::vector<mirror::Object*> raw_instances; heap->GetReferringObjects(o, max_count, raw_instances); for (size_t i = 0; i < raw_instances.size(); ++i) { - referring_objects.push_back(gRegistry->Add(raw_instances[i])); + referring_objects->push_back(gRegistry->Add(raw_instances[i])); } return JDWP::ERR_NONE; } -JDWP::JdwpError Dbg::DisableCollection(JDWP::ObjectId object_id) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); - if (o == NULL || o == ObjectRegistry::kInvalidObject) { +JDWP::JdwpError Dbg::DisableCollection(JDWP::ObjectId object_id) { + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error); + if (o == nullptr) { return JDWP::ERR_INVALID_OBJECT; } gRegistry->DisableCollection(object_id); return JDWP::ERR_NONE; } -JDWP::JdwpError Dbg::EnableCollection(JDWP::ObjectId object_id) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); +JDWP::JdwpError Dbg::EnableCollection(JDWP::ObjectId object_id) { + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error); // Unlike DisableCollection, JDWP specs do not state an invalid object causes an error. The RI // also ignores these cases and never return an error. However it's not obvious why this command // should behave differently from DisableCollection and IsCollected commands. So let's be more // strict and return an error if this happens. - if (o == NULL || o == ObjectRegistry::kInvalidObject) { + if (o == nullptr) { return JDWP::ERR_INVALID_OBJECT; } gRegistry->EnableCollection(object_id); return JDWP::ERR_NONE; } -JDWP::JdwpError Dbg::IsCollected(JDWP::ObjectId object_id, bool& is_collected) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +JDWP::JdwpError Dbg::IsCollected(JDWP::ObjectId object_id, bool* is_collected) { + *is_collected = true; if (object_id == 0) { // Null object id is invalid. return JDWP::ERR_INVALID_OBJECT; } // JDWP specs state an INVALID_OBJECT error is returned if the object ID is not valid. However // the RI seems to ignore this and assume object has been collected. - mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); - if (o == NULL || o == ObjectRegistry::kInvalidObject) { - is_collected = true; - } else { - is_collected = gRegistry->IsCollected(object_id); + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error); + if (o != nullptr) { + *is_collected = gRegistry->IsCollected(object_id); } return JDWP::ERR_NONE; } -void Dbg::DisposeObject(JDWP::ObjectId object_id, uint32_t reference_count) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +void Dbg::DisposeObject(JDWP::ObjectId object_id, uint32_t reference_count) { gRegistry->DisposeObject(object_id, reference_count); } @@ -1113,10 +1119,10 @@ static JDWP::JdwpTypeTag GetTypeTag(mirror::Class* klass) } JDWP::JdwpError Dbg::GetReflectedType(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) { - JDWP::JdwpError status; - mirror::Class* c = DecodeClass(class_id, status); - if (c == NULL) { - return status; + JDWP::JdwpError error; + mirror::Class* c = DecodeClass(class_id, &error); + if (c == nullptr) { + return error; } JDWP::JdwpTypeTag type_tag = GetTypeTag(c); @@ -1125,12 +1131,12 @@ JDWP::JdwpError Dbg::GetReflectedType(JDWP::RefTypeId class_id, JDWP::ExpandBuf* return JDWP::ERR_NONE; } -void Dbg::GetClassList(std::vector<JDWP::RefTypeId>& classes) { +void Dbg::GetClassList(std::vector<JDWP::RefTypeId>* classes) { // Get the complete list of reference classes (i.e. all classes except // the primitive types). // Returns a newly-allocated buffer full of RefTypeId values. struct ClassListCreator { - explicit ClassListCreator(std::vector<JDWP::RefTypeId>& classes) : classes(classes) { + explicit ClassListCreator(std::vector<JDWP::RefTypeId>* classes) : classes(classes) { } static bool Visit(mirror::Class* c, void* arg) { @@ -1141,12 +1147,12 @@ void Dbg::GetClassList(std::vector<JDWP::RefTypeId>& classes) { // annotalysis. bool Visit(mirror::Class* c) NO_THREAD_SAFETY_ANALYSIS { if (!c->IsPrimitive()) { - classes.push_back(gRegistry->AddRefType(c)); + classes->push_back(gRegistry->AddRefType(c)); } return true; } - std::vector<JDWP::RefTypeId>& classes; + std::vector<JDWP::RefTypeId>* const classes; }; ClassListCreator clc(classes); @@ -1155,10 +1161,10 @@ void Dbg::GetClassList(std::vector<JDWP::RefTypeId>& classes) { JDWP::JdwpError Dbg::GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* pTypeTag, uint32_t* pStatus, std::string* pDescriptor) { - JDWP::JdwpError status; - mirror::Class* c = DecodeClass(class_id, status); - if (c == NULL) { - return status; + JDWP::JdwpError error; + mirror::Class* c = DecodeClass(class_id, &error); + if (c == nullptr) { + return error; } if (c->IsArrayClass()) { @@ -1173,26 +1179,26 @@ JDWP::JdwpError Dbg::GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* p *pTypeTag = c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS; } - if (pDescriptor != NULL) { + if (pDescriptor != nullptr) { std::string temp; *pDescriptor = c->GetDescriptor(&temp); } return JDWP::ERR_NONE; } -void Dbg::FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>& ids) { +void Dbg::FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>* ids) { std::vector<mirror::Class*> classes; Runtime::Current()->GetClassLinker()->LookupClasses(descriptor, classes); - ids.clear(); + ids->clear(); for (size_t i = 0; i < classes.size(); ++i) { - ids.push_back(gRegistry->Add(classes[i])); + ids->push_back(gRegistry->Add(classes[i])); } } -JDWP::JdwpError Dbg::GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* pReply) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); - if (o == NULL || o == ObjectRegistry::kInvalidObject) { +JDWP::JdwpError Dbg::GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* pReply) { + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error); + if (o == nullptr) { return JDWP::ERR_INVALID_OBJECT; } @@ -1206,37 +1212,39 @@ JDWP::JdwpError Dbg::GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* } JDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string* signature) { - JDWP::JdwpError status; - mirror::Class* c = DecodeClass(class_id, status); - if (c == NULL) { - return status; + JDWP::JdwpError error; + mirror::Class* c = DecodeClass(class_id, &error); + if (c == nullptr) { + return error; } std::string temp; *signature = c->GetDescriptor(&temp); return JDWP::ERR_NONE; } -JDWP::JdwpError Dbg::GetSourceFile(JDWP::RefTypeId class_id, std::string& result) { - JDWP::JdwpError status; - mirror::Class* c = DecodeClass(class_id, status); +JDWP::JdwpError Dbg::GetSourceFile(JDWP::RefTypeId class_id, std::string* result) { + JDWP::JdwpError error; + mirror::Class* c = DecodeClass(class_id, &error); if (c == nullptr) { - return status; + return error; } const char* source_file = c->GetSourceFile(); if (source_file == nullptr) { return JDWP::ERR_ABSENT_INFORMATION; } - result = source_file; + *result = source_file; return JDWP::ERR_NONE; } -JDWP::JdwpError Dbg::GetObjectTag(JDWP::ObjectId object_id, uint8_t& tag) { +JDWP::JdwpError Dbg::GetObjectTag(JDWP::ObjectId object_id, uint8_t* tag) { ScopedObjectAccessUnchecked soa(Thread::Current()); - mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); - if (o == ObjectRegistry::kInvalidObject) { - return JDWP::ERR_INVALID_OBJECT; + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error); + if (error != JDWP::ERR_NONE) { + *tag = JDWP::JT_VOID; + return error; } - tag = TagFromObject(soa, o); + *tag = TagFromObject(soa, o); return JDWP::ERR_NONE; } @@ -1270,21 +1278,21 @@ size_t Dbg::GetTagWidth(JDWP::JdwpTag tag) { } } -JDWP::JdwpError Dbg::GetArrayLength(JDWP::ObjectId array_id, int& length) { - JDWP::JdwpError status; - mirror::Array* a = DecodeArray(array_id, status); - if (a == NULL) { - return status; +JDWP::JdwpError Dbg::GetArrayLength(JDWP::ObjectId array_id, int32_t* length) { + JDWP::JdwpError error; + mirror::Array* a = DecodeNonNullArray(array_id, &error); + if (a == nullptr) { + return error; } - length = a->GetLength(); + *length = a->GetLength(); return JDWP::ERR_NONE; } JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count, JDWP::ExpandBuf* pReply) { - JDWP::JdwpError status; - mirror::Array* a = DecodeArray(array_id, status); + JDWP::JdwpError error; + mirror::Array* a = DecodeNonNullArray(array_id, &error); if (a == nullptr) { - return status; + return error; } if (offset < 0 || count < 0 || offset > a->GetLength() || a->GetLength() - offset < count) { @@ -1327,24 +1335,23 @@ JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count, } template <typename T> -static void CopyArrayData(mirror::Array* a, JDWP::Request& src, int offset, int count) +static void CopyArrayData(mirror::Array* a, JDWP::Request* src, int offset, int count) NO_THREAD_SAFETY_ANALYSIS { // TODO: fix when annotalysis correctly handles non-member functions. DCHECK(a->GetClass()->IsPrimitiveArray()); T* dst = reinterpret_cast<T*>(a->GetRawData(sizeof(T), offset)); for (int i = 0; i < count; ++i) { - *dst++ = src.ReadValue(sizeof(T)); + *dst++ = src->ReadValue(sizeof(T)); } } JDWP::JdwpError Dbg::SetArrayElements(JDWP::ObjectId array_id, int offset, int count, - JDWP::Request& request) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - JDWP::JdwpError status; - mirror::Array* dst = DecodeArray(array_id, status); - if (dst == NULL) { - return status; + JDWP::Request* request) { + JDWP::JdwpError error; + mirror::Array* dst = DecodeNonNullArray(array_id, &error); + if (dst == nullptr) { + return error; } if (offset < 0 || count < 0 || offset > dst->GetLength() || dst->GetLength() - offset < count) { @@ -1367,10 +1374,11 @@ JDWP::JdwpError Dbg::SetArrayElements(JDWP::ObjectId array_id, int offset, int c } else { mirror::ObjectArray<mirror::Object>* oa = dst->AsObjectArray<mirror::Object>(); for (int i = 0; i < count; ++i) { - JDWP::ObjectId id = request.ReadObjectId(); - mirror::Object* o = gRegistry->Get<mirror::Object*>(id); - if (o == ObjectRegistry::kInvalidObject) { - return JDWP::ERR_INVALID_OBJECT; + JDWP::ObjectId id = request->ReadObjectId(); + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get<mirror::Object*>(id, &error); + if (error != JDWP::ERR_NONE) { + return error; } oa->Set<false>(offset + i, o); } @@ -1383,13 +1391,14 @@ JDWP::ObjectId Dbg::CreateString(const std::string& str) { return gRegistry->Add(mirror::String::AllocFromModifiedUtf8(Thread::Current(), str.c_str())); } -JDWP::JdwpError Dbg::CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId& new_object) { - JDWP::JdwpError status; - mirror::Class* c = DecodeClass(class_id, status); - if (c == NULL) { - return status; +JDWP::JdwpError Dbg::CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId* new_object) { + JDWP::JdwpError error; + mirror::Class* c = DecodeClass(class_id, &error); + if (c == nullptr) { + *new_object = 0; + return error; } - new_object = gRegistry->Add(c->AllocObject(Thread::Current())); + *new_object = gRegistry->Add(c->AllocObject(Thread::Current())); return JDWP::ERR_NONE; } @@ -1397,24 +1406,25 @@ JDWP::JdwpError Dbg::CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId& new_ * Used by Eclipse's "Display" view to evaluate "new byte[5]" to get "(byte[]) [0, 0, 0, 0, 0]". */ JDWP::JdwpError Dbg::CreateArrayObject(JDWP::RefTypeId array_class_id, uint32_t length, - JDWP::ObjectId& new_array) { - JDWP::JdwpError status; - mirror::Class* c = DecodeClass(array_class_id, status); - if (c == NULL) { - return status; + JDWP::ObjectId* new_array) { + JDWP::JdwpError error; + mirror::Class* c = DecodeClass(array_class_id, &error); + if (c == nullptr) { + *new_array = 0; + return error; } - new_array = gRegistry->Add(mirror::Array::Alloc<true>(Thread::Current(), c, length, - c->GetComponentSize(), - Runtime::Current()->GetHeap()->GetCurrentAllocator())); + *new_array = gRegistry->Add(mirror::Array::Alloc<true>(Thread::Current(), c, length, + c->GetComponentSize(), + Runtime::Current()->GetHeap()->GetCurrentAllocator())); return JDWP::ERR_NONE; } bool Dbg::MatchType(JDWP::RefTypeId instance_class_id, JDWP::RefTypeId class_id) { - JDWP::JdwpError status; - mirror::Class* c1 = DecodeClass(instance_class_id, status); - CHECK(c1 != NULL); - mirror::Class* c2 = DecodeClass(class_id, status); - CHECK(c2 != NULL); + JDWP::JdwpError error; + mirror::Class* c1 = DecodeClass(instance_class_id, &error); + CHECK(c1 != nullptr); + mirror::Class* c2 = DecodeClass(class_id, &error); + CHECK(c2 != nullptr); return c2->IsAssignableFrom(c1); } @@ -1442,27 +1452,25 @@ static mirror::ArtMethod* FromMethodId(JDWP::MethodId mid) return reinterpret_cast<mirror::ArtMethod*>(static_cast<uintptr_t>(mid)); } -static void SetLocation(JDWP::JdwpLocation& location, mirror::ArtMethod* m, uint32_t dex_pc) +static void SetLocation(JDWP::JdwpLocation* location, mirror::ArtMethod* m, uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (m == NULL) { + if (m == nullptr) { memset(&location, 0, sizeof(location)); } else { mirror::Class* c = m->GetDeclaringClass(); - location.type_tag = GetTypeTag(c); - location.class_id = gRegistry->AddRefType(c); - location.method_id = ToMethodId(m); - location.dex_pc = (m->IsNative() || m->IsProxyMethod()) ? static_cast<uint64_t>(-1) : dex_pc; + location->type_tag = GetTypeTag(c); + location->class_id = gRegistry->AddRefType(c); + location->method_id = ToMethodId(m); + location->dex_pc = (m->IsNative() || m->IsProxyMethod()) ? static_cast<uint64_t>(-1) : dex_pc; } } -std::string Dbg::GetMethodName(JDWP::MethodId method_id) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +std::string Dbg::GetMethodName(JDWP::MethodId method_id) { mirror::ArtMethod* m = FromMethodId(method_id); return m->GetName(); } -std::string Dbg::GetFieldName(JDWP::FieldId field_id) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +std::string Dbg::GetFieldName(JDWP::FieldId field_id) { return FromFieldId(field_id)->GetName(); } @@ -1525,10 +1533,10 @@ static uint16_t DemangleSlot(uint16_t slot, mirror::ArtMethod* m) } JDWP::JdwpError Dbg::OutputDeclaredFields(JDWP::RefTypeId class_id, bool with_generic, JDWP::ExpandBuf* pReply) { - JDWP::JdwpError status; - mirror::Class* c = DecodeClass(class_id, status); - if (c == NULL) { - return status; + JDWP::JdwpError error; + mirror::Class* c = DecodeClass(class_id, &error); + if (c == nullptr) { + return error; } size_t instance_field_count = c->NumInstanceFields(); @@ -1552,10 +1560,10 @@ JDWP::JdwpError Dbg::OutputDeclaredFields(JDWP::RefTypeId class_id, bool with_ge JDWP::JdwpError Dbg::OutputDeclaredMethods(JDWP::RefTypeId class_id, bool with_generic, JDWP::ExpandBuf* pReply) { - JDWP::JdwpError status; - mirror::Class* c = DecodeClass(class_id, status); - if (c == NULL) { - return status; + JDWP::JdwpError error; + mirror::Class* c = DecodeClass(class_id, &error); + if (c == nullptr) { + return error; } size_t direct_method_count = c->NumDirectMethods(); @@ -1578,12 +1586,12 @@ JDWP::JdwpError Dbg::OutputDeclaredMethods(JDWP::RefTypeId class_id, bool with_g } JDWP::JdwpError Dbg::OutputDeclaredInterfaces(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) { - JDWP::JdwpError status; + JDWP::JdwpError error; Thread* self = Thread::Current(); StackHandleScope<1> hs(self); - Handle<mirror::Class> c(hs.NewHandle(DecodeClass(class_id, status))); + Handle<mirror::Class> c(hs.NewHandle(DecodeClass(class_id, &error))); if (c.Get() == nullptr) { - return status; + return error; } size_t interface_count = c->NumDirectInterfaces(); expandBufAdd4BE(pReply, interface_count); @@ -1594,8 +1602,7 @@ JDWP::JdwpError Dbg::OutputDeclaredInterfaces(JDWP::RefTypeId class_id, JDWP::Ex return JDWP::ERR_NONE; } -void Dbg::OutputLineTable(JDWP::RefTypeId, JDWP::MethodId method_id, JDWP::ExpandBuf* pReply) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +void Dbg::OutputLineTable(JDWP::RefTypeId, JDWP::MethodId method_id, JDWP::ExpandBuf* pReply) { struct DebugCallbackContext { int numItems; JDWP::ExpandBuf* pReply; @@ -1634,7 +1641,7 @@ void Dbg::OutputLineTable(JDWP::RefTypeId, JDWP::MethodId method_id, JDWP::Expan if (code_item != nullptr) { m->GetDexFile()->DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(), - DebugCallbackContext::Callback, NULL, &context); + DebugCallbackContext::Callback, nullptr, &context); } JDWP::Set4BE(expandBufGetBuffer(pReply) + numLinesOffset, context.numItems); @@ -1692,7 +1699,7 @@ void Dbg::OutputVariableTable(JDWP::RefTypeId, JDWP::MethodId method_id, bool wi const DexFile::CodeItem* code_item = m->GetCodeItem(); if (code_item != nullptr) { m->GetDexFile()->DecodeDebugInfo( - code_item, m->IsStatic(), m->GetDexMethodIndex(), NULL, DebugCallbackContext::Callback, + code_item, m->IsStatic(), m->GetDexMethodIndex(), nullptr, DebugCallbackContext::Callback, &context); } @@ -1714,10 +1721,9 @@ void Dbg::OutputFieldValue(JDWP::FieldId field_id, const JValue* field_value, } JDWP::JdwpError Dbg::GetBytecodes(JDWP::RefTypeId, JDWP::MethodId method_id, - std::vector<uint8_t>& bytecodes) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + std::vector<uint8_t>* bytecodes) { mirror::ArtMethod* m = FromMethodId(method_id); - if (m == NULL) { + if (m == nullptr) { return JDWP::ERR_INVALID_METHODID; } const DexFile::CodeItem* code_item = m->GetCodeItem(); @@ -1725,7 +1731,7 @@ JDWP::JdwpError Dbg::GetBytecodes(JDWP::RefTypeId, JDWP::MethodId method_id, const uint8_t* begin = reinterpret_cast<const uint8_t*>(code_item->insns_); const uint8_t* end = begin + byte_count; for (const uint8_t* p = begin; p != end; ++p) { - bytecodes.push_back(*p); + bytecodes->push_back(*p); } return JDWP::ERR_NONE; } @@ -1742,24 +1748,24 @@ static JDWP::JdwpError GetFieldValueImpl(JDWP::RefTypeId ref_type_id, JDWP::Obje JDWP::FieldId field_id, JDWP::ExpandBuf* pReply, bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - JDWP::JdwpError status; - mirror::Class* c = DecodeClass(ref_type_id, status); - if (ref_type_id != 0 && c == NULL) { - return status; + JDWP::JdwpError error; + mirror::Class* c = DecodeClass(ref_type_id, &error); + if (ref_type_id != 0 && c == nullptr) { + return error; } - mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); - if ((!is_static && o == NULL) || o == ObjectRegistry::kInvalidObject) { + mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error); + if ((!is_static && o == nullptr) || error != JDWP::ERR_NONE) { return JDWP::ERR_INVALID_OBJECT; } mirror::ArtField* f = FromFieldId(field_id); mirror::Class* receiver_class = c; - if (receiver_class == NULL && o != NULL) { + if (receiver_class == nullptr && o != nullptr) { receiver_class = o->GetClass(); } - // TODO: should we give up now if receiver_class is NULL? - if (receiver_class != NULL && !f->GetDeclaringClass()->IsAssignableFrom(receiver_class)) { + // TODO: should we give up now if receiver_class is nullptr? + if (receiver_class != nullptr && !f->GetDeclaringClass()->IsAssignableFrom(receiver_class)) { LOG(INFO) << "ERR_INVALID_FIELDID: " << PrettyField(f) << " " << PrettyClass(receiver_class); return JDWP::ERR_INVALID_FIELDID; } @@ -1772,7 +1778,8 @@ static JDWP::JdwpError GetFieldValueImpl(JDWP::RefTypeId ref_type_id, JDWP::Obje } } else { if (f->IsStatic()) { - LOG(WARNING) << "Ignoring non-NULL receiver for ObjectReference.SetValues on static field " << PrettyField(f); + LOG(WARNING) << "Ignoring non-nullptr receiver for ObjectReference.SetValues on static field " + << PrettyField(f); } } if (f->IsStatic()) { @@ -1800,15 +1807,17 @@ JDWP::JdwpError Dbg::GetFieldValue(JDWP::ObjectId object_id, JDWP::FieldId field return GetFieldValueImpl(0, object_id, field_id, pReply, false); } -JDWP::JdwpError Dbg::GetStaticFieldValue(JDWP::RefTypeId ref_type_id, JDWP::FieldId field_id, JDWP::ExpandBuf* pReply) { +JDWP::JdwpError Dbg::GetStaticFieldValue(JDWP::RefTypeId ref_type_id, JDWP::FieldId field_id, + JDWP::ExpandBuf* pReply) { return GetFieldValueImpl(ref_type_id, 0, field_id, pReply, true); } static JDWP::JdwpError SetFieldValueImpl(JDWP::ObjectId object_id, JDWP::FieldId field_id, uint64_t value, int width, bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); - if ((!is_static && o == NULL) || o == ObjectRegistry::kInvalidObject) { + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error); + if ((!is_static && o == nullptr) || error != JDWP::ERR_NONE) { return JDWP::ERR_INVALID_OBJECT; } mirror::ArtField* f = FromFieldId(field_id); @@ -1821,7 +1830,7 @@ static JDWP::JdwpError SetFieldValueImpl(JDWP::ObjectId object_id, JDWP::FieldId } } else { if (f->IsStatic()) { - LOG(WARNING) << "Ignoring non-NULL receiver for ObjectReference.SetValues on static field " << PrettyField(f); + LOG(WARNING) << "Ignoring non-nullptr receiver for ObjectReference.SetValues on static field " << PrettyField(f); } } if (f->IsStatic()) { @@ -1841,11 +1850,11 @@ static JDWP::JdwpError SetFieldValueImpl(JDWP::ObjectId object_id, JDWP::FieldId f->Set32<false>(o, value); } } else { - mirror::Object* v = gRegistry->Get<mirror::Object*>(value); - if (v == ObjectRegistry::kInvalidObject) { + mirror::Object* v = gRegistry->Get<mirror::Object*>(value, &error); + if (error != JDWP::ERR_NONE) { return JDWP::ERR_INVALID_OBJECT; } - if (v != NULL) { + if (v != nullptr) { mirror::Class* field_type; { StackHandleScope<3> hs(Thread::Current()); @@ -1875,7 +1884,9 @@ JDWP::JdwpError Dbg::SetStaticFieldValue(JDWP::FieldId field_id, uint64_t value, } std::string Dbg::StringToUtf8(JDWP::ObjectId string_id) { - mirror::String* s = gRegistry->Get<mirror::String*>(string_id); + JDWP::JdwpError error; + mirror::String* s = gRegistry->Get<mirror::String*>(string_id, &error); + CHECK(s != nullptr) << error; return s->ToModifiedUtf8(); } @@ -1901,40 +1912,42 @@ void Dbg::OutputJValue(JDWP::JdwpTag tag, const JValue* return_value, JDWP::Expa } } -JDWP::JdwpError Dbg::GetThreadName(JDWP::ObjectId thread_id, std::string& name) { +JDWP::JdwpError Dbg::GetThreadName(JDWP::ObjectId thread_id, std::string* name) { ScopedObjectAccessUnchecked soa(Thread::Current()); MutexLock mu(soa.Self(), *Locks::thread_list_lock_); - Thread* thread; - JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); + JDWP::JdwpError error; + Thread* thread = DecodeThread(soa, thread_id, &error); + UNUSED(thread); if (error != JDWP::ERR_NONE && error != JDWP::ERR_THREAD_NOT_ALIVE) { return error; } // We still need to report the zombie threads' names, so we can't just call Thread::GetThreadName. - mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id); + mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id, &error); + CHECK(thread_object != nullptr) << error; mirror::ArtField* java_lang_Thread_name_field = soa.DecodeField(WellKnownClasses::java_lang_Thread_name); mirror::String* s = reinterpret_cast<mirror::String*>(java_lang_Thread_name_field->GetObject(thread_object)); - if (s != NULL) { - name = s->ToModifiedUtf8(); + if (s != nullptr) { + *name = s->ToModifiedUtf8(); } return JDWP::ERR_NONE; } JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply) { ScopedObjectAccess soa(Thread::Current()); - mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id); - if (thread_object == ObjectRegistry::kInvalidObject) { + JDWP::JdwpError error; + mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id, &error); + if (error != JDWP::ERR_NONE) { return JDWP::ERR_INVALID_OBJECT; } const char* old_cause = soa.Self()->StartAssertNoThreadSuspension("Debugger: GetThreadGroup"); // Okay, so it's an object, but is it actually a thread? - JDWP::JdwpError error; { MutexLock mu(soa.Self(), *Locks::thread_list_lock_); - Thread* thread; - error = DecodeThread(soa, thread_id, thread); + Thread* thread = DecodeThread(soa, thread_id, &error); + UNUSED(thread); } if (error == JDWP::ERR_THREAD_NOT_ALIVE) { // Zombie threads are in the null group. @@ -1956,13 +1969,14 @@ JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* p std::string Dbg::GetThreadGroupName(JDWP::ObjectId thread_group_id) { ScopedObjectAccess soa(Thread::Current()); - mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id); - CHECK(thread_group != nullptr); + JDWP::JdwpError error; + mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id, &error); + CHECK(thread_group != nullptr) << error; const char* old_cause = soa.Self()->StartAssertNoThreadSuspension("Debugger: GetThreadGroupName"); mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ThreadGroup); CHECK(c != nullptr); mirror::ArtField* f = c->FindInstanceField("name", "Ljava/lang/String;"); - CHECK(f != NULL); + CHECK(f != nullptr); mirror::String* s = reinterpret_cast<mirror::String*>(f->GetObject(thread_group)); soa.Self()->EndAssertNoThreadSuspension(old_cause); return s->ToModifiedUtf8(); @@ -1970,13 +1984,14 @@ std::string Dbg::GetThreadGroupName(JDWP::ObjectId thread_group_id) { JDWP::ObjectId Dbg::GetThreadGroupParent(JDWP::ObjectId thread_group_id) { ScopedObjectAccessUnchecked soa(Thread::Current()); - mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id); - CHECK(thread_group != nullptr); + JDWP::JdwpError error; + mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id, &error); + CHECK(thread_group != nullptr) << error; const char* old_cause = soa.Self()->StartAssertNoThreadSuspension("Debugger: GetThreadGroupParent"); mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ThreadGroup); CHECK(c != nullptr); mirror::ArtField* f = c->FindInstanceField("parent", "Ljava/lang/ThreadGroup;"); - CHECK(f != NULL); + CHECK(f != nullptr); mirror::Object* parent = f->GetObject(thread_group); soa.Self()->EndAssertNoThreadSuspension(old_cause); return gRegistry->Add(parent); @@ -2037,8 +2052,8 @@ JDWP::JdwpError Dbg::GetThreadStatus(JDWP::ObjectId thread_id, JDWP::JdwpThreadS *pSuspendStatus = JDWP::SUSPEND_STATUS_NOT_SUSPENDED; MutexLock mu(soa.Self(), *Locks::thread_list_lock_); - Thread* thread; - JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); + JDWP::JdwpError error; + Thread* thread = DecodeThread(soa, thread_id, &error); if (error != JDWP::ERR_NONE) { if (error == JDWP::ERR_THREAD_NOT_ALIVE) { *pThreadStatus = JDWP::TS_ZOMBIE; @@ -2058,8 +2073,8 @@ JDWP::JdwpError Dbg::GetThreadStatus(JDWP::ObjectId thread_id, JDWP::JdwpThreadS JDWP::JdwpError Dbg::GetThreadDebugSuspendCount(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply) { ScopedObjectAccess soa(Thread::Current()); MutexLock mu(soa.Self(), *Locks::thread_list_lock_); - Thread* thread; - JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); + JDWP::JdwpError error; + Thread* thread = DecodeThread(soa, thread_id, &error); if (error != JDWP::ERR_NONE) { return error; } @@ -2071,8 +2086,8 @@ JDWP::JdwpError Dbg::GetThreadDebugSuspendCount(JDWP::ObjectId thread_id, JDWP:: JDWP::JdwpError Dbg::Interrupt(JDWP::ObjectId thread_id) { ScopedObjectAccess soa(Thread::Current()); MutexLock mu(soa.Self(), *Locks::thread_list_lock_); - Thread* thread; - JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); + JDWP::JdwpError error; + Thread* thread = DecodeThread(soa, thread_id, &error); if (error != JDWP::ERR_NONE) { return error; } @@ -2080,11 +2095,11 @@ JDWP::JdwpError Dbg::Interrupt(JDWP::ObjectId thread_id) { return JDWP::ERR_NONE; } -void Dbg::GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>& thread_ids) { +void Dbg::GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>* thread_ids) { class ThreadListVisitor { public: ThreadListVisitor(const ScopedObjectAccessUnchecked& soa, mirror::Object* desired_thread_group, - std::vector<JDWP::ObjectId>& thread_ids) + std::vector<JDWP::ObjectId>* thread_ids) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : soa_(soa), desired_thread_group_(desired_thread_group), thread_ids_(thread_ids) {} @@ -2107,15 +2122,15 @@ void Dbg::GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId> } mirror::Object* peer = t->GetPeer(); if (IsInDesiredThreadGroup(peer)) { - thread_ids_.push_back(gRegistry->Add(peer)); + thread_ids_->push_back(gRegistry->Add(peer)); } } private: bool IsInDesiredThreadGroup(mirror::Object* peer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - // peer might be NULL if the thread is still starting up. - if (peer == NULL) { + // peer might be nullptr if the thread is still starting up. + if (peer == nullptr) { // We can't tell the debugger about this thread yet. // TODO: if we identified threads to the debugger by their Thread* // rather than their peer's mirror::Object*, we could fix this. @@ -2123,7 +2138,7 @@ void Dbg::GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId> return false; } // Do we want threads from all thread groups? - if (desired_thread_group_ == NULL) { + if (desired_thread_group_ == nullptr) { return true; } mirror::Object* group = soa_.DecodeField(WellKnownClasses::java_lang_Thread_group)->GetObject(peer); @@ -2132,19 +2147,24 @@ void Dbg::GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId> const ScopedObjectAccessUnchecked& soa_; mirror::Object* const desired_thread_group_; - std::vector<JDWP::ObjectId>& thread_ids_; + std::vector<JDWP::ObjectId>* const thread_ids_; }; ScopedObjectAccessUnchecked soa(Thread::Current()); - mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id); + JDWP::JdwpError error; + mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id, &error); + CHECK_EQ(error, JDWP::ERR_NONE); ThreadListVisitor tlv(soa, thread_group, thread_ids); MutexLock mu(soa.Self(), *Locks::thread_list_lock_); Runtime::Current()->GetThreadList()->ForEach(ThreadListVisitor::Visit, &tlv); } -void Dbg::GetChildThreadGroups(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>& child_thread_group_ids) { +void Dbg::GetChildThreadGroups(JDWP::ObjectId thread_group_id, + std::vector<JDWP::ObjectId>* child_thread_group_ids) { ScopedObjectAccess soa(Thread::Current()); - mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id); + JDWP::JdwpError error; + mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id, &error); + CHECK(thread_group != nullptr) << error; // Get the ArrayList<ThreadGroup> "groups" out of this thread group... mirror::ArtField* groups_field = thread_group->GetClass()->FindInstanceField("groups", "Ljava/util/List;"); @@ -2159,15 +2179,14 @@ void Dbg::GetChildThreadGroups(JDWP::ObjectId thread_group_id, std::vector<JDWP: // Copy the first 'size' elements out of the array into the result. for (int32_t i = 0; i < size; ++i) { - child_thread_group_ids.push_back(gRegistry->Add(groups_array->Get(i))); + child_thread_group_ids->push_back(gRegistry->Add(groups_array->Get(i))); } } -static int GetStackDepth(Thread* thread) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +static int GetStackDepth(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { struct CountStackDepthVisitor : public StackVisitor { explicit CountStackDepthVisitor(Thread* thread) - : StackVisitor(thread, NULL), depth(0) {} + : StackVisitor(thread, nullptr), depth(0) {} // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses // annotalysis. @@ -2185,18 +2204,19 @@ static int GetStackDepth(Thread* thread) return visitor.depth; } -JDWP::JdwpError Dbg::GetThreadFrameCount(JDWP::ObjectId thread_id, size_t& result) { +JDWP::JdwpError Dbg::GetThreadFrameCount(JDWP::ObjectId thread_id, size_t* result) { ScopedObjectAccess soa(Thread::Current()); MutexLock mu(soa.Self(), *Locks::thread_list_lock_); - Thread* thread; - JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); + JDWP::JdwpError error; + *result = 0; + Thread* thread = DecodeThread(soa, thread_id, &error); if (error != JDWP::ERR_NONE) { return error; } if (!IsSuspendedForDebugger(soa, thread)) { return JDWP::ERR_THREAD_NOT_SUSPENDED; } - result = GetStackDepth(thread); + *result = GetStackDepth(thread); return JDWP::ERR_NONE; } @@ -2206,7 +2226,7 @@ JDWP::JdwpError Dbg::GetThreadFrames(JDWP::ObjectId thread_id, size_t start_fram public: GetFrameVisitor(Thread* thread, size_t start_frame, size_t frame_count, JDWP::ExpandBuf* buf) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) - : StackVisitor(thread, NULL), depth_(0), + : StackVisitor(thread, nullptr), depth_(0), start_frame_(start_frame), frame_count_(frame_count), buf_(buf) { expandBufAdd4BE(buf_, frame_count_); } @@ -2223,7 +2243,7 @@ JDWP::JdwpError Dbg::GetThreadFrames(JDWP::ObjectId thread_id, size_t start_fram if (depth_ >= start_frame_) { JDWP::FrameId frame_id(GetFrameId()); JDWP::JdwpLocation location; - SetLocation(location, GetMethod(), GetDexPc()); + SetLocation(&location, GetMethod(), GetDexPc()); VLOG(jdwp) << StringPrintf(" Frame %3zd: id=%3" PRIu64 " ", depth_, frame_id) << location; expandBufAdd8BE(buf_, frame_id); expandBufAddLocation(buf_, location); @@ -2241,8 +2261,8 @@ JDWP::JdwpError Dbg::GetThreadFrames(JDWP::ObjectId thread_id, size_t start_fram ScopedObjectAccessUnchecked soa(Thread::Current()); MutexLock mu(soa.Self(), *Locks::thread_list_lock_); - Thread* thread; - JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); + JDWP::JdwpError error; + Thread* thread = DecodeThread(soa, thread_id, &error); if (error != JDWP::ERR_NONE) { return error; } @@ -2269,12 +2289,13 @@ void Dbg::ResumeVM() { JDWP::JdwpError Dbg::SuspendThread(JDWP::ObjectId thread_id, bool request_suspension) { Thread* self = Thread::Current(); - ScopedLocalRef<jobject> peer(self->GetJniEnv(), NULL); + ScopedLocalRef<jobject> peer(self->GetJniEnv(), nullptr); { ScopedObjectAccess soa(self); - peer.reset(soa.AddLocalReference<jobject>(gRegistry->Get<mirror::Object*>(thread_id))); + JDWP::JdwpError error; + peer.reset(soa.AddLocalReference<jobject>(gRegistry->Get<mirror::Object*>(thread_id, &error))); } - if (peer.get() == NULL) { + if (peer.get() == nullptr) { return JDWP::ERR_THREAD_NOT_ALIVE; } // Suspend thread to build stack trace. Take suspend thread lock to avoid races with threads @@ -2284,7 +2305,7 @@ JDWP::JdwpError Dbg::SuspendThread(JDWP::ObjectId thread_id, bool request_suspen ThreadList* thread_list = Runtime::Current()->GetThreadList(); Thread* thread = thread_list->SuspendThreadByPeer(peer.get(), request_suspension, true, &timed_out); - if (thread != NULL) { + if (thread != nullptr) { return JDWP::ERR_NONE; } else if (timed_out) { return JDWP::ERR_INTERNAL; @@ -2295,13 +2316,15 @@ JDWP::JdwpError Dbg::SuspendThread(JDWP::ObjectId thread_id, bool request_suspen void Dbg::ResumeThread(JDWP::ObjectId thread_id) { ScopedObjectAccessUnchecked soa(Thread::Current()); - mirror::Object* peer = gRegistry->Get<mirror::Object*>(thread_id); + JDWP::JdwpError error; + mirror::Object* peer = gRegistry->Get<mirror::Object*>(thread_id, &error); + CHECK(peer != nullptr) << error; Thread* thread; { MutexLock mu(soa.Self(), *Locks::thread_list_lock_); thread = Thread::FromManagedThread(soa, peer); } - if (thread == NULL) { + if (thread == nullptr) { LOG(WARNING) << "No such thread for resume: " << peer; return; } @@ -2322,7 +2345,7 @@ void Dbg::SuspendSelf() { struct GetThisVisitor : public StackVisitor { GetThisVisitor(Thread* thread, Context* context, JDWP::FrameId frame_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) - : StackVisitor(thread, context), this_object(NULL), frame_id(frame_id) {} + : StackVisitor(thread, context), this_object(nullptr), frame_id(frame_id) {} // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses // annotalysis. @@ -2345,7 +2368,8 @@ JDWP::JdwpError Dbg::GetThisObject(JDWP::ObjectId thread_id, JDWP::FrameId frame Thread* thread; { MutexLock mu(soa.Self(), *Locks::thread_list_lock_); - JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); + JDWP::JdwpError error; + thread = DecodeThread(soa, thread_id, &error); if (error != JDWP::ERR_NONE) { return error; } @@ -2514,8 +2538,8 @@ JDWP::JdwpError Dbg::GetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame ScopedObjectAccessUnchecked soa(Thread::Current()); MutexLock mu(soa.Self(), *Locks::thread_list_lock_); - Thread* thread; - JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); + JDWP::JdwpError error; + Thread* thread = DecodeThread(soa, thread_id, &error); if (error != JDWP::ERR_NONE) { return error; } @@ -2596,9 +2620,11 @@ JDWP::JdwpError Dbg::SetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame case JDWP::JT_THREAD: case JDWP::JT_THREAD_GROUP: { CHECK_EQ(width_, sizeof(JDWP::ObjectId)); - mirror::Object* o = gRegistry->Get<mirror::Object*>(static_cast<JDWP::ObjectId>(value_)); - if (o == ObjectRegistry::kInvalidObject) { - VLOG(jdwp) << tag_ << " object " << o << " is an invalid object"; + JDWP::JdwpError error; + mirror::Object* o = + gRegistry->Get<mirror::Object*>(static_cast<JDWP::ObjectId>(value_), &error); + if (error != JDWP::ERR_NONE) { + VLOG(jdwp) << tag_ << " object " << value_ << " is an invalid object"; error_ = JDWP::ERR_INVALID_OBJECT; } else if (!SetVReg(m, reg, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(o)), kReferenceVReg)) { @@ -2642,8 +2668,8 @@ JDWP::JdwpError Dbg::SetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame ScopedObjectAccessUnchecked soa(Thread::Current()); MutexLock mu(soa.Self(), *Locks::thread_list_lock_); - Thread* thread; - JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); + JDWP::JdwpError error; + Thread* thread = DecodeThread(soa, thread_id, &error); if (error != JDWP::ERR_NONE) { return error; } @@ -2674,7 +2700,7 @@ void Dbg::PostLocationEvent(mirror::ArtMethod* m, int dex_pc, mirror::Object* th DCHECK(m != nullptr); DCHECK_EQ(m->IsStatic(), this_object == nullptr); JDWP::JdwpLocation location; - SetLocation(location, m, dex_pc); + SetLocation(&location, m, dex_pc); // We need 'this' for InstanceOnly filters only. JDWP::ObjectId this_id = GetThisObjectIdForEvent(this_object); @@ -2689,7 +2715,7 @@ void Dbg::PostFieldAccessEvent(mirror::ArtMethod* m, int dex_pc, DCHECK(m != nullptr); DCHECK(f != nullptr); JDWP::JdwpLocation location; - SetLocation(location, m, dex_pc); + SetLocation(&location, m, dex_pc); JDWP::RefTypeId type_id = gRegistry->AddRefType(f->GetDeclaringClass()); JDWP::FieldId field_id = ToFieldId(f); @@ -2708,7 +2734,7 @@ void Dbg::PostFieldModificationEvent(mirror::ArtMethod* m, int dex_pc, DCHECK(f != nullptr); DCHECK(field_value != nullptr); JDWP::JdwpLocation location; - SetLocation(location, m, dex_pc); + SetLocation(&location, m, dex_pc); JDWP::RefTypeId type_id = gRegistry->AddRefType(f->GetDeclaringClass()); JDWP::FieldId field_id = ToFieldId(f); @@ -2725,9 +2751,9 @@ void Dbg::PostException(const ThrowLocation& throw_location, } JDWP::JdwpLocation jdwp_throw_location; - SetLocation(jdwp_throw_location, throw_location.GetMethod(), throw_location.GetDexPc()); + SetLocation(&jdwp_throw_location, throw_location.GetMethod(), throw_location.GetDexPc()); JDWP::JdwpLocation catch_location; - SetLocation(catch_location, catch_method, catch_dex_pc); + SetLocation(&catch_location, catch_method, catch_dex_pc); // We need 'this' for InstanceOnly filters only. JDWP::ObjectId this_id = GetThisObjectIdForEvent(throw_location.GetThis()); @@ -3159,7 +3185,7 @@ class ScopedThreadSuspension { ScopedObjectAccessUnchecked soa(self); { MutexLock mu(soa.Self(), *Locks::thread_list_lock_); - error_ = DecodeThread(soa, thread_id, thread_); + thread_ = DecodeThread(soa, thread_id, &error_); } if (error_ == JDWP::ERR_NONE) { if (thread_ == soa.Self()) { @@ -3225,10 +3251,10 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize explicit SingleStepStackVisitor(Thread* thread, SingleStepControl* single_step_control, int32_t* line_number) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) - : StackVisitor(thread, NULL), single_step_control_(single_step_control), + : StackVisitor(thread, nullptr), single_step_control_(single_step_control), line_number_(line_number) { DCHECK_EQ(single_step_control_, thread->GetSingleStepControl()); - single_step_control_->method = NULL; + single_step_control_->method = nullptr; single_step_control_->stack_depth = 0; } @@ -3238,11 +3264,11 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize mirror::ArtMethod* m = GetMethod(); if (!m->IsRuntimeMethod()) { ++single_step_control_->stack_depth; - if (single_step_control_->method == NULL) { + if (single_step_control_->method == nullptr) { mirror::DexCache* dex_cache = m->GetDeclaringClass()->GetDexCache(); single_step_control_->method = m; *line_number_ = -1; - if (dex_cache != NULL) { + if (dex_cache != nullptr) { const DexFile& dex_file = *dex_cache->GetDexFile(); *line_number_ = dex_file.GetLineNumFromPC(m, GetDexPc()); } @@ -3315,7 +3341,7 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize const DexFile::CodeItem* const code_item = m->GetCodeItem(); DebugCallbackContext context(single_step_control, line_number, code_item); m->GetDexFile()->DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(), - DebugCallbackContext::Callback, NULL, &context); + DebugCallbackContext::Callback, nullptr, &context); } // @@ -3345,8 +3371,8 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize void Dbg::UnconfigureStep(JDWP::ObjectId thread_id) { ScopedObjectAccessUnchecked soa(Thread::Current()); MutexLock mu(soa.Self(), *Locks::thread_list_lock_); - Thread* thread; - JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); + JDWP::JdwpError error; + Thread* thread = DecodeThread(soa, thread_id, &error); if (error == JDWP::ERR_NONE) { SingleStepControl* single_step_control = thread->GetSingleStepControl(); DCHECK(single_step_control != nullptr); @@ -3390,13 +3416,14 @@ JDWP::JdwpError Dbg::InvokeMethod(JDWP::ObjectId thread_id, JDWP::ObjectId objec JDWP::ObjectId* pExceptionId) { ThreadList* thread_list = Runtime::Current()->GetThreadList(); - Thread* targetThread = NULL; - DebugInvokeReq* req = NULL; + Thread* targetThread = nullptr; + DebugInvokeReq* req = nullptr; Thread* self = Thread::Current(); { ScopedObjectAccessUnchecked soa(self); MutexLock mu(soa.Self(), *Locks::thread_list_lock_); - JDWP::JdwpError error = DecodeThread(soa, thread_id, targetThread); + JDWP::JdwpError error; + targetThread = DecodeThread(soa, thread_id, &error); if (error != JDWP::ERR_NONE) { LOG(ERROR) << "InvokeMethod request for invalid thread id " << thread_id; return error; @@ -3431,25 +3458,24 @@ JDWP::JdwpError Dbg::InvokeMethod(JDWP::ObjectId thread_id, JDWP::ObjectId objec return JDWP::ERR_THREAD_SUSPENDED; // Probably not expected here. } - JDWP::JdwpError status; - mirror::Object* receiver = gRegistry->Get<mirror::Object*>(object_id); - if (receiver == ObjectRegistry::kInvalidObject) { + mirror::Object* receiver = gRegistry->Get<mirror::Object*>(object_id, &error); + if (error != JDWP::ERR_NONE) { return JDWP::ERR_INVALID_OBJECT; } - mirror::Object* thread = gRegistry->Get<mirror::Object*>(thread_id); - if (thread == ObjectRegistry::kInvalidObject) { + mirror::Object* thread = gRegistry->Get<mirror::Object*>(thread_id, &error); + if (error != JDWP::ERR_NONE) { return JDWP::ERR_INVALID_OBJECT; } // TODO: check that 'thread' is actually a java.lang.Thread! - mirror::Class* c = DecodeClass(class_id, status); - if (c == NULL) { - return status; + mirror::Class* c = DecodeClass(class_id, &error); + if (c == nullptr) { + return error; } mirror::ArtMethod* m = FromMethodId(method_id); - if (m->IsStatic() != (receiver == NULL)) { + if (m->IsStatic() != (receiver == nullptr)) { return JDWP::ERR_INVALID_METHODID; } if (m->IsStatic()) { @@ -3483,11 +3509,11 @@ JDWP::JdwpError Dbg::InvokeMethod(JDWP::ObjectId thread_id, JDWP::ObjectId objec if (shorty[i + 1] == 'L') { // Did we really get an argument of an appropriate reference type? mirror::Class* parameter_type = mh.GetClassFromTypeIdx(types->GetTypeItem(i).type_idx_); - mirror::Object* argument = gRegistry->Get<mirror::Object*>(arg_values[i]); - if (argument == ObjectRegistry::kInvalidObject) { + mirror::Object* argument = gRegistry->Get<mirror::Object*>(arg_values[i], &error); + if (error != JDWP::ERR_NONE) { return JDWP::ERR_INVALID_OBJECT; } - if (argument != NULL && !argument->InstanceOf(parameter_type)) { + if (argument != nullptr && !argument->InstanceOf(parameter_type)) { return JDWP::ERR_ILLEGAL_ARGUMENT; } @@ -3598,7 +3624,7 @@ void Dbg::ExecuteMethod(DebugInvokeReq* pReq) { // Translate the method through the vtable, unless the debugger wants to suppress it. Handle<mirror::ArtMethod> m(hs.NewHandle(pReq->method)); - if ((pReq->options & JDWP::INVOKE_NONVIRTUAL) == 0 && pReq->receiver != NULL) { + if ((pReq->options & JDWP::INVOKE_NONVIRTUAL) == 0 && pReq->receiver != nullptr) { mirror::ArtMethod* actual_method = pReq->klass->FindVirtualMethodForVirtualOrInterface(m.Get()); if (actual_method != m.Get()) { VLOG(jdwp) << "ExecuteMethod translated " << PrettyMethod(m.Get()) << " to " << PrettyMethod(actual_method); @@ -3615,7 +3641,7 @@ void Dbg::ExecuteMethod(DebugInvokeReq* pReq) { pReq->result_value = InvokeWithJValues(soa, pReq->receiver, soa.EncodeMethod(m.Get()), reinterpret_cast<jvalue*>(pReq->arg_values)); - mirror::Throwable* exception = soa.Self()->GetException(NULL); + mirror::Throwable* exception = soa.Self()->GetException(nullptr); soa.Self()->ClearException(); pReq->exception = gRegistry->Add(exception); pReq->result_tag = BasicTagFromDescriptor(m.Get()->GetShorty()); @@ -3643,7 +3669,7 @@ void Dbg::ExecuteMethod(DebugInvokeReq* pReq) { gRegistry->Add(pReq->result_value.GetL()); } - if (old_exception.Get() != NULL) { + if (old_exception.Get() != nullptr) { ThrowLocation gc_safe_throw_location(old_throw_this_object.Get(), old_throw_method.Get(), old_throw_dex_pc); soa.Self()->SetException(gc_safe_throw_location, old_exception.Get()); @@ -3662,23 +3688,24 @@ void Dbg::ExecuteMethod(DebugInvokeReq* pReq) { * OLD-TODO: we currently assume that the request and reply include a single * chunk. If this becomes inconvenient we will need to adapt. */ -bool Dbg::DdmHandlePacket(JDWP::Request& request, uint8_t** pReplyBuf, int* pReplyLen) { +bool Dbg::DdmHandlePacket(JDWP::Request* request, uint8_t** pReplyBuf, int* pReplyLen) { Thread* self = Thread::Current(); JNIEnv* env = self->GetJniEnv(); - uint32_t type = request.ReadUnsigned32("type"); - uint32_t length = request.ReadUnsigned32("length"); + uint32_t type = request->ReadUnsigned32("type"); + uint32_t length = request->ReadUnsigned32("length"); // Create a byte[] corresponding to 'request'. - size_t request_length = request.size(); + size_t request_length = request->size(); ScopedLocalRef<jbyteArray> dataArray(env, env->NewByteArray(request_length)); - if (dataArray.get() == NULL) { + if (dataArray.get() == nullptr) { LOG(WARNING) << "byte[] allocation failed: " << request_length; env->ExceptionClear(); return false; } - env->SetByteArrayRegion(dataArray.get(), 0, request_length, reinterpret_cast<const jbyte*>(request.data())); - request.Skip(request_length); + env->SetByteArrayRegion(dataArray.get(), 0, request_length, + reinterpret_cast<const jbyte*>(request->data())); + request->Skip(request_length); // Run through and find all chunks. [Currently just find the first.] ScopedByteArrayRO contents(env, dataArray.get()); @@ -3698,7 +3725,7 @@ bool Dbg::DdmHandlePacket(JDWP::Request& request, uint8_t** pReplyBuf, int* pRep return false; } - if (chunk.get() == NULL) { + if (chunk.get() == nullptr) { return false; } @@ -3720,13 +3747,13 @@ bool Dbg::DdmHandlePacket(JDWP::Request& request, uint8_t** pReplyBuf, int* pRep type = env->GetIntField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_type); VLOG(jdwp) << StringPrintf("DDM reply: type=0x%08x data=%p offset=%d length=%d", type, replyData.get(), offset, length); - if (length == 0 || replyData.get() == NULL) { + if (length == 0 || replyData.get() == nullptr) { return false; } const int kChunkHdrLen = 8; uint8_t* reply = new uint8_t[length + kChunkHdrLen]; - if (reply == NULL) { + if (reply == nullptr) { LOG(WARNING) << "malloc failed: " << (length + kChunkHdrLen); return false; } @@ -3791,8 +3818,8 @@ void Dbg::DdmSendThreadNotification(Thread* t, uint32_t type) { ScopedObjectAccessUnchecked soa(Thread::Current()); StackHandleScope<1> hs(soa.Self()); Handle<mirror::String> name(hs.NewHandle(t->GetThreadName(soa))); - size_t char_count = (name.Get() != NULL) ? name->GetLength() : 0; - const jchar* chars = (name.Get() != NULL) ? name->GetCharArray()->GetData() : NULL; + size_t char_count = (name.Get() != nullptr) ? name->GetLength() : 0; + const jchar* chars = (name.Get() != nullptr) ? name->GetCharArray()->GetData() : nullptr; std::vector<uint8_t> bytes; JDWP::Append4BE(bytes, t->GetThreadId()); @@ -3844,7 +3871,7 @@ void Dbg::PostThreadDeath(Thread* t) { } void Dbg::DdmSendChunk(uint32_t type, size_t byte_count, const uint8_t* buf) { - CHECK(buf != NULL); + CHECK(buf != nullptr); iovec vec[1]; vec[0].iov_base = reinterpret_cast<void*>(const_cast<uint8_t*>(buf)); vec[0].iov_len = byte_count; @@ -3856,7 +3883,7 @@ void Dbg::DdmSendChunk(uint32_t type, const std::vector<uint8_t>& bytes) { } void Dbg::DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count) { - if (gJdwpState == NULL) { + if (gJdwpState == nullptr) { VLOG(jdwp) << "Debugger thread not active, ignoring DDM send: " << type; } else { gJdwpState->DdmSendChunkV(type, iov, iov_count); @@ -4013,7 +4040,7 @@ class HeapChunkContext { } void Flush() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (pieceLenField_ == NULL) { + if (pieceLenField_ == nullptr) { // Flush immediately post Reset (maybe back-to-back Flush). Ignore. CHECK(needHeader_); return; @@ -4041,7 +4068,7 @@ class HeapChunkContext { ResetStartOfNextChunk(); totalAllocationUnits_ = 0; needHeader_ = true; - pieceLenField_ = NULL; + pieceLenField_ = nullptr; } void HeapChunkCallback(void* start, void* /*end*/, size_t used_bytes) @@ -4050,9 +4077,9 @@ class HeapChunkContext { // Note: heap call backs cannot manipulate the heap upon which they are crawling, care is taken // in the following code not to allocate memory, by ensuring buf_ is of the correct size if (used_bytes == 0) { - if (start == NULL) { + if (start == nullptr) { // Reset for start of new heap. - startOfNextMemoryChunk_ = NULL; + startOfNextMemoryChunk_ = nullptr; Flush(); } // Only process in use memory so that free region information @@ -4067,7 +4094,7 @@ class HeapChunkContext { // TODO: I'm not sure using start of next chunk works well with multiple spaces. We shouldn't // count gaps inbetween spaces as free memory. - if (startOfNextMemoryChunk_ != NULL) { + if (startOfNextMemoryChunk_ != nullptr) { // Transmit any pending free memory. Native free memory of // over kMaxFreeLen could be because of the use of mmaps, so // don't report. If not free memory then start a new segment. @@ -4083,7 +4110,7 @@ class HeapChunkContext { } } if (flush) { - startOfNextMemoryChunk_ = NULL; + startOfNextMemoryChunk_ = nullptr; Flush(); } } @@ -4129,7 +4156,7 @@ class HeapChunkContext { uint8_t ExamineObject(mirror::Object* o, bool is_native_heap) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) { - if (o == NULL) { + if (o == nullptr) { return HPSG_STATE(SOLIDITY_FREE, 0); } @@ -4146,7 +4173,7 @@ class HeapChunkContext { } mirror::Class* c = o->GetClass(); - if (c == NULL) { + if (c == nullptr) { // The object was probably just created but hasn't been initialized yet. return HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT); } @@ -4295,14 +4322,14 @@ void Dbg::SetAllocTrackingEnabled(bool enabled) { if (enabled) { { MutexLock mu(Thread::Current(), *alloc_tracker_lock_); - if (recent_allocation_records_ == NULL) { + if (recent_allocation_records_ == nullptr) { alloc_record_max_ = GetAllocTrackerMax(); LOG(INFO) << "Enabling alloc tracker (" << alloc_record_max_ << " entries of " << kMaxAllocRecordStackDepth << " frames, taking " << PrettySize(sizeof(AllocRecord) * alloc_record_max_) << ")"; alloc_record_head_ = alloc_record_count_ = 0; recent_allocation_records_ = new AllocRecord[alloc_record_max_]; - CHECK(recent_allocation_records_ != NULL); + CHECK(recent_allocation_records_ != nullptr); } } Runtime::Current()->GetInstrumentation()->InstrumentQuickAllocEntryPoints(); @@ -4312,7 +4339,7 @@ void Dbg::SetAllocTrackingEnabled(bool enabled) { MutexLock mu(Thread::Current(), *alloc_tracker_lock_); LOG(INFO) << "Disabling alloc tracker"; delete[] recent_allocation_records_; - recent_allocation_records_ = NULL; + recent_allocation_records_ = nullptr; type_cache_.Clear(); } } @@ -4321,7 +4348,7 @@ void Dbg::SetAllocTrackingEnabled(bool enabled) { struct AllocRecordStackVisitor : public StackVisitor { AllocRecordStackVisitor(Thread* thread, AllocRecord* record) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) - : StackVisitor(thread, NULL), record(record), depth(0) {} + : StackVisitor(thread, nullptr), record(record), depth(0) {} // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses // annotalysis. @@ -4352,10 +4379,10 @@ struct AllocRecordStackVisitor : public StackVisitor { void Dbg::RecordAllocation(mirror::Class* type, size_t byte_count) { Thread* self = Thread::Current(); - CHECK(self != NULL); + CHECK(self != nullptr); MutexLock mu(self, *alloc_tracker_lock_); - if (recent_allocation_records_ == NULL) { + if (recent_allocation_records_ == nullptr) { return; } @@ -4395,7 +4422,7 @@ size_t Dbg::HeadIndex() { void Dbg::DumpRecentAllocations() { ScopedObjectAccess soa(Thread::Current()); MutexLock mu(soa.Self(), *alloc_tracker_lock_); - if (recent_allocation_records_ == NULL) { + if (recent_allocation_records_ == nullptr) { LOG(INFO) << "Not recording tracked allocations"; return; } @@ -4415,7 +4442,7 @@ void Dbg::DumpRecentAllocations() { for (size_t stack_frame = 0; stack_frame < kMaxAllocRecordStackDepth; ++stack_frame) { AllocRecordStackTraceElement* stack_element = record->StackElement(stack_frame); mirror::ArtMethod* m = stack_element->Method(); - if (m == NULL) { + if (m == nullptr) { break; } LOG(INFO) << " " << PrettyMethod(m) << " line " << stack_element->LineNumber(); @@ -4543,7 +4570,7 @@ jbyteArray Dbg::GetRecentAllocations() { class_names.Add(record->Type()->GetDescriptor(&temp)); for (size_t i = 0; i < kMaxAllocRecordStackDepth; i++) { mirror::ArtMethod* m = record->StackElement(i)->Method(); - if (m != NULL) { + if (m != nullptr) { class_names.Add(m->GetDeclaringClassDescriptor()); method_names.Add(m->GetName()); filenames.Add(GetMethodSourceFile(m)); @@ -4626,7 +4653,7 @@ jbyteArray Dbg::GetRecentAllocations() { } JNIEnv* env = self->GetJniEnv(); jbyteArray result = env->NewByteArray(bytes.size()); - if (result != NULL) { + if (result != nullptr) { env->SetByteArrayRegion(result, 0, bytes.size(), reinterpret_cast<const jbyte*>(&bytes[0])); } return result; diff --git a/runtime/debugger.h b/runtime/debugger.h index 1d3668c1f6..52ae7a916d 100644 --- a/runtime/debugger.h +++ b/runtime/debugger.h @@ -248,9 +248,9 @@ class Dbg { */ static std::string GetClassName(JDWP::RefTypeId id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static JDWP::JdwpError GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId& class_object_id) + static JDWP::JdwpError GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId* class_object_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static JDWP::JdwpError GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId& superclass_id) + static JDWP::JdwpError GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId* superclass_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError GetClassLoader(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -258,38 +258,38 @@ class Dbg { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError GetReflectedType(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static void GetClassList(std::vector<JDWP::RefTypeId>& classes) + static void GetClassList(std::vector<JDWP::RefTypeId>* classes) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* pTypeTag, uint32_t* pStatus, std::string* pDescriptor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static void FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>& ids) + static void FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>* ids) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError GetSignature(JDWP::RefTypeId ref_type_id, std::string* signature) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static JDWP::JdwpError GetSourceFile(JDWP::RefTypeId ref_type_id, std::string& source_file) + static JDWP::JdwpError GetSourceFile(JDWP::RefTypeId ref_type_id, std::string* source_file) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static JDWP::JdwpError GetObjectTag(JDWP::ObjectId object_id, uint8_t& tag) + static JDWP::JdwpError GetObjectTag(JDWP::ObjectId object_id, uint8_t* tag) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static size_t GetTagWidth(JDWP::JdwpTag tag); - static JDWP::JdwpError GetArrayLength(JDWP::ObjectId array_id, int& length) + static JDWP::JdwpError GetArrayLength(JDWP::ObjectId array_id, int32_t* length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError OutputArray(JDWP::ObjectId array_id, int offset, int count, JDWP::ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError SetArrayElements(JDWP::ObjectId array_id, int offset, int count, - JDWP::Request& request) + JDWP::Request* request) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::ObjectId CreateString(const std::string& str) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static JDWP::JdwpError CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId& new_object) + static JDWP::JdwpError CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId* new_object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError CreateArrayObject(JDWP::RefTypeId array_class_id, uint32_t length, - JDWP::ObjectId& new_array) + JDWP::ObjectId* new_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static bool MatchType(JDWP::RefTypeId instance_class_id, JDWP::RefTypeId class_id) @@ -301,12 +301,12 @@ class Dbg { static JDWP::JdwpError GetMonitorInfo(JDWP::ObjectId object_id, JDWP::ExpandBuf* reply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError GetOwnedMonitors(JDWP::ObjectId thread_id, - std::vector<JDWP::ObjectId>& monitors, - std::vector<uint32_t>& stack_depths) + std::vector<JDWP::ObjectId>* monitors, + std::vector<uint32_t>* stack_depths) LOCKS_EXCLUDED(Locks::thread_list_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError GetContendedMonitor(JDWP::ObjectId thread_id, - JDWP::ObjectId& contended_monitor) + JDWP::ObjectId* contended_monitor) LOCKS_EXCLUDED(Locks::thread_list_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -314,19 +314,19 @@ class Dbg { // Heap. // static JDWP::JdwpError GetInstanceCounts(const std::vector<JDWP::RefTypeId>& class_ids, - std::vector<uint64_t>& counts) + std::vector<uint64_t>* counts) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError GetInstances(JDWP::RefTypeId class_id, int32_t max_count, - std::vector<JDWP::ObjectId>& instances) + std::vector<JDWP::ObjectId>* instances) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError GetReferringObjects(JDWP::ObjectId object_id, int32_t max_count, - std::vector<JDWP::ObjectId>& referring_objects) + std::vector<JDWP::ObjectId>* referring_objects) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError DisableCollection(JDWP::ObjectId object_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError EnableCollection(JDWP::ObjectId object_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static JDWP::JdwpError IsCollected(JDWP::ObjectId object_id, bool& is_collected) + static JDWP::JdwpError IsCollected(JDWP::ObjectId object_id, bool* is_collected) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void DisposeObject(JDWP::ObjectId object_id, uint32_t reference_count) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -358,7 +358,7 @@ class Dbg { JDWP::ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError GetBytecodes(JDWP::RefTypeId class_id, JDWP::MethodId method_id, - std::vector<uint8_t>& bytecodes) + std::vector<uint8_t>* bytecodes) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static std::string GetFieldName(JDWP::FieldId field_id) @@ -387,7 +387,7 @@ class Dbg { /* * Thread, ThreadGroup, Frame */ - static JDWP::JdwpError GetThreadName(JDWP::ObjectId thread_id, std::string& name) + static JDWP::JdwpError GetThreadName(JDWP::ObjectId thread_id, std::string* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCKS_EXCLUDED(Locks::thread_list_lock_); static JDWP::JdwpError GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply) @@ -412,12 +412,13 @@ class Dbg { // Fills 'thread_ids' with the threads in the given thread group. If thread_group_id == 0, // returns all threads. - static void GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>& thread_ids) + static void GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>* thread_ids) LOCKS_EXCLUDED(Locks::thread_list_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static void GetChildThreadGroups(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>& child_thread_group_ids); + static void GetChildThreadGroups(JDWP::ObjectId thread_group_id, + std::vector<JDWP::ObjectId>* child_thread_group_ids); - static JDWP::JdwpError GetThreadFrameCount(JDWP::ObjectId thread_id, size_t& result) + static JDWP::JdwpError GetThreadFrameCount(JDWP::ObjectId thread_id, size_t* result) LOCKS_EXCLUDED(Locks::thread_list_lock_); static JDWP::JdwpError GetThreadFrames(JDWP::ObjectId thread_id, size_t start_frame, size_t frame_count, JDWP::ExpandBuf* buf) @@ -542,7 +543,7 @@ class Dbg { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void DdmSetThreadNotification(bool enable) LOCKS_EXCLUDED(Locks::thread_list_lock_); - static bool DdmHandlePacket(JDWP::Request& request, uint8_t** pReplyBuf, int* pReplyLen); + static bool DdmHandlePacket(JDWP::Request* request, uint8_t** pReplyBuf, int* pReplyLen); static void DdmConnected() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void DdmDisconnected() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void DdmSendChunk(uint32_t type, const std::vector<uint8_t>& bytes) @@ -595,8 +596,8 @@ class Dbg { static void DdmSendHeapSegments(bool native) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static TypeCache& GetTypeCache() { - return type_cache_; + static TypeCache* GetTypeCache() { + return &type_cache_; } private: diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc index cf89850fa2..e1c532ece4 100644 --- a/runtime/entrypoints/entrypoint_utils.cc +++ b/runtime/entrypoints/entrypoint_utils.cc @@ -220,21 +220,18 @@ void ThrowStackOverflowError(Thread* self) { } void CheckReferenceResult(mirror::Object* o, Thread* self) { - if (o == NULL) { + if (o == nullptr) { return; } - mirror::ArtMethod* m = self->GetCurrentMethod(NULL); - if (o == kInvalidIndirectRefObject) { - Runtime::Current()->GetJavaVM()->JniAbortF(NULL, "invalid reference returned from %s", - PrettyMethod(m).c_str()); - } + mirror::ArtMethod* m = self->GetCurrentMethod(nullptr); // Make sure that the result is an instance of the type this method was expected to return. StackHandleScope<1> hs(self); Handle<mirror::ArtMethod> h_m(hs.NewHandle(m)); mirror::Class* return_type = MethodHelper(h_m).GetReturnType(); if (!o->InstanceOf(return_type)) { - Runtime::Current()->GetJavaVM()->JniAbortF(NULL, "attempt to return an instance of %s from %s", + Runtime::Current()->GetJavaVM()->JniAbortF(nullptr, + "attempt to return an instance of %s from %s", PrettyTypeOf(o).c_str(), PrettyMethod(h_m.Get()).c_str()); } diff --git a/runtime/indirect_reference_table-inl.h b/runtime/indirect_reference_table-inl.h index 00f7b06f1b..9bf3ea258d 100644 --- a/runtime/indirect_reference_table-inl.h +++ b/runtime/indirect_reference_table-inl.h @@ -19,6 +19,7 @@ #include "indirect_reference_table.h" +#include "runtime-inl.h" #include "verify_object-inl.h" namespace art { @@ -26,6 +27,15 @@ namespace mirror { class Object; } // namespace mirror +inline void IrtIterator::SkipNullsAndTombstones() { + // We skip NULLs and tombstones. Clients don't want to see implementation details. + while (i_ < capacity_ && + (table_[i_].IsNull() || + Runtime::Current()->IsClearedJniWeakGlobal(table_[i_].Read<kWithoutReadBarrier>()))) { + ++i_; + } +} + // Verifies that the indirect table lookup is valid. // Returns "false" if something looks bad. inline bool IndirectReferenceTable::GetChecked(IndirectRef iref) const { @@ -73,15 +83,11 @@ inline bool IndirectReferenceTable::CheckEntry(const char* what, IndirectRef ire template<ReadBarrierOption kReadBarrierOption> inline mirror::Object* IndirectReferenceTable::Get(IndirectRef iref) const { if (!GetChecked(iref)) { - return kInvalidIndirectRefObject; + return nullptr; } uint32_t idx = ExtractIndex(iref); - mirror::Object* obj = table_[idx].Read<kWithoutReadBarrier>(); - if (LIKELY(obj != kClearedJniWeakGlobal)) { - // The read barrier or VerifyObject won't handle kClearedJniWeakGlobal. - obj = table_[idx].Read<kReadBarrierOption>(); - VerifyObject(obj); - } + mirror::Object* obj = table_[idx].Read<kReadBarrierOption>(); + VerifyObject(obj); return obj; } diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc index 1ba2291adf..49bffa404e 100644 --- a/runtime/indirect_reference_table.cc +++ b/runtime/indirect_reference_table.cc @@ -276,10 +276,6 @@ void IndirectReferenceTable::Dump(std::ostream& os) const { mirror::Object* obj = table_[i].Read<kWithoutReadBarrier>(); if (UNLIKELY(obj == nullptr)) { // Remove NULLs. - } else if (UNLIKELY(obj == kClearedJniWeakGlobal)) { - // ReferenceTable::Dump() will handle kClearedJniWeakGlobal - // while the read barrier won't. - entries.push_back(GcRoot<mirror::Object>(obj)); } else { obj = table_[i].Read(); entries.push_back(GcRoot<mirror::Object>(obj)); diff --git a/runtime/indirect_reference_table.h b/runtime/indirect_reference_table.h index d25bc42dfc..562ba1e8df 100644 --- a/runtime/indirect_reference_table.h +++ b/runtime/indirect_reference_table.h @@ -105,10 +105,6 @@ class MemMap; */ typedef void* IndirectRef; -// Magic failure values; must not pass Heap::ValidateObject() or Heap::IsHeapAddress(). -static mirror::Object* const kInvalidIndirectRefObject = reinterpret_cast<mirror::Object*>(0xdead4321); -static mirror::Object* const kClearedJniWeakGlobal = reinterpret_cast<mirror::Object*>(0xdead1234); - /* * Indirect reference kind, used as the two low bits of IndirectRef. * @@ -229,18 +225,11 @@ class IrtIterator { } private: - void SkipNullsAndTombstones() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - // We skip NULLs and tombstones. Clients don't want to see implementation details. - while (i_ < capacity_ && - (table_[i_].IsNull() || - table_[i_].Read<kWithoutReadBarrier>() == kClearedJniWeakGlobal)) { - ++i_; - } - } + void SkipNullsAndTombstones() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); GcRoot<mirror::Object>* const table_; size_t i_; - size_t capacity_; + const size_t capacity_; }; bool inline operator==(const IrtIterator& lhs, const IrtIterator& rhs) { diff --git a/runtime/indirect_reference_table_test.cc b/runtime/indirect_reference_table_test.cc index a33a981545..99ee597bb8 100644 --- a/runtime/indirect_reference_table_test.cc +++ b/runtime/indirect_reference_table_test.cc @@ -49,15 +49,15 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { IndirectReferenceTable irt(kTableInitial, kTableMax, kGlobal); mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"); - ASSERT_TRUE(c != NULL); + ASSERT_TRUE(c != nullptr); mirror::Object* obj0 = c->AllocObject(soa.Self()); - ASSERT_TRUE(obj0 != NULL); + ASSERT_TRUE(obj0 != nullptr); mirror::Object* obj1 = c->AllocObject(soa.Self()); - ASSERT_TRUE(obj1 != NULL); + ASSERT_TRUE(obj1 != nullptr); mirror::Object* obj2 = c->AllocObject(soa.Self()); - ASSERT_TRUE(obj2 != NULL); + ASSERT_TRUE(obj2 != nullptr); mirror::Object* obj3 = c->AllocObject(soa.Self()); - ASSERT_TRUE(obj3 != NULL); + ASSERT_TRUE(obj3 != nullptr); const uint32_t cookie = IRT_FIRST_SEGMENT; @@ -68,13 +68,13 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { // Add three, check, remove in the order in which they were added. iref0 = irt.Add(cookie, obj0); - EXPECT_TRUE(iref0 != NULL); + EXPECT_TRUE(iref0 != nullptr); CheckDump(&irt, 1, 1); IndirectRef iref1 = irt.Add(cookie, obj1); - EXPECT_TRUE(iref1 != NULL); + EXPECT_TRUE(iref1 != nullptr); CheckDump(&irt, 2, 2); IndirectRef iref2 = irt.Add(cookie, obj2); - EXPECT_TRUE(iref2 != NULL); + EXPECT_TRUE(iref2 != nullptr); CheckDump(&irt, 3, 3); EXPECT_EQ(obj0, irt.Get(iref0)); @@ -92,15 +92,15 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { EXPECT_EQ(0U, irt.Capacity()); // Get invalid entry (off the end of the list). - EXPECT_EQ(kInvalidIndirectRefObject, irt.Get(iref0)); + EXPECT_TRUE(irt.Get(iref0) == nullptr); // Add three, remove in the opposite order. iref0 = irt.Add(cookie, obj0); - EXPECT_TRUE(iref0 != NULL); + EXPECT_TRUE(iref0 != nullptr); iref1 = irt.Add(cookie, obj1); - EXPECT_TRUE(iref1 != NULL); + EXPECT_TRUE(iref1 != nullptr); iref2 = irt.Add(cookie, obj2); - EXPECT_TRUE(iref2 != NULL); + EXPECT_TRUE(iref2 != nullptr); CheckDump(&irt, 3, 3); ASSERT_TRUE(irt.Remove(cookie, iref2)); @@ -116,11 +116,11 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { // Add three, remove middle / middle / bottom / top. (Second attempt // to remove middle should fail.) iref0 = irt.Add(cookie, obj0); - EXPECT_TRUE(iref0 != NULL); + EXPECT_TRUE(iref0 != nullptr); iref1 = irt.Add(cookie, obj1); - EXPECT_TRUE(iref1 != NULL); + EXPECT_TRUE(iref1 != nullptr); iref2 = irt.Add(cookie, obj2); - EXPECT_TRUE(iref2 != NULL); + EXPECT_TRUE(iref2 != nullptr); CheckDump(&irt, 3, 3); ASSERT_EQ(3U, irt.Capacity()); @@ -131,7 +131,7 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { CheckDump(&irt, 2, 2); // Get invalid entry (from hole). - EXPECT_EQ(kInvalidIndirectRefObject, irt.Get(iref1)); + EXPECT_TRUE(irt.Get(iref1) == nullptr); ASSERT_TRUE(irt.Remove(cookie, iref2)); CheckDump(&irt, 1, 1); @@ -145,20 +145,20 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { // is still 4 (i.e. holes are getting filled). Remove #1 and #3, verify // that we delete one and don't hole-compact the other. iref0 = irt.Add(cookie, obj0); - EXPECT_TRUE(iref0 != NULL); + EXPECT_TRUE(iref0 != nullptr); iref1 = irt.Add(cookie, obj1); - EXPECT_TRUE(iref1 != NULL); + EXPECT_TRUE(iref1 != nullptr); iref2 = irt.Add(cookie, obj2); - EXPECT_TRUE(iref2 != NULL); + EXPECT_TRUE(iref2 != nullptr); IndirectRef iref3 = irt.Add(cookie, obj3); - EXPECT_TRUE(iref3 != NULL); + EXPECT_TRUE(iref3 != nullptr); CheckDump(&irt, 4, 4); ASSERT_TRUE(irt.Remove(cookie, iref1)); CheckDump(&irt, 3, 3); iref1 = irt.Add(cookie, obj1); - EXPECT_TRUE(iref1 != NULL); + EXPECT_TRUE(iref1 != nullptr); ASSERT_EQ(4U, irt.Capacity()) << "hole not filled"; CheckDump(&irt, 4, 4); @@ -181,12 +181,12 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { // iref. They have the same slot number but are for different objects. // With the extended checks in place, this should fail. iref0 = irt.Add(cookie, obj0); - EXPECT_TRUE(iref0 != NULL); + EXPECT_TRUE(iref0 != nullptr); CheckDump(&irt, 1, 1); ASSERT_TRUE(irt.Remove(cookie, iref0)); CheckDump(&irt, 0, 0); iref1 = irt.Add(cookie, obj1); - EXPECT_TRUE(iref1 != NULL); + EXPECT_TRUE(iref1 != nullptr); CheckDump(&irt, 1, 1); ASSERT_FALSE(irt.Remove(cookie, iref0)) << "mismatched del succeeded"; CheckDump(&irt, 1, 1); @@ -197,12 +197,12 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { // Same as above, but with the same object. A more rigorous checker // (e.g. with slot serialization) will catch this. iref0 = irt.Add(cookie, obj0); - EXPECT_TRUE(iref0 != NULL); + EXPECT_TRUE(iref0 != nullptr); CheckDump(&irt, 1, 1); ASSERT_TRUE(irt.Remove(cookie, iref0)); CheckDump(&irt, 0, 0); iref1 = irt.Add(cookie, obj0); - EXPECT_TRUE(iref1 != NULL); + EXPECT_TRUE(iref1 != nullptr); CheckDump(&irt, 1, 1); if (iref0 != iref1) { // Try 0, should not work. @@ -212,15 +212,15 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { ASSERT_EQ(0U, irt.Capacity()) << "temporal del not empty"; CheckDump(&irt, 0, 0); - // NULL isn't a valid iref. - ASSERT_EQ(kInvalidIndirectRefObject, irt.Get(NULL)); + // nullptr isn't a valid iref. + ASSERT_TRUE(irt.Get(nullptr) == nullptr); // Stale lookup. iref0 = irt.Add(cookie, obj0); - EXPECT_TRUE(iref0 != NULL); + EXPECT_TRUE(iref0 != nullptr); CheckDump(&irt, 1, 1); ASSERT_TRUE(irt.Remove(cookie, iref0)); - EXPECT_EQ(kInvalidIndirectRefObject, irt.Get(iref0)) << "stale lookup succeeded"; + EXPECT_TRUE(irt.Get(iref0) == nullptr) << "stale lookup succeeded"; CheckDump(&irt, 0, 0); // Test table resizing. @@ -228,12 +228,12 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { IndirectRef manyRefs[kTableInitial]; for (size_t i = 0; i < kTableInitial; i++) { manyRefs[i] = irt.Add(cookie, obj0); - ASSERT_TRUE(manyRefs[i] != NULL) << "Failed adding " << i; + ASSERT_TRUE(manyRefs[i] != nullptr) << "Failed adding " << i; CheckDump(&irt, i + 1, 1); } // ...this one causes overflow. iref0 = irt.Add(cookie, obj0); - ASSERT_TRUE(iref0 != NULL); + ASSERT_TRUE(iref0 != nullptr); ASSERT_EQ(kTableInitial + 1, irt.Capacity()); CheckDump(&irt, kTableInitial + 1, 1); diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc index dd3b7cf2b2..424addb2a8 100644 --- a/runtime/java_vm_ext.cc +++ b/runtime/java_vm_ext.cc @@ -28,6 +28,7 @@ #include "nativebridge/native_bridge.h" #include "java_vm_ext.h" #include "parsed_options.h" +#include "runtime-inl.h" #include "ScopedLocalRef.h" #include "scoped_thread_state_change.h" #include "thread-inl.h" @@ -761,7 +762,7 @@ void JavaVMExt::SweepJniWeakGlobals(IsMarkedCallback* callback, void* arg) { mirror::Object* obj = *entry; mirror::Object* new_obj = callback(obj, arg); if (new_obj == nullptr) { - new_obj = kClearedJniWeakGlobal; + new_obj = Runtime::Current()->GetClearedJniWeakGlobal(); } *entry = new_obj; } diff --git a/runtime/jdwp/jdwp.h b/runtime/jdwp/jdwp.h index 8fd07cc11b..b5b6298b84 100644 --- a/runtime/jdwp/jdwp.h +++ b/runtime/jdwp/jdwp.h @@ -285,7 +285,7 @@ struct JdwpState { private: explicit JdwpState(const JdwpOptions* options); - size_t ProcessRequest(Request& request, ExpandBuf* pReply); + size_t ProcessRequest(Request* request, ExpandBuf* pReply); bool InvokeInProgress(); bool IsConnected(); void SuspendByPolicy(JdwpSuspendPolicy suspend_policy, JDWP::ObjectId thread_self_id) diff --git a/runtime/jdwp/jdwp_event.cc b/runtime/jdwp/jdwp_event.cc index 36fbed4ea2..fc39cc48d0 100644 --- a/runtime/jdwp/jdwp_event.cc +++ b/runtime/jdwp/jdwp_event.cc @@ -781,7 +781,7 @@ static void LogMatchingEventsAndThread(JdwpEvent** match_list, size_t match_coun << StringPrintf(" (requestId=%#" PRIx32 ")", pEvent->requestId); } std::string thread_name; - JdwpError error = Dbg::GetThreadName(basket.threadId, thread_name); + JdwpError error = Dbg::GetThreadName(basket.threadId, &thread_name); if (error != JDWP::ERR_NONE) { thread_name = "<unknown>"; } @@ -924,7 +924,7 @@ bool JdwpState::PostFieldEvent(const JdwpLocation* pLoc, RefTypeId typeId, Field // Get instance type tag. uint8_t tag; - error = Dbg::GetObjectTag(thisPtr, tag); + error = Dbg::GetObjectTag(thisPtr, &tag); if (error != ERR_NONE) { return false; } diff --git a/runtime/jdwp/jdwp_handler.cc b/runtime/jdwp/jdwp_handler.cc index 330d235c03..35095f95ca 100644 --- a/runtime/jdwp/jdwp_handler.cc +++ b/runtime/jdwp/jdwp_handler.cc @@ -65,7 +65,7 @@ static void WriteValue(ExpandBuf* pReply, int width, uint64_t value) { static JdwpError WriteTaggedObject(ExpandBuf* reply, ObjectId object_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { uint8_t tag; - JdwpError rc = Dbg::GetObjectTag(object_id, tag); + JdwpError rc = Dbg::GetObjectTag(object_id, &tag); if (rc == ERR_NONE) { expandBufAdd1(reply, tag); expandBufAddObjectId(reply, object_id); @@ -91,13 +91,13 @@ static JdwpError WriteTaggedObjectList(ExpandBuf* reply, const std::vector<Objec * If "is_constructor" is set, this returns "object_id" rather than the * expected-to-be-void return value of the called function. */ -static JdwpError FinishInvoke(JdwpState*, Request& request, ExpandBuf* pReply, +static JdwpError FinishInvoke(JdwpState*, Request* request, ExpandBuf* pReply, ObjectId thread_id, ObjectId object_id, RefTypeId class_id, MethodId method_id, bool is_constructor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { CHECK(!is_constructor || object_id != 0); - int32_t arg_count = request.ReadSigned32("argument count"); + int32_t arg_count = request->ReadSigned32("argument count"); VLOG(jdwp) << StringPrintf(" --> thread_id=%#" PRIx64 " object_id=%#" PRIx64, thread_id, object_id); @@ -109,14 +109,14 @@ static JdwpError FinishInvoke(JdwpState*, Request& request, ExpandBuf* pReply, std::unique_ptr<JdwpTag[]> argTypes(arg_count > 0 ? new JdwpTag[arg_count] : NULL); std::unique_ptr<uint64_t[]> argValues(arg_count > 0 ? new uint64_t[arg_count] : NULL); for (int32_t i = 0; i < arg_count; ++i) { - argTypes[i] = request.ReadTag(); + argTypes[i] = request->ReadTag(); size_t width = Dbg::GetTagWidth(argTypes[i]); - argValues[i] = request.ReadValue(width); + argValues[i] = request->ReadValue(width); VLOG(jdwp) << " " << argTypes[i] << StringPrintf("(%zd): %#" PRIx64, width, argValues[i]); } - uint32_t options = request.ReadUnsigned32("InvokeOptions bit flags"); + uint32_t options = request->ReadUnsigned32("InvokeOptions bit flags"); VLOG(jdwp) << StringPrintf(" options=0x%04x%s%s", options, (options & INVOKE_SINGLE_THREADED) ? " (SINGLE_THREADED)" : "", (options & INVOKE_NONVIRTUAL) ? " (NONVIRTUAL)" : ""); @@ -161,7 +161,7 @@ static JdwpError FinishInvoke(JdwpState*, Request& request, ExpandBuf* pReply, return err; } -static JdwpError VM_Version(JdwpState*, Request&, ExpandBuf* pReply) +static JdwpError VM_Version(JdwpState*, Request*, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Text information on runtime version. std::string version(StringPrintf("Android Runtime %s", Runtime::Current()->GetVersion())); @@ -185,12 +185,12 @@ static JdwpError VM_Version(JdwpState*, Request&, ExpandBuf* pReply) * referenceTypeID. We need to send back more than one if the class has * been loaded by multiple class loaders. */ -static JdwpError VM_ClassesBySignature(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError VM_ClassesBySignature(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - std::string classDescriptor(request.ReadUtf8String()); + std::string classDescriptor(request->ReadUtf8String()); std::vector<RefTypeId> ids; - Dbg::FindLoadedClassBySignature(classDescriptor.c_str(), ids); + Dbg::FindLoadedClassBySignature(classDescriptor.c_str(), &ids); expandBufAdd4BE(pReply, ids.size()); @@ -217,10 +217,10 @@ static JdwpError VM_ClassesBySignature(JdwpState*, Request& request, ExpandBuf* * We exclude ourselves from the list, because we don't allow ourselves * to be suspended, and that violates some JDWP expectations. */ -static JdwpError VM_AllThreads(JdwpState*, Request&, ExpandBuf* pReply) +static JdwpError VM_AllThreads(JdwpState*, Request*, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { std::vector<ObjectId> thread_ids; - Dbg::GetThreads(0, thread_ids); + Dbg::GetThreads(0, &thread_ids); expandBufAdd4BE(pReply, thread_ids.size()); for (uint32_t i = 0; i < thread_ids.size(); ++i) { @@ -233,7 +233,7 @@ static JdwpError VM_AllThreads(JdwpState*, Request&, ExpandBuf* pReply) /* * List all thread groups that do not have a parent. */ -static JdwpError VM_TopLevelThreadGroups(JdwpState*, Request&, ExpandBuf* pReply) +static JdwpError VM_TopLevelThreadGroups(JdwpState*, Request*, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { /* * TODO: maintain a list of parentless thread groups in the VM. @@ -254,7 +254,7 @@ static JdwpError VM_TopLevelThreadGroups(JdwpState*, Request&, ExpandBuf* pReply * * All IDs are 8 bytes. */ -static JdwpError VM_IDSizes(JdwpState*, Request&, ExpandBuf* pReply) +static JdwpError VM_IDSizes(JdwpState*, Request*, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { expandBufAdd4BE(pReply, sizeof(FieldId)); expandBufAdd4BE(pReply, sizeof(MethodId)); @@ -264,7 +264,7 @@ static JdwpError VM_IDSizes(JdwpState*, Request&, ExpandBuf* pReply) return ERR_NONE; } -static JdwpError VM_Dispose(JdwpState*, Request&, ExpandBuf*) +static JdwpError VM_Dispose(JdwpState*, Request*, ExpandBuf*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { Dbg::Disposed(); return ERR_NONE; @@ -276,7 +276,7 @@ static JdwpError VM_Dispose(JdwpState*, Request&, ExpandBuf*) * * This needs to increment the "suspend count" on all threads. */ -static JdwpError VM_Suspend(JdwpState*, Request&, ExpandBuf*) +static JdwpError VM_Suspend(JdwpState*, Request*, ExpandBuf*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { Thread* self = Thread::Current(); self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSuspension); @@ -288,16 +288,16 @@ static JdwpError VM_Suspend(JdwpState*, Request&, ExpandBuf*) /* * Resume execution. Decrements the "suspend count" of all threads. */ -static JdwpError VM_Resume(JdwpState*, Request&, ExpandBuf*) +static JdwpError VM_Resume(JdwpState*, Request*, ExpandBuf*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { Dbg::ProcessDelayedFullUndeoptimizations(); Dbg::ResumeVM(); return ERR_NONE; } -static JdwpError VM_Exit(JdwpState* state, Request& request, ExpandBuf*) +static JdwpError VM_Exit(JdwpState* state, Request* request, ExpandBuf*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - uint32_t exit_status = request.ReadUnsigned32("exit_status"); + uint32_t exit_status = request->ReadUnsigned32("exit_status"); state->ExitAfterReplying(exit_status); return ERR_NONE; } @@ -308,9 +308,9 @@ static JdwpError VM_Exit(JdwpState* state, Request& request, ExpandBuf*) * (Ctrl-Shift-I in Eclipse on an array of objects causes it to create the * string "java.util.Arrays".) */ -static JdwpError VM_CreateString(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError VM_CreateString(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - std::string str(request.ReadUtf8String()); + std::string str(request->ReadUtf8String()); ObjectId stringId = Dbg::CreateString(str); if (stringId == 0) { return ERR_OUT_OF_MEMORY; @@ -319,7 +319,7 @@ static JdwpError VM_CreateString(JdwpState*, Request& request, ExpandBuf* pReply return ERR_NONE; } -static JdwpError VM_ClassPaths(JdwpState*, Request&, ExpandBuf* pReply) +static JdwpError VM_ClassPaths(JdwpState*, Request*, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { expandBufAddUtf8String(pReply, "/"); @@ -340,18 +340,18 @@ static JdwpError VM_ClassPaths(JdwpState*, Request&, ExpandBuf* pReply) return ERR_NONE; } -static JdwpError VM_DisposeObjects(JdwpState*, Request& request, ExpandBuf*) +static JdwpError VM_DisposeObjects(JdwpState*, Request* request, ExpandBuf*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - size_t object_count = request.ReadUnsigned32("object_count"); + size_t object_count = request->ReadUnsigned32("object_count"); for (size_t i = 0; i < object_count; ++i) { - ObjectId object_id = request.ReadObjectId(); - uint32_t reference_count = request.ReadUnsigned32("reference_count"); + ObjectId object_id = request->ReadObjectId(); + uint32_t reference_count = request->ReadUnsigned32("reference_count"); Dbg::DisposeObject(object_id, reference_count); } return ERR_NONE; } -static JdwpError VM_Capabilities(JdwpState*, Request&, ExpandBuf* reply) +static JdwpError VM_Capabilities(JdwpState*, Request*, ExpandBuf* reply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { expandBufAdd1(reply, true); // canWatchFieldModification expandBufAdd1(reply, true); // canWatchFieldAccess @@ -363,7 +363,7 @@ static JdwpError VM_Capabilities(JdwpState*, Request&, ExpandBuf* reply) return ERR_NONE; } -static JdwpError VM_CapabilitiesNew(JdwpState*, Request& request, ExpandBuf* reply) +static JdwpError VM_CapabilitiesNew(JdwpState*, Request* request, ExpandBuf* reply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // The first few capabilities are the same as those reported by the older call. VM_Capabilities(NULL, request, reply); @@ -393,7 +393,7 @@ static JdwpError VM_CapabilitiesNew(JdwpState*, Request& request, ExpandBuf* rep static JdwpError VM_AllClassesImpl(ExpandBuf* pReply, bool descriptor_and_status, bool generic) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { std::vector<JDWP::RefTypeId> classes; - Dbg::GetClassList(classes); + Dbg::GetClassList(&classes); expandBufAdd4BE(pReply, classes.size()); @@ -421,29 +421,29 @@ static JdwpError VM_AllClassesImpl(ExpandBuf* pReply, bool descriptor_and_status return ERR_NONE; } -static JdwpError VM_AllClasses(JdwpState*, Request&, ExpandBuf* pReply) +static JdwpError VM_AllClasses(JdwpState*, Request*, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return VM_AllClassesImpl(pReply, true, false); } -static JdwpError VM_AllClassesWithGeneric(JdwpState*, Request&, ExpandBuf* pReply) +static JdwpError VM_AllClassesWithGeneric(JdwpState*, Request*, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return VM_AllClassesImpl(pReply, true, true); } -static JdwpError VM_InstanceCounts(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError VM_InstanceCounts(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - int32_t class_count = request.ReadSigned32("class count"); + int32_t class_count = request->ReadSigned32("class count"); if (class_count < 0) { return ERR_ILLEGAL_ARGUMENT; } std::vector<RefTypeId> class_ids; for (int32_t i = 0; i < class_count; ++i) { - class_ids.push_back(request.ReadRefTypeId()); + class_ids.push_back(request->ReadRefTypeId()); } std::vector<uint64_t> counts; - JdwpError rc = Dbg::GetInstanceCounts(class_ids, counts); + JdwpError rc = Dbg::GetInstanceCounts(class_ids, &counts); if (rc != ERR_NONE) { return rc; } @@ -455,22 +455,22 @@ static JdwpError VM_InstanceCounts(JdwpState*, Request& request, ExpandBuf* pRep return ERR_NONE; } -static JdwpError RT_Modifiers(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError RT_Modifiers(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId refTypeId = request.ReadRefTypeId(); + RefTypeId refTypeId = request->ReadRefTypeId(); return Dbg::GetModifiers(refTypeId, pReply); } /* * Get values from static fields in a reference type. */ -static JdwpError RT_GetValues(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError RT_GetValues(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId refTypeId = request.ReadRefTypeId(); - int32_t field_count = request.ReadSigned32("field count"); + RefTypeId refTypeId = request->ReadRefTypeId(); + int32_t field_count = request->ReadSigned32("field count"); expandBufAdd4BE(pReply, field_count); for (int32_t i = 0; i < field_count; ++i) { - FieldId fieldId = request.ReadFieldId(); + FieldId fieldId = request->ReadFieldId(); JdwpError status = Dbg::GetStaticFieldValue(refTypeId, fieldId, pReply); if (status != ERR_NONE) { return status; @@ -482,11 +482,11 @@ static JdwpError RT_GetValues(JdwpState*, Request& request, ExpandBuf* pReply) /* * Get the name of the source file in which a reference type was declared. */ -static JdwpError RT_SourceFile(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError RT_SourceFile(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId refTypeId = request.ReadRefTypeId(); + RefTypeId refTypeId = request->ReadRefTypeId(); std::string source_file; - JdwpError status = Dbg::GetSourceFile(refTypeId, source_file); + JdwpError status = Dbg::GetSourceFile(refTypeId, &source_file); if (status != ERR_NONE) { return status; } @@ -497,9 +497,9 @@ static JdwpError RT_SourceFile(JdwpState*, Request& request, ExpandBuf* pReply) /* * Return the current status of the reference type. */ -static JdwpError RT_Status(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError RT_Status(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId refTypeId = request.ReadRefTypeId(); + RefTypeId refTypeId = request->ReadRefTypeId(); JDWP::JdwpTypeTag type_tag; uint32_t class_status; JDWP::JdwpError status = Dbg::GetClassInfo(refTypeId, &type_tag, &class_status, NULL); @@ -513,20 +513,20 @@ static JdwpError RT_Status(JdwpState*, Request& request, ExpandBuf* pReply) /* * Return interfaces implemented directly by this class. */ -static JdwpError RT_Interfaces(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError RT_Interfaces(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId refTypeId = request.ReadRefTypeId(); + RefTypeId refTypeId = request->ReadRefTypeId(); return Dbg::OutputDeclaredInterfaces(refTypeId, pReply); } /* * Return the class object corresponding to this type. */ -static JdwpError RT_ClassObject(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError RT_ClassObject(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId refTypeId = request.ReadRefTypeId(); + RefTypeId refTypeId = request->ReadRefTypeId(); ObjectId class_object_id; - JdwpError status = Dbg::GetClassObject(refTypeId, class_object_id); + JdwpError status = Dbg::GetClassObject(refTypeId, &class_object_id); if (status != ERR_NONE) { return status; } @@ -540,15 +540,15 @@ static JdwpError RT_ClassObject(JdwpState*, Request& request, ExpandBuf* pReply) * * JDB seems interested, but DEX files don't currently support this. */ -static JdwpError RT_SourceDebugExtension(JdwpState*, Request&, ExpandBuf*) +static JdwpError RT_SourceDebugExtension(JdwpState*, Request*, ExpandBuf*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { /* referenceTypeId in, string out */ return ERR_ABSENT_INFORMATION; } -static JdwpError RT_Signature(JdwpState*, Request& request, ExpandBuf* pReply, bool with_generic) +static JdwpError RT_Signature(JdwpState*, Request* request, ExpandBuf* pReply, bool with_generic) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId refTypeId = request.ReadRefTypeId(); + RefTypeId refTypeId = request->ReadRefTypeId(); std::string signature; JdwpError status = Dbg::GetSignature(refTypeId, &signature); @@ -562,12 +562,12 @@ static JdwpError RT_Signature(JdwpState*, Request& request, ExpandBuf* pReply, b return ERR_NONE; } -static JdwpError RT_Signature(JdwpState* state, Request& request, ExpandBuf* pReply) +static JdwpError RT_Signature(JdwpState* state, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return RT_Signature(state, request, pReply, false); } -static JdwpError RT_SignatureWithGeneric(JdwpState* state, Request& request, ExpandBuf* pReply) +static JdwpError RT_SignatureWithGeneric(JdwpState* state, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return RT_Signature(state, request, pReply, true); } @@ -576,9 +576,9 @@ static JdwpError RT_SignatureWithGeneric(JdwpState* state, Request& request, Exp * Return the instance of java.lang.ClassLoader that loaded the specified * reference type, or null if it was loaded by the system loader. */ -static JdwpError RT_ClassLoader(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError RT_ClassLoader(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId refTypeId = request.ReadRefTypeId(); + RefTypeId refTypeId = request->ReadRefTypeId(); return Dbg::GetClassLoader(refTypeId, pReply); } @@ -586,16 +586,16 @@ static JdwpError RT_ClassLoader(JdwpState*, Request& request, ExpandBuf* pReply) * Given a referenceTypeId, return a block of stuff that describes the * fields declared by a class. */ -static JdwpError RT_FieldsWithGeneric(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError RT_FieldsWithGeneric(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId refTypeId = request.ReadRefTypeId(); + RefTypeId refTypeId = request->ReadRefTypeId(); return Dbg::OutputDeclaredFields(refTypeId, true, pReply); } // Obsolete equivalent of FieldsWithGeneric, without the generic type information. -static JdwpError RT_Fields(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError RT_Fields(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId refTypeId = request.ReadRefTypeId(); + RefTypeId refTypeId = request->ReadRefTypeId(); return Dbg::OutputDeclaredFields(refTypeId, false, pReply); } @@ -603,29 +603,29 @@ static JdwpError RT_Fields(JdwpState*, Request& request, ExpandBuf* pReply) * Given a referenceTypeID, return a block of goodies describing the * methods declared by a class. */ -static JdwpError RT_MethodsWithGeneric(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError RT_MethodsWithGeneric(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId refTypeId = request.ReadRefTypeId(); + RefTypeId refTypeId = request->ReadRefTypeId(); return Dbg::OutputDeclaredMethods(refTypeId, true, pReply); } // Obsolete equivalent of MethodsWithGeneric, without the generic type information. -static JdwpError RT_Methods(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError RT_Methods(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId refTypeId = request.ReadRefTypeId(); + RefTypeId refTypeId = request->ReadRefTypeId(); return Dbg::OutputDeclaredMethods(refTypeId, false, pReply); } -static JdwpError RT_Instances(JdwpState*, Request& request, ExpandBuf* reply) +static JdwpError RT_Instances(JdwpState*, Request* request, ExpandBuf* reply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId class_id = request.ReadRefTypeId(); - int32_t max_count = request.ReadSigned32("max count"); + RefTypeId class_id = request->ReadRefTypeId(); + int32_t max_count = request->ReadSigned32("max count"); if (max_count < 0) { return ERR_ILLEGAL_ARGUMENT; } std::vector<ObjectId> instances; - JdwpError rc = Dbg::GetInstances(class_id, max_count, instances); + JdwpError rc = Dbg::GetInstances(class_id, max_count, &instances); if (rc != ERR_NONE) { return rc; } @@ -636,11 +636,11 @@ static JdwpError RT_Instances(JdwpState*, Request& request, ExpandBuf* reply) /* * Return the immediate superclass of a class. */ -static JdwpError CT_Superclass(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError CT_Superclass(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId class_id = request.ReadRefTypeId(); + RefTypeId class_id = request->ReadRefTypeId(); RefTypeId superClassId; - JdwpError status = Dbg::GetSuperclass(class_id, superClassId); + JdwpError status = Dbg::GetSuperclass(class_id, &superClassId); if (status != ERR_NONE) { return status; } @@ -651,18 +651,18 @@ static JdwpError CT_Superclass(JdwpState*, Request& request, ExpandBuf* pReply) /* * Set static class values. */ -static JdwpError CT_SetValues(JdwpState* , Request& request, ExpandBuf*) +static JdwpError CT_SetValues(JdwpState* , Request* request, ExpandBuf*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId class_id = request.ReadRefTypeId(); - int32_t values_count = request.ReadSigned32("values count"); + RefTypeId class_id = request->ReadRefTypeId(); + int32_t values_count = request->ReadSigned32("values count"); UNUSED(class_id); for (int32_t i = 0; i < values_count; ++i) { - FieldId fieldId = request.ReadFieldId(); + FieldId fieldId = request->ReadFieldId(); JDWP::JdwpTag fieldTag = Dbg::GetStaticFieldBasicTag(fieldId); size_t width = Dbg::GetTagWidth(fieldTag); - uint64_t value = request.ReadValue(width); + uint64_t value = request->ReadValue(width); VLOG(jdwp) << " --> field=" << fieldId << " tag=" << fieldTag << " --> " << value; JdwpError status = Dbg::SetStaticFieldValue(fieldId, value, width); @@ -680,11 +680,11 @@ static JdwpError CT_SetValues(JdwpState* , Request& request, ExpandBuf*) * Example: Eclipse sometimes uses java/lang/Class.forName(String s) on * values in the "variables" display. */ -static JdwpError CT_InvokeMethod(JdwpState* state, Request& request, ExpandBuf* pReply) +static JdwpError CT_InvokeMethod(JdwpState* state, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId class_id = request.ReadRefTypeId(); - ObjectId thread_id = request.ReadThreadId(); - MethodId method_id = request.ReadMethodId(); + RefTypeId class_id = request->ReadRefTypeId(); + ObjectId thread_id = request->ReadThreadId(); + MethodId method_id = request->ReadMethodId(); return FinishInvoke(state, request, pReply, thread_id, 0, class_id, method_id, false); } @@ -696,14 +696,14 @@ static JdwpError CT_InvokeMethod(JdwpState* state, Request& request, ExpandBuf* * Example: in IntelliJ, create a watch on "new String(myByteArray)" to * see the contents of a byte[] as a string. */ -static JdwpError CT_NewInstance(JdwpState* state, Request& request, ExpandBuf* pReply) +static JdwpError CT_NewInstance(JdwpState* state, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId class_id = request.ReadRefTypeId(); - ObjectId thread_id = request.ReadThreadId(); - MethodId method_id = request.ReadMethodId(); + RefTypeId class_id = request->ReadRefTypeId(); + ObjectId thread_id = request->ReadThreadId(); + MethodId method_id = request->ReadMethodId(); ObjectId object_id; - JdwpError status = Dbg::CreateObject(class_id, object_id); + JdwpError status = Dbg::CreateObject(class_id, &object_id); if (status != ERR_NONE) { return status; } @@ -716,13 +716,13 @@ static JdwpError CT_NewInstance(JdwpState* state, Request& request, ExpandBuf* p /* * Create a new array object of the requested type and length. */ -static JdwpError AT_newInstance(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError AT_newInstance(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId arrayTypeId = request.ReadRefTypeId(); - int32_t length = request.ReadSigned32("length"); + RefTypeId arrayTypeId = request->ReadRefTypeId(); + int32_t length = request->ReadSigned32("length"); ObjectId object_id; - JdwpError status = Dbg::CreateArrayObject(arrayTypeId, length, object_id); + JdwpError status = Dbg::CreateArrayObject(arrayTypeId, length, &object_id); if (status != ERR_NONE) { return status; } @@ -737,21 +737,21 @@ static JdwpError AT_newInstance(JdwpState*, Request& request, ExpandBuf* pReply) /* * Return line number information for the method, if present. */ -static JdwpError M_LineTable(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError M_LineTable(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId refTypeId = request.ReadRefTypeId(); - MethodId method_id = request.ReadMethodId(); + RefTypeId refTypeId = request->ReadRefTypeId(); + MethodId method_id = request->ReadMethodId(); Dbg::OutputLineTable(refTypeId, method_id, pReply); return ERR_NONE; } -static JdwpError M_VariableTable(JdwpState*, Request& request, ExpandBuf* pReply, +static JdwpError M_VariableTable(JdwpState*, Request* request, ExpandBuf* pReply, bool generic) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId class_id = request.ReadRefTypeId(); - MethodId method_id = request.ReadMethodId(); + RefTypeId class_id = request->ReadRefTypeId(); + MethodId method_id = request->ReadMethodId(); // We could return ERR_ABSENT_INFORMATION here if the DEX file was built without local variable // information. That will cause Eclipse to make a best-effort attempt at displaying local @@ -761,23 +761,23 @@ static JdwpError M_VariableTable(JdwpState*, Request& request, ExpandBuf* pReply return ERR_NONE; } -static JdwpError M_VariableTable(JdwpState* state, Request& request, ExpandBuf* pReply) +static JdwpError M_VariableTable(JdwpState* state, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return M_VariableTable(state, request, pReply, false); } -static JdwpError M_VariableTableWithGeneric(JdwpState* state, Request& request, ExpandBuf* pReply) +static JdwpError M_VariableTableWithGeneric(JdwpState* state, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return M_VariableTable(state, request, pReply, true); } -static JdwpError M_Bytecodes(JdwpState*, Request& request, ExpandBuf* reply) +static JdwpError M_Bytecodes(JdwpState*, Request* request, ExpandBuf* reply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId class_id = request.ReadRefTypeId(); - MethodId method_id = request.ReadMethodId(); + RefTypeId class_id = request->ReadRefTypeId(); + MethodId method_id = request->ReadMethodId(); std::vector<uint8_t> bytecodes; - JdwpError rc = Dbg::GetBytecodes(class_id, method_id, bytecodes); + JdwpError rc = Dbg::GetBytecodes(class_id, method_id, &bytecodes); if (rc != ERR_NONE) { return rc; } @@ -797,23 +797,23 @@ static JdwpError M_Bytecodes(JdwpState*, Request& request, ExpandBuf* reply) * This can get called on different things, e.g. thread_id gets * passed in here. */ -static JdwpError OR_ReferenceType(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError OR_ReferenceType(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId object_id = request.ReadObjectId(); + ObjectId object_id = request->ReadObjectId(); return Dbg::GetReferenceType(object_id, pReply); } /* * Get values from the fields of an object. */ -static JdwpError OR_GetValues(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError OR_GetValues(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId object_id = request.ReadObjectId(); - int32_t field_count = request.ReadSigned32("field count"); + ObjectId object_id = request->ReadObjectId(); + int32_t field_count = request->ReadSigned32("field count"); expandBufAdd4BE(pReply, field_count); for (int32_t i = 0; i < field_count; ++i) { - FieldId fieldId = request.ReadFieldId(); + FieldId fieldId = request->ReadFieldId(); JdwpError status = Dbg::GetFieldValue(object_id, fieldId, pReply); if (status != ERR_NONE) { return status; @@ -826,17 +826,17 @@ static JdwpError OR_GetValues(JdwpState*, Request& request, ExpandBuf* pReply) /* * Set values in the fields of an object. */ -static JdwpError OR_SetValues(JdwpState*, Request& request, ExpandBuf*) +static JdwpError OR_SetValues(JdwpState*, Request* request, ExpandBuf*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId object_id = request.ReadObjectId(); - int32_t field_count = request.ReadSigned32("field count"); + ObjectId object_id = request->ReadObjectId(); + int32_t field_count = request->ReadSigned32("field count"); for (int32_t i = 0; i < field_count; ++i) { - FieldId fieldId = request.ReadFieldId(); + FieldId fieldId = request->ReadFieldId(); JDWP::JdwpTag fieldTag = Dbg::GetFieldBasicTag(fieldId); size_t width = Dbg::GetTagWidth(fieldTag); - uint64_t value = request.ReadValue(width); + uint64_t value = request->ReadValue(width); VLOG(jdwp) << " --> fieldId=" << fieldId << " tag=" << fieldTag << "(" << width << ") value=" << value; JdwpError status = Dbg::SetFieldValue(object_id, fieldId, value, width); @@ -848,9 +848,9 @@ static JdwpError OR_SetValues(JdwpState*, Request& request, ExpandBuf*) return ERR_NONE; } -static JdwpError OR_MonitorInfo(JdwpState*, Request& request, ExpandBuf* reply) +static JdwpError OR_MonitorInfo(JdwpState*, Request* request, ExpandBuf* reply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId object_id = request.ReadObjectId(); + ObjectId object_id = request->ReadObjectId(); return Dbg::GetMonitorInfo(object_id, reply); } @@ -865,47 +865,47 @@ static JdwpError OR_MonitorInfo(JdwpState*, Request& request, ExpandBuf* reply) * object), it will try to invoke the object's toString() function. This * feature becomes crucial when examining ArrayLists with Eclipse. */ -static JdwpError OR_InvokeMethod(JdwpState* state, Request& request, ExpandBuf* pReply) +static JdwpError OR_InvokeMethod(JdwpState* state, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId object_id = request.ReadObjectId(); - ObjectId thread_id = request.ReadThreadId(); - RefTypeId class_id = request.ReadRefTypeId(); - MethodId method_id = request.ReadMethodId(); + ObjectId object_id = request->ReadObjectId(); + ObjectId thread_id = request->ReadThreadId(); + RefTypeId class_id = request->ReadRefTypeId(); + MethodId method_id = request->ReadMethodId(); return FinishInvoke(state, request, pReply, thread_id, object_id, class_id, method_id, false); } -static JdwpError OR_DisableCollection(JdwpState*, Request& request, ExpandBuf*) +static JdwpError OR_DisableCollection(JdwpState*, Request* request, ExpandBuf*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId object_id = request.ReadObjectId(); + ObjectId object_id = request->ReadObjectId(); return Dbg::DisableCollection(object_id); } -static JdwpError OR_EnableCollection(JdwpState*, Request& request, ExpandBuf*) +static JdwpError OR_EnableCollection(JdwpState*, Request* request, ExpandBuf*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId object_id = request.ReadObjectId(); + ObjectId object_id = request->ReadObjectId(); return Dbg::EnableCollection(object_id); } -static JdwpError OR_IsCollected(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError OR_IsCollected(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId object_id = request.ReadObjectId(); + ObjectId object_id = request->ReadObjectId(); bool is_collected; - JdwpError rc = Dbg::IsCollected(object_id, is_collected); + JdwpError rc = Dbg::IsCollected(object_id, &is_collected); expandBufAdd1(pReply, is_collected ? 1 : 0); return rc; } -static JdwpError OR_ReferringObjects(JdwpState*, Request& request, ExpandBuf* reply) +static JdwpError OR_ReferringObjects(JdwpState*, Request* request, ExpandBuf* reply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId object_id = request.ReadObjectId(); - int32_t max_count = request.ReadSigned32("max count"); + ObjectId object_id = request->ReadObjectId(); + int32_t max_count = request->ReadSigned32("max count"); if (max_count < 0) { return ERR_ILLEGAL_ARGUMENT; } std::vector<ObjectId> referring_objects; - JdwpError rc = Dbg::GetReferringObjects(object_id, max_count, referring_objects); + JdwpError rc = Dbg::GetReferringObjects(object_id, max_count, &referring_objects); if (rc != ERR_NONE) { return rc; } @@ -916,9 +916,9 @@ static JdwpError OR_ReferringObjects(JdwpState*, Request& request, ExpandBuf* re /* * Return the string value in a string object. */ -static JdwpError SR_Value(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError SR_Value(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId stringObject = request.ReadObjectId(); + ObjectId stringObject = request->ReadObjectId(); std::string str(Dbg::StringToUtf8(stringObject)); VLOG(jdwp) << StringPrintf(" --> %s", PrintableString(str.c_str()).c_str()); @@ -931,12 +931,12 @@ static JdwpError SR_Value(JdwpState*, Request& request, ExpandBuf* pReply) /* * Return a thread's name. */ -static JdwpError TR_Name(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError TR_Name(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_id = request.ReadThreadId(); + ObjectId thread_id = request->ReadThreadId(); std::string name; - JdwpError error = Dbg::GetThreadName(thread_id, name); + JdwpError error = Dbg::GetThreadName(thread_id, &name); if (error != ERR_NONE) { return error; } @@ -952,9 +952,9 @@ static JdwpError TR_Name(JdwpState*, Request& request, ExpandBuf* pReply) * It's supposed to remain suspended even if interpreted code wants to * resume it; only the JDI is allowed to resume it. */ -static JdwpError TR_Suspend(JdwpState*, Request& request, ExpandBuf*) +static JdwpError TR_Suspend(JdwpState*, Request* request, ExpandBuf*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_id = request.ReadThreadId(); + ObjectId thread_id = request->ReadThreadId(); if (thread_id == Dbg::GetThreadSelfId()) { LOG(INFO) << " Warning: ignoring request to suspend self"; @@ -971,9 +971,9 @@ static JdwpError TR_Suspend(JdwpState*, Request& request, ExpandBuf*) /* * Resume the specified thread. */ -static JdwpError TR_Resume(JdwpState*, Request& request, ExpandBuf*) +static JdwpError TR_Resume(JdwpState*, Request* request, ExpandBuf*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_id = request.ReadThreadId(); + ObjectId thread_id = request->ReadThreadId(); if (thread_id == Dbg::GetThreadSelfId()) { LOG(INFO) << " Warning: ignoring request to resume self"; @@ -989,9 +989,9 @@ static JdwpError TR_Resume(JdwpState*, Request& request, ExpandBuf*) /* * Return status of specified thread. */ -static JdwpError TR_Status(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError TR_Status(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_id = request.ReadThreadId(); + ObjectId thread_id = request->ReadThreadId(); JDWP::JdwpThreadStatus threadStatus; JDWP::JdwpSuspendStatus suspendStatus; @@ -1011,9 +1011,9 @@ static JdwpError TR_Status(JdwpState*, Request& request, ExpandBuf* pReply) /* * Return the thread group that the specified thread is a member of. */ -static JdwpError TR_ThreadGroup(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError TR_ThreadGroup(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_id = request.ReadThreadId(); + ObjectId thread_id = request->ReadThreadId(); return Dbg::GetThreadGroup(thread_id, pReply); } @@ -1023,14 +1023,14 @@ static JdwpError TR_ThreadGroup(JdwpState*, Request& request, ExpandBuf* pReply) * If the thread isn't suspended, the error code isn't defined, but should * be THREAD_NOT_SUSPENDED. */ -static JdwpError TR_Frames(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError TR_Frames(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_id = request.ReadThreadId(); - uint32_t start_frame = request.ReadUnsigned32("start frame"); - uint32_t length = request.ReadUnsigned32("length"); + ObjectId thread_id = request->ReadThreadId(); + uint32_t start_frame = request->ReadUnsigned32("start frame"); + uint32_t length = request->ReadUnsigned32("length"); size_t actual_frame_count; - JdwpError error = Dbg::GetThreadFrameCount(thread_id, actual_frame_count); + JdwpError error = Dbg::GetThreadFrameCount(thread_id, &actual_frame_count); if (error != ERR_NONE) { return error; } @@ -1055,12 +1055,12 @@ static JdwpError TR_Frames(JdwpState*, Request& request, ExpandBuf* pReply) /* * Returns the #of frames on the specified thread, which must be suspended. */ -static JdwpError TR_FrameCount(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError TR_FrameCount(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_id = request.ReadThreadId(); + ObjectId thread_id = request->ReadThreadId(); size_t frame_count; - JdwpError rc = Dbg::GetThreadFrameCount(thread_id, frame_count); + JdwpError rc = Dbg::GetThreadFrameCount(thread_id, &frame_count); if (rc != ERR_NONE) { return rc; } @@ -1069,13 +1069,13 @@ static JdwpError TR_FrameCount(JdwpState*, Request& request, ExpandBuf* pReply) return ERR_NONE; } -static JdwpError TR_OwnedMonitors(Request& request, ExpandBuf* reply, bool with_stack_depths) +static JdwpError TR_OwnedMonitors(Request* request, ExpandBuf* reply, bool with_stack_depths) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_id = request.ReadThreadId(); + ObjectId thread_id = request->ReadThreadId(); std::vector<ObjectId> monitors; std::vector<uint32_t> stack_depths; - JdwpError rc = Dbg::GetOwnedMonitors(thread_id, monitors, stack_depths); + JdwpError rc = Dbg::GetOwnedMonitors(thread_id, &monitors, &stack_depths); if (rc != ERR_NONE) { return rc; } @@ -1093,31 +1093,31 @@ static JdwpError TR_OwnedMonitors(Request& request, ExpandBuf* reply, bool with_ return ERR_NONE; } -static JdwpError TR_OwnedMonitors(JdwpState*, Request& request, ExpandBuf* reply) +static JdwpError TR_OwnedMonitors(JdwpState*, Request* request, ExpandBuf* reply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return TR_OwnedMonitors(request, reply, false); } -static JdwpError TR_OwnedMonitorsStackDepthInfo(JdwpState*, Request& request, ExpandBuf* reply) +static JdwpError TR_OwnedMonitorsStackDepthInfo(JdwpState*, Request* request, ExpandBuf* reply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return TR_OwnedMonitors(request, reply, true); } -static JdwpError TR_CurrentContendedMonitor(JdwpState*, Request& request, ExpandBuf* reply) +static JdwpError TR_CurrentContendedMonitor(JdwpState*, Request* request, ExpandBuf* reply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_id = request.ReadThreadId(); + ObjectId thread_id = request->ReadThreadId(); ObjectId contended_monitor; - JdwpError rc = Dbg::GetContendedMonitor(thread_id, contended_monitor); + JdwpError rc = Dbg::GetContendedMonitor(thread_id, &contended_monitor); if (rc != ERR_NONE) { return rc; } return WriteTaggedObject(reply, contended_monitor); } -static JdwpError TR_Interrupt(JdwpState*, Request& request, ExpandBuf* reply) +static JdwpError TR_Interrupt(JdwpState*, Request* request, ExpandBuf* reply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_id = request.ReadThreadId(); + ObjectId thread_id = request->ReadThreadId(); return Dbg::Interrupt(thread_id); } @@ -1127,9 +1127,9 @@ static JdwpError TR_Interrupt(JdwpState*, Request& request, ExpandBuf* reply) * (The thread *might* still be running -- it might not have examined * its suspend count recently.) */ -static JdwpError TR_DebugSuspendCount(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError TR_DebugSuspendCount(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_id = request.ReadThreadId(); + ObjectId thread_id = request->ReadThreadId(); return Dbg::GetThreadDebugSuspendCount(thread_id, pReply); } @@ -1138,9 +1138,9 @@ static JdwpError TR_DebugSuspendCount(JdwpState*, Request& request, ExpandBuf* p * * The Eclipse debugger recognizes "main" and "system" as special. */ -static JdwpError TGR_Name(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError TGR_Name(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_group_id = request.ReadThreadGroupId(); + ObjectId thread_group_id = request->ReadThreadGroupId(); expandBufAddUtf8String(pReply, Dbg::GetThreadGroupName(thread_group_id)); @@ -1151,9 +1151,9 @@ static JdwpError TGR_Name(JdwpState*, Request& request, ExpandBuf* pReply) * Returns the thread group -- if any -- that contains the specified * thread group. */ -static JdwpError TGR_Parent(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError TGR_Parent(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_group_id = request.ReadThreadGroupId(); + ObjectId thread_group_id = request->ReadThreadGroupId(); ObjectId parentGroup = Dbg::GetThreadGroupParent(thread_group_id); expandBufAddObjectId(pReply, parentGroup); @@ -1165,19 +1165,19 @@ static JdwpError TGR_Parent(JdwpState*, Request& request, ExpandBuf* pReply) * Return the active threads and thread groups that are part of the * specified thread group. */ -static JdwpError TGR_Children(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError TGR_Children(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_group_id = request.ReadThreadGroupId(); + ObjectId thread_group_id = request->ReadThreadGroupId(); std::vector<ObjectId> thread_ids; - Dbg::GetThreads(thread_group_id, thread_ids); + Dbg::GetThreads(thread_group_id, &thread_ids); expandBufAdd4BE(pReply, thread_ids.size()); for (uint32_t i = 0; i < thread_ids.size(); ++i) { expandBufAddObjectId(pReply, thread_ids[i]); } std::vector<ObjectId> child_thread_groups_ids; - Dbg::GetChildThreadGroups(thread_group_id, child_thread_groups_ids); + Dbg::GetChildThreadGroups(thread_group_id, &child_thread_groups_ids); expandBufAdd4BE(pReply, child_thread_groups_ids.size()); for (uint32_t i = 0; i < child_thread_groups_ids.size(); ++i) { expandBufAddObjectId(pReply, child_thread_groups_ids[i]); @@ -1189,12 +1189,12 @@ static JdwpError TGR_Children(JdwpState*, Request& request, ExpandBuf* pReply) /* * Return the #of components in the array. */ -static JdwpError AR_Length(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError AR_Length(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId array_id = request.ReadArrayId(); + ObjectId array_id = request->ReadArrayId(); - int length; - JdwpError status = Dbg::GetArrayLength(array_id, length); + int32_t length; + JdwpError status = Dbg::GetArrayLength(array_id, &length); if (status != ERR_NONE) { return status; } @@ -1208,28 +1208,28 @@ static JdwpError AR_Length(JdwpState*, Request& request, ExpandBuf* pReply) /* * Return the values from an array. */ -static JdwpError AR_GetValues(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError AR_GetValues(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId array_id = request.ReadArrayId(); - uint32_t offset = request.ReadUnsigned32("offset"); - uint32_t length = request.ReadUnsigned32("length"); + ObjectId array_id = request->ReadArrayId(); + uint32_t offset = request->ReadUnsigned32("offset"); + uint32_t length = request->ReadUnsigned32("length"); return Dbg::OutputArray(array_id, offset, length, pReply); } /* * Set values in an array. */ -static JdwpError AR_SetValues(JdwpState*, Request& request, ExpandBuf*) +static JdwpError AR_SetValues(JdwpState*, Request* request, ExpandBuf*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId array_id = request.ReadArrayId(); - uint32_t offset = request.ReadUnsigned32("offset"); - uint32_t count = request.ReadUnsigned32("count"); + ObjectId array_id = request->ReadArrayId(); + uint32_t offset = request->ReadUnsigned32("offset"); + uint32_t count = request->ReadUnsigned32("count"); return Dbg::SetArrayElements(array_id, offset, count, request); } -static JdwpError CLR_VisibleClasses(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError CLR_VisibleClasses(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - request.ReadObjectId(); // classLoaderObject + request->ReadObjectId(); // classLoaderObject // TODO: we should only return classes which have the given class loader as a defining or // initiating loader. The former would be easy; the latter is hard, because we don't have // any such notion. @@ -1241,11 +1241,11 @@ static JdwpError CLR_VisibleClasses(JdwpState*, Request& request, ExpandBuf* pRe * * Reply with a requestID. */ -static JdwpError ER_Set(JdwpState* state, Request& request, ExpandBuf* pReply) +static JdwpError ER_Set(JdwpState* state, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - JdwpEventKind event_kind = request.ReadEnum1<JdwpEventKind>("event kind"); - JdwpSuspendPolicy suspend_policy = request.ReadEnum1<JdwpSuspendPolicy>("suspend policy"); - int32_t modifier_count = request.ReadSigned32("modifier count"); + JdwpEventKind event_kind = request->ReadEnum1<JdwpEventKind>("event kind"); + JdwpSuspendPolicy suspend_policy = request->ReadEnum1<JdwpSuspendPolicy>("suspend policy"); + int32_t modifier_count = request->ReadSigned32("modifier count"); CHECK_LT(modifier_count, 256); /* reasonableness check */ @@ -1260,12 +1260,12 @@ static JdwpError ER_Set(JdwpState* state, Request& request, ExpandBuf* pReply) */ for (int32_t i = 0; i < modifier_count; ++i) { JdwpEventMod& mod = pEvent->mods[i]; - mod.modKind = request.ReadModKind(); + mod.modKind = request->ReadModKind(); switch (mod.modKind) { case MK_COUNT: { // Report once, when "--count" reaches 0. - uint32_t count = request.ReadUnsigned32("count"); + uint32_t count = request->ReadUnsigned32("count"); if (count == 0) { return ERR_INVALID_COUNT; } @@ -1275,21 +1275,21 @@ static JdwpError ER_Set(JdwpState* state, Request& request, ExpandBuf* pReply) case MK_CONDITIONAL: { // Conditional on expression. - uint32_t exprId = request.ReadUnsigned32("expr id"); + uint32_t exprId = request->ReadUnsigned32("expr id"); mod.conditional.exprId = exprId; } break; case MK_THREAD_ONLY: { // Only report events in specified thread. - ObjectId thread_id = request.ReadThreadId(); + ObjectId thread_id = request->ReadThreadId(); mod.threadOnly.threadId = thread_id; } break; case MK_CLASS_ONLY: { // For ClassPrepare, MethodEntry. - RefTypeId class_id = request.ReadRefTypeId(); + RefTypeId class_id = request->ReadRefTypeId(); mod.classOnly.refTypeId = class_id; } break; @@ -1297,7 +1297,7 @@ static JdwpError ER_Set(JdwpState* state, Request& request, ExpandBuf* pReply) { // Restrict events to matching classes. // pattern is "java.foo.*", we want "java/foo/*". - std::string pattern(request.ReadUtf8String()); + std::string pattern(request->ReadUtf8String()); std::replace(pattern.begin(), pattern.end(), '.', '/'); mod.classMatch.classPattern = strdup(pattern.c_str()); } @@ -1306,7 +1306,7 @@ static JdwpError ER_Set(JdwpState* state, Request& request, ExpandBuf* pReply) { // Restrict events to non-matching classes. // pattern is "java.foo.*", we want "java/foo/*". - std::string pattern(request.ReadUtf8String()); + std::string pattern(request->ReadUtf8String()); std::replace(pattern.begin(), pattern.end(), '.', '/'); mod.classExclude.classPattern = strdup(pattern.c_str()); } @@ -1314,23 +1314,23 @@ static JdwpError ER_Set(JdwpState* state, Request& request, ExpandBuf* pReply) case MK_LOCATION_ONLY: { // Restrict certain events based on location. - JdwpLocation location = request.ReadLocation(); + JdwpLocation location = request->ReadLocation(); mod.locationOnly.loc = location; } break; case MK_EXCEPTION_ONLY: { // Modifies EK_EXCEPTION events, - mod.exceptionOnly.refTypeId = request.ReadRefTypeId(); // null => all exceptions. - mod.exceptionOnly.caught = request.ReadEnum1<uint8_t>("caught"); - mod.exceptionOnly.uncaught = request.ReadEnum1<uint8_t>("uncaught"); + mod.exceptionOnly.refTypeId = request->ReadRefTypeId(); // null => all exceptions. + mod.exceptionOnly.caught = request->ReadEnum1<uint8_t>("caught"); + mod.exceptionOnly.uncaught = request->ReadEnum1<uint8_t>("uncaught"); } break; case MK_FIELD_ONLY: { // For field access/modification events. - RefTypeId declaring = request.ReadRefTypeId(); - FieldId fieldId = request.ReadFieldId(); + RefTypeId declaring = request->ReadRefTypeId(); + FieldId fieldId = request->ReadFieldId(); mod.fieldOnly.refTypeId = declaring; mod.fieldOnly.fieldId = fieldId; } @@ -1338,9 +1338,9 @@ static JdwpError ER_Set(JdwpState* state, Request& request, ExpandBuf* pReply) case MK_STEP: { // For use with EK_SINGLE_STEP. - ObjectId thread_id = request.ReadThreadId(); - uint32_t size = request.ReadUnsigned32("step size"); - uint32_t depth = request.ReadUnsigned32("step depth"); + ObjectId thread_id = request->ReadThreadId(); + uint32_t size = request->ReadUnsigned32("step size"); + uint32_t depth = request->ReadUnsigned32("step depth"); VLOG(jdwp) << StringPrintf(" Step: thread=%#" PRIx64, thread_id) << " size=" << JdwpStepSize(size) << " depth=" << JdwpStepDepth(depth); @@ -1352,7 +1352,7 @@ static JdwpError ER_Set(JdwpState* state, Request& request, ExpandBuf* pReply) case MK_INSTANCE_ONLY: { // Report events related to a specific object. - ObjectId instance = request.ReadObjectId(); + ObjectId instance = request->ReadObjectId(); mod.instanceOnly.objectId = instance; } break; @@ -1382,10 +1382,10 @@ static JdwpError ER_Set(JdwpState* state, Request& request, ExpandBuf* pReply) return err; } -static JdwpError ER_Clear(JdwpState* state, Request& request, ExpandBuf*) +static JdwpError ER_Clear(JdwpState* state, Request* request, ExpandBuf*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - request.ReadEnum1<JdwpEventKind>("event kind"); - uint32_t requestId = request.ReadUnsigned32("request id"); + request->ReadEnum1<JdwpEventKind>("event kind"); + uint32_t requestId = request->ReadUnsigned32("request id"); // Failure to find an event with a matching ID is a no-op // and does not return an error. @@ -1396,16 +1396,16 @@ static JdwpError ER_Clear(JdwpState* state, Request& request, ExpandBuf*) /* * Return the values of arguments and local variables. */ -static JdwpError SF_GetValues(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError SF_GetValues(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_id = request.ReadThreadId(); - FrameId frame_id = request.ReadFrameId(); - int32_t slot_count = request.ReadSigned32("slot count"); + ObjectId thread_id = request->ReadThreadId(); + FrameId frame_id = request->ReadFrameId(); + int32_t slot_count = request->ReadSigned32("slot count"); expandBufAdd4BE(pReply, slot_count); /* "int values" */ for (int32_t i = 0; i < slot_count; ++i) { - uint32_t slot = request.ReadUnsigned32("slot"); - JDWP::JdwpTag reqSigByte = request.ReadTag(); + uint32_t slot = request->ReadUnsigned32("slot"); + JDWP::JdwpTag reqSigByte = request->ReadTag(); VLOG(jdwp) << " --> slot " << slot << " " << reqSigByte; @@ -1423,17 +1423,17 @@ static JdwpError SF_GetValues(JdwpState*, Request& request, ExpandBuf* pReply) /* * Set the values of arguments and local variables. */ -static JdwpError SF_SetValues(JdwpState*, Request& request, ExpandBuf*) +static JdwpError SF_SetValues(JdwpState*, Request* request, ExpandBuf*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_id = request.ReadThreadId(); - FrameId frame_id = request.ReadFrameId(); - int32_t slot_count = request.ReadSigned32("slot count"); + ObjectId thread_id = request->ReadThreadId(); + FrameId frame_id = request->ReadFrameId(); + int32_t slot_count = request->ReadSigned32("slot count"); for (int32_t i = 0; i < slot_count; ++i) { - uint32_t slot = request.ReadUnsigned32("slot"); - JDWP::JdwpTag sigByte = request.ReadTag(); + uint32_t slot = request->ReadUnsigned32("slot"); + JDWP::JdwpTag sigByte = request->ReadTag(); size_t width = Dbg::GetTagWidth(sigByte); - uint64_t value = request.ReadValue(width); + uint64_t value = request->ReadValue(width); VLOG(jdwp) << " --> slot " << slot << " " << sigByte << " " << value; JdwpError error = Dbg::SetLocalValue(thread_id, frame_id, slot, sigByte, value, width); @@ -1445,10 +1445,10 @@ static JdwpError SF_SetValues(JdwpState*, Request& request, ExpandBuf*) return ERR_NONE; } -static JdwpError SF_ThisObject(JdwpState*, Request& request, ExpandBuf* reply) +static JdwpError SF_ThisObject(JdwpState*, Request* request, ExpandBuf* reply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectId thread_id = request.ReadThreadId(); - FrameId frame_id = request.ReadFrameId(); + ObjectId thread_id = request->ReadThreadId(); + FrameId frame_id = request->ReadFrameId(); ObjectId object_id; JdwpError rc = Dbg::GetThisObject(thread_id, frame_id, &object_id); @@ -1466,16 +1466,16 @@ static JdwpError SF_ThisObject(JdwpState*, Request& request, ExpandBuf* reply) * reused, whereas ClassIds can be recycled like any other object. (Either * that, or I have no idea what this is for.) */ -static JdwpError COR_ReflectedType(JdwpState*, Request& request, ExpandBuf* pReply) +static JdwpError COR_ReflectedType(JdwpState*, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - RefTypeId class_object_id = request.ReadRefTypeId(); + RefTypeId class_object_id = request->ReadRefTypeId(); return Dbg::GetReflectedType(class_object_id, pReply); } /* * Handle a DDM packet with a single chunk in it. */ -static JdwpError DDM_Chunk(JdwpState* state, Request& request, ExpandBuf* pReply) +static JdwpError DDM_Chunk(JdwpState* state, Request* request, ExpandBuf* pReply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { state->NotifyDdmsActive(); uint8_t* replyBuf = NULL; @@ -1496,7 +1496,7 @@ static JdwpError DDM_Chunk(JdwpState* state, Request& request, ExpandBuf* pReply /* * Handler map decl. */ -typedef JdwpError (*JdwpRequestHandler)(JdwpState* state, Request& request, ExpandBuf* reply); +typedef JdwpError (*JdwpRequestHandler)(JdwpState* state, Request* request, ExpandBuf* reply); struct JdwpHandlerMap { uint8_t cmdSet; @@ -1639,20 +1639,20 @@ static const JdwpHandlerMap gHandlers[] = { { 199, 1, DDM_Chunk, "DDM.Chunk" }, }; -static const char* GetCommandName(Request& request) { +static const char* GetCommandName(Request* request) { for (size_t i = 0; i < arraysize(gHandlers); ++i) { - if (gHandlers[i].cmdSet == request.GetCommandSet() && gHandlers[i].cmd == request.GetCommand()) { + if (gHandlers[i].cmdSet == request->GetCommandSet() && gHandlers[i].cmd == request->GetCommand()) { return gHandlers[i].name; } } return "?UNKNOWN?"; } -static std::string DescribeCommand(Request& request) { +static std::string DescribeCommand(Request* request) { std::string result; result += "REQUEST: "; result += GetCommandName(request); - result += StringPrintf(" (length=%zu id=0x%06x)", request.GetLength(), request.GetId()); + result += StringPrintf(" (length=%zu id=0x%06x)", request->GetLength(), request->GetId()); return result; } @@ -1661,10 +1661,10 @@ static std::string DescribeCommand(Request& request) { * * On entry, the JDWP thread is in VMWAIT. */ -size_t JdwpState::ProcessRequest(Request& request, ExpandBuf* pReply) { +size_t JdwpState::ProcessRequest(Request* request, ExpandBuf* pReply) { JdwpError result = ERR_NONE; - if (request.GetCommandSet() != kJDWPDdmCmdSet) { + if (request->GetCommandSet() != kJDWPDdmCmdSet) { /* * Activity from a debugger, not merely ddms. Mark us as having an * active debugger session, and zero out the last-activity timestamp @@ -1684,7 +1684,7 @@ size_t JdwpState::ProcessRequest(Request& request, ExpandBuf* pReply) { * thread to finish, and then clear the block. Depending on the thread * suspend policy, this may allow events in other threads to fire, * but those events have no bearing on what the debugger has sent us - * in the current request. + * in the current request-> * * Note that we MUST clear the event token before waking the event * thread up, or risk waiting for the thread to suspend after we've @@ -1693,7 +1693,7 @@ size_t JdwpState::ProcessRequest(Request& request, ExpandBuf* pReply) { SetWaitForEventThread(0); /* - * We do not want events to be sent while we process a request. Indicate the JDWP thread starts + * We do not want events to be sent while we process a request-> Indicate the JDWP thread starts * to process a request so other threads wait for it to finish before sending an event. */ StartProcessingRequest(); @@ -1709,18 +1709,18 @@ size_t JdwpState::ProcessRequest(Request& request, ExpandBuf* pReply) { size_t i; for (i = 0; i < arraysize(gHandlers); ++i) { - if (gHandlers[i].cmdSet == request.GetCommandSet() && gHandlers[i].cmd == request.GetCommand() && gHandlers[i].func != NULL) { + if (gHandlers[i].cmdSet == request->GetCommandSet() && gHandlers[i].cmd == request->GetCommand() && gHandlers[i].func != NULL) { VLOG(jdwp) << DescribeCommand(request); result = (*gHandlers[i].func)(this, request, pReply); if (result == ERR_NONE) { - request.CheckConsumed(); + request->CheckConsumed(); } break; } } if (i == arraysize(gHandlers)) { LOG(ERROR) << "Command not implemented: " << DescribeCommand(request); - LOG(ERROR) << HexDump(request.data(), request.size(), false, ""); + LOG(ERROR) << HexDump(request->data(), request->size(), false, ""); result = ERR_NOT_IMPLEMENTED; } @@ -1732,11 +1732,11 @@ size_t JdwpState::ProcessRequest(Request& request, ExpandBuf* pReply) { uint8_t* replyBuf = expandBufGetBuffer(pReply); size_t replyLength = (result == ERR_NONE) ? expandBufGetLength(pReply) : kJDWPHeaderLen; Set4BE(replyBuf + 0, replyLength); - Set4BE(replyBuf + 4, request.GetId()); + Set4BE(replyBuf + 4, request->GetId()); Set1(replyBuf + 8, kJDWPFlagReply); Set2BE(replyBuf + 9, result); - CHECK_GT(expandBufGetLength(pReply), 0U) << GetCommandName(request) << " " << request.GetId(); + CHECK_GT(expandBufGetLength(pReply), 0U) << GetCommandName(request) << " " << request->GetId(); size_t respLen = expandBufGetLength(pReply) - kJDWPHeaderLen; VLOG(jdwp) << "REPLY: " << GetCommandName(request) << " " << result << " (length=" << respLen << ")"; @@ -1750,7 +1750,7 @@ size_t JdwpState::ProcessRequest(Request& request, ExpandBuf* pReply) { * Update last-activity timestamp. We really only need this during * the initial setup. Only update if this is a non-DDMS packet. */ - if (request.GetCommandSet() != kJDWPDdmCmdSet) { + if (request->GetCommandSet() != kJDWPDdmCmdSet) { last_activity_time_ms_.StoreSequentiallyConsistent(MilliTime()); } diff --git a/runtime/jdwp/jdwp_main.cc b/runtime/jdwp/jdwp_main.cc index a4f427ca29..c500ef5311 100644 --- a/runtime/jdwp/jdwp_main.cc +++ b/runtime/jdwp/jdwp_main.cc @@ -373,7 +373,7 @@ bool JdwpState::HandlePacket() { JDWP::Request request(netStateBase->input_buffer_, netStateBase->input_count_); ExpandBuf* pReply = expandBufAlloc(); - size_t replyLength = ProcessRequest(request, pReply); + size_t replyLength = ProcessRequest(&request, pReply); ssize_t cc = netStateBase->WritePacket(pReply, replyLength); /* diff --git a/runtime/jdwp/object_registry.cc b/runtime/jdwp/object_registry.cc index ad18d8a2ce..35aaf0ab8f 100644 --- a/runtime/jdwp/object_registry.cc +++ b/runtime/jdwp/object_registry.cc @@ -21,8 +21,6 @@ namespace art { -mirror::Object* const ObjectRegistry::kInvalidObject = reinterpret_cast<mirror::Object*>(1); - std::ostream& operator<<(std::ostream& os, const ObjectRegistryEntry& rhs) { os << "ObjectRegistryEntry[" << rhs.jni_reference_type << ",reference=" << rhs.jni_reference @@ -129,14 +127,16 @@ void ObjectRegistry::Clear() { id_to_entry_.clear(); } -mirror::Object* ObjectRegistry::InternalGet(JDWP::ObjectId id) { +mirror::Object* ObjectRegistry::InternalGet(JDWP::ObjectId id, JDWP::JdwpError* error) { Thread* self = Thread::Current(); MutexLock mu(self, lock_); auto it = id_to_entry_.find(id); if (it == id_to_entry_.end()) { - return kInvalidObject; + *error = JDWP::ERR_INVALID_OBJECT; + return nullptr; } ObjectRegistryEntry& entry = *it->second; + *error = JDWP::ERR_NONE; return self->DecodeJObject(entry.jni_reference); } diff --git a/runtime/jdwp/object_registry.h b/runtime/jdwp/object_registry.h index f0314a382f..0e46d5cf20 100644 --- a/runtime/jdwp/object_registry.h +++ b/runtime/jdwp/object_registry.h @@ -22,6 +22,7 @@ #include <map> +#include "base/casts.h" #include "jdwp/jdwp.h" #include "safe_map.h" @@ -64,11 +65,13 @@ class ObjectRegistry { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCKS_EXCLUDED(Locks::thread_list_lock_); JDWP::RefTypeId AddRefType(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - template<typename T> T Get(JDWP::ObjectId id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + template<typename T> T Get(JDWP::ObjectId id, JDWP::JdwpError* error) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (id == 0) { - return NULL; + *error = JDWP::ERR_NONE; + return nullptr; } - return reinterpret_cast<T>(InternalGet(id)); + return down_cast<T>(InternalGet(id, error)); } bool Contains(mirror::Object* o) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -85,9 +88,6 @@ class ObjectRegistry { void DisposeObject(JDWP::ObjectId id, uint32_t reference_count) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - // Returned by Get when passed an invalid object id. - static mirror::Object* const kInvalidObject; - // This is needed to get the jobject instead of the Object*. // Avoid using this and use standard Get when possible. jobject GetJObject(JDWP::ObjectId id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -95,7 +95,8 @@ class ObjectRegistry { private: JDWP::ObjectId InternalAdd(mirror::Object* o) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCKS_EXCLUDED(Locks::thread_list_lock_); - mirror::Object* InternalGet(JDWP::ObjectId id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::Object* InternalGet(JDWP::ObjectId id, JDWP::JdwpError* error) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void Demote(ObjectRegistryEntry& entry) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, lock_); void Promote(ObjectRegistryEntry& entry) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, lock_); bool Contains(mirror::Object* o, ObjectRegistryEntry** out_entry) diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 919655695a..3e9ae09bde 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -2261,25 +2261,15 @@ class JNI { IndirectRef ref = reinterpret_cast<IndirectRef>(java_object); IndirectRefKind kind = GetIndirectRefKind(ref); switch (kind) { - case kLocal: { - ScopedObjectAccess soa(env); - // The local refs don't need a read barrier. - if (static_cast<JNIEnvExt*>(env)->locals.Get<kWithoutReadBarrier>(ref) != - kInvalidIndirectRefObject) { - return JNILocalRefType; - } - return JNIInvalidRefType; - } + case kLocal: + return JNILocalRefType; case kGlobal: return JNIGlobalRefType; case kWeakGlobal: return JNIWeakGlobalRefType; case kHandleScopeOrInvalid: - // Is it in a stack IRT? - if (static_cast<JNIEnvExt*>(env)->self->HandleScopeContains(java_object)) { - return JNILocalRefType; - } - return JNIInvalidRefType; + // Assume value is in a handle scope. + return JNILocalRefType; } LOG(FATAL) << "IndirectRefKind[" << kind << "]"; return JNIInvalidRefType; diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc index b236edea9e..20d031c3e5 100644 --- a/runtime/jni_internal_test.cc +++ b/runtime/jni_internal_test.cc @@ -1269,13 +1269,14 @@ TEST_F(JniInternalTest, GetObjectRefType) { jweak weak_global = env_->NewWeakGlobalRef(local); EXPECT_EQ(JNIWeakGlobalRefType, env_->GetObjectRefType(weak_global)); + CheckJniAbortCatcher jni_abort_catcher; jobject invalid = reinterpret_cast<jobject>(this); EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(invalid)); + jni_abort_catcher.Check("use of invalid jobject"); // TODO: invoke a native method and test that its arguments are considered local references. // Null as object should fail. - CheckJniAbortCatcher jni_abort_catcher; EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(nullptr)); jni_abort_catcher.Check("java_object == null"); } @@ -1687,7 +1688,7 @@ TEST_F(JniInternalTest, DeleteLocalRef) { CheckJniAbortCatcher check_jni_abort_catcher; EXPECT_FALSE(vm_->SetCheckJniEnabled(true)); env_->DeleteLocalRef(s); - std::string expected(StringPrintf("jobject is an invalid local reference: %p", s)); + std::string expected(StringPrintf("use of deleted local reference %p", s)); check_jni_abort_catcher.Check(expected.c_str()); EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni)); } @@ -1723,7 +1724,6 @@ TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) { jobject outer; jobject inner1, inner2; ScopedObjectAccess soa(env_); - mirror::Object* inner2_direct_pointer; { ASSERT_EQ(JNI_OK, env_->PushLocalFrame(4)); outer = env_->NewLocalRef(original); @@ -1732,24 +1732,35 @@ TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) { ASSERT_EQ(JNI_OK, env_->PushLocalFrame(4)); inner1 = env_->NewLocalRef(outer); inner2 = env_->NewStringUTF("survivor"); - inner2_direct_pointer = soa.Decode<mirror::Object*>(inner2); - env_->PopLocalFrame(inner2); + EXPECT_NE(env_->PopLocalFrame(inner2), nullptr); } EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original)); EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(outer)); - EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1)); + { + CheckJniAbortCatcher check_jni_abort_catcher; + EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1)); + check_jni_abort_catcher.Check("use of deleted local reference"); + } // Our local reference for the survivor is invalid because the survivor // gets a new local reference... - EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2)); + { + CheckJniAbortCatcher check_jni_abort_catcher; + EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2)); + check_jni_abort_catcher.Check("use of deleted local reference"); + } - env_->PopLocalFrame(nullptr); + EXPECT_EQ(env_->PopLocalFrame(nullptr), nullptr); } EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original)); + CheckJniAbortCatcher check_jni_abort_catcher; EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(outer)); + check_jni_abort_catcher.Check("use of deleted local reference"); EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1)); + check_jni_abort_catcher.Check("use of deleted local reference"); EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2)); + check_jni_abort_catcher.Check("use of deleted local reference"); } TEST_F(JniInternalTest, NewGlobalRef_nullptr) { @@ -1788,7 +1799,7 @@ TEST_F(JniInternalTest, DeleteGlobalRef) { CheckJniAbortCatcher check_jni_abort_catcher; EXPECT_FALSE(vm_->SetCheckJniEnabled(true)); env_->DeleteGlobalRef(o); - std::string expected(StringPrintf("jobject is an invalid global reference: %p", o)); + std::string expected(StringPrintf("use of deleted global reference %p", o)); check_jni_abort_catcher.Check(expected.c_str()); EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni)); } @@ -1838,7 +1849,7 @@ TEST_F(JniInternalTest, DeleteWeakGlobalRef) { CheckJniAbortCatcher check_jni_abort_catcher; EXPECT_FALSE(vm_->SetCheckJniEnabled(true)); env_->DeleteWeakGlobalRef(o); - std::string expected(StringPrintf("jobject is an invalid weak global reference: %p", o)); + std::string expected(StringPrintf("use of deleted weak global reference %p", o)); check_jni_abort_catcher.Check(expected.c_str()); EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni)); } diff --git a/runtime/reference_table.cc b/runtime/reference_table.cc index 70aba9bbf1..01c5070869 100644 --- a/runtime/reference_table.cc +++ b/runtime/reference_table.cc @@ -24,6 +24,7 @@ #include "mirror/class-inl.h" #include "mirror/object-inl.h" #include "mirror/string-inl.h" +#include "runtime-inl.h" #include "thread.h" #include "utils.h" @@ -62,7 +63,9 @@ void ReferenceTable::Remove(mirror::Object* obj) { // If "obj" is an array, return the number of elements in the array. // Otherwise, return zero. static size_t GetElementCount(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (obj == NULL || obj == kClearedJniWeakGlobal || !obj->IsArrayInstance()) { + // We assume the special cleared value isn't an array in the if statement below. + DCHECK(!Runtime::Current()->GetClearedJniWeakGlobal()->IsArrayInstance()); + if (obj == nullptr || !obj->IsArrayInstance()) { return 0; } return obj->AsArray()->GetLength(); @@ -81,9 +84,10 @@ struct ObjectComparator { } else if (obj2 == NULL) { return false; } - if (obj1 == kClearedJniWeakGlobal) { + Runtime* runtime = Runtime::Current(); + if (runtime->IsClearedJniWeakGlobal(obj1)) { return true; - } else if (obj2 == kClearedJniWeakGlobal) { + } else if (runtime->IsClearedJniWeakGlobal(obj2)) { return false; } @@ -116,7 +120,7 @@ static void DumpSummaryLine(std::ostream& os, mirror::Object* obj, size_t elemen os << " NULL reference (count=" << equiv << ")\n"; return; } - if (obj == kClearedJniWeakGlobal) { + if (Runtime::Current()->IsClearedJniWeakGlobal(obj)) { os << " cleared jweak (count=" << equiv << ")\n"; return; } @@ -167,7 +171,7 @@ void ReferenceTable::Dump(std::ostream& os, Table& entries) { if (ref == NULL) { continue; } - if (ref == kClearedJniWeakGlobal) { + if (Runtime::Current()->IsClearedJniWeakGlobal(ref)) { os << StringPrintf(" %5d: cleared jweak\n", idx); continue; } @@ -209,7 +213,8 @@ void ReferenceTable::Dump(std::ostream& os, Table& entries) { sorted_entries.pop_back(); } while (!sorted_entries.empty() && - sorted_entries.back().Read<kWithoutReadBarrier>() == kClearedJniWeakGlobal) { + Runtime::Current()->IsClearedJniWeakGlobal( + sorted_entries.back().Read<kWithoutReadBarrier>())) { sorted_entries.pop_back(); } if (sorted_entries.empty()) { diff --git a/runtime/runtime-inl.h b/runtime/runtime-inl.h index ac9026b605..8b632b2459 100644 --- a/runtime/runtime-inl.h +++ b/runtime/runtime-inl.h @@ -23,6 +23,18 @@ namespace art { +inline bool Runtime::IsClearedJniWeakGlobal(mirror::Object* obj) { + return obj == GetClearedJniWeakGlobal(); +} + +inline mirror::Object* Runtime::GetClearedJniWeakGlobal() { + mirror::Object* obj = sentinel_.Read(); + if (obj == nullptr) { + LOG(ERROR) << "Failed to return cleared JNI weak global sentinel"; + } + return obj; +} + inline QuickMethodFrameInfo Runtime::GetRuntimeMethodFrameInfo(mirror::ArtMethod* method) { DCHECK(method != nullptr); // Cannot be imt-conflict-method or resolution-method. diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 1a682fb2e0..65ae5b79c8 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -796,6 +796,10 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) class_linker_->InitWithoutImage(*options->boot_class_path_); } CHECK(class_linker_ != nullptr); + + // Initialize the special sentinel_ value early. + sentinel_ = GcRoot<mirror::Object>(class_linker_->AllocObject(self)); + verifier::MethodVerifier::Init(); method_trace_ = options->method_trace_; @@ -1084,6 +1088,10 @@ void Runtime::VisitConcurrentRoots(RootCallback* callback, void* arg, VisitRootF void Runtime::VisitNonThreadRoots(RootCallback* callback, void* arg) { java_vm_->VisitRoots(callback, arg); + if (!sentinel_.IsNull()) { + sentinel_.VisitRoot(callback, arg, 0, kRootVMInternal); + DCHECK(!sentinel_.IsNull()); + } if (!pre_allocated_OutOfMemoryError_.IsNull()) { pre_allocated_OutOfMemoryError_.VisitRoot(callback, arg, 0, kRootVMInternal); DCHECK(!pre_allocated_OutOfMemoryError_.IsNull()); diff --git a/runtime/runtime.h b/runtime/runtime.h index 03952c48cf..caed6643fa 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -244,6 +244,12 @@ class Runtime { return monitor_pool_; } + // Is the given object the special object used to mark a cleared JNI weak global? + bool IsClearedJniWeakGlobal(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Get the special object used to mark a cleared JNI weak global. + mirror::Object* GetClearedJniWeakGlobal() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::Throwable* GetPreAllocatedOutOfMemoryError() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); mirror::Throwable* GetPreAllocatedNoClassDefFoundError() @@ -517,6 +523,10 @@ class Runtime { GcRoot<mirror::ArtMethod> imt_conflict_method_; GcRoot<mirror::ObjectArray<mirror::ArtMethod>> default_imt_; + // Special sentinel object used to invalid conditions in JNI (cleared weak references) and + // JDWP (invalid references). + GcRoot<mirror::Object> sentinel_; + InstructionSet instruction_set_; QuickMethodFrameInfo callee_save_method_frame_infos_[kLastCalleeSaveType]; diff --git a/runtime/thread.cc b/runtime/thread.cc index e0d67d643a..e3234736e2 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -911,7 +911,6 @@ struct StackDumpVisitor : public StackVisitor { std::ostream& os; const Thread* thread; const bool can_allocate; - mirror::ArtMethod* method; mirror::ArtMethod* last_method; int last_line_number; int repetition_count; @@ -1238,7 +1237,7 @@ void Thread::RemoveFromThreadGroup(ScopedObjectAccess& soa) { size_t Thread::NumHandleReferences() { size_t count = 0; - for (HandleScope* cur = tlsPtr_.top_handle_scope; cur; cur = cur->GetLink()) { + for (HandleScope* cur = tlsPtr_.top_handle_scope; cur != nullptr; cur = cur->GetLink()) { count += cur->NumberOfReferences(); } return count; @@ -1247,7 +1246,7 @@ size_t Thread::NumHandleReferences() { bool Thread::HandleScopeContains(jobject obj) const { StackReference<mirror::Object>* hs_entry = reinterpret_cast<StackReference<mirror::Object>*>(obj); - for (HandleScope* cur = tlsPtr_.top_handle_scope; cur; cur = cur->GetLink()) { + for (HandleScope* cur = tlsPtr_.top_handle_scope; cur!= nullptr; cur = cur->GetLink()) { if (cur->Contains(hs_entry)) { return true; } @@ -1280,6 +1279,7 @@ mirror::Object* Thread::DecodeJObject(jobject obj) const { IndirectRef ref = reinterpret_cast<IndirectRef>(obj); IndirectRefKind kind = GetIndirectRefKind(ref); mirror::Object* result; + bool expect_null = false; // The "kinds" below are sorted by the frequency we expect to encounter them. if (kind == kLocal) { IndirectReferenceTable& locals = tlsPtr_.jni_env->locals; @@ -1293,20 +1293,23 @@ mirror::Object* Thread::DecodeJObject(jobject obj) const { result = reinterpret_cast<StackReference<mirror::Object>*>(obj)->AsMirrorPtr(); VerifyObject(result); } else { - result = kInvalidIndirectRefObject; + tlsPtr_.jni_env->vm->JniAbortF(nullptr, "use of invalid jobject %p", obj); + expect_null = true; + result = nullptr; } } else if (kind == kGlobal) { result = tlsPtr_.jni_env->vm->DecodeGlobal(const_cast<Thread*>(this), ref); } else { DCHECK_EQ(kind, kWeakGlobal); result = tlsPtr_.jni_env->vm->DecodeWeakGlobal(const_cast<Thread*>(this), ref); - if (result == kClearedJniWeakGlobal) { + if (Runtime::Current()->IsClearedJniWeakGlobal(result)) { // This is a special case where it's okay to return nullptr. - return nullptr; + expect_null = true; + result = nullptr; } } - if (UNLIKELY(result == nullptr)) { + if (UNLIKELY(!expect_null && result == nullptr)) { tlsPtr_.jni_env->vm->JniAbortF(nullptr, "use of deleted %s %p", ToStr<IndirectRefKind>(kind).c_str(), obj); } |