diff options
author | 2019-06-04 16:48:58 +0100 | |
---|---|---|
committer | 2019-06-06 08:02:04 +0000 | |
commit | d2f13ba7153aa7b77e4662844233c848535f8aac (patch) | |
tree | 9a0f9bda0e886b1652cc306dba4a05648385beb0 | |
parent | e7d7e9dd01b6ce5a079ebc7e369f4a8d4e42f7d8 (diff) |
Remove requirement of a ProfilingInfo for jitted code.
When pre-jitting (zygote or system server in jit zygote mode),
the profiling info is just memory overhead. Remove the need to have
one.
Bug: 119800099
Test: boot, testrunner.py --jit
Change-Id: Ie74d870eebef72c903225542e9b41dfe98132419
-rw-r--r-- | compiler/optimizing/inliner.cc | 5 | ||||
-rw-r--r-- | runtime/jit/jit.cc | 25 | ||||
-rw-r--r-- | runtime/jit/jit.h | 2 | ||||
-rw-r--r-- | runtime/jit/jit_code_cache.cc | 74 | ||||
-rw-r--r-- | runtime/jit/jit_code_cache.h | 6 | ||||
-rw-r--r-- | test/566-polymorphic-inlining/polymorphic_inline.cc | 2 | ||||
-rw-r--r-- | test/570-checker-osr/osr.cc | 3 | ||||
-rw-r--r-- | test/common/runtime_state.cc | 2 |
8 files changed, 47 insertions, 72 deletions
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 205077fb49..9ef5ec31d1 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -604,9 +604,8 @@ bool HInliner::TryInlineFromInlineCache(const DexFile& caller_dex_file, switch (inline_cache_type) { case kInlineCacheNoData: { LOG_FAIL_NO_STAT() - << "Interface or virtual call to " - << caller_dex_file.PrettyMethod(invoke_instruction->GetDexMethodIndex()) - << " could not be statically determined"; + << "No inline cache information for call to " + << caller_dex_file.PrettyMethod(invoke_instruction->GetDexMethodIndex()); return false; } diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc index b828aafcb0..68bdf53d12 100644 --- a/runtime/jit/jit.cc +++ b/runtime/jit/jit.cc @@ -246,7 +246,7 @@ bool Jit::LoadCompilerLibrary(std::string* error_msg) { return true; } -bool Jit::CompileMethod(ArtMethod* method, Thread* self, bool baseline, bool osr) { +bool Jit::CompileMethod(ArtMethod* method, Thread* self, bool baseline, bool osr, bool prejit) { DCHECK(Runtime::Current()->UseJitCompilation()); DCHECK(!method->IsRuntimeMethod()); @@ -269,7 +269,7 @@ bool Jit::CompileMethod(ArtMethod* method, Thread* self, bool baseline, bool osr // If we get a request to compile a proxy method, we pass the actual Java method // of that proxy method, as the compiler does not expect a proxy method. ArtMethod* method_to_compile = method->GetInterfaceMethodIfProxy(kRuntimePointerSize); - if (!code_cache_->NotifyCompilationOf(method_to_compile, self, osr)) { + if (!code_cache_->NotifyCompilationOf(method_to_compile, self, osr, prejit)) { return false; } @@ -561,6 +561,7 @@ class JitCompileTask final : public Task { kCompile, kCompileBaseline, kCompileOsr, + kPreCompile, }; JitCompileTask(ArtMethod* method, TaskKind kind) : method_(method), kind_(kind), klass_(nullptr) { @@ -583,6 +584,7 @@ class JitCompileTask final : public Task { void Run(Thread* self) override { ScopedObjectAccess soa(self); switch (kind_) { + case TaskKind::kPreCompile: case TaskKind::kCompile: case TaskKind::kCompileBaseline: case TaskKind::kCompileOsr: { @@ -590,7 +592,8 @@ class JitCompileTask final : public Task { method_, self, /* baseline= */ (kind_ == TaskKind::kCompileBaseline), - /* osr= */ (kind_ == TaskKind::kCompileOsr)); + /* osr= */ (kind_ == TaskKind::kCompileOsr), + /* prejit= */ (kind_ == TaskKind::kPreCompile)); break; } case TaskKind::kAllocateProfile: { @@ -796,19 +799,15 @@ void Jit::CompileMethodsFromProfile( if (class_linker->IsQuickToInterpreterBridge(entry_point) || class_linker->IsQuickGenericJniStub(entry_point) || class_linker->IsQuickResolutionStub(entry_point)) { - if (!method->IsNative()) { - // The compiler requires a ProfilingInfo object for non-native methods. - ProfilingInfo::Create(self, method, /* retry_allocation= */ true); - } // Special case ZygoteServer class so that it gets compiled before the // zygote enters it. This avoids needing to do OSR during app startup. // TODO: have a profile instead. if (!add_to_queue || method->GetDeclaringClass()->DescriptorEquals( "Lcom/android/internal/os/ZygoteServer;")) { - CompileMethod(method, self, /* baseline= */ false, /* osr= */ false); + CompileMethod(method, self, /* baseline= */ false, /* osr= */ false, /* prejit= */ true); } else { thread_pool_->AddTask(self, - new JitCompileTask(method, JitCompileTask::TaskKind::kCompile)); + new JitCompileTask(method, JitCompileTask::TaskKind::kPreCompile)); } } } @@ -890,7 +889,7 @@ bool Jit::MaybeCompileMethod(Thread* self, method->IsNative() && Runtime::Current()->IsUsingApexBootImageLocation()) { // jitzygote: Compile JNI stub on first use to avoid the expensive generic stub. - CompileMethod(method, self, /* baseline= */ false, /* osr= */ false); + CompileMethod(method, self, /* baseline= */ false, /* osr= */ false, /* prejit= */ false); return true; } if (old_count < HotMethodThreshold() && new_count >= HotMethodThreshold()) { @@ -935,11 +934,7 @@ void Jit::MethodEntered(Thread* thread, ArtMethod* method) { if (UNLIKELY(runtime->UseJitCompilation() && runtime->GetJit()->JitAtFirstUse())) { ArtMethod* np_method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize); if (np_method->IsCompilable()) { - if (!np_method->IsNative()) { - // The compiler requires a ProfilingInfo object for non-native methods. - ProfilingInfo::Create(thread, np_method, /* retry_allocation= */ true); - } - JitCompileTask compile_task(method, JitCompileTask::TaskKind::kCompile); + JitCompileTask compile_task(method, JitCompileTask::TaskKind::kPreCompile); // Fake being in a runtime thread so that class-load behavior will be the same as normal jit. ScopedSetRuntimeThread ssrt(thread); compile_task.Run(thread); diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h index 4b81f717d5..92d2b55b4a 100644 --- a/runtime/jit/jit.h +++ b/runtime/jit/jit.h @@ -170,7 +170,7 @@ class Jit { // Create JIT itself. static Jit* Create(JitCodeCache* code_cache, JitOptions* options); - bool CompileMethod(ArtMethod* method, Thread* self, bool baseline, bool osr) + bool CompileMethod(ArtMethod* method, Thread* self, bool baseline, bool osr, bool prejit) REQUIRES_SHARED(Locks::mutator_lock_); const JitCodeCache* GetCodeCache() const { diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc index 65e6d9d25f..2505111058 100644 --- a/runtime/jit/jit_code_cache.cc +++ b/runtime/jit/jit_code_cache.cc @@ -1127,12 +1127,15 @@ uint8_t* JitCodeCache::CommitCodeInternal(Thread* self, // This situation currently only occurs in the jit-zygote mode. DCHECK(Runtime::Current()->IsZygote()); DCHECK(Runtime::Current()->IsUsingApexBootImageLocation()); - DCHECK(method->GetProfilingInfo(kRuntimePointerSize) != nullptr); DCHECK(method->GetDeclaringClass()->GetClassLoader() == nullptr); - // Save the entrypoint, so it can be fethed later once the class is - // initialized. - method->GetProfilingInfo(kRuntimePointerSize)->SetSavedEntryPoint( - method_header->GetEntryPoint()); + // TODO(ngeoffray): In most cases, the zygote will not have a profiling + // info for a compiled method. Use a map instead. + if (method->GetProfilingInfo(kRuntimePointerSize) != nullptr) { + // Save the entrypoint, so it can be fetched later once the class is + // initialized. + method->GetProfilingInfo(kRuntimePointerSize)->SetSavedEntryPoint( + method_header->GetEntryPoint()); + } } else { Runtime::Current()->GetInstrumentation()->UpdateMethodsCode( method, method_header->GetEntryPoint()); @@ -1564,8 +1567,6 @@ void JitCodeCache::GarbageCollectCache(Thread* self) { } } - DCHECK(CheckLiveCompiledCodeHasProfilingInfo()); - // Change entry points of native methods back to the GenericJNI entrypoint. for (const auto& entry : jni_stubs_map_) { const JniStubData& data = entry.second; @@ -1743,28 +1744,7 @@ void JitCodeCache::DoCollection(Thread* self, bool collect_profiling_info) { return false; }); profiling_infos_.erase(profiling_kept_end, profiling_infos_.end()); - DCHECK(CheckLiveCompiledCodeHasProfilingInfo()); - } -} - -bool JitCodeCache::CheckLiveCompiledCodeHasProfilingInfo() { - ScopedTrace trace(__FUNCTION__); - // Check that methods we have compiled do have a ProfilingInfo object. We would - // have memory leaks of compiled code otherwise. - for (const auto& it : method_code_map_) { - ArtMethod* method = it.second; - if (method->GetProfilingInfo(kRuntimePointerSize) == nullptr) { - const void* code_ptr = it.first; - const OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr); - if (method_header->GetEntryPoint() == method->GetEntryPointFromQuickCompiledCode()) { - // If the code is not dead, then we have a problem. Note that this can even - // happen just after a collection, as mutator threads are running in parallel - // and could deoptimize an existing compiled code. - return false; - } - } } - return true; } OatQuickMethodHeader* JitCodeCache::LookupMethodHeader(uintptr_t pc, ArtMethod* method) { @@ -2003,16 +1983,16 @@ bool JitCodeCache::IsOsrCompiled(ArtMethod* method) { return osr_code_map_.find(method) != osr_code_map_.end(); } -bool JitCodeCache::NotifyCompilationOf(ArtMethod* method, Thread* self, bool osr) { +bool JitCodeCache::NotifyCompilationOf(ArtMethod* method, Thread* self, bool osr, bool prejit) { if (!osr && ContainsPc(method->GetEntryPointFromQuickCompiledCode())) { return false; } ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); if (class_linker->IsQuickResolutionStub(method->GetEntryPointFromQuickCompiledCode())) { - if (!Runtime::Current()->IsUsingApexBootImageLocation() || !Runtime::Current()->IsZygote()) { - // Unless we're running as zygote in the jitzygote experiment, we currently don't save - // the JIT compiled code if we cannot update the entrypoint due to having the resolution stub. + if (!prejit) { + // Unless we're pre-jitting, we currently don't save the JIT compiled code if we cannot + // update the entrypoint due to having the resolution stub. VLOG(jit) << "Not compiling " << method->PrettyMethod() << " because it has the resolution stub"; @@ -2064,18 +2044,20 @@ bool JitCodeCache::NotifyCompilationOf(ArtMethod* method, Thread* self, bool osr } else { ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize); if (info == nullptr) { - VLOG(jit) << method->PrettyMethod() << " needs a ProfilingInfo to be compiled"; - // Because the counter is not atomic, there are some rare cases where we may not hit the - // threshold for creating the ProfilingInfo. Reset the counter now to "correct" this. - ClearMethodCounter(method, /*was_warm=*/ false); - return false; - } - - if (info->IsMethodBeingCompiled(osr)) { - return false; + // When prejitting, we don't allocate a profiling info. + if (!prejit) { + VLOG(jit) << method->PrettyMethod() << " needs a ProfilingInfo to be compiled"; + // Because the counter is not atomic, there are some rare cases where we may not hit the + // threshold for creating the ProfilingInfo. Reset the counter now to "correct" this. + ClearMethodCounter(method, /*was_warm=*/ false); + return false; + } + } else { + if (info->IsMethodBeingCompiled(osr)) { + return false; + } + info->SetIsMethodBeingCompiled(true, osr); } - - info->SetIsMethodBeingCompiled(true, osr); return true; } } @@ -2113,8 +2095,10 @@ void JitCodeCache::DoneCompiling(ArtMethod* method, Thread* self, bool osr) { } // else CommitCodeInternal() updated entrypoints of all methods in the JniStubData. } else { ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize); - DCHECK(info->IsMethodBeingCompiled(osr)); - info->SetIsMethodBeingCompiled(false, osr); + if (info != nullptr) { + DCHECK(info->IsMethodBeingCompiled(osr)); + info->SetIsMethodBeingCompiled(false, osr); + } } } diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h index a3e10c75af..3078e2be8f 100644 --- a/runtime/jit/jit_code_cache.h +++ b/runtime/jit/jit_code_cache.h @@ -101,7 +101,7 @@ class JitCodeCache { std::string* error_msg); ~JitCodeCache(); - bool NotifyCompilationOf(ArtMethod* method, Thread* self, bool osr) + bool NotifyCompilationOf(ArtMethod* method, Thread* self, bool osr, bool prejit) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!lock_); @@ -381,10 +381,6 @@ class JitCodeCache { REQUIRES(!lock_) REQUIRES_SHARED(Locks::mutator_lock_); - bool CheckLiveCompiledCodeHasProfilingInfo() - REQUIRES(lock_) - REQUIRES_SHARED(Locks::mutator_lock_); - CodeCacheBitmap* GetLiveBitmap() const { return live_bitmap_.get(); } diff --git a/test/566-polymorphic-inlining/polymorphic_inline.cc b/test/566-polymorphic-inlining/polymorphic_inline.cc index 00827cf8d5..15187f3c59 100644 --- a/test/566-polymorphic-inlining/polymorphic_inline.cc +++ b/test/566-polymorphic-inlining/polymorphic_inline.cc @@ -46,7 +46,7 @@ static void do_checks(jclass cls, const char* method_name) { usleep(1000); } // Will either ensure it's compiled or do the compilation itself. - jit->CompileMethod(method, soa.Self(), /*baseline=*/ false, /*osr=*/ false); + jit->CompileMethod(method, soa.Self(), /*baseline=*/ false, /*osr=*/ false, /*prejit=*/ false); } CodeInfo info(header); diff --git a/test/570-checker-osr/osr.cc b/test/570-checker-osr/osr.cc index dc0e94cbc7..ee978c2675 100644 --- a/test/570-checker-osr/osr.cc +++ b/test/570-checker-osr/osr.cc @@ -128,7 +128,8 @@ extern "C" JNIEXPORT void JNICALL Java_Main_ensureHasOsrCode(JNIEnv* env, // Sleep to yield to the compiler thread. usleep(1000); // Will either ensure it's compiled or do the compilation itself. - jit->CompileMethod(m, Thread::Current(), /*baseline=*/ false, /*osr=*/ true); + jit->CompileMethod( + m, Thread::Current(), /*baseline=*/ false, /*osr=*/ true, /*prejit=*/ false); } }); } diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc index a0b2f1ea72..7b023dee6a 100644 --- a/test/common/runtime_state.cc +++ b/test/common/runtime_state.cc @@ -246,7 +246,7 @@ static void ForceJitCompiled(Thread* self, ArtMethod* method) REQUIRES(!Locks::m ProfilingInfo::Create(self, method, /* retry_allocation */ true); } // Will either ensure it's compiled or do the compilation itself. - jit->CompileMethod(method, self, /*baseline=*/ false, /*osr=*/ false); + jit->CompileMethod(method, self, /*baseline=*/ false, /*osr=*/ false, /*prejit=*/ false); } } } |