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/nodes.h b/compiler/optimizing/nodes.h
index 48fb611..c70674b 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -317,6 +317,7 @@
          uint32_t method_idx,
          InstructionSet instruction_set,
          InvokeType invoke_type = kInvalidInvokeType,
+         bool dead_reference_safe = false,
          bool debuggable = false,
          bool osr = false,
          int start_instruction_id = 0)
@@ -336,6 +337,7 @@
         has_simd_(false),
         has_loops_(false),
         has_irreducible_loops_(false),
+        dead_reference_safe_(dead_reference_safe),
         debuggable_(debuggable),
         current_instruction_id_(start_instruction_id),
         dex_file_(dex_file),
@@ -526,6 +528,12 @@
     has_bounds_checks_ = value;
   }
 
+  // Is the code known to be robust against eliminating dead references
+  // and the effects of early finalization?
+  bool IsDeadReferenceSafe() const { return dead_reference_safe_; }
+
+  void MarkDeadReferenceUnsafe() { dead_reference_safe_ = false; }
+
   bool IsDebuggable() const { return debuggable_; }
 
   // Returns a constant of the given type and value. If it does not exist
@@ -704,6 +712,14 @@
   // so there might be false positives.
   bool has_irreducible_loops_;
 
+  // Is the code known to be robust against eliminating dead references
+  // and the effects of early finalization? If false, dead reference variables
+  // are kept if they might be visible to the garbage collector.
+  // Currently this means that the class was declared to be dead-reference-safe,
+  // the method accesses no reachability-sensitive fields or data, and the same
+  // is true for any methods that were inlined into the current one.
+  bool dead_reference_safe_;
+
   // Indicates whether the graph should be compiled in a way that
   // ensures full debuggability. If false, we can apply more
   // aggressive optimizations that may limit the level of debugging.