summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/dex/mir_graph.h12
-rw-r--r--compiler/dex/mir_optimization.cc3
-rw-r--r--compiler/dex/mir_optimization_test.cc11
-rw-r--r--runtime/parsed_options.cc3
-rw-r--r--runtime/runtime.cc2
-rw-r--r--runtime/runtime.h8
-rw-r--r--runtime/runtime_options.def1
-rw-r--r--runtime/signal_catcher.cc7
-rw-r--r--runtime/utils.cc8
-rw-r--r--test/109-suspend-check/src/Main.java17
10 files changed, 65 insertions, 7 deletions
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index dbe9062..23b7c42 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -173,7 +173,17 @@ enum OatMethodAttributes {
typedef uint16_t BasicBlockId;
static const BasicBlockId NullBasicBlockId = 0;
-static constexpr bool kLeafOptimization = false;
+
+// Leaf optimization is basically the removal of suspend checks from leaf methods.
+// This is incompatible with SuspendCheckElimination (SCE) which eliminates suspend
+// checks from loops that call any non-intrinsic method, since a loop that calls
+// only a leaf method would end up without any suspend checks at all. So turning
+// this on automatically disables the SCE in MIRGraph::EliminateSuspendChecksGate().
+//
+// Since the Optimizing compiler is actually applying the same optimization, Quick
+// must not run SCE anyway, so we enable this optimization as a way to disable SCE
+// while keeping a consistent behavior across the backends, b/22657404.
+static constexpr bool kLeafOptimization = true;
/*
* In general, vreg/sreg describe Dalvik registers that originated with dx. However,
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 5bb0ce3..80b7ac1 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -1724,7 +1724,8 @@ void MIRGraph::StringChange() {
bool MIRGraph::EliminateSuspendChecksGate() {
- if ((cu_->disable_opt & (1 << kSuspendCheckElimination)) != 0 || // Disabled.
+ if (kLeafOptimization || // Incompatible (could create loops without suspend checks).
+ (cu_->disable_opt & (1 << kSuspendCheckElimination)) != 0 || // Disabled.
GetMaxNestedLoops() == 0u || // Nothing to do.
GetMaxNestedLoops() >= 32u || // Only 32 bits in suspend_checks_in_loops_[.].
// Exclude 32 as well to keep bit shifts well-defined.
diff --git a/compiler/dex/mir_optimization_test.cc b/compiler/dex/mir_optimization_test.cc
index 10a4337..47123ba 100644
--- a/compiler/dex/mir_optimization_test.cc
+++ b/compiler/dex/mir_optimization_test.cc
@@ -467,8 +467,17 @@ class SuspendCheckEliminationTest : public MirOptimizationTest {
cu_.mir_graph->ComputeDominators();
cu_.mir_graph->ComputeTopologicalSortOrder();
cu_.mir_graph->SSATransformationEnd();
+
bool gate_result = cu_.mir_graph->EliminateSuspendChecksGate();
- ASSERT_TRUE(gate_result);
+ ASSERT_NE(gate_result, kLeafOptimization);
+ if (kLeafOptimization) {
+ // Even with kLeafOptimization on and Gate() refusing to allow SCE, we want
+ // to run the SCE test to avoid bitrot, so we need to initialize explicitly.
+ cu_.mir_graph->suspend_checks_in_loops_ =
+ cu_.mir_graph->arena_->AllocArray<uint32_t>(cu_.mir_graph->GetNumBlocks(),
+ kArenaAllocMisc);
+ }
+
TopologicalSortIterator iterator(cu_.mir_graph.get());
bool change = false;
for (BasicBlock* bb = iterator.Next(change); bb != nullptr; bb = iterator.Next(change)) {
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index 0bc834f..a7b4575 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -260,6 +260,9 @@ std::unique_ptr<RuntimeParser> ParsedOptions::MakeParser(bool ignore_unrecognize
.Define("--cpu-abilist=_")
.WithType<std::string>()
.IntoKey(M::CpuAbiList)
+ .Define("-Xfingerprint:_")
+ .WithType<std::string>()
+ .IntoKey(M::Fingerprint)
.Ignore({
"-ea", "-da", "-enableassertions", "-disableassertions", "--runtime-arg", "-esa",
"-dsa", "-enablesystemassertions", "-disablesystemassertions", "-Xrs", "-Xint:_",
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 1453e9f..93f66ec 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -838,6 +838,8 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized)
Split(runtime_options.GetOrDefault(Opt::CpuAbiList), ',', &cpu_abilist_);
+ fingerprint_ = runtime_options.ReleaseOrDefault(Opt::Fingerprint);
+
if (runtime_options.GetOrDefault(Opt::Interpret)) {
GetInstrumentation()->ForceInterpretOnly();
}
diff --git a/runtime/runtime.h b/runtime/runtime.h
index e569333..72ae9a1 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -548,6 +548,11 @@ class Runtime {
return method_ref_string_init_reg_map_;
}
+ // Returns the build fingerprint, if set. Otherwise an empty string is returned.
+ std::string GetFingerprint() {
+ return fingerprint_;
+ }
+
private:
static void InitPlatformSignalHandlers();
@@ -729,6 +734,9 @@ class Runtime {
MethodRefToStringInitRegMap method_ref_string_init_reg_map_;
+ // Contains the build fingerprint, if given as a parameter.
+ std::string fingerprint_;
+
DISALLOW_COPY_AND_ASSIGN(Runtime);
};
std::ostream& operator<<(std::ostream& os, const Runtime::CalleeSaveType& rhs);
diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def
index 8b504c1..8154236 100644
--- a/runtime/runtime_options.def
+++ b/runtime/runtime_options.def
@@ -122,5 +122,6 @@ RUNTIME_OPTIONS_KEY (void (*)(int32_t status), \
RUNTIME_OPTIONS_KEY (void (*)(), HookAbort, nullptr)
RUNTIME_OPTIONS_KEY (unsigned int, ZygoteMaxFailedBoots, 10)
RUNTIME_OPTIONS_KEY (Unit, NoDexFileFallback)
+RUNTIME_OPTIONS_KEY (std::string, Fingerprint)
#undef RUNTIME_OPTIONS_KEY
diff --git a/runtime/signal_catcher.cc b/runtime/signal_catcher.cc
index 9f8c55c..6cb7950 100644
--- a/runtime/signal_catcher.cc
+++ b/runtime/signal_catcher.cc
@@ -133,8 +133,11 @@ void SignalCatcher::HandleSigQuit() {
DumpCmdLine(os);
- // Note: The string "ABI:" is chosen to match the format used by debuggerd.
- os << "ABI: " << GetInstructionSetString(runtime->GetInstructionSet()) << "\n";
+ // Note: The strings "Build fingerprint:" and "ABI:" are chosen to match the format used by
+ // debuggerd. This allows, for example, the stack tool to work.
+ std::string fingerprint = runtime->GetFingerprint();
+ os << "Build fingerprint: '" << (fingerprint.empty() ? "unknown" : fingerprint) << "'\n";
+ os << "ABI: '" << GetInstructionSetString(runtime->GetInstructionSet()) << "'\n";
os << "Build type: " << (kIsDebugBuild ? "debug" : "optimized") << "\n";
diff --git a/runtime/utils.cc b/runtime/utils.cc
index 4923342..80938ce 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -1130,9 +1130,13 @@ void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix,
os << prefix << StringPrintf("#%02zu pc ", it->num);
bool try_addr2line = false;
if (!BacktraceMap::IsValid(it->map)) {
- os << StringPrintf("%08" PRIxPTR " ???", it->pc);
+ os << StringPrintf(Is64BitInstructionSet(kRuntimeISA) ? "%016" PRIxPTR " ???"
+ : "%08" PRIxPTR " ???",
+ it->pc);
} else {
- os << StringPrintf("%08" PRIxPTR " ", BacktraceMap::GetRelativePc(it->map, it->pc));
+ os << StringPrintf(Is64BitInstructionSet(kRuntimeISA) ? "%016" PRIxPTR " "
+ : "%08" PRIxPTR " ",
+ BacktraceMap::GetRelativePc(it->map, it->pc));
os << it->map.name;
os << " (";
if (!it->func_name.empty()) {
diff --git a/test/109-suspend-check/src/Main.java b/test/109-suspend-check/src/Main.java
index 8046d75..3c3353b 100644
--- a/test/109-suspend-check/src/Main.java
+++ b/test/109-suspend-check/src/Main.java
@@ -32,6 +32,8 @@ public class Main {
new InfiniteWhileLoopWithSpecialPutOrNop(new SpecialMethods2()),
new InfiniteWhileLoopWithSpecialConstOrIGet(new SpecialMethods1()),
new InfiniteWhileLoopWithSpecialConstOrIGet(new SpecialMethods2()),
+ new InfiniteWhileLoopWithSpecialConstOrIGetInTryCatch(new SpecialMethods1()),
+ new InfiniteWhileLoopWithSpecialConstOrIGetInTryCatch(new SpecialMethods2()),
};
doWhileLoopWithLong.start();
for (SimpleLoopThread loop : simpleLoops) {
@@ -135,6 +137,21 @@ class InfiniteWhileLoopWithSpecialConstOrIGet extends SimpleLoopThread {
}
}
+class InfiniteWhileLoopWithSpecialConstOrIGetInTryCatch extends SimpleLoopThread {
+ private SpecialMethodInterface smi;
+ public InfiniteWhileLoopWithSpecialConstOrIGetInTryCatch(SpecialMethodInterface smi) {
+ this.smi = smi;
+ }
+ public void run() {
+ try {
+ long i = 0L;
+ while (keepGoing) {
+ i += smi.ConstOrIGet();
+ }
+ } catch (Throwable ignored) { }
+ }
+}
+
class InfiniteWhileLoopWithIntrinsic extends SimpleLoopThread {
private String[] strings = { "a", "b", "c", "d" };
private int sum = 0;