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

Side by Side Diff: pkg/analyzer/lib/src/util/fast_uri.dart

Issue 2284483002: Detect the VM's Uri hashCode computation algorithm and use it in FastUri. (Closed)
Patch Set: Created 4 years, 3 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 | « no previous file | no next file » | 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) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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 import 'dart:collection'; 5 import 'dart:collection';
6 6
7 /** 7 /**
8 * Implementation of [Uri] that understands only a limited set of valid 8 * Implementation of [Uri] that understands only a limited set of valid
9 * URI formats, but works fast. In practice Dart code almost always uses such 9 * URI formats, but works fast. In practice Dart code almost always uses such
10 * limited URI format, so almost always can be processed fast. 10 * limited URI format, so almost always can be processed fast.
11 */ 11 */
12 class FastUri implements Uri { 12 class FastUri implements Uri {
13 /*** 13 /***
14 * The maximum [_cache] length before we flush it and start a new generation. 14 * The maximum [_cache] length before we flush it and start a new generation.
15 */ 15 */
16 static const int _MAX_CACHE_LENGTH_BEFORE_FLUSH = 50000; 16 static const int _MAX_CACHE_LENGTH_BEFORE_FLUSH = 50000;
17 17
18 static HashMap<String, Uri> _cache = new HashMap<String, Uri>(); 18 static HashMap<String, Uri> _cache = new HashMap<String, Uri>();
19 static int _currentCacheLength = 0; 19 static int _currentCacheLength = 0;
20 static int _currentCacheGeneration = 0; 20 static int _currentCacheGeneration = 0;
21 21
22 static bool _hashUsingText = _shouldComputeHashCodeUsingText();
23
22 final int _cacheGeneration; 24 final int _cacheGeneration;
23 final String _text; 25 final String _text;
24 final String _scheme; 26 final String _scheme;
25 final bool _hasEmptyAuthority; 27 final bool _hasEmptyAuthority;
26 final String _path; 28 final String _path;
27 29
28 /** 30 /**
29 * The offset of the last `/` in [_text], or `null` if there isn't any. 31 * The offset of the last `/` in [_text], or `null` if there isn't any.
30 */ 32 */
31 final int _lastSlashIndex; 33 final int _lastSlashIndex;
32 34
35 /**
36 * The cached hash code.
37 */
38 int _hashCode;
39
33 Uri _cachedFallbackUri; 40 Uri _cachedFallbackUri;
34 41
35 FastUri._(this._cacheGeneration, this._text, this._scheme, 42 FastUri._(this._cacheGeneration, this._text, this._scheme,
36 this._hasEmptyAuthority, this._path, this._lastSlashIndex); 43 this._hasEmptyAuthority, this._path, this._lastSlashIndex);
37 44
38 @override 45 @override
39 String get authority => ''; 46 String get authority => '';
40 47
41 @override 48 @override
42 UriData get data => null; 49 UriData get data => null;
43 50
44 @override 51 @override
45 String get fragment => ''; 52 String get fragment => '';
46 53
47 @override 54 @override
48 bool get hasAbsolutePath => path.startsWith('/'); 55 bool get hasAbsolutePath => path.startsWith('/');
49 56
50 @override 57 @override
51 bool get hasAuthority => _hasEmptyAuthority; 58 bool get hasAuthority => _hasEmptyAuthority;
52 59
53 @override 60 @override
54 bool get hasEmptyPath => _path.isEmpty; 61 bool get hasEmptyPath => _path.isEmpty;
55 62
56 @override 63 @override
57 bool get hasFragment => false; 64 bool get hasFragment => false;
58 65
59 @override 66 @override
60 int get hashCode => _text.hashCode; 67 int get hashCode {
68 return _hashCode ??= _hashUsingText
69 ? _computeHashUsingText(this)
70 : _computeHashUsingCombine(this);
71 }
61 72
62 @override 73 @override
63 bool get hasPort => false; 74 bool get hasPort => false;
64 75
65 @override 76 @override
66 bool get hasQuery => false; 77 bool get hasQuery => false;
67 78
68 @override 79 @override
69 bool get hasScheme => _scheme.isNotEmpty; 80 bool get hasScheme => _scheme.isNotEmpty;
70 81
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 // If the cache is too big, start a new generation. 221 // If the cache is too big, start a new generation.
211 if (_currentCacheLength > _MAX_CACHE_LENGTH_BEFORE_FLUSH) { 222 if (_currentCacheLength > _MAX_CACHE_LENGTH_BEFORE_FLUSH) {
212 _cache.clear(); 223 _cache.clear();
213 _currentCacheLength = 0; 224 _currentCacheLength = 0;
214 _currentCacheGeneration++; 225 _currentCacheGeneration++;
215 } 226 }
216 } 227 }
217 return uri; 228 return uri;
218 } 229 }
219 230
231 /**
232 * This implementation was used before 'fast-URI' in Dart VM.
233 */
234 static int _computeHashUsingCombine(FastUri uri) {
235 // This code is copied from the standard Uri implementation.
236 // It is important that Uri and FastUri generate compatible hashCodes
237 // because Uri and FastUri may be used as keys in the same map.
238 int combine(part, current) {
239 // The sum is truncated to 30 bits to make sure it fits into a Smi.
240 return (current * 31 + part.hashCode) & 0x3FFFFFFF;
241 }
242
243 return combine(
244 uri.scheme,
245 combine(
246 uri.userInfo,
247 combine(
248 uri.host,
249 combine(
250 uri.port,
251 combine(uri.path,
252 combine(uri.query, combine(uri.fragment, 1)))))));
253 }
254
255 /**
256 * This implementation should be used with 'fast-URI' in Dart VM.
257 * https://github.com/dart-lang/sdk/commit/afbbbb97cfcd86a64d0ba5dcfe1ab758954 adaf4
258 */
259 static int _computeHashUsingText(FastUri uri) {
260 return uri._text.hashCode;
261 }
262
220 static bool _isAlphabetic(int char) { 263 static bool _isAlphabetic(int char) {
221 return char >= 'A'.codeUnitAt(0) && char <= 'Z'.codeUnitAt(0) || 264 return char >= 'A'.codeUnitAt(0) && char <= 'Z'.codeUnitAt(0) ||
222 char >= 'a'.codeUnitAt(0) && char <= 'z'.codeUnitAt(0); 265 char >= 'a'.codeUnitAt(0) && char <= 'z'.codeUnitAt(0);
223 } 266 }
224 267
225 static bool _isDigit(int char) { 268 static bool _isDigit(int char) {
226 return char >= '0'.codeUnitAt(0) && char <= '9'.codeUnitAt(0); 269 return char >= '0'.codeUnitAt(0) && char <= '9'.codeUnitAt(0);
227 } 270 }
228 271
229 /** 272 /**
(...skipping 30 matching lines...) Expand all
260 if (path.startsWith('//')) { 303 if (path.startsWith('//')) {
261 hasEmptyAuthority = true; 304 hasEmptyAuthority = true;
262 path = path.substring(2); 305 path = path.substring(2);
263 if (!path.startsWith('/')) { 306 if (!path.startsWith('/')) {
264 return null; 307 return null;
265 } 308 }
266 } 309 }
267 return new FastUri._(_currentCacheGeneration, text, scheme, 310 return new FastUri._(_currentCacheGeneration, text, scheme,
268 hasEmptyAuthority, path, lastSlashIndex); 311 hasEmptyAuthority, path, lastSlashIndex);
269 } 312 }
313
314 /**
315 * Determine whether VM has the text based hash code computation in [Uri],
316 * or the old combine style.
317 */
318 static bool _shouldComputeHashCodeUsingText() {
319 String text = 'package:foo/foo.dart';
320 return Uri.parse(text).hashCode == text.hashCode;
321 }
270 } 322 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698