Pass Framework Cleanup
Fixed an end-of-program memory leak and added const as qualifiers
for various parameters.
The memory leak involves the pass array holder that would not be freed.
The solution now uses a template getter that holds the unique instance.
Change-Id: Ie8f5b0e5f4249f92851e8ba14e4238952edffee6
diff --git a/compiler/dex/pass_driver.cc b/compiler/dex/pass_driver.cc
index 99541ac..820dc5a 100644
--- a/compiler/dex/pass_driver.cc
+++ b/compiler/dex/pass_driver.cc
@@ -25,7 +25,20 @@
namespace art {
-PassDriver::PassDriver(CompilationUnit* const cu, bool create_default_passes) : cu_(cu) {
+namespace { // anonymous namespace
+
+/**
+ * @brief Helper function to create a single instance of a given Pass and can be shared across the threads
+ */
+template <typename PassType>
+const Pass* GetPassInstance() {
+ static const PassType pass;
+ return &pass;
+}
+
+} // anonymous namespace
+
+PassDriver::PassDriver(CompilationUnit* cu, bool create_default_passes) : cu_(cu) {
dump_cfg_folder_ = "/sdcard/";
// If need be, create the default passes.
@@ -39,7 +52,7 @@
pass_map_.clear();
}
-void PassDriver::InsertPass(Pass* new_pass, bool warn_override) {
+void PassDriver::InsertPass(const Pass* new_pass, bool warn_override) {
assert(new_pass != 0);
// Get name here to not do it all over the method.
@@ -47,7 +60,7 @@
// Do we want to warn the user about squashing a pass?
if (warn_override == false) {
- SafeMap<std::string, Pass* >::iterator it = pass_map_.find(name);
+ auto it = pass_map_.find(name);
if (it != pass_map_.end()) {
LOG(INFO) << "Pass name " << name << " already used, overwriting pass";
@@ -71,16 +84,16 @@
* Disadvantage is the passes can't change their internal states depending on CompilationUnit:
* - This is not yet an issue: no current pass would require it.
*/
- static UniquePtr<Pass> *passes[] = {
- new UniquePtr<Pass>(new CodeLayout()),
- new UniquePtr<Pass>(new SSATransformation()),
- new UniquePtr<Pass>(new ConstantPropagation()),
- new UniquePtr<Pass>(new InitRegLocations()),
- new UniquePtr<Pass>(new MethodUseCount()),
- new UniquePtr<Pass>(new NullCheckEliminationAndTypeInferenceInit()),
- new UniquePtr<Pass>(new NullCheckEliminationAndTypeInference()),
- new UniquePtr<Pass>(new BBCombine()),
- new UniquePtr<Pass>(new BBOptimizations()),
+ static const Pass* passes[] = {
+ GetPassInstance<CodeLayout>(),
+ GetPassInstance<SSATransformation>(),
+ GetPassInstance<ConstantPropagation>(),
+ GetPassInstance<InitRegLocations>(),
+ GetPassInstance<MethodUseCount>(),
+ GetPassInstance<NullCheckEliminationAndTypeInferenceInit>(),
+ GetPassInstance<NullCheckEliminationAndTypeInference>(),
+ GetPassInstance<BBCombine>(),
+ GetPassInstance<BBOptimizations>(),
};
// Get number of elements in the array.
@@ -90,17 +103,17 @@
// - Map is used for the lookup
// - List is used for the pass walk
for (unsigned int i = 0; i < nbr; i++) {
- InsertPass(passes[i]->get());
+ InsertPass(passes[i]);
}
}
-void PassDriver::HandlePassFlag(CompilationUnit* c_unit, Pass* pass) {
+void PassDriver::HandlePassFlag(CompilationUnit* c_unit, const Pass* pass) {
// Unused parameters for the moment.
UNUSED(c_unit);
UNUSED(pass);
}
-void PassDriver::DispatchPass(CompilationUnit* c_unit, Pass* curPass) {
+void PassDriver::DispatchPass(CompilationUnit* c_unit, const Pass* curPass) {
DataflowIterator* iterator = 0;
LOG(DEBUG) << "Dispatching " << curPass->GetName();
@@ -147,13 +160,13 @@
}
}
-void PassDriver::ApplyPass(CompilationUnit* c_unit, Pass* curPass) {
+void PassDriver::ApplyPass(CompilationUnit* c_unit, const Pass* curPass) {
curPass->Start(c_unit);
DispatchPass(c_unit, curPass);
curPass->End(c_unit);
}
-bool PassDriver::RunPass(CompilationUnit* c_unit, Pass* curPass, bool time_split) {
+bool PassDriver::RunPass(CompilationUnit* c_unit, const Pass* curPass, bool time_split) {
// Paranoid: c_unit or curPass cannot be 0, and the pass should have a name.
if (c_unit == 0 || curPass == 0 || (strcmp(curPass->GetName(), "") == 0)) {
return false;
@@ -200,7 +213,7 @@
return false;
}
- Pass* curPass = GetPass(pass_name);
+ const Pass* curPass = GetPass(pass_name);
if (curPass != 0) {
return RunPass(c_unit, curPass);
@@ -211,8 +224,7 @@
}
void PassDriver::Launch() {
- for (std::list<Pass* >::iterator it = pass_list_.begin(); it != pass_list_.end(); it++) {
- Pass* curPass = *it;
+ for (const Pass *curPass : pass_list_) {
RunPass(cu_, curPass, true);
}
}
@@ -220,14 +232,13 @@
void PassDriver::PrintPassNames() const {
LOG(INFO) << "Loop Passes are:";
- for (std::list<Pass* >::const_iterator it = pass_list_.begin(); it != pass_list_.end(); it++) {
- const Pass* curPass = *it;
+ for (const Pass *curPass : pass_list_) {
LOG(INFO) << "\t-" << curPass->GetName();
}
}
-Pass* PassDriver::GetPass(const std::string& name) const {
- SafeMap<std::string, Pass*>::const_iterator it = pass_map_.find(name);
+const Pass* PassDriver::GetPass(const std::string& name) const {
+ auto it = pass_map_.find(name);
if (it != pass_map_.end()) {
return it->second;
diff --git a/compiler/dex/pass_driver.h b/compiler/dex/pass_driver.h
index 29da351..d580460 100644
--- a/compiler/dex/pass_driver.h
+++ b/compiler/dex/pass_driver.h
@@ -33,7 +33,7 @@
*/
class PassDriver {
public:
- explicit PassDriver(CompilationUnit* const cu, bool create_default_passes = true);
+ explicit PassDriver(CompilationUnit* cu, bool create_default_passes = true);
~PassDriver();
@@ -42,7 +42,7 @@
* @param new_pass the new Pass to insert in the map and list.
* @param warn_override warn if the name of the Pass is already used.
*/
- void InsertPass(Pass *new_pass, bool warn_override = true);
+ void InsertPass(const Pass* new_pass, bool warn_override = true);
/**
* @brief Run a pass using the name as key.
@@ -57,25 +57,25 @@
* @param time_split do we want a time split request(default: false)?
* @return whether the pass was applied.
*/
- bool RunPass(CompilationUnit* c_unit, Pass* pass, bool time_split = false);
+ bool RunPass(CompilationUnit* c_unit, const Pass* pass, bool time_split = false);
void Launch();
- void HandlePassFlag(CompilationUnit* c_unit, Pass* pass);
+ void HandlePassFlag(CompilationUnit* c_unit, const Pass* pass);
/**
* @brief Apply a patch: perform start/work/end functions.
*/
- void ApplyPass(CompilationUnit* c_unit, Pass* pass);
+ void ApplyPass(CompilationUnit* c_unit, const Pass* pass);
/**
* @brief Dispatch a patch: walk the BasicBlocks depending on the traversal mode
*/
- void DispatchPass(CompilationUnit* c_unit, Pass* pass);
+ void DispatchPass(CompilationUnit* c_unit, const Pass* pass);
void PrintPassNames() const;
- Pass* GetPass(const std::string& name) const;
+ const Pass* GetPass(const std::string& name) const;
const char *GetDumpCFGFolder() const {
return dump_cfg_folder_;
@@ -85,10 +85,10 @@
void CreatePasses();
/** @brief The Pass Map: contains name -> pass for quick lookup. */
- SafeMap<std::string, Pass*> pass_map_;
+ SafeMap<std::string, const Pass*> pass_map_;
/** @brief List of passes: provides the order to execute the passes. */
- std::list<Pass*> pass_list_;
+ std::list<const Pass*> pass_list_;
/** @brief The CompilationUnit on which to execute the passes on. */
CompilationUnit* const cu_;