Chromium Code Reviews| Index: tools/gcmole/gcmole.cc |
| diff --git a/tools/gcmole/gcmole.cc b/tools/gcmole/gcmole.cc |
| index 9f1f781453d54bf121109d11f1f3406bfc058524..67f676d667165fe1f3c5baa8f4f5d3ede21d2218 100644 |
| --- a/tools/gcmole/gcmole.cc |
| +++ b/tools/gcmole/gcmole.cc |
| @@ -318,22 +318,24 @@ const std::string DEAD_VAR_MSG("Possibly dead variable."); |
| class Environment { |
| public: |
| - Environment() { } |
| + Environment() = default; |
| static Environment Unreachable() { |
| Environment env; |
| - env.live_.set(); |
| + env.unreachable_ = true; |
| return env; |
| } |
| static Environment Merge(const Environment& l, |
| const Environment& r) { |
| - return Environment(l, r); |
| + Environment out(l); |
| + out &= r; |
| + return out; |
| } |
| Environment ApplyEffect(ExprEffect effect) const { |
| Environment out = effect.hasGC() ? Environment() : Environment(*this); |
| - if (effect.env() != NULL) out.live_ |= effect.env()->live_; |
| + if (effect.env()) out |= *effect.env(); |
| return out; |
| } |
| @@ -342,20 +344,23 @@ class Environment { |
| bool IsAlive(const std::string& name) const { |
| SymbolTable::iterator code = symbol_table_.find(name); |
| if (code == symbol_table_.end()) return false; |
| - return live_[code->second]; |
| + return is_live(code->second); |
| } |
| bool Equal(const Environment& env) { |
| - return live_ == env.live_; |
| + if (unreachable_) return env.unreachable_; |
|
Michael Achenbach
2017/02/15 15:13:13
So, there's an invariant that if unreachable==true
Clemens Hammacher
2017/02/15 15:19:55
If unreachable==true, then is_live always returns
Vyacheslav Egorov (Google)
2017/02/15 15:48:15
This does not seem correct.
We have: env.unreach
Vyacheslav Egorov (Google)
2017/02/15 15:59:37
Clarification:
environment where unreachable_ is
|
| + size_t size = std::max(live_.size(), env.live_.size()); |
|
Michael Achenbach
2017/02/15 15:13:13
Maybe return false early if size differs?
Clemens Hammacher
2017/02/15 15:19:54
That would be a stronger check than before. In thi
Michael Starzinger
2017/02/15 15:20:12
Wouldn't that change semantics? If the size is dif
|
| + for (size_t i = 0; i < size; ++i) { |
| + if (is_live(i) != env.is_live(i)) return false; |
| + } |
| + return true; |
| } |
| Environment Define(const std::string& name) const { |
| return Environment(*this, SymbolToCode(name)); |
| } |
| - void MDefine(const std::string& name) { |
| - live_.set(SymbolToCode(name)); |
| - } |
| + void MDefine(const std::string& name) { set_live(SymbolToCode(name)); } |
| static int SymbolToCode(const std::string& name) { |
| SymbolTable::iterator code = symbol_table_.find(name); |
| @@ -370,12 +375,7 @@ class Environment { |
| } |
| static void ClearSymbolTable() { |
| - std::vector<Environment*>::iterator end = envs_.end(); |
| - for (std::vector<Environment*>::iterator i = envs_.begin(); |
| - i != end; |
| - ++i) { |
| - delete *i; |
| - } |
| + for (Environment* e : envs_) delete e; |
| envs_.clear(); |
| symbol_table_.clear(); |
| } |
| @@ -383,15 +383,11 @@ class Environment { |
| void Print() const { |
| bool comma = false; |
| std::cout << "{"; |
| - SymbolTable::iterator end = symbol_table_.end(); |
| - for (SymbolTable::iterator i = symbol_table_.begin(); |
| - i != end; |
| - ++i) { |
| - if (live_[i->second]) { |
| - if (comma) std::cout << ", "; |
| - std::cout << i->first; |
| - comma = true; |
| - } |
| + for (auto& e : symbol_table_) { |
| + if (!is_live(e.second)) continue; |
| + if (comma) std::cout << ", "; |
| + std::cout << e.first; |
| + comma = true; |
| } |
| std::cout << "}"; |
| } |
| @@ -403,20 +399,43 @@ class Environment { |
| } |
| private: |
| - Environment(const Environment& l, const Environment& r) |
| - : live_(l.live_ & r.live_) { |
| - } |
| - |
| Environment(const Environment& l, int code) |
| : live_(l.live_) { |
| - live_.set(code); |
| + set_live(code); |
| + } |
| + |
| + void set_live(size_t pos) { |
| + if (live_.size() <= pos) live_.resize(std::max(pos + 1, 2 * live_.size())); |
| + live_[pos] = true; |
| + } |
| + |
| + bool is_live(size_t pos) const { |
| + return unreachable_ || (live_.size() > pos && live_[pos]); |
| + } |
| + |
| + Environment& operator|=(const Environment& o) { |
| + unreachable_ |= o.unreachable_; |
| + for (size_t i = 0, e = o.live_.size(); i < e; ++i) { |
|
Vyacheslav Egorov (Google)
2017/02/15 15:59:36
if one of the envs is unreachable we should just m
|
| + if (o.live_[i]) set_live(i); |
| + } |
| + return *this; |
| + } |
| + |
| + Environment& operator&=(const Environment& o) { |
| + unreachable_ &= o.unreachable_; |
| + size_t size = std::min(live_.size(), o.live_.size()); |
|
Vyacheslav Egorov (Google)
2017/02/15 15:48:15
This seems highly suspicious:
if o.unreachable_
Vyacheslav Egorov (Google)
2017/02/15 15:59:36
Clarification: the same problem with o and this. I
|
| + if (live_.size() > size) live_.resize(size); |
| + for (size_t i = 0; i < size; ++i) { |
| + if (live_[i] && (i > o.live_.size() || !o.live_[i])) live_[i] = false; |
| + } |
| + return *this; |
| } |
| static SymbolTable symbol_table_; |
| - static std::vector<Environment* > envs_; |
| + static std::vector<Environment*> envs_; |
| - static const int kMaxNumberOfLocals = 256; |
| - std::bitset<kMaxNumberOfLocals> live_; |
| + std::vector<bool> live_; |
| + bool unreachable_ = false; |
| friend class ExprEffect; |
| friend class CallProps; |
| @@ -432,8 +451,11 @@ class CallProps { |
| if (in.hasRawDef()) raw_def_.set(arg); |
| if (in.hasRawUse()) raw_use_.set(arg); |
| if (in.env() != NULL) { |
| - if (env_ == NULL) env_ = in.env(); |
| - env_->live_ |= in.env()->live_; |
| + if (env_ == NULL) { |
| + env_ = in.env(); |
| + } else { |
| + *env_ |= *in.env(); |
| + } |
| } |
| } |
| @@ -462,8 +484,7 @@ class CallProps { |
| Environment::SymbolTable Environment::symbol_table_; |
| -std::vector<Environment* > Environment::envs_; |
| - |
| +std::vector<Environment*> Environment::envs_; |
| ExprEffect ExprEffect::Merge(ExprEffect a, ExprEffect b) { |
| Environment* a_env = a.env(); |
| @@ -471,7 +492,7 @@ ExprEffect ExprEffect::Merge(ExprEffect a, ExprEffect b) { |
| Environment* out = NULL; |
| if (a_env != NULL && b_env != NULL) { |
| out = Environment::Allocate(*a_env); |
| - out->live_ &= b_env->live_; |
| + *out &= *b_env; |
| } |
| return ExprEffect(a.effect_ | b.effect_, out); |
| } |
| @@ -483,7 +504,7 @@ ExprEffect ExprEffect::MergeSeq(ExprEffect a, ExprEffect b) { |
| Environment* out = (b_env == NULL) ? a_env : b_env; |
| if (a_env != NULL && b_env != NULL) { |
| out = Environment::Allocate(*b_env); |
| - out->live_ |= a_env->live_; |
| + *out |= *a_env; |
| } |
| return ExprEffect(a.effect_ | b.effect_, out); |
| } |