[llvm-commits] [llvm] r41142 - /llvm/trunk/include/llvm/ADT/ilist
Chris Lattner
sabre at nondot.org
Fri Aug 17 09:49:19 PDT 2007
Author: lattner
Date: Fri Aug 17 11:49:19 2007
New Revision: 41142
URL: http://llvm.org/viewvc/llvm-project?rev=41142&view=rev
Log:
improve iplist comments. Switch iplist from allocating its sentinal object (for
end()) eagerly to allocating it lazily. This saves a lot of memory for JIT applications
that read a module but don't materialize most of the functions (e.g. 62K for 252.eon).
Modified:
llvm/trunk/include/llvm/ADT/ilist
Modified: llvm/trunk/include/llvm/ADT/ilist
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/ilist?rev=41142&r1=41141&r2=41142&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/ilist (original)
+++ llvm/trunk/include/llvm/ADT/ilist Fri Aug 17 11:49:19 2007
@@ -212,13 +212,29 @@
//===----------------------------------------------------------------------===//
//
-// iplist - The subset of list functionality that can safely be used on nodes of
-// polymorphic types, i.e. a heterogenous list with a common base class that
-// holds the next/prev pointers...
-//
+/// iplist - The subset of list functionality that can safely be used on nodes
+/// of polymorphic types, i.e. a heterogenous list with a common base class that
+/// holds the next/prev pointers. The only state of the list itself is a single
+/// pointer to the head of the list.
+///
+/// This list can be in one of three interesting states:
+/// 1. The list may be completely unconstructed. In this case, the head
+/// pointer is null. When in this form, any query for an iterator (e.g.
+/// begin() or end()) causes the list to transparently change to state #2.
+/// 2. The list may be empty, but contain a sentinal for the end iterator. This
+/// sentinal is created by the Traits::createSentinel method and is a link
+/// in the list. When the list is empty, the pointer in the iplist points
+/// to the sentinal. Once the sentinal is constructed, it
+/// is not destroyed until the list is.
+/// 3. The list may contain actual objects in it, which are stored as a doubly
+/// linked list of nodes. One invariant of the list is that the predecessor
+/// of the first node in the list always points to the last node in the list,
+/// and the successor pointer for the sentinal (which always stays at the
+/// end of the list) is always null.
+///
template<typename NodeTy, typename Traits=ilist_traits<NodeTy> >
class iplist : public Traits {
- NodeTy *Head;
+ mutable NodeTy *Head;
// Use the prev node pointer of 'head' as the tail pointer. This is really a
// circularly linked list where we snip the 'next' link from the sentinel node
@@ -226,7 +242,16 @@
// the end of the list).
NodeTy *getTail() { return getPrev(Head); }
const NodeTy *getTail() const { return getPrev(Head); }
- void setTail(NodeTy *N) { setPrev(Head, N); }
+ void setTail(NodeTy *N) const { setPrev(Head, N); }
+
+ /// CreateLazySentinal - This method verifies whether the sentinal for the
+ /// list has been created and lazily makes it if not.
+ void CreateLazySentinal() const {
+ if (Head != 0) return;
+ Head = Traits::createSentinel();
+ setNext(Head, 0);
+ setTail(Head);
+ }
static bool op_less(NodeTy &L, NodeTy &R) { return L < R; }
static bool op_equal(NodeTy &L, NodeTy &R) { return L == R; }
@@ -243,28 +268,41 @@
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
- iplist() : Head(Traits::createSentinel()) {
- setNext(Head, 0);
- setTail(Head);
+ iplist() : Head(0) {}
+ ~iplist() {
+ if (!Head) return;
+ clear();
+ Traits::destroySentinel(getTail());
}
- ~iplist() { clear(); Traits::destroySentinel(getTail()); }
// Iterator creation methods.
- iterator begin() { return iterator(Head); }
- const_iterator begin() const { return const_iterator(Head); }
- iterator end() { return iterator(getTail()); }
- const_iterator end() const { return const_iterator(getTail()); }
+ iterator begin() {
+ CreateLazySentinal();
+ return iterator(Head);
+ }
+ const_iterator begin() const {
+ CreateLazySentinal();
+ return const_iterator(Head);
+ }
+ iterator end() {
+ CreateLazySentinal();
+ return iterator(getTail());
+ }
+ const_iterator end() const {
+ CreateLazySentinal();
+ return const_iterator(getTail());
+ }
// reverse iterator creation methods.
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
- const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
+ const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
// Miscellaneous inspection routines.
size_type max_size() const { return size_type(-1); }
- bool empty() const { return Head == getTail(); }
+ bool empty() const { return Head == 0 || Head == getTail(); }
// Front and back accessor functions...
reference front() {
@@ -386,6 +424,7 @@
//
size_type size() const {
+ if (Head == 0) return 0; // Don't require construction of sentinal if empty.
#if __GNUC__ == 2
// GCC 2.95 has a broken std::distance
size_type Result = 0;
@@ -402,7 +441,7 @@
return last;
}
- void clear() { erase(begin(), end()); }
+ void clear() { if (Head) erase(begin(), end()); }
// Front and back inserters...
void push_front(NodeTy *val) { insert(begin(), val); }
More information about the llvm-commits
mailing list