blob: 6c5ce890d2cb64fe8c437bf99c96efb144786357 [file] [log] [blame]
Steve Block44f0eee2011-05-26 01:26:41 +01001// 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
35namespace v8 {
36namespace 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.
42template <typename T>
43class SmallPointerList {
44 public:
45 SmallPointerList() : data_(kEmptyTag) {}
46
Ben Murdoch69a99ed2011-11-30 16:03:39 +000047 explicit SmallPointerList(int capacity) : data_(kEmptyTag) {
48 Reserve(capacity);
49 }
50
51 void Reserve(int capacity) {
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());
57 list()->Rewind(old_length);
58 return;
59 }
60 PointerList* list = new PointerList(capacity);
61 if ((data_ & kTagMask) == kSingletonTag) {
62 list->Add(single_value());
63 }
64 ASSERT(IsAligned(reinterpret_cast<intptr_t>(list), kPointerAlignment));
65 data_ = reinterpret_cast<intptr_t>(list) | kListTag;
66 }
67
68 void Clear() {
69 data_ = kEmptyTag;
70 }
71
Steve Block44f0eee2011-05-26 01:26:41 +010072 bool is_empty() const { return length() == 0; }
73
74 int length() const {
75 if ((data_ & kTagMask) == kEmptyTag) return 0;
76 if ((data_ & kTagMask) == kSingletonTag) return 1;
77 return list()->length();
78 }
79
80 void Add(T* pointer) {
81 ASSERT(IsAligned(reinterpret_cast<intptr_t>(pointer), kPointerAlignment));
82 if ((data_ & kTagMask) == kEmptyTag) {
83 data_ = reinterpret_cast<intptr_t>(pointer) | kSingletonTag;
84 return;
85 }
86 if ((data_ & kTagMask) == kSingletonTag) {
87 PointerList* list = new PointerList(2);
88 list->Add(single_value());
89 list->Add(pointer);
90 ASSERT(IsAligned(reinterpret_cast<intptr_t>(list), kPointerAlignment));
91 data_ = reinterpret_cast<intptr_t>(list) | kListTag;
92 return;
93 }
94 list()->Add(pointer);
95 }
96
97 // Note: returns T* and not T*& (unlike List from list.h).
98 // This makes the implementation simpler and more const correct.
99 T* at(int i) const {
100 ASSERT((data_ & kTagMask) != kEmptyTag);
101 if ((data_ & kTagMask) == kSingletonTag) {
102 ASSERT(i == 0);
103 return single_value();
104 }
105 return list()->at(i);
106 }
107
108 // See the note above.
109 T* operator[](int i) const { return at(i); }
110
111 // Remove the given element from the list (if present).
112 void RemoveElement(T* pointer) {
113 if ((data_ & kTagMask) == kEmptyTag) return;
114 if ((data_ & kTagMask) == kSingletonTag) {
115 if (pointer == single_value()) {
116 data_ = kEmptyTag;
117 }
118 return;
119 }
120 list()->RemoveElement(pointer);
121 }
122
123 T* RemoveLast() {
124 ASSERT((data_ & kTagMask) != kEmptyTag);
125 if ((data_ & kTagMask) == kSingletonTag) {
126 T* result = single_value();
127 data_ = kEmptyTag;
128 return result;
129 }
130 return list()->RemoveLast();
131 }
132
133 void Rewind(int pos) {
134 if ((data_ & kTagMask) == kEmptyTag) {
135 ASSERT(pos == 0);
136 return;
137 }
138 if ((data_ & kTagMask) == kSingletonTag) {
139 ASSERT(pos == 0 || pos == 1);
140 if (pos == 0) {
141 data_ = kEmptyTag;
142 }
143 return;
144 }
145 list()->Rewind(pos);
146 }
147
148 int CountOccurrences(T* pointer, int start, int end) const {
149 if ((data_ & kTagMask) == kEmptyTag) return 0;
150 if ((data_ & kTagMask) == kSingletonTag) {
151 if (start == 0 && end >= 0) {
152 return (single_value() == pointer) ? 1 : 0;
153 }
154 return 0;
155 }
156 return list()->CountOccurrences(pointer, start, end);
157 }
158
159 private:
160 typedef ZoneList<T*> PointerList;
161
162 static const intptr_t kEmptyTag = 1;
163 static const intptr_t kSingletonTag = 0;
164 static const intptr_t kListTag = 2;
165 static const intptr_t kTagMask = 3;
166 static const intptr_t kValueMask = ~kTagMask;
167
168 STATIC_ASSERT(kTagMask + 1 <= kPointerAlignment);
169
170 T* single_value() const {
171 ASSERT((data_ & kTagMask) == kSingletonTag);
172 STATIC_ASSERT(kSingletonTag == 0);
173 return reinterpret_cast<T*>(data_);
174 }
175
176 PointerList* list() const {
177 ASSERT((data_ & kTagMask) == kListTag);
178 return reinterpret_cast<PointerList*>(data_ & kValueMask);
179 }
180
181 intptr_t data_;
182
183 DISALLOW_COPY_AND_ASSIGN(SmallPointerList);
184};
185
186} } // namespace v8::internal
187
188#endif // V8_SMALL_POINTER_LIST_H_