Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(558)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/util/setlet.dart

Issue 27510002: Add a much simplified set implementation designed to waste little memory for small sets. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library dart2js.util.setlet;
6
7 class Setlet<E> {
8 static const _MARKER = const _SetletMarker();
9 static const CAPACITY = 8;
10
11 // The setlet can be in one of four states:
12 //
13 // * Empty (extra: null, contents: marker)
14 // * Single element (extra: null, contents: element)
15 // * List-backed (extra: length, contents: list)
16 // * Set-backed (extra: marker, contents: set)
17 //
18 // When the setlet is list-backed, the list in the contents field
19 // may have empty slots filled with the marker value.
20 var _contents = _MARKER;
21 var _extra;
22
23 Iterator<E> get iterator {
24 if (_extra == null) {
25 return new _SetletSingleIterator<E>(_contents);
26 } else if (_MARKER == _extra) {
27 return _contents.iterator;
28 } else {
29 return new _SetletListIterator<E>(_contents, _extra);
30 }
31 }
32
33 int get length {
34 if (_extra == null) {
35 return (_MARKER == _contents) ? 0 : 1;
36 } else if (_MARKER == _extra) {
37 return _contents.length;
38 } else {
39 return _extra;
40 }
41 }
42
43 bool get isEmpty {
44 if (_extra == null) {
45 return _MARKER == _contents;
46 } else if (_MARKER == _extra) {
47 return _contents.isEmpty;
48 } else {
49 return _extra == 0;
50 }
51 }
52
53 bool contains(E element) {
54 if (_extra == null) {
55 return _contents == element;
56 } else if (_MARKER == _extra) {
57 return _contents.contains(element);
58 } else {
59 for (int remaining = _extra, i = 0; remaining > 0 && i < CAPACITY; i++) {
60 var candidate = _contents[i];
61 if (_MARKER == candidate) continue;
62 if (candidate == element) return true;
63 remaining--;
64 }
65 return false;
66 }
67 }
68
69 bool remove(E element) {
70 if (_extra == null) {
71 if (_contents == element) {
72 _contents = _MARKER;
73 return true;
74 } else {
75 return false;
76 }
77 } else if (_MARKER == _extra) {
78 return _contents.remove(element);
79 } else {
80 for (int remaining = _extra, i = 0; remaining > 0 && i < CAPACITY; i++) {
81 var candidate = _contents[i];
82 if (_MARKER == candidate) continue;
83 if (candidate == element) {
84 _contents[i] = _MARKER;
85 _extra--;
86 return true;
87 }
88 remaining--;
89 }
90 return false;
91 }
92 }
93
94 void add(E element) {
95 if (_extra == null) {
96 if (_MARKER == _contents) {
97 _contents = element;
98 } else if (_contents == element) {
99 // Do nothing.
100 } else {
101 List list = new List(CAPACITY);
102 list[0] = _contents;
103 list[1] = element;
104 _contents = list;
105 _extra = 2; // Two elements.
106 }
107 } else if (_MARKER == _extra) {
108 _contents.add(element);
109 } else {
110 int remaining = _extra;
111 int index = 0;
112 int copyTo, copyFrom;
113 while (remaining > 0 && index < CAPACITY) {
114 var candidate = _contents[index++];
115 if (_MARKER == candidate) {
116 // Keep track of the last range of empty slots in the
117 // list. When we're done we'll move all the elements
118 // after those empty slots down, so that adding an element
119 // after that will preserve the insertion order.
120 if (copyFrom == index - 1) {
121 copyFrom++;
122 } else {
123 copyTo = index - 1;
124 copyFrom = index;
125 }
126 continue;
127 } else if (candidate == element) {
128 return;
129 }
130 remaining--;
131 }
132 if (index < CAPACITY) {
133 _contents[index] = element;
134 _extra++;
135 } else if (_extra < CAPACITY) {
136 // Move the last elements down into the last empty slots
137 // so that we have empty slots after the last element.
138 while (copyFrom < CAPACITY) {
139 _contents[copyTo++] = _contents[copyFrom++];
140 }
141 // Insert the new element as the last element.
142 _contents[copyTo++] = element;
143 _extra++;
144 // Clear all elements after the new last elements to
145 // make sure we don't keep extra stuff alive.
146 while (copyTo < CAPACITY) _contents[copyTo++] = null;
147 } else {
148 _contents = new Set<E>()..addAll(_contents)..add(element);
149 _extra = _MARKER;
150 }
151 }
152 }
153
154 void forEach(void action(E element)) {
155 if (_extra == null) {
156 if (_MARKER != _contents) action(_contents);
157 } else if (_MARKER == _extra) {
158 _contents.forEach(action);
159 } else {
160 for (int remaining = _extra, i = 0; remaining > 0 && i < CAPACITY; i++) {
161 var element = _contents[i];
162 if (_MARKER == element) continue;
163 action(element);
164 remaining--;
165 }
166 }
167 }
168 }
169
170 class _SetletMarker {
171 const _SetletMarker();
172 toString() => "-";
173 }
174
175 class _SetletSingleIterator<E> implements Iterator<E> {
176 var _element;
177 E _current;
178 _SetletSingleIterator(this._element);
179
180 E get current => _current;
181
182 bool moveNext() {
183 if (Setlet._MARKER == _element) {
184 _current = null;
185 return false;
186 }
187 _current = _element;
188 _element = Setlet._MARKER;
189 return true;
190 }
191 }
192
193 class _SetletListIterator<E> implements Iterator<E> {
194 final List _list;
195 int _remaining;
196 int _index = 0;
197 E _current;
198 _SetletListIterator(this._list, this._remaining);
199
200 E get current => _current;
201
202 bool moveNext() {
203 while (_remaining > 0) {
204 var candidate = _list[_index++];
205 if (Setlet._MARKER != candidate) {
206 _current = candidate;
207 _remaining--;
208 return true;
209 }
210 }
211 _current = null;
212 return false;
213 }
214 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698