Commit 86262b2a authored by bratell@opera.com's avatar bratell@opera.com

Make ObserverList non-inline to save 90KB with gcc

With gcc, ObserverList expands to 6-700 bytes every time it is 
iterated. By not trying to force OberservListBase to be inline
that shrinks some. clang already ignores the hints to inline 
the code and actually doesn't change a single bit in the generated
program with this change.

raw data:
Total change: -90875 bytes
==========================
  262 added, totalling +39188 bytes across 2 sources
  49 removed, totalling -27573 bytes across 16 sources
  23 grown, for a net change of +3600 bytes (34968 bytes before, 38568 bytes after) across 8 sources
  228 shrunk, for a net change of -106090 bytes (239819 bytes before, 133729 bytes after) across 53 sources

The additions is about 2-300 different flavours of ObserverListBase, 100-300 bytes each.

The savings are 200-600 bytes each every time an observer list is used. For example:

-870: content::RenderFrameImpl::didFailLoad(blink::WebLocalFrame*, blink::WebURLError const&) type=t, (was 1635 bytes, 
now 765 bytes)
-895: content::RenderFrameImpl::didFinishLoad(blink::WebLocalFrame*) type=t, (was 1646 bytes, now 751 bytes)
-583: content::WebContentsImpl::DidFailProvisionalLoadWithError(content::RenderFrameHostImpl*, FrameHostMsg_DidFailProvisionalLoadWithError_Params const&) type=t, (was 768 bytes, now 185 bytes)
-611: content::WebContentsImpl::DidStartProvisionalLoad(content::RenderFrameHostImpl*, GURL const&, bool, bool) type=t, (was 895 bytes, now 284 bytes)

BUG=394311

Review URL: https://codereview.chromium.org/396473004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@283762 0039d316-1c4b-4281-b951-d872f2087c98
parent 34f8cf51
...@@ -79,30 +79,9 @@ class ObserverListBase ...@@ -79,30 +79,9 @@ class ObserverListBase
// also the FOR_EACH_OBSERVER macro defined below. // also the FOR_EACH_OBSERVER macro defined below.
class Iterator { class Iterator {
public: public:
Iterator(ObserverListBase<ObserverType>& list) Iterator(ObserverListBase<ObserverType>& list);
: list_(list.AsWeakPtr()), ~Iterator();
index_(0), ObserverType* GetNext();
max_index_(list.type_ == NOTIFY_ALL ?
std::numeric_limits<size_t>::max() :
list.observers_.size()) {
++list_->notify_depth_;
}
~Iterator() {
if (list_.get() && --list_->notify_depth_ == 0)
list_->Compact();
}
ObserverType* GetNext() {
if (!list_.get())
return NULL;
ListType& observers = list_->observers_;
// Advance if the current element is null
size_t max_index = std::min(max_index_, observers.size());
while (index_ < max_index && !observers[index_])
++index_;
return index_ < max_index ? observers[index_++] : NULL;
}
private: private:
base::WeakPtr<ObserverListBase<ObserverType> > list_; base::WeakPtr<ObserverListBase<ObserverType> > list_;
...@@ -116,55 +95,19 @@ class ObserverListBase ...@@ -116,55 +95,19 @@ class ObserverListBase
// Add an observer to the list. An observer should not be added to // Add an observer to the list. An observer should not be added to
// the same list more than once. // the same list more than once.
void AddObserver(ObserverType* obs) { void AddObserver(ObserverType* obs);
if (std::find(observers_.begin(), observers_.end(), obs)
!= observers_.end()) {
NOTREACHED() << "Observers can only be added once!";
return;
}
observers_.push_back(obs);
}
// Remove an observer from the list if it is in the list. // Remove an observer from the list if it is in the list.
void RemoveObserver(ObserverType* obs) { void RemoveObserver(ObserverType* obs);
typename ListType::iterator it =
std::find(observers_.begin(), observers_.end(), obs);
if (it != observers_.end()) {
if (notify_depth_) {
*it = 0;
} else {
observers_.erase(it);
}
}
}
bool HasObserver(ObserverType* observer) const { bool HasObserver(ObserverType* observer) const;
for (size_t i = 0; i < observers_.size(); ++i) {
if (observers_[i] == observer)
return true;
}
return false;
}
void Clear() { void Clear();
if (notify_depth_) {
for (typename ListType::iterator it = observers_.begin();
it != observers_.end(); ++it) {
*it = 0;
}
} else {
observers_.clear();
}
}
protected: protected:
size_t size() const { return observers_.size(); } size_t size() const { return observers_.size(); }
void Compact() { void Compact();
observers_.erase(
std::remove(observers_.begin(), observers_.end(),
static_cast<ObserverType*>(NULL)), observers_.end());
}
private: private:
friend class ObserverListThreadSafe<ObserverType>; friend class ObserverListThreadSafe<ObserverType>;
...@@ -180,6 +123,86 @@ class ObserverListBase ...@@ -180,6 +123,86 @@ class ObserverListBase
DISALLOW_COPY_AND_ASSIGN(ObserverListBase); DISALLOW_COPY_AND_ASSIGN(ObserverListBase);
}; };
template <class ObserverType>
ObserverListBase<ObserverType>::Iterator::Iterator(
ObserverListBase<ObserverType>& list)
: list_(list.AsWeakPtr()),
index_(0),
max_index_(list.type_ == NOTIFY_ALL ?
std::numeric_limits<size_t>::max() :
list.observers_.size()) {
++list_->notify_depth_;
}
template <class ObserverType>
ObserverListBase<ObserverType>::Iterator::~Iterator() {
if (list_.get() && --list_->notify_depth_ == 0)
list_->Compact();
}
template <class ObserverType>
ObserverType* ObserverListBase<ObserverType>::Iterator::GetNext() {
if (!list_.get())
return NULL;
ListType& observers = list_->observers_;
// Advance if the current element is null
size_t max_index = std::min(max_index_, observers.size());
while (index_ < max_index && !observers[index_])
++index_;
return index_ < max_index ? observers[index_++] : NULL;
}
template <class ObserverType>
void ObserverListBase<ObserverType>::AddObserver(ObserverType* obs) {
if (std::find(observers_.begin(), observers_.end(), obs)
!= observers_.end()) {
NOTREACHED() << "Observers can only be added once!";
return;
}
observers_.push_back(obs);
}
template <class ObserverType>
void ObserverListBase<ObserverType>::RemoveObserver(ObserverType* obs) {
typename ListType::iterator it =
std::find(observers_.begin(), observers_.end(), obs);
if (it != observers_.end()) {
if (notify_depth_) {
*it = 0;
} else {
observers_.erase(it);
}
}
}
template <class ObserverType>
bool ObserverListBase<ObserverType>::HasObserver(ObserverType* observer) const {
for (size_t i = 0; i < observers_.size(); ++i) {
if (observers_[i] == observer)
return true;
}
return false;
}
template <class ObserverType>
void ObserverListBase<ObserverType>::Clear() {
if (notify_depth_) {
for (typename ListType::iterator it = observers_.begin();
it != observers_.end(); ++it) {
*it = 0;
}
} else {
observers_.clear();
}
}
template <class ObserverType>
void ObserverListBase<ObserverType>::Compact() {
observers_.erase(
std::remove(observers_.begin(), observers_.end(),
static_cast<ObserverType*>(NULL)), observers_.end());
}
template <class ObserverType, bool check_empty = false> template <class ObserverType, bool check_empty = false>
class ObserverList : public ObserverListBase<ObserverType> { class ObserverList : public ObserverListBase<ObserverType> {
public: public:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment