diff options
-rw-r--r-- | compiler/dex/mir_graph.h | 12 | ||||
-rw-r--r-- | compiler/dex/mir_optimization.cc | 3 | ||||
-rw-r--r-- | compiler/dex/mir_optimization_test.cc | 11 | ||||
-rw-r--r-- | runtime/parsed_options.cc | 3 | ||||
-rw-r--r-- | runtime/runtime.cc | 2 | ||||
-rw-r--r-- | runtime/runtime.h | 8 | ||||
-rw-r--r-- | runtime/runtime_options.def | 1 | ||||
-rw-r--r-- | runtime/signal_catcher.cc | 7 | ||||
-rw-r--r-- | runtime/utils.cc | 8 | ||||
-rw-r--r-- | test/109-suspend-check/src/Main.java | 17 |
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; |