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