using RuntimeParser = CmdlineParser<RuntimeArgumentMap, RuntimeArgumentMap::Key>; using HiddenapiPolicyValueMap =
std::initializer_list<std::pair<constchar*, hiddenapi::EnforcementPolicy>>;
// Yes, the stack frame is huge. But we get called super early on (and just once) // to pass the command line arguments, so we'll probably be ok. // Ideas to avoid suppressing this diagnostic are welcome! #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wframe-larger-than="
std::unique_ptr<RuntimeParser> ParsedOptions::MakeParser(bool ignore_unrecognized) { using M = RuntimeArgumentMap;
// Remove all the special options that have something in the void* part of the option. // If runtime_options is not null, put the options in there. // As a side-effect, populate the hooks from options. bool ParsedOptions::ProcessSpecialOptions(const RuntimeOptions& options,
RuntimeArgumentMap* runtime_options,
std::vector<std::string>* out_options) { using M = RuntimeArgumentMap;
// TODO: Move the below loop into JNI // Handle special options that set up hooks for (size_t i = 0; i < options.size(); ++i) { const std::string option(options[i].first); // TODO: support -Djava.class.path if (option == "bootclasspath") { auto boot_class_path = static_cast<std::vector<std::unique_ptr<const DexFile>>*>( const_cast<void*>(options[i].second));
if (runtime_options != nullptr) {
runtime_options->Set(M::HookIsSensitiveThread, hook_is_sensitive_thread);
}
} elseif (option == "vfprintf") { constvoid* hook = options[i].second; if (hook == nullptr) {
Usage("vfprintf argument was nullptr"); returnfalse;
} int (*hook_vfprintf)(FILE *, constchar*, va_list) = reinterpret_cast<int (*)(FILE *, constchar*, va_list)>(const_cast<void*>(hook));
if (runtime_options != nullptr) {
runtime_options->Set(M::HookVfprintf, hook_vfprintf);
}
hook_vfprintf_ = hook_vfprintf;
} elseif (option == "exit") { constvoid* hook = options[i].second; if (hook == nullptr) {
Usage("exit argument was nullptr"); returnfalse;
} void(*hook_exit)(jint) = reinterpret_cast<void(*)(jint)>(const_cast<void*>(hook)); if (runtime_options != nullptr) {
runtime_options->Set(M::HookExit, hook_exit);
}
hook_exit_ = hook_exit;
} elseif (option == "abort") { constvoid* hook = options[i].second; if (hook == nullptr) {
Usage("abort was nullptr\n"); returnfalse;
} void(*hook_abort)() = reinterpret_cast<void(*)()>(const_cast<void*>(hook)); if (runtime_options != nullptr) {
runtime_options->Set(M::HookAbort, hook_abort);
}
hook_abort_ = hook_abort;
} else { // It is a regular option, that doesn't have a known 'second' value. // Push it on to the regular options which will be parsed by our parser. if (out_options != nullptr) {
out_options->push_back(option);
}
}
}
returntrue;
}
// Intended for local changes only. staticvoid MaybeOverrideVerbosity() { // gLogVerbosity.class_linker = true; // TODO: don't check this in! // gLogVerbosity.collector = true; // TODO: don't check this in! // gLogVerbosity.compiler = true; // TODO: don't check this in! // gLogVerbosity.deopt = true; // TODO: don't check this in! // gLogVerbosity.gc = true; // TODO: don't check this in! // gLogVerbosity.heap = true; // TODO: don't check this in! // gLogVerbosity.image = true; // TODO: don't check this in! // gLogVerbosity.interpreter = true; // TODO: don't check this in! // gLogVerbosity.jdwp = true; // TODO: don't check this in! // gLogVerbosity.jit = true; // TODO: don't check this in! // gLogVerbosity.jni = true; // TODO: don't check this in! // gLogVerbosity.monitor = true; // TODO: don't check this in! // gLogVerbosity.oat = true; // TODO: don't check this in! // gLogVerbosity.profiler = true; // TODO: don't check this in! // gLogVerbosity.signals = true; // TODO: don't check this in! // gLogVerbosity.simulator = true; // TODO: don't check this in! // gLogVerbosity.startup = true; // TODO: don't check this in! // gLogVerbosity.third_party_jni = true; // TODO: don't check this in! // gLogVerbosity.threads = true; // TODO: don't check this in! // gLogVerbosity.verifier = true; // TODO: don't check this in! // gLogVerbosity.hiddenapi = true; // TODO: don't check this in!
}
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;
}
}
auto parser = MakeParser(ignore_unrecognized);
// Convert to a simple string list (without the magic pointer options)
std::vector<std::string> argv_list; if (!ProcessSpecialOptions(options, nullptr, &argv_list)) { returnfalse;
}
// Handle parse errors by displaying the usage and potentially exiting. if (parse_result.IsError()) { if (parse_result.GetStatus() == CmdlineResult::kHelp) {
UsageMessage(stdout, "%s\n", parse_result.GetMessage().c_str()); Exit(0);
}
Usage("%s\n", parse_result.GetMessage().c_str());
UNREACHABLE();
}
using M = RuntimeArgumentMap;
RuntimeArgumentMap args = parser->ReleaseArgumentsMap(); bool use_default_bootclasspath = true;
// -help if (args.Exists(M::Help)) {
Usage(nullptr);
UNREACHABLE();
}
// -showversion if (args.Exists(M::ShowVersion)) {
UsageMessage(stdout, "ART version %s %s\n",
Runtime::GetVersion(),
GetInstructionSetString(kRuntimeISA)); Exit(0);
}
if (args.Exists(M::BootClassPath)) {
LOG(INFO) << "setting boot class path to " << args.Get(M::BootClassPath)->Join();
use_default_bootclasspath = false;
}
if (args.GetOrDefault(M::Interpret)) { if (args.Exists(M::UseJitCompilation) && *args.Get(M::UseJitCompilation)) {
Usage("-Xusejit:true and -Xint cannot be specified together\n");
UNREACHABLE();
}
args.Set(M::UseJitCompilation, false);
}
// Set a default boot class path if we didn't get an explicit one via command line. constchar* env_bcp = getenv("BOOTCLASSPATH"); if (env_bcp != nullptr) {
args.SetIfMissing(M::BootClassPath, ParseStringList<':'>::Split(env_bcp));
}
// Set a default class path if we didn't get an explicit one via command line. if (getenv("CLASSPATH") != nullptr) {
args.SetIfMissing(M::ClassPath, std::string(getenv("CLASSPATH")));
}
// Default to number of processors minus one since the main GC thread also does work.
args.SetIfMissing(M::ParallelGCThreads, gc::Heap::kDefaultEnableParallelGC ? static_cast<unsignedint>(sysconf(_SC_NPROCESSORS_CONF) - 1u) : 0u);
const ParseStringList<':'>* boot_class_path_locations = args.Get(M::BootClassPathLocations); if (boot_class_path_locations != nullptr && boot_class_path_locations->Size() != 0u) { const ParseStringList<':'>* boot_class_path = args.Get(M::BootClassPath); if (boot_class_path == nullptr ||
boot_class_path_locations->Size() != boot_class_path->Size()) {
Usage("The number of boot class path files does not match" " the number of boot class path locations given\n" " boot class path files (%zu): %s\n" " boot class path locations (%zu): %s\n",
(boot_class_path != nullptr) ? boot_class_path->Size() : 0u,
(boot_class_path != nullptr) ? boot_class_path->Join().c_str() : "<nil>",
boot_class_path_locations->Size(),
boot_class_path_locations->Join().c_str()); returnfalse;
}
}
if (args.Exists(M::ForceJitZygote)) { if (args.Exists(M::Image)) {
Usage("-Ximage and -Xforcejitzygote cannot be specified together\n");
UNREACHABLE();
} // If `boot.art` exists in the ART APEX, it will be used. Otherwise, Everything will be JITed.
args.Set(M::Image, ParseStringList<':'>::Split(GetJitZygoteBootImageLocation()));
}
if (args.Exists(M::Zygote)) {
args.Set(M::AllowInMemoryCompilation, Unit());
}
// 0 means no growth limit, and growth limit should be always <= heap size if (args.GetOrDefault(M::HeapGrowthLimit) <= 0u ||
args.GetOrDefault(M::HeapGrowthLimit) > args.GetOrDefault(M::MemoryMaximumSize)) {
args.Set(M::HeapGrowthLimit, args.GetOrDefault(M::MemoryMaximumSize));
}
// Increase log thresholds for GC in stress/continuous mode to avoid excessive log spam. if (args.GetOrDefault(M::GcOption).gcstress_ || args.GetOrDefault(M::GcOption).continuous_gc_) {
args.SetIfMissing(M::AlwaysLogExplicitGcs, false);
args.SetIfMissing(M::LongPauseLogThreshold, gc::Heap::kDefaultLongPauseLogThresholdGcStress);
args.SetIfMissing(M::LongGCLogThreshold, gc::Heap::kDefaultLongGCLogThresholdGcStress);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.