summaryrefslogtreecommitdiff
path: root/openjdkjvmti/deopt_manager.cc
diff options
context:
space:
mode:
author Alex Light <allight@google.com> 2018-08-13 15:55:44 -0700
committer Alex Light <allight@google.com> 2018-08-14 13:25:15 -0700
commit3b8aa77c8c4c458e69ae8872a22f68894b94ef4a (patch)
tree55f6576cbaae0c06ad5ed32f8da8e8357f04a92f /openjdkjvmti/deopt_manager.cc
parent350b6a312222b9b27bfee0e72ce261a45cb60e1c (diff)
Pause GC during deoptimization work
When we are deoptimizing code we should stop the gc to prevent deadlocks. This change also reorganizes gc pause code a bit to make this simpler to implement. Test: ./test.py --host Bug: 79175795 Change-Id: I00000ab608231a7fd1627d69d58216b9115a47ca
Diffstat (limited to 'openjdkjvmti/deopt_manager.cc')
-rw-r--r--openjdkjvmti/deopt_manager.cc15
1 files changed, 12 insertions, 3 deletions
diff --git a/openjdkjvmti/deopt_manager.cc b/openjdkjvmti/deopt_manager.cc
index 2f24d7ea3d..d20c756522 100644
--- a/openjdkjvmti/deopt_manager.cc
+++ b/openjdkjvmti/deopt_manager.cc
@@ -40,6 +40,8 @@
#include "dex/dex_file_annotations.h"
#include "dex/modifiers.h"
#include "events-inl.h"
+#include "gc/heap.h"
+#include "gc/scoped_gc_critical_section.h"
#include "jit/jit.h"
#include "jni/jni_internal.h"
#include "mirror/class-inl.h"
@@ -266,29 +268,35 @@ void DeoptManager::WaitForDeoptimizationToFinish(art::Thread* self) {
deoptimization_status_lock_.ExclusiveUnlock(self);
}
+// Users should make sure that only gc-critical-section safe code is used while a
+// ScopedDeoptimizationContext exists.
class ScopedDeoptimizationContext : public art::ValueObject {
public:
ScopedDeoptimizationContext(art::Thread* self, DeoptManager* deopt)
RELEASE(deopt->deoptimization_status_lock_)
ACQUIRE(art::Locks::mutator_lock_)
ACQUIRE(art::Roles::uninterruptible_)
- : self_(self), deopt_(deopt), uninterruptible_cause_(nullptr) {
+ : self_(self),
+ deopt_(deopt),
+ critical_section_(self_, "JVMTI Deoptimizing methods"),
+ uninterruptible_cause_(nullptr) {
deopt_->WaitForDeoptimizationToFinishLocked(self_);
DCHECK(!deopt->performing_deoptimization_)
<< "Already performing deoptimization on another thread!";
// Use performing_deoptimization_ to keep track of the lock.
deopt_->performing_deoptimization_ = true;
deopt_->deoptimization_status_lock_.Unlock(self_);
+ uninterruptible_cause_ = critical_section_.Enter(art::gc::kGcCauseInstrumentation,
+ art::gc::kCollectorTypeCriticalSection);
art::Runtime::Current()->GetThreadList()->SuspendAll("JMVTI Deoptimizing methods",
/*long_suspend*/ false);
- uninterruptible_cause_ = self_->StartAssertNoThreadSuspension("JVMTI deoptimizing methods");
}
~ScopedDeoptimizationContext()
RELEASE(art::Locks::mutator_lock_)
RELEASE(art::Roles::uninterruptible_) {
// Can be suspended again.
- self_->EndAssertNoThreadSuspension(uninterruptible_cause_);
+ critical_section_.Exit(uninterruptible_cause_);
// Release the mutator lock.
art::Runtime::Current()->GetThreadList()->ResumeAll();
// Let other threads know it's fine to proceed.
@@ -300,6 +308,7 @@ class ScopedDeoptimizationContext : public art::ValueObject {
private:
art::Thread* self_;
DeoptManager* deopt_;
+ art::gc::GCCriticalSection critical_section_;
const char* uninterruptible_cause_;
};