diff options
author | 2017-06-21 22:45:43 +0000 | |
---|---|---|
committer | 2017-06-21 22:45:45 +0000 | |
commit | 7888b59b4542e15dd061047e4cb34f795cc2354c (patch) | |
tree | 7f35e0e88850d91fd108ea3816078d50c9a4706a | |
parent | 7506c70e2e68c2a012b581601c4fe3f3c1695e56 (diff) | |
parent | 1c5b42f00933b8f28b447f039fb93a7d9a9db06f (diff) |
Merge "ART: Add support for runtime debug checks"
-rw-r--r-- | runtime/Android.bp | 1 | ||||
-rw-r--r-- | runtime/base/logging.cc | 49 | ||||
-rw-r--r-- | runtime/base/logging.h | 37 | ||||
-rw-r--r-- | runtime/base/logging_test.cc | 59 | ||||
-rw-r--r-- | runtime/common_runtime_test.cc | 1 | ||||
-rw-r--r-- | runtime/parsed_options.cc | 8 | ||||
-rw-r--r-- | runtime/runtime_options.def | 2 | ||||
-rwxr-xr-x | test/etc/run-test-jar | 3 | ||||
-rw-r--r-- | tools/art | 4 | ||||
-rwxr-xr-x | tools/run-jdwp-tests.sh | 2 | ||||
-rwxr-xr-x | tools/run-libcore-tests.sh | 2 |
11 files changed, 165 insertions, 3 deletions
diff --git a/runtime/Android.bp b/runtime/Android.bp index 20f95c0c74..9b110ebc7f 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -528,6 +528,7 @@ art_cc_test { "base/hash_set_test.cc", "base/hex_dump_test.cc", "base/histogram_test.cc", + "base/logging_test.cc", "base/mutex_test.cc", "base/safe_copy_test.cc", "base/scoped_flock_test.cc", diff --git a/runtime/base/logging.cc b/runtime/base/logging.cc index adfd7d323c..2be9067e64 100644 --- a/runtime/base/logging.cc +++ b/runtime/base/logging.cc @@ -34,6 +34,55 @@ namespace art { +// We test here that the runtime-debug-checks are actually a no-op constexpr false in release +// builds, as we can't check that in gtests (which are always debug). + +#ifdef NDEBUG +namespace { +DECLARE_RUNTIME_DEBUG_FLAG(kTestForConstexpr); +static_assert(!kTestForConstexpr, "Issue with DECLARE_RUNTIME_DEBUG_FLAG in NDEBUG."); +} +#endif + +// Implementation of runtime debug flags. This should be compile-time optimized away in release +// builds. +namespace { +bool gSlowEnabled = false; // Default for slow flags is "off." + +// Use a function with a static to ensure our vector storage doesn't have initialization order +// issues. +std::vector<bool*>& GetFlagPtrs() { + static std::vector<bool*> g_flag_ptrs; + return g_flag_ptrs; +} + +bool RegisterRuntimeDebugFlagImpl(bool* flag_ptr) { + GetFlagPtrs().push_back(flag_ptr); + return gSlowEnabled; +} + +void SetRuntimeDebugFlagsEnabledImpl(bool enabled) { + gSlowEnabled = enabled; + for (bool* flag_ptr : GetFlagPtrs()) { + *flag_ptr = enabled; + } +} + +} // namespace + +bool RegisterRuntimeDebugFlag(bool* flag_ptr) { + if (kIsDebugBuild) { + return RegisterRuntimeDebugFlagImpl(flag_ptr); + } + return false; +} + +void SetRuntimeDebugFlagsEnabled(bool enabled) { + if (kIsDebugBuild) { + SetRuntimeDebugFlagsEnabledImpl(enabled); + } +} + LogVerbosity gLogVerbosity; unsigned int gAborting = 0; diff --git a/runtime/base/logging.h b/runtime/base/logging.h index 7a9184e07e..d8954e59d0 100644 --- a/runtime/base/logging.h +++ b/runtime/base/logging.h @@ -62,6 +62,43 @@ struct LogVerbosity { // Global log verbosity setting, initialized by InitLogging. extern LogVerbosity gLogVerbosity; +// Runtime debug flags are flags that have a runtime component, that is, their value can be changed. +// This is meant to implement fast vs slow debug builds, in that certain debug flags can be turned +// on and off. To that effect, expose two macros to help implement and globally drive these flags: +// +// In the header, declare a (class) flag like this: +// +// class C { +// DECLARE_RUNTIME_DEBUG_FLAG(kFlag); +// }; +// +// This will declare a flag kFlag that is a constexpr false in release builds, and a static field +// in debug builds. Usage is than uniform as C::kFlag. +// +// In the cc file, define the flag like this: +// +// DEFINE_RUNTIME_DEBUG_FLAG(C, kFlag); +// +// This will define the static storage, as necessary, and register the flag with the runtime +// infrastructure to toggle the value. + +#ifdef NDEBUG +#define DECLARE_RUNTIME_DEBUG_FLAG(x) \ + static constexpr bool x = false; +// Note: the static_assert in the following only works for public flags. Fix this when we cross +// the line at some point. +#define DEFINE_RUNTIME_DEBUG_FLAG(C, x) \ + static_assert(!C::x, "Unexpected enabled flag in release build"); +#else +#define DECLARE_RUNTIME_DEBUG_FLAG(x) \ + static bool x; +#define DEFINE_RUNTIME_DEBUG_FLAG(C, x) \ + bool C::x = RegisterRuntimeDebugFlag(&C::x); +#endif // NDEBUG + +bool RegisterRuntimeDebugFlag(bool* runtime_debug_flag); +void SetRuntimeDebugFlagsEnabled(bool enabled); + // 0 if not abort, non-zero if an abort is in progress. Used on fatal exit to prevents recursive // aborts. Global declaration allows us to disable some error checking to ensure fatal shutdown // makes forward progress. diff --git a/runtime/base/logging_test.cc b/runtime/base/logging_test.cc new file mode 100644 index 0000000000..d380b9eccc --- /dev/null +++ b/runtime/base/logging_test.cc @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "logging.h" + +#include <type_traits> + +#include "android-base/logging.h" +#include "base/bit_utils.h" +#include "base/macros.h" +#include "common_runtime_test.h" + +namespace art { + +static void SimpleAborter(const char* msg) { + LOG(FATAL_WITHOUT_ABORT) << msg; + _exit(1); +} + +class LoggingTest : public CommonRuntimeTest { + protected: + void PostRuntimeCreate() OVERRIDE { + // In our abort tests we really don't want the runtime to create a real dump. + android::base::SetAborter(SimpleAborter); + } +}; + +#ifdef NDEBUG +#error Unexpected NDEBUG +#endif + +class TestClass { + public: + DECLARE_RUNTIME_DEBUG_FLAG(kFlag); +}; +DEFINE_RUNTIME_DEBUG_FLAG(TestClass, kFlag); + +TEST_F(LoggingTest, DECL_DEF) { + SetRuntimeDebugFlagsEnabled(true); + EXPECT_TRUE(TestClass::kFlag); + + SetRuntimeDebugFlagsEnabled(false); + EXPECT_FALSE(TestClass::kFlag); +} + +} // namespace art diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc index f9259944b4..5a4a26a390 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -404,6 +404,7 @@ void CommonRuntimeTestImpl::SetUp() { options.push_back(std::make_pair("-Xcheck:jni", nullptr)); options.push_back(std::make_pair(min_heap_string, nullptr)); options.push_back(std::make_pair(max_heap_string, nullptr)); + options.push_back(std::make_pair("-XX:SlowDebug=true", nullptr)); callbacks_.reset(new NoopCompilerCallbacks()); diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index abb6f8c018..b1eb506209 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -18,6 +18,7 @@ #include <sstream> +#include "base/logging.h" #include "base/stringpiece.h" #include "debugger.h" #include "gc/heap.h" @@ -306,6 +307,10 @@ std::unique_ptr<RuntimeParser> ParsedOptions::MakeParser(bool ignore_unrecognize .Define("-XX:ThreadSuspendTimeout=_") // in ms .WithType<MillisecondsToNanoseconds>() // store as ns .IntoKey(M::ThreadSuspendTimeout) + .Define("-XX:SlowDebug=_") + .WithType<bool>() + .WithValueMap({{"false", false}, {"true", true}}) + .IntoKey(M::SlowDebug) .Ignore({ "-ea", "-da", "-enableassertions", "-disableassertions", "--runtime-arg", "-esa", "-dsa", "-enablesystemassertions", "-disablesystemassertions", "-Xrs", "-Xint:_", @@ -517,6 +522,8 @@ bool ParsedOptions::DoParse(const RuntimeOptions& options, MaybeOverrideVerbosity(); + SetRuntimeDebugFlagsEnabled(args.Get(M::SlowDebug)); + // -Xprofile: Trace::SetDefaultClockSource(args.GetOrDefault(M::ProfileClock)); @@ -704,6 +711,7 @@ void ParsedOptions::Usage(const char* fmt, ...) { UsageMessage(stream, " -XX:LargeObjectSpace={disabled,map,freelist}\n"); UsageMessage(stream, " -XX:LargeObjectThreshold=N\n"); UsageMessage(stream, " -XX:DumpNativeStackOnSigQuit=booleanvalue\n"); + UsageMessage(stream, " -XX:SlowDebug={false,true}\n"); UsageMessage(stream, " -Xmethod-trace\n"); UsageMessage(stream, " -Xmethod-trace-file:filename"); UsageMessage(stream, " -Xmethod-trace-file-size:integervalue\n"); diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def index cfc681f23f..3d23e20e1e 100644 --- a/runtime/runtime_options.def +++ b/runtime/runtime_options.def @@ -142,4 +142,6 @@ RUNTIME_OPTIONS_KEY (void (*)(int32_t status), \ // Runtime::Abort. RUNTIME_OPTIONS_KEY (void (*)(), HookAbort, nullptr) +RUNTIME_OPTIONS_KEY (bool, SlowDebug, false) + #undef RUNTIME_OPTIONS_KEY diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar index c44fb97c50..d24edccd8b 100755 --- a/test/etc/run-test-jar +++ b/test/etc/run-test-jar @@ -79,6 +79,9 @@ SET_STACK_TRACE_DUMP_DIR="n" # build step (e.g. dex2oat) were finished writing. SYNC_BEFORE_RUN="n" +# When running a debug build, we want to run with all checks. +ANDROID_FLAGS="${ANDROID_FLAGS} -XX:SlowDebug=true" + while true; do if [ "x$1" = "x--quiet" ]; then QUIET="y" @@ -24,6 +24,7 @@ LAUNCH_WRAPPER= LIBART=libart.so JIT_PROFILE="no" VERBOSE="no" +EXTRA_OPTIONS="" # Follow all sym links to get the program name. if [ z"$BASH_SOURCE" != z ]; then @@ -147,6 +148,8 @@ while [[ "$1" = "-"* ]]; do ;& # Fallthrough --debug) LIBART="libartd.so" + # Expect that debug mode wants all checks. + EXTRA_OPTIONS="${EXTRA_OPTIONS} -XX:SlowDebug=true" ;; --gdb) LIBART="libartd.so" @@ -203,7 +206,6 @@ fi LIBDIR="$(find_libdir $ART_BINARY_PATH)" LD_LIBRARY_PATH=$ANDROID_ROOT/$LIBDIR -EXTRA_OPTIONS="" # If ANDROID_DATA is the system ANDROID_DATA or is not set, use our own, # and ensure we delete it at the end. diff --git a/tools/run-jdwp-tests.sh b/tools/run-jdwp-tests.sh index f7427676eb..225fb394d1 100755 --- a/tools/run-jdwp-tests.sh +++ b/tools/run-jdwp-tests.sh @@ -154,7 +154,7 @@ debuggee_args="$debuggee_args -Xusejit:$use_jit" if [[ $debug == "yes" ]]; then art="$art -d" art_debugee="$art_debugee -d" - vm_args="$vm_args --vm-arg -XXlib:libartd.so" + vm_args="$vm_args --vm-arg -XXlib:libartd.so --vm-arg -XX:SlowDebug=true" fi if [[ $verbose == "yes" ]]; then # Enable JDWP logs in the debuggee. diff --git a/tools/run-libcore-tests.sh b/tools/run-libcore-tests.sh index 8b3df3a28c..6dcc23a9fc 100755 --- a/tools/run-libcore-tests.sh +++ b/tools/run-libcore-tests.sh @@ -127,7 +127,7 @@ while true; do elif [[ "$1" == "--debug" ]]; then # Remove the --debug from the arguments. vogar_args=${vogar_args/$1} - vogar_args="$vogar_args --vm-arg -XXlib:libartd.so" + vogar_args="$vogar_args --vm-arg -XXlib:libartd.so --vm-arg -XX:SlowDebug=true" debug=true shift elif [[ "$1" == "-Xgc:gcstress" ]]; then |