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