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

Side by Side Diff: runtime/lib/growable_array.dart

Issue 2968003004: Revert "The current growth strategy for growable arrays allocates a backing array of size 2 at (emp… (Closed)
Patch Set: Created 3 years, 5 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
« no previous file with comments | « runtime/lib/growable_array.cc ('k') | runtime/lib/stacktrace.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 class _GrowableList<T> extends ListBase<T> { 5 class _GrowableList<T> extends ListBase<T> {
6 void insert(int index, T element) { 6 void insert(int index, T element) {
7 if ((index < 0) || (index > length)) { 7 if ((index < 0) || (index > length)) {
8 throw new RangeError.range(index, 0, length); 8 throw new RangeError.range(index, 0, length);
9 } 9 }
10 if (index == this.length) { 10 if (index == this.length) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 if (length == 0) return <T>[]; 80 if (length == 0) return <T>[];
81 List list = new _List(length); 81 List list = new _List(length);
82 for (int i = 0; i < length; i++) { 82 for (int i = 0; i < length; i++) {
83 list[i] = this[start + i]; 83 list[i] = this[start + i];
84 } 84 }
85 var result = new _GrowableList<T>.withData(list); 85 var result = new _GrowableList<T>.withData(list);
86 result._setLength(length); 86 result._setLength(length);
87 return result; 87 return result;
88 } 88 }
89 89
90 static const int _kDefaultCapacity = 2;
91
90 factory _GrowableList(int length) { 92 factory _GrowableList(int length) {
91 var data = _allocateData(length); 93 var data = new _List((length == 0) ? _kDefaultCapacity : length);
92 var result = new _GrowableList<T>.withData(data); 94 var result = new _GrowableList<T>.withData(data);
93 if (length > 0) { 95 if (length > 0) {
94 result._setLength(length); 96 result._setLength(length);
95 } 97 }
96 return result; 98 return result;
97 } 99 }
98 100
99 factory _GrowableList.withCapacity(int capacity) { 101 factory _GrowableList.withCapacity(int capacity) {
100 var data = _allocateData(capacity); 102 var data = new _List((capacity == 0) ? _kDefaultCapacity : capacity);
101 return new _GrowableList<T>.withData(data); 103 return new _GrowableList<T>.withData(data);
102 } 104 }
103 105
104 factory _GrowableList.withData(_List data) native "GrowableList_allocate"; 106 factory _GrowableList.withData(_List data) native "GrowableList_allocate";
105 107
106 int get _capacity native "GrowableList_getCapacity"; 108 int get _capacity native "GrowableList_getCapacity";
107 109
108 int get length native "GrowableList_getLength"; 110 int get length native "GrowableList_getLength";
109 111
110 void set length(int new_length) { 112 void set length(int new_length) {
111 int old_capacity = _capacity; 113 int old_capacity = _capacity;
112 int new_capacity = new_length; 114 int new_capacity = new_length;
115 if (new_length == 0) {
116 // Ensure that we use _kDefaultCapacity only when the old_capacity
117 // is greater than _kDefaultCapacity otherwise we end up growing the
118 // the array.
119 if (old_capacity < _kDefaultCapacity) {
120 new_capacity = old_capacity;
121 } else {
122 new_capacity = _kDefaultCapacity;
123 }
124 }
113 if (new_capacity > old_capacity) { 125 if (new_capacity > old_capacity) {
114 _grow(new_capacity); 126 _grow(new_capacity);
115 _setLength(new_length); 127 _setLength(new_length);
116 return; 128 return;
117 } 129 }
118 // We are shrinking. Pick the method which has fewer writes. 130 // We are shrinking. Pick the method which has fewer writes.
119 // In the shrink-to-fit path, we write |new_capacity + new_length| words 131 // In the shrink-to-fit path, we write |new_capacity + new_length| words
120 // (null init + copy). 132 // (null init + copy).
121 // In the non-shrink-to-fit path, we write |length - new_length| words 133 // In the non-shrink-to-fit path, we write |length - new_length| words
122 // (null overwrite). 134 // (null overwrite).
(...skipping 10 matching lines...) Expand all
133 } 145 }
134 146
135 void _setLength(int new_length) native "GrowableList_setLength"; 147 void _setLength(int new_length) native "GrowableList_setLength";
136 148
137 void _setData(_List array) native "GrowableList_setData"; 149 void _setData(_List array) native "GrowableList_setData";
138 150
139 T operator [](int index) native "GrowableList_getIndexed"; 151 T operator [](int index) native "GrowableList_getIndexed";
140 152
141 void operator []=(int index, T value) native "GrowableList_setIndexed"; 153 void operator []=(int index, T value) native "GrowableList_setIndexed";
142 154
155 // The length of this growable array. It is always less than or equal to the
156 // length of the object array, which itself is always greater than 0, so that
157 // grow() does not have to check for a zero length object array before
158 // doubling its size.
143 void add(T value) { 159 void add(T value) {
144 var len = length; 160 var len = length;
145 if (len == _capacity) { 161 if (len == _capacity) {
146 _grow(_nextCapacity(len)); 162 _grow(len * 2);
147 } 163 }
148 _setLength(len + 1); 164 _setLength(len + 1);
149 this[len] = value; 165 this[len] = value;
150 } 166 }
151 167
152 void addAll(Iterable<T> iterable) { 168 void addAll(Iterable<T> iterable) {
153 var len = length; 169 var len = length;
154 final cid = ClassID.getID(iterable); 170 final cid = ClassID.getID(iterable);
155 final isVMList = (cid == ClassID.cidArray) || 171 final isVMList = (cid == ClassID.cidArray) ||
156 (cid == ClassID.cidGrowableObjectArray) || 172 (cid == ClassID.cidGrowableObjectArray) ||
157 (cid == ClassID.cidImmutableArray); 173 (cid == ClassID.cidImmutableArray);
158 if (isVMList || (iterable is EfficientLengthIterable)) { 174 if (isVMList || (iterable is EfficientLengthIterable)) {
159 var cap = _capacity; 175 var cap = _capacity;
160 // Pregrow if we know iterable.length. 176 // Pregrow if we know iterable.length.
161 var iterLen = iterable.length; 177 var iterLen = iterable.length;
162 var newLen = len + iterLen; 178 var newLen = len + iterLen;
163 if (newLen > cap) { 179 if (newLen > cap) {
164 do { 180 do {
165 cap = _nextCapacity(cap); 181 cap *= 2;
166 } while (newLen > cap); 182 } while (newLen > cap);
167 _grow(cap); 183 _grow(cap);
168 } 184 }
169 if (isVMList) { 185 if (isVMList) {
170 if (identical(iterable, this)) { 186 if (identical(iterable, this)) {
171 throw new ConcurrentModificationError(this); 187 throw new ConcurrentModificationError(this);
172 } 188 }
173 this._setLength(newLen); 189 this._setLength(newLen);
174 for (int i = 0; i < iterLen; i++) { 190 for (int i = 0; i < iterLen; i++) {
175 this[len++] = iterable[i]; 191 this[len++] = iterable[i];
176 } 192 }
177 return; 193 return;
178 } 194 }
179 } 195 }
180 Iterator it = iterable.iterator; 196 Iterator it = iterable.iterator;
181 if (!it.moveNext()) return; 197 if (!it.moveNext()) return;
182 do { 198 do {
183 while (len < _capacity) { 199 while (len < _capacity) {
184 int newLen = len + 1; 200 int newLen = len + 1;
185 this._setLength(newLen); 201 this._setLength(newLen);
186 this[len] = it.current; 202 this[len] = it.current;
187 if (!it.moveNext()) return; 203 if (!it.moveNext()) return;
188 if (this.length != newLen) throw new ConcurrentModificationError(this); 204 if (this.length != newLen) throw new ConcurrentModificationError(this);
189 len = newLen; 205 len = newLen;
190 } 206 }
191 _grow(_nextCapacity(_capacity)); 207 _grow(_capacity * 2);
192 } while (true); 208 } while (true);
193 } 209 }
194 210
195 T removeLast() { 211 T removeLast() {
196 var len = length - 1; 212 var len = length - 1;
197 var elem = this[len]; 213 var elem = this[len];
198 this.length = len; 214 this.length = len;
199 return elem; 215 return elem;
200 } 216 }
201 217
202 T get first { 218 T get first {
203 if (length > 0) return this[0]; 219 if (length > 0) return this[0];
204 throw IterableElementError.noElement(); 220 throw IterableElementError.noElement();
205 } 221 }
206 222
207 T get last { 223 T get last {
208 if (length > 0) return this[length - 1]; 224 if (length > 0) return this[length - 1];
209 throw IterableElementError.noElement(); 225 throw IterableElementError.noElement();
210 } 226 }
211 227
212 T get single { 228 T get single {
213 if (length == 1) return this[0]; 229 if (length == 1) return this[0];
214 if (length == 0) throw IterableElementError.noElement(); 230 if (length == 0) throw IterableElementError.noElement();
215 throw IterableElementError.tooMany(); 231 throw IterableElementError.tooMany();
216 ; 232 ;
217 } 233 }
218 234
219 // Shared array used as backing for new empty growable arrays. 235 void _grow(int new_capacity) {
220 static final _List _emptyList = new _List(0); 236 var new_data = new _List(new_capacity);
221 237 for (int i = 0; i < length; i++) {
222 static _List _allocateData(int capacity) { 238 new_data[i] = this[i];
223 if (capacity == 0) {
224 // Use shared empty list as backing.
225 return _emptyList;
226 } 239 }
227 // Round up size to the next odd number, since this is free 240 _setData(new_data);
228 // because of alignment requirements of the GC.
229 return new _List(capacity | 1);
230 }
231
232 // Grow from 0 to 3, and then double + 1.
233 int _nextCapacity(int old_capacity) => (old_capacity * 2) | 3;
234
235 void _grow(int new_capacity) {
236 var newData = _allocateData(new_capacity);
237 for (int i = 0; i < length; i++) {
238 newData[i] = this[i];
239 }
240 _setData(newData);
241 } 241 }
242 242
243 void _shrink(int new_capacity, int new_length) { 243 void _shrink(int new_capacity, int new_length) {
244 var newData = _allocateData(new_capacity); 244 var new_data = new _List(new_capacity);
245 for (int i = 0; i < new_length; i++) { 245 for (int i = 0; i < new_length; i++) {
246 newData[i] = this[i]; 246 new_data[i] = this[i];
247 } 247 }
248 _setData(newData); 248 _setData(new_data);
249 } 249 }
250 250
251 // Iterable interface. 251 // Iterable interface.
252 252
253 void forEach(f(T element)) { 253 void forEach(f(T element)) {
254 int initialLength = length; 254 int initialLength = length;
255 for (int i = 0; i < length; i++) { 255 for (int i = 0; i < length; i++) {
256 f(this[i]); 256 f(this[i]);
257 if (length != initialLength) throw new ConcurrentModificationError(this); 257 if (length != initialLength) throw new ConcurrentModificationError(this);
258 } 258 }
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 result._setLength(length); 358 result._setLength(length);
359 return result; 359 return result;
360 } 360 }
361 return growable ? <T>[] : new List<T>(0); 361 return growable ? <T>[] : new List<T>(0);
362 } 362 }
363 363
364 Set<T> toSet() { 364 Set<T> toSet() {
365 return new Set<T>.from(this); 365 return new Set<T>.from(this);
366 } 366 }
367 } 367 }
OLDNEW
« no previous file with comments | « runtime/lib/growable_array.cc ('k') | runtime/lib/stacktrace.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698