summaryrefslogtreecommitdiffstats
path: root/runtime/thread.cc
diff options
context:
space:
mode:
authorSebastien Hertz <shertz@google.com>2015-02-25 15:05:59 +0100
committerSebastien Hertz <shertz@google.com>2015-03-09 15:19:49 +0100
commit1558b577907b613864e98f05862543557263e864 (patch)
tree5498d8d15f198341fe46a8badc7e7591611a09b5 /runtime/thread.cc
parent2cfdabd2bb4833d7092819d27ef08a9e1cdffead (diff)
downloadart-1558b577907b613864e98f05862543557263e864.zip
art-1558b577907b613864e98f05862543557263e864.tar.gz
art-1558b577907b613864e98f05862543557263e864.tar.bz2
JDWP: allocate DebugInvokeReq only when requested
Only allocates thread-local DebugInvokeReq when the debugger requests a thread to invoke a method. The JDWP thread allocates that structure then attaches it to the target thread. When the thread is resumed, it executes the method. Once the invocation completes, the thread detaches the DebugInvokeReq, signals the JDWP thread then suspends. Finally, the JDWP thread wakes up, prepares the reply with the invoke result (or exception) and deallocates the DebugInvokeReq. Also ensures GC safety for object returned by the invoke. We add the object to the JDWP object registry right after the invoke. We now reference that object with a JDWP ObjectID instead of an Object* in the DebugInvokeReq struct. This prevent from accessing a stale reference if the GC runs and moves the Object*. This CL includes the following changes: - Move former DebugInvokeReq::ready flag to Thread::tls_32bit_sized_values::ready_for_debug_invoke. It's needed to know whether a thread has been suspended by an event, thus ready to invoke a method from the debugger. - Remove DebugInvokeReq::invoke_needed: we now test if we attached a DebugInvokeReq* to the thread. - Rename misleading FinishMethod function to RequestMethod. Bug: 19142632 Bug: 18166750 Change-Id: I351fb4eb94bfe69fcafb544d21d55ff35a033000
Diffstat (limited to 'runtime/thread.cc')
-rw-r--r--runtime/thread.cc20
1 files changed, 17 insertions, 3 deletions
diff --git a/runtime/thread.cc b/runtime/thread.cc
index e31af16..699e31f 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1138,8 +1138,6 @@ void Thread::Shutdown() {
Thread::Thread(bool daemon) : tls32_(daemon), wait_monitor_(nullptr), interrupted_(false) {
wait_mutex_ = new Mutex("a thread wait mutex");
wait_cond_ = new ConditionVariable("a thread wait condition variable", *wait_mutex_);
- tlsPtr_.debug_invoke_req = new DebugInvokeReq;
- tlsPtr_.single_step_control = nullptr;
tlsPtr_.instrumentation_stack = new std::deque<instrumentation::InstrumentationStackFrame>;
tlsPtr_.name = new std::string(kThreadNameDuringStartup);
tlsPtr_.nested_signal_state = static_cast<jmp_buf*>(malloc(sizeof(jmp_buf)));
@@ -1291,7 +1289,6 @@ Thread::~Thread() {
CleanupCpu();
}
- delete tlsPtr_.debug_invoke_req;
if (tlsPtr_.single_step_control != nullptr) {
delete tlsPtr_.single_step_control;
}
@@ -2416,4 +2413,21 @@ void Thread::DeactivateSingleStepControl() {
delete ssc;
}
+void Thread::SetDebugInvokeReq(DebugInvokeReq* req) {
+ CHECK(Dbg::IsDebuggerActive());
+ CHECK(GetInvokeReq() == nullptr) << "Debug invoke req already active in thread " << *this;
+ CHECK(Thread::Current() != this) << "Debug invoke can't be dispatched by the thread itself";
+ CHECK(req != nullptr);
+ tlsPtr_.debug_invoke_req = req;
+}
+
+void Thread::ClearDebugInvokeReq() {
+ CHECK(Dbg::IsDebuggerActive());
+ CHECK(GetInvokeReq() != nullptr) << "Debug invoke req not active in thread " << *this;
+ CHECK(Thread::Current() == this) << "Debug invoke must be finished by the thread itself";
+ // We do not own the DebugInvokeReq* so we must not delete it, it is the responsibility of
+ // the owner (the JDWP thread).
+ tlsPtr_.debug_invoke_req = nullptr;
+}
+
} // namespace art