Fix go/lem breakages on baseline configs
- Don't collect profiling info for now, as compiled code reference
them directly.
- Only compile optimized after reaching baseline hotness threshold if
tiered JIT is enabled.
Test: test.py, go/lem benchmarks.
Change-Id: I0d21d5f77825a710588ef5a7c11288a5b9757907
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 04e8d39..945600a 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -1119,18 +1119,24 @@
// Start polling the liveness of compiled code to prepare for the next full collection.
if (next_collection_will_be_full) {
- // Save the entry point of methods we have compiled, and update the entry
- // point of those methods to the interpreter. If the method is invoked, the
- // interpreter will update its entry point to the compiled code and call it.
- for (ProfilingInfo* info : profiling_infos_) {
- const void* entry_point = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
- if (!IsInZygoteDataSpace(info) && ContainsPc(entry_point)) {
- info->SetSavedEntryPoint(entry_point);
- // Don't call Instrumentation::UpdateMethodsCode(), as it can check the declaring
- // class of the method. We may be concurrently running a GC which makes accessing
- // the class unsafe. We know it is OK to bypass the instrumentation as we've just
- // checked that the current entry point is JIT compiled code.
- info->GetMethod()->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
+ if (Runtime::Current()->GetJITOptions()->CanCompileBaseline()) {
+ for (ProfilingInfo* info : profiling_infos_) {
+ info->SetBaselineHotnessCount(0);
+ }
+ } else {
+ // Save the entry point of methods we have compiled, and update the entry
+ // point of those methods to the interpreter. If the method is invoked, the
+ // interpreter will update its entry point to the compiled code and call it.
+ for (ProfilingInfo* info : profiling_infos_) {
+ const void* entry_point = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
+ if (!IsInZygoteDataSpace(info) && ContainsPc(entry_point)) {
+ info->SetSavedEntryPoint(entry_point);
+ // Don't call Instrumentation::UpdateMethodsCode(), as it can check the declaring
+ // class of the method. We may be concurrently running a GC which makes accessing
+ // the class unsafe. We know it is OK to bypass the instrumentation as we've just
+ // checked that the current entry point is JIT compiled code.
+ info->GetMethod()->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
+ }
}
}
@@ -1219,28 +1225,50 @@
ScopedTrace trace(__FUNCTION__);
{
MutexLock mu(self, *Locks::jit_lock_);
- if (collect_profiling_info) {
- // Clear the profiling info of methods that do not have compiled code as entrypoint.
- // Also remove the saved entry point from the ProfilingInfo objects.
- for (ProfilingInfo* info : profiling_infos_) {
- const void* ptr = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
- if (!ContainsPc(ptr) && !info->IsInUseByCompiler() && !IsInZygoteDataSpace(info)) {
- info->GetMethod()->SetProfilingInfo(nullptr);
- }
- if (info->GetSavedEntryPoint() != nullptr) {
- info->SetSavedEntryPoint(nullptr);
- // We are going to move this method back to interpreter. Clear the counter now to
- // give it a chance to be hot again.
- ClearMethodCounter(info->GetMethod(), /*was_warm=*/ true);
+ if (Runtime::Current()->GetJITOptions()->CanCompileBaseline()) {
+ // Update to interpreter the methods that have baseline entrypoints and whose baseline
+ // hotness count is zero.
+ // Note that these methods may be in thread stack or concurrently revived
+ // between. That's OK, as the thread executing it will mark it.
+ for (ProfilingInfo* info : profiling_infos_) {
+ if (info->GetBaselineHotnessCount() == 0) {
+ const void* entry_point = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
+ if (ContainsPc(entry_point)) {
+ OatQuickMethodHeader* method_header =
+ OatQuickMethodHeader::FromEntryPoint(entry_point);
+ if (CodeInfo::IsBaseline(method_header->GetOptimizedCodeInfoPtr())) {
+ info->GetMethod()->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
+ }
+ }
}
}
- } else if (kIsDebugBuild) {
- // Sanity check that the profiling infos do not have a dangling entry point.
- for (ProfilingInfo* info : profiling_infos_) {
- DCHECK(!Runtime::Current()->IsZygote());
- const void* entry_point = info->GetSavedEntryPoint();
- DCHECK(entry_point == nullptr || IsInZygoteExecSpace(entry_point));
+ // TODO: collect profiling info
+ // TODO: collect optimized code?
+ } else {
+ if (collect_profiling_info) {
+ // Clear the profiling info of methods that do not have compiled code as entrypoint.
+ // Also remove the saved entry point from the ProfilingInfo objects.
+ for (ProfilingInfo* info : profiling_infos_) {
+ const void* ptr = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
+ if (!ContainsPc(ptr) && !info->IsInUseByCompiler() && !IsInZygoteDataSpace(info)) {
+ info->GetMethod()->SetProfilingInfo(nullptr);
+ }
+
+ if (info->GetSavedEntryPoint() != nullptr) {
+ info->SetSavedEntryPoint(nullptr);
+ // We are going to move this method back to interpreter. Clear the counter now to
+ // give it a chance to be hot again.
+ ClearMethodCounter(info->GetMethod(), /*was_warm=*/ true);
+ }
+ }
+ } else if (kIsDebugBuild) {
+ // Sanity check that the profiling infos do not have a dangling entry point.
+ for (ProfilingInfo* info : profiling_infos_) {
+ DCHECK(!Runtime::Current()->IsZygote());
+ const void* entry_point = info->GetSavedEntryPoint();
+ DCHECK(entry_point == nullptr || IsInZygoteExecSpace(entry_point));
+ }
}
}
@@ -1622,6 +1650,12 @@
return new_compilation;
} else {
ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize);
+ if (CanAllocateProfilingInfo() && baseline && info == nullptr) {
+ // We can retry allocation here as we're the JIT thread.
+ if (ProfilingInfo::Create(self, method, /* retry_allocation= */ true)) {
+ info = method->GetProfilingInfo(kRuntimePointerSize);
+ }
+ }
if (info == nullptr) {
// When prejitting, we don't allocate a profiling info.
if (!prejit && !IsSharedRegion(*region)) {