summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Treehugger Robot <treehugger-gerrit@google.com> 2017-06-21 22:45:43 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2017-06-21 22:45:45 +0000
commit7888b59b4542e15dd061047e4cb34f795cc2354c (patch)
tree7f35e0e88850d91fd108ea3816078d50c9a4706a
parent7506c70e2e68c2a012b581601c4fe3f3c1695e56 (diff)
parent1c5b42f00933b8f28b447f039fb93a7d9a9db06f (diff)
Merge "ART: Add support for runtime debug checks"
-rw-r--r--runtime/Android.bp1
-rw-r--r--runtime/base/logging.cc49
-rw-r--r--runtime/base/logging.h37
-rw-r--r--runtime/base/logging_test.cc59
-rw-r--r--runtime/common_runtime_test.cc1
-rw-r--r--runtime/parsed_options.cc8
-rw-r--r--runtime/runtime_options.def2
-rwxr-xr-xtest/etc/run-test-jar3
-rw-r--r--tools/art4
-rwxr-xr-xtools/run-jdwp-tests.sh2
-rwxr-xr-xtools/run-libcore-tests.sh2
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"
diff --git a/tools/art b/tools/art
index 0bc08f0fce..2e5df91bfd 100644
--- a/tools/art
+++ b/tools/art
@@ -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