Allow initializing runtime with parsed options.
Needed by upcoming refactoring of dex2oat to allow
early writing of dex files to the oat file.
Change-Id: Ia13c26132846801522f181f51f64035d625e8416
diff --git a/runtime/base/bit_utils.h b/runtime/base/bit_utils.h
index d6a44f7..8430d68 100644
--- a/runtime/base/bit_utils.h
+++ b/runtime/base/bit_utils.h
@@ -23,6 +23,7 @@
#include "base/logging.h"
#include "base/iteration_range.h"
+#include "base/stl_util.h"
namespace art {
@@ -108,12 +109,12 @@
}
// For rounding integers.
-// NOTE: In the absence of std::omit_from_type_deduction<T> or std::identity<T>, use std::decay<T>.
+// Note: Omit the `n` from T type deduction, deduce only from the `x` argument.
template<typename T>
-static constexpr T RoundDown(T x, typename std::decay<T>::type n) WARN_UNUSED;
+static constexpr T RoundDown(T x, typename Identity<T>::type n) WARN_UNUSED;
template<typename T>
-static constexpr T RoundDown(T x, typename std::decay<T>::type n) {
+static constexpr T RoundDown(T x, typename Identity<T>::type n) {
return
DCHECK_CONSTEXPR(IsPowerOfTwo(n), , T(0))
(x & -n);
diff --git a/runtime/base/stl_util.h b/runtime/base/stl_util.h
index 324ab21..ad03c31 100644
--- a/runtime/base/stl_util.h
+++ b/runtime/base/stl_util.h
@@ -156,6 +156,23 @@
}
};
+// Use to suppress type deduction for a function argument.
+// See std::identity<> for more background:
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1856.html#20.2.2 - move/forward helpers
+//
+// e.g. "template <typename X> void bar(identity<X>::type foo);
+// bar(5); // compilation error
+// bar<int>(5); // ok
+// or "template <typename T> void foo(T* x, typename Identity<T*>::type y);
+// Base b;
+// Derived d;
+// foo(&b, &d); // Use implicit Derived* -> Base* conversion.
+// If T was deduced from both &b and &d, there would be a mismatch, i.e. deduction failure.
+template <typename T>
+struct Identity {
+ using type = T;
+};
+
} // namespace art
#endif // ART_RUNTIME_BASE_STL_UTIL_H_
diff --git a/runtime/base/variant_map.h b/runtime/base/variant_map.h
index 82e5d2e..531cb37 100644
--- a/runtime/base/variant_map.h
+++ b/runtime/base/variant_map.h
@@ -19,8 +19,11 @@
#include <memory.h>
#include <map>
+#include <type_traits>
#include <utility>
+#include "base/stl_util.h"
+
namespace art {
//
@@ -268,8 +271,9 @@
}
// Set a value for a given key, overwriting the previous value if any.
+ // Note: Omit the `value` from TValue type deduction, deduce only from the `key` argument.
template <typename TValue>
- void Set(const TKey<TValue>& key, const TValue& value) {
+ void Set(const TKey<TValue>& key, const typename Identity<TValue>::type& value) {
// Clone the value first, to protect against &value == GetValuePtr(key).
auto* new_value = new TValue(value);
@@ -279,8 +283,9 @@
// Set a value for a given key, only if there was no previous value before.
// Returns true if the value was set, false if a previous value existed.
+ // Note: Omit the `value` from TValue type deduction, deduce only from the `key` argument.
template <typename TValue>
- bool SetIfMissing(const TKey<TValue>& key, const TValue& value) {
+ bool SetIfMissing(const TKey<TValue>& key, const typename Identity<TValue>::type& value) {
TValue* ptr = Get(key);
if (ptr == nullptr) {
Set(key, value);
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index 7f4519c..5b10610 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -41,15 +41,13 @@
// Runtime::Abort
}
-ParsedOptions* ParsedOptions::Create(const RuntimeOptions& options, bool ignore_unrecognized,
- RuntimeArgumentMap* runtime_options) {
+bool ParsedOptions::Parse(const RuntimeOptions& options,
+ bool ignore_unrecognized,
+ RuntimeArgumentMap* runtime_options) {
CHECK(runtime_options != nullptr);
- std::unique_ptr<ParsedOptions> parsed(new ParsedOptions());
- if (parsed->Parse(options, ignore_unrecognized, runtime_options)) {
- return parsed.release();
- }
- return nullptr;
+ ParsedOptions parser;
+ return parser.DoParse(options, ignore_unrecognized, runtime_options);
}
using RuntimeParser = CmdlineParser<RuntimeArgumentMap, RuntimeArgumentMap::Key>;
@@ -407,8 +405,9 @@
// gLogVerbosity.verifier = true; // TODO: don't check this in!
}
-bool ParsedOptions::Parse(const RuntimeOptions& options, bool ignore_unrecognized,
- RuntimeArgumentMap* runtime_options) {
+bool ParsedOptions::DoParse(const RuntimeOptions& options,
+ bool ignore_unrecognized,
+ RuntimeArgumentMap* runtime_options) {
for (size_t i = 0; i < options.size(); ++i) {
if (true && options[0].first == "-Xzygote") {
LOG(INFO) << "option[" << i << "]=" << options[i].first;
diff --git a/runtime/parsed_options.h b/runtime/parsed_options.h
index 529dd5c..5974fb6 100644
--- a/runtime/parsed_options.h
+++ b/runtime/parsed_options.h
@@ -50,8 +50,9 @@
static std::unique_ptr<RuntimeParser> MakeParser(bool ignore_unrecognized);
// returns true if parsing succeeds, and stores the resulting options into runtime_options
- static ParsedOptions* Create(const RuntimeOptions& options, bool ignore_unrecognized,
- RuntimeArgumentMap* runtime_options);
+ static bool Parse(const RuntimeOptions& options,
+ bool ignore_unrecognized,
+ RuntimeArgumentMap* runtime_options);
bool (*hook_is_sensitive_thread_)();
jint (*hook_vfprintf_)(FILE* stream, const char* format, va_list ap);
@@ -72,8 +73,9 @@
void Exit(int status);
void Abort();
- bool Parse(const RuntimeOptions& options, bool ignore_unrecognized,
- RuntimeArgumentMap* runtime_options);
+ bool DoParse(const RuntimeOptions& options,
+ bool ignore_unrecognized,
+ RuntimeArgumentMap* runtime_options);
};
} // namespace art
diff --git a/runtime/parsed_options_test.cc b/runtime/parsed_options_test.cc
index a8575de..fad00c7 100644
--- a/runtime/parsed_options_test.cc
+++ b/runtime/parsed_options_test.cc
@@ -60,8 +60,8 @@
options.push_back(std::make_pair("exit", test_exit));
RuntimeArgumentMap map;
- std::unique_ptr<ParsedOptions> parsed(ParsedOptions::Create(options, false, &map));
- ASSERT_TRUE(parsed.get() != nullptr);
+ bool parsed = ParsedOptions::Parse(options, false, &map);
+ ASSERT_TRUE(parsed);
ASSERT_NE(0u, map.Size());
using Opt = RuntimeArgumentMap;
@@ -102,8 +102,8 @@
options.push_back(std::make_pair("-Xgc:MC", nullptr));
RuntimeArgumentMap map;
- std::unique_ptr<ParsedOptions> parsed(ParsedOptions::Create(options, false, &map));
- ASSERT_TRUE(parsed.get() != nullptr);
+ bool parsed = ParsedOptions::Parse(options, false, &map);
+ ASSERT_TRUE(parsed);
ASSERT_NE(0u, map.Size());
using Opt = RuntimeArgumentMap;
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index fe8eb0d..dedc110 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -434,14 +434,25 @@
GetLambdaBoxTable()->SweepWeakBoxedLambdas(visitor);
}
-bool Runtime::Create(const RuntimeOptions& options, bool ignore_unrecognized) {
+bool Runtime::ParseOptions(const RuntimeOptions& raw_options,
+ bool ignore_unrecognized,
+ RuntimeArgumentMap* runtime_options) {
+ InitLogging(/* argv */ nullptr); // Calls Locks::Init() as a side effect.
+ bool parsed = ParsedOptions::Parse(raw_options, ignore_unrecognized, runtime_options);
+ if (!parsed) {
+ LOG(ERROR) << "Failed to parse options";
+ return false;
+ }
+ return true;
+}
+
+bool Runtime::Create(RuntimeArgumentMap&& runtime_options) {
// TODO: acquire a static mutex on Runtime to avoid racing.
if (Runtime::instance_ != nullptr) {
return false;
}
- InitLogging(nullptr); // Calls Locks::Init() as a side effect.
instance_ = new Runtime;
- if (!instance_->Init(options, ignore_unrecognized)) {
+ if (!instance_->Init(std::move(runtime_options))) {
// TODO: Currently deleting the instance will abort the runtime on destruction. Now This will
// leak memory, instead. Fix the destructor. b/19100793.
// delete instance_;
@@ -451,6 +462,12 @@
return true;
}
+bool Runtime::Create(const RuntimeOptions& raw_options, bool ignore_unrecognized) {
+ RuntimeArgumentMap runtime_options;
+ return ParseOptions(raw_options, ignore_unrecognized, &runtime_options) &&
+ Create(std::move(runtime_options));
+}
+
static jobject CreateSystemClassLoader(Runtime* runtime) {
if (runtime->IsAotCompiler() && !runtime->GetCompilerCallbacks()->IsBootImage()) {
return nullptr;
@@ -829,21 +846,14 @@
sentinel_ = GcRoot<mirror::Object>(sentinel);
}
-bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) {
+bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
+ RuntimeArgumentMap runtime_options(std::move(runtime_options_in));
ATRACE_BEGIN("Runtime::Init");
CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);
MemMap::Init();
using Opt = RuntimeArgumentMap;
- RuntimeArgumentMap runtime_options;
- std::unique_ptr<ParsedOptions> parsed_options(
- ParsedOptions::Create(raw_options, ignore_unrecognized, &runtime_options));
- if (parsed_options.get() == nullptr) {
- LOG(ERROR) << "Failed to parse options";
- ATRACE_END();
- return false;
- }
VLOG(startup) << "Runtime::Init -verbose:startup enabled";
QuasiAtomic::Startup();
diff --git a/runtime/runtime.h b/runtime/runtime.h
index bd36414..93d8fcf 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -84,6 +84,7 @@
class MonitorPool;
class NullPointerHandler;
class OatFileManager;
+struct RuntimeArgumentMap;
class SignalCatcher;
class StackOverflowHandler;
class SuspensionHandler;
@@ -112,8 +113,17 @@
class Runtime {
public:
+ // Parse raw runtime options.
+ static bool ParseOptions(const RuntimeOptions& raw_options,
+ bool ignore_unrecognized,
+ RuntimeArgumentMap* runtime_options);
+
// Creates and initializes a new runtime.
- static bool Create(const RuntimeOptions& options, bool ignore_unrecognized)
+ static bool Create(RuntimeArgumentMap&& runtime_options)
+ SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_);
+
+ // Creates and initializes a new runtime.
+ static bool Create(const RuntimeOptions& raw_options, bool ignore_unrecognized)
SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_);
// IsAotCompiler for compilers that don't have a running runtime. Only dex2oat currently.
@@ -599,7 +609,7 @@
void BlockSignals();
- bool Init(const RuntimeOptions& options, bool ignore_unrecognized)
+ bool Init(RuntimeArgumentMap&& runtime_options)
SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_);
void InitNativeMethods() REQUIRES(!Locks::mutator_lock_);
void InitThreadGroups(Thread* self);
diff --git a/runtime/runtime_options.h b/runtime/runtime_options.h
index 88ac00a..4610f6f 100644
--- a/runtime/runtime_options.h
+++ b/runtime/runtime_options.h
@@ -17,14 +17,13 @@
#ifndef ART_RUNTIME_RUNTIME_OPTIONS_H_
#define ART_RUNTIME_RUNTIME_OPTIONS_H_
-#include "runtime/base/variant_map.h"
-#include "cmdline/cmdline_types.h" // TODO: don't need to include this file here
+#include "base/variant_map.h"
+#include "cmdline_types.h" // TODO: don't need to include this file here
// Map keys
#include <vector>
#include <string>
-#include "runtime/base/logging.h"
-#include "cmdline/unit.h"
+#include "base/logging.h"
#include "jdwp/jdwp.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"