Snap for 11526283 from d64187a4b1706c9517d1c469056caec835443aee to 24Q2-release

Change-Id: If65b87484269514cee093f885e64581322777306
diff --git a/compiler/dex/inline_method_analyser.cc b/compiler/dex/inline_method_analyser.cc
index 43e984b..91944b0 100644
--- a/compiler/dex/inline_method_analyser.cc
+++ b/compiler/dex/inline_method_analyser.cc
@@ -467,10 +467,6 @@
     case Instruction::IGET_CHAR:
     case Instruction::IGET_SHORT:
     case Instruction::IGET_WIDE:
-    // TODO: Add handling for JIT.
-    // case Instruction::IGET_QUICK:
-    // case Instruction::IGET_WIDE_QUICK:
-    // case Instruction::IGET_OBJECT_QUICK:
       return AnalyseIGetMethod(method, code_item, result);
     case Instruction::IPUT:
     case Instruction::IPUT_OBJECT:
@@ -479,10 +475,6 @@
     case Instruction::IPUT_CHAR:
     case Instruction::IPUT_SHORT:
     case Instruction::IPUT_WIDE:
-      // TODO: Add handling for JIT.
-    // case Instruction::IPUT_QUICK:
-    // case Instruction::IPUT_WIDE_QUICK:
-    // case Instruction::IPUT_OBJECT_QUICK:
       return AnalyseIPutMethod(method, code_item, result);
     default:
       return false;
diff --git a/compiler/optimizing/constant_folding.cc b/compiler/optimizing/constant_folding.cc
index f57d8ad..52cbfe8 100644
--- a/compiler/optimizing/constant_folding.cc
+++ b/compiler/optimizing/constant_folding.cc
@@ -876,18 +876,35 @@
 
 void InstructionWithAbsorbingInputSimplifier::VisitOr(HOr* instruction) {
   HConstant* input_cst = instruction->GetConstantRight();
-
-  if (input_cst == nullptr) {
-    return;
-  }
-
-  if (Int64FromConstant(input_cst) == -1) {
+  if (input_cst != nullptr && Int64FromConstant(input_cst) == -1) {
     // Replace code looking like
     //    OR dst, src, 0xFFF...FF
     // with
     //    CONSTANT 0xFFF...FF
     instruction->ReplaceWith(input_cst);
     instruction->GetBlock()->RemoveInstruction(instruction);
+    return;
+  }
+
+  HInstruction* left = instruction->GetLeft();
+  HInstruction* right = instruction->GetRight();
+  if (left->IsNot() ^ right->IsNot()) {
+    // Replace code looking like
+    //    NOT notsrc, src
+    //    OR  dst, notsrc, src
+    // with
+    //    CONSTANT 0xFFF...FF
+    HInstruction* hnot = (left->IsNot() ? left : right);
+    HInstruction* hother = (left->IsNot() ? right : left);
+    HInstruction* src = hnot->AsNot()->GetInput();
+
+    if (src == hother) {
+      DCHECK(instruction->GetType() == DataType::Type::kInt32 ||
+             instruction->GetType() == DataType::Type::kInt64);
+      instruction->ReplaceWith(GetGraph()->GetConstant(instruction->GetType(), -1));
+      instruction->GetBlock()->RemoveInstruction(instruction);
+      return;
+    }
   }
 }
 
@@ -974,6 +991,28 @@
     HBasicBlock* block = instruction->GetBlock();
     instruction->ReplaceWith(GetGraph()->GetConstant(type, 0));
     block->RemoveInstruction(instruction);
+    return;
+  }
+
+  HInstruction* left = instruction->GetLeft();
+  HInstruction* right = instruction->GetRight();
+  if (left->IsNot() ^ right->IsNot()) {
+    // Replace code looking like
+    //    NOT notsrc, src
+    //    XOR dst, notsrc, src
+    // with
+    //    CONSTANT 0xFFF...FF
+    HInstruction* hnot = (left->IsNot() ? left : right);
+    HInstruction* hother = (left->IsNot() ? right : left);
+    HInstruction* src = hnot->AsNot()->GetInput();
+
+    if (src == hother) {
+      DCHECK(instruction->GetType() == DataType::Type::kInt32 ||
+             instruction->GetType() == DataType::Type::kInt64);
+      instruction->ReplaceWith(GetGraph()->GetConstant(instruction->GetType(), -1));
+      instruction->GetBlock()->RemoveInstruction(instruction);
+      return;
+    }
   }
 }
 
diff --git a/libartservice/service/java/com/android/server/art/ReasonMapping.java b/libartservice/service/java/com/android/server/art/ReasonMapping.java
index 7c64abf..2a1c81b 100644
--- a/libartservice/service/java/com/android/server/art/ReasonMapping.java
+++ b/libartservice/service/java/com/android/server/art/ReasonMapping.java
@@ -188,13 +188,14 @@
 
     /**
      * Loads the concurrency from the system property, for batch dexopt ({@link
-     * ArtManagerLocal#dexoptPackages}), or 1 if the system property is not found or cannot be
-     * parsed.
+     * ArtManagerLocal#dexoptPackages}). The default is tuned to strike a good balance between
+     * device load and dexopt coverage, depending on the situation.
      *
      * @hide
      */
     public static int getConcurrencyForReason(@NonNull @BatchDexoptReason String reason) {
         return SystemProperties.getInt("persist.device_config.runtime." + reason + "_concurrency",
-                SystemProperties.getInt("pm.dexopt." + reason + ".concurrency", 1 /* def */));
+                SystemProperties.getInt("pm.dexopt." + reason + ".concurrency",
+                        reason.equals(REASON_BG_DEXOPT) ? 4 : 1 /* def */));
     }
 }
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 54a56f2..90e9095 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -163,6 +163,13 @@
     compilation_kind = CompilationKind::kBaseline;
   }
 
+  if (method->IsPreCompiled() && !prejit) {
+    VLOG(jit) << "JIT not compiling " << method->PrettyMethod()
+              << " due to method marked pre-compile,"
+              << " and the compilation request isn't for pre-compilation.";
+    return false;
+  }
+
   // If we're asked to compile baseline, but we cannot allocate profiling infos,
   // change the compilation kind to optimized.
   if ((compilation_kind == CompilationKind::kBaseline) &&
@@ -1366,6 +1373,7 @@
   if (thread_pool_ == nullptr) {
     return;
   }
+
   // We arrive here after a baseline compiled code has reached its baseline
   // hotness threshold. If we're not only using the baseline compiler, enqueue a compilation
   // task that will compile optimize the method.
diff --git a/runtime/thread-inl.h b/runtime/thread-inl.h
index 2fcc4b0..57d606c 100644
--- a/runtime/thread-inl.h
+++ b/runtime/thread-inl.h
@@ -279,7 +279,21 @@
   }
 }
 
+inline void Thread::CheckBarrierInactive(WrappedSuspend1Barrier* suspend1_barrier) {
+  for (WrappedSuspend1Barrier* w = tlsPtr_.active_suspend1_barriers; w != nullptr; w = w->next_) {
+    CHECK_EQ(w->magic_, WrappedSuspend1Barrier::kMagic)
+        << "first = " << tlsPtr_.active_suspend1_barriers << " current = " << w
+        << " next = " << w->next_;
+    CHECK_NE(w, suspend1_barrier);
+  }
+}
+
 inline void Thread::AddSuspend1Barrier(WrappedSuspend1Barrier* suspend1_barrier) {
+  if (tlsPtr_.active_suspend1_barriers != nullptr) {
+    CHECK_EQ(tlsPtr_.active_suspend1_barriers->magic_, WrappedSuspend1Barrier::kMagic)
+        << "first = " << tlsPtr_.active_suspend1_barriers;
+  }
+  CHECK_EQ(suspend1_barrier->magic_, WrappedSuspend1Barrier::kMagic);
   suspend1_barrier->next_ = tlsPtr_.active_suspend1_barriers;
   tlsPtr_.active_suspend1_barriers = suspend1_barrier;
 }
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 0363288..2ebbe13 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1513,6 +1513,9 @@
       tlsPtr_.active_suspendall_barrier = nullptr;
     }
     for (WrappedSuspend1Barrier* w = tlsPtr_.active_suspend1_barriers; w != nullptr; w = w->next_) {
+      CHECK_EQ(w->magic_, WrappedSuspend1Barrier::kMagic)
+          << "first = " << tlsPtr_.active_suspend1_barriers << " current = " << w
+          << " next = " << w->next_;
       pass_barriers.push_back(&(w->barrier_));
     }
     tlsPtr_.active_suspend1_barriers = nullptr;
@@ -1685,9 +1688,9 @@
   // Although this is a thread suspension, the target thread only blocks while we run the
   // checkpoint, which is presumed to terminate quickly even if other threads are blocked.
   // Note: IncrementSuspendCount also expects the thread_list_lock to be held unless this == self.
+  WrappedSuspend1Barrier wrapped_barrier{};
   {
     bool is_suspended = false;
-    WrappedSuspend1Barrier wrapped_barrier{};
 
     {
       MutexLock suspend_count_mu(self, *Locks::thread_suspend_count_lock_);
@@ -1767,6 +1770,9 @@
     DCHECK_NE(GetState(), ThreadState::kRunnable);
     DCHECK_GT(GetSuspendCount(), 0);
     DecrementSuspendCount(self);
+    if (kIsDebugBuild) {
+      CheckBarrierInactive(&wrapped_barrier);
+    }
     resume_cond_->Broadcast(self);
   }
 
diff --git a/runtime/thread.h b/runtime/thread.h
index 5dcdb8b..8bcd815 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -199,8 +199,11 @@
 
 // See Thread.tlsPtr_.active_suspend1_barriers below for explanation.
 struct WrappedSuspend1Barrier {
-  WrappedSuspend1Barrier() : barrier_(1), next_(nullptr) {}
-  AtomicInteger barrier_;  // Only updated while holding thread_suspend_count_lock_ .
+  // TODO(b/23668816): At least weaken CHECKs to DCHECKs once the bug is fixed.
+  static constexpr int kMagic = 0xba8;
+  WrappedSuspend1Barrier() : magic_(kMagic), barrier_(1), next_(nullptr) {}
+  int magic_;
+  AtomicInteger barrier_;
   struct WrappedSuspend1Barrier* next_ GUARDED_BY(Locks::thread_suspend_count_lock_);
 };
 
@@ -1769,6 +1772,10 @@
 
   ALWAYS_INLINE bool HasActiveSuspendBarrier() REQUIRES(Locks::thread_suspend_count_lock_);
 
+  // CHECK that the given barrier is no longer on our list.
+  ALWAYS_INLINE void CheckBarrierInactive(WrappedSuspend1Barrier* suspend1_barrier)
+      REQUIRES(Locks::thread_suspend_count_lock_);
+
   // Registers the current thread as the jit sensitive thread. Should be called just once.
   static void SetJitSensitiveThread() {
     if (jit_sensitive_thread_ == nullptr) {
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index b841eaa..02e3f54 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -1089,6 +1089,8 @@
           if (thread->IsSuspended()) {
             // See the discussion in mutator_gc_coord.md and SuspendAllInternal for the race here.
             thread->RemoveFirstSuspend1Barrier(&wrapped_barrier);
+            // PassActiveSuspendBarriers couldn't have seen our barrier, since it also acquires
+            // 'thread_suspend_count_lock_'. `wrapped_barrier` will not be accessed.
             if (!thread->HasActiveSuspendBarrier()) {
               thread->AtomicClearFlag(ThreadFlag::kActiveSuspendBarrier);
             }
@@ -1185,7 +1187,7 @@
     }
     is_suspended = true;
   }
-  // wrapped_barrier.barrier_ has been decremented and will no longer be accessed.
+  // wrapped_barrier.barrier_ will no longer be accessed.
   VLOG(threads) << func_name << " suspended: " << *thread;
   if (ATraceEnabled()) {
     std::string name;
@@ -1194,7 +1196,11 @@
         StringPrintf("%s suspended %s for tid=%d", func_name, name.c_str(), thread->GetTid())
             .c_str());
   }
-  DCHECK(thread->IsSuspended());
+  if (kIsDebugBuild) {
+    CHECK(thread->IsSuspended());
+    MutexLock suspend_count_mu(self, *Locks::thread_suspend_count_lock_);
+    thread->CheckBarrierInactive(&wrapped_barrier);
+  }
   return true;
 }
 
diff --git a/test/442-checker-constant-folding/src/Main.java b/test/442-checker-constant-folding/src/Main.java
index 7c6d609..13c42d2 100644
--- a/test/442-checker-constant-folding/src/Main.java
+++ b/test/442-checker-constant-folding/src/Main.java
@@ -886,6 +886,91 @@
     return arg & ~arg;
   }
 
+  /// CHECK-START: int Main.OrSelfNegated(int) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Not:i\d+>>     Not [<<Arg>>]
+  /// CHECK-DAG:     <<Or:i\d+>>      Or [<<Not>>,<<Arg>>]
+  /// CHECK-DAG:                      Return [<<Or>>]
+
+  /// CHECK-START: int Main.OrSelfNegated(int) constant_folding (after)
+  /// CHECK-DAG:     <<Const:i\d+>>  IntConstant -1
+  /// CHECK-DAG:                     Return [<<Const>>]
+
+  /// CHECK-START: int Main.OrSelfNegated(int) constant_folding (after)
+  /// CHECK-NOT:                      Or
+
+  public static int OrSelfNegated(int arg) {
+    return arg | ~arg;
+  }
+
+  /// CHECK-START: int Main.XorSelfNegated(int) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Not:i\d+>>     Not [<<Arg>>]
+  /// CHECK-DAG:     <<Xor:i\d+>>     Xor [<<Not>>,<<Arg>>]
+  /// CHECK-DAG:                      Return [<<Xor>>]
+
+  /// CHECK-START: int Main.XorSelfNegated(int) constant_folding (after)
+  /// CHECK-DAG:     <<Const:i\d+>>  IntConstant -1
+  /// CHECK-DAG:                     Return [<<Const>>]
+
+  /// CHECK-START: int Main.XorSelfNegated(int) constant_folding (after)
+  /// CHECK-NOT:                      Xor
+
+  public static int XorSelfNegated(int arg) {
+    return arg ^ ~arg;
+  }
+
+  /// CHECK-START: long Main.AndSelfNegated(long) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Not:j\d+>>     Not [<<Arg>>]
+  /// CHECK-DAG:     <<And:j\d+>>     And [<<Not>>,<<Arg>>]
+  /// CHECK-DAG:                      Return [<<And>>]
+
+  /// CHECK-START: long Main.AndSelfNegated(long) constant_folding (after)
+  /// CHECK-DAG:     <<Const0:j\d+>>  LongConstant 0
+  /// CHECK-DAG:                      Return [<<Const0>>]
+
+  /// CHECK-START: long Main.AndSelfNegated(long) constant_folding (after)
+  /// CHECK-NOT:                      And
+
+  public static long AndSelfNegated(long arg) {
+    return arg & ~arg;
+  }
+
+  /// CHECK-START: long Main.OrSelfNegated(long) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Not:j\d+>>     Not [<<Arg>>]
+  /// CHECK-DAG:     <<Or:j\d+>>      Or [<<Not>>,<<Arg>>]
+  /// CHECK-DAG:                      Return [<<Or>>]
+
+  /// CHECK-START: long Main.OrSelfNegated(long) constant_folding (after)
+  /// CHECK-DAG:     <<Const:j\d+>>  LongConstant -1
+  /// CHECK-DAG:                     Return [<<Const>>]
+
+  /// CHECK-START: long Main.OrSelfNegated(long) constant_folding (after)
+  /// CHECK-NOT:                      Or
+
+  public static long OrSelfNegated(long arg) {
+    return arg | ~arg;
+  }
+
+  /// CHECK-START: long Main.XorSelfNegated(long) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Not:j\d+>>     Not [<<Arg>>]
+  /// CHECK-DAG:     <<Xor:j\d+>>     Xor [<<Not>>,<<Arg>>]
+  /// CHECK-DAG:                      Return [<<Xor>>]
+
+  /// CHECK-START: long Main.XorSelfNegated(long) constant_folding (after)
+  /// CHECK-DAG:     <<Const:j\d+>>  LongConstant -1
+  /// CHECK-DAG:                     Return [<<Const>>]
+
+  /// CHECK-START: long Main.XorSelfNegated(long) constant_folding (after)
+  /// CHECK-NOT:                      Xor
+
+  public static long XorSelfNegated(long arg) {
+    return arg ^ ~arg;
+  }
+
 
   /**
    * Exercise constant folding on logical or.
diff --git a/test/569-checker-pattern-replacement/src/Main.java b/test/569-checker-pattern-replacement/src/Main.java
index 9d0f772..9f4598d 100644
--- a/test/569-checker-pattern-replacement/src/Main.java
+++ b/test/569-checker-pattern-replacement/src/Main.java
@@ -17,19 +17,13 @@
 public class Main {
   static class ExpectedError extends Error {}
 
-  /// CHECK-START: void Main.localStaticNopAndThrow() inliner (before)
-  /// CHECK:                          InvokeStaticOrDirect method_name:Main.localStaticNop
-
-  /// CHECK-START: void Main.localStaticNopAndThrow() inliner (after)
-  /// CHECK-NOT:                      InvokeStaticOrDirect method_name:Main.localStaticNop
-
   public static void localStaticNopAndThrow() {
     // Pattern matching replaces the invoke even in a block that ends with a `throw`.
-    localStaticNop();
+    $inline$localStaticNop();
     throw new ExpectedError();
   }
 
-  public static void localStaticNop() {}
+  public static void $inline$localStaticNop() {}
 
   /// CHECK-START: void Main.staticNopNeverInline() inliner (before)
   /// CHECK:                          InvokeStaticOrDirect
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 5323fd5..31158e3 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -1570,5 +1570,17 @@
       "description": ["Test relies on profiling done by baseline compiled code. Meanwhile, it",
                       "can't use --baseline because it has a test case checking the behavior when",
                       "a method is optimized compiled."]
+    },
+    {
+      "tests": ["004-ThreadStress",
+                "050-sync-test",
+                "083-compiler-regressions",
+                "137-cfi",
+                "913-heaps",
+                "2043-reference-pauses",
+                "2239-varhandle-perf"],
+      "bug": "b/328023607",
+      "description": ["Fails on QEMU"],
+      "env_vars": {"ART_TEST_ON_VM": "true"}
     }
 ]
diff --git a/tools/run-libcore-tests.py b/tools/run-libcore-tests.py
index 72db66c..244f912 100755
--- a/tools/run-libcore-tests.py
+++ b/tools/run-libcore-tests.py
@@ -264,6 +264,8 @@
   "test.java.lang.StrictMath.HypotTests#testAgainstTranslit_shard4",
   "test.java.math.BigDecimal",
   "test.java.math.BigInteger#testConstructor",
+  "test.java.util.TestFormatter",
+  "test.java.util.Collection",
 }
 
 DISABLED_FUGU_TESTS = {