cmdline_types.h revision 3be6e9d904baa13d7cf51dfc6742dea12e766b2e
1aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin/* 2aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin * Copyright (C) 2015 The Android Open Source Project 3aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin * 4aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin * Licensed under the Apache License, Version 2.0 (the "License"); 5aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin * you may not use this file except in compliance with the License. 6aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin * You may obtain a copy of the License at 7aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin * 8aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin * http://www.apache.org/licenses/LICENSE-2.0 9aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin * 10aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin * Unless required by applicable law or agreed to in writing, software 11aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin * distributed under the License is distributed on an "AS IS" BASIS, 12aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin * See the License for the specific language governing permissions and 14aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin * limitations under the License. 15aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin */ 16aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin#ifndef ART_CMDLINE_CMDLINE_TYPES_H_ 17aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin#define ART_CMDLINE_CMDLINE_TYPES_H_ 18aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 19aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin#define CMDLINE_NDEBUG 1 // Do not output any debugging information for parsing. 20aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 21aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin#include "cmdline/memory_representation.h" 22aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin#include "cmdline/detail/cmdline_debug_detail.h" 23aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin#include "cmdline_type_parser.h" 24aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 25aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin// Includes for the types that are being specialized 26aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin#include <string> 27aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin#include "unit.h" 28aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin#include "jdwp/jdwp.h" 29aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin#include "runtime/base/logging.h" 30aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin#include "gc/collector_type.h" 31aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin#include "gc/space/large_object_space.h" 32aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin#include "profiler_options.h" 33aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 34aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinnamespace art { 35aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 36aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin// The default specialization will always fail parsing the type from a string. 37aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin// Provide your own specialization that inherits from CmdlineTypeParser<T> 38aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin// and implements either Parse or ParseAndAppend 39aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin// (only if the argument was defined with ::AppendValues()) but not both. 40aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkintemplate <typename T> 41aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct CmdlineType : CmdlineTypeParser<T> { 42aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 43aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 44aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin// Specializations for CmdlineType<T> follow: 45aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 46aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin// Parse argument definitions for Unit-typed arguments. 47aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkintemplate <> 48aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct CmdlineType<Unit> : CmdlineTypeParser<Unit> { 49aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Result Parse(const std::string& args) { 50aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (args == "") { 51aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Success(Unit{}); // NOLINT [whitespace/braces] [5] 52aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 53aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Failure("Unexpected extra characters " + args); 54aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 55aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 56aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 57aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkintemplate <> 58aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct CmdlineType<JDWP::JdwpOptions> : CmdlineTypeParser<JDWP::JdwpOptions> { 593be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz /* 603be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz * Handle one of the JDWP name/value pairs. 613be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz * 623be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz * JDWP options are: 633be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz * help: if specified, show help message and bail 643be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz * transport: may be dt_socket or dt_shmem 653be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz * address: for dt_socket, "host:port", or just "port" when listening 663be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz * server: if "y", wait for debugger to attach; if "n", attach to debugger 673be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz * timeout: how long to wait for debugger to connect / listen 683be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz * 693be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz * Useful with server=n (these aren't supported yet): 703be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz * onthrow=<exception-name>: connect to debugger when exception thrown 713be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz * onuncaught=y|n: connect to debugger when uncaught exception thrown 723be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz * launch=<command-line>: launch the debugger itself 733be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz * 743be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz * The "transport" option is required, as is "address" if server=n. 753be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz */ 76aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Result Parse(const std::string& options) { 77aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin VLOG(jdwp) << "ParseJdwpOptions: " << options; 78aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 79aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (options == "help") { 80aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Usage( 81aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n" 82aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n\n"); 83aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 84aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 85aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin const std::string s; 86aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 87aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin std::vector<std::string> pairs; 88aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Split(options, ',', &pairs); 89aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 903be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz JDWP::JdwpOptions jdwp_options; 91aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin std::stringstream error_stream; 92aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 933be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz for (const std::string& jdwp_option : pairs) { 943be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz std::string::size_type equals_pos = jdwp_option.find('='); 953be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz if (equals_pos == std::string::npos) { 96aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Failure(s + 973be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz "Can't parse JDWP option '" + jdwp_option + "' in '" + options + "'"); 98aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 99aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 1003be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz if (!ParseJdwpOption(jdwp_option.substr(0, equals_pos), 1013be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz jdwp_option.substr(equals_pos + 1), 102aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin error_stream, 1033be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz &jdwp_options)) { 104aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Failure(error_stream.str()); 105aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 106aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 107aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 108aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (jdwp_options.transport == JDWP::kJdwpTransportUnknown) { 109aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Failure(s + "Must specify JDWP transport: " + options); 110aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 111aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (!jdwp_options.server && (jdwp_options.host.empty() || jdwp_options.port == 0)) { 112aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Failure(s + "Must specify JDWP host and port when server=n: " + options); 113aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 114aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 115aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Success(std::move(jdwp_options)); 116aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 117aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 118aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin bool ParseJdwpOption(const std::string& name, const std::string& value, 119aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin std::ostream& error_stream, 1203be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz JDWP::JdwpOptions* jdwp_options) { 121aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (name == "transport") { 122aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (value == "dt_socket") { 1233be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz jdwp_options->transport = JDWP::kJdwpTransportSocket; 124aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (value == "dt_android_adb") { 1253be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz jdwp_options->transport = JDWP::kJdwpTransportAndroidAdb; 126aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else { 127aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin error_stream << "JDWP transport not supported: " << value; 128aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return false; 129aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 130aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (name == "server") { 131aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (value == "n") { 1323be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz jdwp_options->server = false; 133aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (value == "y") { 1343be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz jdwp_options->server = true; 135aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else { 136aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin error_stream << "JDWP option 'server' must be 'y' or 'n'"; 137aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return false; 138aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 139aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (name == "suspend") { 140aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (value == "n") { 1413be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz jdwp_options->suspend = false; 142aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (value == "y") { 1433be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz jdwp_options->suspend = true; 144aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else { 145aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin error_stream << "JDWP option 'suspend' must be 'y' or 'n'"; 146aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return false; 147aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 148aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (name == "address") { 149aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin /* this is either <port> or <host>:<port> */ 150aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin std::string port_string; 1513be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz jdwp_options->host.clear(); 152aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin std::string::size_type colon = value.find(':'); 153aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (colon != std::string::npos) { 1543be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz jdwp_options->host = value.substr(0, colon); 155aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin port_string = value.substr(colon + 1); 156aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else { 157aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin port_string = value; 158aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 159aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (port_string.empty()) { 160aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin error_stream << "JDWP address missing port: " << value; 161aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return false; 162aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 163aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin char* end; 164aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin uint64_t port = strtoul(port_string.c_str(), &end, 10); 165aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (*end != '\0' || port > 0xffff) { 166aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin error_stream << "JDWP address has junk in port field: " << value; 167aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return false; 168aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 1693be6e9d904baa13d7cf51dfc6742dea12e766b2eSebastien Hertz jdwp_options->port = port; 170aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (name == "launch" || name == "onthrow" || name == "oncaught" || name == "timeout") { 171aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin /* valid but unsupported */ 172aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin LOG(INFO) << "Ignoring JDWP option '" << name << "'='" << value << "'"; 173aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else { 174aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin LOG(INFO) << "Ignoring unrecognized JDWP option '" << name << "'='" << value << "'"; 175aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 176aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 177aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return true; 178aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 179aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 180aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static const char* Name() { return "JdwpOptions"; } 181aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 182aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 183aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkintemplate <size_t Divisor> 184aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct CmdlineType<Memory<Divisor>> : CmdlineTypeParser<Memory<Divisor>> { 185aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin using typename CmdlineTypeParser<Memory<Divisor>>::Result; 186aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 187aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Result Parse(const std::string arg) { 188aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin CMDLINE_DEBUG_LOG << "Parsing memory: " << arg << std::endl; 189aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin size_t val = ParseMemoryOption(arg.c_str(), Divisor); 190aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin CMDLINE_DEBUG_LOG << "Memory parsed to size_t value: " << val << std::endl; 191aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 192aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (val == 0) { 193aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Failure(std::string("not a valid memory value, or not divisible by ") 194aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin + std::to_string(Divisor)); 195aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 196aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 197aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Success(Memory<Divisor>(val)); 198aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 199aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 200aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify 201aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // memory sizes. [kK] indicates kilobytes, [mM] megabytes, and 202aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // [gG] gigabytes. 203aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // 204aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // "s" should point just past the "-Xm?" part of the string. 205aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // "div" specifies a divisor, e.g. 1024 if the value must be a multiple 206aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // of 1024. 207aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // 208aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // The spec says the -Xmx and -Xms options must be multiples of 1024. It 209aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // doesn't say anything about -Xss. 210aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // 211aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Returns 0 (a useless size) if "s" is malformed or specifies a low or 212aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // non-evenly-divisible value. 213aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // 214aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static size_t ParseMemoryOption(const char* s, size_t div) { 215aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // strtoul accepts a leading [+-], which we don't want, 216aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // so make sure our string starts with a decimal digit. 217aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (isdigit(*s)) { 218aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin char* s2; 219aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin size_t val = strtoul(s, &s2, 10); 220aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (s2 != s) { 221aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // s2 should be pointing just after the number. 222aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // If this is the end of the string, the user 223aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // has specified a number of bytes. Otherwise, 224aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // there should be exactly one more character 225aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // that specifies a multiplier. 226aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (*s2 != '\0') { 227aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // The remainder of the string is either a single multiplier 228aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // character, or nothing to indicate that the value is in 229aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // bytes. 230aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin char c = *s2++; 231aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (*s2 == '\0') { 232aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin size_t mul; 233aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (c == '\0') { 234aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin mul = 1; 235aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (c == 'k' || c == 'K') { 236aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin mul = KB; 237aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (c == 'm' || c == 'M') { 238aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin mul = MB; 239aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (c == 'g' || c == 'G') { 240aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin mul = GB; 241aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else { 242aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Unknown multiplier character. 243aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return 0; 244aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 245aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 246aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (val <= std::numeric_limits<size_t>::max() / mul) { 247aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin val *= mul; 248aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else { 249aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Clamp to a multiple of 1024. 250aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin val = std::numeric_limits<size_t>::max() & ~(1024-1); 251aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 252aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else { 253aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // There's more than one character after the numeric part. 254aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return 0; 255aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 256aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 257aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // The man page says that a -Xm value must be a multiple of 1024. 258aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (val % div == 0) { 259aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return val; 260aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 261aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 262aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 263aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return 0; 264aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 265aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 266aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static const char* Name() { return Memory<Divisor>::Name(); } 267aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 268aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 269aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkintemplate <> 270aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct CmdlineType<double> : CmdlineTypeParser<double> { 271aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Result Parse(const std::string& str) { 272aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin char* end = nullptr; 273aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin errno = 0; 274aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin double value = strtod(str.c_str(), &end); 275aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 276aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (*end != '\0') { 277aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Failure("Failed to parse double from " + str); 278aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 279aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (errno == ERANGE) { 280aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::OutOfRange( 281aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin "Failed to parse double from " + str + "; overflow/underflow occurred"); 282aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 283aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 284aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Success(value); 285aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 286aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 287aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static const char* Name() { return "double"; } 288aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 289aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 290aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkintemplate <> 291aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct CmdlineType<unsigned int> : CmdlineTypeParser<unsigned int> { 292aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Result Parse(const std::string& str) { 293aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin const char* begin = str.c_str(); 294aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin char* end; 295aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 296aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Parse into a larger type (long long) because we can't use strtoul 297aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // since it silently converts negative values into unsigned long and doesn't set errno. 298aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin errno = 0; 299aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin long long int result = strtoll(begin, &end, 10); // NOLINT [runtime/int] [4] 300aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (begin == end || *end != '\0' || errno == EINVAL) { 301aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Failure("Failed to parse integer from " + str); 302aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if ((errno == ERANGE) || // NOLINT [runtime/int] [4] 303aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin result < std::numeric_limits<int>::min() 304aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin || result > std::numeric_limits<unsigned int>::max() || result < 0) { 305aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::OutOfRange( 306aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin "Failed to parse integer from " + str + "; out of unsigned int range"); 307aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 308aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 309aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Success(static_cast<unsigned int>(result)); 310aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 311aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 312aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static const char* Name() { return "unsigned integer"; } 313aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 314aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 315aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin// Lightweight nanosecond value type. Allows parser to convert user-input from milliseconds 316aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin// to nanoseconds automatically after parsing. 317aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin// 318aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin// All implicit conversion from uint64_t uses nanoseconds. 319aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct MillisecondsToNanoseconds { 320aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Create from nanoseconds. 321aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin MillisecondsToNanoseconds(uint64_t nanoseconds) : nanoseconds_(nanoseconds) { // NOLINT [runtime/explicit] [5] 322aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 323aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 324aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Create from milliseconds. 325aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static MillisecondsToNanoseconds FromMilliseconds(unsigned int milliseconds) { 326aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return MillisecondsToNanoseconds(MsToNs(milliseconds)); 327aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 328aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 329aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Get the underlying nanoseconds value. 330aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin uint64_t GetNanoseconds() const { 331aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return nanoseconds_; 332aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 333aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 334aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Get the milliseconds value [via a conversion]. Loss of precision will occur. 335aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin uint64_t GetMilliseconds() const { 336aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return NsToMs(nanoseconds_); 337aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 338aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 339aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Get the underlying nanoseconds value. 340aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin operator uint64_t() const { 341aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return GetNanoseconds(); 342aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 343aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 344aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Default constructors/copy-constructors. 345aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin MillisecondsToNanoseconds() : nanoseconds_(0ul) {} 346aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin MillisecondsToNanoseconds(const MillisecondsToNanoseconds& rhs) = default; 347aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin MillisecondsToNanoseconds(MillisecondsToNanoseconds&& rhs) = default; 348aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 349aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin private: 350aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin uint64_t nanoseconds_; 351aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 352aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 353aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkintemplate <> 354aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct CmdlineType<MillisecondsToNanoseconds> : CmdlineTypeParser<MillisecondsToNanoseconds> { 355aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Result Parse(const std::string& str) { 356aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin CmdlineType<unsigned int> uint_parser; 357aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin CmdlineParseResult<unsigned int> res = uint_parser.Parse(str); 358aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 359aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (res.IsSuccess()) { 360aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Success(MillisecondsToNanoseconds::FromMilliseconds(res.GetValue())); 361aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else { 362aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::CastError(res); 363aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 364aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 365aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 366aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static const char* Name() { return "MillisecondsToNanoseconds"; } 367aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 368aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 369aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkintemplate <> 370aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct CmdlineType<std::string> : CmdlineTypeParser<std::string> { 371aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Result Parse(const std::string& args) { 372aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Success(args); 373aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 374aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 375aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Result ParseAndAppend(const std::string& args, 376aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin std::string& existing_value) { 377aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (existing_value.empty()) { 378aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin existing_value = args; 379aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else { 380aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin existing_value += ' '; 381aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin existing_value += args; 382aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 383aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::SuccessNoValue(); 384aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 385aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 386aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 387aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkintemplate <> 388aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct CmdlineType<std::vector<std::string>> : CmdlineTypeParser<std::vector<std::string>> { 389aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Result Parse(const std::string& args) { 390aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin assert(false && "Use AppendValues() for a string vector type"); 391aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Failure("Unconditional failure: string vector must be appended: " + args); 392aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 393aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 394aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Result ParseAndAppend(const std::string& args, 395aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin std::vector<std::string>& existing_value) { 396aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin existing_value.push_back(args); 397aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::SuccessNoValue(); 398aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 399aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 400aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static const char* Name() { return "std::vector<std::string>"; } 401aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 402aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 403aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkintemplate <char Separator> 404aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct ParseStringList { 405aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin explicit ParseStringList(std::vector<std::string>&& list) : list_(list) {} 406aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 407aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin operator std::vector<std::string>() const { 408aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return list_; 409aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 410aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 411aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin operator std::vector<std::string>&&() && { 412aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return std::move(list_); 413aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 414aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 415aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin size_t Size() const { 416aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return list_.size(); 417aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 418aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 419aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin std::string Join() const { 420aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return art::Join(list_, Separator); 421aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 422aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 423aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static ParseStringList<Separator> Split(const std::string& str) { 424aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin std::vector<std::string> list; 425aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin art::Split(str, Separator, &list); 426aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return ParseStringList<Separator>(std::move(list)); 427aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 428aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 429aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin ParseStringList() = default; 430aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin ParseStringList(const ParseStringList& rhs) = default; 431aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin ParseStringList(ParseStringList&& rhs) = default; 432aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 433aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin private: 434aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin std::vector<std::string> list_; 435aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 436aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 437aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkintemplate <char Separator> 438aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct CmdlineType<ParseStringList<Separator>> : CmdlineTypeParser<ParseStringList<Separator>> { 439aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin using Result = CmdlineParseResult<ParseStringList<Separator>>; 440aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 441aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Result Parse(const std::string& args) { 442aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Success(ParseStringList<Separator>::Split(args)); 443aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 444aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 445aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static const char* Name() { return "ParseStringList<Separator>"; } 446aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 447aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 448aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstatic gc::CollectorType ParseCollectorType(const std::string& option) { 449aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (option == "MS" || option == "nonconcurrent") { 450aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return gc::kCollectorTypeMS; 451aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (option == "CMS" || option == "concurrent") { 452aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return gc::kCollectorTypeCMS; 453aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (option == "SS") { 454aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return gc::kCollectorTypeSS; 455aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (option == "GSS") { 456aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return gc::kCollectorTypeGSS; 457aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (option == "CC") { 458aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return gc::kCollectorTypeCC; 459aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (option == "MC") { 460aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return gc::kCollectorTypeMC; 461aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else { 462aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return gc::kCollectorTypeNone; 463aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 464aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin} 465aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 466aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct XGcOption { 467aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // These defaults are used when the command line arguments for -Xgc: 468aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // are either omitted completely or partially. 469aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin gc::CollectorType collector_type_ = kUseReadBarrier ? 470aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // If RB is enabled (currently a build-time decision), 471aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // use CC as the default GC. 472aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin gc::kCollectorTypeCC : 473aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin gc::kCollectorTypeDefault; 474aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin bool verify_pre_gc_heap_ = false; 475aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin bool verify_pre_sweeping_heap_ = kIsDebugBuild; 476aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin bool verify_post_gc_heap_ = false; 477aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin bool verify_pre_gc_rosalloc_ = kIsDebugBuild; 478aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin bool verify_pre_sweeping_rosalloc_ = false; 479aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin bool verify_post_gc_rosalloc_ = false; 480aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 481aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 482aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkintemplate <> 483aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct CmdlineType<XGcOption> : CmdlineTypeParser<XGcOption> { 484aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Result Parse(const std::string& option) { // -Xgc: already stripped 485aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin XGcOption xgc{}; // NOLINT [readability/braces] [4] 486aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 487aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin std::vector<std::string> gc_options; 488aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Split(option, ',', &gc_options); 489aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin for (const std::string& gc_option : gc_options) { 490aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin gc::CollectorType collector_type = ParseCollectorType(gc_option); 491aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (collector_type != gc::kCollectorTypeNone) { 492aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin xgc.collector_type_ = collector_type; 493aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (gc_option == "preverify") { 494aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin xgc.verify_pre_gc_heap_ = true; 495aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (gc_option == "nopreverify") { 496aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin xgc.verify_pre_gc_heap_ = false; 497aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (gc_option == "presweepingverify") { 498aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin xgc.verify_pre_sweeping_heap_ = true; 499aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (gc_option == "nopresweepingverify") { 500aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin xgc.verify_pre_sweeping_heap_ = false; 501aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (gc_option == "postverify") { 502aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin xgc.verify_post_gc_heap_ = true; 503aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (gc_option == "nopostverify") { 504aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin xgc.verify_post_gc_heap_ = false; 505aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (gc_option == "preverify_rosalloc") { 506aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin xgc.verify_pre_gc_rosalloc_ = true; 507aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (gc_option == "nopreverify_rosalloc") { 508aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin xgc.verify_pre_gc_rosalloc_ = false; 509aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (gc_option == "presweepingverify_rosalloc") { 510aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin xgc.verify_pre_sweeping_rosalloc_ = true; 511aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (gc_option == "nopresweepingverify_rosalloc") { 512aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin xgc.verify_pre_sweeping_rosalloc_ = false; 513aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (gc_option == "postverify_rosalloc") { 514aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin xgc.verify_post_gc_rosalloc_ = true; 515aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (gc_option == "nopostverify_rosalloc") { 516aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin xgc.verify_post_gc_rosalloc_ = false; 517aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if ((gc_option == "precise") || 518aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin (gc_option == "noprecise") || 519aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin (gc_option == "verifycardtable") || 520aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin (gc_option == "noverifycardtable")) { 521aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Ignored for backwards compatibility. 522aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else { 523aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Usage(std::string("Unknown -Xgc option ") + gc_option); 524aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 525aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 526aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 527aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Success(std::move(xgc)); 528aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 529aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 530aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static const char* Name() { return "XgcOption"; } 531aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 532aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 533aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct BackgroundGcOption { 534aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // If background_collector_type_ is kCollectorTypeNone, it defaults to the 535aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // XGcOption::collector_type_ after parsing options. If you set this to 536aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // kCollectorTypeHSpaceCompact then we will do an hspace compaction when 537aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // we transition to background instead of a normal collector transition. 538aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin gc::CollectorType background_collector_type_; 539aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 540aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin BackgroundGcOption(gc::CollectorType background_collector_type) // NOLINT [runtime/explicit] [5] 541aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin : background_collector_type_(background_collector_type) {} 542aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin BackgroundGcOption() 543aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin : background_collector_type_(gc::kCollectorTypeNone) { 544aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 545aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (kUseReadBarrier) { 546aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin background_collector_type_ = gc::kCollectorTypeCC; // Disable background compaction for CC. 547aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 548aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 549aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 550aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin operator gc::CollectorType() const { return background_collector_type_; } 551aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 552aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 553aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkintemplate<> 554aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct CmdlineType<BackgroundGcOption> 555aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin : CmdlineTypeParser<BackgroundGcOption>, private BackgroundGcOption { 556aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Result Parse(const std::string& substring) { 557aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Special handling for HSpaceCompact since this is only valid as a background GC type. 558aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (substring == "HSpaceCompact") { 559aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin background_collector_type_ = gc::kCollectorTypeHomogeneousSpaceCompact; 560aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else { 561aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin gc::CollectorType collector_type = ParseCollectorType(substring); 562aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (collector_type != gc::kCollectorTypeNone) { 563aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin background_collector_type_ = collector_type; 564aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else { 565aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Failure(); 566aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 567aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 568aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 569aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin BackgroundGcOption res = *this; 570aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Success(res); 571aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 572aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 573aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static const char* Name() { return "BackgroundGcOption"; } 574aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 575aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 576aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkintemplate <> 577aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct CmdlineType<LogVerbosity> : CmdlineTypeParser<LogVerbosity> { 578aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Result Parse(const std::string& options) { 579aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin LogVerbosity log_verbosity = LogVerbosity(); 580aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 581aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin std::vector<std::string> verbose_options; 582aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Split(options, ',', &verbose_options); 583aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin for (size_t j = 0; j < verbose_options.size(); ++j) { 584aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (verbose_options[j] == "class") { 585aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin log_verbosity.class_linker = true; 586aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (verbose_options[j] == "compiler") { 587aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin log_verbosity.compiler = true; 588aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (verbose_options[j] == "gc") { 589aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin log_verbosity.gc = true; 590aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (verbose_options[j] == "heap") { 591aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin log_verbosity.heap = true; 592aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (verbose_options[j] == "jdwp") { 593aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin log_verbosity.jdwp = true; 594aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (verbose_options[j] == "jni") { 595aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin log_verbosity.jni = true; 596aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (verbose_options[j] == "monitor") { 597aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin log_verbosity.monitor = true; 598aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (verbose_options[j] == "profiler") { 599aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin log_verbosity.profiler = true; 600aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (verbose_options[j] == "signals") { 601aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin log_verbosity.signals = true; 602aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (verbose_options[j] == "startup") { 603aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin log_verbosity.startup = true; 604aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (verbose_options[j] == "third-party-jni") { 605aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin log_verbosity.third_party_jni = true; 606aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (verbose_options[j] == "threads") { 607aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin log_verbosity.threads = true; 608aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (verbose_options[j] == "verifier") { 609aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin log_verbosity.verifier = true; 610aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else { 611aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Usage(std::string("Unknown -verbose option ") + verbose_options[j]); 612aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 613aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 614aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 615aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Success(log_verbosity); 616aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 617aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 618aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static const char* Name() { return "LogVerbosity"; } 619aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 620aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 621aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin// TODO: Replace with art::ProfilerOptions for the real thing. 622aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct TestProfilerOptions { 623aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Whether or not the applications should be profiled. 624aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin bool enabled_; 625aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Destination file name where the profiling data will be saved into. 626aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin std::string output_file_name_; 627aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Generate profile every n seconds. 628aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin uint32_t period_s_; 629aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Run profile for n seconds. 630aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin uint32_t duration_s_; 631aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Microseconds between samples. 632aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin uint32_t interval_us_; 633aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Coefficient to exponential backoff. 634aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin double backoff_coefficient_; 635aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Whether the profile should start upon app startup or be delayed by some random offset. 636aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin bool start_immediately_; 637aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Top K% of samples that are considered relevant when deciding if the app should be recompiled. 638aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin double top_k_threshold_; 639aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // How much the top K% samples needs to change in order for the app to be recompiled. 640aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin double top_k_change_threshold_; 641aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // The type of profile data dumped to the disk. 642aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin ProfileDataType profile_type_; 643aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // The max depth of the stack collected by the profiler 644aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin uint32_t max_stack_depth_; 645aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 646aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin TestProfilerOptions() : 647aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin enabled_(false), 648aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin output_file_name_(), 649aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin period_s_(0), 650aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin duration_s_(0), 651aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin interval_us_(0), 652aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin backoff_coefficient_(0), 653aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin start_immediately_(0), 654aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin top_k_threshold_(0), 655aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin top_k_change_threshold_(0), 656aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin profile_type_(ProfileDataType::kProfilerMethod), 657aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin max_stack_depth_(0) { 658aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 659aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 660aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin TestProfilerOptions(const TestProfilerOptions& other) = default; 661aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin TestProfilerOptions(TestProfilerOptions&& other) = default; 662aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 663aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 664aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstatic inline std::ostream& operator<<(std::ostream& stream, const TestProfilerOptions& options) { 665aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin stream << "TestProfilerOptions {" << std::endl; 666aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 667aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin#define PRINT_TO_STREAM(field) \ 668aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin stream << #field << ": '" << options.field << "'" << std::endl; 669aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 670aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin PRINT_TO_STREAM(enabled_); 671aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin PRINT_TO_STREAM(output_file_name_); 672aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin PRINT_TO_STREAM(period_s_); 673aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin PRINT_TO_STREAM(duration_s_); 674aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin PRINT_TO_STREAM(interval_us_); 675aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin PRINT_TO_STREAM(backoff_coefficient_); 676aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin PRINT_TO_STREAM(start_immediately_); 677aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin PRINT_TO_STREAM(top_k_threshold_); 678aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin PRINT_TO_STREAM(top_k_change_threshold_); 679aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin PRINT_TO_STREAM(profile_type_); 680aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin PRINT_TO_STREAM(max_stack_depth_); 681aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 682aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin stream << "}"; 683aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 684aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return stream; 685aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin#undef PRINT_TO_STREAM 686aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin} 687aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 688aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkintemplate <> 689aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinstruct CmdlineType<TestProfilerOptions> : CmdlineTypeParser<TestProfilerOptions> { 690aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin using Result = CmdlineParseResult<TestProfilerOptions>; 691aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 692aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin private: 693aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin using StringResult = CmdlineParseResult<std::string>; 694aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin using DoubleResult = CmdlineParseResult<double>; 695aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 696aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin template <typename T> 697aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static Result ParseInto(TestProfilerOptions& options, 698aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin T TestProfilerOptions::*pField, 699aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin CmdlineParseResult<T>&& result) { 700aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin assert(pField != nullptr); 701aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 702aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (result.IsSuccess()) { 703aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin options.*pField = result.ReleaseValue(); 704aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::SuccessNoValue(); 705aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 706aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 707aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::CastError(result); 708aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 709aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 710aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin template <typename T> 711aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static Result ParseIntoRangeCheck(TestProfilerOptions& options, 712aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin T TestProfilerOptions::*pField, 713aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin CmdlineParseResult<T>&& result, 714aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin T min, 715aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin T max) { 716aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (result.IsSuccess()) { 717aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin const T& value = result.GetValue(); 718aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 719aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (value < min || value > max) { 720aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin CmdlineParseResult<T> out_of_range = CmdlineParseResult<T>::OutOfRange(value, min, max); 721aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::CastError(out_of_range); 722aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 723aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 724aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 725aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return ParseInto(options, pField, std::forward<CmdlineParseResult<T>>(result)); 726aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 727aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 728aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static StringResult ParseStringAfterChar(const std::string& s, char c) { 729aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin std::string parsed_value; 730aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 731aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin std::string::size_type colon = s.find(c); 732aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (colon == std::string::npos) { 733aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return StringResult::Usage(std::string() + "Missing char " + c + " in option " + s); 734aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 735aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Add one to remove the char we were trimming until. 736aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin parsed_value = s.substr(colon + 1); 737aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return StringResult::Success(parsed_value); 738aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 739aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 740aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static std::string RemovePrefix(const std::string& source) { 741aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin size_t prefix_idx = source.find(":"); 742aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 743aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (prefix_idx == std::string::npos) { 744aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return ""; 745aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 746aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 747aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return source.substr(prefix_idx + 1); 748aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 749aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 750aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin public: 751aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin Result ParseAndAppend(const std::string& option, TestProfilerOptions& existing) { 752aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // Special case which doesn't include a wildcard argument definition. 753aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // We pass-it through as-is. 754aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (option == "-Xenable-profiler") { 755aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin existing.enabled_ = true; 756aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::SuccessNoValue(); 757aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 758aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 759aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin // The rest of these options are always the wildcard from '-Xprofile-*' 760aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin std::string suffix = RemovePrefix(option); 761aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 762aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (StartsWith(option, "filename:")) { 763aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin CmdlineType<std::string> type_parser; 764aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 765aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return ParseInto(existing, 766aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin &TestProfilerOptions::output_file_name_, 767aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin type_parser.Parse(suffix)); 768aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (StartsWith(option, "period:")) { 769aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin CmdlineType<unsigned int> type_parser; 770aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 771aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return ParseInto(existing, 772aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin &TestProfilerOptions::period_s_, 773aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin type_parser.Parse(suffix)); 774aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (StartsWith(option, "duration:")) { 775aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin CmdlineType<unsigned int> type_parser; 776aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 777aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return ParseInto(existing, 778aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin &TestProfilerOptions::duration_s_, 779aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin type_parser.Parse(suffix)); 780aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (StartsWith(option, "interval:")) { 781aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin CmdlineType<unsigned int> type_parser; 782aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 783aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return ParseInto(existing, 784aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin &TestProfilerOptions::interval_us_, 785aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin type_parser.Parse(suffix)); 786aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (StartsWith(option, "backoff:")) { 787aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin CmdlineType<double> type_parser; 788aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 789aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return ParseIntoRangeCheck(existing, 790aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin &TestProfilerOptions::backoff_coefficient_, 791aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin type_parser.Parse(suffix), 792aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 1.0, 793aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 10.0); 794aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 795aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (option == "start-immediately") { 796aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin existing.start_immediately_ = true; 797aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::SuccessNoValue(); 798aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (StartsWith(option, "top-k-threshold:")) { 799aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin CmdlineType<double> type_parser; 800aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 801aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return ParseIntoRangeCheck(existing, 802aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin &TestProfilerOptions::top_k_threshold_, 803aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin type_parser.Parse(suffix), 804aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 0.0, 805aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 100.0); 806aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (StartsWith(option, "top-k-change-threshold:")) { 807aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin CmdlineType<double> type_parser; 808aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 809aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return ParseIntoRangeCheck(existing, 810aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin &TestProfilerOptions::top_k_change_threshold_, 811aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin type_parser.Parse(suffix), 812aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 0.0, 813aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 100.0); 814aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (option == "type:method") { 815aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin existing.profile_type_ = kProfilerMethod; 816aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::SuccessNoValue(); 817aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (option == "type:stack") { 818aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin existing.profile_type_ = kProfilerBoundedStack; 819aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::SuccessNoValue(); 820aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else if (StartsWith(option, "max-stack-depth:")) { 821aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin CmdlineType<unsigned int> type_parser; 822aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 823aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return ParseInto(existing, 824aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin &TestProfilerOptions::max_stack_depth_, 825aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin type_parser.Parse(suffix)); 826aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } else { 827aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return Result::Failure(std::string("Invalid suboption '") + option + "'"); 828aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 829aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 830aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 831aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static const char* Name() { return "TestProfilerOptions"; } 832aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin static constexpr bool kCanParseBlankless = true; 833aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin}; 834aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 835aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 836aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin} // namespace art 837aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin#endif // ART_CMDLINE_CMDLINE_TYPES_H_ 838