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
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 205077f..9ef5ec3 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -604,9 +604,8 @@
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 b828aaf..68bdf53 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -246,7 +246,7 @@
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 @@
// 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 @@
kCompile,
kCompileBaseline,
kCompileOsr,
+ kPreCompile,
};
JitCompileTask(ArtMethod* method, TaskKind kind) : method_(method), kind_(kind), klass_(nullptr) {
@@ -583,6 +584,7 @@
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 @@
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 @@
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 @@
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 @@
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 4b81f71..92d2b55 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -170,7 +170,7 @@
// 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 65e6d9d..2505111 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -1127,12 +1127,15 @@
// 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 @@
}
}
- 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,30 +1744,9 @@
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) {
static_assert(kRuntimeISA != InstructionSet::kThumb2, "kThumb2 cannot be a runtime ISA");
if (kRuntimeISA == InstructionSet::kArm) {
@@ -2003,16 +1983,16 @@
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 @@
} 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;
+ // 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);
}
-
- if (info->IsMethodBeingCompiled(osr)) {
- return false;
- }
-
- info->SetIsMethodBeingCompiled(true, osr);
return true;
}
}
@@ -2113,8 +2095,10 @@
} // 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 a3e10c7..3078e2b 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -101,7 +101,7 @@
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 @@
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 00827cf..15187f3 100644
--- a/test/566-polymorphic-inlining/polymorphic_inline.cc
+++ b/test/566-polymorphic-inlining/polymorphic_inline.cc
@@ -46,7 +46,7 @@
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 dc0e94c..ee978c2 100644
--- a/test/570-checker-osr/osr.cc
+++ b/test/570-checker-osr/osr.cc
@@ -128,7 +128,8 @@
// 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 a0b2f1e..7b023de 100644
--- a/test/common/runtime_state.cc
+++ b/test/common/runtime_state.cc
@@ -246,7 +246,7 @@
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);
}
}
}