summaryrefslogtreecommitdiffstats
path: root/compiler/dex
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2015-02-04 19:21:04 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-02-04 19:21:05 +0000
commit7d3186247cd382c4f7cf8093961795e8565b00e0 (patch)
treef702c9a665eca50fe30b163d70476a28e265274e /compiler/dex
parentc470aefe5abb9ab0b209c7c99139734efe97b177 (diff)
parent98a26e17bb7ecfcd5c9b96394fdeca0a67cafcb3 (diff)
downloadart-7d3186247cd382c4f7cf8093961795e8565b00e0.zip
art-7d3186247cd382c4f7cf8093961795e8565b00e0.tar.gz
art-7d3186247cd382c4f7cf8093961795e8565b00e0.tar.bz2
Merge "ART: Pass Options should be strings instead of integers"
Diffstat (limited to 'compiler/dex')
-rw-r--r--compiler/dex/compiler_ir.h125
-rw-r--r--compiler/dex/pass_driver_me.h25
-rw-r--r--compiler/dex/pass_me.h81
3 files changed, 211 insertions, 20 deletions
diff --git a/compiler/dex/compiler_ir.h b/compiler/dex/compiler_ir.h
index 51c4a43..0c46d43 100644
--- a/compiler/dex/compiler_ir.h
+++ b/compiler/dex/compiler_ir.h
@@ -34,6 +34,129 @@ class CompilerDriver;
class Mir2Lir;
class MIRGraph;
+constexpr size_t kOptionStringMaxLength = 2048;
+
+/**
+ * Structure abstracting pass option values, which can be of type string or integer.
+ */
+struct OptionContent {
+ OptionContent(const OptionContent& option) :
+ type(option.type), container(option.container, option.type) {}
+
+ explicit OptionContent(const char* value) :
+ type(kString), container(value) {}
+
+ explicit OptionContent(int value) :
+ type(kInteger), container(value) {}
+
+ explicit OptionContent(int64_t value) :
+ type(kInteger), container(value) {}
+
+ ~OptionContent() {
+ if (type == kString) {
+ container.StringDelete();
+ }
+ }
+
+ /**
+ * Allows for a transparent display of the option content.
+ */
+ friend std::ostream& operator<<(std::ostream& out, const OptionContent& option) {
+ if (option.type == kString) {
+ out << option.container.s;
+ } else {
+ out << option.container.i;
+ }
+
+ return out;
+ }
+
+ inline const char* GetString() const {
+ return container.s;
+ }
+
+ inline int64_t GetInteger() const {
+ return container.i;
+ }
+
+ /**
+ * @brief Used to compare a string option value to a given @p value.
+ * @details Will return whether the internal string option is equal to
+ * the parameter @p value. It will return false if the type of the
+ * object is not a string.
+ * @param value The string to compare to.
+ * @return Returns whether the internal string option is equal to the
+ * parameter @p value.
+ */
+ inline bool Equals(const char* value) const {
+ DCHECK(value != nullptr);
+ if (type != kString) {
+ return false;
+ }
+ return !strncmp(container.s, value, kOptionStringMaxLength);
+ }
+
+ /**
+ * @brief Used to compare an integer option value to a given @p value.
+ * @details Will return whether the internal integer option is equal to
+ * the parameter @p value. It will return false if the type of the
+ * object is not an integer.
+ * @param value The integer to compare to.
+ * @return Returns whether the internal integer option is equal to the
+ * parameter @p value.
+ */
+ inline bool Equals(int64_t value) const {
+ if (type != kInteger) {
+ return false;
+ }
+ return container.i == value;
+ }
+
+ /**
+ * Describes the type of parameters allowed as option values.
+ */
+ enum OptionType {
+ kString = 0,
+ kInteger
+ };
+
+ OptionType type;
+
+ private:
+ /**
+ * Union containing the option value of either type.
+ */
+ union OptionContainer {
+ explicit OptionContainer(const OptionContainer& c, OptionType t) {
+ if (t == kString) {
+ DCHECK(c.s != nullptr);
+ s = strndup(c.s, kOptionStringMaxLength);
+ } else {
+ i = c.i;
+ }
+ }
+
+ explicit OptionContainer(const char* value) {
+ DCHECK(value != nullptr);
+ s = strndup(value, kOptionStringMaxLength);
+ }
+
+ explicit OptionContainer(int64_t value) : i(value) {}
+ ~OptionContainer() {}
+
+ void StringDelete() {
+ if (s != nullptr) {
+ free(s);
+ }
+ }
+
+ char* s;
+ int64_t i;
+ };
+
+ OptionContainer container;
+};
+
struct CompilationUnit {
CompilationUnit(ArenaPool* pool, InstructionSet isa, CompilerDriver* driver, ClassLinker* linker);
~CompilationUnit();
@@ -77,7 +200,7 @@ struct CompilationUnit {
* default settings have been changed. The key is simply the option string without
* the pass name.
*/
- SafeMap<const std::string, int> overridden_pass_options;
+ SafeMap<const std::string, const OptionContent> overridden_pass_options;
};
} // namespace art
diff --git a/compiler/dex/pass_driver_me.h b/compiler/dex/pass_driver_me.h
index fed92be..94eef22 100644
--- a/compiler/dex/pass_driver_me.h
+++ b/compiler/dex/pass_driver_me.h
@@ -165,7 +165,7 @@ class PassDriverME: public PassDriver {
const PassME* me_pass = down_cast<const PassME*>(pass);
if (me_pass->HasOptions()) {
LOG(INFO) << "Pass options for \"" << me_pass->GetName() << "\" are:";
- SafeMap<const std::string, int> overridden_settings;
+ SafeMap<const std::string, const OptionContent> overridden_settings;
FillOverriddenPassSettings(&manager->GetOptions(), me_pass->GetName(),
overridden_settings);
me_pass->PrintPassOptions(overridden_settings);
@@ -212,7 +212,7 @@ class PassDriverME: public PassDriver {
* configuration.
*/
static void FillOverriddenPassSettings(const PassManagerOptions* options, const char* pass_name,
- SafeMap<const std::string, int>& settings_to_fill) {
+ SafeMap<const std::string, const OptionContent>& settings_to_fill) {
const std::string& settings = options->GetOverriddenPassOptions();
const size_t settings_len = settings.size();
@@ -285,17 +285,28 @@ class PassDriverME: public PassDriver {
continue;
}
- // Get the actual setting itself. Strtol is being used to convert because it is
- // exception safe. If the input is not sane, it will set a setting of 0.
+ // Get the actual setting itself.
std::string setting_string =
settings.substr(setting_pos, next_configuration_separator - setting_pos);
- int setting = std::strtol(setting_string.c_str(), 0, 0);
std::string setting_name =
settings.substr(setting_name_pos, setting_pos - setting_name_pos - 1);
- settings_to_fill.Put(setting_name, setting);
-
+ // We attempt to convert the option value to integer. Strtoll is being used to
+ // convert because it is exception safe.
+ char* end_ptr = nullptr;
+ const char* setting_ptr = setting_string.c_str();
+ DCHECK(setting_ptr != nullptr); // Paranoid: setting_ptr must be a valid pointer.
+ int64_t int_value = strtoll(setting_ptr, &end_ptr, 0);
+ DCHECK(end_ptr != nullptr); // Paranoid: end_ptr must be set by the strtoll call.
+
+ // If strtoll call succeeded, the option is now considered as integer.
+ if (*setting_ptr != '\0' && end_ptr != setting_ptr && *end_ptr == '\0') {
+ settings_to_fill.Put(setting_name, OptionContent(int_value));
+ } else {
+ // Otherwise, it is considered as a string.
+ settings_to_fill.Put(setting_name, OptionContent(setting_string.c_str()));
+ }
search_pos = next_configuration_separator;
} while (true);
}
diff --git a/compiler/dex/pass_me.h b/compiler/dex/pass_me.h
index 79d8f51..d3cf393 100644
--- a/compiler/dex/pass_me.h
+++ b/compiler/dex/pass_me.h
@@ -21,6 +21,7 @@
#include "base/logging.h"
#include "pass.h"
+#include "compiler_ir.h"
#include "safe_map.h"
namespace art {
@@ -104,7 +105,7 @@ class PassME : public Pass {
*/
void PrintPassDefaultOptions() const {
for (const auto& option : default_options_) {
- LOG(INFO) << "\t" << option.first << ":" << std::dec << option.second;
+ LOG(INFO) << "\t" << option.first << ":" << option.second;
}
}
@@ -112,15 +113,49 @@ class PassME : public Pass {
* @brief Prints the pass options along with either default or overridden setting.
* @param overridden_options The overridden settings for this pass.
*/
- void PrintPassOptions(SafeMap<const std::string, int>& overridden_options) const {
+ void PrintPassOptions(SafeMap<const std::string, const OptionContent>& overridden_options) const {
// We walk through the default options only to get the pass names. We use GetPassOption to
// also consider the overridden ones.
for (const auto& option : default_options_) {
- LOG(INFO) << "\t" << option.first << ":" << std::dec
+ LOG(INFO) << "\t" << option.first << ":"
<< GetPassOption(option.first, overridden_options);
}
}
+ /**
+ * @brief Used to obtain the option structure for a pass.
+ * @details Will return the overridden option if it exists or default one otherwise.
+ * @param option_name The name of option whose setting to look for.
+ * @param c_unit The compilation unit currently being handled.
+ * @return Returns the option structure containing the option value.
+ */
+ const OptionContent& GetPassOption(const char* option_name, CompilationUnit* c_unit) const {
+ return GetPassOption(option_name, c_unit->overridden_pass_options);
+ }
+
+ /**
+ * @brief Used to obtain the option for a pass as a string.
+ * @details Will return the overridden option if it exists or default one otherwise.
+ * It will return nullptr if the required option value is not a string.
+ * @param option_name The name of option whose setting to look for.
+ * @param c_unit The compilation unit currently being handled.
+ * @return Returns the overridden option if it exists or the default one otherwise.
+ */
+ const char* GetStringPassOption(const char* option_name, CompilationUnit* c_unit) const {
+ return GetStringPassOption(option_name, c_unit->overridden_pass_options);
+ }
+
+ /**
+ * @brief Used to obtain the pass option value as an integer.
+ * @details Will return the overridden option if it exists or default one otherwise.
+ * It will return 0 if the required option value is not an integer.
+ * @param c_unit The compilation unit currently being handled.
+ * @return Returns the overriden option if it exists or the default one otherwise.
+ */
+ int64_t GetIntegerPassOption(const char* option_name, CompilationUnit* c_unit) const {
+ return GetIntegerPassOption(option_name, c_unit->overridden_pass_options);
+ }
+
const char* GetDumpCFGFolder() const {
return dump_cfg_folder_;
}
@@ -130,29 +165,51 @@ class PassME : public Pass {
}
protected:
- int GetPassOption(const char* option_name, const SafeMap<const std::string, int>& overridden_options) const {
+ const OptionContent& GetPassOption(const char* option_name,
+ const SafeMap<const std::string, const OptionContent>& overridden_options) const {
+ DCHECK(option_name != nullptr);
+
// First check if there are any overridden settings.
auto overridden_it = overridden_options.find(std::string(option_name));
if (overridden_it != overridden_options.end()) {
return overridden_it->second;
+ } else {
+ // Otherwise, there must be a default value for this option name.
+ auto default_it = default_options_.find(option_name);
+ // An invalid option is being requested.
+ if (default_it == default_options_.end()) {
+ LOG(FATAL) << "Fatal: Cannot find an option named \"" << option_name << "\"";
+ }
+
+ return default_it->second;
}
+ }
- // Next check the default options.
- auto default_it = default_options_.find(option_name);
+ const char* GetStringPassOption(const char* option_name,
+ const SafeMap<const std::string, const OptionContent>& overridden_options) const {
+ const OptionContent& option_content = GetPassOption(option_name, overridden_options);
+ if (option_content.type != OptionContent::kString) {
+ return nullptr;
+ }
- if (default_it == default_options_.end()) {
- // An invalid option is being requested.
- DCHECK(false);
+ return option_content.GetString();
+ }
+
+ int64_t GetIntegerPassOption(const char* option_name,
+ const SafeMap<const std::string, const OptionContent>& overridden_options) const {
+ const OptionContent& option_content = GetPassOption(option_name, overridden_options);
+ if (option_content.type != OptionContent::kInteger) {
return 0;
}
- return default_it->second;
+ return option_content.GetInteger();
}
/** @brief Type of traversal: determines the order to execute the pass on the BasicBlocks. */
const DataFlowAnalysisMode traversal_type_;
- /** @brief Flags for additional directives: used to determine if a particular post-optimization pass is necessary. */
+ /** @brief Flags for additional directives: used to determine if a particular
+ * post-optimization pass is necessary. */
const unsigned int flags_;
/** @brief CFG Dump Folder: what sub-folder to use for dumping the CFGs post pass. */
@@ -163,7 +220,7 @@ class PassME : public Pass {
* @details The constructor of the specific pass instance should fill this
* with default options.
* */
- SafeMap<const char*, int> default_options_;
+ SafeMap<const char*, const OptionContent> default_options_;
};
} // namespace art
#endif // ART_COMPILER_DEX_PASS_ME_H_