diff options
| author | 2016-03-11 09:57:57 +0000 | |
|---|---|---|
| committer | 2016-03-11 09:57:57 +0000 | |
| commit | 07e3ca9a46801990d662c48d0fddedc63c4c053c (patch) | |
| tree | 94fedc96b28c6a46d2b83c80b2cfefd4c2898f4a /compiler/optimizing | |
| parent | b7f257f353b1eb2db2732939a0404c118316891d (diff) | |
Fix thread race when fetching the ProfilingInfo object.
Problem is:
1) Compiler fetches the ProfilingInfo of A, it's null.
2) Mutator creates the ProfilingInfo.
3) Compiler notifies it's not using A anymore, calls
ProfilingInfo::DecrementInlineUse -> Crash as we expected
ProfilingInfo::IncrementUse to be called before.
Also update some namings to better reflect what is going on.
Change-Id: I55ea4c5d81988131467095e18a0d13a8be9d0ef7
Diffstat (limited to 'compiler/optimizing')
| -rw-r--r-- | compiler/optimizing/inliner.cc | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index bbdac262c4..d861e39c8b 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -224,16 +224,29 @@ static uint32_t FindClassIndexIn(mirror::Class* cls, class ScopedProfilingInfoInlineUse { public: - explicit ScopedProfilingInfoInlineUse(ArtMethod* method) : method_(method) { - Runtime::Current()->GetJit()->GetCodeCache()->NotifyInliningOf(method_, Thread::Current()); + explicit ScopedProfilingInfoInlineUse(ArtMethod* method, Thread* self) + : method_(method), + self_(self), + // Fetch the profiling info ahead of using it. If it's null when fetching, + // we should not call JitCodeCache::DoneInlining. + profiling_info_( + Runtime::Current()->GetJit()->GetCodeCache()->NotifyCompilerUse(method, self)) { } ~ScopedProfilingInfoInlineUse() { - Runtime::Current()->GetJit()->GetCodeCache()->DoneInlining(method_, Thread::Current()); + if (profiling_info_ != nullptr) { + size_t pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize(); + DCHECK_EQ(profiling_info_, method_->GetProfilingInfo(pointer_size)); + Runtime::Current()->GetJit()->GetCodeCache()->DoneCompilerUse(method_, self_); + } } + ProfilingInfo* GetProfilingInfo() const { return profiling_info_; } + private: ArtMethod* const method_; + Thread* const self_; + ProfilingInfo* const profiling_info_; }; bool HInliner::TryInline(HInvoke* invoke_instruction) { @@ -287,15 +300,14 @@ bool HInliner::TryInline(HInvoke* invoke_instruction) { // Check if we can use an inline cache. ArtMethod* caller = graph_->GetArtMethod(); - size_t pointer_size = class_linker->GetImagePointerSize(); if (Runtime::Current()->UseJit()) { // Under JIT, we should always know the caller. DCHECK(caller != nullptr); - ScopedProfilingInfoInlineUse spiis(caller); - ProfilingInfo* profiling_info = caller->GetProfilingInfo(pointer_size); + ScopedProfilingInfoInlineUse spiis(caller, soa.Self()); + ProfilingInfo* profiling_info = spiis.GetProfilingInfo(); if (profiling_info != nullptr) { const InlineCache& ic = *profiling_info->GetInlineCache(invoke_instruction->GetDexPc()); - if (ic.IsUnitialized()) { + if (ic.IsUninitialized()) { VLOG(compiler) << "Interface or virtual call to " << PrettyMethod(method_index, caller_dex_file) << " is not hit and not inlined"; |