Merge "Compile less stuff" into dalvik-dev
diff --git a/src/debugger.cc b/src/debugger.cc
index 0712c93..fdab63a 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -2374,22 +2374,75 @@
}
}
-JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize step_size,
- JDWP::JdwpStepDepth step_depth) {
- ScopedObjectAccessUnchecked soa(Thread::Current());
- MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
- Thread* thread;
- JDWP::JdwpError error = DecodeThread(soa, thread_id, thread);
- if (error != JDWP::ERR_NONE) {
- return error;
+// Scoped utility class to suspend a thread so that we may do tasks such as walk its stack. Doesn't
+// cause suspension if the thread is the current thread.
+class ScopedThreadSuspension {
+ public:
+ ScopedThreadSuspension(Thread* self, JDWP::ObjectId thread_id) :
+ thread_(NULL),
+ error_(JDWP::ERR_NONE),
+ self_suspend_(false),
+ other_suspend_(false) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ ScopedObjectAccessUnchecked soa(self);
+ {
+ MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
+ error_ = DecodeThread(soa, thread_id, thread_);
+ }
+ if (error_ == JDWP::ERR_NONE) {
+ if (thread_ == soa.Self()) {
+ self_suspend_ = true;
+ } else {
+ soa.Self()->TransitionFromRunnableToSuspended(kWaitingForDebuggerSuspension);
+ jobject thread_peer = gRegistry->GetJObject(thread_id);
+ bool timed_out;
+ Thread* suspended_thread = Thread::SuspendForDebugger(thread_peer, true, &timed_out);
+ CHECK_EQ(soa.Self()->TransitionFromSuspendedToRunnable(), kWaitingForDebuggerSuspension);
+ if (suspended_thread == NULL) {
+ // Thread terminated from under us while suspending.
+ error_ = JDWP::ERR_INVALID_THREAD;
+ } else {
+ CHECK_EQ(suspended_thread, thread_);
+ other_suspend_ = true;
+ }
+ }
+ }
}
- MutexLock mu2(soa.Self(), *Locks::breakpoint_lock_);
+ Thread* GetThread() const {
+ return thread_;
+ }
+
+ JDWP::JdwpError GetError() const {
+ return error_;
+ }
+
+ ~ScopedThreadSuspension() {
+ if (other_suspend_) {
+ Runtime::Current()->GetThreadList()->Resume(thread_, true);
+ }
+ }
+
+ private:
+ Thread* thread_;
+ JDWP::JdwpError error_;
+ bool self_suspend_;
+ bool other_suspend_;
+};
+
+JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize step_size,
+ JDWP::JdwpStepDepth step_depth) {
+ Thread* self = Thread::Current();
+ ScopedThreadSuspension sts(self, thread_id);
+ if (sts.GetError() != JDWP::ERR_NONE) {
+ return sts.GetError();
+ }
+
+ MutexLock mu2(self, *Locks::breakpoint_lock_);
// TODO: there's no theoretical reason why we couldn't support single-stepping
// of multiple threads at once, but we never did so historically.
- if (gSingleStepControl.thread != NULL && thread != gSingleStepControl.thread) {
+ if (gSingleStepControl.thread != NULL && sts.GetThread() != gSingleStepControl.thread) {
LOG(WARNING) << "single-step already active for " << *gSingleStepControl.thread
- << "; switching to " << *thread;
+ << "; switching to " << *sts.GetThread();
}
//
@@ -2426,7 +2479,8 @@
return true;
}
};
- SingleStepStackVisitor visitor(thread);
+
+ SingleStepStackVisitor visitor(sts.GetThread());
visitor.WalkStack();
//
@@ -2493,7 +2547,7 @@
// Everything else...
//
- gSingleStepControl.thread = thread;
+ gSingleStepControl.thread = sts.GetThread();
gSingleStepControl.step_size = step_size;
gSingleStepControl.step_depth = step_depth;
gSingleStepControl.is_active = true;
@@ -2636,10 +2690,27 @@
return JDWP::ERR_ILLEGAL_ARGUMENT;
}
const char* shorty = mh.GetShorty();
+ const DexFile::TypeList* types = mh.GetParameterTypeList();
for (size_t i = 0; i < arg_count; ++i) {
if (shorty[i + 1] != JdwpTagToShortyChar(arg_types[i])) {
return JDWP::ERR_ILLEGAL_ARGUMENT;
}
+
+ if (shorty[i + 1] == 'L') {
+ // Did we really get an argument of an appropriate reference type?
+ mirror::Class* parameter_type = mh.GetClassFromTypeIdx(types->GetTypeItem(i).type_idx_);
+ mirror::Object* argument = gRegistry->Get<mirror::Object*>(arg_values[i]);
+ if (argument == ObjectRegistry::kInvalidObject) {
+ return JDWP::ERR_INVALID_OBJECT;
+ }
+ if (!argument->InstanceOf(parameter_type)) {
+ return JDWP::ERR_ILLEGAL_ARGUMENT;
+ }
+
+ // Turn the on-the-wire ObjectId into a jobject.
+ jvalue& v = reinterpret_cast<jvalue&>(arg_values[i]);
+ v.l = gRegistry->GetJObject(arg_values[i]);
+ }
}
req->receiver_ = receiver;
diff --git a/src/jdwp/jdwp_adb.cc b/src/jdwp/jdwp_adb.cc
index 8734077..788b25a 100644
--- a/src/jdwp/jdwp_adb.cc
+++ b/src/jdwp/jdwp_adb.cc
@@ -332,7 +332,7 @@
if (netState->wakeFds[1] >= 0) {
VLOG(jdwp) << "+++ writing to wakePipe";
- write(netState->wakeFds[1], "", 1);
+ TEMP_FAILURE_RETRY(write(netState->wakeFds[1], "", 1));
}
}
@@ -520,7 +520,7 @@
}
errno = 0;
- cc = write(netState->clientSock, netState->inputBuffer, kMagicHandshakeLen);
+ cc = TEMP_FAILURE_RETRY(write(netState->clientSock, netState->inputBuffer, kMagicHandshakeLen));
if (cc != kMagicHandshakeLen) {
PLOG(ERROR) << "Failed writing handshake bytes (" << cc << " of " << kMagicHandshakeLen << ")";
goto fail;
diff --git a/src/jdwp/jdwp_event.cc b/src/jdwp/jdwp_event.cc
index 5b65aa4..56ba131 100644
--- a/src/jdwp/jdwp_event.cc
+++ b/src/jdwp/jdwp_event.cc
@@ -143,8 +143,6 @@
* not be added to the list, and an appropriate error will be returned.
*/
JdwpError JdwpState::RegisterEvent(JdwpEvent* pEvent) {
- MutexLock mu(Thread::Current(), event_list_lock_);
-
CHECK(pEvent != NULL);
CHECK(pEvent->prev == NULL);
CHECK(pEvent->next == NULL);
@@ -175,6 +173,7 @@
/*
* Add to list.
*/
+ MutexLock mu(Thread::Current(), event_list_lock_);
if (event_list_ != NULL) {
pEvent->next = event_list_;
event_list_->prev = pEvent;
diff --git a/src/jdwp/jdwp_main.cc b/src/jdwp/jdwp_main.cc
index 1f121f8..6fca7a5 100644
--- a/src/jdwp/jdwp_main.cc
+++ b/src/jdwp/jdwp_main.cc
@@ -58,7 +58,7 @@
*/
ssize_t JdwpNetStateBase::WritePacket(ExpandBuf* pReply) {
MutexLock mu(Thread::Current(), socket_lock_);
- return write(clientSock, expandBufGetBuffer(pReply), expandBufGetLength(pReply));
+ return TEMP_FAILURE_RETRY(write(clientSock, expandBufGetBuffer(pReply), expandBufGetLength(pReply)));
}
/*
@@ -66,7 +66,7 @@
*/
ssize_t JdwpNetStateBase::WriteBufferedPacket(const iovec* iov, int iov_count) {
MutexLock mu(Thread::Current(), socket_lock_);
- return writev(clientSock, iov, iov_count);
+ return TEMP_FAILURE_RETRY(writev(clientSock, iov, iov_count));
}
bool JdwpState::IsConnected() {
diff --git a/src/jdwp/jdwp_socket.cc b/src/jdwp/jdwp_socket.cc
index 43906ef..13e150a 100644
--- a/src/jdwp/jdwp_socket.cc
+++ b/src/jdwp/jdwp_socket.cc
@@ -207,7 +207,7 @@
/* if we might be sitting in select, kick us loose */
if (netState->wakePipe[1] >= 0) {
VLOG(jdwp) << "+++ writing to wakePipe";
- (void) write(netState->wakePipe[1], "", 1);
+ TEMP_FAILURE_RETRY(write(netState->wakePipe[1], "", 1));
}
}
@@ -581,7 +581,7 @@
}
errno = 0;
- cc = write(netState->clientSock, netState->inputBuffer, kMagicHandshakeLen);
+ cc = TEMP_FAILURE_RETRY(write(netState->clientSock, netState->inputBuffer, kMagicHandshakeLen));
if (cc != kMagicHandshakeLen) {
PLOG(ERROR) << "Failed writing handshake bytes (" << cc << " of " << kMagicHandshakeLen << ")";
goto fail;
diff --git a/src/jdwp/object_registry.cc b/src/jdwp/object_registry.cc
index 1e21ed0..54e7a8e 100644
--- a/src/jdwp/object_registry.cc
+++ b/src/jdwp/object_registry.cc
@@ -117,6 +117,15 @@
return self->DecodeJObject(entry.jni_reference);
}
+jobject ObjectRegistry::GetJObject(JDWP::ObjectId id) {
+ Thread* self = Thread::Current();
+ MutexLock mu(self, lock_);
+ id_iterator it = id_to_entry_.find(id);
+ CHECK(it != id_to_entry_.end()) << id;
+ ObjectRegistryEntry& entry = *(it->second);
+ return entry.jni_reference;
+}
+
void ObjectRegistry::DisableCollection(JDWP::ObjectId id) {
Thread* self = Thread::Current();
MutexLock mu(self, lock_);
diff --git a/src/jdwp/object_registry.h b/src/jdwp/object_registry.h
index e2893ca..d0ea59d 100644
--- a/src/jdwp/object_registry.h
+++ b/src/jdwp/object_registry.h
@@ -76,6 +76,10 @@
// 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_);
+
private:
JDWP::ObjectId InternalAdd(mirror::Object* o) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::Object* InternalGet(JDWP::ObjectId id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/src/object_utils.h b/src/object_utils.h
index 8a4bf77..9ad2b79 100644
--- a/src/object_utils.h
+++ b/src/object_utils.h
@@ -480,27 +480,6 @@
return GetDexFile().GetProtoParameters(proto);
}
- mirror::ObjectArray<mirror::Class>* GetParameterTypes(Thread* self)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const DexFile::TypeList* params = GetParameterTypeList();
- uint32_t num_params = params == NULL ? 0 : params->Size();
- SirtRef<mirror::ObjectArray<mirror::Class> >
- result(self, GetClassLinker()->AllocClassArray(self, num_params));
- if (UNLIKELY(result.get() == NULL)) {
- CHECK(self->IsExceptionPending());
- return NULL;
- }
- for (uint32_t i = 0; i < num_params; i++) {
- mirror::Class* param_type = GetClassFromTypeIdx(params->GetTypeItem(i).type_idx_);
- if (param_type == NULL) {
- DCHECK(Thread::Current()->IsExceptionPending());
- return NULL;
- }
- result->Set(i, param_type);
- }
- return result.get();
- }
-
mirror::Class* GetReturnType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
const DexFile& dex_file = GetDexFile();
const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex());