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 = {