• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifndef V8_SMALL_POINTER_LIST_H_
29 #define V8_SMALL_POINTER_LIST_H_
30 
31 #include "checks.h"
32 #include "v8globals.h"
33 #include "zone.h"
34 
35 namespace v8 {
36 namespace internal {
37 
38 // SmallPointerList is a list optimized for storing no or just a
39 // single value. When more values are given it falls back to ZoneList.
40 //
41 // The interface tries to be as close to List from list.h as possible.
42 template <typename T>
43 class SmallPointerList {
44  public:
SmallPointerList()45   SmallPointerList() : data_(kEmptyTag) {}
46 
SmallPointerList(int capacity,Zone * zone)47   SmallPointerList(int capacity, Zone* zone) : data_(kEmptyTag) {
48     Reserve(capacity, zone);
49   }
50 
Reserve(int capacity,Zone * zone)51   void Reserve(int capacity, Zone* zone) {
52     if (capacity < 2) return;
53     if ((data_ & kTagMask) == kListTag) {
54       if (list()->capacity() >= capacity) return;
55       int old_length = list()->length();
56       list()->AddBlock(NULL, capacity - list()->capacity(), zone);
57       list()->Rewind(old_length);
58       return;
59     }
60     PointerList* list = new(zone) PointerList(capacity, zone);
61     if ((data_ & kTagMask) == kSingletonTag) {
62       list->Add(single_value(), zone);
63     }
64     ASSERT(IsAligned(reinterpret_cast<intptr_t>(list), kPointerAlignment));
65     data_ = reinterpret_cast<intptr_t>(list) | kListTag;
66   }
67 
Clear()68   void Clear() {
69     data_ = kEmptyTag;
70   }
71 
Sort()72   void Sort() {
73     if ((data_ & kTagMask) == kListTag) {
74       list()->Sort(compare_value);
75     }
76   }
77 
is_empty()78   bool is_empty() const { return length() == 0; }
79 
length()80   int length() const {
81     if ((data_ & kTagMask) == kEmptyTag) return 0;
82     if ((data_ & kTagMask) == kSingletonTag) return 1;
83     return list()->length();
84   }
85 
Add(T * pointer,Zone * zone)86   void Add(T* pointer, Zone* zone) {
87     ASSERT(IsAligned(reinterpret_cast<intptr_t>(pointer), kPointerAlignment));
88     if ((data_ & kTagMask) == kEmptyTag) {
89       data_ = reinterpret_cast<intptr_t>(pointer) | kSingletonTag;
90       return;
91     }
92     if ((data_ & kTagMask) == kSingletonTag) {
93       PointerList* list = new(zone) PointerList(2, zone);
94       list->Add(single_value(), zone);
95       list->Add(pointer, zone);
96       ASSERT(IsAligned(reinterpret_cast<intptr_t>(list), kPointerAlignment));
97       data_ = reinterpret_cast<intptr_t>(list) | kListTag;
98       return;
99     }
100     list()->Add(pointer, zone);
101   }
102 
103   // Note: returns T* and not T*& (unlike List from list.h).
104   // This makes the implementation simpler and more const correct.
at(int i)105   T* at(int i) const {
106     ASSERT((data_ & kTagMask) != kEmptyTag);
107     if ((data_ & kTagMask) == kSingletonTag) {
108       ASSERT(i == 0);
109       return single_value();
110     }
111     return list()->at(i);
112   }
113 
114   // See the note above.
115   T* operator[](int i) const { return at(i); }
116 
117   // Remove the given element from the list (if present).
RemoveElement(T * pointer)118   void RemoveElement(T* pointer) {
119     if ((data_ & kTagMask) == kEmptyTag) return;
120     if ((data_ & kTagMask) == kSingletonTag) {
121       if (pointer == single_value()) {
122         data_ = kEmptyTag;
123       }
124       return;
125     }
126     list()->RemoveElement(pointer);
127   }
128 
RemoveLast()129   T* RemoveLast() {
130     ASSERT((data_ & kTagMask) != kEmptyTag);
131     if ((data_ & kTagMask) == kSingletonTag) {
132       T* result = single_value();
133       data_ = kEmptyTag;
134       return result;
135     }
136     return list()->RemoveLast();
137   }
138 
Rewind(int pos)139   void Rewind(int pos) {
140     if ((data_ & kTagMask) == kEmptyTag) {
141       ASSERT(pos == 0);
142       return;
143     }
144     if ((data_ & kTagMask) == kSingletonTag) {
145       ASSERT(pos == 0 || pos == 1);
146       if (pos == 0) {
147         data_ = kEmptyTag;
148       }
149       return;
150     }
151     list()->Rewind(pos);
152   }
153 
CountOccurrences(T * pointer,int start,int end)154   int CountOccurrences(T* pointer, int start, int end) const {
155     if ((data_ & kTagMask) == kEmptyTag) return 0;
156     if ((data_ & kTagMask) == kSingletonTag) {
157       if (start == 0 && end >= 0) {
158         return (single_value() == pointer) ? 1 : 0;
159       }
160       return 0;
161     }
162     return list()->CountOccurrences(pointer, start, end);
163   }
164 
165  private:
166   typedef ZoneList<T*> PointerList;
167 
compare_value(T * const * a,T * const * b)168   static int compare_value(T* const* a, T* const* b) {
169     return Compare<T>(**a, **b);
170   }
171 
172   static const intptr_t kEmptyTag = 1;
173   static const intptr_t kSingletonTag = 0;
174   static const intptr_t kListTag = 2;
175   static const intptr_t kTagMask = 3;
176   static const intptr_t kValueMask = ~kTagMask;
177 
178   STATIC_ASSERT(kTagMask + 1 <= kPointerAlignment);
179 
single_value()180   T* single_value() const {
181     ASSERT((data_ & kTagMask) == kSingletonTag);
182     STATIC_ASSERT(kSingletonTag == 0);
183     return reinterpret_cast<T*>(data_);
184   }
185 
list()186   PointerList* list() const {
187     ASSERT((data_ & kTagMask) == kListTag);
188     return reinterpret_cast<PointerList*>(data_ & kValueMask);
189   }
190 
191   intptr_t data_;
192 
193   DISALLOW_COPY_AND_ASSIGN(SmallPointerList);
194 };
195 
196 } }  // namespace v8::internal
197 
198 #endif  // V8_SMALL_POINTER_LIST_H_
199