From c0542af3e2170143ba40d89136e284997e16bf64 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 3 Sep 2014 16:16:56 -0700 Subject: [PATCH] Remove abuse of mirror::Object* to reference special values. Remove kInvalidIndirectRefObject, kClearedJniWeakGlobal and ObjectRegistry::kInvalidObject. Handle error conditions by passing in or returning an error value. GetObjectRefType is simplified to be faster and not return invalid references that are not expected according to the spec. Adjust check JNI and jni_internal_test appropriately. Fix cases in the debugger/JDWP of out arguments being passed by reference. Bug: 17376993 Change-Id: I3ce8a28c01827e163f4dc288449959464da788b1 --- runtime/check_jni.cc | 30 +- runtime/class_linker-inl.h | 5 + runtime/class_linker.h | 3 + runtime/debugger.cc | 737 ++++++++++++++++--------------- runtime/debugger.h | 51 +-- runtime/entrypoints/entrypoint_utils.cc | 11 +- runtime/indirect_reference_table-inl.h | 20 +- runtime/indirect_reference_table.cc | 4 - runtime/indirect_reference_table.h | 15 +- runtime/indirect_reference_table_test.cc | 62 +-- runtime/java_vm_ext.cc | 3 +- runtime/jdwp/jdwp.h | 2 +- runtime/jdwp/jdwp_event.cc | 4 +- runtime/jdwp/jdwp_handler.cc | 490 ++++++++++---------- runtime/jdwp/jdwp_main.cc | 2 +- runtime/jdwp/object_registry.cc | 8 +- runtime/jdwp/object_registry.h | 15 +- runtime/jni_internal.cc | 18 +- runtime/jni_internal_test.cc | 31 +- runtime/reference_table.cc | 17 +- runtime/runtime-inl.h | 12 + runtime/runtime.cc | 8 + runtime/runtime.h | 10 + runtime/thread.cc | 17 +- 24 files changed, 829 insertions(+), 746 deletions(-) diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc index b0f8e22ab..95223d856 100644 --- a/runtime/check_jni.cc +++ b/runtime/check_jni.cc @@ -650,6 +650,24 @@ class ScopedCheck { } mirror::Object* obj = soa.Decode(java_object); + if (obj == nullptr) { + // Either java_object is invalid or is a cleared weak. + IndirectRef ref = reinterpret_cast(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(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(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 d05f7af87..130654680 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(self, + Runtime::Current()->GetHeap()->GetCurrentAllocator()); +} + template inline mirror::ObjectArray* ClassLinker::AllocObjectArray(Thread* self, size_t length) { return mirror::ObjectArray::Alloc(self, GetClassRoot(kObjectArrayClass), length); diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 064a85d13..a7a68b754 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 mirror::ObjectArray* AllocObjectArray(Thread* self, size_t length) diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 9136f9f8d..8b8e7c827 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(id); - if (o == NULL || o == ObjectRegistry::kInvalidObject) { - status = JDWP::ERR_INVALID_OBJECT; - return NULL; + mirror::Object* o = gRegistry->Get(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(id); - if (o == NULL || o == ObjectRegistry::kInvalidObject) { - status = JDWP::ERR_INVALID_OBJECT; - return NULL; + mirror::Object* o = gRegistry->Get(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(thread_id); - if (thread_peer == NULL || thread_peer == ObjectRegistry::kInvalidObject) { + mirror::Object* thread_peer = gRegistry->Get(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(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(class_id); - if (o == NULL) { - return "NULL"; - } - if (o == ObjectRegistry::kInvalidObject) { - return StringPrintf("invalid object %p", reinterpret_cast(class_id)); + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get(class_id, &error); + if (o == nullptr) { + if (error == JDWP::ERR_NONE) { + return "NULL"; + } else { + return StringPrintf("invalid object %p", reinterpret_cast(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(id); - if (o == NULL || o == ObjectRegistry::kInvalidObject) { + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get(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(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(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& monitors, - std::vector& stack_depths) { + std::vector* monitors, + std::vector* stack_depths) { struct OwnedMonitorVisitor : public StackVisitor { OwnedMonitorVisitor(Thread* thread, Context* context, std::vector* monitor_vector, @@ -955,16 +962,17 @@ JDWP::JdwpError Dbg::GetOwnedMonitors(JDWP::ObjectId thread_id, } size_t current_stack_depth; - std::vector* monitors; - std::vector* stack_depths; + std::vector* const monitors; + std::vector* 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::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& class_ids, - std::vector& counts) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + std::vector* counts) { gc::Heap* heap = Runtime::Current()->GetHeap(); heap->CollectGarbage(false); std::vector 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& instances) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +JDWP::JdwpError Dbg::GetInstances(JDWP::RefTypeId class_id, int32_t max_count, + std::vector* 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 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& referring_objects) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + std::vector* referring_objects) { gc::Heap* heap = Runtime::Current()->GetHeap(); heap->CollectGarbage(false); - mirror::Object* o = gRegistry->Get(object_id); - if (o == NULL || o == ObjectRegistry::kInvalidObject) { + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get(object_id, &error); + if (o == nullptr) { return JDWP::ERR_INVALID_OBJECT; } std::vector 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(object_id); - if (o == NULL || o == ObjectRegistry::kInvalidObject) { +JDWP::JdwpError Dbg::DisableCollection(JDWP::ObjectId object_id) { + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get(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(object_id); +JDWP::JdwpError Dbg::EnableCollection(JDWP::ObjectId object_id) { + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get(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(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(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& classes) { +void Dbg::GetClassList(std::vector* 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& classes) : classes(classes) { + explicit ClassListCreator(std::vector* classes) : classes(classes) { } static bool Visit(mirror::Class* c, void* arg) { @@ -1141,12 +1147,12 @@ void Dbg::GetClassList(std::vector& 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& classes; + std::vector* const classes; }; ClassListCreator clc(classes); @@ -1155,10 +1161,10 @@ void Dbg::GetClassList(std::vector& 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& ids) { +void Dbg::FindLoadedClassBySignature(const char* descriptor, std::vector* ids) { std::vector 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(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(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(object_id); - if (o == ObjectRegistry::kInvalidObject) { - return JDWP::ERR_INVALID_OBJECT; + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get(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 -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(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* oa = dst->AsObjectArray(); for (int i = 0; i < count; ++i) { - JDWP::ObjectId id = request.ReadObjectId(); - mirror::Object* o = gRegistry->Get(id); - if (o == ObjectRegistry::kInvalidObject) { - return JDWP::ERR_INVALID_OBJECT; + JDWP::ObjectId id = request->ReadObjectId(); + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get(id, &error); + if (error != JDWP::ERR_NONE) { + return error; } oa->Set(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(Thread::Current(), c, length, - c->GetComponentSize(), - Runtime::Current()->GetHeap()->GetCurrentAllocator())); + *new_array = gRegistry->Add(mirror::Array::Alloc(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(static_cast(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(-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(-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 c(hs.NewHandle(DecodeClass(class_id, status))); + Handle 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& bytecodes) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + std::vector* 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(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(object_id); - if ((!is_static && o == NULL) || o == ObjectRegistry::kInvalidObject) { + mirror::Object* o = gRegistry->Get(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(object_id); - if ((!is_static && o == NULL) || o == ObjectRegistry::kInvalidObject) { + JDWP::JdwpError error; + mirror::Object* o = gRegistry->Get(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(o, value); } } else { - mirror::Object* v = gRegistry->Get(value); - if (v == ObjectRegistry::kInvalidObject) { + mirror::Object* v = gRegistry->Get(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(string_id); + JDWP::JdwpError error; + mirror::String* s = gRegistry->Get(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(thread_id); + mirror::Object* thread_object = gRegistry->Get(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(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(thread_id); - if (thread_object == ObjectRegistry::kInvalidObject) { + JDWP::JdwpError error; + mirror::Object* thread_object = gRegistry->Get(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(thread_group_id); - CHECK(thread_group != nullptr); + JDWP::JdwpError error; + mirror::Object* thread_group = gRegistry->Get(thread_group_id, &error); + CHECK(thread_group != nullptr) << error; const char* old_cause = soa.Self()->StartAssertNoThreadSuspension("Debugger: GetThreadGroupName"); mirror::Class* c = soa.Decode(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(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(thread_group_id); - CHECK(thread_group != nullptr); + JDWP::JdwpError error; + mirror::Object* thread_group = gRegistry->Get(thread_group_id, &error); + CHECK(thread_group != nullptr) << error; const char* old_cause = soa.Self()->StartAssertNoThreadSuspension("Debugger: GetThreadGroupParent"); mirror::Class* c = soa.Decode(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& thread_ids) { +void Dbg::GetThreads(JDWP::ObjectId thread_group_id, std::vector* thread_ids) { class ThreadListVisitor { public: ThreadListVisitor(const ScopedObjectAccessUnchecked& soa, mirror::Object* desired_thread_group, - std::vector& thread_ids) + std::vector* 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 } 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 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 const ScopedObjectAccessUnchecked& soa_; mirror::Object* const desired_thread_group_; - std::vector& thread_ids_; + std::vector* const thread_ids_; }; ScopedObjectAccessUnchecked soa(Thread::Current()); - mirror::Object* thread_group = gRegistry->Get(thread_group_id); + JDWP::JdwpError error; + mirror::Object* thread_group = gRegistry->Get(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& child_thread_group_ids) { +void Dbg::GetChildThreadGroups(JDWP::ObjectId thread_group_id, + std::vector* child_thread_group_ids) { ScopedObjectAccess soa(Thread::Current()); - mirror::Object* thread_group = gRegistry->Get(thread_group_id); + JDWP::JdwpError error; + mirror::Object* thread_group = gRegistry->Get(thread_group_id, &error); + CHECK(thread_group != nullptr) << error; // Get the ArrayList "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::vectorAdd(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 peer(self->GetJniEnv(), NULL); + ScopedLocalRef peer(self->GetJniEnv(), nullptr); { ScopedObjectAccess soa(self); - peer.reset(soa.AddLocalReference(gRegistry->Get(thread_id))); + JDWP::JdwpError error; + peer.reset(soa.AddLocalReference(gRegistry->Get(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(thread_id); + JDWP::JdwpError error; + mirror::Object* peer = gRegistry->Get(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(static_cast(value_)); - if (o == ObjectRegistry::kInvalidObject) { - VLOG(jdwp) << tag_ << " object " << o << " is an invalid object"; + JDWP::JdwpError error; + mirror::Object* o = + gRegistry->Get(static_cast(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(reinterpret_cast(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(object_id); - if (receiver == ObjectRegistry::kInvalidObject) { + mirror::Object* receiver = gRegistry->Get(object_id, &error); + if (error != JDWP::ERR_NONE) { return JDWP::ERR_INVALID_OBJECT; } - mirror::Object* thread = gRegistry->Get(thread_id); - if (thread == ObjectRegistry::kInvalidObject) { + mirror::Object* thread = gRegistry->Get(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(arg_values[i]); - if (argument == ObjectRegistry::kInvalidObject) { + mirror::Object* argument = gRegistry->Get(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 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(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 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(request.data())); - request.Skip(request_length); + env->SetByteArrayRegion(dataArray.get(), 0, request_length, + reinterpret_cast(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 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 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(const_cast(buf)); vec[0].iov_len = byte_count; @@ -3856,7 +3883,7 @@ void Dbg::DdmSendChunk(uint32_t type, const std::vector& 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(&bytes[0])); } return result; diff --git a/runtime/debugger.h b/runtime/debugger.h index 1d3668c1f..52ae7a916 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& classes) + static void GetClassList(std::vector* 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& ids) + static void FindLoadedClassBySignature(const char* descriptor, std::vector* 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& monitors, - std::vector& stack_depths) + std::vector* monitors, + std::vector* 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& class_ids, - std::vector& counts) + std::vector* counts) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError GetInstances(JDWP::RefTypeId class_id, int32_t max_count, - std::vector& instances) + std::vector* instances) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static JDWP::JdwpError GetReferringObjects(JDWP::ObjectId object_id, int32_t max_count, - std::vector& referring_objects) + std::vector* 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& bytecodes) + std::vector* 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& thread_ids) + static void GetThreads(JDWP::ObjectId thread_group_id, std::vector* thread_ids) LOCKS_EXCLUDED(Locks::thread_list_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static void GetChildThreadGroups(JDWP::ObjectId thread_group_id, std::vector& child_thread_group_ids); + static void GetChildThreadGroups(JDWP::ObjectId thread_group_id, + std::vector* 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& 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 cf89850fa..e1c532ece 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 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 00f7b06f1..9bf3ea258 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()))) { + ++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 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(); - if (LIKELY(obj != kClearedJniWeakGlobal)) { - // The read barrier or VerifyObject won't handle kClearedJniWeakGlobal. - obj = table_[idx].Read(); - VerifyObject(obj); - } + mirror::Object* obj = table_[idx].Read(); + VerifyObject(obj); return obj; } diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc index 1ba2291ad..49bffa404 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(); 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(obj)); } else { obj = table_[i].Read(); entries.push_back(GcRoot(obj)); diff --git a/runtime/indirect_reference_table.h b/runtime/indirect_reference_table.h index d25bc42df..562ba1e8d 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(0xdead4321); -static mirror::Object* const kClearedJniWeakGlobal = reinterpret_cast(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() == kClearedJniWeakGlobal)) { - ++i_; - } - } + void SkipNullsAndTombstones() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); GcRoot* 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 a33a98154..99ee597bb 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 dd3b7cf2b..424addb2a 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 8fd07cc11..b5b6298b8 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 36fbed4ea..fc39cc48d 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 = ""; } @@ -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 330d235c0..35095f95c 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::vectorReadSigned32("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 argTypes(arg_count > 0 ? new JdwpTag[arg_count] : NULL); std::unique_ptr 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 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 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 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 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 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 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 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 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 monitors; std::vector 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 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 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("event kind"); - JdwpSuspendPolicy suspend_policy = request.ReadEnum1("suspend policy"); - int32_t modifier_count = request.ReadSigned32("modifier count"); + JdwpEventKind event_kind = request->ReadEnum1("event kind"); + JdwpSuspendPolicy suspend_policy = request->ReadEnum1("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("caught"); - mod.exceptionOnly.uncaught = request.ReadEnum1("uncaught"); + mod.exceptionOnly.refTypeId = request->ReadRefTypeId(); // null => all exceptions. + mod.exceptionOnly.caught = request->ReadEnum1("caught"); + mod.exceptionOnly.uncaught = request->ReadEnum1("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("event kind"); - uint32_t requestId = request.ReadUnsigned32("request id"); + request->ReadEnum1("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 a4f427ca2..c500ef531 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 ad18d8a2c..35aaf0ab8 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(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 f0314a382..0e46d5cf2 100644 --- a/runtime/jdwp/object_registry.h +++ b/runtime/jdwp/object_registry.h @@ -22,6 +22,7 @@ #include +#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 T Get(JDWP::ObjectId id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + template 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(InternalGet(id)); + return down_cast(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 919655695..3e9ae09bd 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -2261,25 +2261,15 @@ class JNI { IndirectRef ref = reinterpret_cast(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(env)->locals.Get(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(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 b236edea9..20d031c3e 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(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(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 70aba9bbf..01c507086 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() == kClearedJniWeakGlobal) { + Runtime::Current()->IsClearedJniWeakGlobal( + sorted_entries.back().Read())) { sorted_entries.pop_back(); } if (sorted_entries.empty()) { diff --git a/runtime/runtime-inl.h b/runtime/runtime-inl.h index ac9026b60..8b632b245 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 1a682fb2e..65ae5b79c 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(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 03952c48c..caed6643f 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 imt_conflict_method_; GcRoot> default_imt_; + // Special sentinel object used to invalid conditions in JNI (cleared weak references) and + // JDWP (invalid references). + GcRoot sentinel_; + InstructionSet instruction_set_; QuickMethodFrameInfo callee_save_method_frame_infos_[kLastCalleeSaveType]; diff --git a/runtime/thread.cc b/runtime/thread.cc index e0d67d643..e3234736e 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* hs_entry = reinterpret_cast*>(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(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*>(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(this), ref); } else { DCHECK_EQ(kind, kWeakGlobal); result = tlsPtr_.jni_env->vm->DecodeWeakGlobal(const_cast(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(kind).c_str(), obj); } -- 2.11.0