Selectively allow dead reference elimination
Allow dead reference elimination in methods not containing
@ReachabilitySensitive accesses or calls, when the class is marked
@DeadReferenceSafe.
Add 1339-dead-reference-safe to aggressively check that everything
works as intended.
Bug: 111453875
Test: art/test/testrunner/testrunner.py --host --64 -t 1339-dead-reference-safe
Detect ReachabilitySensitive annotations.
Change-Id: I70c20431fdbcfcfd2692b2255d12ad59e37cb669
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 42dbc77..e8f8d32 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -828,6 +828,29 @@
}
CodeItemDebugInfoAccessor code_item_accessor(dex_file, code_item, method_idx);
+
+ bool dead_reference_safe;
+ ArrayRef<const uint8_t> interpreter_metadata;
+ // For AOT compilation, we may not get a method, for example if its class is erroneous,
+ // possibly due to an unavailable superclass. JIT should always have a method.
+ DCHECK(Runtime::Current()->IsAotCompiler() || method != nullptr);
+ if (method != nullptr) {
+ const dex::ClassDef* containing_class;
+ {
+ ScopedObjectAccess soa(Thread::Current());
+ containing_class = &method->GetClassDef();
+ interpreter_metadata = method->GetQuickenedInfo();
+ }
+ // MethodContainsRSensitiveAccess is currently slow, but HasDeadReferenceSafeAnnotation()
+ // is currently rarely true.
+ dead_reference_safe =
+ annotations::HasDeadReferenceSafeAnnotation(dex_file, *containing_class)
+ && !annotations::MethodContainsRSensitiveAccess(dex_file, *containing_class, method_idx);
+ } else {
+ // If we could not resolve the class, conservatively assume it's dead-reference unsafe.
+ dead_reference_safe = false;
+ }
+
HGraph* graph = new (allocator) HGraph(
allocator,
arena_stack,
@@ -835,17 +858,12 @@
method_idx,
compiler_options.GetInstructionSet(),
kInvalidInvokeType,
+ dead_reference_safe,
compiler_driver->GetCompilerOptions().GetDebuggable(),
- osr);
+ /* osr= */ osr);
- ArrayRef<const uint8_t> interpreter_metadata;
- // For AOT compilation, we may not get a method, for example if its class is erroneous.
- // JIT should always have a method.
- DCHECK(Runtime::Current()->IsAotCompiler() || method != nullptr);
if (method != nullptr) {
graph->SetArtMethod(method);
- ScopedObjectAccess soa(Thread::Current());
- interpreter_metadata = method->GetQuickenedInfo();
}
std::unique_ptr<CodeGenerator> codegen(
@@ -963,6 +981,7 @@
method_idx,
compiler_options.GetInstructionSet(),
kInvalidInvokeType,
+ /* dead_reference_safe= */ true, // Intrinsics don't affect dead reference safety.
compiler_options.GetDebuggable(),
/* osr= */ false);