Fix JIT for class unloading
Keep declaring class of method live to prevent unloading.
Wait for JIT to finish compiling before calling Runtime.gc(), this
prevents flaky failures due to classes not being unloaded.
Bug: 22720414
Change-Id: I9fe5e5e39d681bcd22acc2d2f34b0dbc9887708d
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index 643bc23..e73ba82 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -67,6 +67,9 @@
void DumpInfo(std::ostream& os);
// Add a timing logger to cumulative_timings_.
void AddTimingLogger(const TimingLogger& logger);
+ JitInstrumentationCache* GetInstrumentationCache() const {
+ return instrumentation_cache_.get();
+ }
private:
Jit();
diff --git a/runtime/jit/jit_instrumentation.cc b/runtime/jit/jit_instrumentation.cc
index d437dd5..af6aba3 100644
--- a/runtime/jit/jit_instrumentation.cc
+++ b/runtime/jit/jit_instrumentation.cc
@@ -26,7 +26,17 @@
class JitCompileTask : public Task {
public:
- explicit JitCompileTask(ArtMethod* method) : method_(method) {}
+ explicit JitCompileTask(ArtMethod* method) : method_(method) {
+ ScopedObjectAccess soa(Thread::Current());
+ // Add a global ref to the class to prevent class unloading until compilation is done.
+ klass_ = soa.Vm()->AddGlobalRef(soa.Self(), method_->GetDeclaringClass());
+ CHECK(klass_ != nullptr);
+ }
+
+ ~JitCompileTask() {
+ ScopedObjectAccess soa(Thread::Current());
+ soa.Vm()->DeleteGlobalRef(soa.Self(), klass_);
+ }
virtual void Run(Thread* self) OVERRIDE {
ScopedObjectAccess soa(self);
@@ -42,6 +52,7 @@
private:
ArtMethod* const method_;
+ jobject klass_;
DISALLOW_IMPLICIT_CONSTRUCTORS(JitCompileTask);
};
@@ -104,5 +115,28 @@
}
}
+class WaitForCompilationToFinishTask : public Task {
+ public:
+ WaitForCompilationToFinishTask() : barrier_(0) {}
+
+ void Wait(Thread* self) {
+ barrier_.Increment(self, 1);
+ }
+
+ virtual void Run(Thread* self) OVERRIDE {
+ barrier_.Pass(self);
+ }
+
+ private:
+ Barrier barrier_;
+ DISALLOW_COPY_AND_ASSIGN(WaitForCompilationToFinishTask);
+};
+
+void JitInstrumentationCache::WaitForCompilationToFinish(Thread* self) {
+ std::unique_ptr<WaitForCompilationToFinishTask> task(new WaitForCompilationToFinishTask);
+ thread_pool_->AddTask(self, task.get());
+ task->Wait(self);
+}
+
} // namespace jit
} // namespace art
diff --git a/runtime/jit/jit_instrumentation.h b/runtime/jit/jit_instrumentation.h
index 6fdef65..9eb464b 100644
--- a/runtime/jit/jit_instrumentation.h
+++ b/runtime/jit/jit_instrumentation.h
@@ -50,6 +50,8 @@
SHARED_REQUIRES(Locks::mutator_lock_);
void CreateThreadPool();
void DeleteThreadPool();
+ // Wait until there is no more pending compilation tasks.
+ void WaitForCompilationToFinish(Thread* self);
private:
size_t hot_method_threshold_;