summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/base/mutex.cc4
-rw-r--r--runtime/base/mutex.h5
-rw-r--r--runtime/debugger.cc185
-rw-r--r--runtime/debugger.h64
-rw-r--r--runtime/instrumentation.h4
-rw-r--r--runtime/jdwp/jdwp.h4
-rw-r--r--runtime/jdwp/jdwp_event.cc41
-rw-r--r--runtime/jdwp/jdwp_main.cc1
8 files changed, 186 insertions, 122 deletions
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index fdf5763..52a1672 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -31,7 +31,6 @@ namespace art {
Mutex* Locks::abort_lock_ = nullptr;
Mutex* Locks::breakpoint_lock_ = nullptr;
-Mutex* Locks::deoptimization_lock_ = nullptr;
ReaderWriterMutex* Locks::classlinker_classes_lock_ = nullptr;
ReaderWriterMutex* Locks::heap_bitmap_lock_ = nullptr;
Mutex* Locks::logging_lock_ = nullptr;
@@ -812,7 +811,6 @@ void Locks::Init() {
// Already initialized.
DCHECK(abort_lock_ != nullptr);
DCHECK(breakpoint_lock_ != nullptr);
- DCHECK(deoptimization_lock_ != nullptr);
DCHECK(classlinker_classes_lock_ != nullptr);
DCHECK(heap_bitmap_lock_ != nullptr);
DCHECK(logging_lock_ != nullptr);
@@ -829,8 +827,6 @@ void Locks::Init() {
DCHECK(breakpoint_lock_ == nullptr);
breakpoint_lock_ = new Mutex("breakpoint lock", kBreakpointLock);
- DCHECK(deoptimization_lock_ == nullptr);
- deoptimization_lock_ = new Mutex("deoptimization lock", kDeoptimizationLock);
DCHECK(classlinker_classes_lock_ == nullptr);
classlinker_classes_lock_ = new ReaderWriterMutex("ClassLinker classes lock",
kClassLinkerClassesLock);
diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h
index 55ec1c3..4b881f6 100644
--- a/runtime/base/mutex.h
+++ b/runtime/base/mutex.h
@@ -537,11 +537,8 @@ class Locks {
// Guards breakpoints.
static Mutex* breakpoint_lock_ ACQUIRED_AFTER(thread_list_lock_);
- // Guards deoptimization requests.
- static Mutex* deoptimization_lock_ ACQUIRED_AFTER(breakpoint_lock_);
-
// Guards trace requests.
- static Mutex* trace_lock_ ACQUIRED_AFTER(deoptimization_lock_);
+ static Mutex* trace_lock_ ACQUIRED_AFTER(breakpoint_lock_);
// Guards profile objects.
static Mutex* profiler_lock_ ACQUIRED_AFTER(trace_lock_);
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index c18d5c6..62019fa 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -200,17 +200,9 @@ size_t Dbg::alloc_record_head_ = 0;
size_t Dbg::alloc_record_count_ = 0;
// Deoptimization support.
-struct MethodInstrumentationRequest {
- bool deoptimize;
-
- // Method for selective deoptimization. NULL means full deoptimization.
- mirror::ArtMethod* method;
-
- MethodInstrumentationRequest(bool deoptimize, mirror::ArtMethod* method)
- : deoptimize(deoptimize), method(method) {}
-};
-// TODO we need to visit associated methods as roots.
-static std::vector<MethodInstrumentationRequest> gDeoptimizationRequests GUARDED_BY(Locks::deoptimization_lock_);
+Mutex* Dbg::deoptimization_lock_ = nullptr;
+std::vector<DeoptimizationRequest> Dbg::deoptimization_requests_;
+size_t Dbg::full_deoptimization_event_count_ = 0;
// Breakpoints.
static std::vector<Breakpoint> gBreakpoints GUARDED_BY(Locks::breakpoint_lock_);
@@ -238,6 +230,12 @@ void SingleStepControl::VisitRoots(RootCallback* callback, void* arg, uint32_t t
}
}
+void DeoptimizationRequest::VisitRoots(RootCallback* callback, void* arg) {
+ if (method != nullptr) {
+ callback(reinterpret_cast<mirror::Object**>(&method), arg, 0, kRootDebugger);
+ }
+}
+
static bool IsBreakpoint(const mirror::ArtMethod* m, uint32_t dex_pc)
LOCKS_EXCLUDED(Locks::breakpoint_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -502,6 +500,7 @@ void Dbg::StartJdwp() {
gRegistry = new ObjectRegistry;
alloc_tracker_lock_ = new Mutex("AllocTracker lock");
+ deoptimization_lock_ = new Mutex("deoptimization lock", kDeoptimizationLock);
// Init JDWP if the debugger is enabled. This may connect out to a
// debugger, passively listen for a debugger, or block waiting for a
// debugger.
@@ -524,9 +523,17 @@ void Dbg::StartJdwp() {
}
void Dbg::VisitRoots(RootCallback* callback, void* arg) {
- MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
- for (Breakpoint& bp : gBreakpoints) {
- bp.VisitRoots(callback, arg);
+ {
+ MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
+ for (Breakpoint& bp : gBreakpoints) {
+ bp.VisitRoots(callback, arg);
+ }
+ }
+ if (deoptimization_lock_ != nullptr) { // only true if the debugger is started.
+ MutexLock mu(Thread::Current(), *deoptimization_lock_);
+ for (DeoptimizationRequest& req : deoptimization_requests_) {
+ req.VisitRoots(callback, arg);
+ }
}
}
@@ -539,6 +546,8 @@ void Dbg::StopJdwp() {
gRegistry = nullptr;
delete alloc_tracker_lock_;
alloc_tracker_lock_ = nullptr;
+ delete deoptimization_lock_;
+ deoptimization_lock_ = nullptr;
}
void Dbg::GcDidFinish() {
@@ -605,8 +614,9 @@ void Dbg::GoActive() {
}
{
- MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_);
- CHECK_EQ(gDeoptimizationRequests.size(), 0U);
+ MutexLock mu(Thread::Current(), *deoptimization_lock_);
+ CHECK_EQ(deoptimization_requests_.size(), 0U);
+ CHECK_EQ(full_deoptimization_event_count_, 0U);
}
Runtime* runtime = Runtime::Current();
@@ -646,8 +656,9 @@ void Dbg::Disconnected() {
// Since we're going to disable deoptimization, we clear the deoptimization requests queue.
// This prevents us from having any pending deoptimization request when the debugger attaches
// to us again while no event has been requested yet.
- MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_);
- gDeoptimizationRequests.clear();
+ MutexLock mu(Thread::Current(), *deoptimization_lock_);
+ deoptimization_requests_.clear();
+ full_deoptimization_event_count_ = 0U;
}
runtime->GetInstrumentation()->RemoveListener(&gDebugInstrumentationListener,
instrumentation::Instrumentation::kMethodEntered |
@@ -2546,44 +2557,86 @@ void Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object,
}
}
-static void ProcessDeoptimizationRequests()
- LOCKS_EXCLUDED(Locks::deoptimization_lock_)
- EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_) {
- Locks::mutator_lock_->AssertExclusiveHeld(Thread::Current());
- MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_);
+// Process request while all mutator threads are suspended.
+void Dbg::ProcessDeoptimizationRequest(const DeoptimizationRequest& request) {
instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
- for (const MethodInstrumentationRequest& request : gDeoptimizationRequests) {
- mirror::ArtMethod* const method = request.method;
- if (method != nullptr) {
- // Selective deoptimization.
- if (request.deoptimize) {
- VLOG(jdwp) << "Deoptimize method " << PrettyMethod(method);
- instrumentation->Deoptimize(method);
- } else {
- VLOG(jdwp) << "Undeoptimize method " << PrettyMethod(method);
- instrumentation->Undeoptimize(method);
+ switch (request.kind) {
+ case DeoptimizationRequest::kNothing:
+ LOG(WARNING) << "Ignoring empty deoptimization request.";
+ break;
+ case DeoptimizationRequest::kFullDeoptimization:
+ VLOG(jdwp) << "Deoptimize the world";
+ instrumentation->DeoptimizeEverything();
+ break;
+ case DeoptimizationRequest::kFullUndeoptimization:
+ VLOG(jdwp) << "Undeoptimize the world";
+ instrumentation->UndeoptimizeEverything();
+ break;
+ case DeoptimizationRequest::kSelectiveDeoptimization:
+ VLOG(jdwp) << "Deoptimize method " << PrettyMethod(request.method);
+ instrumentation->Deoptimize(request.method);
+ break;
+ case DeoptimizationRequest::kSelectiveUndeoptimization:
+ VLOG(jdwp) << "Undeoptimize method " << PrettyMethod(request.method);
+ instrumentation->Undeoptimize(request.method);
+ break;
+ default:
+ LOG(FATAL) << "Unsupported deoptimization request kind " << request.kind;
+ break;
+ }
+}
+
+void Dbg::RequestDeoptimization(const DeoptimizationRequest& req) {
+ if (req.kind == DeoptimizationRequest::kNothing) {
+ // Nothing to do.
+ return;
+ }
+ MutexLock mu(Thread::Current(), *deoptimization_lock_);
+ switch (req.kind) {
+ case DeoptimizationRequest::kFullDeoptimization: {
+ DCHECK(req.method == nullptr);
+ if (full_deoptimization_event_count_ == 0) {
+ VLOG(jdwp) << "Request full deoptimization";
+ deoptimization_requests_.push_back(req);
}
- } else {
- // Full deoptimization.
- if (request.deoptimize) {
- VLOG(jdwp) << "Deoptimize the world";
- instrumentation->DeoptimizeEverything();
- } else {
- VLOG(jdwp) << "Undeoptimize the world";
- instrumentation->UndeoptimizeEverything();
+ ++full_deoptimization_event_count_;
+ break;
+ }
+ case DeoptimizationRequest::kFullUndeoptimization: {
+ DCHECK(req.method == nullptr);
+ DCHECK_GT(full_deoptimization_event_count_, 0U);
+ --full_deoptimization_event_count_;
+ if (full_deoptimization_event_count_ == 0) {
+ VLOG(jdwp) << "Request full undeoptimization";
+ deoptimization_requests_.push_back(req);
}
+ break;
+ }
+ case DeoptimizationRequest::kSelectiveDeoptimization: {
+ DCHECK(req.method != nullptr);
+ VLOG(jdwp) << "Request deoptimization of " << PrettyMethod(req.method);
+ deoptimization_requests_.push_back(req);
+ break;
+ }
+ case DeoptimizationRequest::kSelectiveUndeoptimization: {
+ DCHECK(req.method != nullptr);
+ VLOG(jdwp) << "Request undeoptimization of " << PrettyMethod(req.method);
+ deoptimization_requests_.push_back(req);
+ break;
+ }
+ default: {
+ LOG(FATAL) << "Unknown deoptimization request kind " << req.kind;
+ break;
}
}
- gDeoptimizationRequests.clear();
}
-// Process deoptimization requests after suspending all mutator threads.
void Dbg::ManageDeoptimization() {
Thread* const self = Thread::Current();
{
// Avoid suspend/resume if there is no pending request.
- MutexLock mu(self, *Locks::deoptimization_lock_);
- if (gDeoptimizationRequests.empty()) {
+ MutexLock mu(self, *deoptimization_lock_);
+ if (deoptimization_requests_.empty()) {
return;
}
}
@@ -2593,27 +2646,21 @@ void Dbg::ManageDeoptimization() {
Runtime* const runtime = Runtime::Current();
runtime->GetThreadList()->SuspendAll();
const ThreadState old_state = self->SetStateUnsafe(kRunnable);
- ProcessDeoptimizationRequests();
+ {
+ MutexLock mu(self, *deoptimization_lock_);
+ for (const DeoptimizationRequest& request : deoptimization_requests_) {
+ ProcessDeoptimizationRequest(request);
+ }
+ deoptimization_requests_.clear();
+ }
CHECK_EQ(self->SetStateUnsafe(old_state), kRunnable);
runtime->GetThreadList()->ResumeAll();
self->TransitionFromSuspendedToRunnable();
}
-// Enable full deoptimization.
-void Dbg::EnableFullDeoptimization() {
- MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_);
- VLOG(jdwp) << "Request full deoptimization";
- gDeoptimizationRequests.push_back(MethodInstrumentationRequest(true, nullptr));
-}
-
-// Disable full deoptimization.
-void Dbg::DisableFullDeoptimization() {
- MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_);
- VLOG(jdwp) << "Request full undeoptimization";
- gDeoptimizationRequests.push_back(MethodInstrumentationRequest(false, nullptr));
-}
-
-void Dbg::WatchLocation(const JDWP::JdwpLocation* location) {
+void Dbg::WatchLocation(const JDWP::JdwpLocation* location, DeoptimizationRequest* req) {
+ // TODO we don't need to deoptimize a method if it's not compiled since it already runs with the
+ // interpreter.
bool need_deoptimization = true;
mirror::ArtMethod* m = FromMethodId(location->method_id);
{
@@ -2630,18 +2677,17 @@ void Dbg::WatchLocation(const JDWP::JdwpLocation* location) {
}
gBreakpoints.push_back(Breakpoint(m, location->dex_pc));
- VLOG(jdwp) << "Set breakpoint #" << (gBreakpoints.size() - 1) << ": " << gBreakpoints[gBreakpoints.size() - 1];
+ VLOG(jdwp) << "Set breakpoint #" << (gBreakpoints.size() - 1) << ": "
+ << gBreakpoints[gBreakpoints.size() - 1];
}
if (need_deoptimization) {
- // Request its deoptimization. This will be done after updating the JDWP event list.
- MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_);
- gDeoptimizationRequests.push_back(MethodInstrumentationRequest(true, m));
- VLOG(jdwp) << "Request deoptimization of " << PrettyMethod(m);
+ req->kind = DeoptimizationRequest::kSelectiveDeoptimization;
+ req->method = m;
}
}
-void Dbg::UnwatchLocation(const JDWP::JdwpLocation* location) {
+void Dbg::UnwatchLocation(const JDWP::JdwpLocation* location, DeoptimizationRequest* req) {
bool can_undeoptimize = true;
mirror::ArtMethod* m = FromMethodId(location->method_id);
DCHECK(Runtime::Current()->GetInstrumentation()->IsDeoptimized(m));
@@ -2666,9 +2712,8 @@ void Dbg::UnwatchLocation(const JDWP::JdwpLocation* location) {
if (can_undeoptimize) {
// Request its undeoptimization. This will be done after updating the JDWP event list.
- MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_);
- gDeoptimizationRequests.push_back(MethodInstrumentationRequest(false, m));
- VLOG(jdwp) << "Request undeoptimization of " << PrettyMethod(m);
+ req->kind = DeoptimizationRequest::kSelectiveUndeoptimization;
+ req->method = m;
}
}
diff --git a/runtime/debugger.h b/runtime/debugger.h
index 5fbdb37..23c9c6a 100644
--- a/runtime/debugger.h
+++ b/runtime/debugger.h
@@ -25,6 +25,7 @@
#include <set>
#include <string>
+#include <vector>
#include "jdwp/jdwp.h"
#include "jni.h"
@@ -121,6 +122,25 @@ struct SingleStepControl {
DISALLOW_COPY_AND_ASSIGN(SingleStepControl);
};
+struct DeoptimizationRequest {
+ enum Kind {
+ kNothing, // no action.
+ kFullDeoptimization, // deoptimize everything.
+ kFullUndeoptimization, // undeoptimize everything.
+ kSelectiveDeoptimization, // deoptimize one method.
+ kSelectiveUndeoptimization // undeoptimize one method.
+ };
+
+ DeoptimizationRequest() : kind(kNothing), method(nullptr) {}
+
+ void VisitRoots(RootCallback* callback, void* arg);
+
+ Kind kind;
+
+ // Method for selective deoptimization.
+ mirror::ArtMethod* method;
+};
+
class Dbg {
public:
static bool ParseJdwpOptions(const std::string& options);
@@ -144,8 +164,8 @@ class Dbg {
*/
static void Connected();
static void GoActive()
- LOCKS_EXCLUDED(Locks::breakpoint_lock_, Locks::deoptimization_lock_, Locks::mutator_lock_);
- static void Disconnected() LOCKS_EXCLUDED(Locks::deoptimization_lock_, Locks::mutator_lock_);
+ LOCKS_EXCLUDED(Locks::breakpoint_lock_, deoptimization_lock_, Locks::mutator_lock_);
+ static void Disconnected() LOCKS_EXCLUDED(deoptimization_lock_, Locks::mutator_lock_);
static void Disposed();
// Returns true if we're actually debugging with a real debugger, false if it's
@@ -407,26 +427,23 @@ class Dbg {
LOCKS_EXCLUDED(Locks::breakpoint_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Full Deoptimization control. Only used for method entry/exit and single-stepping.
- static void EnableFullDeoptimization()
- LOCKS_EXCLUDED(Locks::deoptimization_lock_)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static void DisableFullDeoptimization()
- LOCKS_EXCLUDED(Locks::deoptimization_lock_)
+ // Records deoptimization request in the queue.
+ static void RequestDeoptimization(const DeoptimizationRequest& req)
+ LOCKS_EXCLUDED(deoptimization_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Manage deoptimization after updating JDWP events list. This must be done while all mutator
- // threads are suspended.
+ // Manage deoptimization after updating JDWP events list. Suspends all threads, processes each
+ // request and finally resumes all threads.
static void ManageDeoptimization()
- LOCKS_EXCLUDED(Locks::deoptimization_lock_)
+ LOCKS_EXCLUDED(deoptimization_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Breakpoints.
- static void WatchLocation(const JDWP::JdwpLocation* pLoc)
- LOCKS_EXCLUDED(Locks::breakpoint_lock_, Locks::deoptimization_lock_)
+ static void WatchLocation(const JDWP::JdwpLocation* pLoc, DeoptimizationRequest* req)
+ LOCKS_EXCLUDED(Locks::breakpoint_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static void UnwatchLocation(const JDWP::JdwpLocation* pLoc)
- LOCKS_EXCLUDED(Locks::breakpoint_lock_, Locks::deoptimization_lock_)
+ static void UnwatchLocation(const JDWP::JdwpLocation* pLoc, DeoptimizationRequest* req)
+ LOCKS_EXCLUDED(Locks::breakpoint_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Single-stepping.
@@ -521,6 +538,9 @@ class Dbg {
static void PostThreadStartOrStop(Thread*, uint32_t)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static void ProcessDeoptimizationRequest(const DeoptimizationRequest& request)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_);
+
static Mutex* alloc_tracker_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
static AllocRecord* recent_allocation_records_ PT_GUARDED_BY(alloc_tracker_lock_);
@@ -528,6 +548,20 @@ class Dbg {
static size_t alloc_record_head_ GUARDED_BY(alloc_tracker_lock_);
static size_t alloc_record_count_ GUARDED_BY(alloc_tracker_lock_);
+ // Guards deoptimization requests.
+ static Mutex* deoptimization_lock_ ACQUIRED_AFTER(Locks::breakpoint_lock_);
+
+ // Deoptimization requests to be processed each time the event list is updated. This is used when
+ // registering and unregistering events so we do not deoptimize while holding the event list
+ // lock.
+ static std::vector<DeoptimizationRequest> deoptimization_requests_ GUARDED_BY(deoptimization_lock_);
+
+ // Count the number of events requiring full deoptimization. When the counter is > 0, everything
+ // is deoptimized, otherwise everything is undeoptimized.
+ // Note: we fully deoptimize on the first event only (when the counter is set to 1). We fully
+ // undeoptimize when the last event is unregistered (when the counter is set to 0).
+ static size_t full_deoptimization_event_count_ GUARDED_BY(deoptimization_lock_);
+
DISALLOW_COPY_AND_ASSIGN(Dbg);
};
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index d2aa8d2..cf7271b 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -118,7 +118,7 @@ class Instrumentation {
void EnableDeoptimization() EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
LOCKS_EXCLUDED(deoptimized_methods_lock_);
void DisableDeoptimization() EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
- LOCKS_EXCLUDED(deoptimized_methods_lock_);
+ LOCKS_EXCLUDED(deoptimized_methods_lock_);
bool ShouldNotifyMethodEnterExitEvents() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Executes everything with interpreter.
@@ -142,7 +142,7 @@ class Instrumentation {
// (except a class initializer) set to the resolution trampoline will be updated only once its
// declaring class is initialized.
void Undeoptimize(mirror::ArtMethod* method)
- LOCKS_EXCLUDED(Locks::thread_list_lock_)
+ LOCKS_EXCLUDED(Locks::thread_list_lock_, deoptimized_methods_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsDeoptimized(mirror::ArtMethod* method) const LOCKS_EXCLUDED(deoptimized_methods_lock_);
diff --git a/runtime/jdwp/jdwp.h b/runtime/jdwp/jdwp.h
index 4c17c96..66ebb96 100644
--- a/runtime/jdwp/jdwp.h
+++ b/runtime/jdwp/jdwp.h
@@ -335,12 +335,10 @@ struct JdwpState {
AtomicInteger event_serial_;
// Linked list of events requested by the debugger (breakpoints, class prep, etc).
- Mutex event_list_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+ Mutex event_list_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER ACQUIRED_BEFORE(Locks::breakpoint_lock_);
JdwpEvent* event_list_ GUARDED_BY(event_list_lock_);
size_t event_list_size_ GUARDED_BY(event_list_lock_); // Number of elements in event_list_.
- size_t full_deoptimization_requests_ GUARDED_BY(event_list_lock_); // Number of events requiring
- // full deoptimization.
// Used to synchronize suspension of the event thread (to avoid receiving "resume"
// events before the thread has finished suspending itself).
diff --git a/runtime/jdwp/jdwp_event.cc b/runtime/jdwp/jdwp_event.cc
index 427350e..9b3ea2e 100644
--- a/runtime/jdwp/jdwp_event.cc
+++ b/runtime/jdwp/jdwp_event.cc
@@ -163,11 +163,12 @@ JdwpError JdwpState::RegisterEvent(JdwpEvent* pEvent) {
* If one or more "break"-type mods are used, register them with
* the interpreter.
*/
+ DeoptimizationRequest req;
for (int i = 0; i < pEvent->modCount; i++) {
const JdwpEventMod* pMod = &pEvent->mods[i];
if (pMod->modKind == MK_LOCATION_ONLY) {
/* should only be for Breakpoint, Step, and Exception */
- Dbg::WatchLocation(&pMod->locationOnly.loc);
+ Dbg::WatchLocation(&pMod->locationOnly.loc, &req);
} else if (pMod->modKind == MK_STEP) {
/* should only be for EK_SINGLE_STEP; should only be one */
JdwpStepSize size = static_cast<JdwpStepSize>(pMod->step.size);
@@ -181,6 +182,11 @@ JdwpError JdwpState::RegisterEvent(JdwpEvent* pEvent) {
dumpEvent(pEvent); /* TODO - need for field watches */
}
}
+ if (NeedsFullDeoptimization(pEvent->eventKind)) {
+ CHECK_EQ(req.kind, DeoptimizationRequest::kNothing);
+ CHECK(req.method == nullptr);
+ req.kind = DeoptimizationRequest::kFullDeoptimization;
+ }
{
/*
@@ -193,19 +199,11 @@ JdwpError JdwpState::RegisterEvent(JdwpEvent* pEvent) {
}
event_list_ = pEvent;
++event_list_size_;
-
- /**
- * Do we need to enable full deoptimization ?
- */
- if (NeedsFullDeoptimization(pEvent->eventKind)) {
- if (full_deoptimization_requests_ == 0) {
- // This is the first event that needs full deoptimization: enable it.
- Dbg::EnableFullDeoptimization();
- }
- ++full_deoptimization_requests_;
- }
}
+ // TODO we can do better job here since we should process only one request: the one we just
+ // created.
+ Dbg::RequestDeoptimization(req);
Dbg::ManageDeoptimization();
return ERR_NONE;
@@ -238,31 +236,28 @@ void JdwpState::UnregisterEvent(JdwpEvent* pEvent) {
/*
* Unhook us from the interpreter, if necessary.
*/
+ DeoptimizationRequest req;
for (int i = 0; i < pEvent->modCount; i++) {
JdwpEventMod* pMod = &pEvent->mods[i];
if (pMod->modKind == MK_LOCATION_ONLY) {
/* should only be for Breakpoint, Step, and Exception */
- Dbg::UnwatchLocation(&pMod->locationOnly.loc);
+ Dbg::UnwatchLocation(&pMod->locationOnly.loc, &req);
}
if (pMod->modKind == MK_STEP) {
/* should only be for EK_SINGLE_STEP; should only be one */
Dbg::UnconfigureStep(pMod->step.threadId);
}
}
+ if (NeedsFullDeoptimization(pEvent->eventKind)) {
+ CHECK_EQ(req.kind, DeoptimizationRequest::kNothing);
+ CHECK(req.method == nullptr);
+ req.kind = DeoptimizationRequest::kFullUndeoptimization;
+ }
--event_list_size_;
CHECK(event_list_size_ != 0 || event_list_ == NULL);
- /**
- * Can we disable full deoptimization ?
- */
- if (NeedsFullDeoptimization(pEvent->eventKind)) {
- --full_deoptimization_requests_;
- if (full_deoptimization_requests_ == 0) {
- // We no longer need full deoptimization.
- Dbg::DisableFullDeoptimization();
- }
- }
+ Dbg::RequestDeoptimization(req);
}
/*
diff --git a/runtime/jdwp/jdwp_main.cc b/runtime/jdwp/jdwp_main.cc
index 77c963f..5fc0228 100644
--- a/runtime/jdwp/jdwp_main.cc
+++ b/runtime/jdwp/jdwp_main.cc
@@ -215,7 +215,6 @@ JdwpState::JdwpState(const JdwpOptions* options)
event_list_lock_("JDWP event list lock", kJdwpEventListLock),
event_list_(NULL),
event_list_size_(0),
- full_deoptimization_requests_(0),
event_thread_lock_("JDWP event thread lock"),
event_thread_cond_("JDWP event thread condition variable", event_thread_lock_),
event_thread_id_(0),